From 8bf509a2d2d82f81f704574159c532fecb6a5faf Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Mon, 12 Jan 2026 11:44:22 +0100 Subject: [PATCH 1/3] bugfix(ocl): Fix uninitialized variable in ObjectCreationList to avoid mismatches --- .../Source/GameLogic/Object/ObjectCreationList.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 215763f9c50..467825a82fb 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -1387,7 +1387,17 @@ class GenericObjectCreationNugget : public ObjectCreationNugget fpOptions.minRadius = GameLogicRandomValueReal(m_minDistanceAFormation, m_minDistanceBFormation); fpOptions.maxRadius = m_maxDistanceFormation; fpOptions.flags = FPF_USE_HIGHEST_LAYER; - ThePartitionManager->findPositionAround(pos, &fpOptions, &resultPos); + + // TheSuperHackers @bugfix Caball009 12/01/2026 Position variable needs to be initialized before use. + // The non-deterministic behavior for retail clients cannot be fixed, so this will remain a source of potential mismatches for unpatched clients. + // Fall back to the center position because no valid position was found, so that the behavior is deterministic for patched clients. + if (!ThePartitionManager->findPositionAround(pos, &fpOptions, &resultPos)) + { +#if RETAIL_COMPATIBLE_CRC + DEBUG_CRASH(("A mismatch is likely to happen if this code path is used in a match with unpatched clients.")); +#endif + resultPos = *pos; + } doStuffToObj( debris, m_names[pick], &resultPos, mtx, orientation, sourceObj, lifetimeFrames ); } else From 4b1dc5cbf8a22eb6531ab84ef3b26fa58aa4c52e Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 23 Jan 2026 17:46:49 +0100 Subject: [PATCH 2/3] Removed branch for release build. --- .../Source/GameLogic/Object/ObjectCreationList.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 467825a82fb..eb4a690fce6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -1382,7 +1382,6 @@ class GenericObjectCreationNugget : public ObjectCreationNugget // longer be necessary and can be taken out -- amit if (m_spreadFormation) { - Coord3D resultPos; FindPositionOptions fpOptions; fpOptions.minRadius = GameLogicRandomValueReal(m_minDistanceAFormation, m_minDistanceBFormation); fpOptions.maxRadius = m_maxDistanceFormation; @@ -1390,13 +1389,16 @@ class GenericObjectCreationNugget : public ObjectCreationNugget // TheSuperHackers @bugfix Caball009 12/01/2026 Position variable needs to be initialized before use. // The non-deterministic behavior for retail clients cannot be fixed, so this will remain a source of potential mismatches for unpatched clients. - // Fall back to the center position because no valid position was found, so that the behavior is deterministic for patched clients. + // Fall back to the center position if no valid position was found, so that the behavior is deterministic for patched clients. + Coord3D resultPos = *pos; + if (!ThePartitionManager->findPositionAround(pos, &fpOptions, &resultPos)) { + DEBUG_ASSERTCRASH(resultPos == *pos, ("Position should not have been changed")); + #if RETAIL_COMPATIBLE_CRC DEBUG_CRASH(("A mismatch is likely to happen if this code path is used in a match with unpatched clients.")); #endif - resultPos = *pos; } doStuffToObj( debris, m_names[pick], &resultPos, mtx, orientation, sourceObj, lifetimeFrames ); } From 6831933e25821254ba15958cf2703ccc276d2e21 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 23 Jan 2026 20:42:16 +0100 Subject: [PATCH 3/3] Replicated in Generals. --- .../GameLogic/Object/ObjectCreationList.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 2398127315d..5c80908f20a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -1294,12 +1294,24 @@ class GenericObjectCreationNugget : public ObjectCreationNugget // longer be necessary and can be taken out -- amit if (m_spreadFormation) { - Coord3D resultPos; FindPositionOptions fpOptions; fpOptions.minRadius = GameLogicRandomValueReal(m_minDistanceAFormation, m_minDistanceBFormation); fpOptions.maxRadius = m_maxDistanceFormation; fpOptions.flags = FPF_USE_HIGHEST_LAYER; - ThePartitionManager->findPositionAround(pos, &fpOptions, &resultPos); + + // TheSuperHackers @bugfix Caball009 12/01/2026 Position variable needs to be initialized before use. + // The non-deterministic behavior for retail clients cannot be fixed, so this will remain a source of potential mismatches for unpatched clients. + // Fall back to the center position if no valid position was found, so that the behavior is deterministic for patched clients. + Coord3D resultPos = *pos; + + if (!ThePartitionManager->findPositionAround(pos, &fpOptions, &resultPos)) + { + DEBUG_ASSERTCRASH(resultPos == *pos, ("Position should not have been changed")); + +#if RETAIL_COMPATIBLE_CRC + DEBUG_CRASH(("A mismatch is likely to happen if this code path is used in a match with unpatched clients.")); +#endif + } doStuffToObj( debris, m_names[pick], &resultPos, mtx, orientation, sourceObj, lifetimeFrames ); } else