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;
 | |
| } |