#include "Runtime/World/CAmbientAI.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/World/CPlayer.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path namespace metaforce { CAmbientAI::CAmbientAI(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabox, const CMaterialList& matList, float mass, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, const CActorParameters& aParms, float alertRange, float impactRange, s32 alertAnim, s32 impactAnim, bool active) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), matList, aabox, SMoverData(mass), aParms, 0.3f, 0.1f) , x258_initialHealthInfo(hInfo) , x260_healthInfo(hInfo) , x268_dVuln(dVuln) , x2d4_alertRange(alertRange) , x2d8_impactRange(impactRange) , x2dc_defaultAnim(GetModelData()->GetAnimationData()->GetDefaultAnimation()) , x2e0_alertAnim(alertAnim) , x2e4_impactAnim(impactAnim) { GetModelData()->GetAnimationData()->EnableLooping(true); } void CAmbientAI::Accept(IVisitor& visitor) { visitor.Visit(this); } void CAmbientAI::Think(float dt, CStateManager& mgr) { if (!GetActive()) return; if (GetModelData() && GetModelData()->GetAnimationData() != nullptr) { bool hasAnimTime = GetModelData()->GetAnimationData()->IsAnimTimeRemaining( dt - FLT_EPSILON, "Whole Body"sv); bool isLooping = GetModelData()->GetIsLoop(); if (hasAnimTime || isLooping) { x2e8_25_animating = true; SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); MoveToOR(deltas.x0_posDelta, dt); RotateToOR(deltas.xc_rotDelta, dt); } if (hasAnimTime) { } else if (x2e8_25_animating && !isLooping) { SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); x2e8_25_animating = false; } } bool inAlertRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d4_alertRange; bool inImpactRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d8_impactRange; switch (x2d0_animState) { case EAnimationState::Ready: { if (inAlertRange) { x2d0_animState = EAnimationState::Alert; GetModelData()->GetAnimationData()->SetAnimation(CAnimPlaybackParms(x2e0_alertAnim, -1, 1.f, true), false); GetModelData()->EnableLooping(true); RandomizePlaybackRate(mgr); } break; } case EAnimationState::Alert: { if (!inAlertRange) { x2d0_animState = EAnimationState::Ready; GetModelData()->GetAnimationData()->SetAnimation( CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); GetModelData()->EnableLooping(true); RandomizePlaybackRate(mgr); } else if (inImpactRange) { SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); RemoveEmitter(); SetActive(false); } break; } case EAnimationState::Impact: { if (!x2e8_25_animating) { x2d0_animState = EAnimationState::Ready; GetModelData()->GetAnimationData()->SetAnimation( CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); GetModelData()->EnableLooping(true); RandomizePlaybackRate(mgr); } break; } } if (x2e8_24_dead) { return; } CHealthInfo* hInfo = HealthInfo(mgr); if (hInfo->GetHP() <= 0.f) { x2e8_24_dead = true; SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); RemoveEmitter(); SetActive(false); } } void CAmbientAI::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { switch (msg) { case EScriptObjectMessage::Reset: { if (!GetActive()) SetActive(true); x2d0_animState = EAnimationState::Ready; GetModelData()->GetAnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); GetModelData()->GetAnimationData()->EnableLooping(true); RandomizePlaybackRate(mgr); x2e8_24_dead = false; x260_healthInfo = x258_initialHealthInfo; break; } case EScriptObjectMessage::InitializedInArea: RandomizePlaybackRate(mgr); break; case EScriptObjectMessage::Damage: { if (GetActive()) { x2d0_animState = EAnimationState::Impact; GetModelData()->GetAnimationData()->SetAnimation(CAnimPlaybackParms(x2e4_impactAnim, -1, 1.f, true), false); GetModelData()->GetAnimationData()->EnableLooping(false); RandomizePlaybackRate(mgr); } break; } default: break; } CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); } std::optional CAmbientAI::GetTouchBounds() const { if (GetActive()) { return {GetBoundingBox()}; } return std::nullopt; } void CAmbientAI::RandomizePlaybackRate(CStateManager& mgr) { GetModelData()->GetAnimationData()->MultiplyPlaybackRate(0.4f * mgr.GetActiveRandom()->Float() + 0.8f); } } // namespace metaforce