From e6c39713b4ee601e3d402d6d2ee9ff109005443e Mon Sep 17 00:00:00 2001 From: Henrique Gemignani Passos Lima Date: Fri, 28 Oct 2022 16:16:03 +0300 Subject: [PATCH] Add CBSFall Former-commit-id: 4e55f8c7ddb9ea1e8c47cd12a141885e1c945722 --- asm/MetroidPrime/BodyState/CBSFall.s | 12 ++-- configure.py | 2 +- include/Kyoto/Animation/CPASAnimState.hpp | 1 + include/MetroidPrime/BodyState/CBSFall.hpp | 23 ++++++ .../BodyState/CBodyStateCmdMgr.hpp | 20 +++++- src/MetroidPrime/BodyState/CBSFall.cpp | 72 +++++++++++++++++++ 6 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 include/MetroidPrime/BodyState/CBSFall.hpp create mode 100644 src/MetroidPrime/BodyState/CBSFall.cpp diff --git a/asm/MetroidPrime/BodyState/CBSFall.s b/asm/MetroidPrime/BodyState/CBSFall.s index 1fd50856..23268f8b 100644 --- a/asm/MetroidPrime/BodyState/CBSFall.s +++ b/asm/MetroidPrime/BodyState/CBSFall.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803E13E0 -lbl_803E13E0: +.global __vt__7CBSFall +__vt__7CBSFall: # ROM: 0x3DE3E0 .4byte 0 .4byte 0 @@ -31,8 +31,8 @@ __dt__7CBSFallFv: /* 80135944 001328A4 93 E1 00 0C */ stw r31, 0xc(r1) /* 80135948 001328A8 7C 7F 1B 79 */ or. r31, r3, r3 /* 8013594C 001328AC 41 82 00 30 */ beq lbl_8013597C -/* 80135950 001328B0 3C 60 80 3E */ lis r3, lbl_803E13E0@ha -/* 80135954 001328B4 38 03 13 E0 */ addi r0, r3, lbl_803E13E0@l +/* 80135950 001328B0 3C 60 80 3E */ lis r3, __vt__7CBSFall@ha +/* 80135954 001328B4 38 03 13 E0 */ addi r0, r3, __vt__7CBSFall@l /* 80135958 001328B8 90 1F 00 00 */ stw r0, 0(r31) /* 8013595C 001328BC 41 82 00 10 */ beq lbl_8013596C /* 80135960 001328C0 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha @@ -388,11 +388,11 @@ lbl_80135E3C: .global __ct__7CBSFallFv __ct__7CBSFallFv: /* 80135E58 00132DB8 3C A0 80 3E */ lis r5, __vt__10CBodyState@ha -/* 80135E5C 00132DBC 3C 80 80 3E */ lis r4, lbl_803E13E0@ha +/* 80135E5C 00132DBC 3C 80 80 3E */ lis r4, __vt__7CBSFall@ha /* 80135E60 00132DC0 38 05 13 18 */ addi r0, r5, __vt__10CBodyState@l /* 80135E64 00132DC4 C0 02 99 C0 */ lfs f0, lbl_805AB6E0@sda21(r2) /* 80135E68 00132DC8 90 03 00 00 */ stw r0, 0(r3) -/* 80135E6C 00132DCC 38 84 13 E0 */ addi r4, r4, lbl_803E13E0@l +/* 80135E6C 00132DCC 38 84 13 E0 */ addi r4, r4, __vt__7CBSFall@l /* 80135E70 00132DD0 38 00 FF FF */ li r0, -1 /* 80135E74 00132DD4 90 83 00 00 */ stw r4, 0(r3) /* 80135E78 00132DD8 D0 03 00 04 */ stfs f0, 4(r3) diff --git a/configure.py b/configure.py index 4ad1b1bb..6b19a274 100755 --- a/configure.py +++ b/configure.py @@ -186,7 +186,7 @@ LIBS = [ ["MetroidPrime/BodyState/CBodyStateInfo", False], "MetroidPrime/BodyState/CBSAttack", ["MetroidPrime/BodyState/CBSDie", True], - "MetroidPrime/BodyState/CBSFall", + ["MetroidPrime/BodyState/CBSFall", False], ["MetroidPrime/BodyState/CBSGetup", True], "MetroidPrime/BodyState/CBSKnockBack", ["MetroidPrime/BodyState/CBSLieOnGround", True], diff --git a/include/Kyoto/Animation/CPASAnimState.hpp b/include/Kyoto/Animation/CPASAnimState.hpp index 6c32b6e3..cda0d9dc 100644 --- a/include/Kyoto/Animation/CPASAnimState.hpp +++ b/include/Kyoto/Animation/CPASAnimState.hpp @@ -36,6 +36,7 @@ public: int GetEnumValue() const; // { return x0_value.m_int; } int GetInt32Value() const; float GetReal32Value() const; + bool GetBoolValue() const; private: UParmValue x0_value; diff --git a/include/MetroidPrime/BodyState/CBSFall.hpp b/include/MetroidPrime/BodyState/CBSFall.hpp new file mode 100644 index 00000000..a664ecd8 --- /dev/null +++ b/include/MetroidPrime/BodyState/CBSFall.hpp @@ -0,0 +1,23 @@ +#ifndef _CBSFALL +#define _CBSFALL + +#include "MetroidPrime/BodyState/CBodyState.hpp" + +class CBSFall : public CBodyState { +public: + CBSFall(); + ~CBSFall(); + + void Start(CBodyController& bc, CStateManager& mgr) override; + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override; + void Shutdown(CBodyController& bc) override; + +private: + float x4_rotateSpeed; + float x8_remTime; + pas::EFallState xc_fallState; + + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +}; + +#endif // _CBSFALL diff --git a/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp b/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp index b1e992f4..30753e53 100644 --- a/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp +++ b/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp @@ -135,7 +135,7 @@ public: , x8_weight(1.f) , xc_type(pas::kART_Invalid) , x10_active(false) {} - + explicit CBCAdditiveReactionCmd(pas::EAdditiveReactionType type, float weight, bool active) : CBodyStateCmd(kBSC_AdditiveReaction), x8_weight(weight), xc_type(type), x10_active(active) {} @@ -168,6 +168,24 @@ private: // +class CBCKnockDownCmd : public CBodyStateCmd { +public: + explicit CBCKnockDownCmd() + : CBodyStateCmd(kBSC_KnockDown), x8_dir(0.f, 0.f, 0.f), x14_severity(pas::kS_Invalid) {} + + explicit CBCKnockDownCmd(const CVector3f& vec, pas::ESeverity severity) + : CBodyStateCmd(kBSC_KnockDown), x8_dir(vec), x14_severity(severity) {} + + const CVector3f& GetHitDirection() const { return x8_dir; } + pas::ESeverity GetHitSeverity() const { return x14_severity; } + +private: + CVector3f x8_dir; + pas::ESeverity x14_severity; +}; + +// + class CBodyStateCmdMgr { public: CBodyStateCmd* GetCmd(EBodyStateCmd cmd); diff --git a/src/MetroidPrime/BodyState/CBSFall.cpp b/src/MetroidPrime/BodyState/CBSFall.cpp new file mode 100644 index 00000000..29416d59 --- /dev/null +++ b/src/MetroidPrime/BodyState/CBSFall.cpp @@ -0,0 +1,72 @@ +#include "MetroidPrime/BodyState/CBSFall.hpp" + +#include "MetroidPrime/BodyState/CBodyController.hpp" +#include "MetroidPrime/CActor.hpp" +#include "MetroidPrime/CAnimPlaybackParms.hpp" +#include "MetroidPrime/CStateManager.hpp" + +#include "Kyoto/Animation/CPASAnimParmData.hpp" +#include "Kyoto/Animation/CPASDatabase.hpp" +#include "Kyoto/Math/CRelAngle.hpp" +#include "Kyoto/Math/CAbsAngle.hpp" + +#include "math.h" +#include "rstl/math.hpp" + + +CBSFall::CBSFall() : x4_rotateSpeed(0.f), x8_remTime(0.f), xc_fallState(pas::kFS_Invalid) {} + +void CBSFall::Start(CBodyController& bc, CStateManager& mgr) { + const CBCKnockDownCmd* cmd = + static_cast< const CBCKnockDownCmd* >(bc.CommandMgr().GetCmd(kBSC_KnockDown)); + CVector3f localDir = bc.GetOwner().GetTransform().TransposeRotate(cmd->GetHitDirection()); + CAbsAngle angle = CAbsAngle::FromRadians(atan2(localDir.GetY(), localDir.GetZ())); + + const CPASDatabase& db = bc.GetPASDatabase(); + const CPASAnimParmData parms(pas::kAS_Fall, CPASAnimParm::FromReal32(angle.AsDegrees()), + CPASAnimParm::FromEnum(cmd->GetHitSeverity())); + const rstl::pair< float, int > best = db.FindBestAnimation(parms, *mgr.Random(), -1); + const CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + + const CPASAnimState* knockdownState = db.GetAnimState(pas::kAS_Fall); + CPASAnimParm knockdownParm2(knockdownState->GetAnimParmData(best.second, 2)); + if (!knockdownParm2.GetBoolValue()) { + CPASAnimParm knockdownParm0(knockdownState->GetAnimParmData(best.second, 0)); + float knockdownAngle = knockdownParm0.GetReal32Value(); + float delta1 = CAbsAngle::FromRadians(angle.AsRadians() - CRelAngle::FromDegrees(knockdownAngle).AsRadians()).AsRadians(); + float delta2 = CAbsAngle::FromRadians(CRelAngle::FromDegrees(knockdownAngle).AsRadians() - angle.AsRadians()).AsRadians(); + float minAngle = rstl::min_val(delta1, delta2); + // There's a missing `if (delta1 < 0) { delta1 += M_2PIF; }` here + // But it's not exactly delta1, but a temporary from inside the FromRadians call?! + const float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; + x8_remTime = 0.15f * bc.GetAnimTimeRemaining(); + x4_rotateSpeed = (x8_remTime > FLT_EPSILON) ? flippedAngle / x8_remTime : flippedAngle; + } else { + x8_remTime = 0.f; + x4_rotateSpeed = 0.f; + } + + CPASAnimParm knockdownParm3(knockdownState->GetAnimParmData(best.second, 3)); + xc_fallState = pas::EFallState(knockdownParm3.GetEnumValue()); +} + +pas::EAnimationState CBSFall::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + const pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::kAS_Invalid && x8_remTime > 0.f) { + bc.SetDeltaRotation(CQuaternion::ZRotation(CRelAngle::FromRadians(x4_rotateSpeed * dt))); + x8_remTime -= dt; + } + return st; +} + +void CBSFall::Shutdown(CBodyController& bc) { bc.SetFallState(xc_fallState); } + +pas::EAnimationState CBSFall::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.IsAnimationOver()) { + return pas::kAS_LieOnGround; + } + return pas::kAS_Invalid; +} + +CBSFall::~CBSFall() {}