From c10f6de127b5a2dbfa87577f0fc23b43ce54e692 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:36:19 +0100 Subject: [PATCH 1/4] fix(logic): Improve handling of ENABLE_RETALIATION_MODE in GameLogicDispatch --- .../Source/GameLogic/System/GameLogicDispatch.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index f2483a1e15..5cb0fd99b3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -632,15 +632,9 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) case GameMessage::MSG_ENABLE_RETALIATION_MODE: { - //Logically turns on or off retaliation mode for a specified player. - Int playerIndex = msg->getArgument( 0 )->integer; + // TheSuperHackers @info The first argument is unused. Bool enableRetaliation = msg->getArgument( 1 )->boolean; - - Player *player = ThePlayerList->getNthPlayer( playerIndex ); - if( player ) - { - player->setLogicalRetaliationModeEnabled( enableRetaliation ); - } + thisPlayer->setLogicalRetaliationModeEnabled( enableRetaliation ); break; } From 6d9e872aa50d4dcb481cd323e48a8ca71137ed02 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Wed, 4 Mar 2026 23:26:44 +0100 Subject: [PATCH 2/4] Skip the first message argument in non-retail mode --- GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h | 2 +- GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp | 2 ++ .../GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h b/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h index 100e6dd682..66a9165a8f 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h @@ -600,7 +600,7 @@ class GameMessage : public MemoryPoolObject MSG_CREATE_FORMATION, ///< Creates a formation. MSG_LOGIC_CRC, ///< CRC from the logic passed around in a network game :) MSG_SET_MINE_CLEARING_DETAIL, ///< CRC from the logic passed around in a network game :) - MSG_ENABLE_RETALIATION_MODE, ///< Turn retaliation mode on or off for the specified player. + MSG_ENABLE_RETALIATION_MODE, ///< Turn retaliation mode on or off. MSG_BEGIN_DEBUG_NETWORK_MESSAGES = 1900, ///< network messages that exist only in debug/internal builds. all grouped separately. diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp index f7a676be93..5c4009fd42 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -707,7 +707,9 @@ void Player::update() GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_ENABLE_RETALIATION_MODE ); if( msg ) { +#if RETAIL_COMPATIBLE_CRC msg->appendIntegerArgument( getPlayerIndex() ); +#endif msg->appendBooleanArgument( TheGlobalData->m_clientRetaliationModeEnabled ); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index 5cb0fd99b3..e2d5a57643 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -632,8 +632,12 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) case GameMessage::MSG_ENABLE_RETALIATION_MODE: { +#if RETAIL_COMPATIBLE_CRC // TheSuperHackers @info The first argument is unused. Bool enableRetaliation = msg->getArgument( 1 )->boolean; +#else + Bool enableRetaliation = msg->getArgument( 0 )->boolean; +#endif thisPlayer->setLogicalRetaliationModeEnabled( enableRetaliation ); break; } From 1b1cd37c33f5780e6abacc5d8b9bd6d2a211f172 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Thu, 5 Mar 2026 21:38:03 +0100 Subject: [PATCH 3/4] Add const --- .../GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index e2d5a57643..65cbf3cb5f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -634,9 +634,9 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { #if RETAIL_COMPATIBLE_CRC // TheSuperHackers @info The first argument is unused. - Bool enableRetaliation = msg->getArgument( 1 )->boolean; + const Bool enableRetaliation = msg->getArgument( 1 )->boolean; #else - Bool enableRetaliation = msg->getArgument( 0 )->boolean; + const Bool enableRetaliation = msg->getArgument( 0 )->boolean; #endif thisPlayer->setLogicalRetaliationModeEnabled( enableRetaliation ); break; From d4acfd63c0e8407bb8907a119f6975f2a736fc4d Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Sun, 8 Mar 2026 23:10:43 +0100 Subject: [PATCH 4/4] Use retail compatible crc. Add debug assertcrash --- .../GameLogic/System/GameLogicDispatch.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index 65cbf3cb5f..85bd86f197 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -633,12 +633,25 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) case GameMessage::MSG_ENABLE_RETALIATION_MODE: { #if RETAIL_COMPATIBLE_CRC - // TheSuperHackers @info The first argument is unused. + //Logically turns on or off retaliation mode for a specified player. + const Int playerIndex = msg->getArgument( 0 )->integer; const Bool enableRetaliation = msg->getArgument( 1 )->boolean; + + Player *player = ThePlayerList->getNthPlayer( playerIndex ); + if( player ) + { + DEBUG_ASSERTCRASH(player == thisPlayer, + ("Retaliation mode of player '%ls' was illegally set by player '%ls'. Before: '%d', after: '%d'.", + player->getPlayerDisplayName().str(), thisPlayer->getPlayerDisplayName().str(), + player->isLogicalRetaliationModeEnabled(), enableRetaliation) ); + + player->setLogicalRetaliationModeEnabled( enableRetaliation ); + } #else + // TheSuperHackers @fix stephanmeesters 08/03/2026 Ensure that players can only set their own retaliation mode. const Bool enableRetaliation = msg->getArgument( 0 )->boolean; -#endif thisPlayer->setLogicalRetaliationModeEnabled( enableRetaliation ); +#endif break; }