From 288f24ac50c4b76fc80a86405c3e23ed447619f0 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sat, 21 May 2022 21:39:22 +0200 Subject: [PATCH 1/2] Port rocket patch to sp --- src/game/game.cpp | 23 +++++++---- src/game/game.hpp | 21 +++++++--- src/game/structs.hpp | 75 ++++++++++++++++++++++++++++++---- src/module/command.cpp | 10 ++--- src/module/fov.cpp | 2 +- src/module/player_movement.cpp | 37 +++++++++++++---- src/module/player_movement.hpp | 6 ++- src/module/scheduler.cpp | 6 +-- src/module/test_clients.cpp | 2 +- src/utils/hook.hpp | 12 ++++++ 10 files changed, 153 insertions(+), 41 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index 7056ef1..aced6b6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -17,11 +17,14 @@ namespace game Dvar_RegisterInt_t Dvar_RegisterInt; + Dvar_RegisterString_t Dvar_RegisterString; + Dvar_SetIntByName_t Dvar_SetIntByName; Dvar_SetFromStringByName_t Dvar_SetFromStringByName; G_RunFrame_t G_RunFrame; + G_GetWeaponForName_t G_GetWeaponForName; MSG_ReadData_t MSG_ReadData; @@ -35,6 +38,8 @@ namespace game Scr_Notify_t Scr_Notify; Scr_NotifyLevel_t Scr_NotifyLevel; + Scr_GetNumParam_t Scr_GetNumParam; + Scr_GetString_t Scr_GetString; Sys_ShowConsole_t Sys_ShowConsole; @@ -70,8 +75,6 @@ namespace game CM_TransformedCapsuleTrace_t CM_TransformedCapsuleTrace; - Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire; - PM_playerTrace_t PM_playerTrace; PM_trace_t PM_trace; @@ -126,9 +129,11 @@ namespace game namespace sp { - sp::IsServerRunning_t IsServerRunning; + IsServerRunning_t IsServerRunning; - sp::gentity_s* g_entities; + gentity_s* g_entities; + + gclient_s* g_clients; } void AddRefToValue(VariableValue* value) @@ -712,8 +717,8 @@ namespace game native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020, 0x44F770)); native::Dvar_RegisterBool = native::Dvar_RegisterBool_t(SELECT_VALUE(0x4914D0, 0x5BE9F0, 0x0)); - native::Dvar_RegisterInt = native::Dvar_RegisterInt_t(SELECT_VALUE(0x48CD40, 0x5BEA40, 0x0)); + native::Dvar_RegisterString = native::Dvar_RegisterString_t(SELECT_VALUE(0x5197F0, 0x5BEC90, 0x0)); native::Dvar_SetIntByName = native::Dvar_SetIntByName_t(SELECT_VALUE(0x5396B0, 0x5BF560, 0x0)); @@ -721,6 +726,7 @@ namespace game SELECT_VALUE(0x4DD090, 0x5BF740, 0x518DF0)); native::G_RunFrame = native::G_RunFrame_t(SELECT_VALUE(0x52EAA0, 0x50CB70, 0x48AD60)); + native::G_GetWeaponForName = native::G_GetWeaponForName_t(SELECT_VALUE(0x495E40, 0x531070, 0x0)); native::MSG_ReadData = native::MSG_ReadData_t(SELECT_VALUE(0, 0x5592A0, 0)); @@ -734,6 +740,8 @@ namespace game native::Scr_Notify = native::Scr_Notify_t(SELECT_VALUE(0x4895B0, 0x52B190, 0x0)); native::Scr_NotifyLevel = native::Scr_NotifyLevel_t(SELECT_VALUE(0x445E10, 0x56B6B0, 0x0)); + native::Scr_GetNumParam = native::Scr_GetNumParam_t(SELECT_VALUE(0x4C6FE0, 0x56AA10, 0x0)); + native::Scr_GetString = native::Scr_GetString_t(SELECT_VALUE(0x497530, 0x56A3D0, 0x0)); native::Sys_ShowConsole = native::Sys_ShowConsole_t(SELECT_VALUE(0x470AF0, 0x5CF590, 0)); @@ -775,9 +783,6 @@ namespace game native::CM_TransformedCapsuleTrace = native::CM_TransformedCapsuleTrace_t( SELECT_VALUE(0x4F9B80, 0x541340, 0x0)); - native::Weapon_RocketLauncher_Fire = native::Weapon_RocketLauncher_Fire_t( - SELECT_VALUE(0x48C920, 0x5305D0, 0x0)); - native::PM_playerTrace = native::PM_playerTrace_t(SELECT_VALUE(0x4CE600, 0x421F00, 0x0)); native::PM_trace = native::PM_trace_t(SELECT_VALUE(0x544BF0, 0x41CEB0, 0x0)); @@ -826,6 +831,8 @@ namespace game native::g_entities = reinterpret_cast(SELECT_VALUE(0, 0x1A66E28, 0x191B900)); native::sp::g_entities = reinterpret_cast(0x1197AD8); + native::sp::g_clients = reinterpret_cast(0x1381D48); + native::deferredQueue = reinterpret_cast(SELECT_VALUE(0x0, 0x1D55438, 0x0)); } } diff --git a/src/game/game.hpp b/src/game/game.hpp index 4024db5..67e1c0a 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -31,6 +31,10 @@ namespace game int min, int max, unsigned __int16 flags, const char* description); extern Dvar_RegisterInt_t Dvar_RegisterInt; + typedef const dvar_t* (*Dvar_RegisterString_t)(const char* dvarName, const char* value, + unsigned __int16 flags, const char* description); + extern Dvar_RegisterString_t Dvar_RegisterString; + typedef void (*Dvar_SetIntByName_t)(const char* dvarName, int value); extern Dvar_SetIntByName_t Dvar_SetIntByName; @@ -40,6 +44,9 @@ namespace game typedef int (*G_RunFrame_t)(int, int); extern G_RunFrame_t G_RunFrame; + typedef Weapon (*G_GetWeaponForName_t)(const char* name); + extern G_GetWeaponForName_t G_GetWeaponForName; + typedef void (*MSG_ReadData_t)(msg_t* msg, void* data, int len); extern MSG_ReadData_t MSG_ReadData; @@ -61,6 +68,12 @@ namespace game typedef void (*Scr_NotifyLevel_t)(unsigned int stringValue, unsigned int paramcount); extern Scr_NotifyLevel_t Scr_NotifyLevel; + typedef unsigned int (*Scr_GetNumParam_t)(); + extern Scr_GetNumParam_t Scr_GetNumParam; + + typedef const char* (*Scr_GetString_t)(unsigned int index); + extern Scr_GetString_t Scr_GetString; + typedef void (*Sys_ShowConsole_t)(); extern Sys_ShowConsole_t Sys_ShowConsole; @@ -114,10 +127,6 @@ namespace game const float* origin, const float* angles); extern CM_TransformedCapsuleTrace_t CM_TransformedCapsuleTrace; - typedef gentity_s* (*Weapon_RocketLauncher_Fire_t)(gentity_s* ent, const Weapon weapon, float spread, - weaponParms* wp, const float* gunVel, missileFireParms* fireParms, missileFireParms* magicBullet); - extern Weapon_RocketLauncher_Fire_t Weapon_RocketLauncher_Fire; - typedef void (*PM_playerTrace_t)(pmove_t* pm, trace_t* results, const float* start, const float* end, const Bounds* bounds, int passEntityNum, int contentMask); extern PM_playerTrace_t PM_playerTrace; @@ -194,7 +203,9 @@ namespace game typedef bool (*IsServerRunning_t)(); extern IsServerRunning_t IsServerRunning; - extern sp::gentity_s* g_entities; + extern gentity_s* g_entities; + + extern gclient_s* g_clients; } void AddRefToValue(VariableValue* value); diff --git a/src/game/structs.hpp b/src/game/structs.hpp index e3be37d..45ee4d9 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -758,18 +758,18 @@ namespace game struct Weapon_s { - unsigned int padding : 8; - unsigned int scopeVariation : 3; - unsigned int weaponOthers : 4; - unsigned int weaponUnderBarrels : 2; - unsigned int weaponScopes : 3; unsigned int weaponIdx : 8; unsigned int weaponVariation : 4; + unsigned int weaponScopes : 3; + unsigned int weaponUnderBarrels : 2; + unsigned int weaponOthers : 4; + unsigned int scopeVariation : 3; + unsigned int padding : 8; }; union Weapon { - Weapon_s _s_0; + Weapon_s __s0; unsigned int data; }; @@ -1183,11 +1183,70 @@ namespace game namespace sp { + struct usercmd_s + { + int serverTime; + int buttons; + int angles[3]; + Weapon weapon; + Weapon offHand; + char forwardmove; + char rightmove; + unsigned char upmove; + unsigned char downmove; + char pitchmove; + char yawmove; + float gunPitch; + float gunYaw; + float gunXOfs; + float gunYOfs; + float gunZOfs; + short meleeChargeYaw; + unsigned char meleeChargeDist; + char selectedLoc[2]; + unsigned char selectedLocAngle; + char remoteControlAngles[2]; + }; + + static_assert(sizeof(usercmd_s) == 0x40); + + struct clientPersistent_t + { + usercmd_s cmd; + usercmd_s oldcmd; + int maxHealth; + float moveSpeedScaleMultiplier; + int motionTrackerEnabled; + char playerName[0x20]; + }; + + static_assert(sizeof(clientPersistent_t) == 0xAC); + + struct playerState_s + { + int commandTime; + int pm_type; + int pm_time; + int pm_flags; + int otherFlags; + int linkFlags; + int bobCycle; + float origin[3]; + float velocity[3]; + unsigned char __pad0[0xAD24]; + }; + + static_assert(sizeof(playerState_s) == 0xAD58); + struct gclient_s { - unsigned char __pad0[0xAE04]; + playerState_s ps; + clientPersistent_t pers; int flags; - }; // Warning, incorrect size + unsigned char __pad1[0x2BC]; + }; + + static_assert(sizeof(gclient_s) == 0xB0C4); struct entityState_s { diff --git a/src/module/command.cpp b/src/module/command.cpp index c637b04..43e034d 100644 --- a/src/module/command.cpp +++ b/src/module/command.cpp @@ -233,7 +233,7 @@ __declspec(naked) void command::client_command_dedi_stub() // Between ufo/noclip functions and their mp counterpart is that I reversed the 'CG' type void command::add_sp_commands() { - add("noclip", []() + add("noclip", [] { if (!game::native::sp::IsServerRunning()) return; @@ -251,7 +251,7 @@ void command::add_sp_commands() printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "noclip print", game::native::LOCMSG_SAFE)); }); - add("ufo", []() + add("ufo", [] { if (!game::native::sp::IsServerRunning()) return; @@ -269,7 +269,7 @@ void command::add_sp_commands() printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "ufo print", game::native::LOCMSG_SAFE)); }); - add("god", []() + add("god", [] { if (!game::native::sp::IsServerRunning()) return; @@ -287,7 +287,7 @@ void command::add_sp_commands() printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "god print", game::native::LOCMSG_SAFE)); }); - add("demigod", []() + add("demigod", [] { if (!game::native::sp::IsServerRunning()) return; @@ -305,7 +305,7 @@ void command::add_sp_commands() printf("%s\n", game::native::SEH_LocalizeTextMessage(msg, "demigod print", game::native::LOCMSG_SAFE)); }); - add("notarget", []() + add("notarget", [] { if (!game::native::sp::IsServerRunning()) return; diff --git a/src/module/fov.cpp b/src/module/fov.cpp index 19ae102..5fca813 100644 --- a/src/module/fov.cpp +++ b/src/module/fov.cpp @@ -28,7 +28,7 @@ public: private: static void set_server_command_dvar_stub(const char* dvar, const char* value) { - if (strcmp(dvar, "cg_fov") != 0 || strcmp(value, "65") != 0) + if (strcmp(dvar, "cg_fov") != 0) { game::native::Dvar_SetFromStringByName(dvar, value); } diff --git a/src/module/player_movement.cpp b/src/module/player_movement.cpp index c03c8a9..1235f8f 100644 --- a/src/module/player_movement.cpp +++ b/src/module/player_movement.cpp @@ -67,7 +67,7 @@ int player_movement::stuck_in_client_stub(game::native::gentity_s* self) { if (pm_playerEjection->current.enabled) { - return reinterpret_cast(0x4F8930)(self); + return utils::hook::invoke(0x4F8930, self); } return 0; @@ -84,18 +84,35 @@ void player_movement::cm_transformed_capsule_trace_stub(game::native::trace_t* r } } -game::native::gentity_s* player_movement::weapon_rocket_launcher_fire_stub(game::native::gentity_s* ent, +game::native::gentity_s* player_movement::weapon_rocket_launcher_fire_mp_stub(game::native::gentity_s* ent, const game::native::Weapon weapon, float spread, game::native::weaponParms* wp, const float* gun_vel, game::native::missileFireParms* fire_parms, game::native::missileFireParms* magic_bullet) { - auto* result = game::native::Weapon_RocketLauncher_Fire(ent, weapon, spread, wp, + auto* result = utils::hook::invoke(0x5305D0, ent, weapon, spread, wp, gun_vel, fire_parms, magic_bullet); if (ent->client != nullptr && pm_rocketJump->current.enabled) { - ent->client->ps.velocity[0] += (0 - wp->forward[0]) * 64.0f; - ent->client->ps.velocity[1] += (0 - wp->forward[1]) * 64.0f; - ent->client->ps.velocity[2] += (0 - wp->forward[2]) * 64.0f; + ent->client->ps.velocity[0] += (0.0f - wp->forward[0]) * 64.0f; + ent->client->ps.velocity[1] += (0.0f - wp->forward[1]) * 64.0f; + ent->client->ps.velocity[2] += (0.0f - wp->forward[2]) * 64.0f; + } + + return result; +} + +game::native::sp::gentity_s* player_movement::weapon_rocket_launcher_fire_sp_stub(game::native::sp::gentity_s* ent, + const game::native::Weapon weapon, float spread, game::native::weaponParms* wp, const float* gun_vel, + game::native::missileFireParms* fire_parms, game::native::missileFireParms* magic_bullet) +{ + auto* result = utils::hook::invoke(0x48C920, ent, weapon, spread, wp, + gun_vel, fire_parms, magic_bullet); + + if (ent->client != nullptr && pm_rocketJump->current.enabled) + { + ent->client->ps.velocity[0] += (0.0f - wp->forward[0]) * 64.0f; + ent->client->ps.velocity[1] += (0.0f - wp->forward[1]) * 64.0f; + ent->client->ps.velocity[2] += (0.0f - wp->forward[2]) * 64.0f; } return result; @@ -458,8 +475,6 @@ void player_movement::patch_mp() { pm_playerEjection = game::native::Dvar_RegisterBool("pm_playerEjection", true, game::native::DVAR_CODINFO, "Push intersecting players away from each other"); - pm_rocketJump = game::native::Dvar_RegisterBool("pm_rocketJump", - false, game::native::DVAR_CODINFO, "CoD4 rocket jumps"); // Name is correct, SP registers this dvar in BG_RegisterDvars but still names it just "g_gravity" bg_gravity = game::native::Dvar_RegisterFloat("g_gravity", 800.0f, 1.0f, std::numeric_limits::max(), game::native::DVAR_CODINFO, "Gravity in inches per second per second"); @@ -484,7 +499,7 @@ void player_movement::patch_mp() utils::hook(0x57CF45, cm_transformed_capsule_trace_stub, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity utils::hook(0x482C1B, cm_transformed_capsule_trace_stub, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity - utils::hook(0x530CCB, weapon_rocket_launcher_fire_stub, HOOK_CALL).install()->quick(); // FireWeapon + utils::hook(0x530CCB, weapon_rocket_launcher_fire_mp_stub, HOOK_CALL).install()->quick(); // FireWeapon utils::hook(0x422861, pm_player_trace_stub, HOOK_CALL).install()->quick(); // PM_JitterPoint utils::hook(0x4228B5, pm_player_trace_stub, HOOK_CALL).install()->quick(); // PM_JitterPoint @@ -545,6 +560,8 @@ void player_movement::patch_sp() utils::hook(0x41F9A6, cm_transformed_capsule_trace_stub, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity utils::hook(0x57B14F, cm_transformed_capsule_trace_stub, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity + utils::hook(0x45E606, weapon_rocket_launcher_fire_sp_stub, HOOK_CALL).install()->quick(); // FireWeapon + utils::hook(0x643F84, pm_player_trace_stub, HOOK_CALL).install()->quick(); // PM_JitterPoint utils::hook(0x643FDB, pm_player_trace_stub, HOOK_CALL).install()->quick(); // PM_JitterPoint @@ -582,6 +599,8 @@ void player_movement::register_common_dvars() true, game::native::DVAR_CODINFO, "Push intersecting players away from each other"); pm_elevators = game::native::Dvar_RegisterBool("pm_elevators", false, game::native::DVAR_CODINFO, "CoD4 Elevators"); + pm_rocketJump = game::native::Dvar_RegisterBool("pm_rocketJump", + false, game::native::DVAR_CODINFO, "CoD4 rocket jumps"); // Jump dvars jump_enableFallDamage = game::native::Dvar_RegisterBool("jump_enableFallDamage", diff --git a/src/module/player_movement.hpp b/src/module/player_movement.hpp index 0a00e16..1ec33ce 100644 --- a/src/module/player_movement.hpp +++ b/src/module/player_movement.hpp @@ -58,7 +58,11 @@ private: const float* end, const game::native::Bounds* bounds, const game::native::Bounds* capsule, int contents, const float* origin, const float* angles); - static game::native::gentity_s* weapon_rocket_launcher_fire_stub(game::native::gentity_s* ent, + static game::native::gentity_s* weapon_rocket_launcher_fire_mp_stub(game::native::gentity_s* ent, + const game::native::Weapon weapon, float spread, game::native::weaponParms* wp, + const float* gun_vel, game::native::missileFireParms* fire_parms, game::native::missileFireParms* magic_bullet); + + static game::native::sp::gentity_s* weapon_rocket_launcher_fire_sp_stub(game::native::sp::gentity_s* ent, const game::native::Weapon weapon, float spread, game::native::weaponParms* wp, const float* gun_vel, game::native::missileFireParms* fire_parms, game::native::missileFireParms* magic_bullet); diff --git a/src/module/scheduler.cpp b/src/module/scheduler.cpp index 7c87997..c9256bb 100644 --- a/src/module/scheduler.cpp +++ b/src/module/scheduler.cpp @@ -95,19 +95,19 @@ void scheduler::execute(const pipeline type) void scheduler::r_end_frame_stub() { - reinterpret_cast(SELECT_VALUE(0x4193D0, 0x67F840, 0x0))(); + utils::hook::invoke(SELECT_VALUE(0x4193D0, 0x67F840, 0x0)); execute(pipeline::renderer); } void scheduler::g_glass_update_stub() { - reinterpret_cast(SELECT_VALUE(0x4E3730, 0x505BB0, 0x481EA0))(); + utils::hook::invoke(SELECT_VALUE(0x4E3730, 0x505BB0, 0x481EA0)); execute(pipeline::server); } void scheduler::main_frame_stub() { - reinterpret_cast(SELECT_VALUE(0x458600, 0x556470, 0x4DB070))(); + utils::hook::invoke(SELECT_VALUE(0x458600, 0x556470, 0x4DB070)); execute(pipeline::main); } diff --git a/src/module/test_clients.cpp b/src/module/test_clients.cpp index 9ccae59..5a499b5 100644 --- a/src/module/test_clients.cpp +++ b/src/module/test_clients.cpp @@ -135,7 +135,7 @@ void test_clients::spawn(const int count) void test_clients::scr_shutdown_system_mp_stub(unsigned char sys) { game::native::SV_DropAllBots(); - reinterpret_cast(0x569E30)(sys); + utils::hook::invoke(0x569E30, sys); } __declspec(naked) void test_clients::reset_reliable_mp() diff --git a/src/utils/hook.hpp b/src/utils/hook.hpp index 91f89c0..7b81954 100644 --- a/src/utils/hook.hpp +++ b/src/utils/hook.hpp @@ -164,6 +164,18 @@ namespace utils return set(reinterpret_cast(place), value); } + template + static T invoke(size_t func, Args ... args) + { + return reinterpret_cast(func)(args...); + } + + template + static T invoke(void* func, Args ... args) + { + return static_cast(func)(args...); + } + private: bool initialized_; bool installed_; From 9b32aa94200ef798edd4b0fdfab16f0abceef8ac Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sat, 21 May 2022 21:41:44 +0200 Subject: [PATCH 2/2] Fix format --- src/game/game.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index aced6b6..4d277bc 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -14,13 +14,9 @@ namespace game DB_LoadXAssets_t DB_LoadXAssets; Dvar_RegisterBool_t Dvar_RegisterBool; - Dvar_RegisterInt_t Dvar_RegisterInt; - Dvar_RegisterString_t Dvar_RegisterString; - Dvar_SetIntByName_t Dvar_SetIntByName; - Dvar_SetFromStringByName_t Dvar_SetFromStringByName; G_RunFrame_t G_RunFrame;