Henrique Gemignani Passos Lima b988da7f60 Add CBSAttack
Former-commit-id: 50c6435c62f6d7769ff60c4a5489667f9fdd92a4
2022-11-11 16:53:38 +02:00

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());
}
}
}