· 6 years ago · Apr 29, 2019, 09:32 AM
1#pragma semicolon 1
2
3#include < cstrike >
4#include < multicolors >
5#include < sdktools >
6#include < sdkhooks >
7
8#define VIP_FLAG ADMFLAG_CUSTOM1
9#define PREFIX "{purple}[Rangi]{default}"
10
11Database DB;
12
13ConVar cvMinPlayerRequired;
14ConVar cvKillPoints;
15ConVar cvHsPoints;
16ConVar cvDeadPoints;
17ConVar cvBombPlantPoints;
18ConVar cvBombDefusePoints;
19ConVar cvRoundWinPoints;
20ConVar cvBombPlantPointsPenalty;
21ConVar cvBombDefusePointsPenalty;
22ConVar cvRoundLosePoints;
23ConVar cvNoScopePoints;
24ConVar cvKillPointsVIP;
25ConVar cvHsPointsVIP;
26ConVar cvDeadPointsVIP;
27ConVar cvBombPlantPointsVIP;
28ConVar cvBombDefusePointsVIP;
29ConVar cvRoundWinPointsVIP;
30ConVar cvBombPlantPointsPenaltyVIP;
31ConVar cvBombDefusePointsPenaltyVIP;
32ConVar cvRoundLosePointsVIP;
33ConVar cvNoScopePointsVIP;
34
35enum ePlayerData {
36 PlayerRank = 0,
37 PlayerPoints = 1,
38 PlayerKills = 2,
39 PlayerHs = 3,
40 PlayerDeaths = 4,
41 PlayerNoScopes = 5,
42 PlayerNoScopeDistance=6,
43 PlayerTime = 7,
44 PlayerConnectTime = 8
45};
46
47enum ePointsGrant {
48 Kill = 0,
49 HS = 1,
50 Dead = 2,
51 BombPlanted = 3,
52 BombDefused = 4,
53 RoundWin = 5,
54 RoundLose = 6,
55 NoScope = 7
56};
57
58int gPlayer[MAXPLAYERS][ePlayerData];
59
60int gRankPoints[] = {
61 25,
62 50,
63 100,
64 250,
65 500,
66 750,
67 1000,
68 1250,
69 1500,
70 2000,
71 2500,
72 5000,
73 7500,
74 10000,
75 12500,
76 15000,
77 17000,
78 24000,
79 24000
80};
81
82public void OnPluginStart() {
83 HookEvent("player_death", Event_PlayerDeath);
84 HookEvent("bomb_planted", Event_BombPlanted);
85 HookEvent("bomb_defused", Event_BombDefused);
86
87 RegConsoleCmd("sm_rank", RankMenu);
88
89 char error[512];
90 DB = SQL_Connect("RankMagnet", true, error, sizeof(error));
91 if (DB == null) {
92 LogError("[RankMagnet] Could not connect do DB! Error: %s", error);
93 }
94 SQL_CreateTable();
95
96 InitConVars();
97
98}
99
100public Action RankMenu(int client, int args) {
101 Menu menu = new Menu(RankMenu_Handler);
102
103 char timeBuffer[128];
104 GetFormattedTime(gPlayer[client][PlayerTime] + (GetTime() - gPlayer[client][PlayerConnectTime]), timeBuffer, sizeof(timeBuffer));
105
106 char buffer[512];
107 Format(buffer, sizeof(buffer), "Twoje statystyki:\nRanga: %d (%d pkt.)\nKille: %d(%dHS) | Deady: %d\n NoScope'ów: %d | Najdalej: %d\n Czas online: %s", gPlayer[client][PlayerRank], gPlayer[client][PlayerPoints], gPlayer[client][PlayerKills], gPlayer[client][PlayerHs], gPlayer[client][PlayerDeaths], gPlayer[client][PlayerNoScopes], gPlayer[client][PlayerNoScopeDistance], timeBuffer);
108
109menu.SetTitle(buffer);
110
111 menu.AddItem("", "Wyjscie");
112 menu.ExitButton=false;
113 menu.Display(client, 120);
114}
115
116public int RankMenu_Handler(Handle classhandle, MenuAction action, int client, int position) {
117 if (action == MenuAction_Select) {
118 PrintToChat(client, "Wyjscie...");
119 }
120}
121
122void InitConVars() {
123 cvMinPlayerRequired = CreateConVar("rm_min_players_required", "3", "Od ilu graczy plugin ma naliczac statystyki? (def: 3)");
124 cvKillPoints = CreateConVar("rm_kill_points", "2", "Punkty za zabójstwo (def: 2)");
125 cvHsPoints = CreateConVar("rm_hs_points", "1", "Dodatkowe punkty za HS (def: 1)");
126 cvDeadPoints = CreateConVar("rm_dead_points", "1", "Ilość punktów zabieranych za śmierć (def: 1)");
127 cvBombPlantPoints = CreateConVar("rm_bomb_plant_points", "10", "Punkty za podłożenie bomby (def: 10)");
128 cvBombDefusePoints = CreateConVar("rm_bomb_defuse_points", "3", "Punkty za rozbrojenie bomby (def: 10)");
129 cvRoundWinPoints = CreateConVar("rm_round_win_points", "3", "Punkty za wygranÄ… rundÄ™ (def: 3)");
130 cvBombPlantPointsPenalty = CreateConVar("rm_bomb_plant_points_penalty", "7", "Punkty zabierane za dopuszczenie do podłożenia bomby (def: 7)");
131 cvBombDefusePointsPenalty = CreateConVar("rm_bomb_defuse_points_penalty", "7", "Punkty zabierane za dopuszczenie do rozbrojenia bomby (def: 7)");
132 cvRoundLosePoints = CreateConVar("rm_round_lose_points", "1", "Punkty zabierane za przegranÄ… rundÄ™ (def: 1)");
133 cvNoScopePoints = CreateConVar("rm_no_scope_points", "1", "Punkty za NoScope (def: 1)");
134 cvKillPointsVIP = CreateConVar("rm_kill_points_vip", "2", "Punkty za zabójstwo VIP (def: 2)");
135 cvHsPointsVIP = CreateConVar("rm_hs_points_vip", "1", "Dodatkowe punkty za HS VIP (def: 1)");
136 cvDeadPointsVIP = CreateConVar("rm_dead_points_vip", "1", "Ilość punktów zabieranych za śmierć VIP (def: 1)");
137 cvBombPlantPointsVIP = CreateConVar("rm_bomb_plant_points_vip", "10", "Punkty za podłożenie bomby VIP (def: 10)");
138 cvBombDefusePointsVIP = CreateConVar("rm_bomb_defuse_points_vip", "3", "Punkty za rozbrojenie bomby VIP (def: 10)");
139 cvRoundWinPointsVIP = CreateConVar("rm_round_win_points_vip", "3", "Punkty za wygranÄ… rundÄ™ VIP (def: 3)");
140 cvBombPlantPointsPenaltyVIP = CreateConVar("rm_bomb_plant_points_penalty_vip", "7", "Punkty zabierane za dopuszczenie do podłożenia bomby VIP (def: 7)");
141 cvBombDefusePointsPenaltyVIP = CreateConVar("rm_bomb_defuse_points_penalty_vip", "7", "Punkty zabierane za dopuszczenie do rozbrojenia bomby VIP (def: 7)");
142 cvRoundLosePointsVIP = CreateConVar("rm_round_lose_points_vip", "1", "Punkty zabierane za przegranÄ… rundÄ™ VIP (def: 1)");
143 cvNoScopePointsVIP = CreateConVar("rm_no_scope_points", "1", "Punkty za NoScope VIP (def: 1)");
144}
145
146public void OnClientPutInServer(int client) {
147 for (int i = 0; i < _:ePlayerData; i++) {
148 gPlayer[client][i] = 0;
149 }
150 SQL_LoadData(client);
151 gPlayer[client][PlayerConnectTime] = GetTime();
152}
153public void OnClientDisconnect(int client) {
154 gPlayer[client][PlayerTime] += GetTime() - gPlayer[client][PlayerConnectTime];
155 SQL_SaveData(client);
156}
157
158void SQL_CreateTable() {
159 char buffer[512];
160 Format(buffer, sizeof(buffer), "CREATE TABLE IF NOT EXISTS `RankMagnet`(`steamID` INT NOT NULL UNIQUE, `nick` VARCHAR(%d), `online` INT NOT NULL, `points` INT NOT NULL, `kills` INT NOT NULL, `hs` INT NOT NULL, `deaths` INT NOT NULL, `noScopeAmount` INT NOT NULL, `noScopeDistance` INT NOT NULL) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", MAX_NAME_LENGTH);
161 DB.Query(CreateTable_Handler, buffer);
162}
163
164public void CreateTable_Handler(Database db, DBResultSet results, const char[] error, any data) {
165 if (db == null)
166 LogError("[RankMagnet] Create table query failed! %s", error);
167}
168
169void SQL_LoadData(int client) {
170 char buffer[1024];
171 Format(buffer, sizeof(buffer), "SELECT online,points,kills,hs,deaths,noScopeAmount,noScopeDistance FROM `RankMagnet` WHERE `steamID`=%d", GetSteamAccountID(client));
172 DB.Query(LoadData_Handler, buffer, client);
173}
174
175public void LoadData_Handler(Database db, DBResultSet results, const char[] error, int client) {
176 if (results == null) {
177 LogError("[RankMagnet] Load data query failed! %s", error);
178 return;
179 }
180
181 if (results.RowCount == 0) {
182 char buffer[1024];
183 Format(buffer, sizeof(buffer), "INSERT INTO `RankMagnet` VALUES(%d,'%N',0,0,0,0,0,0,0)", GetSteamAccountID(client), client);
184 DB.Query(InsertData_Handler, buffer);
185 } else {
186 while (SQL_FetchRow(results)) {
187 gPlayer[client][PlayerTime] = SQL_FetchInt(results, 0);
188 gPlayer[client][PlayerPoints] = SQL_FetchInt(results, 1);
189 gPlayer[client][PlayerKills] = SQL_FetchInt(results, 2);
190 gPlayer[client][PlayerHs] = SQL_FetchInt(results, 3);
191 gPlayer[client][PlayerDeaths] = SQL_FetchInt(results, 4);
192 gPlayer[client][PlayerNoScopes] = SQL_FetchInt(results, 5);
193 gPlayer[client][PlayerNoScopeDistance] = SQL_FetchInt(results, 6);
194 }
195 }
196}
197
198public void InsertData_Handler(Database db, DBResultSet results, const char[] error, any data) {
199 if (db == null)
200 LogError("[RankMagnet] Insert data query failed! %s", error);
201}
202
203void SQL_SaveData(int client) {
204 char buffer[1024];
205 Format(buffer, sizeof(buffer), "UPDATE RankMagnet SET nick`='%N',online`=%d,`points`=%d,`kills`=%d,`hs`=%d,`deaths`=%d,`noScopeAmount`=%d,`noScopeDistance`=%d WHERE `steamID`=%d", client, gPlayer[client][PlayerTime], gPlayer[client][PlayerPoints], gPlayer[client][PlayerKills], gPlayer[client][PlayerHs], gPlayer[client][PlayerDeaths], gPlayer[client][PlayerNoScopes], gPlayer[client][PlayerNoScopeDistance], GetSteamAccountID(client));
206 DB.Query(SaveData_Handler, buffer, client);
207}
208
209public void SaveData_Handler(Database db, DBResultSet results, const char[] error, any data) {
210 if (db == null)
211 LogError("[RankMagnet] Save data query failed! %s", error);
212}
213
214public void OnMapStart() {
215
216 char sBuffer[64];
217 for (int i = 1; i < sizeof(gRankPoints) + 1; i++) {
218 Format(sBuffer, sizeof(sBuffer), "materials/valkiria_overlays/rank_%d.vmt", i);
219 AddFileToDownloadsTable(sBuffer);
220 Format(sBuffer, sizeof(sBuffer), "materials/valkiria_overlays/rank_%d.vtf", i);
221 AddFileToDownloadsTable(sBuffer);
222 Format(sBuffer, sizeof(sBuffer), "valkiria_overlays/rank_%d.vmt", i);
223 PrecacheDecal(sBuffer, true);
224 Format(sBuffer, sizeof(sBuffer), "valkiria_overlays/rank_%d.vmt", i);
225 PrecacheDecal(sBuffer, true);
226 }
227
228 AddFileToDownloadsTable("sound/valkiria/rangi/awans.mp3");
229 PrecacheSound("*/valkiria/rangi/awans.mp3", true);
230}
231
232// przyznaje punkty, wyświetla komunikaty, wywołuje funkcję do obliczenia rangi
233void GrantPoints(int client, int type) {
234 switch (type) {
235 case Kill:
236 {
237 gPlayer[client][PlayerKills]++;
238 if (isPlayerVIP(client)) {
239 gPlayer[client][PlayerPoints] += cvKillPointsVIP.IntValue;
240 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz{green} %d{default} punkty za {lightred}zabójstwo!", PREFIX, cvKillPointsVIP.IntValue);
241 } else {
242 gPlayer[client][PlayerPoints] += cvKillPoints.IntValue;
243 CPrintToChat(client, "%s Otrzymujesz {green} %d{default} punkty za {lightred}zabójstwo!", PREFIX, cvKillPoints.IntValue);
244 }
245 }
246 case HS:
247 {
248 gPlayer[client][PlayerHs]++;
249 if (isPlayerVIP(client)) {
250 gPlayer[client][PlayerPoints] += cvHsPointsVIP.IntValue;
251 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz dodatkowo{green} %d{default} punkty za {lightred}HS!", PREFIX, cvHsPointsVIP.IntValue);
252 } else {
253 gPlayer[client][PlayerPoints] += cvHsPoints.IntValue;
254 CPrintToChat(client, "%s Otrzymujesz dodatkowo{green} %d{default} punkty za {lightred}HS!", PREFIX, cvHsPoints.IntValue);
255 }
256 }
257 case Dead:
258 {
259 gPlayer[client][PlayerDeaths]++;
260 if (isPlayerVIP(client)) {
261 gPlayer[client][PlayerPoints] -= cvDeadPointsVIP.IntValue;
262 CPrintToChat(client, "%s Jako{olive} VIP{default} tracisz %d{default} punktow za {red}smierc!", PREFIX, cvDeadPointsVIP.IntValue);
263 } else {
264 gPlayer[client][PlayerPoints] -= cvDeadPoints.IntValue;
265 CPrintToChat(client, "%s Tracisz %d{default} punktow za {red}smierc!", PREFIX, cvDeadPoints.IntValue);
266 }
267 }
268 case BombPlanted:
269 {
270 if (GetClientTeam(client) == CS_TEAM_T) {
271 if (isPlayerVIP(client)) {
272 gPlayer[client][PlayerPoints] += cvBombPlantPointsVIP.IntValue;
273 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz {green} %d{default} punkty za {lightred}Podlozenie bomby!", PREFIX, cvBombPlantPointsVIP.IntValue);
274 } else {
275 gPlayer[client][PlayerPoints] += cvBombPlantPoints.IntValue;
276 CPrintToChat(client, "%s Otrzymujesz {green} %d{default} punkty za {lightred}Podlozenie bomby!", PREFIX, cvBombPlantPoints.IntValue);
277 }
278 } else {
279 if (isPlayerVIP(client)) {
280 gPlayer[client][PlayerPoints] -= cvBombPlantPointsPenaltyVIP.IntValue;
281 CPrintToChat(client, "%s Jako{olive} VIP{default} tracisz {green} %d{default} punktow za {red}dopuszczenie do podlozenia bomby!", PREFIX, cvBombPlantPointsPenaltyVIP.IntValue);
282 } else {
283 gPlayer[client][PlayerPoints] -= cvBombPlantPointsPenalty.IntValue;
284 CPrintToChat(client, "%s Tracisz {green} %d{default} punktow za {red}dopuszczenie do podlozenia bomby!", PREFIX, cvBombPlantPointsPenalty.IntValue);
285
286 }
287 }
288
289 }
290 case BombDefused:
291 {
292 if (GetClientTeam(client) == CS_TEAM_CT) {
293 if (isPlayerVIP(client)) {
294 gPlayer[client][PlayerPoints] += cvBombDefusePointsVIP.IntValue;
295 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz {green} %d{default} punkty za {lightred}Rozbrojenie bomby!", PREFIX, cvBombDefusePointsVIP.IntValue);
296 } else {
297 gPlayer[client][PlayerPoints] += cvBombDefusePoints.IntValue;
298 CPrintToChat(client, "%s Otrzymujesz {green} %d{default} punkty za {lightred}Rozbrojenie bomby!", PREFIX, cvBombDefusePoints.IntValue);
299 }
300 } else {
301 if (isPlayerVIP(client)) {
302 gPlayer[client][PlayerPoints] -= cvBombDefusePointsPenaltyVIP.IntValue;
303 CPrintToChat(client, "%s Jako{olive} VIP{default} tracisz {green} %d{default} punktow za {red}dopuszczenie do rozbrojenia bomby!", PREFIX, cvBombDefusePointsPenaltyVIP.IntValue);
304 } else {
305 gPlayer[client][PlayerPoints] -= cvBombDefusePointsPenalty.IntValue;
306 CPrintToChat(client, "%s Tracisz {green} %d{default} punktow za {red}dopuszczenie do rozbrojenia bomby!", PREFIX, cvBombDefusePointsPenalty.IntValue);
307
308 }
309 }
310 }
311 case RoundWin:
312 {
313 if (isPlayerVIP(client)) {
314 gPlayer[client][PlayerPoints] += cvRoundWinPointsVIP.IntValue;
315 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz{green} %d{default} punkty za {lightred}Wygrana runda!", PREFIX, cvRoundWinPointsVIP.IntValue);
316 } else {
317 gPlayer[client][PlayerPoints] += cvRoundWinPoints.IntValue;
318 CPrintToChat(client, "%s Otrzymujesz{green} %d{default} punkty za {lightred}Wygrana runda!", PREFIX, cvRoundWinPoints.IntValue);
319
320 }
321 }
322 case RoundLose:
323 {
324 if (isPlayerVIP(client)) {
325 gPlayer[client][PlayerPoints] -= cvRoundLosePointsVIP.IntValue;
326 CPrintToChat(client, "%s Jako{olive} VIP{default} tracisz {green} %d{default} punktow za {red}Przegrana runde!", PREFIX, cvRoundLosePointsVIP.IntValue);
327 } else {
328 gPlayer[client][PlayerPoints] -= cvRoundLosePoints.IntValue;
329 CPrintToChat(client, "%s Tracisz {green} %d{default} punktow za {red}Przegrana runde!", PREFIX, cvRoundLosePoints.IntValue);
330
331 }
332 }
333 case NoScope:
334 {
335 gPlayer[client][PlayerNoScopes]++;
336 if (isPlayerVIP(client)) {
337 gPlayer[client][PlayerPoints] += cvNoScopePointsVIP.IntValue;
338 CPrintToChat(client, "%s Jako{olive} VIP{default} otrzymujesz{green} %d{default} punkty za {lightred}NoScope!", PREFIX, cvNoScopePointsVIP.IntValue);
339 } else {
340 gPlayer[client][PlayerPoints] += cvNoScopePoints.IntValue;
341 CPrintToChat(client, "%s Otrzymujesz{green} %d{default} punkty za {lightred}NoScope!", PREFIX, cvNoScopePoints.IntValue);
342 }
343 }
344 }
345
346 CalculateRank(client);
347}
348
349// sprawdza, czy gracz zdobył rangę/spadł z niej...
350void CalculateRank(int client) {
351 if (gPlayer[client][PlayerPoints] < 0)
352 gPlayer[client][PlayerPoints] = 0;
353
354 // najpierw sprawdzamy, czy jest awansik...
355 if (gPlayer[client][PlayerRank] < sizeof(gRankPoints)-1 && gRankPoints[gPlayer[client][PlayerRank]] <= gPlayer[client][PlayerPoints]) {
356 gPlayer[client][PlayerRank]++;
357 CPrintToChat(client, "%s Gratulujemy uzyskania awansu na wyższą rangę!", PREFIX);
358 // TODO: dzwiek + overlay
359 }
360
361 // teraz czy nie ma degradacji...
362 if (gPlayer[client][PlayerRank] > 0 && gRankPoints[gPlayer[client][PlayerRank]-1] > gPlayer[client][PlayerPoints]) {
363 gPlayer[client][PlayerRank]--;
364 CPrintToChat(client, "%s Niestety, zostałeś zdegradowany!", PREFIX);
365 // TODO: dzwiek + overlay
366 }
367}
368
369public Action Event_PlayerDeath(Event hEvent,
370 const char[] chName, bool bDontBroadcast) {
371 if (isWarmup())
372 return Plugin_Continue;
373
374 if (GetCurrentPlayers() < cvMinPlayerRequired.IntValue)
375 return Plugin_Continue;
376
377 bool headshot = GetEventBool(hEvent, "headshot");
378 int attacker = GetClientOfUserId(hEvent.GetInt("attacker"));
379 int client = GetClientOfUserId(hEvent.GetInt("userid"));
380
381 if (attacker == client)
382 return Plugin_Continue;
383
384 if (!IsValidClient(attacker))
385 return Plugin_Continue;
386
387 // killer
388 GrantPoints(attacker, Kill);
389 if (headshot == true)
390 GrantPoints(attacker, HS);
391
392 // victim
393 GrantPoints(client, Dead);
394
395 char weapon[16];
396 hEvent.GetString("weapon", weapon, sizeof(weapon));
397 ReplaceString(weapon, 16, "weapon_", "");
398
399 // if NoScope...
400 if (((StrContains(weapon, "awp") != -1 || StrContains(weapon, "ssg08") != -1 || StrContains(weapon, "scout") != -1) ||
401 ((StrContains(weapon, "g3sg1") != -1 || StrContains(weapon, "scar20") != -1))) &&
402 (GetEntProp(attacker, Prop_Data, "m_iFOV") <= 0 || GetEntProp(attacker, Prop_Data, "m_iFOV") == GetEntProp(attacker, Prop_Data, "m_iDefaultFOV"))) {
403 GrantPoints(client, NoScope);
404 float attackerPos[3];
405 float victimPos[3];
406 GetClientAbsOrigin(attacker, attackerPos);
407 GetClientAbsOrigin(client, victimPos);
408 float distance = GetVectorDistance(attackerPos, victimPos);
409 if (gPlayer[attacker][PlayerNoScopeDistance] < distance) {
410 gPlayer[attacker][PlayerNoScopeDistance] = RoundToCeil(distance);
411 CPrintToChat(attacker, "%s{darkred} [-->%N]{green} NoScope!{default} nowy{red} REKORD!{green} Dystans: %.2f", PREFIX, client, distance);
412 } else {
413 CPrintToChat(attacker, "%s{darkred} [-->%N]{green} NoScope!{green} Dystans: %.2f", PREFIX, client, distance);
414 }
415 }
416 return Plugin_Continue;
417}
418
419public Action Event_BombPlanted(Handle hEvent,
420 const char[] chName, bool bDontBroadcast) {
421
422 if (GetCurrentPlayers() < cvMinPlayerRequired.IntValue)
423 return Plugin_Continue;
424
425 int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
426
427 if (!IsValidClient(client))
428 return Plugin_Continue;
429
430 GrantPoints(client, BombPlanted);
431
432 for (int i = 1; i < MAXPLAYERS; i++) {
433 if (GetClientTeam(i) == CS_TEAM_CT)
434 GrantPoints(i, BombPlanted);
435 }
436 return Plugin_Continue;
437}
438
439public Action Event_BombDefused(Handle hEvent,
440 const char[] chName, bool bDontBroadcast) {
441 if (GetCurrentPlayers() < cvMinPlayerRequired.IntValue)
442 return Plugin_Continue;
443
444 int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
445
446 if (!IsValidClient(client))
447 return Plugin_Continue;
448
449 GrantPoints(client, BombDefused);
450
451 for (int i = 1; i < MAXPLAYERS; i++) {
452 if (GetClientTeam(i) == CS_TEAM_T)
453 GrantPoints(i, BombDefused);
454 }
455 return Plugin_Continue;
456}
457
458bool isWarmup() {
459 return GameRules_GetProp("m_bWarmupPeriod") != 0;
460}
461
462int isPlayerVIP(int client) {
463 return (GetUserFlagBits(client) & VIP_FLAG);
464}
465
466int GetCurrentPlayers() {
467 int count;
468 for (int i = 1; i < MAXPLAYERS; i++) {
469 if (IsValidClient(i) && !IsFakeClient(i)) {
470 count++;
471 }
472 }
473 return count;
474}
475
476bool IsValidClient(int client) {
477 if (!(1 <= client <= MAXPLAYERS) || !IsClientInGame(client) || IsFakeClient(client))
478 return false;
479 return true;
480}
481
482void GetFormattedTime(int time, char[] tab, int size) {
483 if (!time) {
484 Format(tab, size, "---");
485 return;
486 }
487
488 if (time > 3600) {
489 int hours = time / 3600;
490 int remaining = time % 3600;
491 int mins = remaining / 60;
492 Format(tab, size, "%d Godzin i %d Minut", hours, mins);
493 } else {
494 int mins = time / 60;
495 Format(tab, size, "%d Minut", mins);
496 }
497}