From 54adbcdce8bf98ad8570e26a7ef04705533e7c34 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Thu, 1 Oct 2026 15:47:10 -0500 Subject: [PATCH] refactor(component): proximity monitor and movement AI load their own rows The ProximityMonitorComponent row's radii and the MovementAIComponent row (with the level's wanderRadius over it) move out of Entity::Initialize into each component's LoadDataFromTemplate / LoadConfigData. Same components and bytes for every LOT. Co-Authored-By: Claude Opus 5.5 --- dGame/Entity.cpp | 39 ++----------------- dGame/dComponents/MovementAIComponent.cpp | 33 +++++++++++++--- dGame/dComponents/MovementAIComponent.h | 1 + .../dComponents/ProximityMonitorComponent.cpp | 18 +++++++++ dGame/dComponents/ProximityMonitorComponent.h | 2 + 5 files changed, 52 insertions(+), 41 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index a2d2a1e30..8c55e3644 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -470,47 +470,14 @@ void Entity::Initialize() { } case eReplicaComponentType::PROXIMITY_MONITOR: { const auto proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR); - if (proximityMonitorID > 0) { - auto* const proxCompTable = CDClientManager::GetTable(); - const auto proxCompData = proxCompTable->Query([proximityMonitorID](const CDProximityMonitorComponent& entry) { return (entry.id == proximityMonitorID); }); - if (proxCompData.size() > 0) { - // "small,large"; one value (LOT 9833: "4") is both - const auto radii = GeneralUtils::SplitString(proxCompData[0].Proximities, ','); - const auto small = radii.empty() ? std::nullopt : GeneralUtils::TryParse(radii[0]); - const auto large = radii.size() > 1 ? GeneralUtils::TryParse(radii[1]) : small; - if (small && large) AddComponent(proximityMonitorID, *small, *large); - } - } + if (proximityMonitorID > 0) AddComponent(proximityMonitorID); break; } case eReplicaComponentType::MOVEMENT_AI: { const int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI); if (movementAIID > 0) { - CDMovementAIComponentTable* moveAITable = CDClientManager::GetTable(); - std::vector moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); }); - - if (moveAIComp.size() > 0) { - MovementAIInfo moveInfo{ - .movementType = moveAIComp[0].MovementType, - .wanderRadius = moveAIComp[0].WanderRadius, - .wanderSpeed = moveAIComp[0].WanderSpeed, - .wanderChance = moveAIComp[0].WanderChance, - .wanderDelayMin = moveAIComp[0].WanderDelayMin, - .wanderDelayMax = moveAIComp[0].WanderDelayMax, - }; - - const bool useWanderDB = GetVar(u"usewanderdb"); - - if (!useWanderDB) { - const auto wanderOverride = GetVarAs(u"wanderRadius"); - - if (wanderOverride != 0.0f) { - moveInfo.wanderRadius = wanderOverride; - } - } - - AddComponent(movementAIID, moveInfo); - } + // Its row and the level's wanderRadius load in the component + AddComponent(movementAIID, MovementAIInfo{}); } else if (petComponentID > 0 || combatAiID > 0 && BaseCombatAIComponent::TetherSpeedOf(combatAiID) > 0) { MovementAIInfo moveInfo{ .movementType = "", diff --git a/dGame/dComponents/MovementAIComponent.cpp b/dGame/dComponents/MovementAIComponent.cpp index 4bac3562e..da5536558 100644 --- a/dGame/dComponents/MovementAIComponent.cpp +++ b/dGame/dComponents/MovementAIComponent.cpp @@ -1,4 +1,6 @@ #include "MovementAIComponent.h" +#include "CDClientManager.h" +#include "CDMovementAIComponentTable.h" #include #include @@ -46,11 +48,6 @@ MovementAIComponent::MovementAIComponent(Entity* parent, const int32_t component m_BaseCombatAI = m_Parent->GetComponent(); - //Try and fix the insane values: - if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f; - if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f; - if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f; - m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT()); m_NextWaypoint = m_Parent->GetPosition(); @@ -73,7 +70,33 @@ MovementAIComponent::MovementAIComponent(Entity* parent, const int32_t component } // The level config: the attached path +// The MovementAIComponent row (an object made without one gets its info from the constructor) +void MovementAIComponent::LoadDataFromTemplate() { + if (m_ComponentID <= 0) return; + const auto componentID = m_ComponentID; + const auto moveAIComp = CDClientManager::GetTable()->Query([componentID](const CDMovementAIComponent& entry) { return (entry.id == componentID); }); + if (moveAIComp.empty()) return; + + m_Info.movementType = moveAIComp[0].MovementType; + m_Info.wanderRadius = moveAIComp[0].WanderRadius; + m_Info.wanderSpeed = moveAIComp[0].WanderSpeed; + m_Info.wanderChance = moveAIComp[0].WanderChance; + m_Info.wanderDelayMin = moveAIComp[0].WanderDelayMin; + m_Info.wanderDelayMax = moveAIComp[0].WanderDelayMax; +} + void MovementAIComponent::LoadConfigData() { + // The level's wanderRadius over the row's, unless usewanderdb + if (m_ComponentID > 0 && !m_Parent->GetVar(u"usewanderdb")) { + const auto wanderOverride = m_Parent->GetVarAs(u"wanderRadius"); + if (wanderOverride != 0.0f) m_Info.wanderRadius = wanderOverride; + } + + //Try and fix the insane values: + if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f; + if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f; + if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f; + SetPath(m_Parent->GetVarAsString(u"attached_path")); } diff --git a/dGame/dComponents/MovementAIComponent.h b/dGame/dComponents/MovementAIComponent.h index 910e241b0..159c4d17c 100644 --- a/dGame/dComponents/MovementAIComponent.h +++ b/dGame/dComponents/MovementAIComponent.h @@ -66,6 +66,7 @@ public: MovementAIComponent(Entity* parentEntity, const int32_t componentID, MovementAIInfo info); + void LoadDataFromTemplate() override; void LoadConfigData() override; void SetPath(const std::string pathName); diff --git a/dGame/dComponents/ProximityMonitorComponent.cpp b/dGame/dComponents/ProximityMonitorComponent.cpp index 8aabeb4a9..112fc2429 100644 --- a/dGame/dComponents/ProximityMonitorComponent.cpp +++ b/dGame/dComponents/ProximityMonitorComponent.cpp @@ -1,4 +1,6 @@ #include "ProximityMonitorComponent.h" +#include "CDClientManager.h" +#include "CDProximityMonitorComponentTable.h" #include "GameMessages.h" #include "dZoneManager.h" #include "ControllablePhysicsComponent.h" @@ -17,6 +19,22 @@ ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, const int32 RegisterMsg(&ProximityMonitorComponent::OnGetObjectReportInfo); } +// The ProximityMonitorComponent row's radii, "small,large" (one value, as LOT 9833's "4", is both): the rocket +// launch radii +void ProximityMonitorComponent::LoadDataFromTemplate() { + if (m_ComponentID <= 0) return; + const auto componentID = m_ComponentID; + const auto proxCompData = CDClientManager::GetTable()->Query([componentID](const CDProximityMonitorComponent& entry) { return (entry.id == componentID); }); + if (proxCompData.empty()) return; + + const auto radii = GeneralUtils::SplitString(proxCompData[0].Proximities, ','); + const auto small = radii.empty() ? std::nullopt : GeneralUtils::TryParse(radii[0]); + const auto large = radii.size() > 1 ? GeneralUtils::TryParse(radii[1]) : small; + if (!small || !large) return; + SetProximityRadius(*small, "rocketSmall"); + SetProximityRadius(*large, "rocketLarge"); +} + ProximityMonitorComponent::~ProximityMonitorComponent() { for (const auto& en : m_ProximitiesData) { if (!en.second) continue; diff --git a/dGame/dComponents/ProximityMonitorComponent.h b/dGame/dComponents/ProximityMonitorComponent.h index e9c1690db..53fae7713 100644 --- a/dGame/dComponents/ProximityMonitorComponent.h +++ b/dGame/dComponents/ProximityMonitorComponent.h @@ -25,6 +25,8 @@ public: ProximityMonitorComponent(Entity* parentEntity, const int32_t componentID, int smallRadius = -1, int largeRadius = -1); ~ProximityMonitorComponent() override; + + void LoadDataFromTemplate() override; void Run(float deltaTime) override; /**