diff --git a/.gitignore b/.gitignore index b93a943..293e66f 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,7 @@ sounds.sp spcomp sql-admin-manager.sp testsuite/ +compile.exe +compiled/ +spcomp.exe + diff --git a/ClientParticles.sp b/ClientParticles.sp new file mode 100644 index 0000000..d6bb2be --- /dev/null +++ b/ClientParticles.sp @@ -0,0 +1,446 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include +#include + +new String:clientParticle[MAXPLAYERS+1][256]; +new Handle:hProjectileArray[56]; +new curSecCount=-1; +new Handle:hDb = INVALID_HANDLE; + + +public Plugin:myinfo = +{ + name = "ClientParticles", + author = "Chefe", + description = "Set your own particle effect", + version = "1.0", + url = "oktoberfest-servers.net" +} + +public OnPluginStart() +{ + RegConsoleCmd("sm_particles", Command_Particles, "Set your own custom projectile particle effects"); + + HookEvent("player_changeclass", Event_PlayerChangeClass); + + InitDB(); + + ProcessConfigFile("configs/clientparticles.cfg"); +} + +InitDB() +{ + SQL_TConnect(InitDBHnld, "clientparticles"); +} + +public InitDBHnld(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE) + { + SetFailState("Database connection failed: %s", error); + } + else + { + hDb = hndl; + } +} + +public Event_PlayerChangeClass(Handle:event,const String:name[],bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + + PrintToServer("Class changed, update requested"); + + CreateTimer(0.5, Timer_Update, client); +} + +public Action:Timer_Update(Handle:timer, any:client) +{ + updateClientParticle(client); +} + +stock ProcessConfigFile(const String:file[]) +{ + new String:sConfigFile[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), file); + if (!FileExists(sConfigFile)) + { + /** + Config file doesn't exists, stop the plugin + */ + LogError("[CP] Plugin startup failed! Could not find file %s", sConfigFile); + SetFailState("Could not find file %s", sConfigFile); + } + else if (!ParseConfigFile(sConfigFile)) + { + /** + Couldn't parse the file, stop the plugin + */ + LogError("[SM] Plugin is not running! Failed to parse %s", sConfigFile); + SetFailState("Parse error on file %s", sConfigFile); + } +} + +stock bool:ParseConfigFile(const String:file[]) +{ + new Handle:hParser = SMC_CreateParser(); + new String:error[128]; + new line = 0; + new col = 0; + + /** + Define the parser functions + */ + SMC_SetReaders(hParser, Config_NewSection, Config_KeyValue, Config_EndSection); + SMC_SetParseEnd(hParser, Config_End); + + /** + Parse the file and get the result + */ + new SMCError:result = SMC_ParseFile(hParser, file, line, col); + CloseHandle(hParser); + + if (result != SMCError_Okay) + { + SMC_GetErrorString(result, error, sizeof(error)); + LogError("%s on line %d, col %d of %s", error, line, col, file); + } + + return (result == SMCError_Okay); +} + +public SMCResult:Config_NewSection(Handle:parser, const String:section[], bool:quotes) +{ + if (StrEqual(section, "projectiles")) + { + return SMCParse_Continue; + } + + curSecCount++; + hProjectileArray[curSecCount] = CreateArray(32, 0); + PushArrayString(hProjectileArray[curSecCount], section); + + return SMCParse_Continue; +} + +public SMCResult:Config_KeyValue(Handle:parser, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes) +{ + if(StrEqual(key, "display", false)) + { + PushArrayString(hProjectileArray[curSecCount], value); + PrintToServer("[PC_DEBUG] New value %s to key %s to array %i", value, key, curSecCount); + } + else if (StrEqual(key, "effect", false)) + { + new index = PushArrayString(hProjectileArray[curSecCount], value); + PrintToServer("[PC_DEBUG] New value %s to key %s to array %i with index %i", value, key, curSecCount, index); + } + + return SMCParse_Continue; +} + +public SMCResult:Config_EndSection(Handle:parser) +{ + return SMCParse_Continue; +} + +public Config_End(Handle:parser, bool:halted, bool:failed) +{ + if (failed) + { + SetFailState("Plugin configuration error"); + } +} + +public Action:Command_Particles(client, args) +{ + new Handle:menu = CreateMenu(Menu_Particles); + SetMenuTitle(menu, "Choose the projectile"); + + for (new i=0; i<32; i++) + { + if (hProjectileArray[i] != INVALID_HANDLE && hProjectileArray[i]) + { + new String:projectileName[256]; + GetArrayString(hProjectileArray[i], 0, projectileName, sizeof(projectileName)); + + new String:displayName[256]; + GetArrayString(hProjectileArray[i], 1, displayName, sizeof(displayName)); + + //new String:secNum[5]; + //IntToString(i, secNum, sizeof(secNum)); + AddMenuItem(menu, projectileName, displayName); + } + } + + SetMenuExitButton(menu, true); + DisplayMenu(menu, client, MENU_TIME_FOREVER); + + return Plugin_Handled; +} + +public Menu_Particles(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:projectile[256]; + GetMenuItem(menu, param2, projectile, sizeof(projectile)); + + new Handle:effectmenu = CreateMenu(Menu_Effect); + SetMenuTitle(effectmenu, "Choose your effect"); + + new client = param1; + + for (new a=0; a<32; a++) + { + if (hProjectileArray[a] != INVALID_HANDLE && hProjectileArray[a]) + { + new String:projectileName[256]; + GetArrayString(hProjectileArray[a], 0, projectileName, sizeof(projectileName)); + + if (StrEqual(projectile, projectileName)) + { + for (new g=1; g<=(GetArraySize(hProjectileArray[a])-2); g++) + { + new String:myNewItem[256]; + GetArrayString(hProjectileArray[a], g+1, myNewItem, sizeof(myNewItem)); + + if (!StrEqual(myNewItem, NULL_STRING)) + { + AddMenuItem(effectmenu, myNewItem, myNewItem); + } + } + break; + } + } + } + + // Pass projetile to menu as item for next menu handler + AddMenuItem(effectmenu, projectile, "", ITEMDRAW_IGNORE); + + SetMenuExitButton(effectmenu, true); + DisplayMenu(effectmenu, client, MENU_TIME_FOREVER); + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_Effect(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:effect[256]; + GetMenuItem(menu, param2, effect, sizeof(effect)); + + new String:projectile[256]; + GetMenuItem(menu, GetMenuItemCount(menu)-1, projectile, sizeof(projectile)); + + PrintToChat(param1, "[CP] Effect: %s", effect); + + new String:steamid[256]; + GetClientAuthString(param1, steamid, sizeof(steamid)); + + new String:sqlstr[1024]; + Format(sqlstr, sizeof(sqlstr), "SELECT particle FROM clientParticles WHERE steamid='%s' AND proj='%s'", steamid, projectile); + + new Handle:pck = CreateDataPack(); + WritePackCell(pck, param1); + WritePackString(pck, steamid); + WritePackString(pck, projectile); + WritePackString(pck, effect); + + SQL_TQuery(hDb, searchClassEffect, sqlstr, pck); + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public searchClassEffect(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("Query error: %s", error); + return; + } + + ResetPack(data); + new client = ReadPackCell(data); + new String:steamid[256]; + ReadPackString(data, steamid, sizeof(steamid)); + new String:projectile[256]; + ReadPackString(data, projectile, sizeof(projectile)); + new String:effect[256]; + ReadPackString(data, effect, sizeof(effect)); + + if (SQL_GetRowCount(hndl)) { + while (SQL_FetchRow(hndl)) + { + new String:name[150]; + SQL_FetchString(hndl, 0, name, sizeof(name)) + + if (strcmp(name, projectile) != 0) + { + PrintToServer("%s was foudn in db. Update!", name); + + new String:sqlstr[1024]; + Format(sqlstr, sizeof(sqlstr), "UPDATE clientParticles SET particle = '%s' WHERE steamid='%s' AND proj='%s'", effect, steamid, projectile); + + SQL_TQuery(hDb, noRtnCllbck, sqlstr); + + CreateTimer(0.5, Timer_Update, client); + } + } + } + else + { + PrintToServer("NOT foudn in db. Insert!"); + + new String:sqlstr[1024]; + Format(sqlstr, sizeof(sqlstr), "INSERT INTO clientParticles (steamid,proj,particle) VALUES ('%s','%s','%s')", steamid, projectile, effect); + + SQL_TQuery(hDb, noRtnCllbck, sqlstr); + + CreateTimer(0.5, Timer_Update, client); + } +} + +public noRtnCllbck(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("Query error: %s", error); + return; + } +} + +stock updateClientParticle(client) +{ + if (IsClientInGame(client)) + { + new String:steamid[256]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + new TFClassType:class = TF2_GetPlayerClass(client); + new String:proj[256]; + + if (class == TFClass_Soldier) + { + proj = "tf_projectile_rocket"; + } else if (class == TFClass_DemoMan) + { + proj = "tf_projectile_pipe_remote"; + } else + { + clientParticle[client] = NULL_STRING; + return; + } + + new String:sqlstr[1024]; + Format(sqlstr, sizeof(sqlstr), "SELECT particle FROM clientParticles WHERE steamid='%s' AND proj='%s'", steamid, proj); + + SQL_TQuery(hDb, updateClientParticleDbCallback, sqlstr, client); + } +} + +public updateClientParticleDbCallback(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("Query error: %s", error); + return; + } + + if (SQL_GetRowCount(hndl)) { + while (SQL_FetchRow(hndl)) + { + new String:effect[256]; + SQL_FetchString(hndl, 0, effect, sizeof(effect)); + + clientParticle[data] = effect; + + PrintToServer("Effect for %N activated: %s", data, effect); + } + } +} + + +public OnEntityCreated(entity, const String:classname[]) +{ + if (StrEqual(classname, "tf_projectile_rocket") || StrEqual(classname, "tf_projectile_pipe_remote")) { + SDKHook(entity, SDKHook_Spawn, OnEntitySpawned); + } +} + +public OnEntitySpawned(entity) +{ + new client = GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity"); + if (client > 0 && IsClientInGame(client) && !StrEqual(clientParticle[client], NULL_STRING)) + { + AddParticle(client, entity); + } + SDKUnhook(entity, SDKHook_Spawn, OnEntitySpawned); +} + +stock AddParticle(client, entity) +{ + new iClusters = 5, iIndex = -1; + new String:sParticle[256]; + sParticle = clientParticle[client]; + decl String:sExtras[64]; + + for (new i = 0; i < iClusters; i++) + { + while ((iIndex = SplitString(sParticle, ",", sExtras, sizeof(sExtras))) > -1) + { + CreateParticle(entity, sExtras, true); + strcopy(sParticle, sizeof(sParticle), sParticle[iIndex]); + } + + CreateParticle(entity, sParticle, true); + } +} + +stock CreateParticle(iEntity, String:sParticle[], bool:bAttach = false) +{ + new iParticle = CreateEntityByName("info_particle_system"); + if (IsValidEdict(iParticle)) + { + decl Float:fPosition[3]; + GetEntPropVector(iEntity, Prop_Send, "m_vecOrigin", fPosition); + + TeleportEntity(iParticle, fPosition, NULL_VECTOR, NULL_VECTOR); + DispatchKeyValue(iParticle, "effect_name", sParticle); + + if (bAttach) + { + SetVariantString("!activator"); + AcceptEntityInput(iParticle, "SetParent", iEntity, iParticle, 0); + } + + DispatchSpawn(iParticle); + ActivateEntity(iParticle); + AcceptEntityInput(iParticle, "Start"); + } + return iParticle; +} \ No newline at end of file diff --git a/VMC.sp b/VMC.sp new file mode 100644 index 0000000..0a12b28 --- /dev/null +++ b/VMC.sp @@ -0,0 +1,29 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +new Handle:hVisibleMaxPlayers; +new g_visibleMaxPlayersVal = 24; + +public Plugin:myinfo = +{ + name = "VMPChecker", + author = "Chefe", + description = "Checks that visiblemaxplayers is set correctly", + version = "1.0", + url = "oktoberfest-servers.net" +} + +public OnPluginStart() +{ + hVisibleMaxPlayers = FindConVar("sv_visiblemaxplayers"); + HookConVarChange(hVisibleMaxPlayers, OnVisibleChange); +} + +public OnVisibleChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + if (StringToInt(newVal) != g_visibleMaxPlayersVal) { + SetConVarInt(hVisibleMaxPlayers, g_visibleMaxPlayersVal); + PrintToServer("[VMC] Set visible maxplayers %i => %i", StringToInt(newVal), g_visibleMaxPlayersVal); + } +} \ No newline at end of file diff --git a/afk4ever.sp b/afk4ever.sp new file mode 100644 index 0000000..013484f --- /dev/null +++ b/afk4ever.sp @@ -0,0 +1,125 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include + +new client_points[MAXPLAYERS]; +new spec_points[MAXPLAYERS]; +new Float:client_angels[MAXPLAYERS][3]; +new Handle:cv_pointlimit, Handle:cv_speclimit; + +public Plugin:myinfo = +{ + name = "AFK4ever", + author = "Chefe", + description = "Simple AFK kicker", + version = "1.4", + url = "www.chefgaming.de" +} + +public OnPluginStart() +{ + CreateTimer(60.0, CheckClients, _, TIMER_REPEAT); + cv_pointlimit = CreateConVar("sm_afk_pointlimit", "50", "Set the maximum point limit a active player can have before he get kicked"); + cv_speclimit = CreateConVar("sm_afk_speclimit", "100", "Set the maximum point limit a spectator can have before he get kicked"); + HookEvent("player_activate", Event_PlayerConnect); + + AutoExecConfig(true); +} + +public Event_PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) +{ + new uid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(uid); + + client_points[client] = 0; + spec_points[client] = 0; +} + +public Action:CheckClients(Handle:timer) +{ + new i = 1; + while (i <= GetMaxClients()) + { + if (IsClientInGame(i) && !IsClientBot(i) && !IsClientAdm(i) && !IsClientReplay(i)) + { + if (IsClientActive(i) && IsPlayerAlive(i)) + { + new Float:currentangels[3]; + GetClientEyeAngles(i, currentangels); + + if (currentangels[0] == client_angels[i][0] && currentangels[1] == client_angels[i][1] && currentangels[2] == client_angels[i][2]) + { + client_points[i] = client_points[i]+10; + } + else if (client_points[i] > 0) + { + client_points[i] = client_points[i]-10; + } + + spec_points[i] = 0; + client_angels[i] = currentangels; + + if (client_points[i] >= GetConVarInt(cv_pointlimit)) + { + PrintToChatAll("\x04%N\x01 kicked out of the game for been afk too long", i); + KickClient(i, "You have been kicked due beeing afk"); + } + } + else if (!IsClientActive(i)) + { + spec_points[i] = spec_points[i]+10; + + if (spec_points[i] >= GetConVarInt(cv_speclimit)) + { + PrintToChatAll("\x04%N\x01 kicked out of the game for been afk too long", i); + KickClient(i, "You have been kicked due beeing afk too long"); + } + } + } + i++; + } +} + +IsClientBot(client) +{ + if (IsClientInGame(client)) + { + new String:auth[255]; + GetClientAuthString(client, auth, sizeof(auth)); + + if (strcmp(auth, "BOT", false) == 0) + { + return true; + } + else + { + return false; + } + } + return false; +} + +IsClientActive(client) +{ + new team = GetClientTeam(client); + + if (team == 2 || team == 3) + { + return true; + } + return false; +} + +IsClientAdm(client) +{ + new AdminId:admid = GetUserAdmin(client); + if (admid != INVALID_ADMIN_ID) + { + return GetAdminFlag(admid, AdminFlag:Admin_Custom1); + } + else + { + return false; + } +} \ No newline at end of file diff --git a/antitk.sp b/antitk.sp new file mode 100644 index 0000000..e9bf90b --- /dev/null +++ b/antitk.sp @@ -0,0 +1,2513 @@ +/* +############################################################################################################# +# 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 +#include + +// SourceBans +#include + + +// 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>\" 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>\" 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>\" 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; +} \ No newline at end of file diff --git a/antitk/keyvalues.sp b/antitk/keyvalues.sp new file mode 100644 index 0000000..da7a692 --- /dev/null +++ b/antitk/keyvalues.sp @@ -0,0 +1,254 @@ +// Keyvalue Storage +//#define ANTITK_KV_FILE "AntiTK.txt" + +new String:AntiTK_DataFile[PLATFORM_MAX_PATH]; + +new Handle:g_kv_AntiTK = INVALID_HANDLE; +new LastTKPurge = 0; + +new String:arrayPlayerIDs[MAXPLAYERS + 1][MAX_NETWORKID_LENGTH]; + +// Create KeyValue Data Path. +BuildKeyValuePath() +{ + // Build Data File Path + BuildPath(Path_SM, AntiTK_DataFile, sizeof(AntiTK_DataFile), "data/AntiTK.txt"); + LogAction(0, -1, "[Anti-TK Manager] Data File: %s", AntiTK_DataFile); +} + +// Read All TKer Information from Keyvalue file. +ReadTKers() +{ + LogDebug(false, "ReadTKers - Reading all TK'ers from Keyvalue file: %s", AntiTK_DataFile); + + if (g_kv_AntiTK == INVALID_HANDLE) + { + LogDebug(false, "ReadTKers - Keyvalues Handle is invalid (May not have been read yet)"); + g_kv_AntiTK = CreateKeyValues("Anti-TK"); + } + else + LogDebug(false, "ReadTKers - Keyvalues Handle is valid (File has probably already been read?)"); + + FileToKeyValues(g_kv_AntiTK, AntiTK_DataFile); +} + +SaveTKFile(Handle:file_handle) +{ + // Safety Precation? + KvRewind(file_handle); + KeyValuesToFile(file_handle, AntiTK_DataFile); +} + +// Save All TKer data to Keyvalue file. +SaveTKers() +{ + LogDebug(false, "SaveTKers - Saving all TK'ers to Keyvalue file: %s", AntiTK_DataFile); + + if (g_kv_AntiTK == INVALID_HANDLE) + LogDebug(false, "SaveTKers - Keyvalues Handle is invalid? (This should probably not happen)"); + else + SaveTKFile(g_kv_AntiTK); + + CloseHandle(g_kv_AntiTK); + g_kv_AntiTK = INVALID_HANDLE; +} + +// Purge Old TK'er data that has expired? +bool:PurgeTKerData(const purgetime, checklast = false) +{ + new time = GetTime(); +#if _DEBUG >= 2 + LogDebug(false, "PurgeTKerData - Checking Old TKer data. LastPurge: %d Time: %d", LastTKPurge, time); +#endif + + if (checklast) + if ((time - LastTKPurge) >= purgetime) + { + LogDebug(false, "PurgeTKerData - Old TKer data being purged: LastPurge: %d Time: %d", LastTKPurge, time); + } + else + return false; + + if (g_kv_AntiTK == INVALID_HANDLE) + { + LogDebug(false, "PurgeTKerData - Keyvalues Handle is invalid? Attempting to read file?"); + ReadTKers(); + } + + LogDebug(false, "PurgeTKerData - TKer's are being checked."); + + new bool:check_record = true; + decl savetime; + decl String:steam_id[MAX_NETWORKID_LENGTH]; + + if (KvGotoFirstSubKey(g_kv_AntiTK)) + { + LogDebug(false, "PurgeTKerData - Starting loop"); + do + { + check_record = true; + + do + { + savetime = KvGetNum(g_kv_AntiTK, "saved"); + LogDebug(false, "PurgeTKerData - Record Retrieved: Time: %i Saved: %i", time, savetime); + + if (savetime > 0) + { + if ((time - savetime) >= purgetime) + { + if ( KvGetSectionName(g_kv_AntiTK, steam_id, sizeof(steam_id)) ) + LogDebug(false, "PurgeTKerData - Deleting record %s.", steam_id); + else + LogDebug(false, "PurgeTKerData - Deleting record... could not retrieve record name"); + + if (KvDeleteThis(g_kv_AntiTK) < 1) + check_record = false; + } + else + check_record = false; + } + else + check_record = false; + } while (check_record); + } while(KvGotoNextKey(g_kv_AntiTK)); + } + else + LogDebug(false, "PurgeTKerData - Could not get first Key?"); + + + LastTKPurge = time; + SaveTKFile(g_kv_AntiTK); + return true; +} + +// Retrieve stored TKer data for players steamid. +bool:RetrieveTKer(client) +{ + // Retrieve Steam ID + GetClientAuthString(client, arrayPlayerIDs[client], MAX_NETWORKID_LENGTH); + +#if _DEBUG >= 2 + LogDebug(false, "RetrieveTKer - Reading TK'er data for: %s", arrayPlayerIDs[client]); +#endif + + if (g_kv_AntiTK == INVALID_HANDLE) + { + LogDebug(false, "RetrieveTKer - Keyvalues Handle is invalid? (This should not happen)"); + ReadTKers(); + } + + // Rewind File + KvRewind(g_kv_AntiTK); + + if (KvJumpToKey(g_kv_AntiTK, arrayPlayerIDs[client])) + { +#if _DEBUG >= 2 + LogDebug(false, "RetrieveTKer - Found Key: %s", arrayPlayerIDs[client]); +#endif + arrayPlayerStats[client][STAT_KARMA] = KvGetNum(g_kv_AntiTK, "karma"); + arrayPlayerStats[client][STAT_KILLS] = KvGetNum(g_kv_AntiTK, "kills"); + arrayPlayerStats[client][STAT_TEAM_KILLS] = KvGetNum(g_kv_AntiTK, "tks"); + KvRewind(g_kv_AntiTK); + return true; + } + else + { +#if _DEBUG >= 2 + LogDebug(false, "RetrieveTKer - Failed? Key Not Found."); +#endif + return false; + } +} + +bool:SaveTKer(client) +{ +#if _DEBUG >= 2 + LogDebug(false, "SaveTKer - Saving TK'er data for: %s", arrayPlayerIDs[client]); +#endif + + if (g_kv_AntiTK == INVALID_HANDLE) + { + LogDebug(false, "SaveTKer - Keyvalues Handle is invalid? (This should not happen)"); + ReadTKers(); + } + + // Safety Precaution + KvRewind(g_kv_AntiTK); + if (!StrEqual(arrayPlayerIDs[client], "")) + { + KvJumpToKey(g_kv_AntiTK,arrayPlayerIDs[client],true); + + // Store Values + KvSetNum(g_kv_AntiTK, "karma", arrayPlayerStats[client][STAT_KARMA]); + KvSetNum(g_kv_AntiTK, "kills", arrayPlayerStats[client][STAT_KILLS]); + KvSetNum(g_kv_AntiTK, "tks", arrayPlayerStats[client][STAT_TEAM_KILLS]); + KvSetNum(g_kv_AntiTK, "saved", GetTime()); + + SaveTKFile(g_kv_AntiTK); + + arrayPlayerIDs[client] = ""; + + return true; + } + return false; +} + +bool:RemoveTKer(const String:steamid[]) +{ + LogDebug(false, "RemoveTKer - Removing TK'er data for: %s", steamid); + + if (g_kv_AntiTK == INVALID_HANDLE) + { + LogDebug(false, "RemoveTKer - Keyvalues Handle is invalid? (This should not happen)"); + ReadTKers(); + } + + if (KvGotoFirstSubKey(g_kv_AntiTK)) + { + if (KvJumpToKey(g_kv_AntiTK, steamid)) + { + KvDeleteThis(g_kv_AntiTK); + KvRewind(g_kv_AntiTK); + return true; + } + else + return false; + } + else + return false; +} + +/* +DeleteAllTKers() +{ +#if _DEBUG + LogAction(0, -1, "DeleteAllTKers - Removing all TKer data."); +#endif + if (g_kv_AntiTK == INVALID_HANDLE) + { +#if _DEBUG + LogAction(0, -1, "DeleteAllTKers - Keyvalues Handle is invalid? (This should not happen)"); +#endif + } + if (!KvGotoFirstSubKey(g_kv_AntiTK)) + { + return; + } + + for (;;) + { + decl String:name[4]; + KvGetString(g_kv_AntiTK, name, sizeof(name)) + if (name[0] == '\0') + { + if (KvDeleteThis(g_kv_AntiTK) < 1) + { + break; + } + } else if (!KvGotoNextKey(g_kv_AntiTK)) { + break; + } + } +} +*/ \ No newline at end of file diff --git a/ask4change.sp b/ask4change.sp new file mode 100644 index 0000000..0b1821b --- /dev/null +++ b/ask4change.sp @@ -0,0 +1,69 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include + +new Handle:hTimer = INVALID_HANDLE; + +public Plugin:myinfo = +{ + name = "Ask4MapChange", + author = "Chefe", + description = "", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + +} + +public OnMapStart() +{ + if (hTimer == INVALID_HANDLE) + { + hTimer = CreateTimer(3600.0, Timer_Ask4Change, _, TIMER_REPEAT); + } + else + { + CloseHandle(hTimer); + hTimer = CreateTimer(3600.0, Timer_Ask4Change, _, TIMER_REPEAT); + } +} + +public Action:Timer_Ask4Change(Handle:timer) +{ + if (IsVoteInProgress()) + { + return; + } + + new Handle:menu = CreateMenu(Handle_Ask4ChangeMenu); + SetMenuTitle(menu, "Change map? (next vote in 60min)"); + AddMenuItem(menu, "dismiss", "Press-only-1-noobing", ITEMDRAW_DISABLED); + AddMenuItem(menu, "no", "No"); + AddMenuItem(menu, "yes", "Yes"); + SetMenuExitButton(menu, false); + VoteMenuToAll(menu, 20); +} + +public Handle_Ask4ChangeMenu(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_End) + { + /* This is called after VoteEnd */ + CloseHandle(menu); + } else if (action == MenuAction_VoteEnd) { + /* 0=yes, 1=no */ + if (param1 == 2) + { + PrintToChatAll("Vote succeed. Starting mapvote ..."); + InitiateMapChooserVote(MapChange_Instant); + } + else + { + PrintToChatAll("Vote failed. Next Mapchange vote in 60 minutes."); + } + } +} \ No newline at end of file diff --git a/ask4connect.sp b/ask4connect.sp new file mode 100644 index 0000000..4c76338 --- /dev/null +++ b/ask4connect.sp @@ -0,0 +1,42 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +new Handle:cv_ip, Handle:cv_port; + +public Plugin:myinfo = +{ + name = "Ask4Connect", + author = "Chefe", + description = "Redirect your players (if they want) to another server", + version = "1.0", + url = "www.chefgaming.de" +} + +public OnPluginStart() +{ + cv_ip = CreateConVar("sm_a4c_ip", "0.0.0.0", "Set to witch IP the client should be asked to connect to."); + cv_port = CreateConVar("sm_a4c_port", "27015", "Set the port the client should be asked to connect to."); + + AutoExecConfig(true); +} + +public OnClientConnected(client) +{ + CreateTimer(10.0, DisplayAsk, client); +} + +public Action:DisplayAsk(Handle:timer, any:data) +{ + if (IsClientConnected(data)) + { + new String:ip[50]; + GetConVarString(cv_ip, ip, sizeof(ip)); + new String:port[10]; + GetConVarString(cv_port, port, sizeof(port)); + new String:destination[50]; + Format(destination, sizeof(destination), "%s:%s", ip, port); + DisplayAskConnectBox(data, 120.0, destination); + PrintToChat(data, "\x04Our server has moved to an other IP address, pls use the connection box displayed now upper left and save the new server IP: %s!!!", destination); + } +} \ No newline at end of file diff --git a/autoinvite.sp b/autoinvite.sp new file mode 100644 index 0000000..f017c1d --- /dev/null +++ b/autoinvite.sp @@ -0,0 +1,75 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +#define AI_VERSION "1.0" + +new Handle:dbcon = INVALID_HANDLE; + +public Plugin:myinfo = +{ + name = "Autoinvite Tracking", + author = "Chefe", + description = "Tracks players for AI", + version = AI_VERSION, + url = "www.chefgaming.de" +} + +public OnPluginStart() +{ + SQL_TConnect(DBInit, "default"); +} + +public DBInit(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE) + { + LogError("[AI] Database connection failed: %s", error); + SetFailState("Unable to connect to database, look for more infos in the error logs!"); + return; + } + + dbcon = hndl; +} + +public OnClientAuthorized(client, const String:auth[]) +{ + if (strcmp(auth, "BOT", false) != 0 && dbcon != INVALID_HANDLE) + { + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM autoinvite_player WHERE steamid = '%s'", auth); + + SQL_TQuery(dbcon, InitDBCheck1, sqlstring, client); + } +} + +public InitDBCheck1(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("AI Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + if (SQL_GetRowCount(hndl) == 0) + { + new String:auth[100]; + GetClientAuthString(data, auth, sizeof(auth)); + + new String:createsql[250]; + Format(createsql, sizeof(createsql), "INSERT INTO autoinvite_player(steamid) VALUES ('%s')", auth); + SQL_TQuery(dbcon, EmptyResultSet, createsql); + } + } +} + +public EmptyResultSet(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } +} \ No newline at end of file diff --git a/autorespawn_for_admins.sp b/autorespawn_for_admins.sp new file mode 100644 index 0000000..130c4a1 --- /dev/null +++ b/autorespawn_for_admins.sp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include + +#define AFA_VERSION "1.5.8" + +new bool:temp_disabled = false +new Handle:h_enabled, Handle:h_time, Handle:h_admins_only; +new Float:client_orgin[MAXPLAYERS][3]; +new Float:client_angels[MAXPLAYERS][3]; +new Handle:h_sudden_death, Handle:h_re, Handle:h_teleport_enabled, + Handle:h_flag, Handle:h_tags; +new AdminFlag:cflag; + +public Plugin:myinfo = +{ + name = "Autorespawn for Admins", + author = "Chefe", + description = "Respawn(&Teleport) Admins/Players in a varaible amount of time.", + version = AFA_VERSION, + url = "http://forums.alliedmods.net/showthread.php?t=110918" +} + +public OnPluginStart() +{ + HookEvent("player_death", Event_PlayerDeath) + HookEvent("teamplay_round_win", Event_TeamplayRoundWin) + HookEvent("teamplay_round_start", Event_TeamplayRoundStart) + HookEvent("teamplay_suddendeath_begin", Event_SuddendeathBegin) + h_enabled = CreateConVar("sm_instant_enabled", "1", "Enable or Disable Instant Respawn for Admins."); + h_time = CreateConVar("sm_instant_time", "0.1", "Set the Instant Respawn Time for Admins.", _, true, 0.1); + h_admins_only = CreateConVar("sm_instant_admins_only", "1", "Set is instant respawn only enabled for admins or for all."); + h_sudden_death = CreateConVar("sm_instant_sudeath", "1", "Enable or Disable the Respawn in Sudden Death."); + h_re = CreateConVar("sm_instant_re", "1", "Enable or Disable the Respawn on Roundend"); + h_teleport_enabled = CreateConVar("sm_instant_teleport", "0", "Enable or Disable teleport Player to ther old Position"); + h_flag = CreateConVar("sm_instant_flag", "t", "Set the flag witch admins must have to use instant respawn."); + CreateConVar("sm_instant_version", AFA_VERSION, "Autorespawn Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); + + AutoExecConfig(true); + + new String:flagcvar[1]; + GetConVarString(h_flag, flagcvar, sizeof(flagcvar)); + FindFlagByChar(flagcvar[0], cflag); + + h_tags = FindConVar("sv_tags"); + HookConVarChange(h_tags, OnTagsChange); + CheckForPluginTag(h_tags, "respawntimes"); +} + +CheckForPluginTag(Handle:convar, String:tag[]) +{ + new String:oldtags[256]; + GetConVarString(convar, oldtags, sizeof(oldtags)); + + if (StrContains(oldtags, tag, false) == -1) + { + new String:newtags[256]; + Format(newtags, sizeof(newtags), "%s,%s", oldtags, tag); + + SetConVarString(convar, newtags, _, true); + } +} + +RemovePluginTag(Handle:convar, String:tag[]) +{ + new String:oldtags[256]; + GetConVarString(convar, oldtags, sizeof(oldtags)); + + if (StrContains(oldtags, tag, false) != -1) + { + ReplaceString(oldtags, sizeof(oldtags), tag, "", false); + + SetConVarString(convar, oldtags, _, true); + } +} + +public OnPluginEnd() +{ + RemovePluginTag(h_tags, "respawntimes"); +} + +public OnTagsChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + CheckForPluginTag(h_tags, "respawntimes"); +} + +public Event_SuddendeathBegin(Handle:event,const String:name[],bool:dontBroadcast) +{ + if (!GetConVarBool(h_sudden_death)) + { + temp_disabled = true; + } +} + +public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client_userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(client_userid); + + new AdminId:admin_id = GetUserAdmin(client); + + if (GetConVarBool(h_teleport_enabled)) + { + GetClientAbsOrigin(client, client_orgin[client]); + GetClientAbsAngles(client, client_angels[client]); + } + + new Float:time = GetConVarFloat(h_time); + new death_flags = GetEventInt(event, "death_flags"); + + if (GetConVarBool(h_admins_only)) + { + if (admin_id != INVALID_ADMIN_ID && IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled && !(death_flags & 32) && GetAdminFlag(admin_id, cflag, AdmAccessMode:Access_Effective)) + { + CreateTimer(time, RespawnClient, client) + } + } + else + { + if (IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled && !(death_flags & 32)) + { + CreateTimer(time, RespawnClient, client) + } + } +} + +public Event_TeamplayRoundWin(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (!GetConVarBool(h_re)) + { + temp_disabled = true; + } +} + +public Event_TeamplayRoundStart(Handle:event, const String:name[], bool:dontBroadcast) +{ + temp_disabled = false; +} + +public Action:RespawnClient(Handle:timer, any:client) +{ + if (IsClientInGame(client)) + { + TF2_RespawnPlayer(client); + if (GetConVarBool(h_teleport_enabled)) + { + TeleportEntity(client, client_orgin[client], client_angels[client], NULL_VECTOR); + } + } +} \ No newline at end of file diff --git a/autorespawn_for_admins_css.sp b/autorespawn_for_admins_css.sp new file mode 100644 index 0000000..51ff29b --- /dev/null +++ b/autorespawn_for_admins_css.sp @@ -0,0 +1,138 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include +#include + +#define AFA_VERSION "1.5.5" + +new bool:temp_disabled = false +new Handle:h_enabled, Handle:h_time, Handle:h_admins_only; +new Float:client_orgin[MAXPLAYERS][3]; +new Float:client_angels[MAXPLAYERS][3]; +new Handle:h_teleport_enabled, Handle:h_flag; +new AdminFlag:cflag; + +public Plugin:myinfo = +{ + name = "Autorespawn for Admins", + author = "Chefe", + description = "Respawn(&Teleport) Admins/Players in a varaible amount of time.", + version = AFA_VERSION, + url = "http://forums.alliedmods.net/showthread.php?t=110918" +} + +public OnPluginStart() +{ + HookEvent("player_death", Event_PlayerDeath) + HookEvent("player_class", Event_PlayerClass); + HookEvent("player_team", Event_PlayerTeam); + h_enabled = CreateConVar("sm_instant_enabled", "1", "Enable or Disable Instant Respawn for Admins."); + h_time = CreateConVar("sm_instant_time", "0.1", "Set the Instant Respawn Time.", _, true, 0.1); + h_admins_only = CreateConVar("sm_instant_admins_only", "1", "Set is instant respawn only enabled for admins or for all."); + h_teleport_enabled = CreateConVar("sm_instant_teleport", "0", "Enable or Disable teleport Player to ther old Position"); + h_flag = CreateConVar("sm_instant_flag", "t", "Set the flag witch admins must have to use instant respawn."); + CreateConVar("sm_instant_version", AFA_VERSION, "Autorespawn Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); + + AutoExecConfig(true); + + new String:flagcvar[1]; + GetConVarString(h_flag, flagcvar, sizeof(flagcvar)); + FindFlagByChar(flagcvar[0], cflag); +} + +public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client_userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(client_userid); + + new AdminId:admin_id = GetUserAdmin(client); + + if (GetConVarBool(h_teleport_enabled)) + { + GetClientAbsOrigin(client, client_orgin[client]); + GetClientAbsAngles(client, client_angels[client]); + } + + new Float:time = GetConVarFloat(h_time); + + if (GetConVarBool(h_admins_only)) + { + if (admin_id != INVALID_ADMIN_ID && IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled && GetAdminFlag(admin_id, cflag, AdmAccessMode:Access_Effective)) + { + CreateTimer(time, RespawnClient, client) + } + } + else + { + if (IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled) + { + CreateTimer(time, RespawnClient, client) + } + } +} + +public Event_PlayerClass(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client_userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(client_userid); + //new team = GetEventInt(event, "team"); + + new AdminId:admin_id = GetUserAdmin(client); + + new Float:time = GetConVarFloat(h_time); + + if (GetConVarBool(h_admins_only)) + { + if (admin_id != INVALID_ADMIN_ID && IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled && GetAdminFlag(admin_id, cflag, AdmAccessMode:Access_Effective)) + { + CreateTimer(time, RespawnClient, client) + } + } + else + { + if (IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled) + { + CreateTimer(time, RespawnClient, client) + } + } +} + +public Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client_userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(client_userid); + new team = GetEventInt(event, "team"); + + new AdminId:admin_id = GetUserAdmin(client); + + new Float:time = GetConVarFloat(h_time); + + if (GetConVarBool(h_admins_only)) + { + if (team > 0 && admin_id != INVALID_ADMIN_ID && IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled && GetAdminFlag(admin_id, cflag, AdmAccessMode:Access_Effective)) + { + CreateTimer(time, RespawnClient, client) + } + } + else + { + if (team > 0 && IsClientInGame(client) && GetConVarBool(h_enabled) && !temp_disabled) + { + CreateTimer(time, RespawnClient, client) + } + } +} + +public Action:RespawnClient(Handle:timer, any:client) +{ + if (IsClientInGame(client)) + { + CS_RespawnPlayer(client); + if (GetConVarBool(h_teleport_enabled)) + { + TeleportEntity(client, client_orgin[client], client_angels[client], NULL_VECTOR); + } + } +} \ No newline at end of file diff --git a/autoteambalance.sp b/autoteambalance.sp new file mode 100644 index 0000000..9cd8e47 --- /dev/null +++ b/autoteambalance.sp @@ -0,0 +1,115 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include + +new Handle:cv_enabled, Handle:cv_unbalancelimit; +new bool:tmp_disabled = false; + +public Plugin:myinfo = +{ + name = "Automated Teambalancer", + author = "Chefe", + description = "Balances teams", + version = "1.0", + url = "www.chefgaming.de" +} + +public OnPluginStart() +{ + cv_enabled = CreateConVar("sm_atb_enabled", "1", "Enabled/Disable the ATB"); + cv_unbalancelimit = CreateConVar("sm_atb_limit", "1", "The max difference beetween the teams"); + HookEvent("player_team", Event_PlayerTeam); +} + +public OnMapStart() +{ + tmp_disabled = false; +} + +public OnMapEnd() +{ + tmp_disabled = true; +} + +public Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) +{ + CheckTeams(); +} + +public OnClientDisconnect(client) +{ + CheckTeams(); +} + +CheckTeams() +{ + if (!tmp_disabled && GetConVarBool(cv_enabled)) + { + new cred = GetTeamClientCount(2); + new cblu = GetTeamClientCount(3); + new dif = cred-cblu; + + if (dif > GetConVarInt(cv_unbalancelimit)) + { + DoClientMove(GetRandomPlayer(2), 3); + } + else if (dif < -GetConVarInt(cv_unbalancelimit)) + { + DoClientMove(GetRandomPlayer(3), 2); + } + } +} + +public Action:TmpDis(Handle:timer, any:client) +{ + tmp_disbaled = false; + CheckTeams(); +} + +public Action:TmpDelay(Handle:timer, any:client) +{ + CheckTeams(); +} + +GetRandomPlayer(team) +{ + new client; + new i = 0; + + while (i < 1000) + { + client = GetRandomInt(1, GetClientCount(true)); + + if (IsClientInGame(client) && GetClientTeam(client) == team && !IsClientAdm(client) && !TF2_IsPlayerInDuel(client)) + { + break; + } + } + + return client; +} + +DoClientMove(client, team) +{ + new String:teamname[50]; + GetTeamName(team, teamname, sizeof(teamname)); + + tmp_disbaled = true; + ChangeClientTeam(client, team); + PrintToChatAll("\x04%N\x01 was moved to %s for teambalance", client, teamname); +} + +IsClientAdm(client) +{ + new AdminId:admid = GetUserAdmin(client); + if (admid != INVALID_ADMIN_ID) + { + return GetAdminFlag(admid, AdminFlag:Admin_Custom2); + } + else + { + return false; + } +} \ No newline at end of file diff --git a/basic_player_votes.sp b/basic_player_votes.sp new file mode 100644 index 0000000..702066b --- /dev/null +++ b/basic_player_votes.sp @@ -0,0 +1,124 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include + +new kickclients[MAXPLAYERS+1]; +new banclients[MAXPLAYERS+1]; +new muteclients[MAXPLAYERS+1]; +new alreadyvoted_kick[MAXPLAYERS+1]; +new alreadyvoted_ban[MAXPLAYERS+1]; +new alreadyvoted_mute[MAXPLAYERS+1]; + +public Plugin:myinfo = +{ + name = "Basic Votes", + author = "Chefe", + description = "<- Description ->", + version = "1.1", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegConsoleCmd("sm_votekick", Command_VoteKick, "Vote for kick a client.") + RegConsoleCmd("sm_voteban", Command_VoteBan, "Vote for ban a client.") +} + +public OnClientConnected(client) +{ + alreadyvoted_kick[client] = 0; + alreadyvoted_ban[client] = 0; + alreadyvoted_mute[client] = 0; +} + +public OnClientDisconnect(client) +{ + alreadyvoted_kick[client] = 0; + alreadyvoted_ban[client] = 0; + alreadyvoted_mute[client] = 0; +} + +public Action:Command_VoteKick(client, args) +{ + new Handle:votekick = CreateMenu(Menu_VoteKick); + SetMenuTitle(votekick, "Select Player to Vote") + AddTargetsToMenu(votekick, 0, true, false); + DisplayMenu(votekick, client, MENU_TIME_FOREVER); + + return Plugin_Handled; +} + +public Action:Command_VoteBan(client, args) +{ + new Handle:voteban = CreateMenu(Menu_VoteBan); + SetMenuTitle(voteban, "Select Player to Vote"); + AddTargetsToMenu(voteban, 0, true, false); + DisplayMenu(voteban, client, MENU_TIME_FOREVER); + + return Plugin_Handled; +} + +public Menu_VoteKick(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + new client = GetClientOfUserId(StringToInt(info)); + new required = (60 * GetClientCount(true) / 100); + + if (alreadyvoted_kick[param1] != client) + { + kickclients[client]++; + alreadyvoted_kick[param1] = client; + PrintToChatAll(" [SM] Register votekicks against %N (%i registered, %i required)", client, kickclients[client], required); + } + else + { + PrintToChat(param1, "[SM] You have already voted for %N", client); + } + + if (kickclients[client] >= required) + { + KickClient(client, "You are kicked by Vote!"); + PrintToChatAll("[SM] Kicked %N by %i votes.", client, kickclients[client]); + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_VoteBan(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + new client = GetClientOfUserId(StringToInt(info)); + new required = (60 * GetClientCount(true) / 100); + + if (alreadyvoted_ban[param1] != client) + { + banclients[client]++; + alreadyvoted_ban[param1] = client; + PrintToChatAll(" [SM] Register voteban against %N (%i registered, %i required)", client, banclients[client], required); + } + else + { + PrintToChat(param1, "[SM] You have already voted for %N", client); + } + + if (banclients[client] >= required) + { + BanClient(client, 3600, BANFLAG_AUTHID, "Voteban.", "You are banned by Vote for %i seconds!"); + PrintToChatAll("[SM] Banned %N for %i seconds by %i votes.", client, 3600, kickclients[client]); + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} diff --git a/beer.sp b/beer.sp new file mode 100644 index 0000000..8e83352 --- /dev/null +++ b/beer.sp @@ -0,0 +1,734 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include + +new Handle:g_NextMap = INVALID_HANDLE; +new Handle:g_ChangeMap = INVALID_HANDLE; +new Handle:g_NominationMap = INVALID_HANDLE; + +new Handle:cv_serverid, Handle:cv_lotto; + +new price_nomination = 25; +new price_mapvote = 100; +new price_nextmap = 150; +new price_changelevel = 200; + +new String:MapchangeTo[100]; + +public Plugin:myinfo = +{ + name = "Beer System", + author = "Chefe", + description = "System that gives Players Points for they Playtime.", + version = "2.4", + url = "www.the-bos.de" +} + +public OnPluginStart() +{ + CreateTimer(300.0, Abbrechnung, _, TIMER_REPEAT); + RegConsoleCmd("sm_beer", CommandLP, "Shows you your liter Beer!"); + cv_serverid = CreateConVar("sm_beer_serverid", "0", "Serverid for remove liter"); + cv_lotto = CreateConVar("sm_beer_lotto", "0", "Lotto I/0"); + //HookEvent("player_activate", Event_PlayerActivate); + + if (GetConVarBool(cv_lotto)) + { + CreateTimer(7200.0, LottoZiehung, _, TIMER_REPEAT); + } + + if (CheckCon()) + { + PrintToServer("[BEER] Connection sucessfull!"); + } + else + { + SetFailState("Can't etablish connection to Database"); + } + + AutoExecConfig(true); +} + +public OnMapStart() +{ + MapchangeTo = NULL_STRING; + g_NextMap = BuildMapMenu(Menu_NextMap); + g_ChangeMap = BuildMapMenu(Menu_ChangeMap); + g_NominationMap = BuildMapMenu(Menu_NominateMap); +} + +public OnMapEnd() +{ + if (g_NextMap != INVALID_HANDLE) + { + CloseHandle(g_NextMap); + g_NextMap = INVALID_HANDLE; + } + + if (g_ChangeMap != INVALID_HANDLE) + { + CloseHandle(g_ChangeMap); + g_ChangeMap = INVALID_HANDLE; + } + + if (g_NominationMap != INVALID_HANDLE) + { + CloseHandle(g_NominationMap); + g_NominationMap = INVALID_HANDLE; + } +} + +Handle:BuildMapMenu(MenuHandler:handel) +{ + /* Open the file */ + new Handle:file = OpenFile("mapcycle.txt", "rt"); + if (file == INVALID_HANDLE) + { + return INVALID_HANDLE; + } + + /* Create the menu Handle */ + new Handle:menu = CreateMenu(handel); + new String:mapname[255]; + while (!IsEndOfFile(file) && ReadFileLine(file, mapname, sizeof(mapname))) + { + if (mapname[0] == ';' || !IsCharAlpha(mapname[0])) + { + continue; + } + /* Cut off the name at any whitespace */ + new len = strlen(mapname); + for (new i=0; i= price_nomination) + { + DisplayMenu(g_NominationMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need %i l to nominate!", lp, price_nomination); + } + } + case 3: + { + new lp = GetLP(param1); + + if (lp >= price_mapvote) + { + RemoveLP(param1, price_mapvote); + + PrintToChatAll("\x04[BEER]\x01 %N forced Mapvote!", param1) + + InitiateMapChooserVote(MapChange_Instant); + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need %i l to force Mapvote!", lp, price_mapvote); + } + } + case 4: + { + new lp = GetLP(param1); + + if (lp >= price_nextmap) + { + DisplayMenu(g_NextMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need %i l to set Nextmap!", lp, price_nextmap); + } + } + case 5: + { + new lp = GetLP(param1); + + if (lp >= price_changelevel) + { + DisplayMenu(g_ChangeMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need %i l to change the Map!", lp, price_changelevel); + } + } + case 6: + { + + } + case 7: + { + new Handle:menu2 = CreateMenu(MenuRS); + SetMenuTitle(menu2, "Select RS-time"); + AddMenuItem(menu2, "1", "1 Day (100 l)"); + AddMenuItem(menu2, "2", "5 Days (450 l)"); + AddMenuItem(menu2, "3", "14 Days (800 l)"); + AddMenuItem(menu2, "4", "30 Days (999 l)"); + DisplayMenu(menu2, param1, MENU_TIME_FOREVER); + } + } + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_NextMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + /* Get item info */ + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_nextmap); + PrintToChatAll("\x04[BEER]\x01 %N changed the nextmap to %s!", param1, info); + SetNextMap(info); + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_ChangeMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + /* Get item info */ + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_changelevel); + PrintToChatAll("\x04[BEER]\x01 %N forced mapchange to %s!", param1, info); + + if (!strcmp(MapchangeTo, NULL_STRING, false)) + { + MapchangeTo = info; + CreateTimer(5.0, Timer_Changelevel); + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 Mapchange already in Progress"); + } + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Action:Timer_Changelevel(Handle:timer) +{ + ForceChangeLevel(MapchangeTo, "BEER"); +} + +public Menu_NominateMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + /* Get item info */ + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_nomination); + PrintToChatAll("\x04[BEER]\x01 %N nominated %s!", param1, info); + NominateMap(info, true, 0); + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public MenuRS(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + + new lp = GetLP(param1) + + switch(StringToInt(info)) + { + case 1: + { + if (lp >= 100) + { + + RemoveLP(param1, 100) + GiveRS(param1, 1440); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[BEER]\x01 You have bouth RS! If Server is full, connect via console, and you can connect!") + } + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need 100 l for 1 Day RS!", lp); + } + } + case 2: + { + if (lp >= 450) + { + + RemoveLP(param1, 450) + GiveRS(param1, 7200); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[BEER]\x01 You have bouth RS! If Server is full, connect via console, and you can connect!") + } + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need 450 l for 5 Days RS!", lp); + } + } + case 3: + { + if (lp >= 800) + { + + RemoveLP(param1, 800) + GiveRS(param1, 20160); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[BEER]\x01 You have bouth RS! If Server is full, connect via console, and you can connect!") + } + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need 800 l for 14 Days RS!", lp); + } + } + case 4: + { + if (lp >= 100) + { + + RemoveLP(param1, 999) + GiveRS(param1, 43200); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[BEER]\x01 You have bouth RS! If Server is full, connect via console, and you can connect!") + } + } + else + { + PrintToChat(param1, "\x04[BEER]\x01 You have %i liter, but you need 999 l for 30 Days RS!", lp); + } + } + } + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Action:Abbrechnung(Handle:timer) +{ + new players = GetClientCount(false); + new players_max = GetMaxClients(); + + if (players <= (players_max / 4)) + { + GiveLP(3); + } + else if (players <= (players_max / 2)) + { + GiveLP(2); + } + else + { + GiveLP(1); + } + + RemoveRSMIN(5) + + PrintToChatAll("\x04[Oktoberfest]\x01 Our Server running the \x04Beer!\x01 System to reward Players."); + PrintToChatAll("\x04[BEER]\x01 Type \x04!beer\x01 to get up the Beer! menu with more options."); + PrintHintTextToAll("[BEER] ONLINE"); +} + +GetLP(client) +{ + new String:steamid[125]; + GetClientAuthString(client, steamid, sizeof(steamid)); + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT points FROM lp WHERE steamid = '%s'", steamid); + + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + new Handle:sql = SQL_Query(db, sqlstring); + + SQL_FetchRow(sql); + new lp = SQL_FetchInt(sql, 0); + + CloseHandle(sql); + CloseHandle(db); + + return lp; +} + +GiveLP(amount) +{ + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + new i = 1; + + while (i != (MaxClients+1)) + { + new client = i; + if (IsClientInGame(client)) + { + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points + %i WHERE steamid = '%s'", amount, steamid); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + + PrintToServer("[BEER] Gived %N %i l (client %i)", client, amount, i); + } + i = i + 1; + } + + CloseHandle(db); +} + +RemoveLP(client, amount) +{ + if (IsClientInGame(client)) + { + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points - %i WHERE steamid = '%s'", amount, steamid); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + CloseHandle(db); + } +} + +GiveRS(client, min) +{ + if (IsClientInGame(client)) + { + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + // In die lp-Datenbank eintragen (Step 1) + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rs = 1, rsmin = %i, serverid = %i WHERE steamid = '%s'", min, GetConVarInt(cv_serverid), steamid); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + + // In die Sm-Admin Datenbank eintragen (Step 2) + + Format(sqlstring, sizeof(sqlstring), "INSERT INTO sm_admins(authtype, identity, flags, name, immunity) VALUES ('steam','%s', 'b,a', '%N', 5)", steamid, client); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + + CloseHandle(db); + + ServerCommand("sm_reloadadmins"); + } +} + +bool:HaveClientRS(client) +{ + if (IsClientInGame(client)) + { + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE steamid = '%s' AND rs = '1'", steamid); + + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + new Handle:sql = SQL_Query(db, sqlstring); + new rs_bool = SQL_GetRowCount(sql); + CloseHandle(sql); + CloseHandle(db); + + if (rs_bool >= 1) + { + return true; + } + else if (rs_bool == 0) + { + return false; + } + } + else + { + return true; + } + + return true; +} + +GetRSMIN(client) +{ + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)); + new String:sqlstring[200]; + Format(sqlstring, sizeof(sqlstring), "SELECT rsmin FROM lp WHERE steamid = '%s'", steamid); + + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + new Handle:sql = SQL_Query(db, sqlstring); + + SQL_FetchRow(sql); + new rsmin = SQL_FetchInt(sql, 0); + + CloseHandle(sql); + CloseHandle(db); + + return rsmin; +} + +RemoveRSMIN(min) +{ + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rsmin = rsmin - %i WHERE rs = 1 AND serverid = %i", min, GetConVarInt(cv_serverid)); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + + new String:sqlstring2[150]; + Format(sqlstring2, sizeof(sqlstring2), "SELECT steamid FROM lp WHERE rs = 1 AND serverid = %i AND rsmin <= 0", GetConVarInt(cv_serverid)); + + new Handle:sql = SQL_Query(db, sqlstring2); + new nummber = SQL_GetRowCount(sql); + + if (nummber != 0) + { + for (new a = 0; a != nummber; a++) + { + new String:steamid[256]; + SQL_FetchRow(sql); + SQL_FetchString(sql, 0, steamid, sizeof(steamid)); + + // Aus der LP-Datenbank austragen (Step 1) + new String:sqlstr[256]; + Format(sqlstr, sizeof(sqlstr), "UPDATE lp SET rs = 0, rsmin = 0, serverid = 0 WHERE steamid = '%s'", steamid); + + if (!SQL_FastQuery(db, sqlstr)) + { + new String:ero[255]; + SQL_GetError(db, ero, sizeof(ero)); + PrintToServer("Failed to query (error: %s)", ero); + } + + // Aus der SM-Admin Datenbank austragen (Step 2) + new String:sqlstr2[150]; + Format(sqlstr2, sizeof(sqlstr2), "DELETE FROM sm_admins WHERE identity = '%s'", steamid); + + if (!SQL_FastQuery(db, sqlstr2)) + { + new String:ero2[255]; + SQL_GetError(db, ero2, sizeof(ero2)); + PrintToServer("Failed to query (error: %s)", ero2); + } + } + ServerCommand("sm_reloadadmins"); + } + + CloseHandle(sql); + CloseHandle(db); +} + +public Action:LottoZiehung(Handle:timer) +{ + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + for (new i = 1; i != (GetMaxClients()+1); i++) + { + if (IsClientInGame(i)) + { + if (0.25 >= GetRandomFloat(0.1, 1.0)) + { + new String:steamid[50]; + GetClientAuthString(i, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points + 500 WHERE steamid = '%s'", steamid); + + if (!SQL_FastQuery(db, sqlstring)) + { + new String:error[255]; + SQL_GetError(db, error, sizeof(error)); + PrintToServer("Failed to query (error: %s)", error); + } + + PrintToChat(i, "\x01[\x04BEER\x01] Congratulations, you have won in the BEER Lottery! You got \x04500 l\x01 add to your beer stock!"); + PrintToChatAll("\x01[\x04BEER\x01] %N won in the BEER Lottery!", i); + } + } + } + CloseHandle(db); +} + +CheckCon() +{ + new String:error_connect[255]; + new Handle:db = SQL_Connect("db", false, error_connect, sizeof(error_connect)); + + if (db != INVALID_HANDLE) + { + CloseHandle(db); + return 1; + } + else + { + CloseHandle(db); + return 0; + } +} \ No newline at end of file diff --git a/buffreloader.sp b/buffreloader.sp new file mode 100644 index 0000000..67d9246 --- /dev/null +++ b/buffreloader.sp @@ -0,0 +1,27 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +public Plugin:myinfo = +{ + name = "buffReloader", + author = "Chefe", + description = "<- Description ->", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_reloadbuff", Command_RB, ADMFLAG_CHEATS, "reloads buffbanner"); +} + +public Action:Command_RB(client, args) +{ + if (IsPlayerAlive(client) && IsClientInGame(client)) + { + SetEntPropFloat(client, Prop_Send, "m_flRageMeter", 100.0); + return Plugin_Handled; + } + return Plugin_Handled; +} \ No newline at end of file diff --git a/classrestrict.sp b/classrestrict.sp new file mode 100644 index 0000000..7f324d0 --- /dev/null +++ b/classrestrict.sp @@ -0,0 +1,194 @@ +#pragma semicolon 1 + +#include +#include + +#define PL_VERSION "0.6" + +#define TF_CLASS_DEMOMAN 4 +#define TF_CLASS_ENGINEER 9 +#define TF_CLASS_HEAVY 6 +#define TF_CLASS_MEDIC 5 +#define TF_CLASS_PYRO 7 +#define TF_CLASS_SCOUT 1 +#define TF_CLASS_SNIPER 2 +#define TF_CLASS_SOLDIER 3 +#define TF_CLASS_SPY 8 +#define TF_CLASS_UNKNOWN 0 + +#define TF_TEAM_BLU 3 +#define TF_TEAM_RED 2 + +public Plugin:myinfo = +{ + name = "TF2 Class Restrictions", + author = "Tsunami", + description = "Restrict classes in TF2.", + version = PL_VERSION, + url = "http://www.tsunami-productions.nl" +} + +new g_iClass[MAXPLAYERS + 1]; +new Handle:g_hEnabled; +new Handle:g_hFlags; +new Handle:g_hImmunity; +new Handle:g_hLimits[4][10]; +new String:g_sSounds[10][24] = {"", "vo/scout_no03.wav", "vo/sniper_no04.wav", "vo/soldier_no01.wav", + "vo/demoman_no03.wav", "vo/medic_no03.wav", "vo/heavy_no02.wav", + "vo/pyro_no01.wav", "vo/spy_no02.wav", "vo/engineer_no03.wav"}; + +public OnPluginStart() +{ + CreateConVar("sm_classrestrict_version", PL_VERSION, "Restrict classes in TF2.", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); + g_hEnabled = CreateConVar("sm_classrestrict_enabled", "1", "Enable/disable restricting classes in TF2."); + g_hFlags = CreateConVar("sm_classrestrict_flags", "", "Admin flags for restricted classes in TF2."); + g_hImmunity = CreateConVar("sm_classrestrict_immunity", "0", "Enable/disable admins being immune for restricted classes in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_DEMOMAN] = CreateConVar("sm_classrestrict_blu_demomen", "-1", "Limit for Blu demomen in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_ENGINEER] = CreateConVar("sm_classrestrict_blu_engineers", "-1", "Limit for Blu engineers in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_HEAVY] = CreateConVar("sm_classrestrict_blu_heavies", "-1", "Limit for Blu heavies in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_MEDIC] = CreateConVar("sm_classrestrict_blu_medics", "-1", "Limit for Blu medics in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_PYRO] = CreateConVar("sm_classrestrict_blu_pyros", "-1", "Limit for Blu pyros in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_SCOUT] = CreateConVar("sm_classrestrict_blu_scouts", "-1", "Limit for Blu scouts in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_SNIPER] = CreateConVar("sm_classrestrict_blu_snipers", "-1", "Limit for Blu snipers in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_SOLDIER] = CreateConVar("sm_classrestrict_blu_soldiers", "-1", "Limit for Blu soldiers in TF2."); + g_hLimits[TF_TEAM_BLU][TF_CLASS_SPY] = CreateConVar("sm_classrestrict_blu_spies", "-1", "Limit for Blu spies in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_DEMOMAN] = CreateConVar("sm_classrestrict_red_demomen", "-1", "Limit for Red demomen in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_ENGINEER] = CreateConVar("sm_classrestrict_red_engineers", "-1", "Limit for Red engineers in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_HEAVY] = CreateConVar("sm_classrestrict_red_heavies", "-1", "Limit for Red heavies in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_MEDIC] = CreateConVar("sm_classrestrict_red_medics", "-1", "Limit for Red medics in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_PYRO] = CreateConVar("sm_classrestrict_red_pyros", "-1", "Limit for Red pyros in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_SCOUT] = CreateConVar("sm_classrestrict_red_scouts", "-1", "Limit for Red scouts in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_SNIPER] = CreateConVar("sm_classrestrict_red_snipers", "-1", "Limit for Red snipers in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_SOLDIER] = CreateConVar("sm_classrestrict_red_soldiers", "-1", "Limit for Red soldiers in TF2."); + g_hLimits[TF_TEAM_RED][TF_CLASS_SPY] = CreateConVar("sm_classrestrict_red_spies", "-1", "Limit for Red spies in TF2."); + + HookEvent("player_changeclass", Event_PlayerClass); + HookEvent("player_spawn", Event_PlayerSpawn); + HookEvent("player_team", Event_PlayerTeam); + + AutoExecConfig(true); +} + +public OnMapStart() +{ + decl i, String:sSound[32]; + for(i = 1; i < sizeof(g_sSounds); i++) + { + Format(sSound, sizeof(sSound), "sound/%s", g_sSounds[i]); + PrecacheSound(g_sSounds[i]); + AddFileToDownloadsTable(sSound); + } +} + +public OnClientPutInServer(client) +{ + g_iClass[client] = TF_CLASS_UNKNOWN; +} + +public Event_PlayerClass(Handle:event, const String:name[], bool:dontBroadcast) +{ + new iClient = GetClientOfUserId(GetEventInt(event, "userid")), + iClass = GetEventInt(event, "class"), + iTeam = GetClientTeam(iClient); + + if(!(GetConVarBool(g_hImmunity) && IsImmune(iClient)) && IsFull(iTeam, iClass)) + { + ShowVGUIPanel(iClient, iTeam == TF_TEAM_BLU ? "class_blue" : "class_red"); + EmitSoundToClient(iClient, g_sSounds[iClass]); + TF2_SetPlayerClass(iClient, TFClassType:g_iClass[iClient]); + } +} + +public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +{ + new iClient = GetClientOfUserId(GetEventInt(event, "userid")), + iTeam = GetClientTeam(iClient); + + if(!(GetConVarBool(g_hImmunity) && IsImmune(iClient)) && IsFull(iTeam, (g_iClass[iClient] = _:TF2_GetPlayerClass(iClient)))) + { + ShowVGUIPanel(iClient, iTeam == TF_TEAM_BLU ? "class_blue" : "class_red"); + EmitSoundToClient(iClient, g_sSounds[g_iClass[iClient]]); + PickClass(iClient); + } +} + +public Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) +{ + new iClient = GetClientOfUserId(GetEventInt(event, "userid")), + iTeam = GetEventInt(event, "team"); + + if(!(GetConVarBool(g_hImmunity) && IsImmune(iClient)) && IsFull(iTeam, g_iClass[iClient])) + { + ShowVGUIPanel(iClient, iTeam == TF_TEAM_BLU ? "class_blue" : "class_red"); + EmitSoundToClient(iClient, g_sSounds[g_iClass[iClient]]); + PickClass(iClient); + } +} + +bool:IsFull(iTeam, iClass) +{ + // If plugin is disabled, or team or class is invalid, class is not full + if(!GetConVarBool(g_hEnabled) || iTeam < TF_TEAM_RED || iClass < TF_CLASS_SCOUT) + return false; + + // Get team's class limit + new iLimit, + Float:flLimit = GetConVarFloat(g_hLimits[iTeam][iClass]); + + // If limit is a percentage, calculate real limit + if(flLimit > 0.0 && flLimit < 1.0) + iLimit = RoundToNearest(flLimit * GetTeamClientCount(iTeam)); + else + iLimit = RoundToNearest(flLimit); + + // If limit is -1, class is not full + if(iLimit == -1) + return false; + // If limit is 0, class is full + else if(iLimit == 0) + return true; + + // Loop through all clients + for(new i = 1, iCount = 0; i <= MaxClients; i++) + { + // If client is in game, on this team, has this class and limit has been reached, class is full + if(IsClientInGame(i) && GetClientTeam(i) == iTeam && _:TF2_GetPlayerClass(i) == iClass && ++iCount > iLimit) + return true; + } + + return false; +} + +bool:IsImmune(iClient) +{ + if(!iClient || !IsClientInGame(iClient)) + return false; + + decl String:sFlags[32]; + GetConVarString(g_hFlags, sFlags, sizeof(sFlags)); + + // If flags are specified and client has generic or root flag, client is immune + return !StrEqual(sFlags, "") && GetUserFlagBits(iClient) & (ReadFlagString(sFlags)|ADMFLAG_ROOT); +} + +PickClass(iClient) +{ + // Loop through all classes, starting at random class + for(new i = GetRandomInt(TF_CLASS_SCOUT, TF_CLASS_ENGINEER), iClass = i, iTeam = GetClientTeam(iClient);;) + { + // If team's class is not full, set client's class + if(!IsFull(iTeam, i)) + { + TF2_SetPlayerClass(iClient, TFClassType:i); + TF2_RespawnPlayer(iClient); + g_iClass[iClient] = i; + break; + } + // If next class index is invalid, start at first class + else if(++i > TF_CLASS_ENGINEER) + i = TF_CLASS_SCOUT; + // If loop has finished, stop searching + else if(i == iClass) + break; + } +} \ No newline at end of file diff --git a/colortest.sp b/colortest.sp new file mode 100644 index 0000000..e5806ca --- /dev/null +++ b/colortest.sp @@ -0,0 +1,33 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +public Plugin:myinfo = +{ + name = "TestPlugin", + author = "Chefe", + description = "test", + version = "1.0", + url = "<- test ->" +} + +public OnPluginStart() +{ + RegConsoleCmd("sm_test", Command_Test, "test"); +} + +public Action:Command_Test(client, args) +{ + PrintToChatAll("\x00 Farbe 00"); + PrintToChatAll("\x01 Farbe 01"); + PrintToChatAll("\x02 Farbe 02"); + PrintToChatAll("\x03 Farbe 03"); + PrintToChatAll("\x04 Farbe 04"); + PrintToChatAll("\x05 Farbe 05"); + PrintToChatAll("\x06 Farbe 06"); + PrintToChatAll("\x07 Farbe 07"); + PrintToChatAll("\x08 Farbe 08"); + PrintToChatAll("\x09 Farbe 09"); + PrintToChatAll("\x10 Farbe 10"); + return Plugin_Handled; +} \ No newline at end of file diff --git a/coop.sp b/coop.sp new file mode 100644 index 0000000..d20a03e --- /dev/null +++ b/coop.sp @@ -0,0 +1,63 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include + +new TFClassType:classarray[9]; + +public Plugin:myinfo = +{ + name = "Coop Plugin", + author = "Chefe", + description = "Coop Setting", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + HookEvent("player_activate", Event_PlayerActive); + + classarray[0] = TF2_GetClass("scout"); + classarray[1] = TF2_GetClass("soldier"); + classarray[2] = TF2_GetClass("pyro"); + classarray[3] = TF2_GetClass("demoman"); + classarray[4] = TF2_GetClass("heavyweapons"); + classarray[5] = TF2_GetClass("engineer"); + classarray[6] = TF2_GetClass("medic"); + classarray[7] = TF2_GetClass("sniper"); + classarray[8] = TF2_GetClass("spy"); +} + +public Event_PlayerActive(Handle:event,const String:name[],bool:dontBroadcast) +{ + new uid = GetEventInt(event, "userid"); + new ev_client = GetClientOfUserId(uid); + + new i = 1; + + while (i != (MaxClients+1)) + { + new client = i; + if (IsClientInGame(client)) + { + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + if (strcmp(steamid, "BOT") != 0) + { + ChangeClientTeam(ev_client, GetClientTeam(client)); + TF2_SetPlayerClass(ev_client, classarray[GetRandomInt(0, 8)]); + //PrintToServer("Changed %N team to %i with maxclients %i and i= %i", ev_client, GetClientTeam(client), MaxClients, i); + } + + if (GetClientCount(true) == 1 && i == 1) + { + ChangeClientTeam(ev_client, GetRandomInt(2, 3)); + TF2_SetPlayerClass(ev_client, classarray[GetRandomInt(0, 8)]); + } + } + i = i + 1; + } +} \ No newline at end of file diff --git a/crithit_system.sp b/crithit_system.sp new file mode 100644 index 0000000..fb7da7e --- /dev/null +++ b/crithit_system.sp @@ -0,0 +1,134 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include + +new Handle:crit_e, Handle:crit_ao, Handle:crit_cc, Handle:crit_m; +new bool:crit_e_bool, bool:crit_ao_bool, Float:crit_cc_float, crit_m_int; + +public Plugin:myinfo = +{ + name = "CritHit System", + author = "Chefe", + description = "Allows to modify the Crit-Calculation.", + version = "1.1", + url = "www.sourcemod.net" +} + +public OnPluginStart() +{ + crit_e = CreateConVar("sm_crit_enabled", "1", "Enable or Disable the Plugin."); + HookConVarChange(crit_e, OnCritEnabledChange); + crit_ao = CreateConVar("sm_crit_only_admins", "1", "Enable or Disable only for Admins."); + HookConVarChange(crit_ao, OnCritAOChange); + crit_cc = CreateConVar("sm_crit_chance", "0.50", "Set the Critchance in Mode 1.", _, true, 0.0, true, 1.0); + HookConVarChange(crit_cc, OnCritCCChange); + crit_m = CreateConVar("sm_crit_mode", "2", "Set the crit Mode ( 1 = chance set in sm_crit_chance | 2 = crit only | 3 = Aim mode)"); + HookConVarChange(crit_m, OnCritMChange); + CreateConVar("sm_crit_version", "1.1", "Version of the Critplugin", FCVAR_NOTIFY); + + crit_e_bool = GetConVarBool(crit_e) + crit_ao_bool = GetConVarBool(crit_ao) + crit_cc_float = GetConVarFloat(crit_cc) + crit_m_int = GetConVarInt(crit_m) + + AutoExecConfig(true); +} + +public OnCritEnabledChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + crit_e_bool = !!StringToInt(newVal); +} + +public OnCritAOChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + crit_ao_bool = !!StringToInt(newVal); +} + +public OnCritCCChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + crit_cc_float = StringToFloat(newVal); +} + +public OnCritMChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + crit_m_int = StringToInt(newVal); +} + + +public Action:TF2_CalcIsAttackCritical(client, weapon, String:weaponname[], &bool:result) +{ + new AdminId:admin_id = GetUserAdmin(client); + new client_aim = GetClientAimTarget(client, true); + + if (crit_e_bool) + { + if (crit_m_int == 1) + { + if (!crit_ao_bool && IsClientInGame(client)) + { + if (crit_cc_float > GetRandomFloat(0.0, 1.0)) + { + result = true; + return Plugin_Handled; + } + } + else if (crit_ao_bool && IsClientInGame(client) && admin_id != INVALID_ADMIN_ID) + { + if (crit_cc_float > GetRandomFloat(0.0, 1.0)) + { + result = true; + return Plugin_Handled; + } + } + } + else if (crit_m_int == 2) + { + if (!crit_ao_bool && IsClientInGame(client)) + { + result = true; + return Plugin_Handled; + } + else if (crit_ao_bool && IsClientInGame(client) && admin_id != INVALID_ADMIN_ID) + { + result = true; + return Plugin_Handled; + } + } + else if (crit_m_int == 3) + { + if (crit_ao_bool && admin_id != INVALID_ADMIN_ID && IsClientInGame(client)) + { + if (client_aim != -1) + { + result = true; + return Plugin_Handled; + } + else if (client_aim == -1) + { + result = false; + return Plugin_Handled; + } + } + else if (!crit_ao_bool && IsClientInGame(client)) + { + if (client_aim != -1) + { + result = true; + return Plugin_Handled; + } + else if (client_aim == -1) + { + result = false; + return Plugin_Handled; + } + } + } + } + else + { + return Plugin_Continue; + } + + return Plugin_Continue; +} diff --git a/ctf_bball2_arena.sp b/ctf_bball2_arena.sp new file mode 100644 index 0000000..30e6e77 --- /dev/null +++ b/ctf_bball2_arena.sp @@ -0,0 +1,167 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include +#include + +new teamnum[MAXPLAYERS+1], arenanum[MAXPLAYERS+1], anzplayinteam[4][4], Float:newdest[MAXPLAYERS+1][3]; +new Float:arena_z = 68.0; +new String:path[PLATFORM_MAX_PATH]; + +public Plugin:myinfo = +{ + name = "CTF_BBALL2_ARENA", + author = "Chefe", + description = "", + version = "1.0", + url = "<<< www.the-bos.de >>>" +} + +public OnPluginStart() +{ + HookEvent("player_team", Event_PlayerTeam, EventHookMode_Pre); + HookEvent("player_death", Event_PlayerDeath); + RegConsoleCmd("sm_join", Command_Join, "Join an Arena"); + + BuildPath(Path_SM, path, sizeof(path), "configs/dest.txt"); +} + +public Action:Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) +{ + new userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(userid); + SetEventBool(event, "silent", true); + + if (GetEventInt(event, "team") != teamnum[client]) + { + CreateTimer(0.1, ChangeTeam, client); + } + + return Plugin_Changed; +} + +public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(userid); + + PerformPlayerSpawn(arenanum[client], teamnum[client], client, 2.0); +} + +public Action:ChangeTeam(Handle:timer, any:client) +{ + new team = 1; + if (teamnum[client] != 0) + { + team = teamnum[client] + } + ChangeClientTeam(client, team); + PrintToChat(client, "[BBA] Select Arena with !join"); +} + +public Action:Command_Join(client, args) +{ + new Handle:menu = CreateMenu(MenuHandler1); + SetMenuTitle(menu, "Join Arena"); + AddMenuItem(menu, "1", "Arena 1"); + AddMenuItem(menu, "2", "Arena 2"); + AddMenuItem(menu, "3", "Arena 3"); + AddMenuItem(menu, "4", "Arena 4"); + DisplayMenu(menu, client, MENU_TIME_FOREVER); + return Plugin_Handled; +} + +public MenuHandler1(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + /* Get item info */ + GetMenuItem(menu, param2, info, sizeof(info)); + + switch (StringToInt(info)) + { + case 1: + { + PerformArenaJoin(0, param1); + } + case 2: + { + PerformArenaJoin(1, param1); + } + case 3: + { + PerformArenaJoin(2, param1); + } + case 4: + { + PerformArenaJoin(3, param1); + } + } + } +} + +public Action:RespawnClient(Handle:timer, any:client) +{ + TF2_RespawnPlayer(client); +} + +public Action:TeleportClient(Handle:timer, any:client) +{ + TeleportEntity(client, newdest[client], NULL_VECTOR, NULL_VECTOR); +} + +FindPerfektTeam(arena) +{ + new anzblu = anzplayinteam[arena][3] + new anzred = anzplayinteam[arena][2] + + if (anzblu > anzred) + { + return 2; + } else if (anzblu < anzred) { + return 3; + } else if (anzred == anzblu) { + return GetRandomInt(2, 3); + } + return 1; +} + +PerformArenaJoin(arena, client) +{ + ForcePlayerSuicide(client); + new newteam = FindPerfektTeam(0); + + teamnum[client] = newteam; + arenanum[client] = arena; + ChangeClientTeam(client, newteam); + anzplayinteam[arena][newteam] = anzplayinteam[arena][newteam] + 1; + TF2_SetPlayerClass(client, TFClass_Soldier, false, true); + + PerformPlayerSpawn(arena, newteam, client, 0.0); +} + +PerformPlayerSpawn(arena, team, client, Float:spawntime) +{ + new Handle:kv = CreateKeyValues("ArenaDest"); + FileToKeyValues(kv, path) + KvJumpToKey(kv, "y", false); + + new String:strteam[5], String:strarena[5]; + IntToString(team, strteam, sizeof(strteam)); + IntToString(arena, strarena, sizeof(strarena)); + newdest[client][1] = KvGetFloat(kv, strteam, 0.0); + KvGoBack(kv); + KvJumpToKey(kv, "x"); + KvJumpToKey(kv, strarena); + newdest[client][0] = GetRandomFloat(KvGetFloat(kv, "min"), KvGetFloat(kv, "max")); + newdest[client][2] = arena_z; + + CloseHandle(kv); + + CreateTimer(FloatAdd(spawntime, 0.2), RespawnClient, client); + CreateTimer(FloatAdd(spawntime, 0.3), TeleportClient, client); +} + \ No newline at end of file diff --git a/edit_flags.sp b/edit_flags.sp new file mode 100644 index 0000000..1e968cd --- /dev/null +++ b/edit_flags.sp @@ -0,0 +1,142 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +public Plugin:myinfo = +{ + name = "Unset Cheats", + author = "Chefe", + description = "<- Description ->", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_unsetcheat", Command_UnSetCheat, ADMFLAG_KICK, "Unset a Cheatflag from an ConVar."); + RegAdminCmd("sm_setcheat", Command_SetCheat, ADMFLAG_KICK, "Set a Cheatflag from an ConVar."); + RegAdminCmd("sm_unsetcheatcmd", Command_UnSetCheatCmd, ADMFLAG_KICK, "Unset a Cheatflag from an ConVar."); + RegAdminCmd("sm_setcheatcmd", Command_SetCheat, ADMFLAG_KICK, "Set a Cheatflag from an ConVar."); + RegAdminCmd("sm_fakecmd", Command_FakeClientCmd, ADMFLAG_CHEATS, "Fake a CMD of an given Client.") +} + +public Action:Command_FakeClientCmd(client_at, args) +{ + if (args < 1) + { + ReplyToCommand(client_at, "Usage: sm_fakecmd "); + return Plugin_Handled; + } + + new String:cmd[256], String:arg1[256]; + + GetCmdArg(1, arg1, sizeof(arg1)); + GetCmdArg(2, cmd, sizeof(cmd)); + + new userid = StringToInt(arg1); + new client = GetClientOfUserId(userid); + + if (IsClientInGame(client)) + { + FakeClientCommand(client, cmd); + } + return Plugin_Handled; +} + +public Action:Command_UnSetCheat(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_unsetcheat "); + return Plugin_Handled; + } + + new String:convar[256]; + GetCmdArg(1, convar, sizeof(convar)); + new Handle:convar_handle = FindConVar(convar); + + if (convar_handle != INVALID_HANDLE) + { + UnsetCheatVar(convar_handle); + } + else + { + ReplyToCommand(client, "[SM] Unable to find ConVar %s", convar) + } + + return Plugin_Handled; +} + +public Action:Command_UnSetCheatCmd(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_unsetcheatcmd "); + return Plugin_Handled; + } + + new String:cmd[256]; + GetCmdArg(1, cmd, sizeof(cmd)); + + new flags = GetCommandFlags(cmd); + flags &= ~FCVAR_CHEAT; + SetCommandFlags(cmd, flags); + + return Plugin_Handled; +} + +public Action:Command_SetCheat(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_setcheat "); + return Plugin_Handled; + } + + new String:convar[256]; + GetCmdArg(1, convar, sizeof(convar)); + new Handle:convar_handle = FindConVar(convar); + + if (convar_handle != INVALID_HANDLE) + { + SetCheatVar(convar_handle); + } + else + { + ReplyToCommand(client, "[SM] Unable to find ConVar %s", convar) + } + + return Plugin_Handled; +} + +public Action:Command_SetCheatCmd(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_setcheatcmd "); + return Plugin_Handled; + } + + new String:cmd[256]; + GetCmdArg(1, cmd, sizeof(cmd)); + + new flags = GetCommandFlags(cmd); + flags |= FCVAR_CHEAT; + SetCommandFlags(cmd, flags); + + return Plugin_Handled; +} + +UnsetCheatVar(Handle:hndl) +{ + new flags = GetConVarFlags(hndl); + flags &= ~FCVAR_CHEAT; + SetConVarFlags(hndl, flags); +} + +SetCheatVar(Handle:hndl) +{ + new flags = GetConVarFlags(hndl); + flags |= FCVAR_CHEAT; + SetConVarFlags(hndl, flags); +} \ No newline at end of file diff --git a/fakeclient.sp b/fakeclient.sp new file mode 100644 index 0000000..764829f --- /dev/null +++ b/fakeclient.sp @@ -0,0 +1,38 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +public Plugin:myinfo = +{ + name = "Fakeclients", + author = "Chefe", + description = "", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_fakeclient", + Command_Fakeclient, + ADMFLAG_KICK, + "Add a Fakeclient.") +} + + +public Action:Command_Fakeclient(client_at, args) +{ + if (args < 1) + { + PrintToConsole(client_at, "Usage: sm_fakeclient "); + return Plugin_Handled; + } + + new String:name[256] + + GetCmdArg(1, name, sizeof(name)); + + CreateFakeClient(name); + + return Plugin_Handled; +} \ No newline at end of file diff --git a/forceclass.sp b/forceclass.sp new file mode 100644 index 0000000..cd414b8 --- /dev/null +++ b/forceclass.sp @@ -0,0 +1,209 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include +#include +#include +#include + +#undef REQUIRE_PLUGIN +#include + +/* Keep track of the top menu */ +new Handle:hAdminMenu = INVALID_HANDLE +new Handle:hPlayerSelectMenu = INVALID_HANDLE; +new Handle:hClassSelectMenu = INVALID_HANDLE; +new String:targetSelected[32] = ""; + +public Plugin:myinfo = +{ + name = "ClassForcer", + author = "Chefe", + description = "wayne", + version = "1.2", + url = "" +} + +public OnPluginStart() +{ + /* See if the menu pluginis already ready */ + new Handle:topmenu; + if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + /* If so, manually fire the callback */ + OnAdminMenuReady(topmenu); + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, "adminmenu")) + { + hAdminMenu = INVALID_HANDLE; + } +} + +public OnAdminMenuReady(Handle:topmenu) +{ + /* Block us from being called twice */ + if (topmenu == hAdminMenu) + { + return; + } + + hAdminMenu = topmenu; + /* If the category is third party, it will have its own unique name. */ + new TopMenuObject:player_commands = FindTopMenuCategory(hAdminMenu, ADMINMENU_PLAYERCOMMANDS); + + if (player_commands == INVALID_TOPMENUOBJECT) + { + /* Error! */ + return; + } + + AddToTopMenu(hAdminMenu, "sm_forceclass", TopMenuObject_Item, AdminMenu_ForceClass, player_commands, "sm_forceclass", ADMFLAG_SLAY); +} + +public AdminMenu_ForceClass(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Force Class"); + } + else if (action == TopMenuAction_SelectOption) + { + hPlayerSelectMenu = CreateMenu(Menu_PlayerSelect); + SetMenuTitle(hPlayerSelectMenu, "Select Target"); + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + new TFClassType:class = TF2_GetPlayerClass(i); + + new String:infostr[200]; + Format(infostr, sizeof(infostr), "%N (%s)", i, class); + + new String:indexstr[32]; + IntToString(i, indexstr, sizeof(indexstr)); + AddMenuItem(hPlayerSelectMenu,indexstr, infostr) + } + AddMenuItem(hPlayerSelectMenu, "red", "Red Team"); + AddMenuItem(hPlayerSelectMenu, "blue", "Team Blu"); + AddMenuItem(hPlayerSelectMenu, "all", "All Player"); + SetMenuExitButton(hPlayerSelectMenu, true); + DisplayMenu(hPlayerSelectMenu, param, MENU_TIME_FOREVER); + } +} + +public Menu_PlayerSelect(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + targetSelected = info; + + hClassSelectMenu = CreateMenu(Menu_ClassSelect); + SetMenuTitle(hClassSelectMenu, "Select Class"); + AddMenuItem(hClassSelectMenu, "scout", "Scout"); + AddMenuItem(hClassSelectMenu, "soldier", "Soldier"); + AddMenuItem(hClassSelectMenu, "pyro", "Pyro"); + AddMenuItem(hClassSelectMenu, "demoman", "Demoman"); + AddMenuItem(hClassSelectMenu, "heavy", "Heavy"); + AddMenuItem(hClassSelectMenu, "engineer", "Engineer"); + AddMenuItem(hClassSelectMenu, "medic", "Medic"); + AddMenuItem(hClassSelectMenu, "sniper", "Sniper"); + AddMenuItem(hClassSelectMenu, "spy", "Spy"); + SetMenuExitButton(hClassSelectMenu, true); + DisplayMenu(hClassSelectMenu, param1, MENU_TIME_FOREVER); + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + + +public Menu_ClassSelect(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:class[32]; + GetMenuItem(menu, param2, class, sizeof(class)); + + if (strcmp(targetSelected, "red", false) != 0 && strcmp(targetSelected, "blue", false) != 0 && strcmp(targetSelected, "all", false) != 0) + { + new client = StringToInt(targetSelected); + + if (IsClientInGame(client)) + { + changePlayerClass(client, class); + } + } + else + { + if (strcmp(targetSelected, "red") == 0 || strcmp(targetSelected, "blue") == 0) + { + new targetteam = FindTeamByName(targetSelected); + + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + if (GetClientTeam(i) == targetteam) + { + changePlayerClass(i, class); + } + } + } + else if (strcmp(targetSelected, "all") == 0) + { + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + changePlayerClass(i, class); + } + } + } + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +changePlayerClass(client, String:class[32]) +{ + new TFClassType:classtf = TF2_GetClass(class); + TF2_SetPlayerClass(client, classtf, false, true); + FakeClientCommand(client, "kill"); + PrintToChat(client, "[OF] You have been forced to class %s", class); +} \ No newline at end of file diff --git a/gospec.sp b/gospec.sp new file mode 100644 index 0000000..fc5b63d --- /dev/null +++ b/gospec.sp @@ -0,0 +1,28 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +public Plugin:myinfo = +{ + name = "L4D2 Spec", + author = "Chefe", + description = "<- Description ->", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegAdminCmd("admin_gospec", Command_GoSpec, ADMFLAG_CHEATS, "go to spec"); + RegAdminCmd("admin_goua", Command_GoUA, ADMFLAG_CHEATS, "go to spec"); +} + +public Action:Command_GoSpec(client, args) +{ + ChangeClientTeam(client, 1); +} + +public Action:Command_GoUA(client, args) +{ + ChangeClientTeam(client, 0); +} \ No newline at end of file diff --git a/health_regenerater.sp b/health_regenerater.sp new file mode 100644 index 0000000..ec1d6fd --- /dev/null +++ b/health_regenerater.sp @@ -0,0 +1,75 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +new Handle:h_enabled; +new bool:enabled, health[MAXPLAYERS+1]; + +public Plugin:myinfo = +{ + name = "Health 4 Ever (GOD MODE)", + author = "Chefe", + description = "Give Health (GODMODE)", + version = "1.3", + url = "www.sourcemod.net" +} + +public OnPluginStart() +{ + HookEvent("player_hurt", Event_PlayerHurt); + HookEvent("player_spawn", Event_PlayerSpawn); + h_enabled = CreateConVar("sm_god_enabled", "1", "Enable or Disable Health for Admins."); + AutoExecConfig(true); + + CreateTimer(1.0, Timer_RefillClip, _, TIMER_REPEAT); + + enabled = GetConVarBool(h_enabled); + + HookConVarChange(h_enabled, OnEnabledChange); +} + +public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +{ + new userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(userid); + + health[client] = GetClientHealth(client); +} + +public OnEnabledChange(Handle:cvar, const String:oldVal[], const String:newVal[]) +{ + enabled = !!StringToInt(String:newVal); +} + +public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client_userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(client_userid); + new AdminId:client_admin = GetUserAdmin(client); + new damage = GetEventInt(event, "health"); + + if (IsClientInGame(client) && enabled && IsPlayerAlive(client) && !IsFakeClient(client)) + { + SetEntData(client, FindDataMapOffs(client, "m_iMaxHealth"), health[client], 4, true); + SetEntData(client, FindDataMapOffs(client, "m_iHealth"), health[client], 4, true); + + PrintToChat(client, "\x01[\x04HR\x01] Blocked \x04%i\x01 damage!", (health[client]-damage)); + } +} + +public Action:Timer_RefillClip(Handle:timer) +{ + for (new i = 1; i != GetMaxClients(); i++) + { + if (IsClientInGame(i) && IsPlayerAlive(i) && !IsFakeClient(i)) + { + RefillClip(i) + } + } +} + +stock RefillClip(i) +{ + new iWeapon = GetEntDataEnt2(i, FindSendPropInfo("CTFPlayer", "m_hActiveWeapon")); + SetEntData(iWeapon, FindSendPropInfo("CBaseCombatWeapon", "m_iClip1"), 500); +} \ No newline at end of file diff --git a/jumpmode.sp b/jumpmode.sp new file mode 100644 index 0000000..21660a0 --- /dev/null +++ b/jumpmode.sp @@ -0,0 +1,646 @@ +#include +#include +#include +#include +#include + +#define PLUGIN_VERSION "1.4.1" + +public Plugin:myinfo = +{ + name = "Jump Mode", + author = "TheJCS", + description = "Utilities to TF2 Jump Maps", + version = PLUGIN_VERSION, + url = "http://kongbr.com.br" +} +static const TFClass_MaxAmmo[TFClassType][3] = +{ + {-1, -1, -1}, {32, 36, -1}, + {25, 75, -1}, {16, 32, -1}, + {16, 24, -1}, {150, -1, -1}, + {200, 32, -1}, {200, 32, -1}, + {24, -1, -1}, {32, 200, 200} +}; + +static const TFClass_MaxClip[TFClassType][2] = +{ + {-1, -1}, {6, 12}, {25, 0}, {4, 6}, {4, 8}, + {40, -1}, {-1, 6}, {-1, 6}, {6, -1}, {6, 12} +}; + +new Handle:g_hPluginEnabled +new Handle:g_hTeleport +new Handle:g_hAutoTeleport +new Handle:g_hAutoRespawn +new Handle:g_hAutoHeal +new Handle:g_hAutoRessuply; +new Handle:g_hRessuply; +new Handle:g_hCriticals; +new Handle:g_hTFCriticals; +new Handle:g_hTFAutoTeamBalance; +new Handle:g_hTFUnbalanceLimit; +new Handle:g_hForceTeam; +new Handle:g_hRemoveCPs; +new Handle:g_hReachedCP; +new Handle:g_hChangeLevel; +new Handle:g_hKeywords; + +new bool:g_bPluginEnabled +new bool:g_bCPTouched[33][8] +new bool:g_bTimerToChange; +new bool:g_bRoundEnd; + +new Float:g_fLocation[33][3]; + +new g_iMaxClients, g_iCPs, g_iCPsTouched[33]; + + +public OnPluginStart() +{ + CreateConVar("jm_version", PLUGIN_VERSION, "Jump Mode plugin Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); + + g_hPluginEnabled = CreateConVar("jm_enabled", "1", "Enable the Jump Mode", FCVAR_PLUGIN, true, 0.0, true, 2.0); + g_hTeleport = CreateConVar("jm_teleport_enabled", "1", "Enable the Jump Mode Teleporter", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hAutoTeleport = CreateConVar("jm_autoteleport", "1", "Enable the Jump Mode Auto Teleporter", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hAutoRespawn = CreateConVar("jm_autorespawn", "1", "Enable the Jump Mode Auto Respawn", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hAutoHeal = CreateConVar("jm_autoheal", "1", "Enable the Jump Mode Auto Healer", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hAutoRessuply = CreateConVar("jm_autoressuply", "1", "Enable the Jump Mode Auto Ressuply", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hRessuply = CreateConVar("jm_ressuply_enabled", "1", "Enable the Jump Mode Ressuply", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hCriticals = CreateConVar("jm_criticals", "0", "Set Jump Mode Criticals", FCVAR_PLUGIN, true, 0.0, true, 2.0); + g_hForceTeam = CreateConVar("jm_forceteam", "0", "Force players to join on a specific team", FCVAR_PLUGIN, true, 0.0, true, 2.0); + g_hRemoveCPs = CreateConVar("jm_removecps", "1", "Remove Control Points from the map", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hReachedCP = CreateConVar("jm_cpmsg", "1", "Shows a message when the player reachs CP", FCVAR_PLUGIN, true, 0.0, true, 1.0); + g_hChangeLevel = CreateConVar("jm_time", "5.0", "Time to change level, starting when a player reach all CPs.", FCVAR_PLUGIN, true, 0.0); + g_hKeywords = CreateConVar("jm_keywords", "jump,rj_,skyscraper", "Keywords to search on the map name to active the plugin, seperated by commas", FCVAR_PLUGIN); + + g_hTFCriticals = FindConVar("tf_weapon_criticals"); + g_hTFAutoTeamBalance = FindConVar("mp_autoteambalance"); + g_hTFUnbalanceLimit = FindConVar("mp_teams_unbalance_limit"); + + // Commands + RegConsoleCmd("jm_saveloc", cmdSaveLoc, "Save your current position"); + RegConsoleCmd("jm_resetloc", cmdResetLoc, "Reset your saved location"); + RegConsoleCmd("jm_teleport", cmdTeleport, "Teleport you to the saved position"); + RegConsoleCmd("jm_ressuply", cmdRessuply, "Ressuply your ammo"); + RegConsoleCmd("jm_help", cmdHelp, "Ressuply your ammo"); + + HookEvent("teamplay_round_stalemate", eventRoundEnd); + HookEvent("teamplay_round_win", eventRoundEnd); + HookEvent("teamplay_round_start", eventRoundStart); + HookEvent("player_changeclass", eventPlayerChangeClass); + HookEvent("player_team", eventChangeTeam); + HookEvent("player_death", eventPlayerDeath); + HookEvent("player_spawn", eventPlayerSpawn); + HookEvent("player_hurt", eventPlayerHurt); + HookEvent("controlpoint_starttouch", eventTouchCP); + + HookConVarChange(g_hPluginEnabled, cvarEnabledChanged); + HookConVarChange(g_hAutoRessuply, cvarRessuplyChanged); + HookConVarChange(g_hAutoHeal, cvarRessuplyChanged); + HookConVarChange(g_hRemoveCPs, cvarRemoveCPsChanged); + HookConVarChange(g_hCriticals, cvarCriticalsChanged); + HookConVarChange(g_hForceTeam, cvarForceTeamChanged); + + g_iMaxClients = GetMaxClients(); +} + +/***************************************************** + * OnFunctions + ****************************************************/ + +public OnConfigsExecuted() +{ + new iEnabled = GetConVarInt(g_hPluginEnabled); + if(iEnabled == 0) + TurnOffPlugin(); + else if(iEnabled == 1) + { + if(IsMapEnabled()) + TurnOnPlugin(); + else + TurnOffPlugin(); + } + else + TurnOnPlugin(); +} + +public OnMapStart() { + PrecacheSound("misc/achievement_earned.wav"); + AddFileToDownloadsTable("sound/misc/achievement_earned.wav"); +} + +public OnClientDisconnect(client) +{ + if(g_bPluginEnabled) + { + ZeroCPs(client); + ZeroLocs(client); + } +} + +public Action:TF2_CalcIsAttackCritical(client, weapon, String:weaponname[], &bool:result) +{ + new criticals = GetConVarInt(g_hCriticals); + if(g_bPluginEnabled && criticals == 2) + { + result = true; + return Plugin_Handled; + } + return Plugin_Continue; +} + +/***************************************************** + * Events + ****************************************************/ + +public Action:eventRoundStart(Handle:event, const String:name[], bool:dontBroadcast) +{ + if(g_bPluginEnabled) + { + if(GetConVarBool(g_hRemoveCPs)) + RemoveCPs(); + if(GetConVarBool(g_hAutoRessuply) && GetConVarBool(g_hAutoHeal)) + ToggleRessuplies(false); + if(GetConVarInt(g_hForceTeam) == 1) + { + SetConVarInt(g_hTFUnbalanceLimit, 30); + SetConVarBool(g_hTFAutoTeamBalance, false); + } + ZeroCPsAll(); + } + g_bRoundEnd = false; +} + +public Action:eventRoundEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + g_bRoundEnd = true; + ZeroLocsAll(); +} + +public Action:eventPlayerChangeClass(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + if(g_bPluginEnabled && IsClientInGame(client) && client != 0) + { + ZeroLocs(client); + PrintToChat(client, "\x04[JM]\x01 Your position has been reset"); + } +} + +public Action:eventChangeTeam(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + if(g_bPluginEnabled && IsClientInGame(client) && client != 0) + { + new iForceTeam = GetConVarInt(g_hForceTeam) + 1; + if(iForceTeam != 1) + { + new iTeam = GetEventInt(event, "team"); + if(iTeam != iForceTeam && iTeam != 1) + CreateTimer(0.1, timerTeam, client); + } + ZeroLocs(client); + PrintToChat(client, "\x04[JM]\x01 Your position has been reset"); + } +} + +public Action:eventTouchCP(Handle:event, const String:name[], bool:dontBroadcast) +{ + if(g_bPluginEnabled) + { + new client = GetEventInt(event, "player"); + new area = GetEventInt(event, "area"); + if(!g_bCPTouched[client][area]) + { + g_iCPsTouched[client]++; + if(GetConVarBool(g_hReachedCP)) + { + new String:playerName[64]; + GetClientName(client, playerName, 64); + AttachParticle(client, "achieved"); + EmitSoundToAll("misc/achievement_earned.wav"); + g_bCPTouched[client][area] = true; + if(g_iCPsTouched[client] == g_iCPs) + PrintToChatAll("\x04[JM]\x01 Player \x03%s \x01has reached the final Control Point!", playerName); + else + PrintToChatAll("\x04[JM]\x01 Player \x03%s \x01has reached a Control Point! (%i of %i)", playerName, g_iCPsTouched[client], g_iCPs); + } + new Float:time = GetConVarFloat(g_hChangeLevel); + if(g_iCPsTouched[client] == g_iCPs && time > 0.0 && !g_bTimerToChange) + { + new String:mapName[64]; + new timeRounded = RoundToCeil(time); + GetNextMap(mapName, 64); + if(timeRounded == 1) + PrintToChatAll("\x04[JM]\x01 The map will be changed to %s in 1 minute!", mapName); + else + PrintToChatAll("\x04[JM]\x01 The map will be changed to %s in %i minute!", mapName, timeRounded); + CreateTimer(time * 60.0, timerChangeLevel); + g_bTimerToChange = true; + } + } + } +} +public Action:eventPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + if(g_bPluginEnabled && GetConVarBool(g_hAutoRespawn)) + { + new client = GetClientOfUserId(GetEventInt(event, "userid")); + CreateTimer(0.1, timerRespawn, client); + } +} +public Action:eventPlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + if(g_bPluginEnabled) + { + if(g_fLocation[client][0] == 0.0) + PrintToChat(client, "\x04[JM]\x01 Jump Mode is enabled! Say \x03!jm_help\x01 to see the available commands"); + else if (GetConVarBool(g_hAutoTeleport) && GetConVarBool(g_hTeleport)) + { + TeleportEntity(client, g_fLocation[client], NULL_VECTOR, NULL_VECTOR); + PrintToChat(client, "\x04[JM]\x01 You have been auto teleported"); + } + } +} +public Action:eventPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + if(g_bPluginEnabled) + { + new client = GetClientOfUserId(GetEventInt(event, "userid")); + if(GetConVarBool(g_hAutoHeal)) + CreateTimer(0.1, timerRegen, client); + if(GetConVarBool(g_hAutoRessuply)) + GiveAmmo(client); + } +} + +/***************************************************** + * Timers + ****************************************************/ + +public Action:timerRegen(Handle:timer, any:client) +{ + new iMaxHealth = TF2_GetPlayerResourceData(client, TFResource_MaxHealth); + SetEntityHealth(client, iMaxHealth); +} + +public Action:timerRespawn(Handle:timer, any:client) +{ + TF2_RespawnPlayer(client); +} + +public Action:timerTeam(Handle:timer, any:client) +{ + new iForceTeam = GetConVarInt(g_hForceTeam) + 1; + ChangeClientTeam(client, iForceTeam); +} + +public Action:timerChangeLevel(Handle:timer) +{ + new String:mapName[64]; + GetNextMap(mapName, 64); + ForceChangeLevel(mapName, "Jump Mode auto changelevel"); +} + +/***************************************************** + * CVar changes + ****************************************************/ + +public cvarEnabledChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + new iEnabled = GetConVarInt(g_hPluginEnabled); + if(iEnabled == 0) + TurnOffPlugin(); + else if(iEnabled == 1) + { + if(IsMapEnabled()) + TurnOnPlugin(); + else + TurnOffPlugin(); + } + else + TurnOnPlugin(); +} + +public cvarRemoveCPsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if(StringToInt(newValue) == 0) + ServerCommand("mp_restartgame 1"); + else + RemoveCPs(); +} + +public cvarCriticalsChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if(StringToInt(newValue) == 0) + SetConVarBool(g_hTFCriticals, false); + else + SetConVarBool(g_hTFCriticals, true); +} + +public cvarForceTeamChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if(StringToInt(newValue) > 0) + { + SetConVarInt(g_hTFUnbalanceLimit, 30); + SetConVarBool(g_hTFAutoTeamBalance, false); + } +} + +public cvarRessuplyChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if(GetConVarBool(g_hAutoRessuply) && GetConVarBool(g_hAutoHeal)) + ToggleRessuplies(false); + else + ToggleRessuplies(true); +} + +/***************************************************** + * Client Commands + ****************************************************/ + +public Action:cmdHelp(client, args) +{ + PrintToChat(client, "\x04[JM]\x01 See console for output"); + if(g_bPluginEnabled) + { + PrintToConsole(client, "[JM] Jump Mode Help"); + PrintToConsole(client, "[JM] - General"); + if(GetConVarBool(g_hAutoHeal)) + PrintToConsole(client, "[JM] - Auto healing on player hurt"); + if(GetConVarBool(g_hAutoRessuply)) + PrintToConsole(client, "[JM] - Auto ammo ressuply on player hurt"); + if(GetConVarInt(g_hCriticals) == 0) + PrintToConsole(client, "[JM] - No criticals"); + else if(GetConVarInt(g_hCriticals) == 2) + PrintToConsole(client, "[JM] - 100% criticals"); + if(GetConVarBool(g_hAutoTeleport) && GetConVarBool(g_hTeleport)) + PrintToConsole(client, "[JM] - Auto teleport on respawn"); + if(GetConVarBool(g_hAutoRespawn)) + PrintToConsole(client, "[JM] - No respawn times"); + if(GetConVarBool(g_hRemoveCPs)) + PrintToConsole(client, "[JM] - Remove Control-Points"); + if(GetConVarBool(g_hReachedCP)) + PrintToConsole(client, "[JM] - Displays a message when a player reach a CP"); + if(GetConVarFloat(g_hChangeLevel) > 0.0) + PrintToConsole(client, "[JM] - Change map when somebody reachs the final CP"); + if(GetConVarBool(g_hAutoRessuply) && GetConVarBool(g_hAutoHeal)) + PrintToConsole(client, "[JM] - Remove Ressuplies"); + PrintToConsole(client, "[JM] - Console Commands (or \"say !\" commands)"); + if(GetConVarBool(g_hTeleport)) + { + PrintToConsole(client, "[JM] - jm_saveloc: Save your current position"); + PrintToConsole(client, "[JM] - jm_resetloc: Reset your saved location"); + PrintToConsole(client, "[JM] - jm_teleport: Teleport you to the saved position"); + } + if(GetConVarBool(g_hRessuply)) + PrintToConsole(client, "[JM] - jm_ressuply: Ressuply your ammo"); + } + else + PrintToChat(client, "[JM] Jump Mode is not enabled"); + +} + +public Action:cmdResetLoc(client, args) +{ + if(!g_bPluginEnabled) + PrintToChat(client, "\x04[JM]\x01 Jump Mode is not enabled"); + else if(!GetConVarBool(g_hTeleport)) + PrintToChat(client, "\x04[JM]\x01 Jump Mode Teleporter is not enabled"); + else + { + ZeroLocs(client); + PrintToChat(client, "\x04[JM]\x01 Your location has been reset"); + } +} + + +public Action:cmdRessuply(client, args) +{ + if(GetConVarBool(g_hRessuply)) + GiveAmmo(client); + else + PrintToChat(client, "\x04[JM]\x01 Ressuply is disabled") +} + +public Action:cmdSaveLoc(client, args) +{ + if(!g_bPluginEnabled) + PrintToChat(client, "\x04[JM]\x01 Jump Mode is not enabled"); + else if(!GetConVarBool(g_hTeleport)) + PrintToChat(client, "\x04[JM]\x01 Jump Mode Teleporter is not enabled"); + else if(!IsPlayerAlive(client)) + PrintToChat(client, "\x04[JM]\x01 You must be alive to save your location"); + else if(!(GetEntityFlags(client) & FL_ONGROUND)) + PrintToChat(client, "\x04[JM]\x01 You can't save your location on air"); + else if(GetEntProp(client, Prop_Send, "m_bDucked") == 1) + PrintToChat(client, "\x04[JM]\x01 You can't save your location ducked"); + else if(g_bRoundEnd) + PrintToChat(client, "\x04[JM]\x01 You can't save your location on humiliation"); + else + { + GetClientAbsOrigin(client, g_fLocation[client]); + PrintToChat(client, "\x04[JM]\x01 Your location has been saved"); + } +} + +public Action:cmdTeleport(client, args) { + if(!g_bPluginEnabled) + PrintToChat(client, "\x04[JM]\x01 Jump Mode is not enabled"); + else if(!GetConVarBool(g_hTeleport)) + PrintToChat(client, "\x04[JM]\x01 Jump Mode Teleporter is not enabled"); + else if(!IsPlayerAlive(client)) + PrintToChat(client, "\x04[JM]\x01 You must be alive to teleport"); + else if(g_fLocation[client][0] == 0.0) + PrintToChat(client, "\x04[JM]\x01 You haven't saved your position yet"); + else if(g_bRoundEnd) + PrintToChat(client, "\x04[JM]\x01 You can't teleport on humiliation"); + else + { + TeleportEntity(client, g_fLocation[client], NULL_VECTOR, NULL_VECTOR); + PrintToChat(client, "\x04[JM]\x01 You have been teleported"); + } +} + +/***************************************************** + * Functions + ****************************************************/ + + bool:IsMapEnabled() +{ + new String:sMapName[32]; + new String:sKeywords[64]; + new String:sKeyword[16][32]; + GetCurrentMap(sMapName, 32); + GetConVarString(g_hKeywords, sKeywords, 64); + new iKeywords = ExplodeString(sKeywords, ",", sKeyword, 16, 32); + for(new i = 0; i < iKeywords; i++) + { + if(StrContains(sMapName, sKeyword[i], false) > -1) + return true; + } + return false; +} + +TurnOnPlugin() +{ + g_bPluginEnabled = true; + g_bRoundEnd = false; + g_bTimerToChange = false; + for(new i = 0; i < g_iMaxClients; i++) + ZeroLocs(i); + if(GetConVarInt(g_hForceTeam) == 1) + { + SetConVarInt(g_hTFUnbalanceLimit, 30); + SetConVarBool(g_hTFAutoTeamBalance, false); + } + if(GetConVarInt(g_hCriticals) == 0) + SetConVarBool(g_hTFCriticals, false); + else + SetConVarBool(g_hTFCriticals, true); + if(GetConVarInt(g_hForceTeam) > 0) + { + SetConVarInt(g_hTFUnbalanceLimit, 30); + SetConVarBool(g_hTFAutoTeamBalance, false); + } + if(GetConVarBool(g_hRemoveCPs)) + RemoveCPs(); + if(GetConVarBool(g_hAutoRessuply) && GetConVarBool(g_hAutoHeal)) + ToggleRessuplies(false); + if(!g_bPluginEnabled) + PrintToChatAll("\x04[JM]\x01 Jump Mode has been turned on"); +} + +TurnOffPlugin() +{ + if(g_bPluginEnabled) + { + g_bPluginEnabled = false; + if(GetConVarBool(g_hRemoveCPs)) + ServerCommand("mp_restartgame 1"); + if(GetConVarBool(g_hAutoRessuply) && GetConVarBool(g_hAutoHeal)) + ToggleRessuplies(true); + PrintToChatAll("\x04[JM]\x01 Jump Mode has been turned off"); + } +} + + +ZeroLocsAll() +{ + for(new i = 0; i <= g_iMaxClients; i++) + ZeroLocs(i); +} + +ZeroLocs(client) +{ + g_fLocation[client][0] = 0.0; + g_fLocation[client][1] = 0.0; + g_fLocation[client][2] = 0.0; +} + +ZeroCPsAll() +{ + for(new i = 0; i <= g_iMaxClients; i++) + ZeroCPs(i); +} + +ZeroCPs(client) +{ + for(new j = 0; j < 8; j++) + g_bCPTouched[client][j] = false; + g_iCPsTouched[client] = 0; +} + +GiveAmmo(client) +{ + new TFClassType:iClass = TF2_GetPlayerClass(client); + for (new i = 0; i < 3; i++) + { + if(!(iClass == TFClass_Heavy && i == 1)) + { + if (TFClass_MaxAmmo[iClass][i] != -1) + SetEntData(client, FindSendPropInfo("CTFPlayer", "m_iAmmo") + ((i+1)*4), TFClass_MaxAmmo[iClass][i]); + if (i != 2 && TFClass_MaxClip[iClass][i] != -1) + SetEntData(GetPlayerWeaponSlot(client, i), FindSendPropInfo("CTFWeaponBase", "m_iClip1"), TFClass_MaxClip[iClass][i]); + } + } +} + +RemoveCPs() +{ + new iCP = -1; + g_iCPs = 0; + while ((iCP = FindEntityByClassname(iCP, "trigger_capture_area")) != -1) + { + SetVariantString("2 0"); + AcceptEntityInput(iCP, "SetTeamCanCap"); + SetVariantString("3 0"); + AcceptEntityInput(iCP, "SetTeamCanCap"); + g_iCPs++; + } +} + +ToggleRessuplies(bool:newStatus) +{ + new iRs = -1; + while ((iRs = FindEntityByClassname(iRs, "func_regenerate")) != -1) + AcceptEntityInput(iRs, (newStatus ? "Enable" : "Disable")); +} + +AttachParticle(ent, String:particleType[]) +{ + new particle = CreateEntityByName("info_particle_system") + + new String:tName[128] + if (IsValidEdict(particle)) + { + new Float:pos[3] + GetEntPropVector(ent, Prop_Send, "m_vecOrigin", pos) + TeleportEntity(particle, pos, NULL_VECTOR, NULL_VECTOR) + + Format(tName, sizeof(tName), "target%i", ent) + DispatchKeyValue(ent, "targetname", tName) + + DispatchKeyValue(particle, "targetname", "tf2particle") + DispatchKeyValue(particle, "parentname", tName) + DispatchKeyValue(particle, "effect_name", particleType) + DispatchSpawn(particle) + SetVariantString(tName) + AcceptEntityInput(particle, "SetParent", particle, particle, 0) + SetVariantString("head") + AcceptEntityInput(particle, "SetParentAttachment", particle, particle, 0) + ActivateEntity(particle) + AcceptEntityInput(particle, "start") + CreateTimer(5.0, DeleteParticles, particle) + } +} + +public ShowParticle(Float:pos[3], String:particlename[], Float:time) +{ + new particle = CreateEntityByName("info_particle_system") + if (IsValidEdict(particle)) + { + TeleportEntity(particle, pos, NULL_VECTOR, NULL_VECTOR) + DispatchKeyValue(particle, "effect_name", particlename) + ActivateEntity(particle) + AcceptEntityInput(particle, "start") + CreateTimer(time, DeleteParticles, particle) + } +} + + +public Action:DeleteParticles(Handle:timer, any:particle) +{ + if (IsValidEntity(particle)) + { + new String:classname[256] + GetEdictClassname(particle, classname, sizeof(classname)) + if (StrEqual(classname, "info_particle_system", false)) + { + RemoveEdict(particle) + } + } +} + diff --git a/l4d2_dc.sp b/l4d2_dc.sp new file mode 100644 index 0000000..2b83b0a --- /dev/null +++ b/l4d2_dc.sp @@ -0,0 +1,296 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include + +new TopMenuObject:obj_dccommands; +new Handle:hAdminMenu = INVALID_HANDLE +new bool:timersetinprogress; + +public Plugin:myinfo = +{ + name = "[L4D2] Left4Control", + author = "Chefe", + description = "Manipulate the L4D2 AI Director & Game Settings", + version = "1.0", + url = "www.the-bos.de" +} + +public OnPluginStart() +{ + /* See if the menu pluginis already ready */ + new Handle:topmenu; + if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + /* If so, manually fire the callback */ + OnAdminMenuReady(topmenu); + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, "adminmenu")) + { + hAdminMenu = INVALID_HANDLE; + } +} + +public OnAdminMenuReady(Handle:topmenu) +{ + /* Block us from being called twice */ + if (topmenu == hAdminMenu) + { + return; + } + else + { + hAdminMenu = topmenu; + } + + AttachAdminMenu() +} + +AttachAdminMenu() +{ + obj_dccommands = AddToTopMenu(hAdminMenu, "dc_category", TopMenuObject_Category, CategoryHandler, INVALID_TOPMENUOBJECT); + AddToTopMenu(hAdminMenu, "sm_dc_forcepanic", TopMenuObject_Item, AdminMenu_ForcePanicEvent, obj_dccommands, "sm_dc_forcepanic", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_panicforever", TopMenuObject_Item, AdminMenu_PanicForever, obj_dccommands, "sm_dc_panicforever", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_forcetank", TopMenuObject_Item, AdminMenu_ForceTank, obj_dccommands, "sm_dc_forcetank", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_forcewitch", TopMenuObject_Item, AdminMenu_ForceWitch, obj_dccommands, "sm_dc_forcewitch", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_resetall", TopMenuObject_Item, AdminMenu_ResetAll, obj_dccommands, "sm_dc_resetall", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_foreregen", TopMenuObject_Item, AdminMenu_ForeRegen, obj_dccommands, "sm_dc_foreregen", ADMFLAG_CHEATS); + AddToTopMenu(hAdminMenu, "sm_dc_forcemob", TopMenuObject_Item, AdminMenu_SpawnMob, obj_dccommands, "sm_dc_spawnmob", ADMFLAG_CHEATS); +} + +public CategoryHandler(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayTitle) + { + Format(buffer, maxlength, "Left4Control:"); + } + else if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Left4Control"); + } +} + +public AdminMenu_ForcePanicEvent(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Force PanicEvent"); + } + else if (action == TopMenuAction_SelectOption) + { + UnsetCheatCmd("director_force_panic_event"); + ServerCommand("director_force_panic_event"); + + if (!timersetinprogress) + { + new Handle:pack = CreateDataPack(); + CreateDataTimer(2.0, SetCheatCmdDelay, pack); + timersetinprogress = true; + WritePackString(pack, "director_force_panic_event"); + } + PrintToChat(param, "[DC] Forced Panic Event!"); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +public AdminMenu_PanicForever(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + if (!GetConVarBool(FindConVar("director_panic_forever"))) + { + Format(buffer, maxlength, "Start Endless Panic Events"); + } + else if (GetConVarBool(FindConVar("director_panic_forever"))) + { + Format(buffer, maxlength, "End Endless Panic Events"); + } + } + else if (action == TopMenuAction_SelectOption) + { + UnsetCheatVar(FindConVar("director_panic_forever")); + if (!GetConVarBool(FindConVar("director_panic_forever"))) + { + ServerCommand("director_panic_forever 1"); + PrintToChat(param, "[DC] Forced endless Panic Event!"); + } + else if (GetConVarBool(FindConVar("director_panic_forever"))) + { + ServerCommand("director_panic_forever 0"); + PrintToChat(param, "[DC] Unforced endless Panic Event!"); + } + CreateTimer(1.0, SetCheatVarDelay, FindConVar("director_panic_forever")); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +public AdminMenu_ForceTank(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + if (!GetConVarBool(FindConVar("director_force_tank"))) + { + Format(buffer, maxlength, "Force spawn Tank this round"); + } + else if (GetConVarBool(FindConVar("director_force_tank"))) + { + Format(buffer, maxlength, "Dont force spawn Tank this round"); + } + } + else if (action == TopMenuAction_SelectOption) + { + + UnsetCheatVar(FindConVar("director_force_tank")); + if (!GetConVarBool(FindConVar("director_force_tank"))) + { + ServerCommand("director_force_tank 1"); + PrintToChat(param, "[DC] Forced to spawn a tank this round!"); + } + else if (GetConVarBool(FindConVar("director_force_tank"))) + { + ServerCommand("director_force_tank 0"); + PrintToChat(param, "[DC] Unforced to spawn a tank this round!"); + } + CreateTimer(1.0, SetCheatVarDelay, FindConVar("director_force_tank")); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +public AdminMenu_ForceWitch(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + if (!GetConVarBool(FindConVar("director_force_witch"))) + { + Format(buffer, maxlength, "Force spawn witch this round"); + } + else if (GetConVarBool(FindConVar("director_force_witch"))) + { + Format(buffer, maxlength, "Dont force witch Tank this round"); + } + } + else if (action == TopMenuAction_SelectOption) + { + + UnsetCheatVar(FindConVar("director_force_witch")); + if (!GetConVarBool(FindConVar("director_force_witch"))) + { + ServerCommand("director_force_witch 1"); + PrintToChat(param, "[DC] Forced to spawn a witch this round!"); + } + else if (GetConVarBool(FindConVar("director_force_witch"))) + { + ServerCommand("director_force_witch 0"); + PrintToChat(param, "[DC] Unforced to spawn a witch this round!"); + } + CreateTimer(1.0, SetCheatVarDelay, FindConVar("director_force_witch")); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +public AdminMenu_ResetAll(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Reset Settings"); + } + else if (action == TopMenuAction_SelectOption) + { + + } +} + +public AdminMenu_ForeRegen(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + if (!GetConVarBool(FindConVar("sv_regeneration_force_on"))) + { + Format(buffer, maxlength, "Start Regeneration"); + } + else if (GetConVarBool(FindConVar("sv_regeneration_force_on"))) + { + Format(buffer, maxlength, "Stop Regeneration"); + } + } + else if (action == TopMenuAction_SelectOption) + { + UnsetCheatVar(FindConVar("sv_regeneration_force_on")); + if (!GetConVarBool(FindConVar("sv_regeneration_force_on"))) + { + ServerCommand("sv_regeneration_force_on 1"); + PrintToChat(param, "[DC] Forced regeneration ON!"); + } + else if (GetConVarBool(FindConVar("sv_regeneration_force_on"))) + { + ServerCommand("sv_regeneration_force_on 0"); + PrintToChat(param, "[DC] Forced regeneration OFF!"); + } + CreateTimer(1.0, SetCheatVarDelay, FindConVar("sv_regeneration_force_on")); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +public AdminMenu_SpawnMob(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Force Mob"); + } + else if (action == TopMenuAction_SelectOption) + { + UnsetCheatCmd("z_spawn"); + ServerCommand("z_spawn mob"); + PrintToChat(param, "[DC] Spawned Mob!"); + SetCheatCmd("z_spawn"); + RedisplayAdminMenu(hAdminMenu, param); + } +} + +UnsetCheatVar(Handle:hndl) +{ + new flags = GetConVarFlags(hndl) + flags &= ~FCVAR_CHEAT + SetConVarFlags(hndl, flags) +} + +SetCheatVar(Handle:hndl) +{ + new flags = GetConVarFlags(hndl) + flags |= FCVAR_CHEAT + SetConVarFlags(hndl, flags) +} + +public Action:SetCheatVarDelay(Handle:timer, Handle:convar) +{ + SetCheatVar(convar); +} + +UnsetCheatCmd(String:cmd[]) +{ + new flags = GetCommandFlags(cmd) + flags &= ~FCVAR_CHEAT + SetCommandFlags(cmd, flags) +} + +SetCheatCmd(String:cmd[]) +{ + new flags = GetCommandFlags(cmd) + flags |= FCVAR_CHEAT + SetCommandFlags(cmd, flags) +} + +public Action:SetCheatCmdDelay(Handle:timer, Handle:pack) +{ + new String:cmd[265]; + ResetPack(pack); + ReadPackString(pack, cmd, sizeof(cmd)); + CloseHandle(pack); + timersetinprogress = false; + SetCheatCmd(cmd); +} \ No newline at end of file diff --git a/lp/offical/lp.sp b/lp/offical/lp.sp new file mode 100644 index 0000000..1ae30bf --- /dev/null +++ b/lp/offical/lp.sp @@ -0,0 +1,825 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#define LP_VERSION "2.1" + +new sql_id[MAXPLAYERS]; +new Handle:g_NextMap = INVALID_HANDLE; +new Handle:g_ChangeMap = INVALID_HANDLE; +new Handle:g_NominationMap = INVALID_HANDLE; + +new Handle:cv_serverid, Handle:cv_price_snomination, Handle:cv_price_mapvote, Handle:cv_price_nextmap, Handle:cv_price_changelevel; +new Handle:cv_price_rs_1day, Handle:cv_price_rs_7day, Handle:cv_price_rs_14day, Handle:cv_price_rs_30day; +new Handle:cv_quaterplayers, Handle:cv_halfplayers, Handle:cv_morethenhalf; +new Handle:cv_snomination, Handle:cv_mapvote, Handle:cv_nextmap, Handle:cv_changelevel; +new Handle:cv_rsflags, Handle:cv_immu; +//new Handle:cv_removeall; + +new price_snomination, price_mapvote, price_nextmap, price_changelevel; +new price_rs_1day, price_rs_7day, price_rs_14day, price_rs_30day; +new quaterplayers, halfplayers, morethenhalf; + +new bool:en_snomination = true; +new bool:en_mapvote = true; +new bool:en_nextmap = true; +new bool:en_changelevel = true; + +new String:rsflags[50]; +//new bool:removeflags; +new rsimmunity; + +new String:MapchangeTo[100]; +new serverid; +new Handle:dbcon = INVALID_HANDLE; + +public Plugin:myinfo = +{ + name = "Loyalty System", + author = "Chefe", + description = "System that gives players points for their playtime.", + version = LP_VERSION, + url = "http://forums.alliedmods.net/showthread.php?t=154296" +} + +public OnPluginStart() +{ + CreateTimer(300.0, ForgivePoints, _, TIMER_REPEAT); + CreateTimer(86400.0, CleanDatabase, _, TIMER_REPEAT); + + RegConsoleCmd("sm_lp", CommandLP, "Shows you your loyalty points!"); + RegAdminCmd("sm_lp_refresh", CommandRefresh, ADMFLAG_CONFIG, "Refresh lp-settings"); + CreateConVar("sm_lp_version", LP_VERSION, "Shows current plugin version.", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); + cv_serverid = CreateConVar("sm_lp_serverid", "0", "Unique serverid if you run the plugin on multipe servers. If not, ignore this."); + + cv_price_snomination = CreateConVar("sm_lp_price_snomination", "25", "Set the price clients must pay for a super-nomination."); + cv_price_mapvote = CreateConVar("sm_lp_price_mapvote", "100", "Set the price clients must pay for forcing a mapvote."); + cv_price_nextmap = CreateConVar("sm_lp_price_nextmap", "150", "Set the price clients must pay for setting the nextmap."); + cv_price_changelevel = CreateConVar("sm_lp_price_changelevel", "200", "Set the price clients must pay to change the map."); + + cv_price_rs_1day = CreateConVar("sm_lp_rs_price_1day", "100", "Set the price clients have to pay for 1 day reserved slot access."); + cv_price_rs_7day = CreateConVar("sm_lp_rs_price_7day", "450", "Set the price clients have to pay for 7 day reserved slot access."); + cv_price_rs_14day = CreateConVar("sm_lp_rs_price_14day", "900", "Set the price clients have to pay for 14 day reserved slot access."); + cv_price_rs_30day = CreateConVar("sm_lp_rs_price_30day", "1500", "Set the price clients have to pay for 30 day reserved slot access."); + + cv_quaterplayers = CreateConVar("sm_lp_quaterplayers", "3", "Set points if playercount <= quater of maxclients."); + cv_halfplayers = CreateConVar("sm_lp_halfplayers", "2", "Set points if playercount between quater and half of maxclients."); + cv_morethenhalf = CreateConVar("sm_lp_morethenhalf", "1", "Set points if playercount more then half of maxclients."); + + cv_snomination = CreateConVar("sm_lp_snomination", "1", "Enable/disable snomination option in lp menu."); + cv_mapvote = CreateConVar("sm_lp_mapvote", "1", "Enable/disable mapvote option in lp menu."); + cv_nextmap = CreateConVar("sm_lp_nextmap", "1", "Enable/disable nextmap option in lp menu."); + cv_changelevel = CreateConVar("sm_lp_changelevel", "1", "Enable/disable changelevel option in lp menu."); + + cv_rsflags = CreateConVar("sm_lp_flags", "a", "Flags a player get if he buys a reserved slot. Make sure that the flags are correct, they wont get checked!"); + //cv_removeall = CreateConVar("sm_lp_removeallflags", "0", "Enable/disable that only the flags set in sm_lp_flags or all flags get removed when the reserved slot expire."); + cv_immu = CreateConVar("sm_lp_immunity", "5", "Set the immunity the reserved slot player will have"); + + AutoExecConfig(true); + + SQL_TConnect(DBInit, "default"); +} + +public DBInit(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE) + { + LogError("[LP] Database connection failed: %s", error); + SetFailState("Unable to connect to database, look for more infos in the error logs!"); + return; + } + + dbcon = hndl; +} + +public OnConfigsExecuted() +{ + price_snomination = GetConVarInt(cv_price_snomination); + price_mapvote = GetConVarInt(cv_price_mapvote); + price_nextmap = GetConVarInt(cv_price_nextmap); + price_changelevel = GetConVarInt(cv_price_changelevel); + + price_rs_1day = GetConVarInt(cv_price_rs_1day); + price_rs_7day = GetConVarInt(cv_price_rs_7day); + price_rs_14day = GetConVarInt(cv_price_rs_14day); + price_rs_30day = GetConVarInt(cv_price_rs_30day); + + quaterplayers = GetConVarInt(cv_quaterplayers); + halfplayers = GetConVarInt(cv_halfplayers); + morethenhalf = GetConVarInt(cv_morethenhalf); + + serverid = GetConVarInt(cv_serverid); + + en_snomination = GetConVarBool(cv_snomination); + en_mapvote = GetConVarBool(cv_mapvote); + en_nextmap = GetConVarBool(cv_nextmap); + en_changelevel = GetConVarBool(cv_changelevel); + + GetConVarString(cv_rsflags, rsflags, sizeof(rsflags)); + //removeflags = GetConVarBool(cv_removeall); + rsimmunity = GetConVarInt(cv_immu); +} + +public OnMapStart() +{ + MapchangeTo = NULL_STRING; + g_NextMap = BuildMapMenu(Menu_NextMap); + g_ChangeMap = BuildMapMenu(Menu_ChangeMap); + g_NominationMap = BuildMapMenu(Menu_NominateMap); +} + +public OnMapEnd() +{ + if (g_NextMap != INVALID_HANDLE) + { + CloseHandle(g_NextMap); + g_NextMap = INVALID_HANDLE; + } + + if (g_ChangeMap != INVALID_HANDLE) + { + CloseHandle(g_ChangeMap); + g_ChangeMap = INVALID_HANDLE; + } + + if (g_NominationMap != INVALID_HANDLE) + { + CloseHandle(g_NominationMap); + g_NominationMap = INVALID_HANDLE; + } +} + +Handle:BuildMapMenu(MenuHandler:handel) +{ + new Handle:file = OpenFile("mapcycle.txt", "rt"); + if (file == INVALID_HANDLE) + { + return INVALID_HANDLE; + } + + new Handle:menu = CreateMenu(handel); + new String:mapname[255]; + while (!IsEndOfFile(file) && ReadFileLine(file, mapname, sizeof(mapname))) + { + if (mapname[0] == ';' || !IsCharAlpha(mapname[0])) + { + continue; + } + new len = strlen(mapname); + for (new i=0; i 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + if (SQL_GetRowCount(hndl) == 0) + { + new String:auth[100]; + GetClientAuthString(data, auth, sizeof(auth)); + + new String:createsql[250]; + Format(createsql, sizeof(createsql), "INSERT INTO lp(steamid, points, ingameid, ingame) VALUES ('%s',0,%i,1)", auth, serverid); + SQL_TQuery(dbcon, InitDBCheck2, createsql, data); + } + else + { + SQL_FetchRow(hndl); + sql_id[data] = SQL_FetchInt(hndl, 0); + + new String:updatesql[255]; + Format(updatesql, sizeof(updatesql), "UPDATE lp SET ingame = 1, ingameid = %i WHERE id = %i", serverid, sql_id[data]); + SQL_TQuery(dbcon, EmptyResultSet, updatesql); + } + } +} + +public InitDBCheck2(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + new String:auth[100]; + GetClientAuthString(data, auth, sizeof(auth)); + + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE steamid = '%s'", auth); + SQL_TQuery(dbcon, InitDBCheck3, sqlstring, data); + } +} + +public InitDBCheck3(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + SQL_FetchRow(hndl); + sql_id[data] = SQL_FetchInt(hndl, 0); + } +} + +public OnClientDisconnect(client) +{ + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET ingame = 0 WHERE id = %i", sql_id[client]); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + sql_id[client] = -1; +} + +public Action:CommandRefresh(client, args) +{ + RefreshSet(); + ReplyToCommand(client, "[LP] Settings refreshed"); + return Plugin_Handled; +} + +public Action:CommandLP(client, args) +{ + new String:s_menu1[100]; + Format(s_menu1, sizeof(s_menu1), "SNomination (%i lp)", price_snomination); + new String:s_menu2[100]; + Format(s_menu2, sizeof(s_menu2), "Force Mapvote (%i lp)", price_mapvote); + new String:s_menu3[100]; + Format(s_menu3, sizeof(s_menu3), "Set Nextmap (%i lp)", price_nextmap); + new String:s_menu4[100]; + Format(s_menu4, sizeof(s_menu4), "Change Map (%i lp)", price_changelevel); + + new Handle:menu = CreateMenu(MenuHandler); + SetMenuTitle(menu, "Loyalty Point System"); + AddMenuItem(menu, "1", "Show LP"); + if (en_snomination) + { + AddMenuItem(menu, "2", s_menu1); + } + if (en_mapvote) + { + AddMenuItem(menu, "3", s_menu2); + } + if (en_nextmap) + { + AddMenuItem(menu, "4", s_menu3); + } + if (en_changelevel) + { + AddMenuItem(menu, "5", s_menu4); + } + + + if (HaveClientRS(client)) + { + new String:s_menu5[100]; + new client_rsmin = GetRSMIN(client); + if (client_rsmin <= 60) + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i min", GetRSMIN(client)); + } + else if (client_rsmin <= 1440) + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i h", GetRSMIN(client)/60); + } + else + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i d", GetRSMIN(client)/1440); + } + AddMenuItem(menu, "6", s_menu5, ITEMDRAW_DISABLED); + } + else + { + AddMenuItem(menu, "7", "Reserved Slot"); + } + + DisplayMenu(menu, client, MENU_TIME_FOREVER); + + return Plugin_Handled; +} + +public MenuHandler(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + + switch(StringToInt(info)) + { + case 1: + { + new lp = GetLP(param1); + PrintToChat(param1, "\x04[LP]\x01 %N, you have %i LP!", param1, lp); + } + case 2: + { + new lp = GetLP(param1); + + if (lp >= price_snomination) + { + DisplayMenu(g_NominationMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i to nominate!", lp, price_snomination); + } + } + case 3: + { + new lp = GetLP(param1); + + if (lp >= price_mapvote) + { + RemoveLP(param1, price_mapvote); + + PrintToChatAll("\x04[LP]\x01 %N forced Mapvote!", param1) + + InitiateMapChooserVote(MapChange_Instant); + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i to force Mapvote!", lp, price_mapvote); + } + } + case 4: + { + new lp = GetLP(param1); + + if (lp >= price_nextmap) + { + DisplayMenu(g_NextMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i to set Nextmap!", lp, price_nextmap); + } + } + case 5: + { + new lp = GetLP(param1); + + if (lp >= price_changelevel) + { + DisplayMenu(g_ChangeMap, param1, MENU_TIME_FOREVER); + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i to change the Map!", lp, price_changelevel); + } + } + case 7: + { + new String:rs_menu1[100]; + Format(rs_menu1, sizeof(rs_menu1), "1 Day (%i lp)", price_rs_1day); + new String:rs_menu2[100]; + Format(rs_menu2, sizeof(rs_menu2), "7 Days (%i lp)", price_rs_7day); + new String:rs_menu3[100]; + Format(rs_menu3, sizeof(rs_menu3), "14 Days (%i lp)", price_rs_14day); + new String:rs_menu4[100]; + Format(rs_menu4, sizeof(rs_menu4), "30 Days (%i lp)", price_rs_30day); + + new Handle:menu2 = CreateMenu(MenuRS); + SetMenuTitle(menu2, "Select RS-time"); + AddMenuItem(menu2, "1", rs_menu1); + AddMenuItem(menu2, "2", rs_menu2); + AddMenuItem(menu2, "3", rs_menu3); + AddMenuItem(menu2, "4", rs_menu4); + DisplayMenu(menu2, param1, MENU_TIME_FOREVER); + } + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_NextMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_nextmap); + PrintToChatAll("\x04[LP]\x01 %N changed the nextmap to %s!", param1, info); + SetNextMap(info); + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + g_NextMap = BuildMapMenu(Menu_NextMap); + } +} + +public Menu_ChangeMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_changelevel); + PrintToChatAll("\x04[LP]\x01 %N forced mapchange to %s!", param1, info); + + if (!strcmp(MapchangeTo, NULL_STRING, false)) + { + MapchangeTo = info; + CreateTimer(5.0, Timer_Changelevel); + } + else + { + PrintToChat(param1, "\x04[LP]\x01 Mapchange already in progress"); + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + g_ChangeMap = BuildMapMenu(Menu_ChangeMap); + } +} + +public Action:Timer_Changelevel(Handle:timer) +{ + ForceChangeLevel(MapchangeTo, "LP"); +} + +public Menu_NominateMap(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + + GetMenuItem(menu, param2, info, sizeof(info)); + RemoveLP(param1, price_snomination); + PrintToChatAll("\x04[LP]\x01 %N nominated %s!", param1, info); + NominateMap(info, true, 0); + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + g_NominationMap = BuildMapMenu(Menu_NominateMap); + } +} + +public MenuRS(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + + new lp = GetLP(param1) + + switch(StringToInt(info)) + { + case 1: + { + if (lp >= price_rs_1day) + { + RemoveLP(param1, price_rs_1day) + GiveRS(param1, 1440); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 1 Day RS!", lp, price_rs_1day); + } + } + case 2: + { + if (lp >= price_rs_7day) + { + + RemoveLP(param1, price_rs_7day) + GiveRS(param1, 10080); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If server is full, connect via console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 7 Days RS!", lp, price_rs_7day); + } + } + case 3: + { + if (lp >= price_rs_14day) + { + + RemoveLP(param1, price_rs_14day) + GiveRS(param1, 20160); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 14 Days RS!", lp, price_rs_14day); + } + } + case 4: + { + if (lp >= price_rs_30day) + { + + RemoveLP(param1, price_rs_30day) + GiveRS(param1, 43200); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 30 Days RS!", lp, price_rs_30day); + } + } + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Action:ForgivePoints(Handle:timer) +{ + new players = GetClientCount(false); + new players_max = GetMaxClients(); + + if (players <= (players_max / 4)) + { + GiveLP(quaterplayers); + } + else if (players <= (players_max / 2)) + { + GiveLP(halfplayers); + } + else + { + GiveLP(morethenhalf); + } + + RemoveRSMIN(5); + + PrintToChatAll("\x04[LP]\x01 This Server is running the \x04LP\x01 System to reward Players. Type \x04!lp\x01 to get up the LP menu with more options."); +} + +public Action:CleanDatabase(Handle:timer) +{ + RemoveInaktivePlayers(); +} + +GetLP(client) +{ + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT points FROM lp WHERE id = %i", sql_id[client]); + + SQL_LockDatabase(dbcon); + + new Handle:sql = SQL_Query(dbcon, sqlstring); + SQL_FetchRow(sql); + new lp = SQL_FetchInt(sql, 0); + CloseHandle(sql); + + SQL_UnlockDatabase(dbcon); + + return lp; +} + +GiveLP(amount) +{ + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points + %i WHERE ingame = 1 AND ingameid = %i", amount, serverid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); +} + +RemoveLP(client, amount) +{ + if (IsClientInGame(client)) + { + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points - %i WHERE id = %i", amount, sql_id[client]); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + } +} + +GiveRS(client, min) +{ + if (IsClientInGame(client)) + { + // In die lp-Datenbank eintragen (Step 1) + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rs = 1, rsmin = %i, serverid = %i WHERE steamid = '%s'", min, serverid, steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + // In die sm-Admin Datenbank eintragen (Step 2) + new String:sqlstring2[256]; + Format(sqlstring2, sizeof(sqlstring2), "INSERT INTO sm_admins(authtype, identity, flags, name, immunity) VALUES ('steam' ,'%s', '%s', '%N', %i)", steamid, rsflags, client, rsimmunity); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring2); + + ServerCommand("sm_reloadadmins"); + } +} + +bool:HaveClientRS(client) +{ + if (IsClientInGame(client)) + { + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE id = %i AND rs = '1'", sql_id[client]); + SQL_LockDatabase(dbcon); + new Handle:sql = SQL_Query(dbcon, sqlstring); + new rs_bool = SQL_GetRowCount(sql); + CloseHandle(sql); + SQL_UnlockDatabase(dbcon); + + if (rs_bool) + { + return true; + } + else + { + return false; + } + } + + return true; +} + +GetRSMIN(client) +{ + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)); + new String:sqlstring[200]; + Format(sqlstring, sizeof(sqlstring), "SELECT rsmin FROM lp WHERE steamid = '%s'", steamid); + SQL_LockDatabase(dbcon); + new Handle:sql = SQL_Query(dbcon, sqlstring); + SQL_UnlockDatabase(dbcon); + SQL_FetchRow(sql); + new rsmin = SQL_FetchInt(sql, 0); + + CloseHandle(sql); + + return rsmin; +} + +RemoveRSMIN(min) +{ + new String:sqlstring[150]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rsmin = rsmin - %i WHERE rs = 1 AND serverid = %i", min, serverid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + new String:sqlstring2[150]; + Format(sqlstring2, sizeof(sqlstring2), "SELECT steamid FROM lp WHERE rs = 1 AND serverid = %i AND rsmin <= 0", serverid); + + SQL_TQuery(dbcon, RemoveInPl1, sqlstring2); +} + +public RemoveInPl1(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + new number = SQL_GetRowCount(hndl); + + if (number != 0) + { + for (new a = 0; a != number; a++) + { + new String:steamid[256]; + SQL_FetchRow(hndl); + SQL_FetchString(hndl, 0, steamid, sizeof(steamid)); + + // Aus der LP-Datenbank austragen (Step 1) + new String:sqlstr[256]; + Format(sqlstr, sizeof(sqlstr), "UPDATE lp SET rs = 0, rsmin = 0, serverid = 0 WHERE steamid = '%s'", steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr); + + // Aus der SM-Admin Datenbank austragen (Step 2) + new String:sqlstr2[150]; + /* + if (removeflags) + { + Format(sqlstr2, sizeof(sqlstr2), "DELETE FROM sm_admins WHERE identity = '%s'", steamid); + } + else + { + Format(sqlstr3, sizeof(sqlstr3), "UPDATE sm_admins SET flags = replace(flags, '%s' WHERE identity = '%s'", steamid); + } + */ + Format(sqlstr2, sizeof(sqlstr2), "DELETE FROM sm_admins WHERE identity = '%s'", steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr2); + } + ServerCommand("sm_reloadadmins"); + } +} + +RemoveInaktivePlayers() +{ + new String:sqlstr[150]; + Format(sqlstr, sizeof(sqlstr), "DELETE FROM lp WHERE points <= 0 AND ingame = 0 AND rs = 0"); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr); +} + +RefreshSet() +{ + price_snomination = GetConVarInt(cv_price_snomination); + price_mapvote = GetConVarInt(cv_price_mapvote); + price_nextmap = GetConVarInt(cv_price_nextmap); + price_changelevel = GetConVarInt(cv_price_changelevel); + + price_rs_1day = GetConVarInt(cv_price_rs_1day); + price_rs_7day = GetConVarInt(cv_price_rs_7day); + price_rs_14day = GetConVarInt(cv_price_rs_14day); + price_rs_30day = GetConVarInt(cv_price_rs_30day); + + quaterplayers = GetConVarInt(cv_quaterplayers); + halfplayers = GetConVarInt(cv_halfplayers); + morethenhalf = GetConVarInt(cv_morethenhalf); + + serverid = GetConVarInt(cv_serverid); + + en_snomination = GetConVarBool(cv_snomination); + en_mapvote = GetConVarBool(cv_mapvote); + en_nextmap = GetConVarBool(cv_nextmap); + en_changelevel = GetConVarBool(cv_changelevel); + + GetConVarString(cv_rsflags, rsflags, sizeof(rsflags)); + //removeflags = GetConVarBool(cv_removeall); + rsimmunity = GetConVarInt(cv_immu); +} + +public EmptyResultSet(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } +} \ No newline at end of file diff --git a/lp/offical/lp_light.sp b/lp/offical/lp_light.sp new file mode 100644 index 0000000..4226ff6 --- /dev/null +++ b/lp/offical/lp_light.sp @@ -0,0 +1,562 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#define LP_VERSION "2.1" + +new sql_id[MAXPLAYERS]; + +new Handle:cv_serverid; +new Handle:cv_price_rs_1day, Handle:cv_price_rs_7day, Handle:cv_price_rs_14day, Handle:cv_price_rs_30day; +new Handle:cv_quaterplayers, Handle:cv_halfplayers, Handle:cv_morethenhalf; +new Handle:cv_rsflags, Handle:cv_immu; +//new Handle:cv_removeall; +new price_rs_1day, price_rs_7day, price_rs_14day, price_rs_30day; +new quaterplayers, halfplayers, morethenhalf; +new String:rsflags[50]; +//new bool:removeflags; +new rsimmunity; + +new serverid; +new Handle:dbcon = INVALID_HANDLE; + +public Plugin:myinfo = +{ + name = "Loyalty System Light", + author = "Chefe", + description = "System that gives players points for their playtime.", + version = LP_VERSION, + url = "http://forums.alliedmods.net/showthread.php?t=154296" +} + +public OnPluginStart() +{ + CreateTimer(300.0, ForgivePoints, _, TIMER_REPEAT); + CreateTimer(86400.0, CleanDatabase, _, TIMER_REPEAT); + + RegConsoleCmd("sm_lp", CommandLP, "Shows you your loyalty points!"); + RegAdminCmd("sm_lp_refresh", CommandRefresh, ADMFLAG_CONFIG, "Refresh lp-settings"); + CreateConVar("sm_lp_version", LP_VERSION, "Shows current plugin version.", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); + cv_serverid = CreateConVar("sm_lp_serverid", "0", "Unique serverid if you run the plugin on multipe servers. If not, ignore this."); + + cv_price_rs_1day = CreateConVar("sm_lp_rs_price_1day", "100", "Set the price clients must pay for 1 day reserved slot access."); + cv_price_rs_7day = CreateConVar("sm_lp_rs_price_7day", "450", "Set the price clients must pay for 7 day reserved slot access."); + cv_price_rs_14day = CreateConVar("sm_lp_rs_price_14day", "900", "Set the price clients must pay for 14 day reserved slot access."); + cv_price_rs_30day = CreateConVar("sm_lp_rs_price_30day", "1500", "Set the price clients must pay for 30 day reserved slot access."); + + cv_quaterplayers = CreateConVar("sm_lp_quaterplayers", "3", "Set points players get if players <= quater of maxclients."); + cv_halfplayers = CreateConVar("sm_lp_halfplayers", "2", "Set points players get if players between quater and half of maxclients."); + cv_morethenhalf = CreateConVar("sm_lp_morethenhalf", "1", "Set points players get if players more then half of maxclients."); + + cv_rsflags = CreateConVar("sm_lp_flags", "a", "Flags a player get if he buys a reserved slot. Make sure that the flags are correct, they wont get checked!"); + //cv_removeall = CreateConVar("sm_lp_removeallflags", "0", "Enable/disable that only the flags set in sm_lp_flags or all flags get removed when the reserved slot expire."); + cv_immu = CreateConVar("sm_lp_immunity", "5", "Set the immunity the reserved slot player will have"); + + AutoExecConfig(true); + + SQL_TConnect(DBInit, "default"); +} + +public DBInit(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE) + { + LogError("[LP] Database connection failed: %s", error); + SetFailState("Unable to connect to database, look for more infos in the error logs!"); + return; + } + + dbcon = hndl; +} + +public OnConfigsExecuted() +{ + price_rs_1day = GetConVarInt(cv_price_rs_1day); + price_rs_7day = GetConVarInt(cv_price_rs_7day); + price_rs_14day = GetConVarInt(cv_price_rs_14day); + price_rs_30day = GetConVarInt(cv_price_rs_30day); + + quaterplayers = GetConVarInt(cv_quaterplayers); + halfplayers = GetConVarInt(cv_halfplayers); + morethenhalf = GetConVarInt(cv_morethenhalf); + + serverid = GetConVarInt(cv_serverid); + + GetConVarString(cv_rsflags, rsflags, sizeof(rsflags)); + //removeflags = GetConVarBool(cv_removeall); + rsimmunity = GetConVarInt(cv_immu); +} + +public OnClientAuthorized(client, const String:auth[]) +{ + if (strcmp(auth, "BOT", false) != 0) + { + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE steamid = '%s'", auth); + + SQL_TQuery(dbcon, InitDBCheck1, sqlstring, client); + } + else + { + sql_id[client] = -1; + } +} + +public InitDBCheck1(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + if (SQL_GetRowCount(hndl) == 0) + { + new String:auth[100]; + GetClientAuthString(data, auth, sizeof(auth)); + + new String:createsql[250]; + Format(createsql, sizeof(createsql), "INSERT INTO lp(steamid, points, ingameid, ingame) VALUES ('%s',0,%i,1)", auth, serverid); + SQL_TQuery(dbcon, InitDBCheck2, createsql, data); + } + else + { + SQL_FetchRow(hndl); + sql_id[data] = SQL_FetchInt(hndl, 0); + + new String:updatesql[255]; + Format(updatesql, sizeof(updatesql), "UPDATE lp SET ingame = 1, ingameid = %i WHERE id = %i", serverid, sql_id[data]); + SQL_TQuery(dbcon, EmptyResultSet, updatesql); + } + } +} + +public InitDBCheck2(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + new String:auth[100]; + GetClientAuthString(data, auth, sizeof(auth)); + + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE steamid = '%s'", auth); + SQL_TQuery(dbcon, InitDBCheck3, sqlstring, data); + } +} + +public InitDBCheck3(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + if (IsClientConnected(data)) + { + SQL_FetchRow(hndl); + sql_id[data] = SQL_FetchInt(hndl, 0); + } +} + +public OnClientDisconnect(client) +{ + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET ingame = 0 WHERE id = %i", sql_id[client]); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + sql_id[client] = -1; +} + +public Action:CommandRefresh(client, args) +{ + RefreshSet(); + ReplyToCommand(client, "[LP] Settings refreshed"); + return Plugin_Handled; +} + +public Action:CommandLP(client, args) +{ + new Handle:menu = CreateMenu(MenuHandler); + SetMenuTitle(menu, "Loyalty Point System"); + AddMenuItem(menu, "1", "Show LP"); + + if (HaveClientRS(client)) + { + new String:s_menu5[100]; + new client_rsmin = GetRSMIN(client); + if (client_rsmin <= 60) + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i min", GetRSMIN(client)); + } + else if (client_rsmin <= 1440) + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i h", GetRSMIN(client)/60); + } + else + { + Format(s_menu5, sizeof(s_menu5), "Your RS access end in %i d", GetRSMIN(client)/1440); + } + AddMenuItem(menu, "6", s_menu5, ITEMDRAW_DISABLED); + } + else + { + AddMenuItem(menu, "7", "Reserved Slot"); + } + + DisplayMenu(menu, client, MENU_TIME_FOREVER); + + return Plugin_Handled; +} + +public MenuHandler(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + + switch(StringToInt(info)) + { + case 1: + { + new lp = GetLP(param1); + PrintToChat(param1, "\x04[LP]\x01 %N, you have %i LP!", param1, lp); + } + case 7: + { + new String:rs_menu1[100]; + Format(rs_menu1, sizeof(rs_menu1), "1 Day (%i lp)", price_rs_1day); + new String:rs_menu2[100]; + Format(rs_menu2, sizeof(rs_menu2), "7 Days (%i lp)", price_rs_7day); + new String:rs_menu3[100]; + Format(rs_menu3, sizeof(rs_menu3), "14 Days (%i lp)", price_rs_14day); + new String:rs_menu4[100]; + Format(rs_menu4, sizeof(rs_menu4), "30 Days (%i lp)", price_rs_30day); + + new Handle:menu2 = CreateMenu(MenuRS); + SetMenuTitle(menu2, "Select RS-time"); + AddMenuItem(menu2, "1", rs_menu1); + AddMenuItem(menu2, "2", rs_menu2); + AddMenuItem(menu2, "3", rs_menu3); + AddMenuItem(menu2, "4", rs_menu4); + DisplayMenu(menu2, param1, MENU_TIME_FOREVER); + } + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public MenuRS(Handle:menu, MenuAction:action, param1, param2) +{ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + + new lp = GetLP(param1) + + switch(StringToInt(info)) + { + case 1: + { + if (lp >= price_rs_1day) + { + RemoveLP(param1, price_rs_1day) + GiveRS(param1, 1440); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 1 Day RS!", lp, price_rs_1day); + } + } + case 2: + { + if (lp >= price_rs_7day) + { + + RemoveLP(param1, price_rs_7day) + GiveRS(param1, 10080); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If server is full, connect via console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 7 Days RS!", lp, price_rs_7day); + } + } + case 3: + { + if (lp >= price_rs_14day) + { + + RemoveLP(param1, price_rs_14day) + GiveRS(param1, 20160); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 14 Days RS!", lp, price_rs_14day); + } + } + case 4: + { + if (lp >= price_rs_30day) + { + + RemoveLP(param1, price_rs_30day) + GiveRS(param1, 43200); + + if (IsClientInGame(param1)) + { + PrintToChat(param1, "\x04[LP]\x01 You have bought RS! If Server is full, connect by console to use your reserved slot.") + } + } + else + { + PrintToChat(param1, "\x04[LP]\x01 You have %i lp, but you need %i for 30 Days RS!", lp, price_rs_30day); + } + } + } + } + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Action:ForgivePoints(Handle:timer) +{ + new players = GetClientCount(false); + new players_max = GetMaxClients(); + + if (players <= (players_max / 4)) + { + GiveLP(quaterplayers); + } + else if (players <= (players_max / 2)) + { + GiveLP(halfplayers); + } + else + { + GiveLP(morethenhalf); + } + + RemoveRSMIN(5); + + PrintToChatAll("\x04[LP]\x01 This Server is running the \x04LP\x01 System to reward Players. Type \x04!lp\x01 to get up the LP menu with more options."); +} + +public Action:CleanDatabase(Handle:timer) +{ + RemoveInaktivePlayers(); +} + +GetLP(client) +{ + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT points FROM lp WHERE id = %i", sql_id[client]); + + SQL_LockDatabase(dbcon); + + new Handle:sql = SQL_Query(dbcon, sqlstring); + SQL_FetchRow(sql); + new lp = SQL_FetchInt(sql, 0); + CloseHandle(sql); + + SQL_UnlockDatabase(dbcon); + + return lp; +} + +GiveLP(amount) +{ + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points + %i WHERE ingame = 1 AND ingameid = %i", amount, serverid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); +} + +RemoveLP(client, amount) +{ + if (IsClientInGame(client)) + { + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET points = points - %i WHERE id = %i", amount, sql_id[client]); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + } +} + +GiveRS(client, min) +{ + if (IsClientInGame(client)) + { + // In die lp-Datenbank eintragen (Step 1) + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)) + new String:sqlstring[256]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rs = 1, rsmin = %i, serverid = %i WHERE steamid = '%s'", min, serverid, steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + // In die sm-Admin Datenbank eintragen (Step 2) + new String:sqlstring2[256]; + Format(sqlstring2, sizeof(sqlstring2), "INSERT INTO sm_admins(authtype, identity, flags, name, immunity) VALUES ('steam' ,'%s', '%s', '%N', %i)", steamid, rsflags, client, rsimmunity); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring2); + + ServerCommand("sm_reloadadmins"); + } +} + +bool:HaveClientRS(client) +{ + if (IsClientInGame(client)) + { + new String:sqlstring[255]; + Format(sqlstring, sizeof(sqlstring), "SELECT id FROM lp WHERE id = %i AND rs = '1'", sql_id[client]); + SQL_LockDatabase(dbcon); + new Handle:sql = SQL_Query(dbcon, sqlstring); + new rs_bool = SQL_GetRowCount(sql); + CloseHandle(sql); + SQL_UnlockDatabase(dbcon); + + if (rs_bool) + { + return true; + } + else + { + return false; + } + } + + return true; +} + +GetRSMIN(client) +{ + new String:steamid[50]; + GetClientAuthString(client, steamid, sizeof(steamid)); + new String:sqlstring[200]; + Format(sqlstring, sizeof(sqlstring), "SELECT rsmin FROM lp WHERE steamid = '%s'", steamid); + SQL_LockDatabase(dbcon); + new Handle:sql = SQL_Query(dbcon, sqlstring); + SQL_UnlockDatabase(dbcon); + SQL_FetchRow(sql); + new rsmin = SQL_FetchInt(sql, 0); + + CloseHandle(sql); + + return rsmin; +} + +RemoveRSMIN(min) +{ + new String:sqlstring[150]; + Format(sqlstring, sizeof(sqlstring), "UPDATE lp SET rsmin = rsmin - %i WHERE rs = 1 AND serverid = %i", min, serverid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstring); + + new String:sqlstring2[150]; + Format(sqlstring2, sizeof(sqlstring2), "SELECT steamid FROM lp WHERE rs = 1 AND serverid = %i AND rsmin <= 0", serverid); + + SQL_TQuery(dbcon, RemoveInPl1, sqlstring2); +} + +public RemoveInPl1(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } + + new number = SQL_GetRowCount(hndl); + + if (number != 0) + { + for (new a = 0; a != number; a++) + { + new String:steamid[256]; + SQL_FetchRow(hndl); + SQL_FetchString(hndl, 0, steamid, sizeof(steamid)); + + // Aus der LP-Datenbank austragen (Step 1) + new String:sqlstr[256]; + Format(sqlstr, sizeof(sqlstr), "UPDATE lp SET rs = 0, rsmin = 0, serverid = 0 WHERE steamid = '%s'", steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr); + + // Aus der SM-Admin Datenbank austragen (Step 2) + new String:sqlstr2[150]; + /* + if (removeflags) + { + Format(sqlstr2, sizeof(sqlstr2), "DELETE FROM sm_admins WHERE identity = '%s'", steamid); + } + else + { + Format(sqlstr3, sizeof(sqlstr3), "UPDATE sm_admins SET flags = replace(flags, '%s' WHERE identity = '%s'", steamid); + } + */ + Format(sqlstr2, sizeof(sqlstr2), "DELETE FROM sm_admins WHERE identity = '%s'", steamid); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr2); + } + ServerCommand("sm_reloadadmins"); + } +} + +RemoveInaktivePlayers() +{ + new String:sqlstr[150]; + Format(sqlstr, sizeof(sqlstr), "DELETE FROM lp WHERE points <= 0 AND ingame = 0 AND rs = 0"); + SQL_TQuery(dbcon, EmptyResultSet, sqlstr); +} + +RefreshSet() +{ + price_rs_1day = GetConVarInt(cv_price_rs_1day); + price_rs_7day = GetConVarInt(cv_price_rs_7day); + price_rs_14day = GetConVarInt(cv_price_rs_14day); + price_rs_30day = GetConVarInt(cv_price_rs_30day); + + quaterplayers = GetConVarInt(cv_quaterplayers); + halfplayers = GetConVarInt(cv_halfplayers); + morethenhalf = GetConVarInt(cv_morethenhalf); + + serverid = GetConVarInt(cv_serverid); + + GetConVarString(cv_rsflags, rsflags, sizeof(rsflags)); + //removeflags = GetConVarBool(cv_removeall); + rsimmunity = GetConVarInt(cv_immu); +} + +public EmptyResultSet(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE || strlen(error) > 0) + { + LogError("LP Query error: %s", error); + return; + } +} \ No newline at end of file diff --git a/lp/sql/lp_update_v1_0-v1_1.sql b/lp/sql/lp_update_v1_0-v1_1.sql new file mode 100644 index 0000000..4986ed7 --- /dev/null +++ b/lp/sql/lp_update_v1_0-v1_1.sql @@ -0,0 +1,2 @@ +ALTER TABLE `lp` ADD `ingame` BOOL NOT NULL DEFAULT '0' AFTER `rsmin` , +ADD `ingameid` INT NOT NULL DEFAULT '0' AFTER `ingame` ; \ No newline at end of file diff --git a/lp/sql/lp_v1_0.sql b/lp/sql/lp_v1_0.sql new file mode 100644 index 0000000..941b997 --- /dev/null +++ b/lp/sql/lp_v1_0.sql @@ -0,0 +1,19 @@ + +SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; + +DROP TABLE IF EXISTS `lp`; +CREATE TABLE IF NOT EXISTS `lp` ( + `id` int(11) NOT NULL auto_increment, + `steamid` varchar(150) NOT NULL, + `points` int(11) NOT NULL, + `rs` tinyint(1) NOT NULL, + `rsmin` int(11) NOT NULL, + `serverid` int(11) NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=ascii AUTO_INCREMENT=0 ; \ No newline at end of file diff --git a/lp/sql/lp_v1_1.sql b/lp/sql/lp_v1_1.sql new file mode 100644 index 0000000..4362459 --- /dev/null +++ b/lp/sql/lp_v1_1.sql @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS `lp`; +CREATE TABLE `lp` ( + `id` int(11) NOT NULL auto_increment, + `steamid` varchar(150) NOT NULL, + `points` int(11) NOT NULL, + `rs` tinyint(1) NOT NULL, + `rsmin` int(11) NOT NULL, + `ingame` tinyint(1) NOT NULL default '0', + `ingameid` int(11) NOT NULL default '0', + `serverid` int(11) NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=ascii; \ No newline at end of file diff --git a/mapend.sp b/mapend.sp new file mode 100644 index 0000000..c2b40cd --- /dev/null +++ b/mapend.sp @@ -0,0 +1,213 @@ +////////////////////////////////////////////////////////////////// +// Mapend Action By HSFighter / http://www.hsfighter.net" // +////////////////////////////////////////////////////////////////// + +#include +#include +#pragma semicolon 1 +#define PLUGIN_VERSION "4.0" + +////////////////////////////////////////////////////////////////// +// Delcare Variables and Handles +////////////////////////////////////////////////////////////////// + +new Handle:CvarMCenabled; +new Handle:CvarMCdebug; + +new g_MapendTemp = 0; + +////////////////////////////////////////////////////////////////// +// Plugin Info +////////////////////////////////////////////////////////////////// + +public Plugin:myinfo = +{ + name = "Simple Mapend Countdown", + author = "HSFighter", + description = "Mapendaction with countdown", + version = PLUGIN_VERSION, + url = "http://www.hsfighter.net" +} + +////////////////////////////////////////////////////////////////// +// Start Plugin +////////////////////////////////////////////////////////////////// + +public OnPluginStart() +{ + CvarMCenabled = CreateConVar("sm_mapend_countdown_enabled", "1", "Enable/disable mapend action."); + CvarMCdebug = CreateConVar("sm_mapend_countdown_debug", "0", "Debug countdown."); + + AutoExecConfig(true); +} + +////////////////////////////////////////////////////////////////// +// Start Map +////////////////////////////////////////////////////////////////// + +public OnMapStart(){ + + PrecacheSound( "hl1/fvox/beep.wav", true); + PrecacheSound( "oktoberfest/fvox/ten.wav", true); + PrecacheSound( "oktoberfest/fvox/nine.wav", true); + PrecacheSound( "oktoberfest/fvox/eight.wav", true); + PrecacheSound( "oktoberfest/fvox/seven.wav", true); + PrecacheSound( "oktoberfest/fvox/six.wav", true); + PrecacheSound( "oktoberfest/fvox/five.wav", true); + PrecacheSound( "oktoberfest/fvox/four.wav", true); + PrecacheSound( "oktoberfest/fvox/three.wav", true); + PrecacheSound( "oktoberfest/fvox/two.wav", true); + PrecacheSound( "oktoberfest/fvox/one.wav", true); + + + AddFileToDownloadsTable("sound/oktoberfest/fvox/ten.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/nine.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/eight.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/seven.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/six.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/five.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/four.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/three.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/two.wav"); + AddFileToDownloadsTable("sound/oktoberfest/fvox/one.wav"); + + g_MapendTemp = 0; + + CreateTimer(0.5, Checktime, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); + +} + +////////////////////////////////////////////////////////////////// +// Timer +////////////////////////////////////////////////////////////////// + +public Action:Checktime(Handle:timer) +{ + if (GetConVarBool(CvarMCenabled)) { + + new timeleft; + GetMapTimeLeft(timeleft); + timeleft = timeleft + 1; + + if (g_MapendTemp != timeleft) + { + g_MapendTemp = timeleft; + if (GetConVarBool(CvarMCdebug)) PrintToChatAll("Debug: %i Sec. left",timeleft); + + switch (timeleft) + { + case 1200: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 20 Min..."); + } + case 600: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 10 Min..."); + } + case 300: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 5 Min..."); + } + case 60: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 60 Sec..."); + } + case 30: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 30 Sec..."); + } + case 20: + { + EmitSoundToAll("hl1/fvox/beep.wav"); + PrintToChatAll("Endmap in 20 Sec..."); + } + case 10: + { + EmitSoundToAll("oktoberfest/fvox/ten.wav"); + PrintToChatAll("Endmap in 10 Sec..."); + } + case 9: + { + EmitSoundToAll("oktoberfest/fvox/nine.wav"); + PrintToChatAll("Endmap in 9 Sec..."); + } + case 8: + { + EmitSoundToAll("oktoberfest/fvox/eight.wav"); + PrintToChatAll("Endmap in 8 Sec..."); + } + case 7: + { + EmitSoundToAll("oktoberfest/fvox/seven.wav"); + PrintToChatAll("Endmap in 7 Sec..."); + } + case 6: + { + EmitSoundToAll("oktoberfest/fvox/six.wav"); + PrintToChatAll("Endmap in 6 Sec..."); + } + case 5: + { + EmitSoundToAll("oktoberfest/fvox/five.wav"); + PrintToChatAll("Endmap in 5 Sec..."); + } + case 4: + { + EmitSoundToAll("oktoberfest/fvox/four.wav"); + PrintToChatAll("Endmap in 4 Sec..."); + } + case 3: + { + EmitSoundToAll("oktoberfest/fvox/three.wav"); + PrintToChatAll("Endmap in 3 Sec..."); + } + case 2: + { + EmitSoundToAll("oktoberfest/fvox/two.wav"); + PrintToChatAll("Endmap in 2 Sec..."); + } + case 1: + { + EmitSoundToAll("oktoberfest/fvox/one.wav"); + ServerCommand("mp_ignore_round_win_conditions 0"); + ServerCommand("cssdm_enabled 0"); + PrintToChatAll("Endmap in 1 Sec..."); + } + } + + if (timeleft <= 0) + { + new String:nextmap[250]; + GetConVarString(FindConVar("sm_nextmap"), nextmap, sizeof(nextmap)); + ServerCommand("changelevel %s", nextmap); + return Plugin_Continue; + } + } + } + return Plugin_Handled; +} + +////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////// + + +public OnMapEnd() +{ + +} + + +public OnPluginEnd() +{ + +} + +////////////////////////////////////////////////////////////////// +// End Plugin +////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/maprate.sp b/maprate.sp new file mode 100644 index 0000000..5364a13 --- /dev/null +++ b/maprate.sp @@ -0,0 +1,858 @@ +#pragma semicolon 1 + +#include + +#undef REQUIRE_PLUGIN +#include +#define REQUIRE_PLUGIN + +#define MR_VERSION "1.2" + +#define MAXLEN_MAP 32 + +#define CVAR_DB_CONFIG 0 +#define CVAR_VERSION 1 +#define CVAR_AUTORATE_TIME 2 +#define CVAR_ALLOW_REVOTE 3 +#define CVAR_TABLE 4 +#define CVAR_AUTORATE_DELAY 5 +#define CVAR_DISMISS 6 +#define CVAR_RESULTS 7 +#define CVAR_NUM_CVARS 8 + +#define FLAG_RESET_RATINGS ADMFLAG_VOTE + +new String:g_current_map[64]; +new Handle:db = INVALID_HANDLE; +new Handle:g_cvars[CVAR_NUM_CVARS]; +new bool:g_SQLite = false; +new Handle:g_admin_menu = INVALID_HANDLE; +new String:g_table_name[32]; +new g_lastRateTime[MAXPLAYERS+1]; +new bool:g_dismiss = false; + +enum MapRatingOrigin +{ + MRO_PlayerInitiated, + MRO_ViewRatingsByRating, + MRO_ViewRatingsByMap +}; +new MapRatingOrigin:g_maprating_origins[MAXPLAYERS+1]; + +public Plugin:myinfo = +{ + name = "Map Rate", + author = "Ryan \"FLOOR_MASTER\" Mannion & Chefe", + description = "Allow players to rate the current map and view the map's average rating.", + version = MR_VERSION, + url = "http://forums.alliedmods.net/showthread.php?p=1530651" +} + +public OnPluginStart() +{ + LoadTranslations("maprate.phrases"); + + RegConsoleCmd("sm_maprate", Command_Rate); + RegConsoleCmd("sm_maprating", Command_Rating); + /* RegConsoleCmd("sm_mapratings", Command_Ratings); */ + RegAdminCmd("sm_maprate_resetratings", Command_ResetRatings, FLAG_RESET_RATINGS); + + g_cvars[CVAR_DB_CONFIG] = CreateConVar("sm_maprate_db_config", "default", "Database configuration to use for Map Rate plugin", FCVAR_PLUGIN); + g_cvars[CVAR_VERSION] = CreateConVar("sm_maprate_version", MR_VERSION, "Map Rate Version", FCVAR_PLUGIN|FCVAR_REPLICATED|FCVAR_NOTIFY); + g_cvars[CVAR_AUTORATE_TIME] = CreateConVar("sm_maprate_autorate_time", "0", "If non-zero, automatically asks dead players to rate map after they have played the map for this number of seconds", FCVAR_PLUGIN); + g_cvars[CVAR_ALLOW_REVOTE] = CreateConVar("sm_maprate_allow_revote", "1", "If non-zero, allow a user to override his/her previous vote on a map", FCVAR_PLUGIN); + g_cvars[CVAR_TABLE] = CreateConVar("sm_maprate_table", "map_ratings", "The name of the database table to use", FCVAR_PLUGIN); + g_cvars[CVAR_AUTORATE_DELAY] = CreateConVar("sm_maprate_autorate_delay", "5", "After a player dies, wait this number of seconds before asking to rate if maprate_autorate_tie is non-zero", FCVAR_PLUGIN); + g_cvars[CVAR_DISMISS] = CreateConVar("sm_maprate_dismiss", "0", "If non-zero, the first voting option will be \"Dismiss\"", FCVAR_PLUGIN); + g_cvars[CVAR_RESULTS] = CreateConVar("sm_maprate_autoresults", "1", "If non-zero, the results graph will automatically be displayed when a player rates a map", FCVAR_PLUGIN); + + HookEvent("player_death", Event_PlayerDeath); + AutoExecConfig(true, "maprate"); + + g_dismiss = GetConVarBool(g_cvars[CVAR_DISMISS]); + + new Handle:top_menu; + if (LibraryExists("adminmenu") && ((top_menu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + OnAdminMenuReady(top_menu); + } +} + +public OnConfigsExecuted() +{ + GetConVarString(g_cvars[CVAR_TABLE], g_table_name, sizeof(g_table_name)); + g_dismiss = GetConVarBool(g_cvars[CVAR_DISMISS]); + PrintToServer("[MAPRATE] Using table name \"%s\"", g_table_name); + + if (!ConnectDB()) + { + LogError("FATAL: An error occurred while connecting to the database."); + SetFailState("An error occurred while connecting to the database."); + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, "adminmenu")) + { + g_admin_menu = INVALID_HANDLE; + } +} + +public OnAdminMenuReady(Handle:topmenu) +{ + if (topmenu == g_admin_menu) + { + return; + } + + g_admin_menu = topmenu; + + new TopMenuObject:server_commands = FindTopMenuCategory(g_admin_menu, ADMINMENU_SERVERCOMMANDS); + + if (server_commands == INVALID_TOPMENUOBJECT) + { + return; + } + + AddToTopMenu(g_admin_menu, "sm_all_maprate", TopMenuObject_Item, AdminMenu_AllRate, server_commands, "sm_all_maprate", ADMFLAG_VOTE); +} + +public AdminMenu_AllRate(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + switch (action) + { + case TopMenuAction_DisplayOption: + { + Format(buffer, maxlength, "%T", "Everyone Rate Command", param); + } + case TopMenuAction_SelectOption: + { + new max_clients = GetMaxClients(); + for (new i = 1; i <= max_clients; i++) + { + if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > 0) + { + InitiateRate(i, g_current_map, false, param); + } + } + } + } +} + +public OnMapStart() +{ + GetCurrentMap(g_current_map, sizeof(g_current_map)); + + g_dismiss = GetConVarBool(g_cvars[CVAR_DISMISS]); +} + +public OnMapEnd() +{ + if (db != INVALID_HANDLE) + { + CloseHandle(db); + db = INVALID_HANDLE; + } +} + +public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + new autorateTime = GetConVarInt(g_cvars[CVAR_AUTORATE_TIME]); + new death_flags = GetEventInt(event, "death_flags"); + + if (IsClientInGame(client) && !IsFakeClient(client) && autorateTime && g_lastRateTime[client] + autorateTime < GetTime() && !(death_flags & 32)) + { + new Float:time = GetConVarFloat(g_cvars[CVAR_AUTORATE_DELAY]); + if (time >= 0.0) + { + decl String:steamid[24]; + GetClientAuthString(client, steamid, sizeof(steamid)); + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + WritePackString(dp, steamid); + CreateTimer(time, Timer_AutoRateClient, dp); + } + } + + return Plugin_Continue; +} + +public Action:Timer_AutoRateClient(Handle:timer, any:dp) +{ + decl String:steamid_orig[24]; + decl String:steamid[24]; + ResetPack(dp); + new client = ReadPackCell(dp); + ReadPackString(dp, steamid_orig, sizeof(steamid_orig)); + CloseHandle(dp); + + g_lastRateTime[client] = GetTime(); + + if (IsClientConnected(client)) + { + GetClientAuthString(client, steamid, sizeof(steamid)); + + if (!strcmp(steamid, steamid_orig)) + { + InitiateRate(client, g_current_map, false); + } + } +} + +stock bool:ConnectDB() +{ + decl String:db_config[64]; + GetConVarString(g_cvars[CVAR_DB_CONFIG], db_config, sizeof(db_config)); + + /* Verify that the configuration is defined in databases.cfg */ + if (!SQL_CheckConfig(db_config)) + { + LogError("Database configuration \"%s\" does not exist", db_config); + return false; + } + + /* Establish a connection */ + new String:error[256]; + db = SQL_Connect(db_config, true, error, sizeof(error)); + if (db == INVALID_HANDLE) + { + LogError("Error establishing database connection: %s", error); + return false; + } + + decl String:driver[32]; + SQL_ReadDriver(db, driver, sizeof(driver)); + + if (!strcmp(driver, "sqlite")) + { + g_SQLite = true; + } + + decl String:query[256]; + + if (g_SQLite) + { + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS %s (steamid TEXT, map TEXT, rating INTEGER, rated DATE, UNIQUE (map, steamid))", g_table_name); + if (!SQL_FastQuery(db, query)) { + new String:sqlerror[300]; + SQL_GetError(db, sqlerror, sizeof(sqlerror)); + LogError("FATAL: Could not create table %s. (%s)", g_table_name, sqlerror); + SetFailState("Could not create table %s.", g_table_name); + } + } + else + { + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS %s (steamid VARCHAR(24), map VARCHAR(48), rating INT(4), rated DATETIME, UNIQUE KEY (map, steamid))", g_table_name); + if (!SQL_FastQuery(db, query)) + { + new String:sqlerror[300]; + SQL_GetError(db, sqlerror, sizeof(sqlerror)); + LogError("FATAL: Could not create table %s. (%s)", g_table_name, sqlerror); + SetFailState("Could not create table %s.", g_table_name); + } + } + + return true; +} + +public Menu_Rate(Handle:menu, MenuAction:action, param1, param2) +{ + new client = param1; + + switch (action) + { + /* User selected a rating - update database */ + case MenuAction_Select: + { + decl String:steamid[24]; + decl String:map[MAXLEN_MAP]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + if (!GetMenuItem(menu, param2, map, sizeof(map))) + { + return; + } + + if (g_dismiss && param2 == 0) + { + return; + } + + /* param2 is the menu selection index starting from 0 */ + new rating = param2 + 1 - (g_dismiss ? 1 : 0); + + decl String:query[256]; + + if (g_SQLite) + { + Format(query, sizeof(query), "REPLACE INTO %s VALUES ('%s', '%s', %d, DATETIME('NOW'))", g_table_name, steamid, map, rating); + } + else + { + Format(query, sizeof(query), "INSERT INTO %s SET map = '%s', steamid = '%s', rating = %d, rated = NOW() ON DUPLICATE KEY UPDATE rating = %d, rated = NOW()", g_table_name, map, steamid, rating, rating); + } + LogAction(client, -1, "%L rated %s: %d", client, map, rating); + + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + WritePackString(dp, map); + SQL_TQuery(db, T_PostRating, query, dp); + } + case MenuAction_Cancel: + { + } + case MenuAction_End: + { + CloseHandle(menu); + } + } +} + +public Action:Command_Rating(client, args) +{ + if (!client) + { + return Plugin_Handled; + } + + CreateMenuRatings(client); + + return Plugin_Handled; +} + +stock CreateMenuRatings(client) +{ + new Handle:menu = CreateMenu(Menu_Ratings); + decl String:text[64]; + Format(text, sizeof(text), "%T", "View Ratings", client); + SetMenuTitle(menu, text); + AddMenuItem(menu, "none", g_current_map); + Format(text, sizeof(text), "%T", "Ordered by Rating", client); + AddMenuItem(menu, "rating", text); + Format(text, sizeof(text), "%T", "Ordered by Map Name", client); + AddMenuItem(menu, "map", text); + SetMenuExitButton(menu, true); + DisplayMenu(menu, client, 300); +} + +public Menu_Ratings(Handle:menu, MenuAction:action, param1, param2) +{ + new client = param1; + + switch (action) + { + case MenuAction_Select: + { + switch (param2) + { + case 0: + { + g_maprating_origins[client] = MRO_PlayerInitiated; + GetMapRating(client, g_current_map); + } + case 1: + { + ViewRatingsByRating(client); + } + case 2: + { + ViewRatingsByMap(client); + } + } + } + + case MenuAction_Cancel: + { + } + + case MenuAction_End: + { + CloseHandle(menu); + } + } +} + +stock ViewRatingsByRating(client) +{ + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + decl String:text[64]; + Format(text, sizeof(text), "%T", "Ordered by Rating Title", client); + WritePackString(dp, text); + g_maprating_origins[client] = MRO_ViewRatingsByRating; + + decl String:query[256]; + Format(query, sizeof(query), "SELECT map, AVG(rating) AS rating, COUNT(*) AS ratings FROM %s GROUP BY map ORDER BY rating DESC", g_table_name); + SQL_TQuery(db, T_CreateMenuRatingsResults, query, dp); +} + +stock ViewRatingsByMap(client) +{ + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + decl String:text[64]; + Format(text, sizeof(text), "%T", "Ordered by Map Name Title", client); + WritePackString(dp, text); + g_maprating_origins[client] = MRO_ViewRatingsByMap; + + decl String:query[256]; + Format(query, sizeof(query), "SELECT map, AVG(rating) AS rating, COUNT(*) AS ratings FROM %s GROUP BY map ORDER BY map", g_table_name); + SQL_TQuery(db, T_CreateMenuRatingsResults, query, dp); +} + +public T_CreateMenuRatingsResults(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (hndl == INVALID_HANDLE) + { + LogError("Query failed! %s", error); + PrintToChat(data, "A database error occurred. Please try again later."); + return; + } + + ResetPack(data); + new client = ReadPackCell(data); + decl String:menu_title[64]; + ReadPackString(data, menu_title, sizeof(menu_title)); + CloseHandle(data); + + new Handle:menu = CreateMenu(Menu_ViewMapRatings); + + decl String:map[MAXLEN_MAP]; + new Float:rating; + new ratings; + decl String:menu_item[128]; + + while (SQL_FetchRow(hndl)) + { + SQL_FetchString(hndl, 0, map, sizeof(map)); + rating = SQL_FetchFloat(hndl, 1); + ratings = SQL_FetchInt(hndl, 2); + + Format(menu_item, sizeof(menu_item), "%.2f %s (%d)", rating, map, ratings); + AddMenuItem(menu, map, menu_item); + } + CloseHandle(hndl); + + SetMenuTitle(menu, menu_title); + SetMenuExitButton(menu, true); + SetMenuExitBackButton(menu, true); + DisplayMenu(menu, client, 300); +} + +public Menu_ViewMapRatings(Handle:menu, MenuAction:action, param1, param2) +{ + new client = param1; + + switch (action) + { + case MenuAction_Select: + { + decl String:map[MAXLEN_MAP]; + if (GetMenuItem(menu, param2, map, sizeof(map))) + { + GetMapRating(client, map); + } + } + case MenuAction_Cancel: + { + switch (param2) + { + case MenuCancel_ExitBack: + { + CreateMenuRatings(client); + } + } + } + case MenuAction_End: { + CloseHandle(menu); + } + } +} + +public T_CreateMenuRating(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + ResetPack(data); + new client = ReadPackCell(data); + + if (hndl == INVALID_HANDLE) + { + LogError("Query failed! %s", error); + CloseHandle(data); + PrintToChat(client, "A database error occurred. Please try again later."); + return; + } + + decl String:map[MAXLEN_MAP]; + ReadPackString(data, map, sizeof(map)); + new my_rating = ReadPackCell(data); + CloseHandle(data); + + /* This is kind of ugly */ + new rating = 0; + new arr_ratings[5] = {0, 0, 0, 0, 0}; + new ratings = 0; + new total_ratings = 0; + new total_rating = 0; + decl String:menu_item[64]; + + while (SQL_FetchRow(hndl)) + { + rating = SQL_FetchInt(hndl, 0); + ratings = SQL_FetchInt(hndl, 1); + total_rating += rating * ratings; + + arr_ratings[rating - 1] = ratings; + total_ratings += ratings; + } + CloseHandle(hndl); + + /* Now build the menu */ + decl String:menu_title[64]; + new Handle:menu = CreateMenu(Menu_ViewRating); + + new Float:average_rating = 0.0; + if (total_ratings) + { + average_rating = float(total_rating) / float(total_ratings); + } + + Format(menu_title, sizeof(menu_title), "%T\n%T", "Ratings Title", client, map, "Average Rating", client, average_rating); + if (my_rating) + { + Format(menu_title, sizeof(menu_title), "%s\n%T", menu_title, "Your Rating", client, my_rating); + } + SetMenuTitle(menu, menu_title); + + /* VARIABLE WIDTH FONTS ARE EVIL */ + new bars[5]; + new max_bars = 0; + if (total_ratings) + { + for (new i = 0; i < sizeof(arr_ratings); i++) + { + bars[i] = RoundToNearest(float(arr_ratings[i] * 100 / total_ratings) / 5); + max_bars = (bars[i] > max_bars ? bars[i] : max_bars); + } + + if (max_bars >= 15) + { + for (new i = 0; i < sizeof(arr_ratings); i++) + { + bars[i] /= 2; + } + max_bars /= 2; + } + } + decl String:menu_item_bars[64]; + new String:rating_phrase[] = "1 Star"; + for (new i = 0; i < sizeof(arr_ratings); i++) + { + new j; + for (j = 0; j < bars[i]; j++) + { + menu_item_bars[j] = '='; + } + new max = RoundToNearest(float(max_bars - j) * 2.5) + j; + for (; j < max; j++) + { + menu_item_bars[j] = ' '; + } + menu_item_bars[j] = 0; + + rating_phrase[0] = '1' + i; + Format(menu_item, sizeof(menu_item), "%s (%T - %T)", menu_item_bars, rating_phrase, client, (arr_ratings[i] == 1 ? "Rating" : "Rating Plural"), client, arr_ratings[i]); + /* AddMenuItem(menu, map, menu_item, ITEMDRAW_DISABLED); */ + AddMenuItem(menu, map, menu_item); + } + + decl String:text[64]; + if (!my_rating) + { + Format(text, sizeof(text), "%T", "Rate Map", client); + AddMenuItem(menu, map, text); + } + else if (GetConVarInt(g_cvars[CVAR_ALLOW_REVOTE])) + { + Format(text, sizeof(text), "%T", "Change Rating", client); + AddMenuItem(menu, map, text); + } + + SetMenuExitBackButton(menu, true); + SetMenuExitButton(menu, true); + DisplayMenu(menu, client, 300); +} + +public Menu_ViewRating(Handle:menu, MenuAction:action, param1, param2) +{ + new client = param1; + + switch (action) + { + case MenuAction_Select: + { + switch (param2) + { + case 5: + { + decl String:map[MAXLEN_MAP]; + if (GetMenuItem(menu, param2, map, sizeof(map))) + { + InitiateRate(client, map, true); + } + } + } + } + case MenuAction_Cancel: + { + switch (param2) + { + case MenuCancel_ExitBack: + { + switch (g_maprating_origins[client]) + { + case MRO_PlayerInitiated: + { + CreateMenuRatings(client); + } + case MRO_ViewRatingsByRating: + { + ViewRatingsByRating(client); + } + case MRO_ViewRatingsByMap: + { + ViewRatingsByMap(client); + } + } + } + } + } + case MenuAction_End: + { + CloseHandle(menu); + } + } +} + +public Action:Command_Rate(client, args) +{ + if (!client) + { + return Plugin_Handled; + } + + InitiateRate(client, g_current_map, true); + return Plugin_Handled; +} + +stock InitiateRate(client, const String:map[], bool:voluntary, initiator = 0) +{ + decl String:steamid[24]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + WritePackString(dp, map); + WritePackCell(dp, voluntary); + WritePackCell(dp, initiator); + + decl String:query[256]; + Format(query, sizeof(query), "SELECT rating FROM %s WHERE map = '%s' AND steamid = '%s'", g_table_name, map, steamid); + SQL_TQuery(db, T_CreateMenuRate, query, dp); +} + +public T_PostRating(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + ResetPack(data); + new client = ReadPackCell(data); + + if (hndl == INVALID_HANDLE) + { + LogError("Query failed! %s", error); + PrintToChat(client, "%t", "Database Error"); + CloseHandle(data); + return; + } + + decl String:map[MAXLEN_MAP]; + ReadPackString(data, map, sizeof(map)); + CloseHandle(data); + + PrintToChat(client, "\03%t", "Successful Rate", map); + g_maprating_origins[client] = MRO_PlayerInitiated; + + if (GetConVarInt(g_cvars[CVAR_RESULTS])) + { + GetMapRating(client, map); + } +} + +stock GetMapRating(client, const String:map[]) +{ + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + WritePackString(dp, map); + + decl String:steamid[24]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + decl String:query[256]; + Format(query, sizeof(query), "SELECT rating FROM %s WHERE steamid = '%s' AND map = '%s'", g_table_name, steamid, map); + SQL_TQuery(db, T_GetMapRating2, query, dp); +} + +public T_GetMapRating2(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + ResetPack(data); + new client = ReadPackCell(data); + + if (hndl == INVALID_HANDLE) + { + LogError("Query failed! %s", error); + PrintToChat(data, "%t", "Database Error"); + CloseHandle(data); + return; + } + + decl String:map[MAXLEN_MAP]; + ReadPackString(data, map, sizeof(map)); + CloseHandle(data); + + new Handle:dp = CreateDataPack(); + WritePackCell(dp, client); + WritePackString(dp, map); + + if (SQL_GetRowCount(hndl) == 1) + { + SQL_FetchRow(hndl); + WritePackCell(dp, SQL_FetchInt(hndl, 0)); + } + else + { + WritePackCell(dp, 0); + } + CloseHandle(hndl); + + decl String:query[256]; + Format(query, sizeof(query), "SELECT rating, COUNT(*) FROM %s WHERE map = '%s' GROUP BY rating ORDER BY rating DESC", g_table_name, map); + SQL_TQuery(db, T_CreateMenuRating, query, dp); +} + +public T_CreateMenuRate(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + ResetPack(data); + new client = ReadPackCell(data); + + if (hndl == INVALID_HANDLE) + { + LogError("Query failed! %s", error); + if (IsClientConnected(client)) + { + PrintToChat(client, "%t", "Database Error"); + } + CloseHandle(data); + return; + } + + decl String:map[MAXLEN_MAP]; + ReadPackString(data, map, sizeof(map)); + new bool:voluntary = bool:ReadPackCell(data); + new initiator = ReadPackCell(data); + new rating = 0; + + CloseHandle(data); + + new allow_revote = GetConVarInt(g_cvars[CVAR_ALLOW_REVOTE]); + + /* The player has rated this map before */ + if (SQL_GetRowCount(hndl) == 1) + { + SQL_FetchRow(hndl); + rating = SQL_FetchInt(hndl, 0); + + /* If the user didn't initiate the maprate, just ignore the request */ + if (!voluntary) + { + return; + } + + /* Deny rerating if the applicable cvar is set */ + else if (!allow_revote) + { + PrintToChat(client, "\03%t", "Already Rated", rating); + return; + } + } + CloseHandle(hndl); + + decl String:title[256]; + + /* If an initiator was set, then this map rating request was initiated by + * an admin. We'll specify who in the map rate panel title. */ + if (initiator) + { + decl String:initiator_name[32]; + GetClientName(initiator, initiator_name, sizeof(initiator_name)); + Format(title, sizeof(title), "%T", "Everyone Rate Title", + client, initiator_name, g_current_map); + } + else + { + Format(title, sizeof(title), "%T", "Rate Map Title", client, map); + } + + /* If the player already rated this map, show the previous rating. */ + if (rating) + { + Format(title, sizeof(title), "%s\n%T", title, "Previous Rating", client, rating); + } + + /* Build the menu panel */ + new Handle:menu = CreateMenu(Menu_Rate); + SetMenuTitle(menu, title); + + decl String:menu_item[128]; + + if (g_dismiss) + { + Format(menu_item, sizeof(menu_item), "%T", "Dismiss", client); + AddMenuItem(menu, "dismiss", menu_item); + } + + new String:rating_phrase[] = "1 Star"; + for (new i = 0; i < 5; i++) + { + rating_phrase[0] = '1' + i; + Format(menu_item, sizeof(menu_item), "%T", rating_phrase, client); + AddMenuItem(menu, map, menu_item); + } + SetMenuExitButton(menu, true); + DisplayMenu(menu, client, 300); +} + +public Action:Command_ResetRatings(client, args) +{ + ResetRatings(client, g_current_map); + + return Plugin_Handled; +} + +stock ResetRatings(client, const String:map[]) +{ + decl String:query[256]; + + Format(query, sizeof(query), "DELETE FROM %s WHERE map = '%s'", + g_table_name, map); + PrintToServer(query); + SQL_LockDatabase(db); + SQL_FastQuery(db, query); + SQL_UnlockDatabase(db); + + LogAction(client, -1, "%L reset ratings for map %s", client, g_current_map); +} + +public OnClientPostAdminCheck(client) +{ + g_lastRateTime[client] = GetTime(); +} \ No newline at end of file diff --git a/maprate_rld.sp b/maprate_rld.sp new file mode 100644 index 0000000..351dd81 --- /dev/null +++ b/maprate_rld.sp @@ -0,0 +1,67 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#undef REQUIRE_PLUGIN +#include +#define REQUIRE_PLUGIN + +#define MR_VERSION "1.0" + +new Handle:g_hDatabase; +new String:cv_db[32]; +new Handle:g_cvars[]; + +public Plugin:myinfo = +{ + name = "Maprate Reloaded", + author = "Chefe", + description = "Allow players to rate the current map and view the map's average rating.", + version = MR_VERSION, + url = "" +} + +public OnPluginStart() +{ + LoadTranslations("maprate_rld.phrases"); + + RegConsoleCmd("sm_maprate", Command_Maprate); + RegConsoleCmd("sm_maprating", Command_Maprating); + RegAdminCmd("sm_maprate_clear", Command_ResetRatings, FLAG_RESET_RATINGS); + + g_cvars[CVAR_DB_CONFIG] = CreateConVar("sm_maprate_db", "default", "Database configuration to use for Map Rate plugin", FCVAR_PLUGIN); + g_cvars[CVAR_VERSION] = CreateConVar("sm_maprate_version", MR_VERSION, "Map Rate Version", FCVAR_PLUGIN|FCVAR_REPLICATED|FCVAR_NOTIFY); + g_cvars[CVAR_AUTORATE_TIME] = CreateConVar("sm_maprate_autorate_time", "0", "If non-zero, automatically asks dead players to rate map after they have played the map for this number of seconds", FCVAR_PLUGIN); + g_cvars[CVAR_ALLOW_REVOTE] = CreateConVar("sm_maprate_allow_revote", "1", "If non-zero, allow a user to override his/her previous vote on a map", FCVAR_PLUGIN); + g_cvars[CVAR_AUTORATE_DELAY] = CreateConVar("sm_maprate_autorate_delay", "5", "After a player dies, wait this number of seconds before asking to rate if maprate_autorate_time is non-zero", FCVAR_PLUGIN); + g_cvars[CVAR_DISMISS] = CreateConVar("sm_maprate_dismiss", "0", "If non-zero, the first voting option will be \"Dismiss\"", FCVAR_PLUGIN); + g_cvars[CVAR_RESULTS] = CreateConVar("sm_maprate_autoresults", "1", "If non-zero, the results graph will automatically be displayed when a player rates a map", FCVAR_PLUGIN); + + HookEvent("player_death", Event_PlayerDeath); + AutoExecConfig(true, "maprate"); + + g_dismiss = GetConVarBool(g_cvars[CVAR_DISMISS]); + GetConVarString(g_cvars[CVAR_DB_CONFIG], cv_db, sizeof(cv_db)); + + new Handle:top_menu; + if (LibraryExists("adminmenu") && ((top_menu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + OnAdminMenuReady(top_menu); + } +} + +InitialiseDatabase() { + if (!SQL_TConnect(g_hDatabase, cv_db)) { + LogError("Couldn't connect to database."); + } + + if (g_hDatabase != INVALID_HANDLE) { + decl String:path[256]; + BuildPath(Path_SM, path, sizeof(path), "configs/maprate/initialise.sql"); + + if (!SQLH_FastQueriesFromFile(g_hDatabase, path, true)) { + CloseHandle(g_hDatabase); + + LogError("Couldn't execute initialisation queries."); + } + } +} \ No newline at end of file diff --git a/mvmsetaddmoney.sp b/mvmsetaddmoney.sp new file mode 100644 index 0000000..d74325c --- /dev/null +++ b/mvmsetaddmoney.sp @@ -0,0 +1,298 @@ +#include +#include +#include +#undef REQUIRE_PLUGIN +#include + +#define VERSION "1.1" + +new Handle:hAdminMenu = INVALID_HANDLE +new Handle:hPlayerSelectMenu = INVALID_HANDLE; +new Handle:hAmountSelectMenu = INVALID_HANDLE; +new String:targetSelected[32] = ""; + +public Plugin:myinfo = +{ + name = "MvM Set/Add Money", + author = "Chefe", + description = "Add/set players amount of cash", + version = VERSION, + url = "" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_setmoney", Command_SetMoney, ADMFLAG_CUSTOM2, "Set money of specifed userid"); + RegAdminCmd("sm_addmoney", Command_AddMoney, ADMFLAG_CUSTOM2, "Set money of specifed userid"); + CreateConVar("sm_setaddmoney_version", VERSION, "Version of the Plugin", FCVAR_NOTIFY); + + new Handle:topmenu; + if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) + { + OnAdminMenuReady(topmenu); + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, "adminmenu")) + { + hAdminMenu = INVALID_HANDLE; + } +} + +public OnAdminMenuReady(Handle:topmenu) +{ + /* Block us from being called twice */ + if (topmenu == hAdminMenu) + { + return; + } + + hAdminMenu = topmenu; + /* If the category is third party, it will have its own unique name. */ + new TopMenuObject:player_commands = FindTopMenuCategory(hAdminMenu, ADMINMENU_PLAYERCOMMANDS); + + if (player_commands == INVALID_TOPMENUOBJECT) + { + /* Error! */ + return; + } + + AddToTopMenu(hAdminMenu, "sm_addmoney", TopMenuObject_Item, AdminMenu_AddMoney, player_commands, "sm_addmoney", ADMFLAG_CUSTOM2); +} + +public AdminMenu_AddMoney(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength) +{ + if (action == TopMenuAction_DisplayOption) + { + Format(buffer, maxlength, "Add Money (MvM)"); + } + else if (action == TopMenuAction_SelectOption) + { + hPlayerSelectMenu = CreateMenu(Menu_PlayerSelect); + SetMenuTitle(hPlayerSelectMenu, "Select Target"); + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + new currentCash = getClientCash(i); + + new String:infostr[200]; + Format(infostr, sizeof(infostr), "%N (%i)", i, currentCash); + + new String:indexstr[32]; + IntToString(i, indexstr, sizeof(indexstr)); + AddMenuItem(hPlayerSelectMenu,indexstr, infostr) + } + AddMenuItem(hPlayerSelectMenu, "red", "All Red"); + AddMenuItem(hPlayerSelectMenu, "blue", "All Blu"); + AddMenuItem(hPlayerSelectMenu, "all", "All Player"); + SetMenuExitButton(hPlayerSelectMenu, true); + DisplayMenu(hPlayerSelectMenu, param, MENU_TIME_FOREVER); + } +} + +public Menu_PlayerSelect(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:info[32]; + GetMenuItem(menu, param2, info, sizeof(info)); + targetSelected = info; + + hAmountSelectMenu = CreateMenu(Menu_AmountSelect); + SetMenuTitle(hAmountSelectMenu, "Select Amount"); + AddMenuItem(hAmountSelectMenu, "50", "50"); + AddMenuItem(hAmountSelectMenu, "100", "100"); + AddMenuItem(hAmountSelectMenu, "500", "500"); + AddMenuItem(hAmountSelectMenu, "1000", "1000"); + AddMenuItem(hAmountSelectMenu, "5000", "5000"); + AddMenuItem(hAmountSelectMenu, "10000", "10000"); + AddMenuItem(hAmountSelectMenu, "30000", "30000"); + SetMenuExitButton(hAmountSelectMenu, true); + DisplayMenu(hAmountSelectMenu, param1, MENU_TIME_FOREVER); + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Menu_AmountSelect(Handle:menu, MenuAction:action, param1, param2) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + new String:stramount[32]; + GetMenuItem(menu, param2, stramount, sizeof(stramount)); + new amount = StringToInt(stramount); + + if (strcmp(targetSelected, "red", false) != 0 && strcmp(targetSelected, "blue", false) != 0 && strcmp(targetSelected, "all", false) != 0) + { + new client = StringToInt(targetSelected); + + if (IsClientInGame(client)) + { + addClientCash(client, amount); + + CloseHandle(menu); + } + } + else + { + if (strcmp(targetSelected, "red") == 0 || strcmp(targetSelected, "blue") == 0) + { + new targetteam = FindTeamByName(targetSelected); + + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + if (GetClientTeam(i) == targetteam) + { + addClientCash(i, amount); + + CloseHandle(menu); + } + } + } + else if (strcmp(targetSelected, "all") == 0) + { + new maxClients = GetMaxClients(); + for (new i=1; i<=maxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + + addClientCash(i, amount); + + CloseHandle(menu); + } + } + } + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + CloseHandle(menu); + } +} + +public Action:Command_SetMoney(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_setmoney "); + return Plugin_Handled; + } + + new String:amount[10]; + GetCmdArg(2, amount, sizeof(amount)); + + new String:name[32], target = -1; + GetCmdArg(1, name, sizeof(name)); + + for (new i=1; i<=MaxClients; i++) + { + if (!IsClientConnected(i)) + { + continue; + } + decl String:other[32]; + GetClientName(i, other, sizeof(other)); + if (StrEqual(name, other)) + { + target = i; + } + } + + if (target == -1) + { + PrintToConsole(client, "Could not find any player with the name: \"%s\"", name); + return Plugin_Handled; + } + + setClientCash(target, StringToInt(amount)); + + return Plugin_Handled; +} + +public Action:Command_AddMoney(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_addmoney "); + return Plugin_Handled; + } + + new String:amount[10]; + GetCmdArg(2, amount, sizeof(amount)); + + new String:name[32], target = -1; + GetCmdArg(1, name, sizeof(name)); + + for (new i=1; i<=MaxClients; i++) + { + if (!IsClientConnected(i)) + { + continue; + } + decl String:other[32]; + GetClientName(i, other, sizeof(other)); + if (StrEqual(name, other)) + { + target = i; + } + } + + if (target == -1) + { + PrintToConsole(client, "Could not find any player with the name: \"%s\"", name); + return Plugin_Handled; + } + + new currentCash = getClientCash(client); + setClientCash(client, StringToInt(amount)+currentCash); + + return Plugin_Handled; +} + +getClientCash(client) +{ + new CurrentCash = GetEntProp(client, Prop_Send, "m_nCurrency"); + return CurrentCash; +} + +setClientCash(client, amount) +{ + SetEntProp(client, Prop_Send, "m_nCurrency", amount); +} + +addClientCash(client, amount) +{ + new currentCash = getClientCash(client); + setClientCash(client, amount+currentCash); +} \ No newline at end of file diff --git a/opend.sp b/opend.sp new file mode 100644 index 0000000..33c3f19 --- /dev/null +++ b/opend.sp @@ -0,0 +1,40 @@ +/* Plugin Template generated by Pawn Studio */ + +#include +#include +#include + +public Plugin:myinfo = +{ + name = "jump_4starter_dopener", + author = "Chefe", + description = "<- Description ->", + version = "1.0", + url = "<- URL ->" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_opend", Command_DOpen, ADMFLAG_CHEATS, "opens the door on D"); +} + +public Action:Command_DOpen(client, args) +{ + new ent = -1; + + while ((ent = FindEntityByClassname(ent, "logic_branch")) != -1) + { + decl String:strName[50]; + GetEntPropString(ent, Prop_Data, "m_iName", strName, sizeof(strName)); + + if(!strcmp(strName, "bonus_button_01_listener") || !strcmp(strName, "bonus_button_02_listener") || !strcmp(strName, "bonus_button_03_listener")) + { + SetVariantInt(1); + new bool:donechange = AcceptEntityInput(ent, "setValue"); + + if (donechange) { PrintToServer("Sucessfully set all logic_branches!"); } + } + } + + return Plugin_Handled; +} \ No newline at end of file diff --git a/quakesounds_tf2.sp b/quakesounds_tf2.sp new file mode 100644 index 0000000..49768b8 --- /dev/null +++ b/quakesounds_tf2.sp @@ -0,0 +1,796 @@ +#include +#include +#include + +#pragma semicolon 1 + +#define PLUGIN_VERSION "2.7" + +// Plugin definitions +public Plugin:myinfo = +{ + name = "Quake Sounds", + author = "dalto, Grrrrrrrrrrrrrrrrrrr, and psychonic", + description = "Quake Sounds Plugin", + version = PLUGIN_VERSION, + url = "http://forums.alliedmods.net" +}; + +//#define OTHER +//#define DODS +//#define CSS +//#define HL2DM +#define TF2 + +//#define MAX_FILE_LEN 65 +#define NOT_BASED_ON_KILLS 0 + +#define MAX_NUM_SETS 5 +new numSets = 0; +new String:setsName[MAX_NUM_SETS][PLATFORM_MAX_PATH]; + +#define NUM_TYPES 10 +static const String:typeNames[NUM_TYPES][] = {"headshot", "grenade", "selfkill", "round play", "knife", "killsound", "first blood", "teamkill", "combo", "join server"}; + +#define MAX_NUM_KILLS 200 +new settingConfig[NUM_TYPES][MAX_NUM_KILLS]; +new soundsList[NUM_TYPES][MAX_NUM_KILLS][MAX_NUM_SETS]; + +#define MAX_NUM_FILES 102 +new numSounds = 0; +new String:soundsFiles[MAX_NUM_FILES][PLATFORM_MAX_PATH]; + +#define HEADSHOT 0 +#define GRENADE 1 +#define SELFKILL 2 +#define ROUND_PLAY 3 +#define KNIFE 4 +#define KILLSOUND 5 +#define FIRSTBLOOD 6 +#define TEAMKILL 7 +#define COMBO 8 +#define JOINSERVER 9 + +new Handle:cvarEnabled = INVALID_HANDLE; +new Handle:cvarAnnounce = INVALID_HANDLE; +new Handle:cvarTextDefault = INVALID_HANDLE; +new Handle:cvarSoundDefault = INVALID_HANDLE; +new Handle:cvarVolume = INVALID_HANDLE; + +new iMaxClients; + +new totalKills = 0; +new soundPreference[MAXPLAYERS + 1]; +new textPreference[MAXPLAYERS + 1]; +new consecutiveKills[MAXPLAYERS + 1]; +new Float:lastKillTime[MAXPLAYERS + 1]; +new lastKillCount[MAXPLAYERS + 1]; +new headShotCount[MAXPLAYERS + 1]; +#if defined DODS +new hurtHitGroup[MAXPLAYERS + 1]; +#endif + +new Handle:cookieTextPref; +new Handle:cookieSoundPref; + +new bool:lateLoaded = false; + +// if the plugin was loaded late we have a bunch of initialization that needs to be done +public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) +{ + lateLoaded = late; + + return true; +} + +public OnPluginStart() +{ + cvarEnabled = CreateConVar("sm_quakesounds_enable", "1", "Enables the Quake sounds plugin"); + HookConVarChange(cvarEnabled, EnableChanged); + + LoadTranslations("plugin.quakesounds"); + + CreateConVar("sm_quakesounds_version", PLUGIN_VERSION, "Quake Sounds Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); + cvarAnnounce = CreateConVar("sm_quakesounds_announce", "1", "Announcement preferences"); + cvarTextDefault = CreateConVar("sm_quakesounds_text", "1", "Default text setting for new users"); + cvarSoundDefault = CreateConVar("sm_quakesounds_sound", "1", "Default sound for new users, 1=Standard, 2=Female, 0=Disabled"); + cvarVolume = CreateConVar("sm_quakesounds_volume", "1.0", "Volume: should be a number between 0.0. and 1.0"); + + if(GetConVarBool(cvarEnabled)) + { + HookEvent("player_death", EventPlayerDeath); + + #if defined CSS + HookEvent("round_freeze_end", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + #elseif defined DODS + HookEvent("dod_warmup_ends", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + HookEvent("player_hurt", EventPlayerHurt); + #endif + + #if defined DODS + HookEvent("dod_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif defined TF2 + HookEvent("teamplay_round_start", EventRoundStart, EventHookMode_PostNoCopy); + HookEvent("arena_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif !defined HL2DM + HookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy); + #endif + } + + RegConsoleCmd("quake", MenuQuake); + + AutoExecConfig(true, "sm_quakesounds"); + + LoadSounds(); + + //initialize kvQUS + cookieTextPref = RegClientCookie("Quake Text Pref", "Text setting", CookieAccess_Private); + cookieSoundPref = RegClientCookie("Quake Sound Pref", "Sound setting", CookieAccess_Private); + + //add to clientpref's built-in !settings menu + SetCookieMenuItem(QuakePrefSelected, 0, "Quake Sound Prefs"); + + if (lateLoaded) + { + iMaxClients=GetMaxClients(); + + // First we need to do whatever we would have done at RoundStart() + NewRoundInitialization(); + + // Next we need to whatever we would have done as each client authorized + new tempSoundDefault = GetConVarInt(cvarSoundDefault) - 1; + new tempTextDefault = GetConVarInt(cvarTextDefault); + for(new i = 1; i <= iMaxClients; i++) + { + if(IsClientInGame(i) && IsFakeClient(i)) + { + soundPreference[i] = -1; + textPreference[i] = 0; + } + else + { + soundPreference[i] = tempSoundDefault; + textPreference[i] = tempTextDefault; + + if(IsClientInGame(i) && AreClientCookiesCached(i)) + { + loadClientCookiesFor(i); + } + } + } + } +} + +//add to clientpref's built-in !settings menu +public QuakePrefSelected(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) +{ + if (action == CookieMenuAction_SelectOption) + { + ShowQuakeMenu(client); + } +} + +// Looks for cvar changes of the enable cvar and hooks or unhooks the events +public EnableChanged(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + new intNewValue = StringToInt(newValue); + new intOldValue = StringToInt(oldValue); + + if(intNewValue == 1 && intOldValue == 0) + { + HookEvent("player_death", EventPlayerDeath); + + #if defined CSS + HookEvent("round_freeze_end", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + #elseif defined DODS + HookEvent("dod_warmup_ends", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + HookEvent("player_hurt", EventPlayerHurt); + #endif + + #if defined DODS + HookEvent("dod_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif defined TF2 + HookEvent("teamplay_round_start", EventRoundStart, EventHookMode_PostNoCopy); + HookEvent("arena_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif !defined HL2DM + HookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy); + #endif + } + else if(intNewValue == 0 && intOldValue == 1) + { + UnhookEvent("player_death", EventPlayerDeath); + + #if defined CSS + UnhookEvent("round_freeze_end", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + #elseif defined DODS + UnhookEvent("dod_warmup_ends", EventRoundFreezeEnd, EventHookMode_PostNoCopy); + UnhookEvent("player_hurt", EventPlayerHurt); + #endif + + #if defined DODS + UnhookEvent("dod_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif defined TF2 + UnhookEvent("teamplay_round_start", EventRoundStart, EventHookMode_PostNoCopy); + UnhookEvent("arena_round_start", EventRoundStart, EventHookMode_PostNoCopy); + #elseif !defined HL2DM + UnhookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy); + #endif + } +} + +public LoadSounds() +{ + decl String:buffer[PLATFORM_MAX_PATH]; + + decl String:fileQSL[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, fileQSL, PLATFORM_MAX_PATH, "configs/QuakeSoundsList.cfg"); + + new Handle:kvQSL = CreateKeyValues("QuakeSoundsList"); + FileToKeyValues(kvQSL, fileQSL); + + // Read the sound set information in + if (!KvJumpToKey(kvQSL, "sound sets")) + { + SetFailState("configs/QuakeSoundsList.cfg not found or not correctly structured"); + return; + } + + numSets = 0; + for(new i = 1; i <= MAX_NUM_SETS; i++) + { + Format(buffer, PLATFORM_MAX_PATH, "sound set %i", i); + KvGetString(kvQSL, buffer, setsName[numSets], PLATFORM_MAX_PATH); + if(!StrEqual(setsName[numSets], "")) + { + numSets++; + } + } + + // Read the sounds in by type + numSounds = 0; + for(new typeKey = 0; typeKey < NUM_TYPES; typeKey++) + { + KvRewind(kvQSL); + if(KvJumpToKey(kvQSL, typeNames[typeKey])) + { + if (KvGotoFirstSubKey(kvQSL)) + { + do + { + KvGetSectionName(kvQSL, buffer, sizeof(buffer)); + new settingKills = StringToInt(buffer); + new tempConfig = KvGetNum(kvQSL, "config", 9); + if(!StrEqual(buffer, "") && settingKills>-1 && settingKills0) + { + settingConfig[typeKey][settingKills] = tempConfig; + + if((tempConfig & 1) || (tempConfig & 2) || (tempConfig & 4)) + { + for(new set = 0; set < numSets; set++) + { + KvGetString(kvQSL, setsName[set], soundsFiles[numSounds], PLATFORM_MAX_PATH); + if(StrEqual(soundsFiles[numSounds], "")) + { + soundsList[typeKey][settingKills][set] = -1; + } + else + { + soundsList[typeKey][settingKills][set] = numSounds; + numSounds++; + } + } + } + } + } while (KvGotoNextKey(kvQSL)); + + KvGoBack(kvQSL); + } + else + { + new settingKills = KvGetNum(kvQSL, "kills", 0); + new tempConfig = KvGetNum(kvQSL, "config", 9); + if(settingKills>-1 && settingKills0) + { + settingConfig[typeKey][settingKills] = tempConfig; + + if((tempConfig & 1) || (tempConfig & 2) || (tempConfig & 4)) + { + for(new set = 0; set < numSets; set++) + { + KvGetString(kvQSL, setsName[set], soundsFiles[numSounds], PLATFORM_MAX_PATH); + if(StrEqual(soundsFiles[numSounds], "")) + { + soundsList[typeKey][settingKills][set] = -1; + } + else + { + soundsList[typeKey][settingKills][set] = numSounds; + numSounds++; + } + } + } + } + } + } + } + + CloseHandle(kvQSL); +} + +public OnMapStart() +{ + iMaxClients=GetMaxClients(); + + decl String:downloadFile[PLATFORM_MAX_PATH]; + for(new i=0; i < numSounds; i++) + { + if(PrecacheSound(soundsFiles[i], true)) + { + Format(downloadFile, PLATFORM_MAX_PATH, "sound/%s", soundsFiles[i]); + AddFileToDownloadsTable(downloadFile); + } + else + { + LogError("Quake Sounds: Cannot precache sound: %s", soundsFiles[i]); + } + } + + #if defined HL2DM + NewRoundInitialization(); + #endif +} + +#if !defined HL2DM +public EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast) +{ + NewRoundInitialization(); +} +#endif + +// This is called from EventRoundStart or OnMapStart depending on the mod +public NewRoundInitialization() +{ + totalKills = 0; + for(new i = 1; i <= iMaxClients; i++) + { + headShotCount[i] = 0; + lastKillTime[i] = -1.0; + #if defined DODS + hurtHitGroup[i] = 0; + #endif + } +} + +// Play the starting sound +public EventRoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + PlayQuakeSound(ROUND_PLAY, 0, 0, 0); + PrintQuakeText(ROUND_PLAY, 0, 0, 0); +} + +// When a new client joins we reset sound preferences +// and let them know how to turn the sounds on and off +public OnClientPutInServer(client) +{ + consecutiveKills[client] = 0; + lastKillTime[client] = -1.0; + headShotCount[client] = 0; + + // Initializations and preferences loading + if(!IsFakeClient(client)) + { + soundPreference[client] = GetConVarInt(cvarSoundDefault) - 1; + textPreference[client] = GetConVarInt(cvarTextDefault); + + if (AreClientCookiesCached(client)) + { + loadClientCookiesFor(client); + } + + // Make the announcement in 30 seconds unless announcements are turned off + if(GetConVarBool(cvarAnnounce)) + { + CreateTimer(30.0, TimerAnnounce, client); + } + + // Play event sound + if(settingConfig[JOINSERVER][NOT_BASED_ON_KILLS] && soundPreference[client]>-1) + { + new filePosition = soundsList[JOINSERVER][NOT_BASED_ON_KILLS][soundPreference[client]]; + if(filePosition>-1) + { + EmitSoundToClient(client, soundsFiles[filePosition], _, _, _, _, GetConVarFloat(cvarVolume)); + } + } + } + else + { + soundPreference[client] = -1; + textPreference[client] = 0; + } +} + +public Action:TimerAnnounce(Handle:timer, any:client) +{ + if(IsClientInGame(client)) + { + PrintToChat(client, "%t", "announce message"); + } +} + +public OnClientCookiesCached(client) +{ + // Initializations and preferences loading + if(IsClientInGame(client) && !IsFakeClient(client)) + { + loadClientCookiesFor(client); + } +} + +loadClientCookiesFor(client) +{ + decl String:buffer[5]; + + GetClientCookie(client, cookieTextPref, buffer, 5); + if(!StrEqual(buffer, "")) + { + textPreference[client] = StringToInt(buffer); + } + + GetClientCookie(client, cookieSoundPref, buffer, 5); + if(!StrEqual(buffer, "")) + { + soundPreference[client] = StringToInt(buffer); + } +} + +// The death event this is where we decide what sound to play +// It is important to note that we will play no more than one sound per death event +// so we will order them as to choose the most appropriate one +#if defined DODS +public EventPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + new victimClient = GetClientOfUserId(GetEventInt(event, "userid")); + + if(victimClient<1 || victimClient>iMaxClients || GetEventInt(event, "health") > 0) + { + return; + } + + hurtHitGroup[victimClient] = GetEventInt(event, "hitgroup"); +} +#endif + +public EventPlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new attackerClient = GetClientOfUserId(GetEventInt(event, "attacker")); + new victimClient = GetClientOfUserId(GetEventInt(event, "userid")); + + new soundId = -1; + new killsValue = 0; + + if(victimClient<1 || victimClient>iMaxClients) + { + return; + } + + if(attackerClient>0 && attackerClient<=iMaxClients) + { + if(attackerClient == victimClient) + { + if(settingConfig[SELFKILL][NOT_BASED_ON_KILLS]) + { + soundId = SELFKILL; + } + } + else if(GetClientTeam(attackerClient) == GetClientTeam(victimClient)) + { + consecutiveKills[attackerClient] = 0; + + if(settingConfig[TEAMKILL][NOT_BASED_ON_KILLS]) + { + soundId = TEAMKILL; + } + } + else + { + totalKills++; + + decl String:weapon[64]; + GetEventString(event, "weapon", weapon, sizeof(weapon)); + #if defined CSS + new bool:headshot = GetEventBool(event, "headshot"); + #elseif defined TF2 + new customkill = GetEventInt(event, "customkill"); + new bool:headshot = (customkill == 1); + #elseif defined DODS + new bool:headshot = (hurtHitGroup[victimClient] == 1); + #else + new bool:headshot = false; + #endif + + consecutiveKills[attackerClient]++; + if(headshot) + { + headShotCount[attackerClient]++; + } + new Float:tempLastKillTime = lastKillTime[attackerClient]; + lastKillTime[attackerClient] = GetEngineTime(); + if(tempLastKillTime == -1.0 || (lastKillTime[attackerClient] - tempLastKillTime) > 6.0) + { + lastKillCount[attackerClient] = 1; + } + else + { + lastKillCount[attackerClient]++; + } + + if(totalKills == 1 && settingConfig[FIRSTBLOOD][NOT_BASED_ON_KILLS]) + { + soundId = FIRSTBLOOD; + } + else if(settingConfig[KILLSOUND][consecutiveKills[attackerClient]]) + { + soundId = KILLSOUND; + killsValue = consecutiveKills[attackerClient]; + } + else if(settingConfig[COMBO][lastKillCount[attackerClient]]) + { + soundId = COMBO; + killsValue = lastKillCount[attackerClient]; + } + else if(headshot && settingConfig[HEADSHOT][headShotCount[attackerClient]]) + { + soundId = HEADSHOT; + killsValue = headShotCount[attackerClient]; + } + else if(headshot && settingConfig[HEADSHOT][NOT_BASED_ON_KILLS]) + { + soundId = HEADSHOT; + } + #if defined TF2 + else if(customkill == 2 && settingConfig[KNIFE][NOT_BASED_ON_KILLS]) + { + soundId = KNIFE; + } + #elseif defined CSS + else if((StrEqual(weapon, "hegrenade") || StrEqual(weapon, "smokegrenade") || StrEqual(weapon, "flashbang")) && settingConfig[GRENADE][NOT_BASED_ON_KILLS]) + { + soundId = GRENADE; + } + else if(StrEqual(weapon, "knife") && settingConfig[KNIFE][NOT_BASED_ON_KILLS]) + { + soundId = KNIFE; + } + #elseif defined DODS + else if((StrEqual(weapon, "riflegren_ger") || StrEqual(weapon, "riflegren_us") || StrEqual(weapon, "frag_ger") || StrEqual(weapon, "frag_us") || StrEqual(weapon, "smoke_ger") || StrEqual(weapon, "smoke_us")) && settingConfig[GRENADE][NOT_BASED_ON_KILLS]) + { + soundId = GRENADE; + } + else if((StrEqual(weapon, "spade") || StrEqual(weapon, "amerknife") || StrEqual(weapon, "punch")) && settingConfig[KNIFE][NOT_BASED_ON_KILLS]) + { + soundId = KNIFE; + } + #elseif defined HL2DM + else if(StrEqual(weapon, "grenade_frag") && settingConfig[GRENADE][NOT_BASED_ON_KILLS]) + { + soundId = GRENADE; + } + else if((StrEqual(weapon, "stunstick") || StrEqual(weapon, "crowbar")) && settingConfig[KNIFE][NOT_BASED_ON_KILLS]) + { + soundId = KNIFE; + } + #endif + } + } + + #if defined DODS + hurtHitGroup[victimClient] = 0; + #endif + + consecutiveKills[victimClient] = 0; + + // Play the appropriate sound if there was a reason to do so + if(soundId != -1) + { + PlayQuakeSound(soundId, killsValue, attackerClient, victimClient); + PrintQuakeText(soundId, killsValue, attackerClient, victimClient); + } +} + +// This plays the quake sounds based on soundPreference +public PlayQuakeSound(soundKey, killsValue, attackerClient, victimClient) +{ + new config = settingConfig[soundKey][killsValue]; + new filePosition; + + if(config & 1) + { + for (new i = 1; i <= iMaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && soundPreference[i]>-1) + { + filePosition = soundsList[soundKey][killsValue][soundPreference[i]]; + if(filePosition>-1) + { + EmitSoundToClient(i, soundsFiles[filePosition], _, _, _, _, GetConVarFloat(cvarVolume)); + } + } + } + } + else + { + new Float:volumeLevel = GetConVarFloat(cvarVolume); + + if(config & 2 && soundPreference[attackerClient]>-1) + { + filePosition = soundsList[soundKey][killsValue][soundPreference[attackerClient]]; + if(filePosition>-1) + { + EmitSoundToClient(attackerClient, soundsFiles[filePosition], _, _, _, _, volumeLevel); + } + } + if(config & 4 && soundPreference[victimClient]>-1) + { + filePosition = soundsList[soundKey][killsValue][soundPreference[victimClient]]; + if(filePosition>-1) + { + EmitSoundToClient(victimClient, soundsFiles[filePosition], _, _, _, _, volumeLevel); + } + } + } +} + +// This prints the quake text +public PrintQuakeText(soundKey, killsValue, attackerClient, victimClient) +{ + decl String:attackerName[MAX_NAME_LENGTH]; + decl String:victimName[MAX_NAME_LENGTH]; + + // Get the names of the victim and the attacker + if(attackerClient && IsClientInGame(attackerClient)) + { + GetClientName(attackerClient, attackerName, MAX_NAME_LENGTH); + } + else + { + attackerName = "Nobody"; + } + if(victimClient && IsClientInGame(victimClient)) + { + GetClientName(victimClient, victimName, MAX_NAME_LENGTH); + } + else + { + victimName = "Nobody"; + } + + decl String:translationName[65]; + if(killsValue>0) + { + Format(translationName, 65, "%s %i", typeNames[soundKey], killsValue); + } + else + { + Format(translationName, 65, "%s", typeNames[soundKey]); + } + + new config = settingConfig[soundKey][killsValue]; + + if(config & 8) + { + for (new i = 1; i <= iMaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && textPreference[i]) + { + PrintToChat(i, "%t", translationName, attackerName, victimName); + } + } + } + else + { + if(config & 16 && textPreference[attackerClient]) + { + PrintToChat(attackerClient, "%t", translationName, attackerName, victimName); + } + if(config & 32 && textPreference[victimClient]) + { + PrintToChat(victimClient, "%t", translationName, attackerName, victimName); + } + } +} + +// This selects or disables the quake sounds +public MenuHandlerQuake(Handle:menu, MenuAction:action, param1, param2) +{ + if(action == MenuAction_Select) + { + // The Disable Choice moves around based on if female sounds are enabled + new disableChoice = numSets + 1; + + // Update both the soundPreference array and User Settings KV + if(param2 == disableChoice) + { + soundPreference[param1] = -1; + } + else if(param2 == 0) + { + if(textPreference[param1] == 0) + { + textPreference[param1] = 1; + } + else + { + textPreference[param1] = 0; + } + } + else + { + soundPreference[param1] = param2 - 1; + } + + decl String:buffer[5]; + IntToString(textPreference[param1], buffer, 5); + SetClientCookie(param1, cookieTextPref, buffer); + IntToString(soundPreference[param1], buffer, 5); + SetClientCookie(param1, cookieSoundPref, buffer); + + MenuQuake(param1, 0); + } + else if(action == MenuAction_End) + { + CloseHandle(menu); + } +} + +// This creates the Quake menu +public Action:MenuQuake(client, args) +{ + ShowQuakeMenu(client); + return Plugin_Handled; +} + +ShowQuakeMenu(client) +{ + new Handle:menu = CreateMenu(MenuHandlerQuake); + decl String:buffer[100]; + + Format(buffer, sizeof(buffer), "%T", "quake menu", client); + SetMenuTitle(menu, buffer); + + if(textPreference[client] == 0) + { + Format(buffer, sizeof(buffer), "%T", "enable text", client); + } + else + { + Format(buffer, sizeof(buffer), "%T", "disable text", client); + } + AddMenuItem(menu, "text pref", buffer); + + for(new set = 0; set < numSets; set++) + { + if(soundPreference[client] == set) + { + Format(buffer, 50, "%T(Enabled)", setsName[set], client); + } + else + { + Format(buffer, 50, "%T", setsName[set], client); + } + AddMenuItem(menu, "sound set", buffer); + } + if(soundPreference[client] == -1) + { + Format(buffer, sizeof(buffer), "%T(Enabled)", "no quake sounds", client); + } + else + { + Format(buffer, sizeof(buffer), "%T", "no quake sounds", client); + } + AddMenuItem(menu, "no sounds", buffer); + + SetMenuExitButton(menu, true); + + DisplayMenu(menu, client, 20); +} \ No newline at end of file diff --git a/reflect_dmg.sp b/reflect_dmg.sp new file mode 100644 index 0000000..84f4a3a --- /dev/null +++ b/reflect_dmg.sp @@ -0,0 +1,53 @@ +/* Plugin Template generated by Pawn Studio */ + +#include + +new client_maxhealth[MAXPLAYERS+1]; + +public Plugin:myinfo = +{ + name = "ReflectDmg", + author = "Chefe", + description = "", + version = "1.0", + url = "www.chefgaming.de" +} + +public OnPluginStart() +{ + //Hooks + HookEvent("player_hurt", Event_PlayerHurt); + HookEvent("player_spawn", Event_PlayerSpawn); +} + +public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +{ + new userid = GetEventInt(event, "userid"); + new client = GetClientOfUserId(userid); + + if (IsClientInGame(client) && IsPlayerAlive(client)) + { + client_maxhealth[client] = GetClientHealth(client); + } +} + +public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + new client = GetClientOfUserId(GetEventInt(event, "userid")); + new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + new client_hp = GetEventInt(event, "health"); + new client_dmg = GetEventInt(event, "damageamount"); + new newhealth; + + if (client && attacker && client != attacker) + { + if (client_hp+client_dmg > client_maxhealth[client]) { + newhealth = client_maxhealth[client]; + } else { + newhealth = client_hp+client_dmg; + } + //SetEntData(client, FindDataMapOffs(client, "m_iMaxHealth"), client_hp[client], 4, true); + //PrintToChat(client, "[DBG] health-var: %i - dmg-var: %i - attacker: %i - cmb-health: %i", client_hp, client_dmg, attacker, newhealth); + SetEntData(client, FindDataMapOffs(client, "m_iHealth"), newhealth, 4, true); + } +} \ No newline at end of file diff --git a/sentry_mod.sp b/sentry_mod.sp new file mode 100644 index 0000000..24ac85e --- /dev/null +++ b/sentry_mod.sp @@ -0,0 +1,123 @@ +//* Plugin Template generated by Pawn Studio */ + +#include +#include + +public Plugin:myinfo = +{ + name = "Sentry Mod", + author = "Chefe", + description = "lw", + version = "1.0", + url = "www.the-bos.de" +} + +public OnPluginStart() +{ + RegAdminCmd("sm_ssa", Command_SetSentryAmmo, ADMFLAG_CHEATS, "Set prop ammo of the sentry your looking at"); + RegAdminCmd("sm_ssr", Command_SetSentryRockets, ADMFLAG_CHEATS, "Set prop rocketammo of the sentry your looking at"); + RegAdminCmd("sm_ssl", Command_SetSentryLevel, ADMFLAG_CHEATS, "Set prop lvl of the sentry your looking at"); +} + +public Action:Command_SetSentryAmmo(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_ssa ") + return Plugin_Handled + } + + new index = GetClientAimTarget(client, false); + + new String:arg1[150]; + GetCmdArg(1, arg1, sizeof(arg1)); + new ammo = StringToInt(arg1); + + SetSentryAmmo(index, ammo); + ReplyToCommand(client, "[SM] Ammo of Sentry %i was set on %i", index, ammo); + + return Plugin_Handled; +} + +public Action:Command_SetSentryRockets(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_ssr ") + return Plugin_Handled + } + + new index = GetClientAimTarget(client, false); + + new String:arg1[150]; + GetCmdArg(1, arg1, sizeof(arg1)); + new ammo = StringToInt(arg1); + new level = GetSentryLevel(index) + + if (level == 3) + { + SetSentryRockets(index, ammo); + ReplyToCommand(client, "[SM] Rockets of Sentry %i was set on %i", index, ammo); + } + else + { + ReplyToCommand(client, "[SM] Sentry %i is not on lvl 3!", index); + } + return Plugin_Handled; +} + +public Action:Command_SetSentryLevel(client, args) +{ + if (args < 1) + { + PrintToConsole(client, "Usage: sm_ssl ") + return Plugin_Handled + } + + new index = GetClientAimTarget(client, false); + + new String:arg1[150]; + GetCmdArg(1, arg1, sizeof(arg1)); + new lvl = StringToInt(arg1); + + SetSentryLevel(index, lvl); + ReplyToCommand(client, "[SM] Sentry %i was set on level %i", index, lvl); + + return Plugin_Handled; +} + +SetSentryAmmo(index, ammo) +{ + SetEntProp(index, Prop_Send, "m_iAmmoShells", ammo); +} + +SetSentryRockets(index, rockets) +{ + SetEntProp(index, Prop_Send, "m_iAmmoRockets", rockets); +} + +SetSentryLevel(index, level) +{ + SetEntProp(index, Prop_Send, "m_iUpgradeLevel", level); +} + +GetSentryAmmo(index) +{ + new ammo = GetEntProp(index, Prop_Send, "m_iAmmoShells"); + + return ammo; +} + +GetSentryRockets(index) +{ + new rockets = GetEntProp(index, Prop_Send, "m_iAmmoRockets"); + + return rockets; +} + +GetSentryLevel(index) +{ + new lvl = GetEntProp(index, Prop_Send, "m_iUpgradeLevel"); + + return lvl; +} \ No newline at end of file diff --git a/sourcebans.sp b/sourcebans.sp new file mode 100644 index 0000000..ea416b8 --- /dev/null +++ b/sourcebans.sp @@ -0,0 +1,2264 @@ +/** +* sourcebans.sp +* +* This file contains all Source Server Plugin Functions +* @author SourceBans Development Team +* @version 0.0.0.$Rev: 108 $ +* @copyright InterWave Studios (www.interwavestudios.com) +* @package SourceBans +* @link http://www.sourcebans.net +*/ + +#pragma semicolon 1 +#include +#include + +#undef REQUIRE_PLUGIN +#include +#include "dbi.inc" + +#define SB_VERSION "1.4.8" + +//GLOBAL DEFINES +#define YELLOW 0x01 +#define NAMECOLOR 0x02 +#define TEAMCOLOR 0x03 +#define GREEN 0x04 + +#define DISABLE_ADDBAN 1 +#define DISABLE_UNBAN 2 + +//#define DEBUG + +enum State /* ConfigState */ +{ + ConfigStateNone = 0, + ConfigStateConfig, + ConfigStateReasons, + ConfigStateHacking +} + +new g_BanTarget[MAXPLAYERS+1] = {-1, ...}; +new g_BanTime[MAXPLAYERS+1] = {-1, ...}; + +new State:ConfigState; +new Handle:ConfigParser; + +new Handle:hTopMenu = INVALID_HANDLE; + +new const String:BLANK[] = ""; +new const String:Prefix[] = "[SourceBans] "; + +new String:ServerIp[24]; +new String:ServerPort[7]; +new String:DatabasePrefix[10] = "sb"; +new String:WebsiteAddress[128]; + +/* Admin Stuff*/ +new AdminCachePart:loadPart; +new bool:loadAdmins; +new bool:loadGroups; +new bool:loadOverrides; +new curLoading=0; +new AdminFlag:g_FlagLetters[26]; + +/* Admin KeyValues */ +new String:groupsLoc[128]; +new String:adminsLoc[128]; + +/* Cvar handle*/ +new Handle:CvarHostIp; +new Handle:CvarPort; + +/* Database handle */ +new Handle:Database; +new Handle:SQLiteDB; + +/* Menu file globals */ +new Handle:ReasonMenuHandle; +new Handle:HackingMenuHandle; + +/* Datapack and Timer handles */ +new Handle:PlayerRecheck[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; +new Handle:PlayerDataPack[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; + +/* Player ban check status */ +new bool:PlayerStatus[MAXPLAYERS + 1]; + +/* Disable of addban and unban */ +new CommandDisable; +new bool:backupConfig = true; +new bool:enableAdmins = true; + +/* Require a lastvisited from SB site */ +new bool:requireSiteLogin = false; + +/* Log Stuff */ +new String:logFile[256]; + +/* Own Chat Reason */ +new g_ownReasons[MAXPLAYERS+1] = {false, ...}; + +new MaxSlots; +new Float:RetryTime = 15.0; +new ProcessQueueTime = 5; +new bool:LateLoaded; +new bool:AutoAdd; +new bool:g_bConnecting = false; + +new serverID = -1; + +public Plugin:myinfo = +{ + name = "SourceBans", + author = "SourceBans Development Team", + description = "Advanced ban management for the Source engine", + version = SB_VERSION, + url = "http://www.sourcebans.net" +}; + +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 3 +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) +#else +public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max) +#endif +{ + RegPluginLibrary("sourcebans"); + CreateNative("SBBanPlayer", Native_SBBanPlayer); + LateLoaded = late; + + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 3 + return APLRes_Success; + #else + return true; + #endif +} + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + LoadTranslations("plugin.basecommands"); + LoadTranslations("sourcebans.phrases"); + LoadTranslations("basebans.phrases"); + loadAdmins = loadGroups = loadOverrides = false; + + CvarHostIp = FindConVar("hostip"); + CvarPort = FindConVar("hostport"); + CreateConVar("sb_version", SB_VERSION, _, FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); + RegServerCmd("sm_rehash",sm_rehash,"Reload SQL admins"); + RegAdminCmd("sm_ban", CommandBan, ADMFLAG_BAN, "sm_ban <#userid|name> [reason]"); + RegAdminCmd("sm_banip", CommandBanIp, ADMFLAG_BAN, "sm_banip