1#include "ObjectFlamePoleFoot.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/RaceManager.hh"
12ObjectFlamePoleFoot::ObjectFlamePoleFoot(
const System::MapdataGeoObj ¶ms)
14 m_extraCycleFrames = params.setting(0);
15 m_initDelay = params.setting(1);
16 m_poleScale =
static_cast<f32
>(params.setting(2));
20 if (m_poleScale == 0.0f) {
21 m_poleScale = 3.0f +
static_cast<f32
>(s_flamePoleCount % 3);
24 m_pole = EGG::egg_new<ObjectFlamePole>(params, pos(), rot(), scale());
29ObjectFlamePoleFoot::~ObjectFlamePoleFoot() {
34void ObjectFlamePoleFoot::init() {
35 constexpr f32 NORMALIZATION =
static_cast<f32
>(CYCLE_FRAMES) * (7.0f - 1.0f);
39 m_eruptUpDuration =
static_cast<s32
>(0.1f * NORMALIZATION / 7.0f);
40 m_eruptDownDuration =
static_cast<s32
>(0.2f * NORMALIZATION / 7.0f);
42 s32 state1 =
static_cast<s32
>(0.3f * NORMALIZATION / 7.0f);
43 s32 state2 = state1 + m_eruptUpDuration;
44 s32 state3 = state2 +
static_cast<s32
>(
static_cast<f32
>(CYCLE_FRAMES) * 1.0f / 7.0f);
45 s32 state4 = state3 + m_eruptDownDuration;
46 s32 state5 = state4 +
static_cast<s32
>(0.4f * NORMALIZATION / 7.0f);
47 m_stateStart = {{0, state1, state2, state3, state4, state5}};
49 m_eruptDownVel = (m_poleScale - 1.0f) /
static_cast<f32
>(state1);
50 m_initScaledHeight = ObjectFlamePole::HEIGHT * m_poleScale;
51 m_scaleDelta = (300.0f + m_initScaledHeight) /
static_cast<f32
>(m_eruptDownDuration);
52 m_pole->setActive(
false);
53 m_pole->disableCollision();
55 EGG::Vector3f polePos = m_pole->pos();
56 polePos.y = pos().y - ObjectFlamePole::HEIGHT * m_poleScale;
57 m_pole->setPos(polePos);
61void ObjectFlamePoleFoot::calc() {
62 if (System::RaceManager::Instance()->timer() < m_initDelay) {
70 f32 scale = getScaleY(0);
73 EGG::Vector3f polePos = m_pole->pos();
75 EGG::Vector3f(polePos.x, m_heightOffset + (pos().y - m_initScaledHeight), polePos.z));
76 m_pole->setScale(m_poleScale);
80void ObjectFlamePoleFoot::calcStates() {
81 u32 frame =
static_cast<s32
>(System::RaceManager::Instance()->timer() - m_initDelay);
82 m_cycleFrame = frame % (m_extraCycleFrames + CYCLE_FRAMES);
85 auto it = std::ranges::upper_bound(m_stateStart.begin(), m_stateStart.end(), m_cycleFrame);
86 auto idx = it - m_stateStart.begin() - 1;
92 u16 stateId =
static_cast<u16
>(idx);
94 if (m_currentStateId != stateId) {
95 m_nextStateId = stateId;
99f32 ObjectFlamePoleFoot::getScaleY(u32 timeOffset)
const {
100 u32 frame = System::RaceManager::Instance()->timer() - timeOffset;
101 if (frame < m_initDelay) {
105 s32 cycleFrame = frame - m_initDelay;
106 cycleFrame %= m_extraCycleFrames + CYCLE_FRAMES;
108 if (cycleFrame >= m_stateStart[5]) {
112 if (cycleFrame >= m_stateStart[4]) {
113 return std::max(1.0f,
114 m_poleScale - m_eruptDownVel *
static_cast<f32
>(m_eruptDownDuration / 2) -
115 m_eruptDownVel *
static_cast<f32
>(cycleFrame - m_stateStart[4]));
118 if (cycleFrame >= m_stateStart[3]) {
119 s32 framesSince194 = cycleFrame - m_stateStart[3];
120 s32 half17c = m_eruptDownDuration / 2;
121 if (framesSince194 > half17c) {
122 return m_poleScale - m_eruptDownVel *
static_cast<f32
>(framesSince194 - half17c);
128 if (cycleFrame >= m_stateStart[2] || cycleFrame >= m_stateStart[1]) {
132 if (cycleFrame >= 0) {
133 return std::min(m_poleScale, m_eruptDownVel *
static_cast<f32
>(cycleFrame) + 1.0f);
140bool ObjectFlamePoleFoot::checkCollision(f32 radius,
const EGG::Vector3f &pos,
141 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
144 calcScale(timeOffset);
145 f32 scale = getScaleY(timeOffset);
147 if (!m_objColMgr->checkSphereFullPush(radius, pos, prevPos, mask, info, maskOut)) {
152 CollisionDirector::Instance()->setCurrentCollisionTrickable(
true);
159bool ObjectFlamePoleFoot::checkCollisionCached(f32 radius,
const EGG::Vector3f &pos,
160 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
163 calcScale(timeOffset);
164 f32 scale = getScaleY(timeOffset);
166 if (!m_objColMgr->checkSphereCachedFullPush(radius, pos, prevPos, mask, info, maskOut)) {
171 CollisionDirector::Instance()->setCurrentCollisionTrickable(
true);
178void ObjectFlamePoleFoot::enterEruptingUp() {
179 m_pole->setActive(
true);
180 m_pole->enableCollision();
181 m_heightOffset = 0.0f;
185 f32 vel = m_initScaledHeight;
186 EGG::Mathf::FindRootsQuadratic(
static_cast<f32
>(m_eruptUpDuration * m_eruptUpDuration),
187 -4.0f * m_initScaledHeight *
static_cast<f32
>(m_eruptUpDuration),
188 4.0f * m_initScaledHeight * m_initScaledHeight, t1, t2);
198 m_initEruptVel = vel;
199 m_eruptAccel = vel * vel / (2.0f * m_initScaledHeight);
203void ObjectFlamePoleFoot::calcEruptingUp() {
204 f32 frame =
static_cast<f32
>(m_cycleFrame - m_stateStart[1]);
205 m_heightOffset = std::min(m_initScaledHeight,
206 m_initEruptVel * frame - frame * 0.5f * m_eruptAccel * frame);
210void ObjectFlamePoleFoot::calcEruptingStay() {
211 constexpr f32 AMPLITUDE = 50.0f;
213 f32 angle = 360.0f *
static_cast<f32
>(m_cycleFrame - m_stateStart[2]) / 30.0f;
214 m_heightOffset = m_scaledHeight + AMPLITUDE * EGG::Mathf::SinFIdx(DEG2FIDX * angle);
217u32 ObjectFlamePoleFoot::s_flamePoleCount = 0;
Base class that represents different "states" for an object.