Skip to content

Commit 59d75ab

Browse files
authored
Merge pull request #144 from SirPlease/master
[pull] master from SirPlease:master
2 parents 29db2e9 + f8df6a1 commit 59d75ab

4 files changed

Lines changed: 378 additions & 0 deletions

File tree

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
"Games"
2+
{
3+
"#default"
4+
{
5+
"Functions"
6+
{
7+
"CBaseAbility::UpdateAbility"
8+
{
9+
"offset" "CBaseAbility::UpdateAbility"
10+
"hooktype" "entity"
11+
"return" "void"
12+
"this" "entity"
13+
}
14+
15+
"CBaseEntity::PhysicsSolidMaskForEntity"
16+
{
17+
"offset" "CBaseEntity::PhysicsSolidMaskForEntity"
18+
"hooktype" "entity"
19+
"return" "int"
20+
"this" "ignore"
21+
}
22+
}
23+
}
24+
25+
"left4dead"
26+
{
27+
"MemPatches"
28+
{
29+
"ShouldHitEntity_MyInfectedPointer"
30+
{
31+
"signature" "CTraceFilterSimpleListNoInfectedOrGhosts_ShouldHitEntity"
32+
"linux"
33+
{
34+
"offset" "101"
35+
36+
/*
37+
* 8B 06 mov eax, [esi]
38+
* 89 34 24 mov [esp+2Ch+var_2C], esi ; IHandleEntity *
39+
*
40+
* OUR_PATCH:
41+
* FF 90 24 01 00 00 call dword ptr [eax+124h] ; CBaseEntity::MyInfectedPointer(void)
42+
* 85 C0 test eax, eax
43+
* 8B 54 24 0C mov edx, [esp+2Ch+var_20]
44+
* 75 CB jnz short loc_2A614C ; return 0 (no collision)
45+
*/
46+
"verify" "\xFF\x90\x2A\x2A\x2A\x2A\x85\xC0\x2A\x2A\x2A\x2A\x75"
47+
48+
"preserve" "\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x00"
49+
50+
/*
51+
* E8 ? ? ? ? call CBaseEntity::GetTeamNumber(void)
52+
* 83 F8 03 cmp eax, 3
53+
* 8B 54 24 0C mov edx, [esp+2Ch+var_20]
54+
* 74 CB jz short loc_2A614C ; return 0 (no collision)
55+
*/
56+
"patch" "\xE8\x00\x00\x00\x00\x83\xF8\x03\x90\x90\x90\x90\x74"
57+
}
58+
"windows"
59+
{
60+
"offset" "46"
61+
62+
/*
63+
* 8B 06 mov eax, [esi] ; IHandleEntity *
64+
* 8B 90 20 01 00 00 mov edx, [eax+120h] ; CBaseEntity::MyInfectedPointer(void)
65+
* 8B CE mov ecx, esi
66+
* FF D2 call edx
67+
* 85 C0 test eax, eax
68+
* 75 0F jnz short loc_102CCC1D
69+
*/
70+
"verify" "\x8B\x06\x8B\x2A\x2A\x2A\x2A\x2A\x8B\xCE\xFF\x2A\x85\xC0\x75"
71+
72+
/*
73+
* EB 02 jmp short OUR_PATCH
74+
* 66 90 NOP
75+
*
76+
* OUR_PATCH:
77+
* 8B CE mov ecx, esi ; IHandleEntity *
78+
* E8 ? ? ? ? call sub_1003FA90 ; CBaseEntity::GetTeamNumber(void)
79+
* 83 F8 03 cmp eax, 3
80+
* 74 0F jz short loc_102CCC1D
81+
*/
82+
"patch" "\xEB\x02\x66\x90\x8B\xCE\xE8\x00\x00\x00\x00\x83\xF8\x03\x74"
83+
}
84+
}
85+
86+
"OnVomitCollide__TraceRayMask_patch"
87+
{
88+
"signature" "OnVomitCollide"
89+
"linux"
90+
{
91+
"offset" "16Eh"
92+
"verify" "\x0B\x40\x00\x46"
93+
"patch" "\x03\x40\x00\x46"
94+
}
95+
"windows"
96+
{
97+
"offset" "5Ch"
98+
"verify" "\x0B\x40\x00\x46"
99+
"patch" "\x03\x40\x00\x46"
100+
}
101+
}
102+
103+
"OnVomitCollide__ClipRayMask_patch"
104+
{
105+
"signature" "OnVomitCollide"
106+
"linux"
107+
{
108+
"offset" "252h"
109+
"verify" "\x0B\x40\x00\x46"
110+
"patch" "\x03\x40\x00\x46"
111+
}
112+
"windows"
113+
{
114+
"offset" "F1h"
115+
"verify" "\x0B\x40\x00\x46"
116+
"patch" "\x03\x40\x00\x46"
117+
}
118+
}
119+
}
120+
121+
"Offsets"
122+
{
123+
"CBaseAbility::UpdateAbility"
124+
{
125+
"linux" "190"
126+
"windows" "189"
127+
}
128+
129+
"PatchOffset"
130+
{
131+
"linux" "1"
132+
"windows" "7"
133+
}
134+
135+
"CBaseEntity::PhysicsSolidMaskForEntity"
136+
{
137+
"linux" "164"
138+
"windows" "163"
139+
}
140+
}
141+
142+
"Addresses"
143+
{
144+
"CBaseEntity_GetTeamNumber"
145+
{
146+
"linux"
147+
{
148+
"signature" "CBaseEntity_GetTeamNumber"
149+
}
150+
"windows"
151+
{
152+
"signature" "CBaseEntity_GetTeamNumber"
153+
}
154+
}
155+
}
156+
157+
"Signatures"
158+
{
159+
"CTraceFilterSimpleListNoInfectedOrGhosts_ShouldHitEntity"
160+
{
161+
"library" "server"
162+
"linux" "@_ZN40CTraceFilterSimpleListNoInfectedOrGhosts15ShouldHitEntityEP13IHandleEntityi"
163+
"windows" "\x53\x8B\x2A\x2A\x2A\x56\x8B\x2A\x2A\x2A\x57\x53\x56\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x84\x2A\x74"
164+
/* 53 8B ? ? ? 56 8B ? ? ? 57 53 56 8B ? E8 ? ? ? ? 84 ? 74 */
165+
}
166+
167+
"CBaseEntity_GetTeamNumber"
168+
{
169+
"library" "server"
170+
"linux" "@_ZNK11CBaseEntity13GetTeamNumberEv"
171+
"windows" "\x8B\x81\xEC\x01\x00\x00\xC3"
172+
/* 8B 81 EC 01 00 00 C3 */
173+
}
174+
175+
"OnVomitCollide"
176+
{
177+
"library" "server"
178+
"linux" "@_Z14OnVomitCollideP13CTerrorPlayerP11CBaseEntityS2_i6VectorS3_"
179+
"windows" "\x81\xEC\x2A\x2A\x2A\x2A\x8B\x84\x24\x2A\x2A\x2A\x2A\x8B\x8C\x24\x2A\x2A\x2A\x2A\x8B\x94\x24"
180+
/* 81 EC ? ? ? ? 8B 84 24 ? ? ? ? 8B 8C 24 ? ? ? ? 8B 94 24 */
181+
}
182+
}
183+
}
184+
185+
"left4dead2"
186+
{
187+
"Offsets"
188+
{
189+
"CBaseEntity::PhysicsSolidMaskForEntity"
190+
{
191+
"linux" "178"
192+
"windows" "177"
193+
}
194+
}
195+
}
196+
}
5.64 KB
Binary file not shown.
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#pragma semicolon 1
2+
#pragma newdecls required
3+
4+
#include <sourcemod>
5+
#include <sdkhooks>
6+
#include <dhooks>
7+
#include <sourcescramble>
8+
9+
#define PLUGIN_VERSION "2.5"
10+
11+
public Plugin myinfo =
12+
{
13+
name = "[L4D & 2] Vomit Trace Patch",
14+
author = "Forgetest",
15+
description = "Fix vomit stuck on Infected teammates & allow stricter collision test.",
16+
version = PLUGIN_VERSION,
17+
url = "https://github.com/Target5150/MoYu_Server_Stupid_Plugins"
18+
}
19+
20+
methodmap GameDataWrapper < GameData {
21+
public GameDataWrapper(const char[] file) {
22+
GameData gd = new GameData(file);
23+
if (!gd) SetFailState("Missing gamedata \"%s\"", file);
24+
return view_as<GameDataWrapper>(gd);
25+
}
26+
property GameData Super {
27+
public get() { return view_as<GameData>(this); }
28+
}
29+
public int GetOffset(const char[] key) {
30+
int offset = this.Super.GetOffset(key);
31+
if (offset == -1) SetFailState("Missing offset \"%s\"", key);
32+
return offset;
33+
}
34+
public Address GetAddress(const char[] key) {
35+
Address ptr = this.Super.GetAddress(key);
36+
if (ptr == Address_Null) SetFailState("Missing address \"%s\"", key);
37+
return ptr;
38+
}
39+
public MemoryPatch CreatePatchOrFail(const char[] name, bool enable = false) {
40+
MemoryPatch hPatch = MemoryPatch.CreateFromConf(this, name);
41+
if (!(enable ? hPatch.Enable() : hPatch.Validate()))
42+
SetFailState("Failed to patch \"%s\"", name);
43+
return hPatch;
44+
}
45+
public DynamicHook CreateDHookOrFail(const char[] name) {
46+
DynamicHook hSetup = DynamicHook.FromConf(this, name);
47+
if (!hSetup)
48+
SetFailState("Missing dhook setup \"%s\"", name);
49+
return hSetup;
50+
}
51+
}
52+
53+
#define OP_CALL_SIZE 5
54+
55+
bool g_bLeft4Dead2;
56+
57+
MemoryPatch g_hPatch;
58+
DynamicHook g_hDHook;
59+
int g_iPatchOffs, g_iFuncOffs;
60+
61+
DynamicHook g_hDHook_PhysicsSolidMaskForEntity;
62+
63+
ConVar g_cvStrictCollide;
64+
65+
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
66+
{
67+
switch (GetEngineVersion())
68+
{
69+
case Engine_Left4Dead: { g_bLeft4Dead2 = false; }
70+
case Engine_Left4Dead2: { g_bLeft4Dead2 = true; }
71+
default: { strcopy(error, err_max, "Plugin supports L4D & 2 only."); return APLRes_SilentFailure; }
72+
}
73+
return APLRes_Success;
74+
}
75+
76+
public void OnPluginStart()
77+
{
78+
GameDataWrapper conf = new GameDataWrapper("l4d_vomit_trace_patch");
79+
80+
g_hDHook_PhysicsSolidMaskForEntity = conf.CreateDHookOrFail("CBaseEntity::PhysicsSolidMaskForEntity");
81+
82+
if (!g_bLeft4Dead2)
83+
{
84+
g_hPatch = conf.CreatePatchOrFail("ShouldHitEntity_MyInfectedPointer", false);
85+
g_hDHook = conf.CreateDHookOrFail("CBaseAbility::UpdateAbility");
86+
87+
Address pGetTeamNumberFuncAddr = conf.GetAddress("CBaseEntity_GetTeamNumber");
88+
g_iPatchOffs = conf.GetOffset("PatchOffset");
89+
g_iFuncOffs =
90+
view_as<int>(pGetTeamNumberFuncAddr) - (view_as<int>(g_hPatch.Address) + (g_iPatchOffs - 1) + OP_CALL_SIZE);
91+
92+
conf.CreatePatchOrFail("OnVomitCollide__TraceRayMask_patch", true);
93+
conf.CreatePatchOrFail("OnVomitCollide__ClipRayMask_patch", true);
94+
}
95+
96+
delete conf;
97+
98+
g_cvStrictCollide = CreateConVar("vomit_collide_strict", "1", "Stricter vomit collision against hitbox instead of bounding box.", FCVAR_NONE, true, 0.0, true, 1.0);
99+
}
100+
101+
void ApplyPatch(bool patch)
102+
{
103+
static bool patched = false;
104+
if (patch && !patched)
105+
{
106+
if (!g_hPatch.Enable())
107+
SetFailState("Failed to enable patch \"ShouldHitEntity_MyInfectedPointer\"");
108+
109+
StoreToAddress(g_hPatch.Address + view_as<Address>(g_iPatchOffs), g_iFuncOffs, NumberType_Int32);
110+
patched = true;
111+
}
112+
else if (!patch && patched)
113+
{
114+
g_hPatch.Disable();
115+
patched = false;
116+
}
117+
}
118+
119+
public void OnEntityCreated(int entity, const char[] classname)
120+
{
121+
if (classname[0] == 'a')
122+
{
123+
if (!strcmp(classname, "ability_vomit"))
124+
{
125+
if (!g_bLeft4Dead2)
126+
{
127+
g_hDHook.HookEntity(Hook_Pre, entity, CVomit_UpdateAbility);
128+
g_hDHook.HookEntity(Hook_Post, entity, CVomit_UpdateAbility_Post);
129+
}
130+
131+
g_hDHook_PhysicsSolidMaskForEntity.HookEntity(Hook_Post, entity, CVomit_PhysicsSolidMaskForEntity_Post);
132+
}
133+
}
134+
else if (classname[0] == 'v')
135+
{
136+
if (!strcmp(classname, "vomit_particle"))
137+
{
138+
g_hDHook_PhysicsSolidMaskForEntity.HookEntity(Hook_Post, entity, CVomitParticle_PhysicsSolidMaskForEntity_Post);
139+
}
140+
}
141+
}
142+
143+
MRESReturn CVomit_UpdateAbility(int pThis)
144+
{
145+
if (GetEntProp(pThis, Prop_Send, "m_isSpraying"))
146+
{
147+
ApplyPatch(true);
148+
}
149+
150+
return MRES_Ignored;
151+
}
152+
153+
MRESReturn CVomit_UpdateAbility_Post(int pThis)
154+
{
155+
ApplyPatch(false);
156+
157+
return MRES_Ignored;
158+
}
159+
160+
MRESReturn CVomit_PhysicsSolidMaskForEntity_Post(DHookReturn hReturn)
161+
{
162+
// (L4D1) 0x200400B -> MASK_SOLID
163+
// (L4D2) 0x2004003 -> MASK_SOLID & ~CONTENTS_GRATE
164+
165+
int flags = hReturn.Value;
166+
167+
flags &= (~CONTENTS_GRATE); // Unnecessary for L4D2 though
168+
169+
if (g_cvStrictCollide.BoolValue)
170+
{
171+
flags |= CONTENTS_HITBOX;
172+
}
173+
174+
hReturn.Value = flags;
175+
return MRES_Override;
176+
}
177+
178+
MRESReturn CVomitParticle_PhysicsSolidMaskForEntity_Post(DHookReturn hReturn)
179+
{
180+
return CVomit_PhysicsSolidMaskForEntity_Post(hReturn);
181+
}

‎cfg/generalfixes.cfg‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ sm plugins load fixes/l4d_prop_touching_rules.smx
7575
sm plugins load fixes/l4d2_fix_tank_rock_handoff.smx
7676
sm plugins load fixes/l4d_fix_prop_los.smx
7777
sm plugins load fixes/l4d2_incap_fire_fix.smx
78+
sm plugins load fixes/l4d_vomit_trace_patch.smx
7879

7980
// Anti-Cheat.
8081
sm plugins load optional/l4d2_block_autoaim.smx // Sort of a cheat..?

0 commit comments

Comments
 (0)