Fixed bunch of includes and a warnings Added ip addresses for admins to status KnifeAlert prints to everyone now if someone gets infected due to a knifed zombie Fixed WeaponCleaner not registering weapons if somebody disconnects Refactored custom-chatcolors to new syntax, added autoreplace and some fixes Added GFLClan.ru support to immunityreservedslots added nominate_removemap to mapchooser_extended and fixed a bug for recently played maps
1326 lines
34 KiB
SourcePawn
1326 lines
34 KiB
SourcePawn
/**
|
|
* ==================================================================================
|
|
* Immunity Reserve Slots Change Log
|
|
* ==================================================================================
|
|
*
|
|
* 0.1
|
|
* - Initial release.
|
|
*
|
|
* 0.2
|
|
* - Added lowest time option to kick types.
|
|
* - Added cvars to control kick message for normal kick and immunity kick.
|
|
* - Small optimizations.
|
|
*
|
|
* 0.3
|
|
* - Fixed some logging bugs.
|
|
* - Fixed a major bug in the immunity check and optimised regular check.
|
|
*
|
|
* 0.3.1
|
|
* - Fixed a very small bug in the logging code to do with detecting spectators.
|
|
*
|
|
* 0.3.2
|
|
* - Added option to only log who gets kicked.
|
|
*
|
|
* 0.3.3
|
|
* - Added cvar to control whether or not spectators get kicked first before other
|
|
* players or not (defaults to enabled).
|
|
*
|
|
* 0.3.4
|
|
* - Added a cvar option to limit the maximum amount of players with high immunity
|
|
* to kick low immunity players when the server is full (if more than the value
|
|
* are connected at the time no further connections will be allowed).
|
|
* - A bit of code clean up.
|
|
*
|
|
* 1.0
|
|
* - Made final.
|
|
* - Added full translation support.
|
|
* - Changed the way the reason cvars work, no config changes needed for old users.
|
|
*
|
|
* 1.0.1
|
|
* - Added cvar "sm_irs_keepbalance", this will try and keep team balance best as
|
|
* possible when kicking players as not to trigger an autobalance.
|
|
* - Drastic recoding for better performance.
|
|
* - Added use of AskPluginLoad2() for improved late load detection (this makes the
|
|
* plugin require SM 1.3 now).
|
|
* - Added detection of accidental installation of the default test plugin for
|
|
* CBaseServer tools to avoid any possible problems.
|
|
* - New verbose logs, now create their own log files instead of spamming regular
|
|
* logs. Also improved verbosity.
|
|
* - Fixed a small leak which happened if any logging was disabled.
|
|
* - Spec check now uses a team check instead as in some games it could "incorrectly"
|
|
* flag users as spectating when they were dead. Also flags unassigned players now.
|
|
*
|
|
* 1.0.2
|
|
* - Fixed incorrect statement in balance check code.
|
|
* - Small optimisations.
|
|
* - Added command check back in for "sm_reskick_immunity" as some servers might
|
|
* expect this as a valid way to grant default immunity if reading the official
|
|
* SM wiki.
|
|
* - Added the regular SM reserve slot plugin to the plugin checks on startup.
|
|
*
|
|
* 1.0.3
|
|
* - Made the default action for detected reserve plugins to move to the disabled
|
|
* folder after unload rather than stopping the plugin.
|
|
* - Changed translation phrase on plugin error to make more sense.
|
|
*
|
|
* 1.0.4
|
|
* - Made use of GetURandomFloat for random mode.
|
|
* - Improved logging code.
|
|
*
|
|
* 2.0
|
|
* - Added Connect extension support.
|
|
* - Added cvars to configure the reject message on a full server
|
|
* (sm_irs_rejectreason_enable and sm_irs_rejectreason).
|
|
*
|
|
* 2.0.1
|
|
* - Added auto password cvar so reserve clients can automatically connect to
|
|
* password protected servers, can also be set so any connecting client can
|
|
* connect e.g. for temporary purposes (sm_irs_autopassword).
|
|
* - Fixed bug in keep balance code where it wouldn't kick spectators if there were
|
|
* any when the cvar for kick spectators first was disabled.
|
|
* - Added kick list mode, this allows anyone to connect to the server (configurable)
|
|
* but goes through a list of steam id's for who should get kicked vs who can
|
|
* connect (sm_irs_kicklist_mode and sm_irs_kicklist_file).
|
|
* - Removed sm_rescheck_mmunity command check thing I still had in there where it
|
|
* wouldn't have mattered anyway (i.e. I missed it).
|
|
*
|
|
* 2.0.2
|
|
* - Recoded kick list mode for less disk I/O.
|
|
* - Fixed a bug if kick list mode was set to 2 which could create a possible rare
|
|
* looping slot scenario.
|
|
* - Added command to reload the kick list if users want to update the list as soon
|
|
* as possible (sm_irs_kicklist_reload), list now also updates automatically on
|
|
* map change properly.
|
|
* - Cleaned up some code.
|
|
*
|
|
* 2.0.3
|
|
* - Fixed CloseHandle() bug.
|
|
*
|
|
* 2.0.4
|
|
* - Fix for too many clients connecting in MVM games. Connect only.
|
|
*
|
|
* 2.0.5
|
|
* - Fix for non-TF2 games throwing errors on map start. Connect only.
|
|
*
|
|
* 2.0.6
|
|
* - Code cleanup.
|
|
* - Added support for Connect 1.2.0+.
|
|
*
|
|
* 2.0.7
|
|
* - Added donator plugin support
|
|
* (see: http://forums.alliedmods.net/showthread.php?t=145542).
|
|
*
|
|
* 2.0.8
|
|
* - Added cvar to control when to kick spectators (sm_irs_kickspecdelay, set to 0
|
|
* instantly kicks spectators, anything else gives them a grace of x secs before
|
|
* being kicked).
|
|
* ==================================================================================
|
|
*/
|
|
|
|
#include <sourcemod>
|
|
#include <sdktools>
|
|
|
|
#undef REQUIRE_PLUGIN
|
|
#include <donator>
|
|
#include <entWatch>
|
|
#include <GFLClanru>
|
|
#define REQUIRE_PLUGIN
|
|
|
|
#define PLUGIN_VERSION "2.1.0"
|
|
|
|
// Toggle build here.
|
|
#define EXT_CBASE 0
|
|
#define EXT_CONNECT 1
|
|
|
|
// Anti-Jamster protection scheme.
|
|
#if EXT_CONNECT && EXT_CBASE
|
|
#define EXT_CBASE 0
|
|
#endif
|
|
|
|
#if EXT_CBASE
|
|
#include <cbaseserver>
|
|
#endif
|
|
|
|
#if EXT_CONNECT
|
|
#define MAX_CLIENTS_MVM 6
|
|
#include <connect>
|
|
#endif
|
|
|
|
new TEAM1;
|
|
new TEAM2;
|
|
new SPEC;
|
|
|
|
new bool:g_HighImmunityPlayers[MAXPLAYERS+1];
|
|
new bool:b_lateLoad;
|
|
new bool:b_loaded;
|
|
new bool:b_useDonator;
|
|
new bool:b_useEntWatch;
|
|
new bool:b_useGFLClanru;
|
|
new bool:b_canKickSpec[MAXPLAYERS+1];
|
|
|
|
new g_HIPCount;
|
|
|
|
new Handle:cvar_KickType = INVALID_HANDLE;
|
|
new Handle:cvar_Spec = INVALID_HANDLE;
|
|
new Handle:cvar_SpecKickDelay = INVALID_HANDLE;
|
|
new Handle:cvar_Logging = INVALID_HANDLE;
|
|
new Handle:cvar_Immunity = INVALID_HANDLE;
|
|
new Handle:cvar_KickReasonImmunity = INVALID_HANDLE;
|
|
new Handle:cvar_KickReason = INVALID_HANDLE;
|
|
new Handle:cvar_HighImmunityLimit = INVALID_HANDLE;
|
|
new Handle:cvar_HighImmunityValue = INVALID_HANDLE;
|
|
new Handle:cvar_KeepBalance = INVALID_HANDLE;
|
|
new Handle:cvar_KickListMode = INVALID_HANDLE;
|
|
new Handle:cvar_KickListFile = INVALID_HANDLE;
|
|
new Handle:cvar_Donator = INVALID_HANDLE;
|
|
new Handle:cvar_DonatorImmunity = INVALID_HANDLE;
|
|
|
|
new Handle:arr_KickListIDs = INVALID_HANDLE;
|
|
|
|
new Handle:t_KickSpecClient[MAXPLAYERS+1] = INVALID_HANDLE;
|
|
|
|
#if EXT_CONNECT
|
|
new bool:isMVM = false;
|
|
new Handle:cvar_AutoPassword = INVALID_HANDLE;
|
|
new Handle:cvar_RejectReason = INVALID_HANDLE;
|
|
new Handle:cvar_RejectReasonEnable = INVALID_HANDLE;
|
|
new Handle:cvar_GameTypeMVM = INVALID_HANDLE;
|
|
#endif
|
|
|
|
new String:g_LogFilePath[PLATFORM_MAX_PATH];
|
|
|
|
public Plugin:myinfo =
|
|
{
|
|
#if EXT_CBASE
|
|
name = "Immunity Reserve Slots [CBASESERVER]",
|
|
#endif
|
|
#if EXT_CONNECT
|
|
name = "Immunity Reserve Slots [CONNECT]",
|
|
#endif
|
|
author = "Jamster",
|
|
description = "Immunity based reserve slots for CBaseServer Tools and Connect extensions",
|
|
version = PLUGIN_VERSION,
|
|
url = "http://www.sourcemod.net/"
|
|
};
|
|
|
|
public OnPluginStart()
|
|
{
|
|
LoadTranslations("immunityreserveslots.phrases");
|
|
decl String:desc[255];
|
|
|
|
arr_KickListIDs = CreateArray(32);
|
|
b_loaded = false;
|
|
|
|
#if EXT_CONNECT
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_autopassword");
|
|
cvar_AutoPassword = CreateConVar("sm_irs_autopassword", "0", desc, _, true, 0.0, true, 2.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_rejectreason_enable");
|
|
cvar_RejectReasonEnable = CreateConVar("sm_irs_rejectreason_enable", "0", desc, _, true, 0.0, true, 1.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_rejectreason");
|
|
cvar_RejectReason = CreateConVar("sm_irs_rejectreason", "default", desc, _);
|
|
|
|
cvar_GameTypeMVM = FindConVar("tf_gamemode_mvm");
|
|
|
|
#endif
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_version");
|
|
CreateConVar("sm_irs_version", PLUGIN_VERSION, desc, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kicktype");
|
|
cvar_KickType = CreateConVar("sm_irs_kicktype", "0", desc, _, true, 0.0, true, 3.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kickreason");
|
|
cvar_KickReason = CreateConVar("sm_irs_kickreason", "default", desc, _);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kickreason_immunity");
|
|
cvar_KickReasonImmunity = CreateConVar("sm_irs_kickreason_immunity", "default", desc, _);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kicklist_file");
|
|
cvar_KickListFile = CreateConVar("sm_irs_kicklist_file", "default", desc, _);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kicklist_mode");
|
|
cvar_KickListMode = CreateConVar("sm_irs_kicklist_mode", "0", desc, _, true, 0.0, true, 2.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_log");
|
|
cvar_Logging = CreateConVar("sm_irs_log", "0", desc, _, true, 0.0, true, 2.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_immunity");
|
|
cvar_Immunity = CreateConVar("sm_irs_immunity", "1", desc, _, true, 0.0, true, 2.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kickspecfirst");
|
|
cvar_Spec = CreateConVar("sm_irs_kickspecfirst", "1", desc, _, true, 0.0, true, 1.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kickspecdelay");
|
|
cvar_SpecKickDelay = CreateConVar("sm_irs_kickspecdelay", "0", desc, _, true, 0.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_donator_support");
|
|
cvar_Donator = CreateConVar("sm_irs_donator_support", "0", desc, _, true, 0.0, true, 1.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_donator_immunity");
|
|
cvar_DonatorImmunity = CreateConVar("sm_irs_donator_immunity", "0", desc, _, true, 0.0, true, 99.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_highimmunitylimit");
|
|
cvar_HighImmunityLimit = CreateConVar("sm_irs_highimmunitylimit", "0", desc, _, true, 0.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_highimmunityvalue");
|
|
cvar_HighImmunityValue = CreateConVar("sm_irs_highimmunityvalue", "0", desc, _, true, 0.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_keepbalance");
|
|
cvar_KeepBalance = CreateConVar("sm_irs_keepbalance", "0", desc, _, true, 0.0, true, 1.0);
|
|
|
|
Format(desc, sizeof(desc), "%t", "irs_kicklist_reload");
|
|
RegServerCmd("sm_irs_kicklist_reload", Command_KickListReload, desc);
|
|
|
|
HookConVarChange(cvar_KickListFile, KickListFileChanged);
|
|
HookConVarChange(cvar_KickListMode, KickListConVarChanged);
|
|
|
|
AddCommandListener(listen_join_team, "jointeam");
|
|
AddCommandListener(listen_join_team, "spectate");
|
|
|
|
AutoExecConfig(true, "plugin.immunityreserveslots");
|
|
}
|
|
|
|
public OnConfigsExecuted()
|
|
{
|
|
LoadKickList();
|
|
|
|
#if EXT_CONNECT
|
|
|
|
if (cvar_GameTypeMVM != INVALID_HANDLE && GetConVarInt(cvar_GameTypeMVM))
|
|
{
|
|
isMVM = true;
|
|
}
|
|
else
|
|
{
|
|
isMVM = false;
|
|
}
|
|
|
|
#endif
|
|
|
|
b_loaded = true;
|
|
|
|
if (GetConVarInt(cvar_Donator) && !b_useDonator)
|
|
{
|
|
LogError("%t", "IRS Donator Plugin Error");
|
|
}
|
|
}
|
|
|
|
public OnMapEnd()
|
|
{
|
|
b_loaded = false;
|
|
}
|
|
|
|
public KickListFileChanged(Handle:convar, const String:oldValue[], const String:newValue[])
|
|
{
|
|
if (!StrEqual(oldValue, newValue, false) && b_loaded)
|
|
{
|
|
LoadKickList();
|
|
}
|
|
}
|
|
|
|
public KickListConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[])
|
|
{
|
|
if (newValue[0] != 0 && b_loaded)
|
|
{
|
|
LoadKickList();
|
|
}
|
|
}
|
|
|
|
public Action:Command_KickListReload(client)
|
|
{
|
|
if (LoadKickList())
|
|
{
|
|
ReplyToCommand(client, "%t", "IRS Kick List Reloaded");
|
|
}
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
LoadKickList()
|
|
{
|
|
ClearArray(arr_KickListIDs);
|
|
if (GetConVarInt(cvar_KickListMode))
|
|
{
|
|
decl String:path[PLATFORM_MAX_PATH];
|
|
GetConVarString(cvar_KickListFile, path, sizeof(path));
|
|
if (StrEqual(path, "default", false))
|
|
{
|
|
BuildPath(Path_SM, path, sizeof(path), "configs/irs_kicklist.ini");
|
|
}
|
|
|
|
new Handle:h_path = OpenFile(path, "r");
|
|
if (h_path == INVALID_HANDLE)
|
|
{
|
|
LogError("%t", "IRS Kick List Path Error", path);
|
|
}
|
|
else
|
|
{
|
|
decl String:line[32];
|
|
while (!IsEndOfFile(h_path))
|
|
{
|
|
ReadFileLine(h_path, line, sizeof(line));
|
|
TrimString(line);
|
|
// Yep, I ain't checking if STEAMID's are valid, I'm raw like that.
|
|
if (line[0] != '/' && line[1] != '/' && line[0] != '\0' && line[0] != '*')
|
|
{
|
|
PushArrayString(arr_KickListIDs, line);
|
|
}
|
|
}
|
|
CloseHandle(h_path);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public OnAllPluginsLoaded()
|
|
{
|
|
b_useDonator = LibraryExists("donator.core");
|
|
b_useEntWatch = LibraryExists("entWatch");
|
|
b_useGFLClanru = LibraryExists("GFLClanru");
|
|
|
|
new Handle:h_Plugin;
|
|
new Handle:arr_Plugins = CreateArray(64);
|
|
decl String:plugin[64];
|
|
|
|
PushArrayString(arr_Plugins, "cbaseservertest.smx");
|
|
PushArrayString(arr_Plugins, "cbsext_reserves.smx");
|
|
PushArrayString(arr_Plugins, "reservedslots.smx");
|
|
PushArrayString(arr_Plugins, "immunityreserveslots.smx");
|
|
|
|
#if EXT_CBASE
|
|
|
|
PushArrayString(arr_Plugins, "immunityreserveslots_connect.smx");
|
|
|
|
#endif
|
|
|
|
#if EXT_CONNECT
|
|
|
|
PushArrayString(arr_Plugins, "immunityreserveslots_cbase.smx");
|
|
|
|
#endif
|
|
|
|
new index = GetArraySize(arr_Plugins);
|
|
|
|
for (new i=0; i<index; i++)
|
|
{
|
|
GetArrayString(arr_Plugins, i, plugin, sizeof(plugin));
|
|
h_Plugin = FindPluginByFile(plugin);
|
|
if (h_Plugin != INVALID_HANDLE)
|
|
{
|
|
CloseHandle(h_Plugin);
|
|
LogError("%t", "IRS Plugin Error", plugin);
|
|
IRS_RemovePlugin(plugin);
|
|
}
|
|
}
|
|
|
|
CloseHandle(arr_Plugins);
|
|
}
|
|
|
|
public OnLibraryRemoved(const String:name[])
|
|
{
|
|
if (StrEqual(name, "donator.core"))
|
|
{
|
|
b_useDonator = false;
|
|
}
|
|
else if (StrEqual(name, "entWatch"))
|
|
{
|
|
b_useEntWatch = false;
|
|
}
|
|
else if (StrEqual(name, "GFLClanru"))
|
|
{
|
|
b_useGFLClanru = false;
|
|
}
|
|
}
|
|
|
|
public OnLibraryAdded(const String:name[])
|
|
{
|
|
if (StrEqual(name, "donator.core"))
|
|
{
|
|
b_useDonator = true;
|
|
}
|
|
else if (StrEqual(name, "entWatch"))
|
|
{
|
|
b_useEntWatch = true;
|
|
}
|
|
else if (StrEqual(name, "GFLClanru"))
|
|
{
|
|
b_useGFLClanru = true;
|
|
}
|
|
}
|
|
|
|
IRS_RemovePlugin(const String:plugin_name[])
|
|
{
|
|
decl String:plugin[PLATFORM_MAX_PATH];
|
|
decl String:dir[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, plugin, sizeof(plugin), "plugins/%s", plugin_name);
|
|
BuildPath(Path_SM, dir, sizeof(dir), "plugins/disabled", plugin_name);
|
|
|
|
ServerCommand("sm plugins unload %s", plugin_name);
|
|
|
|
if (!DirExists(dir))
|
|
{
|
|
CreateDirectory(dir, FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC);
|
|
}
|
|
|
|
Format(dir, sizeof(dir), "%s/%s", dir, plugin_name);
|
|
RenameFile(dir, plugin);
|
|
}
|
|
|
|
public OnMapStart()
|
|
{
|
|
g_HIPCount = 0;
|
|
|
|
if (b_lateLoad)
|
|
{
|
|
for (new i=1; i<=MaxClients; i++)
|
|
{
|
|
g_HighImmunityPlayers[i] = false;
|
|
if (IsClientConnected(i))
|
|
{
|
|
OnClientPostAdminCheck(i);
|
|
}
|
|
}
|
|
b_lateLoad = false;
|
|
}
|
|
}
|
|
|
|
#if EXT_CONNECT
|
|
GetRealClientCount()
|
|
{
|
|
new ClientCount = 0;
|
|
for (new i = 1; i <= MaxClients; i++)
|
|
{
|
|
if (IsClientConnected(i) && !IsFakeClient(i))
|
|
{
|
|
ClientCount++;
|
|
}
|
|
}
|
|
|
|
return ClientCount;
|
|
}
|
|
|
|
public EConnect OnClientPreConnectEx(const String:name[], String:password[255], const String:ip[], const String:steamID[], String:rejectReason[255])
|
|
{
|
|
new AdminId:AdminID = FindAdminByIdentity(AUTHMETHOD_STEAM, steamID);
|
|
|
|
//decl String:Time[32];
|
|
//FormatTime(Time, sizeof(Time), "%Y%m%d");
|
|
//BuildPath(Path_SM, g_LogFilePath, sizeof(g_LogFilePath), "logs/irslogs_%s.log", Time);
|
|
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] %s (%s) connecting", name, steamID);
|
|
|
|
new bool:isDonator = false;
|
|
if (b_useDonator && GetConVarInt(cvar_Donator))
|
|
{
|
|
isDonator = FindDonatorBySteamId(steamID);
|
|
}
|
|
|
|
if (GetConVarInt(cvar_AutoPassword) == 2 || (GetConVarInt(cvar_AutoPassword) == 1 && (GetAdminFlag(AdminID, Admin_Reservation) || isDonator)))
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Giving connecting client the server password to allow connection");
|
|
GetConVarString(FindConVar("sv_password"), password, sizeof(password));
|
|
}
|
|
|
|
if (!isMVM && GetClientCount(false) < MaxClients)
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Game is not full or MVM game mode is disabled");
|
|
return k_OnClientPreConnectEx_Accept;
|
|
}
|
|
|
|
if (isMVM && GetRealClientCount() < MAX_CLIENTS_MVM)
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Game is MVM but there's still room available (%d clients connected)", GetRealClientCount());
|
|
return k_OnClientPreConnectEx_Accept;
|
|
}
|
|
|
|
if (GetConVarInt(cvar_KickListMode) == 2)
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Running kicklist check");
|
|
if (FindStringInArray(arr_KickListIDs, steamID) != -1)
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Connecting client is found in kicklist, refusing connection");
|
|
if (GetConVarInt(cvar_RejectReasonEnable) || isMVM)
|
|
{
|
|
GetConVarString(cvar_RejectReason, rejectReason, sizeof(rejectReason));
|
|
if (StrEqual(rejectReason, "default", false))
|
|
{
|
|
Format(rejectReason, sizeof(rejectReason), "%t", "IRS Reject Reason");
|
|
}
|
|
return k_OnClientPreConnectEx_Reject;
|
|
}
|
|
else
|
|
{
|
|
return k_OnClientPreConnectEx_Accept;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GetAdminFlag(AdminID, Admin_Reservation) || isDonator || GetConVarInt(cvar_KickListMode) == 2)
|
|
{
|
|
// DONATOR LEVEL CHECK HERE WHEN POSSIBLE VIA STEAMID
|
|
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Checking for a valid client to kick for connecting client");
|
|
new ImmunityLevel = GetAdminImmunityLevel(AdminID);
|
|
if (ImmunityLevel == 0 && isDonator)
|
|
{
|
|
ImmunityLevel = GetConVarInt(cvar_DonatorImmunity);
|
|
}
|
|
|
|
if (IRS_KickValidClient(AdminID, name, steamID, ImmunityLevel, isDonator))
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Plugin has made successful kick and will now allow client to connect");
|
|
return k_OnClientPreConnectEx_Accept;
|
|
}
|
|
else if (GetConVarInt(cvar_RejectReasonEnable) || isMVM)
|
|
{
|
|
GetConVarString(cvar_RejectReason, rejectReason, sizeof(rejectReason));
|
|
if (StrEqual(rejectReason, "default", false))
|
|
{
|
|
Format(rejectReason, sizeof(rejectReason), "%t", "IRS Reject Reason");
|
|
}
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] No slot for connecting client, refusing connection (rejection mode)");
|
|
return k_OnClientPreConnectEx_Reject;
|
|
}
|
|
//else
|
|
//{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] No slot for connecting client, refusing connection (normal)");
|
|
//}
|
|
}
|
|
|
|
if (isMVM)
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] MVM game is full, refusing connection");
|
|
GetConVarString(cvar_RejectReason, rejectReason, sizeof(rejectReason));
|
|
if (StrEqual(rejectReason, "default", false))
|
|
{
|
|
Format(rejectReason, sizeof(rejectReason), "%t", "IRS Reject Reason");
|
|
}
|
|
return k_OnClientPreConnectEx_Reject;
|
|
}
|
|
|
|
if (b_useGFLClanru)
|
|
{
|
|
new Handle:pack = CreateDataPack();
|
|
WritePackString(pack, name);
|
|
AsyncHasSteamIDReservedSlot(steamID, AsyncHasSteamIDReservedSlotCallback, pack);
|
|
|
|
return k_OnClientPreConnectEx_Async;
|
|
}
|
|
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] End of preconnection code");
|
|
|
|
return k_OnClientPreConnectEx_Accept;
|
|
}
|
|
|
|
public void AsyncHasSteamIDReservedSlotCallback(const char[] sSteam32ID, int Result, any Data)
|
|
{
|
|
// Slot free'd up while waiting or doesn't have a reserved slot?
|
|
if(GetClientCount(false) < MaxClients || !Result)
|
|
{
|
|
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Accept, "");
|
|
return;
|
|
}
|
|
|
|
new String:name[MAX_NAME_LENGTH];
|
|
ResetPack(Data);
|
|
ReadPackString(Data, name, sizeof(name));
|
|
|
|
if (IRS_KickValidClient(INVALID_ADMIN_ID, name, sSteam32ID, 0, true))
|
|
{
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] Plugin has made successful kick and will now allow client to connect");
|
|
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Accept, "");
|
|
return;
|
|
}
|
|
else if (GetConVarInt(cvar_RejectReasonEnable) || isMVM)
|
|
{
|
|
char rejectReason[255];
|
|
GetConVarString(cvar_RejectReason, rejectReason, sizeof(rejectReason));
|
|
if (StrEqual(rejectReason, "default", false))
|
|
{
|
|
Format(rejectReason, sizeof(rejectReason), "%t", "IRS Reject Reason");
|
|
}
|
|
//LogToFileEx(g_LogFilePath, "[DEBUG] No slot for connecting client, refusing connection (rejection mode)");
|
|
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Reject, rejectReason);
|
|
return;
|
|
}
|
|
|
|
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Accept, "");
|
|
}
|
|
#endif
|
|
|
|
#if EXT_CBASE
|
|
public OnClientPreConnect(const String:name[], const String:pass[], const String:ip[], const String:authid[])
|
|
{
|
|
if (GetClientCount(false) < MaxClients)
|
|
{
|
|
return;
|
|
}
|
|
|
|
new bool:isDonator = false;
|
|
if (b_useDonator && GetConVarInt(cvar_Donator))
|
|
{
|
|
isDonator = FindDonatorBySteamId(authid);
|
|
}
|
|
|
|
if (GetConVarInt(cvar_KickListMode) == 2)
|
|
{
|
|
if (FindStringInArray(arr_KickListIDs, authid) != -1)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
new AdminId:AdminID = FindAdminByIdentity(AUTHMETHOD_STEAM, authid);
|
|
|
|
// DONATOR LEVEL CHECK HERE WHEN POSSIBLE VIA STEAMID
|
|
|
|
new ImmunityLevel = GetAdminImmunityLevel(AdminID);
|
|
if (ImmunityLevel == 0 && isDonator)
|
|
{
|
|
ImmunityLevel = -1;
|
|
}
|
|
|
|
if (GetAdminFlag(AdminID, Admin_Reservation) || isDonator || GetConVarInt(cvar_KickListMode) == 2)
|
|
{
|
|
IRS_KickValidClient(AdminID, name, authid, GetAdminImmunityLevel(AdminID), isDonator);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
IRS_LogClient(const client, const team, const immunity, const Float:value = -1.0)
|
|
{
|
|
decl String:TeamName[32];
|
|
GetTeamName(team, TeamName, sizeof(TeamName));
|
|
if (value == -1.0)
|
|
{
|
|
if (IsClientInGame(client))
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: \"%N\" [i: %02d] (%s)", client, client, immunity, TeamName);
|
|
}
|
|
else
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: \"%N\" [i: %02d] (Connecting)", client, client, immunity);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsClientInGame(client))
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: \"%N\" [i: %02d] [v: %f] (%s)", client, client, immunity, value, TeamName);
|
|
}
|
|
else
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: \"%N\" [i: %02d] (Connecting)", client, client, immunity);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool:IRS_KickValidClient(const AdminId:ConnectingClientAdminID, const String:ConnectingClientName[], const String:ConnectingClientAuthID[], const ConnectingClientImmunity, const isDonator)
|
|
{
|
|
decl String:Time[32];
|
|
FormatTime(Time, sizeof(Time), "%Y%m%d");
|
|
BuildPath(Path_SM, g_LogFilePath, sizeof(g_LogFilePath), "logs/irslogs_%s.log", Time);
|
|
|
|
new KickType = GetConVarInt(cvar_KickType);
|
|
new Logging = GetConVarInt(cvar_Logging);
|
|
new Immunity = GetConVarInt(cvar_Immunity);
|
|
new SpecKick = GetConVarInt(cvar_Spec);
|
|
new SpecKickDelay = GetConVarInt(cvar_SpecKickDelay);
|
|
new Donator = GetConVarInt(cvar_Donator);
|
|
new DonatorImmunityValue = GetConVarInt(cvar_DonatorImmunity);
|
|
|
|
new bool:useKeepBalance;
|
|
new bool:immunityKick;
|
|
new bool:useKickList;
|
|
|
|
new LowestImmunityLevel = 100;
|
|
new ClientImmunity[MAXPLAYERS+1];
|
|
new ClientDonator[MAXPLAYERS+1];
|
|
new countTEAM1;
|
|
new countTEAM2;
|
|
new clientTeam[MAXPLAYERS+1] = -1;
|
|
new useTeam;
|
|
new HighestSpecValueId;
|
|
new HighestValueId;
|
|
new HighestBalanceValueId;
|
|
|
|
new Float:HighestBalanceValue;
|
|
new Float:HighestValue;
|
|
new Float:HighestSpecValue;
|
|
new Float:value;
|
|
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "-- Beginning Check --");
|
|
}
|
|
|
|
if (GetConVarInt(cvar_KeepBalance))
|
|
{
|
|
useKeepBalance = true;
|
|
countTEAM1 = GetTeamClientCount(TEAM1);
|
|
countTEAM2 = GetTeamClientCount(TEAM2);
|
|
if (countTEAM1 == countTEAM2)
|
|
{
|
|
useKeepBalance = false;
|
|
}
|
|
else if (countTEAM1 > countTEAM2)
|
|
{
|
|
useTeam = TEAM1;
|
|
}
|
|
else
|
|
{
|
|
useTeam = TEAM2;
|
|
}
|
|
|
|
if (Logging == 1)
|
|
{
|
|
if (useKeepBalance)
|
|
{
|
|
decl String:TeamName[32];
|
|
GetTeamName(useTeam, TeamName, sizeof(TeamName));
|
|
LogToFileEx(g_LogFilePath, "Balance check: Team \"%s\" has the most players (%02d | %02d)", TeamName, countTEAM1, countTEAM2);
|
|
}
|
|
else
|
|
{
|
|
LogToFileEx(g_LogFilePath, "Balance check: Teams are the same size");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Look at how lazy I am.
|
|
if (GetArraySize(arr_KickListIDs))
|
|
{
|
|
useKickList = true;
|
|
}
|
|
else
|
|
{
|
|
useKickList = false;
|
|
}
|
|
|
|
for (new i=1; i<=MaxClients; i++)
|
|
{
|
|
if (!IsClientConnected(i))
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: NOT CONNECTED", i);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (IsFakeClient(i))
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: BOT", i);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (IsClientInGame(i))
|
|
{
|
|
clientTeam[i] = GetClientTeam(i);
|
|
}
|
|
|
|
decl String:PlayerAuth[32];
|
|
GetClientAuthId(i, AuthId_Steam2, PlayerAuth, sizeof(PlayerAuth));
|
|
new AdminId:PlayerAdmin = FindAdminByIdentity(AUTHMETHOD_STEAM, PlayerAuth)
|
|
ClientImmunity[i] = GetAdminImmunityLevel(PlayerAdmin);
|
|
|
|
if (b_useDonator && Donator)
|
|
{
|
|
if (IsPlayerDonator(i))
|
|
{
|
|
ClientDonator[i] = true;
|
|
}
|
|
if (ClientImmunity[i] == 0)
|
|
{
|
|
ClientImmunity[i] = DonatorImmunityValue;
|
|
}
|
|
}
|
|
|
|
// Kick list check, if the player isn't found then they're excluded.
|
|
if (useKickList)
|
|
{
|
|
if (FindStringInArray(arr_KickListIDs, PlayerAuth) == -1)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Removed the check for root as it seems this doesn't matter any more in modern SM versions (1.3+), or it never did and I'm terrible.
|
|
if (GetAdminFlag(PlayerAdmin, Admin_Reservation) || ClientDonator[i])
|
|
{
|
|
if (Immunity && ClientImmunity[i] < LowestImmunityLevel)
|
|
{
|
|
LowestImmunityLevel = ClientImmunity[i];
|
|
}
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (Immunity == 2 && ClientImmunity[i] > 0)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (b_useEntWatch && IsClientInGame(i) && entWatch_HasSpecialItem(i))
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (IsClientInGame(i))
|
|
{
|
|
switch (KickType)
|
|
{
|
|
case 0:
|
|
value = GetURandomFloat();
|
|
case 1:
|
|
value = GetClientAvgLatency(i, NetFlow_Outgoing);
|
|
case 2:
|
|
value = GetClientTime(i);
|
|
case 3:
|
|
value = GetClientTime(i);
|
|
}
|
|
|
|
if (KickType == 3 && !HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
}
|
|
|
|
if ((clientTeam[i] == SPEC || clientTeam[i] == 0) && (SpecKick || useKeepBalance))
|
|
{
|
|
if (SpecKickDelay && b_canKickSpec[i] || !SpecKickDelay)
|
|
{
|
|
if (KickType == 3 && !HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
}
|
|
|
|
if (KickType == 3 && value <= HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
HighestSpecValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
HighestSpecValueId = i;
|
|
}
|
|
}
|
|
}
|
|
else if (KickType == 3 && value <= HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
HighestValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
HighestValueId = i;
|
|
}
|
|
|
|
if (useKeepBalance && clientTeam[i] == useTeam)
|
|
{
|
|
if (KickType == 3 && !HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
}
|
|
|
|
if (KickType == 3 && value <= HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
HighestBalanceValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
HighestBalanceValueId = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i], value);
|
|
}
|
|
}
|
|
|
|
if (Logging == 1)
|
|
{
|
|
decl String:ConnectingClientAdminName[32];
|
|
if (ConnectingClientAdminID != INVALID_ADMIN_ID)
|
|
{
|
|
GetAdminUsername(ConnectingClientAdminID, ConnectingClientAdminName, sizeof(ConnectingClientAdminName));
|
|
}
|
|
else if (isDonator)
|
|
{
|
|
Format(ConnectingClientAdminName, sizeof(ConnectingClientAdminName), "DONATOR");
|
|
}
|
|
else
|
|
{
|
|
Format(ConnectingClientAdminName, sizeof(ConnectingClientAdminName), "ADMIN_NAME_ERROR");
|
|
}
|
|
LogToFileEx(g_LogFilePath, "Connecting player \"%s\" (cfg: \"%s\") [%02d]", ConnectingClientName, ConnectingClientAdminName, ConnectingClientImmunity);
|
|
LogToFileEx(g_LogFilePath, "Lowest immunity: %02d", LowestImmunityLevel);
|
|
LogToFileEx(g_LogFilePath, "High immunity player count: %d", g_HIPCount);
|
|
LogToFileEx(g_LogFilePath, "Max player count: %d", MaxClients);
|
|
}
|
|
|
|
// Two Loops Supremacy
|
|
if (Immunity && !HighestValueId && !HighestSpecValueId)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "All players immune, running extra immunity check");
|
|
}
|
|
|
|
immunityKick = true;
|
|
|
|
for (new i=1; i<=MaxClients; i++)
|
|
{
|
|
if (!IsClientConnected(i))
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: NOT CONNECTED", i);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (IsFakeClient(i))
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "%02d: BOT", i);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (useKickList)
|
|
{
|
|
decl String:PlayerAuth[32];
|
|
GetClientAuthId(i, AuthId_Steam2, PlayerAuth, sizeof(PlayerAuth));
|
|
if (FindStringInArray(arr_KickListIDs, PlayerAuth) == -1)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (ClientImmunity[i] > LowestImmunityLevel)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (ClientImmunity[i] >= ConnectingClientImmunity)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (IsClientInGame(i))
|
|
{
|
|
switch (KickType)
|
|
{
|
|
case 0:
|
|
value = GetURandomFloat();
|
|
case 1:
|
|
value = GetClientAvgLatency(i, NetFlow_Outgoing);
|
|
case 2:
|
|
value = GetClientTime(i);
|
|
case 3:
|
|
value = GetClientTime(i);
|
|
}
|
|
|
|
if (KickType == 3 && !HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
}
|
|
|
|
if ((clientTeam[i] == SPEC || clientTeam[i] == 0) && (SpecKick || useKeepBalance))
|
|
{
|
|
if (SpecKickDelay && b_canKickSpec[i] || !SpecKickDelay)
|
|
{
|
|
if (KickType == 3 && !HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
}
|
|
|
|
if (KickType == 3 && value <= HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
HighestSpecValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestSpecValue)
|
|
{
|
|
HighestSpecValue = value;
|
|
HighestSpecValueId = i;
|
|
}
|
|
}
|
|
}
|
|
else if (KickType == 3 && value <= HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
HighestValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestValue)
|
|
{
|
|
HighestValue = value;
|
|
HighestValueId = i;
|
|
}
|
|
|
|
if (useKeepBalance && clientTeam[i] == useTeam)
|
|
{
|
|
if (KickType == 3 && !HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
}
|
|
|
|
if (KickType == 3 && value <= HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
HighestBalanceValueId = i;
|
|
}
|
|
else if (KickType != 3 && value >= HighestBalanceValue)
|
|
{
|
|
HighestBalanceValue = value;
|
|
HighestBalanceValueId = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Logging == 1)
|
|
{
|
|
IRS_LogClient(i, clientTeam[i], ClientImmunity[i], value);
|
|
}
|
|
}
|
|
}
|
|
|
|
new KickTarget;
|
|
|
|
if (HighestSpecValueId)
|
|
{
|
|
KickTarget = HighestSpecValueId;
|
|
}
|
|
else if (HighestBalanceValueId)
|
|
{
|
|
KickTarget = HighestBalanceValueId;
|
|
}
|
|
else
|
|
{
|
|
KickTarget = HighestValueId;
|
|
}
|
|
|
|
if (KickTarget)
|
|
{
|
|
decl String:KickName[32];
|
|
decl String:KickAuthid[32];
|
|
GetClientName(KickTarget, KickName, sizeof(KickName));
|
|
GetClientAuthId(KickTarget, AuthId_Steam2, KickAuthid, sizeof(KickAuthid));
|
|
|
|
if (!immunityKick)
|
|
{
|
|
decl String:Reason[255];
|
|
GetConVarString(cvar_KickReason, Reason, sizeof(Reason));
|
|
if (StrEqual(Reason, "default", false))
|
|
{
|
|
Format(Reason, sizeof(Reason), "%t", "IRS Kick Reason");
|
|
}
|
|
KickClientEx(KickTarget, "%s", Reason);
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "\"%s\" was kicked", KickName);
|
|
}
|
|
if (Logging == 2)
|
|
{
|
|
LogMessage("%t", "IRS Kick Log", ConnectingClientName, ConnectingClientAuthID, KickName, KickAuthid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
new HighImmunityLimit = GetConVarInt(cvar_HighImmunityLimit);
|
|
if (HighImmunityLimit && g_HIPCount >= HighImmunityLimit)
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "Too many high immunity players connected (%d players)", g_HIPCount);
|
|
}
|
|
return false;
|
|
}
|
|
decl String:Reason[255];
|
|
GetConVarString(cvar_KickReasonImmunity, Reason, sizeof(Reason));
|
|
if (StrEqual(Reason, "default", false))
|
|
{
|
|
Format(Reason, sizeof(Reason), "%t", "IRS Kick Reason Immunity");
|
|
}
|
|
KickClientEx(KickTarget, "%s", Reason);
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "\"%s\" was kicked (Low immunity)", KickName);
|
|
}
|
|
if (Logging == 2)
|
|
{
|
|
LogMessage("%t", "IRS Kick Log", ConnectingClientName, ConnectingClientAuthID, KickName, KickAuthid);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (Logging == 1)
|
|
{
|
|
LogToFileEx(g_LogFilePath, "No valid client found to kick");
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public OnClientPostAdminCheck(client)
|
|
{
|
|
if (IsFakeClient(client))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// I do this here as it makes sure the client is actually connected, I don't want to add anyone too early.
|
|
new HighImmunityValue = GetConVarInt(cvar_HighImmunityValue);
|
|
if (GetConVarInt(cvar_HighImmunityLimit) && HighImmunityValue && GetAdminImmunityLevel(GetUserAdmin(client)) >= HighImmunityValue)
|
|
{
|
|
g_HighImmunityPlayers[client] = true;
|
|
g_HIPCount++;
|
|
}
|
|
|
|
new Float:KickSpecDelay = GetConVarFloat(cvar_SpecKickDelay);
|
|
if (KickSpecDelay)
|
|
{
|
|
CheckKickSpecDelay(KickSpecDelay, client);
|
|
}
|
|
}
|
|
|
|
public OnClientDisconnect(client)
|
|
{
|
|
if (IsFakeClient(client))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!GetConVarInt(cvar_HighImmunityLimit))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (g_HighImmunityPlayers[client])
|
|
{
|
|
g_HighImmunityPlayers[client] = false;
|
|
g_HIPCount--;
|
|
}
|
|
|
|
if (t_KickSpecClient[client] != INVALID_HANDLE)
|
|
{
|
|
KillTimer(t_KickSpecClient[client]);
|
|
t_KickSpecClient[client] = INVALID_HANDLE;
|
|
b_canKickSpec[client] = false;
|
|
}
|
|
}
|
|
|
|
public Action:listen_join_team(client, const String:command[], argc)
|
|
{
|
|
new Float:KickSpecDelay = GetConVarFloat(cvar_SpecKickDelay);
|
|
|
|
if (!KickSpecDelay || IsFakeClient(client))
|
|
{
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
if (StrEqual(command, "jointeam", false) || StrEqual(command, "spectate", false))
|
|
{
|
|
CheckKickSpecDelay(KickSpecDelay, client);
|
|
}
|
|
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
CheckKickSpecDelay(const Float:delay, const client)
|
|
{
|
|
new clientTeam = GetClientTeam(client);
|
|
if ((clientTeam != TEAM1 || clientTeam != TEAM2) && t_KickSpecClient[client] == INVALID_HANDLE)
|
|
{
|
|
t_KickSpecClient[client] = CreateTimer(delay, t_KickSpecClientTimer, client);
|
|
}
|
|
else if ((clientTeam == TEAM1 || clientTeam == TEAM2) && t_KickSpecClient[client] != INVALID_HANDLE)
|
|
{
|
|
KillTimer(t_KickSpecClient[client]);
|
|
t_KickSpecClient[client] = INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
public Action:t_KickSpecClientTimer(Handle:timer, any:client)
|
|
{
|
|
if (IsClientInGame(client))
|
|
{
|
|
b_canKickSpec[client] = true;
|
|
}
|
|
|
|
t_KickSpecClient[client] = INVALID_HANDLE;
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
|
|
{
|
|
if (late)
|
|
{
|
|
b_lateLoad = true
|
|
}
|
|
|
|
// I think insurgency is the only game that has different team indexes. I'll probably never ever check either, I'm terrible.
|
|
decl String:game[32];
|
|
GetGameFolderName(game, sizeof(game));
|
|
if (StrEqual(game, "insurgency"))
|
|
{
|
|
TEAM1 = 1;
|
|
TEAM2 = 2;
|
|
SPEC = 3;
|
|
}
|
|
else
|
|
{
|
|
SPEC = 1;
|
|
TEAM1 = 2;
|
|
TEAM2 = 3;
|
|
}
|
|
|
|
MarkNativeAsOptional("IsPlayerDonator");
|
|
MarkNativeAsOptional("FindDonatorBySteamId");
|
|
|
|
return APLRes_Success;
|
|
} |