From 68d7bcc1ed1722c0aada924501be25975471687c Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:42:11 +0200 Subject: [PATCH 1/7] [CORE] Fix up RefCountClass, RefCountPtr From 0c3bd75d809cd3c91d6e3cb337804cc75e7d904a Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:46:23 +0200 Subject: [PATCH 2/7] [ZH] Improve AIGroup memory management and fix game crash when a player is selected in Replay playback --- .../Code/GameEngine/Include/Common/Player.h | 2 +- .../Code/GameEngine/Include/GameLogic/AI.h | 17 ++- .../GameEngine/Include/GameLogic/Object.h | 3 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 23 ++- .../Source/GameLogic/AI/AIGroup.cpp | 38 ++--- .../Source/GameLogic/AI/AIPlayer.cpp | 8 +- .../Source/GameLogic/AI/AIStates.cpp | 4 +- .../Source/GameLogic/Object/Object.cpp | 13 +- .../GameLogic/ScriptEngine/ScriptActions.cpp | 136 +++++++++--------- .../GameLogic/ScriptEngine/ScriptEngine.cpp | 8 +- .../Source/GameLogic/System/GameLogic.cpp | 52 +++---- .../GameLogic/System/GameLogicDispatch.cpp | 65 ++++----- 12 files changed, 180 insertions(+), 189 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/Player.h b/GeneralsMD/Code/GameEngine/Include/Common/Player.h index ab3ab4993a..849c4d6f25 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/Player.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/Player.h @@ -634,7 +634,7 @@ class Player : public Snapshot // add to the player's current selection this hotkey team. void processAddTeamGameMessage(Int hotkeyNum, GameMessage *msg); - // returns an AIGroup object that is the currently selected group. + // fills an AIGroup object that is the currently selected group. void getCurrentSelectionAsAIGroup(AIGroup *group); // sets the currently selected group to be the given AIGroup diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index c8cb0c8b01..31bb23e68c 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -37,6 +37,8 @@ #include "Common/GameType.h" #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" +#include "refcount.h" +#include "ref_ptr.h" class AIGroup; class AttackPriorityInfo; @@ -272,7 +274,7 @@ class AI : public SubsystemInterface, public Snapshot void loadPostProcess( void ); // AI Groups ----------------------------------------------------------------------------------------------- - AIGroup *createGroup( void ); ///< instantiate a new AI Group + RefCountPtr createGroup( void ); ///< instantiate a new AI Group void destroyGroup( AIGroup *group ); ///< destroy the given AI Group AIGroup *findGroup( UnsignedInt id ); ///< return the AI Group with the given ID @@ -880,7 +882,7 @@ class AICommandInterface * An "AIGroup" is a simple collection of AI objects, used by the AI * for such things as Group Pathfinding. */ -class AIGroup : public MemoryPoolObject, public Snapshot +class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass { private: void groupAttackObjectPrivate( Bool forced, Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -980,13 +982,15 @@ class AIGroup : public MemoryPoolObject, public Snapshot void add( Object *obj ); ///< add object to group - // returns true if remove destroyed the group for us. + // Returns true if the group was emptied. Bool remove( Object *obj); + + void removeAll( void ); // If the group contains any objects not owned by ownerPlayer, return TRUE. Bool containsAnyObjectsNotOwnedByPlayer( const Player *ownerPlayer ); - // Remove any objects that aren't owned by the player, and return true if the group was destroyed due to emptiness + // Removes any objects that aren't owned by the player, and returns true if the group was emptied. Bool removeAnyObjectsNotOwnedByPlayer( const Player *ownerPlayer ); UnsignedInt getID( void ); @@ -1001,6 +1005,11 @@ class AIGroup : public MemoryPoolObject, public Snapshot void releaseWeaponLockForGroup(WeaponLockType lockType);///< Clear each guys weapon choice void setWeaponSetFlag( WeaponSetType wst ); + virtual void Delete_This(void) + { + TheAI->destroyGroup(this); + } + protected: MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIGroup, "AIGroupPool" ); ///< @todo Set real numbers for mem alloc diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h index d4cc8e1c52..9720465367 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h @@ -31,6 +31,7 @@ #define _OBJECT_H_ #include "Lib/BaseType.h" +#include "ref_ptr.h" #include "Common/Geometry.h" #include "Common/Snapshot.h" @@ -702,7 +703,7 @@ class Object : public Thing, public Snapshot GeometryInfo m_geometryInfo; - AIGroup* m_group; ///< if non-NULL, we are part of this group of agents + RefCountPtr m_group; ///< if non-NULL, we are part of this group of agents // These will last for my lifetime. I will reuse them and reset them. The truly dynamic ones are in PartitionManager SightingInfo *m_partitionLastLook; ///< Where and for whom I last looked, so I can undo its effects when I stop diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp index 2900f19d9f..6c5c702f9d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -333,18 +333,11 @@ void AI::reset( void ) m_aiData = m_aiData->m_next; delete cur; } - while (m_groupList.size()) - { - AIGroup *groupToRemove = m_groupList.front(); - if (groupToRemove) - { - destroyGroup(groupToRemove); - } - else - { - m_groupList.pop_front(); // NULL group, just kill from list. Shouldn't really happen, but just in case. - } - } + + DEBUG_ASSERTCRASH(m_groupList.empty(), ("AI::m_groupList is expected empty already\n")); + + m_groupList.clear(); // Clear just in case... + m_nextGroupID = 0; m_nextFormationID = NO_FORMATION_ID; getNextFormationID(); // increment once past NO_FORMATION_ID. jba. @@ -444,14 +437,14 @@ void AI::parseAiDataDefinition( INI* ini ) /** * Create a new AI Group */ -AIGroup *AI::createGroup( void ) +RefCountPtr AI::createGroup( void ) { // create a new instance - AIGroup *group = newInstance(AIGroup); + RefCountPtr group = RefCountPtr::Create_NoAddRef(newInstance(AIGroup)); // add it to the list // DEBUG_LOG(("***AIGROUP %x is being added to m_groupList.\n", group )); - m_groupList.push_back( group ); + m_groupList.push_back( group.Peek() ); return group; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index a793feceb3..0d600d2732 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -92,20 +92,8 @@ AIGroup::~AIGroup() { // DEBUG_LOG(("***AIGROUP %x is being destructed.\n", this)); // disassociate each member from the group - std::list::iterator i; - for( i = m_memberList.begin(); i != m_memberList.end(); /* empty */ ) - { - Object *member = *i; - if (member) - { - member->leaveGroup(); - i = m_memberList.begin(); // jump back to the beginning, cause ai->leaveGroup will remove this element. - } - else - { - i = m_memberList.erase(i); - } - } + removeAll(); + if (m_groundPath) { deleteInstance(m_groundPath); m_groundPath = NULL; @@ -223,15 +211,33 @@ Bool AIGroup::remove( Object *obj ) // list has changed, properties need recomputation m_dirty = true; - // if the group is empty, no-one is using it any longer, so destroy it if (isEmpty()) { - TheAI->destroyGroup( this ); return TRUE; } return FALSE; } +/** + * Remove all objects from group + */ +void AIGroup::removeAll( void ) +{ + std::list memberList; + memberList.swap(m_memberList); + m_memberListSize = 0; + + std::list::iterator i = memberList.begin(); + for ( ; i != memberList.end(); ++i) + { + Object *member = *i; + if (member) + member->leaveGroup(); + } + + m_dirty = true; +} + /** * If the group contains any objects not owned by ownerPlayer, return TRUE. */ diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index 700012ac94..bbec3e88d9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -900,11 +900,11 @@ void AIPlayer::guardSupplyCenter( Team *team, Int minSupplies ) } if (warehouse) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - team->getTeamAsAIGroup(theGroup); + team->getTeamAsAIGroup(theGroup.Peek()); Coord3D location = *warehouse->getPosition(); // It's probably a defensive move - position towards the enemy. Region2D bounds; @@ -2796,9 +2796,9 @@ void AIPlayer::checkReadyTeams( void ) /* if (team->m_team->getPrototype()->getTemplateInfo()->m_hasHomeLocation && !team->m_reinforcement) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (theGroup) { - team->m_team->getTeamAsAIGroup(theGroup); + team->m_team->getTeamAsAIGroup(theGroup.Peek()); Coord3D destination = team->m_team->getPrototype()->getTemplateInfo()->m_homeLocation; theGroup->groupTightenToPosition( &destination, false, CMD_FROM_AI ); team->m_frameStarted = TheGameLogic->getFrame(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 933d24025e..2277ae41af 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -4171,8 +4171,8 @@ StateReturnType AIFollowWaypointPathState::update() if (m_moveAsGroup) { if (obj->getControllingPlayer()->isSkirmishAIPlayer()) { Team *team = obj->getTeam(); - AIGroup *group = TheAI->createGroup(); - team->getTeamAsAIGroup(group); + RefCountPtr group = TheAI->createGroup(); + team->getTeamAsAIGroup(group.Peek()); Coord3D pos; group->getCenter(&pos); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 169ce1eda6..097faf3df6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -645,9 +645,8 @@ Object::~Object() ThePartitionManager->unRegisterObject( this ); // if we are in a group, remove us - if (m_group) - m_group->remove( this ); - + leaveGroup(); + // note, do NOT free these, there are just a shadow copy! m_ai = NULL; m_physics = NULL; @@ -4371,7 +4370,7 @@ void Object::xfer( Xfer *xfer ) } // Doesn't need to be saved. These are created as needed. jba. - //AIGroup* m_group; ///< if non-NULL, we are part of this group of agents + //m_group; // don't need to save m_partitionData. DEBUG_ASSERTCRASH(!(xfer->getXferMode() == XFER_LOAD && m_partitionData == NULL), ("should not be in partitionmgr yet")); @@ -6284,7 +6283,7 @@ RadarPriorityType Object::getRadarPriority( void ) const // ------------------------------------------------------------------------------------------------ AIGroup *Object::getGroup(void) { - return m_group; + return m_group.Peek(); } //------------------------------------------------------------------------------------------------- @@ -6294,7 +6293,7 @@ void Object::enterGroup( AIGroup *group ) // if we are in another group, remove ourselves from it first leaveGroup(); - m_group = group; + m_group = RefCountPtr::Create_AddRef(group); } //------------------------------------------------------------------------------------------------- @@ -6305,7 +6304,7 @@ void Object::leaveGroup( void ) if (m_group) { // to avoid recursion, set m_group to NULL before removing - AIGroup *group = m_group; + RefCountPtr group = m_group; m_group = NULL; group->remove( this ); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp index b91f81e880..c5fc0d4c92 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp @@ -419,12 +419,12 @@ void ScriptActions::doMoveToWaypoint(const AsciiString& team, const AsciiString& // The team is the team based on the name, and the calling team (if any) and the team that // triggered the condition. jba. :) if (theTeam) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Waypoint *way = TheTerrainLogic->getWaypointByName(waypoint); if (way) { Coord3D destination = *way->getLocation(); @@ -783,12 +783,12 @@ void ScriptActions::doCreateReinforcements(const AsciiString& team, const AsciiS theTeam->setActive(); if (needToMoveToDestination) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupMoveToPosition( &destination, false, CMD_FROM_SCRIPT ); } } @@ -1050,12 +1050,12 @@ void ScriptActions::doAttack(const AsciiString& attackerName, const AsciiString& if( attackingTeam == NULL || victimTeam == NULL ) return; - AIGroup *aiGroup = TheAI->createGroup(); + RefCountPtr aiGroup = TheAI->createGroup(); if (!aiGroup) { return; } - attackingTeam->getTeamAsAIGroup(aiGroup); + attackingTeam->getTeamAsAIGroup(aiGroup.Peek()); aiGroup->groupAttackTeam(victimTeam, NO_MAX_SHOTS_LIMIT, CMD_FROM_SCRIPT); } @@ -1308,12 +1308,12 @@ void ScriptActions::updateTeamSetAttitude(const AsciiString& teamName, Int attit return; } - AIGroup *pAIGroup = TheAI->createGroup(); + RefCountPtr pAIGroup = TheAI->createGroup(); if (!pAIGroup) { return; } - theSrcTeam->getTeamAsAIGroup(pAIGroup); + theSrcTeam->getTeamAsAIGroup(pAIGroup.Peek()); pAIGroup->setAttitude((AttitudeType) attitude); } @@ -1417,12 +1417,12 @@ void ScriptActions::doTeamAttackArea(const AsciiString& teamName, const AsciiStr return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(areaName); if (!pTrig) { @@ -1449,12 +1449,12 @@ void ScriptActions::doTeamAttackNamed(const AsciiString& teamName, const AsciiSt return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupAttackObject(theVictim, NO_MAX_SHOTS_LIMIT, CMD_FROM_SCRIPT); } @@ -1556,8 +1556,8 @@ void ScriptActions::doTeamEnterNamed(const AsciiString& teamName, const AsciiStr return; } - AIGroup* theGroup = TheAI->createGroup(); - theSrcTeam->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + theSrcTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEnter(theTransport, CMD_FROM_SCRIPT); } @@ -1592,8 +1592,8 @@ void ScriptActions::doTeamExitAll(const AsciiString& teamName) return; } - AIGroup* theGroup = TheAI->createGroup(); - theTeamOfTransports->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + theTeamOfTransports->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEvacuate( CMD_FROM_SCRIPT ); } @@ -1684,11 +1684,11 @@ void ScriptActions::doTeamFollowSkirmishApproachPath(const AsciiString& teamName return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1747,11 +1747,11 @@ void ScriptActions::doTeamMoveToSkirmishApproachPath(const AsciiString& teamName return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1795,11 +1795,11 @@ void ScriptActions::doTeamFollowWaypoints(const AsciiString& teamName, const Asc return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1842,11 +1842,11 @@ void ScriptActions::doTeamFollowWaypointsExact(const AsciiString& teamName, cons return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1934,11 +1934,11 @@ void ScriptActions::doTeamGuardPosition(const AsciiString& teamName, const Ascii return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Coord3D position = *way->getLocation(); theGroup->groupGuardPosition( &position, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); @@ -1955,11 +1955,11 @@ void ScriptActions::doTeamGuardObject(const AsciiString& teamName, const AsciiSt return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupGuardObject( theUnit, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); } @@ -1975,11 +1975,11 @@ void ScriptActions::doTeamGuardArea(const AsciiString& teamName, const AsciiStri return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupGuardArea( pTrig, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); } @@ -2013,11 +2013,11 @@ void ScriptActions::doTeamHunt(const AsciiString& teamName) return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupHunt( CMD_FROM_SCRIPT ); } @@ -3337,12 +3337,12 @@ void ScriptActions::doTeamGarrisonSpecificBuilding(const AsciiString& teamName, return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEnter(theBuilding, CMD_FROM_SCRIPT); } @@ -4412,13 +4412,13 @@ void ScriptActions::doTeamUseCommandButtonAbility( const AsciiString& team, cons } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButton( commandButton, CMD_FROM_SCRIPT ); } @@ -4447,13 +4447,13 @@ void ScriptActions::doTeamUseCommandButtonAbilityOnNamed( const AsciiString& tea } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButtonAtObject( commandButton, theObj, CMD_FROM_SCRIPT ); } @@ -4482,13 +4482,13 @@ void ScriptActions::doTeamUseCommandButtonAbilityAtWaypoint( const AsciiString& } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButtonAtPosition( commandButton, pWaypoint->getLocation(), CMD_FROM_SCRIPT ); } @@ -4566,12 +4566,12 @@ void ScriptActions::doTeamStop(const AsciiString& teamName, Bool shouldDisband) return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupIdle(CMD_FROM_SCRIPT); if (shouldDisband) { @@ -4779,12 +4779,12 @@ void ScriptActions::doTeamStartSequentialScript(const AsciiString& teamName, con } // Idle the team so the seq script will start executing. jba. - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - team->getTeamAsAIGroup(theGroup); + team->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupIdle(CMD_FROM_SCRIPT); @@ -4886,12 +4886,12 @@ void ScriptActions::doTeamIdleForFramecount(const AsciiString& teamName, Int fra return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Coord3D center; theGroup->getCenter(¢er); @@ -5365,8 +5365,8 @@ void ScriptActions::doSkirmishAttackNearestGroupWithValue( const AsciiString& te return; } - AIGroup* theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); Player *player = team->getControllingPlayer(); @@ -5394,8 +5394,8 @@ void ScriptActions::doSkirmishCommandButtonOnMostValuable( const AsciiString& te return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); Player *player = team->getControllingPlayer(); if (!player) @@ -5457,8 +5457,8 @@ void ScriptActions::doTeamUseCommandButtonOnNamed( const AsciiString& teamName, return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5496,8 +5496,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestEnemy( const AsciiString& tea return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5542,8 +5542,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestGarrisonedBuilding( const Asc return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5590,8 +5590,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestKindof( const AsciiString& te return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5637,8 +5637,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestBuilding( const AsciiString& return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5684,8 +5684,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestBuildingClass( const AsciiStr return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5732,8 +5732,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestObjectType( const AsciiString return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5862,8 +5862,8 @@ void ScriptActions::doTeamCaptureNearestUnownedFactionUnit( const AsciiString& t return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); PartitionFilterPlayerAffiliation f1(team->getControllingPlayer(), ALLOW_ENEMIES | ALLOW_NEUTRAL, true); PartitionFilterUnmannedObject f2(true); @@ -5978,12 +5978,12 @@ void ScriptActions::doTeamEmoticon(const AsciiString& teamName, const AsciiStrin return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); Int frames = (Int)( duration * LOGICFRAMES_PER_SECOND ); theGroup->groupSetEmoticon( emoticonName, frames ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index 1f90248a31..e057e3e1c9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -7933,9 +7933,9 @@ void ScriptEngine::evaluateAndProgressAllSequentialScripts( void ) } AIUpdateInterface *ai = obj ? obj->getAIUpdateInterface() : NULL; - AIGroup *aigroup = (team ? TheAI->createGroup() : NULL); + RefCountPtr aigroup = team ? TheAI->createGroup() : NULL; if (aigroup) { - team->getTeamAsAIGroup(aigroup); + team->getTeamAsAIGroup(aigroup.Peek()); } if( ai || aigroup ) { @@ -8019,8 +8019,8 @@ void ScriptEngine::evaluateAndProgressAllSequentialScripts( void ) itAdvanced = true; } else if (team) { // attempt to rebuild the aigroup, as it probably expired during the action execution - aigroup = (team ? TheAI->createGroup() : NULL); - team->getTeamAsAIGroup(aigroup); + aigroup = team ? TheAI->createGroup() : NULL; + team->getTeamAsAIGroup(aigroup.Peek()); } if (aigroup && aigroup->isIdle()) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index dfc1909655..10480b2e40 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -2682,22 +2682,21 @@ void GameLogic::selectObject(Object *obj, Bool createNewSelection, PlayerMaskTyp return; } - AIGroup *group = NULL; CRCGEN_LOG(( "Creating AIGroup in GameLogic::selectObject()\n" )); - group = TheAI->createGroup(); + RefCountPtr group = TheAI->createGroup(); group->add(obj); // add all selected agents to the AI group if (createNewSelection) { - player->setCurrentlySelectedAIGroup(group); + player->setCurrentlySelectedAIGroup(group.Peek()); } else { - player->addAIGroupToCurrentSelection(group); + player->addAIGroupToCurrentSelection(group.Peek()); } - TheAI->destroyGroup(group); + group->removeAll(); if( affectClient ) { @@ -2724,35 +2723,26 @@ void GameLogic::deselectObject(Object *obj, PlayerMaskType playerMask, Bool affe return; } - AIGroup *group = NULL; CRCGEN_LOG(( "Removing a unit from a selected group in GameLogic::deselectObject()\n" )); - group = TheAI->createGroup(); - player->getCurrentSelectionAsAIGroup(group); - - Bool deleted = FALSE; - Bool actuallyRemoved = FALSE; - - if (group) { - deleted = group->remove(obj); - actuallyRemoved = TRUE; + RefCountPtr group = TheAI->createGroup(); + player->getCurrentSelectionAsAIGroup(group.Peek()); + + Bool emptied = group->remove(obj); + + // Set this to be the currently selected group. + if (!emptied) { + player->setCurrentlySelectedAIGroup(group.Peek()); + // Cleanup the group. + group->removeAll(); + } else { + // NULL will clear the group. + player->setCurrentlySelectedAIGroup(NULL); } - - if (actuallyRemoved) { - // Set this to be the currently selected group. - if (!deleted) { - player->setCurrentlySelectedAIGroup(group); - // Then, cleanup the group. - TheAI->destroyGroup(group); - } else { - // NULL will clear the group. - player->setCurrentlySelectedAIGroup(NULL); - } - if (affectClient) { - Drawable *draw = obj->getDrawable(); - if (draw) { - TheInGameUI->deselectDrawable(draw); - } + if (affectClient) { + Drawable *draw = obj->getDrawable(); + if (draw) { + TheInGameUI->deselectDrawable(draw); } } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index 7003423f03..668d3914b6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -347,7 +347,7 @@ void GameLogic::prepareNewGame( Int gameMode, GameDifficulty diff, Int rankPoint //------------------------------------------------------------------------------------------------- /** This message handles dispatches object command messages to the * appropriate objects. - * @todo Rename this to "CommandProcessor", or similiar. */ + * @todo Rename this to "CommandProcessor", or similar. */ //------------------------------------------------------------------------------------------------- void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { @@ -359,7 +359,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) DEBUG_ASSERTCRASH( thisPlayer, ("logicMessageDispatcher: Processing message from unknown player (player index '%d')\n", msg->getPlayerIndex()) ); - AIGroup *currentlySelectedGroup = NULL; + RefCountPtr currentlySelectedGroup; if (isInGame()) { @@ -369,16 +369,13 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { currentlySelectedGroup = TheAI->createGroup(); // can't do this outside a game - it'll cause sync errors galore. CRCGEN_LOG(( "Creating AIGroup %d in GameLogic::logicMessageDispatcher()\n", (currentlySelectedGroup)?currentlySelectedGroup->getID():0 )); - thisPlayer->getCurrentSelectionAsAIGroup(currentlySelectedGroup); + thisPlayer->getCurrentSelectionAsAIGroup(currentlySelectedGroup.Peek()); - // We can't issue commands to groups that contain units that don't belong the issuing player, so pretend like + // We can't issue commands to groups that contain units that don't belong to the issuing player, so pretend like // there's nothing selected. Also, if currentlySelectedGroup is empty, go ahead and delete it, so that we can skip // any processing on it. if (currentlySelectedGroup->isEmpty()) - { - TheAI->destroyGroup(currentlySelectedGroup); currentlySelectedGroup = NULL; - } // If there are any units that the player doesn't own, then remove them from the "currentlySelectedGroup" if (currentlySelectedGroup) @@ -458,8 +455,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) #endif if (currentlySelectedGroup) - TheAI->destroyGroup(currentlySelectedGroup); - currentlySelectedGroup = NULL; + { + currentlySelectedGroup->removeAll(); + currentlySelectedGroup = NULL; + } TheGameLogic->clearGameData(); break; @@ -674,10 +673,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPower( specialPowerID, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -715,10 +714,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPowerAtLocation( specialPowerID, &targetCoord, angle, objectInWay, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -754,10 +753,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPowerAtObject( specialPowerID, target, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -1002,7 +1001,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) case GameMessage::MSG_EXIT: { Object *objectWantingToExit = TheGameLogic->findObjectByID( msg->getArgument( 0 )->objectID ); - Object *objectContainingExiter = getSingleObjectFromSelection(currentlySelectedGroup); + Object *objectContainingExiter = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); // sanity if( objectWantingToExit == NULL ) @@ -1189,10 +1188,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupOverrideSpecialPowerDestination( spType, loc, CMD_FROM_PLAYER ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -1301,7 +1300,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //--------------------------------------------------------------------------------------------- case GameMessage::MSG_CANCEL_UPGRADE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); const UpgradeTemplate *upgradeT = TheUpgradeCenter->findUpgradeByKey( (NameKeyType)(msg->getArgument( 0 )->integer) ); // sanity @@ -1327,7 +1326,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //--------------------------------------------------------------------------------------------- case GameMessage::MSG_QUEUE_UNIT_CREATE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); const ThingTemplate *whatToCreate; ProductionID productionID; @@ -1360,7 +1359,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //------------------------------------------------------------------------------------------------- case GameMessage::MSG_CANCEL_UNIT_CREATE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); ProductionID productionID = (ProductionID)msg->getArgument( 0 )->integer; // sanity @@ -1392,7 +1391,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Real angle; // get player, what to place, and location - Object *constructorObject = getSingleObjectFromSelection(currentlySelectedGroup); + Object *constructorObject = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); place = TheThingFactory->findByTemplateID( msg->getArgument( 0 )->integer ); loc = msg->getArgument( 1 )->location; angle = msg->getArgument( 2 )->real; @@ -1439,7 +1438,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { // get the building to cancel construction on - Object *building = getSingleObjectFromSelection(currentlySelectedGroup); + Object *building = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); if( building == NULL ) break; @@ -1563,7 +1562,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Player *player = ThePlayerList->getNthPlayer(msg->getPlayerIndex()); if (player == NULL) { - DEBUG_CRASH(("GameLogicDispatch - MSG_CREATE_SELECTED_GROUP had an invalid player nubmer")); + DEBUG_CRASH(("GameLogicDispatch - MSG_REMOVE_FROM_SELECTED_GROUP had an invalid player nubmer")); break; } @@ -1573,7 +1572,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) if (!objToRemove) { continue; } - + TheGameLogic->deselectObject(objToRemove, player->getPlayerMask()); } @@ -1700,10 +1699,8 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) // -------------------------------------------------------------------------------------------- case GameMessage::MSG_REMOVE_BEACON: { - - AIGroup *allSelectedObjects = NULL; - allSelectedObjects = TheAI->createGroup(); - thisPlayer->getCurrentSelectionAsAIGroup(allSelectedObjects); // need to act on all objects, so we can hide teammates' beacons. + RefCountPtr allSelectedObjects = TheAI->createGroup(); + thisPlayer->getCurrentSelectionAsAIGroup(allSelectedObjects.Peek()); // need to act on all objects, so we can hide teammates' beacons. if( allSelectedObjects ) { const VecObjectID& selectedObjects = allSelectedObjects->getAllIDs(); @@ -1744,11 +1741,6 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) } } } - if (allSelectedObjects->isEmpty()) - { - TheAI->destroyGroup(allSelectedObjects); - allSelectedObjects = NULL; - } } break; } // end beacon removal @@ -2011,9 +2003,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) } /**/ - if( currentlySelectedGroup != NULL ) + if( currentlySelectedGroup ) { - TheAI->destroyGroup(currentlySelectedGroup); + currentlySelectedGroup->removeAll(); + currentlySelectedGroup = NULL; } } // end logicMessageDispatches From a1a1e8c20845fb147c732959d952bb3c464318b4 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sat, 7 Jun 2025 11:02:34 +0200 Subject: [PATCH 3/7] Refactor for loop --- GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index 0d600d2732..8bd9b2d6c3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -227,8 +227,8 @@ void AIGroup::removeAll( void ) memberList.swap(m_memberList); m_memberListSize = 0; - std::list::iterator i = memberList.begin(); - for ( ; i != memberList.end(); ++i) + std::list::iterator i; + for ( i = memberList.begin(); i != memberList.end(); ++i ) { Object *member = *i; if (member) From 069978a454b196bb54da23eeea08759637e486f6 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:09:52 +0200 Subject: [PATCH 4/7] Replace RefCountClass with RefCountValue to avoid changing size of class AIGroup --- .../Code/GameEngine/Include/GameLogic/AI.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 31bb23e68c..5d13de2317 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -882,7 +882,7 @@ class AICommandInterface * An "AIGroup" is a simple collection of AI objects, used by the AI * for such things as Group Pathfinding. */ -class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass +class AIGroup : public MemoryPoolObject, public Snapshot { private: void groupAttackObjectPrivate( Bool forced, Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -894,6 +894,10 @@ class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass void xfer( Xfer *xfer ); void loadPostProcess( void ); + void Add_Ref() const { m_refCount.Add_Ref(); } + void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } + void Num_Refs() const { m_refCount.Num_Refs(); } + void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) void groupMoveToAndEvacuateAndExit( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position & unload transport. @@ -1005,11 +1009,6 @@ class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass void releaseWeaponLockForGroup(WeaponLockType lockType);///< Clear each guys weapon choice void setWeaponSetFlag( WeaponSetType wst ); - virtual void Delete_This(void) - { - TheAI->destroyGroup(this); - } - protected: MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AIGroup, "AIGroupPool" ); ///< @todo Set real numbers for mem alloc @@ -1025,6 +1024,11 @@ class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass friend class AI; AIGroup( void ); + static void destroy(AIGroup* self) + { + TheAI->destroyGroup(self); + } + void recompute( void ); ///< recompute various group info, such as speed, leader, etc ListObjectPtr m_memberList; ///< the list of member Objects @@ -1033,6 +1037,8 @@ class AIGroup : public MemoryPoolObject, public Snapshot, public RefCountClass Real m_speed; ///< maximum speed of group (slowest member) Bool m_dirty; ///< "dirty bit" - if true then group speed, leader, needs recompute + RefCountValue m_refCount; ///< the reference counter + UnsignedInt m_id; ///< the unique ID of this group Path *m_groundPath; ///< Group ground path. From 55c46d91d365c319fcfb3433511c6f263989ebf2 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:25:48 +0200 Subject: [PATCH 5/7] Replicate in Generals --- .../Code/GameEngine/Include/Common/Player.h | 2 +- .../Code/GameEngine/Include/GameLogic/AI.h | 21 ++- .../GameEngine/Include/GameLogic/Object.h | 3 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 23 ++- .../Source/GameLogic/AI/AIGroup.cpp | 38 ++--- .../Source/GameLogic/AI/AIPlayer.cpp | 8 +- .../Source/GameLogic/AI/AIStates.cpp | 4 +- .../Source/GameLogic/Object/Object.cpp | 13 +- .../GameLogic/ScriptEngine/ScriptActions.cpp | 136 +++++++++--------- .../GameLogic/ScriptEngine/ScriptEngine.cpp | 8 +- .../Source/GameLogic/System/GameLogic.cpp | 52 +++---- .../GameLogic/System/GameLogicDispatch.cpp | 65 ++++----- 12 files changed, 185 insertions(+), 188 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/Player.h b/Generals/Code/GameEngine/Include/Common/Player.h index be96a90299..2011a247ea 100644 --- a/Generals/Code/GameEngine/Include/Common/Player.h +++ b/Generals/Code/GameEngine/Include/Common/Player.h @@ -608,7 +608,7 @@ class Player : public Snapshot // add to the player's current selection this hotkey team. void processAddTeamGameMessage(Int hotkeyNum, GameMessage *msg); - // returns an AIGroup object that is the currently selected group. + // fills an AIGroup object that is the currently selected group. void getCurrentSelectionAsAIGroup(AIGroup *group); // sets the currently selected group to be the given AIGroup diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index 5814cad7a6..c826ed74a2 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -37,6 +37,8 @@ #include "Common/GameType.h" #include "GameLogic/Damage.h" #include "Common/STLTypedefs.h" +#include "refcount.h" +#include "ref_ptr.h" class AIGroup; class AttackPriorityInfo; @@ -265,7 +267,7 @@ class AI : public SubsystemInterface, public Snapshot void loadPostProcess( void ); // AI Groups ----------------------------------------------------------------------------------------------- - AIGroup *createGroup( void ); ///< instantiate a new AI Group + RefCountPtr createGroup( void ); ///< instantiate a new AI Group void destroyGroup( AIGroup *group ); ///< destroy the given AI Group AIGroup *findGroup( UnsignedInt id ); ///< return the AI Group with the given ID @@ -851,6 +853,10 @@ class AIGroup : public MemoryPoolObject, public Snapshot void xfer( Xfer *xfer ); void loadPostProcess( void ); + void Add_Ref() const { m_refCount.Add_Ref(); } + void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } + void Num_Refs() const { m_refCount.Num_Refs(); } + void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) void groupMoveToAndEvacuateAndExit( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position & unload transport. @@ -938,13 +944,15 @@ class AIGroup : public MemoryPoolObject, public Snapshot void add( Object *obj ); ///< add object to group - // returns true if remove destroyed the group for us. + // Returns true if the group was emptied. Bool remove( Object *obj); + + void removeAll( void ); // If the group contains any objects not owned by ownerPlayer, return TRUE. Bool containsAnyObjectsNotOwnedByPlayer( const Player *ownerPlayer ); - // Remove any objects that aren't owned by the player, and return true if the group was destroyed due to emptiness + // Removes any objects that aren't owned by the player, and returns true if the group was emptied. Bool removeAnyObjectsNotOwnedByPlayer( const Player *ownerPlayer ); UnsignedInt getID( void ); @@ -974,6 +982,11 @@ class AIGroup : public MemoryPoolObject, public Snapshot friend class AI; AIGroup( void ); + static void destroy(AIGroup* self) + { + TheAI->destroyGroup(self); + } + void recompute( void ); ///< recompute various group info, such as speed, leader, etc ListObjectPtr m_memberList; ///< the list of member Objects @@ -982,6 +995,8 @@ class AIGroup : public MemoryPoolObject, public Snapshot Real m_speed; ///< maximum speed of group (slowest member) Bool m_dirty; ///< "dirty bit" - if true then group speed, leader, needs recompute + RefCountValue m_refCount; ///< the reference counter + UnsignedInt m_id; ///< the unique ID of this group Path *m_groundPath; ///< Group ground path. diff --git a/Generals/Code/GameEngine/Include/GameLogic/Object.h b/Generals/Code/GameEngine/Include/GameLogic/Object.h index aa26a6c2a0..9052017152 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Object.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Object.h @@ -31,6 +31,7 @@ #define _OBJECT_H_ #include "Lib/BaseType.h" +#include "ref_ptr.h" #include "Common/Geometry.h" #include "Common/Snapshot.h" @@ -663,7 +664,7 @@ class Object : public Thing, public Snapshot GeometryInfo m_geometryInfo; - AIGroup* m_group; ///< if non-NULL, we are part of this group of agents + RefCountPtr m_group; ///< if non-NULL, we are part of this group of agents // These will last for my lifetime. I will reuse them and reset them. The truly dynamic ones are in PartitionManager SightingInfo *m_partitionLastLook; ///< Where and for whom I last looked, so I can undo its effects when I stop diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp index 987fe75ea1..99d7d19d9d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -330,18 +330,11 @@ void AI::reset( void ) m_aiData = m_aiData->m_next; delete cur; } - while (m_groupList.size()) - { - AIGroup *groupToRemove = m_groupList.front(); - if (groupToRemove) - { - destroyGroup(groupToRemove); - } - else - { - m_groupList.pop_front(); // NULL group, just kill from list. Shouldn't really happen, but just in case. - } - } + + DEBUG_ASSERTCRASH(m_groupList.empty(), ("AI::m_groupList is expected empty already\n")); + + m_groupList.clear(); // Clear just in case... + m_nextGroupID = 0; m_nextFormationID = NO_FORMATION_ID; getNextFormationID(); // increment once past NO_FORMATION_ID. jba. @@ -441,14 +434,14 @@ void AI::parseAiDataDefinition( INI* ini ) /** * Create a new AI Group */ -AIGroup *AI::createGroup( void ) +RefCountPtr AI::createGroup( void ) { // create a new instance - AIGroup *group = newInstance(AIGroup); + RefCountPtr group = RefCountPtr::Create_NoAddRef(newInstance(AIGroup)); // add it to the list // DEBUG_LOG(("***AIGROUP %x is being added to m_groupList.\n", group )); - m_groupList.push_back( group ); + m_groupList.push_back( group.Peek() ); return group; } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index ad12247a65..581cd02ced 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -92,20 +92,8 @@ AIGroup::~AIGroup() { // DEBUG_LOG(("***AIGROUP %x is being destructed.\n", this)); // disassociate each member from the group - std::list::iterator i; - for( i = m_memberList.begin(); i != m_memberList.end(); /* empty */ ) - { - Object *member = *i; - if (member) - { - member->leaveGroup(); - i = m_memberList.begin(); // jump back to the beginning, cause ai->leaveGroup will remove this element. - } - else - { - i = m_memberList.erase(i); - } - } + removeAll(); + if (m_groundPath) { deleteInstance(m_groundPath); m_groundPath = NULL; @@ -223,15 +211,33 @@ Bool AIGroup::remove( Object *obj ) // list has changed, properties need recomputation m_dirty = true; - // if the group is empty, no-one is using it any longer, so destroy it if (isEmpty()) { - TheAI->destroyGroup( this ); return TRUE; } return FALSE; } +/** + * Remove all objects from group + */ +void AIGroup::removeAll( void ) +{ + std::list memberList; + memberList.swap(m_memberList); + m_memberListSize = 0; + + std::list::iterator i; + for ( i = memberList.begin(); i != memberList.end(); ++i ) + { + Object *member = *i; + if (member) + member->leaveGroup(); + } + + m_dirty = true; +} + /** * If the group contains any objects not owned by ownerPlayer, return TRUE. */ diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index d3563f3cfc..d62cd1605a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -893,11 +893,11 @@ void AIPlayer::guardSupplyCenter( Team *team, Int minSupplies ) } if (warehouse) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - team->getTeamAsAIGroup(theGroup); + team->getTeamAsAIGroup(theGroup.Peek()); Coord3D location = *warehouse->getPosition(); // It's probably a defensive move - position towards the enemy. Region2D bounds; @@ -2467,9 +2467,9 @@ void AIPlayer::checkReadyTeams( void ) /* if (team->m_team->getPrototype()->getTemplateInfo()->m_hasHomeLocation && !team->m_reinforcement) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (theGroup) { - team->m_team->getTeamAsAIGroup(theGroup); + team->m_team->getTeamAsAIGroup(theGroup.Peek()); Coord3D destination = team->m_team->getPrototype()->getTemplateInfo()->m_homeLocation; theGroup->groupTightenToPosition( &destination, false, CMD_FROM_AI ); team->m_frameStarted = TheGameLogic->getFrame(); diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 04cac72bb3..2fe244dd19 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -4050,8 +4050,8 @@ StateReturnType AIFollowWaypointPathState::update() if (m_moveAsGroup) { if (obj->getControllingPlayer()->isSkirmishAIPlayer()) { Team *team = obj->getTeam(); - AIGroup *group = TheAI->createGroup(); - team->getTeamAsAIGroup(group); + RefCountPtr group = TheAI->createGroup(); + team->getTeamAsAIGroup(group.Peek()); Coord3D pos; group->getCenter(&pos); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 0ac475a72c..8d71d0f403 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -563,9 +563,8 @@ Object::~Object() ThePartitionManager->unRegisterObject( this ); // if we are in a group, remove us - if (m_group) - m_group->remove( this ); - + leaveGroup(); + // note, do NOT free these, there are just a shadow copy! m_ai = NULL; m_physics = NULL; @@ -3841,7 +3840,7 @@ void Object::xfer( Xfer *xfer ) } // Doesn't need to be saved. These are created as needed. jba. - //AIGroup* m_group; ///< if non-NULL, we are part of this group of agents + //m_group; // don't need to save m_partitionData. DEBUG_ASSERTCRASH(!(xfer->getXferMode() == XFER_LOAD && m_partitionData == NULL), ("should not be in partitionmgr yet")); @@ -5446,7 +5445,7 @@ RadarPriorityType Object::getRadarPriority( void ) const // ------------------------------------------------------------------------------------------------ AIGroup *Object::getGroup(void) { - return m_group; + return m_group.Peek(); } //------------------------------------------------------------------------------------------------- @@ -5456,7 +5455,7 @@ void Object::enterGroup( AIGroup *group ) // if we are in another group, remove ourselves from it first leaveGroup(); - m_group = group; + m_group = RefCountPtr::Create_AddRef(group); } //------------------------------------------------------------------------------------------------- @@ -5467,7 +5466,7 @@ void Object::leaveGroup( void ) if (m_group) { // to avoid recursion, set m_group to NULL before removing - AIGroup *group = m_group; + RefCountPtr group = m_group; m_group = NULL; group->remove( this ); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp index e07e6bc95b..4667f53106 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp @@ -394,12 +394,12 @@ void ScriptActions::doMoveToWaypoint(const AsciiString& team, const AsciiString& // The team is the team based on the name, and the calling team (if any) and the team that // triggered the condition. jba. :) if (theTeam) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Waypoint *way = TheTerrainLogic->getWaypointByName(waypoint); if (way) { Coord3D destination = *way->getLocation(); @@ -756,12 +756,12 @@ void ScriptActions::doCreateReinforcements(const AsciiString& team, const AsciiS theTeam->setActive(); if (needToMoveToDestination) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupMoveToPosition( &destination, false, CMD_FROM_SCRIPT ); } } @@ -1015,12 +1015,12 @@ void ScriptActions::doAttack(const AsciiString& attackerName, const AsciiString& if( attackingTeam == NULL || victimTeam == NULL ) return; - AIGroup *aiGroup = TheAI->createGroup(); + RefCountPtr aiGroup = TheAI->createGroup(); if (!aiGroup) { return; } - attackingTeam->getTeamAsAIGroup(aiGroup); + attackingTeam->getTeamAsAIGroup(aiGroup.Peek()); aiGroup->groupAttackTeam(victimTeam, NO_MAX_SHOTS_LIMIT, CMD_FROM_SCRIPT); } @@ -1260,12 +1260,12 @@ void ScriptActions::updateTeamSetAttitude(const AsciiString& teamName, Int attit return; } - AIGroup *pAIGroup = TheAI->createGroup(); + RefCountPtr pAIGroup = TheAI->createGroup(); if (!pAIGroup) { return; } - theSrcTeam->getTeamAsAIGroup(pAIGroup); + theSrcTeam->getTeamAsAIGroup(pAIGroup.Peek()); pAIGroup->setAttitude((AttitudeType) attitude); } @@ -1369,12 +1369,12 @@ void ScriptActions::doTeamAttackArea(const AsciiString& teamName, const AsciiStr return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(areaName); if (!pTrig) { @@ -1401,12 +1401,12 @@ void ScriptActions::doTeamAttackNamed(const AsciiString& teamName, const AsciiSt return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupAttackObject(theVictim, NO_MAX_SHOTS_LIMIT, CMD_FROM_SCRIPT); } @@ -1508,8 +1508,8 @@ void ScriptActions::doTeamEnterNamed(const AsciiString& teamName, const AsciiStr return; } - AIGroup* theGroup = TheAI->createGroup(); - theSrcTeam->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + theSrcTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEnter(theTransport, CMD_FROM_SCRIPT); } @@ -1544,8 +1544,8 @@ void ScriptActions::doTeamExitAll(const AsciiString& teamName) return; } - AIGroup* theGroup = TheAI->createGroup(); - theTeamOfTransports->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + theTeamOfTransports->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEvacuate( CMD_FROM_SCRIPT ); } @@ -1614,11 +1614,11 @@ void ScriptActions::doTeamFollowSkirmishApproachPath(const AsciiString& teamName return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1677,11 +1677,11 @@ void ScriptActions::doTeamMoveToSkirmishApproachPath(const AsciiString& teamName return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1725,11 +1725,11 @@ void ScriptActions::doTeamFollowWaypoints(const AsciiString& teamName, const Asc return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1772,11 +1772,11 @@ void ScriptActions::doTeamFollowWaypointsExact(const AsciiString& teamName, cons return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Int count = 0; Coord3D pos; pos.x=pos.y=pos.z=0; @@ -1864,11 +1864,11 @@ void ScriptActions::doTeamGuardPosition(const AsciiString& teamName, const Ascii return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Coord3D position = *way->getLocation(); theGroup->groupGuardPosition( &position, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); @@ -1885,11 +1885,11 @@ void ScriptActions::doTeamGuardObject(const AsciiString& teamName, const AsciiSt return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupGuardObject( theUnit, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); } @@ -1905,11 +1905,11 @@ void ScriptActions::doTeamGuardArea(const AsciiString& teamName, const AsciiStri return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupGuardArea( pTrig, GUARDMODE_NORMAL, CMD_FROM_SCRIPT ); } @@ -1943,11 +1943,11 @@ void ScriptActions::doTeamHunt(const AsciiString& teamName) return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupHunt( CMD_FROM_SCRIPT ); } @@ -3241,12 +3241,12 @@ void ScriptActions::doTeamGarrisonSpecificBuilding(const AsciiString& teamName, return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupEnter(theBuilding, CMD_FROM_SCRIPT); } @@ -4081,13 +4081,13 @@ void ScriptActions::doTeamUseCommandButtonAbility( const AsciiString& team, cons } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButton( commandButton, CMD_FROM_SCRIPT ); } @@ -4116,13 +4116,13 @@ void ScriptActions::doTeamUseCommandButtonAbilityOnNamed( const AsciiString& tea } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButtonAtObject( commandButton, theObj, CMD_FROM_SCRIPT ); } @@ -4151,13 +4151,13 @@ void ScriptActions::doTeamUseCommandButtonAbilityAtWaypoint( const AsciiString& } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); theGroup->groupDoCommandButtonAtPosition( commandButton, pWaypoint->getLocation(), CMD_FROM_SCRIPT ); } @@ -4235,12 +4235,12 @@ void ScriptActions::doTeamStop(const AsciiString& teamName, Bool shouldDisband) return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupIdle(CMD_FROM_SCRIPT); if (shouldDisband) { @@ -4448,12 +4448,12 @@ void ScriptActions::doTeamStartSequentialScript(const AsciiString& teamName, con } // Idle the team so the seq script will start executing. jba. - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - team->getTeamAsAIGroup(theGroup); + team->getTeamAsAIGroup(theGroup.Peek()); theGroup->groupIdle(CMD_FROM_SCRIPT); @@ -4555,12 +4555,12 @@ void ScriptActions::doTeamIdleForFramecount(const AsciiString& teamName, Int fra return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if (!theGroup) { return; } - theTeam->getTeamAsAIGroup(theGroup); + theTeam->getTeamAsAIGroup(theGroup.Peek()); Coord3D center; theGroup->getCenter(¢er); @@ -4941,8 +4941,8 @@ void ScriptActions::doSkirmishAttackNearestGroupWithValue( const AsciiString& te return; } - AIGroup* theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); Player *player = team->getControllingPlayer(); @@ -4970,8 +4970,8 @@ void ScriptActions::doSkirmishCommandButtonOnMostValuable( const AsciiString& te return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); Player *player = team->getControllingPlayer(); if (!player) @@ -5033,8 +5033,8 @@ void ScriptActions::doTeamUseCommandButtonOnNamed( const AsciiString& teamName, return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5072,8 +5072,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestEnemy( const AsciiString& tea return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5118,8 +5118,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestGarrisonedBuilding( const Asc return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if(!commandButton) { @@ -5166,8 +5166,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestKindof( const AsciiString& te return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5213,8 +5213,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestBuilding( const AsciiString& return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5260,8 +5260,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestBuildingClass( const AsciiStr return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5308,8 +5308,8 @@ void ScriptActions::doTeamUseCommandButtonOnNearestObjectType( const AsciiString return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); const CommandButton *commandButton = TheControlBar->findCommandButton(commandAbility); if (!commandButton) { @@ -5399,8 +5399,8 @@ void ScriptActions::doTeamCaptureNearestUnownedFactionUnit( const AsciiString& t return; } - AIGroup *theGroup = TheAI->createGroup(); - team->getTeamAsAIGroup(theGroup); + RefCountPtr theGroup = TheAI->createGroup(); + team->getTeamAsAIGroup(theGroup.Peek()); PartitionFilterPlayerAffiliation f1(team->getControllingPlayer(), ALLOW_ENEMIES | ALLOW_NEUTRAL, true); PartitionFilterUnmannedObject f2(true); @@ -5515,12 +5515,12 @@ void ScriptActions::doTeamEmoticon(const AsciiString& teamName, const AsciiStrin return; } - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); if( !theGroup ) { return; } - theTeam->getTeamAsAIGroup( theGroup ); + theTeam->getTeamAsAIGroup( theGroup.Peek() ); Int frames = (Int)( duration * LOGICFRAMES_PER_SECOND ); theGroup->groupSetEmoticon( emoticonName, frames ); diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index 8d63c563fe..e094583ad0 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -7210,9 +7210,9 @@ void ScriptEngine::evaluateAndProgressAllSequentialScripts( void ) } AIUpdateInterface *ai = obj ? obj->getAIUpdateInterface() : NULL; - AIGroup *aigroup = (team ? TheAI->createGroup() : NULL); + RefCountPtr aigroup = team ? TheAI->createGroup() : NULL; if (aigroup) { - team->getTeamAsAIGroup(aigroup); + team->getTeamAsAIGroup(aigroup.Peek()); } if( ai || aigroup ) { @@ -7296,8 +7296,8 @@ void ScriptEngine::evaluateAndProgressAllSequentialScripts( void ) itAdvanced = true; } else if (team) { // attempt to rebuild the aigroup, as it probably expired during the action execution - aigroup = (team ? TheAI->createGroup() : NULL); - team->getTeamAsAIGroup(aigroup); + aigroup = team ? TheAI->createGroup() : NULL; + team->getTeamAsAIGroup(aigroup.Peek()); } if (aigroup && aigroup->isIdle()) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index dcc23721d5..6c02bfb511 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -2353,19 +2353,18 @@ void GameLogic::selectObject(Object *obj, Bool createNewSelection, PlayerMaskTyp return; } - AIGroup *group = NULL; CRCGEN_LOG(( "Creating AIGroup in GameLogic::selectObject()\n" )); - group = TheAI->createGroup(); + RefCountPtr group = TheAI->createGroup(); group->add(obj); // add all selected agents to the AI group if (createNewSelection) { - player->setCurrentlySelectedAIGroup(group); + player->setCurrentlySelectedAIGroup(group.Peek()); } else { - player->addAIGroupToCurrentSelection(group); + player->addAIGroupToCurrentSelection(group.Peek()); } - TheAI->destroyGroup(group); + group->removeAll(); if (affectClient) { Drawable *draw = obj->getDrawable(); @@ -2390,35 +2389,26 @@ void GameLogic::deselectObject(Object *obj, PlayerMaskType playerMask, Bool affe return; } - AIGroup *group = NULL; CRCGEN_LOG(( "Removing a unit from a selected group in GameLogic::deselectObject()\n" )); - group = TheAI->createGroup(); - player->getCurrentSelectionAsAIGroup(group); - - Bool deleted = FALSE; - Bool actuallyRemoved = FALSE; - - if (group) { - deleted = group->remove(obj); - actuallyRemoved = TRUE; + RefCountPtr group = TheAI->createGroup(); + player->getCurrentSelectionAsAIGroup(group.Peek()); + + Bool emptied = group->remove(obj); + + // Set this to be the currently selected group. + if (!emptied) { + player->setCurrentlySelectedAIGroup(group.Peek()); + // Cleanup the group. + group->removeAll(); + } else { + // NULL will clear the group. + player->setCurrentlySelectedAIGroup(NULL); } - - if (actuallyRemoved) { - // Set this to be the currently selected group. - if (!deleted) { - player->setCurrentlySelectedAIGroup(group); - // Then, cleanup the group. - TheAI->destroyGroup(group); - } else { - // NULL will clear the group. - player->setCurrentlySelectedAIGroup(NULL); - } - if (affectClient) { - Drawable *draw = obj->getDrawable(); - if (draw) { - TheInGameUI->deselectDrawable(draw); - } + if (affectClient) { + Drawable *draw = obj->getDrawable(); + if (draw) { + TheInGameUI->deselectDrawable(draw); } } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp index cf835cb373..4374d4489e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp @@ -338,7 +338,7 @@ void GameLogic::prepareNewGame( Int gameMode, GameDifficulty diff, Int rankPoint //------------------------------------------------------------------------------------------------- /** This message handles dispatches object command messages to the * appropriate objects. - * @todo Rename this to "CommandProcessor", or similiar. */ + * @todo Rename this to "CommandProcessor", or similar. */ //------------------------------------------------------------------------------------------------- void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { @@ -350,7 +350,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) DEBUG_ASSERTCRASH( thisPlayer, ("logicMessageDispatcher: Processing message from unknown player (player index '%d')\n", msg->getPlayerIndex()) ); - AIGroup *currentlySelectedGroup = NULL; + RefCountPtr currentlySelectedGroup; if (isInGame()) { @@ -360,16 +360,13 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { currentlySelectedGroup = TheAI->createGroup(); // can't do this outside a game - it'll cause sync errors galore. CRCGEN_LOG(( "Creating AIGroup %d in GameLogic::logicMessageDispatcher()\n", (currentlySelectedGroup)?currentlySelectedGroup->getID():0 )); - thisPlayer->getCurrentSelectionAsAIGroup(currentlySelectedGroup); + thisPlayer->getCurrentSelectionAsAIGroup(currentlySelectedGroup.Peek()); - // We can't issue commands to groups that contain units that don't belong the issuing player, so pretend like + // We can't issue commands to groups that contain units that don't belong to the issuing player, so pretend like // there's nothing selected. Also, if currentlySelectedGroup is empty, go ahead and delete it, so that we can skip // any processing on it. if (currentlySelectedGroup->isEmpty()) - { - TheAI->destroyGroup(currentlySelectedGroup); currentlySelectedGroup = NULL; - } // If there are any units that the player doesn't own, then remove them from the "currentlySelectedGroup" if (currentlySelectedGroup) @@ -449,8 +446,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) #endif if (currentlySelectedGroup) - TheAI->destroyGroup(currentlySelectedGroup); - currentlySelectedGroup = NULL; + { + currentlySelectedGroup->removeAll(); + currentlySelectedGroup = NULL; + } TheGameLogic->clearGameData(); break; @@ -651,10 +650,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPower( specialPowerID, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -689,10 +688,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPowerAtLocation( specialPowerID, &targetCoord, INVALID_ANGLE, objectInWay, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -728,10 +727,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupDoSpecialPowerAtObject( specialPowerID, target, options ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -974,7 +973,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) case GameMessage::MSG_EXIT: { Object *objectWantingToExit = TheGameLogic->findObjectByID( msg->getArgument( 0 )->objectID ); - Object *objectContainingExiter = getSingleObjectFromSelection(currentlySelectedGroup); + Object *objectContainingExiter = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); // sanity if( objectWantingToExit == NULL ) @@ -1161,10 +1160,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Object* source = TheGameLogic->findObjectByID(sourceID); if (source != NULL) { - AIGroup* theGroup = TheAI->createGroup(); + RefCountPtr theGroup = TheAI->createGroup(); theGroup->add(source); theGroup->groupOverrideSpecialPowerDestination( spType, loc, CMD_FROM_PLAYER ); - TheAI->destroyGroup(theGroup); + theGroup->removeAll(); } else { @@ -1273,7 +1272,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //--------------------------------------------------------------------------------------------- case GameMessage::MSG_CANCEL_UPGRADE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); const UpgradeTemplate *upgradeT = TheUpgradeCenter->findUpgradeByKey( (NameKeyType)(msg->getArgument( 0 )->integer) ); // sanity @@ -1299,7 +1298,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //--------------------------------------------------------------------------------------------- case GameMessage::MSG_QUEUE_UNIT_CREATE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); const ThingTemplate *whatToCreate; ProductionID productionID; @@ -1332,7 +1331,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) //------------------------------------------------------------------------------------------------- case GameMessage::MSG_CANCEL_UNIT_CREATE: { - Object *producer = getSingleObjectFromSelection(currentlySelectedGroup); + Object *producer = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); ProductionID productionID = (ProductionID)msg->getArgument( 0 )->integer; // sanity @@ -1364,7 +1363,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Real angle; // get player, what to place, and location - Object *constructorObject = getSingleObjectFromSelection(currentlySelectedGroup); + Object *constructorObject = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); place = TheThingFactory->findByTemplateID( msg->getArgument( 0 )->integer ); loc = msg->getArgument( 1 )->location; angle = msg->getArgument( 2 )->real; @@ -1411,7 +1410,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) { // get the building to cancel construction on - Object *building = getSingleObjectFromSelection(currentlySelectedGroup); + Object *building = getSingleObjectFromSelection(currentlySelectedGroup.Peek()); if( building == NULL ) break; @@ -1535,7 +1534,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) Player *player = ThePlayerList->getNthPlayer(msg->getPlayerIndex()); if (player == NULL) { - DEBUG_CRASH(("GameLogicDispatch - MSG_CREATE_SELECTED_GROUP had an invalid player nubmer")); + DEBUG_CRASH(("GameLogicDispatch - MSG_REMOVE_FROM_SELECTED_GROUP had an invalid player nubmer")); break; } @@ -1545,7 +1544,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) if (!objToRemove) { continue; } - + TheGameLogic->deselectObject(objToRemove, player->getPlayerMask()); } @@ -1672,10 +1671,8 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) // -------------------------------------------------------------------------------------------- case GameMessage::MSG_REMOVE_BEACON: { - - AIGroup *allSelectedObjects = NULL; - allSelectedObjects = TheAI->createGroup(); - thisPlayer->getCurrentSelectionAsAIGroup(allSelectedObjects); // need to act on all objects, so we can hide teammates' beacons. + RefCountPtr allSelectedObjects = TheAI->createGroup(); + thisPlayer->getCurrentSelectionAsAIGroup(allSelectedObjects.Peek()); // need to act on all objects, so we can hide teammates' beacons. if( allSelectedObjects ) { const VecObjectID& selectedObjects = allSelectedObjects->getAllIDs(); @@ -1716,11 +1713,6 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) } } } - if (allSelectedObjects->isEmpty()) - { - TheAI->destroyGroup(allSelectedObjects); - allSelectedObjects = NULL; - } } break; } // end beacon removal @@ -1983,9 +1975,10 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData ) } /**/ - if( currentlySelectedGroup != NULL ) + if( currentlySelectedGroup ) { - TheAI->destroyGroup(currentlySelectedGroup); + currentlySelectedGroup->removeAll(); + currentlySelectedGroup = NULL; } } // end logicMessageDispatches From ff099610610851855856495b66ddfded961ae748 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:48:15 +0200 Subject: [PATCH 6/7] Fix missing return value of AIGroup::Num_Refs --- 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 c826ed74a2..a1dc1ff2f4 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -855,7 +855,7 @@ class AIGroup : public MemoryPoolObject, public Snapshot void Add_Ref() const { m_refCount.Add_Ref(); } void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } - void Num_Refs() const { m_refCount.Num_Refs(); } + Int Num_Refs() const { return m_refCount.Num_Refs(); } void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 5d13de2317..c6039aec38 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -896,7 +896,7 @@ class AIGroup : public MemoryPoolObject, public Snapshot void Add_Ref() const { m_refCount.Add_Ref(); } void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } - void Num_Refs() const { m_refCount.Num_Refs(); } + Int Num_Refs() const { return m_refCount.Num_Refs(); } void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) From af3c2708cad846049fcac506539da2487b46ce6d Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 18 Jun 2025 23:54:34 +0200 Subject: [PATCH 7/7] Fix return type --- 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 a1dc1ff2f4..02a4cf345d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -855,7 +855,7 @@ class AIGroup : public MemoryPoolObject, public Snapshot void Add_Ref() const { m_refCount.Add_Ref(); } void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } - Int Num_Refs() const { return m_refCount.Num_Refs(); } + UnsignedShort Num_Refs() const { return m_refCount.Num_Refs(); } void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index c6039aec38..f0909bb3a2 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -896,7 +896,7 @@ class AIGroup : public MemoryPoolObject, public Snapshot void Add_Ref() const { m_refCount.Add_Ref(); } void Release_Ref() const { m_refCount.Release_Ref(destroy, this); } - Int Num_Refs() const { return m_refCount.Num_Refs(); } + UnsignedShort Num_Refs() const { return m_refCount.Num_Refs(); } void groupMoveToPosition( const Coord3D *pos, Bool addWaypoint, CommandSourceType cmdSource ); void groupMoveToAndEvacuate( const Coord3D *pos, CommandSourceType cmdSource ); ///< move to given position(s)