From 81f1e22fc25e3338185d8af1aeb822cd4953cc18 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 9 May 2019 19:33:56 -0700 Subject: [PATCH] More CFlameThrower imps, implement `CScriptSpecialFunction::ThinkChaffTarget` and `CScriptSpecialFunction::ObjectFollowObject` --- Runtime/Particle/CFlameWarp.hpp | 6 ++ Runtime/Weapon/CEnergyProjectile.hpp | 1 + Runtime/Weapon/CFlameThrower.cpp | 75 +++++++++++++++++++++++- Runtime/Weapon/CFlameThrower.hpp | 6 +- Runtime/World/CScriptSpecialFunction.cpp | 64 +++++++++++++++++++- 5 files changed, 146 insertions(+), 6 deletions(-) diff --git a/Runtime/Particle/CFlameWarp.hpp b/Runtime/Particle/CFlameWarp.hpp index ea3d9e215..e3789af42 100644 --- a/Runtime/Particle/CFlameWarp.hpp +++ b/Runtime/Particle/CFlameWarp.hpp @@ -34,5 +34,11 @@ public: void Activate(bool val) { xa0_24_activated = val; } bool IsActivated() { return xa0_24_activated; } FourCC Get4CharID() { return FOURCC('FWRP'); } + void ResetPosition(const zeus::CVector3f& pos) { + for (auto& vec : x4_vecs) { + vec = pos; + } + xa0_26_processed = false; + } }; } // namespace urde diff --git a/Runtime/Weapon/CEnergyProjectile.hpp b/Runtime/Weapon/CEnergyProjectile.hpp index 5efb97b9a..3cf88dcb4 100644 --- a/Runtime/Weapon/CEnergyProjectile.hpp +++ b/Runtime/Weapon/CEnergyProjectile.hpp @@ -44,6 +44,7 @@ public: void Touch(CActor& act, CStateManager& mgr); virtual bool Explode(const zeus::CVector3f& pos, const zeus::CVector3f& normal, EWeaponCollisionResponseTypes type, CStateManager& mgr, const CDamageVulnerability& dVuln, TUniqueId hitActor); + void Set3d0_26(bool v) { x3d0_26_ = v; } }; } // namespace urde diff --git a/Runtime/Weapon/CFlameThrower.cpp b/Runtime/Weapon/CFlameThrower.cpp index 7987c438e..facce1aa8 100644 --- a/Runtime/Weapon/CFlameThrower.cpp +++ b/Runtime/Weapon/CFlameThrower.cpp @@ -1,7 +1,9 @@ #include "Weapon/CFlameThrower.hpp" #include "Weapon/CFlameInfo.hpp" +#include "World/CGameLight.hpp" #include "Particle/CElementGen.hpp" #include "Graphics/CBooRenderer.hpp" +#include "CStateManager.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" #include "TCastTo.hpp" @@ -33,15 +35,43 @@ CFlameThrower::CFlameThrower(const TToken& wDesc, std::strin void CFlameThrower::Accept(IVisitor& visitor) { visitor.Visit(this); } +void CFlameThrower::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Registered) { + xe6_27_thermalVisorFlags |= 2; + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + } else if (msg == EScriptObjectMessage::Deleted) { + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + DeleteProjectileLight(mgr); + } + + CGameProjectile::AcceptScriptMsg(msg, uid, mgr); +} + void CFlameThrower::SetTransform(const zeus::CTransform& xf, float) { x2e8_ = xf; } -void CFlameThrower::Reset(CStateManager&, bool) {} +void CFlameThrower::Reset(CStateManager& mgr, bool resetWarp) { + SetFlameLightActive(mgr, false); + if (resetWarp) { + SetActive(false); + x400_25_ = false; + x3f0_flameState = 0; + x330_ = 0.f; + x334_ = 0.f; + x318_ = zeus::skNullBox; + x348_flameGen->SetParticleEmission(false); + x34c_.ResetPosition(x2e8_.origin); + } else { + x348_flameGen->SetParticleEmission(false); + x400_25_ = false; + x3f0_flameState = 3; + } +} void CFlameThrower::Fire(const zeus::CTransform&, CStateManager& mgr, bool) { SetActive(true); x400_25_ = true; x400_24_ = true; - x3f0_ = 1; + x3f0_flameState = 1; CreateFlameParticles(mgr); } @@ -59,4 +89,45 @@ void CFlameThrower::AddToRenderer(const zeus::CFrustum&, const CStateManager& mg g_Renderer->AddParticleGen(*x348_flameGen); EnsureRendered(mgr, x2e8_.origin, GetRenderBounds()); } + +void CFlameThrower::SetFlameLightActive(CStateManager& mgr, bool active) { + if (x2c8_projectileLight == kInvalidUniqueId) + return; + + if (TCastToPtr light = mgr.ObjectById(x2c8_projectileLight)) + light->SetActive(active); +} + +void CFlameThrower::UpdateFlameState(float dt, CStateManager& mgr) { + switch(x3f0_flameState) { + case 1: + x3f0_flameState = 2; + break; + case 3: + x334_ += 4.f * dt; + if (x334_ > 1.f) { + x334_ = 1.f; + x3f0_flameState = 4; + x400_24_ = false; + } + break; + case 4: + x330_ += dt; + if (x330_ > 0.1f && x348_flameGen && x348_flameGen->GetParticleCountAll() == 0) { + x3f0_flameState = 0; + Reset(mgr, true); + } + break; + default: + break; + } +} + +void CFlameThrower::Think(float dt, CStateManager& mgr) { + CWeapon::Think(dt, mgr); + if (!GetActive()) + return; + + UpdateFlameState(dt, mgr); +} } // namespace urde diff --git a/Runtime/Weapon/CFlameThrower.hpp b/Runtime/Weapon/CFlameThrower.hpp index 8a114e7f8..02727f153 100644 --- a/Runtime/Weapon/CFlameThrower.hpp +++ b/Runtime/Weapon/CFlameThrower.hpp @@ -17,7 +17,7 @@ class CFlameThrower : public CGameProjectile { TToken x33c_flameDesc; std::unique_ptr x348_flameGen; CFlameWarp x34c_; - u32 x3f0_; + u32 x3f0_flameState; CAssetId x3f4_; s16 x3f8_; CAssetId x3fc_; @@ -33,6 +33,8 @@ class CFlameThrower : public CGameProjectile { }; void CreateFlameParticles(CStateManager&); + void SetFlameLightActive(CStateManager&, bool); + void UpdateFlameState(float, CStateManager&); public: CFlameThrower(const TToken& wDesc, std::string_view name, EWeaponType wType, const CFlameInfo& flameInfo, const zeus::CTransform& xf, EMaterialTypes matType, @@ -40,6 +42,8 @@ public: CAssetId w2, s16 sId, CAssetId w3); void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; void SetTransform(const zeus::CTransform& xf, float); void Reset(CStateManager&, bool); diff --git a/Runtime/World/CScriptSpecialFunction.cpp b/Runtime/World/CScriptSpecialFunction.cpp index 6bb6c34e3..42ded1b7f 100644 --- a/Runtime/World/CScriptSpecialFunction.cpp +++ b/Runtime/World/CScriptSpecialFunction.cpp @@ -5,6 +5,7 @@ #include "Graphics/CTexture.hpp" #include "World/CActorParameters.hpp" #include "World/CPlayer.hpp" +#include "Weapon/CEnergyProjectile.hpp" #include "GameGlobalObjects.hpp" #include "CMemoryCardSys.hpp" #include "CGameState.hpp" @@ -569,7 +570,8 @@ void CScriptSpecialFunction::ThinkObjectFollowLocator(float, CStateManager& mgr) TUniqueId followerAct = kInvalidUniqueId; TUniqueId followedAct = kInvalidUniqueId; for (const SConnection& conn : x20_conns) { - if (conn.x0_state != EScriptObjectState::Play) + if (conn.x0_state != EScriptObjectState::Play || (conn.x4_msg != EScriptObjectMessage::Activate && + conn.x4_msg != EScriptObjectMessage::Deactivate)) continue; auto search = mgr.GetIdListForScript(conn.x8_objId); @@ -593,9 +595,65 @@ void CScriptSpecialFunction::ThinkObjectFollowLocator(float, CStateManager& mgr) toAct->SetTransform(fromAct->GetTransform() * fromAct->GetScaledLocatorTransform(xec_locatorName)); } -void CScriptSpecialFunction::ThinkObjectFollowObject(float, CStateManager&) {} +void CScriptSpecialFunction::ThinkObjectFollowObject(float, CStateManager& mgr) { + TUniqueId followerAct = kInvalidUniqueId; + TUniqueId followedAct = kInvalidUniqueId; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || (conn.x4_msg != EScriptObjectMessage::Activate && + conn.x4_msg != EScriptObjectMessage::Deactivate)) + continue; -void CScriptSpecialFunction::ThinkChaffTarget(float, CStateManager&) {} + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToConstPtr act = mgr.GetObjectById(it->second)) { + if (conn.x4_msg == EScriptObjectMessage::Activate && act->GetActive()) { + followedAct = it->second; + } else if (conn.x4_msg == EScriptObjectMessage::Deactivate) { + followerAct = it->second; + } + } + } + } + + TCastToConstPtr followed = mgr.GetObjectById(followedAct); + TCastToPtr follower = mgr.ObjectById(followerAct); + if (followed && follower) + follower->SetTransform(followed->GetTransform()); +} + +void CScriptSpecialFunction::ThinkChaffTarget(float dt, CStateManager& mgr) { + zeus::CAABox box(5.f - GetTranslation(), 5.f + GetTranslation()); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, box, CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}), nullptr); + CCameraFilterPassPoly& filter = mgr.GetCameraFilterPass(7); + + for (TUniqueId uid : nearList) { + if (TCastToPtr proj = mgr.ObjectById(uid)) { + if (proj->GetHomingTargetId() == GetUniqueId()) { + proj->Set3d0_26(true); + if (mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) { + mgr.GetPlayer().SetHudDisable(x100_float2, 0.5f, 2.5f); + filter.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, zeus::skWhite, {}); + filter.DisableFilter(0.1f); + } + } + } + } + + x194_ = zeus::max(0.f, x194_ - dt); + if (x194_ != 0.f && mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) { + float intfMag = x104_float3 * (0.5f + ((0.5f + x194_) / xfc_float1); + if (x194_ < 1.f) + intfMag *= x194_; + + mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), intfMag, .5f); + + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + mgr.GetPlayer().AddOrbitDisableSource(mgr, GetUniqueId()). + else + mgr.GetPlayer().RemoveOrbitDisableSource(GetUniqueId()); + } +} void CScriptSpecialFunction::ThinkActorScale(float dt, CStateManager& mgr) { float deltaScale = dt * xfc_float1;