From f494e73c3d70f63d3b39390b6ce4e3145314326b Mon Sep 17 00:00:00 2001 From: CookieLand Projects <140243064+CookieLandProjects@users.noreply.github.com> Date: Wed, 17 Jun 2026 06:04:45 +0200 Subject: [PATCH] Fixed guard (retaliation) states. --- Generals/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp | 6 ++++++ GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp | 7 +++++++ .../GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp index d8caf323f82..e00b82b215d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp @@ -175,7 +175,13 @@ AIGuardMachine::AIGuardMachine( Object *owner ) : // order matters: first state is the default state. // srj sez: I made "return" the start state, so that if ordered to guard a position // that isn't the unit's current position, it moves to that position first. +#if RETAIL_COMPATIBLE_CRC defineState( AI_GUARD_RETURN, newInstance(AIGuardReturnState)( this ), AI_GUARD_IDLE, AI_GUARD_INNER, attackAggressors ); +#else + // TheSuperHackers @bugfix 09/04/2026 The attack aggressors conditions for AI_GUARD_RETURN + // were removed to fix the conflicting movement and fire behavior in guard mode when the unit is under attack. + defineState( AI_GUARD_RETURN, newInstance(AIGuardReturnState)( this ), AI_GUARD_IDLE, AI_GUARD_INNER ); +#endif defineState( AI_GUARD_IDLE, newInstance(AIGuardIdleState)( this ), AI_GUARD_INNER, AI_GUARD_RETURN, attackAggressors ); defineState( AI_GUARD_INNER, newInstance(AIGuardInnerState)( this ), AI_GUARD_OUTER, AI_GUARD_OUTER ); defineState( AI_GUARD_OUTER, newInstance(AIGuardOuterState)( this ), AI_GUARD_GET_CRATE, AI_GUARD_GET_CRATE ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp index 82f96191931..4898b8a9dc4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp @@ -179,8 +179,15 @@ AIGuardMachine::AIGuardMachine( Object *owner ) : //Kris: Except that guard return is more like an attack move, and will acquire targets while moving there. //This breaks deployAI units because they have to completely unpack before realizing that there is a target in range. //So I'm making AI_GUARD_INNER the first state. +#if RETAIL_COMPATIBLE_CRC defineState( AI_GUARD_INNER, newInstance(AIGuardInnerState)( this ), AI_GUARD_OUTER, AI_GUARD_OUTER, attackAggressors ); defineState( AI_GUARD_RETURN, newInstance(AIGuardReturnState)( this ), AI_GUARD_IDLE, AI_GUARD_INNER, attackAggressors ); +#else + // TheSuperHackers @bugfix 09/04/2026 The attack aggressors conditions for AI_GUARD_INNER and AI_GUARD_RETURN + // were removed to fix the conflicting movement and fire behavior in guard mode when the unit is under attack. + defineState( AI_GUARD_INNER, newInstance(AIGuardInnerState)( this ), AI_GUARD_OUTER, AI_GUARD_OUTER ); + defineState( AI_GUARD_RETURN, newInstance(AIGuardReturnState)( this ), AI_GUARD_IDLE, AI_GUARD_INNER ); +#endif defineState( AI_GUARD_IDLE, newInstance(AIGuardIdleState)( this ), AI_GUARD_INNER, AI_GUARD_RETURN, attackAggressors ); defineState( AI_GUARD_OUTER, newInstance(AIGuardOuterState)( this ), AI_GUARD_GET_CRATE, AI_GUARD_GET_CRATE ); defineState( AI_GUARD_GET_CRATE, newInstance(AIGuardPickUpCrateState)( this ), AI_GUARD_RETURN, AI_GUARD_RETURN ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp index e120a58c4df..0c352c2e145 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp @@ -184,7 +184,13 @@ AIGuardRetaliateMachine::AIGuardRetaliateMachine( Object *owner ) : // srj sez: I made "return" the start state, so that if ordered to guard a position // that isn't the unit's current position, it moves to that position first. defineState( AI_GUARD_RETALIATE_ATTACK_AGGRESSOR, newInstance(AIGuardRetaliateAttackAggressorState)( this ), AI_GUARD_RETALIATE_RETURN, AI_GUARD_RETALIATE_RETURN ); +#if RETAIL_COMPATIBLE_CRC defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER, attackAggressors ); +#else + // TheSuperHackers @bugfix 09/04/2026 The attack aggressors conditions for AI_GUARD_RETALIATE_RETURN + // were removed to fix the conflicting movement and fire behavior in guard mode when the unit is under attack. + defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER ); +#endif defineState( AI_GUARD_RETALIATE_IDLE, newInstance(AIGuardRetaliateIdleState)( this ), AI_GUARD_RETALIATE_INNER, EXIT_MACHINE_WITH_SUCCESS, attackAggressors ); defineState( AI_GUARD_RETALIATE_INNER, newInstance(AIGuardRetaliateInnerState)( this ), AI_GUARD_RETALIATE_OUTER, AI_GUARD_RETALIATE_OUTER ); defineState( AI_GUARD_RETALIATE_OUTER, newInstance(AIGuardRetaliateOuterState)( this ), AI_GUARD_RETALIATE_GET_CRATE, AI_GUARD_RETALIATE_GET_CRATE );