diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 7b76cb02..fea7625e 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -104,6 +104,7 @@ namespace Components Loader::Register(new Gamepad()); Loader::Register(new Chat()); Loader::Register(new TextRenderer()); + Loader::Register(new Movement()); Loader::Register(new Client()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 2265b729..dd948b09 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -132,6 +132,7 @@ namespace Components #include "Modules/SoundMutexFix.hpp" #include "Modules/Chat.hpp" #include "Modules/TextRenderer.hpp" +#include "Modules/Movement.hpp" #include "Modules/Gamepad.hpp" #include "Modules/Client.hpp" diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp new file mode 100644 index 00000000..f71c9699 --- /dev/null +++ b/src/Components/Modules/Movement.cpp @@ -0,0 +1,161 @@ +#include "STDInclude.hpp" + +namespace Components +{ + Dvar::Var Movement::PlayerDuckedSpeedScale; + Dvar::Var Movement::PlayerLastStandCrawlSpeedScale; + Dvar::Var Movement::PlayerProneSpeedScale; + + int Movement::PMGetEffectiveStance(Game::playerState_s* ps) + { + auto heightTarget = ps->viewHeightTarget; + + 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; + float scale; + + if (playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0xB) + { + scale = move->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) + { + scale = 1.0f; + return scale * 0.15f + (1.0f - scale) * 0.65f; + } + + if (scale != 0.0f) + { + return scale * 0.15f + (1.0f - scale) * 0.65f; + } + } + } + + if ((playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0x28) && + playerState->viewHeightLerpDown == 0) + { + scale = 400.0f / move->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) + { + scale = 1.0f; + } + else if (scale != 0.0f) + { + return scale * 0.65f + (1.0f - scale) * 0.15f; + } + } + } + + scale = 1.0f; + auto stance = Movement::PMGetEffectiveStance(playerState); + + if (stance == Game::PM_EFF_STANCE_PRONE) + { + scale = Movement::PlayerProneSpeedScale.get(); + } + + else if (stance == Game::PM_EFF_STANCE_DUCKED) + { + scale = Movement::PlayerDuckedSpeedScale.get(); + } + + else if (stance == Game::PM_EFF_STANCE_LASTSTANDCRAWL) + { + scale = Movement::PlayerLastStandCrawlSpeedScale.get(); + } + + return scale; + } + + __declspec(naked) void Movement::PMCmdScaleForStanceStub() + { + __asm + { + pushad + + push edx + call Movement::PMCmdScaleForStance + add esp, 4 + + popad + ret + } + } + + Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int, const char* desc) + { + Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register(name, defaultVal, + min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, desc); + + return Movement::PlayerLastStandCrawlSpeedScale.get(); + } + + Movement::Movement() + { + Dvar::OnInit([] + { + Movement::PlayerDuckedSpeedScale = Dvar::Register("player_duckedSpeedScale", + 0.65f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The scale applied to the player speed when ducking"); + + 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"); + }); + + // Hook PM_CmdScaleForStance in PM_CmdScale_Walk + Utils::Hook(0x572F34, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + + //Hook PM_CmdScaleForStance in PM_GetMaxSpeed + Utils::Hook(0x57395F, Movement::PMCmdScaleForStanceStub, 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(); + } + + Movement::~Movement() + { + } +} diff --git a/src/Components/Modules/Movement.hpp b/src/Components/Modules/Movement.hpp new file mode 100644 index 00000000..07ad6894 --- /dev/null +++ b/src/Components/Modules/Movement.hpp @@ -0,0 +1,22 @@ +#pragma once + +namespace Components +{ + class Movement : public Component + { + public: + Movement(); + ~Movement(); + + private: + static Dvar::Var PlayerDuckedSpeedScale; + static Dvar::Var PlayerLastStandCrawlSpeedScale; + static Dvar::Var PlayerProneSpeedScale; + + static int PMGetEffectiveStance(Game::playerState_s* ps); + static float PMCmdScaleForStance(Game::pmove_s* move); + static void PMCmdScaleForStanceStub(); + + static Game::dvar_t* Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int flags, const char* desc); + }; +} diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 7be1e8d7..2d8b443c 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -109,7 +109,7 @@ namespace Game IMG_CATEGORY_WATER = 0x5, IMG_CATEGORY_RENDERTARGET = 0x6, IMG_CATEGORY_TEMP = 0x7, - } ; + }; enum buttons_t { @@ -6876,6 +6876,37 @@ namespace Game const char* args[9]; }; + struct pmove_s + { + playerState_s* ps; + usercmd_s cmd; + usercmd_s oldcmd; + int tracemask; + int numtouch; + int touchents[32]; + char __pad0[24]; + float xyspeed; + int proneChange; + float maxSprintTimeMultiplier; + bool mantleStarted; + float mantleEndPos[3]; + int mantleDuration; + int viewChangeTime; + float viewChange; + float fTorsoPitch; + float fWaistPitch; + unsigned char handler; + }; + + enum EffectiveStance + { + PM_EFF_STANCE_DEFAULT = 0, + PM_EFF_STANCE_PRONE = 1, + PM_EFF_STANCE_DUCKED = 2, + PM_EFF_STANCE_LASTSTANDCRAWL = 3, + PM_EFF_STANCE_COUNT = 4 + }; + #pragma endregion #ifndef IDA