3#include "game/kart/CollisionGroup.hh"
4#include "game/kart/KartCollide.hh"
5#include "game/kart/KartDynamics.hh"
6#include "game/kart/KartJump.hh"
7#include "game/kart/KartMove.hh"
9#include "game/system/RaceManager.hh"
20static constexpr std::array<StartBoostEntry, 6> START_BOOST_ENTRIES = {{
30KartState::KartState() {
44void KartState::init() {
49void KartState::reset() {
59 m_jumpPadVariant = -1;
60 m_halfPipeInvisibilityTimer = 0;
71 const auto *raceMgr = System::RaceManager::Instance();
72 if (raceMgr->isStageReached(System::RaceManager::Stage::Race)) {
75 const auto ¤tState = inputs()->currentState();
76 const auto &lastState = inputs()->lastState();
102 if (!raceMgr->isStageReached(System::RaceManager::Stage::Countdown)) {
106 const auto ¤tState = inputs()->currentState();
120 collide()->calcBeforeRespawn();
123 collide()->calcBoundingRadius();
127void KartState::resetFlags() {
141 m_bCollidingOffroad =
false;
142 m_bJumpPadDisableYsusForce =
false;
166 if (m_hwgTimer > 0) {
167 if (--m_hwgTimer == 0) {
169 m_bSomethingWallCollision =
false;
174 bool softWallCollision =
false;
176 if (collide()->someSoftWallTimer() > 0) {
177 if (collide()->someNonSoftWallTimer() == 0) {
178 softWallCollision =
true;
180 f32 softSusp = collide()->suspBottomHeightSoftWall() /
181 static_cast<f32
>(collide()->someSoftWallTimer());
182 f32 nonSusp = collide()->suspBottomHeightNonSoftWall() /
183 static_cast<f32
>(collide()->someNonSoftWallTimer());
185 if (softSusp - nonSusp >= 40.0f) {
186 m_bSoftWallDrift =
false;
188 softWallCollision =
true;
193 u16 wheelCollisions = 0;
194 u16 softWallCount = 0;
196 bool trickable =
false;
198 for (
u16 tireIdx = 0; tireIdx < tireCount(); ++tireIdx) {
199 const auto &colData = collisionData(tireIdx);
200 if (hasFloorCollision(tirePhysics(tireIdx))) {
201 m_top += colData.floorNrm;
202 trickable = trickable || colData.bTrickable;
206 if (softWallCollision && colData.bSoftWall) {
208 wallNrm += colData.noBounceWallNrm;
212 if (wheelCollisions > 0) {
214 if (wheelCollisions == tireCount()) {
222 m_top += colData.floorNrm;
223 trickable = trickable || colData.bTrickable;
226 halfPipe()->end(
true);
230 bool hitboxGroupSoftWallCollision =
false;
231 if (softWallCollision && colData.bSoftWall) {
232 hitboxGroupSoftWallCollision =
true;
234 wallNrm += colData.wallNrm;
237 bool bVar3 = colData.bInvisibleWallOnly && m_halfPipeInvisibilityTimer > 0;
238 m_halfPipeInvisibilityTimer = std::max(0, m_halfPipeInvisibilityTimer - 1);
253 if (!wasWallCollision) {
259 if (m_hwgTimer == 0 && colData.movement.y > 1.0f) {
263 if (movement.
dot(EGG::Vector3f::ey) > 0.8f &&
264 colData.wallNrm.
dot(EGG::Vector3f::ey) > 0.85f &&
265 (movement.x * colData.wallNrm.x + movement.z * colData.wallNrm.z < 0.0f ||
266 collide()->colPerpendicularity() >= 1.0f)) {
267 colData.wallNrm.y = 0.0f;
269 wallNrm = colData.wallNrm;
271 if (wallNrm.
length() < 0.05f) {
282 collide()->surfaceFlags().offBit(KartCollide::eSurfaceFlags::StopHalfPipeState)) {
286 if (softWallCount > 0 || hwg) {
288 m_softWallSpeed = wallNrm;
290 if (softWallCount > 0 && !
m_bHop) {
291 m_bSoftWallDrift =
true;
298 if (hitboxGroupSoftWallCollision || hwg || isBike()) {
299 m_bSomethingWallCollision =
true;
309 m_trickableTimer = std::max(0, m_trickableTimer - 1);
311 if (wheelCollisions < 1 && !colData.
bFloor) {
312 if (wasTouchingGround) {
316 if (++m_airtime > 20) {
323 m_bAfterCannon =
false;
326 m_bActionMidZipper =
false;
327 m_bEndHalfPipe =
false;
331 halfPipe()->end(
true);
335 m_trickableTimer = 3;
338 m_bTrickable = m_trickableTimer > 0;
341 m_bJumpPadMushroomCollision =
false;
344 if (!wasTouchingGround) {
348 if (m_bInATrick && jump()->cooldown() == 0) {
350 dynamics()->setForceUpright(
true);
363 constexpr f32 START_BOOST_DELTA_ONE = 0.02f;
364 constexpr f32 START_BOOST_DELTA_TWO = 0.002f;
365 constexpr f32 START_BOOST_FALLOFF = 0.96f;
381 if (System::RaceManager::Instance()->getCountdownTimer() != 0) {
390 for (
size_t i = 1; i < START_BOOST_ENTRIES.size(); ++i) {
413 move()->burnout().start();
415 move()->applyStartBoost(START_BOOST_ENTRIES[idx].frames);
452 m_bSlipdriftCharge =
false;
455 m_bRampBoost =
false;
461 m_bTriggerRespawn =
false;
462 m_bCannonStart =
false;
464 m_bTrickStart =
false;
469 m_bJumpPadMushroomCollision =
false;
478 m_bJumpPadMushroomVelYInc =
false;
482 m_bTrickable =
false;
487 m_bWheelieRot =
false;
488 m_bSkipWheelCalc =
false;
489 m_bJumpPadMushroomTrigger =
false;
490 m_bNoSparkInvisibleWall =
false;
491 m_bCollidingOffroad =
false;
492 m_bInRespawn =
false;
493 m_bAfterRespawn =
false;
495 m_bJumpPadFixedSpeed =
false;
496 m_bJumpPadDisableYsusForce =
false;
502 m_bSomethingWallCollision =
false;
503 m_bSoftWallDrift =
false;
505 m_bAfterCannon =
false;
506 m_bActionMidZipper =
false;
508 m_bEndHalfPipe =
false;
bool m_bZipperBoost
Set when boosting after landing from a zipper.
bool m_bRespawnKillY
Set while respawning to cap external velocity at 0.
bool m_bBoost
Set while in a boost.
bool m_bChargeStartBoost
Like m_bAccelerate but during countdown.
bool m_bHop
Set while we are in a drift hop. Clears when we land.
bool m_bBeforeRespawn
Set on respawn collision, cleared on position snap.
void clearBitfield1()
Helper function to clear all bit flags at 0x8-0xB in KartState.
size_t m_startBoostIdx
Used to map m_startBoostCharge to a start boost duration.
void clearBitfield0()
Helper function to clear all bit flags at 0x4-0x7 in KartState.
bool m_bHopStart
Set if m_bDriftInput was toggled on this frame.
bool m_bHWG
Set when "Horizontal Wall Glitch" is active.
bool m_bBurnout
Set during a burnout on race start.
bool m_bDriftAuto
Currently in a drift w/ automatic.
bool m_bStickRight
Set on right stick input. Mutually exclusive to m_bStickLeft.
void clearBitfield2()
Helper function to clear all bit flags at 0xC-0xF in KartState.
void calcStartBoost()
STAGE 1 - Each frame, calculates the start boost charge.
bool m_bRejectRoad
Collision which causes a change in the player's pos and rot.
bool m_bWallCollision
Set if we are colliding with a wall.
bool m_bZipperTrick
Set while tricking mid-air from a zipper.
s16 m_wallBonkTimer
2f counter that stunts your speed after hitting a wall.
void calcCollisions()
Each frame, checks for collision and saves relevant bit flags.
bool m_bAllWheelsCollision
Set when all wheels are touching floor collision.
bool m_bDriftInput
A "fake" button, normally set if you meet the speed requirement to hop.
void clearBitfield3()
Helper function to clear all bit flags at 0x10-0x13 in KartState.
void calcHandleStartBoost()
On countdown end, calculates and applies our start boost charge.
f32 m_stickY
One of 15 discrete stick values from [-1.0, 1.0].
bool m_bChargingSsmt
Tracks whether we are charging a stand-still mini-turbo.
bool m_bAccelerateStart
Set if m_bAccelerate was toggled on this frame.
bool m_bDriftManual
Currently in a drift w/ manual.
bool m_bAutoDrift
True if auto transmission, false if manual.
void handleStartBoost(size_t idx)
Applies the relevant start boost duration.
void calc()
Every frame, resets the input state and saves collision-related bit flags.
bool m_bZipperStick
Set while mid-air and still influenced by the zipper.
bool m_bMushroomBoost
Set while we are in a mushroom boost.
bool m_bDisableBackwardsAccel
Enforces a 20f delay when reversing after charging SSMT.
bool m_bHalfPipeRamp
Set while colliding with zipper KCL.
f32 m_stickX
One of 15 discrete stick values from [-1.0, 1.0].
bool m_bVehicleBodyFloorCollision
Set if the vehicle body is colliding with the floor.
bool m_bBoostOffroadInvincibility
Set if we should ignore offroad slowdown this frame.
bool m_bAnyWheelCollision
Set when any wheel is touching floor collision.
bool m_bStickyRoad
Like the rBC stairs.
bool m_bWall3Collision
Set when colliding with wall KCL COL_TYPE_WALL_2.
f32 m_startBoostCharge
0-1 representation of start boost charge. Burnout if >0.95f.
bool m_bWheelie
Set while we are in a wheelie (even during the countdown).
bool m_bZipperInvisibleWall
Set when colliding with invisible wall above a zipper.
bool m_bTouchingGround
Set when any part of the vehicle is colliding with floor KCL.
bool m_bRejectRoadTrigger
e.g. DK Summit ending, and Maple Treeway side walls.
bool m_bStickLeft
Set on left stick input. Mutually exclusive to m_bStickRight.
void calcInput()
Each frame, read input and save related bit flags. Also handles start boosts.
bool m_bWallCollisionStart
Set if we have just started colliding with a wall.
bool m_bOverZipper
Set while mid-air from a zipper.
bool m_bAccelerate
Accel button is pressed.
void resetEjection()
Resets certain bitfields pertaining to ejections (reject road, half pipe zippers, etc....
bool m_bGroundStart
Set first frame landing from airtime.
bool m_bAirtimeOver20
Set after 20 frames of airtime, resets on landing.
Pertains to kart-related functionality.
f32 normalise()
Normalizes the vector and returns the original length.
f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
f32 length() const
The square root of the vector's dot product.
Information about the current collision and its properties.
bool bFloor
Set if colliding with KCL which satisfies KCL_TYPE_FLOOR.
bool bWall3
Set if colliding with COL_TYPE_WALL_2.
bool bWall
Set if colliding with KCL which satisfies KCL_TYPE_WALL.