mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-08-01 08:15:36 +00:00
131 lines
4.4 KiB
C++
131 lines
4.4 KiB
C++
#include "MetroidPrime/BodyState/CBSAttack.hpp"
|
|
|
|
#include "MetroidPrime/BodyState/CBodyController.hpp"
|
|
#include "MetroidPrime/CActor.hpp"
|
|
#include "MetroidPrime/CAnimData.hpp"
|
|
#include "MetroidPrime/CAnimPlaybackParms.hpp"
|
|
#include "MetroidPrime/CCharAnimTime.hpp"
|
|
#include "MetroidPrime/CPhysicsActor.hpp"
|
|
#include "MetroidPrime/CStateManager.hpp"
|
|
|
|
#include "Kyoto/Animation/CPASAnimParmData.hpp"
|
|
#include "Kyoto/Animation/CPASDatabase.hpp"
|
|
|
|
CBSAttack::CBSAttack()
|
|
: x4_nextState(pas::kAS_Invalid)
|
|
// , x8_slide(CBCSlideCmd())
|
|
, x20_targetPos(CVector3f::Zero())
|
|
, x2c_alignTargetPosStartTime(-1.f)
|
|
, x30_alignTargetPosTime(-1.f)
|
|
, x34_curTime(0.f) {}
|
|
|
|
void CBSAttack::Start(CBodyController& bc, CStateManager& mgr) {
|
|
const CBCMeleeAttackCmd* cmd =
|
|
static_cast< const CBCMeleeAttackCmd* >(bc.CommandMgr().GetCmd(kBSC_MeleeAttack));
|
|
const CPASDatabase& pasDatabase = bc.GetPASDatabase();
|
|
const CPASAnimParmData parms(pas::kAS_MeleeAttack,
|
|
CPASAnimParm::FromEnum(cmd->GetAttackSeverity()),
|
|
CPASAnimParm::FromEnum(bc.GetLocomotionType()));
|
|
|
|
const rstl::pair< float, int > best = pasDatabase.FindBestAnimation(parms, *mgr.Random(), -1);
|
|
const CAnimPlaybackParms playParms(best.second, -1, 1.f, true);
|
|
bc.SetCurrentAnimation(playParms, false, false);
|
|
if (cmd->HasAttackTargetPos()) {
|
|
x20_targetPos = cmd->GetAttackTargetPos();
|
|
|
|
CCharAnimTime evTime = bc.GetOwner().GetAnimationData()->GetTimeOfUserEvent(
|
|
kUE_AlignTargetPosStart, CCharAnimTime::Infinity());
|
|
x2c_alignTargetPosStartTime = (evTime != CCharAnimTime::Infinity()) ? evTime.GetSeconds() : 0.f;
|
|
|
|
evTime = bc.GetOwner().GetAnimationData()->GetTimeOfUserEvent(kUE_AlignTargetPos,
|
|
CCharAnimTime::Infinity());
|
|
x30_alignTargetPosTime =
|
|
(evTime != CCharAnimTime::Infinity()) ? evTime.GetSeconds() : bc.GetAnimTimeRemaining();
|
|
} else {
|
|
x20_targetPos = CVector3f::Zero();
|
|
x2c_alignTargetPosStartTime = -1.f;
|
|
x30_alignTargetPosTime = -1.f;
|
|
}
|
|
|
|
x4_nextState = pas::kAS_Locomotion;
|
|
x34_curTime = 0.f;
|
|
}
|
|
|
|
pas::EAnimationState CBSAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
|
|
x34_curTime += dt;
|
|
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
|
|
CBodyStateCmdMgr& commandMgr = bc.CommandMgr();
|
|
if (st == pas::kAS_Invalid) {
|
|
if (commandMgr.GetTargetVector().IsNonZero()) {
|
|
bc.FaceDirection(commandMgr.GetTargetVector(), dt);
|
|
}
|
|
UpdatePhysicsActor(bc, dt);
|
|
} else if (st == pas::kAS_Slide) {
|
|
commandMgr.DeliverCmd(x8_slide);
|
|
}
|
|
return st;
|
|
}
|
|
|
|
void CBSAttack::Shutdown(CBodyController&) {}
|
|
|
|
pas::EAnimationState CBSAttack::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 (const CBCSlideCmd* cmd = static_cast< const CBCSlideCmd* >(cmdMgr.GetCmd(kBSC_Slide))) {
|
|
x8_slide = *cmd;
|
|
x4_nextState = pas::kAS_Slide;
|
|
}
|
|
if (cmdMgr.GetCmd(kBSC_Generate)) {
|
|
return pas::kAS_Generate;
|
|
}
|
|
if (bc.IsAnimationOver()) {
|
|
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;
|
|
}
|
|
return x4_nextState;
|
|
}
|
|
if (cmdMgr.GetCmd(kBSC_NextState)) {
|
|
return x4_nextState;
|
|
}
|
|
return pas::kAS_Invalid;
|
|
}
|
|
|
|
void CBSAttack::UpdatePhysicsActor(CBodyController& bc, float dt) {
|
|
if (!x20_targetPos.IsNonZero()) {
|
|
return;
|
|
}
|
|
|
|
if (x34_curTime >= x2c_alignTargetPosStartTime && x34_curTime <= x30_alignTargetPosTime) {
|
|
|
|
if (CPhysicsActor* act = TCastToPtr< CPhysicsActor >(&bc.GetOwner())) {
|
|
CVector3f delta = x20_targetPos - act->GetTranslation();
|
|
const float dur = x30_alignTargetPosTime - x2c_alignTargetPosStartTime;
|
|
CVector3f deltaMod = (dur > 0.f) ? (delta * (dt / dur)) : delta;
|
|
|
|
CVector3f impulse = act->GetMoveToORImpulseWR(act->GetTransform().TransposeRotate(deltaMod), dt);
|
|
act->ApplyImpulseWR(impulse, CAxisAngle::Identity());
|
|
}
|
|
}
|
|
}
|