From 7b9fecfdc63935198c85ac88354f645858d7fe9b Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 24 Apr 2020 07:36:49 -0700 Subject: [PATCH] CIceSheegoth: Final state implementations --- Runtime/Character/CBodyStateCmdMgr.hpp | 13 +- Runtime/Character/CharacterCommon.hpp | 2 +- Runtime/MP1/World/CIceSheegoth.cpp | 502 +++++++++++++++++++++++-- Runtime/MP1/World/CIceSheegoth.hpp | 26 +- 4 files changed, 499 insertions(+), 44 deletions(-) diff --git a/Runtime/Character/CBodyStateCmdMgr.hpp b/Runtime/Character/CBodyStateCmdMgr.hpp index e8d7e5332..5d6718a43 100644 --- a/Runtime/Character/CBodyStateCmdMgr.hpp +++ b/Runtime/Character/CBodyStateCmdMgr.hpp @@ -88,8 +88,7 @@ class CBCGenerateCmd : public CBodyStateCmd { public: explicit CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) {} - explicit CBCGenerateCmd(pas::EGenerateType type) - : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) {} + explicit CBCGenerateCmd(pas::EGenerateType type) : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) {} explicit CBCGenerateCmd(pas::EGenerateType type, s32 animId) : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId), x1c_25_overrideAnim{animId != -1} {} explicit CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec, bool targetTransform = false, @@ -159,7 +158,8 @@ class CBCLoopHitReactionCmd : public CBodyStateCmd { public: explicit CBCLoopHitReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopHitReaction) {} - explicit CBCLoopHitReactionCmd(pas::EReactionType type) : CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {} + explicit CBCLoopHitReactionCmd(pas::EReactionType type) + : CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {} pas::EReactionType GetReactionType() const { return x8_type; } }; @@ -256,13 +256,14 @@ public: class CBCLoopAttackCmd : public CBodyStateCmd { pas::ELoopAttackType x8_type = pas::ELoopAttackType::Invalid; - u32 xc_waitForAnimOver = 0; + bool xc_waitForAnimOver = false; public: explicit CBCLoopAttackCmd() : CBodyStateCmd(EBodyStateCmd::LoopAttack) {} - explicit CBCLoopAttackCmd(pas::ELoopAttackType type) : CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type) {} + explicit CBCLoopAttackCmd(pas::ELoopAttackType type, bool waitForAnimOver = false) + : CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type), xc_waitForAnimOver(waitForAnimOver) {} pas::ELoopAttackType GetAttackType() const { return x8_type; } - bool WaitForAnimOver() const { return xc_waitForAnimOver == 1; } + bool WaitForAnimOver() const { return xc_waitForAnimOver; } }; class CBCTauntCmd : public CBodyStateCmd { diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index a577ef498..fa5e76b6a 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -94,7 +94,7 @@ enum class EGetupType { Invalid = -1, Zero = 0, One = 1, Two = 2 }; enum class ELoopState { Invalid = -1, Begin, Loop, End }; -enum class ELoopAttackType { Invalid = -1 }; +enum class ELoopAttackType { Invalid = -1, Zero }; enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four, Five, Six, Seven, Eight }; diff --git a/Runtime/MP1/World/CIceSheegoth.cpp b/Runtime/MP1/World/CIceSheegoth.cpp index 20b565bb7..255d76c1a 100644 --- a/Runtime/MP1/World/CIceSheegoth.cpp +++ b/Runtime/MP1/World/CIceSheegoth.cpp @@ -55,7 +55,7 @@ CIceSheegothData::CIceSheegothData(CInputStream& in, [[maybe_unused]] s32 proper , x174_(in.readFloatBig()) , x178_(in) , x17c_fireBreathResId(in) -, x180_(in) +, x180_fireBreathDamage(in) , x19c_(in) , x1a0_(in) , x1a4_(in) @@ -67,7 +67,7 @@ CIceSheegothData::CIceSheegothData(CInputStream& in, [[maybe_unused]] s32 proper , x1d4_(CSfxManager::TranslateSFXID(in.readUint32Big())) , x1d8_(in.readFloatBig()) , x1dc_(in.readFloatBig()) -, x1e0_(in.readFloatBig()) +, x1e0_maxInterestTime(in.readFloatBig()) , x1e4_(in) , x1e8_(CSfxManager::TranslateSFXID(in.readUint32Big())) , x1ec_(in) @@ -147,7 +147,7 @@ void CIceSheegoth::Think(float dt, CStateManager& mgr) { if (!IsAlive()) { x974_ = std::max(0.f, x974_ - (dt * x56c_sheegothData.Get_x170())); if (GetBodyController()->GetBodyStateInfo().GetCurrentState()->IsDying()) { - sub_8019eb50(mgr); + SetPassthroughVulnerability(mgr); } } x96c_ -= dt; @@ -162,7 +162,7 @@ void CIceSheegoth::Think(float dt, CStateManager& mgr) { *GetBodyController()); xa2c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); PreventWorldCollisions(dt, mgr); - sub_8019f680(mgr); + UpdateHealthInfo(mgr); sub_8019f5cc(dt, mgr); UpdateParticleEffects(dt, mgr); UpdateThermalFrozenState(x428_damageCooldownTimer > 0.f); @@ -223,8 +223,6 @@ void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, C case EScriptObjectMessage::InitializedInArea: { x760_pathSearch.SetArea(mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); x844_approachSearch.SetArea(mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); - // TODO: Remove this - mgr.SetBossParams(GetUniqueId(), GetHealthInfo(mgr)->GetHP(), 0); break; } case EScriptObjectMessage::Damage: { @@ -297,8 +295,66 @@ EWeaponCollisionResponseTypes CIceSheegoth::GetCollisionResponseType(const zeus: : CPatterned::GetCollisionResponseType(v1, v2, mode, attrib); } -zeus::CAABox CIceSheegoth::GetSortingBounds(const CStateManager& mgr) const { return CActor::GetSortingBounds(mgr); } +zeus::CAABox CIceSheegoth::GetSortingBounds(const CStateManager& mgr) const { + const zeus::CAABox box = CActor::GetSortingBounds(mgr); + const zeus::CVector3f offset = 0.125f * (box.max - box.min); + const zeus::CVector3f center = box.center(); + return {center - offset, center + offset}; +} + void CIceSheegoth::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + switch (type) { + case EUserEventType::Projectile: { + zeus::CTransform gunPos = GetLctrTransform(node.GetLocatorName()); + zeus::CVector3f interceptPos = GetProjectileInfo()->PredictInterceptPos( + gunPos.origin, mgr.GetPlayer().GetAimPosition(mgr, 0.f), mgr.GetPlayer(), true, dt); + zeus::CVector3f predictOffset = interceptPos - gunPos.origin; + zeus::CVector3f lookPos; + if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), predictOffset) > zeus::degToRad(60.f)) { + if (!predictOffset.canBeNormalized()) { + lookPos = gunPos.origin + predictOffset.magnitude() * gunPos.frontVector(); + } else { + lookPos = gunPos.origin + (predictOffset.magnitude() * + zeus::CVector3f::slerp(GetTransform().frontVector(), predictOffset.normalized(), + zeus::CRelAngle::FromDegrees(60.f))); + } + } + + LaunchProjectile(zeus::lookAt(gunPos.origin, lookPos), mgr, 4, EProjectileAttrib::None, false, std::nullopt, -1, + false, zeus::skOne3f); + x974_ = std::max(0.f, x974_ - 0.3333f * x56c_sheegothData.Get_x170()); + if (xb28_27_ && !ShouldSpecialAttack(mgr, 0.f)) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd{EBodyStateCmd::ExitState}); + } + return; + } + case EUserEventType::DamageOn: + if (!xb28_26_) { + break; + } + + if (CFlameThrower* fl = static_cast(mgr.ObjectById(xa80_flameThrowerId))) { + fl->Fire(GetTransform(), mgr, false); + } + break; + case EUserEventType::DamageOff: + if (!xb28_26_) { + break; + } + + if (CFlameThrower* fl = static_cast(mgr.ObjectById(xa80_flameThrowerId))) { + fl->Reset(mgr, false); + } + break; + case EUserEventType::ScreenShake: + sub_801a0708(mgr); + return; + case EUserEventType::BecomeShootThrough: + SetPassthroughVulnerability(mgr); + return; + default: + break; + } CPatterned::DoUserAnimEvent(mgr, node, type, dt); } @@ -340,7 +396,51 @@ void CIceSheegoth::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { x3b4_speed = x94c_; } } -void CIceSheegoth::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CIceSheegoth::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed); + + if (HasPatrolPath(mgr, 0.f)) { + Patrol(mgr, msg, dt); + UpdateDest(mgr); + } else { + SetDestPos(x3a0_latestLeashPosition); + } + + const zeus::CVector3f arrivalPos = x45c_steeringBehaviors.Arrival(*this, x92c_lastDest, 15.f); + x92c_lastDest = x2e0_destPos; + + if (GetSearchPath() != nullptr) { + SetPathFindMode(EPathFindMode::Normal); + CPatterned::PathFind(mgr, msg, dt); + const zeus::CVector3f moveVec = GetBodyController()->GetCommandMgr().GetMoveVector(); + if (moveVec.canBeNormalized()) { + GetBodyController()->GetCommandMgr().ClearLocomotionCmds(); + GetBodyController()->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd{arrivalPos.magnitude() * moveVec.normalized(), zeus::skZero3f, 1.f}); + } else { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{arrivalPos, zeus::skZero3f, 1.f}); + } + } + } else if (msg == EStateMsg::Update) { + const zeus::CVector3f arrivalPos = x45c_steeringBehaviors.Arrival(*this, x92c_lastDest, 15.f); + + if (GetSearchPath() && PathShagged(mgr, dt)) { + SetPathFindMode(EPathFindMode::Normal); + CPatterned::PathFind(mgr, EStateMsg::Update, dt); + const zeus::CVector3f moveVec = GetBodyController()->GetCommandMgr().GetMoveVector(); + if (moveVec.canBeNormalized()) { + GetBodyController()->GetCommandMgr().ClearLocomotionCmds(); + GetBodyController()->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd{arrivalPos.magnitude() * moveVec.normalized(), zeus::skZero3f, 1.f}); + } else { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{arrivalPos, zeus::skZero3f, 1.f}); + } + } + } +} + void CIceSheegoth::Generate(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { x568_ = 0; @@ -361,9 +461,113 @@ void CIceSheegoth::Generate(CStateManager& mgr, EStateMsg msg, float dt) { } } } -void CIceSheegoth::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::Attack(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CIceSheegoth::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 1; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { + x568_ = 3; + } else { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCGenerateCmd{pas::EGenerateType::One}); + } + } else if (x568_ == 1) { + if ((x3a0_latestLeashPosition - GetTranslation()).magSquared() > 1.f) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{ + x45c_steeringBehaviors.Arrival(*this, x3a0_latestLeashPosition, 15.f), zeus::skZero3f, 1.f}); + } else { + x568_ = 2; + } + } else if (x568_ == 2) { + const float angleDiff = zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), x938_); + if (angleDiff <= zeus::degToRad(5.f)) { + x568_ = 0; + } else { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::skZero3f, x938_, 1.f}); + } + } else if (x568_ == 3) { + x568_ = 4; + } + } +} +void CIceSheegoth::Attack(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xb28_29_ = true; + xb28_25_ = true; + x2e0_destPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + SetPathFindMode(EPathFindMode::Normal); + PathFind(mgr, msg, dt); + SetCollisionActorExtendedTouchBounds(mgr, zeus::CVector3f{2.f}); + x95c_ = 0.f; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + x95c_ += dt; + if (x95c_ >= x56c_sheegothData.Get_x1d8()) { + x568_ = 4; + } else if (!xb28_29_) { + x568_ = 3; + xb28_29_ = true; + const bool isPlayerMorphed = + mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed; + GetBodyController()->GetCommandMgr().DeliverCmd( + CBCMeleeAttackCmd{isPlayerMorphed ? pas::ESeverity::Two : pas::ESeverity::One}); + } else if (xb28_29_) { + const zeus::CTransform mouthXf = GetLctrTransform(xaf4_mouthLocator); + if (GetTransform().frontVector().dot(mgr.GetPlayer().GetTranslation() - mouthXf.origin) > 0.f) { + SetPathFindMode(EPathFindMode::Normal); + if (GetSearchPath() != nullptr && !PathShagged(mgr, 0.f)) { + PathFind(mgr, EStateMsg::Update, dt); + } else { + x568_ = 4; + } + } else { + x568_ = 4; + } + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) { + x568_ = 4; + } + } else if (msg == EStateMsg::Deactivate) { + if (!sub_801a1794(mgr)) { + x954_attackTimeLeft = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; + } + + SetCollisionActorExtendedTouchBounds(mgr, zeus::skZero3f); + xb28_29_ = false; + xb28_25_ = false; + x960_ = x56c_sheegothData.Get_x1dc(); + x95c_ = 0.f; + } +} + +void CIceSheegoth::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xb28_29_ = true; + xb28_28_ = true; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) { + x568_ = 3; + } else if (IsOnGround()) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd{pas::ESeverity::Zero}); + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) { + x568_ = 4; + } + } else if (msg == EStateMsg::Deactivate) { + if (!sub_801a1794(mgr) || !TooClose(mgr, dt)) { + x958_ = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; + } + xb28_29_ = false; + xb28_28_ = false; + } +} + void CIceSheegoth::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { x9f4_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); @@ -406,7 +610,7 @@ void CIceSheegoth::Taunt(CStateManager& mgr, EStateMsg msg, float dt) { if (msg == EStateMsg::Activate) { x568_ = 0; xb29_25_ = true; - sub_8019e894(mgr, true); + SetMouthVulnerability(mgr, true); } else if (msg == EStateMsg::Update) { if (x568_ == 0) { if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Taunt) { @@ -419,15 +623,161 @@ void CIceSheegoth::Taunt(CStateManager& mgr, EStateMsg msg, float dt) { x568_ = 4; } } else if (msg == EStateMsg::Deactivate) { - sub_8019e894(mgr, false); + SetMouthVulnerability(mgr, false); xb29_25_ = false; } } -void CIceSheegoth::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::Flinch(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::Approach(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::Enraged(CStateManager& mgr, EStateMsg msg, float dt) {} -void CIceSheegoth::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CIceSheegoth::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xb28_26_ = true; + xb29_25_ = true; + xb29_27_ = false; + x968_interestTimer = 0.f; + SetGillVulnerability(mgr, true); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { + GetBodyController()->GetCommandMgr().DeliverCmd( + CBCProjectileAttackCmd{pas::ESeverity::Two, mgr.GetPlayer().GetTranslation(), false}); + } else { + x568_ = 3; + x3b4_speed = 2.f * x94c_; + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { + x568_ = 4; + } + } else if (msg == EStateMsg::Deactivate) { + x3b4_speed = x94c_; + if (!sub_801a1794(mgr)) { + x954_attackTimeLeft = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; + } + + if (CFlameThrower* fl = static_cast(mgr.ObjectById(xa80_flameThrowerId))) { + fl->Reset(mgr, false); + } + SetGillVulnerability(mgr, false); + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd{EBodyStateCmd::NextState}); + } + xb29_25_ = false; + xb28_26_ = false; + } +} +void CIceSheegoth::Flinch(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xb29_25_ = true; + SetGillVulnerability(mgr, true); + SetMouthVulnerability(mgr, true); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd{x980_, pas::ESeverity::One}); + } else { + x568_ = 4; + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) { + x568_ = 4; + } + } else if (msg == EStateMsg::Deactivate) { + SetGillVulnerability(mgr, true); + SetMouthVulnerability(mgr, true); + xb29_25_ = false; + } +} + +void CIceSheegoth::Approach(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed); + x9f4_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + UpdateAttackPosition(mgr, x2e0_destPos); + SetPathFindMode(EPathFindMode::Normal); + if (!xb29_27_) { + GetBodyController()->GetCommandMgr().ClearLocomotionCmds(); + } + xb29_24_ = !xb29_24_; + xb29_28_ = true; + x92c_lastDest = mgr.GetPlayer().GetTranslation(); + } else if (msg == EStateMsg::Update) { + SetPathFindMode(EPathFindMode::Approach); + if (xb29_24_) { + x2e0_destPos = x92c_lastDest; + if (x844_approachSearch.FindClosestReachablePoint(GetTranslation(), x2e0_destPos) == + CPathFindSearch::EResult::Success) { + if ((GetTranslation() - x2e0_destPos).magSquared() < 81.f) { + x2e0_destPos = GetTranslation(); + } + x92c_lastDest = x2e0_destPos; + PathFind(mgr, EStateMsg::Activate, dt); + if (!xb29_27_) { + GetBodyController()->GetCommandMgr().ClearLocomotionCmds(); + } + } + xb29_24_ = false; + } + + if (x56c_sheegothData.Get_x1f0_24() && GetSearchPath() != nullptr && !PathShagged(mgr, 0.f) && + x760_pathSearch.GetCurrentWaypoint() < x760_pathSearch.GetWaypoints().size() - 1) { + PathFind(mgr, EStateMsg::Update, dt); + } else { + const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation(); + if (sub_8019ecdc(mgr, zeus::degToRad(15.f)) && posDiff.canBeNormalized()) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::skZero3f, posDiff.normalized(), 1.f}); + } + } + + xb29_27_ = true; + x3b4_speed = + (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn ? 2.f : 1.f) * x94c_; + } else if (msg == EStateMsg::Deactivate) { + x9f4_boneTracking.SetActive(false); + SetPathFindMode(EPathFindMode::Normal); + x3b4_speed = x94c_; + } +} +void CIceSheegoth::Enraged(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + xb28_30_ = true; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Three)); + } else { + x568_ = 3; + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) { + x568_ = 4; + } + } +} + +void CIceSheegoth::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + x968_interestTimer = 0.f; + xb28_27_ = true; + xb29_27_ = false; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::LoopAttack) { + GetBodyController()->GetCommandMgr().DeliverCmd(CBCLoopAttackCmd{pas::ELoopAttackType::Zero, true}); + } else { + x568_ = 4; + x3b4_speed = 2.f * x94c_; + } + } else if (x568_ == 3 && + GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::LoopAttack) { + x568_ = 4; + } + } +} + bool CIceSheegoth::Leash(CStateManager& mgr, float arg) { const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation(); if ((x3a0_latestLeashPosition - posDiff).magSquared() <= x3c8_leashRadius * x3c8_leashRadius) { @@ -482,16 +832,48 @@ bool CIceSheegoth::SpotPlayer(CStateManager& mgr, float arg) { } return true; } + bool CIceSheegoth::AnimOver(CStateManager& mgr, float arg) { return x568_ == 4; } -bool CIceSheegoth::ShouldAttack(CStateManager& mgr, float arg) { return CAi::ShouldAttack(mgr, arg); } -bool CIceSheegoth::ShouldDoubleSnap(CStateManager& mgr, float arg) { return CAi::ShouldDoubleSnap(mgr, arg); } -bool CIceSheegoth::InPosition(CStateManager& mgr, float arg) { return CPatterned::InPosition(mgr, arg); } -bool CIceSheegoth::ShouldTurn(CStateManager& mgr, float arg) { return CAi::ShouldTurn(mgr, arg); } +bool CIceSheegoth::ShouldAttack(CStateManager& mgr, float arg) { + if (GetAreaIdAlways() == mgr.GetPlayer().GetAreaId() && x954_attackTimeLeft <= 0.f && + x974_ >= 0.3333f * x56c_sheegothData.Get_x170() && sub_8019ecbc()) { + const zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + const zeus::CTransform lctrXf = GetLctrTransform(xaf4_mouthLocator); + if ((aimPos - lctrXf.origin).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange && + !ShouldTurn(mgr, zeus::degToRad(15.f))) { + return !IsPatternObstructed(mgr, lctrXf.origin, aimPos); + } + } + + return false; +} + +bool CIceSheegoth::ShouldDoubleSnap(CStateManager& mgr, float arg) { + if (GetAreaIdAlways() != mgr.GetPlayer().GetAreaIdAlways() || x958_ > 0.f) { + return false; + } + SetPathFindMode(EPathFindMode::Approach); + return (!PathShagged(mgr, 0.f) && x760_pathSearch.GetCurrentWaypoint() < x760_pathSearch.GetWaypoints().size() - 1) || + (x92c_lastDest - GetTranslation()).magSquared() < 81.f; +} + +bool CIceSheegoth::InPosition(CStateManager& mgr, float arg) { + return (x92c_lastDest - GetTranslation()).magSquared() < 81.f; +} + +bool CIceSheegoth::ShouldTurn(CStateManager& mgr, float arg) { + if (arg == 0.f) { + arg = zeus::degToRad(45.f); + } + return zeus::CVector2f::getAngleDiff(GetTransform().frontVector().toVec2f(), + mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f()) > arg; +} bool CIceSheegoth::AggressionCheck(CStateManager& mgr, float arg) { return !(!IsAlive() || xb28_30_ || !sub_801a1794(mgr)); } + bool CIceSheegoth::ShouldFire(CStateManager& mgr, float arg) { if (GetAreaIdAlways() != mgr.GetPlayer().GetAreaIdAlways()) { return false; @@ -505,24 +887,29 @@ bool CIceSheegoth::ShouldFire(CStateManager& mgr, float arg) { } return false; } + bool CIceSheegoth::ShouldFlinch(CStateManager& mgr, float arg) { return xb29_25_ && x97c_ > 0.f; } + bool CIceSheegoth::ShotAt(CStateManager& mgr, float arg) { return x400_24_hitByPlayerProjectile; } + bool CIceSheegoth::ShouldSpecialAttack(CStateManager& mgr, float arg) { if (GetAreaIdAlways() == mgr.GetPlayer().GetAreaId() && x954_attackTimeLeft <= 0.f && x974_ >= 0.3333f * x56c_sheegothData.Get_x170() && sub_8019ecbc()) { const zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); const zeus::CTransform lctrXf = GetLctrTransform(xaf4_mouthLocator); if ((aimPos - lctrXf.origin).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange && - !ShouldTurn(mgr, 0.2617994f)) { + !ShouldTurn(mgr, zeus::degToRad(15.f))) { return !IsPatternObstructed(mgr, lctrXf.origin, aimPos); } } return false; } + bool CIceSheegoth::LostInterest(CStateManager& mgr, float arg) { return x968_interestTimer >= x56c_sheegothData.GetMaxInterestTime(); } + void CIceSheegoth::UpdateTouchBounds() { x978_ = 1.75f * GetModelData()->GetScale().y(); zeus::CAABox box{-x978_, -x978_, 0.f, x978_, x978_, 2.f * x978_}; @@ -535,6 +922,7 @@ void CIceSheegoth::UpdateTouchBounds() { x844_approachSearch.SetCharacterHeight(x978_); x844_approachSearch.SetPadding(20.f); } + void CIceSheegoth::ApplyContactDamage(TUniqueId sender, CStateManager& mgr) { if (const TCastToConstPtr colAct = mgr.GetObjectById(sender)) { if (colAct->GetHealthInfo(mgr)->GetHP() <= 0.f) { @@ -553,6 +941,7 @@ void CIceSheegoth::ApplyContactDamage(TUniqueId sender, CStateManager& mgr) { } } } + void CIceSheegoth::AddSphereCollisionList(const SSphereJointInfo* info, size_t count, std::vector& vecOut) { for (size_t i = 0; i < count; ++i) { @@ -621,6 +1010,7 @@ void CIceSheegoth::SetupCollisionActorManager(CStateManager& mgr) { } void CIceSheegoth::SetupHealthInfo(CStateManager& mgr) { CHealthInfo* thisHealth = HealthInfo(mgr); + x970_maxHp = thisHealth->GetHP(); for (auto& id : xafc_) { if (TCastToPtr colAct = mgr.ObjectById(id)) { *colAct->HealthInfo(mgr) = *thisHealth; @@ -669,7 +1059,7 @@ void CIceSheegoth::CreateFlameThrower(CStateManager& mgr) { void CIceSheegoth::AttractProjectiles(CStateManager& mgr) {} void CIceSheegoth::sub_801a0b8c(float dt) {} void CIceSheegoth::sub_8019e6f0(CStateManager& mgr) {} -void CIceSheegoth::sub_8019eb50(CStateManager& mgr) { +void CIceSheegoth::SetPassthroughVulnerability(CStateManager& mgr) { for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) { const auto& jInfo = xa2c_collisionManager->GetCollisionDescFromIndex(i); if (TCastToPtr colAct = mgr.ObjectById(jInfo.GetCollisionActorId())) { @@ -714,7 +1104,47 @@ void CIceSheegoth::PreventWorldCollisions(float dt, CStateManager& mgr) { ApplyImpulseOR(GetMoveToORImpulseWR(direction, dt), zeus::CAxisAngle{}); } -void CIceSheegoth::sub_8019f680(CStateManager& mgr) {} +void CIceSheegoth::UpdateHealthInfo(CStateManager& mgr) { + if (!IsAlive()) { + return; + } + + float hpDelta = 0.f; + if (TCastToPtr colAct = mgr.ObjectById(xaf8_mouthCollider)) { + hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP()); + } + + for (TUniqueId uid : xafc_) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP()); + } + } + + for (TUniqueId uid : xb04_) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP()); + } + } + HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - hpDelta); + if (GetHealthInfo(mgr)->GetHP() > 0.f) { + if (TCastToPtr colAct = mgr.ObjectById(xaf8_mouthCollider)) { + colAct->HealthInfo(mgr)->SetHP(x970_maxHp); + } + for (TUniqueId uid : xafc_) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + colAct->HealthInfo(mgr)->SetHP(x970_maxHp); + } + } + + for (TUniqueId uid : xb04_) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + colAct->HealthInfo(mgr)->SetHP(x970_maxHp); + } + } + } else { + Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle); + } +} void CIceSheegoth::sub_8019f5cc(float dt, CStateManager& mgr) {} void CIceSheegoth::UpdateParticleEffects(float dt, CStateManager& mgr) {} void CIceSheegoth::UpdateAttackPosition(CStateManager& mgr, zeus::CVector3f& attackPos) { @@ -737,9 +1167,27 @@ bool CIceSheegoth::sub_8019ecdc(CStateManager& mgr, float minAngle) { return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), plAimPos.toVec2f() - GetTranslation().toVec2f()) > minAngle; } -void CIceSheegoth::sub_8019e894(CStateManager& mgr, bool b1) { +void CIceSheegoth::SetMouthVulnerability(CStateManager& mgr, bool isVulnerable) { if (TCastToPtr colAct = mgr.ObjectById(xaf8_mouthCollider)) { - colAct->SetDamageVulnerability(b1 ? x56c_sheegothData.Get_xe8() : x98c_mouthVulnerability); + colAct->SetDamageVulnerability(isVulnerable ? x56c_sheegothData.Get_xe8() : x98c_mouthVulnerability); } } +void CIceSheegoth::SetGillVulnerability(CStateManager& mgr, bool isVulnerable) { + for (TUniqueId uid : xafc_) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + colAct->SetDamageVulnerability(isVulnerable ? x56c_sheegothData.Get_x18() + : CDamageVulnerability::ImmuneVulnerabilty()); + } + } +} + +void CIceSheegoth::SetCollisionActorExtendedTouchBounds(CStateManager& mgr, const zeus::CVector3f& extents) { + for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) { + if (TCastToPtr colAct = + mgr.ObjectById(xa2c_collisionManager->GetCollisionDescFromIndex(i).GetCollisionActorId())) { + colAct->SetExtendedTouchBounds(extents); + } + } +} +void CIceSheegoth::sub_801a0708(CStateManager& mgr) {} } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CIceSheegoth.hpp b/Runtime/MP1/World/CIceSheegoth.hpp index 8e3059cb7..fd0d22bcc 100644 --- a/Runtime/MP1/World/CIceSheegoth.hpp +++ b/Runtime/MP1/World/CIceSheegoth.hpp @@ -25,7 +25,7 @@ class CIceSheegothData { float x174_; CAssetId x178_; CAssetId x17c_fireBreathResId; - CDamageInfo x180_; + CDamageInfo x180_fireBreathDamage; CAssetId x19c_; CAssetId x1a0_; CAssetId x1a4_; @@ -37,7 +37,7 @@ class CIceSheegothData { s16 x1d4_; float x1d8_; float x1dc_; - float x1e0_; + float x1e0_maxInterestTime; CAssetId x1e4_; s16 x1e8_; CAssetId x1ec_; @@ -46,6 +46,7 @@ class CIceSheegothData { public: CIceSheegothData(CInputStream& in, s32 propertyCount); + [[nodiscard]] CDamageVulnerability Get_x18() const { return x18_; } [[nodiscard]] CDamageVulnerability Get_x80() const { return x80_; } [[nodiscard]] CDamageVulnerability Get_xe8() const { return xe8_; } [[nodiscard]] CAssetId Get_x150() const { return x150_; } @@ -54,14 +55,16 @@ public: [[nodiscard]] float Get_x174() const { return x174_; } [[nodiscard]] CAssetId Get_x178() const { return x178_; } [[nodiscard]] CAssetId GetFireBreathResId() const { return x17c_fireBreathResId; } - [[nodiscard]] CDamageInfo GetFireBreathDamage() const { return x180_; } + [[nodiscard]] CDamageInfo GetFireBreathDamage() const { return x180_fireBreathDamage; } [[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]] float GetMaxInterestTime() const { return x1e0_; } + [[nodiscard]] float Get_x1d8() const { return x1d8_; } + [[nodiscard]] float Get_x1dc() const { return x1dc_; } + [[nodiscard]] float GetMaxInterestTime() const { return x1e0_maxInterestTime; } [[nodiscard]] CAssetId Get_x1e4() const { return x1e4_; } [[nodiscard]] s16 Get_x1e8() const { return x1e8_; } [[nodiscard]] CAssetId Get_x1ec() const { return x1ec_; } @@ -76,7 +79,7 @@ class CIceSheegoth : public CPatterned { CPathFindSearch x760_pathSearch; CPathFindSearch x844_approachSearch; EPathFindMode x928_pathFindMode = EPathFindMode::Normal; - zeus::CVector3f x92c_ = zeus::skZero3f; + zeus::CVector3f x92c_lastDest = zeus::skZero3f; zeus::CVector3f x938_ = zeus::skZero3f; float x944_ = 1.f; float x948_ = 1.f; @@ -89,7 +92,7 @@ class CIceSheegoth : public CPatterned { /* x964_ */ float x968_interestTimer = 0.f; float x96c_ = 2.f; - float x970_ = 0.f; + float x970_maxHp = 0.f; float x974_; float x978_ = 0.f; float x97c_ = 0.f; @@ -156,20 +159,23 @@ class CIceSheegoth : public CPatterned { void AttractProjectiles(CStateManager& mgr); void sub_801a0b8c(float dt); void sub_8019e6f0(CStateManager& mgr); - void sub_8019eb50(CStateManager& mgr); + void SetPassthroughVulnerability(CStateManager& mgr); void PreventWorldCollisions(float dt, CStateManager& mgr); - void sub_8019f680(CStateManager& mgr); + void UpdateHealthInfo(CStateManager& mgr); void sub_8019f5cc(float dt, CStateManager& mgr); void SetPathFindMode(EPathFindMode mode) { x928_pathFindMode = mode; } void UpdateParticleEffects(float dt, CStateManager& mgr); bool sub_801a1794(CStateManager& mgr) const { const CHealthInfo* hInfo = GetHealthInfo(mgr); - return hInfo != nullptr && hInfo->GetHP() < 0.3f * x970_; + return hInfo != nullptr && hInfo->GetHP() < 0.3f * x970_maxHp; } bool sub_8019ecbc() const { return xb28_27_ || xb29_26_; } bool sub_8019ecdc(CStateManager& mgr, float minAngle); - void sub_8019e894(CStateManager& mgr, bool b1); + void SetMouthVulnerability(CStateManager& mgr, bool isVulnerable); + void SetGillVulnerability(CStateManager& mgr, bool isVulnerable); + void sub_801a0708(CStateManager& mgr); + void SetCollisionActorExtendedTouchBounds(CStateManager& mgr, const zeus::CVector3f& extents); void UpdateAttackPosition(CStateManager& mgr, zeus::CVector3f& attackPos);