Add almost matched CBSLoopAttack

Former-commit-id: 64ec879441
This commit is contained in:
Henrique Gemignani Passos Lima 2022-11-11 18:16:51 +02:00
parent b988da7f60
commit 79503f7b2e
5 changed files with 181 additions and 9 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E17C8
lbl_803E17C8:
.global __vt__13CBSLoopAttack
__vt__13CBSLoopAttack:
# ROM: 0x3DE7C8
.4byte 0
.4byte 0
@ -31,8 +31,8 @@ __dt__13CBSLoopAttackFv:
/* 8013AED8 00137E38 93 E1 00 0C */ stw r31, 0xc(r1)
/* 8013AEDC 00137E3C 7C 7F 1B 79 */ or. r31, r3, r3
/* 8013AEE0 00137E40 41 82 00 30 */ beq lbl_8013AF10
/* 8013AEE4 00137E44 3C 60 80 3E */ lis r3, lbl_803E17C8@ha
/* 8013AEE8 00137E48 38 03 17 C8 */ addi r0, r3, lbl_803E17C8@l
/* 8013AEE4 00137E44 3C 60 80 3E */ lis r3, __vt__13CBSLoopAttack@ha
/* 8013AEE8 00137E48 38 03 17 C8 */ addi r0, r3, __vt__13CBSLoopAttack@l
/* 8013AEEC 00137E4C 90 1F 00 00 */ stw r0, 0(r31)
/* 8013AEF0 00137E50 41 82 00 10 */ beq lbl_8013AF00
/* 8013AEF4 00137E54 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha
@ -701,11 +701,11 @@ lbl_8013B81C:
.global __ct__13CBSLoopAttackFv
__ct__13CBSLoopAttackFv:
/* 8013B838 00138798 3C A0 80 3E */ lis r5, __vt__10CBodyState@ha
/* 8013B83C 0013879C 3C 80 80 3E */ lis r4, lbl_803E17C8@ha
/* 8013B83C 0013879C 3C 80 80 3E */ lis r4, __vt__13CBSLoopAttack@ha
/* 8013B840 001387A0 38 C5 13 18 */ addi r6, r5, __vt__10CBodyState@l
/* 8013B844 001387A4 38 00 FF FF */ li r0, -1
/* 8013B848 001387A8 90 C3 00 00 */ stw r6, 0(r3)
/* 8013B84C 001387AC 38 A4 17 C8 */ addi r5, r4, lbl_803E17C8@l
/* 8013B84C 001387AC 38 A4 17 C8 */ addi r5, r4, __vt__13CBSLoopAttack@l
/* 8013B850 001387B0 38 80 00 00 */ li r4, 0
/* 8013B854 001387B4 90 A3 00 00 */ stw r5, 0(r3)
/* 8013B858 001387B8 90 03 00 04 */ stw r0, 4(r3)

View File

@ -194,7 +194,7 @@ LIBS = [
["MetroidPrime/BodyState/CBSStep", True],
"MetroidPrime/BodyState/CBSTurn",
"MetroidPrime/BodyState/CBodyController",
"MetroidPrime/BodyState/CBSLoopAttack",
["MetroidPrime/BodyState/CBSLoopAttack", False],
["MetroidPrime/Weapons/CTargetableProjectile", False],
"MetroidPrime/BodyState/CBSLoopReaction",
"MetroidPrime/CSteeringBehaviors",

View File

@ -0,0 +1,28 @@
#ifndef _CBSLOOPATTACK
#define _CBSLOOPATTACK
#include "MetroidPrime/BodyState/CBodyState.hpp"
class CBSLoopAttack : public CBodyState {
public:
CBSLoopAttack();
bool CanShoot() const override { return true; }
void Start(CBodyController& bc, CStateManager& mgr) override;
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override;
void Shutdown(CBodyController&) override;
pas::ELoopState GetState() const { return x4_state; }
pas::ELoopAttackType GetAttackType() const { return x8_loopAttackType; }
bool GetAdvance() const { return xc_25_advance; }
private:
pas::ELoopState x4_state;
pas::ELoopAttackType x8_loopAttackType;
bool xc_24_waitForAnimOver : 1;
bool xc_25_advance : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
};
#endif // _CBSLOOPATTACK

View File

@ -252,11 +252,11 @@ public:
: CBodyStateCmd(kBSC_LoopAttack), x8_type(type), xc_waitForAnimOver(waitForAnimOver) {}
pas::ELoopAttackType GetAttackType() const { return x8_type; }
bool WaitForAnimOver() const { return xc_waitForAnimOver; }
int WaitForAnimOver() const { return xc_waitForAnimOver; }
private:
pas::ELoopAttackType x8_type;
bool xc_waitForAnimOver;
int xc_waitForAnimOver;
};
//
@ -423,6 +423,7 @@ public:
CBodyStateCmd* GetCmd(EBodyStateCmd cmd);
const CVector3f& GetMoveVector() const { return x0_move; }
const CVector3f& GetFaceVector() const { return xc_face; }
const CVector3f& GetTargetVector() const { return x18_target; }
const CVector3f& GetAdditiveTargetVector() const { return x24_additiveTarget; }

