diff --git a/Generals/Code/GameEngine/Include/GameClient/Drawable.h b/Generals/Code/GameEngine/Include/GameClient/Drawable.h index bbe206ff429..a621d1051a8 100644 --- a/Generals/Code/GameEngine/Include/GameClient/Drawable.h +++ b/Generals/Code/GameEngine/Include/GameClient/Drawable.h @@ -687,7 +687,7 @@ class Drawable : public Thing, FADING_OUT }; FadingMode m_fadeMode; - UnsignedInt m_timeElapsedFade; ///< for how many frames have i been fading + Real m_timeElapsedFade; ///< for how long have i been fading (in 30fps-equivalent frames) UnsignedInt m_timeToFade; ///< how slowly am I fading UnsignedInt m_shroudClearFrame; ///< Last frame the local player saw this drawable "OBJECTSHROUD_CLEAR" diff --git a/Generals/Code/GameEngine/Source/GameClient/Drawable.cpp b/Generals/Code/GameEngine/Source/GameClient/Drawable.cpp index e482166c024..e968fe8a4a4 100644 --- a/Generals/Code/GameEngine/Source/GameClient/Drawable.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/Drawable.cpp @@ -1147,10 +1147,14 @@ void Drawable::updateDrawable() Real numer = (m_fadeMode == FADING_IN) ? (m_timeElapsedFade) : (m_timeToFade-m_timeElapsedFade); setDrawableOpacity(numer/(Real)m_timeToFade); - ++m_timeElapsedFade; + // TheSuperHackers @bugfix bobtista 15/09/2026 Decouple Drawable fade timing from render updates. + m_timeElapsedFade += TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); if (m_timeElapsedFade > m_timeToFade) + { + setDrawableOpacity(m_fadeMode == FADING_IN ? 1.0f : 0.0f); m_fadeMode = FADING_NONE; + } } } @@ -1165,7 +1169,8 @@ void Drawable::updateDrawable() { //LERP (*dm)->setTerrainDecalOpacity(m_decalOpacity); - m_decalOpacity += m_decalOpacityFadeRate; + // TheSuperHackers @bugfix bobtista 15/09/2026 Decouple decal opacity fade timing from render updates. + m_decalOpacity += m_decalOpacityFadeRate * TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); } //--------------- @@ -4845,6 +4850,7 @@ void Drawable::xferDrawableModules( Xfer *xfer ) * 6: Added m_ambientSoundEnabledFromScript flag (Added in Zero Hour) * 7: Save the customize ambient sound info (Added in Zero Hour) * 8: TheSuperHackers @bugfix Removed m_prevTintStatus because loading its value is unnecessary and undesirable + * 9: TheSuperHackers @info Preserve fractional fade progress in non-retail saves */ // ------------------------------------------------------------------------------------------------ void Drawable::xfer( Xfer *xfer ) @@ -4856,7 +4862,7 @@ void Drawable::xfer( Xfer *xfer ) #elif RETAIL_COMPATIBLE_XFER_SAVE const XferVersion currentVersion = 7; #else - const XferVersion currentVersion = 8; + const XferVersion currentVersion = 9; #endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -5030,7 +5036,19 @@ void Drawable::xfer( Xfer *xfer ) xfer->xferUser( &m_fadeMode, sizeof( FadingMode ) ); // time elapsed fade - xfer->xferUnsignedInt( &m_timeElapsedFade ); + if (version >= 9) + { + xfer->xferReal( &m_timeElapsedFade ); + } + else + { + UnsignedInt timeElapsedFadeFrames = static_cast(m_timeElapsedFade); + xfer->xferUnsignedInt( &timeElapsedFadeFrames ); + if (xfer->getXferMode() == XFER_LOAD) + { + m_timeElapsedFade = static_cast(timeElapsedFadeFrames); + } + } // time to fade xfer->xferUnsignedInt( &m_timeToFade ); diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h b/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h index 7169b8cb51f..84c7431dc0f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h @@ -687,7 +687,7 @@ class Drawable : public Thing, FADING_OUT }; FadingMode m_fadeMode; - UnsignedInt m_timeElapsedFade; ///< for how many frames have i been fading + Real m_timeElapsedFade; ///< for how long have i been fading (in 30fps-equivalent frames) UnsignedInt m_timeToFade; ///< how slowly am I fading UnsignedInt m_shroudClearFrame; ///< Last frame the local player saw this drawable "OBJECTSHROUD_CLEAR" diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp index 54dff3325f2..200c4658aec 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp @@ -1149,10 +1149,14 @@ void Drawable::updateDrawable() Real numer = (m_fadeMode == FADING_IN) ? (m_timeElapsedFade) : (m_timeToFade-m_timeElapsedFade); setDrawableOpacity(numer/(Real)m_timeToFade); - ++m_timeElapsedFade; + // TheSuperHackers @bugfix bobtista 15/09/2026 Decouple Drawable fade timing from render updates. + m_timeElapsedFade += TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); if (m_timeElapsedFade > m_timeToFade) + { + setDrawableOpacity(m_fadeMode == FADING_IN ? 1.0f : 0.0f); m_fadeMode = FADING_NONE; + } } } @@ -1167,7 +1171,8 @@ void Drawable::updateDrawable() { //LERP (*dm)->setTerrainDecalOpacity(m_decalOpacity); - m_decalOpacity += m_decalOpacityFadeRate; + // TheSuperHackers @bugfix bobtista 15/09/2026 Decouple decal opacity fade timing from render updates. + m_decalOpacity += m_decalOpacityFadeRate * TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); } //--------------- @@ -4850,6 +4855,7 @@ void Drawable::xferDrawableModules( Xfer *xfer ) * 6: Added m_ambientSoundEnabledFromScript flag (Added in Zero Hour) * 7: Save the customize ambient sound info (Added in Zero Hour) * 8: TheSuperHackers @bugfix Removed m_prevTintStatus because loading its value is unnecessary and undesirable + * 9: TheSuperHackers @info Preserve fractional fade progress in non-retail saves */ // ------------------------------------------------------------------------------------------------ void Drawable::xfer( Xfer *xfer ) @@ -4861,7 +4867,7 @@ void Drawable::xfer( Xfer *xfer ) #elif RETAIL_COMPATIBLE_XFER_SAVE const XferVersion currentVersion = 7; #else - const XferVersion currentVersion = 8; + const XferVersion currentVersion = 9; #endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -5035,7 +5041,19 @@ void Drawable::xfer( Xfer *xfer ) xfer->xferUser( &m_fadeMode, sizeof( FadingMode ) ); // time elapsed fade - xfer->xferUnsignedInt( &m_timeElapsedFade ); + if (version >= 9) + { + xfer->xferReal( &m_timeElapsedFade ); + } + else + { + UnsignedInt timeElapsedFadeFrames = static_cast(m_timeElapsedFade); + xfer->xferUnsignedInt( &timeElapsedFadeFrames ); + if (xfer->getXferMode() == XFER_LOAD) + { + m_timeElapsedFade = static_cast(timeElapsedFadeFrames); + } + } // time to fade xfer->xferUnsignedInt( &m_timeToFade );