Skip to content

Conversation

@CookieLandProjects
Copy link

Made Guard do what its supposed to instead of retaliating when its not supposed to.
Fix for:
#2097

@greptile-apps
Copy link

greptile-apps bot commented Jan 26, 2026

Greptile Overview

Greptile Summary

Removed the attackAggressors condition from specific guard AI states (AI_GUARD_INNER, AI_GUARD_RETURN, and AI_GUARD_RETALIATE_RETURN) to fix incorrect retaliation behavior.

  • Units in RETURN state (moving back to guard position) no longer inappropriately retaliate when attacked
  • Units in INNER state (actively engaging detected enemies) no longer switch targets when hit by a different attacker
  • Only units in IDLE state will now retaliate when attacked, which is the correct behavior for guard mode
  • The fix ensures guard units complete their current objective before responding to new threats

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are minimal, focused, and logically sound. The fix correctly removes automatic retaliation from states where units should not be distracted (INNER and RETURN states), while preserving it in the IDLE state where it belongs. The change is consistent across both guard AI implementations and does not introduce new code or modify existing logic beyond removing the inappropriate state condition parameter.
  • No files require special attention

Important Files Changed

Filename Overview
GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuard.cpp Removed attackAggressors condition from AI_GUARD_INNER and AI_GUARD_RETURN states to prevent incorrect retaliation behavior
GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGuardRetaliate.cpp Removed attackAggressors condition from AI_GUARD_RETALIATE_RETURN state to prevent incorrect retaliation behavior during return movement

Sequence Diagram

sequenceDiagram
    participant Unit as Guard Unit
    participant Idle as IDLE State
    participant Inner as INNER State
    participant Return as RETURN State
    participant AttackAgg as ATTACK_AGGRESSOR State

    Note over Unit,AttackAgg: Before Fix
    Unit->>Return: Move to guard position
    Return-->>AttackAgg: Unit gets attacked (attackAggressors)
    AttackAgg->>AttackAgg: Retaliate inappropriately
    
    Note over Unit,AttackAgg: After Fix
    Unit->>Return: Move to guard position
    Note over Return: No retaliation while returning
    Return->>Idle: Reach guard position
    Idle-->>AttackAgg: Unit gets attacked (attackAggressors)
    AttackAgg->>AttackAgg: Retaliate correctly
    AttackAgg->>Inner: Return to guard
    
    Note over Unit,AttackAgg: State Transition Logic
    Idle->>Inner: Enemy detected in range
    Inner->>Inner: Engage enemy
    Inner->>Return: Combat complete
    Return->>Idle: Reached guard position
Loading

Comment on lines +182 to +183
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 );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to check RETAIL_COMPATIBLE_CRC to maintain retail compatibility.

Suggested change
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 );
#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
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs // TheSuperHackers @bugfix ... comment in the #else block.

@@ -184,7 +184,7 @@ 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 );
defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER, attackAggressors );
defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to check RETAIL_COMPATIBLE_CRC to maintain retail compatibility.

Suggested change
defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER );
#if RETAIL_COMPATIBLE_CRC
defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER, attackAggressors );
#else
defineState( AI_GUARD_RETALIATE_RETURN, newInstance(AIGuardRetaliateReturnState)( this ), AI_GUARD_RETALIATE_IDLE, AI_GUARD_RETALIATE_INNER );
#endif

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs // TheSuperHackers @bugfix ... comment in the #else block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants