diff --git a/include/Kyoto/Animation/CPASAnimState.hpp b/include/Kyoto/Animation/CPASAnimState.hpp index d0df199b..ee01b010 100644 --- a/include/Kyoto/Animation/CPASAnimState.hpp +++ b/include/Kyoto/Animation/CPASAnimState.hpp @@ -53,6 +53,8 @@ public: f32 m_float; bool m_bool; }; + CPASAnimParm(const CPASAnimParm& other) + : x0_value(other.x0_value), x4_type(other.x4_type) {} static CPASAnimParm FromEnum(s32 val); static CPASAnimParm FromBool(bool val); @@ -61,6 +63,8 @@ public: static CPASAnimParm FromInt32(s32 val); static CPASAnimParm NoParameter(); + int GetInt32Value() const; + private: UParmValue x0_value; EParmType x4_type; @@ -90,6 +94,8 @@ private: }; class CPASAnimState { +public: + CPASAnimParm GetAnimParmData(int, unsigned int) const; private: pas::EAnimationState x0_id; rstl::vector< CPASParmInfo > x4_parms; diff --git a/include/Kyoto/Animation/CPASDatabase.hpp b/include/Kyoto/Animation/CPASDatabase.hpp index 89750595..baebead5 100644 --- a/include/Kyoto/Animation/CPASDatabase.hpp +++ b/include/Kyoto/Animation/CPASDatabase.hpp @@ -17,6 +17,7 @@ private: int x10_defaultState; public: + const CPASAnimState* GetAnimState(int) const; rstl::pair FindBestAnimation(const CPASAnimParmData&, CRandom16&, int) const; }; CHECK_SIZEOF(CPASDatabase, 0x14) diff --git a/include/MetroidPrime/Weapons/GunController/CGSFreeLook.hpp b/include/MetroidPrime/Weapons/GunController/CGSFreeLook.hpp index b220ea15..235249a4 100644 --- a/include/MetroidPrime/Weapons/GunController/CGSFreeLook.hpp +++ b/include/MetroidPrime/Weapons/GunController/CGSFreeLook.hpp @@ -12,7 +12,7 @@ class CGSFreeLook { int x8_loopState; // In, loop, out int xc_gunId; int x10_setId; - bool x14_idle; + bool x14_idle : 1; public: CGSFreeLook(); diff --git a/src/MetroidPrime/Weapons/GunController/CGSFreeLook.cpp b/src/MetroidPrime/Weapons/GunController/CGSFreeLook.cpp index 6883453c..d6dcea09 100644 --- a/src/MetroidPrime/Weapons/GunController/CGSFreeLook.cpp +++ b/src/MetroidPrime/Weapons/GunController/CGSFreeLook.cpp @@ -1,4 +1,63 @@ #include "MetroidPrime/Weapons/GunController/CGSFreeLook.hpp" +#include "MetroidPrime/CAnimData.hpp" +#include "MetroidPrime/CAnimPlaybackParms.hpp" +#include "MetroidPrime/CStateManager.hpp" + +#include "Kyoto/Animation/CPASAnimParmData.hpp" + CGSFreeLook::CGSFreeLook() : x0_delay(0.f), x4_cueAnimId(-1), x8_loopState(-1), xc_gunId(0), x10_setId(-1), x14_idle(false) {} + +bool CGSFreeLook::Update(CAnimData& data, float dt, CStateManager& mgr) { + if (x4_cueAnimId != -1) { + x0_delay -= dt; + if (x0_delay <= 0.f) { + data.EnableLooping(x8_loopState == 1); + CAnimPlaybackParms aparms(x4_cueAnimId, -1, 1.f, true); + data.SetAnimation(aparms, false); + x0_delay = 0.f; + x4_cueAnimId = -1; + } + } else if (!data.IsAnimTimeRemaining(0.001f, "Whole Body")) { + switch (x8_loopState) { + case 0: + SetAnim(data, xc_gunId, x10_setId, 1, mgr, 0.f); + break; + case 2: + x8_loopState = -1; + return true; + default: + break; + } + } + return false; +} + +int CGSFreeLook::SetAnim(CAnimData& data, int gunId, int setId, int loopState, CStateManager& mgr, + float delay) { + int useLoopState = 1; + if (!x14_idle) + useLoopState = loopState; + x14_idle = false; + + const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); + rstl::pair< float, int > anim = pas.FindBestAnimation( + CPASAnimParmData(pas::kAS_Step, CPASAnimParm::FromInt32(gunId), + CPASAnimParm::FromInt32(setId), CPASAnimParm::FromEnum(useLoopState)), + *mgr.GetActiveRandom(), -1); + + CPASAnimParm animParm = pas.GetAnimState(pas::kAS_Step)->GetAnimParmData(anim.second, 1); + xc_gunId = gunId; + x10_setId = animParm.GetInt32Value(); + x8_loopState = useLoopState; + if (delay != 0.f) { + x0_delay = delay; + x4_cueAnimId = anim.second; + } else { + data.EnableLooping(loopState == 1); + CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); + data.SetAnimation(aparms, false); + } + return anim.second; +}