Skip to content

Commit 110aa2d

Browse files
committed
bugfix(ai): fix crash when AI fires China Nuclear Missile while another is under construction
1 parent 24f8da9 commit 110aa2d

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,6 +2620,12 @@ void AIGroup::groupDoSpecialPower( UnsignedInt specialPowerID, UnsignedInt comma
26202620
//Special powers do a lot of different things, but the top level stuff doesn't use
26212621
//ai interface code. It finds the special power module and calls it directly for each object.
26222622
Object *object = (*i);
2623+
#if !RETAIL_COMPATIBLE_AIGROUP
2624+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2625+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2626+
continue;
2627+
}
2628+
#endif
26232629
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
26242630
if( spTemplate )
26252631
{
@@ -2659,6 +2665,12 @@ void AIGroup::groupDoSpecialPowerAtLocation( UnsignedInt specialPowerID, const C
26592665
//ai interface code. It finds the special power module and calls it directly for each object.
26602666

26612667
Object *object = (*i);
2668+
#if !RETAIL_COMPATIBLE_AIGROUP
2669+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2670+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2671+
continue;
2672+
}
2673+
#endif
26622674
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
26632675
if( spTemplate )
26642676
{
@@ -2698,6 +2710,12 @@ void AIGroup::groupDoSpecialPowerAtObject( UnsignedInt specialPowerID, Object *t
26982710
//ai interface code. It finds the special power module and calls it directly for each object.
26992711

27002712
Object *object = (*i);
2713+
#if !RETAIL_COMPATIBLE_AIGROUP
2714+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2715+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2716+
continue;
2717+
}
2718+
#endif
27012719
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
27022720
if( spTemplate )
27032721
{

Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,16 @@ Bool SpecialPowerModule::initiateIntentToDoSpecialPower( const Object *targetObj
406406
}
407407
}
408408

409+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from consuming special power timer when MissileLauncherBuildingUpdate is not ready.
410+
#if RETAIL_COMPATIBLE_CRC
411+
// TheSuperHackers @info we need to leave early if we are in the MissileLauncherBuildingUpdate crash fix codepath
412+
if (m_availableOnFrame == 0xFFFFFFFF)
413+
{
414+
DEBUG_ASSERTCRASH(!valid, ("Using MissileLauncherBuildingUpdate escape path when valid is set to true"));
415+
return false;
416+
}
417+
#endif
418+
409419
//If we depend on our update module to trigger the special power, make sure we have the
410420
//appropriate update module!
411421
if( !valid && getSpecialPowerModuleData()->m_updateModuleStartsAttack )

Generals/Code/GameEngine/Source/GameLogic/Object/Update/MissileLauncherBuildingUpdate.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,20 @@ void MissileLauncherBuildingUpdate::switchToState(DoorStateType dst)
200200
//-------------------------------------------------------------------------------------------------
201201
Bool MissileLauncherBuildingUpdate::initiateIntentToDoSpecialPower( const SpecialPowerTemplate *specialPowerTemplate, const Object *targetObj, const Coord3D *targetPos, const Waypoint *way, UnsignedInt commandOptions )
202202
{
203+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents crash when AI fires China Nuclear Missile while another is under construction.
204+
if (!m_specialPowerModule) {
205+
#if RETAIL_COMPATIBLE_CRC
206+
Object* us = getObject();
207+
us->getSpecialPowerModule(specialPowerTemplate)->setReadyFrame(0xFFFFFFFF);
208+
#endif
209+
return FALSE;
210+
}
211+
212+
if( m_specialPowerModule->getSpecialPowerTemplate() != specialPowerTemplate )
213+
{
214+
return FALSE;
215+
}
216+
203217
#if defined(RTS_DEBUG)
204218
DEBUG_ASSERTCRASH(!TheGlobalData->m_specialPowerUsesDelay || m_doorState == DOOR_OPEN, ("door is not fully open when specialpower is fired!"));
205219
#endif

GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,12 @@ void AIGroup::groupDoSpecialPower( UnsignedInt specialPowerID, UnsignedInt comma
26832683
//Special powers do a lot of different things, but the top level stuff doesn't use
26842684
//ai interface code. It finds the special power module and calls it directly for each object.
26852685
Object *object = (*i);
2686+
#if !RETAIL_COMPATIBLE_AIGROUP
2687+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2688+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2689+
continue;
2690+
}
2691+
#endif
26862692
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
26872693
if( spTemplate )
26882694
{
@@ -2731,6 +2737,13 @@ void AIGroup::groupDoSpecialPowerAtLocation( UnsignedInt specialPowerID, const C
27312737
// destroys the AIGroup list, in order to keep the selection sync'ed with the group.
27322738
// M Lorenzen... 8/23/03
27332739

2740+
#if !RETAIL_COMPATIBLE_AIGROUP
2741+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2742+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2743+
continue;
2744+
}
2745+
#endif
2746+
27342747
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
27352748
if( spTemplate )
27362749
{
@@ -2771,6 +2784,12 @@ void AIGroup::groupDoSpecialPowerAtObject( UnsignedInt specialPowerID, Object *t
27712784
//ai interface code. It finds the special power module and calls it directly for each object.
27722785

27732786
Object *object = (*i);
2787+
#if !RETAIL_COMPATIBLE_AIGROUP
2788+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents AI from trying to fire special powers from buildings under construction.
2789+
if (object->testStatus(OBJECT_STATUS_UNDER_CONSTRUCTION)) {
2790+
continue;
2791+
}
2792+
#endif
27742793
const SpecialPowerTemplate *spTemplate = TheSpecialPowerStore->findSpecialPowerTemplateByID( specialPowerID );
27752794
if( spTemplate )
27762795
{

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/MissileLauncherBuildingUpdate.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,15 @@ void MissileLauncherBuildingUpdate::switchToState(DoorStateType dst)
201201
//-------------------------------------------------------------------------------------------------
202202
Bool MissileLauncherBuildingUpdate::initiateIntentToDoSpecialPower( const SpecialPowerTemplate *specialPowerTemplate, const Object *targetObj, const Coord3D *targetPos, const Waypoint *way, UnsignedInt commandOptions )
203203
{
204-
#if RETAIL_COMPATIBLE_CRC
205204
// TheSuperHackers @bugfix Mauller 29/06/2025 prevent a game crash when told to launch before ready to do so
205+
// TheSuperHackers @bugfix bobtista 01/11/2025 Prevents crash when AI fires China Nuclear Missile while another is under construction.
206206
if (!m_specialPowerModule) {
207+
#if RETAIL_COMPATIBLE_CRC
207208
Object* us = getObject();
208209
us->getSpecialPowerModule(specialPowerTemplate)->setReadyFrame(0xFFFFFFFF);
210+
#endif
209211
return FALSE;
210212
}
211-
#endif
212213

213214
if( m_specialPowerModule->getSpecialPowerTemplate() != specialPowerTemplate )
214215
{

0 commit comments

Comments
 (0)