Skip to content

Commit 1d3e918

Browse files
authored
Update l4d_consistent_escaperoute (#925)
* Update l4d_consistent_escaperoute * Fix missing include * Update l4d_consistent_escaperoute
1 parent b8f1d2b commit 1d3e918

2 files changed

Lines changed: 140 additions & 3 deletions

File tree

addons/sourcemod/gamedata/l4d_consistent_escaperoute.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,30 @@
3838
}
3939
}
4040
}
41+
42+
// Checkpoint::GetSpawnPosition(Vector *, QAngle *, TerrorNavArea **)const
43+
"l4d_consistent_escaperoute::Checkpoint::GetSpawnPosition"
44+
{
45+
"signature" "Checkpoint::GetSpawnPosition"
46+
"callconv" "thiscall"
47+
"return" "bool"
48+
"this" "address"
49+
"arguments"
50+
{
51+
"Vector *"
52+
{
53+
"type" "vectorptr"
54+
}
55+
"QAngle *"
56+
{
57+
"type" "vectorptr"
58+
}
59+
"TerrorNavArea **"
60+
{
61+
"type" "objectptr"
62+
}
63+
}
64+
}
4165
}
4266
}
4367

@@ -97,6 +121,22 @@
97121
"windows" "\x83\xEC\x34\x8B\x0D\x2A\x2A\x2A\x2A\x53"
98122
/* 83 EC 34 8B 0D ? ? ? ? 53 */
99123
}
124+
125+
"Checkpoint::GetSpawnPosition"
126+
{
127+
"library" "server"
128+
"linux" "@_ZNK10Checkpoint16GetSpawnPositionEP6VectorP6QAnglePP13TerrorNavArea"
129+
"windows" "\x55\x8B\xEC\x83\xE4\xF0\x81\xEC\x14\x01\x00\x00\x8B\x45\x08\x53"
130+
/* 55 8B EC 83 E4 F0 81 EC 14 01 00 00 8B 45 08 53 */
131+
}
132+
133+
"Checkpoint::GetLargestArea"
134+
{
135+
"library" "server"
136+
"linux" "@_ZNK10Checkpoint14GetLargestAreaEv"
137+
"windows" "\x51\xD9\xEE\x8B\xC1"
138+
/* 51 D9 EE 8B C1 */
139+
}
100140
}
101141
}
102142

@@ -156,6 +196,22 @@
156196
"windows" "\x55\x8B\xEC\x83\xEC\x4C\x53\x33\xDB"
157197
/* 55 8B EC 83 EC 4C 53 33 DB */
158198
}
199+
200+
"Checkpoint::GetSpawnPosition"
201+
{
202+
"library" "server"
203+
"linux" "@_ZNK10Checkpoint16GetSpawnPositionEP6VectorP6QAnglePP13TerrorNavArea"
204+
"windows" "\x53\x8B\xDC\x83\xEC\x08\x83\xE4\xF0\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x81\xEC\x28\x01\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x8B\x43\x08\x56"
205+
/* 53 8B DC 83 EC 08 83 E4 F0 83 C4 04 55 8B 6B 04 89 6C 24 04 8B EC 81 EC 28 01 00 00 A1 ? ? ? ? 33 C5 89 45 FC 8B 43 08 56 */
206+
}
207+
208+
"Checkpoint::GetLargestArea"
209+
{
210+
"library" "server"
211+
"linux" "@_ZNK10Checkpoint14GetLargestAreaEv"
212+
"windows" "\x55\x8B\xEC\x51\x0F\x57\xC0\x8B\xD1"
213+
/* 55 8B EC 51 0F 57 C0 8B D1 */
214+
}
159215
}
160216
}
161217
}

addons/sourcemod/scripting/l4d_consistent_escaperoute.sp

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
#pragma newdecls required
33

44
#define DEBUG 1
5-
#define PLUGIN_VERSION "2.0"
5+
#define PLUGIN_VERSION "2.1"
66
#define PLUGIN_TAG "l4d_consistent_escaperoute"
77

