1#include "ObjectHeyho.hh"
3#include "game/field/CollisionDirector.hh"
4#include "game/field/RailManager.hh"
10 : ObjectCollidable(params), StateManager(this), m_color(params.setting(1)) {
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 m_pos = m_railInterpolator->curPos();
37 m_flags.setBit(eFlags::Position);
38 m_currentVel = EGG::Mathf::sqrt(
39 m_maxVelSq - m_accel * (m_railInterpolator->curPos().y - m_midpoint.y));
41 m_transformOffset = m_railInterpolator->curTangentDir() * m_currentVel;
42 m_floorCollision =
false;
43 m_up = EGG::Vector3f::ey;
44 m_forward = EGG::Vector3f::ez;
48 changeAnimation(Animation::Move);
52void ObjectHeyho::calc() {
53 calcStateTransition();
60void ObjectHeyho::loadAnims() {
61 std::array<const char *, 4> names = {{
68 std::array<Render::AnmType, 4> types = {{
75 linkAnims(names, types);
79void ObjectHeyho::calcCollisionTransform() {
80 auto *objCol = collision();
89 objCol->transform(m, m_scale, m_transformOffset);
93void ObjectHeyho::calcMove() {
94 m_forward = m_railInterpolator->nextPoint().pos - m_railInterpolator->curPoint().pos;
95 m_floorCollision =
false;
99 if (CollisionDirector::Instance()->checkSphereFull(COLLISION_RADIUS, m_pos + COLLISION_OFFSET,
101 m_floorCollision =
true;
102 if (info.floorDist > -std::numeric_limits<f32>::min()) {
103 m_floorNrm = info.floorNrm;
109 m_pos = m_pos + info.tangentOff - m_floorNrm * 60.0f;
110 m_flags.setBit(eFlags::Position);
112 if (m_currentAnim == Animation::Jumped) {
113 const auto *anim = m_drawMdl->anmMgr()->activeAnim(Render::AnmType::Chr);
114 if (anim->frame() >= anim->frameCount()) {
115 changeAnimation(Animation::Move);
122void ObjectHeyho::calcJump() {
123 constexpr s16 SPIN_DELAY_FRAMES = 5;
124 constexpr s16 SPIN_RATE = 12;
125 constexpr s16 SPIN_DEGREES = 720;
127 m_floorCollision =
false;
132 if (CollisionDirector::Instance()->checkSphereFull(COLLISION_RADIUS, m_pos + COLLISION_OFFSET,
134 m_floorCollision =
true;
135 if (info.floorDist > -std::numeric_limits<f32>::min()) {
136 m_floorNrm = info.floorNrm;
142 m_pos.x = m_pos.x + info.tangentOff.x - m_floorNrm.x * 60.0f;
143 m_pos.z = m_pos.z + info.tangentOff.z - m_floorNrm.z * 60.0f;
144 m_flags.setBit(eFlags::Position);
147 m_forward = m_railInterpolator->nextPoint().pos - m_railInterpolator->curPoint().pos;
148 if (m_currentAnim == Animation::Jump) {
149 m_currentAnim = Animation::Jumped;
152 m_floorCollision =
false;
153 const auto &curPos = m_railInterpolator->curPoint().pos;
154 const auto &nextPos = m_railInterpolator->nextPoint().pos;
156 m_forward = (nextPos.y > curPos.y ? nextPos : curPos) - m_midpoint;
161 s16 frame = m_spinFrame - SPIN_DELAY_FRAMES;
162 if (frame >= 0 && frame <= SPIN_DEGREES / SPIN_RATE) {
165 (
static_cast<f32
>(-SPIN_RATE) * DEG2RAD),
167 m.
setBase(3, EGG::Vector3f::zero);
176 if (m_railInterpolator->segmentT() > 0.6f && m_currentAnim == Animation::Move) {
177 changeAnimation(Animation::Jump);
182void ObjectHeyho::calcStateTransition() {
183 if (m_railInterpolator->curPoint().setting[1] == 0 ||
184 m_railInterpolator->nextPoint().setting[1] == 0) {
185 if (m_currentStateId != 0) {
186 m_currentStateId = 0;
189 if (m_currentStateId != 1) {
190 m_currentStateId = 1;
196void ObjectHeyho::calcMotion() {
198 f32 sqVel = m_maxVelSq - m_accel * (m_pos.y - m_midpoint.y);
202 m_currentVel = EGG::Mathf::sqrt(sqVel);
203 m_railInterpolator->setCurrVel(m_currentVel);
205 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
209 m_launchVel = m_currentVel;
210 if (m_currentVel > 1.0f) {
215 if (m_currentStateId == 0 && !m_floorCollision) {
216 const auto &curPos = m_railInterpolator->curPos();
219 m_flags.setBit(eFlags::Position);
221 m_pos = m_railInterpolator->curPos();
222 m_flags.setBit(eFlags::Position);
225 m_currentVel -= 1.0f;
226 m_pos.y = m_currentVel + m_pos.y;
227 m_flags.setBit(eFlags::Position);
232 if (m_currentVel < 0.0f &&
233 EGG::Mathf::abs(m_pos.y - m_railInterpolator->curPos().y) <= -m_currentVel) {
234 m_currentVel = m_launchVel;
240void ObjectHeyho::calcInterp() {
241 m_up = Interpolate(0.2f, m_up, m_floorNrm);
243 m_forward.normalise2();
244 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
Matrix34f multiplyTo(const Matrix34f &rhs) const
Multiplies two matrices.
void setBase(size_t col, const Vector3f &base)
Sets one column of a matrix.
void setAxisRotation(f32 angle, const Vector3f &axis)
Rotates the matrix about an axis.
Vector3f ps_multVector(const Vector3f &vec) const
Paired-singles impl. of multVector.