diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index a5ff5504..8f27afb1 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -63,6 +63,7 @@ namespace Components Loader::Register(new QuickPatch()); Loader::Register(new ServerInfo()); Loader::Register(new ServerList()); + Loader::Register(new SlowMotion()); Loader::Register(new StringTable()); Loader::Register(new ZoneBuilder()); Loader::Register(new AssetHandler()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 8d700b9f..faba9e9a 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -76,6 +76,7 @@ namespace Components #include "Modules\QuickPatch.hpp" #include "Modules\ServerInfo.hpp" #include "Modules\ServerList.hpp" +#include "Modules\SlowMotion.hpp" #include "Modules\StringTable.hpp" #include "Modules\ZoneBuilder.hpp" #include "Modules\AssetHandler.hpp" diff --git a/src/Components/Modules/AntiCheat.cpp b/src/Components/Modules/AntiCheat.cpp index 993f51f9..ae81bb12 100644 --- a/src/Components/Modules/AntiCheat.cpp +++ b/src/Components/Modules/AntiCheat.cpp @@ -371,7 +371,7 @@ namespace Components __asm { pushad - push[esp + 20h] + push [esp + 20h] call AntiCheat::AssertCalleeModule diff --git a/src/Components/Modules/Slowmotion.cpp b/src/Components/Modules/Slowmotion.cpp new file mode 100644 index 00000000..240e6a54 --- /dev/null +++ b/src/Components/Modules/Slowmotion.cpp @@ -0,0 +1,85 @@ +#include "STDInclude.hpp" + +namespace Components +{ + int SlowMotion::Delay = 0; + + void SlowMotion::ApplySlowMotion(int timePassed) + { + if (SlowMotion::Delay <= 0) + { + Utils::Hook::Call(0x60B2D0)(timePassed); + } + else + { + SlowMotion::Delay -= timePassed; + } + } + + __declspec(naked) void SlowMotion::ApplySlowMotionStub() + { + __asm + { + pushad + push [esp + 20h] + + call SlowMotion::ApplySlowMotion + + pop ecx + popad + + retn + } + } + + void SlowMotion::SetSlowMotion() + { + int duration = 1000; + float start = Game::Scr_GetFloat(0); + float end = 1.0f; + + if (Game::Scr_GetNumParam() >= 2) + { + end = Game::Scr_GetFloat(1); + } + + if (Game::Scr_GetNumParam() >= 3) + { + duration = static_cast(Game::Scr_GetFloat(2) * 1000.0); + } + + int delay = 0; + + if (start > end) + { + if (duration < 150) + { + delay = duration; + } + else + { + delay = 150; + } + } + + duration = duration - delay; + + Game::Com_SetSlowMotion(start, end, duration); + SlowMotion::Delay = delay; + + // set snapshot num to 1 behind (T6 does this, why shouldn't we?) + for (int i = 0; i < *Game::svs_numclients; i++) + { + Game::svs_clients[i].snapNum = (*reinterpret_cast(0x31D9384)) - 1; + } + } + + SlowMotion::SlowMotion() + { + if (!Dedicated::IsEnabled()) return; + + SlowMotion::Delay = 0; + Utils::Hook(0x5F5FF2, SlowMotion::SetSlowMotion, HOOK_JUMP).Install()->Quick(); + Utils::Hook(0x60B38A, SlowMotion::ApplySlowMotionStub, HOOK_CALL).Install()->Quick(); + } +} diff --git a/src/Components/Modules/Slowmotion.hpp b/src/Components/Modules/Slowmotion.hpp new file mode 100644 index 00000000..f150d4d4 --- /dev/null +++ b/src/Components/Modules/Slowmotion.hpp @@ -0,0 +1,22 @@ +#define BUTTON_FLAG_LEANLEFT 0x40 +#define BUTTON_FLAG_LEANRIGHT 0x80 + +namespace Components +{ + class SlowMotion : public Component + { + public: + SlowMotion(); + +#if defined(DEBUG) || defined(FORCE_UNIT_TESTS) + const char* GetName() { return "SlowMotion"; }; +#endif + + private: + static int Delay; + + static void SetSlowMotion(); + static void ApplySlowMotion(int timePassed); + static void ApplySlowMotionStub(); + }; +} diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 347ba22d..105b331b 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -28,6 +28,7 @@ namespace Game Com_Printf_t Com_Printf = (Com_Printf_t)0x402500; Com_PrintMessage_t Com_PrintMessage = (Com_PrintMessage_t)0x4AA830; Com_ParseExt_t Com_ParseExt = (Com_ParseExt_t)0x474D60; + Com_SetSlowMotion_t Com_SetSlowMotion = (Com_SetSlowMotion_t)0x446E20; Con_DrawMiniConsole_t Con_DrawMiniConsole = (Con_DrawMiniConsole_t)0x464F30; Con_DrawSolidConsole_t Con_DrawSolidConsole = (Con_DrawSolidConsole_t)0x5A5040; @@ -176,6 +177,9 @@ namespace Game Scr_LoadScript_t Scr_LoadScript = (Scr_LoadScript_t)0x45D940; Scr_GetFunctionHandle_t Scr_GetFunctionHandle = (Scr_GetFunctionHandle_t)0x4234F0; + Scr_GetFloat_t Scr_GetFloat = (Scr_GetFloat_t)0x443140; + Scr_GetNumParam_t Scr_GetNumParam = (Scr_GetNumParam_t)0x4B0E90; + Scr_ExecThread_t Scr_ExecThread = (Scr_ExecThread_t)0x4AD0B0; Scr_FreeThread_t Scr_FreeThread = (Scr_FreeThread_t)0x4BD320; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 4ac3219b..fef65f63 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -60,6 +60,9 @@ namespace Game typedef char* (__cdecl * Com_ParseExt_t)(const char **data_p); extern Com_ParseExt_t Com_ParseExt; + typedef void(__cdecl * Com_SetSlowMotion_t)(float start, float end, int duration); + extern Com_SetSlowMotion_t Com_SetSlowMotion; + typedef char* (__cdecl * Con_DrawMiniConsole_t)(int localClientNum, int xPos, int yPos, float alpha); extern Con_DrawMiniConsole_t Con_DrawMiniConsole; @@ -425,6 +428,12 @@ namespace Game typedef int(__cdecl * Scr_LoadScript_t)(const char*); extern Scr_LoadScript_t Scr_LoadScript; + typedef float(__cdecl * Scr_GetFloat_t)(int); + extern Scr_GetFloat_t Scr_GetFloat; + + typedef int(__cdecl * Scr_GetNumParam_t)(void); + extern Scr_GetNumParam_t Scr_GetNumParam; + typedef int(__cdecl * Scr_GetFunctionHandle_t)(const char*, const char*); extern Scr_GetFunctionHandle_t Scr_GetFunctionHandle;