88
#include <sourcemod>
99
#include <dhooks>
1010
#include <sourcescramble>
11+
#include <sdktools>
12+
#include <left4dhooks>
1113

1214
#if DEBUG
1315
#include <sdktools_functions>
@@ -22,6 +24,13 @@ public Plugin myinfo =
2224
url = "https://github.com/Target5150/MoYu_Server_Stupid_Plugins"
2325
};
2426

27+
enum struct SDKCallParamsWrapper {
28+
SDKType type;
29+
SDKPassMethod pass;
30+
int decflags;
31+
int encflags;
32+
}
33+
2534
methodmap GameDataWrapper < GameData {
2635
public GameDataWrapper(const char[] file) {
2736
GameData gd = new GameData(file);
@@ -60,6 +69,27 @@ methodmap GameDataWrapper < GameData {
6069
SetFailState("Failed to post-detour \"%s\"", name);
6170
return hSetup;
6271
}
72+
public Handle CreateSDKCallOrFail(
73+
SDKCallType type,
74+
SDKFuncConfSource src,
75+
const char[] name,
76+
const SDKCallParamsWrapper[] params = {},
77+
int numParams = 0,
78+
bool hasReturnValue = false,
79+
const SDKCallParamsWrapper ret = {}) {
80+
static const char k_sSDKFuncConfSource[SDKFuncConfSource][] = { "offset", "signature", "address" };
81+
Handle result;
82+
StartPrepSDKCall(type);
83+
if (!PrepSDKCall_SetFromConf(this, src, name))
84+
SetFailState("Missing %s \"%s\"", k_sSDKFuncConfSource[src], name);
85+
for (int i = 0; i < numParams; ++i)
86+
PrepSDKCall_AddParameter(params[i].type, params[i].pass, params[i].decflags, params[i].encflags);
87+
if (hasReturnValue)
88+
PrepSDKCall_SetReturnInfo(ret.type, ret.pass, ret.decflags, ret.encflags);
89+
if (!(result = EndPrepSDKCall()))
90+
SetFailState("Failed to prep sdkcall \"%s\"", name);
91+
return result;
92+
}
6393
}
6494

6595
methodmap Address {}
@@ -98,6 +128,7 @@ methodmap TerrorNavArea < Address
98128
#endif
99129

100130
MemoryPatch g_patch_SkipSpawnPosIdx;
131+
Handle g_call_Checkpoint_GetLargestArea;
101132

102133
public void OnPluginStart()
103134
{
@@ -110,6 +141,12 @@ public void OnPluginStart()
110141

111142
g_patch_SkipSpawnPosIdx = gd.CreatePatchOrFail("skip_spawn_position_idx", false);
112143

144+
SDKCallParamsWrapper params[] = {
145+
{ SDKType_PlainOldData, SDKPass_Plain },
146+
};
147+
g_call_Checkpoint_GetLargestArea = gd.CreateSDKCallOrFail(SDKCall_Raw, SDKConf_Signature, "Checkpoint::GetLargestArea", _, 0, true, params[0]);
148+
149+
delete gd.CreateDetourOrFail("l4d_consistent_escaperoute::Checkpoint::GetSpawnPosition", _, DTR_Checkpoint_GetSpawnPosition_Post);
113150
delete gd.CreateDetourOrFail("l4d_consistent_escaperoute::GetPlayerSpawnPosition", DTR_GetPlayerSpawnPosition, DTR_GetPlayerSpawnPosition_Post);
114151
delete gd.CreateDetourOrFail("l4d_consistent_escaperoute::TerrorNavMesh::ComputeFlowDistances", DTR_ComputeFlowDistances, DTR_ComputeFlowDistances_Post);
115152
delete gd;
@@ -136,6 +173,7 @@ MRESReturn DTR_ComputeFlowDistances(DHookReturn hReturn)
136173
return MRES_Ignored;
137174
}
138175

176+
// GetPlayerSpawnPosition(SurvivorCharacterType,Vector *,QAngle *,TerrorNavArea **)
139177
MRESReturn DTR_GetPlayerSpawnPosition(DHookReturn hReturn, DHookParam hParams)
140178
{
141179
if (!g_bInComputeFlowDistances)
@@ -159,6 +197,49 @@ MRESReturn DTR_GetPlayerSpawnPosition(DHookReturn hReturn, DHookParam hParams)
159197
return MRES_Ignored;
160198
}
161199

200+
// Checkpoint::GetSpawnPosition(Vector *, QAngle *, TerrorNavArea **)const
201+
MRESReturn DTR_Checkpoint_GetSpawnPosition_Post(Address pThis, DHookReturn hReturn, DHookParam hParams)
202+
{
203+
if (!g_bInComputeFlowDistances)
204+
return MRES_Ignored;
205+
206+
#if DEBUG
207+
PrintToServer("[%s] Overriding Checkpoint::GetSpawnPosition", PLUGIN_TAG);
208+
#endif
209+
210+
// NOTE:
211+
// GetSpawnPosition always computes a random position within start safe area.
212+
// The following makes it always return the largest area instead.
213+
TerrorNavArea area = SDKCall(g_call_Checkpoint_GetLargestArea, pThis);
214+
if (area == Address_Null)
215+
return MRES_Ignored;
216+
217+
#if DEBUG
218+
PrintToServer("[%s] Fixed player start area = %d", PLUGIN_TAG, area.GetID());
219+
#endif
220+
221+
if (!hParams.IsNull(1))
222+
{
223+
float pos[3];
224+
L4D_GetNavAreaCenter(area, pos);
225+
hParams.SetVector(1, pos);
226+
}
227+
228+
if (!hParams.IsNull(2))
229+
{
230+
hParams.SetVector(2, {0.0, 0.0, 0.0});
231+
}
232+
233+
if (!hParams.IsNull(3))
234+
{
235+
hParams.SetObjectVar(3, 0, ObjectValueType_Int, area);
236+
}
237+
238+
hReturn.Value = true;
239+
return MRES_ChangedOverride;
240+
}
241+
242+
// GetPlayerSpawnPosition(SurvivorCharacterType,Vector *,QAngle *,TerrorNavArea **)
162243
MRESReturn DTR_GetPlayerSpawnPosition_Post(DHookReturn hReturn, DHookParam hParams)
163244
{
164245
if (!g_bInComputeFlowDistances)
@@ -207,7 +288,7 @@ void NextFrame_ComputeFlowDistance()
207288

208289
if (g_SavedEscapeRouteAreas.Length != TheEscapeRoute.m_nMainPathAreaCount)
209290
{
210-
PrintToServer(" Count mismatches (was %d, now %d)", PLUGIN_TAG, g_SavedEscapeRouteAreas.Length, TheEscapeRoute.m_nMainPathAreaCount);
291+
PrintToServer(" Count mismatches (was %d, now %d)", g_SavedEscapeRouteAreas.Length, TheEscapeRoute.m_nMainPathAreaCount);
211292
fullyMatched = false;
212293
}
213294
else
@@ -217,7 +298,7 @@ void NextFrame_ComputeFlowDistance()
217298
TerrorNavArea area = TheEscapeRoute.GetMainPathArea(i);
218299
if (area.GetID() != g_SavedEscapeRouteAreas.Get(i))
219300
{
220-
PrintToServer(" Area @ %d mismatches (was #%d, now #%d)", PLUGIN_TAG, i, g_SavedEscapeRouteAreas.Get(i), area.GetID());
301+
PrintToServer(" Area @ %d mismatches (was #%d, now #%d)", i, g_SavedEscapeRouteAreas.Get(i), area.GetID());
221302
fullyMatched = false;
222303
break;
223304
}

0 commit comments

Comments
 (0)