Skip to content

bugfix(energy): Don't increase power production for disabled power plants on save game load#2508

Open
Caball009 wants to merge 4 commits intoTheSuperHackers:mainfrom
Caball009:bugfix_energy_xfer
Open

bugfix(energy): Don't increase power production for disabled power plants on save game load#2508
Caball009 wants to merge 4 commits intoTheSuperHackers:mainfrom
Caball009:bugfix_energy_xfer

Conversation

@Caball009
Copy link
Copy Markdown

@Caball009 Caball009 commented Mar 30, 2026

When loading a save game with disabled power plants, players still get the power production from those plants. That's because the power production is increased before the Object disabled flags are xfer'd. The following code is supposed to prevent the increase in power production, but the disabled flag would have to be xfer'd before this is called. This PR fixes that.

void Object::friend_adjustPowerForPlayer( Bool incoming )
{
if (isDisabled() && getTemplate()->getEnergyProduction() > 0)
{
// Disabledness only affects Producers, not Consumers.
return;
}

Callstack:

generalszh.exe!Object::friend_adjustPowerForPlayer(bool incoming)
generalszh.exe!Player::becomingTeamMember(Object * obj, bool yes)
generalszh.exe!Object::setOrRestoreTeam(Team * team, bool restoring)
generalszh.exe!Object::xfer(Xfer * xfer)

TODO:

  • Replicate in Generals.

@Caball009 Caball009 added Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Saveload Is Saveload/Xfer related labels Mar 30, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 30, 2026

Greptile Summary

This PR fixes a save game regression where disabled power plants would incorrectly grant power production upon loading. The root cause was that setOrRestoreTeam() (which triggers the becomingTeamMemberfriend_adjustPowerForPlayer chain) was called before m_disabledMask and m_disabledTillFrame were deserialized in Object::xfer(), making isDisabled() return false for actually-disabled producers. The fix defers the setOrRestoreTeam() call until after both disabled-state fields are xfer'd, and is replicated correctly in both the Generals and GeneralsMD (Object.cpp) files.

Confidence Score: 5/5

Safe to merge — targeted, minimal fix with no side effects on non-disabled objects.

The change is a well-understood ordering fix: setOrRestoreTeam (and the power-adjustment chain it triggers) is correctly deferred until after both m_disabledMask and m_disabledTillFrame are deserialized. No new logic is introduced, the fix is symmetrically applied to both game versions, and all remaining findings are P2 or lower.

No files require special attention.

Important Files Changed

Filename Overview
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp Moves setOrRestoreTeam call to after m_disabledMask and m_disabledTillFrame are loaded in Object::xfer(), fixing disabled-producer power bug on save load. Also adds clarifying comment at the deferred team-assignment site.
Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp Same fix replicated from GeneralsMD: setOrRestoreTeam deferred until disabled state is fully deserialized, with matching comment added at call site.

Sequence Diagram

sequenceDiagram
    participant X as Object::xfer()
    participant T as Object::setOrRestoreTeam()
    participant P as Player::becomingTeamMember()
    participant A as Object::friend_adjustPowerForPlayer()

    Note over X: xfer teamID (but DON'T set yet)
    Note over X: xfer m_status, m_scriptStatus...
    Note over X: xfer m_disabledMask ✅
    Note over X: xfer m_disabledTillFrame ✅
    X->>T: setOrRestoreTeam(team, restoring=true)
    T->>P: becomingTeamMember(obj, yes=true)
    P->>A: friend_adjustPowerForPlayer(incoming=true)
    alt isDisabled() && energyProduction > 0
        Note over A: RETURN early — disabled producer skips power adjustment ✅
    else
        Note over A: objectEnteringInfluence(this)
    end
Loading

Reviews (2): Last reviewed commit: "Replicated in Generals." | Re-trigger Greptile

@xezon
Copy link
Copy Markdown

xezon commented Apr 9, 2026

This can be finalized.

@Caball009
Copy link
Copy Markdown
Author

Replicated in Generals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Saveload Is Saveload/Xfer related ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants