· 4 years ago · Dec 16, 2020, 10:36 AM
1/**
2 * ============================================================================
3 *
4 * Voter Core
5 *
6 * Developed by: sNok3
7 * Copyright (C) 2020 Denis Neagoe
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * ============================================================================
23 **/
24#pragma semicolon 1
25
26#include <sourcemod>
27#include <cstrike>
28#include <SteamWorks>
29#include <multicolors>
30
31// Shop integration (and zombie xp)
32#undef REQUIRE_PLUGIN
33#undef REQUIRE_EXTENSIONS
34#tryinclude <store>
35#tryinclude <shop>
36#tryinclude <lvl_ranks>
37#define REQUIRE_EXTENSIONS
38#define REQUIRE_PLUGIN
39#tryinclude <zombieplague>
40
41#define PLUGINS_AUTHOR "sNok3"
42#define PLUGINS_VERSION "2.0.1"
43
44#pragma newdecls required
45
46public Plugin myinfo =
47{
48 name = "[Voter] Server voting plugin",
49 author = PLUGINS_AUTHOR,
50 description = "Give players rewards if they vote the server",
51 version = PLUGINS_VERSION,
52 url = "https://snok3.com"
53}
54
55// Convars
56ConVar g_ConVar_Voter_SoundEnabled,
57 g_ConVar_Voter_SoundPath,
58 g_ConVar_Voter_SoundVolume,
59 g_ConVar_Voter_ClaimURL,
60 g_ConVar_Voter_Credits,
61 g_ConVar_Voter_Enabled,
62 g_ConVar_Voter_ServerID,
63 g_ConVar_Voter_ServerKey,
64 g_ConVar_Voter_StreakEnabled,
65 g_ConVar_Voter_ShopType,
66 g_ConVar_Voter_VoteURL,
67 g_ConVar_Voter_DB,
68 g_ConVar_Voter_DBEnabled,
69 g_ConVar_Voter_Logs,
70 g_ConVar_Voter_LRXP,
71 g_ConVar_Voter_ZPXP,
72 g_ConVar_Voter_Prefix;
73
74Database hDatabase = null;
75
76char Prefix[255],
77 sDatabaseName[128];
78
79int iLogType,
80 g_iCredits[MAXPLAYERS + 1],
81 g_iLR_Xp[MAXPLAYERS + 1],
82 g_iStreak[MAXPLAYERS + 1],
83 g_iVotes[MAXPLAYERS + 1],
84 g_iZP_Xp[MAXPLAYERS + 1];
85
86bool bCreditsEnabled,
87 bDBEnabled,
88 bLREnabled,
89 bStreakEnabled,
90 bSoundEnabled,
91 bZPEnabled;
92
93public void OnPluginStart()
94{
95 LoadTranslations("voter.phrases");
96
97 if(GetEngineVersion() != Engine_CSS && GetEngineVersion() != Engine_CSGO)
98 {
99 SetFailState("Unsupported Game! Only CS:GO and CS:S are supported.");
100 }
101
102 RegConsoleCmd("sm_voteserver", VoteLink, "Prints the server's vote link");
103 RegConsoleCmd("sm_vs", VoteLink, "Prints the server's vote link");
104 RegConsoleCmd("sm_claim", ClaimRewards, "Claims in-game rewards");
105 RegConsoleCmd("sm_votes", VotesAndStreaks, "Prints the number of votes and daily streak");
106
107 //Sound CVars
108 g_ConVar_Voter_SoundEnabled = CreateConVar("sm_voter_claim_sound_enabled", "1", "Enable or disable sounds for the claim (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
109 g_ConVar_Voter_SoundPath = CreateConVar("sm_voter_claim_sound_path", "sound/voter/fireworks.mp3", "The path to the sound used after the claim");
110 g_ConVar_Voter_SoundVolume = CreateConVar("sm_voter_claim_sound_volume", "1", "The volume of the played sound (0 - Minimum, 1 - Maximum)", 0, true, 0.0, true, 1.0);
111
112 //Claim CVars
113 g_ConVar_Voter_ClaimURL = CreateConVar("sm_voter_claim_url", "http://www.api.trackyserver.com/vote/?action=claim&key={serverkey}&steamid={steamid}", "The url for the claiming website (DON'T REMOVE {serverkey} OR {STEAMID})");
114 g_ConVar_Voter_Enabled = CreateConVar("sm_voter_enabled_voter", "1", "Enable/disable Voter (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
115 g_ConVar_Voter_ServerID = CreateConVar("sm_voter_server_id", "", "Your server's unique ID (trackyserver.com)");
116 g_ConVar_Voter_ServerKey = CreateConVar("sm_voter_server_key", "", "Your server's unique key from (trackyserver.com)");
117 g_ConVar_Voter_StreakEnabled= CreateConVar("sm_voter_streak_enabled", "1", "Enable/disable vote streaks", 0, true, 0.0, true, 1.0);
118 g_ConVar_Voter_ShopType = CreateConVar("sm_voter_shop_type", "", "Which Shop plugin will Voter use to award the players? (1 - Shop core, 2 - Zephyrus store, 3 - Zombie Plague store)", 0, true, 1.0, true, 3.0);
119 g_ConVar_Voter_VoteURL = CreateConVar("sm_voter_vote_url", "https://trackyserver.com/server/", "The url for the voting website (DON'T FORGET THE FINAL '/')");
120
121 //Awards
122 g_ConVar_Voter_Credits = CreateConVar("sm_voter_credits_awarded", "1", "Enable/disable credits rewards (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
123 g_ConVar_Voter_LRXP = CreateConVar("sm_voter_lr_xp_awarded", "1", "Enable/disable LevelRanks XP rewards (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
124 g_ConVar_Voter_ZPXP = CreateConVar("sm_voter_zp_xp_awarded", "1", "Enable/disable Zombie Plague XP rewards (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
125
126 //Other CVars
127 g_ConVar_Voter_DB = CreateConVar("sm_voter_db_name", "voter", "The name of the SQL table (both MySQL and database.cfg)");
128 g_ConVar_Voter_DBEnabled = CreateConVar("sm_voter_db_enabled", "1", "Enable/disable saving votes and streaks in the database (0 - Disabled, 1 - Enabled)", 0, true, 0.0, true, 1.0);
129 g_ConVar_Voter_Logs = CreateConVar("sm_voter_logs", "3", "Enable/disable Voter Logs (0 - Disabled, 1 - Error logs, 2 - Vote Logs, 3 - All logs)", 0, true, 0.0, true, 3.0);
130 g_ConVar_Voter_Prefix = CreateConVar("sm_voter_prefix", "{darkred}[Voter]{default}", "The prefix you want to have in your messages");
131
132 g_ConVar_Voter_Prefix.GetString(Prefix, sizeof(Prefix));
133 g_ConVar_Voter_DB.GetString(sDatabaseName, sizeof(sDatabaseName));
134
135 iLogType = g_ConVar_Voter_Logs.IntValue;
136
137 //Bools
138 bCreditsEnabled = g_ConVar_Voter_Credits.BoolValue;
139 bDBEnabled = g_ConVar_Voter_DBEnabled.BoolValue;
140 bLREnabled = g_ConVar_Voter_LRXP.BoolValue;
141 bSoundEnabled = g_ConVar_Voter_SoundEnabled.BoolValue;
142 bStreakEnabled = g_ConVar_Voter_StreakEnabled.BoolValue;
143 bZPEnabled = g_ConVar_Voter_ZPXP.BoolValue;
144
145 if(hDatabase == null)
146 if(bDBEnabled)
147 SQL_DBConnect();
148
149 AutoExecConfig(true, "voter");
150}
151
152public void OnConfigsExecuted()
153{
154 if(hDatabase == null)
155 if(bDBEnabled)
156 SQL_DBConnect();
157}
158
159public void OnMapStart()
160{
161 DownloadSound();
162}
163
164public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) // Remove errors related to some faulty store.inc
165{
166 MarkNativeAsOptional("Store_SetClientCredits");
167 MarkNativeAsOptional("Store_GetClientCredits");
168 return APLRes_Success;
169}
170
171// **********************************************/ Commands /**********************************************/
172public Action VoteLink(int client, int args)
173{
174 if(g_ConVar_Voter_Enabled.BoolValue)
175 {
176 if(IsClientValid(client)){
177 char buffer[256], cCredits[2], cLR_XP[2], c_ZP_XP[2];
178
179 g_ConVar_Voter_Credits.GetString(cCredits, sizeof(cCredits));
180 g_ConVar_Voter_LRXP.GetString(cLR_XP, sizeof(cLR_XP));
181 g_ConVar_Voter_ZPXP.GetString(c_ZP_XP, sizeof(c_ZP_XP));
182 if(strlen(cCredits) <= 0 && strlen(cLR_XP) <= 0 && strlen(c_ZP_XP) <= 0)
183 {
184 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
185 }
186 else
187 {
188 g_ConVar_Voter_VoteURL.GetString(buffer, sizeof(buffer));
189 Format(buffer, sizeof(buffer), "%s%d", buffer, g_ConVar_Voter_ServerID.IntValue);
190
191 if(bStreakEnabled)
192 {
193 GetVotesStreak(client);
194 }
195 else
196 GetRewards("default", client);
197
198 CPrintToChat(client, "{darkred}================================================================");
199 CPrintToChat(client, "%t", "Vote us", Prefix);
200 CPrintToChat(client, "%t", "Vote message", Prefix);
201 CPrintToChat(client, "%t", "Vote rewards", Prefix, FormatRewards(client));
202 CPrintToChat(client, "%t", "Vote link", Prefix, buffer);
203 CPrintToChat(client, "{darkred}================================================================");
204 }
205 }
206 }
207 else
208 {
209 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
210 }
211}
212
213public Action ClaimRewards(int client, int args)
214{
215 if(g_ConVar_Voter_Enabled.BoolValue)
216 {
217 if(IsClientValid(client))
218 {
219 char cCredits[2], cLR_XP[2], c_ZP_XP[2];
220
221 g_ConVar_Voter_Credits.GetString(cCredits, sizeof(cCredits));
222 g_ConVar_Voter_LRXP.GetString(cLR_XP, sizeof(cLR_XP));
223 g_ConVar_Voter_ZPXP.GetString(c_ZP_XP, sizeof(c_ZP_XP));
224 if(strlen(cCredits) >= 0 && strlen(cLR_XP) >= 0 && strlen(c_ZP_XP) >= 0)
225 {
226 char buffer[255], buffer_url[255], buffer_serverkey[255], SteamID[32];
227
228 // Parse Steam ID 64
229 GetClientAuthId(client, AuthId_SteamID64, SteamID, sizeof(SteamID));
230
231 g_ConVar_Voter_ClaimURL.GetString(buffer_url, sizeof(buffer_url));
232 g_ConVar_Voter_ServerKey.GetString(buffer_serverkey, sizeof(buffer_serverkey));
233
234 Format(buffer, sizeof(buffer), "%s&steamid=%s", buffer_serverkey, SteamID);
235 ReplaceString(buffer_url, sizeof(buffer_url), "{serverkey}&steamid={steamid}", buffer);
236
237 // Make API request
238 Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, buffer_url);
239 SteamWorks_SetHTTPCallbacks(hRequest, OnSteamWorksHTTPComplete);
240 SteamWorks_SetHTTPRequestContextValue(hRequest, GetClientUserId(client));
241 SteamWorks_SendHTTPRequest(hRequest);
242 if(!hRequest)
243 {
244 if(iLogType == 1 || iLogType == 3)
245 LogVoter("Error", "ERROR (Code 5): API request error(%i): %s", hRequest, buffer_url);
246 delete hRequest;
247 }
248 }
249 }
250 }
251 else
252 {
253 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
254 }
255
256
257 return Plugin_Handled;
258}
259
260public Action VotesAndStreaks(int client, int args)
261{
262 if(g_ConVar_Voter_Enabled.BoolValue)
263 {
264 if(IsClientValid(client))
265 {
266 GetVotesStreak(client);
267 CPrintToChat(client, "{darkred}================================================================");
268 CPrintToChat(client, "%t", "Votes message", Prefix, g_iVotes[client]);
269 if(bStreakEnabled)
270 CPrintToChat(client, "%t", "Streak message", Prefix, g_iStreak[client]);
271 CPrintToChat(client, "{darkred}================================================================");
272 }
273 }
274 else
275 {
276 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
277 }
278}
279
280// **********************************************/ Handles /**********************************************/
281public void OnSteamWorksHTTPComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any userid)
282{
283 int client = GetClientOfUserId(userid);
284 if(!bFailure && bRequestSuccessful && eStatusCode == k_EHTTPStatusCode200OK)
285 {
286 int bufferSize;
287 SteamWorks_GetHTTPResponseBodySize(hRequest, bufferSize);
288
289 char[] sResponseBody = new char[bufferSize];
290 SteamWorks_GetHTTPResponseBodyData(hRequest, sResponseBody, bufferSize);
291 delete hRequest;
292
293 int iResponse = StringToInt(sResponseBody);
294 iResponse = 1;
295 if(0 <= iResponse <= 2)
296 {
297 if(IsClientValid(client))
298 {
299 switch(iResponse)
300 {
301 case 0: CPrintToChat(client, "%t", "API response 0", Prefix); // Account not found
302
303 case 1:
304 {
305 if(bCreditsEnabled || bLREnabled || bZPEnabled)
306 {
307 if(bStreakEnabled)
308 {
309 GetVotesStreak(client);
310 }
311 else
312 GetRewards("default", client);
313
314 if(bCreditsEnabled)
315 {
316 char buffer[255];
317
318 int ShopType = g_ConVar_Voter_ShopType.IntValue;
319 g_ConVar_Voter_ShopType.GetString(buffer, sizeof(buffer));
320
321 if(strlen(buffer) > 0)
322 {
323 switch(ShopType)
324 {
325 case 1: // Shop core
326 {
327 if(GetFeatureStatus(FeatureType_Native, "Shop_GiveClientCredits") == FeatureStatus_Available)
328 Shop_GiveClientCredits(client, g_iCredits[client]);
329 else
330 if(iLogType == 1 || iLogType == 3)
331 LogVoter("Error", "ERROR (Code 2): Shop core was not found");
332 }
333
334 case 2: // Zephyrus store
335 {
336 if(GetFeatureStatus(FeatureType_Native, "Store_GetClientCredits") == FeatureStatus_Available)
337 Store_SetClientCredits(client, Store_GetClientCredits(client) + g_iCredits[client]);
338 else
339 if(iLogType == 1 || iLogType == 3)
340 LogVoter("Error", "ERROR (Code 2): Zephyrus store was not found");
341 }
342
343 case 3: // Zombie Plague store
344 {
345 if(GetFeatureStatus(FeatureType_Native, "ZP_GetClientMoney") == FeatureStatus_Available)
346 ZP_SetClientMoney(client, ZP_GetClientMoney(client) + g_iCredits[client]);
347 else
348 if(iLogType == 1 || iLogType == 3)
349 LogVoter("Error", "ERROR (Code 2): Zombie Plague store was not found");
350 }
351
352 default: // Invalid store type
353 {
354 if(iLogType == 1 || iLogType == 3)
355 LogVoter("Error", "ERROR (Code 2): Store type value is invalid (1-3 only)");
356 }
357 }
358 }
359 }
360 if(bLREnabled)
361 {
362 if(GetFeatureStatus(FeatureType_Native, "LR_GetClientInfo") == FeatureStatus_Available)
363 LR_ChangeClientValue(client, LR_GetClientInfo(client, ST_EXP) + g_iLR_Xp[client]);
364 }
365 if(bZPEnabled)
366 {
367 if(GetFeatureStatus(FeatureType_Native, "ZP_GetClientExp") == FeatureStatus_Available)
368 ZP_SetClientExp(client, ZP_GetClientExp(client) + g_iZP_Xp[client]);
369 }
370
371 PlayerVote(client);
372 }
373 else
374 {
375 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
376 if(iLogType == 1 || iLogType == 3)
377 LogVoter("Error", "ERROR (Code 3): No rewards selected");
378 }
379 }
380 case 2: CPrintToChat(client, "%t", "API response 2", Prefix); // Already voted
381
382 default: CPrintToChat(client, "%t", "Error occured", Prefix); // API response code
383 }
384 }
385 }
386 }
387 else
388 {
389 if(iLogType == 1 || iLogType == 3)
390 LogVoter("Error", "ERROR (Code 1): Link might be invalid");
391 CPrintToChat(client, "%t", "Rewards disabled", Prefix);
392 }
393
394 delete hRequest;
395}
396
397public void PlayerVote(int client)
398{
399 CPrintToChatAll("%t", "Player voted", Prefix, client);
400 CPrintToChat(client, "%t", "API response 1", Prefix, FormatRewards(client)); // Claim rewards
401
402 if(bSoundEnabled)
403 PlaySound(client);
404
405 char sSteamID[32], sTimeStamp[64];
406
407 if(bDBEnabled)
408 SaveVotes(client);
409
410 GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID));
411 FormatTime(sTimeStamp, sizeof(sTimeStamp), "%Y/%m/%d", GetTime());
412
413 char sError[256];
414 if(iLogType == 2 || iLogType == 3){
415 Format(sError, sizeof(sError), "%L has voted the server! (%s)", client, sTimeStamp);
416 LogVoter("Votes", "VOTE: %s", sError);
417 }
418}
419// **********************************************/ Database /**********************************************/
420void SaveVotes(int client)
421{
422 if(hDatabase != null)
423 {
424 char sName[MAX_NAME_LENGTH], sSteamID[32], sQuery[512];
425
426 GetClientName(client, sName, sizeof(sName));
427 GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID));
428
429 int lenght = strlen(sName) * 2 + 1;
430 char[] sEscapedName = new char[lenght];
431 hDatabase.Escape(sName, sEscapedName, lenght);
432
433 hDatabase.Format(sQuery, sizeof(sQuery), "INSERT INTO `%s` (name, auth, votes, streak, votetime) VALUES ('%s', '%s', 1, 0, '%d') ON DUPLICATE KEY UPDATE votes = votes + 1, votetime = %d;", sDatabaseName, sEscapedName, sSteamID, GetTime(), GetTime());
434 hDatabase.Query(SQL_NoResult, sQuery, client);
435 }
436}
437
438public void GetVotesStreak(int client)
439{
440 if(hDatabase != null)
441 {
442 char sSteamID[32], sQuery[256];
443
444 GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID));
445 hDatabase.Format(sQuery, sizeof(sQuery), "SELECT `votes`,`streak` FROM `%s` WHERE auth = '%s';", sDatabaseName, sSteamID);
446 hDatabase.Query(SQL_VotesStreakCallback, sQuery, GetClientUserId(client));
447 }
448}
449
450void SQL_DBConnect()
451{
452 if(hDatabase != null)
453 delete hDatabase;
454 if(SQL_CheckConfig(sDatabaseName))
455 Database.Connect(SQL_ConnectionCallback, sDatabaseName);
456 else
457 if(iLogType == 1 || iLogType == 3)
458 LogVoter("Error", "ERROR (Code 7): Database connection failure! Couldn't find Voter's database entry in database.cfg");
459}
460
461void SQL_ConnectionCallback(Database db, char[] error, any data)
462{
463 if(db == null)
464 {
465 if(iLogType == 1 || iLogType == 3)
466 LogVoter("Error", "ERROR (Code 8): Can't connect to server. Error: %s", error);
467 return;
468 }
469 hDatabase = db;
470
471 char sQuery[512];
472 hDatabase.Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `%s` (`id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, `name` varchar(64) NOT NULL, `auth` varchar(32) NOT NULL, `votes` int(11) NOT NULL, `streak` int(11) NOT NULL, `votetime` varchar(32) NOT NULL, UNIQUE KEY `auth` (`auth`)) ENGINE = MyISAM DEFAULT CHARSET = utf8;", sDatabaseName);
473 hDatabase.Query(SQL_NoResult, sQuery, DBPrio_High);
474}
475
476void SQL_VotesStreakCallback(Database db, DBResultSet result, char[] error, any data)
477{
478 if(result == null)
479 {
480 if(iLogType == 1 || iLogType == 3)
481 LogVoter("Error", "ERROR (Code 9): %s", error);
482 }
483 else
484 {
485 int client = GetClientOfUserId(data);
486 if(IsClientValid(client))
487 {
488 result.FetchRow();
489 g_iVotes[client] = result.FetchInt(0);
490 g_iStreak[client] = result.FetchInt(1);
491
492 char sStreakDay[2];
493 Format(sStreakDay, sizeof(sStreakDay), "%i", g_iStreak[client]);
494
495 if(g_iStreak[client] > 0)
496 GetRewards(sStreakDay, client);
497 else
498 GetRewards("default", client);
499 }
500 }
501}
502
503void SQL_NoResult(Database db, DBResultSet result, char[] error, any data)
504{
505 if(result == null)
506 if(iLogType == 1 || iLogType == 3)
507 LogVoter("Error", "ERROR (Code 9): %s", error);
508 return;
509}
510
511// **********************************************/ Sounds /**********************************************/
512public void DownloadSound()
513{
514 char buffer[255];
515
516 g_ConVar_Voter_SoundPath.GetString(buffer, sizeof(buffer));
517
518 AddFileToDownloadsTable(buffer);
519 ReplaceString(buffer, sizeof(buffer), "sound/", "*/");
520 FakePrecacheSound(buffer);
521}
522
523public void PlaySound(int client)
524{
525 char buffer[128];
526
527 g_ConVar_Voter_SoundPath.GetString(buffer, sizeof(buffer));
528
529 ReplaceString(buffer, sizeof(buffer), "sound/", "*/");
530 EmitSoundToClient(client, buffer, _, _, _, _, g_ConVar_Voter_SoundVolume.FloatValue);
531}
532
533void FakePrecacheSound(const char[] szPath)
534{
535 AddToStringTable(FindStringTable("soundprecache"), szPath);
536}
537
538// **********************************************/ Files /**********************************************/
539public void LogVoter(char[] type, const char[] message, any...)
540{
541 char[] fMessage = new char[strlen(message) + 255];
542 VFormat(fMessage, strlen(message) + 255, message, 3);
543
544 char sFile[PLATFORM_MAX_PATH];
545 BuildPath(Path_SM, sFile, sizeof(sFile), "logs/Voter_%s.log", type);
546
547 LogToFile(sFile, fMessage);
548}
549
550public void GetRewards(char[] sDay, int client)
551{
552 char CFG[256];
553 BuildPath(Path_SM, CFG, sizeof(CFG), "configs/Voter/rewards.ini");
554
555 if(!FileExists(CFG))
556 SetFailState("Config file \"%s\" couldn't be found!", CFG);
557
558 KeyValues kv = CreateKeyValues("Voter_Rewards");
559 kv.ImportFromFile(CFG);
560 kv.Rewind();
561 kv.JumpToKey(sDay);
562 if(bCreditsEnabled)
563 g_iCredits[client] = kv.GetNum("credits");
564 if(bLREnabled)
565 g_iLR_Xp[client] = kv.GetNum("xp_lr");
566 if(bZPEnabled)
567 g_iZP_Xp[client] = kv.GetNum("xp_zp");
568
569 kv.Rewind();
570 delete kv;
571}
572
573// **********************************************/ Checkings /**********************************************/
574char[] FormatRewards(int client)
575{
576 char buffer[256];
577
578 if(bCreditsEnabled && bLREnabled && bZPEnabled)
579 Format(buffer, sizeof(buffer), "{darkred}%d{default} credits, {darkred}%d{default} Level Ranks XP, {darkred}%d{default} Zombie Xp", g_iCredits[client], g_iLR_Xp[client], g_iZP_Xp[client]);
580 else if(bCreditsEnabled && bLREnabled && bZPEnabled == false)
581 Format(buffer, sizeof(buffer), "{darkred}%d{default} credits, {darkred}%d{default} Level Ranks XP", g_iCredits[client], g_iLR_Xp[client]);
582 else if(bCreditsEnabled && bLREnabled == false && bZPEnabled)
583 Format(buffer, sizeof(buffer), "{darkred}%d{default} credits, {darkred}%d{default} Zombie XP", g_iCredits[client], g_iZP_Xp[client]);
584 else if(bCreditsEnabled == false && bLREnabled && bZPEnabled)
585 Format(buffer, sizeof(buffer), "{darkred}%d{default} Level Ranks, {darkred}%d{default} Zombie XP", g_iLR_Xp[client], g_iZP_Xp[client]);
586 else if(bCreditsEnabled && bLREnabled == false && bZPEnabled == false)
587 Format(buffer, sizeof(buffer), "{darkred}%d{default} credits", g_iCredits[client]);
588 else if(bCreditsEnabled == false && bLREnabled && bZPEnabled == false)
589 Format(buffer, sizeof(buffer), "{darkred}%d{default} Level Ranks XP", g_iLR_Xp[client]);
590 else if(bCreditsEnabled == false && bLREnabled == false && bZPEnabled)
591 Format(buffer, sizeof(buffer), "{darkred}%d{default} Zombie XP", g_iZP_Xp[client]);
592
593 return buffer;
594}
595
596public bool IsClientValid(int client)
597{
598 return (0 < client <= MaxClients) && IsClientInGame(client) && !IsFakeClient(client);
599}