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 size_t actionIdx =
static_cast<size_t>(action);
58 if (m_currentAction != Action::None && s_actionParams[actionIdx].priority <= m_priority) {
63 m_currentAction = action;
64 m_actionParams = &s_actionParams[actionIdx];
65 m_priority = m_actionParams->priority;
66 m_onStart = s_onStart[actionIdx];
67 m_onCalc = s_onCalc[actionIdx];
68 m_onEnd = s_onEnd[actionIdx];
69 state()->setInAction(
true);
71 m_flags.makeAllZero();
85void KartAction::startRotation(
size_t idx) {
86 m_rotation = EGG::Quatf::ident;
93 m_rotationDirection = dir.cross(bodyFront()).
dot(bodyUp()) > 0.0f ? 1.0f : -1.0f;
95 m_flags.setBit(eFlags::Rotating);
99void KartAction::calcSideFromHitDepth() {
100 m_hitDepth.normalise();
101 m_side = m_hitDepth.perpInPlane(move()->smoothedUp(),
true);
103 if (m_side.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
104 m_side = EGG::Vector3f::ey;
109void KartAction::calcSideFromHitDepthAndTranslation() {
110 calcSideFromHitDepth();
113 f32 sign = (cross.y > 0.0f) ? 1.0f : -1.0f;
115 EGG::Vector3f worldSide = EGG::Vector3f::ey.cross(m_translation);
118 m_side = worldSide.
perpInPlane(move()->smoothedUp(),
true);
120 if (m_side.squaredLength() > std::numeric_limits<f32>::epsilon()) {
123 m_side = EGG::Vector3f::ey;
128void KartAction::end() {
129 state()->setInAction(
false);
130 dynamics()->setForceUpright(
true);
132 m_currentAction = Action::None;
134 m_flags.makeAllZero();
140bool KartAction::calcCurrentAction() {
142 return (this->*m_onCalc)();
146void KartAction::calcEndAction(
bool endArg) {
147 if (m_currentAction == Action::None) {
152 (this->*m_onEnd)(endArg);
158bool KartAction::calcRotation() {
159 if (!m_rotationParams) {
164 if (m_currentAngle > m_finalAngle * m_rotationParams->slowdownThreshold) {
165 m_angleIncrement *= m_multiplier;
166 if (m_rotationParams->minAngleIncrement > m_angleIncrement) {
167 m_angleIncrement = m_rotationParams->minAngleIncrement;
170 m_multiplier -= m_multiplierDecrement;
171 if (m_rotationParams->minMultiplier > m_multiplier) {
172 m_multiplier = m_rotationParams->minMultiplier;
176 m_currentAngle += m_angleIncrement;
177 if (m_finalAngle < m_currentAngle) {
178 m_currentAngle = m_finalAngle;
186void KartAction::calcUp() {
187 m_up += (move()->up() - m_up) * 0.3f;
191void KartAction::calcLanding() {
192 if (m_currentAngle < m_targetRot || !state()->isTouchingGround()) {
196 m_flags.setBit(eFlags::Landing);
199 dynamics()->setForceUpright(
false);
202 physics()->composeDecayingExtraRot(m_rotation);
206void KartAction::startLaunch(f32 extVelScalar, f32 extVelKart, f32 extVelBike, f32 numRotations,
208 m_targetRot = 360.0f * numRotations;
211 extVel.y = isBike() ? extVelBike : extVelKart;
214 m_hitDepth = move()->dir();
215 calcSideFromHitDepth();
216 }
else if (param6 == 1) {
217 calcSideFromHitDepth();
218 extVel += extVelScalar * m_side;
219 }
else if (param6 == 2) {
220 calcSideFromHitDepthAndTranslation();
221 extVel += extVelScalar * m_side;
224 setRotation(
static_cast<size_t>(numRotations + 3.0f));
225 m_rotAxis = move()->smoothedUp().cross(m_side);
227 dynamics()->setExtVel(dynamics()->extVel() + extVel);
231void KartAction::activateCrush(
u16 timer) {
232 move()->activateCrush(m_crushTimer + timer);
233 Item::ItemDirector::Instance()->kartItem(0).clear();
237void KartAction::applyStartSpeed() {
238 move()->setSpeed(m_actionParams->startSpeedMult * move()->speed());
239 if (m_actionParams->startSpeedMult == 0.0f) {
240 move()->clearDrift();
245void KartAction::setRotation(
size_t idx) {
246 ASSERT(idx - 1 < s_rotationParams.size());
247 m_rotationParams = &s_rotationParams[--idx];
249 m_finalAngle = m_rotationParams->finalAngle;
250 m_angleIncrement = m_rotationParams->initialAngleIncrement;
251 m_multiplierDecrement = m_rotationParams->initialMultiplierDecrement;
252 m_currentAngle = 0.0f;
260void KartAction::startStub() {}
263void KartAction::startAction1() {
268void KartAction::startAction5() {
269 constexpr f32 EXT_VEL_SCALAR = 13.0f;
270 constexpr f32 EXT_VEL_KART = 40.0f;
271 constexpr f32 EXT_VEL_BIKE = 45.0f;
272 constexpr f32 NUM_ROTATIONS = 1.0f;
274 startLaunch(EXT_VEL_SCALAR, EXT_VEL_KART, EXT_VEL_BIKE, NUM_ROTATIONS, 2);
278void KartAction::startAction9() {
283void KartAction::startLongPressAction() {
284 constexpr u32 ACTION_DURATION = 90;
285 constexpr u16 CRUSH_DURATION = 480;
287 m_crushTimer = ACTION_DURATION;
288 activateCrush(CRUSH_DURATION);
292void KartAction::startShortPressAction() {
293 constexpr u32 ACTION_DURATION = 30;
294 constexpr u16 CRUSH_DURATION = 240;
296 m_crushTimer = ACTION_DURATION;
297 activateCrush(CRUSH_DURATION);
304bool KartAction::calcStub() {
309bool KartAction::calcAction1() {
311 bool finished = calcRotation();
313 m_rotation.setAxisRotation(DEG2RAD * (m_currentAngle * m_rotationDirection), m_up);
314 physics()->composeExtraRot(m_rotation);
319bool KartAction::calcAction5() {
320 constexpr u32 ACTION_DURATION = 100;
322 if (m_flags.offBit(eFlags::Landing)) {
327 bool actionEnded = m_frame >= ACTION_DURATION;
330 if (m_flags.offBit(eFlags::Landing)) {
331 physics()->composeDecayingExtraRot(m_rotation);
333 }
else if (m_flags.offBit(eFlags::Landing)) {
334 m_rotation.setAxisRotation(DEG2RAD * m_currentAngle, m_rotAxis);
335 physics()->composeExtraRot(m_rotation);
342bool KartAction::calcPressAction() {
344 extVel.y = std::min(0.0f, extVel.y);
345 dynamics()->setExtVel(extVel);
347 return m_frame > m_crushTimer;
354void KartAction::endStub(
bool ) {}
357void KartAction::endAction1(
bool arg) {
359 physics()->composeDecayingExtraRot(m_rotation);
364void KartAction::endAction5(
bool arg) {
366 physics()->composeDecayingExtraRot(m_rotation);
374const std::array<KartAction::ActionParams, KartAction::MAX_ACTION> KartAction::s_actionParams = {{
395const std::array<KartAction::RotationParams, 5> KartAction::s_rotationParams = {{
396 {10.0f, 1.5f, 0.9f, 0.005f, 0.6f, 360.0f},
397 {11.0f, 1.5f, 0.9f, 0.0028f, 0.7f, 720.0f},
398 {11.0f, 1.5f, 0.9f, 0.0028f, 0.8f, 1080.0f},
399 {7.0f, 1.5f, 0.9f, 0.005f, 0.6f, 450.0f},
400 {9.0f, 1.5f, 0.9f, 0.0028f, 0.7f, 810.0f},
403const std::array<KartAction::StartActionFunc, KartAction::MAX_ACTION> KartAction::s_onStart = {{
404 &KartAction::startStub,
405 &KartAction::startAction1,
406 &KartAction::startStub,
407 &KartAction::startStub,
408 &KartAction::startStub,
409 &KartAction::startAction5,
410 &KartAction::startStub,
411 &KartAction::startStub,
412 &KartAction::startStub,
413 &KartAction::startAction9,
414 &KartAction::startStub,
415 &KartAction::startStub,
416 &KartAction::startLongPressAction,
417 &KartAction::startStub,
418 &KartAction::startShortPressAction,
419 &KartAction::startStub,
420 &KartAction::startStub,
421 &KartAction::startStub,
424const std::array<KartAction::CalcActionFunc, KartAction::MAX_ACTION> KartAction::s_onCalc = {{
425 &KartAction::calcStub,
426 &KartAction::calcAction1,
427 &KartAction::calcStub,
428 &KartAction::calcStub,
429 &KartAction::calcStub,
430 &KartAction::calcAction5,
431 &KartAction::calcStub,
432 &KartAction::calcStub,
433 &KartAction::calcStub,
434 &KartAction::calcAction1,
435 &KartAction::calcStub,
436 &KartAction::calcStub,
437 &KartAction::calcPressAction,
438 &KartAction::calcStub,
439 &KartAction::calcPressAction,
440 &KartAction::calcStub,
441 &KartAction::calcStub,
442 &KartAction::calcStub,
445const std::array<KartAction::EndActionFunc, KartAction::MAX_ACTION> KartAction::s_onEnd = {{
446 &KartAction::endStub,
447 &KartAction::endAction1,
448 &KartAction::endStub,
449 &KartAction::endStub,
450 &KartAction::endStub,
451 &KartAction::endAction5,
452 &KartAction::endStub,
453 &KartAction::endStub,
454 &KartAction::endStub,
455 &KartAction::endAction1,
456 &KartAction::endStub,
457 &KartAction::endStub,
458 &KartAction::endStub,
459 &KartAction::endStub,
460 &KartAction::endStub,
461 &KartAction::endStub,
462 &KartAction::endStub,
463 &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.