Skip to content

bugfix: Make healed units follow building rally point on exit#1822

Open
tintinhamans wants to merge 3 commits intoTheSuperHackers:mainfrom
tintinhamans:arctic/issue-221
Open

bugfix: Make healed units follow building rally point on exit#1822
tintinhamans wants to merge 3 commits intoTheSuperHackers:mainfrom
tintinhamans:arctic/issue-221

Conversation

@tintinhamans
Copy link

@tintinhamans tintinhamans commented Nov 7, 2025

Units will now follow building rally point after healing.

Closes #221

@tintinhamans tintinhamans added Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker NoRetail This fix or change is not applicable with Retail game compatibility labels Nov 7, 2025
@greptile-apps
Copy link

greptile-apps bot commented Feb 3, 2026

Greptile Summary

This PR makes healed units follow building rally points after exiting, fixing issue #221. The implementation adds rally point movement logic for Chinooks and helicopters after healing completes, and updates the contain exit system to properly chain rally points from the building's primary exit interface.

Key changes:

  • OpenContain::getRallyPoint() now falls back to the primary exit interface's rally point when the contain itself doesn't have one
  • OpenContain::exitObjectViaDoor() uses the getRallyPoint() method for better rally point resolution
  • Chinooks and helicopters move to their airfield's rally point after healing completes and taking off
  • All changes properly guarded with !RETAIL_COMPATIBLE_CRC for compatibility
  • Changes mirrored correctly between Generals/ and GeneralsMD/ codebases

Code quality:

  • Defensive null checking at all levels (airfield, exit interface, rally point)
  • Follows established patterns seen in ParkingPlaceBehavior for rally point movement
  • Recursion protection in getRallyPoint() fallback logic

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • All changes follow established patterns, use proper null checking, and are well-guarded for compatibility. Previous review concerns have been adequately addressed and the implementation is straightforward and defensive
  • No files require special attention

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp Modified getRallyPoint() to fall back to primary exit interface and updated exitObjectViaDoor() to use the method instead of direct member access
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp Added logic to move healed Chinooks to airfield rally point after takeoff, with proper null checks for airfield, exit interface, and rally point
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp Added logic to move healed helicopters to airfield rally point after takeoff, with proper null checks matching the Chinook implementation
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp Mirror of Generals version - modified getRallyPoint() fallback logic and exitObjectViaDoor() to use the method
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp Mirror of Generals version - added rally point movement logic for healed Chinooks with proper null checks
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp Mirror of Generals version - added rally point movement logic for healed helicopters with proper null checks

Last reviewed commit: 5a3b849

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

6 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@tintinhamans tintinhamans changed the title bugfix: Make healed infantry follow the building rally point bugfix: Make healed units follow building rally point on exit Feb 8, 2026
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link

greptile-apps bot commented Feb 8, 2026

Additional Comments (2)

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
airfield could be nullptr if the airfield was destroyed or doesn't exist. Need null check before calling getObjectExitInterface().

				Object *airfield = TheGameLogic->findObjectByID( m_airfieldForHealing );
				if (airfield)
				{
					const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
					if( rp )
					{
						AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
						parms.m_pos = *rp;
						m_pendingCommand.store( parms );
						m_hasPendingCommand = true;
					}
				}
Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
Line: 1038:1039

Comment:
`airfield` could be `nullptr` if the airfield was destroyed or doesn't exist. Need null check before calling `getObjectExitInterface()`.

```suggestion
				Object *airfield = TheGameLogic->findObjectByID( m_airfieldForHealing );
				if (airfield)
				{
					const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
					if( rp )
					{
						AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
						parms.m_pos = *rp;
						m_pendingCommand.store( parms );
						m_hasPendingCommand = true;
					}
				}
```

How can I resolve this? If you propose a fix, please make it concise.

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
airfield could be nullptr if the airfield was destroyed or doesn't exist (see line 1717-1718 in same file for precedent). Need null check before calling getObjectExitInterface().

					Object *airfield = TheGameLogic->findObjectByID( jet->getProducerID() );
					if (airfield)
					{
						const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
						if( rp )
						{
							AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
							parms.m_pos = *rp;
							m_mostRecentCommand.store( parms );
							setFlag(HAS_PENDING_COMMAND, true);
						}
					}
Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Line: 1782:1783

