9696#include " GameLogic/Module/SpecialPowerModule.h"
9797#include " GameLogic/Module/SupplyTruckAIUpdate.h"
9898#include " GameLogic/Module/BattlePlanUpdate.h"
99+ #include " GameLogic/Module/ProductionUpdate.h"
99100#include " GameLogic/VictoryConditions.h"
100101
101102#include " GameNetwork/GameInfo.h"
@@ -2023,6 +2024,18 @@ void Player::setObjectsEnabled(AsciiString templateTypeToAffect, Bool enable)
20232024 }
20242025}
20252026
2027+ // =============================================================================
2028+ static void cancelUpgradeInProduction (Object* obj, void * userData)
2029+ {
2030+ const UpgradeTemplate* upgradeTemplate = static_cast <const UpgradeTemplate*>(userData);
2031+ ProductionUpdateInterface* pui = ProductionUpdate::getProductionUpdateInterfaceFromObject (obj);
2032+
2033+ if (pui && pui->isUpgradeInQueue (upgradeTemplate))
2034+ {
2035+ pui->cancelUpgrade (upgradeTemplate);
2036+ }
2037+ }
2038+
20262039// =============================================================================
20272040void Player::transferAssetsFromThat (Player *that)
20282041{
@@ -2031,6 +2044,33 @@ void Player::transferAssetsFromThat(Player *that)
20312044 return ;
20322045 }
20332046
2047+ #if !RETAIL_COMPATIBLE_CRC
2048+ // TheSuperHackers @bugfix Stubbjax 03/02/2026 Cancel any in-progress player upgrades 'that'
2049+ // player currently has in progress that 'this' player already has in progress or completed.
2050+ std::vector<const UpgradeTemplate*> upgradesToCancel;
2051+ for (Upgrade* upgrade = that->m_upgradeList ; upgrade; upgrade = upgrade->friend_getNext ())
2052+ {
2053+ const UpgradeTemplate* upgradeTemplate = upgrade->getTemplate ();
2054+
2055+ if (upgrade->getStatus () == UPGRADE_STATUS_IN_PRODUCTION
2056+ && upgradeTemplate->getUpgradeType () == UPGRADE_TYPE_PLAYER
2057+ && (hasUpgradeComplete (upgradeTemplate) || hasUpgradeInProduction (upgradeTemplate)))
2058+ {
2059+ upgradesToCancel.push_back (upgradeTemplate);
2060+ }
2061+ }
2062+
2063+ for (std::vector<const UpgradeTemplate*>::iterator cancelIt = upgradesToCancel.begin (); cancelIt != upgradesToCancel.end (); ++cancelIt)
2064+ {
2065+ const UpgradeTemplate* upgradeTemplate = *cancelIt;
2066+ that->iterateObjects (cancelUpgradeInProduction, const_cast <UpgradeTemplate*>(upgradeTemplate));
2067+ }
2068+
2069+ // TheSuperHackers @bugfix Stubbjax 03/02/2026 Ensure the in-progress upgrade mask is copied from 'that'
2070+ // player to 'this' player to prevent duplicate player upgrades being purchased.
2071+ m_upgradesInProgress.set (that->m_upgradesInProgress );
2072+ #endif
2073+
20342074 std::list<Object *> objsToTransfer;
20352075
20362076 // let's not transfer beacons
0 commit comments