From 687e3d6e279a0150bf186c86d86ece3602c3389d Mon Sep 17 00:00:00 2001 From: Diavolo Date: Fri, 7 Jan 2022 12:20:43 +0100 Subject: [PATCH] Refactor movement. --- src/Components/Modules/Movement.cpp | 159 +++++++++++++++++++--------- src/Components/Modules/Movement.hpp | 14 ++- src/Game/Functions.cpp | 2 + src/Game/Functions.hpp | 3 + src/Game/Structs.hpp | 26 +++++ 5 files changed, 148 insertions(+), 56 deletions(-) diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp index f71c9699..e3d42e72 100644 --- a/src/Components/Modules/Movement.cpp +++ b/src/Components/Modules/Movement.cpp @@ -5,47 +5,24 @@ namespace Components Dvar::Var Movement::PlayerDuckedSpeedScale; Dvar::Var Movement::PlayerLastStandCrawlSpeedScale; Dvar::Var Movement::PlayerProneSpeedScale; + Dvar::Var Movement::PlayerSpectateSpeedScale; + Dvar::Var Movement::CGUfoScaler; + Dvar::Var Movement::CGNoclipScaler; - int Movement::PMGetEffectiveStance(Game::playerState_s* ps) + float Movement::PM_CmdScaleForStance(const Game::pmove_s* pm) { - auto heightTarget = ps->viewHeightTarget; + assert(pm->ps != nullptr); - if (heightTarget == 0x16) - return Game::PM_EFF_STANCE_LASTSTANDCRAWL; - - if (heightTarget == 0x28) - return Game::PM_EFF_STANCE_DUCKED; - - if (heightTarget == 0xB) - return Game::PM_EFF_STANCE_PRONE; - - return Game::PM_EFF_STANCE_DEFAULT; - } - - float Movement::PMCmdScaleForStance(Game::pmove_s* move) - { - auto* playerState = move->ps; + const auto* playerState = pm->ps; float scale; if (playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0xB) { - scale = move->cmd.serverTime - playerState->viewHeightLerpTime / 400.0f; + scale = pm->cmd.serverTime - playerState->viewHeightLerpTime / 400.0f; if (0.0f <= scale) { - auto flags = 0; - - if (scale < 1.0f) - { - flags |= 1 << 8; - } - - if (scale == 1.0f) - { - flags |= 1 << 14; - } - - if (flags == 0) + if (scale > 1.0f) { scale = 1.0f; return scale * 0.15f + (1.0f - scale) * 0.65f; @@ -61,23 +38,11 @@ namespace Components if ((playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0x28) && playerState->viewHeightLerpDown == 0) { - scale = 400.0f / move->cmd.serverTime - playerState->viewHeightLerpTime; + scale = 400.0f / pm->cmd.serverTime - playerState->viewHeightLerpTime; if (0.0f <= scale) { - auto flags = 0; - - if (scale < 1.0f) - { - flags |= 1 << 8; - } - - if (scale == 1.0f) - { - flags |= 1 << 14; - } - - if (flags == 0) + if (scale > 1.0f) { scale = 1.0f; } @@ -89,7 +54,7 @@ namespace Components } scale = 1.0f; - auto stance = Movement::PMGetEffectiveStance(playerState); + const auto stance = Game::PM_GetEffectiveStance(playerState); if (stance == Game::PM_EFF_STANCE_PRONE) { @@ -109,14 +74,14 @@ namespace Components return scale; } - __declspec(naked) void Movement::PMCmdScaleForStanceStub() + __declspec(naked) void Movement::PM_CmdScaleForStanceStub() { __asm { pushad push edx - call Movement::PMCmdScaleForStance + call Movement::PM_CmdScaleForStance add esp, 4 popad @@ -124,14 +89,88 @@ namespace Components } } - Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int, const char* desc) + float Movement::PM_MoveScale(Game::playerState_s* ps, float forwardmove, + float rightmove, float upmove) { - Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register(name, defaultVal, + assert(ps != nullptr); + + auto max = (std::fabsf(forwardmove) < std::fabsf(rightmove)) + ? std::fabsf(rightmove) + : std::fabsf(forwardmove); + + if (std::fabsf(upmove) > max) + { + max = std::fabsf(upmove); + } + + if (max == 0.0f) + { + return 0.0f; + } + + auto total = std::sqrtf(forwardmove * forwardmove + + rightmove * rightmove + upmove * upmove); + auto scale = (ps->speed * max) / (127.0f * total); + + if (ps->pm_flags & Game::PMF_WALKING || ps->leanf != 0.0f) + { + scale *= 0.4f; + } + + if (ps->pm_type == Game::PM_NOCLIP) + { + return scale * Movement::CGNoclipScaler.get(); + } + + if (ps->pm_type == Game::PM_UFO) + { + return scale * Movement::CGUfoScaler.get(); + } + + if (ps->pm_type == Game::PM_SPECTATOR) + { + return scale * Movement::PlayerSpectateSpeedScale.get(); + } + + return scale; + } + + __declspec(naked) void Movement::PM_MoveScaleStub() + { + __asm + { + pushad + + push [esp + 0xC + 0x20] + push [esp + 0xC + 0x20] + push [esp + 0xC + 0x20] + push esi + call Movement::PM_MoveScale + add esp, 0x10 + + popad + ret + } + } + + Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float value, + float min, float max, int, const char* desc) + { + Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register(name, value, min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, desc); return Movement::PlayerLastStandCrawlSpeedScale.get(); } + Game::dvar_t* Movement::Dvar_RegisterSpectateSpeedScale(const char* name, float value, + float min, float max, int, const char* desc) + { + Movement::PlayerSpectateSpeedScale = Dvar::Register(name, value, + min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, desc); + + return Movement::PlayerSpectateSpeedScale.get(); + } + Movement::Movement() { Dvar::OnInit([] @@ -143,16 +182,32 @@ namespace Components Movement::PlayerProneSpeedScale = Dvar::Register("player_proneSpeedScale", 0.15f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "The scale applied to the player speed when crawling"); + + // 3arch naming convention + Movement::CGUfoScaler = Dvar::Register("cg_ufo_scaler", + 6.0f, 0.001f, 1000.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The speed at which ufo camera moves"); + + Movement::CGNoclipScaler = Dvar::Register("cg_noclip_scaler", + 3.0f, 0.001f, 1000.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The speed at which noclip camera moves"); }); // Hook PM_CmdScaleForStance in PM_CmdScale_Walk - Utils::Hook(0x572F34, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x572F34, Movement::PM_CmdScaleForStanceStub, HOOK_CALL).install()->quick(); //Hook PM_CmdScaleForStance in PM_GetMaxSpeed - Utils::Hook(0x57395F, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x57395F, Movement::PM_CmdScaleForStanceStub, HOOK_CALL).install()->quick(); // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. Utils::Hook(0x448B66, Movement::Dvar_RegisterLastStandSpeedScale, HOOK_CALL).install()->quick(); + + // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. + Utils::Hook(0x448990, Movement::Dvar_RegisterSpectateSpeedScale, HOOK_CALL).install()->quick(); + + // Hook PM_MoveScale so we can add custom speed scale for Ufo and Noclip + Utils::Hook(0x56F845, Movement::PM_MoveScaleStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x56FABD, Movement::PM_MoveScaleStub, HOOK_CALL).install()->quick(); } Movement::~Movement() diff --git a/src/Components/Modules/Movement.hpp b/src/Components/Modules/Movement.hpp index 07ad6894..09678e37 100644 --- a/src/Components/Modules/Movement.hpp +++ b/src/Components/Modules/Movement.hpp @@ -12,11 +12,17 @@ namespace Components static Dvar::Var PlayerDuckedSpeedScale; static Dvar::Var PlayerLastStandCrawlSpeedScale; static Dvar::Var PlayerProneSpeedScale; + static Dvar::Var PlayerSpectateSpeedScale; + static Dvar::Var CGUfoScaler; + static Dvar::Var CGNoclipScaler; - static int PMGetEffectiveStance(Game::playerState_s* ps); - static float PMCmdScaleForStance(Game::pmove_s* move); - static void PMCmdScaleForStanceStub(); + static float PM_CmdScaleForStance(const Game::pmove_s* move); + static void PM_CmdScaleForStanceStub(); - static Game::dvar_t* Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int flags, const char* desc); + static float PM_MoveScale(Game::playerState_s* ps, float forwardmove, float rightmove, float upmove); + static void PM_MoveScaleStub(); + + static Game::dvar_t* Dvar_RegisterLastStandSpeedScale(const char* name, float value, float min, float max, int flags, const char* desc); + static Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* name, float value, float min, float max, int flags, const char* desc); }; } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index b09916fe..98bf9ce8 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -381,6 +381,8 @@ namespace Game PM_playerTrace_t PM_playerTrace = PM_playerTrace_t(0x458980); PM_Trace_t PM_Trace = PM_Trace_t(0x441F60); + PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540); + XAssetHeader* DB_XAssetPool = reinterpret_cast(0x7998A8); unsigned int* g_poolSize = reinterpret_cast(0x7995E8); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 9e7b7132..11db1c96 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -903,6 +903,9 @@ namespace Game typedef void(__cdecl * PM_Trace_t)(pmove_s*, trace_t*, const float*, const float*, const Bounds*, int, int); extern PM_Trace_t PM_Trace; + typedef EffectiveStance(__cdecl* PM_GetEffectiveStance_t)(const playerState_s* ps); + extern PM_GetEffectiveStance_t PM_GetEffectiveStance; + extern XAssetHeader* DB_XAssetPool; extern unsigned int* g_poolSize; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index bad13871..f76aafaa 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1096,6 +1096,32 @@ namespace Game hudelem_s archival[31]; }; + enum playerStateFlag + { + PMF_PRONE = 0x1, + PMF_DUCKED = 0x2, + PMF_MANTLE = 0x4, + PMF_LADDER = 0x8, + PMF_SIGHT_AIMING = 0x10, + PMF_BACKWARDS_RUN = 0x20, + PMF_WALKING = 0x40, + PMF_TIME_HARDLANDING = 0x80, + PMF_TIME_KNOCKBACK = 0x100, + PMF_PRONEMOVE_OVERRIDDEN = 0x200, + PMF_RESPAWNED = 0x400, + PMF_FROZEN = 0x800, + PMF_LADDER_FALL = 0x1000, + PMF_JUMPING = 0x2000, + PMF_SPRINTING = 0x4000, + PMF_SHELLSHOCKED = 0x8000, + PMF_MELEE_CHARGE = 0x10000, + PMF_NO_SPRINT = 0x20000, + PMF_NO_JUMP = 0x40000, + PMF_REMOTE_CONTROLLING = 0x80000, + PMF_ANIM_SCRIPTED = 0x100000, + PMF_DIVING = 0x400000 + }; + enum pmtype_t { PM_NORMAL = 0x0,