The Idle Warthog That Crashed Halo PC Five Minutes Later
The vehicle cleanup worked exactly as intended.
An intact, unused Warthog reached its timeout, the script called destroyobject, and the object disappeared. Nothing crashed. Nothing unusual appeared in the logs.
Then, several minutes later, a Halo PC client hit an access violation.
A sensible cleanup rule
Custom Race tracks can create their own vehicle pads. Leaving every abandoned vehicle in the world forever would consume Halo PC's shared 2,048-object table, so the first cleanup system called destroyobject on intact, idle vehicles after a timeout.
That is a normal approach in many game systems. Once an object is no longer occupied or useful, delete it and create another one when needed.
Using destroyobject on an intact Race vehicle made that dangerous.
The delay hid the cause
The crash did not happen when destroyobject ran. It appeared roughly five minutes later, far removed from the original cleanup event.
That delay made the object-table limit look suspicious again. Vehicle counts, respawn settings, and unrelated scripts all seemed plausible.
The eventual path through retail haloded.exe pointed somewhere else.
Race kept the identifier
Halo PC objects use identifiers containing both an index and a salt value. The salt helps distinguish a newly created object from an older object that once occupied the same table slot.
Race retained the destroyed vehicle's identifier. Later, code in the path around:
FUN_0056D400 walked that cached identifier without performing the expected salt validation.
The resulting access violation occurred at:
0x0056D459 By then, the object was long gone and its slot could have been reused.
That explains the timing. Destroying the Warthog planted the problem, while a later Race update finally touched the stale reference.
Recycle instead of destroy
The safer approach was to stop destroying idle Race vehicles.
When an unused vehicle times out, the script now moves it back to its pad and resets the state needed for reuse. The object identifier remains valid because the original object remains alive.
Its expiry is also kept long, and normal respawn behaviour remains enabled.
This costs an object slot for the lifetime of the vehicle, but it avoids leaving Race with a stale identifier.
Why scripted destruction was unusual
In this Halo PC Race setup, the vehicles cannot be destroyed or exploded through normal gameplay. Halo PC therefore has no ordinary explosion-and-replacement lifecycle removing these vehicles from the track.
The deletion happened only because the cleanup script explicitly called destroyobject on an intact, idle vehicle. That forced Race into an object lifecycle it would not normally encounter on this track.
For now, the operating rule is simple:
Do not call destroyobject on an intact, idle Race vehicle
Move intact idle vehicles back to their pads
Reuse the same vehicle object and identifier
Keep the vehicle alive instead of forcing a deletion Halo PC would not normally perform
Why this mattered
The eventual fix was not complicated. The difficult part was connecting a clean-looking deletion to a crash that arrived minutes later on another machine.
Honestly, those are the failures that make server scripting difficult. The script can finish successfully while the engine quietly preserves an assumption that the script has already invalidated.