Add CBSLoopReaction

This commit is contained in:
Henrique Gemignani Passos Lima 2022-11-22 01:25:57 +02:00
parent 286180ee0c
commit 36653c19b0
No known key found for this signature in database
GPG Key ID: E224F951761145F8
4 changed files with 173 additions and 7 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E1878
lbl_803E1878:
.global __vt__15CBSLoopReaction
__vt__15CBSLoopReaction:
# ROM: 0x3DE878
.4byte 0
.4byte 0
@ -31,8 +31,8 @@ __dt__15CBSLoopReactionFv:
/* 8013C054 00138FB4 93 E1 00 0C */ stw r31, 0xc(r1)
/* 8013C058 00138FB8 7C 7F 1B 79 */ or. r31, r3, r3
/* 8013C05C 00138FBC 41 82 00 30 */ beq lbl_8013C08C
/* 8013C060 00138FC0 3C 60 80 3E */ lis r3, lbl_803E1878@ha
/* 8013C064 00138FC4 38 03 18 78 */ addi r0, r3, lbl_803E1878@l
/* 8013C060 00138FC0 3C 60 80 3E */ lis r3, __vt__15CBSLoopReaction@ha
/* 8013C064 00138FC4 38 03 18 78 */ addi r0, r3, __vt__15CBSLoopReaction@l
/* 8013C068 00138FC8 90 1F 00 00 */ stw r0, 0(r31)
/* 8013C06C 00138FCC 41 82 00 10 */ beq lbl_8013C07C
/* 8013C070 00138FD0 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha
@ -734,11 +734,11 @@ lbl_8013CA00:
.global __ct__15CBSLoopReactionFv
__ct__15CBSLoopReactionFv:
/* 8013CA20 00139980 3C A0 80 3E */ lis r5, __vt__10CBodyState@ha
/* 8013CA24 00139984 3C 80 80 3E */ lis r4, lbl_803E1878@ha
/* 8013CA24 00139984 3C 80 80 3E */ lis r4, __vt__15CBSLoopReaction@ha
/* 8013CA28 00139988 38 C5 13 18 */ addi r6, r5, __vt__10CBodyState@l
/* 8013CA2C 0013998C 38 00 FF FF */ li r0, -1
/* 8013CA30 00139990 90 C3 00 00 */ stw r6, 0(r3)
/* 8013CA34 00139994 38 A4 18 78 */ addi r5, r4, lbl_803E1878@l
/* 8013CA34 00139994 38 A4 18 78 */ addi r5, r4, __vt__15CBSLoopReaction@l
/* 8013CA38 00139998 38 80 00 00 */ li r4, 0
/* 8013CA3C 0013999C 90 A3 00 00 */ stw r5, 0(r3)
/* 8013CA40 001399A0 90 03 00 04 */ stw r0, 4(r3)

View File

