From 4252cd405cf198b8ce61247045424d93252986f9 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Sun, 27 Sep 2026 19:56:23 +0200 Subject: [PATCH 1/2] bugfix(aiplayer): Improve initialization of uninitialized variable in AIPlayer::onUnitProduced. --- Generals/Code/GameEngine/Include/GameLogic/GameLogic.h | 5 +++++ .../Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp | 10 ++++++++++ .../Source/GameLogic/Object/Behavior/SpawnBehavior.cpp | 7 +++++++ .../GameEngine/Source/GameLogic/System/GameLogic.cpp | 4 ++++ 4 files changed, 26 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/GameLogic.h b/Generals/Code/GameEngine/Include/GameLogic/GameLogic.h index c47c61eb7dc..11a7cf81b66 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/GameLogic.h +++ b/Generals/Code/GameEngine/Include/GameLogic/GameLogic.h @@ -479,6 +479,11 @@ class GameLogic : public SubsystemInterface, public Snapshot void xferObjectTOC( Xfer *xfer ); ///< save/load object TOC for current state of map void prepareLogicForObjectLoad(); ///< prepare engine for object data from game file +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 +public: + Bool m_onUnitProducedZeroInit; +#endif + }; // INLINE ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index fc9385a7b68..760b06144f6 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -1051,6 +1051,16 @@ void AIPlayer::onUnitProduced( Object *factory, Object *unit ) // To keep retail compatibility it needs to be set true in VS6 builds. #if defined(_MSC_VER) && _MSC_VER < 1300 Bool supplyTruck = true; + +#if RTS_GENERALS + // A special initialization case for the call site in SpawnBehavior::createSpawn + // to mimic the initialization behavior in the retail Generals binary. + if (TheGameLogic->m_onUnitProducedZeroInit) + { + supplyTruck = false; + } +#endif + #else Bool supplyTruck = false; #endif diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp index 19fd49ea218..f44d467c767 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp @@ -585,7 +585,14 @@ Bool SpawnBehavior::createSpawn() newSpawn = TheThingFactory->newObject( m_spawnTemplate, parent->getTeam() ); // just a little worried about this... // Count this unit towards our score. +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 + // TheSuperHackers @info Set m_onUnitProducedZeroInit to true so it can be used in AIPlayer::onUnitProduced. + TheGameLogic->m_onUnitProducedZeroInit = true; newSpawn->getControllingPlayer()->onUnitCreated(parent, newSpawn); + TheGameLogic->m_onUnitProducedZeroInit = false; +#else + newSpawn->getControllingPlayer()->onUnitCreated(parent, newSpawn); +#endif // Gee, this is new... // Now, we can have a list of template names. diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 118cc3a898b..c1fc79c4c9d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -278,6 +278,10 @@ GameLogic::GameLogic() m_loadingMap = FALSE; m_loadingSave = FALSE; m_clearingGameData = FALSE; + +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 + m_onUnitProducedZeroInit = false; +#endif } //------------------------------------------------------------------------------------------------- From 0d57a77230e77c68181fd6b48acb301114789394 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Tue, 29 Sep 2026 20:46:12 +0200 Subject: [PATCH 2/2] Replicated to Zero Hour. --- .../Code/GameEngine/Include/GameLogic/GameLogic.h | 5 +++++ .../Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp | 10 ++++++++++ .../Source/GameLogic/Object/Behavior/SpawnBehavior.cpp | 7 +++++++ .../GameEngine/Source/GameLogic/System/GameLogic.cpp | 4 ++++ 4 files changed, 26 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h index 8192d3fbe68..be05f76f384 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h @@ -488,6 +488,11 @@ class GameLogic : public SubsystemInterface, public Snapshot void xferObjectTOC( Xfer *xfer ); ///< save/load object TOC for current state of map void prepareLogicForObjectLoad(); ///< prepare engine for object data from game file +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 +public: + Bool m_onUnitProducedZeroInit; +#endif + }; // INLINE ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index 10e5faa96af..cb34c7b3ba2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -1058,6 +1058,16 @@ void AIPlayer::onUnitProduced( Object *factory, Object *unit ) // To keep retail compatibility it needs to be set true in VS6 builds. #if defined(_MSC_VER) && _MSC_VER < 1300 Bool supplyTruck = true; + +#if RTS_GENERALS + // A special initialization case for the call site in SpawnBehavior::createSpawn + // to mimic the initialization behavior in the retail Generals binary. + if (TheGameLogic->m_onUnitProducedZeroInit) + { + supplyTruck = false; + } +#endif + #else Bool supplyTruck = false; #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp index 39d49bd25fa..54d235c7687 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp @@ -629,7 +629,14 @@ Bool SpawnBehavior::createSpawn() newSpawn = TheThingFactory->newObject( m_spawnTemplate, parent->getTeam() ); // just a little worried about this... // Count this unit towards our score. +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 + // TheSuperHackers @info Set m_onUnitProducedZeroInit to true so it can be used in AIPlayer::onUnitProduced. + TheGameLogic->m_onUnitProducedZeroInit = true; newSpawn->getControllingPlayer()->onUnitCreated(parent, newSpawn); + TheGameLogic->m_onUnitProducedZeroInit = false; +#else + newSpawn->getControllingPlayer()->onUnitCreated(parent, newSpawn); +#endif // Gee, this is new... // Now, we can have a list of template names. diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index dec2e14cc76..f9ae913affb 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -289,6 +289,10 @@ GameLogic::GameLogic() m_loadingSave = FALSE; m_clearingGameData = FALSE; m_quitToDesktopAfterMatch = FALSE; + +#if RTS_GENERALS && defined(_MSC_VER) && _MSC_VER < 1300 + m_onUnitProducedZeroInit = false; +#endif } //-------------------------------------------------------------------------------------------------