From 0194cdfe8e1817606ab2a1133d39b33d5debdf93 Mon Sep 17 00:00:00 2001 From: Forgetest <33988868+jensewe@users.noreply.github.com> Date: Tue, 17 Sep 2024 08:24:46 +0800 Subject: [PATCH] Attempt to fix unexpected stagger directions (#816) * Add files * Update generalfixes.cfg --- .../gamedata/l4d_fix_stagger_dir.txt | 109 ++++++++++++++++++ .../plugins/fixes/l4d_fix_stagger_dir.smx | Bin 0 -> 4278 bytes .../scripting/l4d_fix_stagger_dir.sp | 81 +++++++++++++ cfg/generalfixes.cfg | 1 + 4 files changed, 191 insertions(+) create mode 100644 addons/sourcemod/gamedata/l4d_fix_stagger_dir.txt create mode 100644 addons/sourcemod/plugins/fixes/l4d_fix_stagger_dir.smx create mode 100644 addons/sourcemod/scripting/l4d_fix_stagger_dir.sp diff --git a/addons/sourcemod/gamedata/l4d_fix_stagger_dir.txt b/addons/sourcemod/gamedata/l4d_fix_stagger_dir.txt new file mode 100644 index 000000000..5fdbc695f --- /dev/null +++ b/addons/sourcemod/gamedata/l4d_fix_stagger_dir.txt @@ -0,0 +1,109 @@ +"Games" +{ + "#default" + { + "Functions" + { + "CTerrorPlayer::OnStaggered" + { + "signature" "CTerrorPlayer::OnStaggered" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + "a2" + { + "type" "vectorptr" + } + } + } + } + } + + "left4dead" + { + "Offsets" + { + "CTerrorPlayer::m_PlayerAnimState" + { + "linux" "6024" + "windows" "6004" + } + + "m_flEyeYaw" + { + "linux" "112" + "windows" "116" + } + } + + "Signatures" + { + // Stolen from left4dhooks thanks to Silvers + /* + * CTerrorPlayer::OnStaggered(CBaseEntity *, Vector const) + */ + "CTerrorPlayer::OnStaggered" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer11OnStaggeredEP11CBaseEntityPK6Vector" + "windows" "\x83\x2A\x2A\x2A\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x0F\x85\x2A\x2A\x2A\x2A\x8B\x2A\x8B" + /* 83 ? ? ? 8B ? E8 ? ? ? ? 84 ? 0F 85 ? ? ? ? 8B ? 8B */ + /* Search: "Player.Shoved" */ + } + } + } + + "left4dead2" + { + "Offsets" + { + /* Windows offset: + * + * Search string "PlayerLedgeHangMiddle", which will lead you to "CTerrorPlayerAnimState::HandleActivity_Incapacitated". + * Go to its only xref function, and again, then you are at vtable of "CTerrorPlayerAnimState". + * Double click on the first virtual function "CTerrorPlayerAnimState::ClearAnimationState". + * Go to its function xref 3 times, and you will meet with an enormous constructor function. + * + * 1. Generate pseudocode and you can easily find the offset where the cursor is. + * 2. See the "mov" instruction below the highlighted "call". + */ + + "CTerrorPlayer::m_PlayerAnimState" + { + "linux" "10512" + "windows" "10524" + } + + "m_flEyeYaw" + { + "linux" "228" + "windows" "228" + } + } + + "Signatures" + { + // Stolen from left4dhooks thanks to Silvers + /* + * CTerrorPlayer::OnStaggered(CBaseEntity *, Vector const*) - used by L4D2 on Survivors, causes staggering (e.g. Charger Impact nearby) + * + * - string "PlayerShoved" has 3 refs, the one furthest into a function should be this one. + */ + "CTerrorPlayer::OnStaggered" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer11OnStaggeredEP11CBaseEntityPK6Vector" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x83\x2A\x2A\x56\x57\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x0F\x85\x2A\x2A\x2A\x2A\x8B\x2A\x8B" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 83 ? ? 56 57 8B ? E8 ? ? ? ? 84 ? 0F 85 ? ? ? ? 8B ? 8B + * Using a long local jump as the unique portion (last few bytes of sig) + */ + } + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/plugins/fixes/l4d_fix_stagger_dir.smx b/addons/sourcemod/plugins/fixes/l4d_fix_stagger_dir.smx new file mode 100644 index 0000000000000000000000000000000000000000..662881ea45abe1c9da7ba2ac572f8115856c09c2 GIT binary patch literal 4278 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 literal 0 HcmV?d00001 diff --git a/addons/sourcemod/scripting/l4d_fix_stagger_dir.sp b/addons/sourcemod/scripting/l4d_fix_stagger_dir.sp new file mode 100644 index 000000000..78a3e00b1 --- /dev/null +++ b/addons/sourcemod/scripting/l4d_fix_stagger_dir.sp @@ -0,0 +1,81 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include + +#define PLUGIN_VERSION "1.0" + +public Plugin myinfo = +{ + name = "[L4D & 2] Fix Stagger Direction", + author = "Forgetest", + description = "Fix survivors getting stumbled to the \"opposite\" direction.", + version = PLUGIN_VERSION, + url = "https://github.com/Target5150/MoYu_Server_Stupid_Plugins", +} + +methodmap GameDataWrapper < GameData { + public GameDataWrapper(const char[] file) { + GameData gd = new GameData(file); + if (!gd) SetFailState("Missing gamedata \"%s\"", file); + return view_as(gd); + } + property GameData Super { + public get() { return view_as(this); } + } + public int GetOffset(const char[] key) { + int offset = this.Super.GetOffset(key); + if (offset == -1) SetFailState("Missing offset \"%s\"", key); + return offset; + } + public DynamicDetour CreateDetourOrFail( + const char[] name, + DHookCallback preHook = INVALID_FUNCTION, + DHookCallback postHook = INVALID_FUNCTION) { + DynamicDetour hSetup = DynamicDetour.FromConf(this, name); + if (!hSetup) + SetFailState("Missing detour setup \"%s\"", name); + if (preHook != INVALID_FUNCTION && !hSetup.Enable(Hook_Pre, preHook)) + SetFailState("Failed to pre-detour \"%s\"", name); + if (postHook != INVALID_FUNCTION && !hSetup.Enable(Hook_Post, postHook)) + SetFailState("Failed to post-detour \"%s\"", name); + return hSetup; + } +} + +int g_iOffs_m_PlayerAnimState; +int g_iOffs_m_flEyeYaw; + +methodmap Address {} +methodmap PlayerAnimState < Address { + public static PlayerAnimState FromPlayer(int client) { + return view_as(GetEntData(client, g_iOffs_m_PlayerAnimState)); + } + + property float m_flEyeYaw { + public set(float flAimYaw) { StoreToAddress(this + view_as
(g_iOffs_m_flEyeYaw), flAimYaw, NumberType_Int32); } + } +} + +public void OnPluginStart() +{ + GameDataWrapper gd = new GameDataWrapper("l4d_fix_stagger_dir"); + g_iOffs_m_PlayerAnimState = gd.GetOffset("CTerrorPlayer::m_PlayerAnimState"); + g_iOffs_m_flEyeYaw = gd.GetOffset("m_flEyeYaw"); + + delete gd.CreateDetourOrFail("CTerrorPlayer::OnStaggered", DTR_OnStaggered); + delete gd; +} + +MRESReturn DTR_OnStaggered(int client, DHookParam hParams) +{ + if (IsClientInGame(client) && GetClientTeam(client) == 2) + { + float ang[3]; + GetClientAbsAngles(client, ang); + PlayerAnimState.FromPlayer(client).m_flEyeYaw = ang[1]; + } + + return MRES_Ignored; +} \ No newline at end of file diff --git a/cfg/generalfixes.cfg b/cfg/generalfixes.cfg index a75da925e..3465b1c1d 100644 --- a/cfg/generalfixes.cfg +++ b/cfg/generalfixes.cfg @@ -67,6 +67,7 @@ sm plugins load fixes/l4d2_tank_flying_incap.smx sm plugins load fixes/l4d2_tank_spawn_antirock_protect.smx sm plugins load fixes/l4d_fix_rotated_physblocker.smx sm plugins load fixes/firebulletsfix.smx +sm plugins load fixes/l4d_fix_stagger_dir.smx // Anti-Cheat. sm plugins load anticheat/l4d2_noghostcheat.smx