1#include "KartAction.hh"
3#include "game/kart/KartMove.hh"
4#include "game/kart/KartPhysics.hh"
5#include "game/kart/KartState.hh"
7#include "game/item/ItemDirector.hh"
8#include "game/item/KartItem.hh"
10#include <egg/math/Math.hh>
15KartAction::KartAction()
16 : m_currentAction(Action::None), m_hitDepth(
EGG::Vector3f::zero),
17 m_translation(
EGG::Vector3f::ez), m_onStart(nullptr), m_onCalc(nullptr), m_onEnd(nullptr),
18 m_actionParams(nullptr), m_rotationParams(nullptr), m_priority(0) {}
21KartAction::~KartAction() =
default;
24void KartAction::init() {
25 m_currentAction = Action::None;
26 m_flags.makeAllZero();
30void KartAction::calc() {
31 if (m_currentAction == Action::None || !m_onCalc) {
35 if (calcCurrentAction()) {
41void KartAction::calcVehicleSpeed() {
42 move()->setSpeed(m_actionParams->calcSpeedMult * move()->speed());
49bool KartAction::start(Action action) {
50 ASSERT(action != Action::None);
52 if (state()->isInRespawn() || state()->isAfterRespawn() || state()->isBeforeRespawn() ||
53 state()->isInCannon()) {
57 if (state()->isZipperStick()) {
64 action = Action::UNK_1;
71 size_t actionIdx =
static_cast<size_t>(action);
73 if (m_currentAction != Action::None && s_actionParams[actionIdx].priority <= m_priority) {
78 m_currentAction = action;
79 m_actionParams = &s_actionParams[actionIdx];
80 m_priority = m_actionParams->priority;
81 m_onStart = s_onStart[actionIdx];
82 m_onCalc = s_onCalc[actionIdx];
83 m_onEnd = s_onEnd[actionIdx];
84 state()->setInAction(
true);
86 m_flags.makeAllZero();
100void KartAction::startRotation(
size_t idx) {
101 m_rotation = EGG::Quatf::ident;
104 if (speed() < 0.0f) {
108 m_rotationDirection = dir.cross(bodyFront()).
dot(bodyUp()) > 0.0f ? 1.0f : -1.0f;
110 m_flags.setBit(eFlags::Rotating);
114void KartAction::calcSideFromHitDepth() {
115 m_hitDepth.normalise();
116 m_side = m_hitDepth.perpInPlane(move()->smoothedUp(),
true);
118 if (m_side.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
119 m_side = EGG::Vector3f::ey;
124void KartAction::calcSideFromHitDepthAndTranslation() {
125 calcSideFromHitDepth();
128 f32 sign = (cross.y > 0.0f) ? 1.0f : -1.0f;
130 EGG::Vector3f worldSide = EGG::Vector3f::ey.cross(m_translation);
133 m_side = worldSide.
perpInPlane(move()->smoothedUp(),
true);
135 if (m_side.squaredLength() > std::numeric_limits<f32>::epsilon()) {
138 m_side = EGG::Vector3f::ey;
143void KartAction::end() {
144 state()->setInAction(
false);
145 dynamics()->setForceUpright(
true);
147 m_currentAction = Action::None;
149 m_flags.makeAllZero();
155bool KartAction::calcCurrentAction() {
157 return (this->*m_onCalc)();
161void KartAction::calcEndAction(
bool endArg) {
162 if (m_currentAction == Action::None) {
167 (this->*m_onEnd)(endArg);
173bool KartAction::calcRotation() {
174 if (!m_rotationParams) {
179 if (m_currentAngle > m_finalAngle * m_rotationParams->slowdownThreshold) {
180 m_angleIncrement *= m_multiplier;
181 if (m_rotationParams->minAngleIncrement > m_angleIncrement) {
182 m_angleIncrement = m_rotationParams->minAngleIncrement;
185 m_multiplier -= m_multiplierDecrement;
186 if (m_rotationParams->minMultiplier > m_multiplier) {
187 m_multiplier = m_rotationParams->minMultiplier;
191 m_currentAngle += m_angleIncrement;
192 if (m_finalAngle < m_currentAngle) {
193 m_currentAngle = m_finalAngle;
201void KartAction::calcUp() {
202 m_up += (move()->up() - m_up) * 0.3f;
206void KartAction::calcLanding() {
207 if (m_currentAngle < m_targetRot || !state()->isTouchingGround()) {
211 m_flags.setBit(eFlags::Landing);
214 dynamics()->setForceUpright(
false);
217 physics()->composeDecayingExtraRot(m_rotation);
221void KartAction::startLaunch(f32 extVelScalar, f32 extVelKart, f32 extVelBike, f32 numRotations,
223 m_targetRot = 360.0f * numRotations;
226 extVel.y = isBike() ? extVelBike : extVelKart;
229 m_hitDepth = move()->dir();
230 calcSideFromHitDepth();
231 }
else if (param6 == 1) {
232 calcSideFromHitDepth();
233 extVel += extVelScalar * m_side;
234 }
else if (param6 == 2) {
235 calcSideFromHitDepthAndTranslation();
236 extVel += extVelScalar * m_side;
239 setRotation(
static_cast<size_t>(numRotations + 3.0f));
240 m_rotAxis = move()->smoothedUp().cross(m_side);
242 dynamics()->setExtVel(dynamics()->extVel() + extVel);
246void KartAction::activateCrush(
u16 timer) {
247 move()->activateCrush(m_crushTimer + timer);
248 Item::ItemDirector::Instance()->kartItem(0).clear();
252void KartAction::applyStartSpeed() {
253 move()->setSpeed(m_actionParams->startSpeedMult * move()->speed());
254 if (m_actionParams->startSpeedMult == 0.0f) {
255 move()->clearDrift();
260void KartAction::setRotation(
size_t idx) {
261 ASSERT(idx - 1 < s_rotationParams.size());
262 m_rotationParams = &s_rotationParams[--idx];
264 m_finalAngle = m_rotationParams->finalAngle;
265 m_angleIncrement = m_rotationParams->initialAngleIncrement;
266 m_multiplierDecrement = m_rotationParams->initialMultiplierDecrement;
267 m_currentAngle = 0.0f;
275void KartAction::startStub() {}
278void KartAction::startAction1() {
283void KartAction::startAction2() {
284 constexpr f32 EXT_VEL_SCALAR = 0.0f;
285 constexpr f32 EXT_VEL_KART = 30.0f;
286 constexpr f32 EXT_VEL_BIKE = 30.0f;
287 constexpr f32 NUM_ROTATIONS = 1.0f;
289 startLaunch(EXT_VEL_SCALAR, EXT_VEL_KART, EXT_VEL_BIKE, NUM_ROTATIONS, 0);
293void KartAction::startAction3() {
294 constexpr f32 EXT_VEL_SCALAR = 25.0f;
295 constexpr f32 EXT_VEL_KART = 30.0f;
296 constexpr f32 EXT_VEL_BIKE = 30.0f;
297 constexpr f32 NUM_ROTATIONS = 1.0f;
299 startLaunch(EXT_VEL_SCALAR, EXT_VEL_KART, EXT_VEL_BIKE, NUM_ROTATIONS, 1);
300 Item::ItemDirector::Instance()->kartItem(0).clear();
304void KartAction::startAction5() {
305 constexpr f32 EXT_VEL_SCALAR = 13.0f;
306 constexpr f32 EXT_VEL_KART = 40.0f;
307 constexpr f32 EXT_VEL_BIKE = 45.0f;
308 constexpr f32 NUM_ROTATIONS = 1.0f;
310 startLaunch(EXT_VEL_SCALAR, EXT_VEL_KART, EXT_VEL_BIKE, NUM_ROTATIONS, 2);
314void KartAction::startAction9() {
319void KartAction::startLongPressAction() {
320 constexpr u32 ACTION_DURATION = 90;
321 constexpr u16 CRUSH_DURATION = 480;
323 m_crushTimer = ACTION_DURATION;
324 activateCrush(CRUSH_DURATION);
328void KartAction::startShortPressAction() {
329 constexpr u32 ACTION_DURATION = 30;
330 constexpr u16 CRUSH_DURATION = 240;
332 m_crushTimer = ACTION_DURATION;
333 activateCrush(CRUSH_DURATION);
340bool KartAction::calcStub() {
345bool KartAction::calcAction1() {
347 bool finished = calcRotation();
349 m_rotation.setAxisRotation(DEG2RAD * (m_currentAngle * m_rotationDirection), m_up);
350 physics()->composeExtraRot(m_rotation);
355bool KartAction::calcLaunchAction() {
356 constexpr u32 ACTION_DURATION = 100;
358 if (m_flags.offBit(eFlags::Landing)) {
363 bool actionEnded = m_frame >= ACTION_DURATION;
366 if (m_flags.offBit(eFlags::Landing)) {
367 physics()->composeDecayingExtraRot(m_rotation);
369 }
else if (m_flags.offBit(eFlags::Landing)) {
370 m_rotation.setAxisRotation(DEG2RAD * m_currentAngle, m_rotAxis);
371 physics()->composeExtraRot(m_rotation);
378bool KartAction::calcPressAction() {
380 extVel.y = std::min(0.0f, extVel.y);
381 dynamics()->setExtVel(extVel);
383 return m_frame > m_crushTimer;
390void KartAction::endStub(
bool ) {}
393void KartAction::endAction1(
bool arg) {
395 physics()->composeDecayingExtraRot(m_rotation);
400void KartAction::endLaunchAction(
bool arg) {
402 physics()->composeDecayingExtraRot(m_rotation);
410const std::array<KartAction::ActionParams, KartAction::MAX_ACTION> KartAction::s_actionParams = {{
431const std::array<KartAction::RotationParams, 5> KartAction::s_rotationParams = {{
432 {10.0f, 1.5f, 0.9f, 0.005f, 0.6f, 360.0f},
433 {11.0f, 1.5f, 0.9f, 0.0028f, 0.7f, 720.0f},
434 {11.0f, 1.5f, 0.9f, 0.0028f, 0.8f, 1080.0f},
435 {7.0f, 1.5f, 0.9f, 0.005f, 0.6f, 450.0f},
436 {9.0f, 1.5f, 0.9f, 0.0028f, 0.7f, 810.0f},
439const std::array<KartAction::StartActionFunc, KartAction::MAX_ACTION> KartAction::s_onStart = {{
440 &KartAction::startStub,
441 &KartAction::startAction1,
442 &KartAction::startAction2,
443 &KartAction::startAction3,
444 &KartAction::startStub,
445 &KartAction::startAction5,
446 &KartAction::startStub,
447 &KartAction::startStub,
448 &KartAction::startStub,
449 &KartAction::startAction9,
450 &KartAction::startStub,
451 &KartAction::startStub,
452 &KartAction::startLongPressAction,
453 &KartAction::startStub,
454 &KartAction::startShortPressAction,
455 &KartAction::startStub,
456 &KartAction::startStub,
457 &KartAction::startStub,
460const std::array<KartAction::CalcActionFunc, KartAction::MAX_ACTION> KartAction::s_onCalc = {{
461 &KartAction::calcStub,
462 &KartAction::calcAction1,
463 &KartAction::calcLaunchAction,
464 &KartAction::calcLaunchAction,
465 &KartAction::calcStub,
466 &KartAction::calcLaunchAction,
467 &KartAction::calcStub,
468 &KartAction::calcStub,
469 &KartAction::calcStub,
470 &KartAction::calcAction1,
471 &KartAction::calcStub,
472 &KartAction::calcStub,
473 &KartAction::calcPressAction,
474 &KartAction::calcStub,
475 &KartAction::calcPressAction,
476 &KartAction::calcStub,
477 &KartAction::calcStub,
478 &KartAction::calcStub,
481const std::array<KartAction::EndActionFunc, KartAction::MAX_ACTION> KartAction::s_onEnd = {{
482 &KartAction::endStub,
483 &KartAction::endAction1,
484 &KartAction::endLaunchAction,
485 &KartAction::endLaunchAction,
486 &KartAction::endStub,
487 &KartAction::endLaunchAction,
488 &KartAction::endStub,
489 &KartAction::endStub,
490 &KartAction::endStub,
491 &KartAction::endAction1,
492 &KartAction::endStub,
493 &KartAction::endStub,
494 &KartAction::endStub,
495 &KartAction::endStub,
496 &KartAction::endStub,
497 &KartAction::endStub,
498 &KartAction::endStub,
499 &KartAction::endStub,
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.
Vector3f perpInPlane(const EGG::Vector3f &rhs, bool normalise) const
Calculates the orthogonal vector, based on the plane defined by this vector and rhs.