From 5724be3294b992cbc91514aa17d2e8475ac1baae Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 26 Apr 2020 17:43:22 -0700 Subject: [PATCH] CIceSheegoth: Implement AddToRenderer and AttractProjectiles --- Runtime/MP1/World/CIceSheegoth.cpp | 317 ++++++++++++++++++++++++++--- Runtime/MP1/World/CIceSheegoth.hpp | 18 +- 2 files changed, 304 insertions(+), 31 deletions(-) diff --git a/Runtime/MP1/World/CIceSheegoth.cpp b/Runtime/MP1/World/CIceSheegoth.cpp index 24b380bca..19f79c7ac 100644 --- a/Runtime/MP1/World/CIceSheegoth.cpp +++ b/Runtime/MP1/World/CIceSheegoth.cpp @@ -9,6 +9,7 @@ #include "Runtime/Collision/CCollisionActor.hpp" #include "Runtime/Collision/CCollisionActorManager.hpp" #include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Particle/CElementGen.hpp" #include "Runtime/Particle/CParticleElectric.hpp" #include "Runtime/Particle/CParticleSwoosh.hpp" @@ -105,6 +106,7 @@ CIceSheegoth::CIceSheegoth(TUniqueId uid, std::string_view name, const CEntityIn CElementGen::EOptionalSystemFlags::One)) , xac8_(g_SimplePool->GetObj({SBIG('ELSC'), sheegothData.Get_x1ac()})) , xad8_(std::make_unique(xac8_)) +, xadc_(g_SimplePool->GetObj({SBIG('PART'), sheegothData.Get_x19c()})) , xb28_24_shotAt(false) , xb28_25_(false) , xb28_26_(false) @@ -118,7 +120,7 @@ CIceSheegoth::CIceSheegoth(TUniqueId uid, std::string_view name, const CEntityIn , xb29_26_(false) , xb29_27_(false) , xb29_28_(false) -, xb29_29_(false) { +, xb29_29_scanned(false) { UpdateTouchBounds(); x460_knockBackController.SetEnableFreeze(false); @@ -146,7 +148,7 @@ void CIceSheegoth::Think(float dt, CStateManager& mgr) { CPatterned::Think(dt, mgr); AttractProjectiles(mgr); UpdateTimers(dt); - sub_8019e6f0(mgr); + UpdateScanState(mgr); if (!IsAlive()) { x974_ = std::max(0.f, x974_ - (dt * x56c_sheegothData.Get_x170())); if (GetBodyController()->GetBodyStateInfo().GetCurrentState()->IsDying()) { @@ -217,9 +219,9 @@ void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C mgr.FreeScriptObject(xa80_flameThrowerId); xa80_flameThrowerId = kInvalidUniqueId; } - if (xaf0_) { - CSfxManager::RemoveEmitter(xaf0_); - xaf0_.reset(); + if (xaf0_crackleSfx) { + CSfxManager::RemoveEmitter(xaf0_crackleSfx); + xaf0_crackleSfx.reset(); } break; } @@ -231,7 +233,7 @@ void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C case EScriptObjectMessage::Damage: { if (TCastToPtr colAct = mgr.ObjectById(sender)) { if (const TCastToConstPtr wp = mgr.GetObjectById(colAct->GetLastTouchedObject())) { - if (sender == xaf6_ && !xb28_27_) { + if (sender == xaf6_iceShardsCollider && !xb28_27_) { sub_8019ebf0(mgr, wp->GetDamageInfo().GetDamage()); if (!xaec_ || xaec_->IsSystemDeletable()) { xaec_ = std::make_unique(xadc_, CElementGen::EModelOrientationType::Normal, @@ -254,7 +256,7 @@ void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C break; } case EScriptObjectMessage::InvulnDamage: { - if (sender == xaf6_ && !xb28_27_) { + if (sender == xaf6_iceShardsCollider && !xb28_27_) { if (TCastToPtr colAct = mgr.ObjectById(sender)) { if (const TCastToConstPtr wp = mgr.GetObjectById(colAct->GetLastTouchedObject())) { sub_8019ebf0(mgr, wp->GetDamageInfo().GetDamage()); @@ -284,11 +286,100 @@ void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C void CIceSheegoth::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) { CPatterned::AddToRenderer(frustum, mgr); + + if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) { + if (x428_damageCooldownTimer == 0.f && xb29_25_ && + (HasModelData() && (GetModelData()->HasAnimData() || GetModelData()->HasNormalModel()))) { + GetModelData()->RenderParticles(frustum); + } + } else { + std::optional bounds1; + if (xaec_) { + bounds1 = xaec_->GetBounds(); + } + std::optional bounds2; + if (xa9c_) { + bounds2 = xa9c_->GetBounds(); + } + + std::optional bounds3; + if (xab0_) { + bounds3 = xab0_->GetBounds(); + } + + std::optional bounds4; + if (xac4_) { + bounds4 = xac4_->GetBounds(); + } + + std::optional bounds5; + if (xad8_) { + bounds5 = xad8_->GetBounds(); + } + + /* Lawl retro + std::optional bounds6; + if (xad8_) { + bounds6 = xad8_->GetBounds(); + } + */ + + zeus::CAABox accumulatedBounds = zeus::skInvertedBox; + if (bounds1) { + accumulatedBounds.accumulateBounds(*bounds1); + } + /* Lawl retro + if (bounds6) { + accumulatedBounds.accumulateBounds(*bounds6); + } + */ + if (bounds2) { + accumulatedBounds.accumulateBounds(*bounds2); + } + if (bounds3) { + accumulatedBounds.accumulateBounds(*bounds3); + } + if (bounds4) { + accumulatedBounds.accumulateBounds(*bounds4); + } + if (bounds5) { + accumulatedBounds.accumulateBounds(*bounds5); + } + + if (frustum.aabbFrustumTest(accumulatedBounds)) { + if (xaec_) { + g_Renderer->AddParticleGen(*xaec_); + } + + g_Renderer->AddParticleGen(*xa9c_); + g_Renderer->AddParticleGen(*xab0_); + g_Renderer->AddParticleGen(*xac4_); + g_Renderer->AddParticleGen(*xad8_); + } + } } -void CIceSheegoth::Render(CStateManager& mgr) { CPatterned::Render(mgr); } - zeus::CVector3f CIceSheegoth::GetAimPosition(const CStateManager& mgr, float dt) const { + if (GetBodyController()->GetLocomotionType() != pas::ELocomotionType::Crouch) { + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) { + zeus::CVector3f pos = zeus::skZero3f; + for (TUniqueId uid : xafc_gillColliders) { + if (const TCastToConstPtr colAct = mgr.GetObjectById(uid)) { + pos += colAct->GetTranslation(); + } + } + if (!pos.isZero()) { + return pos * (1.f / static_cast(xafc_gillColliders.size())); + } + } else if (!xb29_29_scanned && mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Scan) { + if (const TCastToConstPtr colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) { + return colAct->GetTranslation(); + } + } else if (const TCastToConstPtr colAct = mgr.GetObjectById(xaf8_mouthCollider)) { + return colAct->GetTranslation(); + } + } + return CPatterned::GetAimPosition(mgr, dt); } @@ -972,6 +1063,7 @@ void CIceSheegoth::AddCollisionList(const SJointInfo* info, size_t count, 1000.f)); } } + void CIceSheegoth::SetupCollisionActorManager(CStateManager& mgr) { std::vector joints; joints.reserve(7); @@ -994,6 +1086,7 @@ void CIceSheegoth::SetupCollisionActorManager(CStateManager& mgr) { } else if (desc.GetName() == "Jaw_end_LCTR"sv) { colAct->SetDamageVulnerability(CDamageVulnerability::PassThroughVulnerabilty()); } else if (desc.GetName() == "Ice_Shards_LCTR"sv) { + xaf6_iceShardsCollider = desc.GetCollisionActorId(); colAct->SetWeaponCollisionResponseType(EWeaponCollisionResponseTypes::None); } else if (desc.GetName() == "GillL_LCTR"sv || desc.GetName() == "GillR_LCTR"sv) { xafc_gillColliders.emplace_back(desc.GetCollisionActorId()); @@ -1030,6 +1123,7 @@ void CIceSheegoth::SetupHealthInfo(CStateManager& mgr) { } } } + void CIceSheegoth::sub_8019ebf0(CStateManager& mgr, float damage) { x974_ = zeus::clamp(0.f, x974_ + damage, x56c_sheegothData.Get_x170()); float fVar1 = (1.f / 3.f) * x56c_sheegothData.Get_x170(); @@ -1046,6 +1140,7 @@ void CIceSheegoth::ApplyWeaponDamage(CStateManager& mgr, TUniqueId sender) { CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f); } } + void CIceSheegoth::CreateFlameThrower(CStateManager& mgr) { if (xa80_flameThrowerId != kInvalidUniqueId) { return; @@ -1059,7 +1154,58 @@ void CIceSheegoth::CreateFlameThrower(CStateManager& mgr) { x56c_sheegothData.Get_x1e4(), x56c_sheegothData.Get_x1e8(), x56c_sheegothData.Get_x1ec())); } -void CIceSheegoth::AttractProjectiles(CStateManager& mgr) {} +void CIceSheegoth::AttractProjectiles(CStateManager& mgr) { + if (!IsAlive()) + return; + + rstl::reserved_vector nearProjectiles; + zeus::CAABox attractionBounds = + zeus::CAABox{GetTranslation() - x56c_sheegothData.Get_x14(), GetTranslation() + x56c_sheegothData.Get_x14()}; + mgr.BuildNearList(nearProjectiles, attractionBounds, CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}), + nullptr); + + if (nearProjectiles.empty()) + return; + + zeus::CVector3f attractionPos = GetEnergyAttractionPos(mgr); + rstl::reserved_vector nearCharacters; + mgr.BuildNearList(nearCharacters, attractionBounds, CMaterialFilter::MakeInclude({EMaterialTypes::Character}), + nullptr); + + for (TUniqueId projectileId : nearProjectiles) { + if (TCastToPtr proj = mgr.ObjectById(projectileId)) { + if (!ShouldAttractProjectile(*proj, mgr)) + continue; + + const zeus::CVector3f projPos = (attractionPos - proj->GetTranslation()) - proj->GetPreviousPos(); + if (!projPos.canBeNormalized() || !IsClosestSheegoth(mgr, nearCharacters, projPos)) + continue; + + const float mag = (attractionPos - proj->GetTranslation()).magnitude(); + const zeus::CVector3f b = + proj->GetTranslation() + (0.5f * mag) * (proj->GetTranslation() - proj->GetPreviousPos()).normalized(); + const zeus::CVector3f c = attractionPos + zeus::CVector3f{0.f, 0.f, 0.4f * (0.4f * mag)}; + const zeus::CVector3f point1 = zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos, 0.333f); + const zeus::CVector3f point2 = zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos, 0.666f); + const float t = (point2 - point1).magnitude() + (point1 - proj->GetTranslation()).magnitude() + + (attractionPos - point2).magnitude(); + const zeus::CVector3f point3 = + zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos, + t / (proj->GetTranslation() - proj->GetPreviousPos()).magnitude()); + zeus::CVector3f lookPos = point3 - proj->GetTranslation(); + if (!lookPos.canBeNormalized()) { + return; + } + + zeus::CTransform xf = zeus::lookAt(zeus::skZero3f, lookPos); + xf.orthonormalize(); + proj->ProjectileWeapon().SetWorldSpaceOrientation(xf); + zeus::CVector3f velocity = 0.8f * proj->GetProjectileWeapon().GetVelocity().normalized(); + proj->ProjectileWeapon().SetVelocity(proj->ProjectileWeapon().GetVelocity() * (0.3999f + (velocity * 0.6f))); + } + } +} + void CIceSheegoth::UpdateTimers(float dt) { if (x954_attackTimeLeft > 0.f) { x954_attackTimeLeft -= (xb29_27_ ? 2.f : 1.f) * dt; @@ -1077,7 +1223,13 @@ void CIceSheegoth::UpdateTimers(float dt) { x968_interestTimer += dt; } } -void CIceSheegoth::sub_8019e6f0(CStateManager& mgr) {} +void CIceSheegoth::UpdateScanState(CStateManager& mgr) { + if (!xb29_29_scanned && GetScannableObjectInfo() != nullptr && + zeus::close_enough(1.f, mgr.GetPlayerState()->GetScanTime(GetScannableObjectInfo()->GetScannableObjectId()))) { + xb29_29_scanned = true; + } +} + void CIceSheegoth::SetPassthroughVulnerability(CStateManager& mgr) { for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) { const auto& jInfo = xa2c_collisionManager->GetCollisionDescFromIndex(i); @@ -1086,6 +1238,7 @@ void CIceSheegoth::SetPassthroughVulnerability(CStateManager& mgr) { } } } + void CIceSheegoth::PreventWorldCollisions(float dt, CStateManager& mgr) { if (GetBodyController()->GetLocomotionType() == pas::ELocomotionType::Crouch || !IsOnGround() || mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { @@ -1177,7 +1330,66 @@ void CIceSheegoth::SetSteeringSpeed(float dt, CStateManager& mgr) { GetBodyController()->GetCommandMgr().SetSteeringSpeedRange(x948_, x948_); } -void CIceSheegoth::UpdateParticleEffects(float dt, CStateManager& mgr) {} +void CIceSheegoth::UpdateParticleEffects(float dt, CStateManager& mgr) { + if (auto* fl = static_cast(mgr.ObjectById(xa80_flameThrowerId))) { + if (fl->GetActive()) { + fl->SetTransform(GetLctrTransform("LCTR_SHEMOUTH"sv), dt); + } + } + + if (const TCastToConstPtr colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) { + const float time = 0.333f * x56c_sheegothData.Get_x170(); + if (x974_ >= 3.f * time) { + xa9c_->SetParticleEmission(false); + xab0_->SetParticleEmission(false); + xac4_->SetParticleEmission(true); + xad8_->SetParticleEmission(true); + } else if (x974_ >= 2.f * time) { + xa9c_->SetParticleEmission(false); + xab0_->SetParticleEmission(true); + xac4_->SetParticleEmission(false); + xad8_->SetParticleEmission(false); + } else { + xa9c_->SetParticleEmission(x974_ > 0.f); + xab0_->SetParticleEmission(false); + xac4_->SetParticleEmission(false); + xad8_->SetParticleEmission(false); + } + + const zeus::CTransform rotation = GetTransform().getRotation(); + const zeus::CVector3f pos = colAct->GetTranslation(); + xa9c_->SetOrientation(rotation); + xa9c_->SetGlobalTranslation(pos); + xab0_->SetOrientation(rotation); + xab0_->SetGlobalTranslation(pos); + xac4_->SetOrientation(rotation); + xac4_->SetGlobalTranslation(pos); + xad8_->SetOrientation(rotation); + xad8_->SetGlobalTranslation(pos); + if (xaec_) { + xaec_->SetParticleEmission(true); + xaec_->SetOrientation(rotation); + xaec_->SetGlobalTranslation(pos); + xaec_->SetGlobalScale(GetModelData()->GetScale()); + xaec_->Update(dt); + } + xa9c_->Update(dt); + xab0_->Update(dt); + xac4_->Update(dt); + xad8_->Update(dt); + if (x974_ < 2.f * time && xaf0_crackleSfx) { + CSfxManager::RemoveEmitter(xaf0_crackleSfx); + } else { + xaf0_crackleSfx = CSfxManager::AddEmitter(x56c_sheegothData.Get_x1d4(), GetTranslation(), zeus::skZero3f, false, + true, 127, kInvalidAreaId); + } + } else { + xa9c_->SetParticleEmission(false); + xab0_->SetParticleEmission(false); + xac4_->SetParticleEmission(false); + xad8_->SetParticleEmission(false); + } +} void CIceSheegoth::UpdateAttackPosition(CStateManager& mgr, zeus::CVector3f& attackPos) { attackPos = GetTranslation(); @@ -1222,29 +1434,32 @@ void CIceSheegoth::SetCollisionActorExtendedTouchBounds(CStateManager& mgr, cons } } } + void CIceSheegoth::ShakePlayer(CStateManager& mgr) { const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation(); const float magnitude = (0.5f - (0.01f * posDiff.magnitude())); if (magnitude > 0.f) { - bool applyImpulseToPlayer = true; if (mgr.GetPlayer().GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::Air && !mgr.GetPlayer().IsInWaterMovement()) { - if (mgr.GetCameraManager()->GetCurrentCameraId() == - mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()) { - mgr.GetCameraManager()->AddCameraShaker( - CCameraShakeData::BuildPatternedExplodeShakeData(GetTranslation(), 0.5f, magnitude, 50.f), true); + bool applyImpulseToPlayer = true; + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + if (mgr.GetCameraManager()->GetCurrentCameraId() == + mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()) { + mgr.GetCameraManager()->AddCameraShaker( + CCameraShakeData::BuildPatternedExplodeShakeData(GetTranslation(), 0.5f, magnitude, 50.f), true); + } + applyImpulseToPlayer = xb28_27_; } - applyImpulseToPlayer = xb28_27_; - } - if (applyImpulseToPlayer) { - const zeus::CVector3f direction = magnitude * ((xb28_27_ ? 40.f : 25.f) * zeus::skUp); - zeus::CVector3f impulse = zeus::skZero3f; - if (x978_ < posDiff.magnitude() && xb28_27_ && posDiff.toVec2f().canBeNormalized()) { - impulse = magnitude * (12.5f * posDiff.toVec2f().normalized()); + if (applyImpulseToPlayer) { + const zeus::CVector3f direction = magnitude * ((xb28_27_ ? 40.f : 25.f) * zeus::skUp); + zeus::CVector3f impulse = zeus::skZero3f; + if (x978_ < posDiff.magnitude() && xb28_27_ && posDiff.toVec2f().canBeNormalized()) { + impulse = magnitude * (12.5f * posDiff.toVec2f().normalized()); + } + mgr.GetPlayer().ApplyImpulseWR(mgr.GetPlayer().GetMass() * (direction + impulse), zeus::CAxisAngle{}); + mgr.GetPlayer().SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr); } - mgr.GetPlayer().ApplyImpulseWR(mgr.GetPlayer().GetMass() * (direction + impulse), zeus::CAxisAngle{}); - mgr.GetPlayer().SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr); } } @@ -1252,4 +1467,54 @@ void CIceSheegoth::ShakePlayer(CStateManager& mgr) { sub_8019ebf0(mgr, 0.25f * x56c_sheegothData.Get_x170()); } } +zeus::CVector3f CIceSheegoth::GetEnergyAttractionPos(CStateManager& mgr) const { + if (const TCastToConstPtr colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) { + return colAct->GetTranslation(); + } + + return GetTranslation(); +} +bool CIceSheegoth::ShouldAttractProjectile(const CGameProjectile& proj, CStateManager& mgr) const { + if (proj.GetType() != EWeaponType::Missile && proj.GetType() != EWeaponType::Plasma && + (!proj.GetDamageInfo().GetWeaponMode().IsComboed() || proj.GetType() != EWeaponType::Power)) { + const CActor* ent = static_cast(mgr.GetObjectById(proj.GetOwnerId())); + if (ent != nullptr) { + if (CPatterned::CastTo(ent) == nullptr && ent->GetAreaIdAlways() == GetAreaIdAlways()) { + zeus::CVector3f r = GetTransform().rotate(x56c_sheegothData.Get_x8()); + zeus::CVector3f posDiff = proj.GetTranslation() - ent->GetTranslation(); + if (proj.GetType() == EWeaponType::Wave && !proj.GetDamageInfo().GetWeaponMode().IsCharged() && + !proj.GetDamageInfo().GetWeaponMode().IsComboed() && posDiff.magSquared() < 100.f) { + return false; + } + + zeus::CVector3f xyPos = posDiff.toVec2f() - GetTranslation().toVec2f() + r.toVec2f(); + if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), xyPos) <= x56c_sheegothData.Get_x4()) { + if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), -xyPos) >= x56c_sheegothData.Get_x0()) { + return false; + } + } + return true; + } + } + } + + return false; +} +bool CIceSheegoth::IsClosestSheegoth(CStateManager& mgr, rstl::reserved_vector nearList, + zeus::CVector3f projectileOffset) const { + + zeus::CVector3f diff = projectileOffset - GetTranslation(); + const float diffMag = diff.magSquared(); + for (TUniqueId uid : nearList) { + const CIceSheegoth* goth = CPatterned::CastTo(mgr.GetObjectById(uid)); + if (!goth || goth->GetUniqueId() == GetUniqueId()) + continue; + + diff = projectileOffset - goth->GetTranslation(); + if (diff.magSquared() < diffMag) { + return false; + } + } + return true; +} } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CIceSheegoth.hpp b/Runtime/MP1/World/CIceSheegoth.hpp index fa7cc4216..c7bd0daa9 100644 --- a/Runtime/MP1/World/CIceSheegoth.hpp +++ b/Runtime/MP1/World/CIceSheegoth.hpp @@ -46,6 +46,10 @@ class CIceSheegothData { public: CIceSheegothData(CInputStream& in, s32 propertyCount); + [[nodiscard]] float Get_x0() const { return x0_; } + [[nodiscard]] float Get_x4() const { return x4_; } + [[nodiscard]] zeus::CVector3f Get_x8() const { return x8_; } + [[nodiscard]] float Get_x14() const { return x14_; } [[nodiscard]] CDamageVulnerability Get_x18() const { return x18_; } [[nodiscard]] CDamageVulnerability Get_x80() const { return x80_; } [[nodiscard]] CDamageVulnerability Get_xe8() const { return xe8_; } @@ -56,12 +60,14 @@ public: [[nodiscard]] CAssetId Get_x178() const { return x178_; } [[nodiscard]] CAssetId GetFireBreathResId() const { return x17c_fireBreathResId; } [[nodiscard]] CDamageInfo GetFireBreathDamage() const { return x180_fireBreathDamage; } + [[nodiscard]] CAssetId Get_x19c() const { return x19c_; } [[nodiscard]] CAssetId Get_x1a0() const { return x1a0_; } [[nodiscard]] CAssetId Get_x1a4() const { return x1a4_; } [[nodiscard]] CAssetId Get_x1a8() const { return x1a8_; } [[nodiscard]] CAssetId Get_x1ac() const { return x1ac_; } [[nodiscard]] float Get_x1b0() const { return x1b0_; } [[nodiscard]] CDamageInfo Get_x1b8() const { return x1b8_; } + [[nodiscard]] s16 Get_x1d4() const { return x1d4_; } [[nodiscard]] float Get_x1d8() const { return x1d8_; } [[nodiscard]] float Get_x1dc() const { return x1dc_; } [[nodiscard]] float GetMaxInterestTime() const { return x1e0_maxInterestTime; } @@ -119,9 +125,9 @@ class CIceSheegoth : public CPatterned { TCachedToken xadc_; // bool xae8_; std::unique_ptr xaec_; - CSfxHandle xaf0_; + CSfxHandle xaf0_crackleSfx; CSegId xaf4_mouthLocator; - TUniqueId xaf6_ = kInvalidUniqueId; + TUniqueId xaf6_iceShardsCollider = kInvalidUniqueId; TUniqueId xaf8_mouthCollider = kInvalidUniqueId; rstl::reserved_vector xafc_gillColliders; rstl::reserved_vector xb04_; @@ -139,7 +145,7 @@ class CIceSheegoth : public CPatterned { bool xb29_26_ : 1; bool xb29_27_ : 1; bool xb29_28_ : 1; - bool xb29_29_ : 1; + bool xb29_29_scanned : 1; void UpdateTouchBounds(); bool IsMouthCollider(TUniqueId uid) { return xaf8_mouthCollider == uid; } @@ -158,7 +164,7 @@ class CIceSheegoth : public CPatterned { void SetupHealthInfo(CStateManager& mgr); void AttractProjectiles(CStateManager& mgr); void UpdateTimers(float dt); - void sub_8019e6f0(CStateManager& mgr); + void UpdateScanState(CStateManager& mgr); void SetPassthroughVulnerability(CStateManager& mgr); void PreventWorldCollisions(float dt, CStateManager& mgr); void UpdateHealthInfo(CStateManager& mgr); @@ -178,6 +184,9 @@ class CIceSheegoth : public CPatterned { void SetCollisionActorExtendedTouchBounds(CStateManager& mgr, const zeus::CVector3f& extents); void UpdateAttackPosition(CStateManager& mgr, zeus::CVector3f& attackPos); + zeus::CVector3f GetEnergyAttractionPos(CStateManager& mgr) const; + bool ShouldAttractProjectile(const CGameProjectile& proj, CStateManager& mgr) const; + bool IsClosestSheegoth(CStateManager& mgr, const rstl::reserved_vector nearList, const zeus::CVector3f projectileOffset) const; public: DEFINE_PATTERNED(IceSheeegoth); @@ -189,7 +198,6 @@ public: void Think(float dt, CStateManager& mgr) override; void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) override; void AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) override; - void Render(CStateManager& mgr) override; [[nodiscard]] const CDamageVulnerability* GetDamageVulnerability() const override { return &CDamageVulnerability::PassThroughVulnerabilty(); }