From b3166865382cc54b82eb44bb2d90b17bb8dafd4f Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Sat, 26 Sep 2026 18:42:25 -0500 Subject: [PATCH] fix: Crux Prime dropship computer respawns and no longer crashes The dropship computer's OnDie activated the "next" spawner network (pipe number + 1) when a player smashed it and only fell back to the first network otherwise. The computer has no next network, so once a player smashed it (easiest with area attacks like the Doom Hammer) it never came back. The live script (L_DROPSHIP_COMPUTER.lua, shipped in the client's server scripts) always resets its own network and activates the first one, which is what it does now. OnUse also dereferenced GetMission(979) without a null check, crashing the world when a player without that mission used the built computer. It now matches the live script: only players with the mission active get the Nexus Talon data card, once. SsModularBuildServer had the same unchecked GetMission and now checks the mission state. Fixes #596 Co-Authored-By: Claude Opus 5.5 --- .../02_server/Map/AM/AmDropshipComputer.cpp | 28 ++++--------------- .../02_server/Map/SS/SsModularBuildServer.cpp | 8 ++---- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/dScripts/02_server/Map/AM/AmDropshipComputer.cpp b/dScripts/02_server/Map/AM/AmDropshipComputer.cpp index e88ec4687..40a83d571 100644 --- a/dScripts/02_server/Map/AM/AmDropshipComputer.cpp +++ b/dScripts/02_server/Map/AM/AmDropshipComputer.cpp @@ -19,7 +19,8 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) { if (!missionComponent || !inventoryComponent) return; - if (inventoryComponent->GetLotCount(m_NexusTalonDataCard) != 0 || missionComponent->GetMission(979)->GetMissionState() == eMissionState::COMPLETE) { + // Only players on the mission get the data card, and only once. + if (missionComponent->GetMissionState(979) != eMissionState::ACTIVE || inventoryComponent->GetLotCount(m_NexusTalonDataCard) != 0) { return; } @@ -27,15 +28,10 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) { } void AmDropshipComputer::OnDie(Entity* self, Entity* killer) { + // Reset this computer's spawner network and start the first one again, however it died. const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar(u"spawner_name")); - - const auto pipeNum = GeneralUtils::TryParse(myGroup.substr(10, 1)); - if (!pipeNum) return; - const auto pipeGroup = myGroup.substr(0, 10); - const auto nextPipeNum = pipeNum.value() + 1; - const auto samePipeSpawners = Game::zoneManager->GetSpawnersByName(myGroup); if (!samePipeSpawners.empty()) { @@ -44,22 +40,10 @@ void AmDropshipComputer::OnDie(Entity* self, Entity* killer) { samePipeSpawners[0]->Deactivate(); } - if (killer != nullptr && killer->IsPlayer()) { - const auto nextPipe = pipeGroup + std::to_string(nextPipeNum); + const auto firstPipeSpawners = Game::zoneManager->GetSpawnersByName(pipeGroup + "1"); - const auto nextPipeSpawners = Game::zoneManager->GetSpawnersByName(nextPipe); - - if (!nextPipeSpawners.empty()) { - nextPipeSpawners[0]->Activate(); - } - } else { - const auto nextPipe = pipeGroup + "1"; - - const auto firstPipeSpawners = Game::zoneManager->GetSpawnersByName(nextPipe); - - if (!firstPipeSpawners.empty()) { - firstPipeSpawners[0]->Activate(); - } + if (!firstPipeSpawners.empty()) { + firstPipeSpawners[0]->Activate(); } } diff --git a/dScripts/02_server/Map/SS/SsModularBuildServer.cpp b/dScripts/02_server/Map/SS/SsModularBuildServer.cpp index dfb291682..0b2a52458 100644 --- a/dScripts/02_server/Map/SS/SsModularBuildServer.cpp +++ b/dScripts/02_server/Map/SS/SsModularBuildServer.cpp @@ -1,16 +1,14 @@ #include "SsModularBuildServer.h" #include "MissionComponent.h" #include "eMissionState.h" -#include "eReplicaComponentType.h" void SsModularBuildServer::OnModularBuildExit(Entity* self, Entity* player, bool bCompleted, std::vector modules) { int missionNum = 1732; if (bCompleted) { - MissionComponent* mission = static_cast(player->GetComponent(eReplicaComponentType::MISSION)); - Mission* rocketMission = mission->GetMission(missionNum); - - if (rocketMission->GetMissionState() == eMissionState::ACTIVE) { + auto* const mission = player->GetComponent(); + // The player may never have had this mission, so check the state instead of the mission itself. + if (mission && mission->GetMissionState(missionNum) == eMissionState::ACTIVE) { mission->ForceProgress(missionNum, 2478, 1); } }