Skip to content

Commit 0dd58aa

Browse files
MaullerStubbjax
andauthored
bugfix(behavior): Fix wrong and unsafe logic in CountermeasuresBehavior::calculateCountermeasureToDivertTo() (#1367)
Co-authored-by: Stubbjax <[email protected]>
1 parent 51a3494 commit 0dd58aa

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/CountermeasuresBehavior.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -152,36 +152,38 @@ ObjectID CountermeasuresBehavior::calculateCountermeasureToDivertTo( const Objec
152152
{
153153
const CountermeasuresBehaviorModuleData *data = getCountermeasuresBehaviorModuleData();
154154

155-
//Flares are pushed to the front of the list, but we only want to acquire the "newest" of the flares, therefore
156-
//stop iterating after we've reached size of a single volley.
157-
Int iteratorMax = MAX( data->m_volleySize, 1 );
155+
// TheSuperHackers @bugfix Mauller/Stubbjax 27/07/2025 Fix unsafe iterator handling and correct the countermeasures behavior
156+
// The code now iterates through all flares in the volley and selects the nearest one to the weapon as intended in the original EA code
157+
// This can slightly change behavior but does not significantly impact the overall survivability of the aircraft
158158

159-
Real closestDist = 1e15f;
159+
Real closestFlareDist = 1e15f;
160160
Object *closestFlare = NULL;
161+
162+
const int volleySize = data->m_volleySize;
163+
int volleyFlaresCounted = 0;
161164

165+
//Flares are pushed to the front of the list, but we only want to acquire the "newest" of the flares, therefore
162166
//Start at the end of the list and go towards the beginning.
163-
CountermeasuresVec::iterator it = m_counterMeasures.end();
164-
DEBUG_ASSERTCRASH(iteratorMax <= (Int)m_counterMeasures.size(), ("Unsafe size"));
165-
//end is actually the end so advance the iterator.
166-
if( it != m_counterMeasures.begin() )
167+
CountermeasuresVec::reverse_iterator it = m_counterMeasures.rbegin();
168+
//stop iterating after we've reached size of a single volley.
169+
while( it != m_counterMeasures.rend() && volleyFlaresCounted < volleySize )
167170
{
168-
--it;
169-
while( iteratorMax-- )
171+
Object *obj = TheGameLogic->findObjectByID( *it++ );
172+
if( obj )
170173
{
171-
Object *obj = TheGameLogic->findObjectByID( *it );
172-
if( obj )
173-
{
174-
Real dist = ThePartitionManager->getDistanceSquared( obj, getObject(), FROM_CENTER_2D );
175-
if( dist < closestDist )
176-
{
177-
closestDist = dist;
178-
closestFlare = obj;
179-
}
180-
}
181-
else
174+
Real weaponToFlareDist = ThePartitionManager->getDistanceSquared( obj, getObject(), FROM_CENTER_2D );
175+
if( weaponToFlareDist < closestFlareDist )
182176
{
183-
--it;
177+
closestFlareDist = weaponToFlareDist;
178+
closestFlare = obj;
184179
}
180+
#if RETAIL_COMPATIBLE_CRC
181+
// TheSuperHackers @info Original EA code did not work as intended and stopped on the first retrieved flare
182+
// The non retail behaviour corrects the code to iterate through all flares in the volley
183+
break;
184+
#else
185+
volleyFlaresCounted++;
186+
#endif
185187
}
186188
}
187189

0 commit comments

Comments
 (0)