Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Core/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2120,10 +2120,9 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
}

#if RETAIL_COMPATIBLE_AIGROUP
// TheSuperHackers @bugfix xezon 28/06/2025 This hack avoids crashing when players are selected during Replay playback.
// It can read data from an already deleted AIGroup and return this function when its member size is 0, signifying that
// it is indeed deleted.
if (currentlySelectedGroup && currentlySelectedGroup->getCount() == 0)
// TheSuperHackers @bugfix xezon/Caball009 14/05/2026 This fix avoids crashing when players are selected during Replay playback.
// The current AI group may have been destroyed, and its memory deallocated, in which case it shouldn't be used.
if (currentlySelectedGroup && !TheAI->doesGroupExist(currentlySelectedGroup))
return;
Comment thread
Caball009 marked this conversation as resolved.
#endif

Expand Down
1 change: 1 addition & 0 deletions Generals/Code/GameEngine/Include/GameLogic/AI.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ class AI : public SubsystemInterface, public Snapshot
AIGroupPtr createGroup(); ///< 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
Bool doesGroupExist(AIGroup* group) const; ///< return whether the given AI Group exists, i.e. is part of the group list

// Formation info
enum FormationID getNextFormationID();
Expand Down
5 changes: 5 additions & 0 deletions Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,11 @@ AIGroup *AI::findGroup( UnsignedInt id )
return nullptr;
}

Bool AI::doesGroupExist(AIGroup* group) const
{
return std::find(m_groupList.begin(), m_groupList.end(), group) != m_groupList.end();
}

//--------------------------------------------------------------------------------------------------------
/**
* Get the next formation id.
Expand Down
1 change: 1 addition & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ class AI : public SubsystemInterface, public Snapshot
AIGroupPtr createGroup(); ///< 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
Bool doesGroupExist(AIGroup* group) const; ///< return whether the given AI Group exists, i.e. is part of the group list

// Formation info
enum FormationID getNextFormationID();
Expand Down
5 changes: 5 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,11 @@ AIGroup *AI::findGroup( UnsignedInt id )
return nullptr;
}

Bool AI::doesGroupExist(AIGroup* group) const
{
return std::find(m_groupList.begin(), m_groupList.end(), group) != m_groupList.end();
}

//--------------------------------------------------------------------------------------------------------
/**
* Get the next formation id.
Expand Down
Loading