3#include "game/kart/KartCollide.hh"
4#include "game/kart/KartMove.hh"
5#include "game/kart/KartParam.hh"
6#include "game/kart/KartPhysics.hh"
7#include "game/kart/KartState.hh"
9#include "game/system/KPadController.hh"
11#include <egg/math/Math.hh>
16KartJump::KartJump(KartMove *move) : m_move(move) {
24KartJump::~KartJump() =
default;
27void KartJump::calcRot() {
28 m_angleDelta *= m_angleDeltaFactor;
29 m_angleDelta = std::max(m_angleDelta, m_properties.angleDeltaMin);
30 m_angleDeltaFactor -= m_angleDeltaFactorDec;
31 m_angleDeltaFactor = std::max(m_angleDeltaFactor, m_properties.angleDeltaFactorMin);
32 m_angle += m_angleDelta;
33 m_angle = std::min(m_angle, m_finalAngle);
36 case TrickType::KartFlipTrickZ:
37 m_rot.setRPY(
EGG::Vector3f(0.0f, 0.0f, -(m_angle * DEG2RAD) * m_rotSign));
39 case TrickType::FlipTrickYLeft:
40 case TrickType::FlipTrickYRight:
41 m_rot.setRPY(
EGG::Vector3f(0.0f, m_angle * DEG2RAD * m_rotSign, 0.0f));
47 physics()->composeStuntRot(m_rot);
51void KartJump::setupProperties() {
52 static constexpr std::array<TrickProperties, 3> TRICK_PROPERTIES = {{
53 {11.0f, 1.5f, 0.9f, 0.0018f},
54 {14.0f, 1.5f, 0.9f, 0.0006f},
55 {7.5f, 2.5f, 0.93f, 0.05f},
58 static constexpr std::array<f32, 3> FINAL_ANGLES = {{
64 if (m_variant == SurfaceVariant::SingleFlipTrick) {
65 m_properties = TRICK_PROPERTIES[0];
66 m_finalAngle = FINAL_ANGLES[0];
67 }
else if (m_variant == SurfaceVariant::StuntTrick) {
68 m_properties = TRICK_PROPERTIES[1];
69 m_finalAngle = FINAL_ANGLES[1];
70 }
else if (m_type == TrickType::BikeSideStuntTrick) {
71 m_properties = TRICK_PROPERTIES[2];
72 m_finalAngle = FINAL_ANGLES[2];
75 m_angleDelta = m_properties.initialAngleDiff;
76 m_angleDeltaFactorDec = m_properties.angleDiffMulDec;
78 m_angleDeltaFactor = 1.0f;
82void KartJump::reset() {
88 if (!state()->isTrickStart()) {
92 if (m_move->speedRatioCapped() > 0.5f) {
93 s32 boostRampType = state()->boostRampType();
95 if (boostRampType == 0) {
96 m_variant = SurfaceVariant::StuntTrick;
97 }
else if (boostRampType == 1) {
98 m_variant = SurfaceVariant::SingleFlipTrick;
100 m_variant = SurfaceVariant::DoubleFlipTrick;
106 state()->setTrickStart(
false);
110void KartJump::calc() {
111 m_cooldown = std::max(0, m_cooldown - 1);
113 if (state()->isTrickRot()) {
120bool KartJump::someFlagCheck() {
121 return state()->isInAction() || state()->isTrickStart() || state()->isInATrick() ||
122 state()->isOverZipper();
126void KartJump::calcInput() {
127 constexpr s16 TRICK_ALLOW_TIMER = 14;
129 System::Trick trick = inputs()->currentState().trick;
131 if (!someFlagCheck() && trick != System::Trick::None) {
133 m_nextAllowTimer = TRICK_ALLOW_TIMER;
136 u32 airtime = state()->airtime();
137 if (airtime == 0 || m_nextAllowTimer < 1 || airtime > 10 ||
138 (!state()->isTrickable() && state()->boostRampType() < 0) || someFlagCheck()) {
139 m_nextAllowTimer = std::max(0, m_nextAllowTimer - 1);
142 state()->setTrickStart(
true);
144 if (state()->isRampBoost()) {
145 m_boostRampEnabled =
true;
148 if (state()->isTouchingGround() &&
149 collide()->surfaceFlags().offBit(KartCollide::eSurfaceFlags::BoostRamp)) {
150 m_boostRampEnabled =
false;
155void KartJump::end() {
156 if (state()->isTrickRot()) {
157 physics()->composeDecayingStuntRot(m_rot);
160 state()->setInATrick(
false);
161 state()->setTrickRot(
false);
162 m_boostRampEnabled =
false;
167 static constexpr std::array<std::array<AngleProperties, 3>, 3> ANGLE_PROPERTIES = {{
185 f32 vel1YDot = m_move->vel1Dir().dot(EGG::Vector3f::ey);
186 EGG::Vector3f vel1YCross = m_move->vel1Dir().cross(EGG::Vector3f::ey);
187 f32 vel1YCrossMag = vel1YCross.
length();
188 f32 pitch = EGG::Mathf::abs(EGG::Mathf::atan2(vel1YCrossMag, vel1YDot));
189 f32 angle = 90.0f - (pitch * RAD2DEG);
190 u32 weightClass =
static_cast<u32
>(param()->stats().weightClass);
191 f32 targetAngle = ANGLE_PROPERTIES[weightClass][
static_cast<u32
>(m_variant)].targetAngle;
193 if (state()->isJumpPad() || angle > targetAngle) {
197 f32 rotAngle = ANGLE_PROPERTIES[weightClass][
static_cast<u32
>(m_variant)].rotAngle;
199 if (angle + rotAngle > targetAngle) {
200 rotAngle = targetAngle - angle;
206 m_move->setVel1Dir(m_move->dir());
213 state()->setInATrick(
true);
218void KartJump::init() {
219 if (m_variant == SurfaceVariant::DoubleFlipTrick) {
220 m_type = TrickType::StuntTrickBasic;
224 if (m_nextTrick < System::Trick::Left) {
225 m_type = TrickType::KartFlipTrickZ;
226 m_rotSign = (m_nextTrick == System::Trick::Up) ? -1.0f : 1.0f;
228 m_type =
static_cast<TrickType
>(m_nextTrick);
229 m_rotSign = (m_type == TrickType::FlipTrickYRight) ? -1.0f : 1.0f;
233 state()->setTrickRot(
true);
236KartJumpBike::KartJumpBike(KartMove *move) : KartJump(move) {}
239KartJumpBike::~KartJumpBike() =
default;
242void KartJumpBike::calcRot() {
244 constexpr f32 PI_OVER_9 = 0.34906584f;
246 constexpr f32 PI_OVER_3 = 1.0471976f;
248 m_angleDelta *= m_angleDeltaFactor;
249 m_angleDelta = std::max(m_angleDelta, m_properties.angleDeltaMin);
250 m_angleDeltaFactor -= m_angleDeltaFactorDec;
251 m_angleDeltaFactor = std::max(m_angleDeltaFactor, m_properties.angleDeltaFactorMin);
252 m_angle += m_angleDelta;
253 m_angle = std::min(m_angle, m_finalAngle);
256 case TrickType::BikeFlipTrickNose:
257 case TrickType::BikeFlipTrickTail: {
259 m_rot.setRPY(angles);
261 case TrickType::FlipTrickYLeft:
262 case TrickType::FlipTrickYRight: {
264 m_rot.setRPY(angles);
266 case TrickType::BikeSideStuntTrick: {
267 f32 sin = EGG::Mathf::SinFIdx(m_angle * DEG2FIDX);
269 (sin * m_rotSign) * PI_OVER_9);
270 m_rot.setRPY(angles);
276 physics()->composeStuntRot(m_rot);
281 KartJump::start(left);
288void KartJumpBike::init() {
289 constexpr f32 DOUBLE_FLIP_TRICK_FINAL_ANGLE = 180.0f;
291 if (m_variant == SurfaceVariant::DoubleFlipTrick) {
292 if (m_nextTrick < System::Trick::Left) {
296 m_type = TrickType::BikeSideStuntTrick;
297 m_rotSign = (m_nextTrick == System::Trick::Right) ? -1.0f : 1.0f;
299 m_finalAngle = DOUBLE_FLIP_TRICK_FINAL_ANGLE;
301 m_type =
static_cast<TrickType
>(m_nextTrick);
303 (m_type == TrickType::FlipTrickYRight || m_type == TrickType::BikeFlipTrickTail) ?
309 state()->setTrickRot(
true);
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.
Responsible for reacting to player inputs and moving the bike.
virtual void cancelWheelie()
Clears the wheelie bit flag and resets the rotation decrement.
Pertains to kart-related functionality.
f32 length() const
The square root of the vector's dot product.