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