Parent Directory
|
Revision Log
Revision 44 - (view) (download)
1 : | ian | 44 | /* 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 : | |||
1033 : | format_kill_vinfo(id, 0, g_sBuffer) | ||
1034 : | client_print(id, print_chat, "* %s", g_sBuffer) | ||
1035 : | |||
1036 : | return PLUGIN_CONTINUE | ||
1037 : | } | ||
1038 : | |||
1039 : | // Display user rank | ||
1040 : | public cmdRank(id) | ||
1041 : | { | ||
1042 : | if (!SayRank) | ||
1043 : | { | ||
1044 : | client_print(id, print_chat, "%L", id, "DISABLED_MSG") | ||
1045 : | return PLUGIN_HANDLED | ||
1046 : | } | ||
1047 : | |||
1048 : | new izStats[8], izBody[8] | ||
1049 : | new iRankPos, iRankMax | ||
1050 : | new Float:fEff, Float:fAcc | ||
1051 : | |||
1052 : | iRankPos = get_user_stats(id, izStats, izBody) | ||
1053 : | iRankMax = get_statsnum() | ||
1054 : | |||
1055 : | fEff = effec(izStats) | ||
1056 : | fAcc = accuracy(izStats) | ||
1057 : | |||
1058 : | client_print(id, print_chat, "* %L", id, "YOUR_RANK_IS", iRankPos, iRankMax, izStats[STATS_KILLS], izStats[STATS_HITS], fEff, fAcc) | ||
1059 : | |||
1060 : | return PLUGIN_CONTINUE | ||
1061 : | } | ||
1062 : | |||
1063 : | // Report user weapon status to team. | ||
1064 : | public cmdReport(id) | ||
1065 : | { | ||
1066 : | if (!SayReport) | ||
1067 : | { | ||
1068 : | client_print(id, print_chat, "%L", id, "DISABLED_MSG") | ||
1069 : | return PLUGIN_HANDLED | ||
1070 : | } | ||
1071 : | |||
1072 : | new iWeapon, iClip, iAmmo, iHealth, iArmor | ||
1073 : | |||
1074 : | iWeapon = get_user_weapon(id, iClip, iAmmo) | ||
1075 : | |||
1076 : | if (iWeapon != 0) | ||
1077 : | xmod_get_wpnname(iWeapon, t_sWpn, MAX_WEAPON_LENGTH) | ||
1078 : | |||
1079 : | iHealth = get_user_health(id) | ||
1080 : | iArmor = get_user_armor(id) | ||
1081 : | |||
1082 : | new lWeapon[16] | ||
1083 : | |||
1084 : | format(lWeapon, 15, "%L", id, "WEAPON") | ||
1085 : | strtolower(lWeapon) | ||
1086 : | |||
1087 : | if (iClip >= 0) | ||
1088 : | { | ||
1089 : | 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) | ||
1090 : | } | ||
1091 : | else | ||
1092 : | format(g_sBuffer, MAX_BUFFER_LENGTH, "%s: %s, %L: %d, %L: %d", lWeapon, t_sWpn[7], LANG_SERVER, "HEALTH", iHealth, LANG_SERVER, "ARMOR", iArmor) | ||
1093 : | |||
1094 : | engclient_cmd(id, "say_team", g_sBuffer) | ||
1095 : | |||
1096 : | return PLUGIN_CONTINUE | ||
1097 : | } | ||
1098 : | |||
1099 : | // Display team map score | ||
1100 : | public cmdScore(id) | ||
1101 : | { | ||
1102 : | if (!SayScore) | ||
1103 : | { | ||
1104 : | client_print(id, print_chat, "%L", id, "DISABLED_MSG") | ||
1105 : | return PLUGIN_HANDLED | ||
1106 : | } | ||
1107 : | |||
1108 : | client_print(id, print_chat, "%L: %s", id, "GAME_SCORE", g_sScore) | ||
1109 : | |||
1110 : | return PLUGIN_CONTINUE | ||
1111 : | } | ||
1112 : | |||
1113 : | // Client switch to enable or disable stats announcements. | ||
1114 : | public cmdSwitch(id) | ||
1115 : | { | ||
1116 : | g_izStatsSwitch[id] = (g_izStatsSwitch[id]) ? 0 : -1 | ||
1117 : | num_to_str(g_izStatsSwitch[id], t_sText, MAX_TEXT_LENGTH) | ||
1118 : | client_cmd(id, "setinfo _amxstatsx %s", t_sText) | ||
1119 : | |||
1120 : | new lEnDis[32] | ||
1121 : | |||
1122 : | format(lEnDis, 31, "%L", id, g_izStatsSwitch[id] ? "ENABLED" : "DISABLED") | ||
1123 : | client_print(id, print_chat, "* %L", id, "STATS_ANNOUNCE", lEnDis) | ||
1124 : | |||
1125 : | return PLUGIN_CONTINUE | ||
1126 : | } | ||
1127 : | |||
1128 : | // Player stats menu. | ||
1129 : | public cmdStats(id) | ||
1130 : | { | ||
1131 : | if (!SayStatsAll) | ||
1132 : | { | ||
1133 : | client_print(id, print_chat, "%L", id, "DISABLED_MSG") | ||
1134 : | return PLUGIN_HANDLED | ||
1135 : | } | ||
1136 : | |||
1137 : | showStatsMenu(id, g_izUserMenuPosition[id] = 0) | ||
1138 : | |||
1139 : | return PLUGIN_CONTINUE | ||
1140 : | } | ||
1141 : | |||
1142 : | //-------------------------------- | ||
1143 : | // Menu | ||
1144 : | //-------------------------------- | ||
1145 : | |||
1146 : | public actionStatsMenu(id, key) | ||
1147 : | { | ||
1148 : | switch (key) | ||
1149 : | { | ||
1150 : | // Key '1' to '7', execute action on this option | ||
1151 : | case 0..6: | ||
1152 : | { | ||
1153 : | new iOption, iIndex | ||
1154 : | iOption = (g_izUserMenuPosition[id] * PPL_MENU_OPTIONS) + key | ||
1155 : | |||
1156 : | if (iOption >= 0 && iOption < 32) | ||
1157 : | { | ||
1158 : | iIndex = g_izUserMenuPlayers[id][iOption] | ||
1159 : | |||
1160 : | if (is_user_connected(iIndex)) | ||
1161 : | { | ||
1162 : | switch (g_izUserMenuAction[id]) | ||
1163 : | { | ||
1164 : | case 0: format_stats(iIndex, g_sBuffer) | ||
1165 : | case 1: format_rankstats(iIndex, g_sBuffer, id) | ||
1166 : | default: g_sBuffer[0] = 0 | ||
1167 : | } | ||
1168 : | |||
1169 : | if (g_sBuffer[0]) | ||
1170 : | { | ||
1171 : | get_user_name(iIndex, t_sName, MAX_NAME_LENGTH) | ||
1172 : | show_motd(id, g_sBuffer, t_sName) | ||
1173 : | } | ||
1174 : | } | ||
1175 : | } | ||
1176 : | |||
1177 : | showStatsMenu(id, g_izUserMenuPosition[id]) | ||
1178 : | } | ||
1179 : | // Key '8', change action | ||
1180 : | case 7: | ||
1181 : | { | ||
1182 : | g_izUserMenuAction[id]++ | ||
1183 : | |||
1184 : | if (g_izUserMenuAction[id] >= MAX_PPL_MENU_ACTIONS) | ||
1185 : | g_izUserMenuAction[id] = 0 | ||
1186 : | |||
1187 : | showStatsMenu(id, g_izUserMenuPosition[id]) | ||
1188 : | } | ||
1189 : | // Key '9', select next page of options | ||
1190 : | case 8: showStatsMenu(id, ++g_izUserMenuPosition[id]) | ||
1191 : | // Key '10', cancel or go back to previous menu | ||
1192 : | case 9: | ||
1193 : | { | ||
1194 : | if (g_izUserMenuPosition[id] > 0) | ||
1195 : | showStatsMenu(id, --g_izUserMenuPosition[id]) | ||
1196 : | } | ||
1197 : | } | ||
1198 : | |||
1199 : | return PLUGIN_HANDLED | ||
1200 : | } | ||
1201 : | |||
1202 : | new g_izUserMenuActionText[MAX_PPL_MENU_ACTIONS][] = {"Show stats", "Show rank stats"} | ||
1203 : | |||
1204 : | showStatsMenu(id, iMenuPos) | ||
1205 : | { | ||
1206 : | new iLen, iKeyMask, iPlayers | ||
1207 : | new iUserIndex, iMenuPosMax, iMenuOption, iMenuOptionMax | ||
1208 : | |||
1209 : | get_players(g_izUserMenuPlayers[id], iPlayers) | ||
1210 : | iMenuPosMax = ((iPlayers - 1) / PPL_MENU_OPTIONS) + 1 | ||
1211 : | |||
1212 : | // If menu pos does not excist use last menu (if players has left) | ||
1213 : | if (iMenuPos >= iMenuPosMax) | ||
1214 : | iMenuPos = iMenuPosMax - 1 | ||
1215 : | |||
1216 : | iUserIndex = iMenuPos * PPL_MENU_OPTIONS | ||
1217 : | iLen = format(g_sBuffer, MAX_BUFFER_LENGTH, "\y%L\R%d/%d^n\w^n", id, "SERVER_STATS", iMenuPos + 1, iMenuPosMax) | ||
1218 : | iMenuOptionMax = iPlayers - iUserIndex | ||
1219 : | |||
1220 : | if (iMenuOptionMax > PPL_MENU_OPTIONS) | ||
1221 : | iMenuOptionMax = PPL_MENU_OPTIONS | ||
1222 : | |||
1223 : | for (iMenuOption = 0; iMenuOption < iMenuOptionMax; iMenuOption++) | ||
1224 : | { | ||
1225 : | get_user_name(g_izUserMenuPlayers[id][iUserIndex++], t_sName, MAX_NAME_LENGTH) | ||
1226 : | iKeyMask |= (1<<iMenuOption) | ||
1227 : | iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "%d. %s^n\w", iMenuOption + 1, t_sName) | ||
1228 : | } | ||
1229 : | |||
1230 : | iKeyMask |= MENU_KEY_8|MENU_KEY_0 | ||
1231 : | iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n8. %s^n\w", g_izUserMenuActionText[g_izUserMenuAction[id]]) | ||
1232 : | |||
1233 : | if (iPlayers > iUserIndex) | ||
1234 : | { | ||
1235 : | iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n9. %L...", id, "MORE") | ||
1236 : | iKeyMask |= MENU_KEY_9 | ||
1237 : | } | ||
1238 : | |||
1239 : | if (iMenuPos > 0) | ||
1240 : | iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n0. %L", id, "BACK") | ||
1241 : | else | ||
1242 : | iLen += format(g_sBuffer[iLen], MAX_BUFFER_LENGTH - iLen, "^n0. %L", id, "EXIT") | ||
1243 : | |||
1244 : | show_menu(id, iKeyMask, g_sBuffer, -1, "Server Stats") | ||
1245 : | |||
1246 : | return PLUGIN_HANDLED | ||
1247 : | } | ||
1248 : | |||
1249 : | //------------------------------------------------------------ | ||
1250 : | // Plugin events | ||
1251 : | //------------------------------------------------------------ | ||
1252 : | |||
1253 : | // Reset game stats on game start and restart. | ||
1254 : | public eventStartGame() | ||
1255 : | { | ||
1256 : | read_data(2, t_sText, MAX_TEXT_LENGTH) | ||
1257 : | |||
1258 : | if (t_sText[6] == 'w') | ||
1259 : | { | ||
1260 : | read_data(3, t_sText, MAX_TEXT_LENGTH) | ||
1261 : | g_fStartGame = get_gametime() + float(str_to_num(t_sText)) | ||
1262 : | } | ||
1263 : | else | ||
1264 : | g_fStartGame = get_gametime() | ||
1265 : | |||
1266 : | return PLUGIN_CONTINUE | ||
1267 : | } | ||
1268 : | |||
1269 : | // Round start | ||
1270 : | public eventStartRound() | ||
1271 : | { | ||
1272 : | new iTeam, id, i | ||
1273 : | |||
1274 : | new Float:roundtime = get_cvar_float("mp_roundtime"); | ||
1275 : | 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 | ||
1276 : | { | ||
1277 : | #if defined STATSX_DEBUG | ||
1278 : | log_amx("Reset round stats") | ||
1279 : | #endif | ||
1280 : | |||
1281 : | // Reset game stats on game start and restart. | ||
1282 : | if (g_fStartGame > 0.0 && g_fStartGame <= get_gametime()) | ||
1283 : | { | ||
1284 : | #if defined STATSX_DEBUG | ||
1285 : | log_amx("Reset game stats") | ||
1286 : | #endif | ||
1287 : | g_fStartGame = 0.0 | ||
1288 : | |||
1289 : | // Clear team and game stats. | ||
1290 : | for (iTeam = 0; iTeam < MAX_TEAMS; iTeam++) | ||
1291 : | { | ||
1292 : | g_izTeamEventScore[iTeam] = 0 | ||
1293 : | |||
1294 : | for (i = 0; i < 8; i++) | ||
1295 : | g_izTeamGameStats[iTeam][i] = 0 | ||
1296 : | } | ||
1297 : | |||
1298 : | // Clear game stats, incl '0' that is sum of all users. | ||
1299 : | for (id = 0; id < MAX_PLAYERS; id++) | ||
1300 : | { | ||
1301 : | for (i = 0; i < 8; i++) | ||
1302 : | g_izUserGameStats[id][i] = 0 | ||
1303 : | } | ||
1304 : | } | ||
1305 : | |||
1306 : | // Update team score with "TeamScore" event values and | ||
1307 : | // clear team round stats. | ||
1308 : | for (iTeam = 0; iTeam < MAX_TEAMS; iTeam++) | ||
1309 : | { | ||
1310 : | g_izTeamScore[iTeam] = g_izTeamEventScore[iTeam] | ||
1311 : | |||
1312 : | for (i = 0; i < 8; i++) | ||
1313 : | g_izTeamRndStats[iTeam][i] = 0 | ||
1314 : | } | ||
1315 : | |||
1316 : | // Clear user round stats, incl '0' that is sum of all users. | ||
1317 : | for (id = 0; id < MAX_PLAYERS; id++) | ||
1318 : | { | ||
1319 : | g_izUserRndName[id][0] = 0 | ||
1320 : | |||
1321 : | for (i = 0; i < 8; i++) | ||
1322 : | g_izUserRndStats[id][i] = 0 | ||
1323 : | |||
1324 : | g_fzShowUserStatsTime[id] = 0.0 | ||
1325 : | } | ||
1326 : | |||
1327 : | // Allow end round stats and reset end round triggered indicator. | ||
1328 : | g_iRoundEndTriggered = 0 | ||
1329 : | g_iRoundEndProcessed = 0 | ||
1330 : | g_fShowStatsTime = 0.0 | ||
1331 : | |||
1332 : | // Update local configuration vars with value in cvars. | ||
1333 : | get_config_cvars() | ||
1334 : | } | ||
1335 : | |||
1336 : | return PLUGIN_CONTINUE | ||
1337 : | } | ||
1338 : | |||
1339 : | // Reset killer info on round restart. | ||
1340 : | public eventResetHud(id) | ||
1341 : | { | ||
1342 : | new args[1] | ||
1343 : | args[0] = id | ||
1344 : | |||
1345 : | if (g_iPluginMode & MODE_HUD_DELAY) | ||
1346 : | set_task(0.01, "delay_resethud", 200 + id, args, 1) | ||
1347 : | else | ||
1348 : | delay_resethud(args) | ||
1349 : | |||
1350 : | return PLUGIN_CONTINUE | ||
1351 : | } | ||
1352 : | |||
1353 : | public delay_resethud(args[]) | ||
1354 : | { | ||
1355 : | new id = args[0] | ||
1356 : | new Float:fGameTime | ||
1357 : | |||
1358 : | // Show user and score round stats after HUD-reset | ||
1359 : | #if defined STATSX_DEBUG | ||
1360 : | log_amx("Reset HUD for #%d", id) | ||
1361 : | #endif | ||
1362 : | fGameTime = get_gametime() | ||
1363 : | show_user_hudstats(id, fGameTime) | ||
1364 : | show_roundend_hudstats(id, fGameTime) | ||
1365 : | |||
1366 : | // Reset round stats | ||
1367 : | g_izKilled[id][KILLED_KILLER_ID] = 0 | ||
1368 : | g_izKilled[id][KILLED_KILLER_STATSFIX] = 0 | ||
1369 : | g_izShowStatsFlags[id] = -1 // Initialize flags | ||
1370 : | g_fzShowUserStatsTime[id] = 0.0 | ||
1371 : | g_izUserAttackerDistance[id] = 0 | ||
1372 : | |||
1373 : | for (new i = 0; i < MAX_PLAYERS; i++) | ||
1374 : | g_izUserVictimDistance[id][i] = 0 | ||
1375 : | |||
1376 : | return PLUGIN_CONTINUE | ||
1377 : | } | ||
1378 : | |||
1379 : | // Save killer info on death. | ||
1380 : | public client_death(killer, victim, wpnindex, hitplace, TK) | ||
1381 : | { | ||
1382 : | // Bail out if no killer. | ||
1383 : | if (!killer) | ||
1384 : | return PLUGIN_CONTINUE | ||
1385 : | |||
1386 : | if (killer != victim) | ||
1387 : | { | ||
1388 : | new iaVOrigin[3], iaKOrigin[3] | ||
1389 : | new iDistance | ||
1390 : | |||
1391 : | get_user_origin(victim, iaVOrigin) | ||
1392 : | get_user_origin(killer, iaKOrigin) | ||
1393 : | |||
1394 : | g_izKilled[victim][KILLED_KILLER_ID] = killer | ||
1395 : | g_izKilled[victim][KILLED_KILLER_HEALTH] = get_user_health(killer) | ||
1396 : | g_izKilled[victim][KILLED_KILLER_ARMOUR] = get_user_armor(killer) | ||
1397 : | g_izKilled[victim][KILLED_KILLER_STATSFIX] = 0 | ||
1398 : | |||
1399 : | iDistance = get_distance(iaVOrigin, iaKOrigin) | ||
1400 : | g_izUserAttackerDistance[victim] = iDistance | ||
1401 : | g_izUserVictimDistance[killer][victim] = iDistance | ||
1402 : | } | ||
1403 : | |||
1404 : | g_izKilled[victim][KILLED_TEAM] = get_user_team(victim) | ||
1405 : | g_izKilled[victim][KILLED_KILLER_STATSFIX] = 1 | ||
1406 : | |||
1407 : | // Display kill stats for the player if round | ||
1408 : | // end stats was not processed. | ||
1409 : | if (!g_iRoundEndProcessed) | ||
1410 : | kill_stats(victim) | ||
1411 : | |||
1412 : | return PLUGIN_CONTINUE | ||
1413 : | } | ||
1414 : | |||
1415 : | // Display hudmessage stats on death. | ||
1416 : | // This will also update all round and game stats. | ||
1417 : | // Must be called at least once per round. | ||
1418 : | kill_stats(id) | ||
1419 : | { | ||
1420 : | // Bail out if user stats timer is non-zero, | ||
1421 : | // ie function already called. | ||
1422 : | if (g_fzShowUserStatsTime[id] > 0.0) | ||
1423 : | { | ||
1424 : | return | ||
1425 : | } | ||
1426 : | |||
1427 : | new team = get_user_team(id) | ||
1428 : | if (team < 1 || team > 2) | ||
1429 : | { | ||
1430 : | return | ||
1431 : | } | ||
1432 : | |||
1433 : | // Flag kill stats displayed for this player. | ||
1434 : | g_fzShowUserStatsTime[id] = get_gametime() | ||
1435 : | |||
1436 : | // Add user death stats to user round stats | ||
1437 : | new izStats[8], izBody[8] | ||
1438 : | new iTeam, i | ||
1439 : | new iKiller | ||
1440 : | |||
1441 : | iKiller = g_izKilled[id][KILLED_KILLER_ID] | ||
1442 : | |||
1443 : | // Get user's team (if dead use the saved team) | ||
1444 : | if (iKiller) | ||
1445 : | iTeam = g_izKilled[id][KILLED_TEAM] - 1 | ||
1446 : | else | ||
1447 : | iTeam = get_user_team(id) - 1 | ||
1448 : | |||
1449 : | get_user_name(id, g_izUserRndName[id], MAX_NAME_LENGTH) | ||
1450 : | |||
1451 : | if (get_user_rstats(id, izStats, izBody)) | ||
1452 : | { | ||
1453 : | // Update user's team round stats | ||
1454 : | if (iTeam >= 0 && iTeam < MAX_TEAMS) | ||
1455 : | { | ||
1456 : | for (i = 0; i < 8; i++) | ||
1457 : | { | ||
1458 : | g_izTeamRndStats[iTeam][i] += izStats[i] | ||
1459 : | g_izTeamGameStats[iTeam][i] += izStats[i] | ||
1460 : | g_izUserRndStats[0][i] += izStats[i] | ||
1461 : | g_izUserGameStats[0][i] += izStats[i] | ||
1462 : | } | ||
1463 : | } | ||
1464 : | |||
1465 : | // Update user's round stats | ||
1466 : | if (g_izUserUserID[id] == get_user_userid(id)) | ||
1467 : | { | ||
1468 : | for (i = 0; i < 8; i++) | ||
1469 : | { | ||
1470 : | g_izUserRndStats[id][i] += izStats[i] | ||
1471 : | g_izUserGameStats[id][i] += izStats[i] | ||
1472 : | } | ||
1473 : | } else { | ||
1474 : | g_izUserUserID[id] = get_user_userid(id) | ||
1475 : | |||
1476 : | for (i = 0; i < 8; i++) | ||
1477 : | { | ||
1478 : | g_izUserRndStats[id][i] = izStats[i] | ||
1479 : | g_izUserGameStats[id][i] = izStats[i] | ||
1480 : | } | ||
1481 : | } | ||
1482 : | |||
1483 : | } // endif (get_user_rstats()) | ||
1484 : | |||
1485 : | // Report stats in the chat section, if player is killed. | ||
1486 : | if (KillerChat && iKiller && iKiller != id) | ||
1487 : | { | ||
1488 : | if (format_kill_ainfo(id, iKiller, g_sBuffer)) | ||
1489 : | { | ||
1490 : | client_print(id, print_chat, "* %s", g_sBuffer) | ||
1491 : | format_kill_vinfo(id, iKiller, g_sBuffer) | ||
1492 : | } | ||
1493 : | |||
1494 : | client_print(id, print_chat, "* %s", g_sBuffer) | ||
1495 : | } | ||
1496 : | |||
1497 : | // Display player stats info. | ||
1498 : | #if defined STATSX_DEBUG | ||
1499 : | log_amx("Kill stats for #%d", id) | ||
1500 : | #endif | ||
1501 : | show_user_hudstats(id, 0.0) | ||
1502 : | } | ||
1503 : | |||
1504 : | public eventEndRound() | ||
1505 : | { | ||
1506 : | // Update local configuration vars with value in cvars. | ||
1507 : | get_config_cvars() | ||
1508 : | |||
1509 : | // If first end round event in the round, calculate team score. | ||
1510 : | if (!g_iRoundEndTriggered) | ||
1511 : | { | ||
1512 : | read_data(2, t_sText, MAX_TEXT_LENGTH) | ||
1513 : | |||
1514 : | if (t_sText[7] == 't') // Terrorist wins | ||
1515 : | g_izTeamScore[0]++ | ||
1516 : | else if (t_sText[7] == 'c') // CT wins | ||
1517 : | g_izTeamScore[1]++ | ||
1518 : | } | ||
1519 : | |||
1520 : | set_task(0.3, "ERTask", 997) | ||
1521 : | |||
1522 : | return PLUGIN_CONTINUE | ||
1523 : | } | ||
1524 : | |||
1525 : | public ERTask() | ||
1526 : | { | ||
1527 : | // Flag round end triggered. | ||
1528 : | g_iRoundEndTriggered = 1 | ||
1529 : | |||
1530 : | // Display round end stats to all players. | ||
1531 : | endround_stats() | ||
1532 : | } | ||
1533 : | |||
1534 : | endround_stats() | ||
1535 : | { | ||
1536 : | // Bail out if end round stats has already been processed | ||
1537 : | // or round end not triggered. | ||
1538 : | if (g_iRoundEndProcessed || !g_iRoundEndTriggered) | ||
1539 : | return | ||
1540 : | |||
1541 : | new iaPlayers[32], iPlayer, iPlayers, id | ||
1542 : | |||
1543 : | get_players(iaPlayers, iPlayers) | ||
1544 : | |||
1545 : | // Display attacker & victim list for all living players. | ||
1546 : | // This will also update all round and game stats for all players | ||
1547 : | // not killed. | ||
1548 : | #if defined STATSX_DEBUG | ||
1549 : | log_amx("End round stats") | ||
1550 : | #endif | ||
1551 : | |||
1552 : | for (iPlayer = 0; iPlayer < iPlayers; iPlayer++) | ||
1553 : | { | ||
1554 : | id = iaPlayers[iPlayer] | ||
1555 : | |||
1556 : | if (g_fzShowUserStatsTime[id] == 0.0) | ||
1557 : | { | ||
1558 : | kill_stats(id) | ||
1559 : | } | ||
1560 : | } | ||
1561 : | |||
1562 : | g_sAwardAndScore[0] = 0 | ||
1563 : | |||
1564 : | // Create round awards. | ||
1565 : | if (ShowMostDisruptive) | ||
1566 : | add_most_disruptive(g_sAwardAndScore) | ||
1567 : | if (ShowBestScore) | ||
1568 : | add_best_score(g_sAwardAndScore) | ||
1569 : | |||
1570 : | // Create round score. | ||
1571 : | // Compensate HUD message if awards are disabled. | ||
1572 : | if (ShowTeamScore || ShowTotalStats) | ||
1573 : | { | ||
1574 : | if (ShowMostDisruptive && ShowBestScore) | ||
1575 : | add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n") | ||
1576 : | else if (ShowMostDisruptive || ShowBestScore) | ||
1577 : | add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n^n^n") | ||
1578 : | else | ||
1579 : | add(g_sAwardAndScore, MAX_BUFFER_LENGTH, "^n^n^n^n^n^n") | ||
1580 : | |||
1581 : | if (ShowTeamScore) | ||
1582 : | add_team_score(g_sAwardAndScore) | ||
1583 : | |||
1584 : | if (ShowTotalStats) | ||
1585 : | add_total_stats(g_sAwardAndScore) | ||
1586 : | } | ||
1587 : | |||
1588 : | save_team_chatscore() | ||
1589 : | |||
1590 : | // Get and save round end stats time. | ||
1591 : | g_fShowStatsTime = get_gametime() | ||
1592 : | |||
1593 : | // Display round end stats to all players. | ||
1594 : | for (iPlayer = 0; iPlayer < iPlayers; iPlayer++) | ||
1595 : | { | ||
1596 : | id = iaPlayers[iPlayer] | ||
1597 : | show_roundend_hudstats(id, 0.0) | ||
1598 : | } | ||
1599 : | |||
1600 : | // Flag round end processed. | ||
1601 : | g_iRoundEndProcessed = 1 | ||
1602 : | } | ||
1603 : | |||
1604 : | public eventTeamScore() | ||
1605 : | { | ||
1606 : | new sTeamID[1 + 1], iTeamScore | ||
1607 : | read_data(1, sTeamID, 1) | ||
1608 : | iTeamScore = read_data(2) | ||
1609 : | g_izTeamEventScore[(sTeamID[0] == 'C') ? 1 : 0] = iTeamScore | ||
1610 : | |||
1611 : | return PLUGIN_CONTINUE | ||
1612 : | } | ||
1613 : | |||
1614 : | public eventIntermission() | ||
1615 : | { | ||
1616 : | if (EndPlayer || EndTop15) | ||
1617 : | set_task(1.0, "end_game_stats", 900) | ||
1618 : | } | ||
1619 : | |||
1620 : | public end_game_stats() | ||
1621 : | { | ||
1622 : | new iaPlayers[32], iPlayer, iPlayers, id | ||
1623 : | |||
1624 : | if (EndPlayer) | ||
1625 : | { | ||
1626 : | get_players(iaPlayers, iPlayers) | ||
1627 : | |||
1628 : | for (iPlayer = 0; iPlayer < iPlayers; iPlayer++) | ||
1629 : | { | ||
1630 : | id = iaPlayers[iPlayer] | ||
1631 : | |||
1632 : | if (!g_izStatsSwitch[id]) | ||
1633 : | continue // Do not show any stats | ||
1634 : | |||
1635 : | cmdStatsMe(iaPlayers[iPlayer]) | ||
1636 : | } | ||
1637 : | } | ||
1638 : | else if (EndTop15) | ||
1639 : | { | ||
1640 : | get_players(iaPlayers, iPlayers) | ||
1641 : | format_top15(g_sBuffer) | ||
1642 : | |||
1643 : | for (iPlayer = 0; iPlayer < iPlayers; iPlayer++) | ||
1644 : | { | ||
1645 : | id = iaPlayers[iPlayer] | ||
1646 : | |||
1647 : | if (!g_izStatsSwitch[id]) | ||
1648 : | continue // Do not show any stats | ||
1649 : | |||
1650 : | show_motd(iaPlayers[iPlayer], g_sBuffer, "Top 15") | ||
1651 : | } | ||
1652 : | } | ||
1653 : | |||
1654 : | return PLUGIN_CONTINUE | ||
1655 : | } | ||
1656 : | |||
1657 : | public eventSpecMode(id) | ||
1658 : | { | ||
1659 : | new sData[12] | ||
1660 : | read_data(2, sData, 11) | ||
1661 : | g_izSpecMode[id] = (sData[10] == '2') | ||
1662 : | |||
1663 : | return PLUGIN_CONTINUE | ||
1664 : | } | ||
1665 : | |||
1666 : | public eventShowRank(id) | ||
1667 : | { | ||
1668 : | if (SpecRankInfo && g_izSpecMode[id]) | ||
1669 : | { | ||
1670 : | new iPlayer = read_data(2) | ||
1671 : | |||
1672 : | if (is_user_connected(iPlayer)) | ||
1673 : | { | ||
1674 : | new izStats[8], izBody[8] | ||
1675 : | new iRankPos, iRankMax | ||
1676 : | |||
1677 : | get_user_name(iPlayer, t_sName, MAX_NAME_LENGTH) | ||
1678 : | |||
1679 : | iRankPos = get_user_stats(iPlayer, izStats, izBody) | ||
1680 : | iRankMax = get_statsnum() | ||
1681 : | |||
1682 : | set_hudtype_specmode() | ||
1683 : | ShowSyncHudMsg(id, g_HudSync_SpecInfo, "%L", id, "X_RANK_IS", t_sName, iRankPos, iRankMax) | ||
1684 : | } | ||
1685 : | } | ||
1686 : | |||
1687 : | return PLUGIN_CONTINUE | ||
1688 : | } | ||
1689 : | |||
1690 : | public client_connect(id) | ||
1691 : | { | ||
1692 : | if (ShowStats) | ||
1693 : | { | ||
1694 : | get_user_info(id, "_amxstatsx", t_sText, MAX_TEXT_LENGTH) | ||
1695 : | g_izStatsSwitch[id] = (t_sText[0]) ? str_to_num(t_sText) : -1 | ||
1696 : | } | ||
1697 : | else | ||
1698 : | g_izStatsSwitch[id] = 0 | ||
1699 : | |||
1700 : | g_izKilled[id][KILLED_KILLER_ID] = 0 | ||
1701 : | g_izKilled[id][KILLED_KILLER_STATSFIX] = 0 | ||
1702 : | g_izShowStatsFlags[id] = 0 // Clear all flags | ||
1703 : | g_fzShowUserStatsTime[id] = 0.0 | ||
1704 : | |||
1705 : | return PLUGIN_CONTINUE | ||
1706 : | } |
Contact | ViewVC Help |
Powered by ViewVC 1.0.4 |