Skip to content

Commit e9e3701

Browse files
authored
Update l4d2_fix_changelevel (#946)
* Update l4d2_fix_changelevel * Add compiled l4d2_fix_changelevel
1 parent c40a53b commit e9e3701

3 files changed

Lines changed: 86 additions & 12 deletions

File tree

addons/sourcemod/gamedata/l4d2_fix_changelevel.txt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,19 @@
3737
"linux" "944"
3838
"windows" "944"
3939
}
40+
41+
"CDirector::m_szOriginalMap"
42+
{
43+
"linux" "948"
44+
"windows" "948"
45+
}
4046
}
4147

4248
"Addresses"
4349
{
4450
"CDirector::m_isTransitioning"
4551
{
46-
"signature" "CDirector::OnBeginTransition"
52+
"signature" "CDirector::OnBeginTransition"
4753
"linux"
4854
{
4955
"read" "14"
@@ -53,6 +59,32 @@
5359
"read" "26"
5460
}
5561
}
62+
63+
"s_landmarkName"
64+
{
65+
"signature" "InfoChangelevel::StartChangeLevel"
66+
"linux"
67+
{
68+
"read" "88"
69+
}
70+
"windows"
71+
{
72+
"read" "77"
73+
}
74+
}
75+
76+
"s_landmarkPosition"
77+
{
78+
"signature" "InfoChangelevel::StartChangeLevel"
79+
"linux"
80+
{
81+
"read" "190"
82+
}
83+
"windows"
84+
{
85+
"read" "160"
86+
}
87+
}
5688
}
5789

5890
"Signatures"
@@ -90,6 +122,14 @@
90122
"windows" "\x55\x8B\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x2A\x2A\x89\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\x57\x8B"
91123
/* 55 8B ? ? ? ? ? ? ? A1 ? ? ? ? ? ? 89 ? ? A1 ? ? ? ? 56 8B ? ? 57 8B */
92124
}
125+
126+
"InfoChangelevel::StartChangeLevel"
127+
{
128+
"library" "server"
129+
"linux" "@_ZN15InfoChangelevel16StartChangeLevelEPK10Checkpoint"
130+
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\x78\x30\x00\x56\x8B\xF1\x74"
131+
// 55 8B EC A1 ? ? ? ? 83 78 30 00 56 8B F1 74
132+
}
93133
}
94134
}
95135
}
604 Bytes
Binary file not shown.

addons/sourcemod/scripting/l4d2_fix_changelevel.sp

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <dhooks>
77
#include <left4dhooks>
88

9-
#define PLUGIN_VERSION "1.1"
9+
#define PLUGIN_VERSION "1.2"
1010

