From 46b57882a976a4ebbfb858a361ee0e13474e7dbe Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Wed, 10 Dec 2025 16:37:46 +1100 Subject: [PATCH 1/3] bugfix: Do not show veterancy effects for dead units --- .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 10 ++++++++++ .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index d0f4b52301..27f3cd2e8f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2789,6 +2789,11 @@ Bool Object::hasSpecialPower( SpecialPowerType type ) const //------------------------------------------------------------------------------------------------- void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) { +#if !RETAIL_COMPATIBLE_CRC + if (isEffectivelyDead()) + return; +#endif + updateUpgradeModules(); const UpgradeTemplate* up = TheUpgradeCenter->findVeterancyUpgrade(newLevel); @@ -2843,6 +2848,11 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne && outerDrawable && outerDrawable->isVisible(); +#if RETAIL_COMPATIBLE_CRC + if (isEffectivelyDead()) + return; +#endif + if( doAnimation && TheGameLogic->getDrawIconUI() ) { if( TheAnim2DCollection && TheGlobalData->m_levelGainAnimationName.isEmpty() == FALSE ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 598e266bea..437a5433cd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3104,6 +3104,11 @@ Bool Object::hasAnySpecialPower() const //------------------------------------------------------------------------------------------------- void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) { +#if !RETAIL_COMPATIBLE_CRC + if (isEffectivelyDead()) + return; +#endif + updateUpgradeModules(); const UpgradeTemplate* up = TheUpgradeCenter->findVeterancyUpgrade(newLevel); @@ -3158,6 +3163,11 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne && outerDrawable && outerDrawable->isVisible(); +#if RETAIL_COMPATIBLE_CRC + if (isEffectivelyDead()) + return; +#endif + if( doAnimation && TheGameLogic->getDrawIconUI() ) { if( TheAnim2DCollection && TheGlobalData->m_levelGainAnimationName.isEmpty() == FALSE ) From 220442da8d046b5797ae1e577a273515d303f81b Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Thu, 11 Dec 2025 11:55:37 +1100 Subject: [PATCH 2/3] docs: Add comments --- Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp | 1 + GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 27f3cd2e8f..972b6e7eb7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2790,6 +2790,7 @@ Bool Object::hasSpecialPower( SpecialPowerType type ) const void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) { #if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 10/12/2025 Do not play veterancy animations for dead units. if (isEffectivelyDead()) return; #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 437a5433cd..28e5b8de3f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3105,6 +3105,7 @@ Bool Object::hasAnySpecialPower() const void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback ) { #if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 10/12/2025 Do not play veterancy animations for dead units. if (isEffectivelyDead()) return; #endif From 4227b45b2a821d9cdc107b3cb399a2dcd7483e88 Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Mon, 22 Dec 2025 09:13:10 +1100 Subject: [PATCH 3/3] refactor: Split veterancy effect logic --- Generals/Code/GameEngine/Include/GameLogic/Object.h | 1 + .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 9 +++++++-- GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h | 1 + .../Code/GameEngine/Source/GameLogic/Object/Object.cpp | 9 +++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameLogic/Object.h b/Generals/Code/GameEngine/Include/GameLogic/Object.h index 49617d3fc0..827f06056b 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Object.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Object.h @@ -213,6 +213,7 @@ class Object : public Thing, public Snapshot void scoreTheKill( const Object *victim ); ///< I just killed this object. void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = TRUE ); ///< I just achieved this level right this moment + void createVeterancyLevelFX(VeterancyLevel oldLevel, VeterancyLevel newLevel); ExperienceTracker* getExperienceTracker() {return m_experienceTracker;} const ExperienceTracker* getExperienceTracker() const {return m_experienceTracker;} VeterancyLevel getVeterancyLevel() const; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 972b6e7eb7..86c96bf980 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -2849,12 +2849,18 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne && outerDrawable && outerDrawable->isVisible(); + if (doAnimation) + createVeterancyLevelFX(oldLevel, newLevel); +} + +void Object::createVeterancyLevelFX(VeterancyLevel oldLevel, VeterancyLevel newLevel) +{ #if RETAIL_COMPATIBLE_CRC if (isEffectivelyDead()) return; #endif - if( doAnimation && TheGameLogic->getDrawIconUI() ) + if (TheGameLogic->getDrawIconUI()) { if( TheAnim2DCollection && TheGlobalData->m_levelGainAnimationName.isEmpty() == FALSE ) { @@ -2874,7 +2880,6 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne soundToPlay.setObjectID( getID() ); TheAudio->addAudioEvent( &soundToPlay ); } - } //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h index a2f51fe28b..4bd50049b5 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h @@ -229,6 +229,7 @@ class Object : public Thing, public Snapshot void scoreTheKill( const Object *victim ); ///< I just killed this object. void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = TRUE ); ///< I just achieved this level right this moment + void createVeterancyLevelFX(VeterancyLevel oldLevel, VeterancyLevel newLevel); ExperienceTracker* getExperienceTracker() {return m_experienceTracker;} const ExperienceTracker* getExperienceTracker() const {return m_experienceTracker;} VeterancyLevel getVeterancyLevel() const; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 28e5b8de3f..b9644c0fe3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -3164,12 +3164,18 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne && outerDrawable && outerDrawable->isVisible(); + if (doAnimation) + createVeterancyLevelFX(oldLevel, newLevel); +} + +void Object::createVeterancyLevelFX(VeterancyLevel oldLevel, VeterancyLevel newLevel) +{ #if RETAIL_COMPATIBLE_CRC if (isEffectivelyDead()) return; #endif - if( doAnimation && TheGameLogic->getDrawIconUI() ) + if (TheGameLogic->getDrawIconUI()) { if( TheAnim2DCollection && TheGlobalData->m_levelGainAnimationName.isEmpty() == FALSE ) { @@ -3189,7 +3195,6 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne soundToPlay.setObjectID( getID() ); TheAudio->addAudioEvent( &soundToPlay ); } - } //-------------------------------------------------------------------------------------------------