Add CBSTurn

This commit is contained in:
Henrique Gemignani Passos Lima 2022-11-23 23:25:35 +02:00
parent 3a425ceeff
commit 29457d953c
No known key found for this signature in database
GPG Key ID: E224F951761145F8
6 changed files with 226 additions and 15 deletions

View File

@ -3,8 +3,8 @@
.section .data
.balign 8
.global lbl_803E1750
lbl_803E1750:
.global __vt__12CBSFlyerTurn
__vt__12CBSFlyerTurn:
# ROM: 0x3DE750
.4byte 0
.4byte 0
@ -22,8 +22,8 @@ lbl_803E1750:
.4byte Shutdown__7CBSTurnFR15CBodyController
.4byte GetBodyStateTransition__7CBSTurnFfR15CBodyController
.global lbl_803E178C
lbl_803E178C:
.global __vt__7CBSTurn
__vt__7CBSTurn:
# ROM: 0x3DE78C
.4byte 0
.4byte 0
@ -51,12 +51,12 @@ __dt__12CBSFlyerTurnFv:
/* 801391D0 00136130 93 E1 00 0C */ stw r31, 0xc(r1)
/* 801391D4 00136134 7C 7F 1B 79 */ or. r31, r3, r3
/* 801391D8 00136138 41 82 00 40 */ beq lbl_80139218
/* 801391DC 0013613C 3C 60 80 3E */ lis r3, lbl_803E1750@ha
/* 801391E0 00136140 38 03 17 50 */ addi r0, r3, lbl_803E1750@l
/* 801391DC 0013613C 3C 60 80 3E */ lis r3, __vt__12CBSFlyerTurn@ha
/* 801391E0 00136140 38 03 17 50 */ addi r0, r3, __vt__12CBSFlyerTurn@l
/* 801391E4 00136144 90 1F 00 00 */ stw r0, 0(r31)
/* 801391E8 00136148 41 82 00 20 */ beq lbl_80139208
/* 801391EC 0013614C 3C 60 80 3E */ lis r3, lbl_803E178C@ha
/* 801391F0 00136150 38 03 17 8C */ addi r0, r3, lbl_803E178C@l
/* 801391EC 0013614C 3C 60 80 3E */ lis r3, __vt__7CBSTurn@ha
/* 801391F0 00136150 38 03 17 8C */ addi r0, r3, __vt__7CBSTurn@l
/* 801391F4 00136154 90 1F 00 00 */ stw r0, 0(r31)
/* 801391F8 00136158 41 82 00 10 */ beq lbl_80139208
/* 801391FC 0013615C 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha
@ -361,9 +361,9 @@ __ct__12CBSFlyerTurnFv:
/* 80139630 00136590 93 E1 00 0C */ stw r31, 0xc(r1)
/* 80139634 00136594 7C 7F 1B 78 */ mr r31, r3
/* 80139638 00136598 48 00 06 A9 */ bl __ct__7CBSTurnFv
/* 8013963C 0013659C 3C 80 80 3E */ lis r4, lbl_803E1750@ha
/* 8013963C 0013659C 3C 80 80 3E */ lis r4, __vt__12CBSFlyerTurn@ha
/* 80139640 001365A0 7F E3 FB 78 */ mr r3, r31
/* 80139644 001365A4 38 04 17 50 */ addi r0, r4, lbl_803E1750@l
/* 80139644 001365A4 38 04 17 50 */ addi r0, r4, __vt__12CBSFlyerTurn@l
/* 80139648 001365A8 90 1F 00 00 */ stw r0, 0(r31)
/* 8013964C 001365AC 83 E1 00 0C */ lwz r31, 0xc(r1)
/* 80139650 001365B0 80 01 00 14 */ lwz r0, 0x14(r1)
@ -379,8 +379,8 @@ __dt__7CBSTurnFv:
/* 8013966C 001365CC 93 E1 00 0C */ stw r31, 0xc(r1)
/* 80139670 001365D0 7C 7F 1B 79 */ or. r31, r3, r3
/* 80139674 001365D4 41 82 00 30 */ beq lbl_801396A4
/* 80139678 001365D8 3C 60 80 3E */ lis r3, lbl_803E178C@ha
/* 8013967C 001365DC 38 03 17 8C */ addi r0, r3, lbl_803E178C@l
/* 80139678 001365D8 3C 60 80 3E */ lis r3, __vt__7CBSTurn@ha
/* 8013967C 001365DC 38 03 17 8C */ addi r0, r3, __vt__7CBSTurn@l
/* 80139680 001365E0 90 1F 00 00 */ stw r0, 0(r31)
/* 80139684 001365E4 41 82 00 10 */ beq lbl_80139694
/* 80139688 001365E8 3C 60 80 3E */ lis r3, __vt__10CBodyState@ha
@ -851,9 +851,9 @@ __ct__7CBSTurnFv:
/* 80139CF8 00136C58 FC 40 08 90 */ fmr f2, f1
/* 80139CFC 00136C5C 93 E1 00 0C */ stw r31, 0xc(r1)
/* 80139D00 00136C60 7C 7F 1B 78 */ mr r31, r3
/* 80139D04 00136C64 3C 60 80 3E */ lis r3, lbl_803E178C@ha
/* 80139D04 00136C64 3C 60 80 3E */ lis r3, __vt__7CBSTurn@ha
/* 80139D08 00136C68 90 1F 00 00 */ stw r0, 0(r31)
/* 80139D0C 00136C6C 38 03 17 8C */ addi r0, r3, lbl_803E178C@l
/* 80139D0C 00136C6C 38 03 17 8C */ addi r0, r3, __vt__7CBSTurn@l
/* 80139D10 00136C70 38 7F 00 08 */ addi r3, r31, 8
/* 80139D14 00136C74 90 1F 00 00 */ stw r0, 0(r31)
/* 80139D18 00136C78 D0 3F 00 04 */ stfs f1, 4(r31)

