From 328749d1bad44f667ddf85a5b661681f5ca5b359 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 16 Jul 2019 08:54:07 -0700 Subject: [PATCH] More CFlaahgra imps, initial CTryclops imps --- Runtime/Character/CAnimData.cpp | 47 ++- Runtime/Character/CInt32POINode.cpp | 7 +- Runtime/Character/CInt32POINode.hpp | 1 + Runtime/Character/CharacterCommon.hpp | 16 +- Runtime/MP1/World/CBabygoth.hpp | 2 +- Runtime/MP1/World/CBeetle.cpp | 2 +- Runtime/MP1/World/CFlaahgra.cpp | 163 ++++++--- Runtime/MP1/World/CFlaahgra.hpp | 3 +- Runtime/MP1/World/CParasite.cpp | 8 +- Runtime/MP1/World/CPuddleToadGamma.cpp | 2 +- Runtime/MP1/World/CTryclops.cpp | 440 ++++++++++++++++++++++++- Runtime/MP1/World/CTryclops.hpp | 76 +++++ Runtime/Weapon/CBomb.cpp | 6 +- Runtime/Weapon/CBomb.hpp | 7 +- Runtime/Weapon/CEnergyProjectile.cpp | 10 +- Runtime/World/CDamageVulnerability.cpp | 57 +++- Runtime/World/CDamageVulnerability.hpp | 18 +- Runtime/World/CPatterned.hpp | 2 +- Runtime/World/CPhysicsActor.cpp | 2 +- Runtime/World/CPhysicsActor.hpp | 1 + Runtime/World/CScriptActor.cpp | 4 +- Runtime/World/CScriptDebris.cpp | 2 +- Runtime/World/CWallCrawlerSwarm.cpp | 9 +- 23 files changed, 765 insertions(+), 120 deletions(-) diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index 94a3f1ca3..14698a6e2 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -188,25 +188,22 @@ bool CAnimData::IsAdditiveAnimation(s32 idx) const { bool CAnimData::IsAdditiveAnimationAdded(s32 idx) const { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); + auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); return search != x434_additiveAnims.cend(); } const std::shared_ptr& CAnimData::GetAdditiveAnimationTree(s32 idx) const { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); + auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); return search->second.GetAnim(); } bool CAnimData::IsAdditiveAnimationActive(s32 idx) const { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); + auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); if (search == x434_additiveAnims.cend()) return false; return search->second.IsActive(); @@ -214,11 +211,9 @@ bool CAnimData::IsAdditiveAnimationActive(s32 idx) const { void CAnimData::DelAdditiveAnimation(s32 idx) { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); - if (search != x434_additiveAnims.cend() && - search->second.GetPhase() != EAdditivePlaybackPhase::FadingOut && + auto search = std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); + if (search != x434_additiveAnims.cend() && search->second.GetPhase() != EAdditivePlaybackPhase::FadingOut && search->second.GetPhase() != EAdditivePlaybackPhase::FadedOut) { search->second.FadeOut(); } @@ -226,26 +221,25 @@ void CAnimData::DelAdditiveAnimation(s32 idx) { void CAnimData::AddAdditiveAnimation(s32 idx, float weight, bool active, bool fadeOut) { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); + auto search = std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); if (search != x434_additiveAnims.cend()) { search->second.SetActive(active); search->second.SetWeight(weight); search->second.SetNeedsFadeOut(!search->second.IsActive() && fadeOut); } else { std::shared_ptr node = - GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders()); const CAdditiveAnimationInfo& info = x0_charFactory->FindAdditiveInfo(animIdx); - x434_additiveAnims.emplace_back(std::make_pair(animIdx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut))); + x434_additiveAnims.emplace_back( + std::make_pair(animIdx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut))); } } float CAnimData::GetAdditiveAnimationWeight(s32 idx) const { s32 animIdx = xc_charInfo.GetAnimationIndex(idx); - auto search = - std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [animIdx](const auto& pair) { return pair.first == animIdx; }); + auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [animIdx](const auto& pair) { return pair.first == animIdx; }); if (search != x434_additiveAnims.cend()) return search->second.GetTargetWeight(); return 0.f; @@ -541,15 +535,13 @@ void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time) { void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const { x120_particleDB.AddToRendererClipped(frustum); } void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, - const std::optional& morphEffect, - const float* morphMagnitudes) { + const std::optional& morphEffect, const float* morphMagnitudes) { SetupRender(model, drawFlags, morphEffect, morphMagnitudes); DrawSkinnedModel(model, drawFlags); } void CAnimData::SetupRender(CSkinnedModel& model, const CModelFlags& drawFlags, - const std::optional& morphEffect, - const float* morphMagnitudes) { + const std::optional& morphEffect, const float* morphMagnitudes) { if (!x220_30_poseBuilt) { x2fc_poseBuilder.BuildNoScale(x224_pose); x220_30_poseBuilt = true; @@ -798,8 +790,7 @@ void CAnimData::SetInfraModel(const TLockedToken& model, const TLockedTo } void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, const CModelFlags& drawFlags, - const std::optional& morphEffect, - const float* morphMagnitudes) { + const std::optional& morphEffect, const float* morphMagnitudes) { model.Calculate(pose, drawFlags, morphEffect, morphMagnitudes); } diff --git a/Runtime/Character/CInt32POINode.cpp b/Runtime/Character/CInt32POINode.cpp index aad1b8a79..037a33407 100644 --- a/Runtime/Character/CInt32POINode.cpp +++ b/Runtime/Character/CInt32POINode.cpp @@ -2,9 +2,12 @@ #include "CAnimSourceReader.hpp" namespace urde { - CInt32POINode::CInt32POINode() -: CPOINode("root", EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0), x38_val(0), x3c_locatorName("root") {} +: CInt32POINode(""sv, EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0, 0, "root"sv) {} + +CInt32POINode::CInt32POINode(std::string_view name, EPOIType type, const CCharAnimTime& time, s32 index, bool unique, float weight, s32 charIndex, + s32 flags, s32 val, std::string_view locator) +: CPOINode(name, type, time, index, unique, weight, charIndex, flags), x38_val(val), x3c_locatorName(locator) {} CInt32POINode::CInt32POINode(CInputStream& in) : CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {} diff --git a/Runtime/Character/CInt32POINode.hpp b/Runtime/Character/CInt32POINode.hpp index 209dcd73a..9306a5f07 100644 --- a/Runtime/Character/CInt32POINode.hpp +++ b/Runtime/Character/CInt32POINode.hpp @@ -11,6 +11,7 @@ class CInt32POINode : public CPOINode { public: CInt32POINode(); + CInt32POINode(std::string_view, EPOIType, const CCharAnimTime&, s32, bool, float, s32, s32, s32, std::string_view); CInt32POINode(CInputStream& in); s32 GetValue() const { return x38_val; } std::string_view GetLocatorName() const { return x3c_locatorName; } diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index 456130afa..b76356613 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -64,7 +64,7 @@ enum class EHurledState { Seven }; -enum class EFallState { Invalid = -1, Zero }; +enum class EFallState { Invalid = -1, Zero, One }; enum class EReactionType { Invalid = -1, Zero, One, Two, Three }; @@ -77,8 +77,18 @@ enum class EJumpState { Invalid = -1, IntoJump, AmbushJump, Loop, OutOfJump, Wal enum class EStepDirection { Invalid = -1, Forward = 0, Backward = 1, Left = 2, Right = 3, Up = 4, Down = 5 }; enum class EStepType { Normal = 0, Dodge = 1, BreakDodge = 2, RollDodge = 3 }; - -enum class ESeverity { Invalid = -1, Zero = 0, One = 1, Two = 2, Three, Four, Seven = 7, Eight = 8 }; +enum class ESeverity { + Invalid = -1, + Zero = 0, + One = 1, + Two = 2, + Three = 3, + Four = 4, + Five = 5, + Six = 6, + Seven = 7, + Eight = 8 +}; enum class EGetupType { Invalid = -1, Zero = 0, One = 1, Two = 2 }; diff --git a/Runtime/MP1/World/CBabygoth.hpp b/Runtime/MP1/World/CBabygoth.hpp index 0b40bb835..a32bdd375 100644 --- a/Runtime/MP1/World/CBabygoth.hpp +++ b/Runtime/MP1/World/CBabygoth.hpp @@ -197,7 +197,7 @@ public: void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); - float GetGravityConstant() const { return 10.f * 24.525f; } + float GetGravityConstant() const { return 10.f * CPhysicsActor::GravityConstant(); } void SetPathFindMode(EPathFindMode mode) { x8b4_pathFindMode = mode; } diff --git a/Runtime/MP1/World/CBeetle.cpp b/Runtime/MP1/World/CBeetle.cpp index 3b7e5580e..097375b5e 100644 --- a/Runtime/MP1/World/CBeetle.cpp +++ b/Runtime/MP1/World/CBeetle.cpp @@ -982,6 +982,6 @@ void CBeetle::Shock(CStateManager& mgr, float duration, float damage) { CPathFindSearch* CBeetle::GetSearchPath() { return &x5fc_pathFindSearch; } -float CBeetle::GetGravityConstant() const { return 4.f * 24.525f; } +float CBeetle::GetGravityConstant() const { return 4.f * CPhysicsActor::GravityConstant(); } } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlaahgra.cpp b/Runtime/MP1/World/CFlaahgra.cpp index 8ee67c274..bf8acd8d4 100644 --- a/Runtime/MP1/World/CFlaahgra.cpp +++ b/Runtime/MP1/World/CFlaahgra.cpp @@ -76,7 +76,21 @@ CFlaahgra::CFlaahgra(TUniqueId uid, std::string_view name, const CEntityInfo& in , x820_(xf.origin) , x8a0_(xf.frontVector()) , x8ac_(animRes) { + x8e4_24_loaded = false; + x8e4_25_loading = false; + x8e4_26_ = false; + x8e4_27_ = false; + x8e4_28_ = false; + x8e4_29_getup = false; + x8e4_30_ = false; + x8e4_31_ = false; + x8e5_24_ = false; + x8e5_25_ = false; + x8e5_26_ = false; + x8e5_27_ = false; + x8e5_28_ = false; x8e5_29_ = true; + x8e5_30_ = false; x6dc_.Token().Lock(); x704_.Token().Lock(); x7dc_.SetDamage(0.5f * x7dc_.GetDamage()); @@ -115,7 +129,7 @@ void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM } case EScriptObjectMessage::Activate: { GatherAssets(mgr); - if (x8e5_25_) + if (x8e5_27_) break; SetupCollisionManagers(mgr); @@ -150,10 +164,10 @@ void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM if (x7a8_ == 4) contactDamage = x7dc_; - if (sub801ae670()) + if (!sub801ae670()) contactDamage.SetDamage(0.5f * contactDamage.GetDamage()); - if (x788_ == 2) + if (x788_ >= 2) contactDamage.SetDamage(1.33f * contactDamage.GetDamage()); mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), contactDamage, @@ -266,6 +280,7 @@ void CFlaahgra::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, E return; } case EUserEventType::BeginAction: { + printf("BeginAction\n"); x8e4_26_ = true; x7c4_ = GetEndActionTime(); break; @@ -504,21 +519,26 @@ void CFlaahgra::sub801ae980(CStateManager& mgr) { HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - x56c_.x8_); x7d4_ = x56c_.xc_; x8e4_29_getup = true; + x7d8_ = 0.f; x430_damageColor = skUnkColor; ++x788_; } void CFlaahgra::sub801ade80() { - x894_ = (x7ac_ ? -GetTransform().basis[0] : GetTransform().basis[0]); + x894_ = (x7ac_ == 0 ? -GetTransform().basis[0] : GetTransform().basis[0]); - const rstl::reserved_vector& vec = (x7ac_ ? x82c_ : x860_); + const rstl::reserved_vector& vec = (x7ac_ == 0 ? x860_ : x82c_); + float curDist = FLT_MIN; for (const zeus::CVector3f& v : vec) { if (v.magSquared() < 0.f) continue; - if (GetTransform().basis[1].dot(v) > FLT_MIN) + float dist = GetTransform().basis[1].dot(v); + if (dist > curDist) { + curDist = dist; x894_ = v; + } } } @@ -539,8 +559,7 @@ bool CFlaahgra::ShouldAttack(CStateManager& mgr, float) { (x7cc_ > 0.f || player.GetVelocity().magSquared() < 25.f)) return false; - - return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), diff) > zeus::degToRad(45.f); + return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), diff) < zeus::degToRad(45.f); } void CFlaahgra::UpdateHeadDamageVulnerability(CStateManager& mgr, bool b) { @@ -567,6 +586,7 @@ void CFlaahgra::FadeOut(CStateManager& mgr, EStateMsg msg, float) { x7a4_sphereCollision->SetActive(mgr, true); x79c_leftArmCollision->SetActive(mgr, true); x7a0_rightArmCollision->SetActive(mgr, true); + x784_ = x780_; x81c_ = GetModelData()->GetScale().z(); UpdateScale(1.f, x81c_, x56c_.x4_); x8e4_26_ = false; @@ -601,7 +621,7 @@ void CFlaahgra::UpdateSmallScaleReGrowth(float dt) { if (!x8e4_29_getup || x7d8_ > 6.f) return; - x430_damageColor = zeus::CColor::lerp(skUnkColor, zeus::skBlack, (M_PIF * std::cos(x7d8_))); + x430_damageColor = zeus::CColor::lerp(skUnkColor, zeus::skBlack, std::round(std::fabs(M_PIF * std::cos(x7d8_)))); TakeDamage({}, 0.f); x7d8_ += dt; } @@ -718,7 +738,7 @@ void CFlaahgra::GetUp(CStateManager& mgr, EStateMsg msg, float) { SetCollisionActorBounds(mgr, x79c_leftArmCollision, skUnkVec1); SetCollisionActorBounds(mgr, x7a0_rightArmCollision, skUnkVec1); } else { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(x8e4_29_getup))); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(!x8e4_29_getup))); } } else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) { @@ -777,7 +797,8 @@ void CFlaahgra::SetCollisionActorBounds(CStateManager& mgr, const std::unique_pt } } void CFlaahgra::UpdateScale(float t, float min, float max) { - ModelData()->SetScale(zeus::skOne3f * (t * (max - min) + min)); + float scale = (t * (max - min) + min); + ModelData()->SetScale(zeus::skOne3f * scale); } float CFlaahgra::GetEndActionTime() { @@ -838,7 +859,7 @@ void CFlaahgra::RattlePlayer(CStateManager& mgr, const zeus::CVector3f& vec) { } void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) { - static const pas::ESeverity kSeverities[2] {pas::ESeverity::Zero, pas::ESeverity::One}; + static const pas::ESeverity kSeverities[2]{pas::ESeverity::Zero, pas::ESeverity::One}; if (msg == EStateMsg::Activate) { x568_ = 0; x7d4_ = 0.f; @@ -877,11 +898,8 @@ void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) { void CFlaahgra::Dead(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { - bool r29 = true; - if (x450_bodyController->GetFallState() == pas::EFallState::Zero && - x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall) - r29 = false; - x568_ = r29; + x568_ = (x450_bodyController->GetFallState() != pas::EFallState::Zero || + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall); SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None); } else if (msg == EStateMsg::Update) { if (x568_ == 0) { @@ -915,9 +933,8 @@ static const pas::ESeverity kStates1[5]{pas::ESeverity::Invalid, pas::ESeverity: pas::ESeverity::Two, pas::ESeverity::Invalid}; void CFlaahgra::Attack(CStateManager& mgr, EStateMsg msg, float arg) { - static const pas::ESeverity kSeverity[5] { - pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, pas::ESeverity::Zero, pas::ESeverity::Invalid - }; + static const pas::ESeverity kSeverity[5]{pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, + pas::ESeverity::Zero, pas::ESeverity::Invalid}; if (msg == EStateMsg::Activate) { x568_ = 0; @@ -1016,6 +1033,7 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) { x568_ = 0; x8e4_26_ = false; x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Two)); + x784_ = x780_; } else if (msg == EStateMsg::Update) { if (x568_ == 0) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup) @@ -1026,7 +1044,7 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) x568_ = 4; else if (x8e4_26_) { - UpdateScale(x7c4_ > 0.f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f, x56c_.x4_, x56c_.x0_); + UpdateScale(x7c4_ > 0.0f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f, x56c_.x4_, x56c_.x0_); } } @@ -1037,8 +1055,44 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) { x7a0_rightArmCollision->SetActive(mgr, false); } } -void CFlaahgra::ProjectileAttack(CStateManager&, EStateMsg, float) { +void CFlaahgra::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { + x568_ = 2; + } else { + x7b4_ = 3; + pas::ESeverity severity; + if (x8e4_31_) { + x7b4_ = 2; + severity = pas::ESeverity::Six; + } else if (mgr.GetPlayer().GetVelocity().magSquared() > 100.f) { + if (mgr.GetPlayer().GetTransform().basis[0].magSquared() < 0.f) { + x7b4_ = 1; + severity = pas::ESeverity::Four; + x72c_ = 0; + } else { + severity = pas::ESeverity::Three; + x7b4_ = x72c_ = 0; + } + } else { + severity = pas::ESeverity::Seven; + } + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCProjectileAttackCmd(severity, mgr.GetPlayer().GetTranslation(), false)); + } + } else if (x568_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { + x568_ = 4; + } else { + x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + } + } + } } void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) { static pas::ESeverity severities[2]{pas::ESeverity::Eight, pas::ESeverity::Seven}; @@ -1054,7 +1108,7 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) { else x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(severities[x7b0_])); } else if (x568_ == 1) { - if (TCastToConstPtr wp = mgr.GetObjectById(x77c_)) { + if (TCastToConstPtr wp = mgr.GetObjectById(x77c_)) { zeus::CVector3f direction = wp->GetTranslation() - GetTranslation(); if (zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), direction.toVec2f()) > zeus::degToRad(15.f) && @@ -1069,7 +1123,7 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) { } else if (x568_ == 2) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) x568_ = 4; - else if (TCastToConstPtr wp = mgr.GetObjectById(x77c_)) { + else if (TCastToConstPtr wp = mgr.GetObjectById(x77c_)) { x450_bodyController->GetCommandMgr().SetTargetVector(wp->GetTranslation() - GetTranslation()); } } @@ -1083,9 +1137,28 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) { x7b0_ ^= 1; } } -void CFlaahgra::SpecialAttack(CStateManager&, EStateMsg, float) {} +void CFlaahgra::SpecialAttack(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + x8e5_24_ = false; + x7b4_ = 3; + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { + x568_ = 2; + x8e4_30_ = true; + } else { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCProjectileAttackCmd(pas::ESeverity::Eight, mgr.GetPlayer().GetTranslation(), false)); + } + } else if (x568_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {} + } + } +} bool CFlaahgra::CoverCheck(CStateManager& mgr, float) { - if (x7f8_ < 0 && x7bc_ > 0.f) + if (x7f8_ <= 0 && x7bc_ > 0.f) return false; for (TUniqueId id : x770_mirrorWaypoints) { @@ -1103,11 +1176,10 @@ TUniqueId CFlaahgra::GetMirrorNearestPlayer(CStateManager& mgr) { TUniqueId nearId = kInvalidUniqueId; for (TUniqueId id : x770_mirrorWaypoints) { - if (TCastToConstPtr wp = mgr.GetObjectById(id)) { + if (TCastToConstPtr wp = mgr.GetObjectById(id)) { if (!wp->GetActive()) continue; - if ((wp->GetTranslation() - playerPos).magSquared() > -1.f) nearId = id; } @@ -1116,22 +1188,37 @@ TUniqueId CFlaahgra::GetMirrorNearestPlayer(CStateManager& mgr) { return nearId; } +void CFlaahgra::Enraged(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0; + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Taunt) + x568_ = 2; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::Zero)); + } else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) + x568_ = 4; + } else if (msg == EStateMsg::Deactivate) { + x7d0_ = 0.f; + } +} + CFlaahgraPlants::CFlaahgraPlants(const TToken& genDesc, const CActorParameters& actParms, TUniqueId uid, TAreaId aId, TUniqueId owner, const zeus::CTransform& xf, const CDamageInfo& dInfo, const zeus::CVector3f& extents) - : CActor(uid, true, "Flaahgra Plants"sv, CEntityInfo(aId, NullConnectionList), xf, CModelData::CModelDataNull(), - CMaterialList(EMaterialTypes::Projectile), actParms, kInvalidUniqueId) - , xe8_elementGen(new CElementGen(genDesc)) - , xf0_ownerId(owner) - , x130_obbox(xf, extents) { - xe8_elementGen->SetGlobalOrientation(xf.getRotation()); - xe8_elementGen->SetGlobalTranslation(xf.origin); +: CActor(uid, true, "Flaahgra Plants"sv, CEntityInfo(aId, NullConnectionList), xf, CModelData::CModelDataNull(), + CMaterialList(EMaterialTypes::Projectile), actParms, kInvalidUniqueId) +, xe8_elementGen(new CElementGen(genDesc)) +, xf0_ownerId(owner) +, x130_obbox(xf, extents) { + xe8_elementGen->SetOrientation(xf.getRotation()); + xe8_elementGen->SetTranslation(xf.origin); + xe8_elementGen->SetModelsUseLights(true); x110_aabox = {x130_obbox.calculateAABox(xf)}; } -void CFlaahgraPlants::Accept(IVisitor& visitor) { - visitor.Visit(this); -} +void CFlaahgraPlants::Accept(IVisitor& visitor) { visitor.Visit(this); } void CFlaahgraPlants::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { CActor::AcceptScriptMsg(msg, uid, mgr); diff --git a/Runtime/MP1/World/CFlaahgra.hpp b/Runtime/MP1/World/CFlaahgra.hpp index 0722cbf70..1da681efe 100644 --- a/Runtime/MP1/World/CFlaahgra.hpp +++ b/Runtime/MP1/World/CFlaahgra.hpp @@ -200,7 +200,7 @@ public: bool AnimOver(CStateManager&, float) { return x568_ == 4; } bool AIStage(CStateManager&, float arg) { return x780_ == u32(arg); } bool HitSomething(CStateManager&, float arg) { return x7d0_ > 0.f; } - bool OffLine(CStateManager&, float) { return (!x8e5_29_ && !x8e5_28_); } + bool OffLine(CStateManager&, float) { return (x8e5_29_ && x8e5_28_); } bool ShouldTurn(CStateManager&, float); bool ShouldAttack(CStateManager&, float); bool BreakAttack(CStateManager&, float) { return x7d4_ >= x56c_.xc_ && !x8e4_29_getup; } @@ -223,6 +223,7 @@ public: void ProjectileAttack(CStateManager&, EStateMsg, float); void Cover(CStateManager&, EStateMsg, float); void SpecialAttack(CStateManager&, EStateMsg, float); + void Enraged(CStateManager&, EStateMsg, float); }; } \ No newline at end of file diff --git a/Runtime/MP1/World/CParasite.cpp b/Runtime/MP1/World/CParasite.cpp index debc0d148..87fa9ad50 100644 --- a/Runtime/MP1/World/CParasite.cpp +++ b/Runtime/MP1/World/CParasite.cpp @@ -17,11 +17,11 @@ namespace urde::MP1 { -const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / 24.525002f); -const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / 24.525002f)); +const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant()); +const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / CPhysicsActor::GravityConstant())); short CParasite::word_805A8FC0 = 0; -const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / 24.525002f); -const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / 24.525002f); +const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant()); +const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant()); CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EBodyType bodyType, diff --git a/Runtime/MP1/World/CPuddleToadGamma.cpp b/Runtime/MP1/World/CPuddleToadGamma.cpp index 9ffc37bf8..01c725258 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.cpp +++ b/Runtime/MP1/World/CPuddleToadGamma.cpp @@ -142,7 +142,7 @@ void CPuddleToadGamma::ShootPlayer(CStateManager& mgr, float speed) { for (TUniqueId id : nearList) { if (TCastToPtr bomb = mgr.ObjectById(id)) { bomb->SetVelocityWR((mgr.GetActiveRandom()->Float() * 5.f + 20.f) * shootDir); - bomb->SetConstantAccelerationWR({0.f, 0.f, -24.525f}); + bomb->SetConstantAccelerationWR({0.f, 0.f, -CPhysicsActor::GravityConstant()}); } } } diff --git a/Runtime/MP1/World/CTryclops.cpp b/Runtime/MP1/World/CTryclops.cpp index 379b03837..b0274b855 100644 --- a/Runtime/MP1/World/CTryclops.cpp +++ b/Runtime/MP1/World/CTryclops.cpp @@ -2,13 +2,37 @@ #include "CStateManager.hpp" #include "World/CWorld.hpp" #include "World/CGameArea.hpp" +#include "World/CPatternedInfo.hpp" +#include "World/CPlayer.hpp" +#include "Weapon/CBomb.hpp" +#include "TCastTo.hpp" namespace urde::MP1 { +const CDamageVulnerability CTryclops::skVulnerabilities = CDamageVulnerability( + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Deflect, EVulnerability::Normal, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::Two); + CTryclops::CTryclops(urde::TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, urde::CModelData&& mData, const urde::CPatternedInfo& pInfo, - const urde::CActorParameters& actParms, float, float, float, float) + const urde::CActorParameters& actParms, float f1, float f2, float f3, float f4) : CPatterned(ECharacter::Tryclops, 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) +, x67c_(f1) +, x680_(std::cos(zeus::degToRad(0.5f * f2))) +, x684_(f3) +, x688_(f4) +, x698_24_(false) +, x698_25_(false) +, x698_26_(false) +, x698_27_dizzy(false) { + CreateShadow(false); + MakeThermalColdAndHot(); + x460_knockBackController.SetAutoResetImpulse(false); + x328_30_lookAtDeathDir = false; +} void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { CPatterned::AcceptScriptMsg(msg, uid, mgr); @@ -16,7 +40,417 @@ void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM if (msg == EScriptObjectMessage::Registered) { x450_bodyController->Activate(mgr); } else if (msg == EScriptObjectMessage::InitializedInArea) { - //x568_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); + x568_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); } } + +void CTryclops::Think(float dt, CStateManager& mgr) { + CPatterned::Think(dt, mgr); + + if (x400_25_alive && x68c_ > 0.f) + x68c_ -= dt; + + if (mgr.GetPlayer().GetAttachedActor() != GetUniqueId() || x698_27_dizzy) + return; + + x698_27_dizzy = (mgr.GetPlayer().GetAttachedActorStruggle() == 1.f && sub8025dbd0(mgr)); +} + +void CTryclops::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& poi, EUserEventType type, float dt) { + + switch (type) { + case EUserEventType::Projectile: + if (x694_bombId == kInvalidUniqueId) { + LaunchPlayer(mgr, GetLctrTransform(poi.GetLocatorName()), (x698_27_dizzy ? 5.f : x688_)); + } else { + DragBomb(mgr, GetLctrTransform(poi.GetLocatorName())); + } + return; + default: + break; + } + CPatterned::DoUserAnimEvent(mgr, poi, type, dt); +} + +void CTryclops::Death(CStateManager& mgr, const zeus::CVector3f& vec, EScriptObjectState state) { + if (x400_25_alive) { + CPlayer& player = mgr.GetPlayer(); + if (player.GetAttachedActor() == GetUniqueId()) { + player.SetLeaveMorphBallAllowed(true); + player.AddMaterial(EMaterialTypes::Solid, mgr); + player.DetachActorFromPlayer(); + } else if (x694_bombId != kInvalidUniqueId) { + if (TCastToPtr bomb = mgr.ObjectById(x694_bombId)) { + bomb->SetFuseDisabled(false); + bomb->SetIsBeingDragged(false); + } + x694_bombId = kInvalidUniqueId; + } + } + + CPatterned::Death(mgr, vec, state); +} + +void CTryclops::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::Patrol(mgr, msg, arg); + + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + } else if (msg == EStateMsg::Update) { + ApplySeparation(mgr); + } +} + +void CTryclops::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::PathFind(mgr, msg, arg); + + zeus::CVector3f front = GetTransform().basis[1]; + if (front.dot(x450_bodyController->GetCommandMgr().GetMoveVector()) < 0.f && front.canBeNormalized()) { + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(front.normalized(), {}, 1.f)); + } + ApplySeparation(mgr); +} + +void CTryclops::SelectTarget(CStateManager&, EStateMsg, float) {} + +void CTryclops::TargetPatrol(CStateManager&, EStateMsg, float) {} + +void CTryclops::TargetPlayer(CStateManager&, EStateMsg, float) {} + +void CTryclops::TargetCover(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Update) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + if (x694_bombId == kInvalidUniqueId) + return; + + if (TCastToConstPtr bomb = mgr.GetObjectById(x694_bombId)) + SetDestPos(bomb->GetTranslation()); + else + x694_bombId = kInvalidUniqueId; + } +} + +void CTryclops::Attack(CStateManager&, EStateMsg, float) {} +void CTryclops::JumpBack(CStateManager&, EStateMsg, float) {} +void CTryclops::Shuffle(CStateManager& mgr, EStateMsg msg, float arg) { PathFind(mgr, msg, arg); } +void CTryclops::TurnAround(CStateManager&, EStateMsg, float) {} +void CTryclops::Crouch(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + if (TCastToConstPtr wp = + mgr.GetObjectById(GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Follow))) { + SetDestPos(wp->GetTranslation()); + } + + mgr.GetPlayer().Stop(); + mgr.GetPlayer().RemoveMaterial(EMaterialTypes::Solid, mgr); + SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); + mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), true); + mgr.GetPlayer().SetLeaveMorphBallAllowed(false); + mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + } else if (msg == EStateMsg::Update) { + DragPlayer(mgr, GetLctrTransform("ballGrab_locator"sv).origin); + } else if (msg == EStateMsg::Deactivate) { + if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId()) + mgr.GetPlayer().DetachActorFromPlayer(); + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); + mgr.GetPlayer().AddMaterial(EMaterialTypes::Solid, mgr); + } +} + +void CTryclops::GetUp(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::Ready; + x698_24_ = false; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, 1); + if (!x698_24_) { + GrabBomb(mgr); + } + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + } +} + +void CTryclops::Suck(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + mgr.GetPlayer().SetLeaveMorphBallAllowed(false); + mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal6); + } else if (msg == EStateMsg::Update) { + SuckPlayer(mgr, arg); + } else if (msg == EStateMsg::Deactivate) { + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); + mgr.GetPlayer().AddMaterial(EMaterialTypes::Solid, mgr); + } +} + +void CTryclops::Cover(CStateManager&, EStateMsg, float) {} +void CTryclops::Approach(CStateManager&, EStateMsg, float) {} +void CTryclops::PathFindEx(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::PathFind(mgr, msg, arg); + ApplySeparation(mgr); + + CPlayer& player = mgr.GetPlayer(); + if (msg == EStateMsg::Activate) { + player.Stop(); + player.RemoveMaterial(EMaterialTypes::Solid, mgr); + player.GetMorphBall()->DisableHalfPipeStatus(); + player.AttachActorToPlayer(GetUniqueId(), true); + } else if (msg == EStateMsg::Update) { + DragPlayer(mgr, GetLctrTransform("ballGrab_locator"sv).origin); + } +} +void CTryclops::Dizzy(CStateManager&, EStateMsg, float) {} +bool CTryclops::InAttackPosition(CStateManager& mgr, float) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) + return false; + + CPlayer& player = mgr.GetPlayer(); + return sub80260180(player.GetTranslation(), + player.GetTranslation() + zeus::CVector3f(0.f, 0.f, player.GetMorphBall()->GetBallRadius()), + player.GetBoundingBox(), mgr); +} + +bool CTryclops::InRange(CStateManager& mgr, float) { + if (x694_bombId != kInvalidUniqueId) { + if (TCastToConstPtr bomb = mgr.GetObjectById(x694_bombId)) { + return sub80260180(bomb->GetTranslation(), bomb->GetTranslation(), *bomb->GetTouchBounds(), mgr); + } + } + + return false; +} + +bool CTryclops::InMaxRange(CStateManager& mgr, float) { + if (x694_bombId != kInvalidUniqueId) + return true; + + rstl::reserved_vector nearList; + + float dectRange = x3bc_detectionRange * x3bc_detectionRange; + float dectRangeHeight = x3c0_detectionHeightRange * x3c0_detectionHeightRange; + mgr.BuildNearList(nearList, {GetTranslation() - x3bc_detectionRange, GetTranslation() + x3bc_detectionRange}, + CMaterialFilter::MakeInclude({EMaterialTypes::Bomb}), this); + + x694_bombId = kInvalidUniqueId; + + for (TUniqueId uid : nearList) { + if (TCastToConstPtr bomb = mgr.GetObjectById(uid)) { + if (!bomb->IsBeingDragged()) { + float dist = (bomb->GetTranslation() - GetTranslation()).magSquared(); + float height = (bomb->GetTranslation().z() - GetTranslation().z()); + if (dist < dectRange && (height * height) < dectRangeHeight) { + if (x568_pathFindSearch.OnPath(bomb->GetTranslation()) == CPathFindSearch::EResult::Success) { + dectRange = dist; + x694_bombId = bomb->GetUniqueId(); + } + } + } + } + } + + if (x694_bombId != kInvalidUniqueId) { + if (TCastToPtr bomb = mgr.ObjectById(x694_bombId)) { + bomb->SetFuseDisabled(true); + bomb->SetIsBeingDragged(true); + return true; + } + } + + return false; +} + +bool CTryclops::InDetectionRange(CStateManager& mgr, float arg) { + CPlayer& player = mgr.GetPlayer(); + + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed || + player.GetAttachedActor() != kInvalidUniqueId || x68c_ > 0.f || !CPatterned::InDetectionRange(mgr, arg)) + return false; + + return x568_pathFindSearch.OnPath(player.GetBallPosition()) == CPathFindSearch::EResult::Success; +} + +bool CTryclops::SpotPlayer(CStateManager& mgr, float) { + if (x694_bombId != kInvalidUniqueId) { + + CPlayer& player = mgr.GetPlayer(); + if (TCastToPtr bomb = mgr.ObjectById(x694_bombId)) { + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + bool isPlayerCloser = (player.GetTranslation() - GetTranslation()).magSquared() < + (bomb->GetTranslation() - GetTranslation()).magSquared(); + if (isPlayerCloser) { + bomb->SetFuseDisabled(false); + bomb->SetIsBeingDragged(false); + x694_bombId = kInvalidUniqueId; + } + return isPlayerCloser; + } + } + } + + return true; +} +bool CTryclops::InPosition(CStateManager& mgr, float arg) { + if (x694_bombId != kInvalidUniqueId) { + if (TCastToConstPtr bomb = mgr.GetObjectById(x694_bombId)) { + return sub802600c8(bomb->GetTranslation(), arg); + } + } + + return false; +} + +bool CTryclops::HearShot(CStateManager& mgr, float) { + x698_26_ = false; + if (x694_bombId != kInvalidUniqueId) { + if (TCastToConstPtr(mgr.GetObjectById(x694_bombId))) { + x698_26_ = true; + return false; + } else + x694_bombId = kInvalidUniqueId; + } + + return true; +} + +bool CTryclops::CoverBlown(CStateManager&, float) { + return x568_pathFindSearch.OnPath(GetTranslation()) != CPathFindSearch::EResult::InvalidArea; +} + +bool CTryclops::Inside(CStateManager& mgr, float arg) { + const zeus::CTransform xf = mgr.GetPlayer().GetTransform(); + x64c_ = xf.getRotation(); + + return sub802600c8(xf.origin + zeus::CVector3f(0.f, 0.f, mgr.GetPlayer().GetMorphBall()->GetBallRadius()), arg); +} + +bool CTryclops::ShouldRetreat(CStateManager& mgr, float) { + if (TCastToConstPtr wp = + mgr.GetObjectById(GetWaypointForState(mgr, EScriptObjectState::Modify, EScriptObjectMessage::Next))) { + SetDestPos(wp->GetTranslation()); + return true; + } + + return false; +} + +bool CTryclops::IsDizzy(CStateManager&, float) { return x698_27_dizzy; } + +void CTryclops::LaunchPlayer(CStateManager& mgr, const zeus::CTransform& xf, float f1) { + CPlayer& player = mgr.GetPlayer(); + player.SetLeaveMorphBallAllowed(true); + + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) + return; + + x698_24_ = true; + x68c_ = 1.5f; + player.Stop(); + zeus::CTransform tmpXf = (xf * x64c_); + tmpXf.origin += zeus::CVector3f(0.f, 0.f, -0.5f); + player.Teleport(xf, mgr, false); + player.ApplyImpulseWR(f1 * (player.GetMass() * xf.basis[1].normalized()), zeus::CAxisAngle()); + player.SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr); + player.AddMaterial(EMaterialTypes::Solid, mgr); + mgr.ApplyDamage(GetUniqueId(), player.GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); +} + +void CTryclops::DragBomb(CStateManager& mgr, const zeus::CTransform& xf) { + if (x694_bombId != kInvalidUniqueId) { + if (TCastToPtr bomb = mgr.ObjectById(x694_bombId)) { + bomb->SetVelocityWR((5.f * mgr.GetActiveRandom()->Float() + 20.f) * xf.basis[1].normalized()); + bomb->SetConstantAccelerationWR({0.f, 0.f, -CPhysicsActor::GravityConstant()}); + } + } + + x698_26_ = false; + x698_24_ = true; + x694_bombId = kInvalidUniqueId; +} + +void CTryclops::ApplySeparation(CStateManager& mgr) { + for (CEntity* ent : mgr.GetListeningAiObjectList()) { + if (TCastToPtr ai = ent) { + if (ai == this || ai->GetAreaIdAlways() != GetAreaId()) + continue; + + zeus::CVector3f sep = x45c_steeringBehaviors.Separation(*this, ai->GetTranslation(), 8.f); + if (sep.x() != 0.f && sep.y() != 0.f && sep.z() != 0.f) + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(sep, {}, 1.f)); + } + } +} + +void CTryclops::GrabBomb(CStateManager& mgr) { + if (TCastToPtr bomb = mgr.ObjectById(x694_bombId)) { + zeus::CTransform grabLctr = GetLctrTransform("ballGrab_locator"sv); + grabLctr.origin += zeus::CVector3f(0.f, 0.f, -3.f); + bomb->SetTransform(grabLctr); + } +} + +void CTryclops::DragPlayer(CStateManager& mgr, const zeus::CVector3f& locOrig) { + CPlayer& player = mgr.GetPlayer(); + player.Stop(); + player.RemoveMaterial(EMaterialTypes::Solid, mgr); + zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv) * x64c_; + xf.origin += {0.f, 0.f, -.5f}; + player.SetTransform(xf); +} + +bool CTryclops::sub802600c8(const zeus::CVector3f& vec, float arg) { + return (vec - GetLctrTransform("ballGrab_locator"sv).origin).magSquared() <= arg; +} + +bool CTryclops::sub80260180(const zeus::CVector3f& vec1, const zeus::CVector3f& vec2, const zeus::CAABox& bounds, + CStateManager& mgr) { + + if (bounds.intersects(GetBoundingBox())) + return true; + + zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv); + zeus::CVector3f tmpVec2 = vec2 - (xf.origin - (1.f * GetTransform().basis[1])); + float f28 = tmpVec2.normalized().dot(GetTransform().basis[1]); + zeus::CVector3f tmpVec4 = (vec1 - (xf.origin - (4.f * GetTransform().basis[1]))).normalized(); + float f30 = tmpVec4.dot(GetTransform().basis[1]); + float f29 = tmpVec2.magnitude(); + + if (f29 > 2.f) { + CRayCastResult res = mgr.RayStaticIntersection( + xf.origin, (1.f / f29) * tmpVec2, f29 - mgr.GetPlayer().GetMorphBall()->GetBallRadius(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::Character, EMaterialTypes::Player, + EMaterialTypes::ProjectilePassthrough})); + if (res.IsValid()) + return false; + } + + return !(f29 >= x684_ || f28 <= 0.f || f30 <= x680_); +} + +void CTryclops::SuckPlayer(CStateManager& mgr, float arg) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) + return; + + CPlayer& player = mgr.GetPlayer(); + zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv); + zeus::CVector3f diff = (player.GetTranslation() - xf.origin); + float diffMag = diff.magnitude(); + if (diffMag < 3.f) { + player.Stop(); + AttractPlayer(mgr, xf.origin, arg); + } else { + player.ApplyForceWR(((x67c_ * (x684_ / (diffMag * diffMag))) * (player.GetMass() * -diff)), {}); + } +} + +void CTryclops::AttractPlayer(CStateManager& mgr, const zeus::CVector3f& dest, float arg) { + CPlayer& player = mgr.GetPlayer(); + const float ballRad = player.GetMorphBall()->GetBallRadius(); + player.SetVelocityWR(1.f / (2.f * arg) * + (dest - (player.GetTranslation() + zeus::CVector3f(0.f, 0.f, ballRad))).normalized()); +} + } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CTryclops.hpp b/Runtime/MP1/World/CTryclops.hpp index 4d039183d..5ffba956a 100644 --- a/Runtime/MP1/World/CTryclops.hpp +++ b/Runtime/MP1/World/CTryclops.hpp @@ -1,14 +1,90 @@ #pragma once #include "World/CPatterned.hpp" +#include "World/CPathFindSearch.hpp" namespace urde::MP1 { class CTryclops : public CPatterned { + + static const CDamageVulnerability skVulnerabilities; + CPathFindSearch x568_pathFindSearch; + zeus::CTransform x64c_; + float x67c_; + float x680_; + float x684_; + float x688_; + float x68c_ = 0.f; + u32 x690_ = 0; + TUniqueId x694_bombId = kInvalidUniqueId; + TUniqueId x696_ = kInvalidUniqueId; + bool x698_24_ : 1; + bool x698_25_ : 1; + bool x698_26_ : 1; + bool x698_27_dizzy : 1; + bool sub8025dbd0(CStateManager&) { return false; } + void LaunchPlayer(CStateManager& mgr, const zeus::CTransform& xf, float); + void DragBomb(CStateManager& mgr, const zeus::CTransform& xf); + void ApplySeparation(CStateManager&); + void GrabBomb(CStateManager& mgr); + void DragPlayer(CStateManager& mgr, const zeus::CVector3f& locOrig); + bool sub802600c8(const zeus::CVector3f&, float); + bool sub80260180(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CAABox&, CStateManager&); + void SuckPlayer(CStateManager& mgr, float); + void AttractPlayer(CStateManager& mgr, const zeus::CVector3f& dest, float); + public: DEFINE_PATTERNED(Tryclops) CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, const CActorParameters&, float, float, float, float); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + const CDamageVulnerability* GetDamageVulnerability() const { + if (x698_26_) + return CAi::GetDamageVulnerability(); + + return &skVulnerabilities; + } + + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, + const CDamageInfo&) const { + if (x698_26_) + return CAi::GetDamageVulnerability(); + + return &skVulnerabilities; + } + + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float); + void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState); + bool IsListening() const { return true; } + void Patrol(CStateManager&, EStateMsg, float); + void PathFind(CStateManager&, EStateMsg, float); + void SelectTarget(CStateManager&, EStateMsg, float); + void TargetPatrol(CStateManager&, EStateMsg, float); + void TargetPlayer(CStateManager&, EStateMsg, float); + void TargetCover(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void JumpBack(CStateManager&, EStateMsg, float); + void Shuffle(CStateManager&, EStateMsg, float); + void TurnAround(CStateManager&, EStateMsg, float); + void Crouch(CStateManager&, EStateMsg, float); + void GetUp(CStateManager&, EStateMsg, float); + void Suck(CStateManager&, EStateMsg, float); + void Cover(CStateManager&, EStateMsg, float); + void Approach(CStateManager&, EStateMsg, float); + void PathFindEx(CStateManager&, EStateMsg, float); + void Dizzy(CStateManager&, EStateMsg, float); + bool InAttackPosition(CStateManager&, float); + bool InRange(CStateManager&, float); + bool InMaxRange(CStateManager&, float); + bool InDetectionRange(CStateManager&, float); + bool SpotPlayer(CStateManager&, float); + bool InPosition(CStateManager&, float); + bool HearShot(CStateManager&, float); + bool CoverBlown(CStateManager&, float); + bool Inside(CStateManager&, float); + bool ShouldRetreat(CStateManager&, float); + bool IsDizzy(CStateManager&, float); + CPathFindSearch* GetSearchPath() { return &x568_pathFindSearch; } }; } // namespace urde::MP1 diff --git a/Runtime/Weapon/CBomb.cpp b/Runtime/Weapon/CBomb.cpp index 603b778ef..a6b83a790 100644 --- a/Runtime/Weapon/CBomb.cpp +++ b/Runtime/Weapon/CBomb.cpp @@ -24,9 +24,9 @@ CBomb::CBomb(const TCachedToken& particle1, const TCachedToken< new CElementGen(particle1, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)) , x184_particle2( new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)) -, x18c_(particle2.GetObj()) +, x18c_particle2Obj(particle2.GetObj()) , x190_24_isNotDetonated(true) -, x190_25_(false) +, x190_25_beingDragged(false) , x190_26_disableFuse(false) { x180_particle1->SetGlobalTranslation(xf.origin); x184_particle2->SetGlobalTranslation(xf.origin); @@ -40,7 +40,7 @@ void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManag x188_lightId = mgr.AllocateUniqueId(); CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false, std::string("Bomb_PLight") + GetName().data(), GetTransform(), GetUniqueId(), - x184_particle2->GetLight(), reinterpret_cast(x18c_), 1, 0.f); + x184_particle2->GetLight(), reinterpret_cast(x18c_particle2Obj), 1, 0.f); mgr.AddObject(gameLight); mgr.AddWeaponId(xec_ownerId, xf0_weaponType); CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1); diff --git a/Runtime/Weapon/CBomb.hpp b/Runtime/Weapon/CBomb.hpp index cb0fb9f61..3c348aacb 100644 --- a/Runtime/Weapon/CBomb.hpp +++ b/Runtime/Weapon/CBomb.hpp @@ -15,9 +15,9 @@ class CBomb : public CWeapon { std::unique_ptr x180_particle1; std::unique_ptr x184_particle2; TUniqueId x188_lightId = kInvalidUniqueId; - const CGenDescription* x18c_; + const CGenDescription* x18c_particle2Obj; bool x190_24_isNotDetonated : 1; - bool x190_25_ : 1; + bool x190_25_beingDragged : 1; bool x190_26_disableFuse : 1; public: @@ -35,6 +35,9 @@ public: std::optional GetTouchBounds() const; void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; } void SetConstantAccelerationWR(const zeus::CVector3f& acc) { x164_acceleration = acc; } + void SetFuseDisabled(bool b) { x190_26_disableFuse = false; } + void SetIsBeingDragged(bool b) { x190_25_beingDragged = b; } + bool IsBeingDragged() const { return x190_25_beingDragged; } }; } // namespace urde diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index 1106cc993..1ff68f848 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -241,14 +241,14 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3 EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false); if (vulnType == EVulnerability::Deflect) { deflect = true; - EVulnerability deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); + EDeflectType deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); switch (deflectType) { - case EVulnerability::Weak: + case EDeflectType::None: deflect = false; break; - case EVulnerability::Deflect: - case EVulnerability::Immune: - if (deflectType != EVulnerability::Deflect || + case EDeflectType::Two: + case EDeflectType::Three: + if (deflectType != EDeflectType::Two || (xf0_weaponType != EWeaponType::Missile && (xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) diff --git a/Runtime/World/CDamageVulnerability.cpp b/Runtime/World/CDamageVulnerability.cpp index 4a1fca361..07d73b7e2 100644 --- a/Runtime/World/CDamageVulnerability.cpp +++ b/Runtime/World/CDamageVulnerability.cpp @@ -8,7 +8,7 @@ const CDamageVulnerability CDamageVulnerability::sNormalVulnerability( EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, - EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Weak); + EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EDeflectType::None); const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability( EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, @@ -16,7 +16,7 @@ const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability( EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, - EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Weak); + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None); /* LOL, thanks retro */ const CDamageVulnerability CDamageVulnerability::sReflectVulnerability( EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, @@ -24,7 +24,7 @@ const CDamageVulnerability CDamageVulnerability::sReflectVulnerability( EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, - EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Weak); + EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None); const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability( EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, @@ -32,7 +32,7 @@ const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability( EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, - EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::Weak); + EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EDeflectType::None); static inline bool is_not_immune(EVulnerability vuln) { return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune; @@ -56,19 +56,19 @@ void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) { for (int i = 15; i < propCount; ++i) in.readUint32Big(); - x5c_deflected = EVulnerability(in.readUint32Big()); + x5c_deflected = EDeflectType(in.readUint32Big()); EVulnerability* vulns2 = &x3c_chargedPower; in.readUint32Big(); for (int i = 0; i < 4; ++i) vulns2[i] = EVulnerability(in.readUint32Big()); - x60_chargedDeflected = EVulnerability(in.readUint32Big()); + x60_chargedDeflected = EDeflectType(in.readUint32Big()); EVulnerability* vulns3 = &x4c_superMissile; in.readUint32Big(); for (int i = 0; i < 4; ++i) vulns3[i] = EVulnerability(in.readUint32Big()); - x64_comboDeflected = EVulnerability(in.readUint32Big()); + x64_comboDeflected = EDeflectType(in.readUint32Big()); } CDamageVulnerability::CDamageVulnerability(CInputStream& in) { @@ -79,9 +79,9 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) { vulns[i] = EVulnerability(in.readUint32Big()); if (propCount == 15) - x5c_deflected = EVulnerability::Weak; + x5c_deflected = EDeflectType::None; else - x5c_deflected = EVulnerability(in.readUint32Big()); + x5c_deflected = EDeflectType(in.readUint32Big()); x3c_chargedPower = x0_power; x4c_superMissile = x0_power; @@ -95,13 +95,44 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) { ConstructNew(in, propCount); } +CDamageVulnerability::CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, + EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb, + EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, + EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, + EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, + EDeflectType deflectType) +: x0_power(power) +, x4_ice(ice) +, x8_wave(wave) +, xc_plasma(plasma) +, x10_bomb(bomb) +, x14_powerbomb(powerBomb) +, x18_missile(missile) +, x1c_boostBall(boostBall) +, x20_phazon(phazon) +, x24_enemyWp1(enemyWp1) +, x28_enemyWp2Poison(enemyWp2) +, x2c_enemyWp3Lava(enemyWp3) +, x30_enemyWp4(enemyWp4) +, x34_unk1(v1) +, x38_unk2(v2) +, x3c_chargedPower(x0_power) +, x40_chargedIce(x4_ice) +, x44_chargedWave(x8_wave) +, x48_chargedPlasma(xc_plasma) +, x4c_superMissile(x0_power) +, x50_iceSpreader(x4_ice) +, x54_wavebuster(x8_wave) +, x58_flamethrower(xc_plasma) +, x5c_deflected(deflectType) {} + CDamageVulnerability::CDamageVulnerability( EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce, EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader, - EVulnerability waveBuster, EVulnerability flameThrower, EVulnerability deflected) + EVulnerability waveBuster, EVulnerability flameThrower, EDeflectType deflected) : x0_power(power) , x4_ice(ice) , x8_wave(wave) @@ -127,7 +158,7 @@ CDamageVulnerability::CDamageVulnerability( , x58_flamethrower(flameThrower) , x5c_deflected(deflected) {} -EVulnerability CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const { +EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const { if (mode.IsCharged()) return x60_chargedDeflected; if (mode.IsComboed()) @@ -205,9 +236,7 @@ bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) return true; if (chargedVuln && mode.IsCharged()) return true; - if (comboedVuln && mode.IsComboed()) - return true; - return false; + return comboedVuln && mode.IsComboed(); } EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { diff --git a/Runtime/World/CDamageVulnerability.hpp b/Runtime/World/CDamageVulnerability.hpp index 0538973d0..32b929039 100644 --- a/Runtime/World/CDamageVulnerability.hpp +++ b/Runtime/World/CDamageVulnerability.hpp @@ -6,6 +6,7 @@ namespace urde { enum class EVulnerability { Weak, Normal, Deflect, Immune, PassThrough, DirectWeak, DirectNormal, DirectImmune }; +enum class EDeflectType { None, One, Two, Three, Four }; class CDamageVulnerability { EVulnerability x0_power; @@ -34,9 +35,12 @@ class CDamageVulnerability { EVulnerability x54_wavebuster; EVulnerability x58_flamethrower; - EVulnerability x5c_deflected; - EVulnerability x60_chargedDeflected; - EVulnerability x64_comboDeflected; + EDeflectType x5c_deflected; + /* The following two values are hard coded to bizarre values on purpose to more closely reflect the behavior seen + * in-game. + */ + EDeflectType x60_chargedDeflected = EDeflectType(6); + EDeflectType x64_comboDeflected = EDeflectType(0x3e666666); void ConstructNew(CInputStream& in, int propCount); @@ -47,15 +51,19 @@ class CDamageVulnerability { public: CDamageVulnerability(CInputStream& in); + CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, + EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, + EVulnerability phazon, EVulnerability enemyWp1, EVulnerability wnemyWp2, EVulnerability enemyWp3, + EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EDeflectType deflectType); CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce, EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader, EVulnerability waveBuster, - EVulnerability flameThrower, EVulnerability deflected); + EVulnerability flameThrower, EDeflectType deflected); - EVulnerability GetDeflectionType(const CWeaponMode& mode) const; + EDeflectType GetDeflectionType(const CWeaponMode& mode) const; bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const; bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const; diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 783e85e8f..4f55001d3 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -346,7 +346,7 @@ public: virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255); } virtual bool IsOnGround() const { return x328_27_onGround; } - virtual float GetGravityConstant() const { return 24.525002f; } + virtual float GetGravityConstant() const { return CPhysicsActor::GravityConstant(); } virtual CProjectileInfo* GetProjectileInfo() { return nullptr; } virtual void PhazeOut(CStateManager&); virtual const std::optional>& GetDeathExplosionParticle() const { diff --git a/Runtime/World/CPhysicsActor.cpp b/Runtime/World/CPhysicsActor.cpp index 4f3881b7e..75b0f159f 100644 --- a/Runtime/World/CPhysicsActor.cpp +++ b/Runtime/World/CPhysicsActor.cpp @@ -47,7 +47,7 @@ float CPhysicsActor::GetStepUpHeight() const { return x23c_stepUpHeight; } float CPhysicsActor::GetStepDownHeight() const { return x240_stepDownHeight; } -float CPhysicsActor::GetWeight() const { return 24.525002f * xe8_mass; } +float CPhysicsActor::GetWeight() const { return CPhysicsActor::GravityConstant() * xe8_mass; } void CPhysicsActor::SetPrimitiveOffset(const zeus::CVector2f& offset) { x1e8_primitiveOffset = offset; } diff --git a/Runtime/World/CPhysicsActor.hpp b/Runtime/World/CPhysicsActor.hpp index 801f4f25f..afb4b5044 100644 --- a/Runtime/World/CPhysicsActor.hpp +++ b/Runtime/World/CPhysicsActor.hpp @@ -202,5 +202,6 @@ public: void ApplyTorqueWR(const zeus::CVector3f& torque); void UseCollisionImpulses(); + static constexpr float GravityConstant() { return 9.81f * 2.5f; } /* 9.81 m/s ^ 2 is normal acceleration under earth gravity, Tallon 4 is 2.5 times that */ }; } // namespace urde diff --git a/Runtime/World/CScriptActor.cpp b/Runtime/World/CScriptActor.cpp index b2f8fca3d..37dd2133b 100644 --- a/Runtime/World/CScriptActor.cpp +++ b/Runtime/World/CScriptActor.cpp @@ -174,8 +174,8 @@ EWeaponCollisionResponseTypes CScriptActor::GetCollisionResponseType(const zeus: EProjectileAttrib w) const { const CDamageVulnerability* dVuln = GetDamageVulnerability(); if (dVuln->GetVulnerability(wMode, false) == EVulnerability::Deflect) { - EVulnerability phazonVuln = dVuln->GetDeflectionType(wMode); - if (phazonVuln < EVulnerability::PassThrough && phazonVuln >= EVulnerability::Normal) + EDeflectType deflectType = dVuln->GetDeflectionType(wMode); + if (deflectType < EDeflectType::Four && deflectType >= EDeflectType::One) return EWeaponCollisionResponseTypes::Unknown15; } return CActor::GetCollisionResponseType(v1, v2, wMode, w); diff --git a/Runtime/World/CScriptDebris.cpp b/Runtime/World/CScriptDebris.cpp index 7194dc8b7..b30be389e 100644 --- a/Runtime/World/CScriptDebris.cpp +++ b/Runtime/World/CScriptDebris.cpp @@ -53,7 +53,7 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity x2d4_particleGens[0]->SetGlobalScale(particleScale); } - x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass); + x150_momentum = zeus::CVector3f(0.f, 0.f, -CPhysicsActor::GravityConstant() * xe8_mass); if (x90_actorLights) x90_actorLights->SetAmbienceGenerated(true); diff --git a/Runtime/World/CWallCrawlerSwarm.cpp b/Runtime/World/CWallCrawlerSwarm.cpp index 45dbc9c54..b29c8babc 100644 --- a/Runtime/World/CWallCrawlerSwarm.cpp +++ b/Runtime/World/CWallCrawlerSwarm.cpp @@ -16,6 +16,7 @@ #include "GameGlobalObjects.hpp" #include "CStateManager.hpp" #include "CSimplePool.hpp" +#include "World/CPhysicsActor.hpp" #include "TCastTo.hpp" namespace urde { @@ -490,7 +491,7 @@ void CWallCrawlerSwarm::UpdateBoid(const CAreaCollisionCache& ccache, CStateMana f28 += f25; } if (!found) { - boid.x30_velocity += zeus::CVector3f(0.f, 0.f, -(x558_flavor == EFlavor::Scarab ? 3.f * 24.525f : 24.525f)) * dt; + boid.x30_velocity += zeus::CVector3f(0.f, 0.f, -(x558_flavor == EFlavor::Scarab ? 3.f * CPhysicsActor::GravityConstant() : CPhysicsActor::GravityConstant())) * dt; if (boid.x7c_remainingLaunchNotOnSurfaceFrames) boid.x7c_remainingLaunchNotOnSurfaceFrames -= 1; } @@ -561,7 +562,7 @@ void CWallCrawlerSwarm::UpdateBoid(const CAreaCollisionCache& ccache, CStateMana void CWallCrawlerSwarm::LaunchBoid(CBoid& boid, const zeus::CVector3f& dir) { zeus::CVector3f pos = boid.GetTranslation(); - static float skAttackTime = std::sqrt(2.5f / 24.525f) * 2.f; + static float skAttackTime = std::sqrt(2.5f / CPhysicsActor::GravityConstant()) * 2.f; static float skAttackVelocity = 15.f / skAttackTime; zeus::CVector3f deltaFlat = dir - pos; float deltaZ = deltaFlat.z(); @@ -578,14 +579,14 @@ void CWallCrawlerSwarm::LaunchBoid(CBoid& boid, const zeus::CVector3f& dir) { bool r29 = deltaZ < 0.f; float _12c, _130; float f25 = 0.f; - if (CSteeringBehaviors::SolveQuadratic(-24.525f, vec.z(), -deltaZ, _12c, _130)) + if (CSteeringBehaviors::SolveQuadratic(-CPhysicsActor::GravityConstant(), vec.z(), -deltaZ, _12c, _130)) f25 = r29 ? _130 : _12c; if (!r29) f25 += deltaMag / dot; if (f25 < 10.f) { vec.x() = deltaMag / f25 * deltaFlat.x() * 0.6f; vec.y() = deltaMag / f25 * deltaFlat.y() * 0.6f; - vec.z() = deltaZ / f25 - 0.5f * -24.525f * f25; + vec.z() = deltaZ / f25 - 0.5f * -CPhysicsActor::GravityConstant() * f25; } } }