1#include "KartReject.hh"
3#include "game/kart/KartDynamics.hh"
4#include "game/kart/KartMove.hh"
5#include "game/kart/KartParam.hh"
6#include "game/kart/KartState.hh"
8#include "game/field/CollisionDirector.hh"
9#include "game/field/CourseColMgr.hh"
11#include <egg/math/Math.hh>
12#include <egg/math/Quat.hh>
17KartReject::KartReject() =
default;
20KartReject::~KartReject() =
default;
23void KartReject::reset() {
28void KartReject::calcRejectRoad() {
29 auto &status = KartObjectProxy::status();
31 if (status.
onBit(eStatus::InAction)) {
38 f32 cos = down.
dot(move()->lastDir());
39 f32 sin = down.cross(move()->lastDir()).
length();
40 f32 angle = EGG::Mathf::atan2(sin, cos);
41 angle = angle > 0.0f ? angle : -angle;
47 if (move()->up().dot(EGG::Vector3f::ey) < -0.7f) {
52 if (angle > minAngle) {
53 angle = 0.05f * (angle - 60.0f);
55 (1.0f + angle * move()->speedRatio()) * dVar11 * DEG2RAD * m_rejectSign, 0.0f);
59 dynamics()->setAngVel0(EGG::Vector3f::zero);
60 dynamics()->setFullRot(local_78);
61 dynamics()->setMainRot(local_78);
66 bool didReject = calcRejection();
68 if (status.
offBit(eStatus::NoSparkInvisibleWall) && !didReject) {
69 move()->clearRejectRoad();
81 if (upXZ.
length() > 0.0f && speed() > 0.0f) {
85 if (local_88.y > 0.0f) {
87 m_rejectSign = upCross.
dot(move()->up()) > 0.0f ? 1.0f : -1.0f;
96bool KartReject::calcRejection() {
98 Field::KCLTypeMask mask = KCL_NONE;
99 auto &status = KartObjectProxy::status();
100 status.
resetBit(eStatus::NoSparkInvisibleWall);
102 f32 posScalar = 100.0f;
103 f32 radius = posScalar;
105 for (
size_t i = 0; i < 2; ++i) {
107 EGG::Vector3f worldPos = pos() + (-posScalar * move()->scale().y) * local_d0;
109 auto *colDir = Field::CollisionDirector::Instance();
110 if (!colDir->checkSphereFullPush(radius, worldPos, worldUpPos,
KCL_TYPE_B0E82DFF, &colInfo,
121 if (!calcCollision(colInfo, mask, tangentOff)) {
125 EGG::Vector3f tangentUp = (tangentOff - move()->up()) * 1.0f;
126 move()->setUp(move()->up() + tangentUp);
127 move()->setSmoothedUp(move()->up());
129 bool bVar15 = tangentOff.
dot(EGG::Vector3f::ey) < -0.17f;
130 if (bVar15 || extVel().y < 0.0f || status.
onBit(eStatus::NoSparkInvisibleWall)) {
132 colInfo.tangentOff += worldPos;
134 f32 yOffset = bsp().initialYPos * scale().y;
135 f32 speedScalar = bVar15 ?
137 static_cast<f32
>(
static_cast<f64
>(EGG::Mathf::abs(speed()) * 0.01f) - 0.3d);
138 speedScalar = std::min(1.0f, std::max(0.0f, speedScalar));
141 colInfo.tangentOff + radius * tangentOff + yOffset * tangentOff;
142 posOffset.y += move()->hopPosY();
144 setPos(pos() + posOffset * speedScalar);
148 move()->setDir(local_13c);
149 move()->setVel1Dir(local_13c);
159 auto *colDir = Field::CollisionDirector::Instance();
163 colDir->closestCollisionEntry()->variant() == 0) {
164 tangentOff = colInfo.wallNrm;
165 status().
setBit(eStatus::NoSparkInvisibleWall);
171 if (mask & halfPipeInvisMask) {
172 if (colDir->findClosestCollisionEntry(&mask, halfPipeInvisMask)) {
173 tangentOff = colInfo.wallNrm;
174 status().
setBit(eStatus::NoSparkInvisibleWall);
181 colDir->closestCollisionEntry()->attribute.onBit(
182 Field::CollisionDirector::eCollisionAttribute::RejectRoad)) {
183 tangentOff = colInfo.floorNrm;
@ COL_TYPE_HALFPIPE_INVISIBLE_WALL
Invisible wall after a half-pipe jump, like in BC.
#define KCL_TYPE_DRIVER_FLOOR
0x20E80DFF - Any KCL that the player can drive on.
#define KCL_TYPE_INVISIBLE_WALL
0x80002000
#define KCL_TYPE_B0E82DFF
0xB0E82DFF
constexpr bool offBit(Es... es) const
Checks if all of the corresponding bits for the provided enum values are off.
constexpr bool onBit(Es... es) const
Checks if any of the corresponding bits for the provided enum values are on.
constexpr TBitFlagExt< N, E > & resetBit(Es... es)
Resets the corresponding bits for the provided enum values.
constexpr TBitFlagExt< N, E > & setBit(Es... es)
Sets the corresponding bits for the provided enum values.
EGG::Vector3f bodyUp() const
Returns the second column of the rotation matrix, which is the "up" direction.
Pertains to kart-related functionality.
@ RejectRoad
Collision which causes a change in the player's pos and rot.
@ HalfPipeRamp
Set while colliding with zipper KCL.
@ Hop
Set while we are in a drift hop. Clears when we land.
@ RejectRoadTrigger
e.g. DK Summit ending, and Maple Treeway side walls.
@ OverZipper
Set while mid-air from a zipper.
@ ZipperInvisibleWall
Set when colliding with invisible wall above a zipper.
A quaternion, used to represent 3D rotation.
void normalise()
Scales the quaternion to a unit length.
Vector3f rotateVector(const Vector3f &vec) const
Rotates a vector based on the quat.
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.
Vector3f perpInPlane(const EGG::Vector3f &rhs, bool normalise) const
Calculates the orthogonal vector, based on the plane defined by this vector and rhs.