View File

@ -192,7 +192,7 @@ LIBS = [
["MetroidPrime/BodyState/CBSLieOnGround", True],
"MetroidPrime/BodyState/CBSLocomotion",
["MetroidPrime/BodyState/CBSStep", True],
"MetroidPrime/BodyState/CBSTurn",
["MetroidPrime/BodyState/CBSTurn", False],
"MetroidPrime/BodyState/CBodyController",
["MetroidPrime/BodyState/CBSLoopAttack", False],
["MetroidPrime/Weapons/CTargetableProjectile", False],

View File

@ -71,6 +71,7 @@ public:
CPASAnimParm GetAnimParmData(int, unsigned int) const;
pas::EAnimationState GetStateId() const { return x0_id; }
bool HasAnims() const { return static_cast<uint>(x14_anims.size()) != 0; }
private:
pas::EAnimationState x0_id;

View File

@ -98,6 +98,10 @@ public:
return *this;
}
CVector2f ToVec2f() const {
return CVector2f(mX, mY);
}
static float Dot(const CVector3f& a, const CVector3f& b) {
return (a.GetX() * b.GetX()) + (a.GetY() * b.GetY()) + (a.GetZ() * b.GetZ());
}

View File

@ -0,0 +1,35 @@
#ifndef _CBSTURN
#define _CBSTURN
#include "MetroidPrime/BodyState/CBodyState.hpp"
#include "Kyoto/Math/CVector2f.hpp"
class CBSTurn : public CBodyState {
public:
CBSTurn();
~CBSTurn() override {}
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;
protected:
float x4_rotateSpeed;
CVector2f x8_dest;
pas::ETurnDirection x10_turnDir;
virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
bool FacingDest(CBodyController& bc) const;
};
class CBSFlyerTurn : public CBSTurn {
public:
CBSFlyerTurn();
void Start(CBodyController& bc, CStateManager& mgr) override;
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) override;
};
#endif // _CBSTURN

View File

