mirror of https://github.com/AxioDL/metaforce.git
201 lines
8.4 KiB
C++
201 lines
8.4 KiB
C++
#include "Runtime/Character/CAdditiveBodyState.hpp"
|
|
|
|
#include "Runtime/CStateManager.hpp"
|
|
#include "Runtime/Character/CBodyController.hpp"
|
|
#include "Runtime/Character/CAnimTreeNode.hpp"
|
|
#include "Runtime/Character/CPASDatabase.hpp"
|
|
#include "Runtime/Character/CPASAnimParmData.hpp"
|
|
|
|
namespace metaforce {
|
|
|
|
void CABSAim::Start(CBodyController& bc, CStateManager& mgr) {
|
|
// const CBCAdditiveAimCmd* cmd =
|
|
// static_cast<const CBCAdditiveAimCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim));
|
|
const CPASAnimState* aimState = bc.GetPASDatabase().GetAnimState(pas::EAnimationState::AdditiveAim);
|
|
|
|
// Left, Right, Up, Down
|
|
for (size_t i = 0; i < x8_anims.size(); ++i) {
|
|
const CPASAnimParmData parms(pas::EAnimationState::AdditiveAim, CPASAnimParm::FromEnum(s32(i)));
|
|
const std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
|
|
x8_anims[i] = best.second;
|
|
x18_angles[i] = zeus::degToRad(aimState->GetAnimParmData(x8_anims[i], 1).GetReal32Value());
|
|
}
|
|
|
|
const CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
x28_hWeight = -animData.GetAdditiveAnimationWeight(x8_anims[0]);
|
|
x28_hWeight += animData.GetAdditiveAnimationWeight(x8_anims[1]);
|
|
x30_vWeight = -animData.GetAdditiveAnimationWeight(x8_anims[3]);
|
|
x30_vWeight += animData.GetAdditiveAnimationWeight(x8_anims[2]);
|
|
|
|
x4_needsIdle = false;
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle))
|
|
x4_needsIdle = true;
|
|
}
|
|
|
|
pas::EAnimationState CABSAim::GetBodyStateTransition(float dt, CBodyController& bc) const {
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
|
|
return pas::EAnimationState::AdditiveReaction;
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
|
|
return pas::EAnimationState::AdditiveFlinch;
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle) || x4_needsIdle)
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
return pas::EAnimationState::Invalid;
|
|
}
|
|
|
|
pas::EAnimationState CABSAim::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
|
|
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
|
|
if (st == pas::EAnimationState::Invalid) {
|
|
const zeus::CVector3f& target = bc.GetCommandMgr().GetAdditiveTargetVector();
|
|
if (target.canBeNormalized()) {
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
|
|
float hAngle = zeus::clamp(-x18_angles[0], std::atan2(target.x(), target.y()), x18_angles[1]);
|
|
hAngle *= 0.63661975f;
|
|
hAngle = zeus::clamp(-3.f, (hAngle - x28_hWeight) * 0.25f / dt, 3.f);
|
|
x2c_hWeightVel += dt * zeus::clamp(-10.f, (hAngle - x2c_hWeightVel) / dt, 10.f);
|
|
|
|
float hypotenuse = std::sqrt(target.y() * target.y() + target.x() * target.x());
|
|
float vAngle = zeus::clamp(-x18_angles[3], std::atan2(target.z(), hypotenuse), x18_angles[2]);
|
|
vAngle *= 0.63661975f;
|
|
vAngle = zeus::clamp(-3.f, (vAngle - x30_vWeight) * 0.25f / dt, 3.f);
|
|
x34_vWeightVel += dt * zeus::clamp(-10.f, (vAngle - x34_vWeightVel) / dt, 10.f);
|
|
|
|
float newHWeight = dt * x2c_hWeightVel + x28_hWeight;
|
|
if (newHWeight != x28_hWeight) {
|
|
if (std::fabs(x28_hWeight) > 0.f && x28_hWeight * newHWeight <= 0.f)
|
|
animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
|
|
float absWeight = std::fabs(newHWeight);
|
|
if (absWeight > 0.f)
|
|
animData.AddAdditiveAnimation(x8_anims[newHWeight < 0.f ? 0 : 1], absWeight, false, false);
|
|
}
|
|
|
|
float newVWeight = dt * x34_vWeightVel + x30_vWeight;
|
|
if (newVWeight != x30_vWeight) {
|
|
if (std::fabs(x30_vWeight) > 0.f && x30_vWeight * newVWeight <= 0.f)
|
|
animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
|
|
float absWeight = std::fabs(newVWeight);
|
|
if (absWeight > 0.f)
|
|
animData.AddAdditiveAnimation(x8_anims[newVWeight > 0.f ? 2 : 3], absWeight, false, false);
|
|
}
|
|
|
|
x28_hWeight = newHWeight;
|
|
x30_vWeight = newVWeight;
|
|
}
|
|
}
|
|
return st;
|
|
}
|
|
|
|
void CABSAim::Shutdown(CBodyController& bc) {
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
|
|
if (x28_hWeight != 0.f)
|
|
animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]);
|
|
if (x30_vWeight != 0.f)
|
|
animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]);
|
|
}
|
|
|
|
void CABSFlinch::Start(CBodyController& bc, CStateManager& mgr) {
|
|
const CBCAdditiveFlinchCmd* cmd =
|
|
static_cast<const CBCAdditiveFlinchCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch));
|
|
x4_weight = cmd->GetWeight();
|
|
|
|
CPASAnimParmData parms(pas::EAnimationState::AdditiveFlinch);
|
|
std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
|
|
x8_anim = best.second;
|
|
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
animData.AddAdditiveAnimation(x8_anim, x4_weight, false, true);
|
|
}
|
|
|
|
pas::EAnimationState CABSFlinch::GetBodyStateTransition(float dt, CBodyController& bc) const {
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
|
|
return pas::EAnimationState::AdditiveReaction;
|
|
return pas::EAnimationState::Invalid;
|
|
}
|
|
|
|
pas::EAnimationState CABSFlinch::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
|
|
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
|
|
if (st == pas::EAnimationState::Invalid) {
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
|
|
if (std::fabs(rem.GetSeconds()) < 0.00001f)
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
}
|
|
return st;
|
|
}
|
|
|
|
pas::EAnimationState CABSIdle::GetBodyStateTransition(float dt, CBodyController& bc) const {
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction))
|
|
return pas::EAnimationState::AdditiveReaction;
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch))
|
|
return pas::EAnimationState::AdditiveFlinch;
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim))
|
|
return pas::EAnimationState::AdditiveAim;
|
|
return pas::EAnimationState::Invalid;
|
|
}
|
|
|
|
pas::EAnimationState CABSIdle::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
|
|
return GetBodyStateTransition(dt, bc);
|
|
}
|
|
|
|
void CABSReaction::Start(CBodyController& bc, CStateManager& mgr) {
|
|
const CBCAdditiveReactionCmd* cmd =
|
|
static_cast<const CBCAdditiveReactionCmd*>(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction));
|
|
x4_weight = cmd->GetWeight();
|
|
xc_type = cmd->GetType();
|
|
x10_active = cmd->GetIsActive();
|
|
|
|
CPASAnimParmData parms(pas::EAnimationState::AdditiveReaction, CPASAnimParm::FromEnum(s32(xc_type)));
|
|
std::pair<float, s32> best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1);
|
|
x8_anim = best.second;
|
|
|
|
if (x8_anim != -1) {
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
animData.AddAdditiveAnimation(x8_anim, x4_weight, x10_active, false);
|
|
}
|
|
}
|
|
|
|
pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) const {
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && xc_type == pas::EAdditiveReactionType::IceBreakout)
|
|
return pas::EAnimationState::AdditiveReaction;
|
|
return pas::EAnimationState::Invalid;
|
|
}
|
|
|
|
pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) {
|
|
const pas::EAnimationState st = GetBodyStateTransition(dt, bc);
|
|
if (st == pas::EAnimationState::Invalid) {
|
|
if (x8_anim == -1)
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
if (x10_active) {
|
|
if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction)) {
|
|
StopAnimation(bc);
|
|
bc.GetOwner().RemoveEmitter();
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
}
|
|
} else {
|
|
if (animData.IsAdditiveAnimationAdded(x8_anim)) {
|
|
CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining();
|
|
if (std::fabs(rem.GetSeconds()) < 0.00001f) {
|
|
StopAnimation(bc);
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
}
|
|
} else {
|
|
return pas::EAnimationState::AdditiveIdle;
|
|
}
|
|
}
|
|
}
|
|
return st;
|
|
}
|
|
|
|
void CABSReaction::StopAnimation(CBodyController& bc) {
|
|
if (x8_anim != -1) {
|
|
CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData();
|
|
animData.DelAdditiveAnimation(x8_anim);
|
|
x8_anim = -1;
|
|
}
|
|
}
|
|
|
|
} // namespace metaforce
|