From b3c20b40469516389ccd5237a4023eaba98ba686 Mon Sep 17 00:00:00 2001 From: UncraftedName Date: Fri, 5 Aug 2022 20:50:34 -0700 Subject: [PATCH] Add ivp rng seeding --- spt/features/rng.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++-- spt/features/rng.hpp | 18 +++++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/spt/features/rng.cpp b/spt/features/rng.cpp index 9f6d20351..0c06e0127 100644 --- a/spt/features/rng.cpp +++ b/spt/features/rng.cpp @@ -9,16 +9,34 @@ #include "usercmd.h" #endif +ConVar y_spt_set_ivp_seed_on_load( + "y_spt_set_ivp_seed_on_load", + "", + FCVAR_CHEAT, + "Sets the ivp seed once during the next load, can prevent some physics rng when running a tas.\n"); + RNGStuff spt_rng; namespace patterns { PATTERNS(SetPredictionRandomSeed, "5135", "8B 44 24 ?? 85 C0 75 ?? C7 05 ?? ?? ?? ?? FF FF FF FF"); -} + PATTERNS(ivp_srand, + "5135", + "8B 44 24 04 85 C0 75 05 B8 01 00 00 00 A3 ?? ?? ?? ?? C3", + "7122284", + "55 8B EC 8B 45 08 B9 01 00 00 00 85 C0 0F 44 C1 A3 ?? ?? ?? ?? 5D C3"); + PATTERNS(CBasePlayer__InitVCollision, + "5135", + "57 8B F9 8B 07 8B 90 ?? ?? ?? ?? FF D2 A1 ?? ?? ?? ?? 83 78 30 00", + "7122284", + "55 8B EC 83 EC 34 57 8B F9 8B 07 FF 90 ?? ?? ?? ?? A1 ?? ?? ?? ?? 83 78 30 00"); +} // namespace patterns void RNGStuff::InitHooks() { HOOK_FUNCTION(server, SetPredictionRandomSeed); + HOOK_FUNCTION(server, CBasePlayer__InitVCollision); + FIND_PATTERN(vphysics, ivp_srand); } int RNGStuff::GetPredictionRandomSeed(int commandOffset) @@ -32,7 +50,21 @@ bool RNGStuff::ShouldLoadFeature() return true; } -void RNGStuff::LoadFeature() {} +void RNGStuff::PreHook() +{ + if (ORIG_ivp_srand) + { + uint32_t offs[] = {14, 17}; + int idx = GetPatternIndex((void**)&ORIG_ivp_srand); + IVP_RAND_SEED = *(uint32_t**)((uintptr_t)ORIG_ivp_srand + offs[idx]); + } +} + +void RNGStuff::LoadFeature() +{ + if (ORIG_ivp_srand && ORIG_CBasePlayer__InitVCollision) + InitConcommandBase(y_spt_set_ivp_seed_on_load); +} void RNGStuff::UnloadFeature() {} @@ -46,3 +78,18 @@ void __cdecl RNGStuff::HOOKED_SetPredictionRandomSeed(void* usercmd) spt_rng.ORIG_SetPredictionRandomSeed(usercmd); } + +void __fastcall RNGStuff::HOOKED_CBasePlayer__InitVCollision(void* thisptr, + int edx, + const Vector& vecAbsOrigin, + const Vector& vecAbsVelocity) +{ + spt_rng.ORIG_CBasePlayer__InitVCollision(thisptr, edx, vecAbsOrigin, vecAbsVelocity); + // set the seed before any vphys sim happens, don't use GetInt() since that's casted from a float + if (y_spt_set_ivp_seed_on_load.GetString()[0] != '\0') + { + spt_rng.ORIG_ivp_srand((uint32_t)strtoul(y_spt_set_ivp_seed_on_load.GetString(), nullptr, 10)); + y_spt_set_ivp_seed_on_load.SetValue(""); + } + DevWarning("spt: ivp seed is %u\n", *spt_rng.IVP_RAND_SEED); +} diff --git a/spt/features/rng.hpp b/spt/features/rng.hpp index 2a2cd2b81..0fa09bcdf 100644 --- a/spt/features/rng.hpp +++ b/spt/features/rng.hpp @@ -2,6 +2,11 @@ #include "..\feature.hpp" typedef void(__cdecl* _SetPredictionRandomSeed)(void* usercmd); +typedef void(__cdecl* _ivp_srand)(uint32_t seed); +typedef void(__fastcall* _CBasePlayer__InitVCollision)(void* thisptr, + int edx, + const Vector& vecAbsOrigin, + const Vector& vecAbsVelocity); // RNG prediction class RNGStuff : public FeatureWrapper @@ -10,19 +15,26 @@ class RNGStuff : public FeatureWrapper int GetPredictionRandomSeed(int commandOffset); int commandNumber = 0; + _ivp_srand ORIG_ivp_srand = nullptr; + protected: virtual bool ShouldLoadFeature() override; - virtual void InitHooks() override; - + virtual void PreHook() override; virtual void LoadFeature() override; - virtual void UnloadFeature() override; private: _SetPredictionRandomSeed ORIG_SetPredictionRandomSeed = nullptr; + _CBasePlayer__InitVCollision ORIG_CBasePlayer__InitVCollision = nullptr; static void __cdecl HOOKED_SetPredictionRandomSeed(void* usercmd); + static void __fastcall HOOKED_CBasePlayer__InitVCollision(void* thisptr, + int edx, + const Vector& vecAbsOrigin, + const Vector& vecAbsVelocity); + + uint32_t* IVP_RAND_SEED = nullptr; }; extern RNGStuff spt_rng;