From 082f75063a3f451ca89194583ae30c4cb2fdb48a Mon Sep 17 00:00:00 2001 From: BloodyBlade <111264368+BloodyBlade@users.noreply.github.com> Date: Sat, 4 Oct 2025 16:13:53 +0500 Subject: [PATCH] Update l4dcompstats.sp Transfered to the latest syntax. Fixed all warnings and errors during compilation on SM 1.9+ --- l4dcompstats.sp | 750 ++++++++++++++++++++++++------------------------ 1 file changed, 380 insertions(+), 370 deletions(-) diff --git a/l4dcompstats.sp b/l4dcompstats.sp index 9d640aa..6a5bd0a 100644 --- a/l4dcompstats.sp +++ b/l4dcompstats.sp @@ -7,7 +7,7 @@ * ============================================================================= */ -public Plugin:myinfo = +public Plugin myinfo = { name = "L4D Competitive Stats", author = "Griffin & Philogl", @@ -16,9 +16,10 @@ public Plugin:myinfo = }; #pragma semicolon 1 +#pragma newdecls required #include -#include include/sdkhooks.inc +#include #define MAXENTITIES 2048 #define SAYTEXT_MAXLENGTH 192 @@ -45,7 +46,7 @@ public Plugin:myinfo = #define IsIncapped(%0) (GetEntProp(%0, Prop_Send, "m_isIncapacitated") > 0) #define IsBoomed(%0) ((GetEntPropFloat(%0, Prop_Send, "m_vomitStart") + 20.1) > GetGameTime()) -enum _:ZOMBIECLASS +enum ZOMBIECLASS { ZC_SMOKER = 1, ZC_BOOMER, @@ -54,7 +55,7 @@ enum _:ZOMBIECLASS ZC_TANK } -enum _:STATS +enum STATS { FullSkeets, TeamSkeets, @@ -82,52 +83,51 @@ enum _:STATS } // Cvar related -new g_iMaxPlayerZombies = 4; -new g_iSurvivorLimit = 4; -new g_iMinDPDamage = 20; -new g_iWitchHealth = 1000; // Default -new Handle: g_hCvarMaxPlayerZombies = INVALID_HANDLE; -new Handle: g_hCvarSurvivorLimit = INVALID_HANDLE; -new Handle: g_hCvarMaxPounceBonusDamage = INVALID_HANDLE; -new Handle: g_hCvarWitchHealth = INVALID_HANDLE; -new Handle: g_hCvarDirectorReadyDuration = INVALID_HANDLE; +//int g_iMaxPlayerZombies = 4; +int g_iSurvivorLimit = 4; +int g_iMinDPDamage = 20; +int g_iWitchHealth = 1000; // Default +//ConVar g_hCvarMaxPlayerZombies; +ConVar g_hCvarSurvivorLimit; +ConVar g_hCvarMaxPounceBonusDamage; +ConVar g_hCvarWitchHealth; +ConVar g_hCvarDirectorReadyDuration; // Global state -new bool: g_bShouldAnnounceWitchDamage = false; -new bool: g_bHasRoundEnded = false; -new bool: g_bLogFF = false; -new Handle: g_hBoomerShoveTimer = INVALID_HANDLE; +bool g_bShouldAnnounceWitchDamage = false; +bool g_bHasRoundEnded = false; +bool g_bLogFF = false; +Handle g_hBoomerShoveTimer = null; // Player/Entity state -new g_iAccumulatedWitchDamage; // Current witch health = witch health - accumulated -new g_iBoomerClient; // Client of last player to be boomer (or current boomer) -new g_iBoomerKiller; // Client who shot the boomer -new g_iBoomerShover; // Client who shoved the boomer -new g_iLastHealth[MAXPLAYERS + 1]; -new bool: g_bHasBoomLanded; -new bool: g_bStatsCooldown[MAXPLAYERS + 1]; // Prevent spam of stats command (potential DoS vector I think) -new bool: g_bHasLandedPounce[MAXPLAYERS + 1]; // Used to determine if a deadstop was 'pierced' -new bool: g_bIsWitch[MAXENTITIES]; // Membership testing for fast witch checking -new bool: g_bIsPouncing[MAXPLAYERS + 1]; -new bool: g_bShotCounted[MAXPLAYERS + 1][MAXPLAYERS +1]; // Victim - Attacker, used by playerhurt and weaponfired +int g_iAccumulatedWitchDamage = 0; // Current witch health = witch health - accumulated +int g_iBoomerClient = 0; // Client of last player to be boomer (or current boomer) +int g_iBoomerKiller = 0; // Client who shot the boomer +int g_iBoomerShover = 0; // Client who shoved the boomer +int g_iLastHealth[MAXPLAYERS + 1] = {0, ...}; +bool g_bHasBoomLanded = false; +//bool g_bStatsCooldown[MAXPLAYERS + 1] = {false, ...}; // Prevent spam of stats command (potential DoS vector I think) +bool g_bHasLandedPounce[MAXPLAYERS + 1] = {false, ...}; // Used to determine if a deadstop was 'pierced' +bool g_bIsWitch[MAXENTITIES]; // Membership testing for fast witch checking +bool g_bIsPouncing[MAXPLAYERS + 1] = {false, ...}; +bool g_bShotCounted[MAXPLAYERS + 1][MAXPLAYERS +1]; // Victim - Attacker, used by playerhurt and weaponfired // Map Stats, array for each player for easy trie storage -new g_iMapStats[MAXPLAYERS + 1][STATS_MAX]; +int g_iMapStats[MAXPLAYERS + 1][STATS_MAX]; // Player temp stats -new g_iWitchDamage[MAXPLAYERS + 1]; -new g_iDamageDealt[MAXPLAYERS + 1][MAXPLAYERS + 1]; // Victim - Attacker -new g_iShotsDealt[MAXPLAYERS + 1][MAXPLAYERS + 1]; // Victim - Attacker, count # of shots (not pellets) +int g_iWitchDamage[MAXPLAYERS + 1] = {0, ...}; +int g_iDamageDealt[MAXPLAYERS + 1][MAXPLAYERS + 1]; // Victim - Attacker +int g_iShotsDealt[MAXPLAYERS + 1][MAXPLAYERS + 1]; // Victim - Attacker, count # of shots (not pellets) -public OnPluginStart() +public void OnPluginStart() { if (GetMaxEntities() > MAXENTITIES) { - LogError("Plugin needs to be recompiled with a new MAXENTITIES value of %d. Current value is %d. Witch tracking is unreliable!", - GetMaxEntities(), MAXENTITIES); + LogError("Plugin needs to be recompiled with a new MAXENTITIES value of %d. Current value is %d. Witch tracking is unreliable!", GetMaxEntities(), MAXENTITIES); } - for (new client = 1; client <= MaxClients; client++) + for (int client = 1; client <= MaxClients; client++) { if (!IsClientInGame(client)) continue; SDKHook(client, SDKHook_OnTakeDamage, PlayerHook_OnTakeDamagePre); @@ -153,43 +153,46 @@ public OnPluginStart() // Boomer tracking HookEvent("player_now_it", Event_PlayerBoomed); - g_hCvarMaxPlayerZombies = FindConVar("z_max_player_zombies"); +// g_hCvarMaxPlayerZombies = FindConVar("z_max_player_zombies"); g_hCvarSurvivorLimit = FindConVar("survivor_limit"); g_hCvarMaxPounceBonusDamage = FindConVar("z_hunter_max_pounce_bonus_damage"); g_hCvarWitchHealth = FindConVar("z_witch_health"); g_hCvarDirectorReadyDuration = FindConVar("director_ready_duration"); - HookConVarChange(g_hCvarMaxPlayerZombies, Cvar_MaxPlayerZombies); - HookConVarChange(g_hCvarSurvivorLimit, Cvar_SurvivorLimit); - HookConVarChange(g_hCvarMaxPounceBonusDamage, Cvar_MaxPounceBonusDamage); - HookConVarChange(g_hCvarWitchHealth, Cvar_WitchHealth); - HookConVarChange(g_hCvarDirectorReadyDuration, Cvar_DirectorReadyDuration); +// g_hCvarMaxPlayerZombies.AddChangeHook(Cvar_MaxPlayerZombies); + g_hCvarSurvivorLimit.AddChangeHook(Cvar_SurvivorLimit); + g_hCvarMaxPounceBonusDamage.AddChangeHook(Cvar_MaxPounceBonusDamage); + g_hCvarWitchHealth.AddChangeHook(Cvar_WitchHealth); + g_hCvarDirectorReadyDuration.AddChangeHook(Cvar_DirectorReadyDuration); - g_iMaxPlayerZombies = GetConVarInt(g_hCvarMaxPlayerZombies); - g_iSurvivorLimit = GetConVarInt(g_hCvarSurvivorLimit); - g_iWitchHealth = GetConVarInt(g_hCvarWitchHealth); - if (GetConVarInt(g_hCvarDirectorReadyDuration) > 0) g_bLogFF = true; +// g_iMaxPlayerZombies = g_hCvarMaxPlayerZombies.IntValue; + g_iSurvivorLimit = g_hCvarSurvivorLimit.IntValue; + g_iWitchHealth = g_hCvarWitchHealth.IntValue; + if (g_hCvarDirectorReadyDuration.IntValue > 0) g_bLogFF = true; CalculateMinDPDamage(GetConVarFloat(g_hCvarMaxPounceBonusDamage)); // RegConsoleCmd("sm_stats", Command_Stats, "Prints the client's stats for the current round"); } -public OnClientPutInServer(client) +public void OnClientPutInServer(int client) { - SDKHook(client, SDKHook_OnTakeDamage, PlayerHook_OnTakeDamagePre); + if(client > 0) + { + SDKHook(client, SDKHook_OnTakeDamage, PlayerHook_OnTakeDamagePre); + } } -public OnMapStart() +public void OnMapStart() { g_bHasRoundEnded = false; ClearMapStats(); } - -public Action:Timer_DelayedStatsPrint(Handle:timer) +Action Timer_DelayedStatsPrint(Handle timer) { PrintMVPAndTeamStats(); PrintConsoleStats(); + return Plugin_Stop; } /* @@ -197,20 +200,20 @@ MVP - SI: Philogl (2932 dmg[99%], 53 kills [100%]) Your SI rank: #4 (3 dmg [1%], MVP - CI: Philogl (232 common [90%]) Your CI rank: #4 (1 kills [0%]) */ -public PrintMVPAndTeamStats() +void PrintMVPAndTeamStats() { - decl survivor_clients[g_iSurvivorLimit]; - decl i; - new survivor_count; + int[] survivor_clients = new int[g_iSurvivorLimit]; + int i = 0; + int survivor_count = 0; for (i = 1; i <= MaxClients; i++) { if (!IsClientInGame(i) || !IsSurvivor(i)) continue; survivor_clients[survivor_count++] = i; } - decl sortable[survivor_count][2]; - decl client, val; - new total, totalkills, percent; + int[][] sortable = new int[survivor_count][2]; + int client = 0, val = 0; + int total = 0, totalkills = 0, percent = 0; // --------------------------- SI Damage --------------------------- for (i = 0; i < survivor_count; i++) @@ -232,7 +235,7 @@ public PrintMVPAndTeamStats() client = sortable[0][0]; val = sortable[0][1]; percent = RoundFloat((float(val) / float(total)) * 100.0); - new kills = g_iMapStats[client][SIKills]; + int kills = g_iMapStats[client][SIKills]; // This string (colors, etc) is stolen wholesale from Tabun's L4D2 MVP plugin, credit to him PrintToChatAll("\x01MVP - SI: \x03%N\x01 (\x05%d\x01 dmg [\x04%d%%\x01], \x05%d\x01 kills [\x04%d%%\x01])", client, val, percent, kills, @@ -285,17 +288,17 @@ public PrintMVPAndTeamStats() } // --------------------------- Team Stats --------------------------- - new skeets, fullskeets, teamskeets, deadstops, pounce_eats, dp_eats; - new successful_booms, shutdown_booms, vomited_survivors, proxied_survivors; - new dmg_from_si, dmg_from_ci, dmg_from_ff; + int skeets = 0, /*fullskeets = 0, teamskeets = 0, */deadstops = 0, pounce_eats = 0, dp_eats = 0; + int successful_booms = 0, shutdown_booms = 0, vomited_survivors = 0, proxied_survivors = 0; + int dmg_from_si = 0, dmg_from_ci = 0, dmg_from_ff = 0; for (i = 1; i <= MaxClients; i++) { if (!IsClientInGame(i)) continue; if (IsSurvivor(i)) { - fullskeets += g_iMapStats[i][FullSkeets]; - teamskeets += g_iMapStats[i][TeamSkeets]; +// fullskeets += g_iMapStats[i][FullSkeets]; +// teamskeets += g_iMapStats[i][TeamSkeets]; skeets += g_iMapStats[i][FullSkeets] + g_iMapStats[i][TeamSkeets]; deadstops += g_iMapStats[i][Deadstops]; pounce_eats += g_iMapStats[i][PouncesEaten]; @@ -356,7 +359,7 @@ TEAM - Damage: 173 from SI, 97 from common, 23 from FF // Spectators: Print survivor stats & infected stats // Survivors: Print survivor stats // Infected: Print infected stats -public PrintConsoleStats() +void PrintConsoleStats() { CreateTimer(0.1, Timer_PrintSurvivorStatsHeader); CreateTimer(0.2, Timer_PrintSurvivorStatsBody); @@ -366,110 +369,112 @@ public PrintConsoleStats() CreateTimer(0.6, Timer_PrintInfectedStatsFooter); } -public Action:Timer_PrintSurvivorStatsHeader(Handle:timer) +Action Timer_PrintSurvivorStatsHeader(Handle timer) { - new const maxlength = 1024; - decl String:buf[maxlength]; + const int maxlength = 1024; + char buf[maxlength]; Format(buf, maxlength, "\n|----------------------------------------------- SURVIVOR STATS -----------------------------------------------|\n"); Format(buf, maxlength, "%s| NAME | SIK | SID | CI | DS | Skeets | SA | BS | FF | DFC | Pounces Eaten |\n", buf); Format(buf, maxlength, "%s|----------------------|------|--------|------|-----|----------------|-----|-----|------|------|---------------|", buf); PrintToTeamConsole(FLAG_SPECTATOR | FLAG_SURVIVOR, buf); + return Plugin_Stop; } -public Action:Timer_PrintSurvivorStatsBody(Handle:timer) +Action Timer_PrintSurvivorStatsBody(Handle timer) { - decl i, j, val; - decl lows_highs[STATS_MAX][2]; - // Initialize lows_highs - for (i = 0; i < STATS_MAX; i++) - { - lows_highs[i][0] = 9999999; - lows_highs[i][1] = -1; - } - - // Calculate actual lows_highs values - for (i = 1; i <= MaxClients; i++) - { - if (!IsClientInGame(i) || !IsSurvivor(i)) continue; - for (j = 0; j < STATS_MAX; j++) - { - if (j == TeamSkeets) continue; - else if (j == FullSkeets) - { // Store the total skeets value in fullskeets, just for checking lows_highs - val = g_iMapStats[i][FullSkeets] + g_iMapStats[i][TeamSkeets]; - } - else - { - val = g_iMapStats[i][j]; - } - if (val < lows_highs[j][0]) lows_highs[j][0] = val; - if (val > lows_highs[j][1]) lows_highs[j][1] = val; - } - } - - new const max_name_len = 20; - new const s_len = 15; - decl String:name[MAX_NAME_LENGTH]; - decl String:sikills[s_len], String:sidamage[s_len], String:cikills[s_len], String:deadstops[s_len]; - decl String:skeets[s_len], String:skeetassists[s_len], String:boomershutdowns[s_len]; - decl String:ff[s_len], String:cidamage[s_len], String:pounceseaten[s_len]; - - for (i = 1; i <= MaxClients; i++) - { - if (!IsClientInGame(i) || !IsSurvivor(i)) continue; - GetClientName(i, name, sizeof(name)); - name[max_name_len] = 0; - val = g_iMapStats[i][SIKills]; - Format(sikills, s_len, "%s%d", GetModifierChar(val, SIKills), val); - - val = g_iMapStats[i][SIDamage]; - Format(sidamage, s_len, "%s%d", GetModifierChar(val, SIDamage), val); - - val = g_iMapStats[i][CIKills]; - Format(cikills, s_len, "%s%d", GetModifierChar(val, CIKills), val); - - val = g_iMapStats[i][Deadstops]; - Format(deadstops, s_len, "%s%d", GetModifierChar(val, Deadstops), val); - - val = g_iMapStats[i][FullSkeets] + g_iMapStats[i][TeamSkeets]; - Format(skeets, s_len, "%s%d (%dF/%dT)", GetModifierChar(val, FullSkeets), val, - g_iMapStats[i][FullSkeets], g_iMapStats[i][TeamSkeets]); - - val = g_iMapStats[i][SkeetAssists]; - Format(skeetassists, s_len, "%s%d", GetModifierChar(val, SkeetAssists), val); - - val = g_iMapStats[i][BoomerShutdowns]; - Format(boomershutdowns, s_len, "%s%d", GetModifierChar(val, BoomerShutdowns), val); - - val = g_iMapStats[i][FF]; - Format(ff, s_len, "%s%d", GetModifierCharReversed(val, FF), val); - - val = g_iMapStats[i][CIDamageTaken]; - Format(cidamage, s_len, "%s%d", GetModifierCharReversed(val, CIDamageTaken), val); - - val = g_iMapStats[i][PouncesEaten]; - Format(pounceseaten, s_len, "%s%d (%d DPs)", GetModifierCharReversed(val, PouncesEaten), val, g_iMapStats[i][DPsEaten]); - - PrintToTeamConsole(FLAG_SPECTATOR | FLAG_SURVIVOR, - "| %20s | %4s | %6s | %4s | %3s | %14s | %3s | %3s | %4s | %4s | %13s |", - name, - sikills, - sidamage, - cikills, - deadstops, - skeets, - skeetassists, - boomershutdowns, - ff, - cidamage, - pounceseaten); - } + int i = 0, j = 0, val = 0; + int lows_highs[STATS_MAX][2]; + // Initialize lows_highs + for (i = 0; i < view_as(STATS_MAX); i++) + { + lows_highs[i][0] = 9999999; + lows_highs[i][1] = -1; + } + + // Calculate actual lows_highs values + for (i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) || !IsSurvivor(i)) continue; + for (j = 0; j < view_as(STATS_MAX); j++) + { + if (j == view_as(TeamSkeets)) continue; + else if (j == view_as(FullSkeets)) + { // Store the total skeets value in fullskeets, just for checking lows_highs + val = g_iMapStats[i][FullSkeets] + g_iMapStats[i][TeamSkeets]; + } + else + { + val = g_iMapStats[i][j]; + } + if (val < lows_highs[j][0]) lows_highs[j][0] = val; + if (val > lows_highs[j][1]) lows_highs[j][1] = val; + } + } + + const int max_name_len = 20; + const int s_len = 15; + char name[MAX_NAME_LENGTH]; + char sikills[s_len], sidamage[s_len], cikills[s_len], deadstops[s_len]; + char skeets[s_len], skeetassists[s_len], boomershutdowns[s_len]; + char ff[s_len], cidamage[s_len], pounceseaten[s_len]; + + for (i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) || !IsSurvivor(i)) continue; + GetClientName(i, name, sizeof(name)); + name[max_name_len] = 0; + val = g_iMapStats[i][SIKills]; + Format(sikills, s_len, "%s%d", GetModifierChar(val, SIKills), val); + + val = g_iMapStats[i][SIDamage]; + Format(sidamage, s_len, "%s%d", GetModifierChar(val, SIDamage), val); + + val = g_iMapStats[i][CIKills]; + Format(cikills, s_len, "%s%d", GetModifierChar(val, CIKills), val); + + val = g_iMapStats[i][Deadstops]; + Format(deadstops, s_len, "%s%d", GetModifierChar(val, Deadstops), val); + + val = g_iMapStats[i][FullSkeets] + g_iMapStats[i][TeamSkeets]; + Format(skeets, s_len, "%s%d (%dF/%dT)", GetModifierChar(val, FullSkeets), val, + g_iMapStats[i][FullSkeets], g_iMapStats[i][TeamSkeets]); + + val = g_iMapStats[i][SkeetAssists]; + Format(skeetassists, s_len, "%s%d", GetModifierChar(val, SkeetAssists), val); + + val = g_iMapStats[i][BoomerShutdowns]; + Format(boomershutdowns, s_len, "%s%d", GetModifierChar(val, BoomerShutdowns), val); + + val = g_iMapStats[i][FF]; + Format(ff, s_len, "%s%d", GetModifierCharReversed(val, FF), val); + + val = g_iMapStats[i][CIDamageTaken]; + Format(cidamage, s_len, "%s%d", GetModifierCharReversed(val, CIDamageTaken), val); + + val = g_iMapStats[i][PouncesEaten]; + Format(pounceseaten, s_len, "%s%d (%d DPs)", GetModifierCharReversed(val, PouncesEaten), val, g_iMapStats[i][DPsEaten]); + + PrintToTeamConsole(FLAG_SPECTATOR | FLAG_SURVIVOR, + "| %20s | %4s | %6s | %4s | %3s | %14s | %3s | %3s | %4s | %4s | %13s |", + name, + sikills, + sidamage, + cikills, + deadstops, + skeets, + skeetassists, + boomershutdowns, + ff, + cidamage, + pounceseaten); + } + return Plugin_Stop; } -public Action:Timer_PrintSurvivorStatsFooter(Handle:timer) +Action Timer_PrintSurvivorStatsFooter(Handle timer) { - new const maxlength = 1024; - decl String:buf[maxlength]; + const int maxlength = 1024; + char buf[maxlength]; Format(buf, maxlength, "\nLegend:\n"); Format(buf, maxlength, "%s %s = Best %s = Worst\n", buf, HIGHCHAR, LOWCHAR); Format(buf, maxlength, "%s SIK - Special Infected killed\n", buf); @@ -482,109 +487,112 @@ public Action:Timer_PrintSurvivorStatsFooter(Handle:timer) Format(buf, maxlength, "%s FF - Friendly Fire\n", buf); Format(buf, maxlength, "%s DFC - Damage from common infected\n", buf); PrintToTeamConsole(FLAG_SPECTATOR | FLAG_SURVIVOR, buf); + return Plugin_Stop; } -public Action:Timer_PrintInfectedStatsHeader(Handle:timer) +Action Timer_PrintInfectedStatsHeader(Handle timer) { - new const maxlength = 1024; - decl String:buf[maxlength]; + const int maxlength = 1024; + char buf[maxlength]; Format(buf, maxlength, "\n|----------------------------------- INFECTED STATS -----------------------------------|\n"); Format(buf, maxlength, "%s| NAME | Dmg | Pounce Success | Boomer Success |\n", buf); Format(buf, maxlength, "%s|----------------------|-------|---------------------------|---------------------------|", buf); -//| Name | *1291 | *100% (10L (2DP)/10S/10D) | *100% (10A/13F/10V/10P) | + //| Name | *1291 | *100% (10L (2DP)/10S/10D) | *100% (10A/13F/10V/10P) | PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, buf); + return Plugin_Stop; } -public Action:Timer_PrintInfectedStatsBody(Handle:timer) +Action Timer_PrintInfectedStatsBody(Handle timer) { - new dmg_low = 99999999; - new dmg_high = -1; - new pounces_low = 99999999; - new pounces_high = -1; - new booms_low = 99999999; - new booms_high = -1; - - decl val, i; - new bool:has_printed; - - for (i = 1; i <= MaxClients; i++) - { - if (!IsClientInGame(i) || !IsInfected(i) || IsFakeClient(i)) continue; - val = g_iMapStats[i][DamageDealtAsSI]; - if (val < dmg_low) dmg_low = val; - if (val > dmg_high) dmg_high = val; - - val = g_iMapStats[i][PouncesLanded]; - if (val < pounces_low) pounces_low = val; - if (val > pounces_high) pounces_high = val; - - val = g_iMapStats[i][BoomSuccesses]; - if (val < booms_low) booms_low = val; - if (val > booms_high) booms_high = val; - } - - new const max_name_len = 20; - new const s_len = 30; - decl String:name[MAX_NAME_LENGTH]; - decl String:dmg[s_len], String:pounce_success[s_len], String:boomer_success[s_len]; - - for (i = 1; i <= MaxClients; i++) - { - // No infected bot stats... - if (!IsClientInGame(i) || !IsInfected(i) || IsFakeClient(i)) continue; - GetClientName(i, name, sizeof(name)); - name[max_name_len] = 0; - - val = g_iMapStats[i][DamageDealtAsSI]; - Format(dmg, s_len, "%s%d", - val == dmg_high ? HIGHCHAR:val == dmg_low ? LOWCHAR:"", - val); - - val = g_iMapStats[i][PouncesLanded]; - Format(pounce_success, s_len, "%s%d/%d (%d DPs/%d S/%d DS)", - val == pounces_high ? HIGHCHAR:val == pounces_low ? LOWCHAR:"", - val, - val + g_iMapStats[i][Skeeted] + g_iMapStats[i][Deadstopped], - g_iMapStats[i][DPsLanded], - g_iMapStats[i][Skeeted], - g_iMapStats[i][Deadstopped]); - - val = g_iMapStats[i][BoomSuccesses]; - Format(boomer_success, s_len, "%s%d/%d (%d Vomit/%d Proxy)", - val == booms_high ? HIGHCHAR:val == booms_low ? LOWCHAR:"", - val, - g_iMapStats[i][BoomAttempts], - g_iMapStats[i][BoomedSurvivorsByVomit], - g_iMapStats[i][BoomedSurvivorsByProxy]); - - PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, - "| %20s | %5s | %25s | %25s |", - name, - dmg, - pounce_success, - boomer_success); - - has_printed = true; - } - - if (!has_printed) - { - PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, "No infected found."); - } + int dmg_low = 99999999; + int dmg_high = -1; + int pounces_low = 99999999; + int pounces_high = -1; + int booms_low = 99999999; + int booms_high = -1; + + int val = 0, i = 0; + bool has_printed = false; + + for (i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i) || !IsInfected(i) || IsFakeClient(i)) continue; + val = g_iMapStats[i][DamageDealtAsSI]; + if (val < dmg_low) dmg_low = val; + if (val > dmg_high) dmg_high = val; + + val = g_iMapStats[i][PouncesLanded]; + if (val < pounces_low) pounces_low = val; + if (val > pounces_high) pounces_high = val; + + val = g_iMapStats[i][BoomSuccesses]; + if (val < booms_low) booms_low = val; + if (val > booms_high) booms_high = val; + } + + const int max_name_len = 20; + const int s_len = 30; + char name[MAX_NAME_LENGTH], dmg[s_len], pounce_success[s_len], boomer_success[s_len]; + + for (i = 1; i <= MaxClients; i++) + { + // No infected bot stats... + if (!IsClientInGame(i) || !IsInfected(i) || IsFakeClient(i)) continue; + GetClientName(i, name, sizeof(name)); + name[max_name_len] = 0; + + val = g_iMapStats[i][DamageDealtAsSI]; + Format(dmg, s_len, "%s%d", + val == dmg_high ? HIGHCHAR:val == dmg_low ? LOWCHAR:"", + val); + + val = g_iMapStats[i][PouncesLanded]; + Format(pounce_success, s_len, "%s%d/%d (%d DPs/%d S/%d DS)", + val == pounces_high ? HIGHCHAR:val == pounces_low ? LOWCHAR:"", + val, + val + g_iMapStats[i][Skeeted] + g_iMapStats[i][Deadstopped], + g_iMapStats[i][DPsLanded], + g_iMapStats[i][Skeeted], + g_iMapStats[i][Deadstopped]); + + val = g_iMapStats[i][BoomSuccesses]; + Format(boomer_success, s_len, "%s%d/%d (%d Vomit/%d Proxy)", + val == booms_high ? HIGHCHAR:val == booms_low ? LOWCHAR:"", + val, + g_iMapStats[i][BoomAttempts], + g_iMapStats[i][BoomedSurvivorsByVomit], + g_iMapStats[i][BoomedSurvivorsByProxy]); + + PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, + "| %20s | %5s | %25s | %25s |", + name, + dmg, + pounce_success, + boomer_success); + + has_printed = true; + } + + if (!has_printed) + { + PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, "No infected found."); + } + return Plugin_Stop; } -public Action:Timer_PrintInfectedStatsFooter(Handle:timer) +Action Timer_PrintInfectedStatsFooter(Handle timer) { - new const maxlength = 1024; - decl String:buf[maxlength]; + const int maxlength = 1024; + char buf[maxlength]; Format(buf, maxlength, "\nLegend:\n"); Format(buf, maxlength, "%s Dmg - Damage dealt to non-incapped survivors\n", buf); Format(buf, maxlength, "%s Pounce Success - DP = Damage Pounce, S = Skeeted, DS = Deadstop\n", buf); PrintToTeamConsole(FLAG_SPECTATOR | FLAG_INFECTED, buf); + return Plugin_Stop; } /* -public Action:Command_Stats(client, args) +Action Command_Stats(int client, int args) { if (g_bStatsCooldown[client]) return Plugin_Handled; g_bStatsCooldown[client] = true; @@ -607,51 +615,50 @@ public Action:Command_Stats(client, args) CreateTimer(1.0, Timer_StatsCooldown, client); return Plugin_Handled; } -*/ -public Action:Timer_StatsCooldown(Handle:timer, any:client) +Action Timer_StatsCooldown(Handle timer, any client) { g_bStatsCooldown[client] = false; return Plugin_Stop; -} +}*/ -public Cvar_MaxPlayerZombies(Handle:convar, const String:oldValue[], const String:newValue[]) +/*void Cvar_MaxPlayerZombies(ConVar convar, const char[] oldValue, const char[] newValue) { g_iMaxPlayerZombies = StringToInt(newValue); -} +}*/ -public Cvar_SurvivorLimit(Handle:convar, const String:oldValue[], const String:newValue[]) +void Cvar_SurvivorLimit(ConVar convar, const char[] oldValue, const char[] newValue) { g_iSurvivorLimit = StringToInt(newValue); } -public Cvar_MaxPounceBonusDamage(Handle:convar, const String:oldValue[], const String:newValue[]) +void Cvar_MaxPounceBonusDamage(ConVar convar, const char[] oldValue, const char[] newValue) { CalculateMinDPDamage(StringToFloat(newValue)); } -CalculateMinDPDamage(Float:bonus_pounce_damage) +void CalculateMinDPDamage(float bonus_pounce_damage) { // Max pounce damage = bonus pounce damage + 1 g_iMinDPDamage = RoundToFloor((bonus_pounce_damage + 1.0) * MIN_DP_RATIO); } -public Cvar_WitchHealth(Handle:convar, const String:oldValue[], const String:newValue[]) +void Cvar_WitchHealth(ConVar convar, const char[] oldValue, const char[] newValue) { g_iWitchHealth = StringToInt(newValue); } -public Cvar_DirectorReadyDuration(Handle:convar, const String:oldValue[], const String:newValue[]) +void Cvar_DirectorReadyDuration(ConVar convar, const char[] oldValue, const char[] newValue) { g_bLogFF = StringToInt(newValue) > 0 ? true:false; } -public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) +void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) { g_bHasRoundEnded = false; } -public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) +void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) { // In case witch is avoided g_iAccumulatedWitchDamage = 0; @@ -659,7 +666,7 @@ public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) if (g_bHasRoundEnded) return; g_bHasRoundEnded = true; CreateTimer(2.0, Timer_DelayedStatsPrint); - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { // if (IsClientInGame(i) && IsSurvivor(i)) // { @@ -671,7 +678,7 @@ public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) } } -public Action:PlayerHook_OnTakeDamagePre(victim, &attacker, &inflictor, &Float:damage, &damagetype) +Action PlayerHook_OnTakeDamagePre(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) { // Non incapped survivor victim if (!victim || @@ -679,26 +686,27 @@ public Action:PlayerHook_OnTakeDamagePre(victim, &attacker, &inflictor, &Float:d !IsClientInGame(victim) || !IsSurvivor(victim) || IsIncapped(victim) - ) return; + ) return Plugin_Continue; g_iLastHealth[victim] = GetClientHealth(victim); + return Plugin_Continue; } -public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerHurt(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - new victim = GetClientOfUserId(GetEventInt(event, "userid")); + int victim = GetClientOfUserId(event.GetInt("userid")); if (victim == 0 || !IsClientInGame(victim) ) return; - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (!attacker) { // Damage from common - if (!IsCommonInfected(GetEventInt(event, "attackerentid")) || IsIncapped(victim)) return; - new damage = g_iLastHealth[victim] - GetEventInt(event, "health"); + if (!IsCommonInfected(event.GetInt("attackerentid")) || IsIncapped(victim)) return; + int damage = g_iLastHealth[victim] - event.GetInt("health"); if (damage < 0 || damage > 2) { PrintToChatAll("[DEBUG] Invalid common damage value of %d detected for %N. Tell Griffin what happened!", @@ -719,7 +727,7 @@ public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) } else if (!IsClientInGame(attacker)) return; - new damage = GetEventInt(event, "dmg_health"); + int damage = event.GetInt("dmg_health"); if (IsSurvivor(attacker)) { @@ -731,8 +739,8 @@ public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) // Hot survivor on infected action, baby else if (IsInfected(victim)) { - new zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); - if (zombieclass == ZC_TANK) return; // We don't care about tank damage + int zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); + if (zombieclass == view_as(ZC_TANK)) return; // We don't care about tank damage if (!g_bShotCounted[victim][attacker]) { @@ -740,7 +748,7 @@ public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) g_bShotCounted[victim][attacker] = true; } - new remaining_health = GetEventInt(event, "health"); + int remaining_health = event.GetInt("health"); // Let player_death handle remainder damage (avoid overkill damage) if (remaining_health <= 0) return; @@ -751,9 +759,9 @@ public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) g_iMapStats[attacker][SIDamage] += damage; g_iDamageDealt[victim][attacker] += damage; - if (zombieclass == ZC_BOOMER) + if (zombieclass == view_as(ZC_BOOMER)) { /* Boomer Stuff Here */ } - else if (zombieclass == ZC_HUNTER) + else if (zombieclass == view_as(ZC_HUNTER)) { /* Hunter Stuff Here */ } } } @@ -764,27 +772,27 @@ public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) } } -public Event_PlayerShoved(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerShoved(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - new victim = GetClientOfUserId(GetEventInt(event, "userid")); + int victim = GetClientOfUserId(event.GetInt("userid")); if (victim == 0 || !IsClientInGame(victim) || !IsInfected(victim) ) return; - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (attacker == 0 || // World dmg? !IsClientInGame(attacker) || // Unsure !IsSurvivor(attacker) ) return; - new zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); - if (zombieclass == ZC_BOOMER) + int zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); + if (zombieclass == view_as(ZC_BOOMER)) { - if (g_hBoomerShoveTimer != INVALID_HANDLE) + if (g_hBoomerShoveTimer != null) { - KillTimer(g_hBoomerShoveTimer); + delete g_hBoomerShoveTimer; if (!g_iBoomerShover || !IsClientInGame(g_iBoomerShover)) g_iBoomerShover = attacker; } else @@ -793,7 +801,7 @@ public Event_PlayerShoved(Handle:event, const String:name[], bool:dontBroadcast) } g_hBoomerShoveTimer = CreateTimer(BOOMER_STAGGER_TIME, Timer_BoomerShove); } - else if (zombieclass == ZC_HUNTER && IsPouncing(victim)) + else if (zombieclass == view_as(ZC_HUNTER) && IsPouncing(victim)) { // DEADSTOP // Groundtouch timer will do this for us, but @@ -801,20 +809,20 @@ public Event_PlayerShoved(Handle:event, const String:name[], bool:dontBroadcast) g_bIsPouncing[victim] = false; // Delayed check to see if the pounce actually landed due to bug where player_shoved gets fired but pounce lands anyways g_bHasLandedPounce[attacker] = false; - new Handle:pack; + DataPack pack; CreateDataTimer(0.2, Timer_DeadstopCheck, pack); - WritePackCell(pack, attacker); - WritePackCell(pack, victim); + pack.WriteCell(attacker); + pack.WriteCell(victim); } } -public Action:Timer_DeadstopCheck(Handle:timer, Handle:pack) +Action Timer_DeadstopCheck(Handle timer, DataPack hPack) { - ResetPack(pack); - new attacker = ReadPackCell(pack); + hPack.Reset(); + int attacker = hPack.ReadCell(); if (!g_bHasLandedPounce[attacker]) { - new victim = ReadPackCell(pack); + int victim = hPack.ReadCell(); // TODO: Add tracking for number of times a person was deadstopped (along with other pounce stats) g_iMapStats[attacker][Deadstops]++; if (IsClientInGame(victim) && IsClientInGame(attacker)) @@ -827,26 +835,28 @@ public Action:Timer_DeadstopCheck(Handle:timer, Handle:pack) } } } + return Plugin_Stop; } -public Action:Timer_BoomerShove(Handle:timer) +Action Timer_BoomerShove(Handle timer) { // PrintToChatAll("[DEBUG] BoomerShove timer expired, credit for boomer shutdown is available to anyone at this point!"); - g_hBoomerShoveTimer = INVALID_HANDLE; + g_hBoomerShoveTimer = null; g_iBoomerShover = 0; + return Plugin_Stop; } -public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) { - new client = GetClientOfUserId(GetEventInt(event, "userid")); + int client = GetClientOfUserId(event.GetInt("userid")); if (client == 0 || !IsClientInGame(client)) return; if (IsInfected(client)) { - new zombieclass = GetEntProp(client, Prop_Send, "m_zombieClass"); - if (zombieclass == ZC_TANK) return; + int zombieclass = GetEntProp(client, Prop_Send, "m_zombieClass"); + if (zombieclass == view_as(ZC_TANK)) return; - if (zombieclass == ZC_BOOMER) + if (zombieclass == view_as(ZC_BOOMER)) { // Fresh boomer spawning (if g_iBoomerClient is set and an AI boomer spawns, it's a boomer going AI) if (!IsFakeClient(client) || !g_iBoomerClient) @@ -860,10 +870,9 @@ public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { g_iMapStats[client][BoomAttempts]++; } - if (g_hBoomerShoveTimer != INVALID_HANDLE) + if (g_hBoomerShoveTimer != null) { - KillTimer(g_hBoomerShoveTimer); - g_hBoomerShoveTimer = INVALID_HANDLE; + delete g_hBoomerShoveTimer; } } @@ -871,29 +880,29 @@ public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) } } -public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - new victim = GetClientOfUserId(GetEventInt(event, "userid")); + int victim = GetClientOfUserId(event.GetInt("userid")); if (victim == 0 || !IsClientInGame(victim) ) return; - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (attacker == 0) { // Check for a witch-related death (black & white survivor failing or no-incap configs e.g. 1v1) if (IsInfected(victim)) ClearDamage(victim); - if (!IsWitch(GetEventInt(event, "attackerentid")) || + if (!IsWitch(event.GetInt("attackerentid")) || !g_bShouldAnnounceWitchDamage // Prevent double print on incap -> death by witch ) return; - new health = g_iWitchHealth - g_iAccumulatedWitchDamage; + int health = g_iWitchHealth - g_iAccumulatedWitchDamage; if (health < 0) health = 0; PrintToChatAll("[SM] Witch had %d health remaining.", health); - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { if (g_iWitchDamage[i] > 0 && IsClientInGame(i)) { @@ -913,14 +922,14 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) if (IsSurvivor(attacker) && IsInfected(victim)) { - new zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); - if (zombieclass == ZC_TANK) return; // We don't care about tank damage + int zombieclass = GetEntProp(victim, Prop_Send, "m_zombieClass"); + if (zombieclass == view_as(ZC_TANK)) return; // We don't care about tank damage g_iMapStats[attacker][SIKills]++; - new lasthealth = g_iLastHealth[victim]; + int lasthealth = g_iLastHealth[victim]; g_iMapStats[attacker][SIDamage] += lasthealth; g_iDamageDealt[victim][attacker] += lasthealth; - if (zombieclass == ZC_BOOMER) + if (zombieclass == view_as(ZC_BOOMER)) { // Only happens on mid map plugin load when a boomer is up if (!g_iBoomerClient) g_iBoomerClient = victim; @@ -928,17 +937,17 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) CreateTimer(0.2, Timer_BoomerKilledCheck, victim); g_iBoomerKiller = attacker; } - else if (zombieclass == ZC_HUNTER && IsPouncing(victim)) + else if (zombieclass == view_as(ZC_HUNTER) && IsPouncing(victim)) { // Skeet! if (!IsFakeClient(victim)) { g_iMapStats[victim][Skeeted]++; } - decl assisters[g_iSurvivorLimit][2]; - new assister_count, i; - new damage = g_iDamageDealt[victim][attacker]; - new shots = g_iShotsDealt[victim][attacker]; - new String:plural[1] = "s"; + int[][] assisters = new int[g_iSurvivorLimit][2]; + int assister_count = 0, i = 0; + int damage = g_iDamageDealt[victim][attacker]; + int shots = g_iShotsDealt[victim][attacker]; + char plural[1]; if (shots == 1) plural[0] = 0; for (i = 1; i <= MaxClients; i++) { @@ -955,9 +964,9 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) { // Sort by damage, descending SortCustom2D(assisters, assister_count, ClientValue2DSortDesc); - decl String:assister_string[128]; - decl String:buf[MAX_NAME_LENGTH + 8]; - new assist_shots = g_iShotsDealt[victim][assisters[0][0]]; + char assister_string[128]; + char buf[MAX_NAME_LENGTH + 8]; + int assist_shots = g_iShotsDealt[victim][assisters[0][0]]; // Construct assisters string Format(assister_string, sizeof(assister_string), "%N (%d/%d shot%s)", assisters[0][0], @@ -1003,10 +1012,10 @@ public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) if (IsInfected(victim)) ClearDamage(victim); } -public Action:Timer_BoomerKilledCheck(Handle:timer, any:client) +Action Timer_BoomerKilledCheck(Handle timer, any client) { // if g_iBoomerClient != client, boomer went AI, maybe do something with that info in the future? - if (g_bHasBoomLanded) return; + if (g_bHasBoomLanded) return Plugin_Stop; // In the following code even if it was an AI boomer that was shutdown, we're going to consider the AI boomer // the responsibility of the person who spawned it, aka g_iBoomerClient @@ -1046,13 +1055,14 @@ public Action:Timer_BoomerKilledCheck(Handle:timer, any:client) } g_iBoomerClient = 0; + return Plugin_Stop; } -public Event_InfectedDeath(Handle:event, const String:name[], bool:dontBroadcast) +void Event_InfectedDeath(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; // NOTE: Has some interesting stats like headshots, if it was a minigun kill or from explosion (might use in future) - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (attacker == 0 || // Killed by world? !IsClientInGame(attacker) || @@ -1062,21 +1072,20 @@ public Event_InfectedDeath(Handle:event, const String:name[], bool:dontBroadcast g_iMapStats[attacker][CIKills]++; } -public Event_WeaponFire(Handle:event, const String:name[], bool:dontBroadcast) +void Event_WeaponFire(Event event, const char[] name, bool dontBroadcast) { - new client = GetClientOfUserId(GetEventInt(event, "userid")); - for (new i = 1; i <= MaxClients; i++) + int client = GetClientOfUserId(event.GetInt("userid")); + for (int i = 1; i <= MaxClients; i++) { // [Victim][Attacker] g_bShotCounted[i][client] = false; } } -public Event_PlayerIncapacitated(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerIncapacitated(Event event, const char[] name, bool dontBroadcast) { - new victim = GetClientOfUserId(GetEventInt(event, "userid")); - - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int victim = GetClientOfUserId(event.GetInt("userid")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (attacker && IsClientInGame(attacker) && IsInfected(attacker)) { g_iMapStats[victim][SIDamageTaken] += g_iLastHealth[victim]; @@ -1084,15 +1093,15 @@ public Event_PlayerIncapacitated(Handle:event, const String:name[], bool:dontBro return; } - if (!IsWitch(GetEventInt(event, "attackerentid")) || + if (!IsWitch(event.GetInt("attackerentid")) || !g_bShouldAnnounceWitchDamage // Prevent double print on witch incapping 2 players (rare) ) return; - new health = g_iWitchHealth - g_iAccumulatedWitchDamage; + int health = g_iWitchHealth - g_iAccumulatedWitchDamage; if (health < 0) health = 0; PrintToChatAll("[SM] Witch had %d health remaining.", health); - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { if (g_iWitchDamage[i] > 0 && IsClientInGame(i) && IsSurvivor(i)) { @@ -1103,28 +1112,28 @@ public Event_PlayerIncapacitated(Handle:event, const String:name[], bool:dontBro g_bShouldAnnounceWitchDamage = false; } -public Event_InfectedHurt(Handle:event, const String:name[], bool:dontBroadcast) +void Event_InfectedHurt(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + int attacker = GetClientOfUserId(event.GetInt("attacker")); if (attacker == 0 || // Killed by world? - !IsWitch(GetEventInt(event, "entityid")) || // Tracking witch damage only + !IsWitch(event.GetInt("entityid")) || // Tracking witch damage only !IsClientInGame(attacker) || !IsSurvivor(attacker) // Claws ) return; - new damage = GetEventInt(event, "amount"); + int damage = event.GetInt("amount"); g_iWitchDamage[attacker] += damage; g_iAccumulatedWitchDamage += damage; } -public Event_WitchKilled(Handle:event, const String:name[], bool:dontBroadcast) +void Event_WitchKilled(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - g_bIsWitch[GetEventInt(event, "witchid")] = false; + g_bIsWitch[event.GetInt("witchid")] = false; - new killer = GetClientOfUserId(GetEventInt(event, "userid")); + int killer = GetClientOfUserId(event.GetInt("userid")); if (killer == 0 || // Killed by world? !IsClientInGame(killer) @@ -1135,9 +1144,9 @@ public Event_WitchKilled(Handle:event, const String:name[], bool:dontBroadcast) // Not a crown, show all the survivors how they helped // TODO: will show someone how much damage they did on an unassisted drawcrown, fix? do we care? - if (!GetEventBool(event, "oneshot") && g_bShouldAnnounceWitchDamage) + if (!event.GetBool("oneshot") && g_bShouldAnnounceWitchDamage) { - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { if (g_iWitchDamage[i] > 0 && IsClientInGame(i) && IsSurvivor(i)) { @@ -1147,26 +1156,26 @@ public Event_WitchKilled(Handle:event, const String:name[], bool:dontBroadcast) } } - for (new i = 1; i <= MaxClients; i++) { g_iWitchDamage[i] = 0; } + for (int i = 1; i <= MaxClients; i++) { g_iWitchDamage[i] = 0; } g_iAccumulatedWitchDamage = 0; g_bShouldAnnounceWitchDamage = true; } -public Event_WitchSpawn(Handle:event, const String:name[], bool:dontBroadcast) +void Event_WitchSpawn(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - g_bIsWitch[GetEventInt(event, "witchid")] = true; + g_bIsWitch[event.GetInt("witchid")] = true; g_bShouldAnnounceWitchDamage = true; } // Pounce tracking, from skeet announce -public Event_AbilityUse(Handle:event, const String:name[], bool:dontBroadcast) +void Event_AbilityUse(Event event, const char[] name, bool dontBroadcast) { if (g_bHasRoundEnded) return; - new client = GetClientOfUserId(GetEventInt(event, "userid")); - decl String:ability_name[64]; + int client = GetClientOfUserId(event.GetInt("userid")); + char ability_name[64]; - GetEventString(event, "ability", ability_name, sizeof(ability_name)); + event.GetString("ability", ability_name, sizeof(ability_name)); if (IsClientInGame(client) && strcmp(ability_name, "ability_lunge", false) == 0) { g_bIsPouncing[client] = true; @@ -1174,19 +1183,21 @@ public Event_AbilityUse(Handle:event, const String:name[], bool:dontBroadcast) } } -public Action:Timer_GroundedCheck(Handle:timer, any:client) +Action Timer_GroundedCheck(Handle timer, any client) { if (!IsClientInGame(client) || IsGrounded(client)) { g_bIsPouncing[client] = false; - KillTimer(timer); + timer = null; + return Plugin_Stop; } + return Plugin_Continue; } -public Event_LungePounce(Handle:event, const String:name[], bool:dontBroadcast) +void Event_LungePounce(Event event, const char[] name, bool dontBroadcast) { - new attacker = GetClientOfUserId(GetEventInt(event, "userid")); - new victim = GetClientOfUserId(GetEventInt(event, "victim")); + int attacker = GetClientOfUserId(event.GetInt("userid")); + int victim = GetClientOfUserId(event.GetInt("victim")); g_bIsPouncing[attacker] = false; g_bHasLandedPounce[attacker] = true; @@ -1195,19 +1206,19 @@ public Event_LungePounce(Handle:event, const String:name[], bool:dontBroadcast) g_iMapStats[attacker][PouncesLanded]++; g_iMapStats[victim][PouncesEaten]++; - if (GetEventInt(event, "damage") >= g_iMinDPDamage) + if (event.GetInt("damage") >= g_iMinDPDamage) { g_iMapStats[attacker][DPsLanded]++; g_iMapStats[victim][DPsEaten]++; } } -public Event_PlayerBoomed(Handle:event, const String:name[], bool:dontBroadcast) +void Event_PlayerBoomed(Event event, const char[] name, bool dontBroadcast) { // This will only occur if the plugin is loaded mid map (and a boomer is already spawned) if (!g_iBoomerClient) { - g_iBoomerClient = GetClientOfUserId(GetEventInt(event, "attacker")); + g_iBoomerClient = GetClientOfUserId(event.GetInt("attacker")); } if (!g_bHasBoomLanded) @@ -1220,7 +1231,7 @@ public Event_PlayerBoomed(Handle:event, const String:name[], bool:dontBroadcast) // if (!IsClientInGame(g_iBoomerClient) || IsFakeClient(g_iBoomerClient)) return; // We credit the person who spawned the boomer with booms even if it went AI - if (GetEventBool(event, "exploded")) + if (event.GetBool("exploded")) { // possible TODO: g_iBoomerKiller's fault, use this for something? g_iMapStats[g_iBoomerClient][BoomedSurvivorsByProxy]++; @@ -1231,11 +1242,11 @@ public Event_PlayerBoomed(Handle:event, const String:name[], bool:dontBroadcast) } } -ClearMapStats() +stock void ClearMapStats() { - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { - for (new j = 0; j < STATS_MAX; j++) g_iMapStats[i][j] = 0; + for (int j = 0; j < view_as(STATS_MAX); j++) g_iMapStats[i][j] = 0; g_iWitchDamage[i] = 0; ClearDamage(i); } @@ -1243,42 +1254,42 @@ ClearMapStats() ResetWitchTracking(); } -ClearPlayerStatsAndState(client) +stock void ClearPlayerStatsAndState(int client) { - for (new i = 0; i < STATS_MAX; i++) g_iMapStats[client][i] = 0; + for (int i = 0; i < view_as(STATS_MAX); i++) g_iMapStats[client][i] = 0; g_iWitchDamage[client] = 0; ClearDamage(client); } -ResetWitchTracking() +stock void ResetWitchTracking() { - for (new i = MaxClients + 1; i < MAXENTITIES; i++) g_bIsWitch[i] = false; + for (int i = MaxClients + 1; i < MAXENTITIES; i++) g_bIsWitch[i] = false; } // Clear g_iDamageDealt, g_iShotsDealt, and g_iLastHealth for given client -ClearDamage(client) +stock void ClearDamage(int client) { g_iLastHealth[client] = 0; - for (new i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { g_iDamageDealt[client][i] = 0; g_iShotsDealt[client][i] = 0; } } -bool:IsCommonInfected(entity) +stock bool IsCommonInfected(int entity) { - if(entity && IsValidEntity(entity) && IsValidEdict(entity)) + if(entity > MaxClients && entity <= GetMaxEntities() && IsValidEntity(entity) && IsValidEdict(entity)) { - decl String:classname[32]; + char classname[32]; GetEdictClassname(entity, classname, sizeof(classname)); return StrEqual(classname, "infected"); } return false; -} +} // Takes 2D arrays [index] = {client, value} -public ClientValue2DSortDesc(x[], y[], const array[][], Handle:data) +stock int ClientValue2DSortDesc(int[] x, int[] y, const int[][] array, Handle data) { if (x[1] > y[1]) return -1; else if (x[1] < y[1]) return 1; @@ -1286,16 +1297,15 @@ public ClientValue2DSortDesc(x[], y[], const array[][], Handle:data) } // Jacked from skeet announce -bool:IsGrounded(client) +stock bool IsGrounded(int client) { return (GetEntProp(client, Prop_Data, "m_fFlags") & FL_ONGROUND) > 0; } -PrintToTeamConsole(teamflag, const String:format[], any:...) +stock void PrintToTeamConsole(int teamflag, const char[] format, any ...) { - decl String:buffer[1024]; - - for(new i = 1;i <= MaxClients;i++) + char buffer[1024]; + for(int i = 1;i <= MaxClients;i++) { if(IsClientInGame(i) && (!teamflag || teamflag & (1 << GetClientTeam(i)))) { @@ -1303,4 +1313,4 @@ PrintToTeamConsole(teamflag, const String:format[], any:...) PrintToConsole(i, buffer); } } -} \ No newline at end of file +}