bugfix(save): Fix in-flight DumbProjectile detonating instantly on save game load#2591
bugfix(save): Fix in-flight DumbProjectile detonating instantly on save game load#2591afc-afc0 wants to merge 2 commits intoTheSuperHackers:mainfrom
Conversation
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp | Adds versioned serialization of m_currentFlightPathStep (version 2, guarded by RETAIL_COMPATIBLE_XFER_SAVE) and rebuilds the flight path in loadPostProcess(); return value of calcFlightPath is unchecked. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp | Identical changes to the Zero Hour variant — same version bump, xferInt for step, and unchecked calcFlightPath call in loadPostProcess(). |
Sequence Diagram
sequenceDiagram
participant Save as Save/Load System
participant Xfer as DumbProjectileBehavior::xfer()
participant LPP as loadPostProcess()
participant Update as update()
Note over Save,Update: Saving (version 2 / non-retail)
Save->>Xfer: xfer(XFER_SAVE)
Xfer-->>Save: writes m_flightPathSegments, m_flightPathSpeed, m_flightPathStart, m_flightPathEnd, m_currentFlightPathStep (v2 only)
Note over Save,Update: Loading
Save->>Xfer: xfer(XFER_LOAD)
Xfer-->>Save: reads m_flightPathSegments, m_flightPathSpeed, m_flightPathStart, m_flightPathEnd, m_currentFlightPathStep (if version >= 2)
Save->>LPP: loadPostProcess()
alt m_flightPathSegments > 0
LPP->>LPP: calcFlightPath(false) - rebuilds m_flightPath Bezier curve
end
Note over Save,Update: First update() after load
Save->>Update: update()
alt m_currentFlightPathStep >= m_flightPath.size()
Update-->>Save: detonate() [old bug / off-map edge case]
else
Update-->>Save: move to m_flightPath[m_currentFlightPathStep], ++step
end
Prompt To Fix All With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp
Line: 779-782
Comment:
**Unchecked return value from `calcFlightPath`**
`calcFlightPath(false)` can return `false` when the start/end positions are off-map (the internal call to `estimateTerrainExtremesAlongLine` returns `false`). If that happens here, `m_flightPath` is left empty and the next `update()` frame evaluates `0 >= 0`, triggering `detonate()` — exactly the original bug. Every other call site checks the return value: the fire path calls `TheGameLogic->destroyObject`, and the `update()` tracking path calls `detonate()`. A defensive check and `DEBUG_CRASH` would be consistent with the rest of the codebase.
```suggestion
if( m_flightPathSegments > 0 )
{
if( !calcFlightPath( false ) )
{
DEBUG_CRASH(( "DumbProjectileBehavior::loadPostProcess - Failed to rebuild flight path; projectile will detonate immediately." ));
}
}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp
Line: 830-833
Comment:
**Unchecked return value from `calcFlightPath`**
Same as `Generals/` — `calcFlightPath(false)` can return `false` for off-map coordinates, leaving `m_flightPath` empty and causing instant detonation on the next frame. A `DEBUG_CRASH` on failure would be consistent with the existing call sites in `update()`.
```suggestion
if( m_flightPathSegments > 0 )
{
if( !calcFlightPath( false ) )
{
DEBUG_CRASH(( "DumbProjectileBehavior::loadPostProcess - Failed to rebuild flight path; projectile will detonate immediately." ));
}
}
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "bugfix(save): Add RETAIL_COMPATIBLE_XFER..." | Re-trigger Greptile
Caball009
left a comment
There was a problem hiding this comment.
FWIW it's best to do the Generals changes last (after all feedback), unless there are meaningful changes in the Generals code. That's easier for the PR author and reviewers. This PR is small enough that it doesn't really matter, though.
Fixes Tank/Artillery Shells instantly Detonates Mid-Air after Loading #2346
DumbProjectileBehavior does not serialize
m_flightPath(the Bezier curve points) orm_currentFlightPathStep(the currentposition along the path). On load,
m_flightPathis empty andm_currentFlightPathStepis 0, so the firstupdate()callevaluates
0 >= 0as true and immediately callsdetonate(). This is most visible with slow artillery like Inferno Cannons andNuke Cannons.
The fix adds two things:
m_currentFlightPathStepinxfer()(version bumped from 1 to 2) so the projectile knows where it was along itsflight path.
loadPostProcess()using the already-saved start, end, segments and speed parameters.Old saves (version 1) remain compatible — the step defaults to 0 and the path is rebuilt, so projectiles restart from the
beginning of their arc rather than detonating instantly.
Test