Skip to content

Commit c991e8a

Browse files
authored
Updated 'l4d2_nobhaps' (#899)
1) Updated syntax. 2) Removed unnecessary checks and unnecessary code. 3) Added command 'sm_check_bhop' to check plugin cvars, for more convenient configuration (shows for which classes of infected bhop is disabled). 4) The plugin has been working on servers for a long time and has been tested.
1 parent ec5b033 commit c991e8a

1 file changed

Lines changed: 150 additions & 64 deletions

File tree

Lines changed: 150 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,90 @@
1+
#pragma semicolon 1
2+
#pragma newdecls required
3+
14
#include <sourcemod>
25
#include <sdktools>
6+
#include <l4d2util_constants>
7+
//#define LEFT4FRAMEWORK_GAMEDATA_ONLY 1
8+
//#include <left4framework>
39

410
#define DEBUG 0
511

6-
#define L4DBUILD 1
12+
#define NEW_METHOD_GET_MAX_SPEED 1 // 0 - old
713

814
#define LEFT4FRAMEWORK_GAMEDATA "left4dhooks.l4d2" // left4dhooks
9-
#define SECTION_NAME "CTerrorPlayer::GetRunTopSpeed" // left4dhooks
15+
#define SECTION_NAME "CTerrorPlayer::GetRunTopSpeed"
16+
17+
int
18+
g_iCvarSIExcept = 0;
19+
20+
bool
21+
g_bCvarEnable = false,
22+
g_bCvarSurvivorExcept = false;
23+
24+
float
25+
g_fLeftGroundMaxSpeed[MAXPLAYERS + 1] = {0.0, ...};
26+
27+
ConVar
28+
g_hCvarEnable = null,
29+
g_hCvarSIExcept = null,
30+
g_hCvarSurvivorExcept = null;
1031

11-
//#define LEFT4FRAMEWORK_GAMEDATA "left4downtown.l4d2" // left4downtown
12-
//#define SECTION_NAME "CTerrorPlayer_GetRunTopSpeed" // left4downtown
32+
#if NEW_METHOD_GET_MAX_SPEED
33+
Handle
34+
g_hGetRunTopSpeed = null;
35+
#endif
1336

14-
public Plugin:myinfo =
37+
public Plugin myinfo =
1538
{
1639
name = "Simple Anti-Bunnyhop",
17-
author = "CanadaRox, ProdigySim, blodia, CircleSquared, robex",
40+
author = "CanadaRox, ProdigySim, blodia, CircleSquared, robex, A1m`",
1841
description = "Stops bunnyhops by restricting speed when a player lands on the ground to their MaxSpeed",
19-
version = "0.3",
42+
version = "0.5.1",
2043
url = "https://github.com/SirPlease/L4D2-Competitive-Rework"
2144
};
2245

23-
new Handle:hCvarEnable;
24-
#if defined(L4DBUILD)
25-
new Handle:hCvarSIExcept;
26-
new Handle:hCvarSurvivorExcept;
27-
new Handle:g_hGetRunTopSpeed;
28-
#endif
29-
30-
public OnPluginStart()
46+
public void OnPluginStart()
3147
{
48+
#if NEW_METHOD_GET_MAX_SPEED
3249
LoadSDK();
33-
hCvarEnable = CreateConVar("simple_antibhop_enable", "1", "Enable or disable the Simple Anti-Bhop plugin");
34-
#if defined(L4DBUILD)
35-
hCvarSIExcept = CreateConVar("bhop_except_si_flags", "0", "Bitfield for exempting SI in anti-bhop functionality. From least significant: Smoker, Boomer, Hunter, Spitter, Jockey, Charger, Tank");
36-
hCvarSurvivorExcept = CreateConVar("bhop_allow_survivor", "0", "Allow Survivors to bhop while plugin is enabled");
3750
#endif
51+
52+
g_hCvarEnable = CreateConVar( \
53+
"simple_antibhop_enable", \
54+
"1", \
55+
"Enable or disable the Simple Anti-Bhop plugin (0 - disable, 1 - enable).", \
56+
_, true, 0.0, true, 1.0 \
57+
);
58+
59+
// 1 - smoker, 2 - boomer, 4 - hunter, 8 - spitter, 16 - jockey, 32 - charger, 64 - tank
60+
// 1 + 2 + 4 + 8 + 16 + 32 + 64 = 127 full flag
61+
// Exmaple 1: 1 + 4 = 5 - allow bhop for smoker and hunter.
62+
// Exmaple 2: 1 + 2 + 4 + 8 + 16 + 32 = 63 - allow bhop for all classes, except for the tank.
63+
g_hCvarSIExcept = CreateConVar( \
64+
"bhop_except_si_flags", \
65+
"0", \
66+
"Bitfield for exempting SI in anti-bhop functionality. \
67+
1 - smoker, 2 - boomer, 4 - hunter, 8 - spitter, 16 - jockey, 32 - charger, 64 - tank.", \
68+
_, true, 0.0, true, 127.0 \
69+
);
70+
71+
g_hCvarSurvivorExcept = CreateConVar( \
72+
"bhop_allow_survivor", \
73+
"0", \
74+
"Allow Survivors to bhop while plugin is enabled (1 - allow, 0 - block).", \
75+
_, true, 0.0, true, 1.0 \
76+
);
77+
78+
CvarsToType();
79+
80+
g_hCvarEnable.AddChangeHook(Cvars_Changed);
81+
g_hCvarSIExcept.AddChangeHook(Cvars_Changed);
82+
g_hCvarSurvivorExcept.AddChangeHook(Cvars_Changed);
83+
84+
RegConsoleCmd("sm_check_bhop", Cmd_CheckBhop);
3885
}
3986

