diff --git a/asm/MetroidPrime/BodyState/CBSGetup.s b/asm/MetroidPrime/BodyState/CBSGetup.s index c53e4a65..4c3319ef 100644 --- a/asm/MetroidPrime/BodyState/CBSGetup.s +++ b/asm/MetroidPrime/BodyState/CBSGetup.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803E1418 -lbl_803E1418: +.global __vt__8CBSGetup +__vt__8CBSGetup: # ROM: 0x3DE418 .4byte 0 .4byte 0 @@ -31,8 +31,8 @@ __dt__8CBSGetupFv: /* 80135E94 00132DF4 93 E1 00 0C */ stw r31, 0xc(r1) /* 80135E98 00132DF8 7C 7F 1B 79 */ or. r31, r3, r3 /* 80135E9C 00132DFC 41 82 00 30 */ beq lbl_80135ECC -/* 80135EA0 00132E00 3C 60 80 3E */ lis r3, lbl_803E1418@ha -/* 80135EA4 00132E04 38 03 14 18 */ addi r0, r3, lbl_803E1418@l +/* 80135EA0 00132E00 3C 60 80 3E */ lis r3, __vt__8CBSGetup@ha +/* 80135EA4 00132E04 38 03 14 18 */ addi r0, r3, __vt__8CBSGetup@l /* 80135EA8 00132E08 90 1F 00 00 */ stw r0, 0(r31) /* 80135EAC 00132E0C 41 82 00 10 */ beq lbl_80135EBC /* 80135EB0 00132E10 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha @@ -267,11 +267,11 @@ lbl_801361C4: .global __ct__8CBSGetupFv __ct__8CBSGetupFv: /* 801361D8 00133138 3C A0 80 3E */ lis r5, __vt__10CBodyState@ha -/* 801361DC 0013313C 3C 80 80 3E */ lis r4, lbl_803E1418@ha +/* 801361DC 0013313C 3C 80 80 3E */ lis r4, __vt__8CBSGetup@ha /* 801361E0 00133140 38 A5 13 18 */ addi r5, r5, __vt__10CBodyState@l /* 801361E4 00133144 38 00 FF FF */ li r0, -1 /* 801361E8 00133148 90 A3 00 00 */ stw r5, 0(r3) -/* 801361EC 0013314C 38 84 14 18 */ addi r4, r4, lbl_803E1418@l +/* 801361EC 0013314C 38 84 14 18 */ addi r4, r4, __vt__8CBSGetup@l /* 801361F0 00133150 90 83 00 00 */ stw r4, 0(r3) /* 801361F4 00133154 90 03 00 04 */ stw r0, 4(r3) /* 801361F8 00133158 4E 80 00 20 */ blr diff --git a/configure.py b/configure.py index e8baded5..5eb25bce 100755 --- a/configure.py +++ b/configure.py @@ -187,7 +187,7 @@ LIBS = [ "MetroidPrime/BodyState/CBSAttack", ["MetroidPrime/BodyState/CBSDie", True], "MetroidPrime/BodyState/CBSFall", - "MetroidPrime/BodyState/CBSGetup", + ["MetroidPrime/BodyState/CBSGetup", True], "MetroidPrime/BodyState/CBSKnockBack", "MetroidPrime/BodyState/CBSLieOnGround", "MetroidPrime/BodyState/CBSLocomotion", diff --git a/include/Kyoto/Animation/CPASAnimState.hpp b/include/Kyoto/Animation/CPASAnimState.hpp index 263ed6a0..6c32b6e3 100644 --- a/include/Kyoto/Animation/CPASAnimState.hpp +++ b/include/Kyoto/Animation/CPASAnimState.hpp @@ -33,6 +33,7 @@ public: static CPASAnimParm FromInt32(int val); static CPASAnimParm NoParameter(); + int GetEnumValue() const; // { return x0_value.m_int; } int GetInt32Value() const; float GetReal32Value() const; diff --git a/include/MetroidPrime/BodyState/CBSGetup.hpp b/include/MetroidPrime/BodyState/CBSGetup.hpp new file mode 100644 index 00000000..dfb8c460 --- /dev/null +++ b/include/MetroidPrime/BodyState/CBSGetup.hpp @@ -0,0 +1,20 @@ +#ifndef _CBSGETUP +#define _CBSGETUP + +#include "MetroidPrime/BodyState/CBodyState.hpp" + +class CBSGetup : public CBodyState { +public: + CBSGetup(); + ~CBSGetup(); + + void Start(CBodyController& bc, CStateManager& mgr) override; + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override; + void Shutdown(CBodyController& bc) override; + +private: + pas::EFallState x4_fallState; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +}; + +#endif // _CBSGETUP diff --git a/include/MetroidPrime/BodyState/CBodyController.hpp b/include/MetroidPrime/BodyState/CBodyController.hpp index f3eec8dc..39cf7195 100644 --- a/include/MetroidPrime/BodyState/CBodyController.hpp +++ b/include/MetroidPrime/BodyState/CBodyController.hpp @@ -26,7 +26,9 @@ public: void FaceDirection(const CVector3f& v0, float dt); void EnableAnimation(bool enable); + void SetFallState(pas::EFallState state); // { x2f0_fallState = state; } pas::EFallState GetFallState() const; // { return x2f0_fallState; } + int GetCurrentAnimId() const { return x2f8_curAnim; } pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; } bool IsAnimationOver() const { return x300_24_animationOver; } bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; } diff --git a/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp b/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp index 3f354c22..f3ac2323 100644 --- a/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp +++ b/include/MetroidPrime/BodyState/CBodyStateCmdMgr.hpp @@ -55,6 +55,19 @@ public: bool UseSpecialAnimId() const { return x1c_25_overrideAnim; } }; +// + +class CBCGetupCmd : public CBodyStateCmd { + pas::EGetupType x8_type; + +public: + explicit CBCGetupCmd() : CBodyStateCmd(kBSC_Getup), x8_type(pas::kGetup_Invalid) {} + explicit CBCGetupCmd(pas::EGetupType type) : CBodyStateCmd(kBSC_Getup), x8_type(type) {} + pas::EGetupType GetGetupType() const { return x8_type; } +}; + +// + class CBCSlideCmd : public CBodyStateCmd { public: explicit CBCSlideCmd() diff --git a/obj_files.mk b/obj_files.mk index d21e877c..8e48a48a 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -152,7 +152,7 @@ METROIDPRIME :=\ $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSAttack.o\ $(BUILD_DIR)/src/MetroidPrime/BodyState/CBSDie.o\ $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSFall.o\ - $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSGetup.o\ + $(BUILD_DIR)/src/MetroidPrime/BodyState/CBSGetup.o\ $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSKnockBack.o\ $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSLieOnGround.o\ $(BUILD_DIR)/asm/MetroidPrime/BodyState/CBSLocomotion.o\ diff --git a/src/MetroidPrime/BodyState/CBSGetup.cpp b/src/MetroidPrime/BodyState/CBSGetup.cpp new file mode 100644 index 00000000..0ce68b47 --- /dev/null +++ b/src/MetroidPrime/BodyState/CBSGetup.cpp @@ -0,0 +1,57 @@ +#include "MetroidPrime/BodyState/CBSGetup.hpp" + +#include "MetroidPrime/BodyState/CBodyController.hpp" +#include "MetroidPrime/CAnimPlaybackParms.hpp" +#include "MetroidPrime/CStateManager.hpp" + +#include "Kyoto/Animation/CPASAnimParmData.hpp" +#include "Kyoto/Animation/CPASDatabase.hpp" + +CBSGetup::CBSGetup() : x4_fallState(pas::kFS_Invalid) {} + +void CBSGetup::Start(CBodyController& bc, CStateManager& mgr) { + const CBCGetupCmd* cmd = static_cast< const CBCGetupCmd* >(bc.CommandMgr().GetCmd(kBSC_Getup)); + int fallState = bc.GetFallState(); + const CPASDatabase& db = bc.GetPASDatabase(); + + const CPASAnimParmData parms(pas::kAS_Getup, CPASAnimParm::FromEnum(fallState), + CPASAnimParm::FromEnum(cmd->GetGetupType())); + + const rstl::pair< float, int > best = db.FindBestAnimation(parms, *mgr.Random(), -1); + if (best.first > FLT_EPSILON) { + int f = best.second; + if (best.second != bc.GetCurrentAnimId()) { + const CAnimPlaybackParms playParms(f, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } + CPASAnimParm animParm = db.GetAnimState(pas::kAS_Getup)->GetAnimParmData(f, 2); + x4_fallState = pas::EFallState(animParm.GetEnumValue()); + } else { + x4_fallState = pas::kFS_Zero; + } +} + +pas::EAnimationState CBSGetup::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + return GetBodyStateTransition(dt, bc); +} + +void CBSGetup::Shutdown(CBodyController& bc) { bc.SetFallState(x4_fallState); } + +pas::EAnimationState CBSGetup::GetBodyStateTransition(float dt, CBodyController& bc) { + CBodyStateCmdMgr& commandMgr = bc.CommandMgr(); + if (commandMgr.GetCmd(kBSC_Hurled)) { + return pas::kAS_Hurled; + } + if (commandMgr.GetCmd(kBSC_KnockDown)) { + return pas::kAS_Fall; + } + if (bc.IsAnimationOver()) { + if (x4_fallState == pas::kFS_Zero) { + return pas::kAS_Locomotion; + } + return pas::kAS_Getup; + } + return pas::kAS_Invalid; +} + +CBSGetup::~CBSGetup() {}