1#include "game/field/obj/ObjectVolcanoPiece.hh"
3#include "game/system/RaceManager.hh"
8ObjectVolcanoPiece::ObjectVolcanoPiece(
const System::MapdataGeoObj ¶ms)
9 :
ObjectKCL(params), m_initialPos(pos()), m_restDuration(params.setting(1) * 60),
10 m_shakeDuration(m_restDuration + params.setting(2) * 60),
11 m_quakeDuration(m_shakeDuration + params.setting(7) + 1), m_colMgrB(nullptr),
13 snprintf(m_modelName,
sizeof(m_modelName),
"VolcanoPiece%hd",
14 static_cast<s16
>(params.setting(0)));
17 m_rtMat.makeRT(rot(), m_initialPos);
21ObjectVolcanoPiece::~ObjectVolcanoPiece() {
22 EGG::egg_delete(m_colMgrB);
23 EGG::egg_delete(m_colMgrC);
27void ObjectVolcanoPiece::calc() {
28 u32 timer = System::RaceManager::Instance()->timer();
29 if (calcState(timer) == State::Fall && FALL_DURATION - 1 == calcT(timer)) {
33 EGG::Vector3f movingObjVel;
34 setTransform(calcShakeAndFall(&movingObjVel, 0));
35 setMovingObjVel(movingObjVel);
39void ObjectVolcanoPiece::createCollision() {
40 ObjectKCL::createCollision();
43 snprintf(filepath,
sizeof(filepath),
"%sb.kcl", getKclName());
44 auto *file = System::ResourceManager::Instance()->getFile(filepath,
nullptr,
45 System::ArchiveId::Course);
48 m_colMgrB = EGG::egg_new<ObjColMgr>(file);
51 snprintf(filepath,
sizeof(filepath),
"%sc.kcl", getKclName());
52 file = System::ResourceManager::Instance()->getFile(filepath,
nullptr,
53 System::ArchiveId::Course);
56 m_colMgrC = EGG::egg_new<ObjColMgr>(file);
60 EGG::Matrix34f invMat;
61 rtMat.makeRT(rot(), m_initialPos);
62 rtMat.ps_inverse(invMat);
64 m_objColMgr->setMtx(rtMat);
65 m_objColMgr->setInvMtx(invMat);
66 m_objColMgr->setScale(scale().y);
69 m_colMgrB->setMtx(rtMat);
70 m_colMgrB->setInvMtx(invMat);
71 m_colMgrB->setScale(scale().y);
75 m_colMgrC->setMtx(rtMat);
76 m_colMgrC->setInvMtx(invMat);
77 m_colMgrC->setScale(scale().y);
81template <
typename T,
typename U>
82 requires(std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>) &&
83 (std::is_same_v<U, ObjectVolcanoPiece::CheckPointPartialFunc> ||
84 std::is_same_v<U, ObjectVolcanoPiece::CheckPointFullFunc>)
85bool ObjectVolcanoPiece::checkPointImpl(
const EGG::Vector3f &v0,
const EGG::Vector3f &v1,
86 KCLTypeMask flags, T *pInfo, KCLTypeMask *pFlagsOut, U checkFunc) {
87 State state = calcState(System::RaceManager::Instance()->timer());
88 bool hasCol = (m_objColMgr->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut);
90 if (state == State::Rest || hasCol) {
94 hasCol = m_colMgrB && (m_colMgrB->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut);
95 hasCol = hasCol || (m_colMgrC && (m_colMgrC->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut));
100template <
typename T,
typename U>
101 requires(std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>) &&
102 (std::is_same_v<U, ObjectVolcanoPiece::CheckSpherePartialFunc> ||
103 std::is_same_v<U, ObjectVolcanoPiece::CheckSphereFullFunc>)
104bool ObjectVolcanoPiece::checkSphereImpl(f32 radius,
const EGG::Vector3f &v0,
105 const EGG::Vector3f &v1, KCLTypeMask flags, T *pInfo, KCLTypeMask *pFlagsOut,
106 u32 timeOffset, U checkFunc) {
108 State state = calcState(System::RaceManager::Instance()->timer());
109 bool hasCol = (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
111 if (state == State::Rest || hasCol) {
115 hasCol = m_colMgrB && (m_colMgrB->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
117 (m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
122bool ObjectVolcanoPiece::checkCollisionImpl(f32 radius,
const EGG::Vector3f &v0,
123 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
124 u32 timeOffset, CheckSphereFullFunc checkFunc) {
125 u32 t = System::RaceManager::Instance()->timer() - timeOffset;
126 State state = calcState(t);
129 if (state == State::Rest) {
130 return (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
133 if (state == State::Gone) {
134 return m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
137 bool hasCol = (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
139 (m_colMgrB && (m_colMgrB->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
141 (m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
147void ObjectVolcanoPiece::narrScLocal(f32 radius,
const EGG::Vector3f &pos, KCLTypeMask mask,
149 State state = calcState(System::RaceManager::Instance()->timer());
150 m_objColMgr->narrScLocal(radius, pos, mask);
152 if (state == State::Rest) {
157 m_colMgrB->narrScLocal(radius, pos, mask);
161 m_colMgrC->narrScLocal(radius, pos, mask);
166void ObjectVolcanoPiece::update(u32 timeOffset) {
167 State state = calcState(System::RaceManager::Instance()->timer() - timeOffset);
168 if (state == State::Rest || state == State::Gone) {
172 EGG::Vector3f movingObjVel;
173 const EGG::Matrix34f &rtMat = calcShakeAndFall(&movingObjVel, timeOffset);
174 EGG::Matrix34f invMat;
175 rtMat.ps_inverse(invMat);
177 m_objColMgr->setMtx(rtMat);
178 m_objColMgr->setInvMtx(invMat);
181 m_colMgrB->setMtx(rtMat);
182 m_colMgrB->setInvMtx(invMat);
185 setMovingObjVel(movingObjVel);
189void ObjectVolcanoPiece::calcScale(u32 timeOffset) {
190 State state = calcState(System::RaceManager::Instance()->timer() - timeOffset);
192 if (state == State::Rest || state == State::Gone) {
196 f32 scale = getScaleY(timeOffset);
197 m_objColMgr->setScale(scale);
200 m_colMgrB->setScale(scale);
205void ObjectVolcanoPiece::setMovingObjVel(
const EGG::Vector3f &v) {
206 m_objColMgr->setMovingObjVel(v);
209 m_colMgrB->setMovingObjVel(v);
214const EGG::Matrix34f &ObjectVolcanoPiece::calcShakeAndFall(EGG::Vector3f *vel, u32 timeOffset) {
215 constexpr f32 FALL_SPEED = 10.0f;
216 constexpr s32 SHAKE_STEPS = 8;
217 constexpr s32 SHAKE_STEPS_HALF = SHAKE_STEPS / 2;
218 constexpr f32 SHAKE_STEP_AMPLITUDE = 5.0f;
220 u32 t = System::RaceManager::Instance()->timer() - timeOffset;
221 State state = calcState(t);
223 EGG::Vector3f pos = m_initialPos;
227 s32 step =
static_cast<s32
>(calcT(t)) % SHAKE_STEPS + 1;
229 if (step > SHAKE_STEPS_HALF) {
230 step = SHAKE_STEPS_HALF - step;
232 pos.y += SHAKE_STEP_AMPLITUDE *
static_cast<f32
>(step);
235 pos.y -= FALL_SPEED *
static_cast<f32
>(calcT(t));
238 pos.y -= FALL_SPEED *
static_cast<f32
>(FALL_DURATION);
245 EGG::Vector3f prevPos = m_initialPos;
246 State prevState = calcState(t - 1);
250 s32 step =
static_cast<s32
>(calcT(t - 1)) % SHAKE_STEPS + 1;
252 if (step > SHAKE_STEPS_HALF) {
253 step = SHAKE_STEPS_HALF - step;
255 prevPos.y += SHAKE_STEP_AMPLITUDE *
static_cast<f32
>(step);
258 prevPos.y -= FALL_SPEED *
static_cast<f32
>(calcT(t - 1));
261 prevPos.y -= FALL_SPEED *
static_cast<f32
>(FALL_DURATION);
267 *vel = EGG::Vector3f(0.0f, pos.y - prevPos.y, 0.0f);
272 m_rtMat.setBase(3, pos);
277ObjectVolcanoPiece::State ObjectVolcanoPiece::calcState(u32 frame)
const {
278 if (frame < m_restDuration) {
282 if (frame < m_shakeDuration) {
286 if (frame < m_quakeDuration) {
290 if (frame < m_quakeDuration + FALL_DURATION) {
298f32 ObjectVolcanoPiece::calcT(u32 frame)
const {
299 if (frame < m_restDuration) {
300 return static_cast<f32
>(frame);
303 if (frame < m_shakeDuration) {
304 return static_cast<f32
>(frame - m_restDuration);
307 if (frame < m_quakeDuration) {
308 return static_cast<f32
>(frame - m_shakeDuration);
311 if (frame < m_quakeDuration + FALL_DURATION) {
312 return static_cast<f32
>(frame - m_quakeDuration);
315 return static_cast<f32
>(frame - m_quakeDuration - FALL_DURATION);