bugfix: Fix transferred in-progress upgrades#2396
bugfix: Fix transferred in-progress upgrades#2396Stubbjax wants to merge 4 commits intoTheSuperHackers:mainfrom
Conversation
…eady has in progress or completed
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/Common/RTS/Player.cpp | Adds cancelUpgradeInProduction callback and pre-transfer logic to cancel/mask duplicate in-progress player upgrades; cancelUpgradeInProduction is defined outside the #if !RETAIL_COMPATIBLE_CRC guard despite only being used inside it (dead code in retail builds). |
| GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp | Mirrors the Generals fix for Zero Hour — same cancelUpgradeInProduction dead-code placement concern outside #if !RETAIL_COMPATIBLE_CRC guard, otherwise correct logic. |
Sequence Diagram
sequenceDiagram
participant TA as transferAssetsFromThat()
participant ThatPlayer as that (surrendering)
participant ThisPlayer as this (surviving)
participant PUI as ProductionUpdateInterface
participant PM as Player::removeUpgrade
TA->>ThatPlayer: iterate m_upgradeList
ThatPlayer-->>TA: upgrades with UPGRADE_STATUS_IN_PRODUCTION
loop for each in-progress upgrade
TA->>ThisPlayer: hasUpgradeComplete(upgrade)?
TA->>ThisPlayer: hasUpgradeInProduction(upgrade)?
alt this player already has it
TA->>TA: add to upgradesToCancel
end
end
loop for each upgrade in upgradesToCancel
TA->>ThatPlayer: iterateObjects(cancelUpgradeInProduction, upgradeTemplate)
ThatPlayer->>PUI: isUpgradeInQueue(upgradeTemplate)?
PUI-->>ThatPlayer: true
ThatPlayer->>PUI: cancelUpgrade(upgradeTemplate)
PUI->>PM: removeUpgrade(upgrade) on that player
PM->>ThatPlayer: m_upgradesInProgress.clear(mask)
end
TA->>ThisPlayer: m_upgradesInProgress.set(that->m_upgradesInProgress)
Note over ThisPlayer: OR in that's remaining in-progress bits
TA->>ThatPlayer: iterate objects for transfer
ThatPlayer-->>TA: list of objects
TA->>ThisPlayer: setTeam(defaultTeam) for each object
TA->>ThatPlayer: getMoney()->withdraw(allMoney)
TA->>ThisPlayer: getMoney()->deposit(allMoney)
Last reviewed commit: "fix: Add static cast"
xezon
left a comment
There was a problem hiding this comment.
Nice find and the implementation of the fix makes sense too.
| } | ||
| } | ||
|
|
||
| for (const UpgradeTemplate* upgradeTemplate : upgradesToCancel) |
| //============================================================================= | ||
| static void cancelUpgradeInProduction(Object* obj, void* userData) | ||
| { | ||
| const UpgradeTemplate* upgradeTemplate = (const UpgradeTemplate*)userData; |
|
|
||
| for (const UpgradeTemplate* upgradeTemplate : upgradesToCancel) | ||
| { | ||
| that->iterateObjects(cancelUpgradeInProduction, (void*)upgradeTemplate); |
a213560 to
9fc16a4
Compare
This change fixes two issues with in-progress upgrades when they are transferred to another player.
If a team mate surrenders, the surviving team mate's
m_upgradesInProgressmask does not append any of the surrendering player's in-progress upgrades. This incorrectly allows the surviving player to purchase a duplicate instance of any upgrades that the surrendering player had in progress.For example, Bob starts researching Black Napalm and then surrenders. Fred selects a different War Factory and is able to research a new/separate instance of Black Napalm, despite it already being in progress in another War Factory.
The second problem arises when it comes to transferring in-progress upgrades that the surviving player already has in progress or completed. Once an upgrade has been completed, any duplicate in-progress upgrades can no longer be cancelled, and attempting to do so leads to strange UI behaviour.
For example, Bob starts researching Black Napalm and then surrenders. But Fred already has Black Napalm researched. Fred discovers the second instance of Black Napalm that Bob had begun researching and tries to cancel it, but the upgrade cannot be cancelled.
The solution is to cancel any of the old player's in-progress upgrades if the new player already has them in progress or completed (and the refund is a nice bonus). The
m_upgradesInProgressmask is also appropriately updated so that the new player cannot purchase any duplicate upgrades that the old player had in progress.Before
UPG_BROKEN.mp4
After
UPG_FIXED.mp4