From c6f6aa5d2b3d5ebfa08985f8311484f7b2d16828 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Wed, 30 Sep 2026 23:36:00 -0500 Subject: [PATCH] fix(scripts): AG elevator, bus door and property platform drive their movers as their live scripts did StopPathing, StartPathing and GoToWaypoint instead of hand-made resyncs; a built platform starts before the scripts hear of it so a script can stop it; the FV tree platform's resync hack is gone. Co-Authored-By: Claude Opus 5.5 --- dGame/Entity.cpp | 6 ------ dGame/dComponents/QuickBuildComponent.cpp | 12 +++++++----- .../02_server/Map/General/PropertyPlatform.cpp | 15 +++------------ dScripts/ai/AG/AgBusDoor.cpp | 8 +++++--- dScripts/ai/AG/AgQbElevator.cpp | 9 +++++---- 5 files changed, 20 insertions(+), 30 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 3a6a41784..8c3e41b2f 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -617,12 +617,6 @@ void Entity::Initialize() { quickBuildComponent->SetResetTime(rebuildResetTime); } - const auto objectID = GetObjectID(); - // FV tree handler for when built so it sets the state to moving at the correct time - if (GetLOT() == 9483) quickBuildComponent->AddQuickBuildCompleteCallback([objectID](Entity* user) { - auto* const entity = Game::entityManager->GetEntity(objectID); - if (entity) GameMessages::PlatformResync(*entity, false, 0, 1, 1, eMovementPlatformState::Moving, true).Send(UNASSIGNED_SYSTEM_ADDRESS); - }); // The level's activityID replaces the template's. The client (LWOQuickBuildComponent::LoadDataFromTemplate) // reads RebuildComponent.activityID over it unless the level sets actIDovrd, but live used the level's: diff --git a/dGame/dComponents/QuickBuildComponent.cpp b/dGame/dComponents/QuickBuildComponent.cpp index aa52e4867..53d2b6e8d 100644 --- a/dGame/dComponents/QuickBuildComponent.cpp +++ b/dGame/dComponents/QuickBuildComponent.cpp @@ -518,6 +518,13 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) { Loot::DropActivityLoot(builder, m_Parent->GetObjectID(), m_ActivityId, 1); } + // A built platform sets off before the scripts hear of it, so a script that stops it (live's L_AG_QB_ELEVATOR and + // L_PROP_PLATFORM stop theirs) keeps it stopped + auto* movingPlatform = m_Parent->GetComponent(); + if (movingPlatform != nullptr) { + movingPlatform->OnCompleteQuickBuild(); + } + // Notify scripts auto* script = m_Parent->GetScript(); script->OnQuickBuildComplete(m_Parent, user); @@ -531,11 +538,6 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) { m_Parent->TriggerEvent(eTriggerEventType::REBUILD_COMPLETE, user); - auto* movingPlatform = m_Parent->GetComponent(); - if (movingPlatform != nullptr) { - movingPlatform->OnCompleteQuickBuild(); - } - // Set flag auto* character = user->GetCharacter(); diff --git a/dScripts/02_server/Map/General/PropertyPlatform.cpp b/dScripts/02_server/Map/General/PropertyPlatform.cpp index ac27bb46c..54c82f845 100644 --- a/dScripts/02_server/Map/General/PropertyPlatform.cpp +++ b/dScripts/02_server/Map/General/PropertyPlatform.cpp @@ -1,26 +1,17 @@ #include "PropertyPlatform.h" #include "QuickBuildComponent.h" #include "GameMessages.h" -#include "MovementMessages.h" #include "MovingPlatformComponent.h" void PropertyPlatform::OnQuickBuildComplete(Entity* self, Entity* target) { - // auto* movingPlatform = self->GetComponent(); - // if (movingPlatform != nullptr) { - // movingPlatform->StopPathing(); - // movingPlatform->SetNoAutoStart(true); - // } - GameMessages::PlatformResync(*self, true, 0, 0, 0, eMovementPlatformState::Stationary).Send(UNASSIGNED_SYSTEM_ADDRESS); + // L_PROP_PLATFORM: it stays until it is used + if (auto* const movingPlatform = self->GetComponent()) movingPlatform->StopPathing(); } void PropertyPlatform::OnUse(Entity* self, Entity* user) { auto* quickBuildComponent = self->GetComponent(); if (quickBuildComponent != nullptr && quickBuildComponent->GetState() == eQuickBuildState::COMPLETED) { - // auto* movingPlatform = self->GetComponent(); - // if (movingPlatform != nullptr) { - // movingPlatform->GotoWaypoint(1); - // } - GameMessages::PlatformResync(*self, true, 0, 1, 1, eMovementPlatformState::Moving).Send(UNASSIGNED_SYSTEM_ADDRESS); + if (auto* const movingPlatform = self->GetComponent()) movingPlatform->GotoWaypoint(1); self->AddCallbackTimer(movementDelay + effectDelay, [self, this]() { self->SetNetworkVar(u"startEffect", dieDelay); diff --git a/dScripts/ai/AG/AgBusDoor.cpp b/dScripts/ai/AG/AgBusDoor.cpp index 69c9c3e8c..9672fd30b 100644 --- a/dScripts/ai/AG/AgBusDoor.cpp +++ b/dScripts/ai/AG/AgBusDoor.cpp @@ -2,7 +2,7 @@ #include "Entity.h" #include "GameMessages.h" #include "EffectsMessages.h" -#include "MovementMessages.h" +#include "MovingPlatformComponent.h" #include "ProximityMonitorComponent.h" void AgBusDoor::OnStartup(Entity* self) { @@ -10,6 +10,8 @@ void AgBusDoor::OnStartup(Entity* self) { m_OuterCounter = 0; self->SetProximityRadius(75, "busDoor"); self->SetProximityRadius(85, "busDoorOuter"); + // L_AG_BUS_DOOR: the door only moves when sent + if (auto* const platform = self->GetComponent()) platform->StopPathing(); } void AgBusDoor::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) { @@ -50,9 +52,9 @@ void AgBusDoor::OnProximityUpdate(Entity* self, Entity* entering, std::string na void AgBusDoor::MoveDoor(Entity* self, bool bOpen) { if (bOpen) { - GameMessages::PlatformResync(*self, true, 1, 0).Send(UNASSIGNED_SYSTEM_ADDRESS); + if (auto* const platform = self->GetComponent()) platform->GotoWaypoint(0); } else { - GameMessages::PlatformResync(*self, true, 0, 1).Send(UNASSIGNED_SYSTEM_ADDRESS); + if (auto* const platform = self->GetComponent()) platform->GotoWaypoint(1); self->AddTimer("dustTimer", 2.0f); } diff --git a/dScripts/ai/AG/AgQbElevator.cpp b/dScripts/ai/AG/AgQbElevator.cpp index d7d127773..20251078f 100644 --- a/dScripts/ai/AG/AgQbElevator.cpp +++ b/dScripts/ai/AG/AgQbElevator.cpp @@ -1,7 +1,7 @@ #include "AgQbElevator.h" #include "EntityManager.h" #include "GameMessages.h" -#include "MovementMessages.h" +#include "MovingPlatformComponent.h" void AgQbElevator::OnStartup(Entity* self) { @@ -15,7 +15,8 @@ void AgQbElevator::OnQuickBuildComplete(Entity* self, Entity* target) { float delayTime = killTime - endTime; if (delayTime < 1) delayTime = 1; - GameMessages::PlatformResync(*self, true, 0, 0, 0, eMovementPlatformState::Stationary).Send(UNASSIGNED_SYSTEM_ADDRESS); + // L_AG_QB_ELEVATOR: it waits for its builder + if (auto* const platform = self->GetComponent()) platform->StopPathing(); //add a timer that will kill the QB if no players get on in the killTime self->AddTimer("startKillTimer", killTime); @@ -32,7 +33,7 @@ void AgQbElevator::OnProximityUpdate(Entity* self, Entity* entering, std::string self->SetBoolean(u"qbPlayerRdy", true); self->CancelTimer("StartElevator"); - GameMessages::PlatformResync(*self, true, 0, 1, 1, eMovementPlatformState::Moving).Send(UNASSIGNED_SYSTEM_ADDRESS); + if (auto* const platform = self->GetComponent()) platform->StartPathing(); } else if (!self->GetBoolean(u"StartTimer")) { self->SetBoolean(u"StartTimer", true); self->AddTimer("StartElevator", startTime); @@ -43,7 +44,7 @@ void AgQbElevator::OnProximityUpdate(Entity* self, Entity* entering, std::string void AgQbElevator::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "StartElevator") { - GameMessages::PlatformResync(*self, true, 0, 1, 1, eMovementPlatformState::Moving).Send(UNASSIGNED_SYSTEM_ADDRESS); + if (auto* const platform = self->GetComponent()) platform->StartPathing(); } else if (timerName == "startKillTimer") { killTimerStartup(self); } else if (timerName == "KillTimer") {