Comment:
`airfield` could be `nullptr` if the airfield was destroyed or doesn't exist (see line 1717-1718 in same file for precedent). Need null check before calling `getObjectExitInterface()`.

```suggestion
					Object *airfield = TheGameLogic->findObjectByID( jet->getProducerID() );
					if (airfield)
					{
						const Coord3D *rp = airfield->getObjectExitInterface()->getRallyPoint();
						if( rp )
						{
							AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
							parms.m_pos = *rp;
							m_mostRecentCommand.store( parms );
							setFlag(HAS_PENDING_COMMAND, true);
						}
					}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

6 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +1779 to +1781
// TheSuperHackers @bugfix arcticdolphin 08/02/2026 Move healed helicopter to rally point if present.
#if !RETAIL_COMPATIBLE_CRC
{
Copy link

Choose a reason for hiding this comment

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

Airfield exit interface unchecked
airfield ? airfield->getObjectExitInterface() : nullptr still assumes the airfield exists and that it has an ExitInterface. The earlier pp != nullptr check doesn’t guarantee findObjectByID(jet->getProducerID()) returns a valid object at this later point, nor that getObjectExitInterface() is non-null. A direct if (airfield != nullptr) { ExitInterface* exit = airfield->getObjectExitInterface(); if (exit != nullptr) ... } guard avoids a crash.

Also appears in GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp:2001-2013.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp
Line: 1779:1781

Comment:
**Airfield exit interface unchecked**
`airfield ? airfield->getObjectExitInterface() : nullptr` still assumes the airfield exists and that it has an ExitInterface. The earlier `pp != nullptr` check doesn’t guarantee `findObjectByID(jet->getProducerID())` returns a valid object at this later point, nor that `getObjectExitInterface()` is non-null. A direct `if (airfield != nullptr) { ExitInterface* exit = airfield->getObjectExitInterface(); if (exit != nullptr) ... }` guard avoids a crash.

Also appears in `GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp:2001-2013`.

How can I resolve this? If you propose a fix, please make it concise.

const Coord3D* rp = buildingExit->getRallyPoint();
if (rp)
{
setRallyPoint(rp);
Copy link

Choose a reason for hiding this comment

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

This looks strange. Basically the Rally Point of the HealContain is now set/updated after every heal. Which begs the question, why is the Rally Point not updated for the Heal Contain when the Rally Point of the Object Exit Interface is updated? That would be the most logical and efficient way (and maybe that is what was supposed to happen but is broken somewhere).

const Coord3D *rp = exitInterface ? exitInterface->getRallyPoint() : nullptr;
if( rp )
{
AICommandParms parms( AICMD_MOVE_TO_POSITION, CMD_FROM_AI );
Copy link

Choose a reason for hiding this comment

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

Is this the correct way to do the movement for this purpose?

For reference

OpenContain::exitObjectViaDoor uses ai->aiFollowPath( &exitPath, me, CMD_FROM_AI ) to go to the Rally Point.

DefaultProductionExitUpdate::exitObjectViaDoor uses ai->aiFollowExitProductionPath( &exitPath, creationObject, CMD_FROM_AI ) to go to the Rally Point.

Helicopter looks special, so perhaps that is fine. Unclear.

Copy link
Author

Choose a reason for hiding this comment

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

I think this is correct. The Chinook/helicopter is landed when healing and needs to take off first - it cannot follow a path directly. This matches how ParkingPlaceBehavior::exitObjectViaDoor handles helipad-produced aircraft:

if( producedAtHelipad )
{
const Coord3D *rallyPoint = getRallyPoint();
if( rallyPoint )
{
ai->aiMoveToPosition( rallyPoint, CMD_FROM_AI );
movedToRallyPoint = TRUE;
}
}

I did see from above that I can use aiMoveToPosition instead of storing pending command manually since aiDoCommand already handles takeoff in-progress and queues move for us.

…e rally point if available

Signed-off-by: tintinhamans <5984296+tintinhamans@users.noreply.github.com>
Signed-off-by: tintinhamans <5984296+tintinhamans@users.noreply.github.com>
Signed-off-by: tintinhamans <5984296+tintinhamans@users.noreply.github.com>
@tintinhamans tintinhamans requested a review from xezon March 2, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker NoRetail This fix or change is not applicable with Retail game compatibility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Infantry healed in Barracks does not follow Rally Point, but Vehicle repaired in Factory does

3 participants