@ -196,7 +196,7 @@ LIBS = [
"MetroidPrime/BodyState/CBodyController",
["MetroidPrime/BodyState/CBSLoopAttack", False],
["MetroidPrime/Weapons/CTargetableProjectile", False],
"MetroidPrime/BodyState/CBSLoopReaction",
["MetroidPrime/BodyState/CBSLoopReaction", False],
"MetroidPrime/CSteeringBehaviors",
["MetroidPrime/BodyState/CBSGroundHit", False],
"MetroidPrime/Enemies/CChozoGhost",

View File

@ -0,0 +1,23 @@
#ifndef _CBSLOOPREACTION
#define _CBSLOOPREACTION
#include "MetroidPrime/BodyState/CBodyState.hpp"
class CBSLoopReaction : public CBodyState {
public:
CBSLoopReaction();
void Start(CBodyController& bc, CStateManager& mgr) override;
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override;
void Shutdown(CBodyController&) override {}
private:
pas::ELoopState x4_state;
pas::EReactionType x8_reactionType;
bool xc_24_loopHit : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
bool PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const;
};
#endif // _CBSLOOPREACTION

View File

@ -0,0 +1,143 @@
#include "MetroidPrime/BodyState/CBSLoopReaction.hpp"
#include "MetroidPrime/BodyState/CBodyController.hpp"
#include "MetroidPrime/CAnimPlaybackParms.hpp"
#include "MetroidPrime/CStateManager.hpp"
#include "Kyoto/Animation/CPASAnimParmData.hpp"
#include "Kyoto/Animation/CPASDatabase.hpp"
CBSLoopReaction::CBSLoopReaction()
: x4_state(pas::kLS_Invalid), x8_reactionType(pas::kRT_Invalid), xc_24_loopHit(false) {}
void CBSLoopReaction::Start(CBodyController& bc, CStateManager& mgr) {
CBodyStateCmdMgr& commandMgr = bc.CommandMgr();
CBodyStateCmd* cmd = commandMgr.GetCmd(kBSC_LoopReaction);
if (cmd) {
x8_reactionType = static_cast< const CBCLoopReactionCmd* >(cmd)->GetReactionType();
xc_24_loopHit = false;
} else {
cmd = commandMgr.GetCmd(kBSC_LoopHitReaction);
x8_reactionType = static_cast< const CBCLoopHitReactionCmd* >(cmd)->GetReactionType();
xc_24_loopHit = true;
}
x4_state = pas::kLS_Begin;
const CPASAnimParmData parms(pas::kAS_LoopReaction, CPASAnimParm::FromEnum(x8_reactionType),
CPASAnimParm::FromEnum(x4_state));
rstl::pair< float, int > best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.Random(), -1);
if (best.first > FLT_EPSILON) {
const CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
bc.SetCurrentAnimation(playParms, false, false);
} else {
x4_state = pas::kLS_Loop;
CPASAnimParmData loopParms(pas::kAS_LoopReaction, CPASAnimParm::FromEnum(x8_reactionType),
CPASAnimParm::FromEnum(x4_state));
bc.LoopBestAnimation(parms, *mgr.Random());
}
}
pas::EAnimationState CBSLoopReaction::UpdateBody(float dt, CBodyController& bc,
CStateManager& mgr) {
pas::EAnimationState st = GetBodyStateTransition(dt, bc);
if (st == pas::kAS_Invalid) {
CBodyStateCmdMgr& commandMgr = bc.CommandMgr();
switch (x4_state) {
case pas::kLS_Begin:
if (commandMgr.GetCmd(kBSC_ExitState)) {
if (PlayExitAnimation(bc, mgr)) {
x4_state = pas::kLS_End;
} else {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
}
} else {
if (bc.IsAnimationOver()) {
const CPASAnimParmData parms(pas::kAS_LoopReaction,
CPASAnimParm::FromEnum(s32(x8_reactionType)),
CPASAnimParm::FromEnum(1));
bc.LoopBestAnimation(parms, *mgr.Random());
x4_state = pas::kLS_Loop;
} else if (commandMgr.GetTargetVector().IsNonZero()) {
bc.FaceDirection(commandMgr.GetTargetVector(), dt);
}
}
break;
case pas::kLS_Loop:
if (commandMgr.GetCmd(kBSC_ExitState)) {
if (PlayExitAnimation(bc, mgr)) {
x4_state = pas::kLS_End;
} else {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
}
} else if (commandMgr.GetTargetVector().IsNonZero()) {
bc.FaceDirection(commandMgr.GetTargetVector(), dt);
}
break;
case pas::kLS_End:
if (bc.IsAnimationOver()) {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
}
break;
default:
break;
}
}
return st;
}
bool CBSLoopReaction::PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const {
const CPASDatabase& db = bc.GetPASDatabase();
const CPASAnimParmData parms(pas::kAS_LoopReaction, CPASAnimParm::FromEnum(int(x8_reactionType)),
CPASAnimParm::FromEnum(2));
const rstl::pair< float, int > best = db.FindBestAnimation(parms, *mgr.Random(), -1);
if (best.first > 0.f) {
const CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
bc.SetCurrentAnimation(playParms, false, false);
return true;
}
return false;
}
pas::EAnimationState CBSLoopReaction::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 (commandMgr.GetCmd(kBSC_KnockBack)) {
return pas::kAS_KnockBack;
}
if (!xc_24_loopHit && commandMgr.GetCmd(kBSC_Locomotion)) {
return pas::kAS_Locomotion;
}
if (x4_state == pas::kLS_End) {
if (commandMgr.GetCmd(kBSC_MeleeAttack)) {
return pas::kAS_MeleeAttack;
}
if (commandMgr.GetCmd(kBSC_ProjectileAttack)) {
return pas::kAS_ProjectileAttack;
}
if (commandMgr.GetCmd(kBSC_LoopAttack)) {
return pas::kAS_LoopAttack;
}
if (commandMgr.GetCmd(kBSC_Step)) {
return pas::kAS_Step;
}
if (commandMgr.GetMoveVector().IsNonZero()) {
return pas::kAS_Locomotion;
}
if (commandMgr.GetFaceVector().IsNonZero()) {
return pas::kAS_Turn;
}
}
return pas::kAS_Invalid;
}