From e925dc26284554a73f337f308704530eaa85c6e9 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 12 Mar 2020 01:36:13 -0400 Subject: [PATCH 01/16] CFlyingPirate: Start implementation --- Runtime/MP1/World/CFlyingPirate.cpp | 100 +++++++++++++++++++++++++++- Runtime/MP1/World/CFlyingPirate.hpp | 84 ++++++++++++++++++++++- 2 files changed, 182 insertions(+), 2 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 815a59883..727d71c0d 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1,10 +1,108 @@ #include "Runtime/MP1/World/CFlyingPirate.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/World/CPatternedInfo.hpp" +#include "Runtime/Character/CPASAnimParmData.hpp" + namespace urde::MP1 { +namespace { +constexpr std::array skBurst1{{ + {4, {3, 4, 11, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, + {20, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, + {20, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, + {25, {15, 16, 1, 2, -1, 0, 0, 0}, 0.1f, 0.05f}, + {25, {5, 6, 7, 8, -1, 0, 0, 0}, 0.1f, 0.05f}, + {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}}; + +constexpr std::array skBurst2{{ + {5, {3, 4, 8, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, + {10, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, + {10, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, + {40, {15, 16, 1, 2, -1, 0, 0, 0}, 0.1f, 0.05f}, + {35, {5, 6, 7, 8, -1, 0, 0, 0}, 0.1f, 0.05f}, + {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}}; + +constexpr std::array skBurst3{{ + {30, {3, 4, 5, 11, 12, 4, -1, 0}, 0.1f, 0.05f}, + {20, {2, 3, 4, 5, 4, 3, -1, 0}, 0.1f, 0.05f}, + {20, {5, 4, 3, 13, 12, 11, -1, 0}, 0.1f, 0.05f}, + {30, {1, 2, 3, 4, 5, 6, -1, 0}, 0.1f, 0.05f}, + {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}}; + +constexpr std::array skBurst4{{ + {10, {6, 5, 4, 14, 13, 12, -1, 0}, 0.1f, 0.05f}, + {20, {14, 13, 12, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, + {20, {14, 15, 16, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, + {50, {11, 10, 9, 8, 7, 6, -1, 0}, 0.1f, 0.05f}, + {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}}; + +constexpr std::array skBursts{ + skBurst1.data(), skBurst2.data(), skBurst3.data(), skBurst4.data(), nullptr, +}; +} // namespace +CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCount) +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in.readInt32Big()) +, xc_projInfo1(in) +, x34_sfx1(in.readUint16Big()) +, x38_projInfo2(in) +, x60_projInfo3(in.readInt32Big(), {}) +, x88_(in.readFloatBig()) +, x8c_(in.readFloatBig()) +, x90_particleGenDesc(g_SimplePool->GetObj({SBIG('PART'), in.readInt32Big()})) +, x9c_dInfo(in) +, xb8_(in.readFloatBig()) +, xbc_(in.readFloatBig()) +, xc0_(in.readFloatBig()) +, xc4_(in.readFloatBig()) +, xca_sfx3(in.readUint16Big()) +, xcc_(in.readFloatBig()) +, xd0_(in.readFloatBig()) +, xd4_(in.readFloatBig()) +, xd8_(in) +, xdc_(in) +, xe0_(in) +, xe4_sfx4(in.readUint16Big()) +, xe6_sfx5(in.readUint16Big()) +, xe8_(in.readFloatBig()) +, xec_(in.readFloatBig()) +, xf0_(propCount < 36 ? 0.f : in.readFloatBig()) { + xc_projInfo1.Token().Lock(); + x38_projInfo2.Token().Lock(); + x60_projInfo3.Token().Lock(); +} CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) : CPatterned(ECharacter::FlyingPirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium) {} + EMovementType::Ground, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium) +, x568_data(in, propCount) +, x6a8_pathFindSearch(nullptr, 0 /* TODO */, pInfo.GetHalfExtent(), pInfo.GetHeight(), pInfo.GetPathfindingIndex()) +, x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f), + EBoneTrackingFlags::None) +, x7ec_burstFire(skBursts.data(), 0) { + CModelData* modelData = GetModelData(); + CAnimData* animData = modelData->GetAnimationData(); + x798_ = animData->GetLocatorSegId("Head_1"); + x7e0_ = animData->GetLocatorSegId("L_gun_LCTR"); + x864_missileSegments.push_back(animData->GetLocatorSegId("L_Missile_LCTR")); + x864_missileSegments.push_back(animData->GetLocatorSegId("R_Missile_LCTR")); + x850_ = modelData->GetScale().x() * GetAnimationDistance({3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1)}); + if (x568_data.xd8_.IsValid() && x568_data.xdc_.IsValid() && x568_data.xe0_.IsValid()) { + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xd8_})); + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xdc_})); + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xe0_})); + for (const auto& desc : x65c_particleGenDescs) { + x684_particleGens.push_back(std::make_unique(desc)); + } + } + x460_knockBackController.SetLocomotionDuringElectrocution(true); +} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index dc89c37c4..24aaf422b 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -1,5 +1,10 @@ #pragma once +#include "Runtime/Character/CBoneTracking.hpp" +#include "Runtime/Particle/CElementGen.hpp" +#include "Runtime/Weapon/CBurstFire.hpp" +#include "Runtime/Weapon/CProjectileInfo.hpp" +#include "Runtime/World/CPathFindSearch.hpp" #include "Runtime/World/CPatterned.hpp" namespace urde::MP1 { @@ -7,7 +12,84 @@ class CFlyingPirate : public CPatterned { public: DEFINE_PATTERNED(FlyingPirate) +private: + class CFlyingPirateData { + friend class CFlyingPirate; + float x0_; + float x4_; + int x8_; + CProjectileInfo xc_projInfo1; + u16 x34_sfx1; + CProjectileInfo x38_projInfo2; + CProjectileInfo x60_projInfo3; + float x88_; + float x8c_; + TCachedToken x90_particleGenDesc; + CDamageInfo x9c_dInfo; + float xb8_; + float xbc_; + float xc0_; + float xc4_; + u16 xc8_sfx2; + u16 xca_sfx3; + float xcc_; + float xd0_; + float xd4_; + CAssetId xd8_; + CAssetId xdc_; + CAssetId xe0_; + u16 xe4_sfx4; + u16 xe6_sfx5; + float xe8_; + float xec_; + float xf0_; + + public: + CFlyingPirateData(CInputStream& in, u32 propCount); + }; + +public: CFlyingPirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); + +private: + CFlyingPirateData x568_data; + rstl::reserved_vector, 4> x65c_particleGenDescs; + rstl::reserved_vector, 16> x684_particleGens; + char x6a0_flags1; // TODO + char x6a1_flags2; // TODO + char x6a2_flags3; // TODO + TUniqueId x6a4_id1 = kInvalidUniqueId; + TUniqueId x6a6_id2 = kInvalidUniqueId; + CPathFindSearch x6a8_pathFindSearch; + int x790_ = 0; + int x794_health; + CSegId x798_; + int x79c_ = -1; + CBoneTracking x7a0_boneTracking; + float x7d8_ = 0.f; + int x7dc_ = 0; + CSegId x7e0_; + float x7e4_ = 1.f; + TUniqueId x7e8_id3 = kInvalidUniqueId; + CBurstFire x7ec_burstFire; + int x84c_ = -1; + float x850_ = 3.f; + float x854_ = FLT_MAX; + float x858_ = FLT_MAX; + TUniqueId x85c_ = kInvalidUniqueId; + float x860_ = 15.f; + rstl::reserved_vector x864_missileSegments; + float x86c_ = 0.f; + zeus::CVector3f x870_ = zeus::skZero3f; + zeus::CVector3f x87c_ = zeus::skZero3f; + float x888_ = 10.f; + float x88c_ = 3.f; + TUniqueId x890_ = kInvalidUniqueId; + float x894_ = 1.f; + float x898_ = 1.f; +// CFlyingPirateRagDoll x89c_ragDoll; TODO + TUniqueId x8a0_ = kInvalidUniqueId; + float x8a4_ = 0.f; }; -} // namespace urde::MP1 \ No newline at end of file +} // namespace urde::MP1 From 5765fd8951f1fe3425f743466bafbbfddaeb29c7 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 12 Mar 2020 03:07:41 -0400 Subject: [PATCH 02/16] CFlyingPirate: Method definitions & CFlyingPirateRagDoll constructor --- Runtime/MP1/World/CFlyingPirate.cpp | 87 +++++++++++++++++++++++--- Runtime/MP1/World/CFlyingPirate.hpp | 97 ++++++++++++++++++++++++++++- Runtime/World/CAi.hpp | 2 +- Runtime/World/CPatterned.hpp | 1 + 4 files changed, 178 insertions(+), 9 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 727d71c0d..ddb5dfa8c 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -7,7 +7,7 @@ namespace urde::MP1 { namespace { -constexpr std::array skBurst1{{ +constexpr std::array skBurst1{{ {4, {3, 4, 11, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, {20, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, {20, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, @@ -16,7 +16,7 @@ constexpr std::array skBurst1{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst2{{ +constexpr std::array skBurst2{{ {5, {3, 4, 8, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, {10, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, {10, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, @@ -25,7 +25,7 @@ constexpr std::array skBurst2{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst3{{ +constexpr std::array skBurst3{{ {30, {3, 4, 5, 11, 12, 4, -1, 0}, 0.1f, 0.05f}, {20, {2, 3, 4, 5, 4, 3, -1, 0}, 0.1f, 0.05f}, {20, {5, 4, 3, 13, 12, 11, -1, 0}, 0.1f, 0.05f}, @@ -33,7 +33,7 @@ constexpr std::array skBurst3{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst4{{ +constexpr std::array skBurst4{{ {10, {6, 5, 4, 14, 13, 12, -1, 0}, 0.1f, 0.05f}, {20, {14, 13, 12, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, {20, {14, 15, 16, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, @@ -41,10 +41,16 @@ constexpr std::array skBurst4{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBursts{ +constexpr std::array skBursts{ skBurst1.data(), skBurst2.data(), skBurst3.data(), skBurst4.data(), nullptr, }; + +constexpr std::array skParts{ + "s_Head", "s_R_shoulder", "s_R_elbow", "s_R_wrist", "s_L_shoulder", "s_L_elbow", "s_L_wrist", + "s_R_hip", "s_R_knee", "s_R_ankle", "s_L_hip", "s_L_knee", "s_L_ankle", "s_rocket_LCTR", +}; } // namespace + CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCount) : x0_(in.readFloatBig()) , x4_(in.readFloatBig()) @@ -78,6 +84,73 @@ CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCo x60_projInfo3.Token().Lock(); } +CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2) +: CRagDoll(-actor->GetGravityConstant(), 3.f, 8.f, 0) +, x88_(w1) +, x9c_(w2) +, xa4_(actor->GetDestPos() - actor->GetTranslation()) { + actor->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock, EMaterialTypes::GroundCollider, mgr); + actor->HealthInfo(mgr)->SetHP(-1.f); + SetNumParticles(15); + SetNumLengthConstraints(45); + SetNumJointConstraints(4); + CAnimData* animData = actor->GetModelData()->GetAnimationData(); + animData->BuildPose(); + const zeus::CVector3f& center = actor->GetBoundingBox().center(); + for (const auto& part : skParts) { + const CSegId& id = animData->GetLocatorSegId(part); + AddParticle(id, center, center * animData->GetPose().GetOffset(id), 0.45f * center.z()); + } + SatisfyWorldConstraintsOnConstruction(mgr); + AddLengthConstraint(0, 1); + AddLengthConstraint(0, 2); + AddLengthConstraint(0, 8); + AddLengthConstraint(0, 11); + AddLengthConstraint(0, 5); + AddLengthConstraint(2, 3); + AddLengthConstraint(3, 4); + AddLengthConstraint(5, 6); + AddLengthConstraint(6, 7); + AddLengthConstraint(2, 5); + AddLengthConstraint(2, 11); + AddLengthConstraint(5, 8); + AddLengthConstraint(5, 11); + AddLengthConstraint(8, 11); + AddLengthConstraint(8, 9); + AddLengthConstraint(9, 10); + AddLengthConstraint(11, 12); + AddLengthConstraint(12, 13); + AddLengthConstraint(14, 0); + AddLengthConstraint(14, 2); + AddLengthConstraint(14, 5); + AddLengthConstraint(14, 8); + AddLengthConstraint(14, 11); + AddMinLengthConstraint(1, 8, x14_lengthConstraints[2].GetLength()); + AddMinLengthConstraint(1, 11, x14_lengthConstraints[3].GetLength()); + AddMinLengthConstraint(4, 2, x14_lengthConstraints[5].GetLength()); + AddMinLengthConstraint(7, 5, x14_lengthConstraints[7].GetLength()); + AddMinLengthConstraint(3, 5, 0.5f * x14_lengthConstraints[5].GetLength() + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(6, 2, 0.5f * x14_lengthConstraints[7].GetLength() + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(4, 5, 0.5f * x14_lengthConstraints[5].GetLength() + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(7, 2, 0.5f * x14_lengthConstraints[7].GetLength() + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(10, 8, x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(11, 11, x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(9, 2, 0.707f * x14_lengthConstraints[15].GetLength() + x14_lengthConstraints[10].GetLength()); + AddMinLengthConstraint(12, 5, 0.707f * x14_lengthConstraints[17].GetLength() + x14_lengthConstraints[13].GetLength()); + AddMinLengthConstraint(9, 11, x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(12, 8, x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(10, 0, x14_lengthConstraints[2].GetLength() + x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(13, 0, x14_lengthConstraints[3].GetLength() + x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(9, 12, 0.5f * x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(10, 12, 0.5f * x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(13, 9, 0.5f * x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(10, 13, 0.5f * x14_lengthConstraints[14].GetLength()); + AddJointConstraint(8, 2, 5, 8, 9, 10); + AddJointConstraint(11, 2, 5, 11, 12, 13); + AddJointConstraint(2, 11, 5, 2, 3, 4); + AddJointConstraint(5, 2, 8, 5, 6, 7); +} + CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) @@ -88,8 +161,8 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f), EBoneTrackingFlags::None) , x7ec_burstFire(skBursts.data(), 0) { - CModelData* modelData = GetModelData(); - CAnimData* animData = modelData->GetAnimationData(); + const CModelData* modelData = GetModelData(); + const CAnimData* animData = modelData->GetAnimationData(); x798_ = animData->GetLocatorSegId("Head_1"); x7e0_ = animData->GetLocatorSegId("L_gun_LCTR"); x864_missileSegments.push_back(animData->GetLocatorSegId("L_Missile_LCTR")); diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 24aaf422b..ba7398eb6 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -1,9 +1,11 @@ #pragma once #include "Runtime/Character/CBoneTracking.hpp" +#include "Runtime/Character/CRagDoll.hpp" #include "Runtime/Particle/CElementGen.hpp" #include "Runtime/Weapon/CBurstFire.hpp" #include "Runtime/Weapon/CProjectileInfo.hpp" +#include "Runtime/World/CAi.hpp" #include "Runtime/World/CPathFindSearch.hpp" #include "Runtime/World/CPatterned.hpp" @@ -48,10 +50,91 @@ private: CFlyingPirateData(CInputStream& in, u32 propCount); }; + class CFlyingPirateRagDoll : CRagDoll { + private: + CFlyingPirate* x6c_actor; + float x70_ = 0.f; + zeus::CVector3f x74_ = zeus::skUp; + float x80_ = 0.f; + float x84_ = 5.f; + u16 x88_; + float x8c_ = 0.f; + zeus::CVector3f x90_ = zeus::skZero3f; + u16 x9c_; + int xa0_ = 0; + zeus::CVector3f xa4_; + char xb0_; // TODO flags + + public: + CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2); + + void PreRender(const zeus::CVector3f& pos, CModelData& mData) override; + void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) override; + void Update(CStateManager& mgr, float dt, float waterTop) override; + }; + public: CFlyingPirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); + void Accept(IVisitor& visitor) override { visitor.Visit(this); } + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override; + bool AnimOver(CStateManager& mgr, float arg) override; + void CalculateRenderBounds() override; + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; + void MassiveDeath(CStateManager& mgr) override; + float GetGravityConstant() const override { return 50.f; /* TODO check flags */ } + CPathFindSearch* GetSearchPath() override { return &x6a8_pathFindSearch; } + bool IsListening() const override { return true; } + bool KnockbackWhenFrozen() const override { return false; } + bool Listen(const zeus::CVector3f& pos, EListenNoiseType type) override; + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override; + CProjectileInfo* GetProjectileInfo() override { return &x568_data.xc_projInfo1; } + void Think(float dt, CStateManager& mgr) override; + + void Attack(CStateManager& mgr, EStateMsg msg, float arg) override; + void Bounce(CStateManager& mgr, EStateMsg msg, float arg) override; + void Deactivate(CStateManager& mgr, EStateMsg msg, float arg) override; + void Dead(CStateManager& mgr, EStateMsg msg, float arg) override; + void Dodge(CStateManager& mgr, EStateMsg msg, float arg) override; + void Enraged(CStateManager& mgr, EStateMsg msg, float arg) override; + void Explode(CStateManager& mgr, EStateMsg msg, float arg) override; + void GetUp(CStateManager& mgr, EStateMsg msg, float arg) override; + void Jump(CStateManager& mgr, EStateMsg msg, float arg) override; + void KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, const CDamageInfo& info, EKnockBackType type, + bool inDeferred, float magnitude) override; + void Land(CStateManager& mgr, EStateMsg msg, float arg) override; + void Lurk(CStateManager& mgr, EStateMsg msg, float arg) override; + void PathFind(CStateManager& mgr, EStateMsg msg, float arg) override; + void Patrol(CStateManager& mgr, EStateMsg msg, float arg) override; + void ProjectileAttack(CStateManager& mgr, EStateMsg msg, float arg) override; + void Retreat(CStateManager& mgr, EStateMsg msg, float arg) override; + void TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) override; + void Taunt(CStateManager& mgr, EStateMsg msg, float arg) override; + void TurnAround(CStateManager& mgr, EStateMsg msg, float arg) override; + void Walk(CStateManager& mgr, EStateMsg msg, float arg) override; + + bool AggressionCheck(CStateManager& mgr, float arg) override; + bool Attacked(CStateManager& mgr, float arg) override; + bool CoverCheck(CStateManager& mgr, float arg) override; + bool CoverFind(CStateManager& mgr, float arg) override; + bool HearPlayer(CStateManager& mgr, float arg) override; + bool HearShot(CStateManager& mgr, float arg) override; + bool InPosition(CStateManager& mgr, float arg) override; + bool InRange(CStateManager& mgr, float arg) override; + bool Landed(CStateManager& mgr, float arg) override; + bool LineOfSight(CStateManager& mgr, float arg) override; + bool PatternOver(CStateManager& mgr, float arg) override; + bool ShotAt(CStateManager& mgr, float arg) override; + bool ShouldAttack(CStateManager& mgr, float arg) override; + bool ShouldDodge(CStateManager& mgr, float arg) override; + bool ShouldMove(CStateManager& mgr, float arg) override; + bool ShouldRetreat(CStateManager& mgr, float arg) override; + bool ShouldSpecialAttack(CStateManager& mgr, float arg) override; + bool SpotPlayer(CStateManager& mgr, float arg) override; + bool Stuck(CStateManager& mgr, float arg) override; + private: CFlyingPirateData x568_data; rstl::reserved_vector, 4> x65c_particleGenDescs; @@ -88,8 +171,20 @@ private: TUniqueId x890_ = kInvalidUniqueId; float x894_ = 1.f; float x898_ = 1.f; -// CFlyingPirateRagDoll x89c_ragDoll; TODO + std::unique_ptr x89c_ragDoll; TUniqueId x8a0_ = kInvalidUniqueId; float x8a4_ = 0.f; + + zeus::CVector3f AvoidActors(CStateManager& mgr); + bool CanFireMissiles(CStateManager& mgr); + bool CheckForProjectiles(CStateManager& mgr); + void FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos); + pas::EStepDirection GetDodgeDirection(CStateManager& mgr, float arg); + zeus::CVector3f GetTargetPos(CStateManager& mgr); + bool LineOfSightTest(CStateManager& mgr, zeus::CVector3f& pos, zeus::CVector3f& dir, CMaterialList materials); + void UpdateLandingSmoke(CStateManager& mgr, bool active); + void UpdateParticleEffects(CStateManager& mgr, float f1, bool b1); + void DeliverGetUp(); + void UpdateCantSeePlayer(CStateManager& mgr); }; } // namespace urde::MP1 diff --git a/Runtime/World/CAi.hpp b/Runtime/World/CAi.hpp index 0f739769c..6ba2be1ca 100644 --- a/Runtime/World/CAi.hpp +++ b/Runtime/World/CAi.hpp @@ -55,7 +55,7 @@ public: virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {} virtual bool CanBeShot(const CStateManager&, int) { return true; } virtual bool IsListening() const { return false; } - virtual bool Listen(const zeus::CVector3f&, EListenNoiseType) { return 0; } + virtual bool Listen(const zeus::CVector3f&, EListenNoiseType) { return false; } virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, const zeus::CVector3f& aimPos) const { diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 612eec1be..840ed78c8 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -379,6 +379,7 @@ public: bool sendCollideMsg, const zeus::CVector3f& scale); void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; + const zeus::CVector3f& GetDestPos() const { return x2e0_destPos; } void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } void UpdateAlphaDelta(float dt, CStateManager& mgr); void SetModelAlpha(float a) { x42c_color.a() = a; } From d4982270e8325570fa39dda15ba20c51ad74cac0 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 12 Mar 2020 05:41:41 -0400 Subject: [PATCH 03/16] CFlyingPirate: Start implementing methods --- Runtime/MP1/World/CFlyingPirate.cpp | 279 +++++++++++++++++++++++++++- Runtime/MP1/World/CFlyingPirate.hpp | 23 ++- Runtime/MP1/World/CSpacePirate.cpp | 10 +- 3 files changed, 297 insertions(+), 15 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index ddb5dfa8c..6f3a97806 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1,9 +1,16 @@ #include "Runtime/MP1/World/CFlyingPirate.hpp" -#include "Runtime/CSimplePool.hpp" -#include "Runtime/GameGlobalObjects.hpp" -#include "Runtime/World/CPatternedInfo.hpp" #include "Runtime/Character/CPASAnimParmData.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Runtime/CStateManager.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/Graphics/CBooRenderer.hpp" +#include "Runtime/Weapon/CGameProjectile.hpp" +#include "Runtime/World/CPatternedInfo.hpp" +#include "Runtime/World/CPlayer.hpp" +#include "Runtime/World/CScriptCoverPoint.hpp" +#include "Runtime/World/CTeamAiMgr.hpp" +#include "Runtime/World/CWorld.hpp" namespace urde::MP1 { namespace { @@ -178,4 +185,270 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity } x460_knockBackController.SetLocomotionDuringElectrocution(true); } + +void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Alert) { + if (GetActive()) { + x400_24_hitByPlayerProjectile = true; // ? + } + } else if (msg == EScriptObjectMessage::Activate) { + AddToTeam(mgr); + } else if (msg == EScriptObjectMessage::Deleted) { + RemoveFromTeam(mgr); + } + CPatterned::AcceptScriptMsg(msg, uid, mgr); + switch (msg) { + case EScriptObjectMessage::SetToZero: + x6a2_28_ = true; + break; + case EScriptObjectMessage::Start: + x6a1_31_ = false; + break; + case EScriptObjectMessage::Stop: + x6a1_31_ = true; + break; + case EScriptObjectMessage::OnFloor: + x7ec_burstFire.SetBurstType(2); + break; + case EScriptObjectMessage::Falling: + if (x450_bodyController->GetPercentageFrozen() == 0.f && !x400_28_pendingMassiveDeath && !x6a1_30_) { + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); + } + break; + case EScriptObjectMessage::Registered: + x86c_ = x568_data.xc0_ * mgr.GetActiveRandom()->Float() + x568_data.xbc_; + break; + case EScriptObjectMessage::InitializedInArea: + for (const auto& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Retreat) { + if (TCastToPtr cover = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + cover->Reserve(x8_uid); + } + } else if (conn.x0_state == EScriptObjectState::Patrol && conn.x4_msg == EScriptObjectMessage::Follow) { + x6a0_27_ = true; + } else if (conn.x0_state == EScriptObjectState::Attack && conn.x4_msg == EScriptObjectMessage::Action) { + x85c_ = mgr.GetIdForScript(conn.x8_objId); + } + } + x6a8_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetPostConstructed()->x10bc_pathArea); + if (x30_24_active) { + AddToTeam(mgr); + } + UpdateParticleEffects(mgr, 0.f, x6a0_24_); + GetModelData()->GetAnimationData()->SetParticleEffectState("s_Eyes", true, mgr); + break; + case EScriptObjectMessage::Jumped: + if (CScriptCoverPoint* cover = GetCoverPoint(mgr, x6a4_id1)) { + x328_25_verticalMovement = false; + SetMomentumWR({0.f, 0.f, -xe8_mass * GetGravityConstant()}); + AddMaterial(EMaterialTypes::GroundCollider, mgr); + SetDestPos(cover->GetTranslation()); + const zeus::CVector3f& dist = cover->GetTranslation() - GetTranslation(); + if (dist.z() < 0.f) { + zeus::CVector3f velocity = GetVelocity(); + const float gravity = GetGravityConstant(); + float fVar1 = (2.f * gravity) * dist.z() - (velocity.z() * velocity.z()); + float fVar2 = -fVar1; + float fVar3 = 0.f; + if (0.f != -fVar1) { + fVar3 = fVar2 * (1.f / std::sqrt(fVar2)); + } + float dVar9 = (-velocity.z() + fVar3) / gravity; + if (0.f < dVar9) { + zeus::CVector2f dist2f(dist.x(), dist.y()); + const zeus::CVector2f& normal = dist2f.normalized(); + const float mag = dist2f.magnitude(); + velocity.x() = (mag / dVar9) * normal.x(); + velocity.y() = (mag / dVar9) * normal.y(); + SetVelocityWR(velocity); + + x870_.zeroOut(); + x87c_.zeroOut(); + x898_ = 1.f; + } + } + } + break; + default: + break; + } +} + +void CFlyingPirate::AddToTeam(CStateManager& mgr) { + if (x890_teamAiMgr == kInvalidUniqueId) { + x890_teamAiMgr = CTeamAiMgr::GetTeamAiMgr(*this, mgr); + } + if (x890_teamAiMgr != kInvalidUniqueId) { + if (TCastToPtr team = mgr.ObjectById(x890_teamAiMgr)) { + team->AssignTeamAiRole(*this, CTeamAiRole::ETeamAiRole::Melee, CTeamAiRole::ETeamAiRole::Ranged, + CTeamAiRole::ETeamAiRole::Invalid); + } + } +} + +void CFlyingPirate::RemoveFromTeam(CStateManager& mgr) { + if (x890_teamAiMgr != kInvalidUniqueId) { + if (TCastToPtr team = mgr.ObjectById(x890_teamAiMgr)) { + if (team->IsPartOfTeam(GetUniqueId())) { + team->RemoveTeamAiRole(GetUniqueId()); + x890_teamAiMgr = kInvalidUniqueId; + } + } + } +} + +void CFlyingPirate::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + for (const auto& gen : x684_particleGens) { + if (frustum.aabbFrustumTest(GetBoundingBox())) { + g_Renderer->AddParticleGen(*gen); + } + } + CPatterned::AddToRenderer(frustum, mgr); +} + +bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float arg) { return x6a2_24_; } + +bool CFlyingPirate::AnimOver(CStateManager& mgr, float arg) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Death) { + return true; + } else { + return CPatterned::AnimOver(mgr, arg); + } +} + +void CFlyingPirate::Attack(CStateManager& mgr, EStateMsg msg, float arg) { + switch (msg) { + case EStateMsg::Activate: + x32c_animState = EAnimState::Ready; + if (!x6a2_25_) { + float fVar1; + if (3.f <= x858_) { + fVar1 = x568_data.xe8_; + } else { + fVar1 = 2.f * x568_data.xe8_; + } + x6a2_24_ = mgr.GetActiveRandom()->Range(0.f, 100.f) < fVar1; + x6a2_25_ = true; + } + break; + case EStateMsg::Update: + TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 1); + x450_bodyController->FaceDirection((mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized(), arg); + DeliverGetUp(); + UpdateCantSeePlayer(mgr); + break; + case EStateMsg::Deactivate: + x32c_animState = EAnimState::NotReady; + x6a2_24_ = false; + break; + default: + break; + } +} + +bool CFlyingPirate::Attacked(CStateManager& mgr, float arg) { return x854_ < (arg != 0.f ? arg : 0.5f); } + +zeus::CVector3f CFlyingPirate::AvoidActors(CStateManager& mgr) { + const zeus::CVector3f& origin = GetTranslation(); + zeus::CAABox box(origin - 8.f, origin + 8.f); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, box, CMaterialFilter::MakeInclude(EMaterialTypes::CameraPassthrough), this); + + zeus::CVector3f ret; + for (const auto& id : nearList) { + if (TCastToConstPtr actor = mgr.GetObjectById(id)) { + ret += x45c_steeringBehaviors.Separation(*this, actor->GetTranslation(), 10.f); + } + } + const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); + ret += x45c_steeringBehaviors.Separation(*this, {playerPos.x(), playerPos.y(), origin.z()}, 20.f); + return ret; +} + +void CFlyingPirate::Bounce(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x8_uid, x890_teamAiMgr, true); + } else if (msg == EStateMsg::Update) { + switch (x450_bodyController->GetCurrentStateId()) { + case pas::EAnimationState::Locomotion: + x330_stateMachineState.SetCodeTrigger(); + break; + case pas::EAnimationState::LieOnGround: + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero)); + break; + case pas::EAnimationState::Hurled: + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); + x328_25_verticalMovement = true; + break; + default: + break; + } + } +} + +void CFlyingPirate::CalculateRenderBounds() { + if (!x89c_ragDoll || !x89c_ragDoll->IsPrimed()) { + CActor::CalculateRenderBounds(); + } else { + const zeus::CAABox& bounds = x89c_ragDoll->CalculateRenderBounds(); + const zeus::CVector3f& scale = 0.25f * GetModelData()->GetScale(); + x9c_renderBounds = {bounds.min - scale, bounds.max + scale}; + } +} + +bool CFlyingPirate::CanFireMissiles(CStateManager& mgr) { + for (const auto& seg : x864_missileSegments) { + const zeus::CTransform& xf = GetLctrTransform(seg); + // TODO is this right? + const zeus::CVector3f& pos = xf.origin + (3.f * zeus::CVector3f(xf.basis[0][1], xf.basis[0][2], xf.basis[0][3])); + CMaterialList matList(EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough); + if (!LineOfSightTest(mgr, xf.origin, pos, matList) || !LineOfSightTest(mgr, pos, GetTargetPos(mgr), matList)) { + x6a1_28_ = true; + return false; + } + } + return true; +} + +void CFlyingPirate::CheckForProjectiles(CStateManager& mgr) { + if (!x6a0_29_) + return; + + const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); + zeus::CAABox box(playerPos - 5.f, playerPos + 5.f); + x6a0_30_ = false; + + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, box, CMaterialFilter::MakeInclude(EMaterialTypes::Projectile), this); + for (const auto& id : nearList) { + if (TCastToConstPtr proj = mgr.GetObjectById(id)) { + zeus::CVector3f dist = GetBoundingBox().center() - proj->GetTranslation(); + if (dist.isMagnitudeSafe()) { + if (GetTranslation().dot(dist) < 0.f) { + dist.normalize(); + zeus::CVector3f nv = proj->GetTranslation() - proj->GetPreviousPos(); + if (!nv.isMagnitudeSafe()) { + nv.normalize(); + if (0.939f < nv.dot(dist)) { + x6a0_30_ = true; + } + } + } + } else { + x6a0_30_ = true; + } + if (x6a0_30_) + break; + } + } + x6a0_29_ = false; +} + +bool CFlyingPirate::CoverCheck(CStateManager& mgr, float arg) { + if (0.f < x888_) + return false; + x888_ = 10.f; + return mgr.GetActiveRandom()->Range(0.f, 100.f) < x568_data.xcc_; +} + } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index ba7398eb6..68efec040 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -50,7 +50,7 @@ private: CFlyingPirateData(CInputStream& in, u32 propCount); }; - class CFlyingPirateRagDoll : CRagDoll { + class CFlyingPirateRagDoll : public CRagDoll { private: CFlyingPirate* x6c_actor; float x70_ = 0.f; @@ -139,9 +139,16 @@ private: CFlyingPirateData x568_data; rstl::reserved_vector, 4> x65c_particleGenDescs; rstl::reserved_vector, 16> x684_particleGens; - char x6a0_flags1; // TODO - char x6a1_flags2; // TODO - char x6a2_flags3; // TODO + bool x6a0_24_ : 1; + bool x6a0_27_ : 1; + bool x6a0_29_ : 1; + bool x6a0_30_ : 1; + bool x6a1_28_ : 1; + bool x6a1_30_ : 1; + bool x6a1_31_ : 1; + bool x6a2_24_ : 1; + bool x6a2_25_ : 1; + bool x6a2_28_ : 1; TUniqueId x6a4_id1 = kInvalidUniqueId; TUniqueId x6a6_id2 = kInvalidUniqueId; CPathFindSearch x6a8_pathFindSearch; @@ -168,7 +175,7 @@ private: zeus::CVector3f x87c_ = zeus::skZero3f; float x888_ = 10.f; float x88c_ = 3.f; - TUniqueId x890_ = kInvalidUniqueId; + TUniqueId x890_teamAiMgr = kInvalidUniqueId; float x894_ = 1.f; float x898_ = 1.f; std::unique_ptr x89c_ragDoll; @@ -177,14 +184,16 @@ private: zeus::CVector3f AvoidActors(CStateManager& mgr); bool CanFireMissiles(CStateManager& mgr); - bool CheckForProjectiles(CStateManager& mgr); + void CheckForProjectiles(CStateManager& mgr); void FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos); pas::EStepDirection GetDodgeDirection(CStateManager& mgr, float arg); zeus::CVector3f GetTargetPos(CStateManager& mgr); - bool LineOfSightTest(CStateManager& mgr, zeus::CVector3f& pos, zeus::CVector3f& dir, CMaterialList materials); + bool LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CVector3f& dir, CMaterialList materials); void UpdateLandingSmoke(CStateManager& mgr, bool active); void UpdateParticleEffects(CStateManager& mgr, float f1, bool b1); void DeliverGetUp(); void UpdateCantSeePlayer(CStateManager& mgr); + void AddToTeam(CStateManager& mgr); + void RemoveFromTeam(CStateManager& mgr); }; } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index 99c6535bc..e2af68c1d 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -466,20 +466,20 @@ CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityIn if (x634_29_onlyAttackInRange) x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Small); - else if (x636_24_trooper && GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) + else if (x636_24_trooper && x260_damageVulnerability.WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Large); if (!x450_bodyController->HasBodyState(pas::EAnimationState::AdditiveAim)) x634_27_melee = true; if (x636_24_trooper) { - if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) + if (x260_damageVulnerability.WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) x8cc_trooperColor = zeus::CColor(0.996f, 0.f, 0.157f, 1.f); - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Ice), false)) + else if (x260_damageVulnerability.WeaponHurts(CWeaponMode(EWeaponType::Ice), false)) x8cc_trooperColor = zeus::skWhite; - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Power), false)) + else if (x260_damageVulnerability.WeaponHurts(CWeaponMode(EWeaponType::Power), false)) x8cc_trooperColor = zeus::CColor(0.992f, 0.937f, 0.337f, 1.f); - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Wave), false)) + else if (x260_damageVulnerability.WeaponHurts(CWeaponMode(EWeaponType::Wave), false)) x8cc_trooperColor = zeus::CColor(0.776f, 0.054f, 1.f, 1.f); } From 11ea9d3aa67575ad23de39f283104c730121565c Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 12 Mar 2020 19:30:33 -0400 Subject: [PATCH 04/16] CFlyingPirate: More method implementations --- Runtime/CToken.hpp | 10 +- Runtime/MP1/World/CFlyingPirate.cpp | 169 +++++++++++++++++++++++++++- Runtime/MP1/World/CFlyingPirate.hpp | 6 +- Runtime/Weapon/CBurstFire.hpp | 4 +- Runtime/Weapon/CProjectileInfo.hpp | 4 +- 5 files changed, 177 insertions(+), 16 deletions(-) diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index 7d156928a..964313705 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -77,13 +77,13 @@ public: explicit operator bool() const { return HasReference(); } bool HasReference() const { return x0_objRef != nullptr; } - void Unlock(); + virtual void Unlock(); void Lock(); bool IsLocked() const { return x4_lockHeld; } bool IsLoaded() const; IObj* GetObj(); const IObj* GetObj() const { return const_cast(this)->GetObj(); } - CToken& operator=(const CToken& other); + virtual CToken& operator=(const CToken& other); CToken& operator=(CToken&& other); CToken() = default; CToken(const CToken& other); @@ -108,13 +108,13 @@ public: *this = CToken(GetIObjObjectFor(std::move(obj))); return this; } - T* GetObj() { + virtual T* GetObj() { TObjOwnerDerivedFromIObj* owner = static_cast*>(CToken::GetObj()); if (owner) return owner->GetObj(); return nullptr; } - const T* GetObj() const { return const_cast*>(this)->GetObj(); } + virtual const T* GetObj() const { return const_cast*>(this)->GetObj(); } T* operator->() { return GetObj(); } const T* operator->() const { return GetObj(); } T& operator*() { return *GetObj(); } @@ -136,8 +136,6 @@ public: return m_obj; } const T* GetObj() const { return const_cast*>(this)->GetObj(); } - T* operator->() { return GetObj(); } - const T* operator->() const { return GetObj(); } void Unlock() { TToken::Unlock(); m_obj = nullptr; diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 6f3a97806..e379e25a4 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1,11 +1,15 @@ #include "Runtime/MP1/World/CFlyingPirate.hpp" +#include + #include "Runtime/Character/CPASAnimParmData.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" #include "Runtime/Weapon/CGameProjectile.hpp" +#include "Runtime/Weapon/CEnergyProjectile.hpp" +#include "Runtime/World/CExplosion.hpp" #include "Runtime/World/CPatternedInfo.hpp" #include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CScriptCoverPoint.hpp" @@ -68,7 +72,7 @@ CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCo , x60_projInfo3(in.readInt32Big(), {}) , x88_(in.readFloatBig()) , x8c_(in.readFloatBig()) -, x90_particleGenDesc(g_SimplePool->GetObj({SBIG('PART'), in.readInt32Big()})) +, x90_particleGenDesc(g_SimplePool->GetObj({SBIG('PART'), CAssetId(in)})) , x9c_dInfo(in) , xb8_(in.readFloatBig()) , xbc_(in.readFloatBig()) @@ -399,10 +403,9 @@ void CFlyingPirate::CalculateRenderBounds() { bool CFlyingPirate::CanFireMissiles(CStateManager& mgr) { for (const auto& seg : x864_missileSegments) { const zeus::CTransform& xf = GetLctrTransform(seg); - // TODO is this right? - const zeus::CVector3f& pos = xf.origin + (3.f * zeus::CVector3f(xf.basis[0][1], xf.basis[0][2], xf.basis[0][3])); + const zeus::CVector3f& dir = xf.origin + (3.f * xf.frontVector()); CMaterialList matList(EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough); - if (!LineOfSightTest(mgr, xf.origin, pos, matList) || !LineOfSightTest(mgr, pos, GetTargetPos(mgr), matList)) { + if (!LineOfSightTest(mgr, xf.origin, dir, matList) || !LineOfSightTest(mgr, dir, GetTargetPos(mgr), matList)) { x6a1_28_ = true; return false; } @@ -451,4 +454,162 @@ bool CFlyingPirate::CoverCheck(CStateManager& mgr, float arg) { return mgr.GetActiveRandom()->Range(0.f, 100.f) < x568_data.xcc_; } +bool CFlyingPirate::CoverFind(CStateManager& mgr, float arg) { + float closestMag = x568_data.x0_ * x568_data.x0_; + CScriptCoverPoint* closest = nullptr; + // FIXME const weirdness with GetObjectListById + for (const auto& entity : *mgr.ObjectListById(EGameObjectList::PlatformAndDoor)) { + if (TCastToPtr cover = entity) { + if (cover->GetActive() && cover->ShouldLandHere() && !cover->GetInUse(x8_uid) && + cover->GetAreaIdAlways() == x4_areaId) { + float mag = (GetTranslation() - cover->GetTranslation()).magSquared(); + if (mag < closestMag) { + closest = cover; + closestMag = mag; + } + } + } + } + if (closest != nullptr) { + ReleaseCoverPoint(mgr, x6a4_id1); + SetCoverPoint(closest, x6a4_id1); + x6a6_id2 = x6a4_id1; + return true; + } + return false; +} + +void CFlyingPirate::Deactivate(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x401_30_pendingDeath = true; + } +} + +void CFlyingPirate::Dead(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::Dead(mgr, msg, arg); + if (msg == EStateMsg::Activate) { + x7a0_boneTracking.SetActive(false); + GetModelData()->GetAnimationData()->SetParticleEffectState("s_Eyes", false, mgr); + CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); + } +} + +void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::Ready; + if ((x84c_ = GetDodgeDirection(mgr, x850_)) == pas::EStepDirection::Invalid) { + x84c_ = (mgr.GetActiveRandom()->Next() & 0x4000) == 0 ? pas::EStepDirection::Right : pas::EStepDirection::Left; + } + UpdateParticleEffects(mgr, 1.f, true); + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryDodge, static_cast(x84c_)); + UpdateCantSeePlayer(mgr); + x898_ = std::max(1.f, 2.f - x330_stateMachineState.GetTime()); + DeliverGetUp(); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + x6a1_28_ = false; + } +} + +void CFlyingPirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::DeGenerate || type == EUserEventType::BecomeRagDoll) { + if (!x89c_ragDoll && HealthInfo(mgr)->GetHP() <= 0.f) { + x89c_ragDoll = std::make_unique(mgr, this, x568_data.xc8_sfx2, x568_data.xca_sfx3); + } + } else if (type == EUserEventType::Projectile) { + CProjectileInfo& pInfo = x6a1_26_ ? x568_data.x60_projInfo3 : x568_data.x38_projInfo2; + if (pInfo.Token().IsLoaded() && mgr.CanCreateProjectile(x8_uid, EWeaponType::AI, 16)) { + const zeus::CTransform& xf = GetLctrTransform(node.GetLocatorName()); + TUniqueId& target = x6a1_26_ ? x85c_ : x8_uid; + CEnergyProjectile* projectile = new CEnergyProjectile( + true, pInfo.Token(), EWeaponType::AI, xf, EMaterialTypes::Floor, pInfo.GetDamage(), mgr.AllocateUniqueId(), + x4_areaId, x8_uid, target, EProjectileAttrib::None, false, zeus::skOne3f, std::nullopt, -1, false); + mgr.AddObject(projectile); + if (!x6a1_26_) { + projectile->SetCameraShake( + CCameraShakeData::BuildPatternedExplodeShakeData(projectile->GetTranslation(), 0.3f, 0.2f, 50.f)); + if (x6a0_25_) { + projectile->SetMinHomingDistance(x568_data.xf0_); + } + } + } + } else { + CPatterned::DoUserAnimEvent(mgr, node, type, dt); + } +} + +void CFlyingPirate::Enraged(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg != EStateMsg::Update) + return; + + x87c_ = (arg * arg * x568_data.xc4_) * zeus::skUp; + x898_ = 1.f; + x870_ += x87c_; + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(zeus::skUp, (GetTargetPos(mgr) - GetTranslation()).normalized(), 1.f)); +} + +void CFlyingPirate::Explode(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, EMaterialTypes::GroundCollider, EMaterialTypes::Solid, + mgr); + x150_momentum.zeroOut(); + if (!x400_27_fadeToDeath) { + MassiveDeath(mgr); + } + } else if (msg == EStateMsg::Update) { + if (x330_stateMachineState.GetTime() > 0.1f) { + DeathDelete(mgr); + } + } +} + +void CFlyingPirate::MassiveDeath(CStateManager& mgr) { + CExplosion* explosion = new CExplosion( + static_cast>(x568_data.x90_particleGenDesc), mgr.AllocateUniqueId(), true, + {x4_areaId, CEntity::NullConnectionList}, "", x34_transform, 0, zeus::CVector3f(1.5f), zeus::skWhite); + mgr.AddObject(explosion); + mgr.ApplyDamageToWorld(x8_uid, *this, GetTranslation(), x568_data.x9c_dInfo, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPatternedExplodeShakeData(0.5f, 0.3f)); + CPatterned::MassiveDeath(mgr); +} + +void CFlyingPirate::FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos, float dt) { + bool projectileFired = false; + const zeus::CTransform& xf = GetLctrTransform(x7e0_); + if (x400_25_alive) { + LaunchProjectile(xf, mgr, 8, EProjectileAttrib::None, false, std::nullopt, -1, false, zeus::skOne3f); + projectileFired = true; + } else { + if (TCastToPtr actor = mgr.ObjectById(x7e8_id3)) { + zeus::CVector3f origin = actor->GetTranslation(); + const CPlayer& player = mgr.GetPlayer(); + if (x7e8_id3 == player.GetUniqueId()) { + origin = GetProjectileInfo()->PredictInterceptPos(xf.origin, player.GetAimPosition(mgr, 0.f), player, true, dt); + } + zeus::CVector3f dist = origin - xf.origin; + float mag = dist.magnitude(); + dist *= zeus::CVector3f(1.f / mag); + float fVar13 = xf.frontVector().dot(dist); + if (0.707f < fVar13 || (mag < 6.f && 0.5f < fVar13)) { + if (LineOfSightTest(mgr, xf.origin, origin, {EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough})) { + origin += x34_transform.rotate(CBurstFire::GetDistanceCompensatedError(mag, 6.f)); + LaunchProjectile(zeus::lookAt(xf.origin, origin, zeus::skUp), mgr, 8, EProjectileAttrib::None, false, + std::nullopt, -1, false, zeus::skOne3f); + projectileFired = true; + } + } + } + } + if (projectileFired) { + const std::pair& anim = x450_bodyController->GetPASDatabase().FindBestAnimation( + {24, CPASAnimParm::FromEnum(2)}, *mgr.GetActiveRandom(), -1); + if (anim.first > 0.f) { + GetModelData()->GetAnimationData()->AddAdditiveAnimation(anim.second, 1.f, false, true); + } + CSfxManager::AddEmitter(x568_data.x34_sfx1, GetTranslation(), zeus::skZero3f, true, false, 0x7f, kInvalidAreaId); + } +} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 68efec040..500966884 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -140,9 +140,11 @@ private: rstl::reserved_vector, 4> x65c_particleGenDescs; rstl::reserved_vector, 16> x684_particleGens; bool x6a0_24_ : 1; + bool x6a0_25_ : 1; bool x6a0_27_ : 1; bool x6a0_29_ : 1; bool x6a0_30_ : 1; + bool x6a1_26_ : 1; bool x6a1_28_ : 1; bool x6a1_30_ : 1; bool x6a1_31_ : 1; @@ -163,7 +165,7 @@ private: float x7e4_ = 1.f; TUniqueId x7e8_id3 = kInvalidUniqueId; CBurstFire x7ec_burstFire; - int x84c_ = -1; + pas::EStepDirection x84c_ = pas::EStepDirection::Invalid; float x850_ = 3.f; float x854_ = FLT_MAX; float x858_ = FLT_MAX; @@ -185,7 +187,7 @@ private: zeus::CVector3f AvoidActors(CStateManager& mgr); bool CanFireMissiles(CStateManager& mgr); void CheckForProjectiles(CStateManager& mgr); - void FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos); + void FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos, float dt); pas::EStepDirection GetDodgeDirection(CStateManager& mgr, float arg); zeus::CVector3f GetTargetPos(CStateManager& mgr); bool LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CVector3f& dir, CMaterialList materials); diff --git a/Runtime/Weapon/CBurstFire.hpp b/Runtime/Weapon/CBurstFire.hpp index a46bed4fd..3d426a701 100644 --- a/Runtime/Weapon/CBurstFire.hpp +++ b/Runtime/Weapon/CBurstFire.hpp @@ -44,8 +44,8 @@ public: s32 GetBurstType() const { return x0_burstType; } void Start(CStateManager& mgr); void Update(CStateManager& mgr, float dt); - zeus::CVector3f GetError(float xMag, float zMag) const; - zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const; + static zeus::CVector3f GetError(float xMag, float zMag); + static zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist); float GetMaxXError() const; float GetMaxZError() const; void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; } diff --git a/Runtime/Weapon/CProjectileInfo.hpp b/Runtime/Weapon/CProjectileInfo.hpp index 14d28c20c..8906aaf07 100644 --- a/Runtime/Weapon/CProjectileInfo.hpp +++ b/Runtime/Weapon/CProjectileInfo.hpp @@ -9,7 +9,7 @@ namespace urde { class CPlayer; class CProjectileInfo { - TToken x0_weaponDescription; + TCachedToken x0_weaponDescription; CDamageInfo xc_damageInfo; public: @@ -24,6 +24,6 @@ public: const CDamageInfo& GetDamage() const { return xc_damageInfo; } void SetDamage(const CDamageInfo& damageInfo) { xc_damageInfo = damageInfo; } - TToken& Token() { return x0_weaponDescription; } + TCachedToken& Token() { return x0_weaponDescription; } }; } // namespace urde From 13d8c3fdd14c6b37e66595ccde0717605c3a42f0 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 13 Mar 2020 04:11:17 -0400 Subject: [PATCH 05/16] CFlyingPirate: First draft almost done --- Runtime/CToken.hpp | 15 +- Runtime/Character/CAllFormatsAnimSource.hpp | 6 +- Runtime/Character/IAnimReader.hpp | 30 +- Runtime/MP1/World/CFlyingPirate.cpp | 1029 +++++++++++++++++-- Runtime/MP1/World/CFlyingPirate.hpp | 94 +- Runtime/MP1/World/CSpacePirate.hpp | 1 + Runtime/Weapon/CBurstFire.hpp | 4 +- Runtime/World/CKnockBackController.hpp | 3 +- Runtime/World/ScriptLoader.cpp | 2 +- 9 files changed, 1049 insertions(+), 135 deletions(-) diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index 964313705..ba8722d2b 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -77,13 +77,13 @@ public: explicit operator bool() const { return HasReference(); } bool HasReference() const { return x0_objRef != nullptr; } - virtual void Unlock(); + void Unlock(); void Lock(); bool IsLocked() const { return x4_lockHeld; } bool IsLoaded() const; IObj* GetObj(); const IObj* GetObj() const { return const_cast(this)->GetObj(); } - virtual CToken& operator=(const CToken& other); + CToken& operator=(const CToken& other); CToken& operator=(CToken&& other); CToken() = default; CToken(const CToken& other); @@ -101,6 +101,7 @@ public: return TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::move(obj)); } TToken() = default; + virtual ~TToken() = default; TToken(const CToken& other) : CToken(other) {} TToken(CToken&& other) : CToken(std::move(other)) {} TToken(std::unique_ptr&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {} @@ -108,6 +109,8 @@ public: *this = CToken(GetIObjObjectFor(std::move(obj))); return this; } + virtual void Unlock() { CToken::Unlock(); } + virtual void Lock() { CToken::Lock(); } virtual T* GetObj() { TObjOwnerDerivedFromIObj* owner = static_cast*>(CToken::GetObj()); if (owner) @@ -115,6 +118,10 @@ public: return nullptr; } virtual const T* GetObj() const { return const_cast*>(this)->GetObj(); } + virtual TToken& operator=(const CToken& other) { + CToken::operator=(other); + return *this; + } T* operator->() { return GetObj(); } const T* operator->() const { return GetObj(); } T& operator*() { return *GetObj(); } @@ -142,12 +149,12 @@ public: } TCachedToken& operator=(const TCachedToken& other) { - CToken::operator=(other); + TToken::operator=(other); m_obj = nullptr; return *this; } TCachedToken& operator=(const CToken& other) { - CToken::operator=(other); + TToken::operator=(other); m_obj = nullptr; return *this; } diff --git a/Runtime/Character/CAllFormatsAnimSource.hpp b/Runtime/Character/CAllFormatsAnimSource.hpp index b762a5e8c..862c7bd4f 100644 --- a/Runtime/Character/CAllFormatsAnimSource.hpp +++ b/Runtime/Character/CAllFormatsAnimSource.hpp @@ -29,9 +29,9 @@ public: CAnimFormatUnion(CInputStream& in, IObjectStore& store); ~CAnimFormatUnion(); EAnimFormat GetFormat() const { return x0_format; } - const CAnimSource& GetAsCAnimSource() const { return *reinterpret_cast(x4_storage); } - const CFBStreamedCompression& GetAsCFBStreamedCompression() const { - return *reinterpret_cast(x4_storage); + CAnimSource& GetAsCAnimSource() { return *reinterpret_cast(x4_storage); } + CFBStreamedCompression& GetAsCFBStreamedCompression() { + return *reinterpret_cast(x4_storage); } }; diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp index 3522a5ba7..1f4962182 100644 --- a/Runtime/Character/IAnimReader.hpp +++ b/Runtime/Character/IAnimReader.hpp @@ -71,31 +71,35 @@ template class TSubAnimTypeToken : public TLockedToken {}; template <> -class TSubAnimTypeToken : public TLockedToken { +class TSubAnimTypeToken : public TLockedToken { public: - TSubAnimTypeToken(const TLockedToken& token) - : TLockedToken(token) {} + TSubAnimTypeToken(const TLockedToken& token) : TLockedToken(token) {} - const CAnimSource* GetObj() const { - const CAllFormatsAnimSource* source = TLockedToken::GetObj(); + CAnimSource* GetObj() { + CAllFormatsAnimSource* source = reinterpret_cast(TLockedToken::GetObj()); return &source->GetAsCAnimSource(); } - const CAnimSource* operator->() const { return GetObj(); } - const CAnimSource& operator*() const { return *GetObj(); } + + const CAnimSource* GetObj() const { + return const_cast*>(this)->GetObj(); + } }; template <> -class TSubAnimTypeToken : public TLockedToken { +class TSubAnimTypeToken : public TLockedToken { public: TSubAnimTypeToken(const TLockedToken& token) - : TLockedToken(token) {} + : TLockedToken(token) {} - const CFBStreamedCompression* GetObj() const { - const CAllFormatsAnimSource* source = TLockedToken::GetObj(); + CFBStreamedCompression* GetObj() { + CAllFormatsAnimSource* source = + reinterpret_cast(TLockedToken::GetObj()); return &source->GetAsCFBStreamedCompression(); } - const CFBStreamedCompression* operator->() const { return GetObj(); } - const CFBStreamedCompression& operator*() const { return *GetObj(); } + + const CFBStreamedCompression* GetObj() const { + return const_cast*>(this)->GetObj(); + } }; class IAnimReader { diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index e379e25a4..391bf320b 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1,21 +1,24 @@ #include "Runtime/MP1/World/CFlyingPirate.hpp" -#include - #include "Runtime/Character/CPASAnimParmData.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Graphics/CBooRenderer.hpp" -#include "Runtime/Weapon/CGameProjectile.hpp" +#include "Runtime/MP1/World/CSpacePirate.hpp" #include "Runtime/Weapon/CEnergyProjectile.hpp" +#include "Runtime/Weapon/CGameProjectile.hpp" #include "Runtime/World/CExplosion.hpp" #include "Runtime/World/CPatternedInfo.hpp" #include "Runtime/World/CPlayer.hpp" #include "Runtime/World/CScriptCoverPoint.hpp" +#include "Runtime/World/CScriptWater.hpp" +#include "Runtime/World/CScriptWaypoint.hpp" #include "Runtime/World/CTeamAiMgr.hpp" #include "Runtime/World/CWorld.hpp" +#include + namespace urde::MP1 { namespace { constexpr std::array skBurst1{{ @@ -57,49 +60,51 @@ constexpr std::array skBursts{ }; constexpr std::array skParts{ - "s_Head", "s_R_shoulder", "s_R_elbow", "s_R_wrist", "s_L_shoulder", "s_L_elbow", "s_L_wrist", - "s_R_hip", "s_R_knee", "s_R_ankle", "s_L_hip", "s_L_knee", "s_L_ankle", "s_rocket_LCTR", + "Head_1", "R_shoulder", "R_elbow", "R_wrist", "L_shoulder", "L_elbow", "L_wrist", + "R_hip", "R_knee", "R_ankle", "L_hip", "L_knee", "L_ankle", "rocket_LCTR", }; } // namespace CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCount) -: x0_(in.readFloatBig()) -, x4_(in.readFloatBig()) -, x8_(in.readInt32Big()) -, xc_projInfo1(in) -, x34_sfx1(in.readUint16Big()) -, x38_projInfo2(in) -, x60_projInfo3(in.readInt32Big(), {}) -, x88_(in.readFloatBig()) -, x8c_(in.readFloatBig()) +: x0_maxCoverDistance(in.readFloatBig()) +, x4_hearingDistance(in.readFloatBig()) +, x8_(in.readUint32Big()) +, xc_gunProjectileInfo(in) +, x34_gunSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x38_altProjectileInfo1(in) +, x60_altProjectileInfo2(CAssetId(in), {}) +, x88_knockBackDelay(in.readFloatBig()) +, x8c_flyingHeight(in.readFloatBig()) , x90_particleGenDesc(g_SimplePool->GetObj({SBIG('PART'), CAssetId(in)})) , x9c_dInfo(in) , xb8_(in.readFloatBig()) , xbc_(in.readFloatBig()) , xc0_(in.readFloatBig()) , xc4_(in.readFloatBig()) -, xca_sfx3(in.readUint16Big()) -, xcc_(in.readFloatBig()) +, xc8_ragDollSfx1(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xca_ragDollSfx2(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xcc_coverCheckChance(in.readFloatBig()) , xd0_(in.readFloatBig()) , xd4_(in.readFloatBig()) -, xd8_(in) -, xdc_(in) -, xe0_(in) -, xe4_sfx4(in.readUint16Big()) -, xe6_sfx5(in.readUint16Big()) -, xe8_(in.readFloatBig()) +, xd8_particleGen1(in) +, xdc_particleGen2(in) +, xe0_particleGen3(in) +, xe4_knockBackSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xe6_deathSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xe8_aggressionChance(in.readFloatBig()) , xec_(in.readFloatBig()) -, xf0_(propCount < 36 ? 0.f : in.readFloatBig()) { - xc_projInfo1.Token().Lock(); - x38_projInfo2.Token().Lock(); - x60_projInfo3.Token().Lock(); +, xf0_projectileHomingDistance(propCount < 36 ? 0.f : in.readFloatBig()) { + xc_gunProjectileInfo.Token().Lock(); + x38_altProjectileInfo1.Token().Lock(); + x60_altProjectileInfo2.Token().Lock(); } CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2) : CRagDoll(-actor->GetGravityConstant(), 3.f, 8.f, 0) , x88_(w1) , x9c_(w2) -, xa4_(actor->GetDestPos() - actor->GetTranslation()) { +, xa4_(actor->GetDestPos() - actor->GetTranslation()) +, xb0_24_(false) { actor->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock, EMaterialTypes::GroundCollider, mgr); actor->HealthInfo(mgr)->SetHP(-1.f); SetNumParticles(15); @@ -162,27 +167,65 @@ CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CF AddJointConstraint(5, 2, 8, 5, 6, 7); } +void CFlyingPirate::CFlyingPirateRagDoll::PreRender(const zeus::CVector3f& pos, CModelData& mData) { + // TODO + CRagDoll::PreRender(pos, mData); +} + +void CFlyingPirate::CFlyingPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) { + // TODO + CRagDoll::Prime(mgr, xf, mData); +} + +void CFlyingPirate::CFlyingPirateRagDoll::Update(CStateManager& mgr, float dt, float waterTop) { + // TODO + CRagDoll::Update(mgr, dt, waterTop); +} + CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) : CPatterned(ECharacter::FlyingPirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium) , x568_data(in, propCount) +, x6a0_24_(x568_data.x8_ & 1) +, x6a0_25_isUnderwater(x568_data.x8_ & 0x40) +, x6a0_26_hearShot(false) +, x6a0_27_canPatrol(false) +, x6a0_28_(false) +, x6a0_29_checkForProjectiles(false) +, x6a0_30_(false) +, x6a0_31_(true) +, x6a1_24_(false) +, x6a1_25_(false) +, x6a1_26_isAttackingObject(false) +, x6a1_27_(false) +, x6a1_28_(false) +, x6a1_29_isMoving(false) +, x6a1_30_(false) +, x6a1_31_(false) +, x6a2_24_aggressive(false) +, x6a2_25_aggressionChecked(false) +, x6a2_26_jetpackActive(false) +, x6a2_27_sparksActive(false) +, x6a2_28_(false) , x6a8_pathFindSearch(nullptr, 0 /* TODO */, pInfo.GetHalfExtent(), pInfo.GetHeight(), pInfo.GetPathfindingIndex()) , x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f), EBoneTrackingFlags::None) , x7ec_burstFire(skBursts.data(), 0) { const CModelData* modelData = GetModelData(); const CAnimData* animData = modelData->GetAnimationData(); - x798_ = animData->GetLocatorSegId("Head_1"); - x7e0_ = animData->GetLocatorSegId("L_gun_LCTR"); + x798_headSegId = animData->GetLocatorSegId("Head_1"); + x7e0_gunSegId = animData->GetLocatorSegId("L_gun_LCTR"); x864_missileSegments.push_back(animData->GetLocatorSegId("L_Missile_LCTR")); x864_missileSegments.push_back(animData->GetLocatorSegId("R_Missile_LCTR")); - x850_ = modelData->GetScale().x() * GetAnimationDistance({3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1)}); - if (x568_data.xd8_.IsValid() && x568_data.xdc_.IsValid() && x568_data.xe0_.IsValid()) { - x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xd8_})); - x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xdc_})); - x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xe0_})); + x850_height = + modelData->GetScale().x() * GetAnimationDistance({3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1)}); + if (x568_data.xd8_particleGen1.IsValid() && x568_data.xdc_particleGen2.IsValid() && + x568_data.xe0_particleGen3.IsValid()) { + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xd8_particleGen1})); + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xdc_particleGen2})); + x65c_particleGenDescs.push_back(g_SimplePool->GetObj({SBIG('PART'), x568_data.xe0_particleGen3})); for (const auto& desc : x65c_particleGenDescs) { x684_particleGens.push_back(std::make_unique(desc)); } @@ -193,7 +236,7 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { if (msg == EScriptObjectMessage::Alert) { if (GetActive()) { - x400_24_hitByPlayerProjectile = true; // ? + x400_24_hitByPlayerProjectile = true; } } else if (msg == EScriptObjectMessage::Activate) { AddToTeam(mgr); @@ -229,9 +272,9 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt cover->Reserve(x8_uid); } } else if (conn.x0_state == EScriptObjectState::Patrol && conn.x4_msg == EScriptObjectMessage::Follow) { - x6a0_27_ = true; + x6a0_27_canPatrol = true; } else if (conn.x0_state == EScriptObjectState::Attack && conn.x4_msg == EScriptObjectMessage::Action) { - x85c_ = mgr.GetIdForScript(conn.x8_objId); + x85c_attackObjectId = mgr.GetIdForScript(conn.x8_objId); } } x6a8_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetPostConstructed()->x10bc_pathArea); @@ -239,10 +282,10 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt AddToTeam(mgr); } UpdateParticleEffects(mgr, 0.f, x6a0_24_); - GetModelData()->GetAnimationData()->SetParticleEffectState("s_Eyes", true, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes", true, mgr); break; case EScriptObjectMessage::Jumped: - if (CScriptCoverPoint* cover = GetCoverPoint(mgr, x6a4_id1)) { + if (CScriptCoverPoint* cover = GetCoverPoint(mgr, x6a4_currentCoverPoint)) { x328_25_verticalMovement = false; SetMomentumWR({0.f, 0.f, -xe8_mass * GetGravityConstant()}); AddMaterial(EMaterialTypes::GroundCollider, mgr); @@ -310,7 +353,7 @@ void CFlyingPirate::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan CPatterned::AddToRenderer(frustum, mgr); } -bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float arg) { return x6a2_24_; } +bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float arg) { return x6a2_24_aggressive; } bool CFlyingPirate::AnimOver(CStateManager& mgr, float arg) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Death) { @@ -324,15 +367,15 @@ void CFlyingPirate::Attack(CStateManager& mgr, EStateMsg msg, float arg) { switch (msg) { case EStateMsg::Activate: x32c_animState = EAnimState::Ready; - if (!x6a2_25_) { + if (!x6a2_25_aggressionChecked) { float fVar1; if (3.f <= x858_) { - fVar1 = x568_data.xe8_; + fVar1 = x568_data.xe8_aggressionChance; } else { - fVar1 = 2.f * x568_data.xe8_; + fVar1 = 2.f * x568_data.xe8_aggressionChance; } - x6a2_24_ = mgr.GetActiveRandom()->Range(0.f, 100.f) < fVar1; - x6a2_25_ = true; + x6a2_24_aggressive = mgr.GetActiveRandom()->Range(0.f, 100.f) < fVar1; + x6a2_25_aggressionChecked = true; } break; case EStateMsg::Update: @@ -343,7 +386,7 @@ void CFlyingPirate::Attack(CStateManager& mgr, EStateMsg msg, float arg) { break; case EStateMsg::Deactivate: x32c_animState = EAnimState::NotReady; - x6a2_24_ = false; + x6a2_24_aggressive = false; break; default: break; @@ -414,7 +457,7 @@ bool CFlyingPirate::CanFireMissiles(CStateManager& mgr) { } void CFlyingPirate::CheckForProjectiles(CStateManager& mgr) { - if (!x6a0_29_) + if (!x6a0_29_checkForProjectiles) return; const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); @@ -444,18 +487,18 @@ void CFlyingPirate::CheckForProjectiles(CStateManager& mgr) { break; } } - x6a0_29_ = false; + x6a0_29_checkForProjectiles = false; } bool CFlyingPirate::CoverCheck(CStateManager& mgr, float arg) { if (0.f < x888_) return false; x888_ = 10.f; - return mgr.GetActiveRandom()->Range(0.f, 100.f) < x568_data.xcc_; + return mgr.GetActiveRandom()->Range(0.f, 100.f) < x568_data.xcc_coverCheckChance; } bool CFlyingPirate::CoverFind(CStateManager& mgr, float arg) { - float closestMag = x568_data.x0_ * x568_data.x0_; + float closestMag = x568_data.x0_maxCoverDistance * x568_data.x0_maxCoverDistance; CScriptCoverPoint* closest = nullptr; // FIXME const weirdness with GetObjectListById for (const auto& entity : *mgr.ObjectListById(EGameObjectList::PlatformAndDoor)) { @@ -471,9 +514,9 @@ bool CFlyingPirate::CoverFind(CStateManager& mgr, float arg) { } } if (closest != nullptr) { - ReleaseCoverPoint(mgr, x6a4_id1); - SetCoverPoint(closest, x6a4_id1); - x6a6_id2 = x6a4_id1; + ReleaseCoverPoint(mgr, x6a4_currentCoverPoint); + SetCoverPoint(closest, x6a4_currentCoverPoint); + x6a6_id2 = x6a4_currentCoverPoint; return true; } return false; @@ -489,7 +532,7 @@ void CFlyingPirate::Dead(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::Dead(mgr, msg, arg); if (msg == EStateMsg::Activate) { x7a0_boneTracking.SetActive(false); - GetModelData()->GetAnimationData()->SetParticleEffectState("s_Eyes", false, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes", false, mgr); CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); } } @@ -497,12 +540,13 @@ void CFlyingPirate::Dead(CStateManager& mgr, EStateMsg msg, float arg) { void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { x32c_animState = EAnimState::Ready; - if ((x84c_ = GetDodgeDirection(mgr, x850_)) == pas::EStepDirection::Invalid) { - x84c_ = (mgr.GetActiveRandom()->Next() & 0x4000) == 0 ? pas::EStepDirection::Right : pas::EStepDirection::Left; + if ((x84c_dodgeDirection = GetDodgeDirection(mgr, x850_height)) == pas::EStepDirection::Invalid) { + x84c_dodgeDirection = + (mgr.GetActiveRandom()->Next() & 0x4000) == 0 ? pas::EStepDirection::Right : pas::EStepDirection::Left; } UpdateParticleEffects(mgr, 1.f, true); } else if (msg == EStateMsg::Update) { - TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryDodge, static_cast(x84c_)); + TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryDodge, static_cast(x84c_dodgeDirection)); UpdateCantSeePlayer(mgr); x898_ = std::max(1.f, 2.f - x330_stateMachineState.GetTime()); DeliverGetUp(); @@ -515,22 +559,24 @@ void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float arg) { void CFlyingPirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { if (type == EUserEventType::DeGenerate || type == EUserEventType::BecomeRagDoll) { if (!x89c_ragDoll && HealthInfo(mgr)->GetHP() <= 0.f) { - x89c_ragDoll = std::make_unique(mgr, this, x568_data.xc8_sfx2, x568_data.xca_sfx3); + x89c_ragDoll = + std::make_unique(mgr, this, x568_data.xc8_ragDollSfx1, x568_data.xca_ragDollSfx2); } } else if (type == EUserEventType::Projectile) { - CProjectileInfo& pInfo = x6a1_26_ ? x568_data.x60_projInfo3 : x568_data.x38_projInfo2; + CProjectileInfo& pInfo = + x6a1_26_isAttackingObject ? x568_data.x60_altProjectileInfo2 : x568_data.x38_altProjectileInfo1; if (pInfo.Token().IsLoaded() && mgr.CanCreateProjectile(x8_uid, EWeaponType::AI, 16)) { const zeus::CTransform& xf = GetLctrTransform(node.GetLocatorName()); - TUniqueId& target = x6a1_26_ ? x85c_ : x8_uid; + TUniqueId& target = x6a1_26_isAttackingObject ? x85c_attackObjectId : x8_uid; CEnergyProjectile* projectile = new CEnergyProjectile( true, pInfo.Token(), EWeaponType::AI, xf, EMaterialTypes::Floor, pInfo.GetDamage(), mgr.AllocateUniqueId(), x4_areaId, x8_uid, target, EProjectileAttrib::None, false, zeus::skOne3f, std::nullopt, -1, false); mgr.AddObject(projectile); - if (!x6a1_26_) { + if (!x6a1_26_isAttackingObject) { projectile->SetCameraShake( CCameraShakeData::BuildPatternedExplodeShakeData(projectile->GetTranslation(), 0.3f, 0.2f, 50.f)); - if (x6a0_25_) { - projectile->SetMinHomingDistance(x568_data.xf0_); + if (x6a0_25_isUnderwater) { + projectile->SetMinHomingDistance(x568_data.xf0_projectileHomingDistance); } } } @@ -572,21 +618,21 @@ void CFlyingPirate::MassiveDeath(CStateManager& mgr) { mgr.AddObject(explosion); mgr.ApplyDamageToWorld(x8_uid, *this, GetTranslation(), x568_data.x9c_dInfo, CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); - mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPatternedExplodeShakeData(0.5f, 0.3f)); + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPatternedExplodeShakeData(0.5f, 0.3f), true); CPatterned::MassiveDeath(mgr); } -void CFlyingPirate::FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos, float dt) { +void CFlyingPirate::FireProjectile(CStateManager& mgr, float dt) { bool projectileFired = false; - const zeus::CTransform& xf = GetLctrTransform(x7e0_); + const zeus::CTransform& xf = GetLctrTransform(x7e0_gunSegId); if (x400_25_alive) { LaunchProjectile(xf, mgr, 8, EProjectileAttrib::None, false, std::nullopt, -1, false, zeus::skOne3f); projectileFired = true; } else { - if (TCastToPtr actor = mgr.ObjectById(x7e8_id3)) { + if (TCastToPtr actor = mgr.ObjectById(x7e8_targetId)) { zeus::CVector3f origin = actor->GetTranslation(); const CPlayer& player = mgr.GetPlayer(); - if (x7e8_id3 == player.GetUniqueId()) { + if (x7e8_targetId == player.GetUniqueId()) { origin = GetProjectileInfo()->PredictInterceptPos(xf.origin, player.GetAimPosition(mgr, 0.f), player, true, dt); } zeus::CVector3f dist = origin - xf.origin; @@ -595,7 +641,7 @@ void CFlyingPirate::FireProjectile(CStateManager& mgr, const zeus::CVector3f& po float fVar13 = xf.frontVector().dot(dist); if (0.707f < fVar13 || (mag < 6.f && 0.5f < fVar13)) { if (LineOfSightTest(mgr, xf.origin, origin, {EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough})) { - origin += x34_transform.rotate(CBurstFire::GetDistanceCompensatedError(mag, 6.f)); + origin += x34_transform.rotate(x7ec_burstFire.GetDistanceCompensatedError(mag, 6.f)); LaunchProjectile(zeus::lookAt(xf.origin, origin, zeus::skUp), mgr, 8, EProjectileAttrib::None, false, std::nullopt, -1, false, zeus::skOne3f); projectileFired = true; @@ -609,7 +655,850 @@ void CFlyingPirate::FireProjectile(CStateManager& mgr, const zeus::CVector3f& po if (anim.first > 0.f) { GetModelData()->GetAnimationData()->AddAdditiveAnimation(anim.second, 1.f, false, true); } - CSfxManager::AddEmitter(x568_data.x34_sfx1, GetTranslation(), zeus::skZero3f, true, false, 0x7f, kInvalidAreaId); + CSfxManager::AddEmitter(x568_data.x34_gunSfx, GetTranslation(), zeus::skZero3f, true, false, 0x7f, kInvalidAreaId); } } + +pas::EStepDirection CFlyingPirate::GetDodgeDirection(CStateManager& mgr, float arg) { + float argSquared = arg * arg; + bool canDodgeLeft = true; + bool canDodgeRight = true; + bool canDodgeUp = true; + bool canDodgeDown = true; + pas::EStepDirection direction = pas::EStepDirection::Invalid; + for (const auto& entity : *mgr.ObjectListById(EGameObjectList::AiWaypoint)) { + if (entity == this) + continue; + if (TCastToPtr actor = entity) { + const zeus::CVector3f& dist = actor->GetTranslation() - GetTranslation(); + float distMagSquared = dist.magSquared(); + if (distMagSquared < argSquared) { + float rightVecMag = x34_transform.rightVector().magSquared(); + if ((0.866f * distMagSquared) < rightVecMag || (0.f < rightVecMag && distMagSquared < 3.f)) { + canDodgeRight = false; + } else if (rightVecMag < 0.866f * -distMagSquared || (rightVecMag < 0.f && distMagSquared < 3.f)) { + canDodgeLeft = false; + } + float upVecMag = x34_transform.upVector().magSquared(); + if ((0.866f * distMagSquared) < upVecMag || (0.f < upVecMag && distMagSquared < 3.f)) { + canDodgeUp = false; + } else if (upVecMag < 0.866f * -distMagSquared || (0.f < upVecMag && distMagSquared < 3.f)) { + canDodgeDown = false; + } + } + } + } + + const zeus::CVector3f& center = GetBoundingBox().center(); + if (canDodgeRight) { + canDodgeRight = LineOfSightTest(mgr, center, center + (arg * x34_transform.rightVector()), {}); + } + if (canDodgeLeft) { + canDodgeLeft = LineOfSightTest(mgr, center, center - (arg * x34_transform.rightVector()), {}); + } + if (canDodgeUp) { + canDodgeUp = LineOfSightTest(mgr, center, center + (arg * x34_transform.upVector()), {}); + } + if (canDodgeDown) { + canDodgeDown = LineOfSightTest(mgr, center, center - (arg * x34_transform.upVector()), {}); + } + + if ((canDodgeLeft || canDodgeRight) && (canDodgeUp || canDodgeDown)) { + if ((mgr.GetActiveRandom()->Next() & 0x4000) == 0) { + canDodgeUp = false; + canDodgeDown = false; + } else { + canDodgeLeft = false; + canDodgeRight = false; + } + } + if (canDodgeLeft && canDodgeRight) { + if ((mgr.GetActiveRandom()->Next() & 0x4000) == 0) { + canDodgeRight = false; + } else { + canDodgeLeft = false; + } + } + if (canDodgeUp && canDodgeDown) { + const zeus::CVector3f& target = GetTargetPos(mgr); + if (target.z() - (x34_transform.origin.z() + x568_data.x8c_flyingHeight) <= 0.f) { + canDodgeUp = false; + } else { + canDodgeDown = false; + } + } + + if (canDodgeUp) { + direction = pas::EStepDirection::Up; + } else if (canDodgeDown) { + direction = pas::EStepDirection::Down; + } else if (canDodgeLeft) { + direction = pas::EStepDirection::Left; + } else if (canDodgeRight) { + direction = pas::EStepDirection::Right; + } + return direction; +} + +zeus::CVector3f CFlyingPirate::GetTargetPos(CStateManager& mgr) { + const CPlayer& player = mgr.GetPlayer(); + const TUniqueId& playerUid = player.GetUniqueId(); + if (x7e8_targetId != playerUid) { + if (TCastToPtr actor = mgr.ObjectById(x7e8_targetId)) { + if (actor->GetActive()) { + return actor->GetTranslation(); + } + } + x7a0_boneTracking.SetTarget(playerUid); + x7e8_targetId = playerUid; + } + return player.GetAimPosition(mgr, 0.f); +} + +void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::Ready; + CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); + } else if (msg == EStateMsg::Update) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround) { + // FIXME is this accurate? will always return Success + CPathFindSearch::EResult result = x6a8_pathFindSearch.Search(GetTranslation(), GetTranslation()); + if (result == CPathFindSearch::EResult::NoSourcePoint) { + x401_30_pendingDeath = true; + } + } + TryCommand(mgr, pas::EAnimationState::Getup, &CPatterned::TryGetUp, 0); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + } +} + +bool CFlyingPirate::HearPlayer(CStateManager& mgr, float arg) { + const CPlayer& player = mgr.GetPlayer(); + const float x4squared = x568_data.x4_hearingDistance * x568_data.x4_hearingDistance; + return player.GetVelocity().magSquared() > 0.1f && + (player.GetTranslation() - GetTranslation()).magSquared() < x4squared; +} + +bool CFlyingPirate::HearShot(CStateManager& mgr, float arg) { return x6a0_26_hearShot; } + +bool CFlyingPirate::InPosition(CStateManager& mgr, float arg) { + CScriptCoverPoint* const cover = GetCoverPoint(mgr, x6a4_currentCoverPoint); + if (cover == nullptr) { + return true; + } + const zeus::CVector3f& dist = cover->GetTranslation() - GetTranslation(); + return dist.z() < 0.f && dist.magnitude() < 4.f; +} + +bool CFlyingPirate::InRange(CStateManager& mgr, float arg) { + const CPlayer& player = mgr.GetPlayer(); + const zeus::CVector3f& playerPos = player.GetTranslation(); + return std::abs(playerPos.z()) < x2fc_minAttackRange && + playerPos.magSquared() < x300_maxAttackRange * x300_maxAttackRange; +} + +void CFlyingPirate::Jump(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + x328_25_verticalMovement = true; + x150_momentum.zeroOut(); + x888_ = 10.f; + UpdateParticleEffects(mgr, 1.f, true); + UpdateLandingSmoke(mgr, true); + x6a2_24_aggressive = x568_data.xec_ > mgr.GetActiveRandom()->Range(0.f, 100.f); + } else if (msg == EStateMsg::Deactivate) { + UpdateParticleEffects(mgr, 0.5f, true); + UpdateLandingSmoke(mgr, false); + x6a2_24_aggressive = false; + } +} + +void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, const CDamageInfo& info, + EKnockBackType type, bool inDeferred, float magnitude) { + if (x400_25_alive) { + x460_knockBackController.SetSeverity(x328_25_verticalMovement ? pas::ESeverity::Zero : pas::ESeverity::One); + } else if (!IsOnGround()) { + const float rand = mgr.GetActiveRandom()->Range(0.f, 100.f); + if (x568_data.xb8_ <= rand) { + UpdateParticleEffects(mgr, 0.f, false); + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); + } else { + x6a1_30_ = true; + x150_momentum.zeroOut(); + } + x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::Hurled, EKnockBackAnimationState::Hurled); + x328_25_verticalMovement = false; + const TUniqueId& waypointId = GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Next); + if (waypointId != kInvalidUniqueId) { + // TODO casts and then does nothing? + } + const zeus::CVector3f& homingPosition = mgr.GetPlayer().GetHomingPosition(mgr, 0.f); + const zeus::CVector3f& homingDist = homingPosition - GetTranslation(); + zeus::CVector3f cross = homingDist.cross(zeus::skUp); + if (zeus::close_enough(cross, zeus::skZero3f, 1.0E-4f)) { + cross = homingDist.cross(zeus::skForward); + } + SetDestPos(homingPosition + (homingDist.y() * cross.normalized())); + x7a0_boneTracking.SetActive(false); + } + CPatterned::KnockBack(pos, mgr, info, type, inDeferred, magnitude); + if (x460_knockBackController.GetActiveParms().x0_animState == EKnockBackAnimationState::Hurled) { + if (x400_25_alive) { + if (!x450_bodyController->IsFrozen()) { + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "GetUpNow"); + x330_stateMachineState.SetDelay(x568_data.x88_knockBackDelay); + } + x6a1_28_ = false; + x328_25_verticalMovement = false; + // FIXME 0x7f to volume + CSfxManager::AddEmitter(x568_data.xe4_knockBackSfx, GetTranslation(), zeus::skZero3f, 1.f, true, false, 0x7f, + kInvalidAreaId); + } else { + // FIXME 0x7f to volume + CSfxManager::AddEmitter(x568_data.xe6_deathSfx, GetTranslation(), zeus::skZero3f, 1.f, true, false, 0x7f, + kInvalidAreaId); + if (x400_27_fadeToDeath) { + x6a1_30_ = false; + UpdateParticleEffects(mgr, 0.f, false); + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); + } + } + } +} + +void CFlyingPirate::Land(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::Ready; + UpdateLandingSmoke(mgr, true); + UpdateParticleEffects(mgr, 1.f, true); + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::Jump, &CPatterned::TryJump, 0); + if (x32c_animState == EAnimState::Repeat) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + } + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + UpdateLandingSmoke(mgr, false); + UpdateParticleEffects(mgr, 0.f, false); + } +} + +bool CFlyingPirate::Landed(CStateManager& mgr, float arg) { + return x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround; +} + +bool CFlyingPirate::LineOfSight(CStateManager& mgr, float arg) { return !x6a0_31_; } + +bool CFlyingPirate::LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& start, const zeus::CVector3f& end, + CMaterialList exclude) { + return mgr.RayCollideWorld(start, end, CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, exclude), this); +} + +bool CFlyingPirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) { + bool ret = false; + if (x400_25_alive) { + float x4Squared = x568_data.x4_hearingDistance * x568_data.x4_hearingDistance; + const zeus::CVector3f& dist = pos - GetTranslation(); + if (dist.magSquared() < x4Squared && (x3c0_detectionHeightRange == 0.f || (dist.z() * dist.z() < x4Squared))) { + ret = true; + x6a0_26_hearShot = true; + } + if (type == EListenNoiseType::PlayerFire) { + x6a0_29_checkForProjectiles = true; + } + } + return ret; +} + +void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + ReleaseCoverPoint(mgr, x6a4_currentCoverPoint); + x6a0_31_ = true; + x7d8_ = 0.f; + x7dc_ = 0; + CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); + x330_stateMachineState.SetDelay(0.f); + UpdateParticleEffects(mgr, 0.f, true); + x6a2_25_aggressionChecked = false; + } else if (msg == EStateMsg::Update) { + UpdateCantSeePlayer(mgr); + if (x32c_animState != EAnimState::NotReady) { + TryCommand(mgr, pas::EAnimationState::Turn, &CPatterned::TryTurn, 0); + } + if (x32c_animState != EAnimState::Repeat) { + x2e0_destPos = GetTargetPos(mgr); + if (x34_transform.frontVector().dot((x2e0_destPos - GetTranslation()).normalized()) < 0.8f) { + x32c_animState = EAnimState::Ready; + } + } + } else if (msg == EStateMsg::Deactivate) { + x6a1_25_ = false; + x6a1_28_ = false; + x32c_animState = EAnimState::NotReady; + } +} + +void CFlyingPirate::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + zeus::CVector3f target = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + if (!x6a1_29_isMoving) { + if (const CScriptCoverPoint* const cover = GetCoverPoint(mgr, x6a4_currentCoverPoint)) { + target = cover->GetTranslation(); + } + } else { + target = x2e0_destPos; + } + CPathFindSearch* search = GetSearchPath(); + CPathFindSearch::EResult result = search->Search(GetTranslation(), target); + if (result != CPathFindSearch::EResult::Success && + (result == CPathFindSearch::EResult::NoDestPoint || result == CPathFindSearch::EResult::NoPath)) { + result = search->FindClosestReachablePoint(GetTranslation(), target); + if (result == CPathFindSearch::EResult::Success) { + search->Search(GetTranslation(), target); + } + } + UpdateParticleEffects(mgr, 0.5f, true); + } else if (msg == EStateMsg::Update) { + zeus::CVector3f move = zeus::skZero3f; + CPathFindSearch* search = GetSearchPath(); + if (search->GetResult() == CPathFindSearch::EResult::Success && + search->GetCurrentWaypoint() < search->GetWaypoints().size() - 1) { + zeus::CVector3f out = GetTranslation(); + const zeus::CVector3f& front = out + x34_transform.frontVector(); + search->GetSplinePointWithLookahead(out, front, 3.f); + if (search->SegmentOver(out)) { + search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); + } + move = front - GetTranslation(); + if (move.canBeNormalized()) { + move.normalize(); + } + } + move += 3.f * AvoidActors(mgr); + if (move.canBeNormalized()) { + move.normalize(); + } + + float fVar1 = 1.f; + if (x858_ < 2.f) { + fVar1 = 4.f; + } + float fVar2 = 1.5f * fVar1; + fVar1 = arg * (arg * (fVar1 * x568_data.xc4_)); + x87c_ = fVar1 * move; + x898_ = fVar2; + x870_ += x87c_; + + const zeus::CVector3f& face = (GetTargetPos(mgr) - GetTranslation()).normalized(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, face, 1.f)); + UpdateCantSeePlayer(mgr); + } else if (msg == EStateMsg::Deactivate) { + x6a1_29_isMoving = false; + } +} + +void CFlyingPirate::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { + if (!x6a0_27_canPatrol) + return; + + CPatterned::Patrol(mgr, msg, arg); + if (msg == EStateMsg::Activate) { + x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::FullSpeed); + x8a0_patrolTarget = x2dc_destObj; + x8a4_ = 0.f; + } else if (msg == EStateMsg::Update) { + if (x8a0_patrolTarget != x2dc_destObj) { + x8a0_patrolTarget = x2dc_destObj; + x8a4_ = 0.f; + } + if (x2d8_patrolState == EPatrolState::Patrol) { + float f78 = x3b0_moveSpeed * x568_data.xc4_; + x8a4_ = std::min(f78, arg * f78 + x8a4_); + x87c_ = (arg * x8a4_ * arg) * (x2e0_destPos - GetTranslation()).normalized(); + x898_ = 1.5f * x3b0_moveSpeed; + x870_ += x87c_; + } + if (x30c_behaviourOrient == EBehaviourOrient::Constant) { + x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); + } + UpdateCantSeePlayer(mgr); + } else if (msg == EStateMsg::Deactivate) { + x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::Normal); + } +} + +bool CFlyingPirate::PatternOver(CStateManager& mgr, float arg) { return x2dc_destObj == kInvalidUniqueId; } + +void CFlyingPirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CModelData* modelData = GetModelData(); + if (x89c_ragDoll && x89c_ragDoll->IsPrimed()) { + x89c_ragDoll->PreRender(GetTranslation(), *modelData); + } + CPatterned::PreRender(mgr, frustum); + x7a0_boneTracking.PreRender(mgr, *modelData->GetAnimationData(), GetTransform(), modelData->GetScale(), + *x450_bodyController); +} + +void CFlyingPirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x6a1_26_isAttackingObject = true; + x32c_animState = EAnimState::Ready; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0); + DeliverGetUp(); + } else if (msg == EStateMsg::Deactivate) { + x6a1_26_isAttackingObject = false; + x32c_animState = EAnimState::NotReady; + } +} + +void CFlyingPirate::Retreat(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + const zeus::CVector3f& origin = GetTranslation(); + const zeus::CVector3f& playerOrigin = mgr.GetPlayer().GetTranslation(); + const zeus::CVector3f& dist = (playerOrigin - origin).normalized(); + zeus::CVector3f target{ + origin.x() - x2fc_minAttackRange * dist.x(), + origin.y() - x2fc_minAttackRange * dist.y(), + playerOrigin.z() + x568_data.x8c_flyingHeight, + }; + CPathFindSearch* const search = GetSearchPath(); + if (search->OnPath(target) == CPathFindSearch::EResult::NoSourcePoint) { + search->FindClosestReachablePoint(origin, target); + target.z() += x568_data.x8c_flyingHeight; + if ((playerOrigin - target).magSquared() < 0.25f * x2fc_minAttackRange * x2fc_minAttackRange) { + target.z() -= x568_data.x8c_flyingHeight; // can just subtract instead of recreating dist/target + if (search->OnPath(target) == CPathFindSearch::EResult::NoSourcePoint) { + search->FindClosestReachablePoint(origin, target); + target.z() += x568_data.x8c_flyingHeight; + } + } + } + search->Search(origin, target); + UpdateParticleEffects(mgr, 0.5f, true); + } else if (msg == EStateMsg::Update) { + zeus::CVector3f move = zeus::skZero3f; + CPathFindSearch* const search = GetSearchPath(); + if (search->GetCurrentWaypoint() < search->GetWaypoints().size() - 1) { + const zeus::CVector3f& origin = GetTranslation(); + zeus::CVector3f out = origin + x34_transform.frontVector(); + search->GetSplinePointWithLookahead(out, origin, 3.f); + if (search->SegmentOver(out)) { + search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); + } + move = out - origin; + if (move.canBeNormalized()) { + move.normalize(); + } + } + move += 3.f * AvoidActors(mgr); + if (move.canBeNormalized()) { + move.normalize(); + } + + float fVar1 = 1.f; + if (x858_ < 2.f) { + fVar1 = 4.f; + } + float fVar2 = 1.5f * fVar1; + fVar1 = arg * (arg * (fVar1 * x568_data.xc4_)); + x87c_ = fVar1 * move; + x898_ = fVar2; + x870_ += x87c_; + + const zeus::CVector3f& face = (GetTargetPos(mgr) - GetTranslation()).normalized(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, face, 1.f)); + UpdateCantSeePlayer(mgr); + } +} + +bool CFlyingPirate::ShotAt(CStateManager& mgr, float arg) { return x858_ < (arg != 0.f ? arg : 0.5f); } + +bool CFlyingPirate::ShouldAttack(CStateManager& mgr, float arg) { + CTeamAiRole* const role = CTeamAiMgr::GetTeamAiRole(mgr, x890_teamAiMgr, x8_uid); + const CPlayer& player = mgr.GetPlayer(); + if ((role == nullptr || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged) && + x7e8_targetId == player.GetUniqueId() && (x86c_ <= 0.f || x854_ < 1.f) && CanFireMissiles(mgr)) { + const zeus::CVector3f& dist = player.GetTranslation() - GetTranslation(); + if (dist.z() * dist.z() < dist.y() * dist.y() + dist.x() * dist.x()) { + if (x890_teamAiMgr != kInvalidUniqueId) { + if (!CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid)) { + return false; + } + } + x86c_ = x568_data.xc0_ * mgr.GetActiveRandom()->Float() + x568_data.xbc_; + return true; + } + } + return false; +} + +bool CFlyingPirate::ShouldDodge(CStateManager& mgr, float arg) { + if (x6a1_28_ || x6a1_25_) + return false; + return 0.f < (GetTargetPos(mgr) - x34_transform.origin).dot(x34_transform.frontVector()) && + (x854_ < 0.33f || (x858_ < 0.33f && x7d8_ < 0.5f)); +} + +bool CFlyingPirate::ShouldMove(CStateManager& mgr, float arg) { + const CPlayer& player = mgr.GetPlayer(); + const zeus::CVector3f& origin = GetTranslation(); + const zeus::CVector3f& playerOrigin = player.GetTranslation(); + const zeus::CVector3f& dist = origin - playerOrigin; + + CRandom16* activeRandom = mgr.GetActiveRandom(); + float rand = activeRandom->Float(); + if (0.5f <= rand) { + rand = activeRandom->Range(15.f, 25.f); + } else { + rand = activeRandom->Range(-25.f, -15.f); + } + + const zeus::CVector3f& cross = dist.cross(zeus::skUp).normalized(); + SetDestPos({ + origin.x() + (rand * cross.x()), + origin.y() + (rand * cross.y()), + playerOrigin.z() + x568_data.x8c_flyingHeight, + }); + x6a1_29_isMoving = true; + return true; +} + +bool CFlyingPirate::ShouldRetreat(CStateManager& mgr, float arg) { + if (!x6a2_28_) + return false; + + TUniqueId id = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); + TCastToPtr waypoint = mgr.ObjectById(id); + if (!waypoint) { + id = GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Follow); + waypoint = mgr.ObjectById(id); + } + if (waypoint) { + x6a2_28_ = false; + x2dc_destObj = id; + SetDestPos(waypoint->GetTranslation()); + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + x6a1_29_isMoving = true; + x6a0_26_hearShot = false; + x6a0_24_ = false; + x400_24_hitByPlayerProjectile = false; + return true; + } + return false; +} + +bool CFlyingPirate::ShouldSpecialAttack(CStateManager& mgr, float arg) { + if (x3fc_flavor != EFlavorType::One || x85c_attackObjectId == kInvalidUniqueId || x860_ > 0.f) + return false; + + x860_ = 15.f * mgr.GetActiveRandom()->Float() + 15.f; + if (!mgr.GetPlayer().CheckOrbitDisableSourceList()) { + if (TCastToPtr actor = mgr.ObjectById(x85c_attackObjectId)) { + if (x890_teamAiMgr != kInvalidUniqueId) { + if (!CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid)) { + return false; + } + } + SetDestPos(actor->GetTranslation() + (15.f * zeus::skDown)); + x6a1_29_isMoving = true; + return true; + } + } + return false; +} + +bool CFlyingPirate::SpotPlayer(CStateManager& mgr, float arg) { + const zeus::CVector3f& dir = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetGunEyePos(); + return dir.magnitude() * x3c4_detectionAngle < dir.dot(x34_transform.frontVector()); +} + +bool CFlyingPirate::Stuck(CStateManager& mgr, float arg) { + if (x330_stateMachineState.GetTime() < 0.5f) + return false; + return CPatterned::Stuck(mgr, arg) || GetSearchPath()->GetResult() != CPathFindSearch::EResult::Success; +} + +void CFlyingPirate::UpdateLandingSmoke(CStateManager& mgr, bool active) { + if (active) { + if (x684_particleGens.size()) { + const zeus::CVector3f& origin = GetTranslation(); + float particleLevel = origin.z() - 5.f; + CScriptCoverPoint* const cover = GetCoverPoint(mgr, x6a4_currentCoverPoint); + if (cover != nullptr) { + particleLevel = cover->GetTranslation().z() - 1.f; + } + const CRayCastResult& result = mgr.RayStaticIntersection(origin, zeus::skDown, origin.z() - particleLevel, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + int idx = 1; + if (result.IsValid()) { + const CMaterialList& list = result.GetMaterial(); + if (!list.HasMaterial(EMaterialTypes::Ice) && !list.HasMaterial(EMaterialTypes::Snow)) { + if (list.HasMaterial(EMaterialTypes::Dirt) || list.HasMaterial(EMaterialTypes::MudSlow) || + list.HasMaterial(EMaterialTypes::Sand)) { + idx = 0; + } + } else { + idx = 2; + } + particleLevel = origin.z() - result.GetT(); + } + x684_particleGens[idx]->SetParticleEmission(true); + x684_particleGens[idx]->SetTranslation({origin.x(), origin.y(), particleLevel}); + } + GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke", true, mgr); + } else { + for (const auto& gen : x684_particleGens) { + gen->SetParticleEmission(false); + } + GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke", false, mgr); + } +} + +void CFlyingPirate::UpdateParticleEffects(CStateManager& mgr, float intensity, bool active) { + CAnimData* const animData = GetModelData()->GetAnimationData(); + std::string_view name = "JetPack"; + if (x6a0_25_isUnderwater) { + name = "ScubaGear"; + } + if (active != x6a2_26_jetpackActive) { + animData->SetParticleEffectState(name, active, mgr); + if (x6a0_25_isUnderwater) { + animData->SetParticleEffectState("ScubaBubbles", active, mgr); + } + x6a2_26_jetpackActive = active; + } + if (active) { + animData->SetParticleCEXTValue(name, 0, 0.75f * intensity + 2.25f); + animData->SetParticleCEXTValue(name, 1, -0.13f * intensity + -0.1f); + } + if (!x6a0_25_isUnderwater) { + const bool sparksActive = active && intensity > 0.8f; + if (sparksActive != x6a2_27_sparksActive) { + animData->SetParticleEffectState("Sparks", sparksActive, mgr); + x6a2_27_sparksActive = sparksActive; + } + } +} + +void CFlyingPirate::DeliverGetUp() { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero)); + } +} + +void CFlyingPirate::UpdateCantSeePlayer(CStateManager& mgr) { + // TODO +} + +void CFlyingPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { + // TODO + CPatterned::TargetPatrol(mgr, msg, arg); +} + +void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { + // TODO +} + +void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { + // TODO +} + +void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float arg) { + // TODO +} + +void CFlyingPirate::Think(float dt, CStateManager& mgr) { + if (!x30_24_active) + return; + + if (!x450_bodyController->GetActive()) { + x450_bodyController->Activate(mgr); + if (x6a0_24_) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + x328_25_verticalMovement = true; + } + } + bool bVar17 = mgr.GetCameraManager()->IsInCinematicCamera(); + if (!bVar17 || x6a1_24_) { + if (!bVar17 && x6a1_24_) { + AddMaterial(EMaterialTypes::AIBlock, mgr); + const CMaterialFilter& filter = GetMaterialFilter(); + CMaterialList includes = filter.GetIncludeList(); + includes.Add(EMaterialTypes::AIBlock); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(includes, filter.GetExcludeList())); + } + } else { + RemoveMaterial(EMaterialTypes::AIBlock, mgr); + const CMaterialFilter& filter = GetMaterialFilter(); + CMaterialList includes = filter.GetIncludeList(); + includes.Remove(EMaterialTypes::AIBlock); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(includes, filter.GetExcludeList())); + } + x6a1_24_ = bVar17; + + for (const auto& gen : x684_particleGens) { + gen->Update(dt); + } + + x78c_ = std::max(0.f, x78c_ - dt); + if (x400_25_alive) { + if (x6a0_30_) { + x858_ = 0.f; + x6a0_30_ = false; + } else { + x858_ += dt; + } + if (x400_24_hitByPlayerProjectile) { + x854_ = 0.f; + x400_24_hitByPlayerProjectile = false; + } else { + x854_ += dt; + } + if (!x6a0_25_isUnderwater && xc4_fluidId != kInvalidUniqueId) { + if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) { + const zeus::CAABox& box = water->GetTriggerBoundsWR(); + if (2.f + GetTranslation().z() < box.max.z()) { + x401_30_pendingDeath = true; + } + } + } + } + + if (x450_bodyController->GetPercentageFrozen() == 0.f) { + x86c_ = std::max(0.f, x86c_ - dt); + x860_ = std::max(0.f, x860_ - dt); + x888_ = std::max(0.f, x888_ - dt); + if (x6a0_31_) { + x7d8_ = 0.f; + } else { + x7d8_ += dt; + } + if (x400_25_alive) { + CheckForProjectiles(mgr); + } + if (!x6a0_25_isUnderwater) { + if (x400_25_alive) { + const CBodyState* state = x450_bodyController->GetBodyStateInfo().GetCurrentState(); + if (!state->CanShoot() || !x6a0_28_ || + x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack || x6a1_31_ || + x450_bodyController->IsElectrocuting()) { + goto LAB_801f7bb8; + } + } + if (x7ec_burstFire.GetBurstType() != -1) { + x7e4_ -= dt; + if (x7e4_ < 0.f) { + s32 newType = x7ec_burstFire.GetBurstType() & ~1; + if (!PlayerSpot(mgr, 0.f)) { + newType += 1; + } + x7ec_burstFire.SetBurstType(newType); + x7ec_burstFire.Start(mgr); + if (x400_25_alive) { + x7e4_ = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; + const zeus::CVector3f& dist = + (GetBoundingBox().center() - mgr.GetPlayer().GetAimPosition(mgr, 0.f)).normalized(); + if (dist.magSquared() < 0.9f) { + for (const auto& obj : *mgr.ObjectListById(EGameObjectList::AiWaypoint)) { + if (const CSpacePirate* pirate = CPatterned::CastTo(obj)) { + if (pirate->GetEnableAim() && pirate->GetAreaIdAlways() == x4_areaId) { + x7e4_ += 0.2f; + } + } + } + } + } else { + x7e4_ = 22050.f; + } + } + + x7ec_burstFire.Update(mgr, dt); + if (x7ec_burstFire.ShouldFire()) { + FireProjectile(mgr, dt); + if (0.f < x7ec_burstFire.GetTimeToNextShot()) { + x7ec_burstFire.SetTimeToNextShot(x568_data.xd4_ * (mgr.GetActiveRandom()->Float() - 0.5f) + x568_data.xd0_); + } + } + } + } + } + +LAB_801f7bb8: + if (x89c_ragDoll && x89c_ragDoll->IsPrimed()) { + UpdateAlphaDelta(dt, mgr); + UpdateDamageColor(dt); + } else { + if (!x400_25_alive || x450_bodyController->IsFrozen() || x450_bodyController->IsElectrocuting() || !x6a0_28_ || + x89c_ragDoll || x6a0_25_isUnderwater) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::AdditiveIdle)); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCAdditiveAimCmd()); + x450_bodyController->GetCommandMgr().DeliverAdditiveTargetVector( + x34_transform.transposeRotate(GetTargetPos(mgr) - GetTranslation())); + } + if (0.f < x870_.magSquared()) { + float fVar27 = x870_.magnitude(); + float fVar4 = 1.f / fVar27; + float fVar5 = 0.2; + if (0.f == x87c_.magSquared()) { + fVar5 = 0.2f * 3.f; + } + float mul = -(dt * fVar27 * fVar5 * fVar27 - fVar27); + x870_ = mul * fVar4 * x870_; + } + pas::EAnimationState state = x450_bodyController->GetCurrentStateId(); + if (!x400_25_alive || state == pas::EAnimationState::LoopReaction || state == pas::EAnimationState::LieOnGround || + state == pas::EAnimationState::Getup) { + x870_.zeroOut(); + x87c_.zeroOut(); + } else { + ApplyImpulseWR(xe8_mass * x870_, {}); + } + + if (auto& handle = GetSfxHandle()) { + x898_ = std::clamp(x898_, 1.f, 1.999f); + x894_ += std::clamp(x898_ - x894_, -dt, dt); + CSfxManager::PitchBend(handle, x894_); // TODO * 8192.f? + } + + x87c_.zeroOut(); + x898_ = 1.f; + CPatterned::Think(dt, mgr); + + zeus::CVector3f vf8 = x87c_; + if (vf8.canBeNormalized()) { + vf8.normalize(); + } + + float f290 = 0.333f * x87c_.magnitude(); + zeus::CVector3f v1cc = std::min(f290, 0.333f) * vf8; + const zeus::CVector3f& origin = GetTranslation(); + const zeus::CVector3f& v104 = (zeus::skUp + v1cc).normalized(); + float f26c = std::abs(zeus::CVector3f::getAngleDiff(origin, v104)); + if (f26c > 0.f) { + float f1f4 = std::min(f26c, 30.f * zeus::degToRad(dt)); // ? + float f200 = f26c - f1f4; + zeus::CVector3f v1dc = (f1f4 * v104 + (f200 * origin)).normalized(); + zeus::CVector3f v128 = x34_transform.frontVector().cross(v1dc); + zeus::CVector3f v20c = v1dc.cross(v128).normalized(); + zeus::CVector3f v128_2 = v20c.cross(v1dc); + x34_transform = zeus::CTransform(v128_2, v20c, v1dc, origin); + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; + } + + if (!x450_bodyController->IsFrozen()) { + x7a0_boneTracking.Update(dt); + } + } + + if (x89c_ragDoll) { + // TODO + } +} + } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 500966884..67c663e6e 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -17,34 +17,34 @@ public: private: class CFlyingPirateData { friend class CFlyingPirate; - float x0_; - float x4_; - int x8_; - CProjectileInfo xc_projInfo1; - u16 x34_sfx1; - CProjectileInfo x38_projInfo2; - CProjectileInfo x60_projInfo3; - float x88_; - float x8c_; + float x0_maxCoverDistance; + float x4_hearingDistance; + u32 x8_; + CProjectileInfo xc_gunProjectileInfo; + u16 x34_gunSfx; + CProjectileInfo x38_altProjectileInfo1; + CProjectileInfo x60_altProjectileInfo2; + float x88_knockBackDelay; + float x8c_flyingHeight; TCachedToken x90_particleGenDesc; CDamageInfo x9c_dInfo; float xb8_; float xbc_; float xc0_; float xc4_; - u16 xc8_sfx2; - u16 xca_sfx3; - float xcc_; + u16 xc8_ragDollSfx1; + u16 xca_ragDollSfx2; + float xcc_coverCheckChance; float xd0_; float xd4_; - CAssetId xd8_; - CAssetId xdc_; - CAssetId xe0_; - u16 xe4_sfx4; - u16 xe6_sfx5; - float xe8_; + CAssetId xd8_particleGen1; + CAssetId xdc_particleGen2; + CAssetId xe0_particleGen3; + u16 xe4_knockBackSfx; + u16 xe6_deathSfx; + float xe8_aggressionChance; float xec_; - float xf0_; + float xf0_projectileHomingDistance; public: CFlyingPirateData(CInputStream& in, u32 propCount); @@ -63,7 +63,7 @@ private: u16 x9c_; int xa0_ = 0; zeus::CVector3f xa4_; - char xb0_; // TODO flags + bool xb0_24_ : 1; public: CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2); @@ -84,13 +84,13 @@ public: void CalculateRenderBounds() override; void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; void MassiveDeath(CStateManager& mgr) override; - float GetGravityConstant() const override { return 50.f; /* TODO check flags */ } + float GetGravityConstant() const override { return x6a0_25_isUnderwater ? 5.f : 50.f; } CPathFindSearch* GetSearchPath() override { return &x6a8_pathFindSearch; } bool IsListening() const override { return true; } bool KnockbackWhenFrozen() const override { return false; } bool Listen(const zeus::CVector3f& pos, EListenNoiseType type) override; void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override; - CProjectileInfo* GetProjectileInfo() override { return &x568_data.xc_projInfo1; } + CProjectileInfo* GetProjectileInfo() override { return &x568_data.xc_gunProjectileInfo; } void Think(float dt, CStateManager& mgr) override; void Attack(CStateManager& mgr, EStateMsg msg, float arg) override; @@ -137,39 +137,50 @@ public: private: CFlyingPirateData x568_data; - rstl::reserved_vector, 4> x65c_particleGenDescs; - rstl::reserved_vector, 16> x684_particleGens; + rstl::reserved_vector, 3> x65c_particleGenDescs; + // was rstl::reserved_vector, 3> + rstl::reserved_vector, 3> x684_particleGens; bool x6a0_24_ : 1; - bool x6a0_25_ : 1; - bool x6a0_27_ : 1; - bool x6a0_29_ : 1; + bool x6a0_25_isUnderwater : 1; + bool x6a0_26_hearShot : 1; + bool x6a0_27_canPatrol : 1; + bool x6a0_28_ : 1; + bool x6a0_29_checkForProjectiles : 1; bool x6a0_30_ : 1; - bool x6a1_26_ : 1; + bool x6a0_31_ : 1; + bool x6a1_24_ : 1; + bool x6a1_25_ : 1; + bool x6a1_26_isAttackingObject : 1; + bool x6a1_27_ : 1; bool x6a1_28_ : 1; + bool x6a1_29_isMoving : 1; bool x6a1_30_ : 1; bool x6a1_31_ : 1; - bool x6a2_24_ : 1; - bool x6a2_25_ : 1; + bool x6a2_24_aggressive : 1; + bool x6a2_25_aggressionChecked : 1; + bool x6a2_26_jetpackActive : 1; + bool x6a2_27_sparksActive : 1; bool x6a2_28_ : 1; - TUniqueId x6a4_id1 = kInvalidUniqueId; + TUniqueId x6a4_currentCoverPoint = kInvalidUniqueId; TUniqueId x6a6_id2 = kInvalidUniqueId; CPathFindSearch x6a8_pathFindSearch; + float x78c_ = 0.f; // not initialized in constructor? int x790_ = 0; int x794_health; - CSegId x798_; + CSegId x798_headSegId; int x79c_ = -1; CBoneTracking x7a0_boneTracking; float x7d8_ = 0.f; int x7dc_ = 0; - CSegId x7e0_; + CSegId x7e0_gunSegId; float x7e4_ = 1.f; - TUniqueId x7e8_id3 = kInvalidUniqueId; + TUniqueId x7e8_targetId = kInvalidUniqueId; CBurstFire x7ec_burstFire; - pas::EStepDirection x84c_ = pas::EStepDirection::Invalid; - float x850_ = 3.f; + pas::EStepDirection x84c_dodgeDirection = pas::EStepDirection::Invalid; + float x850_height = 3.f; float x854_ = FLT_MAX; float x858_ = FLT_MAX; - TUniqueId x85c_ = kInvalidUniqueId; + TUniqueId x85c_attackObjectId = kInvalidUniqueId; float x860_ = 15.f; rstl::reserved_vector x864_missileSegments; float x86c_ = 0.f; @@ -181,18 +192,19 @@ private: float x894_ = 1.f; float x898_ = 1.f; std::unique_ptr x89c_ragDoll; - TUniqueId x8a0_ = kInvalidUniqueId; + TUniqueId x8a0_patrolTarget = kInvalidUniqueId; float x8a4_ = 0.f; zeus::CVector3f AvoidActors(CStateManager& mgr); bool CanFireMissiles(CStateManager& mgr); void CheckForProjectiles(CStateManager& mgr); - void FireProjectile(CStateManager& mgr, const zeus::CVector3f& pos, float dt); + void FireProjectile(CStateManager& mgr, float dt); pas::EStepDirection GetDodgeDirection(CStateManager& mgr, float arg); zeus::CVector3f GetTargetPos(CStateManager& mgr); - bool LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CVector3f& dir, CMaterialList materials); + bool LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& start, const zeus::CVector3f& end, + CMaterialList exclude); void UpdateLandingSmoke(CStateManager& mgr, bool active); - void UpdateParticleEffects(CStateManager& mgr, float f1, bool b1); + void UpdateParticleEffects(CStateManager& mgr, float intensity, bool active); void DeliverGetUp(); void UpdateCantSeePlayer(CStateManager& mgr); void AddToTeam(CStateManager& mgr); diff --git a/Runtime/MP1/World/CSpacePirate.hpp b/Runtime/MP1/World/CSpacePirate.hpp index e057ef107..c05f31afc 100644 --- a/Runtime/MP1/World/CSpacePirate.hpp +++ b/Runtime/MP1/World/CSpacePirate.hpp @@ -333,5 +333,6 @@ public: u8 GetModelAlphau8(const CStateManager& mgr) const override; float GetGravityConstant() const override; CProjectileInfo* GetProjectileInfo() override; + bool GetEnableAim() const { return x637_25_enableAim; } }; } // namespace urde::MP1 diff --git a/Runtime/Weapon/CBurstFire.hpp b/Runtime/Weapon/CBurstFire.hpp index 3d426a701..a46bed4fd 100644 --- a/Runtime/Weapon/CBurstFire.hpp +++ b/Runtime/Weapon/CBurstFire.hpp @@ -44,8 +44,8 @@ public: s32 GetBurstType() const { return x0_burstType; } void Start(CStateManager& mgr); void Update(CStateManager& mgr, float dt); - static zeus::CVector3f GetError(float xMag, float zMag); - static zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist); + zeus::CVector3f GetError(float xMag, float zMag) const; + zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const; float GetMaxXError() const; float GetMaxZError() const; void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; } diff --git a/Runtime/World/CKnockBackController.hpp b/Runtime/World/CKnockBackController.hpp index 3c3180832..e3f4339ac 100644 --- a/Runtime/World/CKnockBackController.hpp +++ b/Runtime/World/CKnockBackController.hpp @@ -130,6 +130,7 @@ public: void Update(float dt, CStateManager& mgr, CPatterned& parent); void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, const CDamageInfo& info, EKnockBackType type, float magnitude); + void SetSeverity(pas::ESeverity v) { x7c_severity = v; } void SetEnableFreeze(bool b) { x81_25_enableFreeze = b; } void SetEnableShock(bool b) { x81_26_enableShock = b; } void SetEnableBurn(bool b) { x81_27_enableBurn = b; } @@ -146,4 +147,4 @@ public: bool TestAvailableState(EKnockBackAnimationState s) const { return x80_availableStates.test(size_t(s)); } }; -} // namespace urde \ No newline at end of file +} // namespace urde diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 09244251f..060122f19 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -1365,7 +1365,7 @@ CEntity* ScriptLoader::LoadFlyingPirate(CStateManager& mgr, CInputStream& in, in SScaledActorHead actHead = LoadScaledActorHead(in, mgr); auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (pair.first) + if (!pair.first) return nullptr; CPatternedInfo pInfo(in, pair.second); From 1bcd0916ca540e4cfcee39291dc83de79d725012 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 13 Mar 2020 15:22:21 -0400 Subject: [PATCH 06/16] CFlyingPirate: Fixes; implement all functions --- Runtime/MP1/World/CFlyingPirate.cpp | 176 ++++++++++++++++++++-------- Runtime/MP1/World/CFlyingPirate.hpp | 6 +- 2 files changed, 133 insertions(+), 49 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 391bf320b..ac108e1ca 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -195,8 +195,8 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x6a0_28_(false) , x6a0_29_checkForProjectiles(false) , x6a0_30_(false) -, x6a0_31_(true) -, x6a1_24_(false) +, x6a0_31_canSeePlayer(true) +, x6a1_24_prevInCineCam(false) , x6a1_25_(false) , x6a1_26_isAttackingObject(false) , x6a1_27_(false) @@ -261,6 +261,7 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt if (x450_bodyController->GetPercentageFrozen() == 0.f && !x400_28_pendingMassiveDeath && !x6a1_30_) { SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); } + x7ec_burstFire.SetBurstType(0); break; case EScriptObjectMessage::Registered: x86c_ = x568_data.xc0_ * mgr.GetActiveRandom()->Float() + x568_data.xbc_; @@ -294,10 +295,9 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt if (dist.z() < 0.f) { zeus::CVector3f velocity = GetVelocity(); const float gravity = GetGravityConstant(); - float fVar1 = (2.f * gravity) * dist.z() - (velocity.z() * velocity.z()); - float fVar2 = -fVar1; + float fVar2 = -(2.f * gravity) * dist.z() - (velocity.z() * velocity.z()); float fVar3 = 0.f; - if (0.f != -fVar1) { + if (0.f != fVar2) { fVar3 = fVar2 * (1.f / std::sqrt(fVar2)); } float dVar9 = (-velocity.z() + fVar3) / gravity; @@ -382,7 +382,7 @@ void CFlyingPirate::Attack(CStateManager& mgr, EStateMsg msg, float arg) { TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 1); x450_bodyController->FaceDirection((mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized(), arg); DeliverGetUp(); - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); break; case EStateMsg::Deactivate: x32c_animState = EAnimState::NotReady; @@ -547,7 +547,7 @@ void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float arg) { UpdateParticleEffects(mgr, 1.f, true); } else if (msg == EStateMsg::Update) { TryCommand(mgr, pas::EAnimationState::Step, &CPatterned::TryDodge, static_cast(x84c_dodgeDirection)); - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); x898_ = std::max(1.f, 2.f - x330_stateMachineState.GetTime()); DeliverGetUp(); } else if (msg == EStateMsg::Deactivate) { @@ -888,7 +888,7 @@ bool CFlyingPirate::Landed(CStateManager& mgr, float arg) { return x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround; } -bool CFlyingPirate::LineOfSight(CStateManager& mgr, float arg) { return !x6a0_31_; } +bool CFlyingPirate::LineOfSight(CStateManager& mgr, float arg) { return !x6a0_31_canSeePlayer; } bool CFlyingPirate::LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& start, const zeus::CVector3f& end, CMaterialList exclude) { @@ -914,7 +914,7 @@ bool CFlyingPirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) { void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { ReleaseCoverPoint(mgr, x6a4_currentCoverPoint); - x6a0_31_ = true; + x6a0_31_canSeePlayer = true; x7d8_ = 0.f; x7dc_ = 0; CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); @@ -922,7 +922,7 @@ void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { UpdateParticleEffects(mgr, 0.f, true); x6a2_25_aggressionChecked = false; } else if (msg == EStateMsg::Update) { - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); if (x32c_animState != EAnimState::NotReady) { TryCommand(mgr, pas::EAnimationState::Turn, &CPatterned::TryTurn, 0); } @@ -992,7 +992,7 @@ void CFlyingPirate::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { const zeus::CVector3f& face = (GetTargetPos(mgr) - GetTranslation()).normalized(); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, face, 1.f)); - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); } else if (msg == EStateMsg::Deactivate) { x6a1_29_isMoving = false; } @@ -1022,7 +1022,7 @@ void CFlyingPirate::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { if (x30c_behaviourOrient == EBehaviourOrient::Constant) { x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); } - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); } else if (msg == EStateMsg::Deactivate) { x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::Normal); } @@ -1109,7 +1109,7 @@ void CFlyingPirate::Retreat(CStateManager& mgr, EStateMsg msg, float arg) { const zeus::CVector3f& face = (GetTargetPos(mgr) - GetTranslation()).normalized(); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, face, 1.f)); - UpdateCantSeePlayer(mgr); + UpdateCanSeePlayer(mgr); } } @@ -1289,25 +1289,114 @@ void CFlyingPirate::DeliverGetUp() { } } -void CFlyingPirate::UpdateCantSeePlayer(CStateManager& mgr) { - // TODO +void CFlyingPirate::UpdateCanSeePlayer(CStateManager& mgr) { + int iVar3 = x7dc_; + int iVar1 = iVar3 / 7 + (iVar3 >> 0x1f) * 7; + // x7dc % 7 == ? + if (iVar3 == (iVar1 - (iVar1 >> 0x1f)) * 7) { + bool bVar4 = true; + const zeus::CVector3f& start = GetGunEyePos() - x34_transform.rightVector(); + const zeus::CVector3f& end = GetAimPosition(mgr, 0.f); + const CMaterialList matList(EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough); + if (LineOfSightTest(mgr, start, end, matList)) { + bVar4 = !LineOfSightTest(mgr, start, end, matList); + } + x6a0_31_canSeePlayer = bVar4; + } + x7dc_++; } void CFlyingPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { - // TODO - CPatterned::TargetPatrol(mgr, msg, arg); + if (msg == EStateMsg::Activate) { + x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::Normal); + x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow); + if (x2dc_destObj != kInvalidUniqueId) { + if (TCastToPtr waypoint = mgr.ObjectById(x2dc_destObj)) { + x30c_behaviourOrient = EBehaviourOrient(waypoint->GetBehaviourOrient()); + x3b0_moveSpeed = waypoint->GetSpeed(); + } + } + x8a0_patrolTarget = x2dc_destObj; + x8a4_ = 0.f; + } else if (msg == EStateMsg::Update) { + if (x2dc_destObj != x8a0_patrolTarget) { + x8a0_patrolTarget = x2dc_destObj; + x8a4_ = 0.f; + } + if (x2d8_patrolState == EPatrolState::Patrol) { + float f80 = x3b0_moveSpeed * x568_data.xc4_; + x8a4_ = std::min(arg * f80 + x8a4_, f80); + x87c_ = (arg * x8a4_ * arg) * (x2e0_destPos - GetTranslation()).normalized(); + x898_ = 1.5f * x3b0_moveSpeed; + x870_ += x87c_; + } + if (x30c_behaviourOrient == EBehaviourOrient::Constant) { + x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); + } + UpdateCanSeePlayer(mgr); + } } void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { - // TODO + if (msg == EStateMsg::Activate) { + x6a0_28_ = true; + x7a0_boneTracking.SetActive(true); + x7a0_boneTracking.SetTarget(x8_uid); + bool foundPirate = false; + for (const auto& obj : *mgr.ObjectListById(EGameObjectList::AiWaypoint)) { + if (const CSpacePirate* const pirate = CPatterned::CastTo(obj)) { + if (pirate->GetEnableAim() && pirate->IsAlive() && pirate->GetAreaIdAlways() == x4_areaId && + (pirate->GetTranslation() - GetTranslation()).magSquared() < + x568_data.x4_hearingDistance * x568_data.x4_hearingDistance) { + foundPirate = true; + } + } + } + x79c_ = foundPirate ? 0 : 1; + if (x7e8_targetId == kInvalidUniqueId) { + x7e8_targetId = mgr.GetPlayer().GetUniqueId(); + } + } else if (msg == EStateMsg::Deactivate) { + if (x79c_ == 0) { + mgr.InformListeners(GetTranslation(), EListenNoiseType::PlayerFire); + } + } } void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { - // TODO + if (msg == EStateMsg::Activate) { + x2e0_destPos = GetTargetPos(mgr); + if (x34_transform.frontVector().dot((x2e0_destPos - GetTranslation()).normalized()) < 0.8f) { + x32c_animState = EAnimState::Ready; + } + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::Turn, &CPatterned::TryTurn, 0); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + } } void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float arg) { - // TODO + if (msg == EStateMsg::Activate) { + UpdateParticleEffects(mgr, 0.f, false); + } else if (msg == EStateMsg::Update) { + if (x32c_animState != EAnimState::Ready) { + TryCommand(mgr, pas::EAnimationState::Turn, &CPatterned::TryTurn, 0); + } + if (x32c_animState != EAnimState::Repeat) { + x2e0_destPos = GetTargetPos(mgr); + zeus::CVector3f dist = x2e0_destPos - GetTranslation(); + dist.z() = 0.f; + if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { + x32c_animState = EAnimState::Ready; + } + } + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::NotReady; + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + x328_25_verticalMovement = true; + x150_momentum.zeroOut(); + } } void CFlyingPirate::Think(float dt, CStateManager& mgr) { @@ -1321,23 +1410,20 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { x328_25_verticalMovement = true; } } - bool bVar17 = mgr.GetCameraManager()->IsInCinematicCamera(); - if (!bVar17 || x6a1_24_) { - if (!bVar17 && x6a1_24_) { - AddMaterial(EMaterialTypes::AIBlock, mgr); - const CMaterialFilter& filter = GetMaterialFilter(); - CMaterialList includes = filter.GetIncludeList(); - includes.Add(EMaterialTypes::AIBlock); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(includes, filter.GetExcludeList())); - } - } else { + + bool inCineCam = mgr.GetCameraManager()->IsInCinematicCamera(); + if (inCineCam && !x6a1_24_prevInCineCam) { RemoveMaterial(EMaterialTypes::AIBlock, mgr); - const CMaterialFilter& filter = GetMaterialFilter(); - CMaterialList includes = filter.GetIncludeList(); - includes.Remove(EMaterialTypes::AIBlock); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(includes, filter.GetExcludeList())); + CMaterialFilter filter = GetMaterialFilter(); + filter.IncludeList().Remove(EMaterialTypes::AIBlock); + SetMaterialFilter(filter); + } else if (!inCineCam && x6a1_24_prevInCineCam) { + AddMaterial(EMaterialTypes::AIBlock, mgr); + CMaterialFilter filter = GetMaterialFilter(); + filter.IncludeList().Add(EMaterialTypes::AIBlock); + SetMaterialFilter(filter); } - x6a1_24_ = bVar17; + x6a1_24_prevInCineCam = inCineCam; for (const auto& gen : x684_particleGens) { gen->Update(dt); @@ -1371,10 +1457,10 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { x86c_ = std::max(0.f, x86c_ - dt); x860_ = std::max(0.f, x860_ - dt); x888_ = std::max(0.f, x888_ - dt); - if (x6a0_31_) { - x7d8_ = 0.f; - } else { + if (x6a0_31_canSeePlayer) { x7d8_ += dt; + } else { + x7d8_ = 0.f; } if (x400_25_alive) { CheckForProjectiles(mgr); @@ -1472,20 +1558,18 @@ LAB_801f7bb8: if (vf8.canBeNormalized()) { vf8.normalize(); } - - float f290 = 0.333f * x87c_.magnitude(); - zeus::CVector3f v1cc = std::min(f290, 0.333f) * vf8; - const zeus::CVector3f& origin = GetTranslation(); - const zeus::CVector3f& v104 = (zeus::skUp + v1cc).normalized(); - float f26c = std::abs(zeus::CVector3f::getAngleDiff(origin, v104)); + zeus::CVector3f v1d0 = std::min(0.333f * x87c_.magnitude(), 0.333f) * vf8; + const zeus::CVector3f& v104 = (zeus::skUp + v1d0).normalized(); + const zeus::CVector3f& v110 = x34_transform.upVector(); + float f26c = std::abs(zeus::CVector3f::getAngleDiff(v110, v104)); if (f26c > 0.f) { float f1f4 = std::min(f26c, 30.f * zeus::degToRad(dt)); // ? float f200 = f26c - f1f4; - zeus::CVector3f v1dc = (f1f4 * v104 + (f200 * origin)).normalized(); + zeus::CVector3f v1dc = (f1f4 * v104 + (f200 * v110)).normalized(); zeus::CVector3f v128 = x34_transform.frontVector().cross(v1dc); zeus::CVector3f v20c = v1dc.cross(v128).normalized(); zeus::CVector3f v128_2 = v20c.cross(v1dc); - x34_transform = zeus::CTransform(v128_2, v20c, v1dc, origin); + x34_transform = zeus::CTransform(v128_2, v20c, v1dc, GetTranslation()); xe4_27_notInSortedLists = true; xe4_28_transformDirty = true; xe4_29_actorLightsDirty = true; diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 67c663e6e..0c1810019 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -147,8 +147,8 @@ private: bool x6a0_28_ : 1; bool x6a0_29_checkForProjectiles : 1; bool x6a0_30_ : 1; - bool x6a0_31_ : 1; - bool x6a1_24_ : 1; + bool x6a0_31_canSeePlayer : 1; + bool x6a1_24_prevInCineCam : 1; bool x6a1_25_ : 1; bool x6a1_26_isAttackingObject : 1; bool x6a1_27_ : 1; @@ -206,7 +206,7 @@ private: void UpdateLandingSmoke(CStateManager& mgr, bool active); void UpdateParticleEffects(CStateManager& mgr, float intensity, bool active); void DeliverGetUp(); - void UpdateCantSeePlayer(CStateManager& mgr); + void UpdateCanSeePlayer(CStateManager& mgr); void AddToTeam(CStateManager& mgr); void RemoveFromTeam(CStateManager& mgr); }; From 26ae8beb74a3342e5ca65dd07d036c0b76002371 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 13 Mar 2020 16:22:39 -0400 Subject: [PATCH 07/16] CFlyingPirate: Small fixes --- Runtime/Character/CBodyStateCmdMgr.hpp | 1 - Runtime/MP1/World/CBabygoth.cpp | 2 +- Runtime/MP1/World/CChozoGhost.cpp | 2 +- Runtime/MP1/World/CFlaahgra.cpp | 8 +++--- Runtime/MP1/World/CFlyingPirate.cpp | 35 +++++++++++++------------- Runtime/MP1/World/CJellyZap.cpp | 6 ++--- Runtime/MP1/World/CMetaree.cpp | 2 +- Runtime/MP1/World/CSpacePirate.cpp | 18 ++++++------- 8 files changed, 36 insertions(+), 38 deletions(-) diff --git a/Runtime/Character/CBodyStateCmdMgr.hpp b/Runtime/Character/CBodyStateCmdMgr.hpp index 35448520a..717c686cd 100644 --- a/Runtime/Character/CBodyStateCmdMgr.hpp +++ b/Runtime/Character/CBodyStateCmdMgr.hpp @@ -459,7 +459,6 @@ public: const zeus::CVector3f& GetMoveVector() const { return x0_move; } const zeus::CVector3f& GetFaceVector() const { return xc_face; } const zeus::CVector3f& GetTargetVector() const { return x18_target; } - void SetTargetVector(const zeus::CVector3f& target) { x18_target = target; } const zeus::CVector3f& GetAdditiveTargetVector() const { return x24_additiveTarget; } }; diff --git a/Runtime/MP1/World/CBabygoth.cpp b/Runtime/MP1/World/CBabygoth.cpp index 2dd760946..1a831d151 100644 --- a/Runtime/MP1/World/CBabygoth.cpp +++ b/Runtime/MP1/World/CBabygoth.cpp @@ -708,7 +708,7 @@ void CBabygoth::FollowPattern(CStateManager& mgr, EStateMsg msg, float) { CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); } else if (x568_stateProg == 3) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); else x568_stateProg = 4; } diff --git a/Runtime/MP1/World/CChozoGhost.cpp b/Runtime/MP1/World/CChozoGhost.cpp index 56ead1af0..d267e7703 100644 --- a/Runtime/MP1/World/CChozoGhost.cpp +++ b/Runtime/MP1/World/CChozoGhost.cpp @@ -446,7 +446,7 @@ void CChozoGhost::Attack(CStateManager& mgr, EStateMsg msg, float dt) { xfc_constantForce.zeroOut(); } else if (msg == EStateMsg::Update) { TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, x67c_attackType); - GetBodyController()->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + GetBodyController()->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); if (x67c_attackType != 2) FloatToLevel(x678_floorLevel, dt); } else if (msg == EStateMsg::Deactivate) { diff --git a/Runtime/MP1/World/CFlaahgra.cpp b/Runtime/MP1/World/CFlaahgra.cpp index 1ca620638..2261d7e6b 100644 --- a/Runtime/MP1/World/CFlaahgra.cpp +++ b/Runtime/MP1/World/CFlaahgra.cpp @@ -785,7 +785,7 @@ void CFlaahgra::Growth(CStateManager& mgr, EStateMsg msg, float arg) { UpdateScale((x7c4_ > 0.f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f), x81c_, x56c_.x4_); } - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); } } else if (msg == EStateMsg::Deactivate) { UpdateScale(1.f, x81c_, x56c_.x4_); @@ -983,7 +983,7 @@ void CFlaahgra::Attack(CStateManager& mgr, EStateMsg msg, float arg) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) x568_ = 4; else - x450_bodyController->GetCommandMgr().SetTargetVector(x78c_); + x450_bodyController->GetCommandMgr().DeliverTargetVector(x78c_); } } else if (msg == EStateMsg::Deactivate) { SetCollisionActorBounds(mgr, x79c_leftArmCollision, {}); @@ -1100,7 +1100,7 @@ void CFlaahgra::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { x568_ = 4; } else { - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); } } } @@ -1135,7 +1135,7 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) x568_ = 4; else if (TCastToConstPtr wp = mgr.GetObjectById(x77c_)) { - x450_bodyController->GetCommandMgr().SetTargetVector(wp->GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(wp->GetTranslation() - GetTranslation()); } } } else if (msg == EStateMsg::Deactivate) { diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index ac108e1ca..b5a3ef545 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -567,7 +567,7 @@ void CFlyingPirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& nod x6a1_26_isAttackingObject ? x568_data.x60_altProjectileInfo2 : x568_data.x38_altProjectileInfo1; if (pInfo.Token().IsLoaded() && mgr.CanCreateProjectile(x8_uid, EWeaponType::AI, 16)) { const zeus::CTransform& xf = GetLctrTransform(node.GetLocatorName()); - TUniqueId& target = x6a1_26_isAttackingObject ? x85c_attackObjectId : x8_uid; + TUniqueId target = x6a1_26_isAttackingObject ? x85c_attackObjectId : mgr.GetPlayer().GetUniqueId(); CEnergyProjectile* projectile = new CEnergyProjectile( true, pInfo.Token(), EWeaponType::AI, xf, EMaterialTypes::Floor, pInfo.GetDamage(), mgr.AllocateUniqueId(), x4_areaId, x8_uid, target, EProjectileAttrib::None, false, zeus::skOne3f, std::nullopt, -1, false); @@ -928,7 +928,9 @@ void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { } if (x32c_animState != EAnimState::Repeat) { x2e0_destPos = GetTargetPos(mgr); - if (x34_transform.frontVector().dot((x2e0_destPos - GetTranslation()).normalized()) < 0.8f) { + zeus::CVector3f dist = x2e0_destPos - GetTranslation(); + dist.z() = 0.f; + if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { x32c_animState = EAnimState::Ready; } } @@ -1020,7 +1022,7 @@ void CFlyingPirate::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { x870_ += x87c_; } if (x30c_behaviourOrient == EBehaviourOrient::Constant) { - x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(GetTargetPos(mgr) - GetTranslation()); } UpdateCanSeePlayer(mgr); } else if (msg == EStateMsg::Deactivate) { @@ -1331,7 +1333,7 @@ void CFlyingPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { x870_ += x87c_; } if (x30c_behaviourOrient == EBehaviourOrient::Constant) { - x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(GetTargetPos(mgr) - GetTranslation()); } UpdateCanSeePlayer(mgr); } @@ -1341,7 +1343,8 @@ void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { x6a0_28_ = true; x7a0_boneTracking.SetActive(true); - x7a0_boneTracking.SetTarget(x8_uid); + const TUniqueId& playerUid = mgr.GetPlayer().GetUniqueId(); + x7a0_boneTracking.SetTarget(playerUid); bool foundPirate = false; for (const auto& obj : *mgr.ObjectListById(EGameObjectList::AiWaypoint)) { if (const CSpacePirate* const pirate = CPatterned::CastTo(obj)) { @@ -1354,7 +1357,7 @@ void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { } x79c_ = foundPirate ? 0 : 1; if (x7e8_targetId == kInvalidUniqueId) { - x7e8_targetId = mgr.GetPlayer().GetUniqueId(); + x7e8_targetId = playerUid; } } else if (msg == EStateMsg::Deactivate) { if (x79c_ == 0) { @@ -1526,25 +1529,24 @@ LAB_801f7bb8: x34_transform.transposeRotate(GetTargetPos(mgr) - GetTranslation())); } if (0.f < x870_.magSquared()) { - float fVar27 = x870_.magnitude(); - float fVar4 = 1.f / fVar27; - float fVar5 = 0.2; + float mag = x870_.magnitude(); + float fVar5 = 0.2f; if (0.f == x87c_.magSquared()) { fVar5 = 0.2f * 3.f; } - float mul = -(dt * fVar27 * fVar5 * fVar27 - fVar27); - x870_ = mul * fVar4 * x870_; + float mul = -(dt * mag * fVar5 * mag - mag); + x870_ = mul * (1.f / mag) * x870_; } pas::EAnimationState state = x450_bodyController->GetCurrentStateId(); - if (!x400_25_alive || state == pas::EAnimationState::LoopReaction || state == pas::EAnimationState::LieOnGround || - state == pas::EAnimationState::Getup) { + if (!x400_25_alive || state == pas::EAnimationState::LoopReaction || state == pas::EAnimationState::Hurled || + state == pas::EAnimationState::LieOnGround || state == pas::EAnimationState::Getup) { x870_.zeroOut(); x87c_.zeroOut(); } else { ApplyImpulseWR(xe8_mass * x870_, {}); } - if (auto& handle = GetSfxHandle()) { + if (const auto& handle = GetSfxHandle()) { x898_ = std::clamp(x898_, 1.f, 1.999f); x894_ += std::clamp(x898_ - x894_, -dt, dt); CSfxManager::PitchBend(handle, x894_); // TODO * 8192.f? @@ -1569,10 +1571,7 @@ LAB_801f7bb8: zeus::CVector3f v128 = x34_transform.frontVector().cross(v1dc); zeus::CVector3f v20c = v1dc.cross(v128).normalized(); zeus::CVector3f v128_2 = v20c.cross(v1dc); - x34_transform = zeus::CTransform(v128_2, v20c, v1dc, GetTranslation()); - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; + SetTransform({v128_2, v20c, v1dc, x34_transform.origin}); } if (!x450_bodyController->IsFrozen()) { diff --git a/Runtime/MP1/World/CJellyZap.cpp b/Runtime/MP1/World/CJellyZap.cpp index fc333b99a..ec6e4fc4d 100644 --- a/Runtime/MP1/World/CJellyZap.cpp +++ b/Runtime/MP1/World/CJellyZap.cpp @@ -107,7 +107,7 @@ void CJellyZap::Suck(CStateManager& mgr, EStateMsg msg, float arg) { RemoveAllAttractors(mgr); } else if (msg == EStateMsg::Update) { TryCommand(mgr, pas::EAnimationState::LoopReaction, &CPatterned::TryLoopReaction, 0); - x450_bodyController->GetCommandMgr().SetTargetVector( + x450_bodyController->GetCommandMgr().DeliverTargetVector( (mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.f)) - GetTranslation()); float intensity = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit) ? 0.1f : 1.f; @@ -133,7 +133,7 @@ void CJellyZap::Active(CStateManager& mgr, EStateMsg msg, float arg) { } else if (msg == EStateMsg::Update) { zeus::CVector3f targetVector = GetTranslation() - (zeus::CVector3f(0.f, 0.f, 1.f) + mgr.GetPlayer().GetTranslation()); - x450_bodyController->GetCommandMgr().SetTargetVector(targetVector); + x450_bodyController->GetCommandMgr().DeliverTargetVector(targetVector); if (x5b8_26_) { zeus::CVector3f moveToImpulse = GetMoveToORImpulseWR(GetTransform().transposeRotate(arg * (zeus::CVector3f(0.f, 1.f, 0.f) * x598_)), arg); @@ -233,4 +233,4 @@ const CDamageVulnerability* CJellyZap::GetDamageVulnerability(const zeus::CVecto const CDamageInfo& info) const { return CActor::GetDamageVulnerability(pos, dir, info); } -} // namespace urde::MP1 \ No newline at end of file +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetaree.cpp b/Runtime/MP1/World/CMetaree.cpp index 69a5622aa..55697d0b6 100644 --- a/Runtime/MP1/World/CMetaree.cpp +++ b/Runtime/MP1/World/CMetaree.cpp @@ -144,7 +144,7 @@ void CMetaree::Active(CStateManager& mgr, EStateMsg msg, float) { x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero, x584_lookPos)); SetMomentumWR({0.f, 0.f, -GetGravityConstant() * GetMass()}); } else if (msg == EStateMsg::Update) { - x450_bodyController->GetCommandMgr().SetTargetVector( + x450_bodyController->GetCommandMgr().DeliverTargetVector( (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized()); } else if (msg == EStateMsg::Deactivate) { SetMomentumWR({}); diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index e2af68c1d..92a857060 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -1497,7 +1497,7 @@ void CSpacePirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { } } if (r28) - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); } x828_patrolDestPos = x2e0_destPos; break; @@ -1553,7 +1553,7 @@ void CSpacePirate::Generate(CStateManager& mgr, EStateMsg msg, float dt) { TryCommand(mgr, pas::EAnimationState::Jump, &CPatterned::TryJump, x634_25_ceilingAmbush ? 2 : 0); if (x32c_animState == EAnimState::Repeat) x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); break; case EStateMsg::Deactivate: x32c_animState = EAnimState::NotReady; @@ -1609,7 +1609,7 @@ void CSpacePirate::Attack(CStateManager& mgr, EStateMsg msg, float dt) { case EStateMsg::Update: if (x636_26_enableMeleeAttack) { TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, 1); - x450_bodyController->GetCommandMgr().SetTargetVector(x648_targetDelta); + x450_bodyController->GetCommandMgr().DeliverTargetVector(x648_targetDelta); CheckBlade(mgr); if (x635_27_shadowPirate) { if (x32c_animState == EAnimState::Over) { @@ -1668,7 +1668,7 @@ void CSpacePirate::JumpBack(CStateManager& mgr, EStateMsg msg, float dt) { if (!x639_25_useJumpBackJump) { x450_bodyController->GetCommandMgr().DeliverCmd( CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); - x450_bodyController->GetCommandMgr().SetTargetVector(GetTargetPos(mgr) - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(GetTargetPos(mgr) - GetTranslation()); } else { TryCommand(mgr, pas::EAnimationState::Jump, &CPatterned::TryJump, 0); } @@ -1713,7 +1713,7 @@ void CSpacePirate::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) { } if (x639_30_closeMelee) x648_targetDelta = GetTargetPos(mgr) - GetTranslation(); - x450_bodyController->GetCommandMgr().SetTargetVector(x648_targetDelta); + x450_bodyController->GetCommandMgr().DeliverTargetVector(x648_targetDelta); if (x635_27_shadowPirate) { if (x32c_animState == EAnimState::Over) { x3e8_alphaDelta = -0.4f; @@ -1829,7 +1829,7 @@ void CSpacePirate::Crouch(CStateManager& mgr, EStateMsg msg, float dt) { x79c_coverDir = pas::ECoverDirection::Invalid; break; case EStateMsg::Update: - x450_bodyController->GetCommandMgr().SetTargetVector(x648_targetDelta); + x450_bodyController->GetCommandMgr().DeliverTargetVector(x648_targetDelta); UpdateCantSeePlayer(mgr); break; default: @@ -2089,7 +2089,7 @@ void CSpacePirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) { case EStateMsg::Update: TryCommand(mgr, pas::EAnimationState::Cover, &CPatterned::TryCover, int(x79c_coverDir)); if (CScriptCoverPoint* cp = GetCoverPoint(mgr, x640_coverPoint)) - x450_bodyController->GetCommandMgr().SetTargetVector(-cp->GetTransform().basis[1]); + x450_bodyController->GetCommandMgr().DeliverTargetVector(-cp->GetTransform().basis[1]); UpdateCantSeePlayer(mgr); break; case EStateMsg::Deactivate: @@ -2134,7 +2134,7 @@ void CSpacePirate::WallHang(CStateManager& mgr, EStateMsg msg, float dt) { break; case EStateMsg::Update: TryCommand(mgr, pas::EAnimationState::WallHang, &CSpacePirate::TryWallHang, 0); - x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation()); x7c4_burstFire.SetBurstType(1); break; case EStateMsg::Deactivate: @@ -2173,7 +2173,7 @@ void CSpacePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) { case EStateMsg::Update: TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, int(pas::ESeverity::One)); if (x32c_animState == EAnimState::Ready) - x450_bodyController->GetCommandMgr().SetTargetVector(x648_targetDelta); + x450_bodyController->GetCommandMgr().DeliverTargetVector(x648_targetDelta); break; case EStateMsg::Deactivate: x32c_animState = EAnimState::NotReady; From 651e28e921df06b482a0a2e032b9a561bed2ba37 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 13 Mar 2020 16:28:19 -0400 Subject: [PATCH 08/16] CFlyingPirate: Fix TargetPatrol --- Runtime/MP1/World/CFlyingPirate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index b5a3ef545..8ef9f4bf3 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1309,6 +1309,8 @@ void CFlyingPirate::UpdateCanSeePlayer(CStateManager& mgr) { } void CFlyingPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::Patrol(mgr, msg, arg); + if (msg == EStateMsg::Activate) { x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::Normal); x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow); From 8897d38c6a3ba6399a9857aa615872c06050a6b5 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 13 Mar 2020 18:46:53 -0400 Subject: [PATCH 09/16] CFlyingPirate: Fix Lurk state delay --- Runtime/MP1/World/CFlyingPirate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 8ef9f4bf3..d5a73cf5d 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -918,7 +918,7 @@ void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { x7d8_ = 0.f; x7dc_ = 0; CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); - x330_stateMachineState.SetDelay(0.f); + x330_stateMachineState.SetDelay(3.f); UpdateParticleEffects(mgr, 0.f, true); x6a2_25_aggressionChecked = false; } else if (msg == EStateMsg::Update) { From 57386e6269397cca42eeb21222ad4525ca508213 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 15 Mar 2020 01:02:31 -0400 Subject: [PATCH 10/16] CFlyingPirate: Small fixes --- Runtime/MP1/World/CFlyingPirate.cpp | 43 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index d5a73cf5d..d2b8218bb 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -59,9 +59,9 @@ constexpr std::array skBursts{ skBurst1.data(), skBurst2.data(), skBurst3.data(), skBurst4.data(), nullptr, }; -constexpr std::array skParts{ - "Head_1", "R_shoulder", "R_elbow", "R_wrist", "L_shoulder", "L_elbow", "L_wrist", - "R_hip", "R_knee", "R_ankle", "L_hip", "L_knee", "L_ankle", "rocket_LCTR", +constexpr std::array skParts{ + "Collar"sv, "Head_1"sv, "R_shoulder"sv, "R_elbow"sv, "R_wrist"sv, "L_shoulder"sv, "L_elbow"sv, "L_wrist"sv, + "R_hip"sv, "R_knee"sv, "R_ankle"sv, "L_hip"sv, "L_knee"sv, "L_ankle"sv, "rocket_LCTR"sv, }; } // namespace @@ -210,15 +210,15 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x6a2_27_sparksActive(false) , x6a2_28_(false) , x6a8_pathFindSearch(nullptr, 0 /* TODO */, pInfo.GetHalfExtent(), pInfo.GetHeight(), pInfo.GetPathfindingIndex()) -, x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f), +, x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), EBoneTrackingFlags::None) , x7ec_burstFire(skBursts.data(), 0) { const CModelData* modelData = GetModelData(); const CAnimData* animData = modelData->GetAnimationData(); - x798_headSegId = animData->GetLocatorSegId("Head_1"); - x7e0_gunSegId = animData->GetLocatorSegId("L_gun_LCTR"); - x864_missileSegments.push_back(animData->GetLocatorSegId("L_Missile_LCTR")); - x864_missileSegments.push_back(animData->GetLocatorSegId("R_Missile_LCTR")); + x798_headSegId = animData->GetLocatorSegId("Head_1"sv); + x7e0_gunSegId = animData->GetLocatorSegId("L_gun_LCTR"sv); + x864_missileSegments.push_back(animData->GetLocatorSegId("L_Missile_LCTR"sv)); + x864_missileSegments.push_back(animData->GetLocatorSegId("R_Missile_LCTR"sv)); x850_height = modelData->GetScale().x() * GetAnimationDistance({3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1)}); if (x568_data.xd8_particleGen1.IsValid() && x568_data.xdc_particleGen2.IsValid() && @@ -283,7 +283,7 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt AddToTeam(mgr); } UpdateParticleEffects(mgr, 0.f, x6a0_24_); - GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes", true, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes"sv, true, mgr); break; case EScriptObjectMessage::Jumped: if (CScriptCoverPoint* cover = GetCoverPoint(mgr, x6a4_currentCoverPoint)) { @@ -532,7 +532,7 @@ void CFlyingPirate::Dead(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::Dead(mgr, msg, arg); if (msg == EStateMsg::Activate) { x7a0_boneTracking.SetActive(false); - GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes", false, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("Eyes"sv, false, mgr); CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); } } @@ -846,7 +846,7 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co if (x460_knockBackController.GetActiveParms().x0_animState == EKnockBackAnimationState::Hurled) { if (x400_25_alive) { if (!x450_bodyController->IsFrozen()) { - x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "GetUpNow"); + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "GetUpNow"sv); x330_stateMachineState.SetDelay(x568_data.x88_knockBackDelay); } x6a1_28_ = false; @@ -1140,7 +1140,7 @@ bool CFlyingPirate::ShouldDodge(CStateManager& mgr, float arg) { if (x6a1_28_ || x6a1_25_) return false; return 0.f < (GetTargetPos(mgr) - x34_transform.origin).dot(x34_transform.frontVector()) && - (x854_ < 0.33f || (x858_ < 0.33f && x7d8_ < 0.5f)); + (x854_ < 0.33f || x858_ < 0.33f) && x7d8_ < 0.5f; } bool CFlyingPirate::ShouldMove(CStateManager& mgr, float arg) { @@ -1250,25 +1250,22 @@ void CFlyingPirate::UpdateLandingSmoke(CStateManager& mgr, bool active) { x684_particleGens[idx]->SetParticleEmission(true); x684_particleGens[idx]->SetTranslation({origin.x(), origin.y(), particleLevel}); } - GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke", true, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke"sv, true, mgr); } else { for (const auto& gen : x684_particleGens) { gen->SetParticleEmission(false); } - GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke", false, mgr); + GetModelData()->GetAnimationData()->SetParticleEffectState("LandingSmoke"sv, false, mgr); } } void CFlyingPirate::UpdateParticleEffects(CStateManager& mgr, float intensity, bool active) { CAnimData* const animData = GetModelData()->GetAnimationData(); - std::string_view name = "JetPack"; - if (x6a0_25_isUnderwater) { - name = "ScubaGear"; - } + std::string_view name = x6a0_25_isUnderwater ? "ScubaGear"sv : "JetPack"sv; if (active != x6a2_26_jetpackActive) { animData->SetParticleEffectState(name, active, mgr); if (x6a0_25_isUnderwater) { - animData->SetParticleEffectState("ScubaBubbles", active, mgr); + animData->SetParticleEffectState("ScubaBubbles"sv, active, mgr); } x6a2_26_jetpackActive = active; } @@ -1279,7 +1276,7 @@ void CFlyingPirate::UpdateParticleEffects(CStateManager& mgr, float intensity, b if (!x6a0_25_isUnderwater) { const bool sparksActive = active && intensity > 0.8f; if (sparksActive != x6a2_27_sparksActive) { - animData->SetParticleEffectState("Sparks", sparksActive, mgr); + animData->SetParticleEffectState("Sparks"sv, sparksActive, mgr); x6a2_27_sparksActive = sparksActive; } } @@ -1371,7 +1368,9 @@ void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { x2e0_destPos = GetTargetPos(mgr); - if (x34_transform.frontVector().dot((x2e0_destPos - GetTranslation()).normalized()) < 0.8f) { + zeus::CVector3f dist = x2e0_destPos - GetTranslation(); + dist.z() = 0.f; + if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { x32c_animState = EAnimState::Ready; } } else if (msg == EStateMsg::Update) { @@ -1385,7 +1384,7 @@ void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { UpdateParticleEffects(mgr, 0.f, false); } else if (msg == EStateMsg::Update) { - if (x32c_animState != EAnimState::Ready) { + if (x32c_animState != EAnimState::NotReady) { TryCommand(mgr, pas::EAnimationState::Turn, &CPatterned::TryTurn, 0); } if (x32c_animState != EAnimState::Repeat) { From 932615593e1e093d290e823376136fdf58d02cf5 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 15 Mar 2020 01:04:01 -0400 Subject: [PATCH 11/16] CFlyingPirateRagDoll: Implement PreRender, Prime --- Runtime/Character/CHierarchyPoseBuilder.hpp | 10 +++-- Runtime/MP1/World/CFlyingPirate.cpp | 45 +++++++++++++++++++-- Runtime/MP1/World/CFlyingPirate.hpp | 4 +- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/Runtime/Character/CHierarchyPoseBuilder.hpp b/Runtime/Character/CHierarchyPoseBuilder.hpp index aeaa10035..24e196543 100644 --- a/Runtime/Character/CHierarchyPoseBuilder.hpp +++ b/Runtime/Character/CHierarchyPoseBuilder.hpp @@ -13,16 +13,18 @@ class CLayoutDescription; class CPoseAsTransforms; class CHierarchyPoseBuilder { - CLayoutDescription x0_layoutDesc; - CSegId x30_rootId; - bool x34_hasRoot = false; - +public: struct CTreeNode { CSegId x0_child = 0; CSegId x1_sibling = 0; zeus::CQuaternion x4_rotation; zeus::CVector3f x14_offset; }; + +private: + CLayoutDescription x0_layoutDesc; + CSegId x30_rootId; + bool x34_hasRoot = false; TSegIdMap x38_treeMap; void BuildIntoHierarchy(const CCharLayoutInfo& layout, const CSegId& boneId, const CSegId& nullId); diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index d2b8218bb..f77fccdc8 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -167,13 +167,50 @@ CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CF AddJointConstraint(5, 2, 8, 5, 6, 7); } -void CFlyingPirate::CFlyingPirateRagDoll::PreRender(const zeus::CVector3f& pos, CModelData& mData) { - // TODO - CRagDoll::PreRender(pos, mData); +void CFlyingPirate::CFlyingPirateRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData) { + if (!x68_25_over) { + CAnimData* const animData = mData.GetAnimationData(); + const CCharLayoutInfo& layout = animData->GetCharLayoutInfo(); + CHierarchyPoseBuilder& poseBuilder = animData->PoseBuilder(); + for (const auto& id : layout.GetSegIdList().GetList()) { + if (layout.GetRootNode()->GetBoneMap()[id].x10_children.size() > 1) { + poseBuilder.GetTreeMap()[id].x4_rotation = zeus::CQuaternion(); + } + } + + CHierarchyPoseBuilder::CTreeNode& skeletonRoot = + poseBuilder.GetTreeMap()[animData->GetLocatorSegId("Skeleton_Root"sv)]; + const zeus::CVector3f& rHipPos = x4_particles[8].GetPosition(); // R_hip + const zeus::CVector3f& lHipPos = x4_particles[11].GetPosition(); // L_hip + const zeus::CVector3f& rShoulderPos = x4_particles[2].GetPosition(); // R_shoulder + const zeus::CVector3f& lShoulderPos = x4_particles[5].GetPosition(); // L_shoulder + const zeus::CVector3f& collarPos = x4_particles[0].GetPosition(); // Collar + skeletonRoot.x14_offset = (0.5f * (rHipPos + lHipPos) - v) / mData.GetScale(); + + const zeus::CVector3f& rootRight = rShoulderPos - lShoulderPos; + const zeus::CVector3f& rootUp = (collarPos - (rHipPos + lHipPos) * 0.5f).normalized(); + const zeus::CVector3f& rootFore = rootUp.cross(rootRight).normalized(); + const zeus::CQuaternion& rootRot = zeus::CMatrix3f(rootFore.cross(rootUp), rootFore, rootUp); + skeletonRoot.x4_rotation = rootRot; + + const CRagDollParticle& head = x4_particles[1]; // Head_1 + const zeus::CVector3f& neckRestVec = layout.GetFromParentUnrotated(head.GetBone()); + poseBuilder.GetTreeMap()[head.GetBone()].x4_rotation = zeus::CQuaternion::shortestRotationArc( + neckRestVec, rootRot.inverse().transform(head.GetPosition() - collarPos)); + + BoneAlign(poseBuilder, layout, 3, 4, rootRot * BoneAlign(poseBuilder, layout, 2, 3, rootRot)); + BoneAlign(poseBuilder, layout, 6, 7, rootRot * BoneAlign(poseBuilder, layout, 5, 6, rootRot)); + BoneAlign(poseBuilder, layout, 9, 10, rootRot * BoneAlign(poseBuilder, layout, 8, 9, rootRot)); + BoneAlign(poseBuilder, layout, 12, 13, rootRot * BoneAlign(poseBuilder, layout, 11, 12, rootRot)); + + animData->MarkPoseDirty(); + } } void CFlyingPirate::CFlyingPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) { - // TODO + if (x6c_actor->x6a1_30_) { + xa0_ = CSfxManager::AddEmitter(x9c_, x6c_actor->GetTranslation(), zeus::skZero3f, true, true, 0x7f, kInvalidAreaId); + } CRagDoll::Prime(mgr, xf, mData); } diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 0c1810019..946df1b4e 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -61,14 +61,14 @@ private: float x8c_ = 0.f; zeus::CVector3f x90_ = zeus::skZero3f; u16 x9c_; - int xa0_ = 0; + CSfxHandle xa0_; zeus::CVector3f xa4_; bool xb0_24_ : 1; public: CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2); - void PreRender(const zeus::CVector3f& pos, CModelData& mData) override; + void PreRender(const zeus::CVector3f& v, CModelData& mData) override; void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) override; void Update(CStateManager& mgr, float dt, float waterTop) override; }; From 6f89dbb2400e2aab05267efe2e931a973dc31733 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 15 Mar 2020 20:51:24 -0400 Subject: [PATCH 12/16] CFlyingPirate: More small fixes --- Runtime/MP1/World/CFlyingPirate.cpp | 40 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index f77fccdc8..4120457a3 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -21,7 +21,7 @@ namespace urde::MP1 { namespace { -constexpr std::array skBurst1{{ +constexpr std::array skBurst1{{ {4, {3, 4, 11, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, {20, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, {20, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, @@ -30,7 +30,7 @@ constexpr std::array skBurst1{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst2{{ +constexpr std::array skBurst2{{ {5, {3, 4, 8, 12, -1, 0, 0, 0}, 0.1f, 0.05f}, {10, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f}, {10, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f}, @@ -39,7 +39,7 @@ constexpr std::array skBurst2{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst3{{ +constexpr std::array skBurst3{{ {30, {3, 4, 5, 11, 12, 4, -1, 0}, 0.1f, 0.05f}, {20, {2, 3, 4, 5, 4, 3, -1, 0}, 0.1f, 0.05f}, {20, {5, 4, 3, 13, 12, 11, -1, 0}, 0.1f, 0.05f}, @@ -47,7 +47,7 @@ constexpr std::array skBurst3{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBurst4{{ +constexpr std::array skBurst4{{ {10, {6, 5, 4, 14, 13, 12, -1, 0}, 0.1f, 0.05f}, {20, {14, 13, 12, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, {20, {14, 15, 16, 11, 10, 9, -1, 0}, 0.1f, 0.05f}, @@ -55,11 +55,11 @@ constexpr std::array skBurst4{{ {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }}; -constexpr std::array skBursts{ +constexpr std::array skBursts{ skBurst1.data(), skBurst2.data(), skBurst3.data(), skBurst4.data(), nullptr, }; -constexpr std::array skParts{ +constexpr std::array skParts{ "Collar"sv, "Head_1"sv, "R_shoulder"sv, "R_elbow"sv, "R_wrist"sv, "L_shoulder"sv, "L_elbow"sv, "L_wrist"sv, "R_hip"sv, "R_knee"sv, "R_ankle"sv, "L_hip"sv, "L_knee"sv, "L_ankle"sv, "rocket_LCTR"sv, }; @@ -395,9 +395,8 @@ bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float arg) { return x6a2 bool CFlyingPirate::AnimOver(CStateManager& mgr, float arg) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Death) { return true; - } else { - return CPatterned::AnimOver(mgr, arg); } + return CPatterned::AnimOver(mgr, arg); } void CFlyingPirate::Attack(CStateManager& mgr, EStateMsg msg, float arg) { @@ -434,9 +433,9 @@ bool CFlyingPirate::Attacked(CStateManager& mgr, float arg) { return x854_ < (ar zeus::CVector3f CFlyingPirate::AvoidActors(CStateManager& mgr) { const zeus::CVector3f& origin = GetTranslation(); - zeus::CAABox box(origin - 8.f, origin + 8.f); + const zeus::CAABox box(origin - 8.f, origin + 8.f); rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, box, CMaterialFilter::MakeInclude(EMaterialTypes::CameraPassthrough), this); + mgr.BuildNearList(nearList, box, CMaterialFilter::MakeInclude(EMaterialTypes::Character), this); zeus::CVector3f ret; for (const auto& id : nearList) { @@ -445,8 +444,7 @@ zeus::CVector3f CFlyingPirate::AvoidActors(CStateManager& mgr) { } } const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); - ret += x45c_steeringBehaviors.Separation(*this, {playerPos.x(), playerPos.y(), origin.z()}, 20.f); - return ret; + return ret + x45c_steeringBehaviors.Separation(*this, {playerPos.x(), playerPos.y(), origin.z()}, 20.f); } void CFlyingPirate::Bounce(CStateManager& mgr, EStateMsg msg, float arg) { @@ -498,7 +496,7 @@ void CFlyingPirate::CheckForProjectiles(CStateManager& mgr) { return; const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); - zeus::CAABox box(playerPos - 5.f, playerPos + 5.f); + const zeus::CAABox box(playerPos - 5.f, playerPos + 5.f); x6a0_30_ = false; rstl::reserved_vector nearList; @@ -605,9 +603,10 @@ void CFlyingPirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& nod if (pInfo.Token().IsLoaded() && mgr.CanCreateProjectile(x8_uid, EWeaponType::AI, 16)) { const zeus::CTransform& xf = GetLctrTransform(node.GetLocatorName()); TUniqueId target = x6a1_26_isAttackingObject ? x85c_attackObjectId : mgr.GetPlayer().GetUniqueId(); - CEnergyProjectile* projectile = new CEnergyProjectile( - true, pInfo.Token(), EWeaponType::AI, xf, EMaterialTypes::Floor, pInfo.GetDamage(), mgr.AllocateUniqueId(), - x4_areaId, x8_uid, target, EProjectileAttrib::None, false, zeus::skOne3f, std::nullopt, -1, false); + CEnergyProjectile* projectile = + new CEnergyProjectile(true, pInfo.Token(), EWeaponType::AI, xf, EMaterialTypes::Character, pInfo.GetDamage(), + mgr.AllocateUniqueId(), x4_areaId, x8_uid, target, EProjectileAttrib::None, false, + zeus::skOne3f, std::nullopt, -1, false); mgr.AddObject(projectile); if (!x6a1_26_isAttackingObject) { projectile->SetCameraShake( @@ -662,7 +661,7 @@ void CFlyingPirate::MassiveDeath(CStateManager& mgr) { void CFlyingPirate::FireProjectile(CStateManager& mgr, float dt) { bool projectileFired = false; const zeus::CTransform& xf = GetLctrTransform(x7e0_gunSegId); - if (x400_25_alive) { + if (!x400_25_alive) { LaunchProjectile(xf, mgr, 8, EProjectileAttrib::None, false, std::nullopt, -1, false, zeus::skOne3f); projectileFired = true; } else { @@ -674,8 +673,7 @@ void CFlyingPirate::FireProjectile(CStateManager& mgr, float dt) { } zeus::CVector3f dist = origin - xf.origin; float mag = dist.magnitude(); - dist *= zeus::CVector3f(1.f / mag); - float fVar13 = xf.frontVector().dot(dist); + float fVar13 = xf.frontVector().dot(dist * (1.f / mag)); if (0.707f < fVar13 || (mag < 6.f && 0.5f < fVar13)) { if (LineOfSightTest(mgr, xf.origin, origin, {EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough})) { origin += x34_transform.rotate(x7ec_burstFire.GetDistanceCompensatedError(mag, 6.f)); @@ -812,9 +810,9 @@ void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float arg) { bool CFlyingPirate::HearPlayer(CStateManager& mgr, float arg) { const CPlayer& player = mgr.GetPlayer(); - const float x4squared = x568_data.x4_hearingDistance * x568_data.x4_hearingDistance; + const float hearingDist = x568_data.x4_hearingDistance * x568_data.x4_hearingDistance; return player.GetVelocity().magSquared() > 0.1f && - (player.GetTranslation() - GetTranslation()).magSquared() < x4squared; + (player.GetTranslation() - GetTranslation()).magSquared() < hearingDist; } bool CFlyingPirate::HearShot(CStateManager& mgr, float arg) { return x6a0_26_hearShot; } From 642bf379ced5f3ef1a393642215b009d481c2c3c Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 18 Mar 2020 01:39:32 -0400 Subject: [PATCH 13/16] CFlyingPirate: Add CPathFindSearch flags --- Runtime/MP1/World/CFlyingPirate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 4120457a3..f272e441d 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -246,7 +246,8 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x6a2_26_jetpackActive(false) , x6a2_27_sparksActive(false) , x6a2_28_(false) -, x6a8_pathFindSearch(nullptr, 0 /* TODO */, pInfo.GetHalfExtent(), pInfo.GetHeight(), pInfo.GetPathfindingIndex()) +, x6a8_pathFindSearch(nullptr, x6a0_25_isUnderwater ? 2 : 3, pInfo.GetHalfExtent(), pInfo.GetHeight(), + pInfo.GetPathfindingIndex()) , x7a0_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f), EBoneTrackingFlags::None) , x7ec_burstFire(skBursts.data(), 0) { From 851304ded9f58ab64a7edb27e0c0fbb0311c18d8 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 18 Mar 2020 02:53:53 -0400 Subject: [PATCH 14/16] CFlyingPirate: Finish Think implementation --- Runtime/Character/CRagDoll.hpp | 1 + Runtime/MP1/World/CFlyingPirate.cpp | 133 +++++++++++++++++----------- Runtime/MP1/World/CFlyingPirate.hpp | 6 +- 3 files changed, 83 insertions(+), 57 deletions(-) diff --git a/Runtime/Character/CRagDoll.hpp b/Runtime/Character/CRagDoll.hpp index b8f75d04b..678861df7 100644 --- a/Runtime/Character/CRagDoll.hpp +++ b/Runtime/Character/CRagDoll.hpp @@ -137,6 +137,7 @@ public: bool IsOver() const { return x68_25_over; } void SetNoOverTimer(bool b) { x68_28_noOverTimer = b; } void SetContinueSmallMovements(bool b) { x68_27_continueSmallMovements = b; } + u32 GetImpactCount() const { return x4c_impactCount; } }; } // namespace urde diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index f272e441d..78f288c03 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -240,7 +240,7 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x6a1_28_(false) , x6a1_29_isMoving(false) , x6a1_30_(false) -, x6a1_31_(false) +, x6a1_31_stopped(false) , x6a2_24_aggressive(false) , x6a2_25_aggressionChecked(false) , x6a2_26_jetpackActive(false) @@ -287,10 +287,10 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt x6a2_28_ = true; break; case EScriptObjectMessage::Start: - x6a1_31_ = false; + x6a1_31_stopped = false; break; case EScriptObjectMessage::Stop: - x6a1_31_ = true; + x6a1_31_stopped = true; break; case EScriptObjectMessage::OnFloor: x7ec_burstFire.SetBurstType(2); @@ -391,7 +391,7 @@ void CFlyingPirate::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan CPatterned::AddToRenderer(frustum, mgr); } -bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float arg) { return x6a2_24_aggressive; } +bool CFlyingPirate::AggressionCheck(CStateManager& mgr, float) { return x6a2_24_aggressive; } bool CFlyingPirate::AnimOver(CStateManager& mgr, float arg) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Death) { @@ -448,7 +448,7 @@ zeus::CVector3f CFlyingPirate::AvoidActors(CStateManager& mgr) { return ret + x45c_steeringBehaviors.Separation(*this, {playerPos.x(), playerPos.y(), origin.z()}, 20.f); } -void CFlyingPirate::Bounce(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Bounce(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x8_uid, x890_teamAiMgr, true); } else if (msg == EStateMsg::Update) { @@ -526,17 +526,16 @@ void CFlyingPirate::CheckForProjectiles(CStateManager& mgr) { x6a0_29_checkForProjectiles = false; } -bool CFlyingPirate::CoverCheck(CStateManager& mgr, float arg) { +bool CFlyingPirate::CoverCheck(CStateManager& mgr, float) { if (0.f < x888_) return false; x888_ = 10.f; return mgr.GetActiveRandom()->Range(0.f, 100.f) < x568_data.xcc_coverCheckChance; } -bool CFlyingPirate::CoverFind(CStateManager& mgr, float arg) { +bool CFlyingPirate::CoverFind(CStateManager& mgr, float) { float closestMag = x568_data.x0_maxCoverDistance * x568_data.x0_maxCoverDistance; CScriptCoverPoint* closest = nullptr; - // FIXME const weirdness with GetObjectListById for (const auto& entity : *mgr.ObjectListById(EGameObjectList::PlatformAndDoor)) { if (TCastToPtr cover = entity) { if (cover->GetActive() && cover->ShouldLandHere() && !cover->GetInUse(x8_uid) && @@ -558,7 +557,7 @@ bool CFlyingPirate::CoverFind(CStateManager& mgr, float arg) { return false; } -void CFlyingPirate::Deactivate(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Deactivate(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x401_30_pendingDeath = true; } @@ -573,7 +572,7 @@ void CFlyingPirate::Dead(CStateManager& mgr, EStateMsg msg, float arg) { } } -void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Dodge(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x32c_animState = EAnimState::Ready; if ((x84c_dodgeDirection = GetDodgeDirection(mgr, x850_height)) == pas::EStepDirection::Invalid) { @@ -633,7 +632,7 @@ void CFlyingPirate::Enraged(CStateManager& mgr, EStateMsg msg, float arg) { CBCLocomotionCmd(zeus::skUp, (GetTargetPos(mgr) - GetTranslation()).normalized(), 1.f)); } -void CFlyingPirate::Explode(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Explode(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, EMaterialTypes::GroundCollider, EMaterialTypes::Solid, mgr); @@ -791,14 +790,14 @@ zeus::CVector3f CFlyingPirate::GetTargetPos(CStateManager& mgr) { return player.GetAimPosition(mgr, 0.f); } -void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x32c_animState = EAnimState::Ready; CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x890_teamAiMgr, x8_uid, true); } else if (msg == EStateMsg::Update) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround) { - // FIXME is this accurate? will always return Success - CPathFindSearch::EResult result = x6a8_pathFindSearch.Search(GetTranslation(), GetTranslation()); + // will always return Success? + CPathFindSearch::EResult result = x6a8_pathFindSearch.Search(x34_transform.origin, x34_transform.origin); if (result == CPathFindSearch::EResult::NoSourcePoint) { x401_30_pendingDeath = true; } @@ -809,16 +808,16 @@ void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float arg) { } } -bool CFlyingPirate::HearPlayer(CStateManager& mgr, float arg) { +bool CFlyingPirate::HearPlayer(CStateManager& mgr, float) { const CPlayer& player = mgr.GetPlayer(); const float hearingDist = x568_data.x4_hearingDistance * x568_data.x4_hearingDistance; return player.GetVelocity().magSquared() > 0.1f && (player.GetTranslation() - GetTranslation()).magSquared() < hearingDist; } -bool CFlyingPirate::HearShot(CStateManager& mgr, float arg) { return x6a0_26_hearShot; } +bool CFlyingPirate::HearShot(CStateManager& mgr, float) { return x6a0_26_hearShot; } -bool CFlyingPirate::InPosition(CStateManager& mgr, float arg) { +bool CFlyingPirate::InPosition(CStateManager& mgr, float) { CScriptCoverPoint* const cover = GetCoverPoint(mgr, x6a4_currentCoverPoint); if (cover == nullptr) { return true; @@ -827,14 +826,14 @@ bool CFlyingPirate::InPosition(CStateManager& mgr, float arg) { return dist.z() < 0.f && dist.magnitude() < 4.f; } -bool CFlyingPirate::InRange(CStateManager& mgr, float arg) { +bool CFlyingPirate::InRange(CStateManager& mgr, float) { const CPlayer& player = mgr.GetPlayer(); const zeus::CVector3f& playerPos = player.GetTranslation(); return std::abs(playerPos.z()) < x2fc_minAttackRange && playerPos.magSquared() < x300_maxAttackRange * x300_maxAttackRange; } -void CFlyingPirate::Jump(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Jump(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); x328_25_verticalMovement = true; @@ -865,10 +864,10 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co } x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::Hurled, EKnockBackAnimationState::Hurled); x328_25_verticalMovement = false; - const TUniqueId& waypointId = GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Next); - if (waypointId != kInvalidUniqueId) { - // TODO casts and then does nothing? - } + // const TUniqueId& waypointId = GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Next); + // if (waypointId != kInvalidUniqueId) { + // casts and then does nothing? + // } const zeus::CVector3f& homingPosition = mgr.GetPlayer().GetHomingPosition(mgr, 0.f); const zeus::CVector3f& homingDist = homingPosition - GetTranslation(); zeus::CVector3f cross = homingDist.cross(zeus::skUp); @@ -887,11 +886,9 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co } x6a1_28_ = false; x328_25_verticalMovement = false; - // FIXME 0x7f to volume CSfxManager::AddEmitter(x568_data.xe4_knockBackSfx, GetTranslation(), zeus::skZero3f, 1.f, true, false, 0x7f, kInvalidAreaId); } else { - // FIXME 0x7f to volume CSfxManager::AddEmitter(x568_data.xe6_deathSfx, GetTranslation(), zeus::skZero3f, 1.f, true, false, 0x7f, kInvalidAreaId); if (x400_27_fadeToDeath) { @@ -903,7 +900,7 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co } } -void CFlyingPirate::Land(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Land(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x32c_animState = EAnimState::Ready; UpdateLandingSmoke(mgr, true); @@ -920,11 +917,11 @@ void CFlyingPirate::Land(CStateManager& mgr, EStateMsg msg, float arg) { } } -bool CFlyingPirate::Landed(CStateManager& mgr, float arg) { +bool CFlyingPirate::Landed(CStateManager& mgr, float) { return x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround; } -bool CFlyingPirate::LineOfSight(CStateManager& mgr, float arg) { return !x6a0_31_canSeePlayer; } +bool CFlyingPirate::LineOfSight(CStateManager& mgr, float) { return !x6a0_31_canSeePlayer; } bool CFlyingPirate::LineOfSightTest(CStateManager& mgr, const zeus::CVector3f& start, const zeus::CVector3f& end, CMaterialList exclude) { @@ -947,7 +944,7 @@ bool CFlyingPirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) { return ret; } -void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { ReleaseCoverPoint(mgr, x6a4_currentCoverPoint); x6a0_31_canSeePlayer = true; @@ -1066,7 +1063,7 @@ void CFlyingPirate::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { } } -bool CFlyingPirate::PatternOver(CStateManager& mgr, float arg) { return x2dc_destObj == kInvalidUniqueId; } +bool CFlyingPirate::PatternOver(CStateManager& mgr, float) { return x2dc_destObj == kInvalidUniqueId; } void CFlyingPirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { CModelData* modelData = GetModelData(); @@ -1078,7 +1075,7 @@ void CFlyingPirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) *x450_bodyController); } -void CFlyingPirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x6a1_26_isAttackingObject = true; x32c_animState = EAnimState::Ready; @@ -1153,7 +1150,7 @@ void CFlyingPirate::Retreat(CStateManager& mgr, EStateMsg msg, float arg) { bool CFlyingPirate::ShotAt(CStateManager& mgr, float arg) { return x858_ < (arg != 0.f ? arg : 0.5f); } -bool CFlyingPirate::ShouldAttack(CStateManager& mgr, float arg) { +bool CFlyingPirate::ShouldAttack(CStateManager& mgr, float) { CTeamAiRole* const role = CTeamAiMgr::GetTeamAiRole(mgr, x890_teamAiMgr, x8_uid); const CPlayer& player = mgr.GetPlayer(); if ((role == nullptr || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged) && @@ -1172,14 +1169,14 @@ bool CFlyingPirate::ShouldAttack(CStateManager& mgr, float arg) { return false; } -bool CFlyingPirate::ShouldDodge(CStateManager& mgr, float arg) { +bool CFlyingPirate::ShouldDodge(CStateManager& mgr, float) { if (x6a1_28_ || x6a1_25_) return false; return 0.f < (GetTargetPos(mgr) - x34_transform.origin).dot(x34_transform.frontVector()) && (x854_ < 0.33f || x858_ < 0.33f) && x7d8_ < 0.5f; } -bool CFlyingPirate::ShouldMove(CStateManager& mgr, float arg) { +bool CFlyingPirate::ShouldMove(CStateManager& mgr, float) { const CPlayer& player = mgr.GetPlayer(); const zeus::CVector3f& origin = GetTranslation(); const zeus::CVector3f& playerOrigin = player.GetTranslation(); @@ -1203,7 +1200,7 @@ bool CFlyingPirate::ShouldMove(CStateManager& mgr, float arg) { return true; } -bool CFlyingPirate::ShouldRetreat(CStateManager& mgr, float arg) { +bool CFlyingPirate::ShouldRetreat(CStateManager& mgr, float) { if (!x6a2_28_) return false; @@ -1221,14 +1218,14 @@ bool CFlyingPirate::ShouldRetreat(CStateManager& mgr, float arg) { x328_24_inPosition = false; x6a1_29_isMoving = true; x6a0_26_hearShot = false; - x6a0_24_ = false; + x6a0_28_ = false; x400_24_hitByPlayerProjectile = false; return true; } return false; } -bool CFlyingPirate::ShouldSpecialAttack(CStateManager& mgr, float arg) { +bool CFlyingPirate::ShouldSpecialAttack(CStateManager& mgr, float) { if (x3fc_flavor != EFlavorType::One || x85c_attackObjectId == kInvalidUniqueId || x860_ > 0.f) return false; @@ -1248,7 +1245,7 @@ bool CFlyingPirate::ShouldSpecialAttack(CStateManager& mgr, float arg) { return false; } -bool CFlyingPirate::SpotPlayer(CStateManager& mgr, float arg) { +bool CFlyingPirate::SpotPlayer(CStateManager& mgr, float) { const zeus::CVector3f& dir = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetGunEyePos(); return dir.magnitude() * x3c4_detectionAngle < dir.dot(x34_transform.frontVector()); } @@ -1374,7 +1371,7 @@ void CFlyingPirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { } } -void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x6a0_28_ = true; x7a0_boneTracking.SetActive(true); @@ -1401,7 +1398,7 @@ void CFlyingPirate::Taunt(CStateManager& mgr, EStateMsg msg, float arg) { } } -void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x2e0_destPos = GetTargetPos(mgr); zeus::CVector3f dist = x2e0_destPos - GetTranslation(); @@ -1416,7 +1413,7 @@ void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { } } -void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float arg) { +void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { UpdateParticleEffects(mgr, 0.f, false); } else if (msg == EStateMsg::Update) { @@ -1505,15 +1502,10 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { if (x400_25_alive) { CheckForProjectiles(mgr); } - if (!x6a0_25_isUnderwater) { - if (x400_25_alive) { - const CBodyState* state = x450_bodyController->GetBodyStateInfo().GetCurrentState(); - if (!state->CanShoot() || !x6a0_28_ || - x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack || x6a1_31_ || - x450_bodyController->IsElectrocuting()) { - goto LAB_801f7bb8; - } - } + if (!x6a0_25_isUnderwater && + (!x400_25_alive || !(!x450_bodyController->GetBodyStateInfo().GetCurrentState()->CanShoot() || !x6a0_28_ || + x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack || + x6a1_31_stopped || x450_bodyController->IsElectrocuting()))) { if (x7ec_burstFire.GetBurstType() != -1) { x7e4_ -= dt; if (x7e4_ < 0.f) { @@ -1552,7 +1544,6 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } } -LAB_801f7bb8: if (x89c_ragDoll && x89c_ragDoll->IsPrimed()) { UpdateAlphaDelta(dt, mgr); UpdateDamageColor(dt); @@ -1585,8 +1576,8 @@ LAB_801f7bb8: if (const auto& handle = GetSfxHandle()) { x898_ = std::clamp(x898_, 1.f, 1.999f); - x894_ += std::clamp(x898_ - x894_, -dt, dt); - CSfxManager::PitchBend(handle, x894_); // TODO * 8192.f? + x894_pitchBend += std::clamp(x898_ - x894_pitchBend, -dt, dt); + CSfxManager::PitchBend(handle, x894_pitchBend); } x87c_.zeroOut(); @@ -1617,7 +1608,41 @@ LAB_801f7bb8: } if (x89c_ragDoll) { - // TODO + if (!x89c_ragDoll->IsPrimed()) { + // SetMuted(true); ?? + SetMuted(false); + x89c_ragDoll->Prime(mgr, x34_transform, *x64_modelData); + SetTransform(zeus::CTransform::Translate(x34_transform.origin)); + x450_bodyController->SetPlaybackRate(0.f); + } else { + float waterTop = -FLT_MAX; + if (xc4_fluidId != kInvalidUniqueId) { + if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) { + waterTop = water->GetTriggerBoundsWR().max.z(); + } + } + x89c_ragDoll->Update(mgr, dt * CalcDyingThinkRate(), waterTop); + x64_modelData->AdvanceParticles(x34_transform, dt, mgr); + } + if (x89c_ragDoll->IsPrimed() && !x400_27_fadeToDeath) { + x400_27_fadeToDeath = true; + x3e8_alphaDelta = -1.f / 3.f; + SetVelocityWR(zeus::skZero3f); + x150_momentum.zeroOut(); + x870_.zeroOut(); + } + if (x89c_ragDoll) { + bool wasGtZero = x88c_ragDollTimer > 0.f; + x88c_ragDollTimer -= dt; + if (x88c_ragDollTimer < 2.f) { + if (x89c_ragDoll->GetImpactCount() > 2) { + x88c_ragDollTimer = std::min(0.1f, x88c_ragDollTimer); + } + if (wasGtZero && x88c_ragDollTimer <= 0.f) { + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Explode"); + } + } + } } } diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 946df1b4e..4e3114f8f 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -155,7 +155,7 @@ private: bool x6a1_28_ : 1; bool x6a1_29_isMoving : 1; bool x6a1_30_ : 1; - bool x6a1_31_ : 1; + bool x6a1_31_stopped : 1; bool x6a2_24_aggressive : 1; bool x6a2_25_aggressionChecked : 1; bool x6a2_26_jetpackActive : 1; @@ -187,9 +187,9 @@ private: zeus::CVector3f x870_ = zeus::skZero3f; zeus::CVector3f x87c_ = zeus::skZero3f; float x888_ = 10.f; - float x88c_ = 3.f; + float x88c_ragDollTimer = 3.f; TUniqueId x890_teamAiMgr = kInvalidUniqueId; - float x894_ = 1.f; + float x894_pitchBend = 1.f; float x898_ = 1.f; std::unique_ptr x89c_ragDoll; TUniqueId x8a0_patrolTarget = kInvalidUniqueId; From 6d757f021ffb7baafe721dbf7fa98119fb0c7399 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 18 Mar 2020 04:50:41 -0400 Subject: [PATCH 15/16] CFlyingPirateRagDoll: Implement Update --- Runtime/MP1/World/CFlyingPirate.cpp | 128 +++++++++++++++++++++------- Runtime/MP1/World/CFlyingPirate.hpp | 4 +- 2 files changed, 100 insertions(+), 32 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 78f288c03..29bfe838e 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -101,7 +101,8 @@ CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCo CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CFlyingPirate* actor, u16 w1, u16 w2) : CRagDoll(-actor->GetGravityConstant(), 3.f, 8.f, 0) -, x88_(w1) +, x6c_actor(actor) +, x88_sfx(w1) , x9c_(w2) , xa4_(actor->GetDestPos() - actor->GetTranslation()) , xb0_24_(false) { @@ -208,15 +209,85 @@ void CFlyingPirate::CFlyingPirateRagDoll::PreRender(const zeus::CVector3f& v, CM } void CFlyingPirate::CFlyingPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) { - if (x6c_actor->x6a1_30_) { + if (x6c_actor->x6a1_30_spinToDeath) { xa0_ = CSfxManager::AddEmitter(x9c_, x6c_actor->GetTranslation(), zeus::skZero3f, true, true, 0x7f, kInvalidAreaId); } CRagDoll::Prime(mgr, xf, mData); } void CFlyingPirate::CFlyingPirateRagDoll::Update(CStateManager& mgr, float dt, float waterTop) { - // TODO - CRagDoll::Update(mgr, dt, waterTop); + if (!x68_25_over) { + if (x6c_actor->x6a1_30_spinToDeath) { + x84_ -= dt; + const zeus::CVector3f& v9c = (x6c_actor->x2e0_destPos - x4_particles[14].GetPosition()).normalized(); + x74_ = zeus::CVector3f::slerp(x74_, v9c, zeus::degToRad(360.f * dt)); + x70_ = 25.f; + zeus::CVector3f mul = x70_ * x74_; + if (x84_ <= 0.f) { + x4_particles[14].Velocity() += 11.f * mul; + } else { + x4_particles[14].Velocity() += 25.f * mul; + } + zeus::CVector3f inv = -4 * mul; + x4_particles[4].Velocity() += -mul; + x4_particles[7].Velocity() += -mul; + x4_particles[10].Velocity() += inv; + x4_particles[10].Velocity() += inv; + x4_particles[1].Velocity() += -mul; + + x80_ = std::min(1000.f * dt + x80_, 1000.f); + + zeus::CVector3f vc0 = ((x4_particles[5].Position() - x4_particles[2].Position()) + .cross(x4_particles[8].Position() - x4_particles[2].Position()) + + 0.25f * (x4_particles[2].Position() - x4_particles[5].Position())) + .normalized() * + x80_; + x4_particles[2].Velocity() += vc0; + x4_particles[5].Velocity() += -vc0; + + x44_normalGravity = 0.f; + CSfxManager::UpdateEmitter(xa0_, x6c_actor->GetTranslation(), x58_averageVel, 1.f); + } + + // Collar-hips weighted center + zeus::CVector3f oldTorsoCenter = x4_particles[8].GetPosition() * 0.25f + x4_particles[11].GetPosition() * 0.25f + + x4_particles[0].GetPosition() * 0.5f; + oldTorsoCenter.z() = std::min({x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), + x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), + x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius()}); + + CRagDoll::Update(mgr, dt, waterTop); + + // Collar-hips weighted center + zeus::CVector3f newTorsoCenter = x4_particles[8].GetPosition() * 0.25f + x4_particles[11].GetPosition() * 0.25f + + x4_particles[0].GetPosition() * 0.5f; + newTorsoCenter.z() = std::min({x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), + x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), + x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius()}); + x6c_actor->SetTransform({zeus::CMatrix3f(false), newTorsoCenter}); + x6c_actor->SetVelocityWR((newTorsoCenter - oldTorsoCenter) * (1.f / dt)); + + if (x6c_actor->x6a1_30_spinToDeath) { + if ((newTorsoCenter - x6c_actor->GetDestPos()).magSquared() > 0.f) { + x6c_actor->x88c_ragDollTimer = 0.5f * dt; + } + } + + x8c_ -= dt; + if (x54_impactVel > 2.f && x8c_ < 0.f) { + if (xb0_24_ || (x6c_actor->GetTranslation() - x90_).magSquared() > 0.1f) { + float vol = std::min(10.f * x54_impactVel, 127.f) / 127.f; + CSfxManager::AddEmitter(x88_sfx, x6c_actor->GetTranslation(), zeus::skZero3f, vol, true, false, 0x7f, + kInvalidAreaId); + x8c_ = 0.222f * mgr.GetActiveRandom()->Float() + 0.222f; + xb0_24_ = false; + x90_ = x6c_actor->GetTranslation(); + } + } + } else { + x6c_actor->SetMomentumWR(zeus::skZero3f); + x6c_actor->Stop(); + } } CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, @@ -239,7 +310,7 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity , x6a1_27_(false) , x6a1_28_(false) , x6a1_29_isMoving(false) -, x6a1_30_(false) +, x6a1_30_spinToDeath(false) , x6a1_31_stopped(false) , x6a2_24_aggressive(false) , x6a2_25_aggressionChecked(false) @@ -296,7 +367,7 @@ void CFlyingPirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt x7ec_burstFire.SetBurstType(2); break; case EScriptObjectMessage::Falling: - if (x450_bodyController->GetPercentageFrozen() == 0.f && !x400_28_pendingMassiveDeath && !x6a1_30_) { + if (x450_bodyController->GetPercentageFrozen() == 0.f && !x400_28_pendingMassiveDeath && !x6a1_30_spinToDeath) { SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); } x7ec_burstFire.SetBurstType(0); @@ -859,7 +930,7 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co UpdateParticleEffects(mgr, 0.f, false); SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); } else { - x6a1_30_ = true; + x6a1_30_spinToDeath = true; x150_momentum.zeroOut(); } x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::Hurled, EKnockBackAnimationState::Hurled); @@ -892,7 +963,7 @@ void CFlyingPirate::KnockBack(const zeus::CVector3f& pos, CStateManager& mgr, co CSfxManager::AddEmitter(x568_data.xe6_deathSfx, GetTranslation(), zeus::skZero3f, 1.f, true, false, 0x7f, kInvalidAreaId); if (x400_27_fadeToDeath) { - x6a1_30_ = false; + x6a1_30_spinToDeath = false; UpdateParticleEffects(mgr, 0.f, false); SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); } @@ -1322,10 +1393,7 @@ void CFlyingPirate::DeliverGetUp() { } void CFlyingPirate::UpdateCanSeePlayer(CStateManager& mgr) { - int iVar3 = x7dc_; - int iVar1 = iVar3 / 7 + (iVar3 >> 0x1f) * 7; - // x7dc % 7 == ? - if (iVar3 == (iVar1 - (iVar1 >> 0x1f)) * 7) { + if (x7dc_ % 7 == 0) { bool bVar4 = true; const zeus::CVector3f& start = GetGunEyePos() - x34_transform.rightVector(); const zeus::CVector3f& end = GetAimPosition(mgr, 0.f); @@ -1608,13 +1676,7 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } if (x89c_ragDoll) { - if (!x89c_ragDoll->IsPrimed()) { - // SetMuted(true); ?? - SetMuted(false); - x89c_ragDoll->Prime(mgr, x34_transform, *x64_modelData); - SetTransform(zeus::CTransform::Translate(x34_transform.origin)); - x450_bodyController->SetPlaybackRate(0.f); - } else { + if (x89c_ragDoll->IsPrimed()) { float waterTop = -FLT_MAX; if (xc4_fluidId != kInvalidUniqueId) { if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) { @@ -1623,24 +1685,30 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } x89c_ragDoll->Update(mgr, dt * CalcDyingThinkRate(), waterTop); x64_modelData->AdvanceParticles(x34_transform, dt, mgr); + } else { + // SetMuted(true); ?? + SetMuted(false); + x89c_ragDoll->Prime(mgr, x34_transform, *x64_modelData); + SetTransform(zeus::CTransform::Translate(x34_transform.origin)); + x450_bodyController->SetPlaybackRate(0.f); } - if (x89c_ragDoll->IsPrimed() && !x400_27_fadeToDeath) { + + if (x89c_ragDoll->IsOver() && !x400_27_fadeToDeath) { x400_27_fadeToDeath = true; x3e8_alphaDelta = -1.f / 3.f; SetVelocityWR(zeus::skZero3f); x150_momentum.zeroOut(); x870_.zeroOut(); } - if (x89c_ragDoll) { - bool wasGtZero = x88c_ragDollTimer > 0.f; - x88c_ragDollTimer -= dt; - if (x88c_ragDollTimer < 2.f) { - if (x89c_ragDoll->GetImpactCount() > 2) { - x88c_ragDollTimer = std::min(0.1f, x88c_ragDollTimer); - } - if (wasGtZero && x88c_ragDollTimer <= 0.f) { - x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Explode"); - } + + bool wasGtZero = x88c_ragDollTimer > 0.f; + x88c_ragDollTimer -= dt; + if (x88c_ragDollTimer < 2.f) { + if (x89c_ragDoll->GetImpactCount() > 2) { + x88c_ragDollTimer = std::min(0.1f, x88c_ragDollTimer); + } + if (wasGtZero && x88c_ragDollTimer <= 0.f) { + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Explode"); } } } diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 4e3114f8f..233c537c0 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -57,7 +57,7 @@ private: zeus::CVector3f x74_ = zeus::skUp; float x80_ = 0.f; float x84_ = 5.f; - u16 x88_; + u16 x88_sfx; float x8c_ = 0.f; zeus::CVector3f x90_ = zeus::skZero3f; u16 x9c_; @@ -154,7 +154,7 @@ private: bool x6a1_27_ : 1; bool x6a1_28_ : 1; bool x6a1_29_isMoving : 1; - bool x6a1_30_ : 1; + bool x6a1_30_spinToDeath : 1; bool x6a1_31_stopped : 1; bool x6a2_24_aggressive : 1; bool x6a2_25_aggressionChecked : 1; From 815d83d8434bc119376a27eec5393484317c7cda Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 25 Mar 2020 02:57:57 -0400 Subject: [PATCH 16/16] CFlyingPirateRagDoll: Fix particles & length constraints --- Runtime/MP1/World/CFlyingPirate.cpp | 75 ++++++++++++++++------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index 29bfe838e..ab7635af1 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -63,6 +63,10 @@ constexpr std::array skParts{ "Collar"sv, "Head_1"sv, "R_shoulder"sv, "R_elbow"sv, "R_wrist"sv, "L_shoulder"sv, "L_elbow"sv, "L_wrist"sv, "R_hip"sv, "R_knee"sv, "R_ankle"sv, "L_hip"sv, "L_knee"sv, "L_ankle"sv, "rocket_LCTR"sv, }; + +constexpr std::array skRadii{ + 0.45f, 0.52f, 0.35f, 0.1f, 0.15f, 0.35f, 0.1f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f, 0.35f, +}; } // namespace CFlyingPirate::CFlyingPirateData::CFlyingPirateData(CInputStream& in, u32 propCount) @@ -108,15 +112,18 @@ CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CF , xb0_24_(false) { actor->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock, EMaterialTypes::GroundCollider, mgr); actor->HealthInfo(mgr)->SetHP(-1.f); - SetNumParticles(15); + SetNumParticles(skParts.size()); SetNumLengthConstraints(45); SetNumJointConstraints(4); - CAnimData* animData = actor->GetModelData()->GetAnimationData(); + CModelData* modelData = actor->GetModelData(); + CAnimData* animData = modelData->GetAnimationData(); + const zeus::CVector3f& scale = modelData->GetScale(); animData->BuildPose(); const zeus::CVector3f& center = actor->GetBoundingBox().center(); - for (const auto& part : skParts) { - const CSegId& id = animData->GetLocatorSegId(part); - AddParticle(id, center, center * animData->GetPose().GetOffset(id), 0.45f * center.z()); + for (size_t i = 0; i < skParts.size(); ++i) { + const CSegId& id = animData->GetLocatorSegId(skParts[i]); + AddParticle(id, center, actor->GetTransform() * (scale * animData->GetPose().GetOffset(id)), + skRadii[i] * scale.z()); } SatisfyWorldConstraintsOnConstruction(mgr); AddLengthConstraint(0, 1); @@ -129,6 +136,7 @@ CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CF AddLengthConstraint(5, 6); AddLengthConstraint(6, 7); AddLengthConstraint(2, 5); + AddLengthConstraint(2, 8); AddLengthConstraint(2, 11); AddLengthConstraint(5, 8); AddLengthConstraint(5, 11); @@ -151,13 +159,14 @@ CFlyingPirate::CFlyingPirateRagDoll::CFlyingPirateRagDoll(CStateManager& mgr, CF AddMinLengthConstraint(4, 5, 0.5f * x14_lengthConstraints[5].GetLength() + x14_lengthConstraints[9].GetLength()); AddMinLengthConstraint(7, 2, 0.5f * x14_lengthConstraints[7].GetLength() + x14_lengthConstraints[9].GetLength()); AddMinLengthConstraint(10, 8, x14_lengthConstraints[15].GetLength()); - AddMinLengthConstraint(11, 11, x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(13, 11, x14_lengthConstraints[17].GetLength()); AddMinLengthConstraint(9, 2, 0.707f * x14_lengthConstraints[15].GetLength() + x14_lengthConstraints[10].GetLength()); AddMinLengthConstraint(12, 5, 0.707f * x14_lengthConstraints[17].GetLength() + x14_lengthConstraints[13].GetLength()); AddMinLengthConstraint(9, 11, x14_lengthConstraints[15].GetLength()); AddMinLengthConstraint(12, 8, x14_lengthConstraints[17].GetLength()); AddMinLengthConstraint(10, 0, x14_lengthConstraints[2].GetLength() + x14_lengthConstraints[15].GetLength()); AddMinLengthConstraint(13, 0, x14_lengthConstraints[3].GetLength() + x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength()); AddMinLengthConstraint(9, 12, 0.5f * x14_lengthConstraints[14].GetLength()); AddMinLengthConstraint(10, 12, 0.5f * x14_lengthConstraints[14].GetLength()); AddMinLengthConstraint(13, 9, 0.5f * x14_lengthConstraints[14].GetLength()); @@ -195,9 +204,9 @@ void CFlyingPirate::CFlyingPirateRagDoll::PreRender(const zeus::CVector3f& v, CM skeletonRoot.x4_rotation = rootRot; const CRagDollParticle& head = x4_particles[1]; // Head_1 - const zeus::CVector3f& neckRestVec = layout.GetFromParentUnrotated(head.GetBone()); + const zeus::CVector3f& headRestVec = layout.GetFromParentUnrotated(head.GetBone()); poseBuilder.GetTreeMap()[head.GetBone()].x4_rotation = zeus::CQuaternion::shortestRotationArc( - neckRestVec, rootRot.inverse().transform(head.GetPosition() - collarPos)); + headRestVec, rootRot.inverse().transform(head.GetPosition() - collarPos)); BoneAlign(poseBuilder, layout, 3, 4, rootRot * BoneAlign(poseBuilder, layout, 2, 3, rootRot)); BoneAlign(poseBuilder, layout, 6, 7, rootRot * BoneAlign(poseBuilder, layout, 5, 6, rootRot)); @@ -721,7 +730,7 @@ void CFlyingPirate::Explode(CStateManager& mgr, EStateMsg msg, float) { void CFlyingPirate::MassiveDeath(CStateManager& mgr) { CExplosion* explosion = new CExplosion( static_cast>(x568_data.x90_particleGenDesc), mgr.AllocateUniqueId(), true, - {x4_areaId, CEntity::NullConnectionList}, "", x34_transform, 0, zeus::CVector3f(1.5f), zeus::skWhite); + {x4_areaId, CEntity::NullConnectionList}, "", GetTransform(), 0, zeus::CVector3f(1.5f), zeus::skWhite); mgr.AddObject(explosion); mgr.ApplyDamageToWorld(x8_uid, *this, GetTranslation(), x568_data.x9c_dInfo, CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); @@ -747,7 +756,7 @@ void CFlyingPirate::FireProjectile(CStateManager& mgr, float dt) { float fVar13 = xf.frontVector().dot(dist * (1.f / mag)); if (0.707f < fVar13 || (mag < 6.f && 0.5f < fVar13)) { if (LineOfSightTest(mgr, xf.origin, origin, {EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough})) { - origin += x34_transform.rotate(x7ec_burstFire.GetDistanceCompensatedError(mag, 6.f)); + origin += GetTransform().rotate(x7ec_burstFire.GetDistanceCompensatedError(mag, 6.f)); LaunchProjectile(zeus::lookAt(xf.origin, origin, zeus::skUp), mgr, 8, EProjectileAttrib::None, false, std::nullopt, -1, false, zeus::skOne3f); projectileFired = true; @@ -779,13 +788,13 @@ pas::EStepDirection CFlyingPirate::GetDodgeDirection(CStateManager& mgr, float a const zeus::CVector3f& dist = actor->GetTranslation() - GetTranslation(); float distMagSquared = dist.magSquared(); if (distMagSquared < argSquared) { - float rightVecMag = x34_transform.rightVector().magSquared(); + float rightVecMag = GetTransform().rightVector().magSquared(); if ((0.866f * distMagSquared) < rightVecMag || (0.f < rightVecMag && distMagSquared < 3.f)) { canDodgeRight = false; } else if (rightVecMag < 0.866f * -distMagSquared || (rightVecMag < 0.f && distMagSquared < 3.f)) { canDodgeLeft = false; } - float upVecMag = x34_transform.upVector().magSquared(); + float upVecMag = GetTransform().upVector().magSquared(); if ((0.866f * distMagSquared) < upVecMag || (0.f < upVecMag && distMagSquared < 3.f)) { canDodgeUp = false; } else if (upVecMag < 0.866f * -distMagSquared || (0.f < upVecMag && distMagSquared < 3.f)) { @@ -797,16 +806,16 @@ pas::EStepDirection CFlyingPirate::GetDodgeDirection(CStateManager& mgr, float a const zeus::CVector3f& center = GetBoundingBox().center(); if (canDodgeRight) { - canDodgeRight = LineOfSightTest(mgr, center, center + (arg * x34_transform.rightVector()), {}); + canDodgeRight = LineOfSightTest(mgr, center, center + (arg * GetTransform().rightVector()), {}); } if (canDodgeLeft) { - canDodgeLeft = LineOfSightTest(mgr, center, center - (arg * x34_transform.rightVector()), {}); + canDodgeLeft = LineOfSightTest(mgr, center, center - (arg * GetTransform().rightVector()), {}); } if (canDodgeUp) { - canDodgeUp = LineOfSightTest(mgr, center, center + (arg * x34_transform.upVector()), {}); + canDodgeUp = LineOfSightTest(mgr, center, center + (arg * GetTransform().upVector()), {}); } if (canDodgeDown) { - canDodgeDown = LineOfSightTest(mgr, center, center - (arg * x34_transform.upVector()), {}); + canDodgeDown = LineOfSightTest(mgr, center, center - (arg * GetTransform().upVector()), {}); } if ((canDodgeLeft || canDodgeRight) && (canDodgeUp || canDodgeDown)) { @@ -827,7 +836,7 @@ pas::EStepDirection CFlyingPirate::GetDodgeDirection(CStateManager& mgr, float a } if (canDodgeUp && canDodgeDown) { const zeus::CVector3f& target = GetTargetPos(mgr); - if (target.z() - (x34_transform.origin.z() + x568_data.x8c_flyingHeight) <= 0.f) { + if (target.z() - (GetTranslation().z() + x568_data.x8c_flyingHeight) <= 0.f) { canDodgeUp = false; } else { canDodgeDown = false; @@ -868,7 +877,7 @@ void CFlyingPirate::GetUp(CStateManager& mgr, EStateMsg msg, float) { } else if (msg == EStateMsg::Update) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::LieOnGround) { // will always return Success? - CPathFindSearch::EResult result = x6a8_pathFindSearch.Search(x34_transform.origin, x34_transform.origin); + CPathFindSearch::EResult result = x6a8_pathFindSearch.Search(GetTranslation(), GetTranslation()); if (result == CPathFindSearch::EResult::NoSourcePoint) { x401_30_pendingDeath = true; } @@ -1034,7 +1043,7 @@ void CFlyingPirate::Lurk(CStateManager& mgr, EStateMsg msg, float) { x2e0_destPos = GetTargetPos(mgr); zeus::CVector3f dist = x2e0_destPos - GetTranslation(); dist.z() = 0.f; - if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { + if (GetTransform().frontVector().dot(dist.normalized()) < 0.8f) { x32c_animState = EAnimState::Ready; } } @@ -1071,7 +1080,7 @@ void CFlyingPirate::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { if (search->GetResult() == CPathFindSearch::EResult::Success && search->GetCurrentWaypoint() < search->GetWaypoints().size() - 1) { zeus::CVector3f out = GetTranslation(); - const zeus::CVector3f& front = out + x34_transform.frontVector(); + const zeus::CVector3f& front = out + GetTransform().frontVector(); search->GetSplinePointWithLookahead(out, front, 3.f); if (search->SegmentOver(out)) { search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); @@ -1188,7 +1197,7 @@ void CFlyingPirate::Retreat(CStateManager& mgr, EStateMsg msg, float arg) { CPathFindSearch* const search = GetSearchPath(); if (search->GetCurrentWaypoint() < search->GetWaypoints().size() - 1) { const zeus::CVector3f& origin = GetTranslation(); - zeus::CVector3f out = origin + x34_transform.frontVector(); + zeus::CVector3f out = origin + GetTransform().frontVector(); search->GetSplinePointWithLookahead(out, origin, 3.f); if (search->SegmentOver(out)) { search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); @@ -1243,7 +1252,7 @@ bool CFlyingPirate::ShouldAttack(CStateManager& mgr, float) { bool CFlyingPirate::ShouldDodge(CStateManager& mgr, float) { if (x6a1_28_ || x6a1_25_) return false; - return 0.f < (GetTargetPos(mgr) - x34_transform.origin).dot(x34_transform.frontVector()) && + return 0.f < (GetTargetPos(mgr) - GetTranslation()).dot(GetTransform().frontVector()) && (x854_ < 0.33f || x858_ < 0.33f) && x7d8_ < 0.5f; } @@ -1318,7 +1327,7 @@ bool CFlyingPirate::ShouldSpecialAttack(CStateManager& mgr, float) { bool CFlyingPirate::SpotPlayer(CStateManager& mgr, float) { const zeus::CVector3f& dir = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetGunEyePos(); - return dir.magnitude() * x3c4_detectionAngle < dir.dot(x34_transform.frontVector()); + return dir.magnitude() * x3c4_detectionAngle < dir.dot(GetTransform().frontVector()); } bool CFlyingPirate::Stuck(CStateManager& mgr, float arg) { @@ -1395,7 +1404,7 @@ void CFlyingPirate::DeliverGetUp() { void CFlyingPirate::UpdateCanSeePlayer(CStateManager& mgr) { if (x7dc_ % 7 == 0) { bool bVar4 = true; - const zeus::CVector3f& start = GetGunEyePos() - x34_transform.rightVector(); + const zeus::CVector3f& start = GetGunEyePos() - GetTransform().rightVector(); const zeus::CVector3f& end = GetAimPosition(mgr, 0.f); const CMaterialList matList(EMaterialTypes::Player, EMaterialTypes::ProjectilePassthrough); if (LineOfSightTest(mgr, start, end, matList)) { @@ -1471,7 +1480,7 @@ void CFlyingPirate::TurnAround(CStateManager& mgr, EStateMsg msg, float) { x2e0_destPos = GetTargetPos(mgr); zeus::CVector3f dist = x2e0_destPos - GetTranslation(); dist.z() = 0.f; - if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { + if (GetTransform().frontVector().dot(dist.normalized()) < 0.8f) { x32c_animState = EAnimState::Ready; } } else if (msg == EStateMsg::Update) { @@ -1492,7 +1501,7 @@ void CFlyingPirate::Walk(CStateManager& mgr, EStateMsg msg, float) { x2e0_destPos = GetTargetPos(mgr); zeus::CVector3f dist = x2e0_destPos - GetTranslation(); dist.z() = 0.f; - if (x34_transform.frontVector().dot(dist.normalized()) < 0.8f) { + if (GetTransform().frontVector().dot(dist.normalized()) < 0.8f) { x32c_animState = EAnimState::Ready; } } @@ -1622,7 +1631,7 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } else { x450_bodyController->GetCommandMgr().DeliverCmd(CBCAdditiveAimCmd()); x450_bodyController->GetCommandMgr().DeliverAdditiveTargetVector( - x34_transform.transposeRotate(GetTargetPos(mgr) - GetTranslation())); + GetTransform().transposeRotate(GetTargetPos(mgr) - GetTranslation())); } if (0.f < x870_.magSquared()) { float mag = x870_.magnitude(); @@ -1658,16 +1667,16 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } zeus::CVector3f v1d0 = std::min(0.333f * x87c_.magnitude(), 0.333f) * vf8; const zeus::CVector3f& v104 = (zeus::skUp + v1d0).normalized(); - const zeus::CVector3f& v110 = x34_transform.upVector(); + const zeus::CVector3f& v110 = GetTransform().upVector(); float f26c = std::abs(zeus::CVector3f::getAngleDiff(v110, v104)); if (f26c > 0.f) { float f1f4 = std::min(f26c, 30.f * zeus::degToRad(dt)); // ? float f200 = f26c - f1f4; zeus::CVector3f v1dc = (f1f4 * v104 + (f200 * v110)).normalized(); - zeus::CVector3f v128 = x34_transform.frontVector().cross(v1dc); + zeus::CVector3f v128 = GetTransform().frontVector().cross(v1dc); zeus::CVector3f v20c = v1dc.cross(v128).normalized(); zeus::CVector3f v128_2 = v20c.cross(v1dc); - SetTransform({v128_2, v20c, v1dc, x34_transform.origin}); + SetTransform({v128_2, v20c, v1dc, GetTranslation()}); } if (!x450_bodyController->IsFrozen()) { @@ -1684,12 +1693,12 @@ void CFlyingPirate::Think(float dt, CStateManager& mgr) { } } x89c_ragDoll->Update(mgr, dt * CalcDyingThinkRate(), waterTop); - x64_modelData->AdvanceParticles(x34_transform, dt, mgr); + x64_modelData->AdvanceParticles(GetTransform(), dt, mgr); } else { // SetMuted(true); ?? SetMuted(false); - x89c_ragDoll->Prime(mgr, x34_transform, *x64_modelData); - SetTransform(zeus::CTransform::Translate(x34_transform.origin)); + x89c_ragDoll->Prime(mgr, GetTransform(), *x64_modelData); + SetTransform(zeus::CTransform::Translate(GetTranslation())); x450_bodyController->SetPlaybackRate(0.f); }