You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

2513 lines
73 KiB

/*
#############################################################################################################
# Anti-TK 1.1.3 #
#############################################################################################################
*
* Author:
* -> Rothgar
*
* Description:
* Anti-TK script scripted for SourceMod. This script was created as a basic Anti-TK script alternative
* to ATAC, most of the punishment functions have been taken from the funcommands plugin, or slightly
* modified versions of the fun commands plugin functions. This ensures the script should be efficient
* and makes for cleaner code. This has also been modified to support ZPS (Zombie Panic Source) infections
* so infected players are not counted as TK's.
*
*
* Credits:
* -> Rawr > For providing an alternate slay function which kills players instantly.
* ZPS has a delayed death function... which causes problems.
* -> CustomFactor Server > Being a test bed for the script
* -> NADES Ins Server > NADES and Admins helping test Insurgency Support.
* -> sfPlayer > Helping with adt arrays & suggestions
* -> Tramp > Allowing use of his CS Server for testing.
* -> Milo| > Finding bug in Purge Timer
* -> Pimpinjuice > providing a better way of hooking events.
*
*
* Required Files (Case Sensitive?):
*
* -> These files can be downloaded from http://www.dawgclan.net
*
*
* Usage:
*
* -> Change the compile variables below to enable/disable punishments and remove their code. This is currently based off the funcommands method. Otherwise use the cvar's.
*
*
* Version history:
* v1.1.3:
* - fixed:
* - Error with no forgive internal notify error.
* - Fixed some wrong death checks where round protection TK Menu's would not show and karma calculations would not work.
*
* v1.1.2:
* - fixed:
* - Slap Mirror Damage Hook Issue.
* - Slap Mirror Damage Percentage Bugs.
*
* v1.1.1:
* - added:
* - Burn Punishments.
* - Mirror Damage Percent.
* - Stealing of Player Resources.
* - fixed:
* - Some errors due to players leaving the server before punishments had been made.
*
* v1.1.0:
* - fixed:
* - Error with Stat TK log message when TK'er had left the game.
* - Error hooking round start protection properly.
* - Error detecting round protection incorrectly for early mirror damage.
* - Menu items not using correct values. Punishments were wrong for No Forgive.
* - Bug where Mirror Damage would be disabled after disabling round start protection.
* - added:
* - Added slay message for Mirror Damage attacker Slaying.
* - Resource punishment removal.
* - Added slap option for Mirror Damage.
*
* v1.0.13: (Spawn Protection)
* - fixed:
* - Hooking wrong spawn protection cvar
* - Mirror damage for Counter-Strike
* - added:
* - New CS Mod based TK hooking.
*
* v1.0.12: (Admin immunity)
* - fixed:
* - Admin immunity cvars being incorrect.
* - No longer checking "world" or "console" in player_hurt
* - added:
* - No Forgive Option if everything is disabled.
* - changed:
* - Menu code to be more dynamic.
* - Translation messages to "team attack" instead of "team kill"
*
* v1.0.11: (Timebomb)
* - fixed:
* - Fixed blind Maximum values.
* - added:
* - Time Bomb Punishment.
* - Special Slay.
* - Admin Immunity.
* - changed:
* - Fixed Debug log file message printing when Debug was not enabled.
*
* v1.0.10: (Translation Changes)
* - changed:
* - Changes translations to be more consistent and not rely on plugin tag in Translation file.
*
* v1.0.9: (Round Start Protection)
* - fixed:
* - A few log messages saying the wrong plugin source.
* - Issue with Killing Timers
* - added:
* - Round Spawn Protection.
* - Freeze Bomb Punishment.
* - Automatic Configuration file.
* - TK forgive stat log function modified from psychonic's Log Helper.
* - SourceBans support.
* - Mirror Damage.
* - changed:
* - Re-imported funcommands.
* - Separated Anti-TK log file.
* - Event Hooking method.
* - Debug logging to have different levels.
*
* v1.0.8: (Player Stat Storage)
* - fixed:
* - Slay not working/crashing some mods?
* - added:
* - Translation file for langauges.
* - changed:
* - Optimized a few variables.
*
* v1.0.7: (Player Stat Storage)
* - fixed:
* - TK File Purging
* - Purge Timer
* - added:
* - More Debug messages
* - changed:
* - Nothing
*
* v1.0.6: (Player Stat Storage)
* - fixed:
* - Nothing
* - added:
* - Purging of stats
* - changed:
* - Nothing
*
* v1.0.5: (Insurgency Slay work-around)
* - fixed:
* - Insurgency Slay causes server crash, used client kill command instead.
* - Bantime description being seconds instead of minutes.
* - Misc bugs
* - added:
* - TK user storage functions.
* - changed:
* - Debug functions.
*
* v1.0.4: (Tidy up code)
* - fixed:
* - Errors when disabling options
* - added:
* - Debug option and cvars
* - changed:
* - Moved all funcommands functions into an include script.
*
* v1.0.3: (Initial Public release)
* - fixed:
* - Nothing
* - added:
* - Entire plugin
* - changed:
* - Nothing
*/
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
// SourceBans
#include <sourcebans>
// Enable Punishments (based off funcommands.sp)
// Disabling these will remove un-necessary code as opposed to using cvars
#define BEACON 1
#define FIRE 1
#define ICE 1
#define GRAVITY 1
#define BLIND 1
#define DRUG 1
#define SLAP 1
#define SLAY 1
#define TIMEBOMB 1
// Change this to enable debug
// 0 = No Logging
// 1 = Minimal Logging
// 2 = Maximum Logging
#define _DEBUG 0
#define _DEBUG_MODE 1 // 1 = Log to File, 2 = Log to Game Logs, 3 Print to Chat
#if _DEBUG
new String:AntiTK_LogFile[PLATFORM_MAX_PATH];
#endif
// Shouldn't need to edit anything below this line.
#define VERSION "1.1.3"
// 4 == Usually Green?
// 1 == Normal Color?
#define ANTITK_COLOR 4
#define MAX_NETWORKID_LENGTH 64
// ZPS Related Variables
#define TEAM_ZPS_ZOMBIE 2
#define TEAM_ZPS_SURVIVOR 1
#define TEAM_ZPS_SPECTATOR 3
#define TEAM_ZPS_OBSERVER 4
// Player Array Settings
#define STAT_KARMA 0
#define STAT_KILLS 1
#define STAT_TEAM_KILLS 2
#define STAT_LAST_TKER 3
#define STAT_TKER_RESOURCES 4
new RoundStartTime = 0;
new bool:RoundProtect = false;
new bool:MirrorDamageSlap = false;
new arrayPlayerStats[MAXPLAYERS + 1][5];
new Handle:arrayPlayerPunishments[MAXPLAYERS + 1] = {INVALID_HANDLE, ...};
new String:arrayPlayerName[MAXPLAYERS + 1][MAX_NAME_LENGTH];
new String:arrayPlayerTKerName[MAXPLAYERS + 1][MAX_NAME_LENGTH];
new arrayPlayerSpawnTime[MAXPLAYERS + 1] = { 0, ...};
// Event Array Variables
#define EVENT_ENABLED 0
#define EVENT_ROUND_START 1
#define EVENT_PLAYER_SPAWN 2
#define EVENT_PLAYER_HURT 3
#define EVENT_PLAYER_DEATH 4
#define EVENT_ROUND_END 5
new bool:bEventIsHooked[6] = { false, ...};
// ConVar Array Variables
#define CONVAR_ENABLED 0
#define CONVAR_MOD_ATK 1
#define CONVAR_MOD_TKPUNISH 2
#define CONVAR_MOD_SPAWNPROTECT 3
#define CONVAR_ROUND_START_PROTECT 4
#define CONVAR_PURGE_TIME 5
#define CONVAR_MIRROR_DAMAGE 6
#define CONVAR_MIRROR_DAMAGE_SLAP 7
new bool:bCvarIsHooked[8] = { false, ...};
#define ATK_PUNISHMENTS 13
#define ATK_NOFORGIVE 100
#define ATK_FORGIVE 0
#define ATK_SLAY 1
#define ATK_SLAP 2
#define ATK_BEACON 3
#define ATK_BURN 4
#define ATK_FIREBOMB 5
#define ATK_FREEZE 6
#define ATK_FREEZEBOMB 7
#define ATK_SLOW 8
#define ATK_BLIND 9
#define ATK_DRUG 10
#define ATK_TIMEBOMB 11
#define ATK_RESOURCES 12
new String:arrayPunishmentText[ATK_PUNISHMENTS][16] =
{
"Forgive",
"Slay",
"Slap",
"Beacon",
"Burn",
"FireBomb",
"Freeze",
"FreezeBomb",
"Slow",
"Blind",
"Drug",
"TimeBomb",
"Resources"
};
new g_Player_MaxHealth[MAXPLAYERS+1] = {0, ...};
new Handle:g_Purge_Timer = INVALID_HANDLE;
new Handle:g_Enable_Timer = INVALID_HANDLE;
// Include Key Value Functions
#include "antitk/keyvalues.sp"
// Create console variables
new Handle:g_Cvar_Enabled = INVALID_HANDLE;
new Handle:g_Cvar_AdminsImmune = INVALID_HANDLE;
new Handle:g_Cvar_AdminsFlag = INVALID_HANDLE;
new Handle:g_Cvar_RoundStartTime = INVALID_HANDLE;
new Handle:g_Cvar_RoundStartType = INVALID_HANDLE;
new Handle:g_Cvar_RoundStartExclude = INVALID_HANDLE;
new Handle:g_Cvar_MaxTKs = INVALID_HANDLE;
new Handle:g_Cvar_KarmaKills = INVALID_HANDLE;
new Handle:g_Cvar_AntiTKType = INVALID_HANDLE;
new Handle:g_Cvar_BanTime = INVALID_HANDLE;
new Handle:g_Cvar_PurgeTime = INVALID_HANDLE;
new Handle:g_Cvar_MirrorDamage = INVALID_HANDLE;
new Handle:g_Cvar_MirrorDamagePercent = INVALID_HANDLE;
new Handle:g_Cvar_MirrorDamageSlap = INVALID_HANDLE;
#if BEACON
new Handle:g_Cvar_Beacon = INVALID_HANDLE;
new Handle:g_Cvar_BeaconRadius = INVALID_HANDLE;
#endif
#if FIRE
new Handle:g_Cvar_Burn = INVALID_HANDLE;
new Handle:g_Cvar_BurnDuration = INVALID_HANDLE;
new Handle:g_Cvar_FireBomb = INVALID_HANDLE;
new Handle:g_Cvar_FireBombTicks = INVALID_HANDLE;
new Handle:g_Cvar_FireBombRadius = INVALID_HANDLE;
new Handle:g_Cvar_FireBombMode = INVALID_HANDLE;
#endif
#if ICE
new Handle:g_Cvar_Freeze = INVALID_HANDLE;
new Handle:g_Cvar_FreezeDuration = INVALID_HANDLE;
new Handle:g_Cvar_FreezeBomb = INVALID_HANDLE;
new Handle:g_Cvar_FreezeBombTicks = INVALID_HANDLE;
new Handle:g_Cvar_FreezeBombRadius = INVALID_HANDLE;
new Handle:g_Cvar_FreezeBombMode = INVALID_HANDLE;
#endif
#if GRAVITY
new Handle:g_Cvar_Slow = INVALID_HANDLE;
new Handle:g_Cvar_SlowSpeed = INVALID_HANDLE;
new Handle:g_Cvar_SlowGravity = INVALID_HANDLE;
#endif
#if BLIND
new Handle:g_Cvar_Blind = INVALID_HANDLE;
new Handle:g_Cvar_BlindAmount = INVALID_HANDLE;
#endif
#if DRUG
new Handle:g_Cvar_Drug = INVALID_HANDLE;
#endif
#if SLAP
new Handle:g_Cvar_Slap = INVALID_HANDLE;
new Handle:g_Cvar_SlapDamage = INVALID_HANDLE;
#endif
#if SLAY
new Handle:g_Cvar_Slay = INVALID_HANDLE;
new Handle:g_Cvar_SpecialSlay = INVALID_HANDLE;
#endif
#if TIMEBOMB
new Handle:g_Cvar_TimeBomb = INVALID_HANDLE;
new Handle:g_Cvar_TimeBombTicks = INVALID_HANDLE;
new Handle:g_Cvar_TimeBombRadius = INVALID_HANDLE;
new Handle:g_Cvar_TimeBombMode = INVALID_HANDLE;
#endif
new Handle:g_Cvar_Resources = INVALID_HANDLE;
new Handle:g_Cvar_ResourceSteal = INVALID_HANDLE;
new Handle:g_Cvar_ResourceAmount = INVALID_HANDLE;
// Mods
new g_GameEngine = SOURCE_SDK_UNKNOWN;
new bool:Insurgency = false;
new bool:ZombiePanic = false;
new bool:CounterStrike = false;
new bool:TF2 = false;
new bool:PVKII = false;
// Mod Protection Cvars
new Handle:g_Cvar_ATK = INVALID_HANDLE;
new Handle:g_Cvar_TKPunish = INVALID_HANDLE;
new Handle:g_Cvar_SpawnProtect = INVALID_HANDLE;
// Offsets
new offsInfected = -1;
new offsResourceAmount = -1;
// Team List (Log Helper)
new String: g_team_list[16][64];
// SourceBans
new bool:g_bSBAvailable = false;
// Include Extracted Funcommands Functions
#include "antitk/funcommands.sp"
#if SLAY
new g_Lightning;
#define SOUND_SLAY "weapons/hegrenade/explode3.wav"
#endif
public Plugin:myinfo =
{
name = "Anti-TK",
author = "Rothgar",
description = "Anti-TK Script",
version = VERSION,
url = "http://www.dawgclan.net"
};
#if _DEBUG
BuildLogFilePath()
{
// Build Log File Path
decl String:cTime[64];
FormatTime(cTime, sizeof(cTime), "logs/antitk_%Y%m%d.log");
BuildPath(Path_SM, AntiTK_LogFile, sizeof(AntiTK_LogFile), cTime);
LogAction(0, -1, "[Anti-TK Manager] Log File: %s", AntiTK_LogFile);
}
#endif
LogDebug(bool:Translation, String:text[], any:...)
{
decl String:message[255];
if (Translation)
VFormat(message, sizeof(message), "%T", 2);
else
if (strlen(text) > 0)
VFormat(message, sizeof(message), text, 3);
else
return false;
#if _DEBUG
#if _DEBUG_MODE == 1
LogToFile(AntiTK_LogFile, "[Anti-TK Manager] %s", message);
#elseif _DEBUG_MODE == 2
LogToGame("[Anti-TK Manager] %s", message);
#elseif _DEBUG_MODE == 3
PrintToChatAll("[Anti-TK Manager] %s", message);
#endif
return true;
#else
return false;
#endif
}
public OnPluginStart()
{
#if _DEBUG
BuildLogFilePath();
#endif
BuildKeyValuePath();
LogDebug(false, "Anti-TK Plugin Started! Version: %s", VERSION);
LoadTranslations("common.phrases");
LoadTranslations("funcommands.phrases");
LoadTranslations("antitk.phrases");
// Check Engine
g_GameEngine = GuessSDKVersion();
if (g_GameEngine > SOURCE_SDK_EPISODE2VALVE)
LogDebug(false, "Detected Game Engine Left 4 Dead");
else if (g_GameEngine > SOURCE_SDK_EPISODE1)
LogDebug(false, "Detected Game Engine Orange Box");
else if (g_GameEngine == SOURCE_SDK_EPISODE1)
LogDebug(false, "Detected Game Engine Episode 1");
else if (g_GameEngine == SOURCE_SDK_ORIGINAL)
LogDebug(false, "Detected Game Engine Original Source");
else if (g_GameEngine == SOURCE_SDK_UNKNOWN)
LogDebug(false, "Detected unknown Game Engine");
else
LogDebug(false, "Detected Game Engine Other");
// Check Mods
decl String:game_mod[32];
GetGameFolderName(game_mod, sizeof(game_mod));
if (strcmp(game_mod, "insurgency", false) == 0)
{
LogAction(0, -1, "[Anti-TK] %T", "Insurgency", LANG_SERVER);
Insurgency = true;
}
else if (strcmp(game_mod, "cstrike", false) == 0)
{
LogAction(0, -1, "[Anti-TK] %T", "CS", LANG_SERVER);
CounterStrike = true;
}
else if (strcmp(game_mod, "ZPS", false) == 0)
{
LogAction(0, -1, "[Anti-TK] %T", "ZPS", LANG_SERVER);
ZombiePanic = true;
}
else if (strcmp(game_mod, "tf", false) == 0)
{
LogAction(0, -1, "[Anti-TK] %T", "TF2", LANG_SERVER);
TF2 = true;
}
else if (strcmp(game_mod, "pvkii", false) == 0)
{
LogAction(0, -1, "[Anti-TK] %T", "PVKII", LANG_SERVER);
PVKII = true;
}
if (CounterStrike)
{
offsResourceAmount = FindSendPropOffs("CCSPlayer", "m_iAccount");
// Hook ATK Convars
g_Cvar_ATK = FindConVar("mp_autokick");
g_Cvar_TKPunish = FindConVar("mp_tkpunish");
// Hook Spawn Protect Convar
g_Cvar_SpawnProtect = FindConVar("mp_spawnprotectiontime");
}
// Find Game Offsets
if (ZombiePanic)
offsInfected = FindSendPropOffs("CHL2MP_Player", "m_IsInfected");
// Set UserMessageId for Fade. (based off funcommands.sp)
#if DRUG || BLIND
g_FadeUserMsgId = GetUserMessageId("Fade");
#endif
// Register Cvars
RegisterCvars();
SetConVarInt(g_Cvar_Enabled, 0);
// Hook Events
RegisterHooks();
AutoExecConfig(true, "antitk");
// Load TKers from Key Values File
ReadTKers();
// Initialize Player Arrays
antitk_Initialize();
#if _DEBUG
RegAdminCmd("sm_antitk_test", Command_Test, ADMFLAG_ROOT);
#endif
}
/*
OnPluginEnd()
{
// Plugin Unloading
}
*/
public OnAllPluginsLoaded()
{
if (LibraryExists("sourcebans"))
{
g_bSBAvailable = true;
LogDebug(false, "OnAllPluginsLoaded - SourceBans Plugin Detected.");
}
}
public OnLibraryAdded(const String:name[])
{
if (StrEqual(name, "sourcebans"))
{
g_bSBAvailable = true;
LogDebug(false, "OnAllPluginsLoaded - SourceBans Plugin Added.");
}
}
public OnLibraryRemoved(const String:name[])
{
if (StrEqual(name, "sourcebans"))
{
g_bSBAvailable = false;
LogDebug(false, "OnAllPluginsLoaded - SourceBans Plugin Removed.");
}
}
public OnConfigsExecuted()
{
LogDebug(false, "OnConfigsExecuted - Anti-TK Plugin - All Configs have been executed.");
// Handle Plugin load Hooks
//if (GetConVarBool(g_Cvar_Enabled))
//{
// SetConVarInt(g_Cvar_Enabled, 1);
//}
if (!bCvarIsHooked[CONVAR_PURGE_TIME])
{
HookConVarChange(g_Cvar_PurgeTime, CvarChange_PurgeTime);
bCvarIsHooked[CONVAR_PURGE_TIME] = true;
LogDebug(false, "OnConfigsExecuted - Hooked Purge Time variable.");
}
if (!bCvarIsHooked[CONVAR_MIRROR_DAMAGE])
{
HookConVarChange(g_Cvar_MirrorDamage, CvarChange_MirrorDamage);
bCvarIsHooked[CONVAR_MIRROR_DAMAGE] = true;
LogDebug(false, "OnConfigsExecuted - Hooked Mirror Damage variable.");
}
}
EnablePlugin()
{
if (GetConVarFloat(g_Cvar_RoundStartTime) > 0.0)
{
LogDebug(false, "EnablePlugin - Round Start Protection time is enabled. Running Enable_RoundStartProtection.");
Enable_RoundStartProtection();
}
if (!bEventIsHooked[EVENT_ROUND_END])
{
if (ZombiePanic)
HookEvent("ambient_play", Event_RoundEnd, EventHookMode_PostNoCopy);
else if (TF2)
{
//teamplay_round_start teamplay_restart_round
}
else
HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
bEventIsHooked[EVENT_ROUND_END] = true;
LogDebug(false, "EnablePlugin - Hooked Round End Event.");
}
if (!bEventIsHooked[EVENT_PLAYER_DEATH])
{
HookEvent("player_death",Event_PlayerDeath);
bEventIsHooked[EVENT_PLAYER_DEATH] = true;
LogDebug(false, "EnablePlugin - Hooked Player Death Event.");
}
if (!bEventIsHooked[EVENT_PLAYER_SPAWN])
{
HookEvent("player_spawn",Event_PlayerSpawn);
bEventIsHooked[EVENT_PLAYER_SPAWN] = true;
LogDebug(false, "EnablePlugin - Hooked Player Spawn Event.");
}
if (!bEventIsHooked[EVENT_PLAYER_HURT])
{
HookEvent("player_hurt",Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = true;
LogDebug(false, "EnablePlugin - Hooked Player Hurt Event.");
}
}
DisablePlugin()
{
if (GetConVarFloat(g_Cvar_RoundStartTime) > 0.0)
Disable_RoundStartProtection();
if (bEventIsHooked[EVENT_ROUND_END])
{
if (ZombiePanic)
UnhookEvent("ambient_play", Event_RoundEnd, EventHookMode_PostNoCopy);
else if (TF2)
{
//teamplay_round_start teamplay_restart_round
}
else
UnhookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
bEventIsHooked[EVENT_ROUND_END] = false;
LogDebug(false, "DisablePlugin - Unhooked Round End Event.");
}
if (bEventIsHooked[EVENT_PLAYER_DEATH])
{
UnhookEvent("player_death",Event_PlayerDeath);
bEventIsHooked[EVENT_PLAYER_DEATH] = false;
LogDebug(false, "DisablePlugin - Unhooked Player Death Event.");
}
if (bEventIsHooked[EVENT_PLAYER_SPAWN])
{
UnhookEvent("player_spawn",Event_PlayerSpawn);
bEventIsHooked[EVENT_PLAYER_SPAWN] = false;
LogDebug(false, "DisablePlugin - Unhooked Player Spawn Event.");
}
if (bEventIsHooked[EVENT_PLAYER_HURT])
{
UnhookEvent("player_hurt",Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = false;
LogDebug(false, "DisablePlugin - Unhooked Player Hurt Event.");
}
}
public CvarChange_Enabled(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
LogDebug(false, "CvarChange_Enabled - Anti-TK Plugin Enabled cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
if (!StrEqual(oldvalue, newvalue))
if (StringToInt(newvalue) == 1)
{
LogDebug(false, "CvarChange_Enabled - Enabled (Hooking Events).");
EnablePlugin();
}
else if (StringToInt(newvalue) == 0)
{
LogDebug(false, "CvarChange_Enabled - Disabled (Unhooking Events).");
DisablePlugin();
}
}
// Disable Mod Based ATK System
public CvarChange_ATK(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
#if _DEBUG
LogDebug(false, "CvarChange_ATK - Anti TK cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
#endif
if (StringToInt(newvalue) > 0)
{
#if _DEBUG
LogDebug(false, "CvarChange_ATK - Disabling Mod Anti TK handler.");
#endif
SetConVarInt(cvar, 0);
}
}
public CvarChange_TKPunish(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
#if _DEBUG
LogDebug(false, "CvarChange_TKPunish - TK Punish cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
#endif
if (StringToInt(newvalue) > 0)
{
#if _DEBUG
LogDebug(false, "CvarChange_TKPunish - Disabling Mod TK Punish handler.");
#endif
SetConVarInt(cvar, 0);
}
}
public CvarChange_SpawnProtect(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
#if _DEBUG
LogDebug(false, "CvarChange_SpawnProtect - Spawn Protect cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
#endif
if (StringToInt(newvalue) > 0)
{
#if _DEBUG
LogDebug(false, "CvarChange_SpawnProtect - Disabling Mod Spawn Protect handler.");
#endif
SetConVarInt(cvar, 0);
}
}
Enable_RoundStartProtection()
{
if (!bEventIsHooked[EVENT_ROUND_START])
{
if (ZombiePanic)
HookEvent("game_round_restart", Event_RoundStart, EventHookMode_PostNoCopy);
else
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
bEventIsHooked[EVENT_ROUND_START] = true;
}
if (!bEventIsHooked[EVENT_PLAYER_HURT])
{
HookEvent("player_hurt", Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = true;
}
}
Disable_RoundStartProtection()
{
if (bEventIsHooked[EVENT_ROUND_START])
{
if (ZombiePanic)
UnhookEvent("game_round_restart", Event_RoundStart, EventHookMode_PostNoCopy);
else
UnhookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
bEventIsHooked[EVENT_ROUND_START] = false;
}
if (GetConVarInt(g_Cvar_MirrorDamage) <= 0)
{
if (bEventIsHooked[EVENT_PLAYER_HURT])
{
if (GetConVarInt(g_Cvar_MirrorDamage) > 0)
{
UnhookEvent("player_hurt", Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = false;
}
}
}
}
public CvarChange_RoundStartProtection(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
LogDebug(false, "CvarChange_RoundStartProtection - Round Start Protection cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
if (!StrEqual(oldvalue, newvalue))
if (StringToInt(newvalue) > 0)
{
if (GetConVarBool(g_Cvar_Enabled))
{
LogDebug(false, "CvarChange_RoundStartProtection - Enabled (Hooking Events).");
Enable_RoundStartProtection();
}
}
else
{
if (GetConVarBool(g_Cvar_Enabled))
{
LogDebug(false, "CvarChange_RoundStartProtection - Disabled (Unhooking Events).");
Disable_RoundStartProtection();
}
}
}
public CvarChange_MirrorDamage(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
LogDebug(false, "CvarChange_MirrorDamage - Mirror Damage cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
if (!StrEqual(oldvalue, newvalue))
if (StringToInt(newvalue) > 0)
{
if (GetConVarBool(g_Cvar_Enabled))
{
if (!bEventIsHooked[EVENT_PLAYER_HURT])
{
HookEvent("player_hurt", Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = true;
}
}
}
else
{
if (GetConVarBool(g_Cvar_Enabled))
{
if (bEventIsHooked[EVENT_PLAYER_HURT])
{
if (GetConVarFloat(g_Cvar_RoundStartTime) == 0.0)
{
UnhookEvent("player_hurt", Event_PlayerHurt);
bEventIsHooked[EVENT_PLAYER_HURT] = false;
}
}
}
}
}
public CvarChange_MirrorDamageSlap(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
LogDebug(false, "CvarChange_MirrorDamageSlap - Mirror Damage Slap cvar has been changed. Old value: %s New value: %s", oldvalue[0], newvalue[0]);
if (!StrEqual(oldvalue, newvalue))
if (StringToInt(newvalue) > 0)
MirrorDamageSlap = true;
else
MirrorDamageSlap = false;
}
RegisterHooks()
{
LogDebug(false, "Running RegisterHooks()");
if (!bCvarIsHooked[CONVAR_ENABLED])
{
HookConVarChange(g_Cvar_Enabled, CvarChange_Enabled);
bCvarIsHooked[CONVAR_ENABLED] = true;
LogDebug(false, "RegisterHooks - Hooked Enable variable.");
}
if (!bCvarIsHooked[CONVAR_ROUND_START_PROTECT])
{
HookConVarChange(g_Cvar_RoundStartTime, CvarChange_RoundStartProtection);
bCvarIsHooked[CONVAR_ROUND_START_PROTECT] = true;
LogDebug(false, "RegisterHooks - Hooked Round Start Protection variable.");
}
if (g_Cvar_ATK != INVALID_HANDLE)
{
if (!bCvarIsHooked[CONVAR_MOD_ATK])
{
HookConVarChange(g_Cvar_ATK, CvarChange_ATK);
bCvarIsHooked[CONVAR_MOD_ATK] = true;
#if _DEBUG
LogDebug(false, "RegisterHooks - Hooked Mod Based ATK variable.");
#endif
SetConVarInt(g_Cvar_ATK, 0);
}
}
if (g_Cvar_TKPunish != INVALID_HANDLE)
{
if (!bCvarIsHooked[CONVAR_MOD_TKPUNISH])
{
HookConVarChange(g_Cvar_TKPunish, CvarChange_TKPunish);
bCvarIsHooked[CONVAR_MOD_TKPUNISH] = true;
#if _DEBUG
LogDebug(false, "RegisterHooks - Hooked Mod Based TK Punish variable.");
#endif
SetConVarInt(g_Cvar_TKPunish, 0);
}
}
if (g_Cvar_SpawnProtect != INVALID_HANDLE)
{
if (!bCvarIsHooked[CONVAR_MOD_SPAWNPROTECT])
{
HookConVarChange(g_Cvar_SpawnProtect, CvarChange_SpawnProtect);
bCvarIsHooked[CONVAR_MOD_SPAWNPROTECT] = true;
#if _DEBUG
LogDebug(false, "RegisterHooks - Hooked Mod Based Spawn Protection variable.");
#endif
SetConVarInt(g_Cvar_SpawnProtect, 0);
}
}
if (g_Cvar_MirrorDamageSlap != INVALID_HANDLE)
{
if (!bCvarIsHooked[CONVAR_MIRROR_DAMAGE_SLAP])
{
HookConVarChange(g_Cvar_MirrorDamageSlap, CvarChange_MirrorDamageSlap);
bCvarIsHooked[CONVAR_MIRROR_DAMAGE_SLAP] = true;
#if _DEBUG
LogDebug(false, "RegisterHooks - Hooked Mirror Damage Slap variable.");
#endif
}
}
}
RegisterCvars()
{
// Register all console variables
LogDebug(false, "Running RegisterCvars()");
CreateConVar("sm_antitk_version", VERSION, "Anti-TK management plugin", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED| FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY);
g_Cvar_Enabled = CreateConVar("sm_antitk_enable", "1", "Is the Anti-TK Manager enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_AdminsImmune = CreateConVar("sm_antitk_admins_immune", "0", "Are Admins immune to the Anti-TK Manager? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_AdminsFlag = CreateConVar("sm_antitk_admins_flag", "", "Admin Flag for immunity? Leave Blank for any flag.");
g_Cvar_RoundStartTime = CreateConVar("sm_antitk_round_start_protect_time", "0.0", "Time in seconds the Anti-TK Manager Round Start Protection should take effect. [0 = DISABLED]");
g_Cvar_RoundStartType = CreateConVar("sm_antitk_round_start_type", "0", "Type of action that is taken during the Round Start Protection? [0 = FORGIVE, 1 = SLAY, 2 = SLAP, 3 = BEACON, 4 = BURN, 5 = FIRE BOMB, 6 = FREEZE, 7 = FREEZE BOMB, 8 = SLOW, 9 = BLIND, 10 = DRUG, 11 = TIME BOMB, 12 = RESOURCES, 100 = NO FORGIVE]");
g_Cvar_RoundStartExclude = CreateConVar("sm_antitk_round_start_exclude", "1", "Should we exclude TK's from being tracked during the Round Start Protection? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_MaxTKs = CreateConVar("sm_antitk_max", "0", "Maximum number of TK's allowed before Kick/Ban action occurs.");
g_Cvar_KarmaKills = CreateConVar("sm_antitk_karma_kills", "10", "Number of enemy kills required to remove a TK point. [DEFAULT: 10]");
g_Cvar_AntiTKType = CreateConVar("sm_antitk_type", "0", "Type of action that is taken once the TK limit has been exceeded? [0 = NOTHING, 1 = KICK, 2 = BAN]", 0, true, 0.0, true, 2.0);
g_Cvar_BanTime = CreateConVar("sm_antitk_ban_time", "60", "Time in minutes player should be banned for excessive TK's. [DEFAULT: 60 minutes]");
g_Cvar_PurgeTime = CreateConVar("sm_antitk_purge_time", "1800.0", "Time in seconds TKer data should be kept before purging. [DEFAULT: 30 minutes]");
g_Cvar_MirrorDamage = CreateConVar("sm_antitk_mirror_type", "0", "Type of mirrored damage for when a player is attacked by team player? [0 = NONE, 1 = ATTACKER, 2 = ATTACKER + RETURN HEALTH]", 0, true, 0.0, true, 2.0);
g_Cvar_MirrorDamagePercent = CreateConVar("sm_antitk_mirror_percent", "100", "Mirror damage percent that is returned to attacker? [DEFAULT: 100 Percent]", 0, true, 0.0, true, 100.0);
g_Cvar_MirrorDamageSlap = CreateConVar("sm_antitk_mirror_slap", "0", "Should we slap the attacker when mirroring damage? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
#if BEACON
g_Cvar_Beacon = CreateConVar("sm_antitk_beacon", "1", "Is the Anti-TK Manager Beacon option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_BeaconRadius = CreateConVar("sm_antitk_beacon_radius", "375.0", "Anti-TK Manager radius for beacon's light rings. [DEFAULT: 375]", 0, true, 50.0, true, 1500.0);
#endif
#if FIRE
g_Cvar_Burn = CreateConVar("sm_antitk_burn", "1", "Is the Anti-TK Manager Burn option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_BurnDuration = CreateConVar("sm_antitk_burn_duration", "20", "Anti-TK Manager Burn Duration. [DEFAULT: 20 seconds]", 0, true, 0.5, true, 20.0);
g_Cvar_FireBomb = CreateConVar("sm_antitk_firebomb", "1", "Is the Anti-TK Manager FireBomb option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_FireBombTicks = CreateConVar("sm_antitk_firebomb_fuse", "10.0", "Anti-TK Manager FireBomb fuse length. [DEFAULT: 10 seconds]", 0, true, 5.0, true, 120.0);
g_Cvar_FireBombRadius = CreateConVar("sm_antitk_firebomb_radius", "600", "Anti-TK Manager FireBomb blast radius. [DEFAULT: 600]", 0, true, 50.0, true, 3000.0);
g_Cvar_FireBombMode = CreateConVar("sm_antitk_firebomb_mode", "0", "Who is targeted by the Anti-TK Manager FireBomb? [0 = ATTACKER, 1 = TEAM, 2 = EVERYONE]", 0, true, 0.0, true, 2.0);
#endif
#if ICE
g_Cvar_Freeze = CreateConVar("sm_antitk_freeze", "1", "Is the Anti-TK Manager Freeze option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_FreezeDuration = CreateConVar("sm_antitk_freeze_duration", "10", "Anti-TK Manager Freeze Duration. [DEFAULT: 10 seconds]", 0, true, 1.0, true, 120.0);
g_Cvar_FreezeBomb = CreateConVar("sm_antitk_freezebomb", "1", "Is the Anti-TK Manager FreezeBomb option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_FreezeBombTicks = CreateConVar("sm_antitk_freezebomb_fuse", "10.0", "Anti-TK Manager FreezeBomb fuse length. [DEFAULT: 10 seconds]", 0, true, 5.0, true, 120.0);
g_Cvar_FreezeBombRadius = CreateConVar("sm_antitk_freezebomb_radius", "600", "Anti-TK Manager FreezeBomb blast radius. [DEFAULT: 600]", 0, true, 50.0, true, 3000.0);
g_Cvar_FreezeBombMode = CreateConVar("sm_antitk_freezebomb_mode", "0", "Who is targeted by the Anti-TK Manager FreezeBomb? [0 = ATTACKER, 1 = TEAM, 2 = EVERYONE]", 0, true, 0.0, true, 2.0);
#endif
#if TIMEBOMB
g_Cvar_TimeBomb = CreateConVar("sm_antitk_timebomb", "1", "Is the Anti-TK Manager TimeBomb option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_TimeBombTicks = CreateConVar("sm_antitk_timebomb_fuse", "10.0", "Anti-TK Manager TimeBomb fuse length. [DEFAULT: 10 seconds]", 0, true, 5.0, true, 120.0);
g_Cvar_TimeBombRadius = CreateConVar("sm_antitk_timebomb_radius", "600", "Anti-TK Manager TimeBomb blast radius. [DEFAULT: 600]", 0, true, 50.0, true, 3000.0);
g_Cvar_TimeBombMode = CreateConVar("sm_antitk_timebomb_mode", "0", "Who is targeted by the Anti-TK Manager TimeBomb? [0 = ATTACKER, 1 = TEAM, 2 = EVERYONE]", 0, true, 0.0, true, 2.0);
#endif
#if GRAVITY
g_Cvar_Slow = CreateConVar("sm_antitk_slow", "1", "Is the Anti-TK Manager Slow option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_SlowSpeed = CreateConVar("sm_antitk_slow_speed", "0.4", "Anti-TK Manager Slow Speed Multiplier. [DEFAULT: 0.4]");
g_Cvar_SlowGravity = CreateConVar("sm_antitk_slow_gravity", "1.4", "Anti-TK Manager Slow Gravity Multiplier. [DEFAULT: 1.4]");
#endif
#if BLIND
g_Cvar_Blind = CreateConVar("sm_antitk_blind", "1", "Is the Anti-TK Manager Blind option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_BlindAmount = CreateConVar("sm_antitk_blind_amount", "230", "Anti-TK Manager Blind Amount. [DEFAULT: 230]", 0, true, 0.0, true, 255.0);
#endif
#if DRUG
g_Cvar_Drug = CreateConVar("sm_antitk_drug", "1", "Is the Anti-TK Manager Drug option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
#endif
#if SLAP
g_Cvar_Slap = CreateConVar("sm_antitk_slap", "1", "Is the Anti-TK Manager Slap option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_SlapDamage = CreateConVar("sm_antitk_slap_damage", "50", "Anti-TK Manager Slap Damage. [DEFAULT: 50 health]", 0, true, 0.0, true, 100.0);
#endif
#if SLAY
g_Cvar_Slay = CreateConVar("sm_antitk_slay", "1", "Is the Anti-TK Manager Slay option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_SpecialSlay = CreateConVar("sm_antitk_special_slay", "0", "Should we use a special version of the slay? (May not work with all mods) [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
#endif
g_Cvar_Resources = CreateConVar("sm_antitk_resources", "0", "Is the Anti-TK Manager resource remove option enabled or disabled? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_ResourceSteal = CreateConVar("sm_antitk_resource_steal", "1", "Should the Anti-TK resource option give resources to the victim? [0 = FALSE, 1 = TRUE]", 0, true, 0.0, true, 1.0);
g_Cvar_ResourceAmount = CreateConVar("sm_antitk_resource_amount", "0.2", "Anti-TK Manager resource removal amount. (0.0-1.0 equates to a percentage, otherwise it's an amount) [DEFAULT: 0.20 (20%)]");
}
public Action:Command_Test(client, args)
{
PrintToChat(client, "*************************");
PrintToChat(client, "Health: %i", GetClientHealth(client));
PrintToChat(client, "MaxHealth: %i", g_Player_MaxHealth[client]);
SetEntityHealth(client, 70);
PrintToChat(client, "*************************");
}
public Action:Timer_EnableAntiTK(Handle:timer, any:client)
{
LogDebug(false, "Timer_EnableAntiTK - Re-Enabling Anti-TK");
SetConVarInt(g_Cvar_Enabled, 1);
g_Enable_Timer = INVALID_HANDLE;
return Plugin_Stop;
}
public CvarChange_PurgeTime(Handle:cvar, const String:oldvalue[], const String:newvalue[])
{
LogDebug(false, "CvarChange_PurgeTime - Purge time has been changed, updating timer. Old interval: %s New interval: %s", oldvalue, newvalue);
if (g_Purge_Timer != INVALID_HANDLE)
{
CloseHandle(g_Purge_Timer);
g_Purge_Timer = INVALID_HANDLE;
}
g_Purge_Timer = CreateTimer(StringToFloat(newvalue), Timer_PurgeTKerData, _, TIMER_REPEAT);
}
// Function from Log Helper made by psychonic
// http://forums.alliedmods.net/showthread.php?t=100084
stock GetTeams(bool:insmod = false)
{
if (!insmod)
{
new max_teams_count = GetTeamCount();
for (new team_index = 0; (team_index < max_teams_count); team_index++)
{
decl String: team_name[64];
GetTeamName(team_index, team_name, sizeof(team_name));
if (strcmp(team_name, "") != 0)
{
g_team_list[team_index] = team_name;
}
}
}
else
{
// they really need to get their act together... GetTeamName() would be awesome since they can't even keep their team indexes consistent
decl String:mapname[64];
GetCurrentMap(mapname, sizeof(mapname));
if (strcmp(mapname, "ins_karam") == 0 || strcmp(mapname, "ins_baghdad") == 0)
{
g_team_list[1] = "Iraqi Insurgents";
g_team_list[2] = "U.S. Marines";
}
else
{
g_team_list[1] = "U.S. Marines";
g_team_list[2] = "Iraqi Insurgents";
}
g_team_list[0] = "Unassigned";
g_team_list[3] = "SPECTATOR";
}
}
ResetPlayer(index, bool:FromDatabase = false)
{
// Last TKer name
arrayPlayerTKerName[index] = "";
if (!FromDatabase)
{
#if _DEBUG >= 2
LogDebug(false, "Reseting arrays for index: %d", index);
#endif
// Reset Player Values
arrayPlayerStats[index][STAT_KARMA] = 0;
arrayPlayerStats[index][STAT_KILLS] = 0;
arrayPlayerStats[index][STAT_TEAM_KILLS] = 0;
arrayPlayerStats[index][STAT_LAST_TKER] = 0;
arrayPlayerStats[index][STAT_TKER_RESOURCES] = 0;
arrayPlayerSpawnTime[index] = 0;
}
else
{
// Retrieve TKer Data
if (RetrieveTKer(index))
{
#if _DEBUG >= 2
LogDebug(false, "TKer data retrieved from file for index: %i", index);
#endif
}
else
{
#if _DEBUG >= 2
LogDebug(false, "Could not find TKer data in file for index: %i", index);
LogDebug(false, "Reseting arrays for index: %d", index);
#endif
// Initialize Player Stats
arrayPlayerStats[index][STAT_KARMA] = 0;
arrayPlayerStats[index][STAT_KILLS] = 0;
arrayPlayerStats[index][STAT_TEAM_KILLS] = 0;
}
arrayPlayerStats[index][STAT_LAST_TKER] = 0;
arrayPlayerStats[index][STAT_TKER_RESOURCES] = 0;
arrayPlayerSpawnTime[index] = 0;
}
if (arrayPlayerPunishments[index] != INVALID_HANDLE)
{
// Punishment Array already exists clear it?
#if _DEBUG >= 2
LogDebug(false, "Clearing Old Punishments Array?: %i", arrayPlayerPunishments[index]);
#endif
ClearArray(arrayPlayerPunishments[index]);
}
else
{
// Create Array for Punishment queue
#if _DEBUG >= 2
LogDebug(false, "Creating New Punishments Array For Client: %i", index);
#endif
arrayPlayerPunishments[index] = CreateArray(1);
}
// Reset Max Player Health
g_Player_MaxHealth[index] = 0;
}
// Player initialize functions
InitializePlayer(index, bool:FromDatabase = false)
{
#if _DEBUG >= 2
LogDebug(false, "Running InitializePlayer() on player: %d", index);
#endif
if (!IsFakeClient(index))
ResetPlayer(index, FromDatabase);
/*
if (arrayPlayerStats[index] != INVALID_HANDLE)
{
// Stats Array already exists clear it?
LogDebug("Clearing Old Stats Array?: %i", arrayPlayerStats[index]);
ClearArray(arrayPlayerStats[index]);
}
else
{
// Create Array for Stats
LogDebug("Creating New Stats Array For Client: %i", index);
arrayPlayerStats[index] = CreateArray(1);
}
// Retrieve Old Player Settings?
// Initialize New Player
// Karma
PushArrayCell(arrayPlayerStats[index], 0);
// Kills
PushArrayCell(arrayPlayerStats[index], 0);
// Team Kills
PushArrayCell(arrayPlayerStats[index], 0);
// Last TKer player index
PushArrayCell(arrayPlayerStats[index], 0);
LogDebug("TEST TK COUNT???: %i CLIENT: %d", GetArrayCell(arrayPlayerStats[index], STAT_TEAM_KILLS), index);
*/
}
antitk_Initialize()
{
LogDebug(false, "antitk_Initialize - Anti-TK Plugin Initializing!");
if (GetConVarBool(g_Cvar_Enabled))
{
LogDebug(false, "antitk_Initialize - Plugin Enabled! Running EnablePlugin.");
EnablePlugin();
}
new players = GetMaxClients();
for (new i = 1; i <= players; i++)
{
if (IsClientInGame(i))
{
// Initialize Player Settings
InitializePlayer(i, true);
}
}
if (g_Purge_Timer == INVALID_HANDLE)
{
LogDebug(false, "antitk_Initialize - Creating Purge timer.");
g_Purge_Timer = CreateTimer(GetConVarFloat(g_Cvar_PurgeTime), Timer_PurgeTKerData, _, TIMER_REPEAT);
}
else
LogDebug(false, "antitk_Initialize - ERROR: Purge timer already exists? This should not happen?");
// Run Initial Purge
PurgeTKerData(0, false);
}
public Action:Timer_PurgeTKerData(Handle:Timer)
{
#if _DEBUG >= 2
LogDebug(false, "Timer_PurgeTKerData - Timer is executing... Interval: %f", GetConVarFloat(g_Cvar_PurgeTime));
#endif
new Float:PurgeTime = GetConVarFloat(g_Cvar_PurgeTime);
PurgeTKerData(RoundToFloor(PurgeTime), true);
#if _DEBUG >= 2
LogDebug(false, "Timer_PurgeTKerData - Timer has finished, waiting for next interval.");
#endif
return Plugin_Continue;
}
// Reset punishment effects
KillPunishments(index = 0)
{
LogDebug(false, "KillPunishments - Resetting all punishments.");
// Kill Punishments (based off funcommands.sp)
if (index == 0)
{
#if BEACON
KillAllBeacons();
#endif
#if FIRE
KillAllFireBombs();
#endif
#if ICE
KillAllFreezes();
#endif
#if TIMEBOMB
KillAllTimeBombs();
#endif
#if DRUG
KillAllDrugs();
#endif
}
else
{
#if BEACON
KillBeacon(index);
#endif
#if FIRE
KillFireBomb(index);
#endif
#if ICE
UnfreezeClient(index);
#endif
#if TIMEBOMB
KillTimeBomb(index);
#endif
#if DRUG
KillDrug(index);
#endif
}
}
// Events
public OnMapStart()
{
#if _DEBUG
BuildLogFilePath();
#endif
// Precache Sounds (based off funcommands.sp)
PrecacheSound(SOUND_BLIP, true);
PrecacheSound(SOUND_BEEP, true);
PrecacheSound(SOUND_FINAL, true);
PrecacheSound(SOUND_BOOM, true);
PrecacheSound(SOUND_FREEZE, true);
#if SLAY
PrecacheSound(SOUND_SLAY, true);
#endif
// Precache Models & Index (based off funcommands.sp)
#if BEACON || TIMEBOMB || FIRE || ICE
g_BeamSprite = PrecacheModel("materials/sprites/laser.vmt");
g_HaloSprite = PrecacheModel("materials/sprites/halo01.vmt");
#endif
#if ICE || TIMEBOMB
g_ExplosionSprite = PrecacheModel("sprites/sprite_fire01.vmt");
#endif
#if ICE
g_GlowSprite = PrecacheModel("sprites/blueglow2.vmt");
g_BeamSprite2 = PrecacheModel("sprites/bluelight1.vmt");
#endif
#if SLAY
g_Lightning = PrecacheModel("sprites/lgtning.vmt");
#endif
AutoExecConfig(true, "antitk");
// Load TKers from Key Values
ReadTKers();
// Cache Team Names for Log Events (Log Helper)
GetTeams(Insurgency);
}
public OnMapEnd()
{
LogDebug(false, "Map Ended - Resetting all punishments.");
// Kill Punishments
KillPunishments();
// Save TKer Data
SaveTKers();
}
public OnClientPostAdminCheck(index)
{
#if _DEBUG >= 2
LogDebug(false, "OnClientPostAdminCheck - Client: %d", index);
#endif
InitializePlayer(index, true);
// Store player name in case they leave the server.
GetClientName(index, arrayPlayerName[index], MAX_NAME_LENGTH);
}
public OnClientDisconnect(index)
{
#if _DEBUG >= 2
LogDebug(false, "OnClientDisconnected - Client: %d", index);
#endif
// Store Player Stats History
if (!IsFakeClient(index))
{
SaveTKer(index);
ResetPlayer(index, false);
}
// Kill Punishments?
//KillPunishments(index);
}
public Action:Event_RoundStart(Handle:event,const String:name[],bool:dontBroadcast)
{
LogDebug(false, "Round Started - Checking Round Protection.");
if (GetConVarBool(g_Cvar_Enabled))
{
new Float:ProtectTime = GetConVarFloat(g_Cvar_RoundStartTime);
if (GetConVarFloat(g_Cvar_RoundStartTime) > 0.0)
{
LogDebug(false, "Event_RoundStart - Round Protection Enabled.");
if (ProtectTime > 0)
{
LogDebug(false, "Event_RoundStart - Round Start Time set to %f seconds.", ProtectTime);
RoundStartTime = GetTime();
RoundProtect = true;
//PrintToChatAll("%t", "Eject_Announce_Kick", tkerName);
}
}
else
{
LogDebug(false, "Event_RoundStart - Round Protection Disabled.");
if (ProtectTime > 0)
{
LogDebug(false, "Event_RoundStart - Round Start Time set to %i seconds. Disabling Plugin.");
SetConVarInt(g_Cvar_Enabled, 0);
if (g_Enable_Timer != INVALID_HANDLE)
{
CloseHandle(g_Enable_Timer);
g_Enable_Timer = INVALID_HANDLE;
}
g_Enable_Timer = CreateTimer(ProtectTime, Timer_EnableAntiTK);
//PrintToChatAll("%t", "Eject_Announce_Kick", tkerName);
}
}
}
return Plugin_Handled;
}
public Action:Event_RoundEnd(Handle:event,const String:name[],bool:dontBroadcast)
{
LogDebug(false, "Round Ended - Resetting all punishments.");
// Kill Punishments
KillPunishments();
return Plugin_Handled;
}
Action:CheckTKDetails(victim, attacker, bool:PlayerDeath=true)
{
decl String:attacker_name[MAX_NAME_LENGTH];
if(attacker != 0 && victim != 0 && IsClientConnected(attacker) && IsClientConnected(victim) && victim != attacker)
{
if (GetConVarBool(g_Cvar_AdminsImmune))
{
if (CheckAdminImmunity(attacker))
return Plugin_Continue;
}
new victimTeam = GetClientTeam(victim);
new attackerTeam = GetClientTeam(attacker);
if(victimTeam == attackerTeam)
{
GetClientName(attacker, attacker_name, sizeof(attacker_name));
// Handle TK Event
LogDebug(false, "Player TK event triggered: Victim Team: %i Attacker Team: %i", victimTeam, attackerTeam);
// ZPS Related Check
if (ZombiePanic)
{
if (offsInfected > 0)
{
new infected = GetEntDataEnt2(victim, offsInfected);
if (infected && (victimTeam == TEAM_ZPS_SURVIVOR))
{
LogDebug(false, "TK'd Infected Human, Legitimate?");
return Plugin_Continue;
}
}
}
// Store Victim's last Tk'er details
arrayPlayerStats[victim][STAT_LAST_TKER] = attacker;
arrayPlayerTKerName[victim] = attacker_name;
LogDebug(false, "WARNING: Attackers name: %s",attacker_name);
if (RoundProtect)
{
new curTime = GetTime();
new ProtectTime = GetConVarInt(g_Cvar_RoundStartTime);
if ((curTime - RoundStartTime) > ProtectTime)
{
RoundProtect = false;
if (PlayerDeath)
{
// Show TK Punishment menu to Victim
LogDebug(false, "Creating TK Menu to victim for player: %s",attacker_name);
CreateTKMenu(victim);
}
}
else
{
LogDebug(false, "Round protection event");
new ProtectType = GetConVarInt(g_Cvar_RoundStartType);
if (ProtectType == 0)
ForgivePlayer(victim, attacker);
else
PunishPlayer(victim, attacker, ProtectType);
}
}
else
{
// Show TK Punishment menu to Victim
LogDebug(false, "Creating TK Menu for player: %s",attacker_name);
CreateTKMenu(victim);
}
}
else
{
if (PlayerDeath)
{
GetClientName(attacker, attacker_name, sizeof(attacker_name));
// Handle Karma
new karma_kills = GetConVarInt(g_Cvar_KarmaKills);
if (karma_kills)
{
arrayPlayerStats[attacker][STAT_KILLS]++;
LogDebug(false, "Calculating Karma for player: %s Kills: %d Required: %d",attacker_name, arrayPlayerStats[attacker][STAT_KILLS], karma_kills);
if (arrayPlayerStats[attacker][STAT_KILLS] >= karma_kills)
if (arrayPlayerStats[attacker][STAT_TEAM_KILLS] > 0)
{
arrayPlayerStats[attacker][STAT_TEAM_KILLS]--;
arrayPlayerStats[attacker][STAT_KILLS] = 0;
LogDebug(false, "Player: %s has received Karma New TK Count: %d",attacker_name, arrayPlayerStats[attacker][STAT_TEAM_KILLS]);
}
}
}
}
}
return Plugin_Continue;
}
public Action:Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast){
if (GetConVarBool(g_Cvar_Enabled))
{
new victim = GetClientOfUserId(GetEventInt(event,"userid"));
new attacker = GetClientOfUserId(GetEventInt(event,"attacker"));
LogDebug(false, "Event_PlayerHurt - Attacker: %i Victim: %i", attacker, victim);
if(attacker != 0)
{
if (GetConVarBool(g_Cvar_AdminsImmune))
{
if (CheckAdminImmunity(attacker))
return Plugin_Continue;
}
if (RoundProtect)
{
new curTime = GetTime();
new ProtectTime = GetConVarInt(g_Cvar_RoundStartTime);
if ((curTime - RoundStartTime) > ProtectTime)
{
RoundProtect = false;
}
else
{
LogDebug(false, "Event_PlayerHurt - Round Protection");
return CheckTKDetails(victim, attacker, false);
}
}
if (GetConVarInt(g_Cvar_MirrorDamage) > 0)
{
new Float:mirror_percent = GetConVarFloat(g_Cvar_MirrorDamagePercent);
if (mirror_percent > 0.0)
{
if( ( (attacker > 0) && (victim > 0) ) && (victim != attacker) )
{
if ( GetClientTeam(attacker) == GetClientTeam(victim) )
{
LogDebug(false, "Event_PlayerHurt - Mirror Damage enabled. Attacker and Victim are on the same team and valid players.");
//new bool:spawnAttack = ((GetTime() - SpawnTime[victim]) <= GetConVarInt(g_CvarSpawnProtect));
new damage_armor = 0;
decl damage_health;
if (PVKII)
{
damage_health = GetEventInt(event,"health");
}
else if (CounterStrike)
{
damage_health = GetEventInt(event,"dmg_health");
}
else
{
damage_health = GetEventInt(event,"health");
damage_armor = 0;
}
LogDebug(false, "Event_PlayerHurt - Damage done to health: %i armor: %i", damage_health, damage_armor);
if ( IsClientInGame(attacker) && IsPlayerAlive(attacker) )
{
LogDebug(false, "Event_PlayerHurt - Attackers Health: %i", GetClientHealth(attacker));
LogDebug(false, "Event_PlayerHurt - Mirror Damage Percent: %f", mirror_percent);
new mirror_damage_health = RoundFloat(damage_health * (mirror_percent / 100.0));
LogDebug(false, "Event_PlayerHurt - Mirror Damage Health: %i Armor: %i", mirror_damage_health, RoundFloat(damage_armor * (mirror_percent / 100.0)));
new attackerHealth = GetClientHealth(attacker) - mirror_damage_health;
new attackerArmor = GetClientArmor(attacker) - RoundFloat(damage_armor * (mirror_percent / 100.0));
LogDebug(false, "Event_PlayerHurt - Attackers health will become: %i", attackerHealth);
LogDebug(false, "Event_PlayerHurt - Attackers armor will become: %i", attackerArmor);
if(attackerHealth <= 0)
{
LogDebug(false, "Event_PlayerHurt - New health kills the attacker, will slay attacker: %i", attacker);
PunishPlayer(victim, attacker, ATK_SLAY, false);
}
else
{
if (attackerArmor < 0)
attackerArmor = 0;
//Set Armor?
// Remove Attacker Health (Set new health)
if (MirrorDamageSlap)
{
InformTKClients(victim, attacker, ATK_SLAP, true);
SlapPlayer(attacker, mirror_damage_health, true);
}
else
SetEntityHealth(attacker, attackerHealth);
LogDebug(false, "Event_PlayerHurt - Finished setting attackers new health.");
}
LogDebug(false, "Event_PlayerHurt - Mirrored damage to attacker: %i", attacker);
}
if (IsClientInGame(victim))
{
if (IsPlayerAlive(victim))
{
if (GetConVarInt(g_Cvar_MirrorDamage) == 2)
{
new victimHealth = GetClientHealth(victim) + damage_health;
if(victimHealth > g_Player_MaxHealth[victim])
SetEntityHealth(victim, g_Player_MaxHealth[victim]);
else
SetEntityHealth(victim, victimHealth);
LogDebug(false, "Event_PlayerHurt - Returned damage to victim: %i", victim);
}
}
else
{
}
}
}
}
}
}
}
}
return Plugin_Continue;
}
public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast){
if (GetConVarBool(g_Cvar_Enabled))
{
new victim = GetClientOfUserId(GetEventInt(event,"userid"));
new attacker = GetClientOfUserId(GetEventInt(event,"attacker"));
return CheckTKDetails(victim, attacker);
}
return Plugin_Continue;
}
public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (client > 0)
{
if (GetConVarBool(g_Cvar_Enabled))
{
g_Player_MaxHealth[client] = GetClientHealth(client);
if (!IsFakeClient(client))
{
arrayPlayerSpawnTime[client] = GetTime();
SetEntityGravity(client, 1.0);
// Check Punishment Queue
new arrPunishmentSize = GetArraySize(arrayPlayerPunishments[client]);
decl arrVictimIndex, arrPunishmentIndex, victim, type;
// Quick check if array is damaged?
if (FloatFraction(arrPunishmentSize / 2.0) == 0.0)
{
if (arrPunishmentSize > 0)
{
LogDebug(false, "TKer Client: %d spawned and has queued punishments?", client);
// Array Indexes
arrVictimIndex = arrPunishmentSize - 2;
arrPunishmentIndex = arrPunishmentSize - 1;
// Array Values
victim = GetArrayCell(arrayPlayerPunishments[client],arrVictimIndex);
type = GetArrayCell(arrayPlayerPunishments[client],arrPunishmentIndex);
LogDebug(false, "TKer Client: %d Victim: %d Punishment type: %d", client, victim, type);
// Remove Punishment from Array
RemoveFromArray(arrayPlayerPunishments[client],arrPunishmentIndex);
RemoveFromArray(arrayPlayerPunishments[client],arrVictimIndex);
// Punish TK'er
PunishPlayer(victim, client, type, false);
}
}
else
LogDebug(false, "Punishment array was damaged? Size: %d", arrPunishmentSize);
}
}
}
}
// Menu Functions
CreateTKMenu(victim)
{
decl String:victimName[MAX_NAME_LENGTH];
GetClientName(victim,victimName,sizeof(victimName));
new attacker = arrayPlayerStats[victim][STAT_LAST_TKER];
PrintToConsole(victim, "[Anti-TK] %t", "TK_Message_Victim", arrayPlayerTKerName[victim]);
PrintToChat(victim, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "TK_Message_Victim", arrayPlayerTKerName[victim]);
PrintToConsole(attacker, "[Anti-TK] %t", "TK_Message_TKer", victimName);
PrintToChat(attacker, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "TK_Message_TKer", victimName);
new Handle:menu = CreateMenu(PunishmentMenuSelected);
SetMenuTitle(menu,"[Anti-TK] %T", "Menu_Title", victim, arrayPlayerTKerName[victim]);
// Disable Exit
SetMenuExitButton(menu,false);
decl String:MenuItem[128];
new String:iStr[4];
for (new i = 0; i < ATK_PUNISHMENTS; i++)
{
IntToString(i, iStr, sizeof(iStr));
switch (i)
{
case ATK_FORGIVE:
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Forgive", victim);
AddMenuItem(menu,iStr,MenuItem);
}
case ATK_SLAY:
{
#if SLAY
if (GetConVarBool(g_Cvar_Slay))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Slay", victim);
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_SLAP:
{
#if SLAP
if (GetConVarBool(g_Cvar_Slap))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Slap", victim, GetConVarInt(g_Cvar_SlapDamage));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_BEACON:
{
#if BEACON
if (GetConVarBool(g_Cvar_Beacon))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Beacon", victim);
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_BURN:
{
#if FIRE
if (GetConVarBool(g_Cvar_Burn))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Burn", victim, GetConVarInt(g_Cvar_BurnDuration));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_FIREBOMB:
{
#if FIRE
if (GetConVarBool(g_Cvar_FireBomb))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_FireBomb", victim, GetConVarInt(g_Cvar_BurnDuration));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_FREEZE:
{
#if ICE
if (GetConVarBool(g_Cvar_Freeze))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Freeze", victim, GetConVarInt(g_Cvar_FreezeDuration));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_FREEZEBOMB:
{
#if ICE
if (GetConVarBool(g_Cvar_FreezeBomb))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_FreezeBomb", victim, GetConVarInt(g_Cvar_FreezeDuration));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_SLOW:
{
#if GRAVITY
if (GetConVarBool(g_Cvar_Slow))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Slow", victim);
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_BLIND:
{
#if BLIND
if (GetConVarBool(g_Cvar_Blind))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Blind", victim);
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_DRUG:
{
#if DRUG
// Drug Crashes Insurgency
if (!Insurgency)
if (GetConVarBool(g_Cvar_Drug))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Drug", victim);
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_TIMEBOMB:
{
#if TIMEBOMB
if (GetConVarBool(g_Cvar_TimeBomb))
{
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_TimeBomb", victim, GetConVarInt(g_Cvar_TimeBombTicks));
AddMenuItem(menu,iStr,MenuItem);
}
#endif
}
case ATK_RESOURCES:
{
if (GetConVarBool(g_Cvar_Resources))
{
if (offsResourceAmount > 0)
{
new Float:amount = GetConVarFloat(g_Cvar_ResourceAmount);
decl Float:resources;
if (amount > 0.0)
{
resources = amount;
if (amount <= 1.0)
{
LogDebug(false, "Player: %s has %i resources", arrayPlayerTKerName[victim], GetEntData(attacker, offsResourceAmount));
resources = GetEntData(attacker, offsResourceAmount) * amount;
LogDebug(false, "Resource punishment should remove %f resources", resources);
}
arrayPlayerStats[victim][STAT_TKER_RESOURCES] = (RoundFloat(resources) * -1);
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_Resources", victim, RoundFloat(resources));
AddMenuItem(menu,iStr,MenuItem);
}
}
}
}
}
}
if (GetMenuItemCount(menu) < 2)
{
IntToString(ATK_NOFORGIVE, iStr, sizeof(iStr));
Format(MenuItem, sizeof(MenuItem),"%T", "Menu_NoForgive", victim);
AddMenuItem(menu,iStr,MenuItem);
}
LogDebug(false, "Displaying Punishment menu to Victim: %d TKer: %d", victim, attacker);
DisplayMenu(menu,victim,MENU_TIME_FOREVER);
}
public PunishmentMenuSelected(Handle:menu, MenuAction:action, param1, param2)
{
new victim = param1;
new tker = 0;
if (victim > 0)
{
tker = arrayPlayerStats[victim][STAT_LAST_TKER];
}
decl String:tmp[32], pMenuItemSelected;
GetMenuItem(menu, param2, tmp, sizeof(tmp));
pMenuItemSelected = StringToInt(tmp);
switch (action)
{
case MenuAction_Select:
{
if (victim > 0)
{
switch (pMenuItemSelected)
{
case ATK_FORGIVE:
{
ForgivePlayer(victim,tker);
}
case ATK_RESOURCES:
{
PunishPlayer(victim, tker, pMenuItemSelected);
}
default:
{
arrayPlayerStats[victim][STAT_TKER_RESOURCES] = 0;
PunishPlayer(victim, tker, pMenuItemSelected);
}
}
/*
for (new attacker=1; attacker <= PlayerSlots; ++attacker)
{
if(IsClientConnected(attacker) && IsClientInGame(attacker) && killed[attacker][param1] && attacker != 0)
{
killed[attacker][param1] = false;
TextOutput(1,attacker,param1,"Forgiven");
if(hlxEnabled)
{
decl String:attackerSteamID[64];
GetClientName(attacker,attackerName,64);
GetClientAuthString(attacker, attackerSteamID, 64);
LogToGame("\"%s<%d><%s><ATAC>\" triggered \"Forgiven_For_TeamKill\"",attackerName,GetClientUserId(attacker),attackerSteamID);
}
}
}
new tkCount = GetConVarInt(cvarATACTKCount);
for(new attacker = 1; attacker <= PlayerSlots; ++attacker){
if(IsClientConnected(attacker) && IsClientInGame(attacker) && killed[attacker][param1] && attacker != 0){
GetClientName(attacker,attackerName,64);
tkCounter[attacker]++;
if(tkCount > 0 && tkCounter[attacker] >= tkCount){
if(TKAction(attacker,param1)){
return;
}
tkCounter[attacker] = 0;
killed[attacker][param1] = false;
}else{
killed[attacker][param1] = false;
}
TextOutput2(attacker,param1,"Not Forgiven",tkCounter[attacker],tkCount);
if(hlxEnabled){
decl String:attackerSteamID[64];
GetClientName(attacker,attackerName,64);
GetClientAuthString(attacker, attackerSteamID, 64);
LogToGame("\"%s<%d><%s><ATAC>\" triggered \"Punished_For_TeamKill\"",attackerName,GetClientUserId(attacker),attackerSteamID);
}
}
}
new Handle:ATAC_Menu = Handle:StringToInt(SelectionInfo);
if(ATAC_Menu != INVALID_HANDLE){
for(new attacker = 1; attacker <= PlayerSlots; ++attacker){
if(IsClientConnected(attacker) && IsClientInGame(attacker) && killed[attacker][param1] && attacker != 0){
Call_StartForward(ATAC_Menu);
Call_PushCell(param1);
Call_PushCell(attacker);
Call_Finish();
if(hlxEnabled){
decl String:attackerSteamID[64];
GetClientName(attacker,attackerName,64);
GetClientAuthString(attacker, attackerSteamID, 64);
LogToGame("\"%s<%d><%s><ATAC>\" triggered \"Punished_For_TeamKill\"",attackerName,GetClientUserId(attacker),attackerSteamID);
}
killed[attacker][param1] = false;
}
}
}
*/
}
}
case MenuAction_Cancel:
{
// Will not work because sometimes param1 is 0?
if ((victim > 0) && (tker > 0))
{
LogDebug(false, "Punishment Menu was Cancelled? Forgive Tker? Victim: %d Tker: %d", victim, tker);
ForgivePlayer(victim,tker);
}
}
case MenuAction_End:
{
CloseHandle(menu);
}
}
}
ForgivePlayer(victim,tker)
{
// Forgive Player
LogDebug(false, "Victim: %d forgave TK'er: %d", victim, tker);
new String: tker_authid[32] = "UNKNOWN";
new String: victim_authid[32] = "UNKNOWN";
new Float:tker_origin[3] = {0.0,0.0,0.0};
new Float:victim_origin[3] = {0.0,0.0,0.0};
new tker_clientid = 0;
new victim_clientid = 0;
GetClientAuthString(victim, victim_authid, sizeof(victim_authid));
GetClientAbsOrigin(victim, victim_origin);
victim_clientid = GetClientUserId(victim);
new victim_team = GetClientTeam(victim); // Teams should be the same because it's a TK?
if (IsClientInGame(tker))
{
GetClientAuthString(tker, tker_authid, sizeof(tker_authid));
GetClientAbsOrigin(tker, tker_origin);
tker_clientid = GetClientUserId(tker);
if (IsPlayerAlive(tker))
InformTKClients(victim, tker, 0, true);
else
InformTKClients(victim, tker, 0, false);
// Log Stats Based Forgive Log Message
LogToGame("\"%N<%d><%s><%s>\" %s \"%s\" against \"%N<%d><%s><%s>\" (position \"%d %d %d\") (victim_position \"%d %d %d\")", tker, tker_clientid, tker_authid, g_team_list[victim_team], "triggered", "Forgiven_For_Teamkill", victim, victim_clientid, victim_authid, g_team_list[victim_team], RoundFloat(tker_origin[0]), RoundFloat(tker_origin[1]), RoundFloat(tker_origin[2]), RoundFloat(victim_origin[0]), RoundFloat(victim_origin[1]), RoundFloat(victim_origin[2]));
}
else
{
InformTKClients(victim, tker, 0, false);
// Log Stats Based Forgive Log Message
LogToGame("\"%N<%d><%s><%s>\" %s \"%s\" against \"%N<%d><%s><%s>\" (position \"%d %d %d\") (victim_position \"%d %d %d\")", arrayPlayerTKerName, tker_clientid, tker_authid, g_team_list[victim_team], "triggered", "Forgiven_For_Teamkill", victim, victim_clientid, victim_authid, g_team_list[victim_team], RoundFloat(tker_origin[0]), RoundFloat(tker_origin[1]), RoundFloat(tker_origin[2]), RoundFloat(victim_origin[0]), RoundFloat(victim_origin[1]), RoundFloat(victim_origin[2]));
}
}
KillPlayer(index)
{
if (IsClientInGame(index) && IsPlayerAlive(index))
{
if (Insurgency)
ClientCommand(index, "kill");
else if (ZombiePanic)
{
// Slay Custom Function from Rawr of the Vortex ZPS server (Fix for instant death in ZPS)
decl String:dName[32], Entity;
Format(dName, sizeof(dName), "pd_%d", index);
Entity = CreateEntityByName("env_entity_dissolver");
if (Entity)
{
DispatchKeyValue(index, "targetname", dName);
DispatchKeyValue(Entity, "target", dName);
AcceptEntityInput(Entity, "Dissolve");
AcceptEntityInput(Entity, "kill");
}
}
else
{
if (GetConVarBool(g_Cvar_SpecialSlay))
{
new Float:vec[3];
new Float:pos[3];
new Float:end[3];
GetClientAbsOrigin(index, pos);
new Float:dir[3] = {0.0, 0.0, 0.0};
TE_SetupSparks(pos, dir, 500, 100);
TE_SendToAll();
end = pos;
end[2] += 500;
new color[4] = {255, 255, 255, 255};
TE_SetupBeamPoints(pos, end, g_Lightning, 0, 0, 5, 1.0, 10.0, 10.0, 1, 0.0, color, 64);
TE_SendToAll();
GetClientEyePosition(index, vec);
EmitAmbientSound(SOUND_SLAY, vec, index, SNDLEVEL_RAIDSIREN);
}
ForcePlayerSuicide(index);
}
}
}
// Remove TK'er from server
public Action:EjectTKer(tker, victim)
{
decl String:tkerName[MAX_NAME_LENGTH], String:type[32];
GetClientName(tker, tkerName, sizeof(tkerName));
new method = GetConVarInt(g_Cvar_AntiTKType);
LogDebug(false, "EjectTKer - Using eject mode: %i on client %s on behalf of victim %i", method, tkerName, victim);
switch (method)
{
case 0:
{
LogDebug(false, "WARNING: sm_antitk_type is set to 0 and sm_antitk_max has been defined?");
return Plugin_Continue;
}
case 1:
{
type = "kicked";
KickClient(tker, "[Anti-TK] %t", "Eject_Message_Kick_TKer");
PrintToChat(victim, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "Eject_Message_Victim_Kick", tkerName);
PrintToConsole(victim, "[Anti-TK] %t", "Eject_Message_Victim_Kick", tkerName);
PrintToChatAll("%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "Eject_Announce_Kick", tkerName);
}
case 2:
{
type = "banned";
new bantime = GetConVarInt(g_Cvar_BanTime);
LogAction(0, -1, "[Anti-TK] %T", "Ban_Log", LANG_SERVER, tker);
decl String:ban_message[128];
Format(ban_message, sizeof(ban_message), "[Anti-TK] %T", "Eject_Message_Ban_TKer", tker);
if (g_bSBAvailable)
{
#if defined _sourcebans_included
SBBanPlayer(0, tker, bantime, ban_message);
LogDebug(false, "EjectTKer - Banned Player via SourceBans.");
#else
LogDebug(false, "WARNING: SourceBans is loaded but plugin was not compiled with SourceBans Include file.");
LogDebug(false, "WARNING: Banning player without using SourceBans!");
BanClient(tker,bantime, BANFLAG_AUTO, ban_message, ban_message, "sm_ban", tker);
#endif
}
else
{
BanClient(tker,bantime, BANFLAG_AUTO, ban_message, ban_message, "sm_ban", tker);
PrintToChat(victim, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "Eject_Message_Victim_Ban", tkerName);
PrintToConsole(victim, "[Anti-TK] %t", "Eject_Message_Victim_Ban", tkerName);
PrintToChatAll("%c[Anti-TK]%c %t", ANTITK_COLOR, 1, "Eject_Announce_Ban", tkerName);
}
}
default:
{
// Could be useful as a log message
LogDebug(false, "ERROR: sm_antitk_type is invalid and sm_antitk_max has been defined?");
return Plugin_Continue;
}
}
LogDebug(false, "%s has been %s for exceeding the TK limit.", tkerName, type);
return Plugin_Handled;
}
// Punishment queue function for if TK'er is dead
QueuePunishment(victim, tker, type)
{
LogDebug(false, "Punishment queued victim: %d", victim);
LogDebug(false, "Punishment array size: %d", GetArraySize(arrayPlayerPunishments[tker]));
PushArrayCell(arrayPlayerPunishments[tker], victim);
PushArrayCell(arrayPlayerPunishments[tker], type);
LogDebug(false, "New punishment queue size: %d", GetArraySize(arrayPlayerPunishments[tker]));
}
// Inform players punishment is being taken
InformTKClients(victim, tker, type, bool:now=false)
{
decl String:victimName[MAX_NAME_LENGTH];
if (IsClientInGame(victim))
{
GetClientName(victim, victimName, sizeof(victimName));
}
else
{
victimName = arrayPlayerName[victim];
}
decl String:tker_msg_type[64], String:victim_msg_type[64];
if (now)
{
if (type < ATK_PUNISHMENTS)
{
Format(tker_msg_type, sizeof(tker_msg_type), "Inform_Message_TKer_%s_Now", arrayPunishmentText[type]);
Format(victim_msg_type, sizeof(victim_msg_type), "Inform_Message_Victim_%s_Now", arrayPunishmentText[type]);
}
else if (type == ATK_NOFORGIVE)
{
Format(tker_msg_type, sizeof(tker_msg_type), "Inform_Message_TKer_NoForgive_Now");
Format(victim_msg_type, sizeof(victim_msg_type), "Inform_Message_Victim_NoForgive_Now");
}
}
else
{
if (type < ATK_PUNISHMENTS)
{
Format(tker_msg_type, sizeof(tker_msg_type), "Inform_Message_TKer_%s_Spawn", arrayPunishmentText[type]);
Format(victim_msg_type, sizeof(victim_msg_type), "Inform_Message_Victim_%s_Spawn", arrayPunishmentText[type]);
}
else if (type == ATK_NOFORGIVE)
{
Format(tker_msg_type, sizeof(tker_msg_type), "Inform_Message_TKer_NoForgive_Spawn");
Format(victim_msg_type, sizeof(victim_msg_type), "Inform_Message_Victim_NoForgive_Spawn");
}
}
if(IsClientInGame(tker))
{
PrintToConsole(tker, "[Anti-TK] %t", tker_msg_type, victimName);
PrintToChat(tker, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, tker_msg_type, victimName);
}
if (IsClientInGame(victim))
{
PrintToConsole(victim, "[Anti-TK] %t", victim_msg_type, arrayPlayerTKerName[victim]);
PrintToChat(victim, "%c[Anti-TK]%c %t", ANTITK_COLOR, 1, victim_msg_type, arrayPlayerTKerName[victim]);
}
return true;
}
// Punishment Function
PunishPlayer(victim, tker, type, bool:CountTK=true)
{
if (IsClientInGame(tker))
{
if (CountTK)
{
if ( !( (RoundProtect) && (GetConVarBool(g_Cvar_RoundStartExclude)) ) )
{
// Retrieve TK stats
new maxtks = GetConVarInt(g_Cvar_MaxTKs);
new numtk = arrayPlayerStats[tker][STAT_TEAM_KILLS];
LogDebug(false, "TEST TK NUMBER: %d CLIENT: %d", numtk, tker);
// Increment TK Counter
numtk++;
LogDebug(false, "TEST TK2 NUMBER: %d CLIENT: %d", numtk, tker);
// Store TK count
arrayPlayerStats[tker][STAT_TEAM_KILLS] = numtk;
// Check TK count
if (maxtks > 0)
{
LogDebug(false, "TKer: %d has TKed: %d players.",tker, numtk);
if (numtk >= maxtks)
{
LogDebug(false, "TKer: %d is being ejected from the server for exceeding the TK limit: %d", tker, maxtks);
EjectTKer(tker, victim);
return;
}
}
}
else
LogDebug(false, "Round Protection & TK Exclusion are Enabled, player: %d is being excluded from TK count", tker);
}
if (IsPlayerAlive(tker))
{
// Inform Client that TK action is being taken...
InformTKClients(victim, tker, type, true);
// Punish Player
switch (type)
{
case ATK_FORGIVE:
{
// Forgive
// Could be useful as a log message
LogDebug(false, "ERROR: Victim: %d forgave TK'er: %d - Player should have already been forgiven previously?",victim,tker);
}
case ATK_SLAY:
{
// Slay Player
LogDebug(false, "TKer: %d is being slayed for TKing", tker);
KillPlayer(tker);
}
case ATK_SLAP:
{
// Slap Player
#if SLAP
LogDebug(false, "TKer: %d is being slapped for TKing", tker);
SlapPlayer(tker, GetConVarInt(g_Cvar_SlapDamage), true);
#endif
}
case ATK_BEACON:
{
// Beacon Player
#if BEACON
LogDebug(false, "TKer: %d is being beaconed for TKing", tker);
if (g_BeaconSerial[tker] == 0)
{
CreateBeacon(tker);
}
#endif
}
case ATK_BURN:
{
LogDebug(false, "TKer: %d is being burned for TKing", tker);
#if FIRE
IgniteEntity(tker, GetConVarFloat(g_Cvar_BurnDuration));
#endif
}
case ATK_FIREBOMB:
{
#if FIRE
LogDebug(false, "TKer: %d is being firebombed for TKing", tker);
if (g_FireBombSerial[tker] == 0)
{
CreateFireBomb(tker);
}
#endif
}
case ATK_FREEZE:
{
// Freeze Player
#if ICE
LogDebug(false, "TKer: %d is being frozen for TKing", tker);
if (g_FreezeSerial[tker] == 0)
{
FreezeClient(tker, GetConVarInt(g_Cvar_FreezeDuration));
}
#endif
}
case ATK_FREEZEBOMB:
{
//FreezeBomb Player
#if ICE
LogDebug(false, "TKer: %d is being freezebombed for TKing", tker);
if (g_FreezeBombSerial[tker] == 0)
{
CreateFreezeBomb(tker);
}
#endif
}
case ATK_SLOW:
{
// Slow Player
#if GRAVITY
LogDebug(false, "TKer: %d is being slowed for TKing", tker);
SetEntityGravity(tker, GetConVarFloat(g_Cvar_SlowGravity));
if (Insurgency)
{
SetEntPropFloat(tker, Prop_Send, "m_flLaggedMovementValue", GetConVarFloat(g_Cvar_SlowSpeed));
}
else
SetEntPropFloat(tker, Prop_Data, "m_flLaggedMovementValue", GetConVarFloat(g_Cvar_SlowSpeed));
#endif
}
case ATK_BLIND:
{
// Blind Player
#if BLIND
LogDebug(false, "TKer: %d is being blinded for TKing", tker);
PerformBlind(tker, GetConVarInt(g_Cvar_BlindAmount));
#endif
}
case ATK_DRUG:
{
// Drug Player
#if DRUG
LogDebug(false, "TKer: %d is being drugged for TKing", tker);
if (g_DrugTimers[tker] == INVALID_HANDLE)
{
CreateDrug(tker);
}
#endif
}
case ATK_TIMEBOMB:
{
// TimeBomb Player
#if TIMEBOMB
LogDebug(false, "TKer: %d is being timebombed for TKing", tker);
if (g_TimeBombSerial[tker] == 0)
{
CreateTimeBomb(tker);
}
#endif
}
case ATK_RESOURCES:
{
// Remove Player Resources
LogDebug(false, "TKer: %d is having resources removed for TKing", tker);
if (offsResourceAmount > 0)
{
if (arrayPlayerStats[victim][STAT_TKER_RESOURCES] != 0)
{
LogDebug(false, "TKer: %d currently has %i resources", tker, GetEntData(tker, offsResourceAmount));
new attacker_resources = GetEntData(tker, offsResourceAmount) + arrayPlayerStats[victim][STAT_TKER_RESOURCES];
if (attacker_resources < 0)
attacker_resources = 0;
LogDebug(false, "TKer: %d will end up with %i resources", tker, attacker_resources);
SetEntData(tker, offsResourceAmount, attacker_resources);
if (GetConVarBool(g_Cvar_ResourceSteal))
{
new victim_resources = GetEntData(victim, offsResourceAmount) + (arrayPlayerStats[victim][STAT_TKER_RESOURCES] * -1);
SetEntData(victim, offsResourceAmount, victim_resources);
}
arrayPlayerStats[victim][STAT_TKER_RESOURCES] = 0;
LogDebug(false, "TKer: %d now has %i resources", tker, GetEntData(tker, offsResourceAmount));
}
}
}
case ATK_NOFORGIVE:
{
// Do Not Forgive Player
LogDebug(false, "TKer: %d has not been forgiven for TKing", tker);
}
default:
{
// Could be useful as a log message
LogDebug(false, "ERROR: TK type not defined: %d", type);
}
}
}
else
{
// Inform Client that TK action will be taken...
InformTKClients(victim, tker, type, false);
// Queue Punishment
QueuePunishment(victim, tker, type);
}
}
}
bool:CheckAdminImmunity(client)
{
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - Checking client: %i for admin immunity.", client);
#endif
decl String:name[MAX_NAME_LENGTH];
GetClientName(client, name, sizeof(name));
new AdminId:admin = GetUserAdmin(client);
// Check if player is an admin.
if(admin != INVALID_ADMIN_ID)
{
decl String:flags[8];
decl AdminFlag:flag;
GetConVarString(g_Cvar_AdminsFlag, flags, sizeof(flags));
// Are we checking for specific admin flags?
if (!StrEqual(flags, "", false))
{
// Is the admin flag we are checking valid?
if (!FindFlagByChar(flags[0], flag))
{
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - ERROR: Admin Immunity flag is not valid? %s", flags[0]);
#endif
}
else
{
// Check if the admin has the correct immunity flag.
if (!GetAdminFlag(admin, flag))
{
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - Client %s has a valid Admin ID but does NOT have required immunity flag %s admin is NOT immune.", name, flags[0]);
#endif
}
else
{
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - Client %s has required immunity flag %s admin is immune.", name, flags[0]);
#endif
return true;
}
}
}
else
{
// Player is an admin, we don't care about flags.
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - Client %s is a valid Admin and is immune.", name);
#endif
return true;
}
}
else
{
#if _DEBUG
LogDebug(false, "CheckAdminImmunity - Client %s has an invalid Admin ID.", name);
#endif
}
return false;
}