#include "CBodyStateInfo.hpp" #include "World/CActor.hpp" #include "CBodyController.hpp" namespace urde { CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type) { x34_24_changeLocoAtEndOfAnimOnly = false; const CPASDatabase& pasDatabase = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); for (int 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.push_back({pas::EAnimationState::AdditiveIdle, std::make_unique()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveAim, std::make_unique()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveFlinch, std::make_unique()}); x1c_additiveStates.push_back({pas::EAnimationState::AdditiveReaction, std::make_unique()}); } std::unique_ptr CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupNewFlyerBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupWallWalkerBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupPitchableBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor, true); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupFlyerBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor, false); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupRestrictedBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); case 19: return std::make_unique(); default: return {}; } } std::unique_ptr CBodyStateInfo::SetupBiPedalBodyStates(int stateId, CActor& actor) { switch (stateId) { case 0: return std::make_unique(); case 1: return std::make_unique(); case 2: return std::make_unique(actor); case 3: return std::make_unique(); case 4: return std::make_unique(); case 5: return std::make_unique(actor); case 6: return std::make_unique(); case 7: return std::make_unique(); case 18: return std::make_unique(); case 9: return std::make_unique(); case 8: return std::make_unique(); case 10: return std::make_unique(); case 11: return std::make_unique(); case 12: return std::make_unique(); case 13: return std::make_unique(); case 14: return std::make_unique(); case 15: return std::make_unique(); case 16: return std::make_unique(); case 17: return std::make_unique(); case 19: return std::make_unique(); case 20: 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 urde