diff --git a/src/game/game.cpp b/src/game/game.cpp index 9528bef..c091956 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -71,6 +71,8 @@ namespace game PM_trace_t PM_trace; + Jump_ClearState_t Jump_ClearState; + Vec3Normalize_t Vec3Normalize; Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand; @@ -686,6 +688,8 @@ namespace game native::PM_trace = native::PM_trace_t(SELECT_VALUE(0x544BF0, 0x41CEB0, 0x0)); + native::Jump_ClearState = native::Jump_ClearState_t(SELECT_VALUE(0x514CE0, 0x4160F0, 0x0)); + native::Vec3Normalize = native::Vec3Normalize_t(SELECT_VALUE(0x536A20, 0x415EE0, 0x0)); native::Cmd_ExecuteSingleCommand = native::Cmd_ExecuteSingleCommand_t( diff --git a/src/game/game.hpp b/src/game/game.hpp index 4850157..d77c438 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -117,6 +117,9 @@ namespace game const Bounds* bounds, int passEntityNum, int contentMask); extern PM_trace_t PM_trace; + typedef void (*Jump_ClearState_t)(playerState_s* ps); + extern Jump_ClearState_t Jump_ClearState; + typedef void (*Vec3Normalize_t)(float* v); extern Vec3Normalize_t Vec3Normalize; @@ -154,6 +157,13 @@ namespace game constexpr auto ENTITYNUM_NONE = MAX_GENTITIES - 1u; extern gentity_s* g_entities; + // PM Global Definitions & Functions + constexpr auto JUMP_LAND_SLOWDOWN_TIME = 1800; + + // From Quake III, to match game's assembly + template + constexpr auto VectorScale(T v, R s, T out) { out[0] = v[0] * s; out[1] = v[1] * s; out[2] = v[2] * s; } + namespace mp { extern client_t* svs_clients; diff --git a/src/game/structs.hpp b/src/game/structs.hpp index 922d7af..d72ca9d 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -784,7 +784,8 @@ namespace game int groundEntityNum; float vLadderVec[3]; int jumpTime; - unsigned char __pad0[0x474]; + float jumpOriginZ; + unsigned char __pad0[0x470]; unsigned int perks[0x2]; unsigned int perkSlots[0x9]; unsigned char __pad1[0x2DE8]; diff --git a/src/module/player_movement.cpp b/src/module/player_movement.cpp index 32afca9..c26e563 100644 --- a/src/module/player_movement.cpp +++ b/src/module/player_movement.cpp @@ -6,6 +6,7 @@ #include "player_movement.hpp" const game::native::dvar_t* player_movement::player_sustainAmmo; +const game::native::dvar_t* player_movement::jump_slowdownEnable; const game::native::dvar_t* player_movement::jump_ladderPushVel; const game::native::dvar_t* player_movement::jump_height; const game::native::dvar_t* player_movement::pm_bounces; @@ -14,6 +15,10 @@ const game::native::dvar_t* player_movement::pm_playerCollision; const game::native::dvar_t* player_movement::pm_rocketJump; const game::native::dvar_t* player_movement::pm_elevators; +DWORD player_movement::bounce_addr; +DWORD player_movement::dont_bounce_addr; +DWORD player_movement::push_off_ladder_addr; + void player_movement::pm_weapon_use_ammo(game::native::playerState_s* ps, const game::native::Weapon weapon, bool is_alternate, int amount, game::native::PlayerHandIndex hand) { @@ -23,8 +28,6 @@ void player_movement::pm_weapon_use_ammo(game::native::playerState_s* ps, const } } -static DWORD bounce_addr = SELECT_VALUE(0x43D91F, 0x424D58, 0x0); -static DWORD dont_bounce_addr = SELECT_VALUE(0x43D933, 0x424D6C, 0x0); __declspec(naked) void player_movement::pm_step_slide_move_stub() { __asm @@ -109,7 +112,6 @@ void player_movement::pm_trace_stub(const game::native::pmove_t* pm, game::nativ } } -static DWORD push_off_ladder_addr = SELECT_VALUE(0x63EA4C, 0x41686C, 0x0); __declspec(naked) void player_movement::jump_push_off_ladder_stub() { __asm @@ -123,7 +125,6 @@ __declspec(naked) void player_movement::jump_push_off_ladder_stub() } } -static DWORD jump_start_addr = 0x41696F; void player_movement::jump_start_stub() { __asm @@ -133,7 +134,45 @@ void player_movement::jump_start_stub() fld dword ptr [eax + 0xC] pop eax - jmp jump_start_addr + push 0x41696F + retn + } +} + +void player_movement::jump_apply_slowdown_stub(game::native::playerState_s* ps) +{ + assert(ps->pm_flags & game::native::PMF_JUMPING); + + auto scale = 1.0f; + + if (ps->pm_time <= game::native::JUMP_LAND_SLOWDOWN_TIME) + { + if (ps->pm_time == 0) + { + const auto height = ps->jumpOriginZ + 18.0f; + + if (height <= ps->origin[2]) + { + scale = 0.5f; + ps->pm_time = 1200; + } + else + { + scale = 0.65f; + ps->pm_time = game::native::JUMP_LAND_SLOWDOWN_TIME; + } + } + } + else + { + game::native::Jump_ClearState(ps); + scale = 0.65f; + } + + if ((ps->pm_flags & game::native::PMF_DIVING) == 0 + && player_movement::jump_slowdownEnable->current.enabled) + { + game::native::VectorScale(ps->velocity, scale, ps->velocity); } } @@ -155,6 +194,15 @@ const game::native::dvar_t* player_movement::dvar_register_jump_ladder_push_vel( return player_movement::jump_ladderPushVel; } +const game::native::dvar_t* player_movement::dvar_register_jump_slowdown_enable(const char* dvar_name, + bool value, unsigned __int16 /*flags*/, const char* description) +{ + player_movement::jump_slowdownEnable = game::native::Dvar_RegisterBool(dvar_name, + value, game::native::DVAR_CODINFO, description); + + return player_movement::jump_slowdownEnable; +} + const game::native::dvar_t* player_movement::dvar_register_jump_height(const char* dvar_name, float value, float min, float max, unsigned __int16 /*flags*/, const char* description) { @@ -171,9 +219,11 @@ void player_movement::patch_mp() player_movement::pm_rocketJump = game::native::Dvar_RegisterBool("pm_rocketJump", false, game::native::DVAR_CODINFO, "CoD4 rocket jumps"); + // Un-Cheat the dvars utils::hook(0x418D9C, &player_movement::dvar_register_player_sustain_ammo, HOOK_CALL).install()->quick(); utils::hook(0x4160A7, &player_movement::dvar_register_jump_ladder_push_vel, HOOK_CALL).install()->quick(); utils::hook(0x41602B, &player_movement::dvar_register_jump_height, HOOK_CALL).install()->quick(); + utils::hook(0x416074, &player_movement::dvar_register_jump_slowdown_enable, HOOK_CALL).install()->quick(); utils::hook(0x42B5DA, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick(); utils::hook(0x42B2BD, &player_movement::pm_weapon_use_ammo, HOOK_CALL).install()->quick(); @@ -199,6 +249,8 @@ void player_movement::patch_mp() utils::hook(0x416969, &player_movement::jump_start_stub, HOOK_JUMP).install()->quick(); // Jump_Check utils::hook::nop(0x41696E, 1); // Nop skipped opcode + + utils::hook(0x4225CA, &player_movement::jump_apply_slowdown_stub, HOOK_CALL).install()->quick(); // PM_WalkMove } void player_movement::patch_sp() @@ -238,6 +290,10 @@ void player_movement::post_load() return; } + player_movement::bounce_addr = SELECT_VALUE(0x43D91F, 0x424D58, 0x0); + player_movement::dont_bounce_addr = SELECT_VALUE(0x43D933, 0x424D6C, 0x0); + player_movement::push_off_ladder_addr = SELECT_VALUE(0x63EA4C, 0x41686C, 0x0); + player_movement::pm_bounces = game::native::Dvar_RegisterBool("pm_bounces", false, game::native::dvar_flags::DVAR_CODINFO, "CoD4 Bounces"); player_movement::pm_playerCollision = game::native::Dvar_RegisterBool("pm_playerCollision", diff --git a/src/module/player_movement.hpp b/src/module/player_movement.hpp index cecd46e..afe2241 100644 --- a/src/module/player_movement.hpp +++ b/src/module/player_movement.hpp @@ -8,6 +8,7 @@ public: private: static const game::native::dvar_t* player_sustainAmmo; + static const game::native::dvar_t* jump_slowdownEnable; static const game::native::dvar_t* jump_ladderPushVel; static const game::native::dvar_t* jump_height; static const game::native::dvar_t* pm_bounces; @@ -16,6 +17,10 @@ private: static const game::native::dvar_t* pm_rocketJump; static const game::native::dvar_t* pm_elevators; + static DWORD bounce_addr; + static DWORD dont_bounce_addr; + static DWORD push_off_ladder_addr; + static void pm_weapon_use_ammo(game::native::playerState_s* ps, const game::native::Weapon weapon, bool is_alternate, int amount, game::native::PlayerHandIndex hand); @@ -23,6 +28,8 @@ private: float value, float min, float max, unsigned __int16 flags, const char* description); static const game::native::dvar_t* dvar_register_jump_height(const char* dvar_name, float value, float min, float max, unsigned __int16 flags, const char* description); + static const game::native::dvar_t* dvar_register_jump_slowdown_enable(const char* dvar_name, + bool value, unsigned __int16 flags, const char* description); static const game::native::dvar_t* dvar_register_player_sustain_ammo(const char* dvar_name, bool value, unsigned __int16 flags, const char* description); @@ -48,6 +55,8 @@ private: // On SP this is already unlocked static void jump_start_stub(); + static void jump_apply_slowdown_stub(game::native::playerState_s* ps); + static void patch_mp(); static void patch_sp(); };