87+
#if NEW_METHOD_GET_MAX_SPEED
4088
void LoadSDK()
4189
{
4290
Handle hGameData = LoadGameConfigFile(LEFT4FRAMEWORK_GAMEDATA);
@@ -48,78 +96,116 @@ void LoadSDK()
4896
if (!PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, SECTION_NAME)) {
4997
SetFailState("Function '%s' not found", SECTION_NAME);
5098
}
51-
99+
52100
PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain);
53-
101+
54102
g_hGetRunTopSpeed = EndPrepSDKCall();
55103
if (g_hGetRunTopSpeed == null) {
56104
SetFailState("Function '%s' found, but something went wrong", SECTION_NAME);
57105
}
58-
106+
59107
delete hGameData;
60108
}
109+
#endif
61110

62-
public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon)
111+
void CvarsToType()
63112
{
64-
if (!IsValidClient(client) || IsFakeClient(client))
65-
return Plugin_Continue;
113+
g_bCvarEnable = g_hCvarEnable.BoolValue;
114+
g_iCvarSIExcept = g_hCvarSIExcept.IntValue;
115+
g_bCvarSurvivorExcept = g_hCvarSurvivorExcept.BoolValue;
116+
}
117+
118+
void Cvars_Changed(ConVar hConVar, const char[] sOldValue, const char[] sNewValue)
119+
{
120+
CvarsToType();
121+
}
122+
123+
Action Cmd_CheckBhop(int iClient, int iArgs)
124+
{
125+
if (!g_bCvarEnable) {
126+
ReplyToCommand(iClient, "Bunnyhop is allowed for everyone!");
127+
return Plugin_Handled;
128+
}
129+
130+
ReplyToCommand(iClient, "Bunnyhop is %s for survivors!", (g_bCvarSurvivorExcept) ? "allowed" : "blocked");
131+
132+
for (int i = view_as<int>(L4D2Infected_Smoker); i <= view_as<int>(L4D2Infected_Tank); i++) {
133+
if (i == view_as<int>(L4D2Infected_Witch)) {
134+
continue;
135+
}
66136

67-
static Float:LeftGroundMaxSpeed[MAXPLAYERS + 1];
137+
ReplyToCommand(iClient, "[Infected] Bunnyhop is %s for %s zombie class!", (IsAllowBhopZClass(i)) ? "allowed" : "blocked", L4D2_InfectedNames[i]);
138+
}
139+
140+
return Plugin_Handled;
141+
}
68142

