Don't like ads? PRO users don't see any ads ;-)
Guest

StatsX edited

By: good95 on May 8th, 2012  |  syntax: PAWN  |  size: 50.65 KB  |  hits: 33  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /* AMX Mod X
  2. *   StatsX Plugin
  3. *
  4. * by the AMX Mod X Development Team
  5. *  originally developed by OLO
  6. *
  7. * This file is part of AMX Mod X.
  8. *
  9. *
  10. *  This program is free software; you can redistribute it and/or modify it
  11. *  under the terms of the GNU General Public License as published by the
  12. *  Free Software Foundation; either version 2 of the License, or (at
  13. *  your option) any later version.
  14. *
  15. *  This program is distributed in the hope that it will be useful, but
  16. *  WITHOUT ANY WARRANTY; without even the implied warranty of
  17. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. *  General Public License for more details.
  19. *
  20. *  You should have received a copy of the GNU General Public License
  21. *  along with this program; if not, write to the Free Software Foundation,
  22. *  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. *  In addition, as a special exception, the author gives permission to
  25. *  link the code of this program with the Half-Life Game Engine ("HL
  26. *  Engine") and Modified Game Libraries ("MODs") developed by Valve,
  27. *  L.L.C ("Valve"). You must obey the GNU General Public License in all
  28. *  respects for all of the code used other than the HL Engine and MODs
  29. *  from Valve. If you modify this file, you may extend this exception
  30. *  to your version of the file, but you are not obligated to do so. If
  31. *  you do not wish to do so, delete this exception statement from your
  32. *  version.
  33. */
  34.  
  35. //--------------------------------
  36. #include <amxmodx>
  37. #include <amxmisc>
  38. #include <csx>
  39. //--------------------------------
  40.  
  41. // Uncomment to activate log debug messages.
  42. //#define STATSX_DEBUG
  43.  
  44. // HUD statistics duration in seconds (minimum 1.0 seconds).
  45. #define HUD_DURATION_CVAR   "amx_statsx_duration"
  46. #define HUD_DURATION        "12.0"
  47.  
  48. // HUD statistics stop relative freeze end in seconds.
  49. // To stop before freeze end use a negative value.
  50. #define HUD_FREEZE_LIMIT_CVAR   "amx_statsx_freeze"
  51. #define HUD_FREEZE_LIMIT        "-2.0"
  52.  
  53. // HUD statistics minimum duration, in seconds, to trigger the display logic.
  54. #define HUD_MIN_DURATION    0.2
  55.  
  56. // Config plugin constants.
  57. #define MODE_HUD_DELAY      0   // Make a 0.01 sec delay on HUD reset process.
  58.  
  59. // You can also manualy enable or disable these options by setting them to 1
  60. // For example:
  61. // public ShowAttackers = 1
  62. // However amx_statscfg command is recommended
  63.  
  64. public KillerChat           = 0 // displays killer hp&ap to victim console
  65.                                 // and screen
  66.  
  67. public ShowAttackers        = 0 // shows attackers
  68. public ShowVictims          = 0 // shows victims
  69. public ShowKiller           = 0 // shows killer
  70. public ShowTeamScore        = 0 // shows team score at round end
  71. public ShowTotalStats       = 0 // shows round total stats
  72. public ShowBestScore        = 0 // shows rounds best scored player
  73. public ShowMostDisruptive   = 0 // shows rounds most disruptive player
  74.  
  75. public EndPlayer            = 0 // displays player stats at the end of map
  76. public EndTop15             = 0 // displays top15 at the end of map
  77.  
  78. public SayHP                = 0 // displays information about user killer
  79. public SayStatsMe           = 0 // displays user's stats and rank
  80. public SayRankStats         = 0 // displays user's rank stats
  81. public SayMe                = 0 // displays user's stats
  82. public SayRank              = 0 // displays user's rank
  83. public SayReport            = 0 // report user's weapon status to team
  84. public SayScore             = 0 // displays team's map score
  85. public SayTop15             = 0 // displays first 15 players
  86. public SayStatsAll          = 0 // displays all players stats and rank
  87.  
  88. public ShowStats            = 1 // set client HUD-stats switched off by default
  89. public ShowDistHS           = 0 // show distance and HS in attackers and
  90.                                 //  victims HUD lists
  91. public ShowFullStats        = 0 // show full HUD stats (more than 78 chars)
  92.  
  93. public SpecRankInfo         = 0 // displays rank info when spectating
  94.  
  95. // Standard Contstants.
  96. #define MAX_TEAMS               2
  97. #define MAX_PLAYERS             32 + 1
  98.  
  99. #define MAX_NAME_LENGTH         31
  100. #define MAX_WEAPON_LENGTH       31
  101. #define MAX_TEXT_LENGTH         255
  102. #define MAX_BUFFER_LENGTH       2047
  103.  
  104. // User stats parms id
  105. #define STATS_KILLS             0
  106. #define STATS_DEATHS            1
  107. #define STATS_HS                2
  108. #define STATS_TKS               3
  109. #define STATS_SHOTS             4
  110. #define STATS_HITS              5
  111. #define STATS_DAMAGE            6
  112.  
  113. // Global player flags.
  114. new BODY_PART[8][] =
  115. {
  116.         "WHOLEBODY",
  117.         "HEAD",
  118.         "CHEST",
  119.         "STOMACH",
  120.         "LEFTARM",
  121.         "RIGHTARM",
  122.         "LEFTLEG",
  123.         "RIGHTLEG"
  124. }
  125.  
  126. // Killer information, save killer info at the time when player is killed.
  127. #define KILLED_KILLER_ID        0   // Killer userindex/user-ID
  128. #define KILLED_KILLER_HEALTH    1   // Killer's health
  129. #define KILLED_KILLER_ARMOUR    2   // Killer's armour
  130. #define KILLED_TEAM             3   // Killer's team
  131. #define KILLED_KILLER_STATSFIX  4   // Fix to register the last hit/kill
  132.  
  133. new g_izKilled[MAX_PLAYERS][5]
  134.  
  135. // Menu variables and configuration
  136. #define MAX_PPL_MENU_ACTIONS    2   // Number of player menu actions
  137. #define PPL_MENU_OPTIONS        7   // Number of player options per displayed menu
  138.  
  139. new g_iPluginMode                                   = 0
  140.  
  141. new g_izUserMenuPosition[MAX_PLAYERS]               = {0, ...}
  142. new g_izUserMenuAction[MAX_PLAYERS]                 = {0, ...}
  143. new g_izUserMenuPlayers[MAX_PLAYERS][32]
  144.  
  145. new g_izSpecMode[MAX_PLAYERS]                       = {0, ...}
  146.  
  147. new g_izShowStatsFlags[MAX_PLAYERS]                 = {0, ...}
  148. new g_izStatsSwitch[MAX_PLAYERS]                    = {0, ...}
  149. new Float:g_fzShowUserStatsTime[MAX_PLAYERS]        = {0.0, ...}
  150. new Float:g_fShowStatsTime                          = 0.0
  151. new Float:g_fFreezeTime                             = 0.0
  152. new Float:g_fFreezeLimitTime                        = 0.0
  153. new Float:g_fHUDDuration                            = 0.0
  154.  
  155. new g_iRoundEndTriggered                            = 0
  156. new g_iRoundEndProcessed                            = 0
  157.  
  158. new Float:g_fStartGame                              = 0.0
  159. new g_izTeamScore[MAX_TEAMS]                        = {0, ...}
  160. new g_izTeamEventScore[MAX_TEAMS]                   = {0, ...}
  161. new g_izTeamRndStats[MAX_TEAMS][8]
  162. new g_izTeamGameStats[MAX_TEAMS][8]
  163. new g_izUserUserID[MAX_PLAYERS]                     = {0, ...}
  164. new g_izUserAttackerDistance[MAX_PLAYERS]           = {0, ...}
  165. new g_izUserVictimDistance[MAX_PLAYERS][MAX_PLAYERS]
  166. new g_izUserRndName[MAX_PLAYERS][MAX_NAME_LENGTH + 1]
  167. new g_izUserRndStats[MAX_PLAYERS][8]
  168. new g_izUserGameStats[MAX_PLAYERS][8]
  169.  
  170. // Common buffer to improve performance, as Small always zero-initializes all vars
  171. new g_sBuffer[MAX_BUFFER_LENGTH + 1]                = ""
  172. new g_sScore[MAX_TEXT_LENGTH + 1]                   = ""
  173. new g_sAwardAndScore[MAX_BUFFER_LENGTH + 1]         = ""
  174.  
  175. new t_sText[MAX_TEXT_LENGTH + 1]                    = ""
  176. new t_sName[MAX_NAME_LENGTH + 1]                    = ""
  177. new t_sWpn[MAX_WEAPON_LENGTH + 1]                   = ""
  178.  
  179. new g_HudSync_EndRound
  180. new g_HudSync_SpecInfo
  181.  
  182. //--------------------------------
  183. // Initialize
  184. //--------------------------------
  185. public plugin_init()
  186. {
  187.         // Register plugin.
  188.         register_plugin("StatsX", AMXX_VERSION_STR, "AMXX Dev Team")
  189.         register_dictionary("statsx.txt")
  190.  
  191.         // Register events.
  192.         register_event("TextMsg", "eventStartGame", "a", "2=#Game_Commencing", "2=#Game_will_restart_in")
  193.         register_event("ResetHUD", "eventResetHud", "be")
  194.         register_event("RoundTime", "eventStartRound", "bc")
  195.         register_event("SendAudio", "eventEndRound", "a", "2=%!MRAD_terwin", "2=%!MRAD_ctwin", "2=%!MRAD_rounddraw")
  196.         register_event("TeamScore", "eventTeamScore", "a")
  197.         register_event("30", "eventIntermission", "a")
  198.         register_event("TextMsg", "eventSpecMode", "bd", "2&ec_Mod")
  199.         register_event("StatusValue", "eventShowRank", "bd", "1=2")
  200.  
  201.         // Register commands.
  202.         register_clcmd("say /hp", "cmdHp", 0, "- display info. about your killer (chat)")
  203.         register_clcmd("say /statsme", "cmdStatsMe", 0, "- display your stats (MOTD)")
  204.         register_clcmd("say /rankstats", "cmdRankStats", 0, "- display your server stats (MOTD)")
  205.         register_clcmd("say /me", "cmdMe", 0, "- display current round stats (chat)")
  206.         register_clcmd("say /score", "cmdScore", 0, "- display last score (chat)")
  207.         register_clcmd("say /rank", "cmdRank", 0, "- display your rank (chat)")
  208.         register_clcmd("say /report", "cmdReport", 0, "- display weapon status (say_team)")
  209.         register_clcmd("say /top15", "cmdTop15", 0, "- display top 15 players (MOTD)")
  210.         register_clcmd("say /stats", "cmdStats", 0, "- display players stats (menu/MOTD)")
  211.         register_clcmd("say /switch", "cmdSwitch", 0, "- switch client's stats on or off")
  212.         register_clcmd("say_team /hp", "cmdHp", 0, "- display info. about your killer (chat)")
  213.         register_clcmd("say_team /statsme", "cmdStatsMe", 0, "- display your stats (MOTD)")
  214.         register_clcmd("say_team /rankstats", "cmdRankStats", 0, "- display your server stats (MOTD)")
  215.         register_clcmd("say_team /me", "cmdMe", 0, "- display current round stats (chat)")
  216.         register_clcmd("say_team /score", "cmdScore", 0, "- display last score (chat)")
  217.         register_clcmd("say_team /rank", "cmdRank", 0, "- display your rank (chat)")
  218.         register_clcmd("say_team /report", "cmdReport", 0, "- display weapon status (say_team_team)")
  219.         register_clcmd("say_team /top15", "cmdTop15", 0, "- display top 15 players (MOTD)")
  220.         register_clcmd("say_team /stats", "cmdStats", 0, "- display players stats (menu/MOTD)")
  221.         register_clcmd("say_team /switch", "cmdSwitch", 0, "- switch client's stats on or off")
  222.  
  223.         // Register menus.
  224.         register_menucmd(register_menuid("Server Stats"), 1023, "actionStatsMenu")
  225.  
  226.         // Register special configuration setting and default value.
  227.         register_srvcmd("amx_statsx_mode", "cmdPluginMode", ADMIN_CFG, "<flags> - sets plugin options")
  228.  
  229. #if defined STATSX_DEBUG
  230.         register_clcmd("say /hudtest", "cmdHudTest")
  231. #endif
  232.  
  233.         register_cvar(HUD_DURATION_CVAR, HUD_DURATION)
  234.         register_cvar(HUD_FREEZE_LIMIT_CVAR, HUD_FREEZE_LIMIT)
  235.  
  236.         // Init buffers and some global vars.
  237.         g_sBuffer[0] = 0
  238.         save_team_chatscore()
  239.        
  240.         g_HudSync_EndRound = CreateHudSyncObj()
  241.         g_HudSync_SpecInfo = CreateHudSyncObj()
  242. }
  243.  
  244. public plugin_cfg()
  245. {
  246.         new addStast[] = "amx_statscfg add ^"%s^" %s"
  247.  
  248.         server_cmd(addStast, "ST_SHOW_KILLER_CHAT", "KillerChat")
  249.         server_cmd(addStast, "ST_SHOW_ATTACKERS", "ShowAttackers")
  250.         server_cmd(addStast, "ST_SHOW_VICTIMS", "ShowVictims")
  251.         server_cmd(addStast, "ST_SHOW_KILLER", "ShowKiller")
  252.         server_cmd(addStast, "ST_SHOW_TEAM_SCORE", "ShowTeamScore")
  253.         server_cmd(addStast, "ST_SHOW_TOTAL_STATS", "ShowTotalStats")
  254.         server_cmd(addStast, "ST_SHOW_BEST_SCORE", "ShowBestScore")
  255.         server_cmd(addStast, "ST_SHOW_MOST_DISRUPTIVE", "ShowMostDisruptive")
  256.         server_cmd(addStast, "ST_SHOW_HUD_STATS_DEF", "ShowStats")
  257.         server_cmd(addStast, "ST_SHOW_DIST_HS_HUD", "ShowDistHS")
  258.         server_cmd(addStast, "ST_STATS_PLAYER_MAP_END", "EndPlayer")
  259.         server_cmd(addStast, "ST_STATS_TOP15_MAP_END", "EndTop15")
  260.         server_cmd(addStast, "ST_SAY_HP", "SayHP")
  261.         server_cmd(addStast, "ST_SAY_STATSME", "SayStatsMe")
  262.         server_cmd(addStast, "ST_SAY_RANKSTATS", "SayRankStats")
  263.         server_cmd(addStast, "ST_SAY_ME", "SayMe")
  264.         server_cmd(addStast, "ST_SAY_RANK", "SayRank")
  265.         server_cmd(addStast, "ST_SAY_REPORT", "SayReport")
  266.         server_cmd(addStast, "ST_SAY_SCORE", "SayScore")
  267.         server_cmd(addStast, "ST_SAY_TOP15", "SayTop15")
  268.         server_cmd(addStast, "ST_SAY_STATS", "SayStatsAll")
  269.         server_cmd(addStast, "ST_SPEC_RANK", "SpecRankInfo")
  270.  
  271.         // Update local configuration vars with value in cvars.
  272.         get_config_cvars()
  273. }
  274.  
  275. // Set hudmessage format.
  276. set_hudtype_killer(Float:fDuration)
  277.         set_hudmessage(220, 80, 0, 0.05, 0.15, 0, 6.0, fDuration, (fDuration >= g_fHUDDuration) ? 1.0 : 0.0, 1.0, -1)
  278.  
  279. set_hudtype_endround(Float:fDuration)
  280. {
  281.         set_hudmessage(100, 200, 0, 0.05, 0.55, 0, 0.02, fDuration, (fDuration >= g_fHUDDuration) ? 1.0 : 0.0, 1.0)
  282. }
  283.  
  284. set_hudtype_attacker(Float:fDuration)
  285.         set_hudmessage(220, 80, 0, 0.55, 0.35, 0, 6.0, fDuration, (fDuration >= g_fHUDDuration) ? 1.0 : 0.0, 1.0, -1)
  286.  
  287. set_hudtype_victim(Float:fDuration)
  288.         set_hudmessage(0, 80, 220, 0.55, 0.60, 0, 6.0, fDuration, (fDuration >= g_fHUDDuration) ? 1.0 : 0.0, 1.0, -1)
  289.  
  290. set_hudtype_specmode()
  291. {
  292.         set_hudmessage(255, 255, 255, 0.02, 0.96, 2, 0.05, 0.1, 0.01, 3.0, -1)
  293. }
  294.  
  295. #if defined STATSX_DEBUG
  296. public cmdHudTest(id)
  297. {
  298.         new i, iLen
  299.         iLen = 0
  300.        
  301.         for (i = 1; i < 20; i++)
  302.                 iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "....x....1....x....2....x....3....x....4....x....^n")
  303.        
  304.         set_hudtype_killer(50.0)
  305.         show_hudmessage(id, "%s", g_sBuffer)
  306. }
  307. #endif
  308.  
  309. // Stats formulas
  310. Float:accuracy(izStats[8])
  311. {
  312.         if (!izStats[STATS_SHOTS])
  313.                 return (0.0)
  314.        
  315.         return (100.0 * float(izStats[STATS_HITS]) / float(izStats[STATS_SHOTS]))
  316. }
  317.  
  318. Float:effec(izStats[8])
  319. {
  320.         if (!izStats[STATS_KILLS])
  321.                 return (0.0)
  322.        
  323.         return (100.0 * float(izStats[STATS_KILLS]) / float(izStats[STATS_KILLS] + izStats[STATS_DEATHS]))
  324. }
  325.  
  326. // Distance formula (metric)
  327. Float:distance(iDistance)
  328. {
  329.         return float(iDistance) * 0.0254
  330. }
  331.  
  332. // Get plugin config flags.
  333. set_plugin_mode(id, sFlags[])
  334. {
  335.         if (sFlags[0])
  336.                 g_iPluginMode = read_flags(sFlags)
  337.        
  338.         get_flags(g_iPluginMode, t_sText, MAX_TEXT_LENGTH)
  339.         console_print(id, "%L", id, "MODE_SET_TO", t_sText)
  340.        
  341.         return g_iPluginMode
  342. }
  343.  
  344. // Get config parameters.
  345. get_config_cvars()
  346. {
  347.         g_fFreezeTime = get_cvar_float("mp_freezetime")
  348.        
  349.         if (g_fFreezeTime < 0.0)
  350.                 g_fFreezeTime = 0.0
  351.  
  352.         g_fHUDDuration = get_cvar_float(HUD_DURATION_CVAR)
  353.        
  354.         if (g_fHUDDuration < 1.0)
  355.                 g_fHUDDuration = 1.0
  356.  
  357.         g_fFreezeLimitTime = get_cvar_float(HUD_FREEZE_LIMIT_CVAR)
  358. }
  359.  
  360. // Get and format attackers header and list.
  361. get_attackers(id, sBuffer[MAX_BUFFER_LENGTH + 1])
  362. {
  363.         new izStats[8], izBody[8]
  364.         new iAttacker
  365.         new iFound, iLen
  366.         new iMaxPlayer = get_maxplayers()
  367.  
  368.         iFound = 0
  369.         sBuffer[0] = 0
  370.  
  371.         // Get and format header. Add killing attacker statistics if user is dead.
  372.         // Make sure shots is greater than zero or division by zero will occur.
  373.         // To print a '%', 4 of them must done in a row.
  374.         izStats[STATS_SHOTS] = 0
  375.         iAttacker = g_izKilled[id][KILLED_KILLER_ID]
  376.        
  377.         if (iAttacker)
  378.                 get_user_astats(id, iAttacker, izStats, izBody)
  379.        
  380.         if (izStats[STATS_SHOTS] && ShowFullStats)
  381.         {
  382.                 get_user_name(iAttacker, t_sName, MAX_NAME_LENGTH)
  383.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L -- %s -- %0.2f%% %L:^n", id, "ATTACKERS", t_sName, accuracy(izStats), id, "ACC")
  384.         }
  385.         else
  386.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L:^n", id, "ATTACKERS")
  387.  
  388.         // Get and format attacker list.
  389.         for (iAttacker = 1; iAttacker <= iMaxPlayer; iAttacker++)
  390.         {
  391.                 if (get_user_astats(id, iAttacker, izStats, izBody, t_sWpn, MAX_WEAPON_LENGTH))
  392.                 {
  393.                         iFound = 1
  394.                         get_user_name(iAttacker, t_sName, MAX_NAME_LENGTH)
  395.                        
  396.                         if (izStats[STATS_KILLS])
  397.                         {
  398.                                 if (!ShowDistHS)
  399.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  400.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn)
  401.                                 else if (izStats[STATS_HS])
  402.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s / %0.0f m / HS^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  403.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn, distance(g_izUserAttackerDistance[id]))
  404.                                 else
  405.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s / %0.0f m^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  406.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn, distance(g_izUserAttackerDistance[id]))
  407.                         }
  408.                         else
  409.                                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L^n", t_sName, izStats[STATS_HITS], id, "HIT_S", izStats[STATS_DAMAGE], id, "DMG")
  410.                 }
  411.         }
  412.        
  413.         if (!iFound)
  414.                 sBuffer[0] = 0
  415.        
  416.         return iFound
  417. }
  418.  
  419. // Get and format victims header and list
  420. get_victims(id, sBuffer[MAX_BUFFER_LENGTH + 1])
  421. {
  422.         new izStats[8], izBody[8]
  423.         new iVictim
  424.         new iFound, iLen
  425.         new iMaxPlayer = get_maxplayers()
  426.  
  427.         iFound = 0
  428.         sBuffer[0] = 0
  429.  
  430.         // Get and format header.
  431.         // Make sure shots is greater than zero or division by zero will occur.
  432.         // To print a '%', 4 of them must done in a row.
  433.         izStats[STATS_SHOTS] = 0
  434.         get_user_vstats(id, 0, izStats, izBody)
  435.        
  436.         if (izStats[STATS_SHOTS])
  437.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L -- %0.2f%% %L:^n", id, "VICTIMS", accuracy(izStats), id, "ACC")
  438.         else
  439.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L:^n", id, "VICTIMS")
  440.  
  441.         for (iVictim = 1; iVictim <= iMaxPlayer; iVictim++)
  442.         {
  443.                 if (get_user_vstats(id, iVictim, izStats, izBody, t_sWpn, MAX_WEAPON_LENGTH))
  444.                 {
  445.                         iFound = 1
  446.                         get_user_name(iVictim, t_sName, MAX_NAME_LENGTH)
  447.                        
  448.                         if (izStats[STATS_DEATHS])
  449.                         {
  450.                                 if (!ShowDistHS)
  451.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  452.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn)
  453.                                 else if (izStats[STATS_HS])
  454.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s / %0.0f m / HS^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  455.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn, distance(g_izUserVictimDistance[id][iVictim]))
  456.                                 else
  457.                                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L / %s / %0.0f m^n", t_sName, izStats[STATS_HITS], id, "HIT_S",
  458.                                                                         izStats[STATS_DAMAGE], id, "DMG", t_sWpn, distance(g_izUserVictimDistance[id][iVictim]))
  459.                         }
  460.                         else
  461.                                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%s -- %d %L / %d %L^n", t_sName, izStats[STATS_HITS], id, "HIT_S", izStats[STATS_DAMAGE], id, "DMG")
  462.                 }
  463.         }
  464.        
  465.         if (!iFound)
  466.                 sBuffer[0] = 0
  467.  
  468.         return iFound
  469. }
  470.  
  471. // Get and format kill info.
  472. get_kill_info(id, iKiller, sBuffer[MAX_BUFFER_LENGTH + 1])
  473. {
  474.         new iFound, iLen
  475.  
  476.         iFound = 0
  477.         sBuffer[0] = 0
  478.  
  479.         if (iKiller && iKiller != id)
  480.         {
  481.                 new izAStats[8], izABody[8], izVStats[8], iaVBody[8]
  482.  
  483.                 iFound = 1
  484.                 get_user_name(iKiller, t_sName, MAX_NAME_LENGTH)
  485.  
  486.                 izAStats[STATS_HITS] = 0
  487.                 izAStats[STATS_DAMAGE] = 0
  488.                 t_sWpn[0] = 0
  489.                 get_user_astats(id, iKiller, izAStats, izABody, t_sWpn, MAX_WEAPON_LENGTH)
  490.  
  491.                 izVStats[STATS_HITS] = 0
  492.                 izVStats[STATS_DAMAGE] = 0
  493.                 get_user_vstats(id, iKiller, izVStats, iaVBody)
  494.  
  495.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L^n", id, "KILLED_YOU_DIST", t_sName, t_sWpn, distance(g_izUserAttackerDistance[id]))
  496.                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%L^n", id, "DID_DMG_HITS", izAStats[STATS_DAMAGE], izAStats[STATS_HITS], g_izKilled[id][KILLED_KILLER_HEALTH], g_izKilled[id][KILLED_KILLER_ARMOUR])
  497.                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%L^n", id, "YOU_DID_DMG", izVStats[STATS_DAMAGE], izVStats[STATS_HITS])
  498.         }
  499.        
  500.         return iFound
  501. }
  502.  
  503. // Get and format most disruptive.
  504. add_most_disruptive(sBuffer[MAX_BUFFER_LENGTH + 1])
  505. {
  506.         new id, iMaxDamageId, iMaxDamage, iMaxHeadShots
  507.  
  508.         iMaxDamageId = 0
  509.         iMaxDamage = 0
  510.         iMaxHeadShots = 0
  511.  
  512.         // Find player.
  513.         for (id = 1; id < MAX_PLAYERS; id++)
  514.         {
  515.                 if (g_izUserRndStats[id][STATS_DAMAGE] >= iMaxDamage && (g_izUserRndStats[id][STATS_DAMAGE] > iMaxDamage || g_izUserRndStats[id][STATS_HS] > iMaxHeadShots))
  516.                 {
  517.                         iMaxDamageId = id
  518.                         iMaxDamage = g_izUserRndStats[id][STATS_DAMAGE]
  519.                         iMaxHeadShots = g_izUserRndStats[id][STATS_HS]
  520.                 }
  521.         }
  522.  
  523.         // Format statistics.
  524.         if (iMaxDamageId)
  525.         {
  526.                 id = iMaxDamageId
  527.                
  528.                 new Float:fGameEff = effec(g_izUserGameStats[id])
  529.                 new Float:fRndAcc = accuracy(g_izUserRndStats[id])
  530.                
  531.                 format(t_sText, MAX_TEXT_LENGTH, "%L: %s^n%d %L / %d %L -- %0.2f%% %L / %0.2f%% %L^n", LANG_SERVER, "MOST_DMG", g_izUserRndName[id],
  532.                                 g_izUserRndStats[id][STATS_HITS], LANG_SERVER, "HIT_S", iMaxDamage, LANG_SERVER, "DMG", fGameEff, LANG_SERVER, "EFF", fRndAcc, LANG_SERVER, "ACC")
  533.                 add(sBuffer, MAX_BUFFER_LENGTH, t_sText)
  534.         }
  535.        
  536.         return iMaxDamageId
  537. }
  538.  
  539. // Get and format best score.
  540. add_best_score(sBuffer[MAX_BUFFER_LENGTH + 1])
  541. {
  542.         new id, iMaxKillsId, iMaxKills, iMaxHeadShots
  543.  
  544.         iMaxKillsId = 0
  545.         iMaxKills = 0
  546.         iMaxHeadShots = 0
  547.  
  548.         // Find player
  549.         for (id = 1; id < MAX_PLAYERS; id++)
  550.         {
  551.                 if (g_izUserRndStats[id][STATS_KILLS] >= iMaxKills && (g_izUserRndStats[id][STATS_KILLS] > iMaxKills || g_izUserRndStats[id][STATS_HS] > iMaxHeadShots))
  552.                 {
  553.                         iMaxKillsId = id
  554.                         iMaxKills = g_izUserRndStats[id][STATS_KILLS]
  555.                         iMaxHeadShots = g_izUserRndStats[id][STATS_HS]
  556.                 }
  557.         }
  558.  
  559.         // Format statistics.
  560.         if (iMaxKillsId)
  561.         {
  562.                 id = iMaxKillsId
  563.                
  564.                 new Float:fGameEff = effec(g_izUserGameStats[id])
  565.                 new Float:fRndAcc = accuracy(g_izUserRndStats[id])
  566.                
  567.                 format(t_sText, MAX_TEXT_LENGTH, "%L: %s^n%d %L / %d hs -- %0.2f%% %L / %0.2f%% %L^n", LANG_SERVER, "BEST_SCORE", g_izUserRndName[id],
  568.                                 iMaxKills, LANG_SERVER, "KILL_S", iMaxHeadShots, fGameEff, LANG_SERVER, "EFF", fRndAcc, LANG_SERVER, "ACC")
  569.                 add(sBuffer, MAX_BUFFER_LENGTH, t_sText)
  570.         }
  571.        
  572.         return iMaxKillsId
  573. }
  574.  
  575. // Get and format team score.
  576. add_team_score(sBuffer[MAX_BUFFER_LENGTH + 1])
  577. {
  578.         new Float:fzMapEff[MAX_TEAMS], Float:fzMapAcc[MAX_TEAMS], Float:fzRndAcc[MAX_TEAMS]
  579.  
  580.         // Calculate team stats
  581.         for (new iTeam = 0; iTeam < MAX_TEAMS; iTeam++)
  582.         {
  583.                 fzMapEff[iTeam] = effec(g_izTeamGameStats[iTeam])
  584.                 fzMapAcc[iTeam] = accuracy(g_izTeamGameStats[iTeam])
  585.                 fzRndAcc[iTeam] = accuracy(g_izTeamRndStats[iTeam])
  586.         }
  587.  
  588.         // Format round team stats, MOTD
  589.         format(t_sText, MAX_TEXT_LENGTH, "TERRORIST %d / %0.2f%% %L / %0.2f%% %L^nCT %d / %0.2f%% %L / %0.2f%% %L^n", g_izTeamScore[0],
  590.                         fzMapEff[0], LANG_SERVER, "EFF", fzRndAcc[0], LANG_SERVER, "ACC", g_izTeamScore[1], fzMapEff[1], LANG_SERVER, "EFF", fzRndAcc[1], LANG_SERVER, "ACC")
  591.         add(sBuffer, MAX_BUFFER_LENGTH, t_sText)
  592. }
  593.  
  594. // Get and format team stats, chat version
  595. save_team_chatscore()
  596. {
  597.         new Float:fzMapEff[MAX_TEAMS], Float:fzMapAcc[MAX_TEAMS], Float:fzRndAcc[MAX_TEAMS]
  598.  
  599.         // Calculate team stats
  600.         for (new iTeam = 0; iTeam < MAX_TEAMS; iTeam++)
  601.         {
  602.                 fzMapEff[iTeam] = effec(g_izTeamGameStats[iTeam])
  603.                 fzMapAcc[iTeam] = accuracy(g_izTeamGameStats[iTeam])
  604.                 fzRndAcc[iTeam] = accuracy(g_izTeamRndStats[iTeam])
  605.         }
  606.  
  607.         // Format game team stats, chat
  608.         format(g_sScore, MAX_BUFFER_LENGTH, "TERRORIST %d / %0.2f%% %L / %0.2f%% %L  --  CT %d / %0.2f%% %L / %0.2f%% %L", g_izTeamScore[0],
  609.                         fzMapEff[0], LANG_SERVER, "EFF", fzMapAcc[0], LANG_SERVER, "ACC", g_izTeamScore[1], fzMapEff[1], LANG_SERVER, "EFF", fzMapAcc[1], LANG_SERVER, "ACC")
  610. }
  611.  
  612. // Get and format total stats.
  613. add_total_stats(sBuffer[MAX_BUFFER_LENGTH + 1])
  614. {
  615.         format(t_sText, MAX_TEXT_LENGTH, "%L: %d %L / %d hs -- %d %L / %d %L^n", LANG_SERVER, "TOTAL", g_izUserRndStats[0][STATS_KILLS], LANG_SERVER, "KILL_S",
  616.                         g_izUserRndStats[0][STATS_HS], g_izUserRndStats[0][STATS_HITS], LANG_SERVER, "HITS", g_izUserRndStats[0][STATS_SHOTS], LANG_SERVER, "SHOT_S")
  617.         add(sBuffer, MAX_BUFFER_LENGTH, t_sText)
  618. }
  619.  
  620. // Get and format a user's list of body hits from an attacker.
  621. add_attacker_hits(id, iAttacker, sBuffer[MAX_BUFFER_LENGTH + 1])
  622. {
  623.         new iFound = 0
  624.        
  625.         if (iAttacker && iAttacker != id)
  626.         {
  627.                 new izStats[8], izBody[8], iLen
  628.  
  629.                 izStats[STATS_HITS] = 0
  630.                 get_user_astats(id, iAttacker, izStats, izBody)
  631.  
  632.                 if (izStats[STATS_HITS])
  633.                 {
  634.                         iFound = 1
  635.                         iLen = strlen(sBuffer)
  636.                         get_user_name(iAttacker, t_sName, MAX_NAME_LENGTH)
  637.                        
  638.                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%L:^n", id, "HITS_YOU_IN", t_sName)
  639.                        
  640.                         for (new i = 1; i < 8; i++)
  641.                         {
  642.                                 if (!izBody[i])
  643.                                         continue
  644.                                
  645.                                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%L: %d^n", id, BODY_PART[i], izBody[i])
  646.                         }
  647.                 }
  648.         }
  649.        
  650.         return iFound
  651. }
  652.  
  653. // Get and format killed stats: killer hp, ap, hits.
  654. format_kill_ainfo(id, iKiller, sBuffer[MAX_BUFFER_LENGTH + 1])
  655. {
  656.         new iFound = 0
  657.        
  658.         if (iKiller && iKiller != id)
  659.         {
  660.                 new izStats[8], izBody[8]
  661.                 new iLen
  662.                
  663.                 iFound = 1
  664.                 get_user_name(iKiller, t_sName, MAX_NAME_LENGTH)
  665.                 izStats[STATS_HITS] = 0
  666.                 get_user_astats(id, iKiller, izStats, izBody, t_sWpn, MAX_WEAPON_LENGTH)
  667.  
  668.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L (%dhp, %dap) >>", id, "KILLED_BY_WITH", t_sName, t_sWpn, distance(g_izUserAttackerDistance[id]),
  669.                                                 g_izKilled[id][KILLED_KILLER_HEALTH], g_izKilled[id][KILLED_KILLER_ARMOUR])
  670.  
  671.                 if (izStats[STATS_HITS])
  672.                 {
  673.                         for (new i = 1; i < 8; i++)
  674.                         {
  675.                                 if (!izBody[i])
  676.                                         continue
  677.                                
  678.                                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, " %L: %d", id, BODY_PART[i], izBody[i])
  679.                         }
  680.                 }
  681.                 else
  682.                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, " %L", id, "NO_HITS")
  683.         }
  684.         else
  685.                 format(sBuffer, MAX_BUFFER_LENGTH, "%L", id, "YOU_NO_KILLER")
  686.        
  687.         return iFound
  688. }
  689.  
  690. // Get and format killed stats: hits, damage on killer.
  691. format_kill_vinfo(id, iKiller, sBuffer[MAX_BUFFER_LENGTH + 1])
  692. {
  693.         new iFound = 0
  694.         new izStats[8]
  695.         new izBody[8]
  696.         new iLen
  697.  
  698.         izStats[STATS_HITS] = 0
  699.         izStats[STATS_DAMAGE] = 0
  700.         get_user_vstats(id, iKiller, izStats, izBody)
  701.  
  702.         if (iKiller && iKiller != id)
  703.         {
  704.                 iFound = 1
  705.                 get_user_name(iKiller, t_sName, MAX_NAME_LENGTH)
  706.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L >>", id, "YOU_HIT", t_sName, izStats[STATS_HITS], izStats[STATS_DAMAGE])
  707.         }
  708.         else
  709.                 iLen = format(sBuffer, MAX_BUFFER_LENGTH, "%L >>", id, "LAST_RES", izStats[STATS_HITS], izStats[STATS_DAMAGE])
  710.  
  711.         if (izStats[STATS_HITS])
  712.         {
  713.                 for (new i = 1; i < 8; i++)
  714.                 {
  715.                         if (!izBody[i])
  716.                                 continue
  717.                        
  718.                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, " %L: %d", id, BODY_PART[i], izBody[i])
  719.                 }
  720.         }
  721.         else
  722.                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, " %L", id, "NO_HITS")
  723.        
  724.         return iFound
  725. }
  726.  
  727. // Get and format top 15.
  728. format_top15(sBuffer[MAX_BUFFER_LENGTH + 1])
  729. {
  730.         new iMax = get_statsnum()
  731.         new izStats[8], izBody[8]
  732.         new iLen = 0
  733.  
  734.         if (iMax > 15)
  735.                 iMax = 15
  736.  
  737.         new lKills[16], lDeaths[16], lHits[16], lShots[16], lEff[16], lAcc[16]
  738.        
  739.         format(lKills, 15, "%L", LANG_SERVER, "KILLS")
  740.         format(lDeaths, 15, "%L", LANG_SERVER, "DEATHS")
  741.         format(lHits, 15, "%L", LANG_SERVER, "HITS")
  742.         format(lShots, 15, "%L", LANG_SERVER, "SHOTS")
  743.         format(lEff, 15, "%L", LANG_SERVER, "EFF")
  744.         format(lAcc, 15, "%L", LANG_SERVER, "ACC")
  745.        
  746.         ucfirst(lEff)
  747.         ucfirst(lAcc)
  748.  
  749.         iLen = format(sBuffer, MAX_BUFFER_LENGTH, "<body bgcolor=#000000><font color=#FFB000><pre>")
  750.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%2s %-22.22s %6s %6s %6s %6s %4s %4s %4s^n", "#", "Nick", lKills, lDeaths, lHits, lShots, "HS", lEff, lAcc)
  751.        
  752.         for (new i = 0; i < iMax && MAX_BUFFER_LENGTH - iLen > 0; i++)
  753.         {
  754.                 get_stats(i, izStats, izBody, t_sName, MAX_NAME_LENGTH)
  755.                 replace_all(t_sName, MAX_NAME_LENGTH, "<", "[")
  756.                 replace_all(t_sName, MAX_NAME_LENGTH, ">", "]")
  757.                 iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%2d %-22.22s %6d %6d %6d %6d %4d %3.0f%% %3.0f%%^n", i + 1, t_sName, izStats[STATS_KILLS],
  758.                                                 izStats[STATS_DEATHS], izStats[STATS_HITS], izStats[STATS_SHOTS], izStats[STATS_HS], effec(izStats), accuracy(izStats))
  759.         }
  760. }
  761.  
  762. // Get and format rank stats.
  763. format_rankstats(id, sBuffer[MAX_BUFFER_LENGTH + 1], iMyId = 0)
  764. {
  765.         new izStats[8] = {0, ...}
  766.         new izBody[8]
  767.         new iRankPos, iLen
  768.         new lKills[16], lDeaths[16], lHits[16], lShots[16], lDamage[16], lEff[16], lAcc[16]
  769.        
  770.         format(lKills, 15, "%L", id, "KILLS")
  771.         format(lDeaths, 15, "%L", id, "DEATHS")
  772.         format(lHits, 15, "%L", id, "HITS")
  773.         format(lShots, 15, "%L", id, "SHOTS")
  774.         format(lDamage, 15, "%L", id, "DAMAGE")
  775.         format(lEff, 15, "%L", id, "EFF")
  776.         format(lAcc, 15, "%L", id, "ACC")
  777.        
  778.         ucfirst(lEff)
  779.         ucfirst(lAcc)
  780.        
  781.         iRankPos = get_user_stats(id, izStats, izBody)
  782.         iLen = format(sBuffer, MAX_BUFFER_LENGTH, "<body bgcolor=#000000><font color=#FFB000><pre>")
  783.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%L %L^n^n", id, (!iMyId || iMyId == id) ? "YOUR" : "PLAYERS", id, "RANK_IS", iRankPos, get_statsnum())
  784.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%6s: %d  (%d with hs)^n%6s: %d^n%6s: %d^n%6s: %d^n%6s: %d^n%6s: %0.2f%%^n%6s: %0.2f%%^n^n",
  785.                                         lKills, izStats[STATS_KILLS], izStats[STATS_HS], lDeaths, izStats[STATS_DEATHS], lHits, izStats[STATS_HITS], lShots, izStats[STATS_SHOTS],
  786.                                         lDamage, izStats[STATS_DAMAGE], lEff, effec(izStats), lAcc, accuracy(izStats))
  787.        
  788.         new L_BODY_PART[8][32]
  789.        
  790.         for (new i = 1; i < 8; i++)
  791.         {
  792.                 format(L_BODY_PART[i], 31, "%L", id, BODY_PART[i])
  793.         }
  794.        
  795.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%10s:^n%10s: %d^n%10s: %d^n%10s: %d^n%10s: %d^n%10s: %d^n%10s: %d^n%10s: %d", "HITS",
  796.                                         L_BODY_PART[1], izBody[1], L_BODY_PART[2], izBody[2], L_BODY_PART[3], izBody[3], L_BODY_PART[4], izBody[4], L_BODY_PART[5],
  797.                                         izBody[5], L_BODY_PART[6], izBody[6], L_BODY_PART[7], izBody[7])
  798. }
  799.  
  800. // Get and format stats.
  801. format_stats(id, sBuffer[MAX_BUFFER_LENGTH + 1])
  802. {
  803.         new izStats[8] = {0, ...}
  804.         new izBody[8]
  805.         new iWeapon, iLen
  806.         new lKills[16], lDeaths[16], lHits[16], lShots[16], lDamage[16], lEff[16], lAcc[16], lWeapon[16]
  807.        
  808.         format(lKills, 15, "%L", id, "KILLS")
  809.         format(lDeaths, 15, "%L", id, "DEATHS")
  810.         format(lHits, 15, "%L", id, "HITS")
  811.         format(lShots, 15, "%L", id, "SHOTS")
  812.         format(lDamage, 15, "%L", id, "DAMAGE")
  813.         format(lEff, 15, "%L", id, "EFF")
  814.         format(lAcc, 15, "%L", id, "ACC")
  815.         format(lWeapon, 15, "%L", id, "WEAPON")
  816.        
  817.         ucfirst(lEff)
  818.         ucfirst(lAcc)
  819.        
  820.         get_user_wstats(id, 0, izStats, izBody)
  821.        
  822.         iLen = format(sBuffer, MAX_BUFFER_LENGTH, "<body bgcolor=#000000><font color=#FFB000><pre>")
  823.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%6s: %d  (%d with hs)^n%6s: %d^n%6s: %d^n%6s: %d^n%6s: %d^n%6s: %0.2f%%^n%6s: %0.2f%%^n^n",
  824.                                         lKills, izStats[STATS_KILLS], izStats[STATS_HS], lDeaths, izStats[STATS_DEATHS], lHits, izStats[STATS_HITS], lShots, izStats[STATS_SHOTS],
  825.                                         lDamage, izStats[STATS_DAMAGE], lEff, effec(izStats), lAcc, accuracy(izStats))
  826.         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%-12.12s  %6s  %6s  %6s  %6s  %6s  %4s^n", lWeapon, lKills, lDeaths, lHits, lShots, lDamage, lAcc)
  827.        
  828.         for (iWeapon = 1; iWeapon < xmod_get_maxweapons() && MAX_BUFFER_LENGTH - iLen > 0 ; iWeapon++)
  829.         {
  830.                 if (get_user_wstats(id, iWeapon, izStats, izBody))
  831.                 {
  832.                         xmod_get_wpnname(iWeapon, t_sWpn, MAX_WEAPON_LENGTH)
  833.                         iLen += format(sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%-12.12s  %6d  %6d  %6d  %6d  %6d  %3.0f%%^n", t_sWpn, izStats[STATS_KILLS], izStats[STATS_DEATHS],
  834.                                                         izStats[STATS_HITS], izStats[STATS_SHOTS], izStats[STATS_DAMAGE], accuracy(izStats))
  835.                 }
  836.         }
  837. }
  838.  
  839. // Show round end stats. If gametime is zero then use default duration time.
  840. show_roundend_hudstats(id, Float:fGameTime)
  841. {
  842.         // Bail out if there no HUD stats should be shown
  843.         // for this player or end round stats not created.
  844.         if (!g_izStatsSwitch[id]) return
  845.         if (!g_sAwardAndScore[0]) return
  846.  
  847.         // If round end timer is zero clear round end stats.
  848.         if (g_fShowStatsTime == 0.0)
  849.         {
  850.                 ClearSyncHud(id, g_HudSync_EndRound)
  851. #if defined STATSX_DEBUG
  852.                 log_amx("Clear round end HUD stats for #%d", id)
  853. #endif
  854.         }
  855.  
  856.         // Set HUD-duration to default or remaining time.
  857.         new Float:fDuration
  858.        
  859.         if (fGameTime == 0.0)
  860.                 fDuration = g_fHUDDuration
  861.         else
  862.         {
  863.                 fDuration = g_fShowStatsTime + g_fHUDDuration - fGameTime
  864.                
  865.                 if (fDuration > g_fFreezeTime + g_fFreezeLimitTime)
  866.                         fDuration = g_fFreezeTime + g_fFreezeLimitTime
  867.         }
  868.        
  869.         // Show stats only if more time left than coded minimum.
  870.         if (fDuration >= HUD_MIN_DURATION)
  871.         {
  872.                 set_hudtype_endround(fDuration)
  873.                 ShowSyncHudMsg(id, g_HudSync_EndRound, "%s", g_sAwardAndScore)
  874. #if defined STATSX_DEBUG
  875.                 log_amx("Show %1.2fs round end HUD stats for #%d", fDuration, id)
  876. #endif
  877.         }
  878. }
  879.  
  880. // Show round end stats.
  881. show_user_hudstats(id, Float:fGameTime)
  882. {
  883.         // Bail out if there no HUD stats should be shown
  884.         // for this player or user stats timer is zero.
  885.         if (!g_izStatsSwitch[id]) return
  886.         if (g_fzShowUserStatsTime[id] == 0.0) return
  887.  
  888.         // Set HUD-duration to default or remaining time.
  889.         new Float:fDuration
  890.        
  891.         if (fGameTime == 0.0)
  892.                 fDuration = g_fHUDDuration
  893.         else
  894.         {
  895.                 fDuration = g_fzShowUserStatsTime[id] + g_fHUDDuration - fGameTime
  896.                
  897.                 if (fDuration > g_fFreezeTime + g_fFreezeLimitTime)
  898.                         fDuration = g_fFreezeTime + g_fFreezeLimitTime
  899.         }
  900.  
  901.         // Show stats only if more time left than coded minimum.
  902.         if (fDuration >= HUD_MIN_DURATION)
  903.         {
  904.                 if (ShowKiller)
  905.                 {
  906.                         new iKiller
  907.                        
  908.                         iKiller = g_izKilled[id][KILLED_KILLER_ID]
  909.                         get_kill_info(id, iKiller, g_sBuffer)
  910.                         add_attacker_hits(id, iKiller, g_sBuffer)
  911.                         set_hudtype_killer(fDuration)
  912.                         show_hudmessage(id, "%s", g_sBuffer)
  913. #if defined STATSX_DEBUG
  914.                         log_amx("Show %1.2fs %suser HUD k-stats for #%d", fDuration, g_sBuffer[0] ? "" : "no ", id)
  915. #endif
  916.                 }
  917.                
  918.                 if (ShowVictims)
  919.                 {
  920.                         get_victims(id, g_sBuffer)
  921.                         set_hudtype_victim(fDuration)
  922.                         show_hudmessage(id, "%s", g_sBuffer)
  923. #if defined STATSX_DEBUG
  924.                         log_amx("Show %1.2fs %suser HUD v-stats for #%d", fDuration, g_sBuffer[0] ? "" : "no ", id)
  925. #endif
  926.                 }
  927.                
  928.                 if (ShowAttackers)
  929.                 {
  930.                         get_attackers(id, g_sBuffer)
  931.                         set_hudtype_attacker(fDuration)
  932.                         show_hudmessage(id, "%s", g_sBuffer)
  933. #if defined STATSX_DEBUG
  934.                         log_amx("Show %1.2fs %suser HUD a-stats for #%d", fDuration, g_sBuffer[0] ? "" : "no ", id)
  935. #endif
  936.                 }
  937.         }
  938. }
  939.  
  940. //------------------------------------------------------------
  941. // Plugin commands
  942. //------------------------------------------------------------
  943.  
  944. // Set or get plugin config flags.
  945. public cmdPluginMode(id, level, cid)
  946. {
  947.         if (!cmd_access(id, level, cid, 1))
  948.                 return PLUGIN_HANDLED
  949.        
  950.         if (read_argc() > 1)
  951.                 read_argv(1, g_sBuffer, MAX_BUFFER_LENGTH)
  952.         else
  953.                 g_sBuffer[0] = 0
  954.        
  955.         set_plugin_mode(id, g_sBuffer)
  956.        
  957.         return PLUGIN_HANDLED
  958. }
  959.  
  960. // Display MOTD stats.
  961. public cmdStatsMe(id)
  962. {
  963.         if (!SayStatsMe)
  964.         {
  965.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  966.                 return PLUGIN_HANDLED
  967.         }
  968.  
  969.         format_stats(id, g_sBuffer)
  970.         get_user_name(id, t_sName, MAX_NAME_LENGTH)
  971.         show_motd(id, g_sBuffer, t_sName)
  972.        
  973.         return PLUGIN_CONTINUE
  974. }
  975.  
  976. // Display MOTD rank.
  977. public cmdRankStats(id)
  978. {
  979.         if (!SayRankStats)
  980.         {
  981.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  982.                 return PLUGIN_HANDLED
  983.         }
  984.        
  985.         format_rankstats(id, g_sBuffer)
  986.         get_user_name(id, t_sName, MAX_NAME_LENGTH)
  987.         show_motd(id, g_sBuffer, t_sName)
  988.        
  989.         return PLUGIN_CONTINUE
  990. }
  991.  
  992. // Display MOTD top15 ranked.
  993. public cmdTop15(id)
  994. {
  995.         if (!SayTop15)
  996.         {
  997.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  998.                 return PLUGIN_HANDLED
  999.         }
  1000.        
  1001.         format_top15(g_sBuffer)
  1002.         show_motd(id, g_sBuffer, "Top 15")
  1003.        
  1004.         return PLUGIN_CONTINUE
  1005. }
  1006.  
  1007. // Display killer information.
  1008. public cmdHp(id)
  1009. {
  1010.         if (!SayHP)
  1011.         {
  1012.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1013.                 return PLUGIN_HANDLED
  1014.         }
  1015.        
  1016.         new iKiller = g_izKilled[id][KILLED_KILLER_ID]
  1017.        
  1018.         format_kill_ainfo(id, iKiller, g_sBuffer)
  1019.         client_print(id, print_chat, "* %s", g_sBuffer)
  1020.        
  1021.         return PLUGIN_CONTINUE
  1022. }
  1023.  
  1024. // Display user stats.
  1025. public cmdMe(id)
  1026. {
  1027.         if (!SayMe)
  1028.         {
  1029.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1030.                 return PLUGIN_HANDLED
  1031.         }
  1032.         if (is_user_alive(id))
  1033.         {
  1034.                 client_print(id, print_chat, "Ne mozes koristiti ovu komandu dok si ziv!")
  1035.                 return PLUGIN_HANDLED
  1036.         }
  1037.         format_kill_vinfo(id, 0, g_sBuffer)
  1038.         client_print(id, print_chat, "* %s", g_sBuffer)
  1039.        
  1040.         return PLUGIN_CONTINUE
  1041. }
  1042.  
  1043. // Display user rank
  1044. public cmdRank(id)
  1045. {
  1046.         if (!SayRank)
  1047.         {
  1048.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1049.                 return PLUGIN_HANDLED
  1050.         }
  1051.  
  1052.         new izStats[8], izBody[8]
  1053.         new iRankPos, iRankMax
  1054.         new Float:fEff, Float:fAcc
  1055.        
  1056.         iRankPos = get_user_stats(id, izStats, izBody)
  1057.         iRankMax = get_statsnum()
  1058.        
  1059.         fEff = effec(izStats)
  1060.         fAcc = accuracy(izStats)
  1061.        
  1062.         client_print(id, print_chat, "* %L", id, "YOUR_RANK_IS", iRankPos, iRankMax, izStats[STATS_KILLS], izStats[STATS_HITS], fEff, fAcc)
  1063.        
  1064.         return PLUGIN_CONTINUE
  1065. }
  1066.  
  1067. // Report user weapon status to team.
  1068. public cmdReport(id)
  1069. {
  1070.         if (!SayReport)
  1071.         {
  1072.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1073.                 return PLUGIN_HANDLED
  1074.         }
  1075.        
  1076.         new iWeapon, iClip, iAmmo, iHealth, iArmor
  1077.        
  1078.         iWeapon = get_user_weapon(id, iClip, iAmmo)
  1079.        
  1080.         if (iWeapon != 0)
  1081.                 xmod_get_wpnname(iWeapon, t_sWpn, MAX_WEAPON_LENGTH)
  1082.        
  1083.         iHealth = get_user_health(id)
  1084.         iArmor = get_user_armor(id)
  1085.        
  1086.         new lWeapon[16]
  1087.        
  1088.         format(lWeapon, 15, "%L", id, "WEAPON")
  1089.         strtolower(lWeapon)
  1090.        
  1091.         if (iClip >= 0)
  1092.         {
  1093.                 format(g_sBuffer, MAX_BUFFER_LENGTH, "%s: %s, %L: %d/%d, %L: %d, %L: %d", lWeapon, t_sWpn, LANG_SERVER, "AMMO", iClip, iAmmo, LANG_SERVER, "HEALTH", iHealth, LANG_SERVER, "ARMOR", iArmor)
  1094.         }
  1095.         else
  1096.                 format(g_sBuffer, MAX_BUFFER_LENGTH, "%s: %s, %L: %d, %L: %d", lWeapon, t_sWpn[7], LANG_SERVER, "HEALTH", iHealth, LANG_SERVER, "ARMOR", iArmor)
  1097.        
  1098.         engclient_cmd(id, "say_team", g_sBuffer)
  1099.        
  1100.         return PLUGIN_CONTINUE
  1101. }
  1102.  
  1103. // Display team map score
  1104. public cmdScore(id)
  1105. {
  1106.         if (!SayScore)
  1107.         {
  1108.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1109.                 return PLUGIN_HANDLED
  1110.         }
  1111.        
  1112.         client_print(id, print_chat, "%L: %s", id, "GAME_SCORE", g_sScore)
  1113.        
  1114.         return PLUGIN_CONTINUE
  1115. }
  1116.  
  1117. // Client switch to enable or disable stats announcements.
  1118. public cmdSwitch(id)
  1119. {
  1120.         g_izStatsSwitch[id] = (g_izStatsSwitch[id]) ? 0 : -1
  1121.         num_to_str(g_izStatsSwitch[id], t_sText, MAX_TEXT_LENGTH)
  1122.         client_cmd(id, "setinfo _amxstatsx %s", t_sText)
  1123.        
  1124.         new lEnDis[32]
  1125.        
  1126.         format(lEnDis, 31, "%L", id, g_izStatsSwitch[id] ? "ENABLED" : "DISABLED")
  1127.         client_print(id, print_chat, "* %L", id, "STATS_ANNOUNCE", lEnDis)
  1128.        
  1129.         return PLUGIN_CONTINUE
  1130. }
  1131.  
  1132. // Player stats menu.
  1133. public cmdStats(id)
  1134. {
  1135.         if (!SayStatsAll)
  1136.         {
  1137.                 client_print(id, print_chat, "%L", id, "DISABLED_MSG")
  1138.                 return PLUGIN_HANDLED
  1139.         }
  1140.        
  1141.         showStatsMenu(id, g_izUserMenuPosition[id] = 0)
  1142.        
  1143.         return PLUGIN_CONTINUE
  1144. }
  1145.  
  1146. //--------------------------------
  1147. // Menu
  1148. //--------------------------------
  1149.  
  1150. public actionStatsMenu(id, key)
  1151. {
  1152.         switch (key)
  1153.         {
  1154.                 // Key '1' to '7', execute action on this option
  1155.                 case 0..6:
  1156.                 {
  1157.                         new iOption, iIndex
  1158.                         iOption = (g_izUserMenuPosition[id] * PPL_MENU_OPTIONS) + key
  1159.                        
  1160.                         if (iOption >= 0 && iOption < 32)
  1161.                         {
  1162.                                 iIndex = g_izUserMenuPlayers[id][iOption]
  1163.                        
  1164.                                 if (is_user_connected(iIndex))
  1165.                                 {
  1166.                                         switch (g_izUserMenuAction[id])
  1167.                                         {
  1168.                                                 case 0: format_stats(iIndex, g_sBuffer)
  1169.                                                 case 1: format_rankstats(iIndex, g_sBuffer, id)
  1170.                                                 default: g_sBuffer[0] = 0
  1171.                                         }
  1172.                                        
  1173.                                         if (g_sBuffer[0])
  1174.                                         {
  1175.                                                 get_user_name(iIndex, t_sName, MAX_NAME_LENGTH)
  1176.                                                 show_motd(id, g_sBuffer, t_sName)
  1177.                                         }
  1178.                                 }
  1179.                         }
  1180.                        
  1181.                         showStatsMenu(id, g_izUserMenuPosition[id])
  1182.                 }
  1183.                 // Key '8', change action
  1184.                 case 7:
  1185.                 {
  1186.                         g_izUserMenuAction[id]++
  1187.                        
  1188.                         if (g_izUserMenuAction[id] >= MAX_PPL_MENU_ACTIONS)
  1189.                                 g_izUserMenuAction[id] = 0
  1190.                        
  1191.                         showStatsMenu(id, g_izUserMenuPosition[id])
  1192.                 }
  1193.                 // Key '9', select next page of options
  1194.                 case 8: showStatsMenu(id, ++g_izUserMenuPosition[id])
  1195.                 // Key '10', cancel or go back to previous menu
  1196.                 case 9:
  1197.                 {
  1198.                         if (g_izUserMenuPosition[id] > 0)
  1199.                                 showStatsMenu(id, --g_izUserMenuPosition[id])
  1200.                 }
  1201.         }
  1202.        
  1203.         return PLUGIN_HANDLED
  1204. }
  1205.  
  1206. new g_izUserMenuActionText[MAX_PPL_MENU_ACTIONS][] = {"Show stats", "Show rank stats"}
  1207.  
  1208. showStatsMenu(id, iMenuPos)
  1209. {
  1210.         new iLen, iKeyMask, iPlayers
  1211.         new iUserIndex, iMenuPosMax, iMenuOption, iMenuOptionMax
  1212.        
  1213.         get_players(g_izUserMenuPlayers[id], iPlayers)
  1214.         iMenuPosMax = ((iPlayers - 1) / PPL_MENU_OPTIONS) + 1
  1215.        
  1216.         // If menu pos does not excist use last menu (if players has left)
  1217.         if (iMenuPos >= iMenuPosMax)
  1218.                 iMenuPos = iMenuPosMax - 1
  1219.  
  1220.         iUserIndex = iMenuPos * PPL_MENU_OPTIONS
  1221.         iLen = format(g_sBuffer, MAX_BUFFER_LENGTH, "\y%L\R%d/%d^n\w^n", id, "SERVER_STATS", iMenuPos + 1, iMenuPosMax)
  1222.         iMenuOptionMax = iPlayers - iUserIndex
  1223.        
  1224.         if (iMenuOptionMax > PPL_MENU_OPTIONS)
  1225.                 iMenuOptionMax = PPL_MENU_OPTIONS
  1226.        
  1227.         for (iMenuOption = 0; iMenuOption < iMenuOptionMax; iMenuOption++)
  1228.         {
  1229.                 get_user_name(g_izUserMenuPlayers[id][iUserIndex++], t_sName, MAX_NAME_LENGTH)
  1230.                 iKeyMask |= (1<<iMenuOption)
  1231.                 iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%d. %s^n\w", iMenuOption + 1, t_sName)
  1232.         }
  1233.        
  1234.         iKeyMask |= MENU_KEY_8|MENU_KEY_0
  1235.         iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n8. %s^n\w", g_izUserMenuActionText[g_izUserMenuAction[id]])
  1236.        
  1237.         if (iPlayers > iUserIndex)
  1238.         {
  1239.                 iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n9. %L...", id, "MORE")
  1240.                 iKeyMask |= MENU_KEY_9
  1241.         }
  1242.        
  1243.         if (iMenuPos > 0)
  1244.                 iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n0. %L", id, "BACK")
  1245.         else
  1246.                 iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n0. %L", id, "EXIT")
  1247.        
  1248.         show_menu(id, iKeyMask, g_sBuffer, -1, "Server Stats")
  1249.        
  1250.         return PLUGIN_HANDLED
  1251. }
  1252.  
  1253. //------------------------------------------------------------
  1254. // Plugin events
  1255. //------------------------------------------------------------
  1256.  
  1257. // Reset game stats on game start and restart.
  1258. public eventStartGame()
  1259. {
  1260.         read_data(2, t_sText, MAX_TEXT_LENGTH)
  1261.        
  1262.         if (t_sText[6] == 'w')
  1263.         {
  1264.                 read_data(3, t_sText, MAX_TEXT_LENGTH)
  1265.                 g_fStartGame = get_gametime() + float(str_to_num(t_sText))
  1266.         }
  1267.         else
  1268.                 g_fStartGame = get_gametime()
  1269.        
  1270.         return PLUGIN_CONTINUE
  1271. }
  1272.  
  1273. // Round start
  1274. public eventStartRound()
  1275. {
  1276.         new iTeam, id, i
  1277.        
  1278.         new Float:roundtime = get_cvar_float("mp_roundtime");
  1279.         if (read_data(1) >= floatround(roundtime * 60.0,floatround_floor) || (roundtime == 2.3 && read_data(1) == 137)) // these round too weird for it to work through pawn, have to add an exception for it
  1280.         {
  1281. #if defined STATSX_DEBUG
  1282.                 log_amx("Reset round stats")
  1283. #endif
  1284.                
  1285.                 // Reset game stats on game start and restart.
  1286.                 if (g_fStartGame > 0.0 && g_fStartGame <= get_gametime())
  1287.                 {
  1288. #if defined STATSX_DEBUG
  1289.                         log_amx("Reset game stats")
  1290. #endif
  1291.                         g_fStartGame = 0.0
  1292.  
  1293.                         // Clear team and game stats.
  1294.                         for (iTeam = 0; iTeam < MAX_TEAMS; iTeam++)
  1295.                         {
  1296.                                 g_izTeamEventScore[iTeam] = 0
  1297.                                
  1298.                                 for (i = 0; i < 8; i++)
  1299.                                         g_izTeamGameStats[iTeam][i] = 0
  1300.                         }
  1301.  
  1302.                         // Clear game stats, incl '0' that is sum of all users.
  1303.                         for (id = 0; id < MAX_PLAYERS; id++)
  1304.                         {
  1305.                                 for (i = 0; i < 8; i++)
  1306.                                         g_izUserGameStats[id][i] = 0
  1307.                         }
  1308.                 }
  1309.  
  1310.                 // Update team score with "TeamScore" event values and
  1311.                 // clear team round stats.
  1312.                 for (iTeam = 0; iTeam < MAX_TEAMS; iTeam++)
  1313.                 {
  1314.                         g_izTeamScore[iTeam] = g_izTeamEventScore[iTeam]
  1315.                        
  1316.                         for (i = 0; i < 8; i++)
  1317.                                 g_izTeamRndStats[iTeam][i] = 0
  1318.                 }
  1319.  
  1320.                 // Clear user round stats, incl '0' that is sum of all users.
  1321.                 for (id = 0; id < MAX_PLAYERS; id++)
  1322.                 {
  1323.                         g_izUserRndName[id][0] = 0
  1324.                        
  1325.                         for (i = 0; i < 8; i++)
  1326.                                 g_izUserRndStats[id][i] = 0
  1327.                        
  1328.                         g_fzShowUserStatsTime[id] = 0.0
  1329.                 }
  1330.  
  1331.                 // Allow end round stats and reset end round triggered indicator.
  1332.                 g_iRoundEndTriggered = 0
  1333.                 g_iRoundEndProcessed = 0
  1334.                 g_fShowStatsTime = 0.0
  1335.  
  1336.                 // Update local configuration vars with value in cvars.
  1337.                 get_config_cvars()
  1338.         }
  1339.  
  1340.         return PLUGIN_CONTINUE
  1341. }
  1342.  
  1343. // Reset killer info on round restart.
  1344. public eventResetHud(id)
  1345. {
  1346.         new args[1]
  1347.         args[0] = id
  1348.        
  1349.         if (g_iPluginMode & MODE_HUD_DELAY)
  1350.                 set_task(0.01, "delay_resethud", 200 + id, args, 1)
  1351.         else
  1352.                 delay_resethud(args)
  1353.        
  1354.         return PLUGIN_CONTINUE
  1355. }
  1356.  
  1357. public delay_resethud(args[])
  1358. {
  1359.         new id = args[0]
  1360.         new Float:fGameTime
  1361.  
  1362.         // Show user and score round stats after HUD-reset
  1363. #if defined STATSX_DEBUG
  1364.         log_amx("Reset HUD for #%d", id)
  1365. #endif
  1366.         fGameTime = get_gametime()
  1367.         show_user_hudstats(id, fGameTime)
  1368.         show_roundend_hudstats(id, fGameTime)
  1369.  
  1370.         // Reset round stats
  1371.         g_izKilled[id][KILLED_KILLER_ID] = 0
  1372.         g_izKilled[id][KILLED_KILLER_STATSFIX] = 0
  1373.         g_izShowStatsFlags[id] = -1             // Initialize flags
  1374.         g_fzShowUserStatsTime[id] = 0.0
  1375.         g_izUserAttackerDistance[id] = 0
  1376.        
  1377.         for (new i = 0; i < MAX_PLAYERS; i++)
  1378.                 g_izUserVictimDistance[id][i] = 0
  1379.        
  1380.         return PLUGIN_CONTINUE
  1381. }
  1382.  
  1383. // Save killer info on death.
  1384. public client_death(killer, victim, wpnindex, hitplace, TK)
  1385. {
  1386.         // Bail out if no killer.
  1387.         if (!killer)
  1388.                 return PLUGIN_CONTINUE
  1389.  
  1390.         if (killer != victim)
  1391.         {
  1392.                 new iaVOrigin[3], iaKOrigin[3]
  1393.                 new iDistance
  1394.                
  1395.                 get_user_origin(victim, iaVOrigin)
  1396.                 get_user_origin(killer, iaKOrigin)
  1397.                
  1398.                 g_izKilled[victim][KILLED_KILLER_ID] = killer
  1399.                 g_izKilled[victim][KILLED_KILLER_HEALTH] = get_user_health(killer)
  1400.                 g_izKilled[victim][KILLED_KILLER_ARMOUR] = get_user_armor(killer)
  1401.                 g_izKilled[victim][KILLED_KILLER_STATSFIX] = 0
  1402.  
  1403.                 iDistance = get_distance(iaVOrigin, iaKOrigin)
  1404.                 g_izUserAttackerDistance[victim] = iDistance
  1405.                 g_izUserVictimDistance[killer][victim] = iDistance
  1406.         }
  1407.        
  1408.         g_izKilled[victim][KILLED_TEAM] = get_user_team(victim)
  1409.         g_izKilled[victim][KILLED_KILLER_STATSFIX] = 1
  1410.  
  1411.         // Display kill stats for the player if round
  1412.         // end stats was not processed.
  1413.         if (!g_iRoundEndProcessed)
  1414.                 kill_stats(victim)
  1415.  
  1416.         return PLUGIN_CONTINUE
  1417. }
  1418.  
  1419. // Display hudmessage stats on death.
  1420. // This will also update all round and game stats.
  1421. // Must be called at least once per round.
  1422. kill_stats(id)
  1423. {
  1424.         // Bail out if user stats timer is non-zero,
  1425.         // ie function already called.
  1426.         if (g_fzShowUserStatsTime[id] > 0.0)
  1427.         {
  1428.                 return
  1429.         }
  1430.                
  1431.         new team = get_user_team(id)
  1432.         if (team < 1 || team > 2)
  1433.         {
  1434.                 return
  1435.         }
  1436.  
  1437.         // Flag kill stats displayed for this player.
  1438.         g_fzShowUserStatsTime[id] = get_gametime()
  1439.  
  1440.         // Add user death stats to user round stats
  1441.         new izStats[8], izBody[8]
  1442.         new iTeam, i
  1443.         new iKiller
  1444.  
  1445.         iKiller = g_izKilled[id][KILLED_KILLER_ID]
  1446.  
  1447.         // Get user's team (if dead use the saved team)
  1448.         if (iKiller)
  1449.                 iTeam = g_izKilled[id][KILLED_TEAM] - 1
  1450.         else
  1451.                 iTeam = get_user_team(id) - 1
  1452.  
  1453.         get_user_name(id, g_izUserRndName[id], MAX_NAME_LENGTH)
  1454.  
  1455.         if (get_user_rstats(id, izStats, izBody))
  1456.         {
  1457.                 // Update user's team round stats
  1458.                 if (iTeam >= 0 && iTeam < MAX_TEAMS)
  1459.                 {
  1460.                         for (i = 0; i < 8; i++)
  1461.                         {
  1462.                                 g_izTeamRndStats[iTeam][i] += izStats[i]
  1463.                                 g_izTeamGameStats[iTeam][i] += izStats[i]
  1464.                                 g_izUserRndStats[0][i] += izStats[i]
  1465.                                 g_izUserGameStats[0][i] += izStats[i]
  1466.                         }
  1467.                 }
  1468.  
  1469.                 // Update user's round stats
  1470.                 if (g_izUserUserID[id] == get_user_userid(id))
  1471.                 {
  1472.                         for (i = 0; i < 8; i++)
  1473.                         {
  1474.                                 g_izUserRndStats[id][i] += izStats[i]
  1475.                                 g_izUserGameStats[id][i] += izStats[i]
  1476.                         }
  1477.                 } else {
  1478.                         g_izUserUserID[id] = get_user_userid(id)
  1479.                        
  1480.                         for (i = 0; i < 8; i++)
  1481.                         {
  1482.                                 g_izUserRndStats[id][i] = izStats[i]
  1483.                                 g_izUserGameStats[id][i] = izStats[i]
  1484.                         }
  1485.                 }
  1486.  
  1487.         }       // endif (get_user_rstats())
  1488.  
  1489.         // Report stats in the chat section, if player is killed.
  1490.         if (KillerChat && iKiller && iKiller != id)
  1491.         {
  1492.                 if (format_kill_ainfo(id, iKiller, g_sBuffer))
  1493.                 {
  1494.                         client_print(id, print_chat, "* %s", g_sBuffer)
  1495.                         format_kill_vinfo(id, iKiller, g_sBuffer)
  1496.                 }
  1497.                
  1498.                 client_print(id, print_chat, "* %s", g_sBuffer)
  1499.         }
  1500.  
  1501.         // Display player stats info.
  1502. #if defined STATSX_DEBUG
  1503.         log_amx("Kill stats for #%d", id)
  1504. #endif
  1505.         show_user_hudstats(id, 0.0)
  1506. }
  1507.  
  1508. public eventEndRound()
  1509. {
  1510.         // Update local configuration vars with value in cvars.
  1511.         get_config_cvars()
  1512.  
  1513.         // If first end round event in the round, calculate team score.
  1514.         if (!g_iRoundEndTriggered)
  1515.         {
  1516.                 read_data(2, t_sText, MAX_TEXT_LENGTH)
  1517.                
  1518.                 if (t_sText[7] == 't')                  // Terrorist wins
  1519.                         g_izTeamScore[0]++
  1520.                 else if (t_sText[7] == 'c')             // CT wins
  1521.                         g_izTeamScore[1]++
  1522.         }
  1523.  
  1524.         set_task(0.3, "ERTask", 997)
  1525.        
  1526.         return PLUGIN_CONTINUE
  1527. }
  1528.  
  1529. public ERTask()
  1530. {
  1531.         // Flag round end triggered.
  1532.         g_iRoundEndTriggered = 1
  1533.  
  1534.         // Display round end stats to all players.
  1535.         endround_stats()
  1536. }
  1537.  
  1538. endround_stats()
  1539. {
  1540.         // Bail out if end round stats has already been processed
  1541.         // or round end not triggered.
  1542.         if (g_iRoundEndProcessed || !g_iRoundEndTriggered)
  1543.                 return
  1544.  
  1545.         new iaPlayers[32], iPlayer, iPlayers, id
  1546.  
  1547.         get_players(iaPlayers, iPlayers)
  1548.  
  1549.         // Display attacker & victim list for all living players.
  1550.         // This will also update all round and game stats for all players
  1551.         // not killed.
  1552. #if defined STATSX_DEBUG
  1553.         log_amx("End round stats")
  1554. #endif
  1555.        
  1556.         for (iPlayer = 0; iPlayer < iPlayers; iPlayer++)
  1557.         {
  1558.                 id = iaPlayers[iPlayer]
  1559.                
  1560.                 if (g_fzShowUserStatsTime[id] == 0.0)
  1561.                 {
  1562.                         kill_stats(id)
  1563.                 }
  1564.         }
  1565.  
  1566.         g_sAwardAndScore[0] = 0
  1567.  
  1568.         // Create round awards.
  1569.         if (ShowMostDisruptive)
  1570.                 add_most_disruptive(g_sAwardAndScore)
  1571.         if (ShowBestScore)
  1572.                 add_best_score(g_sAwardAndScore)
  1573.  
  1574.         // Create round score.
  1575.         // Compensate HUD message if awards are disabled.
  1576.         if (ShowTeamScore || ShowTotalStats)
  1577.         {
  1578.                 if (ShowMostDisruptive && ShowBestScore)
  1579.                         add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n")
  1580.                 else if (ShowMostDisruptive || ShowBestScore)
  1581.                         add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n^n^n")
  1582.                 else
  1583.                         add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n^n^n^n^n")
  1584.  
  1585.                 if (ShowTeamScore)
  1586.                         add_team_score(g_sAwardAndScore)
  1587.                
  1588.                 if (ShowTotalStats)
  1589.                         add_total_stats(g_sAwardAndScore)
  1590.         }
  1591.  
  1592.         save_team_chatscore()
  1593.  
  1594.         // Get and save round end stats time.
  1595.         g_fShowStatsTime = get_gametime()
  1596.  
  1597.         // Display round end stats to all players.
  1598.         for (iPlayer = 0; iPlayer < iPlayers; iPlayer++)
  1599.         {
  1600.                 id = iaPlayers[iPlayer]
  1601.                 show_roundend_hudstats(id, 0.0)
  1602.         }
  1603.  
  1604.         // Flag round end processed.
  1605.         g_iRoundEndProcessed = 1
  1606. }
  1607.  
  1608. public eventTeamScore()
  1609. {
  1610.         new sTeamID[1 + 1], iTeamScore
  1611.         read_data(1, sTeamID, 1)
  1612.         iTeamScore = read_data(2)
  1613.         g_izTeamEventScore[(sTeamID[0] == 'C') ? 1 : 0] = iTeamScore
  1614.        
  1615.         return PLUGIN_CONTINUE
  1616. }
  1617.  
  1618. public eventIntermission()
  1619. {
  1620.         if (EndPlayer || EndTop15)
  1621.                 set_task(1.0, "end_game_stats", 900)
  1622. }
  1623.  
  1624. public end_game_stats()
  1625. {
  1626.         new iaPlayers[32], iPlayer, iPlayers, id
  1627.  
  1628.         if (EndPlayer)
  1629.         {
  1630.                 get_players(iaPlayers, iPlayers)
  1631.                
  1632.                 for (iPlayer = 0; iPlayer < iPlayers; iPlayer++)
  1633.                 {
  1634.                         id = iaPlayers[iPlayer]
  1635.                        
  1636.                         if (!g_izStatsSwitch[id])
  1637.                                 continue        // Do not show any stats
  1638.                        
  1639.                         cmdStatsMe(iaPlayers[iPlayer])
  1640.                 }
  1641.         }
  1642.         else if (EndTop15)
  1643.         {
  1644.                 get_players(iaPlayers, iPlayers)
  1645.                 format_top15(g_sBuffer)
  1646.                
  1647.                 for (iPlayer = 0; iPlayer < iPlayers; iPlayer++)
  1648.                 {
  1649.                         id = iaPlayers[iPlayer]
  1650.                        
  1651.                         if (!g_izStatsSwitch[id])
  1652.                                 continue        // Do not show any stats
  1653.                        
  1654.                         show_motd(iaPlayers[iPlayer], g_sBuffer, "Top 15")
  1655.                 }
  1656.         }
  1657.        
  1658.         return PLUGIN_CONTINUE
  1659. }
  1660.  
  1661. public eventSpecMode(id)
  1662. {
  1663.         new sData[12]
  1664.         read_data(2, sData, 11)
  1665.         g_izSpecMode[id] = (sData[10] == '2')
  1666.        
  1667.         return PLUGIN_CONTINUE
  1668. }
  1669.  
  1670. public eventShowRank(id)
  1671. {
  1672.         if (SpecRankInfo && g_izSpecMode[id])
  1673.         {
  1674.                 new iPlayer = read_data(2)
  1675.                
  1676.                 if (is_user_connected(iPlayer))
  1677.                 {
  1678.                         new izStats[8], izBody[8]
  1679.                         new iRankPos, iRankMax
  1680.                        
  1681.                         get_user_name(iPlayer, t_sName, MAX_NAME_LENGTH)
  1682.                        
  1683.                         iRankPos = get_user_stats(iPlayer, izStats, izBody)
  1684.                         iRankMax = get_statsnum()
  1685.                        
  1686.                         set_hudtype_specmode()
  1687.                         ShowSyncHudMsg(id, g_HudSync_SpecInfo, "%L", id, "X_RANK_IS", t_sName, iRankPos, iRankMax)
  1688.                 }
  1689.         }
  1690.        
  1691.         return PLUGIN_CONTINUE
  1692. }
  1693.  
  1694. public client_connect(id)
  1695. {
  1696.         if (ShowStats)
  1697.         {
  1698.                 get_user_info(id, "_amxstatsx", t_sText, MAX_TEXT_LENGTH)
  1699.                 g_izStatsSwitch[id] = (t_sText[0]) ? str_to_num(t_sText) : -1
  1700.         }
  1701.         else
  1702.                 g_izStatsSwitch[id] = 0
  1703.  
  1704.         g_izKilled[id][KILLED_KILLER_ID] = 0
  1705.         g_izKilled[id][KILLED_KILLER_STATSFIX] = 0
  1706.         g_izShowStatsFlags[id] = 0              // Clear all flags
  1707.         g_fzShowUserStatsTime[id] = 0.0
  1708.  
  1709.         return PLUGIN_CONTINUE
  1710. }