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