1111
public Plugin myinfo =
1212
{
@@ -81,7 +81,10 @@ Handle g_CallOnBeginTransition;
8181
Handle g_CallOnBeginChangeLevel;
8282
int g_iOffs_m_mapDurationTimer;
8383
int g_iOffs_m_flTotalMissionElaspedTime;
84+
int g_iOffs_m_szOriginalMap;
8485
Address gp_m_isTransitioning;
86+
Address gp_s_landmarkName;
87+
Address gp_s_landmarkPosition;
8588

8689
methodmap CDirector {
8790
public void ClearTeamScores(bool newCampaign) {
@@ -96,9 +99,15 @@ methodmap CDirector {
9699
property float m_flTotalMissionElaspedTime {
97100
public set(float flTotalMissionElaspedTime) { StoreToAddress(view_as<Address>(this) + view_as<Address>(g_iOffs_m_flTotalMissionElaspedTime), flTotalMissionElaspedTime, NumberType_Int32); }
98101
}
102+
property Address m_szOriginalMap {
103+
public get() { return view_as<Address>(this) + view_as<Address>(g_iOffs_m_szOriginalMap); }
104+
}
99105
public bool IsTransitioning() {
100106
return LoadFromAddress(gp_m_isTransitioning, NumberType_Int8);
101107
}
108+
public void SetOriginalMap(const char[] map) {
109+
UTIL_StoreToAddressString(this.m_szOriginalMap, map, 32);
110+
}
102111
}
103112
CDirector TheDirector;
104113

@@ -110,20 +119,23 @@ public void OnPluginStart()
110119
{SDKType_Bool, SDKPass_Plain}
111120
};
112121
g_CallClearTeamScores = gd.CreateSDKCallOrFail(SDKCall_Raw, SDKConf_Signature, "CDirector::ClearTeamScores", params, sizeof(params), false);
113-
122+
114123
SDKCallParamsWrapper params2[] = {
115124
{SDKType_Bool, SDKPass_Plain}
116125
};
117126
g_CallOnBeginTransition = gd.CreateSDKCallOrFail(SDKCall_Raw, SDKConf_Signature, "CDirector::OnBeginTransition", params2, sizeof(params2), false);
118-
127+
119128
SDKCallParamsWrapper params3[] = {
120129
{SDKType_String, SDKPass_Pointer}
121130
};
122131
g_CallOnBeginChangeLevel = gd.CreateSDKCallOrFail(SDKCall_GameRules, SDKConf_Signature, "CTerrorGameRules::OnBeginChangeLevel", params3, sizeof(params3), false);
123-
132+
124133
g_iOffs_m_mapDurationTimer = gd.GetOffsetOrFail("CDirector::m_mapDurationTimer");
125134
g_iOffs_m_flTotalMissionElaspedTime = gd.GetOffsetOrFail("CDirector::m_flTotalMissionElaspedTime");
135+
g_iOffs_m_szOriginalMap = gd.GetOffsetOrFail("CDirector::m_szOriginalMap");
126136
gp_m_isTransitioning = gd.GetAddressOrFail("CDirector::m_isTransitioning");
137+
gp_s_landmarkName = gd.GetAddressOrFail("s_landmarkName");
138+
gp_s_landmarkPosition = gd.GetAddressOrFail("s_landmarkPosition");
127139

128140
delete gd.CreateDetourOrFail("CVEngineServer::ChangeLevel", DTR__CVEngineServer__ChangeLevel);
129141
delete gd;
@@ -132,29 +144,32 @@ public void OnPluginStart()
132144
public void OnAllPluginsLoaded()
133145
{
134146
TheDirector = view_as<CDirector>(L4D_GetPointer(POINTER_DIRECTOR));
147+
if (!TheDirector)
148+
{
149+
LogError("Failed to retrieve TheDirector pointer from left4dhooks");
150+
}
135151
}
136152

137153
MRESReturn DTR__CVEngineServer__ChangeLevel(DHookParam hParams)
138154
{
139155
if (!TheDirector)
140-
{
141-
LogError("Failed to retrieve TheDirector pointer from left4dhooks");
142156
return MRES_Ignored;
143-
}
144-
157+
145158
char map[64]/*, reason[64]*/;
146159
hParams.GetString(1, map, sizeof(map));
147160
// if (!hParams.IsNull(2))
148161
// hParams.GetString(2, reason, sizeof(reason));
149-
162+
150163
if (TheDirector.IsTransitioning())
151164
return MRES_Ignored;
152-
165+
153166
TheDirector.ClearTeamScores(true);
154-
167+
155168
ITimer_Start(TheDirector.m_mapDurationTimer);
156169
TheDirector.m_flTotalMissionElaspedTime = 0.0;
157170

171+
TheDirector.SetOriginalMap(map);
172+
ClearTransitionedLandmarkName();
158173
TheDirector.OnBeginTransition(false);
159174
GameRules__OnBeginChangeLevel(map);
160175

@@ -164,4 +179,23 @@ MRESReturn DTR__CVEngineServer__ChangeLevel(DHookParam hParams)
164179
void GameRules__OnBeginChangeLevel(const char[] map)
165180
{
166181
SDKCall(g_CallOnBeginChangeLevel, map);
182+
}
183+
184+
void ClearTransitionedLandmarkName()
185+
{
186+
StoreToAddress(gp_s_landmarkName, 0, NumberType_Int8);
187+
StoreToAddress(gp_s_landmarkPosition, 0.0, NumberType_Int32);
188+
StoreToAddress(gp_s_landmarkPosition + view_as<Address>(4), 0.0, NumberType_Int32);
189+
StoreToAddress(gp_s_landmarkPosition + view_as<Address>(8), 0.0, NumberType_Int32);
190+
}
191+
192+
void UTIL_StoreToAddressString(Address dest, const char[] src, int maxlength)
193+
{
194+
int len = strlen(src);
195+
if (len > maxlength - 1)
196+
len = maxlength - 1;
197+
for (int i = 0; i < len; ++i) {
198+
StoreToAddress(dest + view_as<Address>(i), src[i], NumberType_Int8);
199+
}
200+
StoreToAddress(dest + view_as<Address>(len), 0, NumberType_Int8);
167201
}

0 commit comments

Comments
 (0)