From ee19e758b9010f4b03f8f070da7a1d4cf6d37964 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:09:33 +0800 Subject: [PATCH 1/7] Add engineFramerateFixingSetProperty/GetProperty/ResetProperties For adjustable vehicle physics time step and air resistor physics when glitch "vehicle_rapid_stop" is disabled. In this way, DM players can play maps in any FPS. Usage: engineFramerateFixingSetProperty("vehicle_physics", 50.0/30.0) which is the default one. --- .../logic/luadefs/CLuaEngineDefs.cpp | 40 +++++++++++++++++++ .../deathmatch/logic/luadefs/CLuaEngineDefs.h | 4 ++ Client/multiplayer_sa/CMultiplayerSA.h | 6 ++- .../CMultiplayerSA_FrameRateFixes.cpp | 21 ++++++++-- Client/sdk/multiplayer/CMultiplayer.h | 4 ++ 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 1fdc3fe7364..209b1e115d5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -150,6 +150,9 @@ void CLuaEngineDefs::LoadFunctions() {"engineGetPoolUsedCapacity", ArgumentParser}, {"engineSetPoolCapacity", ArgumentParser}, {"enginePreloadWorldArea", ArgumentParser}, + {"engineFramerateFixingSetProperty", ArgumentParser}, + {"engineFramerateFixingGetProperty", ArgumentParser}, + {"engineFramerateFixingResetProperties", ArgumentParser}, // CLuaCFunctions::AddFunction ( "engineReplaceMatchingAtomics", EngineReplaceMatchingAtomics ); // CLuaCFunctions::AddFunction ( "engineReplaceWheelAtomics", EngineReplaceWheelAtomics ); @@ -199,6 +202,11 @@ void CLuaEngineDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setModelTXDID", "engineSetModelTXDID"); lua_classfunction(luaVM, "resetModelTXDID", "engineResetModelTXDID"); + lua_classfunction(luaVM, "framerateFixingSetProperty", "engineFramerateFixingSetProperty"); + lua_classfunction(luaVM, "framerateFixingGetProperty", "engineFramerateFixingGetProperty"); + lua_classfunction(luaVM, "framerateFixingResetProperties", "engineFramerateFixingResetProperties"); + + lua_registerstaticclass(luaVM, "Engine"); // `EngineStreaming` class @@ -2602,3 +2610,35 @@ void CLuaEngineDefs::EnginePreloadWorldArea(CVector position, std::optionalGetStreaming()->LoadSceneCollision(&position); } + + +bool CLuaEngineDefs::EngineFramerateFixingResetProperties() +{ + g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(0); //use default, Should we reset this when player disconnects? + return true; +} + +bool CLuaEngineDefs::EngineFramerateFixingSetProperty(std::string strPropertyName, float timestep) +{ + if (strPropertyName.compare("vehicle_physics") == 0) + { + g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(timestep); + } + else + { + throw std::invalid_argument("Unsupported property name at argument 1"); + } + return true; +} + +float CLuaEngineDefs::EngineFramerateFixingGetProperty(std::string strPropertyName) +{ + if (strPropertyName.compare("vehicle_physics") == 0) + { + return g_pMultiplayer->FramerateFixingGetPhysicsTimeStep(); + } + else + { + throw std::invalid_argument("Unsupported property name at argument 1"); + } +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h index 48fa2706a41..2b0ea2d2187 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h @@ -97,6 +97,10 @@ class CLuaEngineDefs : public CLuaDefs static void EnginePreloadWorldArea(CVector position, std::optional option); + static bool EngineFramerateFixingResetProperties(); + static bool EngineFramerateFixingSetProperty(std::string strPropertyName, float timestep); + static float EngineFramerateFixingGetProperty(std::string strPropertyName); + private: static void AddEngineColClass(lua_State* luaVM); static void AddEngineTxdClass(lua_State* luaVM); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 0aad6ce10d9..a29a2978c37 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -365,6 +365,11 @@ class CMultiplayerSA : public CMultiplayer unsigned int EntryInfoNodePool_NoOfUsedSpaces() const noexcept override; unsigned int PtrNodeDoubleLinkPool_NoOfUsedSpaces() const noexcept override; + //Framerate Fixing Property + void FramerateFixingSetPhysicsTimeStep(float timestep) override; + float FramerateFixingGetPhysicsTimeStep() override; + + CVector m_vecAkimboTarget; bool m_bAkimboTargetUp; static char* ms_PlayerImgCachePtr; @@ -390,7 +395,6 @@ class CMultiplayerSA : public CMultiplayer float m_fShadowsOffset; bool m_isRapidVehicleStopFixEnabled{false}; - /* VOID SetPlayerShotVectors(CPlayerPed* player, Vector3D * vecTarget, Vector3D * vecStart); VOID SetPlayerCameraVectors(CPlayerPed* player, Vector3D * vecSource, Vector3D * vecFront); Vector3D * GetLocalShotOriginVector();*/ diff --git a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp index bf8216ec936..4e4aa9adedc 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp @@ -12,9 +12,12 @@ static bool bWouldBeNewFrame = false; static unsigned int nLastFrameTime = 0; - constexpr float kOriginalTimeStep = 50.0f / 30.0f; +// +static float kPhysicTimeStep = kOriginalTimeStep; + + // Fixes player movement issue while aiming and walking on high FPS. #define HOOKPOS_CTaskSimpleUseGun__SetMoveAnim 0x61E4F2 #define HOOKSIZE_CTaskSimpleUseGun__SetMoveAnim 0x6 @@ -714,7 +717,7 @@ static void __declspec(naked) HOOK_CPhysical__ApplyAirResistance() { fld ds:[0x862CD0] // 0.99000001f fld ds:[0xB7CB5C] // CTimer::ms_fTimeStep - fdiv kOriginalTimeStep // 1.666f + fdiv kPhysicTimeStep // 1.666f mov eax, 0x822130 // powf call eax @@ -742,11 +745,23 @@ static void __declspec(naked) HOOK_VehicleRapidStopFix() { fld ds:[0xC2B9CC] // mod_HandlingManager.m_fWheelFriction fmul ds:[0xB7CB5C] // CTimer::ms_fTimeStep - fdiv kOriginalTimeStep // 1.666f + fdiv kPhysicTimeStep // 1.666f jmp RETURN_VehicleRapidStopFix } } +void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep){ + // Just change time step, will be automatically applied when related hook is installed + // If time step is not set, kOriginalTimeStep will be used as default; + if (timestep == 0) + timestep = kOriginalTimeStep; + kPhysicTimeStep = timestep; +} + +float CMultiplayerSA::FramerateFixingGetPhysicsTimeStep(){ + return kPhysicTimeStep; +} + void CMultiplayerSA::SetRapidVehicleStopFixEnabled(bool enabled) { if (m_isRapidVehicleStopFixEnabled == enabled) diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index e5e591ad5d3..5c33685a85a 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -465,6 +465,10 @@ class CMultiplayer virtual eAnimID GetLastStaticAnimationID() = 0; virtual DWORD GetLastAnimArrayAddress() = 0; + virtual void FramerateFixingSetPhysicsTimeStep(float timestep) = 0; + virtual float FramerateFixingGetPhysicsTimeStep() = 0; + + virtual unsigned int EntryInfoNodePool_NoOfUsedSpaces() const noexcept = 0; virtual unsigned int PtrNodeDoubleLinkPool_NoOfUsedSpaces() const noexcept = 0; }; From ce6a2ab0d0ce556341e3a88bc3f90c619a06c585 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 22:33:54 +0800 Subject: [PATCH 2/7] fix code style --- .../logic/lua/CLuaFunctionParseHelpers.cpp | 4 +++ .../logic/lua/CLuaFunctionParseHelpers.h | 2 ++ .../logic/luadefs/CLuaEngineDefs.cpp | 29 ++++++++----------- .../deathmatch/logic/luadefs/CLuaEngineDefs.h | 6 ++-- Client/multiplayer_sa/CMultiplayerSA.h | 2 +- .../CMultiplayerSA_FrameRateFixes.cpp | 9 ++++-- Client/sdk/multiplayer/CMultiplayer.h | 2 +- Server/mods/deathmatch/logic/CCommon.h | 5 ++++ Shared/sdk/enums/FramerateFixingProperty.h | 17 +++++++++++ 9 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 Shared/sdk/enums/FramerateFixingProperty.h diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 7f7521452c7..0840555f6f5 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -981,6 +981,10 @@ ADD_ENUM(VehicleAudioSettingProperty::VEHICLE_TYPE_FOR_AUDIO, "vehicle-type-for- IMPLEMENT_ENUM_CLASS_END("vehicle-audio-setting") +IMPLEMENT_ENUM_CLASS_BEGIN(eFramerateFixingProperty) +ADD_ENUM(eFramerateFixingProperty::FFP_VEHICLE_PHYSICS, "vehicle_physics") +IMPLEMENT_ENUM_END("framerate-fixing-property") + // // CResource from userdata // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index da35c0d1cc2..0eadfde82a4 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -25,6 +25,7 @@ #include "enums/SoundEffectParams.h" #include "enums/SoundEffectType.h" #include "enums/ObjectGroupPhysicalProperties.h" +#include "enums/FramerateFixingProperty.h" enum eLuaType { @@ -101,6 +102,7 @@ DECLARE_ENUM_CLASS(PreloadAreaOption); DECLARE_ENUM_CLASS(taskType); DECLARE_ENUM(eEntityType); DECLARE_ENUM_CLASS(VehicleAudioSettingProperty); +DECLARE_ENUM_CLASS(eFramerateFixingProperty); class CRemoteCall; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 209b1e115d5..94ea78a44bb 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "CLuaEngineDefs.h" #include @@ -2612,33 +2613,27 @@ void CLuaEngineDefs::EnginePreloadWorldArea(CVector position, std::optionalFramerateFixingSetPhysicsTimeStep(0); //use default, Should we reset this when player disconnects? - return true; } -bool CLuaEngineDefs::EngineFramerateFixingSetProperty(std::string strPropertyName, float timestep) +void CLuaEngineDefs::EngineFramerateFixingSetProperty(eFramerateFixingProperty propertyName, float timestep) { - if (strPropertyName.compare("vehicle_physics") == 0) + switch (propertyName) { - g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(timestep); - } - else - { - throw std::invalid_argument("Unsupported property name at argument 1"); + case eFramerateFixingProperty::FFP_VEHICLE_PHYSICS: + g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(timestep); + break; } - return true; } -float CLuaEngineDefs::EngineFramerateFixingGetProperty(std::string strPropertyName) +std::variant CLuaEngineDefs::EngineFramerateFixingGetProperty(eFramerateFixingProperty propertyName) { - if (strPropertyName.compare("vehicle_physics") == 0) + switch (propertyName) { - return g_pMultiplayer->FramerateFixingGetPhysicsTimeStep(); - } - else - { - throw std::invalid_argument("Unsupported property name at argument 1"); + case eFramerateFixingProperty::FFP_VEHICLE_PHYSICS: + return g_pMultiplayer->FramerateFixingGetPhysicsTimeStep(); } + return false; } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h index 2b0ea2d2187..851c8fdbbd3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h @@ -97,9 +97,9 @@ class CLuaEngineDefs : public CLuaDefs static void EnginePreloadWorldArea(CVector position, std::optional option); - static bool EngineFramerateFixingResetProperties(); - static bool EngineFramerateFixingSetProperty(std::string strPropertyName, float timestep); - static float EngineFramerateFixingGetProperty(std::string strPropertyName); + static void EngineFramerateFixingResetProperties(); + static void EngineFramerateFixingSetProperty(eFramerateFixingProperty propertyName, float timestep); + static std::variant EngineFramerateFixingGetProperty(eFramerateFixingProperty propertyName); private: static void AddEngineColClass(lua_State* luaVM); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index a29a2978c37..f4a5d021886 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -367,7 +367,7 @@ class CMultiplayerSA : public CMultiplayer //Framerate Fixing Property void FramerateFixingSetPhysicsTimeStep(float timestep) override; - float FramerateFixingGetPhysicsTimeStep() override; + float FramerateFixingGetPhysicsTimeStep() const noexcept override; CVector m_vecAkimboTarget; diff --git a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp index 4e4aa9adedc..a9a1e176801 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp @@ -717,7 +717,7 @@ static void __declspec(naked) HOOK_CPhysical__ApplyAirResistance() { fld ds:[0x862CD0] // 0.99000001f fld ds:[0xB7CB5C] // CTimer::ms_fTimeStep - fdiv kPhysicTimeStep // 1.666f + fdiv kPhysicTimeStep // 1.666f mov eax, 0x822130 // powf call eax @@ -750,7 +750,8 @@ static void __declspec(naked) HOOK_VehicleRapidStopFix() } } -void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep){ +void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep) +{ // Just change time step, will be automatically applied when related hook is installed // If time step is not set, kOriginalTimeStep will be used as default; if (timestep == 0) @@ -758,10 +759,12 @@ void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep){ kPhysicTimeStep = timestep; } -float CMultiplayerSA::FramerateFixingGetPhysicsTimeStep(){ +float CMultiplayerSA::FramerateFixingGetPhysicsTimeStep() const noexcept +{ return kPhysicTimeStep; } + void CMultiplayerSA::SetRapidVehicleStopFixEnabled(bool enabled) { if (m_isRapidVehicleStopFixEnabled == enabled) diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 5c33685a85a..4b5258c99d7 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -466,7 +466,7 @@ class CMultiplayer virtual DWORD GetLastAnimArrayAddress() = 0; virtual void FramerateFixingSetPhysicsTimeStep(float timestep) = 0; - virtual float FramerateFixingGetPhysicsTimeStep() = 0; + virtual float FramerateFixingGetPhysicsTimeStep() const noexcept = 0; virtual unsigned int EntryInfoNodePool_NoOfUsedSpaces() const noexcept = 0; diff --git a/Server/mods/deathmatch/logic/CCommon.h b/Server/mods/deathmatch/logic/CCommon.h index 3e884862eec..1f729809dfc 100644 --- a/Server/mods/deathmatch/logic/CCommon.h +++ b/Server/mods/deathmatch/logic/CCommon.h @@ -1068,6 +1068,11 @@ enum eStats STAT_MAYBE_WU_ZI_MEETING = 342 }; +enum class eFramerateFixingProperty +{ + FFP_VEHICLE_PHYSICS = 0 +}; + #include "json.h" // Prettify toJSON (see mantis #9210) enum eJSONPrettyType diff --git a/Shared/sdk/enums/FramerateFixingProperty.h b/Shared/sdk/enums/FramerateFixingProperty.h new file mode 100644 index 00000000000..259705a132d --- /dev/null +++ b/Shared/sdk/enums/FramerateFixingProperty.h @@ -0,0 +1,17 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/FramerateFixingProperty.h + * PURPOSE: Header for common definitions + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +enum class eFramerateFixingProperty +{ + FFP_VEHICLE_PHYSICS +}; From 1048f80de3ba027a133848d5c17ea5ed64a97309 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 23:24:47 +0800 Subject: [PATCH 3/7] fix line format of code --- .../deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp | 4 ++-- .../mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h | 2 +- Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp | 9 ++++----- Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h | 4 ++-- Client/multiplayer_sa/CMultiplayerSA.h | 1 - Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp | 7 ++++--- Server/mods/deathmatch/logic/CCommon.h | 5 ----- Shared/sdk/enums/FramerateFixingProperty.h | 2 +- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 0840555f6f5..c8bcf2a0703 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -981,8 +981,8 @@ ADD_ENUM(VehicleAudioSettingProperty::VEHICLE_TYPE_FOR_AUDIO, "vehicle-type-for- IMPLEMENT_ENUM_CLASS_END("vehicle-audio-setting") -IMPLEMENT_ENUM_CLASS_BEGIN(eFramerateFixingProperty) -ADD_ENUM(eFramerateFixingProperty::FFP_VEHICLE_PHYSICS, "vehicle_physics") +IMPLEMENT_ENUM_CLASS_BEGIN(FramerateFixingProperty) +ADD_ENUM(FramerateFixingProperty::FFP_VEHICLE_PHYSICS, "vehicle_physics") IMPLEMENT_ENUM_END("framerate-fixing-property") // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 0eadfde82a4..403762eb005 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -102,7 +102,7 @@ DECLARE_ENUM_CLASS(PreloadAreaOption); DECLARE_ENUM_CLASS(taskType); DECLARE_ENUM(eEntityType); DECLARE_ENUM_CLASS(VehicleAudioSettingProperty); -DECLARE_ENUM_CLASS(eFramerateFixingProperty); +DECLARE_ENUM_CLASS(FramerateFixingProperty); class CRemoteCall; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 94ea78a44bb..953b3b0c594 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -207,7 +207,6 @@ void CLuaEngineDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "framerateFixingGetProperty", "engineFramerateFixingGetProperty"); lua_classfunction(luaVM, "framerateFixingResetProperties", "engineFramerateFixingResetProperties"); - lua_registerstaticclass(luaVM, "Engine"); // `EngineStreaming` class @@ -2618,21 +2617,21 @@ void CLuaEngineDefs::EngineFramerateFixingResetProperties() g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(0); //use default, Should we reset this when player disconnects? } -void CLuaEngineDefs::EngineFramerateFixingSetProperty(eFramerateFixingProperty propertyName, float timestep) +void CLuaEngineDefs::EngineFramerateFixingSetProperty(FramerateFixingProperty propertyName, float timestep) { switch (propertyName) { - case eFramerateFixingProperty::FFP_VEHICLE_PHYSICS: + case FramerateFixingProperty::FFP_VEHICLE_PHYSICS: g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(timestep); break; } } -std::variant CLuaEngineDefs::EngineFramerateFixingGetProperty(eFramerateFixingProperty propertyName) +std::variant CLuaEngineDefs::EngineFramerateFixingGetProperty(FramerateFixingProperty propertyName) { switch (propertyName) { - case eFramerateFixingProperty::FFP_VEHICLE_PHYSICS: + case FramerateFixingProperty::FFP_VEHICLE_PHYSICS: return g_pMultiplayer->FramerateFixingGetPhysicsTimeStep(); } return false; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h index 851c8fdbbd3..edb7f78ff6d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h @@ -98,8 +98,8 @@ class CLuaEngineDefs : public CLuaDefs static void EnginePreloadWorldArea(CVector position, std::optional option); static void EngineFramerateFixingResetProperties(); - static void EngineFramerateFixingSetProperty(eFramerateFixingProperty propertyName, float timestep); - static std::variant EngineFramerateFixingGetProperty(eFramerateFixingProperty propertyName); + static void EngineFramerateFixingSetProperty(FramerateFixingProperty propertyName, float timestep); + static std::variant EngineFramerateFixingGetProperty(FramerateFixingProperty propertyName); private: static void AddEngineColClass(lua_State* luaVM); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index f4a5d021886..0f64a95ae1d 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -369,7 +369,6 @@ class CMultiplayerSA : public CMultiplayer void FramerateFixingSetPhysicsTimeStep(float timestep) override; float FramerateFixingGetPhysicsTimeStep() const noexcept override; - CVector m_vecAkimboTarget; bool m_bAkimboTargetUp; static char* ms_PlayerImgCachePtr; diff --git a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp index a9a1e176801..d1f946e77c3 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp @@ -12,12 +12,13 @@ static bool bWouldBeNewFrame = false; static unsigned int nLastFrameTime = 0; + +// The global constant timestep for framerate fixing. constexpr float kOriginalTimeStep = 50.0f / 30.0f; -// +// The timestep for vehicle physics framerate fixing is adjustable by script. static float kPhysicTimeStep = kOriginalTimeStep; - // Fixes player movement issue while aiming and walking on high FPS. #define HOOKPOS_CTaskSimpleUseGun__SetMoveAnim 0x61E4F2 #define HOOKSIZE_CTaskSimpleUseGun__SetMoveAnim 0x6 @@ -756,6 +757,7 @@ void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep) // If time step is not set, kOriginalTimeStep will be used as default; if (timestep == 0) timestep = kOriginalTimeStep; + kPhysicTimeStep = timestep; } @@ -764,7 +766,6 @@ float CMultiplayerSA::FramerateFixingGetPhysicsTimeStep() const noexcept return kPhysicTimeStep; } - void CMultiplayerSA::SetRapidVehicleStopFixEnabled(bool enabled) { if (m_isRapidVehicleStopFixEnabled == enabled) diff --git a/Server/mods/deathmatch/logic/CCommon.h b/Server/mods/deathmatch/logic/CCommon.h index 1f729809dfc..3e884862eec 100644 --- a/Server/mods/deathmatch/logic/CCommon.h +++ b/Server/mods/deathmatch/logic/CCommon.h @@ -1068,11 +1068,6 @@ enum eStats STAT_MAYBE_WU_ZI_MEETING = 342 }; -enum class eFramerateFixingProperty -{ - FFP_VEHICLE_PHYSICS = 0 -}; - #include "json.h" // Prettify toJSON (see mantis #9210) enum eJSONPrettyType diff --git a/Shared/sdk/enums/FramerateFixingProperty.h b/Shared/sdk/enums/FramerateFixingProperty.h index 259705a132d..fdb4864243d 100644 --- a/Shared/sdk/enums/FramerateFixingProperty.h +++ b/Shared/sdk/enums/FramerateFixingProperty.h @@ -11,7 +11,7 @@ #pragma once -enum class eFramerateFixingProperty +enum class FramerateFixingProperty { FFP_VEHICLE_PHYSICS }; From b853ae4484d1ba2f34d0a8e9e8221ca3bff91d62 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 23:25:48 +0800 Subject: [PATCH 4/7] Update CLuaEngineDefs.cpp --- Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 953b3b0c594..9e76d5e5fe3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -2611,7 +2611,6 @@ void CLuaEngineDefs::EnginePreloadWorldArea(CVector position, std::optionalGetStreaming()->LoadSceneCollision(&position); } - void CLuaEngineDefs::EngineFramerateFixingResetProperties() { g_pMultiplayer->FramerateFixingSetPhysicsTimeStep(0); //use default, Should we reset this when player disconnects? From f0307eacbf74794b3d4a72537a7f5baec3afc066 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 23:26:47 +0800 Subject: [PATCH 5/7] Update CMultiplayer.h --- Client/sdk/multiplayer/CMultiplayer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 4b5258c99d7..207309e278a 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -468,7 +468,6 @@ class CMultiplayer virtual void FramerateFixingSetPhysicsTimeStep(float timestep) = 0; virtual float FramerateFixingGetPhysicsTimeStep() const noexcept = 0; - virtual unsigned int EntryInfoNodePool_NoOfUsedSpaces() const noexcept = 0; virtual unsigned int PtrNodeDoubleLinkPool_NoOfUsedSpaces() const noexcept = 0; }; From 0935d3961a0d4fe17b239603efce1ca43d02df40 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 23:46:15 +0800 Subject: [PATCH 6/7] implement FramerateFixingResetPhysicsTimeStep instead of using FramerateFixingSetPhysicsTimeStep with "0" --- Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp | 2 +- Client/multiplayer_sa/CMultiplayerSA.h | 1 + Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp | 9 +++++---- Client/sdk/multiplayer/CMultiplayer.h | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 9e76d5e5fe3..9f33fc8f204 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -2613,7 +2613,7 @@ void CLuaEngineDefs::EnginePreloadWorldArea(CVector position, std::optionalFramerateFixingSetPhysicsTimeStep(0); //use default, Should we reset this when player disconnects? + g_pMultiplayer->FramerateFixingResetPhysicsTimeStep(); } void CLuaEngineDefs::EngineFramerateFixingSetProperty(FramerateFixingProperty propertyName, float timestep) diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 0f64a95ae1d..2d6252a565e 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -366,6 +366,7 @@ class CMultiplayerSA : public CMultiplayer unsigned int PtrNodeDoubleLinkPool_NoOfUsedSpaces() const noexcept override; //Framerate Fixing Property + void FramerateFixingResetPhysicsTimeStep() override; void FramerateFixingSetPhysicsTimeStep(float timestep) override; float FramerateFixingGetPhysicsTimeStep() const noexcept override; diff --git a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp index d1f946e77c3..14d6f8e5d95 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_FrameRateFixes.cpp @@ -751,13 +751,14 @@ static void __declspec(naked) HOOK_VehicleRapidStopFix() } } +void CMultiplayerSA::FramerateFixingResetPhysicsTimeStep() +{ + kPhysicTimeStep = kOriginalTimeStep; +} + void CMultiplayerSA::FramerateFixingSetPhysicsTimeStep(float timestep) { // Just change time step, will be automatically applied when related hook is installed - // If time step is not set, kOriginalTimeStep will be used as default; - if (timestep == 0) - timestep = kOriginalTimeStep; - kPhysicTimeStep = timestep; } diff --git a/Client/sdk/multiplayer/CMultiplayer.h b/Client/sdk/multiplayer/CMultiplayer.h index 207309e278a..3e9c7f331a5 100644 --- a/Client/sdk/multiplayer/CMultiplayer.h +++ b/Client/sdk/multiplayer/CMultiplayer.h @@ -465,6 +465,7 @@ class CMultiplayer virtual eAnimID GetLastStaticAnimationID() = 0; virtual DWORD GetLastAnimArrayAddress() = 0; + virtual void FramerateFixingResetPhysicsTimeStep() = 0; virtual void FramerateFixingSetPhysicsTimeStep(float timestep) = 0; virtual float FramerateFixingGetPhysicsTimeStep() const noexcept = 0; From 35063bc423751033b812bf66fd6af5a2132d60e1 Mon Sep 17 00:00:00 2001 From: thisdp <30386052+thisdp@users.noreply.github.com> Date: Fri, 5 Sep 2025 23:46:42 +0800 Subject: [PATCH 7/7] Reset framerate fixing when player join new server --- Client/mods/deathmatch/logic/CClientGame.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 33841956baa..919aa639ff5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3495,6 +3495,9 @@ void CClientGame::Event_OnIngame() g_pGame->GetVehicleAudioSettingsManager()->ResetAudioSettingsData(); + // Reset framerate fixing property + g_pMultiplayer->FramerateFixingResetPhysicsTimeStep(); + // Tell doggy we got the game running WatchDogCompletedSection("L1"); }