1#include "game/field/obj/ObjectVolcanoPiece.hh"
3#include "game/system/RaceManager.hh"
9 : ObjectKCL(params), m_initialPos(m_pos), m_initialRot(m_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() {
25void ObjectVolcanoPiece::calc() {
26 u32 timer = System::RaceManager::Instance()->timer();
27 if (calcState(timer) == State::Fall && FALL_DURATION - 1 == calcT(timer)) {
31 m_flags.setBit(eFlags::Matrix);
33 m_transform = calcShakeAndFall(&movingObjVel, 0);
34 m_pos = m_transform.base(3);
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 =
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 =
new ObjColMgr(file);
61 rtMat.
makeRT(m_initialRot, m_initialPos);
64 m_objColMgr->setMtx(rtMat);
65 m_objColMgr->setInvMtx(invMat);
66 m_objColMgr->setScale(m_scale.y);
69 m_colMgrB->setMtx(rtMat);
70 m_colMgrB->setInvMtx(invMat);
71 m_colMgrB->setScale(m_scale.y);
75 m_colMgrC->setMtx(rtMat);
76 m_colMgrC->setInvMtx(invMat);
77 m_colMgrC->setScale(m_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>)
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) {
173 const EGG::Matrix34f &rtMat = calcShakeAndFall(&movingObjVel, timeOffset);
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);
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);
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);
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);
270 m_rtMat.makeRT(m_rot, pos);
275ObjectVolcanoPiece::State ObjectVolcanoPiece::calcState(u32 frame)
const {
276 if (frame < m_restDuration) {
280 if (frame < m_shakeDuration) {
284 if (frame < m_quakeDuration) {
288 if (frame < m_quakeDuration + FALL_DURATION) {
296f32 ObjectVolcanoPiece::calcT(u32 frame)
const {
297 if (frame < m_restDuration) {
298 return static_cast<f32
>(frame);
301 if (frame < m_shakeDuration) {
302 return static_cast<f32
>(frame - m_restDuration);
305 if (frame < m_quakeDuration) {
306 return static_cast<f32
>(frame - m_shakeDuration);
309 if (frame < m_quakeDuration + FALL_DURATION) {
310 return static_cast<f32
>(frame - m_quakeDuration);
313 return static_cast<f32
>(frame - m_quakeDuration - FALL_DURATION);
void makeRT(const Vector3f &r, const Vector3f &t)
Sets rotation-translation matrix.
bool ps_inverse(Matrix34f &out) const