From 47bb2a980667881b9a1bff9b75a6b69e2a44c419 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 11 Nov 2025 15:44:37 -0500 Subject: [PATCH 01/16] bugfix: Fix Gatling Cannon barrels rotating despite insufficient energy --- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 9 +++++++++ .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 49d49491de..b957877be2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2918,6 +2918,10 @@ Bool Object::isAbleToAttack() const if( testStatus(OBJECT_STATUS_SOLD) ) return false; + // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. + if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + return false; + //We can't fire if we, as a portable structure, are aptly disabled if ( isKindOf( KINDOF_PORTABLE_STRUCTURE ) || isKindOf( KINDOF_SPAWNS_ARE_THE_WEAPONS )) { @@ -4187,6 +4191,11 @@ void Object::adjustModelConditionForWeaponStatus() // we really don't care, so we just force the issue here. (This might still need tweaking for the pursue state.) conditionToSet = WSF_NONE; } + // TheSuperHackers @bugfix bobtista 11/11/2025 Prevent barrel animation when powered structures are underpowered. + else if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + { + conditionToSet = WSF_NONE; + } else { WeaponStatus newStatus = w->getStatus(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index bca7c39b87..48dac0c49d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3236,6 +3236,10 @@ Bool Object::isAbleToAttack() const if ( isDisabledByType( DISABLED_SUBDUED ) ) return FALSE; // A Microwave Tank is cooking me + // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. (#1700) + if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + return false; + //We can't fire if we, as a portable structure, are aptly disabled if ( isKindOf( KINDOF_PORTABLE_STRUCTURE ) || isKindOf( KINDOF_SPAWNS_ARE_THE_WEAPONS )) { From c4e16db4264da022e2e98baa70858e8a9ab4fe46 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 11 Nov 2025 15:45:31 -0500 Subject: [PATCH 02/16] bugfix: Add CRC guard for Gatling Cannon barrel animation fix --- .../GameEngine/Source/GameLogic/Object/Object.cpp | 4 ++++ .../GameEngine/Source/GameLogic/Object/Object.cpp | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index b957877be2..12aa1d10f5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2919,8 +2919,10 @@ Bool Object::isAbleToAttack() const return false; // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. +#if !RETAIL_COMPATIBLE_CRC if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) return false; +#endif //We can't fire if we, as a portable structure, are aptly disabled if ( isKindOf( KINDOF_PORTABLE_STRUCTURE ) || isKindOf( KINDOF_SPAWNS_ARE_THE_WEAPONS )) @@ -4192,10 +4194,12 @@ void Object::adjustModelConditionForWeaponStatus() conditionToSet = WSF_NONE; } // TheSuperHackers @bugfix bobtista 11/11/2025 Prevent barrel animation when powered structures are underpowered. +#if !RETAIL_COMPATIBLE_CRC else if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) { conditionToSet = WSF_NONE; } +#endif else { WeaponStatus newStatus = w->getStatus(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 48dac0c49d..ff8836d499 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3236,9 +3236,11 @@ Bool Object::isAbleToAttack() const if ( isDisabledByType( DISABLED_SUBDUED ) ) return FALSE; // A Microwave Tank is cooking me - // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. (#1700) + // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. +#if !RETAIL_COMPATIBLE_CRC if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) return false; +#endif //We can't fire if we, as a portable structure, are aptly disabled if ( isKindOf( KINDOF_PORTABLE_STRUCTURE ) || isKindOf( KINDOF_SPAWNS_ARE_THE_WEAPONS )) @@ -4755,6 +4757,13 @@ void Object::adjustModelConditionForWeaponStatus() // we really don't care, so we just force the issue here. (This might still need tweaking for the pursue state.) conditionToSet = WSF_NONE; } + // TheSuperHackers @bugfix bobtista 11/11/2025 Prevent barrel animation when powered structures are underpowered. +#if !RETAIL_COMPATIBLE_CRC + else if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + { + conditionToSet = WSF_NONE; + } +#endif else { WeaponStatus newStatus = w->getStatus(); From 98ece8f9624683b029d75a4c5cbc2d8e02c973d0 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 23 Nov 2025 12:14:24 -0500 Subject: [PATCH 03/16] bugfix: Prevent barrel animation from resuming after weapon status transition when underpowered --- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 8 ++++++++ .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 12aa1d10f5..a6098970d7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -4223,7 +4223,15 @@ void Object::adjustModelConditionForWeaponStatus() if (newStatus == READY_TO_FIRE && conditionToSet == WSF_NONE && testStatus( OBJECT_STATUS_IS_ATTACKING ) && (testStatus( OBJECT_STATUS_IS_AIMING_WEAPON ) || testStatus( OBJECT_STATUS_IS_FIRING_WEAPON ))) { + // TheSuperHackers @bugfix bobtista 11/11/2025 Don't resume firing animation if underpowered. +#if !RETAIL_COMPATIBLE_CRC + if ( !( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) ) + { + conditionToSet = WSF_BETWEEN; + } +#else conditionToSet = WSF_BETWEEN; +#endif } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index ff8836d499..7ced3eadd4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -4787,7 +4787,15 @@ void Object::adjustModelConditionForWeaponStatus() if (newStatus == READY_TO_FIRE && conditionToSet == WSF_NONE && testStatus( OBJECT_STATUS_IS_ATTACKING ) && (testStatus( OBJECT_STATUS_IS_AIMING_WEAPON ) || testStatus( OBJECT_STATUS_IS_FIRING_WEAPON ))) { + // TheSuperHackers @bugfix bobtista 11/11/2025 Don't resume firing animation if underpowered. +#if !RETAIL_COMPATIBLE_CRC + if ( !( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) ) + { + conditionToSet = WSF_BETWEEN; + } +#else conditionToSet = WSF_BETWEEN; +#endif } } From abcfcce76fbe8d6d8eb6b2921ea886ac101e9b1f Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 21 Dec 2025 19:38:30 -0500 Subject: [PATCH 04/16] bugfix: Add forceCoolDown to FiringTracker in GeneralsMD --- .../Code/GameEngine/Include/GameLogic/FiringTracker.h | 1 + .../GameEngine/Source/GameLogic/Object/FiringTracker.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index 237b009bb3..e513b12e2f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -55,6 +55,7 @@ class FiringTracker : public UpdateModule void shotFired(const Weapon* weaponFired, ObjectID victimID ); ///< Owner just fired this weapon at this Object ObjectID getLastShotVictim() const { return m_victimID; } ///< get the last victim ID that was shot at Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; + void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp index 61969926d6..f3a2418fc5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp @@ -301,6 +301,13 @@ void FiringTracker::speedUp() } +//------------------------------------------------------------------------------------------------- +void FiringTracker::forceCoolDown() +{ + m_frameToStartCooldown = 0; + coolDown(); +} + //------------------------------------------------------------------------------------------------- void FiringTracker::coolDown() { From 825b100bacc8d01b967c851c3168af8923c1b828 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 21 Dec 2025 19:38:31 -0500 Subject: [PATCH 05/16] bugfix: Add forceCoolDown to FiringTracker in Generals --- Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h | 1 + .../GameEngine/Source/GameLogic/Object/FiringTracker.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h index 46637984e5..1242e7214d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -55,6 +55,7 @@ class FiringTracker : public UpdateModule void shotFired(const Weapon* weaponFired, ObjectID victimID ); ///< Owner just fired this weapon at this Object ObjectID getLastShotVictim() const { return m_victimID; } ///< get the last victim ID that was shot at Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; + void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp index 78bc4fced5..3778856db5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/FiringTracker.cpp @@ -282,6 +282,13 @@ void FiringTracker::speedUp() } +//------------------------------------------------------------------------------------------------- +void FiringTracker::forceCoolDown() +{ + m_frameToStartCooldown = 0; + coolDown(); +} + //------------------------------------------------------------------------------------------------- void FiringTracker::coolDown() { From 566112705c4ecaeeee7d54c93ac8d6eb2ec314a2 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 21 Dec 2025 19:38:31 -0500 Subject: [PATCH 06/16] bugfix: Force FiringTracker cooldown when power lost in GeneralsMD --- .../GameEngine/Source/GameLogic/Object/Object.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 7ced3eadd4..0d61d9a179 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2247,6 +2247,17 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } + // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. + if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED)) + { + if (testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN) || testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST)) + { + clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN); + clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST); + } + m_firingTracker->forceCoolDown(); + } + // This will only be called if we were NOT disabled before coming into this function. if (edgeCase) { onDisabledEdge(true); From b4ddd926274feb3a39527b82f52da15cc65f7490 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 21 Dec 2025 19:38:32 -0500 Subject: [PATCH 07/16] bugfix: Force FiringTracker cooldown when power lost in Generals --- .../GameEngine/Source/GameLogic/Object/Object.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index a6098970d7..18828b6d2b 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2015,6 +2015,17 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } + // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. + if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_HACKED)) + { + if (testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN) || testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST)) + { + clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN); + clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST); + } + m_firingTracker->forceCoolDown(); + } + // This will only be called if we were NOT disabled before coming into this function. if (edgeCase) { onDisabledEdge(true); From 5c36d3cf4acb8be7799cb258b5fe669ea148c74b Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sun, 21 Dec 2025 22:59:41 -0500 Subject: [PATCH 08/16] bugfix: Remove redundant weapon bonus condition clearing in forceCoolDown calls --- Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | 5 ----- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 5 ----- 2 files changed, 10 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 18828b6d2b..373c8b1b95 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2018,11 +2018,6 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_HACKED)) { - if (testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN) || testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST)) - { - clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN); - clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST); - } m_firingTracker->forceCoolDown(); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 0d61d9a179..0055f81e7c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2250,11 +2250,6 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED)) { - if (testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN) || testWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST)) - { - clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_MEAN); - clearWeaponBonusCondition(WEAPONBONUSCONDITION_CONTINUOUS_FIRE_FAST); - } m_firingTracker->forceCoolDown(); } From ca7918fd18bdeb58d9ba7bde9f14e6760153be29 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 18:01:58 -0500 Subject: [PATCH 09/16] refactor: exclude power-related disable types from FiringTracker updates --- .../Code/GameEngine/Include/GameLogic/FiringTracker.h | 10 ++++++++-- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index e513b12e2f..8b4738a949 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,8 +57,14 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) - virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } + /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED, SUBDUED) so update() isn't called when disabled. + /// forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. Other types allow "spin down". + virtual DisabledMaskType getDisabledTypesToProcess() const + { + DisabledMaskType mask = DISABLEDMASK_ALL; + mask.clear(MAKE_DISABLED_MASK4(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED, DISABLED_SUBDUED)); + return mask; + } virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 0055f81e7c..6126ef1681 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2248,6 +2248,7 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. + // FiringTracker::getDisabledTypesToProcess() excludes these types, but we still need forceCoolDown() for immediate cooldown. if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED)) { m_firingTracker->forceCoolDown(); From 2594fdd0a414aae0d1b9c7655a3c4f7454cf0de0 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 22 Dec 2025 18:02:00 -0500 Subject: [PATCH 10/16] fix: force FiringTracker cooldown when power is lost --- .../Code/GameEngine/Include/GameLogic/FiringTracker.h | 10 ++-------- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index 8b4738a949..e513b12e2f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,14 +57,8 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED, SUBDUED) so update() isn't called when disabled. - /// forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. Other types allow "spin down". - virtual DisabledMaskType getDisabledTypesToProcess() const - { - DisabledMaskType mask = DISABLEDMASK_ALL; - mask.clear(MAKE_DISABLED_MASK4(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED, DISABLED_SUBDUED)); - return mask; - } + /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) + virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 6126ef1681..0055f81e7c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2248,7 +2248,6 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. - // FiringTracker::getDisabledTypesToProcess() excludes these types, but we still need forceCoolDown() for immediate cooldown. if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED)) { m_firingTracker->forceCoolDown(); From 968c00983b281dec13728516d1aa70174e4ceb89 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 14:50:08 -0500 Subject: [PATCH 11/16] fix: prevent FiringTracker update when disabled by power-related types --- .../Code/GameEngine/Include/GameLogic/FiringTracker.h | 10 ++++++++-- .../Code/GameEngine/Include/GameLogic/FiringTracker.h | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h index 1242e7214d..b9de2dad40 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,8 +57,14 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) - virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } + /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED) so update() isn't called when disabled. + /// This prevents delayed barrel animation restart. forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. + virtual DisabledMaskType getDisabledTypesToProcess() const + { + DisabledMaskType mask = DISABLEDMASK_ALL; + mask.clear(MAKE_DISABLED_MASK3(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED)); + return mask; + } virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index e513b12e2f..dddd03a244 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,8 +57,14 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) - virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } + /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED, SUBDUED) so update() isn't called when disabled. + /// This prevents delayed barrel animation restart. forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. + virtual DisabledMaskType getDisabledTypesToProcess() const + { + DisabledMaskType mask = DISABLEDMASK_ALL; + mask.clear(MAKE_DISABLED_MASK4(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED, DISABLED_SUBDUED)); + return mask; + } virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while From a679e67edef70a1ab69226cf72f2e09dbed46d84 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 15:11:39 -0500 Subject: [PATCH 12/16] refactor: add isUnderpoweredForAttack helper method --- .../GameEngine/Include/GameLogic/Object.h | 1 + .../Source/GameLogic/Object/Object.cpp | 31 +++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h index 9c601848f6..c90bd580af 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h @@ -586,6 +586,7 @@ class Object : public Thing, public Snapshot void setDisabled( DisabledType type ); void setDisabledUntil( DisabledType type, UnsignedInt frame ); Bool isDisabledByType( DisabledType type ) const { return TEST_DISABLEDMASK( m_disabledMask, type ); } + Bool isUnderpoweredForAttack() const; ///< Returns true if powered-type and underpowered UnsignedInt getDisabledUntil( DisabledType type = DISABLED_ANY ) const; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 0055f81e7c..55197ecb89 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -1724,6 +1724,16 @@ Bool Object::isLogicallyVisible() const //============================================================================= // Object::isLocallyControlled //============================================================================= +Bool Object::isUnderpoweredForAttack() const +{ +#if !RETAIL_COMPATIBLE_CRC + return isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ); +#else + return false; +#endif +} + +//------------------------------------------------------------------------------------------------- Bool Object::isLocallyControlled() const { return getControllingPlayer() == ThePlayerList->getLocalPlayer(); @@ -2247,10 +2257,16 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } - // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. - if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED)) + // TheSuperHackers @bugfix bobtista 21/12/2025 Fix Gatling Cannon barrels rotating despite insufficient energy. + // When power is lost (UNDERPOWERED, EMP, SUBDUED, HACKED), immediately force FiringTracker cooldown to stop barrel animations. + // getDisabledTypesToProcess() prevents update() from restarting animations, and isUnderpoweredForAttack() prevents cursor/attack logic. + if (m_firingTracker) { - m_firingTracker->forceCoolDown(); + Bool isPowerDisableType = (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_SUBDUED || type == DISABLED_HACKED); + if (isPowerDisableType) + { + m_firingTracker->forceCoolDown(); + } } // This will only be called if we were NOT disabled before coming into this function. @@ -3242,9 +3258,8 @@ Bool Object::isAbleToAttack() const if ( isDisabledByType( DISABLED_SUBDUED ) ) return FALSE; // A Microwave Tank is cooking me - // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. #if !RETAIL_COMPATIBLE_CRC - if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + if (isUnderpoweredForAttack()) return false; #endif @@ -4763,9 +4778,8 @@ void Object::adjustModelConditionForWeaponStatus() // we really don't care, so we just force the issue here. (This might still need tweaking for the pursue state.) conditionToSet = WSF_NONE; } - // TheSuperHackers @bugfix bobtista 11/11/2025 Prevent barrel animation when powered structures are underpowered. #if !RETAIL_COMPATIBLE_CRC - else if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + else if (isUnderpoweredForAttack()) { conditionToSet = WSF_NONE; } @@ -4793,9 +4807,8 @@ void Object::adjustModelConditionForWeaponStatus() if (newStatus == READY_TO_FIRE && conditionToSet == WSF_NONE && testStatus( OBJECT_STATUS_IS_ATTACKING ) && (testStatus( OBJECT_STATUS_IS_AIMING_WEAPON ) || testStatus( OBJECT_STATUS_IS_FIRING_WEAPON ))) { - // TheSuperHackers @bugfix bobtista 11/11/2025 Don't resume firing animation if underpowered. #if !RETAIL_COMPATIBLE_CRC - if ( !( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) ) + if (!isUnderpoweredForAttack()) { conditionToSet = WSF_BETWEEN; } From 89bd63d3f86f0cd1e04dd8d19940c0a94527e1e0 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 15:11:43 -0500 Subject: [PATCH 13/16] refactor: add isUnderpoweredForAttack helper method --- .../GameEngine/Include/GameLogic/Object.h | 1 + .../Source/GameLogic/Object/Object.cpp | 31 +++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Object.h b/Generals/Code/GameEngine/Include/GameLogic/Object.h index 9f0f0869b3..23da00757b 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Object.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Object.h @@ -549,6 +549,7 @@ class Object : public Thing, public Snapshot void setDisabled( DisabledType type ); void setDisabledUntil( DisabledType type, UnsignedInt frame ); Bool isDisabledByType( DisabledType type ) const { return TEST_DISABLEDMASK( m_disabledMask, type ); } + Bool isUnderpoweredForAttack() const; ///< Returns true if powered-type and underpowered void pauseAllSpecialPowers( const Bool disabling ) const; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 373c8b1b95..85e0768a9b 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -1569,6 +1569,16 @@ Bool Object::isLogicallyVisible() const //============================================================================= // Object::isLocallyControlled //============================================================================= +Bool Object::isUnderpoweredForAttack() const +{ +#if !RETAIL_COMPATIBLE_CRC + return isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ); +#else + return false; +#endif +} + +//------------------------------------------------------------------------------------------------- Bool Object::isLocallyControlled() const { return getControllingPlayer() == ThePlayerList->getLocalPlayer(); @@ -2015,10 +2025,16 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } - // TheSuperHackers @bugfix bobtista 21/12/2025 Force FiringTracker to cool down immediately when power is lost to prevent delayed barrel animations. - if (m_firingTracker && (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_HACKED)) + // TheSuperHackers @bugfix bobtista 21/12/2025 Fix Gatling Cannon barrels rotating despite insufficient energy. + // When power is lost (UNDERPOWERED, EMP, HACKED), immediately force FiringTracker cooldown to stop barrel animations. + // getDisabledTypesToProcess() prevents update() from restarting animations, and isUnderpoweredForAttack() prevents cursor/attack logic. + if (m_firingTracker) { - m_firingTracker->forceCoolDown(); + Bool isPowerDisableType = (type == DISABLED_UNDERPOWERED || type == DISABLED_EMP || type == DISABLED_HACKED); + if (isPowerDisableType) + { + m_firingTracker->forceCoolDown(); + } } // This will only be called if we were NOT disabled before coming into this function. @@ -2924,9 +2940,8 @@ Bool Object::isAbleToAttack() const if( testStatus(OBJECT_STATUS_SOLD) ) return false; - // TheSuperHackers @bugfix bobtista 31/10/2025 Fixes Gatling Cannon barrels rotating despite insufficient energy. #if !RETAIL_COMPATIBLE_CRC - if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + if (isUnderpoweredForAttack()) return false; #endif @@ -4199,9 +4214,8 @@ void Object::adjustModelConditionForWeaponStatus() // we really don't care, so we just force the issue here. (This might still need tweaking for the pursue state.) conditionToSet = WSF_NONE; } - // TheSuperHackers @bugfix bobtista 11/11/2025 Prevent barrel animation when powered structures are underpowered. #if !RETAIL_COMPATIBLE_CRC - else if ( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) + else if (isUnderpoweredForAttack()) { conditionToSet = WSF_NONE; } @@ -4229,9 +4243,8 @@ void Object::adjustModelConditionForWeaponStatus() if (newStatus == READY_TO_FIRE && conditionToSet == WSF_NONE && testStatus( OBJECT_STATUS_IS_ATTACKING ) && (testStatus( OBJECT_STATUS_IS_AIMING_WEAPON ) || testStatus( OBJECT_STATUS_IS_FIRING_WEAPON ))) { - // TheSuperHackers @bugfix bobtista 11/11/2025 Don't resume firing animation if underpowered. #if !RETAIL_COMPATIBLE_CRC - if ( !( isKindOf( KINDOF_POWERED ) && isDisabledByType( DISABLED_UNDERPOWERED ) ) ) + if (!isUnderpoweredForAttack()) { conditionToSet = WSF_BETWEEN; } From c29ca19205f378efe50fedc96c5504ace8b46f73 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 15:11:45 -0500 Subject: [PATCH 14/16] refactor: simplify FiringTracker getDisabledTypesToProcess comment --- GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index dddd03a244..c1ac2e7ed0 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,8 +57,8 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED, SUBDUED) so update() isn't called when disabled. - /// This prevents delayed barrel animation restart. forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. + /// Exclude power-related disable types so update() doesn't restart barrel animations. + /// forceCoolDown() in setDisabledUntil() handles immediate cooldown. virtual DisabledMaskType getDisabledTypesToProcess() const { DisabledMaskType mask = DISABLEDMASK_ALL; From 8361fbf02066a43c1a69183a6a1cd1fca2d0a05d Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 15:11:47 -0500 Subject: [PATCH 15/16] refactor: simplify FiringTracker getDisabledTypesToProcess comment --- Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h index b9de2dad40..8cd6d5cc38 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,8 +57,8 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states - /// Exclude power-related disable types (UNDERPOWERED, EMP, HACKED) so update() isn't called when disabled. - /// This prevents delayed barrel animation restart. forceCoolDown() in Object::setDisabledUntil() handles immediate cooldown. + /// Exclude power-related disable types so update() doesn't restart barrel animations. + /// forceCoolDown() in setDisabledUntil() handles immediate cooldown. virtual DisabledMaskType getDisabledTypesToProcess() const { DisabledMaskType mask = DISABLEDMASK_ALL; From ab5e59e45d93500efb05f1b0587547ddab693dde Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 23 Dec 2025 15:42:54 -0500 Subject: [PATCH 16/16] fix: add CRC guards to prevent replay mismatches --- Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h | 5 +++++ Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | 2 ++ GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h | 5 +++++ .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 2 ++ 4 files changed, 14 insertions(+) diff --git a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h index 8cd6d5cc38..5c2c4f483d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/Generals/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,6 +57,7 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states +#if !RETAIL_COMPATIBLE_CRC /// Exclude power-related disable types so update() doesn't restart barrel animations. /// forceCoolDown() in setDisabledUntil() handles immediate cooldown. virtual DisabledMaskType getDisabledTypesToProcess() const @@ -65,6 +66,10 @@ class FiringTracker : public UpdateModule mask.clear(MAKE_DISABLED_MASK3(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED)); return mask; } +#else + /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) + virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } +#endif virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 85e0768a9b..ef0a1df0c8 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2025,6 +2025,7 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } +#if !RETAIL_COMPATIBLE_CRC // TheSuperHackers @bugfix bobtista 21/12/2025 Fix Gatling Cannon barrels rotating despite insufficient energy. // When power is lost (UNDERPOWERED, EMP, HACKED), immediately force FiringTracker cooldown to stop barrel animations. // getDisabledTypesToProcess() prevents update() from restarting animations, and isUnderpoweredForAttack() prevents cursor/attack logic. @@ -2036,6 +2037,7 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) m_firingTracker->forceCoolDown(); } } +#endif // This will only be called if we were NOT disabled before coming into this function. if (edgeCase) { diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h index c1ac2e7ed0..49185ca819 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FiringTracker.h @@ -57,6 +57,7 @@ class FiringTracker : public UpdateModule Int getNumConsecutiveShotsAtVictim( const Object *victim ) const; void forceCoolDown(); ///< Force immediate cooldown, stopping all continuous fire states +#if !RETAIL_COMPATIBLE_CRC /// Exclude power-related disable types so update() doesn't restart barrel animations. /// forceCoolDown() in setDisabledUntil() handles immediate cooldown. virtual DisabledMaskType getDisabledTypesToProcess() const @@ -65,6 +66,10 @@ class FiringTracker : public UpdateModule mask.clear(MAKE_DISABLED_MASK4(DISABLED_HACKED, DISABLED_EMP, DISABLED_UNDERPOWERED, DISABLED_SUBDUED)); return mask; } +#else + /// this is never disabled, since we want disabled things to continue to slowly "spin down"... (srj) + virtual DisabledMaskType getDisabledTypesToProcess() const { return DISABLEDMASK_ALL; } +#endif virtual UpdateSleepTime update(); ///< See if spin down is needed because we haven't shot in a while diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 55197ecb89..8bc539cd39 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2257,6 +2257,7 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) } +#if !RETAIL_COMPATIBLE_CRC // TheSuperHackers @bugfix bobtista 21/12/2025 Fix Gatling Cannon barrels rotating despite insufficient energy. // When power is lost (UNDERPOWERED, EMP, SUBDUED, HACKED), immediately force FiringTracker cooldown to stop barrel animations. // getDisabledTypesToProcess() prevents update() from restarting animations, and isUnderpoweredForAttack() prevents cursor/attack logic. @@ -2268,6 +2269,7 @@ void Object::setDisabledUntil( DisabledType type, UnsignedInt frame ) m_firingTracker->forceCoolDown(); } } +#endif // This will only be called if we were NOT disabled before coming into this function. if (edgeCase) {