@ -0,0 +1,171 @@
#include "MetroidPrime/BodyState/CBSTurn.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/CVector3f.hpp"
inline CVector2f FlipCenterColumn(const CTransform4f& m) {
CVector2f v = m.GetColumn(kDY).ToVec2f();
return CVector2f(v.GetY(), -v.GetX());
}
CBSTurn::CBSTurn() : x4_rotateSpeed(0.f), x8_dest(0.0f, 0.0f), x10_turnDir(pas::kTD_Invalid) {}
void CBSTurn::Start(CBodyController& bc, CStateManager& mgr) {
const CVector3f& lookDir = bc.GetOwner().GetTransform().GetColumn(kDY);
const CVector2f lookDir2d(lookDir.GetX(), lookDir.GetY());
x8_dest = bc.GetCommandMgr().GetFaceVector().ToVec2f();
const float deltaAngle = CMath::Rad2Deg(CVector2f::GetAngleDiff(lookDir2d, x8_dest));
const CVector2f lookDir2dInv(lookDir2d.GetY(), -lookDir2d.GetX());
float dot = CVector2f::Dot(CVector2f(lookDir2dInv), x8_dest);
x10_turnDir = dot > 0.f ? pas::kTD_Left : pas::kTD_Right;
const CPASDatabase& db = bc.GetPASDatabase();
const CPASAnimParmData parms(pas::kAS_Turn, CPASAnimParm::FromEnum(x10_turnDir),
CPASAnimParm::FromReal32(deltaAngle),
CPASAnimParm::FromEnum(bc.GetLocomotionType()));
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 CPASAnimParm& animAngle = db.GetAnimState(pas::kAS_Turn)->GetAnimParmData(best.second, 1);
x4_rotateSpeed =
CMath::Deg2Rad((x10_turnDir == pas::kTD_Left) ? animAngle.GetReal32Value() - deltaAngle
: deltaAngle - animAngle.GetReal32Value());
const float timeRem = bc.GetAnimTimeRemaining();
if (timeRem > 0.f) {
x4_rotateSpeed /= timeRem;
}
}
pas::EAnimationState CBSTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
if (st == pas::kAS_Invalid) {
bc.SetDeltaRotation(CQuaternion::ZRotation(CRelAngle::FromRadians(x4_rotateSpeed * dt)));
}
return st;
}
void CBSTurn::Shutdown(CBodyController&) {}
bool CBSTurn::FacingDest(CBodyController& bc) const {
const CVector2f leftDir = FlipCenterColumn(bc.GetOwner().GetTransform());
if (x10_turnDir == pas::kTD_Left) {
if (CVector2f::Dot(leftDir, x8_dest) < 0.f) {
return true;
}
} else {
if (CVector2f::Dot(leftDir, x8_dest) > 0.f) {
return true;
}
}
return false;
}
pas::EAnimationState CBSTurn::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 (cmdMgr.GetCmd(kBSC_Generate)) {
return pas::kAS_Generate;
}
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_LoopReaction)) {
return pas::kAS_LoopReaction;
}
if (cmdMgr.GetCmd(kBSC_Jump)) {
return pas::kAS_Jump;
}
if (cmdMgr.GetCmd(kBSC_Step)) {
return pas::kAS_Step;
}
if (cmdMgr.GetCmd(kBSC_Scripted)) {
return pas::kAS_Scripted;
}
if (bc.IsAnimationOver() || FacingDest(bc) || cmdMgr.GetMoveVector().IsNonZero()) {
return pas::kAS_Locomotion;
}
return pas::kAS_Invalid;
}
CBSFlyerTurn::CBSFlyerTurn() {}
void CBSFlyerTurn::Start(CBodyController& bc, CStateManager& mgr) {
const CPASDatabase& db = bc.GetPASDatabase();
if (db.GetAnimState(pas::kAS_Turn)->HasAnims()) {
CBSTurn::Start(bc, mgr);
} else {
x8_dest = bc.GetCommandMgr().GetFaceVector().ToVec2f();
const CVector2f& lookDir2dInv = FlipCenterColumn(bc.GetOwner().GetTransform());
float dot = CVector2f::Dot(CVector2f(lookDir2dInv), x8_dest);
x10_turnDir = dot > 0.f ? pas::kTD_Left : pas::kTD_Right;
const CPASAnimParmData parms(pas::kAS_Locomotion, CPASAnimParm::FromEnum(0),
CPASAnimParm::FromEnum(bc.GetLocomotionType()));
const rstl::pair< float, int > best = db.FindBestAnimation(parms, *mgr.Random(), -1);
if (best.second != bc.GetCurrentAnimId()) {
const CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
bc.SetCurrentAnimation(playParms, true, false);
}
}
}
pas::EAnimationState CBSFlyerTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
if (bc.GetPASDatabase().GetAnimState(pas::kAS_Turn)->HasAnims()) {
return CBSTurn::UpdateBody(dt, bc, mgr);
}
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
if (st == pas::kAS_Invalid) {
CBodyStateCmdMgr& cmdMgr = bc.CommandMgr();
CVector3f faceVec = cmdMgr.GetFaceVector();
if (faceVec.IsNonZero()) {
x8_dest = faceVec.ToVec2f();
const CVector2f& lookDir2dInv = FlipCenterColumn(bc.GetOwner().GetTransform());
float dot = CVector2f::Dot(CVector2f(lookDir2dInv), x8_dest);
x10_turnDir = dot > 0.f ? pas::kTD_Left : pas::kTD_Right;
}
bc.FaceDirection(CVector3f(x8_dest.GetX(), x8_dest.GetY(), 0.f), dt);
}
return st;
}