-
Notifications
You must be signed in to change notification settings - Fork 151
fix(savegame): Use getFinalOverride in WeaponSet xfer load to match Object constructor #2160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(savegame): Use getFinalOverride in WeaponSet xfer load to match Object constructor #2160
Conversation
…g WeaponSet flags instead of pointer Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Greptile Overview
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameLogic/Object/WeaponSet.cpp | Adds getFinalOverride() call in xfer(LOAD) to match Object constructor behavior, ensuring consistent template pointers and preventing weapon timing corruption |
| GeneralsMD/Code/GameEngine/Source/GameLogic/Object/WeaponSet.cpp | Adds getFinalOverride() call in xfer(LOAD) to match Object constructor behavior, ensuring consistent template pointers and preventing weapon timing corruption |
Sequence Diagram
sequenceDiagram
participant SG as SaveGame Load
participant WS as WeaponSet::xfer(LOAD)
participant TF as ThingFactory
participant TT as ThingTemplate
participant Obj as Object Constructor
participant UWS as updateWeaponSet
Note over SG,UWS: Game Load Sequence
SG->>Obj: Create Object(tt)
Obj->>TT: getFinalOverride()
TT-->>Obj: Final overridden template
Note over Obj: Stores final template
SG->>WS: Load weapon state
WS->>TF: findTemplate(ttName)
TF-->>WS: Base template
WS->>TT: getFinalOverride()
TT-->>WS: Final overridden template
Note over WS: Now matches Object's template
WS->>WS: Set m_curWeaponTemplateSet
Note over Obj,UWS: Later During Gameplay
Obj->>UWS: Update weapons
UWS->>Obj: getTemplate()
Obj-->>UWS: Final template pointer
UWS->>UWS: Compare pointers
alt Pointers Match
UWS-->>Obj: No reallocation needed
Note over UWS: Weapon timing preserved
else Pointers Differ (Bug)
UWS->>UWS: Reallocate all weapons
Note over UWS: Timing state lost!
end
| const WeaponTemplateSet* set = obj->getTemplate()->findWeaponTemplateSet(obj->getWeaponSetFlags()); | ||
| DEBUG_ASSERTCRASH(set, ("findWeaponSet should never return null")); | ||
| if (set && set != m_curWeaponTemplateSet) | ||
| // TheSuperHackers @bugfix bobtista 20/01/2026 After checkpoint load, the m_curWeaponTemplateSet pointer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first hunch here is that this change is a hack. Why is m_curWeaponTemplateSet set to something that satisfies the weapon flags but is not actually the real deal? It indicates that the issue is higher up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, updated with a better approach.
When an Object is created (Object.cpp:230):
tt = (const ThingTemplate*)tt->getFinalOverride();
The Object uses the final override of the template.
But when WeaponSet::xfer(LOAD) restored weapon data (WeaponSet.cpp:231):
const ThingTemplate* tt = TheThingFactory->findTemplate(ttName);
m_curWeaponTemplateSet = tt->findWeaponTemplateSet(wsFlags);
It used findTemplate() which returns the base template, not the final override.
The fix is to just add t = (const ThingTemplate*)tt->getFinalOverride(); to WeaponSet::xfer(LOAD):
| throw INI_INVALID_DATA; | ||
|
|
||
| // TheSuperHackers @bugfix bobtista 23/01/2026 Use final override to match what Object uses. | ||
| tt = (const ThingTemplate*)tt->getFinalOverride(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a static_cast better here?
| if (tt == nullptr) | ||
| throw INI_INVALID_DATA; | ||
|
|
||
| // TheSuperHackers @bugfix bobtista 23/01/2026 Use final override to match what Object uses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this comment explains why we need this fix.
Should probably be a fix as there's no user facing issue here.
|
Looks like a good change, but the title and issue description need to be updated (the summary is no longer in line with the current code change). |
Summary
Fixes weapon timing state corruption after loading a saved game by ensuring WeaponSet uses the same template override as Object.
Notes
Objectconstructor callsgetFinalOverride()on the template (Object.cpp:230)WeaponSet::xfer(LOAD)was usingTheThingFactory->findTemplate()which returns the base template, not the final overridem_curWeaponTemplateSetto point to a different ThingTemplate's weapon sets thanobj->getTemplate()updateWeaponSet()triggered unnecessary weapon reallocation, resetting timing stateFix
Add
getFinalOverride()call inWeaponSet::xfer(LOAD)to match what Object does, ensuring consistent template pointers.Testing
Todo