From 57cf4c2875771ac7a21e14b7a8744344ef26ca69 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 11:53:39 -0500 Subject: [PATCH 01/20] Use move semantics in aiFollowPath and aiFollowExitProductionPath --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 8 ++++---- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index dc2053d4cc..ab5c57e4b1 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -536,18 +536,18 @@ class AICommandInterface aiDoCommand(&parms); } - void aiFollowExitProductionPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = *path; + parms.m_coords = std::move(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } - void aiFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = *path; + parms.m_coords = std::move(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 23cf4f94f8..3336339597 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -550,18 +550,18 @@ class AICommandInterface aiDoCommand(&parms); } - void aiFollowExitProductionPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = *path; + parms.m_coords = std::move(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } - void aiFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = *path; + parms.m_coords = std::move(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } From ea081efe2601cf6eaaeae0826ca2d13dc5665b1a Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 11:53:45 -0500 Subject: [PATCH 02/20] Use move semantics in AIStateMachine::setGoalPath --- Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h | 2 +- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h | 2 +- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 03f0de0e73..7e39c8ec7c 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -138,7 +138,7 @@ class AIStateMachine : public StateMachine virtual StateReturnType setState( StateID newStateID ); /// @todo Rethink state parameter passing. Continuing in this fashion will have a pile of params in the machine (MSB) - void setGoalPath( const std::vector* path ); + void setGoalPath( std::vector* path ); void addToGoalPath( const Coord3D *pathPoint ); const Coord3D *getGoalPathPosition( Int i ) const; ///< return path position at index "i" Int getGoalPathSize() const { return m_goalPath.size(); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 05ce1ea359..f25ad056e5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -816,9 +816,9 @@ void AIStateMachine::loadPostProcess( void ) /** * Define a simple path */ -void AIStateMachine::setGoalPath( const std::vector* path ) +void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = *path; + m_goalPath = std::move(*path); } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 3171df36bc..8d96e65997 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -141,7 +141,7 @@ class AIStateMachine : public StateMachine virtual StateReturnType setState( StateID newStateID ); /// @todo Rethink state parameter passing. Continuing in this fashion will have a pile of params in the machine (MSB) - void setGoalPath( const std::vector* path ); + void setGoalPath( std::vector* path ); void addToGoalPath( const Coord3D *pathPoint ); const Coord3D *getGoalPathPosition( Int i ) const; ///< return path position at index "i" Int getGoalPathSize() const { return m_goalPath.size(); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 63b3474662..aeddb184db 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -821,9 +821,9 @@ void AIStateMachine::loadPostProcess( void ) /** * Define a simple path */ -void AIStateMachine::setGoalPath( const std::vector* path ) +void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = *path; + m_goalPath = std::move(*path); } #ifdef STATE_MACHINE_DEBUG From 7a8b8a5b297f00452dcbe29863d4e5e9bff28790 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 11:53:51 -0500 Subject: [PATCH 03/20] Update privateFollowPath to use move semantics --- Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h | 4 ++-- .../Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h | 4 ++-- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- .../Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp | 2 +- .../Code/GameEngine/Include/GameLogic/Module/AIUpdate.h | 4 ++-- .../Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h | 4 ++-- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- .../Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h index 0482f737aa..b47f353ecf 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h @@ -244,7 +244,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual void privateFollowWaypointPathAsTeam( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathAsTeamExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -338,7 +338,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual Bool isBusy() const; virtual void onObjectCreated(); - virtual void doQuickExit( const std::vector* path ); ///< get out of this Object + virtual void doQuickExit( std::vector* path ); ///< get out of this Object virtual void aiDoCommand(const AICommandParms* parms); diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h index cc6f8c4e72..3c8579ebf1 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h @@ -104,7 +104,7 @@ class JetAIUpdate : public AIUpdateInterface Real friend_getMinHeight() const { return getJetAIUpdateModuleData()->m_minHeight; } Real friend_getParkingOffset() const { return getJetAIUpdateModuleData()->m_parkingOffset; } UnsignedInt friend_getTakeoffPause() const { return getJetAIUpdateModuleData()->m_takeoffPause; } - void friend_setGoalPath( const std::vector* path ) { getStateMachine()->setGoalPath(path); } + void friend_setGoalPath( std::vector* path ) { getStateMachine()->setGoalPath(path); } void friend_setTakeoffInProgress(Bool v) { setFlag(TAKEOFF_IN_PROGRESS, v); } void friend_setLandingInProgress(Bool v) { setFlag(LANDING_IN_PROGRESS, v); } void friend_setTaxiInProgress(Bool v) { setFlag(TAXI_IN_PROGRESS, v); } @@ -122,7 +122,7 @@ class JetAIUpdate : public AIUpdateInterface virtual AIStateMachine* makeStateMachine(); - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateEnter( Object *obj, CommandSourceType cmdSource ); ///< enter the given object virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 67cedc7f37..417da21350 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3240,7 +3240,7 @@ void AIUpdateInterface::privateFollowPathAppend( const Coord3D *pos, CommandSour /** * Follow the path defined by the given array of points */ -void AIUpdateInterface::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void AIUpdateInterface::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (getObject()->isMobile() == FALSE) return; @@ -3681,7 +3681,7 @@ void AIUpdateInterface::privateExit( Object *objectToExit, CommandSourceType cmd /** * Get out of whatever it is inside of */ -void AIUpdateInterface::doQuickExit( const std::vector* path ) +void AIUpdateInterface::doQuickExit( std::vector* path ) { Bool locked = getStateMachine()->isLocked(); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index f264228618..1ce63cffc5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -2172,7 +2172,7 @@ Bool JetAIUpdate::getTreatAsAircraftForLocoDistToGoal() const /** * Follow the path defined by the given array of points */ -void JetAIUpdate::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void JetAIUpdate::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (exitProduction) { diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h index 423977192c..32e562d23a 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h @@ -249,7 +249,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual void privateFollowWaypointPathAsTeam( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathAsTeamExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -351,7 +351,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual Bool isBusy() const; virtual void onObjectCreated(); - virtual void doQuickExit( const std::vector* path ); ///< get out of this Object + virtual void doQuickExit( std::vector* path ); ///< get out of this Object virtual void aiDoCommand(const AICommandParms* parms); diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h index 1840d30a4b..a7cd1157aa 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h @@ -110,7 +110,7 @@ class JetAIUpdate : public AIUpdateInterface Real friend_getMinHeight() const { return getJetAIUpdateModuleData()->m_minHeight; } Real friend_getParkingOffset() const { return getJetAIUpdateModuleData()->m_parkingOffset; } UnsignedInt friend_getTakeoffPause() const { return getJetAIUpdateModuleData()->m_takeoffPause; } - void friend_setGoalPath( const std::vector* path ) { getStateMachine()->setGoalPath(path); } + void friend_setGoalPath( std::vector* path ) { getStateMachine()->setGoalPath(path); } void friend_setTakeoffInProgress(Bool v) { setFlag(TAKEOFF_IN_PROGRESS, v); } void friend_setLandingInProgress(Bool v) { setFlag(LANDING_IN_PROGRESS, v); } void friend_setTaxiInProgress(Bool v) { setFlag(TAXI_IN_PROGRESS, v); } @@ -131,7 +131,7 @@ class JetAIUpdate : public AIUpdateInterface virtual AIStateMachine* makeStateMachine(); - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateEnter( Object *obj, CommandSourceType cmdSource ); ///< enter the given object virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 7bc310b7d6..afc37725bf 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3377,7 +3377,7 @@ void AIUpdateInterface::privateFollowPathAppend( const Coord3D *pos, CommandSour /** * Follow the path defined by the given array of points */ -void AIUpdateInterface::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void AIUpdateInterface::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (getObject()->isMobile() == FALSE) return; @@ -3869,7 +3869,7 @@ void AIUpdateInterface::privateExitInstantly( Object *objectToExit, CommandSourc /** * Get out of whatever it is inside of */ -void AIUpdateInterface::doQuickExit( const std::vector* path ) +void AIUpdateInterface::doQuickExit( std::vector* path ) { Bool locked = getStateMachine()->isLocked(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index 4e3b24a426..dc2a4162b7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -2399,7 +2399,7 @@ Bool JetAIUpdate::getTreatAsAircraftForLocoDistToGoal() const /** * Follow the path defined by the given array of points */ -void JetAIUpdate::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void JetAIUpdate::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (exitProduction) { From 86668ca7a218cde67a3281f7da9d356c6b117258 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 12:18:17 -0500 Subject: [PATCH 04/20] Use swap instead of move for VC6 compatibility --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 2 +- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index ab5c57e4b1..c32eee4101 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -539,7 +539,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = std::move(*path); + parms.m_coords.swap(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -547,7 +547,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = std::move(*path); + parms.m_coords.swap(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index f25ad056e5..ef4ada4794 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -818,7 +818,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = std::move(*path); + m_goalPath.swap(*path); } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 3336339597..706e1e7046 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -553,7 +553,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = std::move(*path); + parms.m_coords.swap(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -561,7 +561,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = std::move(*path); + parms.m_coords.swap(*path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index aeddb184db..a9e64fb8d8 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -823,7 +823,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = std::move(*path); + m_goalPath.swap(*path); } #ifdef STATE_MACHINE_DEBUG From 46f05dbd26b48b78d9d47366f86fc16d3e1b65ea Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 12:19:47 -0500 Subject: [PATCH 05/20] Use const_cast in aiDoCommand to pass non-const vector to privateFollowPath --- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 417da21350..c4921aceb2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2619,13 +2619,13 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); break; case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); break; case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index afc37725bf..a7c87888c4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2681,13 +2681,13 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); break; case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); break; case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); From 0b5e2ab5e5f7c16cf774c996d3b8a33d8f7dab3c Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 25 Nov 2025 12:48:08 -0500 Subject: [PATCH 06/20] Add conditional compilation for move vs swap and clear source vector --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 12 ++++++++++++ .../Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 7 +++++++ GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 12 ++++++++++++ .../Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 7 +++++++ 4 files changed, 38 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index c32eee4101..d6ff11b5bb 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -539,7 +539,13 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); +#if __cplusplus >= 201103L + parms.m_coords = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility parms.m_coords.swap(*path); + path->clear(); +#endif parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -547,7 +553,13 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); +#if __cplusplus >= 201103L + parms.m_coords = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility parms.m_coords.swap(*path); + path->clear(); +#endif parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index ef4ada4794..8341cb2f2e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -818,7 +818,14 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { +#if __cplusplus >= 201103L + m_goalPath = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility + // Swap transfers ownership without copying. Clear source to make intent explicit. m_goalPath.swap(*path); + path->clear(); +#endif } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 706e1e7046..666f8049fc 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -553,7 +553,13 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); +#if __cplusplus >= 201103L + parms.m_coords = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility parms.m_coords.swap(*path); + path->clear(); +#endif parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -561,7 +567,13 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); +#if __cplusplus >= 201103L + parms.m_coords = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility parms.m_coords.swap(*path); + path->clear(); +#endif parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index a9e64fb8d8..0a4bfd1430 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -823,7 +823,14 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { +#if __cplusplus >= 201103L + m_goalPath = std::move(*path); +#else + // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility + // Swap transfers ownership without copying. Clear source to make intent explicit. m_goalPath.swap(*path); + path->clear(); +#endif } #ifdef STATE_MACHINE_DEBUG From 5c21432eff92d22a5bfc3a5c223e9ea23a09cf0a Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 25 Nov 2025 14:18:54 -0500 Subject: [PATCH 07/20] nit: make comments consistent --- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 1 - GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 8341cb2f2e..517e2c6108 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -822,7 +822,6 @@ void AIStateMachine::setGoalPath( std::vector* path ) m_goalPath = std::move(*path); #else // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - // Swap transfers ownership without copying. Clear source to make intent explicit. m_goalPath.swap(*path); path->clear(); #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 0a4bfd1430..73cc1168ce 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -827,7 +827,6 @@ void AIStateMachine::setGoalPath( std::vector* path ) m_goalPath = std::move(*path); #else // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - // Swap transfers ownership without copying. Clear source to make intent explicit. m_goalPath.swap(*path); path->clear(); #endif From 166de5311c6306369f86d0ba08cc6e7fb49ad2cb Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 25 Nov 2025 14:34:08 -0500 Subject: [PATCH 08/20] refactor(perf): centralize move semantics helper in CppMacros.h --- Dependencies/Utility/Utility/CppMacros.h | 16 ++++++++++++++++ Generals/Code/GameEngine/Include/GameLogic/AI.h | 17 +++-------------- .../Include/GameLogic/AIStateMachine.h | 2 ++ .../GameEngine/Source/GameLogic/AI/AIStates.cpp | 8 +------- .../Code/GameEngine/Include/GameLogic/AI.h | 17 +++-------------- .../Include/GameLogic/AIStateMachine.h | 2 ++ .../GameEngine/Source/GameLogic/AI/AIStates.cpp | 8 +------- 7 files changed, 28 insertions(+), 42 deletions(-) diff --git a/Dependencies/Utility/Utility/CppMacros.h b/Dependencies/Utility/Utility/CppMacros.h index 8bfb0297f2..aa7b8cf4c6 100644 --- a/Dependencies/Utility/Utility/CppMacros.h +++ b/Dependencies/Utility/Utility/CppMacros.h @@ -19,6 +19,10 @@ // This file contains macros to help upgrade the code for newer cpp standards. #pragma once +#if __cplusplus >= 201103L +#include +#endif + #if __cplusplus >= 201703L #define NOEXCEPT_17 noexcept #define REGISTER @@ -44,3 +48,15 @@ #define constexpr #define nullptr 0 #endif + +// TheSuperHackers @performance bobtista 25/11/2025 Helper to move-assign from pointer: uses std::move in C++11, swap in C++98 +template +inline void move_assign_from_pointer(T& dest, T* src) +{ +#if __cplusplus >= 201103L + dest = std::move(*src); +#else + // Use swap to emulate move semantics for VC6 compatibility + dest.swap(*src); +#endif +} diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index d6ff11b5bb..f5baf17db6 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -35,6 +35,7 @@ #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" #include "ref_ptr.h" +#include "Utility/CppMacros.h" class AIGroup; class AttackPriorityInfo; @@ -539,13 +540,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); -#if __cplusplus >= 201103L - parms.m_coords = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - parms.m_coords.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(parms.m_coords, path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -553,13 +548,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); -#if __cplusplus >= 201103L - parms.m_coords = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - parms.m_coords.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(parms.m_coords, path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 7e39c8ec7c..3992972456 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -108,6 +108,8 @@ extern Bool outOfWeaponRangeObject( State *thisState, void* userData ); extern Bool outOfWeaponRangePosition( State *thisState, void* userData ); extern Bool wantToSquishTarget( State *thisState, void* userData ); +#include "Utility/CppMacros.h" + //----------------------------------------------------------------------------------------------------------- /** The AI state machine. This is used by AIUpdate to implement all of the diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 517e2c6108..494b0dd6b4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -818,13 +818,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { -#if __cplusplus >= 201103L - m_goalPath = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - m_goalPath.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(m_goalPath, path); } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 666f8049fc..2504489717 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -35,6 +35,7 @@ #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" #include "ref_ptr.h" +#include "Utility/CppMacros.h" class AIGroup; class AttackPriorityInfo; @@ -553,13 +554,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); -#if __cplusplus >= 201103L - parms.m_coords = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - parms.m_coords.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(parms.m_coords, path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -567,13 +562,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); -#if __cplusplus >= 201103L - parms.m_coords = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - parms.m_coords.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(parms.m_coords, path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 8d96e65997..67274eae0d 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -111,6 +111,8 @@ extern Bool outOfWeaponRangeObject( State *thisState, void* userData ); extern Bool outOfWeaponRangePosition( State *thisState, void* userData ); extern Bool wantToSquishTarget( State *thisState, void* userData ); +#include "Utility/CppMacros.h" + //----------------------------------------------------------------------------------------------------------- /** The AI state machine. This is used by AIUpdate to implement all of the diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 73cc1168ce..468c50e11e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -823,13 +823,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { -#if __cplusplus >= 201103L - m_goalPath = std::move(*path); -#else - // TheSuperHackers @performance bobtista 23/11/2025 Use swap to emulate move semantics for VC6 compatibility - m_goalPath.swap(*path); - path->clear(); -#endif + move_assign_from_pointer(m_goalPath, path); } #ifdef STATE_MACHINE_DEBUG From 42e0465c42386fa6cf6ca3fec2ed0a8b6ddfb559 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 28 Nov 2025 18:06:11 -0500 Subject: [PATCH 09/20] refactor: remove unnecessary CppMacros.h includes --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 1 - GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 1 - 2 files changed, 2 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index f5baf17db6..d0634058ae 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -35,7 +35,6 @@ #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" #include "ref_ptr.h" -#include "Utility/CppMacros.h" class AIGroup; class AttackPriorityInfo; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 2504489717..497cb812dd 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -35,7 +35,6 @@ #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" #include "ref_ptr.h" -#include "Utility/CppMacros.h" class AIGroup; class AttackPriorityInfo; From e50980d88fb317a16ad7f683a86782f381d05c71 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Fri, 28 Nov 2025 18:06:26 -0500 Subject: [PATCH 10/20] refactor(perf): rename move_assign_from_pointer to move_or_swap and change parameter to reference --- Dependencies/Utility/Utility/CppMacros.h | 8 ++++---- Generals/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 2 +- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- .../Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dependencies/Utility/Utility/CppMacros.h b/Dependencies/Utility/Utility/CppMacros.h index aa7b8cf4c6..13629e017c 100644 --- a/Dependencies/Utility/Utility/CppMacros.h +++ b/Dependencies/Utility/Utility/CppMacros.h @@ -49,14 +49,14 @@ #define nullptr 0 #endif -// TheSuperHackers @performance bobtista 25/11/2025 Helper to move-assign from pointer: uses std::move in C++11, swap in C++98 +// TheSuperHackers @performance bobtista 25/11/2025 Helper to move-assign from reference: uses std::move in C++11, swap in C++98 template -inline void move_assign_from_pointer(T& dest, T* src) +inline void move_or_swap(T& dest, T& src) { #if __cplusplus >= 201103L - dest = std::move(*src); + dest = std::move(src); #else // Use swap to emulate move semantics for VC6 compatibility - dest.swap(*src); + dest.swap(src); #endif } diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index d0634058ae..5e02c9096d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -539,7 +539,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - move_assign_from_pointer(parms.m_coords, path); + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -547,7 +547,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - move_assign_from_pointer(parms.m_coords, path); + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 494b0dd6b4..2b1ee70194 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -818,7 +818,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { - move_assign_from_pointer(m_goalPath, path); + move_or_swap(m_goalPath, *path); } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 497cb812dd..00bf02666f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -553,7 +553,7 @@ class AICommandInterface inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - move_assign_from_pointer(parms.m_coords, path); + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } @@ -561,7 +561,7 @@ class AICommandInterface inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - move_assign_from_pointer(parms.m_coords, path); + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 468c50e11e..454efde127 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -823,7 +823,7 @@ void AIStateMachine::loadPostProcess( void ) */ void AIStateMachine::setGoalPath( std::vector* path ) { - move_assign_from_pointer(m_goalPath, path); + move_or_swap(m_goalPath, *path); } #ifdef STATE_MACHINE_DEBUG From a4046ceb88aae0816d2d4a9affb00b3c2b086b66 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 29 Nov 2025 09:24:15 -0500 Subject: [PATCH 11/20] refactor(perf): remove comment format and fix C++03 move semantics fallback --- Dependencies/Utility/Utility/CppMacros.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dependencies/Utility/Utility/CppMacros.h b/Dependencies/Utility/Utility/CppMacros.h index 13629e017c..570e8254ce 100644 --- a/Dependencies/Utility/Utility/CppMacros.h +++ b/Dependencies/Utility/Utility/CppMacros.h @@ -49,14 +49,17 @@ #define nullptr 0 #endif -// TheSuperHackers @performance bobtista 25/11/2025 Helper to move-assign from reference: uses std::move in C++11, swap in C++98 +// Helper to move-assign from reference: uses std::move in C++11, swap in C++98 template inline void move_or_swap(T& dest, T& src) { #if __cplusplus >= 201103L dest = std::move(src); #else - // Use swap to emulate move semantics for VC6 compatibility + // C++03 fallback: mimic move semantics + // dest gets src's value, src becomes empty + T empty; dest.swap(src); + src.swap(empty); #endif } From c428f10e97b372e00ba31cd5a33b376e91dddb54 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 29 Nov 2025 09:24:23 -0500 Subject: [PATCH 12/20] refactor(perf): make m_coords mutable to remove const_cast --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 2 +- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 2 +- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index 5e02c9096d..7103edd464 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -407,7 +407,7 @@ struct AICommandParms Object* m_obj; Object* m_otherObj; const Team* m_team; - std::vector m_coords; + mutable std::vector m_coords; const Waypoint* m_waypoint; const PolygonTrigger* m_polygon; Int m_intValue; /// misc usage diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index c4921aceb2..417da21350 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2619,13 +2619,13 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); break; case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); break; case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 00bf02666f..723d53b5be 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -420,7 +420,7 @@ struct AICommandParms Object* m_obj; Object* m_otherObj; const Team* m_team; - std::vector m_coords; + mutable std::vector m_coords; const Waypoint* m_waypoint; const PolygonTrigger* m_polygon; Int m_intValue; /// misc usage diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index a7c87888c4..afc37725bf 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2681,13 +2681,13 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); break; case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&const_cast(parms)->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); break; case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); From 45c064ccd94fb310b638ddd93a93045b810f5255 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 29 Nov 2025 13:34:35 -0500 Subject: [PATCH 13/20] remove include --- Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h | 2 -- GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 3992972456..7e39c8ec7c 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -108,8 +108,6 @@ extern Bool outOfWeaponRangeObject( State *thisState, void* userData ); extern Bool outOfWeaponRangePosition( State *thisState, void* userData ); extern Bool wantToSquishTarget( State *thisState, void* userData ); -#include "Utility/CppMacros.h" - //----------------------------------------------------------------------------------------------------------- /** The AI state machine. This is used by AIUpdate to implement all of the diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 67274eae0d..8d96e65997 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -111,8 +111,6 @@ extern Bool outOfWeaponRangeObject( State *thisState, void* userData ); extern Bool outOfWeaponRangePosition( State *thisState, void* userData ); extern Bool wantToSquishTarget( State *thisState, void* userData ); -#include "Utility/CppMacros.h" - //----------------------------------------------------------------------------------------------------------- /** The AI state machine. This is used by AIUpdate to implement all of the From 8eab14a150dbd2d0c69ba62fccb21cd8980c2d3b Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 15 Dec 2025 10:25:12 -0500 Subject: [PATCH 14/20] refactor(perf): move coords into AICommandParmsStorage via const_cast --- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 5 ++++- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 2b1ee70194..ae0f18d0c7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -95,7 +95,10 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - m_coords = parms.m_coords; + // We intentionally const_cast here so we can move the path coordinates into storage. + // AICommandParms is treated as a transient command container that is not reused after dispatch. + std::vector& coords = const_cast&>(parms.m_coords); + move_or_swap(m_coords, coords); m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 454efde127..1e4c818c5e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -98,7 +98,10 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - m_coords = parms.m_coords; + // We intentionally const_cast here so we can move the path coordinates into storage. + // AICommandParms is treated as a transient command container that is not reused after dispatch. + std::vector& coords = const_cast&>(parms.m_coords); + move_or_swap(m_coords, coords); m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage From 88b027cc0a8d8636b27c11d36ec1c8f145d59f72 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 15 Dec 2025 10:42:21 -0500 Subject: [PATCH 15/20] refactor(perf): remove mutable coords from AICommandParms --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 2 +- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index 7103edd464..5e02c9096d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -407,7 +407,7 @@ struct AICommandParms Object* m_obj; Object* m_otherObj; const Team* m_team; - mutable std::vector m_coords; + std::vector m_coords; const Waypoint* m_waypoint; const PolygonTrigger* m_polygon; Int m_intValue; /// misc usage diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 723d53b5be..00bf02666f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -420,7 +420,7 @@ struct AICommandParms Object* m_obj; Object* m_otherObj; const Team* m_team; - mutable std::vector m_coords; + std::vector m_coords; const Waypoint* m_waypoint; const PolygonTrigger* m_polygon; Int m_intValue; /// misc usage From 80e022c37eb398436ebcbf50173e12113f251845 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 15 Dec 2025 10:50:57 -0500 Subject: [PATCH 16/20] refactor(perf): keep AICommandParms const and copy coords where needed --- .../Source/GameLogic/Object/Update/AIUpdate.cpp | 12 ++++++++++-- .../Source/GameLogic/Object/Update/AIUpdate.cpp | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 417da21350..c200fcc385 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2619,14 +2619,22 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; + } case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break; + } case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); break; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index afc37725bf..7f38a82122 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2681,14 +2681,22 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; + } case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break; + } case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); break; From 8ba650297cd7208501ea0cd967d6201d4ed4f5ce Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 15:45:02 -0500 Subject: [PATCH 17/20] Remove inline keyword from aiFollowPath functions --- GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 00bf02666f..52ba41a5ca 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -550,7 +550,7 @@ class AICommandInterface aiDoCommand(&parms); } - inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); move_or_swap(parms.m_coords, *path); @@ -558,7 +558,7 @@ class AICommandInterface aiDoCommand(&parms); } - inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); move_or_swap(parms.m_coords, *path); From 1f1a897f32830888d9d70b013895e11f3315bbff Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 15:45:03 -0500 Subject: [PATCH 18/20] Use copy instead of const_cast for m_coords in AICommandParmsStorage::store --- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 1e4c818c5e..454efde127 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -98,10 +98,7 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - // We intentionally const_cast here so we can move the path coordinates into storage. - // AICommandParms is treated as a transient command container that is not reused after dispatch. - std::vector& coords = const_cast&>(parms.m_coords); - move_or_swap(m_coords, coords); + m_coords = parms.m_coords; m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage From 95b00a1a2c817d9bf0d618c2c8de31e7c8b309f0 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 15:45:03 -0500 Subject: [PATCH 19/20] Clarify comment about copying coordinates in path following cases --- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 7f38a82122..03e314f43d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2682,7 +2682,7 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) break; case AICMD_FOLLOW_PATH: { - // Keep AICommandParms const; use a local copy of the coordinates when following the path. + // Copy coordinates to a local vector since privateFollowPath requires a non-const pointer. std::vector coords = parms->m_coords; privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; @@ -2692,7 +2692,7 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: { - // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + // Copy coordinates to a local vector since privateFollowPath requires a non-const pointer. std::vector coords = parms->m_coords; privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break; From 5965d0895f8280ac6ff16dd7b2276209a2b8c40b Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 15:45:04 -0500 Subject: [PATCH 20/20] Replicate AI path function changes from GeneralsMD --- Generals/Code/GameEngine/Include/GameLogic/AI.h | 4 ++-- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 5 +---- .../GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index 5e02c9096d..73d678a451 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -536,7 +536,7 @@ class AICommandInterface aiDoCommand(&parms); } - inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); move_or_swap(parms.m_coords, *path); @@ -544,7 +544,7 @@ class AICommandInterface aiDoCommand(&parms); } - inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); move_or_swap(parms.m_coords, *path); diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index ae0f18d0c7..2b1ee70194 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -95,10 +95,7 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - // We intentionally const_cast here so we can move the path coordinates into storage. - // AICommandParms is treated as a transient command container that is not reused after dispatch. - std::vector& coords = const_cast&>(parms.m_coords); - move_or_swap(m_coords, coords); + m_coords = parms.m_coords; m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index c200fcc385..7966ff4bf2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2620,7 +2620,7 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) break; case AICMD_FOLLOW_PATH: { - // Keep AICommandParms const; use a local copy of the coordinates when following the path. + // Copy coordinates to a local vector since privateFollowPath requires a non-const pointer. std::vector coords = parms->m_coords; privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; @@ -2630,7 +2630,7 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: { - // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + // Copy coordinates to a local vector since privateFollowPath requires a non-const pointer. std::vector coords = parms->m_coords; privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break;