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_initialRot(rot()),
10 m_restDuration(params.setting(1) * 60),
11 m_shakeDuration(m_restDuration + params.setting(2) * 60),
12 m_quakeDuration(m_shakeDuration + params.setting(7) + 1), m_colMgrB(nullptr),
14 snprintf(m_modelName,
sizeof(m_modelName),
"VolcanoPiece%hd",
15 static_cast<s16
>(params.setting(0)));
19ObjectVolcanoPiece::~ObjectVolcanoPiece() {
20 EGG::egg_delete(m_colMgrB);
21 EGG::egg_delete(m_colMgrC);
25void ObjectVolcanoPiece::calc() {
26 u32 timer = System::RaceManager::Instance()->timer();
27 if (calcState(timer) == State::Fall && FALL_DURATION - 1 == calcT(timer)) {
31 EGG::Vector3f movingObjVel;
32 setTransform(calcShakeAndFall(&movingObjVel, 0));
33 setMovingObjVel(movingObjVel);
37void ObjectVolcanoPiece::createCollision() {
38 ObjectKCL::createCollision();
41 snprintf(filepath,
sizeof(filepath),
"%sb.kcl", getKclName());
42 auto *file = System::ResourceManager::Instance()->getFile(filepath,
nullptr,
43 System::ArchiveId::Course);
46 m_colMgrB = EGG::egg_new<ObjColMgr>(file);
49 snprintf(filepath,
sizeof(filepath),
"%sc.kcl", getKclName());
50 file = System::ResourceManager::Instance()->getFile(filepath,
nullptr,
51 System::ArchiveId::Course);
54 m_colMgrC = EGG::egg_new<ObjColMgr>(file);
58 EGG::Matrix34f invMat;
59 rtMat.makeRT(m_initialRot, m_initialPos);
60 rtMat.ps_inverse(invMat);
62 m_objColMgr->setMtx(rtMat);
63 m_objColMgr->setInvMtx(invMat);
64 m_objColMgr->setScale(scale().y);
67 m_colMgrB->setMtx(rtMat);
68 m_colMgrB->setInvMtx(invMat);
69 m_colMgrB->setScale(scale().y);
73 m_colMgrC->setMtx(rtMat);
74 m_colMgrC->setInvMtx(invMat);
75 m_colMgrC->setScale(scale().y);
79template <
typename T,
typename U>
80 requires(std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>) &&
81 (std::is_same_v<U, ObjectVolcanoPiece::CheckPointPartialFunc> ||
82 std::is_same_v<U, ObjectVolcanoPiece::CheckPointFullFunc>)
83bool ObjectVolcanoPiece::checkPointImpl(
const EGG::Vector3f &v0,
const EGG::Vector3f &v1,
84 KCLTypeMask flags, T *pInfo, KCLTypeMask *pFlagsOut, U checkFunc) {
85 State state = calcState(System::RaceManager::Instance()->timer());
86 bool hasCol = (m_objColMgr->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut);
88 if (state == State::Rest || hasCol) {
92 hasCol = m_colMgrB && (m_colMgrB->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut);
93 hasCol = hasCol || (m_colMgrC && (m_colMgrC->*checkFunc)(v0, v1, flags, pInfo, pFlagsOut));
98template <
typename T,
typename U>
99 requires(std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>) &&
100 (std::is_same_v<U, ObjectVolcanoPiece::CheckSpherePartialFunc> ||
101 std::is_same_v<U, ObjectVolcanoPiece::CheckSphereFullFunc>)
102bool ObjectVolcanoPiece::checkSphereImpl(f32 radius,
const EGG::Vector3f &v0,
103 const EGG::Vector3f &v1, KCLTypeMask flags, T *pInfo, KCLTypeMask *pFlagsOut,
104 u32 timeOffset, U checkFunc) {
106 State state = calcState(System::RaceManager::Instance()->timer());
107 bool hasCol = (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
109 if (state == State::Rest || hasCol) {
113 hasCol = m_colMgrB && (m_colMgrB->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
115 (m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
120bool ObjectVolcanoPiece::checkCollisionImpl(f32 radius,
const EGG::Vector3f &v0,
121 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
122 u32 timeOffset, CheckSphereFullFunc checkFunc) {
123 u32 t = System::RaceManager::Instance()->timer() - timeOffset;
124 State state = calcState(t);
127 if (state == State::Rest) {
128 return (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
131 if (state == State::Gone) {
132 return m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
135 bool hasCol = (m_objColMgr->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut);
137 (m_colMgrB && (m_colMgrB->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
139 (m_colMgrC && (m_colMgrC->*checkFunc)(radius, v0, v1, flags, pInfo, pFlagsOut));
145void ObjectVolcanoPiece::narrScLocal(f32 radius,
const EGG::Vector3f &pos, KCLTypeMask mask,
147 State state = calcState(System::RaceManager::Instance()->timer());
148 m_objColMgr->narrScLocal(radius, pos, mask);
150 if (state == State::Rest) {
155 m_colMgrB->narrScLocal(radius, pos, mask);
159 m_colMgrC->narrScLocal(radius, pos, mask);
164void ObjectVolcanoPiece::update(u32 timeOffset) {
165 State state = calcState(System::RaceManager::Instance()->timer() - timeOffset);
166 if (state == State::Rest || state == State::Gone) {
170 EGG::Vector3f movingObjVel;
171 const EGG::Matrix34f &rtMat = calcShakeAndFall(&movingObjVel, timeOffset);
172 EGG::Matrix34f invMat;
173 rtMat.ps_inverse(invMat);
175 m_objColMgr->setMtx(rtMat);
176 m_objColMgr->setInvMtx(invMat);
179 m_colMgrB->setMtx(rtMat);
180 m_colMgrB->setInvMtx(invMat);
183 setMovingObjVel(movingObjVel);
187void ObjectVolcanoPiece::calcScale(u32 timeOffset) {
188 State state = calcState(System::RaceManager::Instance()->timer() - timeOffset);
190 if (state == State::Rest || state == State::Gone) {
194 f32 scale = getScaleY(timeOffset);
195 m_objColMgr->setScale(scale);
198 m_colMgrB->setScale(scale);
203void ObjectVolcanoPiece::setMovingObjVel(
const EGG::Vector3f &v) {
204 m_objColMgr->setMovingObjVel(v);
207 m_colMgrB->setMovingObjVel(v);
212const EGG::Matrix34f &ObjectVolcanoPiece::calcShakeAndFall(EGG::Vector3f *vel, u32 timeOffset) {
213 constexpr f32 FALL_SPEED = 10.0f;
214 constexpr s32 SHAKE_STEPS = 8;
215 constexpr s32 SHAKE_STEPS_HALF = SHAKE_STEPS / 2;
216 constexpr f32 SHAKE_STEP_AMPLITUDE = 5.0f;
218 u32 t = System::RaceManager::Instance()->timer() - timeOffset;
219 State state = calcState(t);
221 EGG::Vector3f pos = m_initialPos;
225 s32 step =
static_cast<s32
>(calcT(t)) % SHAKE_STEPS + 1;
227 if (step > SHAKE_STEPS_HALF) {
228 step = SHAKE_STEPS_HALF - step;
230 pos.y += SHAKE_STEP_AMPLITUDE *
static_cast<f32
>(step);
233 pos.y -= FALL_SPEED *
static_cast<f32
>(calcT(t));
236 pos.y -= FALL_SPEED *
static_cast<f32
>(FALL_DURATION);
243 EGG::Vector3f prevPos = m_initialPos;
244 State prevState = calcState(t - 1);
248 s32 step =
static_cast<s32
>(calcT(t - 1)) % SHAKE_STEPS + 1;
250 if (step > SHAKE_STEPS_HALF) {
251 step = SHAKE_STEPS_HALF - step;
253 prevPos.y += SHAKE_STEP_AMPLITUDE *
static_cast<f32
>(step);
256 prevPos.y -= FALL_SPEED *
static_cast<f32
>(calcT(t - 1));
259 prevPos.y -= FALL_SPEED *
static_cast<f32
>(FALL_DURATION);
265 *vel = EGG::Vector3f(0.0f, pos.y - prevPos.y, 0.0f);
268 m_rtMat.makeRT(rot(), pos);
273ObjectVolcanoPiece::State ObjectVolcanoPiece::calcState(u32 frame)
const {
274 if (frame < m_restDuration) {
278 if (frame < m_shakeDuration) {
282 if (frame < m_quakeDuration) {
286 if (frame < m_quakeDuration + FALL_DURATION) {
294f32 ObjectVolcanoPiece::calcT(u32 frame)
const {
295 if (frame < m_restDuration) {
296 return static_cast<f32
>(frame);
299 if (frame < m_shakeDuration) {
300 return static_cast<f32
>(frame - m_restDuration);
303 if (frame < m_quakeDuration) {
304 return static_cast<f32
>(frame - m_shakeDuration);
307 if (frame < m_quakeDuration + FALL_DURATION) {
308 return static_cast<f32
>(frame - m_quakeDuration);
311 return static_cast<f32
>(frame - m_quakeDuration - FALL_DURATION);