From 802849c71133ff61f9d75e6d2affe0b49382ce07 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sat, 4 Apr 2020 01:19:03 -0400 Subject: [PATCH] CPhazonPool: Implementation --- Runtime/MP1/World/CPhazonPool.cpp | 266 +++++++++++++++++++++++++++++- Runtime/MP1/World/CPhazonPool.hpp | 51 ++++-- 2 files changed, 297 insertions(+), 20 deletions(-) diff --git a/Runtime/MP1/World/CPhazonPool.cpp b/Runtime/MP1/World/CPhazonPool.cpp index fd1c4954f..5c24e75f3 100644 --- a/Runtime/MP1/World/CPhazonPool.cpp +++ b/Runtime/MP1/World/CPhazonPool.cpp @@ -1,10 +1,272 @@ #include "Runtime/MP1/World/CPhazonPool.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Runtime/CStateManager.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/Graphics/CBooRenderer.hpp" + +#include "TCastTo.hpp" // Generated file, do not modify include path + namespace urde::MP1 { CPhazonPool::CPhazonPool(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active, CAssetId w1, CAssetId w2, CAssetId w3, CAssetId w4, u32 p11, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool p15, float p16, float p17, float p18, float p19) -: CScriptTrigger(uid, name, info, xf.origin, zeus::skNullBox, dInfo, orientedForce, triggerFlags, active, false, - false) {} +: CScriptTrigger(uid, name, info, xf.origin, zeus::skNullBox, dInfo, orientedForce, triggerFlags, active, false, false) +, x168_modelData1(std::make_unique(CStaticRes{w1, zeus::skOne3f})) +, x16c_modelData2(std::make_unique(CStaticRes{w2, zeus::skOne3f})) +, x190_scale(scale) +, x19c_(p16) +, x1a0_(p16) +, x1bc_(p17) +, x1c0_(p19) +, x1c8_(p18) +, x1d8_(p11) +, x1e0_24_(p15) +, x1e0_25_(false) { + if (w3.IsValid()) { + x170_elementGen1 = std::make_unique(g_SimplePool->GetObj(SObjectTag{SBIG('PART'), w3})); + x170_elementGen1->SetParticleEmission(false); + } + if (w4.IsValid()) { + x174_elementGen2 = std::make_unique(g_SimplePool->GetObj(SObjectTag{SBIG('PART'), w4})); + x174_elementGen2->SetGlobalScale(x190_scale); + x174_elementGen2->SetParticleEmission(false); + } +} + +void CPhazonPool::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CPhazonPool::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Activate: + case EScriptObjectMessage::Open: + UpdateParticleGens(mgr); + break; + case EScriptObjectMessage::Close: + if (!x1e0_25_) { + x1e0_25_ = true; + x1c4_ = 0.f; + SetEmitParticles(false); + } + break; + case EScriptObjectMessage::Decrement: + if (x1dc_ == 2) { + x1cc_ += 1.f; + } + break; + case EScriptObjectMessage::Registered: + if (x170_elementGen1) { + x170_elementGen1->SetGlobalTranslation(GetTranslation()); + } + if (x168_modelData1) { + x178_bounds = x168_modelData1->GetBounds(); + } else { + x178_bounds = zeus::CAABox{0.5f * -x190_scale, 0.5f * x190_scale}; + } + x130_bounds = zeus::CAABox{x178_bounds.min * x190_scale, x178_bounds.max * x190_scale}; + break; + case EScriptObjectMessage::Deleted: + RemoveInhabitants(mgr); + break; + default: + break; + } + CScriptTrigger::AcceptScriptMsg(msg, uid, mgr); +} + +void CPhazonPool::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (GetActive()) { + if (x170_elementGen1) { + g_Renderer->AddParticleGen(*x170_elementGen1); + } + if (x174_elementGen2) { + g_Renderer->AddParticleGen(*x174_elementGen2); + } + } + CActor::AddToRenderer(frustum, mgr); + CActor::EnsureRendered(mgr); +} + +std::optional CPhazonPool::GetTouchBounds() const { return CScriptTrigger::GetTouchBounds(); } + +void CPhazonPool::Render(const CStateManager& mgr) const { + CActor::Render(mgr); + bool discard = x1a4_ < 0.25f; + const CModelFlags flags{5, 0, static_cast(discard ? 3 : 0), zeus::CColor{1.f, x1a4_}}; + if (x168_modelData1) { + x168_modelData1->Render(mgr, GetTransform() * zeus::CTransform::RotateZ(x1ac_rotZ), nullptr, flags); + } + if (x16c_modelData2) { + const zeus::CTransform rot = zeus::CTransform::RotateZ(x1ac_rotZ) * zeus::CTransform::RotateX(x1ac_rotZ) * + zeus::CTransform::RotateY(x1a8_rotY); + x16c_modelData2->Render(mgr, GetTransform() * rot, nullptr, flags); + } +} + +void CPhazonPool::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + return; + } + + CScriptTrigger::Think(dt, mgr); + UpdateInhabitants(mgr); + const zeus::CVector3f scale = (x1dc_ == 1 ? x1a4_ : 1.f) * x190_scale; + SetTransform({zeus::CMatrix3f{scale}, GetTranslation()}); + x130_bounds = zeus::CAABox{x178_bounds.min * scale, x178_bounds.max * scale}; + x1a8_rotY += dt * x1b0_; + x1ac_rotZ += dt * x1b4_; + if (x1a8_rotY > zeus::degToRad(360.f)) { + x1a8_rotY = 0.f; + } + if (x1ac_rotZ > zeus::degToRad(360.f)) { + x1ac_rotZ = 0.f; + } + if (x170_elementGen1) { + x170_elementGen1->SetModulationColor(zeus::CColor{x1a4_, x1a4_, x1a4_, x1a4_}); + x170_elementGen1->SetGlobalScale(zeus::CVector3f{scale.x()}); + x170_elementGen1->Update(dt); + } + if (x174_elementGen2) { + x174_elementGen2->Update(dt); + } + + bool shouldFree = false; + if (x1dc_ == 1) { + x1d4_ += dt; + if (x1d4_ > 2.f) { + x1d4_ = 2.f; + x1a4_ += dt * x1b8_; + if (x1a4_ > 1.f) { + x1a4_ = 1.f; + x1dc_ = 2; + SetEmitParticles(true); + if (x174_elementGen2) { + x174_elementGen2->SetParticleEmission(true); + } + } + } + } else if (x1dc_ == 2) { + float dVar5 = 0.f; + if (x1e0_24_ || x1e0_25_) { + x1c4_ -= dt; + if (x1c4_ <= 0.f) { + x1c4_ = 0.f; + dVar5 = dt; + } + x1a0_ -= x1bc_ * (dt * x1cc_) + dVar5; + x1a4_ = x1a0_ / x19c_; + if (x1a4_ < 0.001f) { + if (x1e0_24_) { + shouldFree = true; + } else { + SetCallTouch(false); + if (x1e0_25_) { + x1dc_ = 0; + SetActive(false); + } else { + x1dc_ = 3; + x1d0_ = x1c8_; + } + } + SetEmitParticles(false); + } + x1cc_ = 0.f; + } + } else if (x1dc_ == 3) { + x1d0_ -= dt; + if (x1d0_ <= 0.f) { + x1d0_ = 0.f; + UpdateParticleGens(mgr); + } + } + if (shouldFree) { + mgr.FreeScriptObject(GetUniqueId()); + } +} + +void CPhazonPool::Touch(CActor& actor, CStateManager& mgr) { + if (!GetActive() || x1dc_ != 2) { + return; + } + + CScriptTrigger::Touch(actor, mgr); + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::PlatformSlave)) { + return; + } + + for (auto& entry : x150_inhabitants) { + if (entry.first == actor.GetUniqueId()) { + entry.second = true; + return; + } + } + + if (actor.GetTouchBounds().has_value()) { + x150_inhabitants.emplace_back(actor.GetUniqueId(), true); + mgr.SendScriptMsg(&actor, GetUniqueId(), EScriptObjectMessage::AddPhazonPoolInhabitant); + } +} + +void CPhazonPool::UpdateInhabitants(CStateManager& mgr) { + auto iter = x150_inhabitants.begin(); + const auto end = x150_inhabitants.end(); + while (iter != end) { + TCastToPtr actor = mgr.ObjectById(iter->first); + if (actor) { + if (actor->GetTouchBounds().has_value()) { + (void)GetTriggerBoundsWR(); // unused? + } + } + if (!actor || !iter->second) { + iter = x150_inhabitants.erase(iter); + if (actor) { + mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::RemovePhazonPoolInhabitant); + } + } else { + mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::UpdatePhazonPoolInhabitant); + iter->second = false; + iter++; + } + } +} + +void CPhazonPool::UpdateParticleGens(CStateManager& mgr) { + x1b0_ = mgr.GetActiveRandom()->Range(-0.5f, 0.5f); + x1b4_ = mgr.GetActiveRandom()->Range(-1.f, 1.f); + x1b8_ = mgr.GetActiveRandom()->Range(0.25f, 2.f); + x1cc_ = 0.f; + x1d4_ = 0.f; + x1c4_ = x1c0_; + x1a0_ = x19c_; + x1dc_ = 1; + x1e0_25_ = false; + if (x170_elementGen1) { + x170_elementGen1->SetGlobalTranslation(GetTranslation()); + x170_elementGen1->SetParticleEmission(false); + } + if (x174_elementGen2) { + x174_elementGen2->SetGlobalTranslation(GetTranslation()); + x174_elementGen2->SetParticleEmission(true); + } +} + +void CPhazonPool::RemoveInhabitants(CStateManager& mgr) { + auto iter = x150_inhabitants.begin(); + const auto end = x150_inhabitants.end(); + while (iter != end) { + if (TCastToPtr actor = mgr.ObjectById(iter->first)) { + iter = x150_inhabitants.erase(iter); + mgr.SendScriptMsg(actor, GetUniqueId(), EScriptObjectMessage::RemovePhazonPoolInhabitant); + } else { + iter++; + } + } +} + +void CPhazonPool::SetEmitParticles(bool val) { + if (x170_elementGen1) { + x170_elementGen1->SetParticleEmission(val); + } +} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CPhazonPool.hpp b/Runtime/MP1/World/CPhazonPool.hpp index f00f828d7..328b365a2 100644 --- a/Runtime/MP1/World/CPhazonPool.hpp +++ b/Runtime/MP1/World/CPhazonPool.hpp @@ -7,36 +7,51 @@ namespace urde::MP1 { class CPhazonPool : public CScriptTrigger { private: - u32 x164_; - std::unique_ptr x168_; - std::unique_ptr x16c_; - std::unique_ptr x170_; - std::unique_ptr x174_; - zeus::CAABox x178_; - zeus::CVector3f x190_; + std::list> x150_inhabitants; + std::unique_ptr x168_modelData1; + std::unique_ptr x16c_modelData2; + std::unique_ptr x170_elementGen1; + std::unique_ptr x174_elementGen2; + zeus::CAABox x178_bounds = zeus::skNullBox; + zeus::CVector3f x190_scale; float x19c_; float x1a0_; - float x1a4_; - float x1a8_; - float x1ac_; - float x1b0_; - float x1b4_; - float x1b8_; + float x1a4_ = 0.001f; + float x1a8_rotY = 0.f; + float x1ac_rotZ = 0.f; + float x1b0_ = 0.f; + float x1b4_ = 0.f; + float x1b8_ = 0.f; float x1bc_; float x1c0_; - float x1c4_; + float x1c4_ = 0.f; float x1c8_; - float x1cc_; - float x1d0_; - float x1d4_; + float x1cc_ = 0.f; + float x1d0_ = 0.f; + float x1d4_ = 0.f; u32 x1d8_; - u32 x1dc_; + u32 x1dc_ = 0; bool x1e0_24_ : 1; + bool x1e0_25_ : 1; public: CPhazonPool(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active, CAssetId w1, CAssetId w2, CAssetId w3, CAssetId w4, u32 p11, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool p15, float p16, float p17, float p18, float p19); + + void Accept(IVisitor& visitor) override; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override; + [[nodiscard]] std::optional GetTouchBounds() const override; + void Render(const CStateManager& mgr) const override; + void Think(float dt, CStateManager& mgr) override; + void Touch(CActor& actor, CStateManager& mgr) override; + +private: + void UpdateInhabitants(CStateManager& mgr); + void UpdateParticleGens(CStateManager& mgr); + void RemoveInhabitants(CStateManager& mgr); + void SetEmitParticles(bool val); }; } // namespace urde::MP1