diff --git a/Runtime/MP1/World/CBurrower.cpp b/Runtime/MP1/World/CBurrower.cpp index abca8d1b7..ca2956771 100644 --- a/Runtime/MP1/World/CBurrower.cpp +++ b/Runtime/MP1/World/CBurrower.cpp @@ -1,22 +1,298 @@ #include "Runtime/MP1/World/CBurrower.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/Graphics/CBooRenderer.hpp" +#include "Runtime/Particle/CElementGen.hpp" +#include "Runtime/World/CGameArea.hpp" +#include "Runtime/World/CPatternedInfo.hpp" +#include "Runtime/World/CPlayer.hpp" +#include "Runtime/World/CWorld.hpp" #include "Runtime/CStateManager.hpp" +#include "TCastTo.hpp" // Generated file, do not modify include path + namespace urde::MP1 { +namespace { +constexpr CDamageVulnerability skVulnerability{ + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None}; +} // namespace CBurrower::CBurrower(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CAssetId, - CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, CAssetId) + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CAssetId aId1, + CAssetId aId2, CAssetId aId3, const CDamageInfo& damageInfo, CAssetId aId4, u32 sfxId, + CAssetId aId5) : CPatterned(ECharacter::Burrower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) {} + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) +, x568_pathFindSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x64c_projectileInfo(aId3, damageInfo) +, x6aa_visorSfx(CSfxManager::TranslateSFXID(sfxId)) { + CreateShadow(false); + MakeThermalColdAndHot(); + + x64c_projectileInfo.Token().Lock(); + if (aId1.IsValid()) { + x674_jumpParticle = + std::make_unique(g_SimplePool->GetObj({SBIG('PART'), aId1}), + CElementGen::EModelOrientationType::One, CElementGen::EOptionalSystemFlags::One); + x674_jumpParticle->SetGlobalScale(GetModelData()->GetScale()); + x674_jumpParticle->SetParticleEmission(false); + } + + if (aId2.IsValid()) { + x678_trailParticle = + std::make_unique(g_SimplePool->GetObj({SBIG('PART'), aId2}), + CElementGen::EModelOrientationType::One, CElementGen::EOptionalSystemFlags::One); + x678_trailParticle->SetGlobalScale(GetModelData()->GetScale()); + x678_trailParticle->SetParticleEmission(false); + } + + if (aId4.IsValid()) { + x67c_visorParticle.emplace(g_SimplePool->GetObj({SBIG('PART'), aId4})); + } + + if (aId5.IsValid()) { + x68c_deathExplosionParticle.emplace(g_SimplePool->GetObj({SBIG('PART'), aId5})); + } +} + +void CBurrower::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + return; + } + CPatterned::Think(dt, mgr); + if (x6a4_invulnDamageTime > 0.f) { + x6a4_invulnDamageTime -= dt; + } + + if (x6ac_24_doFacePlayer) { + zeus::CVector3f front = GetTransform().frontVector().normalized(); + zeus::CVector3f diffPos = (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized(); + if (front.dot(diffPos) < 0.9993) { + zeus::CQuaternion q = zeus::CQuaternion::lookAt(front, diffPos, zeus::degToRad(360.f * dt)); + q.setImaginary(GetTransform().transposeRotate(q.getImaginary())); + RotateToOR(q, dt); + } + } else if (x69c_attackTime > 0.f) { + x69c_attackTime -= dt; + } + + if (x674_jumpParticle) { + x6a0_lurkTimer -= dt; + if (!x6ac_25_inAir && x6a0_lurkTimer <= 0.f) { + if (IsAlive()) { + x674_jumpParticle->SetParticleEmission(true); + x674_jumpParticle->SetOrientation(GetTransform().getRotation()); + x674_jumpParticle->SetTranslation(GetTranslation()); + x674_jumpParticle->ForceParticleCreation(1); + x674_jumpParticle->SetOrientation({}); + x674_jumpParticle->SetParticleEmission(false); + } + x6a0_lurkTimer = 0.f; + } + x674_jumpParticle->Update(dt); + } + + if (x678_trailParticle) { + if (IsAlive() && !x6ac_25_inAir) { + x678_trailParticle->SetTranslation(GetTranslation()); + } + x678_trailParticle->Update(dt); + } +} void CBurrower::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { CPatterned::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Registered) + if (msg == EScriptObjectMessage::Registered) { x450_bodyController->Activate(mgr); - else if (msg == EScriptObjectMessage::InitializedInArea) { - - } else if (msg == EScriptObjectMessage::InvulnDamage) - x6a4_ = 1.f; + } else if (msg == EScriptObjectMessage::InitializedInArea) { + x568_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); + if (!HasPatrolPath(mgr, 0.f)) { + x678_trailParticle.reset(); + } + } else if (msg == EScriptObjectMessage::InvulnDamage) { + x6a4_invulnDamageTime = 1.f; + } } + +void CBurrower::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) { + if (GetActive() && x678_trailParticle) { + g_Renderer->AddParticleGen(*x678_trailParticle); + } + CPatterned::AddToRenderer(frustum, mgr); +} + +void CBurrower::Render(CStateManager& mgr) { + if (GetActorLights() != nullptr && x674_jumpParticle) { + x674_jumpParticle->Render(GetActorLights()); + } + CPatterned::Render(mgr); +} + +const CDamageVulnerability* CBurrower::GetDamageVulnerability() const { + if (x6ac_25_inAir) { + return CAi::GetDamageVulnerability(); + } + return &skVulnerability; +} + +const CDamageVulnerability* CBurrower::GetDamageVulnerability(const zeus::CVector3f& v1, const zeus::CVector3f& v2, + const CDamageInfo& damageInfo) const { + if (x6ac_25_inAir) { + return CAi::GetDamageVulnerability(); + } + return &skVulnerability; +} + +void CBurrower::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::Landing) { + x328_25_verticalMovement = false; + AddMaterial(EMaterialTypes::GroundCollider, mgr); + x55c_moveScale.splat(1.f); + return; + } + + if (type == EUserEventType::Projectile) { + const zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + const zeus::CVector3f gunPos = GetLctrTransform(node.GetLocatorName()).origin; + const zeus::CVector3f interPos = + GetProjectileInfo()->PredictInterceptPos(gunPos, aimPos, mgr.GetPlayer(), true, dt); + const zeus::CTransform gunXf = zeus::lookAt(gunPos, interPos); + LaunchProjectile(gunXf, mgr, 1, EProjectileAttrib::None, false, x67c_visorParticle, + x6aa_visorSfx, false, GetModelData()->GetScale()); + return; + } + + if (type == EUserEventType::TakeOff) { + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + x328_25_verticalMovement = true; + x55c_moveScale = GetModelData()->GetScale(); + return; + } + + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +void CBurrower::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) { + if (!IsAlive()) { + return; + } + + CPatterned::Death(mgr, direction, state); + if (x678_trailParticle) { + x678_trailParticle->SetParticleEmission(false); + } +} + +void CBurrower::Patrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x6ac_25_inAir = false; + if (x678_trailParticle) { + x678_trailParticle->SetParticleEmission(true); + } + } else if (msg == EStateMsg::Deactivate) { + x6a8_lastDestObj = x2dc_destObj; + } + + CPatterned::Patrol(mgr, msg, dt); +} + +void CBurrower::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg != EStateMsg::Activate) { + return; + } + + x2dc_destObj = x6a8_lastDestObj != kInvalidUniqueId + ? x6a8_lastDestObj + : GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); + + if (const TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) { + x2e0_destPos = act->GetTranslation(); + x328_24_inPosition = false; + x2ec_reflectedDestPos = GetTranslation(); + } +} + +void CBurrower::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg != EStateMsg::Activate) { + return; + } + GetBodyController()->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd{-GetTransform().frontVector(), GetTransform().frontVector(), 1.f}); +} + +void CBurrower::Active(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x6ac_24_doFacePlayer = true; + x32c_animState = EAnimState::Ready; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0); + } else if (msg == EStateMsg::Deactivate) { + x6ac_24_doFacePlayer = false; + x6ac_25_inAir = true; + x32c_animState = EAnimState::NotReady; + } +} + +void CBurrower::Lurk(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg != EStateMsg::Activate) { + return; + } + x6ac_25_inAir = false; + x6a0_lurkTimer = 0.1875f; +} + +void CBurrower::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x6ac_24_doFacePlayer = true; + x6ac_25_inAir = true; + if (x678_trailParticle) { + x678_trailParticle->SetParticleEmission(false); + } + x32c_animState = EAnimState::Ready; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + x69c_attackTime = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; + x328_25_verticalMovement = false; + AddMaterial(EMaterialTypes::GroundCollider, mgr); + x55c_moveScale.splat(1.f); + } +} + +void CBurrower::Retreat(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::Ready; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 1); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + if (x678_trailParticle) { + x678_trailParticle->SetParticleEmission(true); + } + } +} + +bool CBurrower::PathShagged(CStateManager& mgr, float arg) { + return x568_pathFindSearch.OnPath(GetTranslation()) == CPathFindSearch::EResult::InvalidArea; +} + +bool CBurrower::ShouldAttack(CStateManager& mgr, float arg) { + if (x6a4_invulnDamageTime > 0.f) { + return false; + } + + return mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 1); +} + +const std::optional>& CBurrower::GetDeathExplosionParticle() const { + if (x6ac_25_inAir) { + return x68c_deathExplosionParticle; + } + return x520_deathExplosionParticle; +} + } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CBurrower.hpp b/Runtime/MP1/World/CBurrower.hpp index 5bdabfc36..61af3014a 100644 --- a/Runtime/MP1/World/CBurrower.hpp +++ b/Runtime/MP1/World/CBurrower.hpp @@ -1,18 +1,54 @@ #pragma once +#include "Runtime/Weapon/CProjectileInfo.hpp" #include "Runtime/World/CPatterned.hpp" +#include "Runtime/World/CPathFindSearch.hpp" -namespace urde::MP1 { +namespace urde { +class CElementGen; +namespace MP1 { class CBurrower : public CPatterned { - float x6a4_ = 0.f; - + CPathFindSearch x568_pathFindSearch; + CProjectileInfo x64c_projectileInfo; + std::unique_ptr x674_jumpParticle; + std::unique_ptr x678_trailParticle; + std::optional> x67c_visorParticle; + std::optional> x68c_deathExplosionParticle; + float x69c_attackTime = 0.f; + float x6a0_lurkTimer = 0.f; + float x6a4_invulnDamageTime = 0.f; + TUniqueId x6a8_lastDestObj = kInvalidUniqueId; + s16 x6aa_visorSfx; + bool x6ac_24_doFacePlayer : 1 = false; + bool x6ac_25_inAir : 1 = false; public: DEFINE_PATTERNED(Burrower) CBurrower(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, const CActorParameters&, CAssetId, CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, CAssetId); + void Think(float, CStateManager&) override; void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override; + void AddToRenderer(const zeus::CFrustum&, CStateManager&) override; + void Render(CStateManager& mgr) override; + const CDamageVulnerability* GetDamageVulnerability() const override; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, + const CDamageInfo&) const override; + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) override; + void Patrol(CStateManager& mgr, EStateMsg msg, float dt) override; + void TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) override; + void TurnAround(CStateManager& mgr, EStateMsg msg, float dt) override; + void Active(CStateManager& mgr, EStateMsg msg, float dt) override; + void Lurk(CStateManager& mgr, EStateMsg msg, float dt) override; + void ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) override; + void Retreat(CStateManager& mgr, EStateMsg msg, float dt) override; + bool PathShagged(CStateManager& mgr, float arg) override; + bool ShouldAttack(CStateManager& mgr, float arg) override; + CPathFindSearch* GetSearchPath() override { return &x568_pathFindSearch; } + CProjectileInfo* GetProjectileInfo() override { return &x64c_projectileInfo; } + const std::optional>& GetDeathExplosionParticle() const override; }; -} // namespace urde::MP1 +} // namespace MP1 +} // namespace urde