From eecc56d167823904a28c04d9e58cd310bcd0746f Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 3 Aug 2025 14:47:28 +1000 Subject: [PATCH 1/5] bugfix: Bunkered Battle Buses can now respond to attack commands --- .../GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp index 14d6fbfd88a..8bf0982276b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp @@ -215,7 +215,11 @@ UpdateSleepTime BattleBusSlowDeathBehavior::update( void ) me->getPhysics()->clearAcceleration(); me->getPhysics()->scrubVelocity2D(0); } +#if RETAIL_COMPATIBLE_CRC me->setDisabled(DISABLED_HELD); +#else + me->setStatus(MAKE_OBJECT_STATUS_MASK(OBJECT_STATUS_IMMOBILE)); +#endif // We can only sleep if we don't have to watch out for being empty. if( data->m_emptyHulkDestructionDelay == 0 ) From 1407809ef4a077e486e7de0d77fb2a8a6929c530 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 3 Aug 2025 14:47:54 +1000 Subject: [PATCH 2/5] bugfix: Prevent building on bunkered Battle Buses --- .../Code/GameEngine/Source/Common/System/BuildAssistant.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index 73f6cd57c5b..fcb746c195b 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -726,7 +726,11 @@ LegalBuildCode BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos } // an immobile object may obstruct our building depending on flags. +#if RETAIL_COMPATIBLE_CRC if( them->isKindOf( KINDOF_IMMOBILE ) ) +#else + if (them->isKindOf(KINDOF_IMMOBILE) || them->getStatusBits().test(OBJECT_STATUS_IMMOBILE)) +#endif { if( feedbackWithFailure ) { From 33a5ab8b8693c4c7bcb64b1321afe0506f742ca5 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 3 Aug 2025 14:48:40 +1000 Subject: [PATCH 3/5] bugfix: Disable attack-move and guard commands for bunkered Battle Buses (and any other immobile objects) --- .../GameClient/GUI/ControlBar/ControlBarCommand.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp index 91931a3e7e3..06817386f40 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp @@ -1092,6 +1092,19 @@ CommandAvailability ControlBar::getCommandAvailability( const CommandButton *com } } + if (obj->isKindOf(KINDOF_IMMOBILE) || obj->getStatusBits().test(OBJECT_STATUS_IMMOBILE)) + { + GUICommandType commandType = command->getCommandType(); + if (commandType == GUI_COMMAND_ATTACK_MOVE || + commandType == GUI_COMMAND_GUARD || + commandType == GUI_COMMAND_GUARD_WITHOUT_PURSUIT || + commandType == GUI_COMMAND_GUARD_FLYING_UNITS_ONLY) + { + // If the object is immobile, it can't attack-move or guard. + return COMMAND_RESTRICTED; + } + } + // if the command requires an upgrade and we don't have it we can't do it if( BitIsSet( command->getOptions(), NEED_UPGRADE ) ) { From 66d1f2bc18b0b90e8a708fe0e29c8c56da16b0a5 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 27 Jan 2026 20:14:39 +1100 Subject: [PATCH 4/5] docs: Add comments --- .../Code/GameEngine/Source/Common/System/BuildAssistant.cpp | 1 + .../GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index fcb746c195b..0af83464da6 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -729,6 +729,7 @@ LegalBuildCode BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos #if RETAIL_COMPATIBLE_CRC if( them->isKindOf( KINDOF_IMMOBILE ) ) #else + // TheSuperHackers @bugfix Stubbjax 03/08/2025 Prevent building on immobile objects like undead Battle Buses. if (them->isKindOf(KINDOF_IMMOBILE) || them->getStatusBits().test(OBJECT_STATUS_IMMOBILE)) #endif { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp index 8bf0982276b..c6afcace2fa 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp @@ -218,6 +218,8 @@ UpdateSleepTime BattleBusSlowDeathBehavior::update( void ) #if RETAIL_COMPATIBLE_CRC me->setDisabled(DISABLED_HELD); #else + // TheSuperHackers @bugfix Stubbjax 03/08/2025 Set the bus to IMMOBILE instead of HELD, + // which allows passengers to now respond to attack commands. me->setStatus(MAKE_OBJECT_STATUS_MASK(OBJECT_STATUS_IMMOBILE)); #endif From 58d4b58b345cb5ff29367207014ce3283c417a4e Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Tue, 27 Jan 2026 20:14:59 +1100 Subject: [PATCH 5/5] refactor: Implement cleaner solution --- .../Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp | 4 ++++ .../Source/Common/System/BuildAssistant.cpp | 5 ----- .../GameClient/GUI/ControlBar/ControlBarCommand.cpp | 13 ------------- .../Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp | 4 ++++ .../Object/Behavior/BattleBusSlowDeathBehavior.cpp | 6 ------ 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index 7b668290a3f..0a7de7444f0 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -2112,10 +2112,14 @@ void AIGroup::groupAttackObjectPrivate( Bool forced, Object *victim, Int maxShot for( i = m_memberList.begin(); i != m_memberList.end(); ++i ) { Real dx, dy; Coord3D unitPos = *((*i)->getPosition()); +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 03/08/2025 This logic block erroneously prevents the + // occupants of DISABLED_HELD units (e.g. undead Battle Buses) from responding to attack commands. if ((*i)->isDisabledByType( DISABLED_HELD ) ) { continue; // don't bother telling the occupants to move. } +#endif dx = unitPos.x - victimPos.x; dy = unitPos.y - victimPos.y; iter->insert((*i), dx*dx+dy*dy); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index 0af83464da6..73f6cd57c5b 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -726,12 +726,7 @@ LegalBuildCode BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos } // an immobile object may obstruct our building depending on flags. -#if RETAIL_COMPATIBLE_CRC if( them->isKindOf( KINDOF_IMMOBILE ) ) -#else - // TheSuperHackers @bugfix Stubbjax 03/08/2025 Prevent building on immobile objects like undead Battle Buses. - if (them->isKindOf(KINDOF_IMMOBILE) || them->getStatusBits().test(OBJECT_STATUS_IMMOBILE)) -#endif { if( feedbackWithFailure ) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp index 06817386f40..91931a3e7e3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp @@ -1092,19 +1092,6 @@ CommandAvailability ControlBar::getCommandAvailability( const CommandButton *com } } - if (obj->isKindOf(KINDOF_IMMOBILE) || obj->getStatusBits().test(OBJECT_STATUS_IMMOBILE)) - { - GUICommandType commandType = command->getCommandType(); - if (commandType == GUI_COMMAND_ATTACK_MOVE || - commandType == GUI_COMMAND_GUARD || - commandType == GUI_COMMAND_GUARD_WITHOUT_PURSUIT || - commandType == GUI_COMMAND_GUARD_FLYING_UNITS_ONLY) - { - // If the object is immobile, it can't attack-move or guard. - return COMMAND_RESTRICTED; - } - } - // if the command requires an upgrade and we don't have it we can't do it if( BitIsSet( command->getOptions(), NEED_UPGRADE ) ) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index 8b69a9faa8c..acec62ed8c9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -2175,10 +2175,14 @@ void AIGroup::groupAttackObjectPrivate( Bool forced, Object *victim, Int maxShot for( i = m_memberList.begin(); i != m_memberList.end(); ++i ) { Real dx, dy; Coord3D unitPos = *((*i)->getPosition()); +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 03/08/2025 This logic block erroneously prevents the + // occupants of DISABLED_HELD units (e.g. undead Battle Buses) from responding to attack commands. if ((*i)->isDisabledByType( DISABLED_HELD ) ) { continue; // don't bother telling the occupants to move. } +#endif dx = unitPos.x - victimPos.x; dy = unitPos.y - victimPos.y; iter->insert((*i), dx*dx+dy*dy); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp index c6afcace2fa..14d6fbfd88a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BattleBusSlowDeathBehavior.cpp @@ -215,13 +215,7 @@ UpdateSleepTime BattleBusSlowDeathBehavior::update( void ) me->getPhysics()->clearAcceleration(); me->getPhysics()->scrubVelocity2D(0); } -#if RETAIL_COMPATIBLE_CRC me->setDisabled(DISABLED_HELD); -#else - // TheSuperHackers @bugfix Stubbjax 03/08/2025 Set the bus to IMMOBILE instead of HELD, - // which allows passengers to now respond to attack commands. - me->setStatus(MAKE_OBJECT_STATUS_MASK(OBJECT_STATUS_IMMOBILE)); -#endif // We can only sleep if we don't have to watch out for being empty. if( data->m_emptyHulkDestructionDelay == 0 )