From 95357c3286a698c7f3bdf336be99e5fca744ff59 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 3 Jan 2026 21:46:45 -0800 Subject: [PATCH 1/4] Decouple GUI transition and world animation timing from render update --- Core/GameEngine/Include/GameClient/GameWindowTransitions.h | 2 +- .../Source/GameClient/GUI/GameWindowTransitions.cpp | 5 ++++- GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Include/GameClient/GameWindowTransitions.h b/Core/GameEngine/Include/GameClient/GameWindowTransitions.h index a95e4c3603d..5812db830c0 100644 --- a/Core/GameEngine/Include/GameClient/GameWindowTransitions.h +++ b/Core/GameEngine/Include/GameClient/GameWindowTransitions.h @@ -647,7 +647,7 @@ class TransitionGroup typedef std::list TransitionWindowList; TransitionWindowList m_transitionWindowList; Int m_directionMultiplier; - Int m_currentFrame; ///< maintain how long we've spent on this transition; + Real m_currentFrame; ///< maintain how long we've spent on this transition (in 30fps-equivalent frames); AsciiString m_name; }; diff --git a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp index cd2205a44a2..26102e01e79 100644 --- a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp @@ -55,6 +55,7 @@ #include "GameClient/GameWindowTransitions.h" #include "GameClient/GameWindow.h" #include "GameClient/GameWindowManager.h" +#include "Common/FramePacer.h" //----------------------------------------------------------------------------- // DEFINES //////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- @@ -270,7 +271,9 @@ void TransitionGroup::init( void ) void TransitionGroup::update( void ) { - m_currentFrame += m_directionMultiplier; // we go forward or backwards depending. + // TheSuperHackers @tweak GUI transition timing is now decoupled from the render update. + const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + m_currentFrame += m_directionMultiplier * timeScale; // we go forward or backwards depending. TransitionWindowList::iterator it = m_transitionWindowList.begin(); while (it != m_transitionWindowList.end()) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 4cc38ed6569..da258d6fdf1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -5707,8 +5707,12 @@ void InGameUI::updateAndDrawWorldAnimations( void ) } // update the Z value + // TheSuperHackers @tweak World animation Z-rise is now decoupled from the render update. if( wad->m_zRisePerSecond ) - wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND; + { + const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND * timeScale; + } } From cff9563fe8a99fff6af896fd47aa6c074aadae12 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Sat, 3 Jan 2026 21:49:58 -0800 Subject: [PATCH 2/4] Replicate to generals --- Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp index 4a90702f645..b76291bcb37 100644 --- a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -5534,8 +5534,12 @@ void InGameUI::updateAndDrawWorldAnimations( void ) } // update the Z value + // TheSuperHackers @tweak World animation Z-rise is now decoupled from the render update. if( wad->m_zRisePerSecond ) - wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND; + { + const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND * timeScale; + } } From e6cd525736d61a33642ace30557d61462c9c8cdd Mon Sep 17 00:00:00 2001 From: bobtista Date: Tue, 3 Feb 2026 16:23:03 -0600 Subject: [PATCH 3/4] Use getBaseOverUpdateFpsRatio() for frame-rate independent timing in all game states --- .../Source/GameClient/GUI/GameWindowTransitions.cpp | 4 ++-- Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp | 4 ++-- GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp index 26102e01e79..c61400d0f53 100644 --- a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp @@ -271,8 +271,8 @@ void TransitionGroup::init( void ) void TransitionGroup::update( void ) { - // TheSuperHackers @tweak GUI transition timing is now decoupled from the render update. - const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + // TheSuperHackers @tweak bobtista GUI transition timing is now decoupled from the render update. + const Real timeScale = TheFramePacer->getBaseOverUpdateFpsRatio(); m_currentFrame += m_directionMultiplier * timeScale; // we go forward or backwards depending. TransitionWindowList::iterator it = m_transitionWindowList.begin(); while (it != m_transitionWindowList.end()) diff --git a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp index b76291bcb37..242fe4669ff 100644 --- a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -5534,10 +5534,10 @@ void InGameUI::updateAndDrawWorldAnimations( void ) } // update the Z value - // TheSuperHackers @tweak World animation Z-rise is now decoupled from the render update. + // TheSuperHackers @tweak bobtista World animation Z-rise is now decoupled from the render update. if( wad->m_zRisePerSecond ) { - const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + const Real timeScale = TheFramePacer->getBaseOverUpdateFpsRatio(); wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND * timeScale; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index da258d6fdf1..f6a5f052998 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -5707,10 +5707,10 @@ void InGameUI::updateAndDrawWorldAnimations( void ) } // update the Z value - // TheSuperHackers @tweak World animation Z-rise is now decoupled from the render update. + // TheSuperHackers @tweak bobtista World animation Z-rise is now decoupled from the render update. if( wad->m_zRisePerSecond ) { - const Real timeScale = TheFramePacer->getActualLogicTimeScaleOverFpsRatio(); + const Real timeScale = TheFramePacer->getBaseOverUpdateFpsRatio(); wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND * timeScale; } From 901bd6ca42c0abd2f0e630841a287976821142ae Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 24 Mar 2026 12:43:36 -0400 Subject: [PATCH 4/4] style: Use explicit float assignments for m_currentFrame --- .../Source/GameClient/GUI/GameWindowTransitions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp index c61400d0f53..9f6d8caae70 100644 --- a/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp @@ -240,7 +240,7 @@ Int TransitionWindow::getTotalFrames( void ) //----------------------------------------------------------------------------- TransitionGroup::TransitionGroup( void ) { - m_currentFrame = 0; + m_currentFrame = 0.0f; m_fireOnce = FALSE; } @@ -257,7 +257,7 @@ TransitionGroup::~TransitionGroup( void ) void TransitionGroup::init( void ) { - m_currentFrame = 0; + m_currentFrame = 0.0f; m_directionMultiplier = 1; TransitionWindowList::iterator it = m_transitionWindowList.begin(); while (it != m_transitionWindowList.end()) @@ -318,7 +318,7 @@ void TransitionGroup::reverse( void ) tWin->reverse(totalFrames); it++; } - m_currentFrame = totalFrames; + m_currentFrame = (Real)totalFrames; // m_currentFrame ++; }