1#include "ObjectHeyho.hh"
3#include "game/field/CollisionDirector.hh"
4#include "game/field/RailManager.hh"
9ObjectHeyho::ObjectHeyho(
const System::MapdataGeoObj ¶ms)
11 const auto *rail = RailManager::Instance()->rail(params.pathId());
13 const auto &railPts = rail->points();
17 m_apex = std::max(railPts.front().pos.y, railPts.back().pos.y);
18 m_midpoint = railPts[railPts.size() / 2].pos;
23 ASSERT(m_apex - m_midpoint.y > std::numeric_limits<f32>::epsilon());
24 f32 maxVel =
static_cast<f32
>(
static_cast<s16
>(params.setting(0)));
25 m_maxVelSq = maxVel * maxVel;
26 m_accel = m_maxVelSq / (m_apex - m_midpoint.y);
30ObjectHeyho::~ObjectHeyho() =
default;
33void ObjectHeyho::init() {
34 ASSERT(m_railInterpolator);
35 m_railInterpolator->init(0.0f, m_railInterpolator->pointCount() / 2);
36 setPos(m_railInterpolator->curPos());
37 m_currentVel = EGG::Mathf::sqrt(
38 m_maxVelSq - m_accel * (m_railInterpolator->curPos().y - m_midpoint.y));
40 m_transformOffset = m_railInterpolator->curTangentDir() * m_currentVel;
41 m_floorCollision =
false;
42 m_up = EGG::Vector3f::ey;
43 m_forward = EGG::Vector3f::ez;
47 changeAnimation(Animation::Move);
51void ObjectHeyho::calc() {
52 calcStateTransition();
59void ObjectHeyho::loadAnims() {
60 std::array<const char *, 4> names = {{
67 std::array<Render::AnmType, 4> types = {{
74 linkAnims(names, types);
78void ObjectHeyho::calcCollisionTransform() {
79 auto *objCol = collision();
85 tm.makeT(EGG::Vector3f(0.0f, 100.0f, 0.0f));
87 EGG::Matrix34f m = transform().multiplyTo(tm);
88 objCol->transform(m, scale(), m_transformOffset);
92void ObjectHeyho::calcMove() {
93 m_forward = m_railInterpolator->nextPoint().pos - m_railInterpolator->curPoint().pos;
94 m_floorCollision =
false;
98 if (CollisionDirector::Instance()->checkSphereFull(COLLISION_RADIUS, pos() + COLLISION_OFFSET,
100 m_floorCollision =
true;
101 if (info.floorDist > -std::numeric_limits<f32>::min()) {
102 m_floorNrm = info.floorNrm;
105 setPos(pos() + info.tangentOff - m_floorNrm * 60.0f);
107 if (m_currentAnim == Animation::Jumped) {
108 const auto *anim = m_drawMdl->anmMgr()->activeAnim(Render::AnmType::Chr);
109 if (anim->frame() >= anim->frameCount()) {
110 changeAnimation(Animation::Move);
117void ObjectHeyho::calcJump() {
118 constexpr s16 SPIN_DELAY_FRAMES = 5;
119 constexpr s16 SPIN_RATE = 12;
120 constexpr s16 SPIN_DEGREES = 720;
122 m_floorCollision =
false;
125 Field::KCLTypeMask flags = KCL_NONE;
127 if (CollisionDirector::Instance()->checkSphereFull(COLLISION_RADIUS, pos() + COLLISION_OFFSET,
129 m_floorCollision =
true;
130 if (info.floorDist > -std::numeric_limits<f32>::min()) {
131 m_floorNrm = info.floorNrm;
137 f32 xPos = pos().x + info.tangentOff.x - m_floorNrm.x * 60.0f;
138 f32 zPos = pos().z + info.tangentOff.z - m_floorNrm.z * 60.0f;
139 setPos(EGG::Vector3f(xPos, pos().y, zPos));
142 m_forward = m_railInterpolator->nextPoint().pos - m_railInterpolator->curPoint().pos;
143 if (m_currentAnim == Animation::Jump) {
144 m_currentAnim = Animation::Jumped;
147 m_floorCollision =
false;
148 const auto &curPos = m_railInterpolator->curPoint().pos;
149 const auto &nextPos = m_railInterpolator->nextPoint().pos;
151 m_forward = (nextPos.y > curPos.y ? nextPos : curPos) - m_midpoint;
156 s16 frame = m_spinFrame - SPIN_DELAY_FRAMES;
157 if (frame >= 0 && frame <= SPIN_DEGREES / SPIN_RATE) {
159 m.setAxisRotation(
static_cast<f32
>(frame) *
160 (
static_cast<f32
>(-SPIN_RATE) * DEG2RAD),
162 m.setBase(3, EGG::Vector3f::zero);
163 m_forward = m.ps_multVector(m_forward);
171 if (m_railInterpolator->segmentT() > 0.6f && m_currentAnim == Animation::Move) {
172 changeAnimation(Animation::Jump);
177void ObjectHeyho::calcStateTransition() {
178 if (m_railInterpolator->curPoint().setting[1] == 0 ||
179 m_railInterpolator->nextPoint().setting[1] == 0) {
180 if (m_currentStateId != 0) {
181 m_currentStateId = 0;
184 if (m_currentStateId != 1) {
185 m_currentStateId = 1;
191void ObjectHeyho::calcMotion() {
193 f32 sqVel = m_maxVelSq - m_accel * (pos().y - m_midpoint.y);
197 m_currentVel = EGG::Mathf::sqrt(sqVel);
198 m_railInterpolator->setCurrVel(m_currentVel);
200 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
204 m_launchVel = m_currentVel;
205 if (m_currentVel > 1.0f) {
210 if (m_currentStateId == 0 && !m_floorCollision) {
211 const auto &curPos = m_railInterpolator->curPos();
212 setPos(EGG::Vector3f(curPos.x, pos().y, curPos.z));
214 setPos(m_railInterpolator->curPos());
217 m_currentVel -= 1.0f;
218 setPos(EGG::Vector3f(pos().x, m_currentVel + pos().y, pos().z));
223 if (m_currentVel < 0.0f &&
224 EGG::Mathf::abs(pos().y - m_railInterpolator->curPos().y) <= -m_currentVel) {
225 m_currentVel = m_launchVel;
231void ObjectHeyho::calcInterp() {
232 m_up = Interpolate(0.2f, m_up, m_floorNrm);
234 m_forward.normalise2();
235 setMatrixTangentTo(m_up, m_forward);
@ COL_TYPE_INVISIBLE_WALL
Solid wall that is (typically) invisible.
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
#define KCL_TYPE_VEHICLE_COLLIDEABLE
0xEAF8BDFF
Base class that represents different "states" for an object.