#include "Runtime/Character/CBodyStateInfo.hpp" #include "Runtime/Character/CBodyController.hpp" #include "Runtime/World/CActor.hpp" namespace metaforce { CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type) { x34_24_changeLocoAtEndOfAnimOnly = false; const CPASDatabase& pasDatabase = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); for (size_t i = 0; i < pasDatabase.GetNumAnimStates(); ++i) { const CPASAnimState* state = pasDatabase.GetAnimStateByIndex(i); std::unique_ptr bs; switch (type) { case EBodyType::BiPedal: bs = SetupBiPedalBodyStates(state->GetStateId(), actor); break; case EBodyType::Restricted: default: bs = SetupRestrictedBodyStates(state->GetStateId(), actor); break; case EBodyType::Flyer: bs = SetupFlyerBodyStates(state->GetStateId(), actor); break; case EBodyType::Pitchable: bs = SetupPitchableBodyStates(state->GetStateId(), actor); break; case EBodyType::WallWalker: bs = SetupWallWalkerBodyStates(state->GetStateId(), actor); break; case EBodyType::NewFlyer: bs = SetupNewFlyerBodyStates(state->GetStateId(), actor); break; case EBodyType::RestrictedFlyer: bs = SetupRestrictedFlyerBodyStates(state->GetStateId(), actor); break; } if (bs) x0_stateMap[pas::EAnimationState(state->GetStateId())] = std::move(bs); } x1c_additiveStates.reserve(4); x1c_additiveStates.emplace_back(pas::EAnimationState::AdditiveIdle, std::make_unique()); x1c_additiveStates.emplace_back(pas::EAnimationState::AdditiveAim, std::make_unique()); x1c_additiveStates.emplace_back(pas::EAnimationState::AdditiveFlinch, std::make_unique()); x1c_additiveStates.emplace_back(pas::EAnimationState::AdditiveReaction, std::make_unique()); } std::unique_ptr CBodyStateInfo::SetupRestrictedFlyerBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupNewFlyerBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupWallWalkerBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupPitchableBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor, true); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupFlyerBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor, false); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupRestrictedBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); case pas::EAnimationState::Cover: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupBiPedalBodyStates(pas::EAnimationState stateId, CActor& actor) const { switch (stateId) { case pas::EAnimationState::Fall: return std::make_unique(); case pas::EAnimationState::Getup: return std::make_unique(); case pas::EAnimationState::LieOnGround: return std::make_unique(actor); case pas::EAnimationState::Step: return std::make_unique(); case pas::EAnimationState::Death: return std::make_unique(); case pas::EAnimationState::Locomotion: return std::make_unique(actor); case pas::EAnimationState::KnockBack: return std::make_unique(); case pas::EAnimationState::MeleeAttack: return std::make_unique(); case pas::EAnimationState::ProjectileAttack: return std::make_unique(); case pas::EAnimationState::LoopAttack: return std::make_unique(); case pas::EAnimationState::Turn: return std::make_unique(); case pas::EAnimationState::LoopReaction: return std::make_unique(); case pas::EAnimationState::GroundHit: return std::make_unique(); case pas::EAnimationState::Generate: return std::make_unique(); case pas::EAnimationState::Jump: return std::make_unique(); case pas::EAnimationState::Hurled: return std::make_unique(); case pas::EAnimationState::Slide: return std::make_unique(); case pas::EAnimationState::Taunt: return std::make_unique(); case pas::EAnimationState::Scripted: return std::make_unique(); case pas::EAnimationState::Cover: return std::make_unique(); case pas::EAnimationState::WallHang: return std::make_unique(); default: return {}; } } float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const { auto search = x0_stateMap.find(pas::EAnimationState::Locomotion); if (search != x0_stateMap.cend() && search->second && x18_bodyController) { const CBSLocomotion& bs = static_cast(*search->second); return bs.GetLocomotionSpeed(x18_bodyController->GetLocomotionType(), anim); } return 0.f; } float CBodyStateInfo::GetMaxSpeed() const { float ret = GetLocomotionSpeed(pas::ELocomotionAnim::Run); if (std::fabs(ret) < 0.00001f) { for (int i = 0; i < 8; ++i) { float tmp = GetLocomotionSpeed(pas::ELocomotionAnim(i)); if (tmp > ret) ret = tmp; } } return ret; } CBodyState* CBodyStateInfo::GetCurrentState() { auto search = x0_stateMap.find(x14_state); if (search == x0_stateMap.end()) return nullptr; return search->second.get(); } const CBodyState* CBodyStateInfo::GetCurrentState() const { auto search = x0_stateMap.find(x14_state); if (search == x0_stateMap.end()) return nullptr; return search->second.get(); } void CBodyStateInfo::SetState(pas::EAnimationState s) { auto search = x0_stateMap.find(s); if (search == x0_stateMap.end()) return; x14_state = s; } CAdditiveBodyState* CBodyStateInfo::GetCurrentAdditiveState() { for (auto& state : x1c_additiveStates) { if (x2c_additiveState == state.first) return state.second.get(); } return nullptr; } void CBodyStateInfo::SetAdditiveState(pas::EAnimationState s) { for (auto& state : x1c_additiveStates) { if (s == state.first) { x2c_additiveState = s; return; } } } bool CBodyStateInfo::ApplyHeadTracking() const { if (x14_state == pas::EAnimationState::Invalid) return false; return GetCurrentState()->ApplyHeadTracking(); } } // namespace metaforce