diff --git a/SelectiveBhop/scripting/SelectiveBhop.sp b/SelectiveBhop/scripting/SelectiveBhop.sp new file mode 100644 index 00000000..8149be16 --- /dev/null +++ b/SelectiveBhop/scripting/SelectiveBhop.sp @@ -0,0 +1,232 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include +#undef REQUIRE_PLUGIN +#include +#define REQUIRE_PLUGIN + +ConVar g_CVar_sv_enablebunnyhopping; +ConVar g_CVar_zr_disablebunnyhopping; + +enum +{ + LIMITED_NONE = 0, + LIMITED_GENERAL = 1, + LIMITED_ZOMBIE = 2 +} + +bool g_bEnabled = false; +bool g_bZombieEnabled = false; +bool g_bInOnPlayerRunCmd = false; + +int g_ClientLimited[MAXPLAYERS + 1] = {LIMITED_NONE, ...}; +int g_ActiveLimitedFlags = LIMITED_GENERAL; + +public Plugin myinfo = +{ + name = "Selective Bunnyhop", + author = "BotoX", + description = "Disables bunnyhop on certain players/groups", + version = "0.1" +} + +public void OnPluginStart() +{ + g_CVar_sv_enablebunnyhopping = FindConVar("sv_enablebunnyhopping"); + g_CVar_sv_enablebunnyhopping.Flags &= ~FCVAR_REPLICATED; + g_CVar_sv_enablebunnyhopping.AddChangeHook(OnConVarChanged); + g_bEnabled = g_CVar_sv_enablebunnyhopping.BoolValue; + + g_CVar_zr_disablebunnyhopping = CreateConVar("zr_disablebunnyhopping", "0", "Disable bhop for zombies.", FCVAR_NOTIFY); + g_CVar_zr_disablebunnyhopping.AddChangeHook(OnConVarChanged); + g_bZombieEnabled = g_CVar_zr_disablebunnyhopping.BoolValue; + + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); + + /* Late load */ + for(int i = 1; i <= MaxClients; i++) + { + if(!IsClientInGame(i) || IsFakeClient(i)) + return; + + if(ZR_IsClientZombie(i)) + AddLimitedFlag(i, LIMITED_ZOMBIE); + } + + UpdateLimitedFlags(); + UpdateClients(); +} + +public void OnClientPutInServer(int client) +{ + TransmitConVar(client); +} + +public void OnPluginEnd() +{ + g_CVar_sv_enablebunnyhopping.BoolValue = g_bEnabled; + g_CVar_sv_enablebunnyhopping.Flags |= FCVAR_REPLICATED|FCVAR_NOTIFY; + + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i)) + { + if(g_CVar_sv_enablebunnyhopping.BoolValue) + g_CVar_sv_enablebunnyhopping.ReplicateToClient(i, "1"); + else + g_CVar_sv_enablebunnyhopping.ReplicateToClient(i, "0"); + } + } +} + +public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + if(convar == g_CVar_sv_enablebunnyhopping) + { + if(g_bInOnPlayerRunCmd) + return; + + g_bEnabled = convar.BoolValue; + UpdateClients(); + } + else if(convar == g_CVar_zr_disablebunnyhopping) + { + g_bZombieEnabled = convar.BoolValue; + UpdateLimitedFlags(); + } +} + +public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) +{ + if(!g_bEnabled) + return Plugin_Continue; + + bool bEnableBunnyhopping = !(g_ClientLimited[client] & g_ActiveLimitedFlags); + if(bEnableBunnyhopping == g_CVar_sv_enablebunnyhopping.BoolValue) + return Plugin_Continue; + + if(!g_bInOnPlayerRunCmd) + { + g_CVar_sv_enablebunnyhopping.Flags &= ~FCVAR_NOTIFY; + g_bInOnPlayerRunCmd = true; + } + + g_CVar_sv_enablebunnyhopping.BoolValue = bEnableBunnyhopping; + + return Plugin_Continue; +} + +public void OnRunThinkFunctionsPost(bool simulating) +{ + if(g_bInOnPlayerRunCmd) + { + g_CVar_sv_enablebunnyhopping.BoolValue = g_bEnabled; + g_CVar_sv_enablebunnyhopping.Flags |= FCVAR_NOTIFY; + g_bInOnPlayerRunCmd = false; + } +} + +public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn) +{ + AddLimitedFlag(client, LIMITED_ZOMBIE); +} + +public void ZR_OnClientHumanPost(int client, bool respawn, bool protect) +{ + RemoveLimitedFlag(client, LIMITED_ZOMBIE); +} + +public void ZR_OnClientRespawned(int client, ZR_RespawnCondition condition) +{ + if(condition == ZR_Respawn_Human) + RemoveLimitedFlag(client, LIMITED_ZOMBIE); + else + AddLimitedFlag(client, LIMITED_ZOMBIE); +} + +public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) +{ + RemoveLimitedFlag(-1, LIMITED_ZOMBIE); +} + +void UpdateLimitedFlags() +{ + int Flags = LIMITED_GENERAL; + + if(g_bZombieEnabled) + Flags |= LIMITED_ZOMBIE; + + if(g_ActiveLimitedFlags != Flags) + { + g_ActiveLimitedFlags = Flags; + UpdateClients(); + } + g_ActiveLimitedFlags = Flags; +} + +stock void AddLimitedFlag(int client, int Flag) +{ + if(client == -1) + { + for(int i = 1; i <= MaxClients; i++) + _AddLimitedFlag(i, Flag); + } + else + _AddLimitedFlag(client, Flag); +} + +stock void _AddLimitedFlag(int client, int Flag) +{ + bool bWasLimited = view_as(g_ClientLimited[client] & g_ActiveLimitedFlags); + g_ClientLimited[client] |= Flag; + bool bIsLimited = view_as(g_ClientLimited[client] & g_ActiveLimitedFlags); + + if(bIsLimited != bWasLimited) + TransmitConVar(client); +} + +stock void RemoveLimitedFlag(int client, int Flag) +{ + if(client == -1) + { + for(int i = 1; i <= MaxClients; i++) + _RemoveLimitedFlag(i, Flag); + } + else + _RemoveLimitedFlag(client, Flag); +} + +stock void _RemoveLimitedFlag(int client, int Flag) +{ + bool bWasLimited = view_as(g_ClientLimited[client] & g_ActiveLimitedFlags); + g_ClientLimited[client] &= ~Flag; + bool bIsLimited = view_as(g_ClientLimited[client] & g_ActiveLimitedFlags); + + if(bIsLimited != bWasLimited) + TransmitConVar(client); +} + +stock void UpdateClients() +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i)) + TransmitConVar(i); + } +} + +stock void TransmitConVar(int client) +{ + if(!IsClientInGame(client) || IsFakeClient(client)) + return; + + bool bIsLimited = view_as(g_ClientLimited[client] & g_ActiveLimitedFlags); + + if(g_bEnabled && !bIsLimited) + g_CVar_sv_enablebunnyhopping.ReplicateToClient(client, "1"); + else + g_CVar_sv_enablebunnyhopping.ReplicateToClient(client, "0"); +} diff --git a/SelectiveBhop/scripting/include/CSSFixes.inc b/SelectiveBhop/scripting/include/CSSFixes.inc new file mode 120000 index 00000000..aa0b4998 --- /dev/null +++ b/SelectiveBhop/scripting/include/CSSFixes.inc @@ -0,0 +1 @@ +../../../includes/CSSFixes.inc \ No newline at end of file diff --git a/includes/CSSFixes.inc b/includes/CSSFixes.inc index 84751b47..6fbe4714 100644 --- a/includes/CSSFixes.inc +++ b/includes/CSSFixes.inc @@ -6,7 +6,7 @@ forward void OnRunThinkFunctions(bool simulating); forward void OnRunThinkFunctionsPost(bool simulating); -public Extension:__ext_CSSFixes = +public Extension __ext_CSSFixes = { name = "CSSFixes", file = "CSSFixes.ext",