1#include "ObjectTruckWagon.hh"
3#include "game/field/CollisionDirector.hh"
4#include "game/field/Rail.hh"
5#include "game/field/RailManager.hh"
7#include "game/kart/KartCollide.hh"
8#include "game/kart/KartObject.hh"
13ObjectTruckWagonCart::ObjectTruckWagonCart(
const System::MapdataGeoObj ¶ms)
14 : ObjectCollidable(params), StateManager(this, STATE_ENTRIES), m_active(true),
15 m_vel(EGG::Vector3f::zero), m_lastVel(EGG::Vector3f::zero), m_up(EGG::Vector3f::zero),
16 m_tangent(EGG::Vector3f::zero), m_pitch(0.0f) {}
19ObjectTruckWagonCart::~ObjectTruckWagonCart() =
default;
22void ObjectTruckWagonCart::calc() {
27 switch (m_railInterpolator->calc()) {
28 case RailInterpolator::Status::SegmentEnd:
29 if (m_currentStateId != 1) {
30 u16 setting = m_railInterpolator->curPoint().setting[1];
32 m_nextStateId = setting;
36 case RailInterpolator::Status::ChangingDirection:
43 m_vel.x = m_railInterpolator->currVel() * m_railInterpolator->curTangentDir().x;
44 m_vel.z = m_railInterpolator->currVel() * m_railInterpolator->curTangentDir().z;
52void ObjectTruckWagonCart::calcCollisionTransform() {
53 auto *col = collision();
54 if (!col || !m_active) {
58 f32 yOffset = m_currentStateId == 1 ? 500.0f : 100.0f;
59 EGG::Matrix34f mat = EGG::Matrix34f::zero;
60 mat.makeT(EGG::Vector3f(0.0f, yOffset, 0.0f));
63 col->transform(m_transform.multiplyTo(mat), m_scale, m_vel);
67Kart::Reaction ObjectTruckWagonCart::onCollision(Kart::KartObject *kartObj,
68 Kart::Reaction reactionOnKart, Kart::Reaction ,
70 return kartObj->speedRatioCapped() < 0.5f ? Kart::Reaction::WallAllSpeed : reactionOnKart;
74void ObjectTruckWagonCart::calcState0() {
75 constexpr f32 RADIUS = 50.0f;
76 constexpr f32 GRAVITY = 2.0f;
77 constexpr f32 INITIAL_FALL_OFFSET = 15.0f;
79 const EGG::Vector3f &railPos = m_railInterpolator->curPos();
80 if (m_railInterpolator->curPointIdx() != 3) {
82 m_flags.setBit(eFlags::Position);
84 m_up = Interpolate(0.1f, m_up,
85 m_railInterpolator->floorNrm(m_railInterpolator->nextPointIdx()));
86 m_tangent = Interpolate(0.1f, m_tangent, m_railInterpolator->curTangentDir());
88 m_tangent.normalise2();
90 setMatrixTangentTo(m_up, m_tangent);
95 m_pos = EGG::Vector3f(railPos.x, m_pos.y - INITIAL_FALL_OFFSET, railPos.z);
96 m_flags.setBit(eFlags::Position);
99 EGG::Vector3f pos = m_pos + EGG::Vector3f(0.0f, RADIUS, 0.0f);
101 EGG::Vector3f floorNrm = m_up;
102 EGG::Vector3f tangent = m_tangent;
104 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, pos, EGG::Vector3f::inf,
109 m_pos += info.tangentOff;
110 m_flags.setBit(eFlags::Position);
112 if (info.floorDist > -std::numeric_limits<f32>::min()) {
113 floorNrm = info.floorNrm;
116 tangent = m_railInterpolator->curTangentDir();
118 m_flags.setBit(eFlags::Position);
120 m_pos.y = m_vel.y + m_pos.y;
123 m_up = Interpolate(0.1f, m_up, floorNrm);
124 m_tangent = Interpolate(0.1f, m_tangent, tangent);
126 m_tangent.normalise2();
128 setMatrixTangentTo(m_up, m_tangent);
132void ObjectTruckWagonCart::calcState1() {
133 constexpr EGG::Vector3f INITIAL_OFFSET = EGG::Vector3f(0.0f, 710.0f, 0.0f);
136 constexpr f32 SPRING_STIFFNESS = 3.9f;
137 constexpr f32 PITCH_INERTIA = 1300.0f;
138 constexpr f32 ANG_VEL_DECAY = 0.998f;
140 EGG::Vector2f lastVelXZ = EGG::Vector2f(m_lastVel.x, m_lastVel.z);
141 EGG::Vector2f velXZ = EGG::Vector2f(m_vel.x, m_vel.z);
142 f32 velMagDiff = EGG::Mathf::sqrt((velXZ - lastVelXZ).dot());
143 velMagDiff = velXZ.cross(lastVelXZ) > 0.0f ? -velMagDiff : velMagDiff;
144 f32 cos = velMagDiff * EGG::Mathf::CosFIdx(RAD2FIDX * m_pitch);
145 f32 sin = EGG::Mathf::SinFIdx(RAD2FIDX * m_pitch);
146 m_angVel = (m_angVel + (cos + -SPRING_STIFFNESS * sin) / PITCH_INERTIA) * ANG_VEL_DECAY;
149 EGG::Vector3f tanXZ = m_railInterpolator->curTangentDir();
153 mat.setAxisRotation(m_pitch, tanXZ);
154 mat.setBase(3, EGG::Vector3f::zero);
156 m_up = Interpolate(0.1f, m_up, mat.ps_multVector(EGG::Vector3f::ey));
157 m_tangent = Interpolate(0.1f, m_tangent, tanXZ);
161 m_tangent.normalise2();
162 EGG::Vector3f cross = m_up.cross(m_tangent);
165 mat.setBase(0, cross);
166 mat.setBase(1, m_up);
167 mat.setBase(2, m_tangent);
168 mat.setBase(3, EGG::Vector3f::zero);
170 m_flags.setBit(eFlags::Matrix);
172 m_transform.setBase(3, m_pos);
174 m_flags.setBit(eFlags::Position);
175 m_pos = m_railInterpolator->curPos() + INITIAL_OFFSET - mat.ps_multVector(INITIAL_OFFSET);
180void ObjectTruckWagonCart::reset(u32 idx) {
181 m_railInterpolator->init(0.0f, idx);
182 m_railInterpolator->setPerPointVelocities(
true);
184 m_pos = m_railInterpolator->curPos();
185 m_flags.setBit(eFlags::Position);
186 m_speed = m_railInterpolator->speed();
187 m_vel = m_railInterpolator->curTangentDir() * m_speed;
190 if (m_currentStateId != 1) {
191 u16 setting = m_railInterpolator->curPoint().setting[1];
193 m_nextStateId = setting;
197 m_up = EGG::Vector3f::ey;
198 m_tangent = EGG::Vector3f::ez;
204ObjectTruckWagon::ObjectTruckWagon(
const System::MapdataGeoObj ¶ms)
205 : ObjectCollidable(params), m_spawn2Frame(static_cast<s32>(params.setting(1))),
206 m_cycleDuration(static_cast<s32>(params.setting(2))) {
207 constexpr u32 CART_COUNT = 12;
210 if (params.setting(3) > 0) {
214 m_carts = owning_span<ObjectTruckWagonCart *>(CART_COUNT);
216 for (
auto *&cart : m_carts) {
217 cart =
new ObjectTruckWagonCart(params);
221 auto *rail = RailManager::Instance()->rail(params.pathId());
224 if (rail->pointCount() > 40) {
225 rail->checkSphereFull();
230ObjectTruckWagon::~ObjectTruckWagon() =
default;
233void ObjectTruckWagon::init() {
235 if (m_carts.empty()) {
239 for (
auto *&cart : m_carts) {
240 if (cart->isActive()) {
245 u16 ptCount = m_carts[0]->railInterpolator()->pointCount();
246 u32 cartCount = m_carts.size();
247 u32 halfCount = m_carts.size() / 2;
249 for (u32 i = halfCount; i < cartCount; ++i) {
250 auto *&cart = m_carts[i];
251 cart->reset(ptCount / halfCount * (cartCount - i));
252 cart->setActive(
true);
253 cart->loadAABB(0.0f);
261void ObjectTruckWagon::calc() {
262 if (m_carts.empty()) {
266 if (m_cycleFrame == m_spawn2Frame || m_cycleFrame == m_spawn2Frame + m_cycleDuration) {
267 m_carts[m_curCartIdx]->activate();
268 m_curCartIdx = (m_curCartIdx + 1) % m_carts.size();
271 m_cycleFrame = m_cycleFrame % (m_spawn2Frame + m_cycleDuration) + 1;
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.