· 7 years ago · Jan 09, 2019, 11:58 PM
1#pragma semicolon 1
2#pragma newdecls required
3
4
5#define PLUGIN_NAME "MyStore - MyResurrection of the Resurrection"
6#define PLUGIN_AUTHOR "shanapu, Zephyrus"
7#define PLUGIN_DESCRIPTION "A completely old Store system - completely new rewritten."
8#define PLUGIN_VERSION "0.x"
9#define PLUGIN_URL ""
10
11
12#include <sourcemod>
13#include <sdktools>
14#include <cstrike>
15
16#include <mystore>
17
18#include <colors>
19#include <autoexecconfig>
20
21#undef REQUIRE_PLUGIN
22#include <adminmenu>
23#define REQUIRE_PLUGIN
24
25
26
27int g_iEquipment[MAXPLAYERS + 1][STORE_MAX_TYPES * STORE_MAX_SLOTS];
28int g_iEquipmentSynced[MAXPLAYERS + 1][STORE_MAX_TYPES * STORE_MAX_SLOTS];
29int g_iPlayerID[MAXPLAYERS + 1] = {0, ...};
30int g_bLastJoin[MAXPLAYERS + 1] = {0, ...};
31int g_iItems[MAXPLAYERS + 1] = {0, ...};
32int g_iCredits[MAXPLAYERS + 1] = {0, ...};
33bool g_bLoaded[MAXPLAYERS + 1] = {false, ...};
34
35char g_sItemID[STORE_MAX_ITEM_HANDLERS][64];
36Handle g_hItemPlugin[STORE_MAX_ITEM_HANDLERS];
37Function g_fnItemMenu[STORE_MAX_ITEM_HANDLERS];
38Function g_fnItemHandler[STORE_MAX_ITEM_HANDLERS];
39
40char g_sPlanName[STORE_MAX_ITEMS][STORE_MAX_PLANS][ITEM_NAME_LENGTH];
41int g_iPlanPrice[STORE_MAX_ITEMS][STORE_MAX_PLANS];
42int g_iPlanTime[STORE_MAX_ITEMS][STORE_MAX_PLANS];
43
44any g_aItems[STORE_MAX_ITEMS][Item_Data];
45any g_aTypeHandlers[STORE_MAX_TYPES][Type_Handler];
46
47int g_iPlayerItems[MAXPLAYERS + 1][STORE_MAX_ITEMS][CLIENT_ITEM_SIZE];
48bool g_bMySQL = false;
49bool g_bInvMode[MAXPLAYERS + 1];
50bool g_bIsInRecurringMenu[MAXPLAYERS + 1] = {false, ...};
51
52char g_sChatPrefix[128];
53char g_sName[64];
54char g_sCreditsName[64];
55char g_sSelectedClient[MAXPLAYERS + 1][256];
56
57ConVar gc_bEnable;
58ConVar gc_iDBRetries;
59ConVar gc_iDBTimeout;
60ConVar gc_iCreditsStart;
61ConVar gc_sMinFlags;
62ConVar gc_sVIPFlags;
63ConVar gc_bConfirm;
64ConVar gc_sAdminFlags;
65ConVar gc_bSaveOnDeath;
66ConVar gc_bShowVIP;
67ConVar gc_bLogging;
68ConVar gc_bLoggingLevel;
69ConVar gc_bSilent;
70ConVar gc_sPrefix;
71ConVar gc_sName;
72ConVar gc_sCustomCommand;
73ConVar gc_sCreditsName;
74ConVar gc_bGenerateUId;
75
76Database g_hDatabase = null;
77
78Handle g_hLogFile = null;
79
80Handle gf_hOnItemEquipt;
81Handle gf_hPreviewItem;
82Handle gf_hOnBuyItem;
83Handle gf_hOnConfigExecuted;
84Handle gf_hOnGetEndPrice;
85
86int g_iItemCount = 0;
87int g_iTypeHandlers = 0;
88int g_iItemHandlers = 0;
89int g_iPackageHandler = -1;
90int g_iDatabaseRetries = 0;
91int g_iPublicChatTrigger = 0;
92int g_iSilentChatTrigger = 0;
93int g_iMinFlags = 0;
94int g_iVIPFlags = 0;
95int g_iAdminFlags = 0;
96int g_iMenuBack[MAXPLAYERS + 1];
97int g_iLastSelection[MAXPLAYERS + 1];
98int g_iSelectedItem[MAXPLAYERS + 1];
99int g_iSelectedPlan[MAXPLAYERS + 1];
100int g_iMenuClient[MAXPLAYERS + 1];
101int g_iMenuNum[MAXPLAYERS + 1];
102int g_iSpam[MAXPLAYERS + 1];
103
104TopMenu g_hTopMenu = null;
105
106TopMenuObject g_hTopMenuObject;
107
108public Plugin myinfo =
109{
110 name = PLUGIN_NAME,
111 author = PLUGIN_AUTHOR,
112 description = PLUGIN_DESCRIPTION,
113 version = PLUGIN_VERSION,
114 url = PLUGIN_URL
115};
116
117public void OnPluginStart()
118{
119 // Load the translations file
120 LoadTranslations("mystore.phrases");
121 LoadTranslations("common.phrases");
122
123 // Register Commands
124 RegConsoleCmd("sm_reloadconfig", Command_ReloadConfig);
125
126 RegConsoleCmd("sm_store", Command_Store);
127 RegConsoleCmd("sm_shop", Command_Store);
128 RegConsoleCmd("sm_inv", Command_Inventory);
129 RegConsoleCmd("sm_inventory", Command_Inventory);
130
131 RegConsoleCmd("sm_givecredits", Command_GiveCredits);
132 RegConsoleCmd("sm_resetplayer", Command_ResetPlayer);
133
134 RegConsoleCmd("sm_credits", Command_Credits);
135
136 DirExistsEx("cfg/MyStore");
137 AutoExecConfig_SetFile("core", "MyStore");
138 AutoExecConfig_SetCreateFile(true);
139
140 // Register ConVars
141 gc_bEnable = AutoExecConfig_CreateConVar("mystore_enable", "1", "Enable/disable plugin", _, true, 0.0, true, 1.0);
142 gc_iDBRetries = AutoExecConfig_CreateConVar("mystore_database_retries", "4", "Number of retries if the connection fails to estabilish with timeout", _, true, 0.0, true, 10.0);
143 gc_iDBTimeout = AutoExecConfig_CreateConVar("mystore_database_timeout", "10", "Timeout in seconds to wait for database connection before retry", _, true, 0.0, true, 6.0);
144 gc_iCreditsStart = AutoExecConfig_CreateConVar("mystore_startcredits", "0", "Number of credits a client starts with", _, true, 0.0);
145 gc_sMinFlags = AutoExecConfig_CreateConVar("mystore_access_flag", "", "Flag to access the !store menu. Leave blank to disable.");
146 gc_sVIPFlags = AutoExecConfig_CreateConVar("mystore_vip_flag", "", "Flag for VIP access (all items unlocked). Leave blank to disable.");
147 gc_sAdminFlags = AutoExecConfig_CreateConVar("mystore_admin_flag", "z", "Flag for admin access. Leave blank to disable.");
148 gc_bConfirm = AutoExecConfig_CreateConVar("mystore_confirm", "1", "Enable/disable confirmation windows.", _, true, 0.0, true, 1.0);
149 gc_bSaveOnDeath = AutoExecConfig_CreateConVar("mystore_save_on_death", "0", "Enable/disable client data saving on client death.", _, true, 0.0, true, 1.0);
150 gc_sPrefix = AutoExecConfig_CreateConVar("mystore_chat_tag", "{green}[MyStore] {default}", "The chat tag to use for displaying messages (with colors).");
151 gc_sName = AutoExecConfig_CreateConVar("mystore_name", "MyStore", "Name for the store for displaying messages & menus (no colors).");
152 gc_bShowVIP = AutoExecConfig_CreateConVar("mystore_show_vip_items", "0", "If you enable this, items with flags will be shown in grey.", _, true, 0.0, true, 1.0);
153 gc_bLogging = AutoExecConfig_CreateConVar("mystore_logging", "0", "Set this to 1 for file logging and 2 to SQL logging (only MySQL). Leaving on 0 = disabled. ", _, true, 0.0, true, 2.0);
154 gc_bLoggingLevel = AutoExecConfig_CreateConVar("mystore_logging_level", "4", "4 = Log all events - Error, Admin, Event & Credit / 3 = No log credits - Log Error, Admin & Event / 2 = No log credits & events - Log Error & Admin / 1 = Only Log Error", _, true, 1.0, true, 4.0);
155 gc_bSilent = AutoExecConfig_CreateConVar("mystore_silent_givecredits", "0", "Controls the give credits message visibility. 0 = public 1 = private 2 = no message", _, true, 0.0, true, 2.0);
156 gc_sCustomCommand = AutoExecConfig_CreateConVar("mystore_cmds", "shop, item, mystore", "Set your custom chat commands for the store(!store (no 'sm_'/'!')(seperate with comma ', ')(max. 12 commands)");
157 gc_sCreditsName = AutoExecConfig_CreateConVar("mystore_credits_name", "Credits", "Set your credits name");
158 gc_bGenerateUId = AutoExecConfig_CreateConVar("mystore_generate_uids", "0", "Enable to generate unique_id for items. Beware can really fuck up your item.txt on bad formating");
159
160 AutoExecConfig_ExecuteFile();
161 AutoExecConfig_CleanFile();
162
163 // Add ConVars Hooks
164 gc_sPrefix.AddChangeHook(OnSettingChanged);
165 gc_sName.AddChangeHook(OnSettingChanged);
166 gc_sCustomCommand.AddChangeHook(OnSettingChanged);
167 gc_sCreditsName.AddChangeHook(OnSettingChanged);
168 gc_sAdminFlags.AddChangeHook(OnSettingChanged);
169 gc_sVIPFlags.AddChangeHook(OnSettingChanged);
170 gc_sMinFlags.AddChangeHook(OnSettingChanged);
171
172 // Hook events
173 HookEvent("player_death", Event_PlayerDeath);
174
175 // Initiaze the fake package handler
176 g_iPackageHandler = MyStore_RegisterHandler("package", _, _, _, _);
177
178 // Initiaze admin menu
179 TopMenu topmenu;
180 if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != null))
181 {
182 OnAdminMenuReady(topmenu);
183 }
184
185 // Read core.cfg for chat triggers
186 ReadCoreCFG();
187
188 // Add a say command listener for shortcuts
189 AddCommandListener(Command_Say, "say");
190 AddCommandListener(Command_Say, "say_team");
191
192 // Late Load
193 for (int i = 1; i <= MaxClients; i++)
194 {
195 g_iCredits[i] = -1;
196 g_iItems[i] = -1;
197
198 if (!IsClientInGame(i) || IsFakeClient(i))
199 continue;
200
201 OnClientConnected(i);
202 OnClientPostAdminCheck(i);
203 }
204}
205
206public void OnSettingChanged(ConVar convar, const char[] oldValue, const char[] newValue)
207{
208 // Add custom commands
209 if (convar == gc_sCustomCommand)
210 {
211 int iCount = 0;
212 char sCommands[128], sCommandsL[12][32], sCommand[32];
213
214 gc_sCustomCommand.GetString(sCommands, sizeof(sCommands));
215 ReplaceString(sCommands, sizeof(sCommands), " ", "");
216 iCount = ExplodeString(sCommands, ", ", sCommandsL, sizeof(sCommandsL), sizeof(sCommandsL[]));
217
218 for (int i = 0; i < iCount; i++)
219 {
220 Format(sCommand, sizeof(sCommand), "sm_%s", sCommandsL[i]);
221 if (GetCommandFlags(sCommand) != INVALID_FCVAR_FLAGS)
222 continue;
223
224 RegConsoleCmd(sCommand, Command_Store);
225 }
226
227 return;
228 }
229 // Get new convar strings
230 else if (convar == gc_sAdminFlags)
231 {
232 g_iAdminFlags = ReadFlagString(newValue);
233 return;
234 }
235 else if (convar == gc_sVIPFlags)
236 {
237 g_iVIPFlags = ReadFlagString(newValue);
238 return;
239 }
240 else if (convar == gc_sMinFlags)
241 {
242 g_iMinFlags = ReadFlagString(newValue);
243 return;
244 }
245 else if (convar == gc_sPrefix)
246 {
247 strcopy(g_sChatPrefix, sizeof(g_sChatPrefix), newValue);
248 }
249 else if (convar == gc_sName)
250 {
251 strcopy(g_sName, sizeof(g_sName), newValue);
252 }
253 else if (convar == gc_sCreditsName)
254 {
255 strcopy(g_sCreditsName, sizeof(g_sCreditsName), newValue);
256 }
257
258 // Call foward MyStore_OnConfigsExecuted
259 Forward_OnConfigsExecuted();
260}
261
262public void OnConfigsExecuted()
263{
264 // Connect to database
265 if (g_hDatabase == null)
266 {
267 Database.Connect(SQLCallback_Connect, "mystore");
268 }
269
270 // Start timer for database connection retry
271 if (gc_iDBRetries.IntValue > 0)
272 {
273 CreateTimer(gc_iDBTimeout.FloatValue, Timer_DatabaseTimeout);
274 }
275
276 // Add custom commands
277 int iCount = 0;
278 char sCommands[128], sCommandsL[12][32], sCommand[32];
279
280 gc_sCustomCommand.GetString(sCommands, sizeof(sCommands));
281 ReplaceString(sCommands, sizeof(sCommands), " ", "");
282 iCount = ExplodeString(sCommands, ", ", sCommandsL, sizeof(sCommandsL), sizeof(sCommandsL[]));
283
284 for (int i = 0; i < iCount; i++)
285 {
286 Format(sCommand, sizeof(sCommand), "sm_%s", sCommandsL[i]);
287 if (GetCommandFlags(sCommand) != INVALID_FCVAR_FLAGS)
288 continue;
289
290 RegConsoleCmd(sCommand, Command_Store);
291 }
292
293 // Get convar strings
294 char sBuffer[16];
295 gc_sAdminFlags.GetString(sBuffer, sizeof(sBuffer));
296 g_iAdminFlags = ReadFlagString(sBuffer);
297
298 gc_sMinFlags.GetString(sBuffer, sizeof(sBuffer));
299 g_iMinFlags = ReadFlagString(sBuffer);
300
301 gc_sVIPFlags.GetString(sBuffer, sizeof(sBuffer));
302 g_iVIPFlags = ReadFlagString(sBuffer);
303
304 gc_sPrefix.GetString(g_sChatPrefix, sizeof(g_sChatPrefix));
305 gc_sName.GetString(g_sName, sizeof(g_sName));
306 gc_sCreditsName.GetString(g_sCreditsName, sizeof(g_sCreditsName));
307
308 // Call foward MyStore_OnConfigsExecuted
309 Forward_OnConfigsExecuted();
310
311 // Open log file
312 if (gc_bLogging.IntValue != 1 || g_hLogFile != null)
313 return;
314
315 char sPath[PLATFORM_MAX_PATH];
316 BuildPath(Path_SM, sPath, sizeof(sPath), "logs/mystore.log.txt");
317 g_hLogFile = OpenFile(sPath, "w+");
318}
319
320public void OnAllPluginsLoaded()
321{
322 CreateTimer(0.1, Timer_LoadConfig);
323}
324
325public void OnPluginEnd()
326{
327 // Save all client data
328 for (int i = 1; i <= MaxClients; i++)
329 {
330 if (!IsClientInGame(i) || IsFakeClient(i))
331 continue;
332
333 if (!g_bLoaded[i])
334 continue;
335
336 OnClientDisconnect(i);
337 }
338}
339
340/******************************************************************************
341 Commands
342******************************************************************************/
343
344public Action Command_Say(int client, char [] command, int args)
345{
346 if (!gc_bEnable.BoolValue)
347 return Plugin_Continue;
348
349 // Monitor chat for menu shortcuts
350 if (args < 1)
351 return Plugin_Continue;
352
353 char sArg[65];
354 GetCmdArg(1, sArg, sizeof(sArg));
355
356 // Check for sourcemod chattriggers ./sourcemod/configs/core.cfg
357 if (strlen(sArg) > 1 && (sArg[0] == g_iPublicChatTrigger || sArg[0] == g_iSilentChatTrigger))
358 {
359 for (int i = 0; i < g_iItemCount; i++)
360 {
361 //Have we found a shortcut?
362 if (strcmp(g_aItems[i][szShortcut], sArg[1]) == 0 && g_aItems[i][szShortcut][0] != 0)
363 {
364 g_bInvMode[client] = false;
365 g_iMenuClient[client] = client;
366 g_iSelectedItem[client] = i;
367
368 //Already has item? Show menu
369 if (MyStore_HasClientItem(client, i))
370 {
371 if (g_aItems[i][bPreview])
372 {
373 DisplayPreviewMenu(client, i);
374 }
375 else
376 {
377 DisplayItemMenu(client, i);
378 }
379 }
380 //Don't has item? show a buy menu or buy item
381 else
382 {
383 if (g_aItems[i][iPlans] != 0)
384 {
385 DisplayPlanMenu(client, i);
386 }
387 else if (gc_bConfirm.BoolValue)
388 {
389 char sTitle[128];
390 Format(sTitle, sizeof(sTitle), "%t", "Confirm_Buy", g_aItems[i][szName], g_aTypeHandlers[g_aItems[i][iHandler]][szType]);
391 MyStore_DisplayConfirmMenu(client, sTitle, MenuHandler_Store, 0);
392 }
393 else
394 {
395 BuyItem(client, i);
396 }
397 }
398 break;
399 }
400 }
401
402 //used the silent trigger? don't show it.
403 if (sArg[0] == g_iSilentChatTrigger)
404 {
405 return Plugin_Handled;
406 }
407 }
408
409 return Plugin_Continue;
410}
411
412public Action Command_ReloadConfig(int client, int params)
413{
414 if (client && !IsClientAdmin(client))
415 {
416 CPrintToChat(client, "%s%t", g_sChatPrefix, "You dont have permission");
417 return Plugin_Handled;
418 }
419
420 Forward_OnConfigsExecuted();
421
422 // Reload items from ./sourcemod/configs/MyStore/items.cfg
423 ReloadConfig();
424 return Plugin_Handled;
425}
426
427public Action Command_Store(int client, int params)
428{
429 //Buisness as usual
430 if (!gc_bEnable.BoolValue)
431 {
432 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
433 return Plugin_Handled;
434 }
435
436 if (g_iMinFlags != 0 && !HasClientAccess(client))
437 {
438 CPrintToChat(client, "%s%t", g_sChatPrefix, "You dont have permission");
439 return Plugin_Handled;
440 }
441
442 if ((g_iCredits[client] == -1 && g_iItems[client] == -1) || !g_bLoaded[client])
443 {
444 CPrintToChat(client, "%s%t", g_sChatPrefix, "Inventory hasnt been fetched");
445 return Plugin_Handled;
446 }
447
448 g_bInvMode[client] = false;
449 g_iMenuClient[client] = client;
450
451 //Display Store Menu ...
452 DisplayStoreMenu(client);
453
454 return Plugin_Handled;
455}
456
457public Action Command_Inventory(int client, int params)
458{
459 //Buisness as usual
460 if (!gc_bEnable.BoolValue)
461 {
462 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
463 return Plugin_Handled;
464 }
465
466 if (g_iMinFlags != 0 && !HasClientAccess(client))
467 {
468 CPrintToChat(client, "%s%t", g_sChatPrefix, "You dont have permission");
469 return Plugin_Handled;
470 }
471
472 if ((g_iCredits[client] == -1 && g_iItems[client] == -1) || !g_bLoaded[client])
473 {
474 CPrintToChat(client, "%s%t", g_sChatPrefix, "Inventory hasnt been fetched");
475 return Plugin_Handled;
476 }
477
478 g_bInvMode[client] = true;
479 g_iMenuClient[client] = client;
480 DisplayStoreMenu(client);
481
482 return Plugin_Handled;
483}
484
485public Action Command_GiveCredits(int client, int params)
486{
487 //Buisness as usual
488 if (!gc_bEnable.BoolValue)
489 {
490 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
491 return Plugin_Handled;
492 }
493
494 if (client && !IsClientAdmin(client))
495 {
496 CPrintToChat(client, "%s%t", g_sChatPrefix, "You dont have permission");
497 return Plugin_Handled;
498 }
499
500 //Credits
501 char sTmp[64];
502 GetCmdArg(2, sTmp, sizeof(sTmp));
503
504 int iCredit = StringToInt(sTmp);
505
506 //Client
507 bool bTmp;
508 int iTargets[1];
509 GetCmdArg(1, sTmp, sizeof(sTmp));
510
511 int iReceiver = -1;
512 if (strncmp(sTmp, "STEAM_", 6) == 0)
513 {
514 iReceiver = GetClientBySteamID(sTmp);
515 // SteamID is not ingame
516 if (iReceiver == 0)
517 {
518 char sQuery[512];
519 if (g_bMySQL)
520 {
521 Format(sQuery, sizeof(sQuery), "INSERT IGNORE INTO mystore_players (authid, credits) VALUES (\"%s\", %i) ON DUPLICATE KEY UPDATE credits = credits+%i", sTmp[8], iCredit, iCredit);
522 }
523 else
524 {
525 Format(sQuery, sizeof(sQuery), "INSERT OR IGNORE INTO mystore_players (authid) VALUES (\"%s\")", sTmp[8]);
526
527 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
528
529 Format(sQuery, sizeof(sQuery), "UPDATE mystore_players SET credits = credits + %i WHERE authid = \"%s\"", iCredit, sTmp[8]);
530 }
531
532 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
533 CPrintToChatAll("%s%t", g_sChatPrefix, "Credits Given", sTmp[8], iCredit, g_sCreditsName);
534 iReceiver = -1;
535 }
536 }
537 else if (strcmp(sTmp, "@all") == 0)
538 {
539 for (int i = 1; i <= MaxClients; i++)
540 {
541 if (!IsClientInGame(i) || IsFakeClient(i))
542 continue;
543
544 FakeClientCommandEx(client, "sm_givecredits \"%N\" %i", i, iCredit);
545 }
546 }
547 else if (strcmp(sTmp, "@t") == 0)
548 {
549 for (int i = 1; i <= MaxClients; i++)
550 {
551 if (!IsClientInGame(i) || IsFakeClient(i))
552 continue;
553
554 if (GetClientTeam(i) != CS_TEAM_T)
555 continue;
556
557 FakeClientCommandEx(client, "sm_givecredits \"%N\" %i", i, iCredit);
558 }
559 }
560 else if (strcmp(sTmp, "@ct") == 0)
561 {
562 for (int i = 1; i <= MaxClients; i++)
563 {
564 if (!IsClientInGame(i) || IsFakeClient(i))
565 continue;
566
567 if (GetClientTeam(i) != CS_TEAM_CT)
568 continue;
569
570 FakeClientCommandEx(client, "sm_givecredits \"%N\" %i", i, iCredit);
571 }
572 }
573 else
574 {
575 int iClients = ProcessTargetString(sTmp, 0, iTargets, 1, 0, sTmp, sizeof(sTmp), bTmp);
576 if (iClients > 2)
577 {
578 ReplyToCommand(client, "%s%t", g_sChatPrefix, "Credit Too Many Matches");
579 return Plugin_Handled;
580 }
581 else if (iClients != 1)
582 {
583 ReplyToCommand(client, "%s%t", g_sChatPrefix, "Credit No Match");
584 return Plugin_Handled;
585 }
586
587 iReceiver = iTargets[0];
588 }
589
590 // The player is on the server
591 if (iReceiver != -1)
592 {
593 g_iCredits[iReceiver] += iCredit;
594 if (gc_bSilent.IntValue == 1)
595 {
596 ReplyToCommand(client, "%s%t", g_sChatPrefix, "Credits Given", iReceiver, iCredit, g_sCreditsName);
597 CPrintToChat(iReceiver, "%s%t", g_sChatPrefix, "Credits Given", iReceiver, iCredit, g_sCreditsName);
598 }
599 else if (gc_bSilent.IntValue == 0)
600 {
601 CPrintToChatAll("%s%t", g_sChatPrefix, "Credits Given", iReceiver, iCredit, g_sCreditsName);
602 }
603
604 MyLogMessage(client, LOG_ADMIN, "%i credits to %L", iCredit, iReceiver);
605 MyLogMessage(iReceiver, LOG_CREDITS, "%i credits given by %L", iCredit, client);
606 }
607
608 return Plugin_Handled;
609}
610
611public Action Command_ResetPlayer(int client, int params)
612{
613 if (client && !IsClientAdmin(client))
614 {
615 CPrintToChat(client, "%s%t", g_sChatPrefix, "You dont have permission");
616 return Plugin_Handled;
617 }
618
619 char sTmp[64];
620 bool bTmp;
621 int iTargets[1];
622 GetCmdArg(1, sTmp, sizeof(sTmp));
623
624 int iReceiver = -1;
625 if (strncmp(sTmp, "STEAM_", 6) == 0)
626 {
627 iReceiver = GetClientBySteamID(sTmp);
628 // SteamID is not ingame
629 if (iReceiver == 0)
630 {
631 char sQuery[512];
632 Format(sQuery, sizeof(sQuery), "SELECT id, authid FROM mystore_players WHERE authid = \"%s\"", sTmp[9]);
633 g_hDatabase.Query(SQLCallback_ResetPlayer, sQuery, GetClientUserId(client));
634 }
635 }
636 else
637 {
638 int iClients = ProcessTargetString(sTmp, 0, iTargets, 1, 0, sTmp, sizeof(sTmp), bTmp);
639 if (iClients>2)
640 {
641 CPrintToChat(client, "%s%t", g_sChatPrefix, "Credit Too Many Matches");
642 return Plugin_Handled;
643 }
644
645 if (iClients != 1)
646 {
647 CPrintToChat(client, "%s%t", g_sChatPrefix, "Credit No Match");
648 return Plugin_Handled;
649 }
650
651 iReceiver = iTargets[0];
652 }
653
654 // The player is on the server
655 if (iReceiver != -1)
656 {
657 g_iCredits[iReceiver] = 0;
658 for (int i = 0; i < g_iItems[iReceiver]; i++)
659 {
660 MyStore_RemoveItem(iReceiver, g_iPlayerItems[iReceiver][i][UNIQUE_ID]);
661 }
662
663 MyLogMessage(client, LOG_ADMIN, "%L resetted. Removed %i credits & %i items", iReceiver, g_iCredits[iReceiver], g_iItems[iReceiver]);
664 MyLogMessage(iReceiver, LOG_CREDITS, "%i credits & %i items resetted by %L", g_iCredits[iReceiver], g_iItems[iReceiver], client);
665
666 CPrintToChatAll("%s%t", g_sChatPrefix, "Player Resetted", iReceiver);
667 }
668
669 return Plugin_Handled;
670}
671
672public Action Command_Credits(int client, int params)
673{
674 //Buisness as usual
675 if (!gc_bEnable.BoolValue)
676 {
677 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
678 return Plugin_Handled;
679 }
680
681 if (g_iCredits[client] == -1 && g_iItems[client] == -1)
682 {
683 CPrintToChat(client, "%s%t", g_sChatPrefix, "Inventory hasnt been fetched");
684 return Plugin_Handled;
685 }
686
687 if (g_iSpam[client] < GetTime())
688 {
689 CPrintToChatAll("%s%t", g_sChatPrefix, "Player Credits", client, g_iCredits[client], g_sCreditsName);
690 g_iSpam[client] = GetTime() + 20;
691 }
692 else
693 {
694 CPrintToChat(client, "%s%t", g_sChatPrefix, "Spam Cooldown", g_iSpam[client] - GetTime());
695 }
696
697 return Plugin_Handled;
698}
699
700/******************************************************************************
701 Events
702******************************************************************************/
703
704public void Event_PlayerDeath(Event event, char[] name, bool dontBroadcast)
705{
706 int victim = GetClientOfUserId(event.GetInt("userid"));
707
708 if (!gc_bSaveOnDeath.BoolValue)
709 return;
710
711 SQL_SaveClientData(victim);
712 SQL_SaveClientInventory(victim);
713 SQL_SaveClientEquipment(victim);
714}
715
716
717/******************************************************************************
718 Sourcemod forwards
719******************************************************************************/
720
721public void OnMapStart()
722{
723 for (int i = 0; i < g_iTypeHandlers; i++)
724 {
725 if (g_aTypeHandlers[i][fnMapStart] == INVALID_FUNCTION)
726 continue;
727
728 Call_StartFunction(g_aTypeHandlers[i][hPlugin], g_aTypeHandlers[i][fnMapStart]);
729 Call_PushString(g_sChatPrefix);
730 Call_Finish();
731 }
732}
733
734public void OnClientConnected(int client)
735{
736 //Reset variables
737 g_iSpam[client] = 0;
738 g_iCredits[client] = -1;
739 g_iItems[client] = -1;
740 g_bLoaded[client] = false;
741
742 for (int i = 0; i < STORE_MAX_TYPES; i++)
743 {
744 for (int a = 0; a < STORE_MAX_SLOTS; a++)
745 {
746 g_iEquipment[client][i * STORE_MAX_SLOTS + a] = -2;
747 g_iEquipmentSynced[client][i * STORE_MAX_SLOTS + a] = -2;
748 }
749 }
750}
751
752public void OnClientPostAdminCheck(int client)
753{
754 if (IsFakeClient(client))
755 return;
756
757 SQL_LoadClientInventory(client);
758}
759
760public void OnClientDisconnect(int client)
761{
762 if (IsFakeClient(client))
763 return;
764
765 SQL_SaveClientData(client);
766 SQL_SaveClientInventory(client);
767 SQL_SaveClientEquipment(client);
768
769 MyLogMessage(client, LOG_EVENT, "Left game with %i credits & %i items", g_iCredits[client], g_iItems[client]);
770
771 g_iCredits[client] = -1;
772 g_iItems[client] = -1;
773 g_bLoaded[client] = false;
774 g_bIsInRecurringMenu[client] = false;
775}
776
777public void OnAdminMenuReady(Handle topmenu)
778{
779 if (topmenu == g_hTopMenu)
780 return;
781
782 g_hTopMenu = view_as<TopMenu>(topmenu);
783
784 g_hTopMenuObject = AddToTopMenu(g_hTopMenu, "MyStore Admin", TopMenuObject_Category, CategoryHandler_StoreAdmin, INVALID_TOPMENUOBJECT);
785 AddToTopMenu(g_hTopMenu, "sm_resetdb", TopMenuObject_Item, AdminMenu_ResetDb, g_hTopMenuObject, "sm_resetdb", g_iAdminFlags);
786 AddToTopMenu(g_hTopMenu, "sm_reloadconfig", TopMenuObject_Item, AdminMenu_ReloadConfig, g_hTopMenuObject, "sm_reloadconfig", g_iAdminFlags);
787 AddToTopMenu(g_hTopMenu, "sm_resetplayer", TopMenuObject_Item, AdminMenu_ResetPlayer, g_hTopMenuObject, "sm_resetplayer", g_iAdminFlags);
788 AddToTopMenu(g_hTopMenu, "sm_givecredits", TopMenuObject_Item, AdminMenu_GiveCredits, g_hTopMenuObject, "sm_givecredits", g_iAdminFlags);
789 AddToTopMenu(g_hTopMenu, "sm_viewinventory", TopMenuObject_Item, AdminMenu_ViewInventory, g_hTopMenuObject, "sm_viewinventory", g_iAdminFlags);
790}
791
792/******************************************************************************
793 Menus & Handler
794******************************************************************************/
795
796public void CategoryHandler_StoreAdmin(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] sBuffer, int maxlength)
797{
798 if (action == TopMenuAction_DisplayTitle || action == TopMenuAction_DisplayOption)
799 {
800 Format(sBuffer, maxlength, "Store Admin");
801 }
802}
803
804public void AdminMenu_ReloadConfig(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int client, char[] sBuffer, int maxlength)
805{
806 if (action == TopMenuAction_DisplayOption)
807 {
808 Format(sBuffer, maxlength, "Reload configs");
809 }
810 else if (action == TopMenuAction_SelectOption)
811 {
812 g_iMenuNum[client] = 0;
813 MyStore_DisplayConfirmMenu(client, "Do you want to reload configs/MyStore/items.txt?", FakeMenuHandler_ReloadConfig, 0);
814 }
815}
816
817
818public void AdminMenu_ResetDb(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int client, char[] sBuffer, int maxlength)
819{
820 if (action == TopMenuAction_DisplayOption)
821 {
822 Format(sBuffer, maxlength, "Reset database");
823 }
824 else if (action == TopMenuAction_SelectOption)
825 {
826 g_iMenuNum[client] = 0;
827 MyStore_DisplayConfirmMenu(client, "Do you want to reset database?\nServer will be restarted!", FakeMenuHandler_ResetDatabase, 0);
828 }
829}
830
831public void FakeMenuHandler_ResetDatabase(Menu menu, MenuAction action, int client, int param2)
832{
833 float time = GetEngineTime();
834 Transaction tnx = new Transaction();
835
836 tnx.AddQuery("DROP TABLE mystore_players");
837 tnx.AddQuery("DROP TABLE mystore_items");
838 tnx.AddQuery("DROP TABLE mystore_equipment");
839
840 g_hDatabase.Execute(tnx, SQLTXNCallback_Success, SQLTXNCallback_Error, time);
841
842// ServerCommand("_restart;");
843}
844
845public void FakeMenuHandler_ReloadConfig(Menu menu, MenuAction action, int client, int param2)
846{
847 Forward_OnConfigsExecuted();
848
849 ReloadConfig();
850}
851
852public void AdminMenu_ResetPlayer(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int client, char[] sBuffer, int maxlength)
853{
854 if (action == TopMenuAction_DisplayOption)
855 {
856 Format(sBuffer, maxlength, "Reset player");
857 }
858 else if (action == TopMenuAction_SelectOption)
859 {
860 g_iMenuNum[client] = 4;
861 Menu menu = new Menu(MenuHandler_ResetPlayer);
862 menu.SetTitle("Choose a player to reset");
863 menu.ExitBackButton = true;
864
865 for (int i = 1; i <= MaxClients; i++)
866 {
867 if (!IsClientConnected(i) || !IsClientAuthorized(i))
868 continue;
869
870 char sName[64];
871 char sAuthId[32];
872 GetClientName(i, sName, sizeof(sName));
873 GetLegacyAuthString(i, sAuthId, sizeof(sAuthId));
874 menu.AddItem(sAuthId, sName);
875 }
876 menu.Display(client, MENU_TIME_FOREVER);
877 }
878}
879
880public int MenuHandler_ResetPlayer(Menu menu, MenuAction action, int client, int param2)
881{
882 if (action == MenuAction_End)
883 {
884 menu.Cancel();
885 }
886 else if (action == MenuAction_Select)
887 {
888 if (menu == null)
889 {
890 FakeClientCommandEx(client, "sm_resetplayer \"%s\"", g_sSelectedClient[client]);
891 }
892 else
893 {
894 int style;
895 char sName[64];
896 menu.GetItem(param2, g_sSelectedClient[client], sizeof(g_sSelectedClient[]), style, sName, sizeof(sName));
897
898 char sTitle[256];
899 Format(sTitle, sizeof(sTitle), "Do you want to reset %s?", sName);
900 MyStore_DisplayConfirmMenu(client, sTitle, MenuHandler_ResetPlayer, 0);
901 }
902 }
903 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
904 {
905 RedisplayAdminMenu(g_hTopMenu, client);
906 }
907}
908
909public void AdminMenu_GiveCredits(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int client, char[] sBuffer, int maxlength)
910{
911 if (action == TopMenuAction_DisplayOption)
912 {
913 Format(sBuffer, maxlength, "Give credits");
914 }
915 else if (action == TopMenuAction_SelectOption)
916 {
917 g_iMenuNum[client] = 5;
918 Menu menu = new Menu(MenuHandler_GiveCredits);
919 menu.SetTitle("Choose a player to give credits to");
920 menu.ExitBackButton = true;
921
922 for (int i = 1; i <= MaxClients; i++)
923 {
924 if (!IsClientConnected(i) || !IsClientAuthorized(i))
925 continue;
926
927 char sName[64];
928 char sAuthId[32];
929 GetClientName(i, sName, sizeof(sName));
930 GetLegacyAuthString(i, sAuthId, sizeof(sAuthId));
931 menu.AddItem(sAuthId, sName);
932 }
933 menu.Display(client, MENU_TIME_FOREVER);
934 }
935}
936
937public int MenuHandler_GiveCredits(Menu menu, MenuAction action, int client, int param2)
938{
939 if (action == MenuAction_End)
940 {
941 menu.Cancel();
942 }
943 else if (action == MenuAction_Select)
944 {
945 if (param2 != -1)
946 {
947 menu.GetItem(param2, g_sSelectedClient[client], sizeof(g_sSelectedClient[]));
948 }
949
950 Menu mMenu = new Menu(MenuHandler_GiveCredits2);
951
952 int target = GetClientBySteamID(g_sSelectedClient[client]);
953 if (target == 0)
954 {
955 AdminMenu_GiveCredits(g_hTopMenu, TopMenuAction_SelectOption, g_hTopMenuObject, client, "", 0);
956 return;
957 }
958
959 mMenu.SetTitle("Choose the amount of %s\n%N - %i %s", g_sCreditsName, target, g_iCredits[target], g_sCreditsName);
960 mMenu.ExitBackButton = true;
961 mMenu.AddItem("-1000", "-1000");
962 mMenu.AddItem("-100", "-100");
963 mMenu.AddItem("-10", "-10");
964 mMenu.AddItem("10", "10");
965 mMenu.AddItem("100", "100");
966 mMenu.AddItem("1000", "1000");
967 mMenu.Display(client, MENU_TIME_FOREVER);
968 }
969 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
970 {
971 RedisplayAdminMenu(g_hTopMenu, client);
972 }
973}
974
975public int MenuHandler_GiveCredits2(Menu menu, MenuAction action, int client, int param2)
976{
977 if (action == MenuAction_End)
978 {
979 menu.Cancel();
980 }
981 else if (action == MenuAction_Select)
982 {
983 char sData[11];
984 menu.GetItem(param2, sData, sizeof(sData));
985 FakeClientCommand(client, "sm_givecredits \"%s\" %s", g_sSelectedClient[client], sData);
986 MenuHandler_GiveCredits(null, MenuAction_Select, client, -1); //null oder menu ??
987 }
988 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
989 {
990 AdminMenu_GiveCredits(g_hTopMenu, TopMenuAction_SelectOption, g_hTopMenuObject, client, "", 0);
991 }
992}
993
994public void AdminMenu_ViewInventory(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int client, char[] sBuffer, int maxlength)
995{
996 if (action == TopMenuAction_DisplayOption)
997 {
998 Format(sBuffer, maxlength, "View inventory");
999 }
1000 else if (action == TopMenuAction_SelectOption)
1001 {
1002 g_iMenuNum[client] = 4;
1003 Menu menu = new Menu(MenuHandler_ViewInventory);
1004 menu.SetTitle("Choose a player");
1005 menu.ExitBackButton = true;
1006
1007 for (int i = 1; i <= MaxClients; i++)
1008 {
1009 if (!IsClientConnected(i) || !IsClientAuthorized(i))
1010 continue;
1011
1012 char sName[64];
1013 char sAuthId[32];
1014 GetClientName(i, sName, sizeof(sName));
1015 GetLegacyAuthString(i, sAuthId, sizeof(sAuthId));
1016 menu.AddItem(sAuthId, sName);
1017 }
1018 menu.Display(client, MENU_TIME_FOREVER);
1019 }
1020}
1021
1022public int MenuHandler_ViewInventory(Menu menu, MenuAction action, int client, int param2)
1023{
1024 if (action == MenuAction_End)
1025 {
1026 menu.Cancel();
1027 }
1028 else if (action == MenuAction_Select)
1029 {
1030 menu.GetItem(param2, g_sSelectedClient[client], sizeof(g_sSelectedClient[]));
1031 int target = GetClientBySteamID(g_sSelectedClient[client]);
1032 if (target == 0)
1033 {
1034 AdminMenu_ViewInventory(g_hTopMenu, TopMenuAction_SelectOption, g_hTopMenuObject, client, "", 0);
1035 return;
1036 }
1037
1038 g_bInvMode[client] = true;
1039 g_iMenuClient[client] = target;
1040 DisplayStoreMenu(client);
1041 }
1042 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
1043 {
1044 RedisplayAdminMenu(g_hTopMenu, client);
1045 }
1046}
1047
1048// The main store menu
1049void DisplayStoreMenu(int client, int parent = -1, int last = -1)
1050{
1051 if (!client)
1052 return;
1053
1054 if (!gc_bEnable.BoolValue)
1055 {
1056 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
1057 return;
1058 }
1059
1060 g_iMenuNum[client] = 1;
1061 int target = g_iMenuClient[client];
1062
1063 Menu menu = new Menu(MenuHandler_Store);
1064
1065 // Build menu title
1066 if (parent != -1)
1067 {
1068 menu.ExitBackButton = true;
1069 if (client == target)
1070 {
1071 menu.SetTitle("%s\n%s\n%t", g_aItems[parent][szName], g_aItems[parent][szDescription], "Title Credits", g_sCreditsName, g_iCredits[target]);
1072 }
1073 else
1074 {
1075 menu.SetTitle("%N\n%s\n%t", target, g_aItems[parent][szName], "Title Credits", g_sCreditsName, g_iCredits[target]);
1076 }
1077
1078 g_iMenuBack[client] = g_aItems[parent][iParent];
1079 }
1080 else if (client == target)
1081 {
1082 menu.SetTitle("%t\n%t", "Title Store", g_sName, "Title Credits", g_sCreditsName, g_iCredits[target]);
1083 }
1084 else
1085 {
1086 menu.SetTitle("%N\n%t\n%t", target, "Title Store", g_sName, "Title Credits", g_sCreditsName, g_iCredits[target]);
1087 }
1088
1089 char sId[11];
1090 int iFlags = GetUserFlagBits(target);
1091 int iPosition = 0;
1092
1093 g_iSelectedItem[client] = parent;
1094
1095 // List all Items
1096 for (int i = 0; i < g_iItemCount; i++)
1097 {
1098 if (g_aItems[i][iParent] == parent && (!gc_bShowVIP.BoolValue && CheckFlagBits(target, g_aItems[i][iFlagBits], iFlags && CheckSteamAuth(target, g_aItems[i][szSteam])) || gc_bShowVIP.BoolValue))
1099 {
1100 int costs = GetLowestPrice(i);
1101 bool reduced = false;
1102 costs = Forward_OnGetEndPrice(client, i, costs, reduced);
1103
1104 // This is a package
1105 if (g_aItems[i][iHandler] == g_iPackageHandler)
1106 {
1107 if (!PackageHasClientItem(target, i, g_bInvMode[client]))
1108 continue;
1109
1110 int iStyle = ITEMDRAW_DEFAULT;
1111 if (gc_bShowVIP.BoolValue && (!CheckFlagBits(target, g_aItems[i][iFlagBits], iFlags) || !CheckSteamAuth(target, g_aItems[i][szSteam])))
1112 {
1113 iStyle = ITEMDRAW_DISABLED;
1114 }
1115
1116 char sBuffer[128];
1117 IntToString(i, sId, sizeof(sId));
1118 // Player already own the package or the package is free
1119 if (g_aItems[i][iPrice] == -1 || MyStore_HasClientItem(target, i))
1120 {
1121 Format(sBuffer, sizeof(sBuffer), "%s\n%s", g_aItems[i][szName], g_aItems[i][szDescription]);
1122 if (PackageHasClientItem(target, i, false))
1123 {
1124 if (menu.ItemCount == iPosition)
1125 {
1126 menu.AddItem(sId, sBuffer, iStyle);
1127 }
1128 else
1129 {
1130 menu.InsertItem(iPosition, sId, sBuffer, iStyle);
1131 }
1132 }
1133 else
1134 {
1135 menu.AddItem(sId, sBuffer, iStyle);
1136 }
1137 }
1138 // Player can buy the package as normal trade in
1139 else if (!g_bInvMode[client] && g_aItems[i][iPlans] == 0 && g_aItems[i][bBuyable])
1140 {
1141 Format(sBuffer, sizeof(sBuffer), "%t\n%s", "Item Available", g_aItems[i][szName], g_aItems[i][iPrice], g_aItems[i][szDescription]);
1142 if (menu.ItemCount == iPosition)
1143 {
1144 menu.AddItem(sId, sBuffer, iStyle);
1145 }
1146 else
1147 {
1148 menu.InsertItem(iPosition, sId, sBuffer, iStyle);
1149 }
1150 }
1151 // Player can buy the package in a plan
1152 else if (!g_bInvMode[client])
1153 {
1154 Format(sBuffer, sizeof(sBuffer), "%t\n%s", "Item Plan Available", g_aItems[i][szName], g_aItems[i][szDescription]);
1155 if (menu.ItemCount == iPosition)
1156 {
1157 menu.AddItem(sId, sBuffer, (costs <= g_iCredits[target] ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED));
1158 }
1159 else
1160 {
1161 menu.InsertItem(iPosition, sId, sBuffer, (costs <= g_iCredits[target] ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED));
1162 }
1163 }
1164 // iPosition++; // old
1165 }
1166 // This is a normal item
1167 else
1168 {
1169 char sBuffer[128];
1170 IntToString(i, sId, sizeof(sId));
1171 // Player already own the item
1172 if (MyStore_HasClientItem(target, i))
1173 {
1174 // Player has item equipt
1175 if (IsEquipped(target, i))
1176 {
1177 Format(sBuffer, sizeof(sBuffer), "%t\n%s", "Item Equipped", g_aItems[i][szName], g_aItems[i][szDescription]);
1178 if (menu.ItemCount == iPosition)
1179 {
1180 menu.AddItem(sId, sBuffer, ITEMDRAW_DEFAULT);
1181 }
1182 else
1183 {
1184 menu.InsertItem(iPosition, sId, sBuffer, ITEMDRAW_DEFAULT);
1185 }
1186 }
1187 // Item is not equipt
1188 else
1189 {
1190 Format(sBuffer, sizeof(sBuffer), "%t\n%s", "Item Bought", g_aItems[i][szName], g_aItems[i][szDescription]);
1191 if (menu.ItemCount == iPosition)
1192 {
1193 menu.AddItem(sId, sBuffer, ITEMDRAW_DEFAULT);
1194 }
1195 else
1196 {
1197 menu.InsertItem(iPosition, sId, sBuffer, ITEMDRAW_DEFAULT);
1198 }
1199 }
1200 }
1201 // Player don't own the item
1202 else if (!g_bInvMode[client] && g_aItems[i][bBuyable])
1203 {
1204 int iStyle = ITEMDRAW_DEFAULT;
1205 if ((g_aItems[i][iPlans] == 0 && g_iCredits[target] < costs && !g_aItems[i][bPreview]) || (gc_bShowVIP.BoolValue && !CheckFlagBits(target, g_aItems[i][iFlagBits], iFlags) && !CheckSteamAuth(target, g_aItems[i][szSteam])))
1206 {
1207 iStyle = ITEMDRAW_DISABLED;
1208 }
1209
1210 // Player can buy the item as normal trade in
1211 if (g_aItems[i][iPlans] == 0)
1212 {
1213 Format(sBuffer, sizeof(sBuffer), "%t %t\n%s", "Item Available", g_aItems[i][szName], costs, reduced ? "discount" : "nodiscount", g_aItems[i][szDescription]);
1214 menu.AddItem(sId, sBuffer, iStyle);
1215 }
1216 // Player can buy the item in a plan
1217 else
1218 {
1219 Format(sBuffer, sizeof(sBuffer), "%t %t\n%s", "Item Plan Available", g_aItems[i][szName], reduced ? "discount" : "nodiscount", g_aItems[i][szDescription]);
1220 menu.AddItem(sId, sBuffer, iStyle);
1221 }
1222 }
1223
1224 }
1225
1226 iPosition++;
1227 }
1228 }
1229
1230 // Package
1231 if (parent != -1)
1232 {
1233 for (int i = 0; i < g_iItemHandlers; i++)
1234 {
1235 if (g_hItemPlugin[i] == null)
1236 continue;
1237
1238 Call_StartFunction(g_hItemPlugin[i], g_fnItemMenu[i]);
1239 Call_PushCellRef(menu);
1240 Call_PushCell(client);
1241 Call_PushCell(parent);
1242 Call_Finish();
1243 }
1244 }
1245
1246 if (last == -1)
1247 {
1248 menu.Display(client, MENU_TIME_FOREVER);
1249 }
1250 else
1251 {
1252 DisplayMenuAtItem(menu, client, (last / menu.Pagination) * menu.Pagination, 0);
1253 }
1254}
1255
1256public int MenuHandler_Store(Menu menu, MenuAction action, int client, int param2)
1257{
1258 if (action == MenuAction_End)
1259 {
1260 menu.Cancel();
1261 }
1262 else if (action == MenuAction_Select)
1263 {
1264 int target = g_iMenuClient[client];
1265 // Confirmation was given
1266 if (menu == null)
1267 {
1268 if (param2 == 0)
1269 {
1270 g_iMenuBack[client] = 1;
1271 int costs = 0;
1272
1273 if (g_iSelectedPlan[client] == -1)
1274 {
1275 costs = Forward_OnGetEndPrice(client, g_iSelectedItem[client], g_aItems[g_iSelectedItem[client]][iPrice]);
1276 }
1277 else
1278 {
1279 costs = Forward_OnGetEndPrice(client, g_iSelectedItem[client], g_iPlanPrice[g_iSelectedItem[client]][g_iSelectedPlan[client]]);
1280 }
1281
1282 if (g_iCredits[target] >= costs && !MyStore_HasClientItem(target, g_iSelectedItem[client]))
1283 {
1284 BuyItem(target, g_iSelectedItem[client], g_iSelectedPlan[client]);
1285 }
1286
1287 DisplayItemMenu(client, g_iSelectedItem[client]);
1288 }
1289 }
1290 else
1291 {
1292 char sId[64];
1293 menu.GetItem(param2, sId, sizeof(sId));
1294
1295 g_iLastSelection[client] = param2;
1296
1297 // This is menu handler stuff
1298 if (!(48 <= sId[0] <= 57))
1299 {
1300 bool ret;
1301 for (int i = 0; i < g_iItemHandlers; i++)
1302 {
1303 Call_StartFunction(g_hItemPlugin[i], g_fnItemHandler[i]);
1304 Call_PushCell(target);
1305 Call_PushString(sId);
1306 Call_PushCell(g_iSelectedItem[client]);
1307 Call_Finish(ret);
1308
1309 if (ret)
1310 break;
1311 }
1312 }
1313 // We are selcting an item
1314 else
1315 {
1316 int iIndex = StringToInt(sId);
1317 g_iMenuBack[client] = g_aItems[iIndex][iParent];
1318 g_iSelectedItem[client] = iIndex;
1319 g_iSelectedPlan[client] = -1;
1320
1321 if (g_aItems[iIndex][bPreview] && !MyStore_HasClientItem(target, iIndex) && g_aItems[iIndex][iPrice] != -1 && g_aItems[iIndex][iPlans] == 0)
1322 {
1323 DisplayPreviewMenu(client, iIndex);
1324 return;
1325 }
1326
1327 int costs = GetLowestPrice(iIndex);
1328 costs = Forward_OnGetEndPrice(client, iIndex, costs);
1329
1330 if ((g_iCredits[target] >= costs || g_aItems[iIndex][iPlans] > 0) && !MyStore_HasClientItem(target, iIndex) && g_aItems[iIndex][iPrice] != -1)
1331 {
1332 if (g_aItems[iIndex][iPlans] > 0)
1333 {
1334 DisplayPlanMenu(client, iIndex);
1335 return;
1336 }
1337 else if (gc_bConfirm.BoolValue)
1338 {
1339 char sTitle[128];
1340 Format(sTitle, sizeof(sTitle), "%t", "Confirm_Buy", g_aItems[iIndex][szName], g_aTypeHandlers[g_aItems[iIndex][iHandler]][szType]);
1341 MyStore_DisplayConfirmMenu(client, sTitle, MenuHandler_Store, 0);
1342 return;
1343 }
1344 else
1345 {
1346 BuyItem(target, iIndex);
1347 DisplayItemMenu(client, iIndex);
1348 }
1349 }
1350
1351 if (g_aItems[iIndex][iHandler] != g_iPackageHandler)
1352 {
1353 if (MyStore_HasClientItem(target, iIndex))
1354 {
1355 DisplayItemMenu(client, iIndex);
1356 }
1357 else
1358 {
1359 DisplayStoreMenu(client, g_iMenuBack[client]);
1360 }
1361 }
1362 else
1363 {
1364 if (MyStore_HasClientItem(target, iIndex) || g_aItems[iIndex][iPrice] == -1)
1365 {
1366 DisplayStoreMenu(client, iIndex);
1367 }
1368 else
1369 {
1370 DisplayStoreMenu(client, g_aItems[iIndex][iParent]);
1371 }
1372 }
1373 }
1374 }
1375 }
1376 else if (action == MenuAction_Cancel)
1377 {
1378 if (param2 == MenuCancel_ExitBack)
1379 {
1380 MyStore_DisplayPreviousMenu(client);
1381 }
1382 }
1383}
1384
1385public void DisplayItemMenu(int client, int itemid)
1386{
1387 if (!gc_bEnable.BoolValue)
1388 {
1389 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
1390 return;
1391 }
1392
1393 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bRaw])
1394 {
1395 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnUse]);
1396 Call_PushCell(client);
1397 Call_PushCell(itemid);
1398 Call_Finish();
1399 return;
1400 }
1401
1402 if (g_aItems[itemid][iHandler] == g_iPackageHandler)
1403 {
1404 DisplayStoreMenu(client, itemid);
1405 return;
1406 }
1407
1408 g_iMenuNum[client] = 1;
1409 g_iMenuBack[client] = g_aItems[itemid][iParent];
1410 int target = g_iMenuClient[client];
1411
1412 Menu menu = new Menu(MenuHandler_Item);
1413 menu.ExitBackButton = true;
1414
1415 bool bEquipped = IsEquipped(target, itemid);
1416 char sTitle[256];
1417 int iIndex = 0;
1418 if (bEquipped)
1419 {
1420 iIndex = Format(sTitle, sizeof(sTitle), "%t\n%s\n%t", "Item Equipped", g_aItems[itemid][szName], g_aItems[itemid][szDescription], "Title Credits", g_sCreditsName, g_iCredits[target]);
1421 }
1422 else
1423 {
1424 iIndex = Format(sTitle, sizeof(sTitle), "%s\n%s\n%t", g_aItems[itemid][szName], g_aItems[itemid][szDescription], "Title Credits", g_sCreditsName, g_iCredits[target]);
1425 }
1426
1427 int iExpiration = GetExpiration(target, itemid);
1428 if (iExpiration != 0)
1429 {
1430 iExpiration = iExpiration - GetTime();
1431 int iDays = iExpiration / (24 * 60 * 60);
1432 int iHours = (iExpiration - iDays * 24 * 60 * 60)/(60 * 60);
1433 Format(sTitle[iIndex - 1], sizeof(sTitle) - iIndex - 1, "\n%t", "Title Expiration", iDays, iHours);
1434 }
1435
1436 menu.SetTitle(sTitle);
1437
1438 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bEquipable])
1439 {
1440 if (!bEquipped)
1441 {
1442 Format(sTitle, sizeof(sTitle), "%t", "Item Equip");
1443 menu.AddItem("0", sTitle, ITEMDRAW_DEFAULT);
1444 }
1445 else
1446 {
1447 Format(sTitle, sizeof(sTitle), "%t", "Item Unequip");
1448 menu.AddItem("3", sTitle, ITEMDRAW_DEFAULT);
1449 }
1450 }
1451 else
1452 {
1453 Format(sTitle, sizeof(sTitle), "%t", "Item Use");
1454 menu.AddItem("0", sTitle, ITEMDRAW_DEFAULT);
1455 }
1456
1457 if (g_aItems[itemid][bPreview])
1458 {
1459 Format(sTitle, sizeof(sTitle), "%t", "Preview Item");
1460 menu.AddItem("4", sTitle, ITEMDRAW_DEFAULT);
1461 }
1462
1463 for (int i = 0; i < g_iItemHandlers; i++)
1464 {
1465 if (g_hItemPlugin[i] == null)
1466 continue;
1467
1468 Call_StartFunction(g_hItemPlugin[i], g_fnItemMenu[i]);
1469 Call_PushCellRef(menu);
1470 Call_PushCell(client);
1471 Call_PushCell(itemid);
1472 Call_Finish();
1473 }
1474
1475 menu.Display(client, MENU_TIME_FOREVER);
1476}
1477
1478public void DisplayPreviewMenu(int client, int itemid)
1479{
1480 if (!gc_bEnable.BoolValue)
1481 {
1482 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
1483 return;
1484 }
1485
1486 g_iMenuNum[client] = 1;
1487 int target = g_iMenuClient[client];
1488
1489 Menu menu = new Menu(MenuHandler_Preview);
1490 menu.ExitBackButton = true;
1491
1492 menu.SetTitle("%s\n%s\n%t", g_aItems[itemid][szName], g_aItems[itemid][szDescription], "Title Credits", g_sCreditsName, g_iCredits[target]);
1493
1494 char sBuffer[128];
1495 bool reduced = false;
1496 int price = Forward_OnGetEndPrice(client, itemid, g_aItems[itemid][iPrice], reduced);
1497
1498 if (MyStore_HasClientItem(client, itemid))
1499 {
1500 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bEquipable])
1501 {
1502 if (!IsEquipped(client, itemid))
1503 {
1504 Format(sBuffer, sizeof(sBuffer), "%t", "Item Equip");
1505 menu.AddItem("item_use", sBuffer, ITEMDRAW_DEFAULT);
1506 }
1507 else
1508 {
1509 Format(sBuffer, sizeof(sBuffer), "%t", "Item Unequip");
1510 menu.AddItem("item_unequipped", sBuffer, ITEMDRAW_DEFAULT);
1511 }
1512 }
1513 else
1514 {
1515 Format(sBuffer, sizeof(sBuffer), "%t", "Item Use");
1516 menu.AddItem("item_use", sBuffer, ITEMDRAW_DEFAULT);
1517 }
1518 }
1519 // Player don't own the item
1520 else if (!g_bInvMode[client] && g_aItems[itemid][bBuyable])
1521 {
1522 int iStyle = ITEMDRAW_DEFAULT;
1523 if ((g_aItems[itemid][iPlans] == 0 && g_iCredits[target] < price) || (gc_bShowVIP.BoolValue && !CheckFlagBits(target, g_aItems[itemid][iFlagBits]) && !CheckSteamAuth(target, g_aItems[itemid][szSteam])))
1524 {
1525 iStyle = ITEMDRAW_DISABLED;
1526 }
1527
1528 // Player can buy the item as normal trade in
1529 if (g_aItems[itemid][iPlans] == 0)
1530 {
1531 Format(sBuffer, sizeof(sBuffer), "%t %t", "Buy Item", price, reduced ? "discount" : "nodiscount");
1532 menu.AddItem("buy_item", sBuffer, g_iCredits[target] >= price ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
1533 }
1534 // Player can buy the item in a plan
1535 else
1536 {
1537 Format(sBuffer, sizeof(sBuffer), "%t %t", "Choose Plan", g_aItems[itemid][szName], reduced ? "discount" : "nodiscount");
1538 menu.AddItem("item_plan", sBuffer, iStyle);
1539 }
1540 }
1541
1542
1543 Format(sBuffer, sizeof(sBuffer), "%t", "Preview Item");
1544 menu.AddItem("preview_item", sBuffer, ITEMDRAW_DEFAULT);
1545
1546 for (int i = 0; i < g_iItemHandlers; i++)
1547 {
1548 if (g_hItemPlugin[i] == null)
1549 continue;
1550
1551 Call_StartFunction(g_hItemPlugin[i], g_fnItemMenu[i]);
1552 Call_PushCellRef(menu);
1553 Call_PushCell(client);
1554 Call_PushCell(itemid);
1555 Call_Finish();
1556 }
1557
1558 menu.Display(client, MENU_TIME_FOREVER);
1559}
1560
1561public int MenuHandler_Preview(Menu menu, MenuAction action, int client, int param2)
1562{
1563 if (action == MenuAction_End)
1564 {
1565 menu.Cancel();
1566 }
1567 else if (action == MenuAction_Select)
1568 {
1569 char sId[24];
1570 menu.GetItem(param2, sId, sizeof(sId));
1571 int itemid = g_iSelectedItem[client];
1572
1573 if (strcmp(sId, "buy_item") == 0)
1574 {
1575 if (gc_bConfirm.BoolValue)
1576 {
1577 char sTitle[128];
1578 Format(sTitle, sizeof(sTitle), "%t", "Confirm_Buy", g_aItems[itemid][szName], g_aTypeHandlers[g_aItems[itemid][iHandler]][szType]);
1579 MyStore_DisplayConfirmMenu(client, sTitle, MenuHandler_Store, 0);
1580 return;
1581 }
1582 else
1583 {
1584 BuyItem(client, itemid);
1585 DisplayPreviewMenu(client, itemid);
1586 }
1587
1588 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bRaw])
1589 {
1590 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnUse]);
1591 Call_PushCell(client);
1592 Call_PushCell(itemid);
1593 Call_Finish();
1594 return;
1595 }
1596 }
1597 else if (strcmp(sId, "item_plan") == 0)
1598 {
1599 DisplayPlanMenu(client, itemid);
1600 }
1601 else if (strcmp(sId, "item_use") == 0)
1602 {
1603 bool bRet = UseItem(client, g_iSelectedItem[client]);
1604 if (GetClientMenu(client) == MenuSource_None && bRet)
1605 {
1606 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bEquipable])
1607 {
1608 if (g_aItems[g_iSelectedItem[client]][bPreview])
1609 {
1610 DisplayPreviewMenu(client, g_iSelectedItem[client]);
1611 }
1612 else
1613 {
1614 DisplayItemMenu(client, g_iSelectedItem[client]);
1615 }
1616 }
1617 }
1618 }
1619 else if (strcmp(sId, "item_unequipped") == 0)
1620 {
1621 UnequipItem(client, itemid);
1622 if (g_aItems[g_iSelectedItem[client]][bPreview])
1623 {
1624 DisplayPreviewMenu(client, g_iSelectedItem[client]);
1625 }
1626 else
1627 {
1628 DisplayItemMenu(client, g_iSelectedItem[client]);
1629 }
1630 }
1631 else if (strcmp(sId, "preview_item") == 0)
1632 {
1633 if (g_iSpam[client] > GetTime())
1634 {
1635 CPrintToChat(client, "%s%t", g_sChatPrefix, "Spam Cooldown", g_iSpam[client] - GetTime());
1636 DisplayPreviewMenu(client, itemid);
1637 return;
1638 }
1639
1640 if (!IsPlayerAlive(client))
1641 {
1642 CPrintToChat(client, "%s%t", g_sChatPrefix, "Must be Alive");
1643 DisplayPreviewMenu(client, itemid);
1644 return;
1645 }
1646
1647 Call_StartForward(gf_hPreviewItem);
1648 Call_PushCell(client);
1649 Call_PushString(g_aTypeHandlers[g_aItems[itemid][iHandler]][szType]);
1650 Call_PushCell(g_aItems[itemid][iDataIndex]);
1651 Call_Finish();
1652 g_iSpam[client] = GetTime() + 10;
1653
1654 DisplayPreviewMenu(client, itemid);
1655 }
1656 else if (!(48 <= sId[0] <= 57))
1657 {
1658 bool ret;
1659 for (int i = 0; i < g_iItemHandlers; i++)
1660 {
1661 Call_StartFunction(g_hItemPlugin[i], g_fnItemHandler[i]);
1662 Call_PushCell(client);
1663 Call_PushString(sId);
1664 Call_PushCell(g_iSelectedItem[client]);
1665 Call_Finish(ret);
1666
1667 if (ret)
1668 break;
1669 }
1670 }
1671 }
1672 else if (action == MenuAction_Cancel)
1673 {
1674 if (param2 == MenuCancel_ExitBack)
1675 {
1676 MyStore_DisplayPreviousMenu(client);
1677 }
1678 }
1679}
1680
1681public void DisplayPlanMenu(int client, int itemid)
1682{
1683 if (!gc_bEnable.BoolValue)
1684 {
1685 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
1686 return;
1687 }
1688
1689 g_iMenuNum[client] = 1;
1690 int target = g_iMenuClient[client];
1691
1692 Menu menu = new Menu(MenuHandler_Plan);
1693 menu.ExitBackButton = true;
1694
1695 menu.SetTitle("%s\n%s\n%t", g_aItems[itemid][szName], g_aItems[itemid][szDescription], "Title Credits", g_sCreditsName, g_iCredits[target]);
1696
1697 char sBuffer[64];
1698 if (g_aItems[itemid][bPreview])
1699 {
1700 Format(sBuffer, sizeof(sBuffer), "%t", "Preview Item");
1701 menu.AddItem("preview", sBuffer, ITEMDRAW_DEFAULT);
1702 }
1703
1704 for (int i = 0; i < g_aItems[itemid][iPlans]; i++)
1705 {
1706 bool reduced = false;
1707 int price = Forward_OnGetEndPrice(client, itemid, g_iPlanPrice[itemid][i], reduced);
1708 Format(sBuffer, sizeof(sBuffer), "%t %t", "Item Available", g_sPlanName[itemid][i], price, reduced ? "discount" : "nodiscount");
1709 menu.AddItem("", sBuffer, g_iCredits[target] >= price ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
1710 }
1711
1712 menu.Display(client, MENU_TIME_FOREVER);
1713}
1714
1715public int MenuHandler_Plan(Menu menu, MenuAction action, int client, int param2)
1716{
1717 if (action == MenuAction_End)
1718 {
1719 menu.Cancel();
1720 }
1721 else if (action == MenuAction_Select)
1722 {
1723 int target = g_iMenuClient[client];
1724 g_iMenuNum[client] = 5;
1725
1726 char sId[24];
1727 menu.GetItem(param2, sId, sizeof(sId));
1728 int itemid = g_iSelectedItem[client];
1729
1730 if (strcmp(sId, "preview") == 0)
1731 {
1732 if (g_iSpam[client] < GetTime())
1733 {
1734 Call_StartForward(gf_hPreviewItem);
1735 Call_PushCell(client);
1736 Call_PushString(g_aTypeHandlers[g_aItems[itemid][iHandler]][szType]);
1737 Call_PushCell(g_aItems[itemid][iDataIndex]);
1738 Call_Finish();
1739 g_iSpam[client] = GetTime() + 10;
1740 }
1741 else
1742 {
1743 CPrintToChat(client, "%s%t", g_sChatPrefix, "Spam Cooldown", g_iSpam[client] - GetTime());
1744 }
1745
1746 DisplayPlanMenu(client, itemid);
1747 return;
1748 }
1749
1750 g_iSelectedPlan[client] = param2;
1751
1752 if (g_aItems[g_iSelectedItem[client]][bPreview])
1753 {
1754 g_iSelectedPlan[client]--;
1755 }
1756
1757 if (gc_bConfirm.BoolValue)
1758 {
1759 char sTitle[128];
1760 Format(sTitle, sizeof(sTitle), "%t", "Confirm_Buy", g_aItems[g_iSelectedItem[client]][szName], g_aTypeHandlers[g_aItems[g_iSelectedItem[client]][iHandler]][szType]);
1761 MyStore_DisplayConfirmMenu(client, sTitle, MenuHandler_Store, 0);
1762 }
1763 else
1764 {
1765 BuyItem(target, g_iSelectedItem[client], g_iSelectedPlan[client]);
1766 DisplayItemMenu(client, g_iSelectedItem[client]);
1767 }
1768
1769 }
1770 else if (action == MenuAction_Cancel)
1771 {
1772 if (param2 == MenuCancel_ExitBack)
1773 {
1774 MyStore_DisplayPreviousMenu(client);
1775 }
1776 }
1777}
1778
1779public int MenuHandler_Item(Menu menu, MenuAction action, int client, int param2)
1780{
1781 if (action == MenuAction_End)
1782 {
1783 menu.Cancel();
1784 }
1785 else if (action == MenuAction_Select)
1786 {
1787 int target = g_iMenuClient[client];
1788
1789 char sId[64];
1790 menu.GetItem(param2, sId, sizeof(sId));
1791
1792 int iIndex = StringToInt(sId);
1793
1794 // Menu handlers
1795 if (!(48 <= sId[0] <= 57))
1796 {
1797 bool ret;
1798 for (int i = 0; i < g_iItemHandlers; i++)
1799 {
1800 if (g_hItemPlugin[i] == null)
1801 continue;
1802
1803 Call_StartFunction(g_hItemPlugin[i], g_fnItemHandler[i]);
1804 Call_PushCell(client);
1805 Call_PushString(sId);
1806 Call_PushCell(g_iSelectedItem[client]);
1807 Call_Finish(ret);
1808
1809 if (ret)
1810 return;
1811 }
1812 }
1813
1814 // Player wants to equip this item
1815 switch(iIndex)
1816 {
1817 case 0:
1818 {
1819 bool bRet = UseItem(target, g_iSelectedItem[client]);
1820 if (GetClientMenu(client) == MenuSource_None && bRet)
1821 {
1822 if (g_aTypeHandlers[g_aItems[g_iSelectedItem[client]][iHandler]][bEquipable])
1823 {
1824 if (g_aItems[g_iSelectedItem[client]][bPreview])
1825 {
1826 DisplayPreviewMenu(client, g_iSelectedItem[client]);
1827 }
1828 else
1829 {
1830 DisplayItemMenu(client, g_iSelectedItem[client]);
1831 }
1832 }
1833 }
1834 }
1835 // Player wants to unequip this item
1836 case 3:
1837 {
1838 UnequipItem(target, g_iSelectedItem[client]);
1839 if (g_aItems[g_iSelectedItem[client]][bPreview])
1840 {
1841 DisplayPreviewMenu(client, g_iSelectedItem[client]);
1842 }
1843 else
1844 {
1845 DisplayItemMenu(client, g_iSelectedItem[client]);
1846 }
1847 }
1848 // Player wants to preview
1849 case 4:
1850 {
1851 if (g_iSpam[client] < GetTime())
1852 {
1853 Call_StartForward(gf_hPreviewItem);
1854 Call_PushCell(client);
1855 Call_PushString(g_aTypeHandlers[g_aItems[g_iSelectedItem[client]][iHandler]][szType]);
1856 Call_PushCell(g_aItems[g_iSelectedItem[client]][iDataIndex]);
1857 Call_Finish();
1858 g_iSpam[client] = GetTime() + 10; //todo preivewtime
1859 }
1860 else
1861 {
1862 CPrintToChat(client, "%s%t", g_sChatPrefix, "Spam Cooldown", g_iSpam[client] - GetTime());
1863 }
1864
1865 DisplayItemMenu(client, g_iSelectedItem[client]);
1866 }
1867 }
1868 }
1869 else if (action == MenuAction_Cancel)
1870 {
1871 if (param2 == MenuCancel_ExitBack)
1872 {
1873 MyStore_DisplayPreviousMenu(client);
1874 }
1875 }
1876}
1877
1878public int MenuHandler_Confirm(Menu menu, MenuAction action, int client, int param2)
1879{
1880 if (action == MenuAction_End)
1881 {
1882 menu.Cancel();
1883 }
1884 else if (action == MenuAction_Select)
1885 {
1886 if (param2 == 0)
1887 {
1888 char sCallback[32];
1889 char sData[11];
1890 GetMenuItem(menu, 0, sCallback, sizeof(sCallback));
1891 GetMenuItem(menu, 1, sData, sizeof(sData));
1892
1893 DataPack pack = view_as<DataPack>(StringToInt(sCallback));
1894 Handle m_hPlugin = view_as<Handle>(pack.ReadCell());
1895 Function fnMenuCallback = pack.ReadCell();
1896 delete pack;
1897
1898 if (fnMenuCallback != INVALID_FUNCTION)
1899 {
1900 Call_StartFunction(m_hPlugin, fnMenuCallback);
1901 Call_PushCell(INVALID_HANDLE);
1902 Call_PushCell(MenuAction_Select);
1903 Call_PushCell(client);
1904 Call_PushCell(StringToInt(sData));
1905 Call_Finish();
1906 }
1907 else
1908 {
1909 MyStore_DisplayPreviousMenu(client);
1910 }
1911 }
1912 else
1913 {
1914 MyStore_DisplayPreviousMenu(client);
1915 }
1916 }
1917}
1918
1919/******************************************************************************
1920 Timer
1921******************************************************************************/
1922
1923public Action Timer_LoadConfig(Handle timer)
1924{
1925 ReloadConfig();
1926}
1927
1928public Action Timer_DatabaseTimeout(Handle timer, int userid)
1929{
1930 // Database is connected successfully
1931 if (g_hDatabase != null)
1932 return Plugin_Stop;
1933
1934 if (g_iDatabaseRetries < gc_iDBRetries.IntValue)
1935 {
1936 Database.Connect(SQLCallback_Connect, "mystore");
1937 CreateTimer(gc_iDBTimeout.FloatValue, Timer_DatabaseTimeout);
1938 g_iDatabaseRetries++;
1939 }
1940 else
1941 {
1942 SetFailState("Database connection failed to initialize after %i retrie(s)", gc_iDBRetries.IntValue);
1943 }
1944
1945 return Plugin_Stop;
1946}
1947
1948/******************************************************************************
1949 SQL
1950******************************************************************************/
1951
1952void SQL_LoadClientInventory(int client)
1953{
1954 if (g_hDatabase == null)
1955 {
1956 MyLogMessage(client, LOG_ERROR, "SQL_LoadClientInventory: Database connection is lost or not yet initialized");
1957 return;
1958 }
1959
1960 char sQuery[256];
1961 char sAuthId[32];
1962
1963 GetLegacyAuthString(client, sAuthId, sizeof(sAuthId));
1964 if (sAuthId[0] == 0)
1965 return;
1966
1967 Format(sQuery, sizeof(sQuery), "SELECT * FROM mystore_players WHERE `authid` = \"%s\"", sAuthId[8]);
1968
1969 g_hDatabase.Query(SQLCallback_LoadClientInventory_Credits, sQuery, GetClientUserId(client));
1970}
1971
1972void SQL_SaveClientInventory(int client)
1973{
1974 if (g_hDatabase == null)
1975 {
1976 MyLogMessage(client, LOG_ERROR, "SQL_SaveClientInventory: Database connection is lost or not yet initialized");
1977 return;
1978 }
1979
1980 // Player disconnected before his inventory was even fetched
1981 if (g_iCredits[client] == -1 && g_iItems[client] == -1)
1982 return;
1983
1984 char sQuery[256];
1985 char sType[16];
1986 char sUniqueId[PLATFORM_MAX_PATH];
1987
1988 for (int i = 0; i < g_iItems[client]; i++) //transaction todo
1989 {
1990 strcopy(sType, sizeof(sType), g_aTypeHandlers[g_aItems[g_iPlayerItems[client][i][UNIQUE_ID]][iHandler]][szType]);
1991 strcopy(sUniqueId, sizeof(sUniqueId), g_aItems[g_iPlayerItems[client][i][UNIQUE_ID]][szUniqueId]);
1992
1993 if (g_iPlayerItems[client][i][SYNCED] == 0 && g_iPlayerItems[client][i][DELETED] == 0)
1994 {
1995 g_iPlayerItems[client][i][SYNCED] = 1;
1996 Format(sQuery, sizeof(sQuery), "INSERT INTO mystore_items (`player_id`, `type`, `unique_id`, `date_of_purchase`, `date_of_expiration`, `price_of_purchase`) VALUES (%i, \"%s\", \"%s\", %i, %i, %i)", g_iPlayerID[client], sType, sUniqueId, g_iPlayerItems[client][i][DATE_PURCHASE], g_iPlayerItems[client][i][DATE_EXPIRATION], g_iPlayerItems[client][i][PRICE_PURCHASE]);
1997 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
1998 }
1999 else if (g_iPlayerItems[client][i][SYNCED] == 1 && g_iPlayerItems[client][i][DELETED] == 1)
2000 {
2001 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_items WHERE `player_id` = %i AND `type` = \"%s\" AND `unique_id` = \"%s\"", g_iPlayerID[client], sType, sUniqueId);
2002
2003 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
2004 }
2005 }
2006}
2007
2008void SQL_SaveClientEquipment(int client) //tnx
2009{
2010 char sQuery[256];
2011 int iIndex;
2012
2013 float time = GetEngineTime();
2014 Transaction tnx = new Transaction();
2015
2016 for (int i = 0; i < STORE_MAX_TYPES; i++)
2017 {
2018 for (int a = 0; a < STORE_MAX_SLOTS; a++)
2019 {
2020 iIndex = i * STORE_MAX_SLOTS + a;
2021 if (g_iEquipmentSynced[client][iIndex] == g_iEquipment[client][iIndex])
2022 continue;
2023
2024 if (g_iEquipmentSynced[client][iIndex] != -2)
2025 {
2026 if (g_iEquipment[client][iIndex] == -1)
2027 {
2028 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_equipment WHERE `player_id` = %i AND `type` = \"%s\" AND `slot` = %i", g_iPlayerID[client], g_aTypeHandlers[i][szType], a);
2029 }
2030 else
2031 {
2032 Format(sQuery, sizeof(sQuery), "UPDATE mystore_equipment SET `unique_id` = \"%s\" WHERE `player_id` = %i AND `type` = \"%s\" AND `slot` = %i", g_aItems[g_iEquipment[client][iIndex]][szUniqueId], g_iPlayerID[client], g_aTypeHandlers[i][szType], a);
2033 }
2034 }
2035 else
2036 {
2037 Format(sQuery, sizeof(sQuery), "INSERT INTO mystore_equipment (`player_id`, `type`, `unique_id`, `slot`) VALUES(%i, \"%s\", \"%s\", %i)", g_iPlayerID[client], g_aTypeHandlers[i][szType], g_aItems[g_iEquipment[client][iIndex]][szUniqueId], a);
2038 }
2039
2040 tnx.AddQuery(sQuery);
2041 g_iEquipmentSynced[client][iIndex] = g_iEquipment[client][iIndex];
2042 }
2043 }
2044
2045 g_hDatabase.Execute(tnx, SQLTXNCallback_Success, SQLTXNCallback_Error, time);
2046}
2047
2048void SQL_SaveClientData(int client)
2049{
2050 if (g_hDatabase == null)
2051 {
2052 MyLogMessage(client, LOG_ERROR, "SQL_SaveClientData: Database connection is lost or not yet initialized ");
2053 return;
2054 }
2055
2056 if ((g_iCredits[client] == -1 && g_iItems[client] == -1) || !g_bLoaded[client])
2057 return;
2058
2059 char sName[32];
2060 GetClientName(client, sName, 32);
2061 g_hDatabase.Escape(sName, sName, 32);
2062
2063 char sQuery[256];
2064 Format(sQuery, sizeof(sQuery), "UPDATE mystore_players SET `credits` = %i, `date_of_last_join` = %i, `name` = '%s' WHERE `id` = %i", g_iCredits[client], g_bLastJoin[client], sName, g_iPlayerID[client]);
2065
2066 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
2067}
2068
2069public void SQLCallback_Connect(Database db, const char[] error, any data)
2070{
2071 if (db == null)
2072 {
2073 SetFailState("Failed to connect to SQL database. Error: %s", error);
2074 }
2075 else
2076 {
2077 // If it's already connected we are good to go
2078 if (g_hDatabase != null)
2079 return;
2080
2081 g_hDatabase = db;
2082
2083 char sBuffer[2];
2084 DBDriver iDriver = db.Driver;
2085 iDriver.GetIdentifier(sBuffer, sizeof(sBuffer));
2086
2087 float time = GetEngineTime();
2088 Transaction tnx = new Transaction();
2089
2090 if (sBuffer[0] == 'm')
2091 {
2092 g_bMySQL = true;
2093
2094 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_players` (\
2095 `id` int(11) NOT NULL AUTO_INCREMENT,\
2096 `authid` varchar(32) NOT NULL,\
2097 `name` varchar(64) NOT NULL,\
2098 `credits` int(11) NOT NULL,\
2099 `date_of_join` int(11) NOT NULL,\
2100 `date_of_last_join` int(11) NOT NULL,\
2101 PRIMARY KEY (`id`),\
2102 UNIQUE KEY `id` (`id`),\
2103 UNIQUE KEY `authid` (`authid`)\
2104 )");
2105
2106 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_items` (\
2107 `player_id` int(11) NOT NULL,\
2108 `type` varchar(16) NOT NULL,\
2109 `unique_id` varchar(256) NOT NULL,\
2110 `date_of_purchase` int(11) NOT NULL,\
2111 `date_of_expiration` int(11) NOT NULL,\
2112 `price_of_purchase` int(11) NOT NULL\
2113 )");
2114
2115 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_equipment` (\
2116 `player_id` int(11) NOT NULL,\
2117 `type` varchar(16) NOT NULL,\
2118 `unique_id` varchar(256) NOT NULL,\
2119 `slot` int(11) NOT NULL\
2120 )");
2121
2122 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_logs` (\
2123 `date` int(11) NOT NULL,\
2124 `level` varchar(8) NOT NULL,\
2125 `player_id` int(11) NOT NULL,\
2126 `reason` varchar(256) NOT NULL\
2127 )");
2128 }
2129 else
2130 {
2131 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_players` (\
2132 `id` INTEGER PRIMARY KEY AUTOINCREMENT,\
2133 `authid` varchar(32) NOT NULL,\
2134 `name` varchar(64) NOT NULL,\
2135 `credits` int(11) NOT NULL,\
2136 `date_of_join` int(11) NOT NULL,\
2137 `date_of_last_join` int(11) NOT NULL\
2138 )");
2139
2140 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_items` (\
2141 `player_id` int(11) NOT NULL,\
2142 `type` varchar(16) NOT NULL,\
2143 `unique_id` varchar(256) NOT NULL,\
2144 `date_of_purchase` int(11) NOT NULL,\
2145 `date_of_expiration` int(11) NOT NULL,\
2146 `price_of_purchase` int(11) NOT NULL\
2147 )");
2148
2149 tnx.AddQuery("CREATE TABLE IF NOT EXISTS `mystore_equipment` (\
2150 `player_id` int(11) NOT NULL,\
2151 `type` varchar(16) NOT NULL,\
2152 `unique_id` varchar(256) NOT NULL,\
2153 `slot` int(11) NOT NULL\
2154 )");
2155 }
2156
2157 char sQuery[256];
2158 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_items WHERE `date_of_expiration` <> 0 AND `date_of_expiration` < %i", GetTime());
2159 tnx.AddQuery(sQuery);
2160
2161 g_hDatabase.Execute(tnx, SQLTXNCallback_Success, SQLTXNCallback_Error, time);
2162 }
2163}
2164
2165public void SQLCallback_LoadClientInventory_Credits(Database db, DBResultSet results, const char[] error, int userid)
2166{
2167 if (results == null)
2168 {
2169 int client = GetClientOfUserId(userid);
2170 MyLogMessage(client, LOG_ERROR, "SQLCallback_LoadClientInventory_Credits: Error: %s", error);
2171 }
2172 else
2173 {
2174 int client = GetClientOfUserId(userid);
2175 if (!client)
2176 return;
2177
2178 char sQuery[256];
2179 char sSteamID[32];
2180 char sName[32];
2181 int itime = GetTime();
2182
2183 g_iItems[client] = -1;
2184
2185 GetLegacyAuthString(client, sSteamID, sizeof(sSteamID), false);
2186
2187 GetClientName(client, sName, 32);
2188 g_hDatabase.Escape(sName, sName, 32);
2189
2190 if (results.FetchRow())
2191 {
2192 g_iPlayerID[client] = results.FetchInt(0);
2193 g_iCredits[client] = results.FetchInt(3);
2194 g_bLastJoin[client] = itime;
2195
2196 Format(sQuery, sizeof(sQuery), "SELECT * FROM mystore_items WHERE `player_id` = %i", g_iPlayerID[client]);
2197 g_hDatabase.Query(SQLCallback_LoadClientInventory_Items, sQuery, userid);
2198
2199 MyLogMessage(client, LOG_EVENT, "Joined game with %i credits", g_iCredits[client]);
2200
2201 SQL_SaveClientData(client);
2202 }
2203 else
2204 {
2205 Format(sQuery, sizeof(sQuery), "INSERT INTO mystore_players (`authid`, `name`, `credits`, `date_of_join`, `date_of_last_join`) VALUES(\"%s\", '%s', %i, %i, %i)",
2206 sSteamID[8], sName, gc_iCreditsStart.IntValue, itime, itime);
2207 g_hDatabase.Query(SQLCallback_InsertClient, sQuery, userid);
2208
2209 g_iCredits[client] = gc_iCreditsStart.IntValue;
2210 g_bLastJoin[client] = itime;
2211 g_bLoaded[client] = true;
2212 g_iItems[client] = 0;
2213
2214 if (gc_iCreditsStart.IntValue > 0)
2215 {
2216 MyLogMessage(client, LOG_EVENT, "Recieved %i start credits", gc_iCreditsStart.IntValue);
2217 }
2218 }
2219 }
2220}
2221
2222public void SQLCallback_LoadClientInventory_Items(Database db, DBResultSet results, const char[] error, int userid)
2223{
2224 if (results == null)
2225 {
2226 int client = GetClientOfUserId(userid);
2227 MyLogMessage(client, LOG_ERROR, "SQLCallback_LoadClientInventory_Items: Error: %s", error);
2228 }
2229 else
2230 {
2231 int client = GetClientOfUserId(userid);
2232 if (!client)
2233 return;
2234
2235 char sQuery[256];
2236 Format(sQuery, sizeof(sQuery), "SELECT * FROM mystore_equipment WHERE `player_id` = %i", g_iPlayerID[client]);
2237 g_hDatabase.Query(SQLCallback_LoadClientInventory_Equipment, sQuery, userid);
2238
2239 if (!results.RowCount)
2240 {
2241 g_bLoaded[client] = true;
2242 g_iItems[client] = 0;
2243 return;
2244 }
2245
2246 char sUniqueId[PLATFORM_MAX_PATH];
2247 char sType[16];
2248 int iExpiration;
2249 int iUniqueID;
2250 int itime = GetTime();
2251
2252 int i = 0;
2253 while(results.FetchRow())
2254 {
2255 iUniqueID = -1;
2256 iExpiration = results.FetchInt(4);
2257 if (iExpiration && iExpiration <= itime)
2258 continue;
2259
2260 results.FetchString(1, sType, sizeof(sType));
2261 results.FetchString(2, sUniqueId, sizeof(sUniqueId));
2262 while((iUniqueID = GetItemId(sType, sUniqueId, iUniqueID)) != -1)
2263 {
2264 g_iPlayerItems[client][i][UNIQUE_ID] = iUniqueID;
2265 g_iPlayerItems[client][i][SYNCED] = 1;
2266 g_iPlayerItems[client][i][DELETED] = 0;
2267 g_iPlayerItems[client][i][DATE_PURCHASE] = results.FetchInt(3);
2268 g_iPlayerItems[client][i][DATE_EXPIRATION] = iExpiration;
2269 g_iPlayerItems[client][i][PRICE_PURCHASE] = results.FetchInt(5);
2270
2271 i++;
2272 }
2273 }
2274
2275 g_iItems[client] = i;
2276 }
2277}
2278
2279public void SQLCallback_LoadClientInventory_Equipment(Database db, DBResultSet results, const char[] error, int userid)
2280{
2281 if (results == null)
2282 {
2283 int client = GetClientOfUserId(userid);
2284 MyLogMessage(client, LOG_ERROR, "SQLCallback_LoadClientInventory_Equipment: Error: %s", error);
2285 }
2286 else
2287 {
2288 int client = GetClientOfUserId(userid);
2289 if (!client)
2290 return;
2291
2292 char sUniqueId[PLATFORM_MAX_PATH];
2293 char sType[16];
2294 int iUniqueID;
2295
2296 while(results.FetchRow())
2297 {
2298 results.FetchString(1, sType, sizeof(sType));
2299 results.FetchString(2, sUniqueId, sizeof(sUniqueId));
2300 iUniqueID = GetItemId(sType, sUniqueId);
2301 if (iUniqueID == -1)
2302 continue;
2303
2304 if (!MyStore_HasClientItem(client, iUniqueID))
2305 {
2306 UnequipItem(client, iUniqueID);
2307 }
2308 else
2309 {
2310 UseItem(client, iUniqueID, true, results.FetchInt(3));
2311 }
2312 }
2313
2314 g_bLoaded[client] = true;
2315 }
2316}
2317
2318public void SQLCallback_InsertClient(Database db, DBResultSet results, const char[] error, int userid)
2319{
2320 if (results == null)
2321 {
2322 int client = GetClientOfUserId(userid);
2323 MyLogMessage(client, LOG_ERROR, "SQLCallback_InsertClient: Error: %s", error);
2324 }
2325 else
2326 {
2327 int client = GetClientOfUserId(userid);
2328 if (!client)
2329 return;
2330
2331 g_iPlayerID[client] = results.InsertId;
2332 }
2333}
2334
2335public void SQLCallback_ResetPlayer(Database db, DBResultSet results, const char[] error, int userid)
2336{
2337 if (results == null)
2338 {
2339 int client = GetClientOfUserId(userid);
2340 MyLogMessage(client, LOG_ERROR, "SQLCallback_ResetPlayer: Error: %s", error);
2341 }
2342 else
2343 {
2344 int client = GetClientOfUserId(userid);
2345
2346 if (results.RowCount)
2347 {
2348 results.FetchRow();
2349 int id = results.FetchInt(0);
2350 char sAuthId[32];
2351 results.FetchString(1, sAuthId, sizeof(sAuthId));
2352
2353 float time = GetEngineTime();
2354 Transaction tnx = new Transaction();
2355
2356 char sQuery[512];
2357 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_players WHERE id = %i", id);
2358 tnx.AddQuery(sQuery);
2359
2360 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_items WHERE player_id = %i", id);
2361 tnx.AddQuery(sQuery);
2362
2363 Format(sQuery, sizeof(sQuery), "DELETE FROM mystore_equipment WHERE player_id = %i", id);
2364 tnx.AddQuery(sQuery);
2365
2366 g_hDatabase.Execute(tnx, SQLTXNCallback_Success, SQLTXNCallback_Error, time);
2367
2368 CPrintToChatAll("%s%t", g_sChatPrefix, "Player Resetted", sAuthId);
2369 }
2370 else
2371 {
2372 if (client)
2373 {
2374 CPrintToChat(client, "%s%t", g_sChatPrefix, "Credit No Match");
2375 }
2376 }
2377 }
2378}
2379
2380public void SQLCallback_Void_Error(Database db, DBResultSet results, const char[] error, any data)
2381{
2382 if (db == null)
2383 {
2384 MyLogMessage(0, LOG_ERROR, "SQLCallback_Void_Error: %s", error);
2385 }
2386}
2387
2388public void SQLTXNCallback_Success(Database db, float time, int numQueries, Handle[] results, any[] queryData)
2389{
2390 float querytime = GetEngineTime() - time;
2391 PrintToServer("MyStore - Transaction Complete - Querys: %i in %0.2f seconds", numQueries, querytime);
2392}
2393
2394public void SQLTXNCallback_Error(Database db, float time, int numQueries, const char[] error, int failIndex, any[] queryData)
2395{
2396 float querytime = GetEngineTime() - time;
2397 MyLogMessage(0, LOG_ERROR, "SQLTXNCallback_Error: %s - Querys: %i - FailedIndex: %i after %0.2f seconds", error, numQueries, failIndex, querytime);
2398}
2399
2400/******************************************************************************
2401 Natives
2402******************************************************************************/
2403
2404public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
2405{
2406 RegPluginLibrary("mystore");
2407
2408 CreateNative("MyStore_RegisterHandler", Native_RegisterHandler);
2409 CreateNative("MyStore_RegisterItemHandler", Native_RegisterItemHandler);
2410 CreateNative("MyStore_SetDataIndex", Native_SetDataIndex);
2411 CreateNative("MyStore_GetDataIndex", Native_GetDataIndex);
2412 CreateNative("MyStore_GetEquippedItem", Native_GetEquippedItem);
2413 CreateNative("MyStore_IsClientLoaded", Native_IsClientLoaded);
2414 CreateNative("MyStore_DisplayItemMenu", Native_DisplayItemMenu);
2415 CreateNative("MyStore_DisplayPreviousMenu", Native_DisplayPreviousMenu);
2416 CreateNative("MyStore_SetClientPreviousMenu", Native_SetClientMenu);
2417 CreateNative("MyStore_GetClientCredits", Native_GetClientCredits);
2418 CreateNative("MyStore_SetClientCredits", Native_SetClientCredits);
2419 CreateNative("MyStore_IsClientVIP", Native_IsClientVIP);
2420 CreateNative("MyStore_IsClientAdmin", Native_IsClientAdmin);
2421 CreateNative("MyStore_HasClientAccess", Native_HasClientAccess);
2422 CreateNative("MyStore_IsItemInBoughtPackage", Native_IsItemInBoughtPackage);
2423 CreateNative("MyStore_DisplayConfirmMenu", Native_DisplayConfirmMenu);
2424 CreateNative("MyStore_ShouldConfirm", Native_ShouldConfirm);
2425 CreateNative("MyStore_IsInRecurringMenu", Native_IsInRecurringMenu);
2426 CreateNative("MyStore_SetClientRecurringMenu", Native_SetClientRecurringMenu);
2427 CreateNative("MyStore_GetItem", Native_GetItem);
2428 CreateNative("MyStore_GetHandler", Native_GetHandler);
2429 CreateNative("MyStore_GiveItem", Native_GiveItem);
2430 CreateNative("MyStore_RemoveItem", Native_RemoveItem);
2431 CreateNative("MyStore_EquipItem", Native_EquipItem);
2432 CreateNative("MyStore_UnequipItem", Native_UnequipItem);
2433 CreateNative("MyStore_GetClientItem", Native_GetClientItem);
2434 CreateNative("MyStore_GetItemIdbyUniqueId", Native_GetItemIdbyUniqueId);
2435 CreateNative("MyStore_GetClientTarget", Native_GetClientTarget);
2436 CreateNative("MyStore_SellClientItem", Native_SellClientItem);
2437 CreateNative("MyStore_TransferClientItem", Native_TransferClientItem);
2438 CreateNative("MyStore_HasClientItem", Native_HasClientItem);
2439 CreateNative("MyStore_IterateEquippedItems", Native_IterateEquippedItems);
2440 CreateNative("MyStore_SQLQuery", Native_SQLQuery);
2441 CreateNative("MyStore_SQLTransaction", Native_SQLTransaction);
2442 CreateNative("MyStore_LogMessage", Native_LogMessage);
2443
2444 gf_hOnGetEndPrice = CreateGlobalForward("MyStore_OnGetEndPrice", ET_Event, Param_Cell, Param_Cell, Param_CellByRef, Param_CellByRef);
2445 gf_hOnConfigExecuted = CreateGlobalForward("MyStore_OnConfigExecuted", ET_Ignore, Param_Cell, Param_String, Param_String, Param_String);
2446 gf_hOnItemEquipt = CreateGlobalForward("MyStore_OnItemEquipt", ET_Ignore, Param_Cell, Param_Cell);
2447 gf_hPreviewItem = CreateGlobalForward("MyStore_OnPreviewItem", ET_Ignore, Param_Cell, Param_String, Param_Cell);
2448 gf_hOnBuyItem = CreateGlobalForward("MyStore_OnBuyItem", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_CellByRef);
2449
2450 return APLRes_Success;
2451}
2452
2453public int Native_RegisterHandler(Handle plugin, int numParams)
2454{
2455 if (g_iTypeHandlers == STORE_MAX_TYPES)
2456 return -1;
2457
2458 char sType[32];
2459 GetNativeString(1, sType, sizeof(sType));
2460 int iHandle = GetTypeHandler(sType);
2461 int iIndex = g_iTypeHandlers;
2462
2463 if (iHandle != -1)
2464 {
2465 iIndex = iHandle;
2466 }
2467 else
2468 {
2469 g_iTypeHandlers++;
2470 }
2471
2472 g_aTypeHandlers[iIndex][hPlugin] = plugin;
2473 g_aTypeHandlers[iIndex][fnMapStart] = GetNativeCell(2);
2474 g_aTypeHandlers[iIndex][fnReset] = GetNativeCell(3);
2475 g_aTypeHandlers[iIndex][fnConfig] = GetNativeCell(4);
2476 g_aTypeHandlers[iIndex][fnUse] = GetNativeCell(5);
2477 g_aTypeHandlers[iIndex][fnRemove] = GetNativeCell(6);
2478 g_aTypeHandlers[iIndex][bEquipable] = GetNativeCell(7);
2479 g_aTypeHandlers[iIndex][bRaw] = GetNativeCell(8);
2480 strcopy(g_aTypeHandlers[iIndex][szType], 32, sType);
2481
2482 return iIndex;
2483}
2484
2485public int Native_SQLTransaction(Handle plugin, int numParams)
2486{
2487 if (g_hDatabase == null)
2488 return -1;
2489
2490 Transaction tnx = GetNativeCell(1);
2491 DataPack pack = new DataPack();
2492 pack.WriteCell(plugin);
2493 pack.WriteFunction(GetNativeFunction(2));
2494 pack.WriteCell(GetNativeCell(3));
2495
2496 g_hDatabase.Execute(tnx, Natives_SQLTXNCallback_Success, Natives_SQLTXNCallback_Error, pack);
2497
2498 return 1;
2499}
2500
2501public void Natives_SQLTXNCallback_Success(Database db, DataPack pack, int numQueries, Handle[] results, any[] queryData)
2502{
2503 PrintToServer("MyStore - Native Transaction Complete - Querys: %i", numQueries);
2504
2505 pack.Reset();
2506 Handle plugin = pack.ReadCell();
2507 Function callback = pack.ReadFunction();
2508 any data = pack.ReadCell();
2509 delete pack;
2510
2511 Call_StartFunction(plugin, callback);
2512 Call_PushCell(db);
2513 Call_PushCell(data);
2514 Call_PushCell(numQueries);
2515 Call_PushArray(results, numQueries);
2516 Call_PushArray(queryData, numQueries);
2517 Call_Finish();
2518}
2519
2520public void Natives_SQLTXNCallback_Error(Database db, DataPack pack, int numQueries, const char[] error, int failIndex, any[] queryData)
2521{
2522 pack.Reset();
2523 Handle plugin = pack.ReadCell();
2524 delete pack;
2525
2526 char sBuffer[64];
2527 GetPluginFilename(plugin, sBuffer, sizeof(sBuffer));
2528
2529 MyLogMessage(0, LOG_ERROR, "Natives_SQLTXNCallback_Error: %s - Plugin: %s Querys: %i - FailedIndex: %i", error, sBuffer, numQueries, failIndex);
2530}
2531
2532
2533public int Native_SQLQuery(Handle plugin, int numParams)
2534{
2535 if (g_hDatabase == null)
2536 return -1;
2537
2538 char sQuery[512];
2539 GetNativeString(1, sQuery, sizeof(sQuery));
2540 DataPack pack = new DataPack();
2541 pack.WriteCell(plugin);
2542 pack.WriteFunction(GetNativeFunction(2));
2543 pack.WriteCell(GetNativeCell(3));
2544
2545 g_hDatabase.Query(Natives_SQLCallback, sQuery, pack);
2546 return 1;
2547}
2548
2549public void Natives_SQLCallback(Database db, DBResultSet results, const char[] error, DataPack pack)
2550{
2551 pack.Reset();
2552 Handle plugin = pack.ReadCell();
2553 Function callback = pack.ReadFunction();
2554 any data = pack.ReadCell();
2555 delete pack;
2556
2557 Call_StartFunction(plugin, callback);
2558 Call_PushCell(db);
2559 Call_PushCell(results);
2560 Call_PushString(error);
2561 Call_PushCell(data);
2562 Call_Finish();
2563}
2564
2565public int Native_RegisterItemHandler(Handle plugin, int numParams)
2566{
2567 if (g_iItemHandlers == STORE_MAX_ITEM_HANDLERS)
2568 return -1;
2569
2570 char sIdentifier[64];
2571 GetNativeString(1, sIdentifier, sizeof(sIdentifier));
2572 int iHandle = GetMenuHandler(sIdentifier);
2573 int iIndex = g_iItemHandlers;
2574
2575 if (iHandle != -1)
2576 {
2577 iIndex = iHandle;
2578 }
2579 else
2580 {
2581 g_iItemHandlers++;
2582 }
2583
2584 g_hItemPlugin[iIndex] = plugin;
2585 g_fnItemMenu[iIndex] = GetNativeCell(2);
2586 g_fnItemHandler[iIndex] = GetNativeCell(3);
2587 strcopy(g_sItemID[iIndex], 64, sIdentifier);
2588
2589 return iIndex;
2590}
2591
2592public int Native_SetDataIndex(Handle plugin, int numParams)
2593{
2594 g_aItems[GetNativeCell(1)][iDataIndex] = GetNativeCell(2);
2595}
2596
2597public int Native_GetDataIndex(Handle plugin, int numParams)
2598{
2599 return g_aItems[GetNativeCell(1)][iDataIndex];
2600}
2601
2602public int Native_GetEquippedItem(Handle plugin, int numParams)
2603{
2604 char sType[16];
2605 GetNativeString(2, sType, sizeof(sType));
2606
2607 int iHandle = GetTypeHandler(sType);
2608 if (iHandle == -1)
2609 return -1;
2610
2611 return g_iEquipment[GetNativeCell(1)][iHandle * STORE_MAX_SLOTS + GetNativeCell(3)];
2612}
2613
2614public int Native_IsClientLoaded(Handle plugin, int numParams)
2615{
2616 return g_bLoaded[GetNativeCell(1)];
2617}
2618
2619public int Native_DisplayPreviousMenu(Handle plugin, int numParams)
2620{
2621 int client = GetNativeCell(1);
2622 switch (g_iMenuNum[client])
2623 {
2624 case MENU_STORE: DisplayStoreMenu(client, g_iMenuBack[client], g_iLastSelection[client]);
2625 case MENU_RESET: AdminMenu_ResetPlayer(g_hTopMenu, TopMenuAction_SelectOption, g_hTopMenuObject, client, "", 0);
2626 case MENU_PLAN: DisplayPlanMenu(client, g_iSelectedItem[client]);
2627 case MENU_ADMIN: RedisplayAdminMenu(g_hTopMenu, client);
2628 case MENU_ITEM, MENU_PREVIEW: g_aItems[g_iSelectedItem[client]][bPreview] ? DisplayPreviewMenu(client, g_iSelectedItem[client]) : DisplayItemMenu(client, g_iSelectedItem[client]);
2629 case MENU_PARENT: DisplayItemMenu(client, g_aItems[g_iSelectedItem[client]][iParent] == -1 ? 0 : g_aItems[g_iSelectedItem[client]][iParent]);
2630 }
2631}
2632
2633public int Native_SetClientMenu(Handle plugin, int numParams)
2634{
2635 g_iMenuNum[GetNativeCell(1)] = GetNativeCell(2);
2636}
2637
2638public int Native_DisplayItemMenu(Handle plugin, int numParams)
2639{
2640 DisplayStoreMenu(GetNativeCell(1), GetNativeCell(2));
2641}
2642
2643public int Native_GetClientCredits(Handle plugin, int numParams)
2644{
2645 return g_iCredits[GetNativeCell(1)];
2646}
2647
2648public int Native_SetClientCredits(Handle plugin, int numParams)
2649{
2650 int client = GetNativeCell(1);
2651 int iCredit = GetNativeCell(2);
2652 char reason[64];
2653 char sPlugin[32];
2654 GetNativeString(3, reason, sizeof(reason));
2655 GetPluginFilename(plugin, sPlugin, sizeof(sPlugin));
2656 MyLogMessage(client, LOG_CREDITS, "%s set the credits to %i Reason: '%s'", sPlugin, iCredit, reason);
2657 g_iCredits[client] = iCredit;
2658
2659 SQL_SaveClientData(client);
2660 return 1;
2661}
2662
2663public int Native_IsClientVIP(Handle plugin, int numParams)
2664{
2665 return IsClientVIP(GetNativeCell(1));
2666}
2667
2668public int Native_IsClientAdmin(Handle plugin, int numParams)
2669{
2670 return IsClientAdmin(GetNativeCell(1));
2671}
2672
2673public int Native_HasClientAccess(Handle plugin, int numParams)
2674{
2675 return HasClientAccess(GetNativeCell(1));
2676}
2677
2678public int Native_IsItemInBoughtPackage(Handle plugin, int numParams)
2679{
2680 int client = GetNativeCell(1);
2681 int itemid = GetNativeCell(2);
2682 int uid = GetNativeCell(3);
2683
2684 int parent;
2685 if (itemid > -1) //edited
2686 {
2687 parent = g_aItems[itemid][iParent];
2688 }
2689 else return false;
2690
2691 while(parent != -1)
2692 {
2693 for (int i = 0; i < g_iItems[client]; i++)
2694 {
2695 if (((uid == -1 && g_iPlayerItems[client][i][UNIQUE_ID] == parent) || (uid != -1 && g_iPlayerItems[client][i][UNIQUE_ID] == uid)) && g_iPlayerItems[client][i][DELETED] == 0)
2696 return true;
2697 }
2698
2699 parent = g_aItems[parent][iParent];
2700 }
2701
2702 return false;
2703}
2704
2705public int Native_DisplayConfirmMenu(Handle plugin, int numParams)
2706{
2707 int client = GetNativeCell(1);
2708 char sBuffer[255];
2709 GetNativeString(2, sBuffer, sizeof(sBuffer));
2710
2711 //Zephyrus magic with pinch of kxnlr
2712 DataPack pack = new DataPack();
2713 pack.WriteCell(plugin);
2714 pack.WriteCell(GetNativeCell(3));
2715 pack.Reset(); //oder hier??
2716
2717 char sCallback[32];
2718 char sData[11];
2719 IntToString(view_as<int>(pack), sCallback, sizeof(sCallback));
2720 IntToString(GetNativeCell(4), sData, sizeof(sData));
2721
2722 //delete pack;
2723
2724 Menu menu = new Menu(MenuHandler_Confirm);
2725 menu.SetTitle(sBuffer);
2726
2727 Format(sBuffer, sizeof(sBuffer), "%t", "Confirm_Yes");
2728 menu.AddItem(sCallback, sBuffer, ITEMDRAW_DEFAULT);
2729
2730 Format(sBuffer, sizeof(sBuffer), "%t", "Confirm_No");
2731 menu.AddItem(sData, sBuffer, ITEMDRAW_DEFAULT);
2732 //Zephyrus magic
2733
2734 menu.ExitButton = false;
2735 menu.Display(client, MENU_TIME_FOREVER);
2736}
2737
2738public int Native_ShouldConfirm(Handle plugin, int numParams)
2739{
2740 return gc_bConfirm.BoolValue;
2741}
2742
2743public int Native_IsInRecurringMenu(Handle plugin, int numParams)
2744{
2745 return g_bIsInRecurringMenu[GetNativeCell(1)];
2746}
2747
2748public int Native_SetClientRecurringMenu(Handle plugin, int numParams)
2749{
2750 g_bIsInRecurringMenu[GetNativeCell(1)] = view_as<bool>(GetNativeCell(2));
2751}
2752
2753public int Native_GetItem(Handle plugin, int numParams)
2754{
2755 int itemID = GetNativeCell(1);
2756 if (itemID > g_iItemCount)
2757 return false;
2758
2759 any aBuffer[sizeof(g_aItems[])];
2760
2761 for (int i = 0; i < sizeof(g_aItems[]); i++)
2762 {
2763 aBuffer[i] = g_aItems[itemID][i];
2764 }
2765
2766 SetNativeArray(2, aBuffer, sizeof(g_aItems[]));
2767
2768 return true;
2769}
2770
2771public int Native_GetHandler(Handle plugin, int numParams)
2772{
2773 int iIndex = GetNativeCell(1);
2774 if (iIndex > g_iTypeHandlers)
2775 return false;
2776
2777 any aBuffer[sizeof(g_aTypeHandlers[])];
2778
2779 for (int i = 0; i < sizeof(g_aTypeHandlers[]); i++)
2780 {
2781 aBuffer[i] = g_aTypeHandlers[iIndex][i];
2782 }
2783
2784 SetNativeArray(2, aBuffer, sizeof(g_aTypeHandlers[]));
2785
2786 return true;
2787}
2788
2789public int Native_GetItemIdbyUniqueId(Handle plugin, int numParams)
2790{
2791 char sUId[32];
2792 GetNativeString(1, sUId, sizeof(sUId));
2793
2794 for (int i = 0; i < g_iItemCount; i++)
2795 {
2796 if (StrEqual(sUId, g_aItems[i][szUniqueId]))
2797 return i;
2798 }
2799
2800 return -1;
2801}
2802
2803public int Native_GetClientItem(Handle plugin, int numParams)
2804{
2805 int client = GetNativeCell(1);
2806
2807 int uid = GetClientItemId(client, GetNativeCell(2));
2808 if (uid < 0)
2809 return false;
2810
2811 any aBuffer[sizeof(g_iPlayerItems[][])]; //[] nur einmal
2812
2813 for (int i = 0; i < sizeof(g_iPlayerItems[][]); i++)
2814 {
2815 aBuffer[i] = g_iPlayerItems[client][uid][i];
2816 }
2817
2818 SetNativeArray(3, aBuffer, sizeof(g_iPlayerItems[][]));
2819
2820 return true;
2821}
2822
2823public int Native_GiveItem(Handle plugin, int numParams)
2824{
2825 int client = GetNativeCell(1);
2826 int itemid = GetNativeCell(2);
2827 int purchase = GetNativeCell(3);
2828 int expiration = GetNativeCell(4);
2829 int price = GetNativeCell(5);
2830
2831 int iDatePurchase = (purchase == 0 ? GetTime() : purchase);
2832 int iDateExpiration = expiration;
2833
2834 int iIndex = g_iItems[client]++;
2835 g_iPlayerItems[client][iIndex][UNIQUE_ID] = itemid;
2836 g_iPlayerItems[client][iIndex][DATE_PURCHASE] = iDatePurchase;
2837 g_iPlayerItems[client][iIndex][DATE_EXPIRATION] = iDateExpiration;
2838 g_iPlayerItems[client][iIndex][PRICE_PURCHASE] = price;
2839 g_iPlayerItems[client][iIndex][SYNCED] = 0;
2840 g_iPlayerItems[client][iIndex][DELETED] = 0;
2841
2842 SQL_SaveClientInventory(client);
2843}
2844
2845public int Native_RemoveItem(Handle plugin, int numParams)
2846{
2847 int client = GetNativeCell(1);
2848 int itemid = GetNativeCell(2);
2849 if (itemid > 0 && g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
2850 {
2851 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove]);
2852 Call_PushCell(client);
2853 Call_PushCell(itemid);
2854 Call_Finish();
2855 }
2856
2857 UnequipItem(client, itemid, false);
2858
2859 int iIndex = GetClientItemId(client, itemid);
2860 if (iIndex != -1)
2861 {
2862 g_iPlayerItems[client][iIndex][DELETED] = 1;
2863 }
2864
2865 SQL_SaveClientInventory(client);
2866}
2867
2868
2869public int Native_UnequipItem(Handle plugin, int numParams)
2870{
2871 int client = GetNativeCell(1);
2872 int itemid = GetNativeCell(2);
2873 if (itemid > 0 && g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
2874 {
2875 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove]);
2876 Call_PushCell(client);
2877 Call_PushCell(itemid);
2878 Call_Finish();
2879 }
2880
2881 UnequipItem(client, itemid, false);
2882
2883 SQL_SaveClientEquipment(client);
2884}
2885
2886public int Native_EquipItem(Handle plugin, int numParams)
2887{
2888 int client = GetNativeCell(1);
2889 UseItem(client, GetNativeCell(2));
2890
2891 SQL_SaveClientEquipment(client);
2892}
2893
2894public int Native_GetClientTarget(Handle plugin, int numParams)
2895{
2896 return g_iMenuClient[GetNativeCell(1)];
2897}
2898
2899public int Native_TransferClientItem(Handle plugin, int numParams)
2900{
2901 int client = GetNativeCell(1);
2902 int receiver = GetNativeCell(2);
2903 int itemid = GetNativeCell(3);
2904
2905 int item = GetClientItemId(client, itemid);
2906 if (item == -1)
2907 return false;
2908
2909 int iIndex = g_iPlayerItems[client][item][UNIQUE_ID];
2910 int target = g_iMenuClient[client];
2911 g_iPlayerItems[client][item][DELETED] = 1;
2912 UnequipItem(client, iIndex);
2913
2914 g_iPlayerItems[receiver][g_iItems[receiver]][UNIQUE_ID] = iIndex;
2915 g_iPlayerItems[receiver][g_iItems[receiver]][SYNCED] = 0;
2916 g_iPlayerItems[receiver][g_iItems[receiver]][DELETED] = 0;
2917 g_iPlayerItems[receiver][g_iItems[receiver]][DATE_PURCHASE] = g_iPlayerItems[target][item][DATE_PURCHASE];
2918 g_iPlayerItems[receiver][g_iItems[receiver]][DATE_EXPIRATION] = g_iPlayerItems[target][item][DATE_EXPIRATION];
2919 g_iPlayerItems[receiver][g_iItems[receiver]][PRICE_PURCHASE] = g_iPlayerItems[target][item][PRICE_PURCHASE];
2920
2921 g_iItems[receiver]++;
2922
2923 return true;
2924}
2925
2926public int Native_SellClientItem(Handle plugin, int numParams)
2927{
2928 int client = GetNativeCell(1);
2929 int itemid = GetNativeCell(2);
2930 float ratio = GetNativeCell(3);
2931
2932 int item = GetClientItemId(client, itemid);
2933 if (item == -1)
2934 return false;
2935
2936 //User own item in a plan, so calculate the rest price for the remaining time
2937 int iCredit = 0;
2938 if (g_iPlayerItems[client][item][DATE_EXPIRATION] != 0)
2939 {
2940 int iLength = g_iPlayerItems[client][item][DATE_EXPIRATION] - g_iPlayerItems[client][item][DATE_PURCHASE];
2941 int iLeft = g_iPlayerItems[client][item][DATE_EXPIRATION] - GetTime();
2942 if (iLeft < 0)
2943 {
2944 iLeft = 0;
2945 }
2946
2947 iCredit = RoundToCeil(iCredit * view_as<float>(iLeft) / view_as<float>(iLength));
2948 }
2949 else
2950 {
2951 iCredit = RoundToCeil(g_iPlayerItems[client][item][PRICE_PURCHASE] * ratio);
2952 }
2953
2954 g_iPlayerItems[client][item][DELETED] = 1;
2955 UnequipItem(client, itemid);
2956 g_iCredits[client] += iCredit;
2957
2958 MyStore_LogMessage(client, LOG_EVENT, "Sold a %s %s for %i credits", g_aItems[itemid][szName], g_aTypeHandlers[g_aItems[itemid][iHandler]][szType], iCredit);
2959 CPrintToChat(client, "%s%t", g_sChatPrefix, "Chat Sold Item", g_aItems[itemid][szName], g_aTypeHandlers[g_aItems[itemid][iHandler]][szType]);
2960
2961 return true;
2962}
2963
2964public int Native_HasClientItem(Handle plugin, int numParams)
2965{
2966 int client = GetNativeCell(1);
2967 int itemid = GetNativeCell(2);
2968
2969 // Can he even have it?
2970 if (!CheckFlagBits(client, g_aItems[itemid][iFlagBits]) || !CheckSteamAuth(client, g_aItems[itemid][szSteam]))
2971 return false;
2972
2973 // Is the item free (available for everyone)?
2974 if (Forward_OnGetEndPrice(client, itemid, g_aItems[itemid][iPrice]) <= 0 && g_aItems[itemid][iPlans] == 0)
2975 return true;
2976
2977 // Is the client a VIP therefore has access to all the items already?
2978 if (IsClientVIP(client) && !g_aItems[itemid][bIgnoreVIP])
2979 return true;
2980
2981 // Check if the client actually has the item
2982 for (int i = 0; i < g_iItems[client]; i++)
2983 {
2984 if (g_iPlayerItems[client][i][UNIQUE_ID] == itemid && g_iPlayerItems[client][i][DELETED] == 0)
2985 {
2986 if (g_iPlayerItems[client][i][DATE_EXPIRATION] == 0 || (g_iPlayerItems[client][i][DATE_EXPIRATION] && GetTime() < g_iPlayerItems[client][i][DATE_EXPIRATION]))
2987 return true;
2988
2989 return false;
2990 }
2991 }
2992
2993 // Check if the item is part of a group the client already has
2994 if (MyStore_IsItemInBoughtPackage(client, itemid))
2995 return true;
2996
2997 return false;
2998}
2999
3000public int Native_IterateEquippedItems(Handle plugin, int numParams)
3001{
3002 int client = GetNativeCell(1);
3003 int start = GetNativeCellRef(2);
3004 bool attributes = GetNativeCell(3);
3005
3006 for (int i = start + 1; i < STORE_MAX_TYPES * STORE_MAX_SLOTS; i++)
3007 {
3008 if (g_iEquipment[client][i] >= 0 && (attributes == false || (attributes && g_aItems[g_iEquipment[client][i]][hAttributes] != null)))
3009 {
3010 SetNativeCellRef(2, i);
3011 return g_iEquipment[client][i];
3012 }
3013 }
3014
3015 return -1;
3016}
3017
3018public int Native_LogMessage(Handle plugin, int numParams)
3019{
3020 char sBuffer[256];
3021 char sPlugin[32];
3022 int client = GetNativeCell(1);
3023 int level = GetNativeCell(2);
3024 GetNativeString(3, sBuffer, sizeof(sBuffer));
3025 FormatNativeString(0, 3, 4, sizeof(sBuffer), _, sBuffer);
3026
3027 GetPluginFilename(plugin, sPlugin, sizeof(sPlugin));
3028 Format(sBuffer, sizeof(sBuffer), "Plugin: %s - %s", sPlugin, sBuffer);
3029
3030 MyLogMessage(client, level, sBuffer);
3031}
3032/******************************************************************************
3033 Functions
3034******************************************************************************/
3035
3036void ReadCoreCFG()
3037{
3038 char sFile[PLATFORM_MAX_PATH];
3039 BuildPath(Path_SM, sFile, sizeof(sFile), "configs/core.cfg");
3040
3041 Handle hParser = SMC_CreateParser();
3042 char error[128];
3043 int line = 0;
3044 int col = 0;
3045
3046 SMC_SetReaders(hParser, INVALID_FUNCTION, Callback_CoreConfig, INVALID_FUNCTION);
3047 SMC_SetParseEnd(hParser, INVALID_FUNCTION);
3048
3049 SMCError result = SMC_ParseFile(hParser, sFile, line, col);
3050 delete hParser;
3051
3052 if (result != SMCError_Okay)
3053 {
3054 SMC_GetErrorString(result, error, sizeof(error));
3055 MyLogMessage(0, LOG_ERROR, "ReadCoreCFG: Error: %s on line %i, col %i of %s", error, line, col, sFile);
3056 }
3057}
3058
3059public SMCResult Callback_CoreConfig(Handle parser, char[] key, char[] value, bool key_quotes, bool value_quotes)
3060{
3061 if (StrEqual(key, "PublicChatTrigger", false))
3062 {
3063 g_iPublicChatTrigger = value[0];
3064 }
3065 else if (StrEqual(key, "SilentChatTrigger", false))
3066 {
3067 g_iSilentChatTrigger = value[0];
3068 }
3069
3070 return SMCParse_Continue;
3071}
3072
3073void ReloadConfig()
3074{
3075 g_iItemCount = 0;
3076
3077 for (int i = 0; i < g_iTypeHandlers; i++)
3078 {
3079 if (g_aTypeHandlers[i][fnReset] != INVALID_FUNCTION)
3080 {
3081 Call_StartFunction(g_aTypeHandlers[i][hPlugin], g_aTypeHandlers[i][fnReset]);
3082 Call_Finish();
3083 }
3084 }
3085
3086 char sFile[PLATFORM_MAX_PATH];
3087 BuildPath(Path_SM, sFile, sizeof(sFile), "configs/MyStore/items.txt");
3088 KeyValues kv = new KeyValues("Store");
3089 kv.ImportFromFile(sFile);
3090 if (!kv.GotoFirstSubKey())
3091 {
3092 SetFailState("Failed to read configs/MyStore/items.txt");
3093 }
3094
3095 GoThroughConfig(kv);
3096
3097 kv.GoBack();
3098
3099 if (gc_bGenerateUId.BoolValue)
3100 {
3101 KeyValuesToFile(kv, sFile); //save the new uids to file
3102 }
3103
3104 delete kv;
3105}
3106
3107void GoThroughConfig(KeyValues &kv, int parent = -1)
3108{
3109 char sFlags[64];
3110 char sType[64];
3111
3112 do
3113 {
3114 // We reached the max amount of items so break and don't add any more items
3115 if (g_iItemCount == STORE_MAX_ITEMS)
3116 {
3117 MyLogMessage(0, LOG_ERROR, "Reached max amount of store items/modules. Maximum is %i.", STORE_MAX_ITEMS);
3118 break;
3119 }
3120
3121 // This is a item category (subfolder) or package
3122 if (kv.GetNum("enabled", 1) && kv.GetNum("type", -1) == -1 && kv.GotoFirstSubKey())
3123 {
3124 kv.GoBack();
3125 kv.GetSectionName(g_aItems[g_iItemCount][szName], 64);
3126 kv.GetSectionName(g_aItems[g_iItemCount][szUniqueId], 64);
3127 ReplaceString(g_aItems[g_iItemCount][szName], 64, "\\n", "\n");
3128 kv.GetString("shortcut", g_aItems[g_iItemCount][szShortcut], 64, "\0");
3129 kv.GetString("description", g_aItems[g_iItemCount][szDescription], 64, "\0");
3130 kv.GetString("steam", g_aItems[g_iItemCount][szSteam], 256, "\0");
3131 kv.GetString("flag", sFlags, sizeof(sFlags));
3132 g_aItems[g_iItemCount][iFlagBits] = ReadFlagString(sFlags);
3133 g_aItems[g_iItemCount][iPrice] = kv.GetNum("price", -1);
3134 g_aItems[g_iItemCount][bBuyable] = kv.GetNum("buyable", 1) ? true : false;
3135 g_aItems[g_iItemCount][bIgnoreVIP] = kv.GetNum("ignore_vip", 0) ? true : false;
3136 g_aItems[g_iItemCount][iHandler] = g_iPackageHandler;
3137 g_aItems[g_iItemCount][iId] = g_iItemCount;
3138
3139 kv.GotoFirstSubKey();
3140
3141 g_aItems[g_iItemCount][iParent] = parent;
3142
3143 GoThroughConfig(kv, g_iItemCount++);
3144 kv.GoBack();
3145 }
3146 // This is a real item
3147 else
3148 {
3149 if (!kv.GetNum("enabled", 1))
3150 continue;
3151
3152 kv.GetSectionName(g_aItems[g_iItemCount][szName], ITEM_NAME_LENGTH);
3153 kv.GetString("type", sType, sizeof(sType));
3154
3155 // Is there the suitable type for this item?
3156 int iHandle = GetTypeHandler(sType);
3157 if (iHandle == -1)
3158 {
3159 MyLogMessage(0, LOG_ERROR, "Can't find store module type '%s' for item '%s'.", sType, g_aItems[g_iItemCount][szName]);
3160 continue;
3161 }
3162
3163 g_aItems[g_iItemCount][iParent] = parent;
3164 g_aItems[g_iItemCount][iPrice] = kv.GetNum("price");
3165 kv.GetString("description", g_aItems[g_iItemCount][szDescription], 64, "\0");
3166 g_aItems[g_iItemCount][bBuyable] = kv.GetNum("buyable", 1) ? true : false;
3167 g_aItems[g_iItemCount][bIgnoreVIP] = kv.GetNum("ignore_vip", 0) ? true : false;
3168 kv.GetString("shortcut", g_aItems[g_iItemCount][szShortcut], 64, "\0");
3169 g_aItems[g_iItemCount][bPreview] = kv.GetNum("preview", 0) ? true : false;
3170 g_aItems[g_iItemCount][iId] = g_iItemCount;
3171
3172 kv.GetString("steam", g_aItems[g_iItemCount][szSteam], 256, "\0");
3173 kv.GetString("flag", sFlags, sizeof(sFlags));
3174 g_aItems[g_iItemCount][iFlagBits] = ReadFlagString(sFlags);
3175
3176 g_aItems[g_iItemCount][iHandler] = iHandle;
3177
3178 kv.GetString("unique_id", g_aItems[g_iItemCount][szUniqueId], 64, "\0");
3179
3180 if (!g_aItems[g_iItemCount][szUniqueId][0] && gc_bGenerateUId.BoolValue)
3181 {
3182 Format(g_aItems[g_iItemCount][szUniqueId], 64, "uid_%s_%s_%i", sType, g_aItems[g_iItemCount][szName], parent);
3183 ReplaceString(g_aItems[g_iItemCount][szUniqueId], 64, " ", "_");
3184 StringToLower(g_aItems[g_iItemCount][szUniqueId]);
3185 kv.SetString("unique_id", g_aItems[g_iItemCount][szUniqueId]);
3186 }
3187
3188 // Has the item a plan?
3189 if (kv.JumpToKey("Plans"))
3190 {
3191 kv.GotoFirstSubKey();
3192 int index = 0;
3193 do
3194 {
3195 kv.GetSectionName(g_sPlanName[g_iItemCount][index], ITEM_NAME_LENGTH);
3196 g_iPlanPrice[g_iItemCount][index] = kv.GetNum("price");
3197 g_iPlanTime[g_iItemCount][index] = kv.GetNum("time");
3198 index++;
3199 }
3200 while kv.GotoNextKey();
3201
3202 g_aItems[g_iItemCount][iPlans] = index;
3203
3204 kv.GoBack();
3205 kv.GoBack();
3206 }
3207
3208 // Has the item attributes?
3209 delete g_aItems[g_iItemCount][hAttributes];
3210 if (kv.JumpToKey("Attributes"))
3211 {
3212 g_aItems[g_iItemCount][hAttributes] = new StringMap();
3213
3214 kv.GotoFirstSubKey(false);
3215
3216 char sAttribute[64];
3217 char sValue[64];
3218 do
3219 {
3220 kv.GetSectionName(sAttribute, sizeof(sAttribute));
3221 kv.GetString(NULL_STRING, sValue, sizeof(sValue));
3222 g_aItems[g_iItemCount][hAttributes].SetString(sAttribute, sValue);
3223 }
3224 while kv.GotoNextKey(false);
3225
3226 kv.GoBack();
3227 kv.GoBack();
3228 }
3229
3230 // Call item plugins config function
3231 bool bSuccess = true;
3232 if (g_aTypeHandlers[iHandle][fnConfig] != INVALID_FUNCTION)
3233 {
3234 Call_StartFunction(g_aTypeHandlers[iHandle][hPlugin], g_aTypeHandlers[iHandle][fnConfig]);
3235 Call_PushCellRef(kv);
3236 Call_PushCell(g_iItemCount);
3237 Call_Finish(bSuccess);
3238 }
3239
3240 // When plugin return true add the item finally, otherwise overwrite item with next item
3241 if (bSuccess)
3242 {
3243 g_iItemCount++;
3244 }
3245 }
3246 }
3247 while kv.GotoNextKey();
3248
3249 /*
3250 kv.GoBack();
3251 //kv.JumpToKey("Store");
3252 char sFile[PLATFORM_MAX_PATH];
3253 BuildPath(Path_SM, sFile, sizeof(sFile), "configs/MyStore/items1.txt");
3254 KeyValuesToFile(kv, sFile);*/
3255}
3256
3257
3258void BuyItem(int client, int itemid, int plan = -1)
3259{
3260 if (MyStore_HasClientItem(client, itemid))
3261 return;
3262
3263 if (!gc_bEnable.BoolValue)
3264 {
3265 CPrintToChat(client, "%s%t", g_sChatPrefix, "Store Disabled");
3266 return;
3267 }
3268
3269 int price = 0;
3270 int costs = 0;
3271 if (plan == -1)
3272 {
3273 price = g_aItems[itemid][iPrice];
3274 costs = Forward_OnGetEndPrice(client, itemid, g_aItems[itemid][iPrice]);
3275 }
3276 else
3277 {
3278 price = g_iPlanPrice[itemid][plan];
3279 costs = Forward_OnGetEndPrice(client, itemid, g_iPlanPrice[itemid][plan]);
3280 }
3281
3282 Action aReturn = Plugin_Continue;
3283 Call_StartForward(gf_hOnBuyItem);
3284 Call_PushCell(client);
3285 Call_PushCell(itemid);
3286 Call_PushCell(price);
3287 Call_PushCellRef(costs);
3288 Call_Finish(aReturn);
3289
3290 if (aReturn == Plugin_Handled)
3291 return;
3292
3293 if (g_iCredits[client] < costs)
3294 return;
3295
3296 int iIndex = g_iItems[client]++;
3297 g_iPlayerItems[client][iIndex][UNIQUE_ID] = itemid;
3298 g_iPlayerItems[client][iIndex][DATE_PURCHASE] = GetTime();
3299 g_iPlayerItems[client][iIndex][DATE_EXPIRATION] = (plan == -1 ? 0 : (g_iPlanTime[itemid][plan] ? GetTime() + g_iPlanTime[itemid][plan] : 0));
3300 g_iPlayerItems[client][iIndex][PRICE_PURCHASE] = costs;
3301 g_iPlayerItems[client][iIndex][SYNCED] = 0;
3302 g_iPlayerItems[client][iIndex][DELETED] = 0;
3303
3304 g_iCredits[client] -= costs;
3305
3306 MyLogMessage(client, LOG_EVENT, "Bought a '%s' - '%s' for %i credits", g_aTypeHandlers[g_aItems[itemid][iHandler]][szType], g_aItems[itemid][szName], costs);
3307
3308 CPrintToChat(client, "%s%t", g_sChatPrefix, "Chat Bought Item", g_aItems[itemid][szName], g_aTypeHandlers[g_aItems[itemid][iHandler]][szType]);
3309
3310 SQL_SaveClientInventory(client);
3311}
3312
3313bool UseItem(int client, int itemid, bool synced = false, int slot = 0)
3314{
3315 if (!gc_bEnable.BoolValue)
3316 return false;
3317
3318 int iSlot = slot;
3319 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][fnUse] != INVALID_FUNCTION)
3320 {
3321 int iReturn = ITEM_EQUIP_SUCCESS;
3322 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnUse]);
3323 Call_PushCell(client);
3324 Call_PushCell(itemid);
3325 Call_Finish(iReturn);
3326
3327 if (iReturn != ITEM_EQUIP_SUCCESS)
3328 {
3329 iSlot = iReturn;
3330 }
3331
3332 Call_StartForward(gf_hOnItemEquipt);
3333 Call_PushCell(client);
3334 Call_PushCell(itemid);
3335 Call_Finish();
3336 }
3337
3338 if (g_aTypeHandlers[g_aItems[itemid][iHandler]][bEquipable])
3339 {
3340 g_iEquipment[client][g_aItems[itemid][iHandler] * STORE_MAX_SLOTS + iSlot] = itemid;
3341 if (synced)
3342 {
3343 g_iEquipmentSynced[client][g_aItems[itemid][iHandler] * STORE_MAX_SLOTS + iSlot] = itemid;
3344 }
3345 }
3346 else if (iSlot == ITEM_EQUIP_REMOVE)
3347 {
3348 MyStore_RemoveItem(client, itemid);
3349 return true;
3350 }
3351
3352 return true;
3353}
3354
3355void UnequipItem(int client, int itemid, bool noDouble = true)
3356{
3357 if (itemid == -1)
3358 return;
3359
3360 int iSlot = 0;
3361 if (noDouble && itemid > 0 && g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
3362 {
3363 Call_StartFunction(g_aTypeHandlers[g_aItems[itemid][iHandler]][hPlugin], g_aTypeHandlers[g_aItems[itemid][iHandler]][fnRemove]);
3364 Call_PushCell(client);
3365 Call_PushCell(itemid);
3366 Call_Finish(iSlot);
3367 }
3368
3369 int iIndex;
3370 if (g_aItems[itemid][iHandler] != g_iPackageHandler)
3371 {
3372 iIndex = g_aItems[itemid][iHandler] * STORE_MAX_SLOTS + iSlot;
3373 if (g_iEquipmentSynced[client][iIndex] == -2)
3374 {
3375 g_iEquipment[client][iIndex] = -2;
3376 }
3377 else
3378 {
3379 g_iEquipment[client][iIndex] = -1;
3380 }
3381 }
3382 else
3383 {
3384 for (int i = 0; i < STORE_MAX_TYPES; i++)
3385 {
3386 for (int a = 0; i < STORE_MAX_SLOTS; i++)
3387 {
3388 if (g_iEquipment[client][i + a] < 0)
3389 continue;
3390
3391 iIndex = i * STORE_MAX_SLOTS + a;
3392 if (MyStore_IsItemInBoughtPackage(client, g_iEquipment[client][iIndex], itemid))
3393 {
3394 if (g_iEquipmentSynced[client][iIndex] == -2)
3395 {
3396 g_iEquipment[client][iIndex] = -2;
3397 }
3398 else
3399 {
3400 g_iEquipment[client][iIndex] = -1;
3401 }
3402 }
3403 }
3404 }
3405 }
3406}
3407
3408bool PackageHasClientItem(int client, int packageid, bool invmode = false)
3409{
3410 int iFlags = GetUserFlagBits(client);
3411 if (!gc_bShowVIP.BoolValue && !CheckFlagBits(client, g_aItems[packageid][iFlagBits], iFlags) && !CheckSteamAuth(client, g_aItems[packageid][szSteam]))
3412 return false;
3413
3414 for (int i = 0; i < g_iItemCount; i++)
3415 {
3416 if (g_aItems[i][iParent] == packageid && (gc_bShowVIP.BoolValue || CheckFlagBits(client, g_aItems[i][iFlagBits], iFlags) || CheckSteamAuth(client, g_aItems[i][szSteam])) && (invmode && MyStore_HasClientItem(client, i) || !invmode))
3417 {
3418 if ((g_aItems[i][iHandler] == g_iPackageHandler && PackageHasClientItem(client, i, invmode)) || g_aItems[i][iHandler] != g_iPackageHandler)
3419 return true;
3420 }
3421 }
3422
3423 return false;
3424}
3425
3426void MyLogMessage(int client = 0, int level, char[] message, any ...)
3427{
3428 if (gc_bLogging.IntValue < 1)
3429 return;
3430
3431 if (gc_bLoggingLevel.IntValue <= level)
3432 return;
3433
3434 char sLevel[8];
3435 char sReason[256];
3436 VFormat(sReason, sizeof(sReason), message, 4);
3437
3438 switch(level)
3439 {
3440 case LOG_ADMIN: strcopy(sLevel, sizeof(sLevel), "[Admin]");
3441 case LOG_EVENT: strcopy(sLevel, sizeof(sLevel), "[Event]");
3442 case LOG_CREDITS: strcopy(sLevel, sizeof(sLevel), "[Credits]");
3443 case LOG_ERROR:
3444 {
3445 strcopy(sLevel, sizeof(sLevel), "[ERROR]");
3446 LogError("%s - %L - %s", sLevel, client, sReason);
3447 }
3448 }
3449
3450 switch(gc_bLogging.IntValue)
3451 {
3452 case 1: LogToOpenFileEx(g_hLogFile, "%s - %L - %s", sLevel, client, sReason);
3453 case 2:
3454 {
3455 char sQuery[256];
3456 Format(sQuery, sizeof(sQuery), "INSERT INTO mystore_logs (level, player_id, reason, date) VALUES(\"%s\", %i, \"%s\", %i)", sLevel, g_iPlayerID[client], sReason, GetTime());
3457 g_hDatabase.Query(SQLCallback_Void_Error, sQuery);
3458 }
3459 }
3460}
3461
3462void Forward_OnConfigsExecuted()
3463{
3464 Call_StartForward(gf_hOnConfigExecuted);
3465 Call_PushCell(gc_bEnable);
3466 Call_PushString(g_sName);
3467 Call_PushString(g_sChatPrefix);
3468 Call_PushString(g_sCreditsName);
3469 Call_Finish();
3470}
3471
3472int GetItemId(char[] type, char[] uid, int start = -1)
3473{
3474 for (int i = start + 1; i < g_iItemCount; i++)
3475 {
3476 if (strcmp(g_aTypeHandlers[g_aItems[i][iHandler]][szType], type) == 0 && strcmp(g_aItems[i][szUniqueId], uid) == 0 && g_aItems[i][iPrice] >= 0)
3477 return i;
3478 }
3479
3480 return -1;
3481}
3482
3483int GetTypeHandler(char[] type)
3484{
3485 for (int i = 0; i < g_iTypeHandlers; i++)
3486 {
3487 if (strcmp(g_aTypeHandlers[i][szType], type) == 0)
3488 return i;
3489 }
3490
3491 return -1;
3492}
3493
3494int GetMenuHandler(char[] id)
3495{
3496 for (int i = 0; i < g_iItemHandlers; i++)
3497 {
3498 if (strcmp(g_sItemID[i], id) == 0)
3499 return i;
3500 }
3501
3502 return -1;
3503}
3504
3505bool IsEquipped(int client, int itemid)
3506{
3507 for (int i = 0; i < STORE_MAX_SLOTS; i++)
3508 {
3509 if (g_iEquipment[client][g_aItems[itemid][iHandler] * STORE_MAX_SLOTS + i] == itemid)
3510 return true;
3511 }
3512
3513 return false;
3514}
3515
3516int GetExpiration(int client, int itemid)
3517{
3518 int uid = GetClientItemId(client, itemid);
3519 if (uid < 0)
3520 return 0;
3521
3522 return g_iPlayerItems[client][uid][DATE_EXPIRATION];
3523}
3524
3525int GetLowestPrice(int itemid)
3526{
3527 if (g_aItems[itemid][iPlans] == 0)
3528 return g_aItems[itemid][iPrice];
3529
3530 int iLowest = g_iPlanPrice[itemid][0];
3531 for (int i = 1; i < g_aItems[itemid][iPlans]; i++)
3532 {
3533 if (iLowest > g_iPlanPrice[itemid][i])
3534 {
3535 iLowest = g_iPlanPrice[itemid][i];
3536 }
3537 }
3538
3539 return iLowest;
3540}
3541
3542int Forward_OnGetEndPrice(int client, int itemid, int price, bool &reduced = false)
3543{
3544 Action aReturn;
3545
3546 Call_StartForward(gf_hOnGetEndPrice);
3547 Call_PushCell(client);
3548 Call_PushCell(itemid);
3549 Call_PushCellRef(price);
3550 Call_Finish(aReturn);
3551
3552 if (aReturn == Plugin_Changed)
3553 {
3554 reduced = true;
3555 }
3556
3557 return price;
3558}
3559
3560int GetClientItemId(int client, int itemid)
3561{
3562 for (int i = 0; i < g_iItems[client]; i++)
3563 {
3564 if (g_iPlayerItems[client][i][UNIQUE_ID] == itemid && g_iPlayerItems[client][i][DELETED] == 0)
3565 return i;
3566 }
3567
3568 return -1;
3569}
3570
3571int GetClientBySteamID(char[] steamid)
3572{
3573 char authid[32];
3574
3575 for(int i = 1; i <= MaxClients; i++)
3576 {
3577 if (!IsClientInGame(i))
3578 continue;
3579
3580 if (!IsClientAuthorized(i))
3581 continue;
3582
3583 if (!GetClientAuthId(i, AuthId_Steam2, authid, sizeof(authid)))
3584 continue;
3585
3586 if (strcmp(authid[8], steamid[8]) == 0 || strcmp(authid, steamid) == 0)
3587 return i;
3588 }
3589
3590 return 0;
3591}
3592
3593bool GetLegacyAuthString(int client, char[] out, int maxlen, bool validate=true)
3594{
3595 char sSteamID[32];
3596 bool success = GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID), validate);
3597
3598 if (sSteamID[0] == '[')
3599 {
3600 int iAccountID = StringToInt(sSteamID[5]);
3601 int iMod = iAccountID % 2;
3602 Format(out, maxlen, "STEAM_0:%i:%i", iMod, (iAccountID - iMod) / 2);
3603 }
3604 else
3605 {
3606 strcopy(out, maxlen, sSteamID);
3607 }
3608
3609 return success;
3610}
3611
3612bool IsClientVIP(int client)
3613{
3614 if (g_iVIPFlags == 0)
3615 return false;
3616
3617 return CheckFlagBits(client, g_iVIPFlags);
3618}
3619
3620bool IsClientAdmin(int client)
3621{
3622 if (g_iAdminFlags == 0)
3623 return false;
3624
3625 return CheckFlagBits(client, g_iAdminFlags);
3626}
3627
3628bool HasClientAccess(int client)
3629{
3630 return CheckFlagBits(client, g_iMinFlags);
3631}
3632
3633bool CheckFlagBits(int client, int flagsNeed, int flags = -1)
3634{
3635 if (flags == -1)
3636 {
3637 flags = GetUserFlagBits(client);
3638 }
3639
3640 if (flagsNeed == 0 || flags & flagsNeed || flags & ADMFLAG_ROOT)
3641 return true;
3642
3643 return false;
3644}
3645
3646bool CheckSteamAuth(int client, char[] steam)
3647{
3648 if (!steam[0])
3649 return true;
3650
3651 char sSteam[32];
3652 if (!GetClientAuthId(client, AuthId_Steam2, sSteam, 32))
3653 return false;
3654
3655 if (StrContains(steam, sSteam) == -1)
3656 return false;
3657
3658 return true;
3659}
3660
3661bool DirExistsEx(const char[] szPath)
3662{
3663 if (DirExists(szPath))
3664 return true;
3665
3666 CreateDirectory(szPath, 511);
3667
3668 if (!DirExists(szPath))
3669 {
3670 MyLogMessage(0, LOG_ERROR, "DirExistsEx: Error: Couldn't create folder! (%s)", szPath);
3671 return false;
3672 }
3673
3674 return true;
3675}
3676
3677void StringToLower(char[] sz)
3678{
3679 int len = strlen(sz);
3680
3681 for (int i = 0; i < len; i++)
3682 if (IsCharUpper(sz[i]))
3683 {
3684 sz[i] = CharToLower(sz[i]);
3685 }
3686}