69-
if(!GetConVarBool(hCvarEnable))
143+
public Action OnPlayerRunCmd(int iClient, int& iButtons, int& iImpulse, float fVel[3], float fAngles[3], \
144+
int& iWeapon, int& iSubtype, int& iCmdNum, int& iTickcount, int& iSeed, int iMouse[2])
145+
{
146+
if (!g_bCvarEnable || IsFakeClient(iClient) || !IsPlayerAlive(iClient)) {
70147
return Plugin_Continue;
148+
}
71149

72-
if (IsPlayerAlive(client)) {
73-
#if defined(L4DBUILD)
74-
if (GetClientTeam(client) == 3) {
75-
new class = GetEntProp(client, Prop_Send, "m_zombieClass");
76-
// tank
77-
if (class == 8) {
78-
--class;
79-
}
80-
class--;
81-
new except = GetConVarInt(hCvarSIExcept);
82-
if (class >= 0 && class <= 6 && ((1 << class) & except)) {
83-
// Skipping calculation for This SI based on exception rules
150+
switch (GetClientTeam(iClient)) {
151+
case L4D2Team_Survivor: {
152+
if (g_bCvarSurvivorExcept) {
84153
return Plugin_Continue;
85154
}
86155
}
87-
if (GetClientTeam(client) == 2) {
88-
if (GetConVarBool(hCvarSurvivorExcept)) {
156+
case L4D2Team_Infected: {
157+
int iZClass = GetEntProp(iClient, Prop_Send, "m_zombieClass");
158+
if (IsAllowBhopZClass(iZClass)) {
89159
return Plugin_Continue;
90160
}
91161
}
92-
#endif
162+
default: {
163+
return Plugin_Continue;
164+
}
165+
}
93166

94-
new ClientFlags = GetEntityFlags(client);
95-
if (ClientFlags & FL_ONGROUND) {
96-
if (LeftGroundMaxSpeed[client] != -1.0) {
167+
if (GetEntityFlags(iClient) & FL_ONGROUND) {
168+
if (g_fLeftGroundMaxSpeed[iClient] != -1.0) {
169+
float CurVelVec[3];
170+
GetEntPropVector(iClient, Prop_Data, "m_vecAbsVelocity", CurVelVec);
97171

98-
new Float:CurVelVec[3];
99-
GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", CurVelVec);
172+
if (GetVectorLength(CurVelVec) > g_fLeftGroundMaxSpeed[iClient]) {
173+
#if DEBUG
174+
PrintToChat(iClient, "Speed: %f {%.02f, %.02f, %.02f}, MaxSpeed: %f", \
175+
GetVectorLength(CurVelVec), CurVelVec[0], CurVelVec[1], CurVelVec[2], g_fLeftGroundMaxSpeed[iClient]);
176+
#endif
100177

101-
if (GetVectorLength(CurVelVec) > LeftGroundMaxSpeed[client]) {
102-
#if DEBUG
103-
PrintToChat(client, "Speed: %f {%.02f, %.02f, %.02f}, MaxSpeed: %f", GetVectorLength(CurVelVec), CurVelVec[0], CurVelVec[1], CurVelVec[2], LeftGroundMaxSpeed[client]);
104-
#endif
105-
NormalizeVector(CurVelVec, CurVelVec);
106-
ScaleVector(CurVelVec, LeftGroundMaxSpeed[client]);
107-
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, CurVelVec);
108-
}
109-
LeftGroundMaxSpeed[client] = -1.0;
178+
NormalizeVector(CurVelVec, CurVelVec);
179+
ScaleVector(CurVelVec, g_fLeftGroundMaxSpeed[iClient]);
180+
TeleportEntity(iClient, NULL_VECTOR, NULL_VECTOR, CurVelVec);
110181
}
111-
} else if (LeftGroundMaxSpeed[client] == -1.0) {
112-
LeftGroundMaxSpeed[client] = SDKCall(g_hGetRunTopSpeed, client);
182+
g_fLeftGroundMaxSpeed[iClient] = -1.0;
113183
}
184+
} else if (g_fLeftGroundMaxSpeed[iClient] == -1.0) {
185+
#if NEW_METHOD_GET_MAX_SPEED
186+
g_fLeftGroundMaxSpeed[iClient] = SDKCall(g_hGetRunTopSpeed, iClient);
187+
#else
188+
g_fLeftGroundMaxSpeed[iClient] = GetEntPropFloat(iClient, Prop_Data, "m_flMaxspeed");
189+
#endif
114190
}
115191

116192
return Plugin_Continue;
117-
}
193+
}
118194

119-
stock bool:IsValidClient(client)
120-
{
121-
if (client <= 0 || client > MaxClients || !IsClientConnected(client)) {
122-
return false;
195+
bool IsAllowBhopZClass(int iZClass)
196+
{
197+
if (iZClass == view_as<int>(L4D2Infected_Tank)) {
198+
iZClass--;
123199
}
124-
return IsClientInGame(client);
200+
iZClass--;
201+
202+
if (iZClass >= view_as<int>(L4D2Infected_Common)
203+
&& iZClass <= view_as<int>(L4D2Infected_Charger)
204+
&& ((1 << iZClass) & g_iCvarSIExcept)
205+
) {
206+
// Skipping calculation for This SI based on exception rules
207+
return true;
208+
}
209+
210+
return false;
125211
}

0 commit comments

Comments
 (0)