View File

@ -0,0 +1,143 @@
#include "MetroidPrime/BodyState/CBSLoopAttack.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"
CBSLoopAttack::CBSLoopAttack()
: x4_state(pas::kLS_Invalid)
, x8_loopAttackType(pas::kLAT_Invalid)
, xc_24_waitForAnimOver(false)
, xc_25_advance(false)
{}
void CBSLoopAttack::Start(CBodyController& bc, CStateManager& mgr) {
const CBCLoopAttackCmd* cmd =
static_cast< const CBCLoopAttackCmd* >(bc.CommandMgr().GetCmd(kBSC_LoopAttack));
x8_loopAttackType = cmd->GetAttackType();
xc_24_waitForAnimOver = cmd->WaitForAnimOver() == 1;
xc_25_advance = false;
if (bc.GetLocomotionType() == pas::kLT_Crouch) {
x4_state = pas::kLS_Loop;
const CPASAnimParmData parms(pas::kAS_LoopAttack, CPASAnimParm::FromEnum(x4_state),
CPASAnimParm::FromEnum(x8_loopAttackType));
bc.LoopBestAnimation(parms, *mgr.Random());
} else {
x4_state = pas::kLS_Begin;
const CPASAnimParmData parms(pas::kAS_LoopAttack, CPASAnimParm::FromEnum(x4_state),
CPASAnimParm::FromEnum(x8_loopAttackType));
const 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;
const CPASAnimParmData loopParms(pas::kAS_LoopAttack, CPASAnimParm::FromEnum(x4_state),
CPASAnimParm::FromEnum(x8_loopAttackType));
bc.LoopBestAnimation(loopParms, *mgr.Random());
}
}
}
pas::EAnimationState CBSLoopAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
pas::EAnimationState st = GetBodyStateTransition(dt, bc);
if (st == pas::kAS_Invalid) {
CBodyStateCmdMgr& commandMgr = bc.CommandMgr();
CBodyStateCmd* cmd = commandMgr.GetCmd(kBSC_ExitState);
xc_25_advance = ((GetAdvance() | cmd != nullptr) << 4) & 0x10;
switch (x4_state) {
case pas::kLS_Begin:
if (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
} else if (bc.IsAnimationOver()) {
const CPASAnimParmData parms(pas::kAS_LoopAttack, CPASAnimParm::FromEnum(1),
CPASAnimParm::FromEnum(x8_loopAttackType));
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 (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) {
if (bc.GetLocomotionType() != pas::kLT_Crouch) {
const CPASAnimParmData parms(pas::kAS_LoopAttack, CPASAnimParm::FromEnum(2),
CPASAnimParm::FromEnum(x8_loopAttackType));
bc.PlayBestAnimation(parms, *mgr.Random());
x4_state = pas::kLS_End;
} else {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
}
}
break;
case pas::kLS_End:
if (bc.IsAnimationOver()) {
x4_state = pas::kLS_Invalid;
st = pas::kAS_Locomotion;
}
break;
default:
break;
}
}
return st;
}
void CBSLoopAttack::Shutdown(CBodyController&) {}
pas::EAnimationState CBSLoopAttack::GetBodyStateTransition(float dt, CBodyController& bc) {
CBodyStateCmdMgr& cmdMgr = bc.CommandMgr();
if (cmdMgr.GetCmd(kBSC_Hurled)) {
return pas::kAS_Hurled;
}
if (cmdMgr.GetCmd(kBSC_KnockDown)) {
return pas::kAS_Fall;
}
if (cmdMgr.GetCmd(kBSC_LoopHitReaction)) {
return pas::kAS_LoopReaction;
}
if (cmdMgr.GetCmd(kBSC_KnockBack)) {
return pas::kAS_KnockBack;
}
if (cmdMgr.GetCmd(kBSC_Locomotion)) {
return pas::kAS_Locomotion;
}
if (x4_state == pas::kLS_End) {
if (cmdMgr.GetCmd(kBSC_MeleeAttack)) {
return pas::kAS_MeleeAttack;
}
if (cmdMgr.GetCmd(kBSC_ProjectileAttack)) {
return pas::kAS_ProjectileAttack;
}
if (cmdMgr.GetCmd(kBSC_LoopAttack)) {
return pas::kAS_LoopAttack;
}
if (cmdMgr.GetCmd(kBSC_Step)) {
return pas::kAS_Step;
}
if (cmdMgr.GetMoveVector().IsNonZero()) {
return pas::kAS_Locomotion;
}
if (cmdMgr.GetFaceVector().IsNonZero()) {
return pas::kAS_Turn;
}
}
return pas::kAS_Invalid;
}