1#include "ObjectFlamePoleFoot.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/RaceManager.hh"
13 : ObjectKCL(params), StateManager(this, STATE_ENTRIES) {
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
>(FLAMEPOLE_COUNT % 3);
24 m_pole =
new ObjectFlamePole(params, m_pos, m_rot, m_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();
56 polePos.y = m_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);
71 m_flags.setBit(eFlags::Scale);
76 EGG::Vector3f(polePos.x, m_heightOffset + (m_pos.y - m_initScaledHeight), polePos.z));
77 m_pole->setScale(
EGG::Vector3f(m_poleScale, m_poleScale, m_poleScale));
81void ObjectFlamePoleFoot::calcStates() {
82 u32 frame =
static_cast<s32
>(System::RaceManager::Instance()->timer() - m_initDelay);
83 m_cycleFrame = frame % (m_extraCycleFrames + CYCLE_FRAMES);
86 auto it = std::ranges::upper_bound(m_stateStart.begin(), m_stateStart.end(), m_cycleFrame);
87 auto idx = it - m_stateStart.begin() - 1;
93 u16 stateId =
static_cast<u16>(idx);
95 if (m_currentStateId != stateId) {
96 m_nextStateId = stateId;
100f32 ObjectFlamePoleFoot::getScaleY(u32 timeOffset)
const {
101 u32 frame = System::RaceManager::Instance()->timer() - timeOffset;
102 if (frame < m_initDelay) {
106 s32 cycleFrame = frame - m_initDelay;
107 cycleFrame %= m_extraCycleFrames + CYCLE_FRAMES;
109 if (cycleFrame >= m_stateStart[5]) {
113 if (cycleFrame >= m_stateStart[4]) {
114 return std::max(1.0f,
115 m_poleScale - m_eruptDownVel *
static_cast<f32
>(m_eruptDownDuration / 2) -
116 m_eruptDownVel *
static_cast<f32
>(cycleFrame - m_stateStart[4]));
119 if (cycleFrame >= m_stateStart[3]) {
120 s32 framesSince194 = cycleFrame - m_stateStart[3];
121 s32 half17c = m_eruptDownDuration / 2;
122 if (framesSince194 > half17c) {
123 return m_poleScale - m_eruptDownVel *
static_cast<f32
>(framesSince194 - half17c);
129 if (cycleFrame >= m_stateStart[2] || cycleFrame >= m_stateStart[1]) {
133 if (cycleFrame >= 0) {
134 return std::min(m_poleScale, m_eruptDownVel *
static_cast<f32
>(cycleFrame) + 1.0f);
141bool ObjectFlamePoleFoot::checkCollision(f32 radius,
const EGG::Vector3f &pos,
142 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
145 calcScale(timeOffset);
146 f32 scale = getScaleY(timeOffset);
148 if (!m_objColMgr->checkSphereFullPush(radius, pos, prevPos, mask, info, maskOut)) {
153 CollisionDirector::Instance()->setCurrentCollisionTrickable(
true);
160bool ObjectFlamePoleFoot::checkCollisionCached(f32 radius,
const EGG::Vector3f &pos,
161 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
164 calcScale(timeOffset);
165 f32 scale = getScaleY(timeOffset);
167 if (!m_objColMgr->checkSphereCachedFullPush(radius, pos, prevPos, mask, info, maskOut)) {
172 CollisionDirector::Instance()->setCurrentCollisionTrickable(
true);
179void ObjectFlamePoleFoot::enterEruptingUp() {
180 m_pole->setActive(
true);
181 m_pole->enableCollision();
182 m_heightOffset = 0.0f;
186 f32 vel = m_initScaledHeight;
187 EGG::Mathf::FindRootsQuadratic(
static_cast<f32
>(m_eruptUpDuration * m_eruptUpDuration),
188 -4.0f * m_initScaledHeight *
static_cast<f32
>(m_eruptUpDuration),
189 4.0f * m_initScaledHeight * m_initScaledHeight, t1, t2);
199 m_initEruptVel = vel;
200 m_eruptAccel = vel * vel / (2.0f * m_initScaledHeight);
204void ObjectFlamePoleFoot::calcEruptingUp() {
205 f32 frame =
static_cast<f32
>(m_cycleFrame - m_stateStart[1]);
206 m_heightOffset = std::min(m_initScaledHeight,
207 m_initEruptVel * frame - frame * 0.5f * m_eruptAccel * frame);
211void ObjectFlamePoleFoot::calcEruptingStay() {
212 constexpr f32 AMPLITUDE = 50.0f;
214 f32 angle = 360.0f *
static_cast<f32
>(m_cycleFrame - m_stateStart[2]) / 30.0f;
215 m_heightOffset = m_scaledHeight + AMPLITUDE * EGG::Mathf::SinFIdx(DEG2FIDX * angle);
218u32 ObjectFlamePoleFoot::FLAMEPOLE_COUNT = 0;