· 8 years ago · Apr 08, 2018, 11:42 AM
1#pragma semicolon 1
2
3//////////////////////////////
4// DEFINITIONS //
5//////////////////////////////
6
7#define PLUGIN_NAME "Store - The Resurrection"
8#define PLUGIN_AUTHOR "Zephyrus"
9#define PLUGIN_DESCRIPTION "A completely new Store system."
10#define PLUGIN_VERSION "1.1"
11#define PLUGIN_URL ""
12
13//////////////////////////////
14// INCLUDES //
15//////////////////////////////
16
17#include <sourcemod>
18#include <sdktools>
19
20#undef REQUIRE_EXTENSIONS
21#undef REQUIRE_PLUGIN
22#include <store>
23#include <zephstocks>
24#include <donate>
25#include <adminmenu>
26#if !defined STANDALONE_BUILD
27#include <sdkhooks>
28#include <cstrike>
29#include <tf2>
30#include <tf2_stocks>
31#include <tf2items>
32#include <gifts>
33#include <chat-processor>
34#include <thirdperson>
35#include <saxtonhale>
36#endif
37
38//////////////////////////////
39// ENUMS //
40//////////////////////////////
41
42enum Client
43{
44 iId,
45 iUserId,
46 String:szAuthId[32],
47 String:szName[64],
48 String:szNameEscaped[128],
49 iCredits,
50 iOriginalCredits,
51 iDateOfJoin,
52 iDateOfLastJoin,
53 iItems,
54 aEquipment[STORE_MAX_HANDLERS*STORE_MAX_SLOTS],
55 aEquipmentSynced[STORE_MAX_HANDLERS*STORE_MAX_SLOTS],
56 Handle:hCreditTimer,
57 bool:bLoaded
58}
59
60enum Menu_Handler
61{
62 String:szIdentifier[64],
63 Handle:hPlugin,
64 Function:fnMenu,
65 Function:fnHandler
66}
67
68//////////////////////////////////
69// GLOBAL VARIABLES //
70//////////////////////////////////
71
72new GAME_CSS = false;
73new GAME_CSGO = false;
74new GAME_DOD = false;
75new GAME_TF2 = false;
76new GAME_L4D = false;
77new GAME_L4D2 = false;
78
79new String:g_szGameDir[64];
80
81new Handle:g_hDatabase = INVALID_HANDLE;
82new Handle:g_hAdminMenu = INVALID_HANDLE;
83new Handle:g_hLogFile = INVALID_HANDLE;
84new Handle:g_hCustomCredits = INVALID_HANDLE;
85
86new g_cvarDatabaseEntry = -1;
87new g_cvarDatabaseRetries = -1;
88new g_cvarDatabaseTimeout = -1;
89new g_cvarItemSource = -1;
90new g_cvarItemsTable = -1;
91new g_cvarStartCredits = -1;
92new g_cvarCreditTimer = -1;
93new g_cvarCreditAmountActive = -1;
94new g_cvarCreditAmountInactive = -1;
95new g_cvarCreditAmountKill = -1;
96new g_cvarRequiredFlag = -1;
97new g_cvarVIPFlag = -1;
98new g_cvarSellEnabled = -1;
99new g_cvarGiftEnabled = -1;
100new g_cvarCreditGiftEnabled = -1;
101new g_cvarSellRatio = -1;
102new g_cvarConfirmation = -1;
103new g_cvarAdminFlag = -1;
104new g_cvarSaveOnDeath = -1;
105new g_cvarCreditMessages = -1;
106new g_cvarShowVIP = -1;
107new g_cvarLogging = -1;
108new g_cvarSilent = -1;
109
110new g_eItems[STORE_MAX_ITEMS][Store_Item];
111new g_eClients[MAXPLAYERS+1][Client];
112new g_eClientItems[MAXPLAYERS+1][STORE_MAX_ITEMS][Client_Item];
113new g_eTypeHandlers[STORE_MAX_HANDLERS][Type_Handler];
114new g_eMenuHandlers[STORE_MAX_HANDLERS][Menu_Handler];
115new g_ePlans[STORE_MAX_ITEMS][STORE_MAX_PLANS][Item_Plan];
116
117new g_iItems = 0;
118new g_iTypeHandlers = 0;
119new g_iMenuHandlers = 0;
120new g_iMenuBack[MAXPLAYERS+1];
121new g_iLastSelection[MAXPLAYERS+1];
122new g_iSelectedItem[MAXPLAYERS+1];
123new g_iSelectedPlan[MAXPLAYERS+1];
124new g_iMenuClient[MAXPLAYERS+1];
125new g_iMenuNum[MAXPLAYERS+1];
126new g_iSpam[MAXPLAYERS+1];
127new g_iPackageHandler = -1;
128new g_iDatabaseRetries = 0;
129
130new bool:g_bInvMode[MAXPLAYERS+1];
131new bool:g_bMySQL = false;
132
133new String:g_szClientData[MAXPLAYERS+1][256];
134
135new TopMenuObject:g_eStoreAdmin;
136
137new PublicChatTrigger = 0;
138new SilentChatTrigger = 0;
139
140//////////////////////////////
141// MODULES //
142//////////////////////////////
143
144#if !defined STANDALONE_BUILD
145#include "store/hats.sp"
146#include "store/tracers.sp"
147#include "store/playerskins.sp"
148#include "store/trails.sp"
149#include "store/grenskins.sp"
150#include "store/grentrails.sp"
151#include "store/weaponcolors.sp"
152#include "store/tfsupport.sp"
153#include "store/paintball.sp"
154#include "store/betting.sp"
155#include "store/watergun.sp"
156#include "store/gifts.sp"
157#include "store/cpsupport.sp"
158#include "store/weapons.sp"
159#include "store/help.sp"
160#include "store/jetpack.sp"
161#include "store/bunnyhop.sp"
162#include "store/lasersight.sp"
163#include "store/health.sp"
164#include "store/speed.sp"
165#include "store/gravity.sp"
166#include "store/invisibility.sp"
167#include "store/commands.sp"
168#include "store/doors.sp"
169#include "store/zrclass.sp"
170#include "store/jihad.sp"
171#include "store/godmode.sp"
172#include "store/sounds.sp"
173#include "store/attributes.sp"
174#include "store/respawn.sp"
175#include "store/pets.sp"
176#include "store/sprays.sp"
177#include "store/admin.sp"
178#include "store/glow.sp"
179#endif
180
181//////////////////////////////////
182// PLUGIN DEFINITION //
183//////////////////////////////////
184
185public Plugin:myinfo =
186{
187 name = PLUGIN_NAME,
188 author = PLUGIN_AUTHOR,
189 description = PLUGIN_DESCRIPTION,
190 version = PLUGIN_VERSION,
191 url = PLUGIN_URL
192};
193
194//////////////////////////////
195// PLUGIN FORWARDS //
196//////////////////////////////
197
198public OnPluginStart()
199{
200 RegPluginLibrary("store_zephyrus");
201
202 // Identify the game
203 GetGameFolderName(STRING(g_szGameDir));
204
205 if(strcmp(g_szGameDir, "cstrike")==0)
206 GAME_CSS = true;
207 else if(strcmp(g_szGameDir, "csgo")==0)
208 GAME_CSGO = true;
209 else if(strcmp(g_szGameDir, "csco")==0)
210 GAME_CSGO = true;
211 else if(strcmp(g_szGameDir, "dod")==0)
212 GAME_DOD = true;
213 else if(strcmp(g_szGameDir, "tf")==0)
214 GAME_TF2 = true;
215 else if(strcmp(g_szGameDir, "l4d")==0)
216 GAME_L4D = true;
217 else if(strcmp(g_szGameDir, "l4d2")==0)
218 GAME_L4D2 = true;
219 else
220 {
221 SetFailState("This game is not be supported. Please contact the author for support.");
222 }
223
224 // Supress warnings about unused variables.....
225 if(GAME_DOD || GAME_L4D || GAME_L4D2 || g_bL4D || g_bL4D2 || g_bND) {}
226
227 // Setting default values
228 for(new i=1;i<=MaxClients;++i)
229 {
230 g_eClients[i][iCredits] = -1;
231 g_eClients[i][iOriginalCredits] = 0;
232 g_eClients[i][iItems] = -1;
233 g_eClients[i][hCreditTimer] = INVALID_HANDLE;
234 }
235
236 // Register ConVars
237 g_cvarDatabaseEntry = RegisterConVar("sm_store_database", "storage-local", "Name of the default store database entry", TYPE_STRING);
238 g_cvarDatabaseRetries = RegisterConVar("sm_store_database_retries", "4", "Number of retries if the connection fails to estabilish with timeout", TYPE_INT);
239 g_cvarDatabaseTimeout = RegisterConVar("sm_store_database_timeout", "10", "Timeout in seconds to wait for database connection before retry", TYPE_FLOAT);
240 g_cvarItemSource = RegisterConVar("sm_store_item_source", "flatfile", "Source of the item list, can be set to flatfile and database, sm_store_items_table must be set if database is chosen (THIS IS HIGHLY EXPERIMENTAL AND MAY NOT WORK YET)", TYPE_STRING);
241 g_cvarItemsTable = RegisterConVar("sm_store_items_table", "store_menu", "Name of the items table", TYPE_STRING);
242 g_cvarStartCredits = RegisterConVar("sm_store_startcredits", "0", "Number of credits a client starts with", TYPE_INT);
243 g_cvarCreditTimer = RegisterConVar("sm_store_credit_interval", "60", "Interval in seconds to give out credits", TYPE_FLOAT, ConVar_CreditTimer);
244 g_cvarCreditAmountActive = RegisterConVar("sm_store_credit_amount_active", "1", "Number of credits to give out for active players", TYPE_INT, ConVar_CreditTimer);
245 g_cvarCreditAmountInactive = RegisterConVar("sm_store_credit_amount_inactive", "1", "Number of credits to give out for inactive players (spectators)", TYPE_INT, ConVar_CreditTimer);
246 g_cvarCreditAmountKill = RegisterConVar("sm_store_credit_amount_kill", "1", "Number of credits to give out for killing a player", TYPE_INT, ConVar_CreditTimer);
247 g_cvarRequiredFlag = RegisterConVar("sm_store_required_flag", "", "Flag to access the !store menu", TYPE_FLAG);
248 g_cvarVIPFlag = RegisterConVar("sm_store_vip_flag", "", "Flag for VIP access (all items unlocked). Leave blank to disable.", TYPE_FLAG);
249 g_cvarAdminFlag = RegisterConVar("sm_store_admin_flag", "z", "Flag for admin access. Leave blank to disable.", TYPE_FLAG);
250 g_cvarSellEnabled = RegisterConVar("sm_store_enable_selling", "1", "Enable/disable selling of already bought items.", TYPE_INT);
251 g_cvarGiftEnabled = RegisterConVar("sm_store_enable_gifting", "1", "Enable/disable gifting of already bought items. [1=everyone, 2=admins only]", TYPE_INT);
252 g_cvarCreditGiftEnabled = RegisterConVar("sm_store_enable_credit_gifting", "1", "Enable/disable gifting of credits.", TYPE_INT);
253 g_cvarSellRatio = RegisterConVar("sm_store_sell_ratio", "0.60", "Ratio of the original price to get for selling an item.", TYPE_FLOAT);
254 g_cvarConfirmation = RegisterConVar("sm_store_confirmation_windows", "1", "Enable/disable confirmation windows.", TYPE_INT);
255 g_cvarSaveOnDeath = RegisterConVar("sm_store_save_on_death", "0", "Enable/disable client data saving on client death.", TYPE_INT);
256 g_cvarCreditMessages = RegisterConVar("sm_store_credit_messages", "1", "Enable/disable messages when a player earns credits.", TYPE_INT);
257 g_cvarChatTag = RegisterConVar("sm_store_chat_tag", "[Store] ", "The chat tag to use for displaying messages.", TYPE_STRING);
258 g_cvarShowVIP = RegisterConVar("sm_store_show_vip_items", "0", "If you enable this VIP items will be shown in grey.", TYPE_INT);
259 g_cvarLogging = RegisterConVar("sm_store_logging", "0", "Set this to 1 for file logging and 2 to SQL logging (only MySQL). Leaving on 0 means disabled.", TYPE_INT);
260 g_cvarSilent = RegisterConVar("sm_store_silent_givecredits", "0", "Controls the give credits message visibility. 0 = public 1 = private 2 = no message", TYPE_INT);
261
262 // Register Commands
263 RegConsoleCmd("sm_store", Command_Store);
264 RegConsoleCmd("sm_shop", Command_Store);
265 RegConsoleCmd("sm_inv", Command_Inventory);
266 RegConsoleCmd("sm_inventory", Command_Inventory);
267 RegConsoleCmd("sm_gift", Command_Gift);
268 RegConsoleCmd("sm_givecredits", Command_GiveCredits);
269 RegConsoleCmd("sm_resetplayer", Command_ResetPlayer);
270 RegConsoleCmd("sm_credits", Command_Credits);
271 RegServerCmd("sm_store_custom_credits", Command_CustomCredits);
272
273 // Hook events
274 HookEvent("player_death", Event_PlayerDeath);
275 HookEvent("player_spawn", Event_PlayerSpawn);
276
277 // Load the translations file
278 LoadTranslations("store.phrases");
279
280 // Initiaze the fake package handler
281 g_iPackageHandler = Store_RegisterHandler("package", "", INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION);
282
283 // Initialize the modules
284#if !defined STANDALONE_BUILD
285 Hats_OnPluginStart();
286 Tracers_OnPluginStart();
287 Trails_OnPluginStart();
288 PlayerSkins_OnPluginStart();
289 GrenadeSkins_OnPluginStart();
290 GrenadeTrails_OnPluginStart();
291 WeaponColors_OnPluginStart();
292 TFSupport_OnPluginStart();
293 Paintball_OnPluginStart();
294 Watergun_OnPluginStart();
295 Betting_OnPluginStart();
296 Gifts_OnPluginStart();
297 CPSupport_OnPluginStart();
298 Weapons_OnPluginStart();
299 Help_OnPluginStart();
300 Jetpack_OnPluginStart();
301 Bunnyhop_OnPluginStart();
302 LaserSight_OnPluginStart();
303 Health_OnPluginStart();
304 Gravity_OnPluginStart();
305 Speed_OnPluginStart();
306 Invisibility_OnPluginStart();
307 Commands_OnPluginStart();
308 Doors_OnPluginStart();
309 ZRClass_OnPluginStart();
310 Jihad_OnPluginStart();
311 Godmode_OnPluginStart();
312 Sounds_OnPluginStart();
313 Attributes_OnPluginStart();
314 Respawn_OnPluginStart();
315 Pets_OnPluginStart();
316 Sprays_OnPluginStart();
317 AdminGroup_OnPluginStart();
318 Glow_OnPluginStart();
319#endif
320
321 new Handle:topmenu;
322 if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
323 OnAdminMenuReady(topmenu);
324
325 // Initialize handles
326 g_hCustomCredits = CreateArray(3);
327
328 // Load the config file
329 Store_ReloadConfig();
330
331 // After every module was loaded we are ready to generate the cfg
332 AutoExecConfig();
333
334 // Read core.cfg for chat triggers
335 ReadCoreCFG();
336
337 // Add a say command listener for shortcuts
338 AddCommandListener(Command_Say, "say");
339
340 LoopIngamePlayers(client)
341 {
342 OnClientConnected(client);
343 OnClientPostAdminCheck(client);
344 OnClientPutInServer(client);
345 }
346
347}
348
349public OnAllPluginsLoaded()
350{
351 CreateTimer(1.0, LoadConfig);
352
353 if(GetFeatureStatus(FeatureType_Native, "Donate_RegisterHandler")==FeatureStatus_Available)
354 Donate_RegisterHandler("Store", Store_OnPaymentReceived);
355}
356
357public Action:LoadConfig(Handle:timer, any:data)
358{
359 // Load the config file
360 Store_ReloadConfig();
361}
362
363public OnPluginEnd()
364{
365 LoopIngamePlayers(i)
366 if(g_eClients[i][bLoaded])
367 OnClientDisconnect(i);
368
369 if(GetFeatureStatus(FeatureType_Native, "Donate_RemoveHandler")==FeatureStatus_Available)
370 Donate_RemoveHandler("Store");
371}
372
373public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
374{
375 CreateNative("Store_RegisterHandler", Native_RegisterHandler);
376 CreateNative("Store_RegisterMenuHandler", Native_RegisterMenuHandler);
377 CreateNative("Store_SetDataIndex", Native_SetDataIndex);
378 CreateNative("Store_GetDataIndex", Native_GetDataIndex);
379 CreateNative("Store_GetEquippedItem", Native_GetEquippedItem);
380 CreateNative("Store_IsClientLoaded", Native_IsClientLoaded);
381 CreateNative("Store_DisplayPreviousMenu", Native_DisplayPreviousMenu);
382 CreateNative("Store_SetClientMenu", Native_SetClientMenu);
383 CreateNative("Store_GetClientCredits", Native_GetClientCredits);
384 CreateNative("Store_SetClientCredits", Native_SetClientCredits);
385 CreateNative("Store_IsClientVIP", Native_IsClientVIP);
386 CreateNative("Store_IsItemInBoughtPackage", Native_IsItemInBoughtPackage);
387 CreateNative("Store_DisplayConfirmMenu", Native_DisplayConfirmMenu);
388 CreateNative("Store_ShouldConfirm", Native_ShouldConfirm);
389 CreateNative("Store_GetItem", Native_GetItem);
390 CreateNative("Store_GetHandler", Native_GetHandler);
391 CreateNative("Store_GiveItem", Native_GiveItem);
392 CreateNative("Store_RemoveItem", Native_RemoveItem);
393 CreateNative("Store_GetClientItem", Native_GetClientItem);
394 CreateNative("Store_GetClientTarget", Native_GetClientTarget);
395 CreateNative("Store_GiveClientItem", Native_GiveClientItem);
396 CreateNative("Store_HasClientItem", Native_HasClientItem);
397 CreateNative("Store_IterateEquippedItems", Native_IterateEquippedItems);
398
399#if !defined STANDALONE_BUILD
400 MarkNativeAsOptional("ZR_IsClientZombie");
401 MarkNativeAsOptional("ZR_IsClientHuman");
402 MarkNativeAsOptional("ZR_GetClassByName");
403 MarkNativeAsOptional("ZR_SelectClientClass");
404 MarkNativeAsOptional("HideTrails_ShouldHide");
405 MarkNativeAsOptional("Hidetracers_ShouldHide");
406 MarkNativeAsOptional("IsPlayerInTP");
407 MarkNativeAsOptional("TogglePlayerTP");
408#endif
409 return APLRes_Success;
410}
411
412#if !defined STANDALONE_BUILD
413public OnLibraryAdded(const String:name[])
414{
415 PlayerSkins_OnLibraryAdded(name);
416 ZRClass_OnLibraryAdded(name);
417}
418#endif
419
420//////////////////////////////
421// ADMIN MENUS //
422//////////////////////////////
423
424public OnAdminMenuReady(Handle:topmenu)
425{
426 if (topmenu == g_hAdminMenu)
427 return;
428 g_hAdminMenu = topmenu;
429
430 g_eStoreAdmin = AddToTopMenu(g_hAdminMenu, "Store Admin", TopMenuObject_Category, CategoryHandler_StoreAdmin, INVALID_TOPMENUOBJECT);
431 AddToTopMenu(g_hAdminMenu, "sm_store_resetdb", TopMenuObject_Item, AdminMenu_ResetDb, g_eStoreAdmin, "sm_store_resetdb", g_eCvars[g_cvarAdminFlag][aCache]);
432 AddToTopMenu(g_hAdminMenu, "sm_store_resetplayer", TopMenuObject_Item, AdminMenu_ResetPlayer, g_eStoreAdmin, "sm_store_resetplayer", g_eCvars[g_cvarAdminFlag][aCache]);
433 AddToTopMenu(g_hAdminMenu, "sm_store_givecredits", TopMenuObject_Item, AdminMenu_GiveCredits, g_eStoreAdmin, "sm_store_givecredits", g_eCvars[g_cvarAdminFlag][aCache]);
434 AddToTopMenu(g_hAdminMenu, "sm_store_viewinventory", TopMenuObject_Item, AdminMenu_ViewInventory, g_eStoreAdmin, "sm_store_viewinventory", g_eCvars[g_cvarAdminFlag][aCache]);
435}
436
437public CategoryHandler_StoreAdmin(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength)
438{
439 if (action == TopMenuAction_DisplayTitle || action == TopMenuAction_DisplayOption)
440 Format(buffer, maxlength, "Store Admin");
441}
442
443//////////////////////////////
444// Reset database //
445//////////////////////////////
446
447public AdminMenu_ResetDb(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
448{
449 if (action == TopMenuAction_DisplayOption)
450 {
451 Format(buffer, maxlength, "Reset database");
452 }
453 else if (action == TopMenuAction_SelectOption)
454 {
455 g_iMenuNum[client] = 0;
456 Store_DisplayConfirmMenu(client, "Do you want to reset database?\nServer will be restarted!", FakeMenuHandler_ResetDatabase, 0);
457 }
458}
459
460public FakeMenuHandler_ResetDatabase(Handle:menu, MenuAction:action, client, param2)
461{
462 SQL_TVoid(g_hDatabase, "DROP TABLE store_players");
463 SQL_TVoid(g_hDatabase, "DROP TABLE store_items");
464 SQL_TVoid(g_hDatabase, "DROP TABLE store_equipment");
465 ServerCommand("_restart");
466}
467
468//////////////////////////////
469// Reset player //
470//////////////////////////////
471
472public AdminMenu_ResetPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
473{
474 if (action == TopMenuAction_DisplayOption)
475 {
476 Format(buffer, maxlength, "Reset player");
477 }
478 else if (action == TopMenuAction_SelectOption)
479 {
480 g_iMenuNum[client] = 4;
481 new Handle:m_hMenu = CreateMenu(MenuHandler_ResetPlayer);
482 SetMenuTitle(m_hMenu, "Choose a player to reset");
483 SetMenuExitBackButton(m_hMenu, true);
484 LoopAuthorizedPlayers(i)
485 {
486 decl String:m_szName[64];
487 decl String:m_szAuthId[32];
488 GetClientName(i, STRING(m_szName));
489 GetLegacyAuthString(i, STRING(m_szAuthId));
490 AddMenuItem(m_hMenu, m_szAuthId, m_szName);
491 }
492 DisplayMenu(m_hMenu, client, 0);
493 }
494}
495
496public MenuHandler_ResetPlayer(Handle:menu, MenuAction:action, client, param2)
497{
498 if (action == MenuAction_End)
499 CloseHandle(menu);
500 else if (action == MenuAction_Select)
501 {
502 if(menu == INVALID_HANDLE)
503 FakeClientCommandEx(client, "sm_resetplayer \"%s\"", g_szClientData[client]);
504 else
505 {
506 decl style;
507 decl String:m_szName[64];
508 GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]), style, STRING(m_szName));
509
510 decl String:m_szTitle[256];
511 Format(STRING(m_szTitle), "Do you want to reset %s?", m_szName);
512 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_ResetPlayer, 0);
513 }
514 }
515 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
516 RedisplayAdminMenu(g_hAdminMenu, client);
517}
518
519//////////////////////////////
520// Give credits //
521//////////////////////////////
522
523public AdminMenu_GiveCredits(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
524{
525 if (action == TopMenuAction_DisplayOption)
526 {
527 Format(buffer, maxlength, "Give credits");
528 }
529 else if (action == TopMenuAction_SelectOption)
530 {
531 g_iMenuNum[client] = 5;
532 new Handle:m_hMenu = CreateMenu(MenuHandler_GiveCredits);
533 SetMenuTitle(m_hMenu, "Choose a player to give credits to");
534 SetMenuExitBackButton(m_hMenu, true);
535 LoopAuthorizedPlayers(i)
536 {
537 decl String:m_szName[64];
538 decl String:m_szAuthId[32];
539 GetClientName(i, STRING(m_szName));
540 GetLegacyAuthString(i, STRING(m_szAuthId));
541 AddMenuItem(m_hMenu, m_szAuthId, m_szName);
542 }
543 DisplayMenu(m_hMenu, client, 0);
544 }
545}
546
547public MenuHandler_GiveCredits(Handle:menu, MenuAction:action, client, param2)
548{
549 if (action == MenuAction_End)
550 CloseHandle(menu);
551 else if (action == MenuAction_Select)
552 {
553 if(param2 != -1)
554 GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]));
555 new Handle:m_hMenu = CreateMenu(MenuHandler_GiveCredits2);
556
557 new target = GetClientBySteamID(g_szClientData[client]);
558 if(target == 0)
559 {
560 AdminMenu_GiveCredits(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
561 return;
562 }
563
564 SetMenuTitle(m_hMenu, "Choose the amount of credits\n%N - %d credits", target, g_eClients[target][iCredits]);
565 SetMenuExitBackButton(m_hMenu, true);
566 AddMenuItem(m_hMenu, "-1000", "-1000");
567 AddMenuItem(m_hMenu, "-100", "-100");
568 AddMenuItem(m_hMenu, "-10", "-10");
569 AddMenuItem(m_hMenu, "10", "10");
570 AddMenuItem(m_hMenu, "100", "100");
571 AddMenuItem(m_hMenu, "1000", "1000");
572 DisplayMenu(m_hMenu, client, 0);
573 }
574 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
575 RedisplayAdminMenu(g_hAdminMenu, client);
576}
577
578public MenuHandler_GiveCredits2(Handle:menu, MenuAction:action, client, param2)
579{
580 if (action == MenuAction_End)
581 CloseHandle(menu);
582 else if (action == MenuAction_Select)
583 {
584 decl String:m_szData[11];
585 GetMenuItem(menu, param2, STRING(m_szData));
586 FakeClientCommand(client, "sm_givecredits \"%s\" %s", g_szClientData[client], m_szData);
587 MenuHandler_GiveCredits(INVALID_HANDLE, MenuAction_Select, client, -1);
588 }
589 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
590 AdminMenu_GiveCredits(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
591}
592
593//////////////////////////////
594// View inventory //
595//////////////////////////////
596
597public AdminMenu_ViewInventory(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
598{
599 if (action == TopMenuAction_DisplayOption)
600 {
601 Format(buffer, maxlength, "View inventory");
602 }
603 else if (action == TopMenuAction_SelectOption)
604 {
605 g_iMenuNum[client] = 4;
606 new Handle:m_hMenu = CreateMenu(MenuHandler_ViewInventory);
607 SetMenuTitle(m_hMenu, "Choose a player");
608 SetMenuExitBackButton(m_hMenu, true);
609 LoopAuthorizedPlayers(i)
610 {
611 decl String:m_szName[64];
612 decl String:m_szAuthId[32];
613 GetClientName(i, STRING(m_szName));
614 GetLegacyAuthString(i, STRING(m_szAuthId));
615 AddMenuItem(m_hMenu, m_szAuthId, m_szName);
616 }
617 DisplayMenu(m_hMenu, client, 0);
618 }
619}
620
621public MenuHandler_ViewInventory(Handle:menu, MenuAction:action, client, param2)
622{
623 if (action == MenuAction_End)
624 CloseHandle(menu);
625 else if (action == MenuAction_Select)
626 {
627 GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]));
628 new target = GetClientBySteamID(g_szClientData[client]);
629 if(target == 0)
630 {
631 AdminMenu_ViewInventory(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
632 return;
633 }
634
635 g_bInvMode[client]=true;
636 g_iMenuClient[client]=target;
637 DisplayStoreMenu(client);
638 }
639 else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
640 RedisplayAdminMenu(g_hAdminMenu, client);
641}
642
643//////////////////////////////////////
644// REST OF PLUGIN FORWARDS //
645//////////////////////////////////////
646
647public OnMapStart()
648{
649 for(new i=0;i<g_iTypeHandlers;++i)
650 {
651 if(g_eTypeHandlers[i][fnMapStart] != INVALID_FUNCTION)
652 {
653 Call_StartFunction(g_eTypeHandlers[i][hPlugin], g_eTypeHandlers[i][fnMapStart]);
654 Call_Finish();
655 }
656 }
657}
658
659public OnConfigsExecuted()
660{
661 Jetpack_OnConfigsExecuted();
662 Jihad_OnConfigsExecuted();
663
664 // Connect to the database
665 if(g_hDatabase == INVALID_HANDLE)
666 SQL_TConnect(SQLCallback_Connect, g_eCvars[g_cvarDatabaseEntry][sCache]);
667 if(g_eCvars[g_cvarDatabaseRetries][aCache] > 0)
668 CreateTimer(Float:g_eCvars[g_cvarDatabaseTimeout][aCache], Timer_DatabaseTimeout);
669
670 if(g_eCvars[g_cvarLogging][aCache] == 1)
671 if(g_hLogFile == INVALID_HANDLE)
672 {
673 new String:m_szPath[PLATFORM_MAX_PATH];
674 BuildPath(Path_SM, STRING(m_szPath), "logs/store.log.txt");
675 g_hLogFile = OpenFile(m_szPath, "w+");
676 }
677}
678
679#if !defined STANDALONE_BUILD
680public OnGameFrame()
681{
682 Trails_OnGameFrame();
683 TFWeapon_OnGameFrame();
684 TFHead_OnGameFrame();
685}
686#endif
687
688#if !defined STANDALONE_BUILD
689public OnEntityCreated(entity, const String:classname[])
690{
691 GrenadeSkins_OnEntityCreated(entity, classname);
692 GrenadeTrails_OnEntityCreated(entity, classname);
693}
694#endif
695
696//////////////////////////////
697// NATIVES //
698//////////////////////////////
699
700public Native_RegisterHandler(Handle:plugin, numParams)
701{
702 if(g_iTypeHandlers == STORE_MAX_HANDLERS)
703 return -1;
704
705 decl String:m_szType[32];
706 GetNativeString(1, STRING(m_szType));
707 new m_iHandler = Store_GetTypeHandler(m_szType);
708 new m_iId = g_iTypeHandlers;
709
710 if(m_iHandler != -1)
711 m_iId = m_iHandler;
712 else
713 ++g_iTypeHandlers;
714
715 g_eTypeHandlers[m_iId][hPlugin] = plugin;
716 g_eTypeHandlers[m_iId][fnMapStart] = GetNativeCell(3);
717 g_eTypeHandlers[m_iId][fnReset] = GetNativeCell(4);
718 g_eTypeHandlers[m_iId][fnConfig] = GetNativeCell(5);
719 g_eTypeHandlers[m_iId][fnUse] = GetNativeCell(6);
720 g_eTypeHandlers[m_iId][fnRemove] = GetNativeCell(7);
721 g_eTypeHandlers[m_iId][bEquipable] = GetNativeCell(8);
722 g_eTypeHandlers[m_iId][bRaw] = GetNativeCell(9);
723 strcopy(g_eTypeHandlers[m_iId][szType], 32, m_szType);
724 GetNativeString(2, g_eTypeHandlers[m_iId][szUniqueKey], 32);
725
726 return m_iId;
727}
728
729public Native_RegisterMenuHandler(Handle:plugin, numParams)
730{
731 if(g_iMenuHandlers == STORE_MAX_HANDLERS)
732 return -1;
733
734 decl String:m_szIdentifier[64];
735 GetNativeString(1, STRING(m_szIdentifier));
736 new m_iHandler = Store_GetMenuHandler(m_szIdentifier);
737 new m_iId = g_iMenuHandlers;
738
739 if(m_iHandler != -1)
740 m_iId = m_iHandler;
741 else
742 ++g_iMenuHandlers;
743
744 g_eMenuHandlers[m_iId][hPlugin] = plugin;
745 g_eMenuHandlers[m_iId][fnMenu] = GetNativeCell(2);
746 g_eMenuHandlers[m_iId][fnHandler] = GetNativeCell(3);
747 strcopy(g_eMenuHandlers[m_iId][szIdentifier], 64, m_szIdentifier);
748
749 return m_iId;
750}
751
752public Native_SetDataIndex(Handle:plugin, numParams)
753{
754 g_eItems[GetNativeCell(1)][iData] = GetNativeCell(2);
755}
756
757public Native_GetDataIndex(Handle:plugin, numParams)
758{
759 return g_eItems[GetNativeCell(1)][iData];
760}
761
762public Native_GetEquippedItem(Handle:plugin, numParams)
763{
764 decl String:m_szType[16];
765 GetNativeString(2, STRING(m_szType));
766
767 new m_iHandler = Store_GetTypeHandler(m_szType);
768 if(m_iHandler == -1)
769 return -1;
770
771 return Store_GetEquippedItemFromHandler(GetNativeCell(1), m_iHandler, GetNativeCell(3));
772}
773
774public Native_IsClientLoaded(Handle:plugin, numParams)
775{
776 return g_eClients[GetNativeCell(1)][bLoaded];
777}
778
779public Native_DisplayPreviousMenu(Handle:plugin, numParams)
780{
781 new client = GetNativeCell(1);
782 if(g_iMenuNum[client] == 1)
783 DisplayStoreMenu(client, g_iMenuBack[client], g_iLastSelection[client]);
784 else if(g_iMenuNum[client] == 2)
785 DisplayItemMenu(client, g_iSelectedItem[client]);
786 else if(g_iMenuNum[client] == 3)
787 DisplayPlayerMenu(client);
788 else if(g_iMenuNum[client] == 4)
789 AdminMenu_ResetPlayer(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
790 else if(g_iMenuNum[client] == 5)
791 DisplayPlanMenu(client, g_iSelectedItem[client]);
792 else if(g_iMenuNum[client] == 0)
793 RedisplayAdminMenu(g_hAdminMenu, client);
794}
795
796public Native_SetClientMenu(Handle:plugin, numParams)
797{
798 g_iMenuNum[GetNativeCell(1)] = GetNativeCell(2);
799}
800
801public Native_GetClientCredits(Handle:plugin, numParams)
802{
803 return g_eClients[GetNativeCell(1)][iCredits];
804}
805
806public Native_SetClientCredits(Handle:plugin, numParams)
807{
808 new client = GetNativeCell(1);
809 new m_iCredits = GetNativeCell(2);
810 Store_LogMessage(client, m_iCredits-g_eClients[client][iCredits], "Set by external plugin");
811 g_eClients[client][iCredits] = m_iCredits;
812 return 1;
813}
814
815public Native_IsClientVIP(Handle:plugin, numParams)
816{
817 return (g_eCvars[g_cvarVIPFlag][aCache] != 0 && GetClientPrivilege(GetNativeCell(1), g_eCvars[g_cvarVIPFlag][aCache]));
818}
819
820public Native_IsItemInBoughtPackage(Handle:plugin, numParams)
821{
822 new client = GetNativeCell(1);
823 new itemid = GetNativeCell(2);
824 new uid = GetNativeCell(3);
825
826 decl m_iParent;
827 if(itemid<0)
828 m_iParent = g_eItems[itemid][iParent];
829 else
830 m_iParent = g_eItems[itemid][iParent];
831
832 while(m_iParent != -1)
833 {
834 for(new i=0;i<g_eClients[client][iItems];++i)
835 if(((uid == -1 && g_eClientItems[client][i][iUniqueId] == m_iParent) || (uid != -1 && g_eClientItems[client][i][iUniqueId] == uid)) && !g_eClientItems[client][i][bDeleted])
836 return true;
837 m_iParent = g_eItems[m_iParent][iParent];
838 }
839 return false;
840}
841
842public Native_DisplayConfirmMenu(Handle:plugin, numParams)
843{
844 new client = GetNativeCell(1);
845 decl String:title[255];
846 GetNativeString(2, STRING(title));
847 new callback = GetNativeCell(3);
848 new data = GetNativeCell(4);
849
850 new Handle:m_hMenu = CreateMenu(MenuHandler_Confirm);
851 SetMenuTitle(m_hMenu, title);
852 SetMenuExitButton(m_hMenu, false);
853 new String:m_szCallback[32];
854 new String:m_szData[11];
855 Format(STRING(m_szCallback), "%d.%d", plugin, callback);
856 IntToString(data, STRING(m_szData));
857 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, m_szCallback, "%t", "Confirm_Yes");
858 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, m_szData, "%t", "Confirm_No");
859 DisplayMenu(m_hMenu, client, 0);
860}
861
862public Native_ShouldConfirm(Handle:plugin, numParams)
863{
864 return g_eCvars[g_cvarConfirmation][aCache];
865}
866
867public Native_GetItem(Handle:plugin, numParams)
868{
869 SetNativeArray(2, _:g_eItems[GetNativeCell(1)], sizeof(g_eItems[]));
870}
871
872public Native_GetHandler(Handle:plugin, numParams)
873{
874 SetNativeArray(2, _:g_eTypeHandlers[GetNativeCell(1)], sizeof(g_eTypeHandlers[]));
875}
876
877public Native_GetClientItem(Handle:plugin, numParams)
878{
879 new client = GetNativeCell(1);
880 new itemid = GetNativeCell(2);
881
882 new uid = Store_GetClientItemId(client, itemid);
883 if(uid<0)
884 return 0;
885
886 SetNativeArray(3, _:g_eClientItems[client][uid], sizeof(g_eClientItems[][]));
887
888 return 1;
889}
890
891public Native_GiveItem(Handle:plugin, numParams)
892{
893 new client = GetNativeCell(1);
894 new itemid = GetNativeCell(2);
895 new purchase = GetNativeCell(3);
896 new expiration = GetNativeCell(4);
897 new price = GetNativeCell(5);
898
899 new m_iDateOfPurchase = (purchase==0?GetTime():purchase);
900 new m_iDateOfExpiration = expiration;
901
902 new m_iId = g_eClients[client][iItems]++;
903 g_eClientItems[client][m_iId][iId] = -1;
904 g_eClientItems[client][m_iId][iUniqueId] = itemid;
905 g_eClientItems[client][m_iId][iDateOfPurchase] = m_iDateOfPurchase;
906 g_eClientItems[client][m_iId][iDateOfExpiration] = m_iDateOfExpiration;
907 g_eClientItems[client][m_iId][iPriceOfPurchase] = price;
908 g_eClientItems[client][m_iId][bSynced] = false;
909 g_eClientItems[client][m_iId][bDeleted] = false;
910}
911
912public Native_RemoveItem(Handle:plugin, numParams)
913{
914 new client = GetNativeCell(1);
915 new itemid = GetNativeCell(2);
916 if(itemid>0 && g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
917 {
918 Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove]);
919 Call_PushCell(client);
920 Call_PushCell(itemid);
921 Call_Finish();
922 }
923
924 Store_UnequipItem(client, itemid, false);
925
926 new m_iId = Store_GetClientItemId(client, itemid);
927 if(m_iId != -1)
928 g_eClientItems[client][m_iId][bDeleted] = true;
929}
930
931public Native_GetClientTarget(Handle:plugin, numParams)
932{
933 return g_iMenuClient[GetNativeCell(1)];
934}
935
936public Native_GiveClientItem(Handle:plugin, numParams)
937{
938 new client = GetNativeCell(1);
939 new receiver = GetNativeCell(2);
940 new itemid = GetNativeCell(3);
941
942 new item = Store_GetClientItemId(client, itemid);
943 if(item == -1)
944 return 1;
945
946 new m_iId = g_eClientItems[client][item][iUniqueId];
947 new target = g_iMenuClient[client];
948 g_eClientItems[client][item][bDeleted] = true;
949 Store_UnequipItem(client, m_iId);
950
951 g_eClientItems[receiver][g_eClients[receiver][iItems]][iId] = -1;
952 g_eClientItems[receiver][g_eClients[receiver][iItems]][iUniqueId] = m_iId;
953 g_eClientItems[receiver][g_eClients[receiver][iItems]][bSynced] = false;
954 g_eClientItems[receiver][g_eClients[receiver][iItems]][bDeleted] = false;
955 g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfPurchase] = g_eClientItems[target][item][iDateOfPurchase];
956 g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfExpiration] = g_eClientItems[target][item][iDateOfExpiration];
957 g_eClientItems[receiver][g_eClients[receiver][iItems]][iPriceOfPurchase] = g_eClientItems[target][item][iPriceOfPurchase];
958
959 ++g_eClients[receiver][iItems];
960
961 return 1;
962}
963
964public Native_HasClientItem(Handle:plugin, numParams)
965{
966 new client = GetNativeCell(1);
967 new itemid = GetNativeCell(2);
968
969 // Can he even have it?
970 if(!GetClientPrivilege(client, g_eItems[itemid][iFlagBits]))
971 return false;
972
973 // Is the item free (available for everyone)?
974 if(g_eItems[itemid][iPrice] <= 0 && g_eItems[itemid][iPlans]==0)
975 return true;
976
977 // Is the client a VIP therefore has access to all the items already?
978 if(Store_IsClientVIP(client) && !g_eItems[itemid][bIgnoreVIP])
979 return true;
980
981 // Can he even have it?
982 if(!GetClientPrivilege(client, g_eItems[itemid][iFlagBits]))
983 return false;
984
985 // Check if the client actually has the item
986 for(new i=0;i<g_eClients[client][iItems];++i)
987 {
988 if(g_eClientItems[client][i][iUniqueId] == itemid && !g_eClientItems[client][i][bDeleted])
989 if(g_eClientItems[client][i][iDateOfExpiration]==0 || (g_eClientItems[client][i][iDateOfExpiration] && GetTime()<g_eClientItems[client][i][iDateOfExpiration]))
990 return true;
991 else
992 return false;
993 }
994
995 // Check if the item is part of a group the client already has
996 if(Store_IsItemInBoughtPackage(client, itemid))
997 return true;
998
999 return false;
1000}
1001
1002public Native_IterateEquippedItems(Handle:plugin, numParams)
1003{
1004 new client = GetNativeCell(1);
1005 new start = GetNativeCellRef(2);
1006 new bool:attributes = GetNativeCell(3);
1007
1008 for(new i=start+1;i<STORE_MAX_HANDLERS*STORE_MAX_SLOTS;++i)
1009 {
1010 if(g_eClients[client][aEquipment][i] >= 0 && (attributes==false || (attributes && g_eItems[g_eClients[client][aEquipment][i]][hAttributes]!=INVALID_HANDLE)))
1011 {
1012 SetNativeCellRef(2, i);
1013 return g_eClients[client][aEquipment][i];
1014 }
1015 }
1016
1017 return -1;
1018}
1019
1020//////////////////////////////
1021// CLIENT FORWARDS //
1022//////////////////////////////
1023
1024public OnClientConnected(client)
1025{
1026 g_iSpam[client] = 0;
1027 g_eClients[client][iUserId] = GetClientUserId(client);
1028 g_eClients[client][iCredits] = -1;
1029 g_eClients[client][iOriginalCredits] = 0;
1030 g_eClients[client][iItems] = -1;
1031 g_eClients[client][bLoaded] = false;
1032 for(new i=0;i<STORE_MAX_HANDLERS;++i)
1033 {
1034 for(new a=0;a<STORE_MAX_SLOTS;++a)
1035 {
1036 g_eClients[client][aEquipment][i*STORE_MAX_SLOTS+a] = -2;
1037 g_eClients[client][aEquipmentSynced][i*STORE_MAX_SLOTS+a] = -2;
1038 }
1039 }
1040
1041#if !defined STANDALONE_BUILD
1042 PlayerSkins_OnClientConnected(client);
1043 Jetpack_OnClientConnected(client);
1044 ZRClass_OnClientConnected(client);
1045 Pets_OnClientConnected(client);
1046 Sprays_OnClientConnected(client);
1047 Glow_OnClientConnected(client);
1048#endif
1049}
1050
1051public OnClientPostAdminCheck(client)
1052{
1053 if(IsFakeClient(client))
1054 return;
1055 Store_LoadClientInventory(client);
1056}
1057
1058#if !defined STANDALONE_BUILD
1059public OnClientPutInServer(client)
1060{
1061 if(IsFakeClient(client))
1062 return;
1063 WeaponColors_OnClientPutInServer(client);
1064}
1065#endif
1066
1067public OnClientDisconnect(client)
1068{
1069 if(IsFakeClient(client))
1070 return;
1071
1072#if !defined STANDALONE_BUILD
1073 Betting_OnClientDisconnect(client);
1074 Pets_OnClientDisconnect(client);
1075 Glow_OnClientDisconnect(client);
1076#endif
1077
1078 Store_SaveClientData(client);
1079 Store_SaveClientInventory(client);
1080 Store_SaveClientEquipment(client);
1081 Store_DisconnectClient(client);
1082}
1083
1084public OnClientSettingsChanged(client)
1085{
1086 GetClientName(client, g_eClients[client][szName], 64);
1087 if(g_hDatabase)
1088 SQL_EscapeString(g_hDatabase, g_eClients[client][szName], g_eClients[client][szNameEscaped], 128);
1089}
1090
1091#if !defined STANDALONE_BUILD
1092public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2])
1093{
1094 if(!IsClientInGame(client))
1095 return Plugin_Continue;
1096
1097 new Action:m_iRet = Plugin_Continue;
1098
1099 Jetpack_OnPlayerRunCmd(client, buttons);
1100 LaserSight_OnPlayerRunCmd(client);
1101 Pets_OnPlayerRunCmd(client, tickcount);
1102 Sprays_OnPlayerRunCmd(client, buttons);
1103 m_iRet = Bunnyhop_OnPlayerRunCmd(client, buttons);
1104
1105 return m_iRet;
1106}
1107#endif
1108
1109//////////////////////////////
1110// EVENTS //
1111//////////////////////////////
1112
1113public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
1114{
1115 new victim = GetClientOfUserId(GetEventInt(event, "userid"));
1116 new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
1117
1118 if(g_eCvars[g_cvarSaveOnDeath][aCache])
1119 {
1120 Store_SaveClientData(victim);
1121 Store_SaveClientInventory(victim);
1122 Store_SaveClientEquipment(victim);
1123 }
1124
1125 if(!attacker || victim == attacker || !IsClientInGame(attacker) || IsFakeClient(attacker))
1126 return Plugin_Continue;
1127
1128 if(g_eCvars[g_cvarCreditAmountKill][aCache])
1129 {
1130 g_eClients[attacker][iCredits] += GetMultipliedCredits(attacker, g_eCvars[g_cvarCreditAmountKill][aCache]);
1131 if(g_eCvars[g_cvarCreditMessages][aCache])
1132 Chat(attacker, "%t", "Credits Earned For Killing", g_eCvars[g_cvarCreditAmountKill][aCache], g_eClients[victim][szName]);
1133 Store_LogMessage(attacker, g_eCvars[g_cvarCreditAmountKill][aCache], "Earned for killing");
1134 }
1135
1136 return Plugin_Continue;
1137}
1138
1139public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
1140{
1141 new client = GetClientOfUserId(GetEventInt(event, "userid"));
1142
1143 if(!IsClientInGame(client))
1144 return Plugin_Continue;
1145
1146#if !defined STANDALONE_BUILD
1147 Health_OnPlayerSpawn(client);
1148#endif
1149
1150 return Plugin_Continue;
1151}
1152
1153
1154//////////////////////////////////
1155// COMMANDS //
1156//////////////////////////////////
1157
1158public Action:Command_Say(client, const String:command[], argc)
1159{
1160 if(argc > 0)
1161 {
1162 decl String:m_szArg[65];
1163 GetCmdArg(1, STRING(m_szArg));
1164 if(m_szArg[0] == PublicChatTrigger)
1165 {
1166 for(new i=0;i<g_iItems;++i)
1167 if(strcmp(g_eItems[i][szShortcut], m_szArg[1])==0 && g_eItems[i][szShortcut][0] != 0)
1168 {
1169 g_bInvMode[client]=false;
1170 g_iMenuClient[client]=client;
1171 DisplayStoreMenu(client, i);
1172 break;
1173 }
1174 }
1175 }
1176 return Plugin_Continue;
1177}
1178
1179public Action:Command_Store(client, params)
1180{
1181 if(g_eCvars[g_cvarRequiredFlag][aCache] && !GetClientPrivilege(client, g_eCvars[g_cvarRequiredFlag][aCache]))
1182 {
1183 Chat(client, "%t", "You dont have permission");
1184 return Plugin_Handled;
1185 }
1186
1187 if((g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1) || !g_eClients[client][bLoaded])
1188 {
1189 Chat(client, "%t", "Inventory hasnt been fetched");
1190 return Plugin_Handled;
1191 }
1192
1193 g_bInvMode[client]=false;
1194 g_iMenuClient[client]=client;
1195 DisplayStoreMenu(client);
1196
1197 return Plugin_Handled;
1198}
1199
1200public Action:Command_Inventory(client, params)
1201{
1202 if(g_eCvars[g_cvarRequiredFlag][aCache] && !GetClientPrivilege(client, g_eCvars[g_cvarRequiredFlag][aCache]))
1203 {
1204 Chat(client, "%t", "You dont have permission");
1205 return Plugin_Handled;
1206 }
1207
1208 if((g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1) || !g_eClients[client][bLoaded])
1209 {
1210 Chat(client, "%t", "Inventory hasnt been fetched");
1211 return Plugin_Handled;
1212 }
1213
1214 g_bInvMode[client]=true;
1215 g_iMenuClient[client]=client;
1216 DisplayStoreMenu(client);
1217
1218 return Plugin_Handled;
1219}
1220
1221public Action:Command_Gift(client, params)
1222{
1223 if(!g_eCvars[g_cvarCreditGiftEnabled][aCache])
1224 {
1225 Chat(client, "%t", "Credit Gift Disabled");
1226 return Plugin_Handled;
1227 }
1228
1229 decl String:m_szTmp[64];
1230 GetCmdArg(2, STRING(m_szTmp));
1231
1232 new m_iCredits = StringToInt(m_szTmp);
1233 if(g_eClients[client][iCredits]<m_iCredits || m_iCredits<=0)
1234 {
1235 Chat(client, "%t", "Credit Invalid Amount");
1236 return Plugin_Handled;
1237 }
1238
1239 decl bool:m_bTmp;
1240 decl m_iTargets[1];
1241 GetCmdArg(1, STRING(m_szTmp));
1242
1243 new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
1244 if(m_iClients>2)
1245 {
1246 Chat(client, "%t", "Credit Too Many Matches");
1247 return Plugin_Handled;
1248 }
1249
1250 if(m_iClients != 1)
1251 {
1252 Chat(client, "%t", "Credit No Match");
1253 return Plugin_Handled;
1254 }
1255
1256 new m_iReceiver = m_iTargets[0];
1257
1258 g_eClients[client][iCredits] -= m_iCredits;
1259 g_eClients[m_iReceiver][iCredits] += m_iCredits;
1260
1261 Chat(client, "%t", "Credit Gift Sent", m_iCredits, g_eClients[m_iReceiver][szName]);
1262 Chat(m_iReceiver, "%t", "Credit Gift Received", m_iCredits, g_eClients[client][szName]);
1263
1264 Store_LogMessage(m_iReceiver, m_iCredits, "Gifted by %N", client);
1265 Store_LogMessage(client, -m_iCredits, "Gifted to %N", m_iReceiver);
1266
1267 return Plugin_Handled;
1268}
1269
1270public Action:Command_GiveCredits(client, params)
1271{
1272 if(client && !GetClientPrivilege(client, g_eCvars[g_cvarAdminFlag][aCache]))
1273 {
1274 Chat(client, "%t", "You dont have permission");
1275 return Plugin_Handled;
1276 }
1277
1278 decl String:m_szTmp[64];
1279 GetCmdArg(2, STRING(m_szTmp));
1280
1281 new m_iCredits = StringToInt(m_szTmp);
1282
1283 decl bool:m_bTmp;
1284 decl m_iTargets[1];
1285 GetCmdArg(1, STRING(m_szTmp));
1286
1287 new m_iReceiver = -1;
1288 if(strncmp(m_szTmp, "STEAM_", 6)==0)
1289 {
1290 m_iReceiver = GetClientBySteamID(m_szTmp);
1291 // SteamID is not ingame
1292 if(m_iReceiver == 0)
1293 {
1294 decl String:m_szQuery[512];
1295 if(g_bMySQL)
1296 Format(STRING(m_szQuery), "INSERT IGNORE INTO store_players (authid, credits) VALUES (\"%s\", %d) ON DUPLICATE KEY UPDATE credits=credits+%d", m_szTmp[8], m_iCredits, m_iCredits);
1297 else
1298 {
1299 Format(STRING(m_szQuery), "INSERT OR IGNORE INTO store_players (authid) VALUES (\"%s\")", m_szTmp[8]);
1300 SQL_TVoid(g_hDatabase, m_szQuery);
1301 Format(STRING(m_szQuery), "UPDATE store_players SET credits=credits+%d WHERE authid=\"%s\"", m_iCredits, m_szTmp[8]);
1302 }
1303 SQL_TVoid(g_hDatabase, m_szQuery);
1304 ChatAll("%t", "Credits Given", m_szTmp[8], m_iCredits);
1305 m_iReceiver = -1;
1306 }
1307 } else if(strcmp(m_szTmp, "@all")==0)
1308 {
1309 LoopIngamePlayers(i)
1310 FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
1311 } else if(strcmp(m_szTmp, "@t")==0 || strcmp(m_szTmp, "@red")==0)
1312 {
1313 LoopIngamePlayers(i)
1314 if(GetClientTeam(i)==2)
1315 FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
1316 } else if(strcmp(m_szTmp, "@ct")==0 || strcmp(m_szTmp, "@blu")==0)
1317 {
1318 LoopIngamePlayers(i)
1319 if(GetClientTeam(i)==3)
1320 FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
1321 }
1322 else
1323 {
1324 new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
1325 if(m_iClients>2)
1326 {
1327 if(client)
1328 Chat(client, "%t", "Credit Too Many Matches");
1329 else
1330 ReplyToCommand(client, "%t", "Credit Too Many Matches");
1331 return Plugin_Handled;
1332 } else if(m_iClients != 1)
1333 {
1334 if(client)
1335 Chat(client, "%t", "Credit No Match");
1336 else
1337 ReplyToCommand(client, "%t", "Credit No Match");
1338 return Plugin_Handled;
1339 }
1340
1341 m_iReceiver = m_iTargets[0];
1342 }
1343
1344 // The player is on the server
1345 if(m_iReceiver != -1)
1346 {
1347 g_eClients[m_iReceiver][iCredits] += m_iCredits;
1348 if(g_eCvars[g_cvarSilent][aCache] == 1)
1349 {
1350 if(client)
1351 Chat(client, "%t", "Credits Given", g_eClients[m_iReceiver][szName], m_iCredits);
1352 else
1353 ReplyToCommand(client, "%t", "Credits Given", g_eClients[m_iReceiver][szName], m_iCredits);
1354 Chat(m_iReceiver, "%t", "Credits Given", g_eClients[m_iReceiver][szName], m_iCredits);
1355 }
1356 else if(g_eCvars[g_cvarSilent][aCache] == 0)
1357 ChatAll("%t", "Credits Given", g_eClients[m_iReceiver][szName], m_iCredits);
1358 Store_LogMessage(m_iReceiver, m_iCredits, "Given by Admin");
1359 }
1360
1361 return Plugin_Handled;
1362}
1363
1364public Action:Command_ResetPlayer(client, params)
1365{
1366 if(client && !GetClientPrivilege(client, g_eCvars[g_cvarAdminFlag][aCache]))
1367 {
1368 Chat(client, "%t", "You dont have permission");
1369 return Plugin_Handled;
1370 }
1371
1372 decl String:m_szTmp[64];
1373 decl bool:m_bTmp;
1374 decl m_iTargets[1];
1375 GetCmdArg(1, STRING(m_szTmp));
1376
1377 new m_iReceiver = -1;
1378 if(strncmp(m_szTmp, "STEAM_", 6)==0)
1379 {
1380 m_iReceiver = GetClientBySteamID(m_szTmp);
1381 // SteamID is not ingame
1382 if(m_iReceiver == 0)
1383 {
1384 decl String:m_szQuery[512];
1385 Format(STRING(m_szQuery), "SELECT id, authid FROM store_players WHERE authid=\"%s\"", m_szTmp[9]);
1386 SQL_TQuery(g_hDatabase, SQLCallback_ResetPlayer, m_szQuery, g_eClients[client][iUserId]);
1387 }
1388 }
1389 else
1390 {
1391 new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
1392 if(m_iClients>2)
1393 {
1394 Chat(client, "%t", "Credit Too Many Matches");
1395 return Plugin_Handled;
1396 }
1397
1398 if(m_iClients != 1)
1399 {
1400 Chat(client, "%t", "Credit No Match");
1401 return Plugin_Handled;
1402 }
1403
1404 m_iReceiver = m_iTargets[0];
1405 }
1406
1407 // The player is on the server
1408 if(m_iReceiver != -1)
1409 {
1410 Store_LogMessage(client, -g_eClients[m_iReceiver][iCredits], "Player resetted");
1411 g_eClients[m_iReceiver][iCredits] = 0;
1412 for(new i=0;i<g_eClients[m_iReceiver][iItems];++i)
1413 Store_RemoveItem(m_iReceiver, g_eClientItems[m_iReceiver][i][iUniqueId]);
1414 ChatAll("%t", "Player Resetted", g_eClients[m_iReceiver][szName]);
1415 }
1416
1417 return Plugin_Handled;
1418}
1419
1420public Action:Command_Credits(client, params)
1421{
1422 if(g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1)
1423 {
1424 Chat(client, "%t", "Inventory hasnt been fetched");
1425 return Plugin_Handled;
1426 }
1427
1428 if(g_iSpam[client]<GetTime())
1429 {
1430 ChatAll("%t", "Player Credits", g_eClients[client][szName], g_eClients[client][iCredits]);
1431 g_iSpam[client] = GetTime()+30;
1432 }
1433
1434 return Plugin_Handled;
1435}
1436
1437public Action:Command_CustomCredits(params)
1438{
1439 if(params < 2)
1440 {
1441 PrintToServer("sm_store_custom_credits [flag] [multiplier]");
1442 return Plugin_Handled;
1443 }
1444
1445 new String:tmp[16];
1446 GetCmdArg(1, STRING(tmp));
1447 new flag = ReadFlagString(tmp);
1448 GetCmdArg(2, STRING(tmp));
1449 new Float:mult = StringToFloat(tmp);
1450
1451 new size = GetArraySize(g_hCustomCredits);
1452 new index = -1;
1453 for(new i=0;i<size;++i)
1454 {
1455 new sflag = GetArrayCell(g_hCustomCredits, i, 0);
1456 if(sflag == flag)
1457 {
1458 index = i;
1459 break;
1460 }
1461 }
1462
1463 if(index == -1)
1464 {
1465 index = PushArrayCell(g_hCustomCredits, flag);
1466 }
1467
1468 SetArrayCell(g_hCustomCredits, index, mult, 1);
1469
1470 return Plugin_Handled;
1471}
1472
1473//////////////////////////////
1474// MENUS //
1475//////////////////////////////
1476
1477DisplayStoreMenu(client, parent=-1, last=-1)
1478{
1479 if(!client || !IsClientInGame(client))
1480 return;
1481
1482 g_iMenuNum[client] = 1;
1483 new target = g_iMenuClient[client];
1484
1485 new Handle:m_hMenu = CreateMenu(MenuHandler_Store);
1486 if(parent!=-1)
1487 {
1488 SetMenuExitBackButton(m_hMenu, true);
1489 if(client == target)
1490 SetMenuTitle(m_hMenu, "%s\n%t", g_eItems[parent][szName], "Title Credits", g_eClients[target][iCredits]);
1491 else
1492 SetMenuTitle(m_hMenu, "%N\n%s\n%t", target, g_eItems[parent][szName], "Title Credits", g_eClients[target][iCredits]);
1493 g_iMenuBack[client] = g_eItems[parent][iParent];
1494 }
1495 else if(client == target)
1496 SetMenuTitle(m_hMenu, "%t\n%t", "Title Store", "Title Credits", g_eClients[target][iCredits]);
1497 else
1498 SetMenuTitle(m_hMenu, "%N\n%t\n%t", target, "Title Store", "Title Credits", g_eClients[target][iCredits]);
1499
1500 decl String:m_szId[11];
1501 new m_iFlags = GetUserFlagBits(target);
1502 new m_iPosition = 0;
1503
1504 g_iSelectedItem[client] = parent;
1505 if(parent != -1)
1506 {
1507 if(g_eItems[parent][iPrice]>0)
1508 {
1509 if(!Store_IsClientVIP(target) && !Store_IsItemInBoughtPackage(target, parent))
1510 {
1511 if(g_eCvars[g_cvarSellEnabled][aCache])
1512 {
1513 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "sell_package", "%t", "Package Sell", RoundToFloor(g_eItems[parent][iPrice]*Float:g_eCvars[g_cvarSellRatio][aCache]));
1514 ++m_iPosition;
1515 }
1516 if(g_eCvars[g_cvarGiftEnabled][aCache] == 1 || (g_eCvars[g_cvarGiftEnabled][aCache] == 2 && GetUserFlagBits(client) & g_eCvars[g_cvarAdminFlag][aCache]))
1517 {
1518 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "gift_package", "%t", "Package Gift");
1519 ++m_iPosition;
1520 }
1521
1522 for(new i=0;i<g_iMenuHandlers;++i)
1523 {
1524 if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
1525 continue;
1526 Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnMenu]);
1527 Call_PushCellRef(m_hMenu);
1528 Call_PushCell(client);
1529 Call_PushCell(parent);
1530 Call_Finish();
1531 }
1532 }
1533 }
1534 }
1535
1536 for(new i=0;i<g_iItems;++i)
1537 {
1538 if(g_eItems[i][iParent]==parent && (g_eCvars[g_cvarShowVIP][aCache] == 0 && GetClientPrivilege(target, g_eItems[i][iFlagBits], m_iFlags) || g_eCvars[g_cvarShowVIP][aCache]))
1539 {
1540 new m_iPrice = Store_GetLowestPrice(i);
1541
1542 // This is a package
1543 if(g_eItems[i][iHandler] == g_iPackageHandler)
1544 {
1545 if(!Store_PackageHasClientItem(target, i, g_bInvMode[client]))
1546 continue;
1547
1548 new m_iStyle = ITEMDRAW_DEFAULT;
1549 if(g_eCvars[g_cvarShowVIP][aCache] && !GetClientPrivilege(target, g_eItems[i][iFlagBits], m_iFlags))
1550 m_iStyle = ITEMDRAW_DISABLED;
1551
1552 IntToString(i, STRING(m_szId));
1553 if(g_eItems[i][iPrice] == -1 || Store_HasClientItem(target, i))
1554 AddMenuItem(m_hMenu, m_szId, g_eItems[i][szName], m_iStyle);
1555 else if(!g_bInvMode[client] && g_eItems[i][iPlans]==0 && g_eItems[i][bBuyable])
1556 InsertMenuItemEx(m_hMenu, m_iPosition, (m_iPrice<=g_eClients[target][iCredits]?ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED), m_szId, "%t", "Item Available", g_eItems[i][szName], g_eItems[i][iPrice]);
1557 else if(!g_bInvMode[client])
1558 InsertMenuItemEx(m_hMenu, m_iPosition, (m_iPrice<=g_eClients[target][iCredits]?ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED), m_szId, "%t", "Item Plan Available", g_eItems[i][szName]);
1559 ++m_iPosition;
1560 }
1561 // This is a normal item
1562 else
1563 {
1564 IntToString(i, STRING(m_szId));
1565 if(Store_HasClientItem(target, i))
1566 {
1567 if(Store_IsEquipped(target, i))
1568 InsertMenuItemEx(m_hMenu, m_iPosition, ITEMDRAW_DEFAULT, m_szId, "%t", "Item Equipped", g_eItems[i][szName]);
1569 else
1570 InsertMenuItemEx(m_hMenu, m_iPosition, ITEMDRAW_DEFAULT, m_szId, "%t", "Item Bought", g_eItems[i][szName]);
1571 }
1572 else if(!g_bInvMode[client])
1573 {
1574 new m_iStyle = ITEMDRAW_DEFAULT;
1575 if((g_eItems[i][iPlans]==0 && g_eClients[target][iCredits]<m_iPrice) || (g_eCvars[g_cvarShowVIP][aCache] && !GetClientPrivilege(target, g_eItems[i][iFlagBits], m_iFlags)))
1576 m_iStyle = ITEMDRAW_DISABLED;
1577
1578 if(!g_eItems[i][bBuyable])
1579 continue;
1580
1581 if(g_eItems[i][iPlans]==0)
1582 AddMenuItemEx(m_hMenu, m_iStyle, m_szId, "%t", "Item Available", g_eItems[i][szName], g_eItems[i][iPrice]);
1583 else
1584 AddMenuItemEx(m_hMenu, m_iStyle, m_szId, "%t", "Item Plan Available", g_eItems[i][szName], g_eItems[i][iPrice]);
1585 }
1586 }
1587 }
1588 }
1589
1590 if(last == -1)
1591 DisplayMenu(m_hMenu, client, 0);
1592 else
1593 DisplayMenuAtItem(m_hMenu, client, (last/GetMenuPagination(m_hMenu))*GetMenuPagination(m_hMenu), 0);
1594}
1595
1596public MenuHandler_Store(Handle:menu, MenuAction:action, client, param2)
1597{
1598 if (action == MenuAction_End)
1599 CloseHandle(menu);
1600 else if (action == MenuAction_Select)
1601 {
1602 new target = g_iMenuClient[client];
1603 // Confirmation was given
1604 if(menu == INVALID_HANDLE)
1605 {
1606 if(param2 == 0)
1607 {
1608 g_iMenuBack[client]=1;
1609 new m_iPrice = 0;
1610 if(g_iSelectedPlan[client]==-1)
1611 m_iPrice = g_eItems[g_iSelectedItem[client]][iPrice];
1612 else
1613 m_iPrice = g_ePlans[g_iSelectedItem[client]][g_iSelectedPlan[client]][iPrice];
1614
1615 if(g_eClients[target][iCredits]>=m_iPrice && !Store_HasClientItem(target, g_iSelectedItem[client]))
1616 Store_BuyItem(target, g_iSelectedItem[client], g_iSelectedPlan[client]);
1617
1618 if(g_eItems[g_iSelectedItem[client]][iHandler] == g_iPackageHandler)
1619 DisplayStoreMenu(client, g_iSelectedItem[client]);
1620 else
1621 DisplayItemMenu(client, g_iSelectedItem[client]);
1622 }
1623 else if(param2 == 1)
1624 {
1625 Store_SellItem(target, g_iSelectedItem[client]);
1626 Store_DisplayPreviousMenu(client);
1627 }
1628 }
1629 else
1630 {
1631 new String:m_szId[64];
1632 GetMenuItem(menu, param2, STRING(m_szId));
1633
1634 g_iLastSelection[client]=param2;
1635
1636 // We are selling a package
1637 if(strcmp(m_szId, "sell_package")==0)
1638 {
1639 if(g_eCvars[g_cvarConfirmation][aCache])
1640 {
1641 decl String:m_szTitle[128];
1642 Format(STRING(m_szTitle), "%t", "Confirm_Sell", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType], RoundToFloor(g_eItems[g_iSelectedItem[client]][iPrice]*Float:g_eCvars[g_cvarSellRatio][aCache]));
1643 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 1);
1644 return;
1645 }
1646 else
1647 {
1648 Store_SellItem(target, g_iSelectedItem[client]);
1649 Store_DisplayPreviousMenu(client);
1650 }
1651 }
1652 // We are gifting a package
1653 else if(strcmp(m_szId, "gift_package")==0)
1654 {
1655 DisplayPlayerMenu(client);
1656 }
1657 // This is menu handler stuff
1658 else if(!(48 <= m_szId[0] <= 57))
1659 {
1660 decl ret;
1661 for(new i=0;i<g_iMenuHandlers;++i)
1662 {
1663 Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnHandler]);
1664 Call_PushCell(target);
1665 Call_PushString(m_szId);
1666 Call_PushCell(g_iSelectedItem[client]);
1667 Call_Finish(ret);
1668
1669 if(ret)
1670 break;
1671 }
1672 }
1673 // We are being boring
1674 else
1675 {
1676 new m_iId = StringToInt(m_szId);
1677 g_iMenuBack[client]=g_eItems[m_iId][iParent];
1678 g_iSelectedItem[client] = m_iId;
1679 g_iSelectedPlan[client] = -1;
1680
1681 if((g_eClients[target][iCredits]>=g_eItems[m_iId][iPrice] || g_eItems[m_iId][iPlans]>0 && g_eClients[target][iCredits]>=Store_GetLowestPrice(m_iId)) && !Store_HasClientItem(target, m_iId) && g_eItems[m_iId][iPrice] != -1) {
1682 if(g_eItems[m_iId][iPlans] > 0)
1683 {
1684 DisplayPlanMenu(client, m_iId);
1685 return;
1686 }
1687 else
1688 if(g_eCvars[g_cvarConfirmation][aCache])
1689 {
1690 decl String:m_szTitle[128];
1691 Format(STRING(m_szTitle), "%t", "Confirm_Buy", g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);
1692 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 0);
1693 return;
1694 }
1695 else
1696 Store_BuyItem(target, m_iId);
1697 }
1698
1699 if(g_eItems[m_iId][iHandler] != g_iPackageHandler)
1700 {
1701 if(Store_HasClientItem(target, m_iId))
1702 {
1703 if(g_eTypeHandlers[g_eItems[m_iId][iHandler]][bRaw])
1704 {
1705 Call_StartFunction(g_eTypeHandlers[g_eItems[m_iId][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[m_iId][iHandler]][fnUse]);
1706 Call_PushCell(target);
1707 Call_PushCell(m_iId);
1708 Call_Finish();
1709 }
1710 else
1711 DisplayItemMenu(client, m_iId);
1712 }
1713 else
1714 DisplayStoreMenu(client, g_iMenuBack[client]);
1715 }
1716 else
1717 {
1718 if(Store_HasClientItem(target, m_iId) || g_eItems[m_iId][iPrice] == -1)
1719 DisplayStoreMenu(client, m_iId);
1720 else
1721 DisplayStoreMenu(client, g_eItems[m_iId][iParent]);
1722 }
1723 }
1724 }
1725 }
1726 else if(action==MenuAction_Cancel)
1727 if (param2 == MenuCancel_ExitBack)
1728 Store_DisplayPreviousMenu(client);
1729}
1730
1731public DisplayItemMenu(client, itemid)
1732{
1733 g_iMenuNum[client] = 1;
1734 g_iMenuBack[client] = g_eItems[itemid][iParent];
1735 new target = g_iMenuClient[client];
1736
1737 new Handle:m_hMenu = CreateMenu(MenuHandler_Item);
1738 SetMenuExitBackButton(m_hMenu, true);
1739
1740 new bool:m_bEquipped = Store_IsEquipped(target, itemid);
1741 new String:m_szTitle[256];
1742 new idx = 0;
1743 if(m_bEquipped)
1744 idx = Format(STRING(m_szTitle), "%t\n%t", "Item Equipped", g_eItems[itemid][szName], "Title Credits", g_eClients[target][iCredits]);
1745 else
1746 idx = Format(STRING(m_szTitle), "%s\n%t", g_eItems[itemid][szName], "Title Credits", g_eClients[target][iCredits]);
1747
1748 new m_iExpiration = Store_GetExpiration(target, itemid);
1749 if(m_iExpiration != 0)
1750 {
1751 m_iExpiration = m_iExpiration-GetTime();
1752 new m_iDays = m_iExpiration/(24*60*60);
1753 new m_iHours = (m_iExpiration-m_iDays*24*60*60)/(60*60);
1754 Format(m_szTitle[idx-1], sizeof(m_szTitle)-idx-1, "\n%t", "Title Expiration", m_iDays, m_iHours);
1755 }
1756
1757 SetMenuTitle(m_hMenu, m_szTitle);
1758
1759 if(g_eTypeHandlers[g_eItems[itemid][iHandler]][bEquipable])
1760 if(!m_bEquipped)
1761 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "0", "%t", "Item Equip");
1762 else
1763 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "3", "%t", "Item Unequip");
1764 else
1765 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "0", "%t", "Item Use");
1766
1767 if(!Store_IsClientVIP(target) && !Store_IsItemInBoughtPackage(target, itemid))
1768 {
1769 new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, itemid)*Float:g_eCvars[g_cvarSellRatio][aCache]);
1770 if(m_iCredits!=0)
1771 {
1772 new uid = Store_GetClientItemId(client, itemid);
1773 if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
1774 {
1775 new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
1776 new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
1777 if(m_iLeft < 0)
1778 m_iLeft = 0;
1779 m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
1780 }
1781
1782 if(g_eCvars[g_cvarSellEnabled][aCache])
1783 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "1", "%t", "Item Sell", m_iCredits);
1784 if(g_eCvars[g_cvarGiftEnabled][aCache] == 1 || (g_eCvars[g_cvarGiftEnabled][aCache] == 2 && GetUserFlagBits(client) & g_eCvars[g_cvarAdminFlag][aCache]))
1785 AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "2", "%t", "Item Gift");
1786 }
1787 }
1788
1789 for(new i=0;i<g_iMenuHandlers;++i)
1790 {
1791 if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
1792 continue;
1793 Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnMenu]);
1794 Call_PushCellRef(m_hMenu);
1795 Call_PushCell(client);
1796 Call_PushCell(itemid);
1797 Call_Finish();
1798 }
1799
1800 DisplayMenu(m_hMenu, client, 0);
1801}
1802
1803public DisplayPlanMenu(client, itemid)
1804{
1805 g_iMenuNum[client] = 1;
1806 new target = g_iMenuClient[client];
1807
1808 new Handle:m_hMenu = CreateMenu(MenuHandler_Plan);
1809 SetMenuExitBackButton(m_hMenu, true);
1810
1811 SetMenuTitle(m_hMenu, "%s\n%t", g_eItems[itemid][szName], "Title Credits", g_eClients[target][iCredits]);
1812
1813 for(new i=0;i<g_eItems[itemid][iPlans];++i)
1814 {
1815 AddMenuItemEx(m_hMenu, (g_eClients[target][iCredits]>=g_ePlans[itemid][i][iPrice]?ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED), "", "%t", "Item Available", g_ePlans[itemid][i][szName], g_ePlans[itemid][i][iPrice]);
1816 }
1817
1818 DisplayMenu(m_hMenu, client, 0);
1819}
1820
1821public MenuHandler_Plan(Handle:menu, MenuAction:action, client, param2)
1822{
1823 if (action == MenuAction_End)
1824 CloseHandle(menu);
1825 else if (action == MenuAction_Select)
1826 {
1827 new target = g_iMenuClient[client];
1828 g_iSelectedPlan[client]=param2;
1829 g_iMenuNum[client]=5;
1830
1831 if(g_eCvars[g_cvarConfirmation][aCache])
1832 {
1833 decl String:m_szTitle[128];
1834 Format(STRING(m_szTitle), "%t", "Confirm_Buy", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType]);
1835 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 0);
1836 return;
1837 }
1838 else
1839 {
1840 Store_BuyItem(target, g_iSelectedItem[client], param2);
1841 DisplayItemMenu(client, g_iSelectedItem[client]);
1842 }
1843 }
1844 else if(action==MenuAction_Cancel)
1845 if (param2 == MenuCancel_ExitBack)
1846 Store_DisplayPreviousMenu(client);
1847}
1848
1849public MenuHandler_Item(Handle:menu, MenuAction:action, client, param2)
1850{
1851 if (action == MenuAction_End)
1852 CloseHandle(menu);
1853 else if (action == MenuAction_Select)
1854 {
1855 new target = g_iMenuClient[client];
1856 // Confirmation was sent
1857 if(menu == INVALID_HANDLE)
1858 {
1859 if(param2 == 0)
1860 {
1861 g_iMenuNum[client] = 1;
1862 Store_SellItem(target, g_iSelectedItem[client]);
1863 Store_DisplayPreviousMenu(client);
1864 }
1865 }
1866 else
1867 {
1868 decl String:m_szId[64];
1869 GetMenuItem(menu, param2, STRING(m_szId));
1870
1871 new m_iId = StringToInt(m_szId);
1872
1873 // Menu handlers
1874 if(!(48 <= m_szId[0] <= 57))
1875 {
1876 decl ret;
1877 for(new i=0;i<g_iMenuHandlers;++i)
1878 {
1879 if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
1880 continue;
1881 Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnHandler]);
1882 Call_PushCell(client);
1883 Call_PushString(m_szId);
1884 Call_PushCell(g_iSelectedItem[client]);
1885 Call_Finish(ret);
1886
1887 if(ret)
1888 break;
1889 }
1890 }
1891 // Player wants to equip this item
1892 else if(m_iId == 0)
1893 {
1894 new m_iRet = Store_UseItem(target, g_iSelectedItem[client]);
1895 if(GetClientMenu(client)==MenuSource_None && m_iRet == 0)
1896 DisplayItemMenu(client, g_iSelectedItem[client]);
1897 }
1898 // Player wants to sell this item
1899 else if(m_iId == 1)
1900 {
1901 if(g_eCvars[g_cvarConfirmation][aCache])
1902 {
1903 new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, g_iSelectedItem[client])*Float:g_eCvars[g_cvarSellRatio][aCache]);
1904 new uid = Store_GetClientItemId(client, g_iSelectedItem[client]);
1905 if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
1906 {
1907 new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
1908 new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
1909 if(m_iLeft < 0)
1910 m_iLeft = 0;
1911 m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
1912 }
1913
1914 decl String:m_szTitle[128];
1915 Format(STRING(m_szTitle), "%t", "Confirm_Sell", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType], m_iCredits);
1916 g_iMenuNum[client] = 2;
1917 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Item, 0);
1918 }
1919 else
1920 {
1921 Store_SellItem(target, g_iSelectedItem[client]);
1922 Store_DisplayPreviousMenu(client);
1923 }
1924 }
1925 // Player wants to gift this item
1926 else if(m_iId == 2)
1927 {
1928 g_iMenuNum[client] = 2;
1929 DisplayPlayerMenu(client);
1930 }
1931 // Player wants to unequip this item
1932 else if(m_iId == 3)
1933 {
1934 Store_UnequipItem(target, g_iSelectedItem[client]);
1935 DisplayItemMenu(client, g_iSelectedItem[client]);
1936 }
1937 }
1938 }
1939 else if(action==MenuAction_Cancel)
1940 if (param2 == MenuCancel_ExitBack)
1941 Store_DisplayPreviousMenu(client);
1942}
1943
1944public DisplayPlayerMenu(client)
1945{
1946 g_iMenuNum[client] = 3;
1947 new target = g_iMenuClient[client];
1948
1949 new m_iCount = 0;
1950 new Handle:m_hMenu = CreateMenu(MenuHandler_Gift);
1951 SetMenuExitBackButton(m_hMenu, true);
1952 SetMenuTitle(m_hMenu, "%t\n%t", "Title Gift", "Title Credits", g_eClients[client][iCredits]);
1953
1954 decl String:m_szID[11];
1955 decl m_iFlags;
1956 LoopIngamePlayers(i)
1957 {
1958 m_iFlags = GetUserFlagBits(i);
1959 if(!GetClientPrivilege(i, g_eItems[g_iSelectedItem[client]][iFlagBits], m_iFlags))
1960 continue;
1961 if(i != target && IsClientInGame(i) && !Store_HasClientItem(i, g_iSelectedItem[client]))
1962 {
1963 IntToString(g_eClients[i][iUserId], STRING(m_szID));
1964 AddMenuItem(m_hMenu, m_szID, g_eClients[i][szName]);
1965 ++m_iCount;
1966 }
1967 }
1968
1969 if(m_iCount == 0)
1970 {
1971 CloseHandle(m_hMenu);
1972 g_iMenuNum[client] = 1;
1973 DisplayItemMenu(client, g_iSelectedItem[client]);
1974 Chat(client, "%t", "Gift No Players");
1975 }
1976 else
1977 DisplayMenu(m_hMenu, client, 0);
1978}
1979
1980public MenuHandler_Gift(Handle:menu, MenuAction:action, client, param2)
1981{
1982 if (action == MenuAction_End)
1983 CloseHandle(menu);
1984 else if (action == MenuAction_Select)
1985 {
1986 decl m_iItem, m_iReceiver;
1987 new target = g_iMenuClient[client];
1988
1989 // Confirmation was given
1990 if(menu == INVALID_HANDLE)
1991 {
1992 m_iItem = Store_GetClientItemId(target, g_iSelectedItem[client]);
1993 m_iReceiver = GetClientOfUserId(param2);
1994 if(!m_iReceiver)
1995 {
1996 Chat(client, "%t", "Gift Player Left");
1997 return;
1998 }
1999 Store_GiftItem(target, m_iReceiver, m_iItem);
2000 g_iMenuNum[client] = 1;
2001 Store_DisplayPreviousMenu(client);
2002 }
2003 else
2004 {
2005 decl String:m_szId[11];
2006 GetMenuItem(menu, param2, STRING(m_szId));
2007
2008 new m_iId = StringToInt(m_szId);
2009 m_iReceiver = GetClientOfUserId(m_iId);
2010 if(!m_iReceiver)
2011 {
2012 Chat(client, "%t", "Gift Player Left");
2013 return;
2014 }
2015
2016 m_iItem = Store_GetClientItemId(target, g_iSelectedItem[client]);
2017
2018 if(g_eCvars[g_cvarConfirmation][aCache])
2019 {
2020 decl String:m_szTitle[128];
2021 Format(STRING(m_szTitle), "%t", "Confirm_Gift", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType], g_eClients[m_iReceiver][szName]);
2022 Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Gift, m_iId);
2023 return;
2024 }
2025 else
2026 Store_GiftItem(target, m_iReceiver, m_iItem);
2027 Store_DisplayPreviousMenu(client);
2028 }
2029 }
2030 else if(action==MenuAction_Cancel)
2031 if (param2 == MenuCancel_ExitBack)
2032 DisplayItemMenu(client, g_iSelectedItem[client]);
2033}
2034
2035public MenuHandler_Confirm(Handle:menu, MenuAction:action, client, param2)
2036{
2037 if (action == MenuAction_End)
2038 CloseHandle(menu);
2039 else if (action == MenuAction_Select)
2040 {
2041 if(param2 == 0)
2042 {
2043 decl String:m_szCallback[32];
2044 decl String:m_szData[11];
2045 GetMenuItem(menu, 0, STRING(m_szCallback));
2046 GetMenuItem(menu, 1, STRING(m_szData));
2047 new m_iPos = FindCharInString(m_szCallback, '.');
2048 m_szCallback[m_iPos] = 0;
2049 new Handle:m_hPlugin = Handle:StringToInt(m_szCallback);
2050 new Function:fnMenuCallback = Function:StringToInt(m_szCallback[m_iPos+1]);
2051 if(fnMenuCallback != INVALID_FUNCTION)
2052 {
2053 Call_StartFunction(m_hPlugin, fnMenuCallback);
2054 Call_PushCell(INVALID_HANDLE);
2055 Call_PushCell(MenuAction_Select);
2056 Call_PushCell(client);
2057 Call_PushCell(StringToInt(m_szData));
2058 Call_Finish();
2059 }
2060 else
2061 Store_DisplayPreviousMenu(client);
2062 }
2063 else
2064 {
2065 Store_DisplayPreviousMenu(client);
2066 }
2067 }
2068}
2069
2070//////////////////////////////
2071// CONVARS //
2072//////////////////////////////
2073
2074public ConVar_CreditTimer(index)
2075{
2076 new m_bTimer = (FloatCompare(g_eCvars[g_cvarCreditTimer][aCache], 0.0)==0 || g_eCvars[g_cvarCreditAmountActive][aCache]==0);
2077 for(new i=1;i<=MaxClients;++i)
2078 {
2079 ClearTimer(g_eClients[i][hCreditTimer]);
2080 if(m_bTimer && IsClientInGame(i))
2081 g_eClients[i][hCreditTimer] = Store_CreditTimer(i);
2082 }
2083}
2084
2085//////////////////////////////
2086// TIMERS //
2087//////////////////////////////
2088
2089public GetMultipliedCredits(client, amount)
2090{
2091 new flags = GetUserFlagBits(client);
2092 new size = GetArraySize(g_hCustomCredits);
2093 new Float:multiplier = 1.0;
2094 for(new i=0;i<size;++i)
2095 {
2096 if(GetClientPrivilege(client, GetArrayCell(g_hCustomCredits, i, 0), flags))
2097 {
2098 new Float:mul = GetArrayCell(g_hCustomCredits, i, 1);
2099
2100 if(multiplier < mul)
2101 multiplier = mul;
2102 }
2103 }
2104
2105 return RoundFloat(amount * multiplier);
2106}
2107
2108public Action:Timer_CreditTimer(Handle:timer, any:userid)
2109{
2110 new client = GetClientOfUserId(userid);
2111 if(!client || !IsClientInGame(client))
2112 return Plugin_Continue;
2113
2114 decl m_iCredits;
2115 new team = GetClientTeam(client);
2116 if(2<=team<=3)
2117 m_iCredits = g_eCvars[g_cvarCreditAmountActive][aCache];
2118 else
2119 m_iCredits = g_eCvars[g_cvarCreditAmountInactive][aCache];
2120
2121 m_iCredits = GetMultipliedCredits(client, m_iCredits);
2122
2123 if(m_iCredits)
2124 {
2125 g_eClients[client][iCredits] += m_iCredits;
2126 if(g_eCvars[g_cvarCreditMessages][aCache])
2127 Chat(client, "%t", "Credits Earned For Playing", m_iCredits);
2128 Store_LogMessage(client, m_iCredits, "Earned for playing");
2129 }
2130
2131 return Plugin_Continue;
2132}
2133
2134public Action:Timer_DatabaseTimeout(Handle:timer, any:userid)
2135{
2136 // Database is connected successfully
2137 if(g_hDatabase != INVALID_HANDLE)
2138 return Plugin_Stop;
2139
2140 if(g_iDatabaseRetries < g_eCvars[g_cvarDatabaseRetries][aCache])
2141 {
2142 SQL_TConnect(SQLCallback_Connect, g_eCvars[g_cvarDatabaseEntry][sCache]);
2143 CreateTimer(Float:g_eCvars[g_cvarDatabaseTimeout][aCache], Timer_DatabaseTimeout);
2144 ++g_iDatabaseRetries;
2145 }
2146 else
2147 {
2148 SetFailState("Database connection failed to initialize after %d retrie(s)", g_eCvars[g_cvarDatabaseRetries][aCache]);
2149 }
2150
2151
2152 return Plugin_Stop;
2153}
2154
2155//////////////////////////////
2156// SQL CALLBACKS //
2157//////////////////////////////
2158
2159public SQLCallback_Connect(Handle:owner, Handle:hndl, const String:error[], any:data)
2160{
2161 if(hndl==INVALID_HANDLE)
2162 {
2163 SetFailState("Failed to connect to SQL database. Error: %s", error);
2164 }
2165 else
2166 {
2167 // If it's already connected we are good to go
2168 if(g_hDatabase != INVALID_HANDLE)
2169 return;
2170
2171 g_hDatabase = hndl;
2172 decl String:m_szDriver[2];
2173 SQL_ReadDriver(g_hDatabase, STRING(m_szDriver));
2174 if(m_szDriver[0] == 'm')
2175 {
2176 g_bMySQL = true;
2177 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_players` (\
2178 `id` int(11) NOT NULL AUTO_INCREMENT,\
2179 `authid` varchar(32) NOT NULL,\
2180 `name` varchar(64) NOT NULL,\
2181 `credits` int(11) NOT NULL,\
2182 `date_of_join` int(11) NOT NULL,\
2183 `date_of_last_join` int(11) NOT NULL,\
2184 PRIMARY KEY (`id`),\
2185 UNIQUE KEY `id` (`id`),\
2186 UNIQUE KEY `authid` (`authid`)\
2187 )");
2188 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_items` (\
2189 `id` int(11) NOT NULL AUTO_INCREMENT,\
2190 `player_id` int(11) NOT NULL,\
2191 `type` varchar(16) NOT NULL,\
2192 `unique_id` varchar(256) NOT NULL,\
2193 `date_of_purchase` int(11) NOT NULL,\
2194 `date_of_expiration` int(11) NOT NULL,\
2195 PRIMARY KEY (`id`)\
2196 )");
2197 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_equipment` (\
2198 `player_id` int(11) NOT NULL,\
2199 `type` varchar(16) NOT NULL,\
2200 `unique_id` varchar(256) NOT NULL,\
2201 `slot` int(11) NOT NULL\
2202 )");
2203 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_logs` (\
2204 `id` int(11) NOT NULL AUTO_INCREMENT,\
2205 `player_id` int(11) NOT NULL,\
2206 `credits` int(11) NOT NULL,\
2207 `reason` varchar(256) NOT NULL,\
2208 `date` int(11) NOT NULL,\
2209 PRIMARY KEY (`id`)\
2210 )");
2211 SQL_TQuery(g_hDatabase, SQLCallback_NoError, "ALTER TABLE store_items ADD COLUMN price_of_purchase int(11)");
2212 decl String:m_szQuery[512];
2213 Format(STRING(m_szQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
2214 `id` int(11) NOT NULL AUTO_INCREMENT,\
2215 `parent_id` int(11) NOT NULL DEFAULT '-1',\
2216 `item_price` int(32) NOT NULL,\
2217 `item_type` varchar(64) NOT NULL,\
2218 `item_flag` varchar(64) NOT NULL,\
2219 `item_name` varchar(64) NOT NULL,\
2220 `additional_info` text NOT NULL,\
2221 `item_status` tinyint(1) NOT NULL,\
2222 `supported_game` varchar(64) NOT NULL,\
2223 PRIMARY KEY (`id`)\
2224 )", g_eCvars[g_cvarItemsTable][sCache]);
2225 SQL_TVoid(g_hDatabase, m_szQuery);
2226 }
2227 else
2228 {
2229 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_players` (\
2230 `id` INTEGER PRIMARY KEY AUTOINCREMENT,\
2231 `authid` varchar(32) NOT NULL,\
2232 `name` varchar(64) NOT NULL,\
2233 `credits` int(11) NOT NULL,\
2234 `date_of_join` int(11) NOT NULL,\
2235 `date_of_last_join` int(11) NOT NULL\
2236 )");
2237 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_items` (\
2238 `id` INTEGER PRIMARY KEY AUTOINCREMENT,\
2239 `player_id` int(11) NOT NULL,\
2240 `type` varchar(16) NOT NULL,\
2241 `unique_id` varchar(256) NOT NULL,\
2242 `date_of_purchase` int(11) NOT NULL,\
2243 `date_of_expiration` int(11) NOT NULL\
2244 )");
2245 SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_equipment` (\
2246 `player_id` int(11) NOT NULL,\
2247 `type` varchar(16) NOT NULL,\
2248 `unique_id` varchar(256) NOT NULL,\
2249 `slot` int(11) NOT NULL\
2250 )");
2251 SQL_TQuery(g_hDatabase, SQLCallback_NoError, "ALTER TABLE store_items ADD COLUMN price_of_purchase int(11)");
2252 if(strcmp(g_eCvars[g_cvarItemSource][sCache], "database")==0)
2253 {
2254
2255 SetFailState("Database item source can only be used with MySQL databases");
2256 }
2257 }
2258
2259 // Do some housekeeping
2260 decl String:m_szQuery[256];
2261 Format(STRING(m_szQuery), "DELETE FROM store_items WHERE `date_of_expiration` <> 0 AND `date_of_expiration` < %d", GetTime());
2262 SQL_TVoid(g_hDatabase, m_szQuery);
2263 }
2264}
2265
2266public SQLCallback_LoadClientInventory_Credits(Handle:owner, Handle:hndl, const String:error[], any:userid)
2267{
2268 if(hndl==INVALID_HANDLE)
2269 LogError("Error happened. Error: %s", error);
2270 else
2271 {
2272 new client = GetClientOfUserId(userid);
2273 if(!client)
2274 return;
2275
2276 decl String:m_szQuery[256];
2277 decl String:m_szSteamID[32];
2278 new m_iTime = GetTime();
2279 g_eClients[client][iUserId] = userid;
2280 g_eClients[client][iItems] = -1;
2281 GetLegacyAuthString(client, STRING(m_szSteamID), false);
2282 strcopy(g_eClients[client][szAuthId], 32, m_szSteamID[8]);
2283 GetClientName(client, g_eClients[client][szName], 64);
2284 SQL_EscapeString(g_hDatabase, g_eClients[client][szName], g_eClients[client][szNameEscaped], 128);
2285
2286 if(SQL_FetchRow(hndl))
2287 {
2288 g_eClients[client][iId] = SQL_FetchInt(hndl, 0);
2289 g_eClients[client][iCredits] = SQL_FetchInt(hndl, 3);
2290 g_eClients[client][iOriginalCredits] = SQL_FetchInt(hndl, 3);
2291 g_eClients[client][iDateOfJoin] = SQL_FetchInt(hndl, 4);
2292 g_eClients[client][iDateOfLastJoin] = m_iTime;
2293
2294 Format(STRING(m_szQuery), "SELECT * FROM store_items WHERE `player_id`=%d", g_eClients[client][iId]);
2295 SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Items, m_szQuery, userid);
2296
2297 Store_LogMessage(client, g_eClients[client][iCredits], "Amount of credits when the player joined");
2298
2299 Store_SaveClientData(client);
2300 }
2301 else
2302 {
2303 Format(STRING(m_szQuery), "INSERT INTO store_players (`authid`, `name`, `credits`, `date_of_join`, `date_of_last_join`) VALUES(\"%s\", '%s', %d, %d, %d)",
2304 g_eClients[client][szAuthId], g_eClients[client][szNameEscaped], g_eCvars[g_cvarStartCredits][aCache], m_iTime, m_iTime);
2305 SQL_TQuery(g_hDatabase, SQLCallback_InsertClient, m_szQuery, userid);
2306 g_eClients[client][iCredits] = g_eCvars[g_cvarStartCredits][aCache];
2307 g_eClients[client][iOriginalCredits] = g_eCvars[g_cvarStartCredits][aCache];
2308 g_eClients[client][iDateOfJoin] = m_iTime;
2309 g_eClients[client][iDateOfLastJoin] = m_iTime;
2310 g_eClients[client][bLoaded] = true;
2311 g_eClients[client][iItems] = 0;
2312
2313 if(g_eCvars[g_cvarStartCredits][aCache] > 0)
2314 Store_LogMessage(client, g_eCvars[g_cvarStartCredits][aCache], "Start credits");
2315 }
2316
2317 g_eClients[client][hCreditTimer] = Store_CreditTimer(client);
2318 }
2319}
2320
2321public SQLCallback_LoadClientInventory_Items(Handle:owner, Handle:hndl, const String:error[], any:userid)
2322{
2323 if(hndl==INVALID_HANDLE)
2324 LogError("Error happened. Error: %s", error);
2325 else
2326 {
2327 new client = GetClientOfUserId(userid);
2328 if(!client)
2329 return;
2330
2331 decl String:m_szQuery[256];
2332 Format(STRING(m_szQuery), "SELECT * FROM store_equipment WHERE `player_id`=%d", g_eClients[client][iId]);
2333 SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Equipment, m_szQuery, userid);
2334
2335 if(!SQL_GetRowCount(hndl))
2336 {
2337 g_eClients[client][bLoaded] = true;
2338 g_eClients[client][iItems] = 0;
2339 return;
2340 }
2341
2342 decl String:m_szUniqueId[PLATFORM_MAX_PATH];
2343 decl String:m_szType[16];
2344 decl m_iExpiration;
2345 decl m_iUniqueId;
2346 new m_iTime = GetTime();
2347
2348 new i = 0;
2349 while(SQL_FetchRow(hndl))
2350 {
2351 m_iUniqueId = -1;
2352 m_iExpiration = SQL_FetchInt(hndl, 5);
2353 if(m_iExpiration && m_iExpiration<=m_iTime)
2354 continue;
2355
2356 SQL_FetchString(hndl, 2, STRING(m_szType));
2357 SQL_FetchString(hndl, 3, STRING(m_szUniqueId));
2358 while((m_iUniqueId = Store_GetItemId(m_szType, m_szUniqueId, m_iUniqueId))!=-1)
2359 {
2360 g_eClientItems[client][i][iId] = SQL_FetchInt(hndl, 0);
2361 g_eClientItems[client][i][iUniqueId] = m_iUniqueId;
2362 g_eClientItems[client][i][bSynced] = true;
2363 g_eClientItems[client][i][bDeleted] = false;
2364 g_eClientItems[client][i][iDateOfPurchase] = SQL_FetchInt(hndl, 4);
2365 g_eClientItems[client][i][iDateOfExpiration] = m_iExpiration;
2366 g_eClientItems[client][i][iPriceOfPurchase] = SQL_FetchInt(hndl, 6);
2367
2368 ++i;
2369 }
2370 }
2371 g_eClients[client][iItems] = i;
2372 }
2373}
2374
2375public SQLCallback_LoadClientInventory_Equipment(Handle:owner, Handle:hndl, const String:error[], any:userid)
2376{
2377 if(hndl==INVALID_HANDLE)
2378 LogError("Error happened. Error: %s", error);
2379 else
2380 {
2381 new client = GetClientOfUserId(userid);
2382 if(!client)
2383 return;
2384
2385 decl String:m_szUniqueId[PLATFORM_MAX_PATH];
2386 decl String:m_szType[16];
2387 decl m_iUniqueId;
2388
2389 while(SQL_FetchRow(hndl))
2390 {
2391 SQL_FetchString(hndl, 1, STRING(m_szType));
2392 SQL_FetchString(hndl, 2, STRING(m_szUniqueId));
2393 m_iUniqueId = Store_GetItemId(m_szType, m_szUniqueId);
2394 if(m_iUniqueId == -1)
2395 continue;
2396
2397 if(!Store_HasClientItem(client, m_iUniqueId))
2398 Store_UnequipItem(client, m_iUniqueId);
2399 else
2400 Store_UseItem(client, m_iUniqueId, true, SQL_FetchInt(hndl, 3));
2401 }
2402 g_eClients[client][bLoaded] = true;
2403 }
2404}
2405
2406public SQLCallback_RefreshCredits(Handle:owner, Handle:hndl, const String:error[], any:userid)
2407{
2408 if(hndl==INVALID_HANDLE)
2409 LogError("Error happened. Error: %s", error);
2410 else
2411 {
2412 new client = GetClientOfUserId(userid);
2413 if(!client)
2414 return;
2415
2416 if(SQL_FetchRow(hndl))
2417 {
2418 g_eClients[client][iCredits] = SQL_FetchInt(hndl, 3);
2419 g_eClients[client][iOriginalCredits] = SQL_FetchInt(hndl, 3);
2420 }
2421 }
2422}
2423
2424public SQLCallback_InsertClient(Handle:owner, Handle:hndl, const String:error[], any:userid)
2425{
2426 if(hndl==INVALID_HANDLE)
2427 LogError("Error happened. Error: %s", error);
2428 else
2429 {
2430 new client = GetClientOfUserId(userid);
2431 if(!client)
2432 return;
2433
2434 g_eClients[client][iId] = SQL_GetInsertId(hndl);
2435 }
2436}
2437
2438public SQLCallback_ReloadConfig(Handle:owner, Handle:hndl, const String:error[], any:userid)
2439{
2440 if(hndl==INVALID_HANDLE)
2441 {
2442 SetFailState("Error happened reading the config table. The plugin cannot continue.", error);
2443 }
2444 else
2445 {
2446 decl String:m_szType[64];
2447 decl String:m_szFlag[64];
2448 decl String:m_szInfo[2048];
2449 decl String:m_szKey[64];
2450 decl String:m_szValue[256];
2451
2452 decl Handle:m_hKV;
2453
2454 decl bool:m_bSuccess;
2455
2456 decl m_iLength;
2457 decl m_iHandler;
2458 new m_iIndex = 0;
2459
2460 while(SQL_FetchRow(hndl))
2461 {
2462 if(g_iItems == STORE_MAX_ITEMS)
2463 return;
2464
2465 if(!SQL_FetchInt(hndl, 7))
2466 continue;
2467
2468 g_eItems[g_iItems][iId] = SQL_FetchInt(hndl, 0);
2469 g_eItems[g_iItems][iParent] = SQL_FetchInt(hndl, 1);
2470 g_eItems[g_iItems][iPrice] = SQL_FetchInt(hndl, 2);
2471
2472 IntToString(g_eItems[g_iItems][iId], g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);
2473
2474 SQL_FetchString(hndl, 3, STRING(m_szType));
2475 m_iHandler = Store_GetTypeHandler(m_szType);
2476 if(m_iHandler == -1)
2477 continue;
2478
2479 g_eItems[g_iItems][iHandler] = m_iHandler;
2480
2481 SQL_FetchString(hndl, 4, STRING(m_szFlag));
2482 g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlag);
2483
2484 SQL_FetchString(hndl, 5, g_eItems[g_iItems][szName], ITEM_NAME_LENGTH);
2485 SQL_FetchString(hndl, 6, STRING(m_szInfo));
2486
2487 m_hKV = CreateKeyValues("Additional Info");
2488
2489 m_iLength = strlen(m_szInfo);
2490 while(m_iIndex != m_iLength)
2491 {
2492 m_iIndex += strcopy(m_szKey, StrContains(m_szInfo[m_iIndex], "="), m_szInfo[m_iIndex])+2;
2493 m_iIndex += strcopy(m_szValue, StrContains(m_szInfo[m_iIndex], "\";"), m_szInfo[m_iIndex])+2; // \"
2494
2495 KvJumpToKey(m_hKV, m_szKey, true);
2496 KvSetString(m_hKV, m_szKey, m_szValue);
2497
2498 m_bSuccess = true;
2499 if(g_eTypeHandlers[m_iHandler][fnConfig]!=INVALID_FUNCTION)
2500 {
2501 Call_StartFunction(g_eTypeHandlers[m_iHandler][hPlugin], g_eTypeHandlers[m_iHandler][fnConfig]);
2502 Call_PushCellRef(m_hKV);
2503 Call_PushCell(g_iItems);
2504 Call_Finish(m_bSuccess);
2505 }
2506
2507 if(m_bSuccess)
2508 ++g_iItems;
2509 }
2510 CloseHandle(m_hKV);
2511 }
2512 }
2513}
2514
2515public SQLCallback_ResetPlayer(Handle:owner, Handle:hndl, const String:error[], any:userid)
2516{
2517 if(hndl==INVALID_HANDLE)
2518 LogError("Error happened. Error: %s", error);
2519 else
2520 {
2521 new client = GetClientOfUserId(userid);
2522
2523 if(SQL_GetRowCount(hndl))
2524 {
2525 SQL_FetchRow(hndl);
2526 new id = SQL_FetchInt(hndl, 0);
2527 decl String:m_szAuthId[32];
2528 SQL_FetchString(hndl, 1, STRING(m_szAuthId));
2529
2530 decl String:m_szQuery[512];
2531 Format(STRING(m_szQuery), "DELETE FROM store_players WHERE id=%d", id);
2532 SQL_TVoid(g_hDatabase, m_szQuery);
2533 Format(STRING(m_szQuery), "DELETE FROM store_items WHERE player_id=%d", id);
2534 SQL_TVoid(g_hDatabase, m_szQuery);
2535 Format(STRING(m_szQuery), "DELETE FROM store_equipment WHERE player_id=%d", id);
2536 SQL_TVoid(g_hDatabase, m_szQuery);
2537
2538 ChatAll("%t", "Player Resetted", m_szAuthId);
2539
2540 }
2541 else
2542 if(client)
2543 Chat(client, "%t", "Credit No Match");
2544 }
2545}
2546
2547//////////////////////////////
2548// STOCKS //
2549//////////////////////////////
2550
2551public Store_LoadClientInventory(client)
2552{
2553 if(g_hDatabase == INVALID_HANDLE)
2554 {
2555 LogError("Database connection is lost or not yet initialized.");
2556 return;
2557 }
2558
2559 decl String:m_szQuery[256];
2560 decl String:m_szAuthId[32];
2561
2562 GetLegacyAuthString(client, STRING(m_szAuthId));
2563 if(m_szAuthId[0] == 0)
2564 return;
2565
2566 Format(STRING(m_szQuery), "SELECT * FROM store_players WHERE `authid`=\"%s\"", m_szAuthId[8]);
2567
2568 SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Credits, m_szQuery, g_eClients[client][iUserId]);
2569}
2570
2571public Store_SaveClientInventory(client)
2572{
2573 if(g_hDatabase == INVALID_HANDLE)
2574 {
2575 LogError("Database connection is lost or not yet initialized.");
2576 return;
2577 }
2578
2579 // Player disconnected before his inventory was even fetched
2580 if(g_eClients[client][iCredits]==-1 && g_eClients[client][iItems]==-1)
2581 return;
2582
2583 decl String:m_szQuery[256];
2584 decl String:m_szType[16];
2585 decl String:m_szUniqueId[PLATFORM_MAX_PATH];
2586
2587 for(new i=0;i<g_eClients[client][iItems];++i)
2588 {
2589 strcopy(STRING(m_szType), g_eTypeHandlers[g_eItems[g_eClientItems[client][i][iUniqueId]][iHandler]][szType]);
2590 strcopy(STRING(m_szUniqueId), g_eItems[g_eClientItems[client][i][iUniqueId]][szUniqueId]);
2591
2592 if(!g_eClientItems[client][i][bSynced] && !g_eClientItems[client][i][bDeleted])
2593 {
2594 g_eClientItems[client][i][bSynced] = true;
2595 Format(STRING(m_szQuery), "INSERT INTO store_items (`player_id`, `type`, `unique_id`, `date_of_purchase`, `date_of_expiration`, `price_of_purchase`) VALUES(%d, \"%s\", \"%s\", %d, %d, %d)", g_eClients[client][iId], m_szType, m_szUniqueId, g_eClientItems[client][i][iDateOfPurchase], g_eClientItems[client][i][iDateOfExpiration], g_eClientItems[client][i][iPriceOfPurchase]);
2596 SQL_TVoid(g_hDatabase, m_szQuery);
2597 } else if(g_eClientItems[client][i][bSynced] && g_eClientItems[client][i][bDeleted])
2598 {
2599 // Might have been synced already but ID wasn't acquired
2600 if(g_eClientItems[client][i][iId]==-1)
2601 Format(STRING(m_szQuery), "DELETE FROM store_items WHERE `player_id`=%d AND `type`=\"%s\" AND `unique_id`=\"%s\"", g_eClients[client][iId], m_szType, m_szUniqueId);
2602 else
2603 Format(STRING(m_szQuery), "DELETE FROM store_items WHERE `id`=%d", g_eClientItems[client][i][iId]);
2604 SQL_TVoid(g_hDatabase, m_szQuery);
2605 }
2606 }
2607}
2608
2609public Store_SaveClientEquipment(client)
2610{
2611 decl String:m_szQuery[256];
2612 decl m_iId;
2613 for(new i=0;i<STORE_MAX_HANDLERS;++i)
2614 {
2615 for(new a=0;a<STORE_MAX_SLOTS;++a)
2616 {
2617 m_iId = i*STORE_MAX_SLOTS+a;
2618 if(g_eClients[client][aEquipmentSynced][m_iId] == g_eClients[client][aEquipment][m_iId])
2619 continue;
2620 else if(g_eClients[client][aEquipmentSynced][m_iId] != -2)
2621 if(g_eClients[client][aEquipment][m_iId]==-1)
2622 Format(STRING(m_szQuery), "DELETE FROM store_equipment WHERE `player_id`=%d AND `type`=\"%s\" AND `slot`=%d", g_eClients[client][iId], g_eTypeHandlers[i][szType], a);
2623 else
2624 Format(STRING(m_szQuery), "UPDATE store_equipment SET `unique_id`=\"%s\" WHERE `player_id`=%d AND `type`=\"%s\" AND `slot`=%d", g_eItems[g_eClients[client][aEquipment][m_iId]][szUniqueId], g_eClients[client][iId], g_eTypeHandlers[i][szType], a);
2625
2626 else
2627 Format(STRING(m_szQuery), "INSERT INTO store_equipment (`player_id`, `type`, `unique_id`, `slot`) VALUES(%d, \"%s\", \"%s\", %d)", g_eClients[client][iId], g_eTypeHandlers[i][szType], g_eItems[g_eClients[client][aEquipment][m_iId]][szUniqueId], a);
2628
2629 SQL_TVoid(g_hDatabase, m_szQuery);
2630 g_eClients[client][aEquipmentSynced][m_iId] = g_eClients[client][aEquipment][m_iId];
2631 }
2632 }
2633}
2634
2635public Store_SaveClientData(client)
2636{
2637 if(g_hDatabase == INVALID_HANDLE)
2638 {
2639 LogError("Database connection is lost or not yet initialized.");
2640 return;
2641 }
2642
2643 if((g_eClients[client][iCredits]==-1 && g_eClients[client][iItems]==-1) || !g_eClients[client][bLoaded])
2644 return;
2645
2646 decl String:m_szQuery[256];
2647 if(g_bMySQL)
2648 Format(STRING(m_szQuery), "UPDATE store_players SET `credits`=GREATEST(`credits`+%d,0), `date_of_last_join`=%d, `name`='%s' WHERE `id`=%d", g_eClients[client][iCredits]-g_eClients[client][iOriginalCredits], g_eClients[client][iDateOfLastJoin], g_eClients[client][szNameEscaped], g_eClients[client][iId]);
2649 else
2650 Format(STRING(m_szQuery), "UPDATE store_players SET `credits`=MAX(`credits`+%d,0), `date_of_last_join`=%d, `name`='%s' WHERE `id`=%d", g_eClients[client][iCredits]-g_eClients[client][iOriginalCredits], g_eClients[client][iDateOfLastJoin], g_eClients[client][szNameEscaped], g_eClients[client][iId]);
2651
2652 g_eClients[client][iOriginalCredits] = g_eClients[client][iCredits];
2653
2654 SQL_TVoid(g_hDatabase, m_szQuery);
2655}
2656
2657public Store_DisconnectClient(client)
2658{
2659 Store_LogMessage(client, g_eClients[client][iCredits], "Amount of credits when the player left");
2660 g_eClients[client][iCredits] = -1;
2661 g_eClients[client][iOriginalCredits] = -1;
2662 g_eClients[client][iItems] = -1;
2663 g_eClients[client][bLoaded] = false;
2664 ClearTimer(g_eClients[client][hCreditTimer]);
2665}
2666
2667Store_GetItemId(String:type[], String:uid[], start=-1)
2668{
2669 for(new i=start+1;i<g_iItems;++i)
2670 if(strcmp(g_eTypeHandlers[g_eItems[i][iHandler]][szType], type)==0 && strcmp(g_eItems[i][szUniqueId], uid)==0 && g_eItems[i][iPrice] >= 0)
2671 return i;
2672 return -1;
2673}
2674
2675Store_BuyItem(client, itemid, plan=-1)
2676{
2677 if(Store_HasClientItem(client, itemid))
2678 return;
2679
2680 new m_iPrice = 0;
2681 if(plan==-1)
2682 m_iPrice = g_eItems[itemid][iPrice];
2683 else
2684 m_iPrice = g_ePlans[itemid][plan][iPrice];
2685
2686 if(g_eClients[client][iCredits]<m_iPrice)
2687 return;
2688
2689 new m_iId = g_eClients[client][iItems]++;
2690 g_eClientItems[client][m_iId][iId] = -1;
2691 g_eClientItems[client][m_iId][iUniqueId] = itemid;
2692 g_eClientItems[client][m_iId][iDateOfPurchase] = GetTime();
2693 g_eClientItems[client][m_iId][iDateOfExpiration] = (plan==-1?0:(g_ePlans[itemid][plan][iTime]?GetTime()+g_ePlans[itemid][plan][iTime]:0));
2694 g_eClientItems[client][m_iId][iPriceOfPurchase] = m_iPrice;
2695 g_eClientItems[client][m_iId][bSynced] = false;
2696 g_eClientItems[client][m_iId][bDeleted] = false;
2697
2698 g_eClients[client][iCredits] -= m_iPrice;
2699
2700 Store_LogMessage(client, -g_eItems[itemid][iPrice], "Bought a %s %s", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
2701
2702 Chat(client, "%t", "Chat Bought Item", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
2703}
2704
2705public Store_SellItem(client, itemid)
2706{
2707 new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, itemid)*Float:g_eCvars[g_cvarSellRatio][aCache]);
2708 new uid = Store_GetClientItemId(client, itemid);
2709 if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
2710 {
2711 new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
2712 new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
2713 if(m_iLeft<0)
2714 m_iLeft = 0;
2715 m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
2716 }
2717
2718 g_eClients[client][iCredits] += m_iCredits;
2719 Chat(client, "%t", "Chat Sold Item", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
2720
2721 Store_LogMessage(client, m_iCredits, "Sold a %s %s", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
2722
2723 Store_RemoveItem(client, itemid);
2724}
2725
2726public Store_GiftItem(client, receiver, item)
2727{
2728 new m_iId = g_eClientItems[client][item][iUniqueId];
2729 new target = g_iMenuClient[client];
2730 g_eClientItems[client][item][bDeleted] = true;
2731 Store_UnequipItem(client, m_iId);
2732
2733 g_eClientItems[receiver][g_eClients[receiver][iItems]][iId] = -1;
2734 g_eClientItems[receiver][g_eClients[receiver][iItems]][iUniqueId] = m_iId;
2735 g_eClientItems[receiver][g_eClients[receiver][iItems]][bSynced] = false;
2736 g_eClientItems[receiver][g_eClients[receiver][iItems]][bDeleted] = false;
2737 g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfPurchase] = g_eClientItems[target][item][iDateOfPurchase];
2738 g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfExpiration] = g_eClientItems[target][item][iDateOfExpiration];
2739 g_eClientItems[receiver][g_eClients[receiver][iItems]][iPriceOfPurchase] = g_eClientItems[target][item][iPriceOfPurchase];
2740
2741 ++g_eClients[receiver][iItems];
2742
2743 Chat(client, "%t", "Chat Gift Item Sent", g_eClients[receiver][szName], g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);
2744 Chat(receiver, "%t", "Chat Gift Item Received", g_eClients[target][szName], g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);
2745
2746 Store_LogMessage(client, 0, "Gifted a %s to %N", g_eItems[m_iId][szName], receiver);
2747}
2748
2749public Store_GetClientItemId(client, itemid)
2750{
2751 for(new i=0;i<g_eClients[client][iItems];++i)
2752 {
2753 if(g_eClientItems[client][i][iUniqueId] == itemid && !g_eClientItems[client][i][bDeleted])
2754 return i;
2755 }
2756
2757 return -1;
2758}
2759
2760public Handle:Store_CreditTimer(client)
2761{
2762 return CreateTimer(g_eCvars[g_cvarCreditTimer][aCache], Timer_CreditTimer, g_eClients[client][iUserId], TIMER_REPEAT);
2763}
2764
2765public ReadCoreCFG()
2766{
2767 new String:m_szFile[PLATFORM_MAX_PATH];
2768 BuildPath(Path_SM, STRING(m_szFile), "configs/core.cfg");
2769
2770 new Handle:hParser = SMC_CreateParser();
2771 new String:error[128];
2772 new line = 0;
2773 new col = 0;
2774
2775 SMC_SetReaders(hParser, Config_NewSection, Config_KeyValue, Config_EndSection);
2776 SMC_SetParseEnd(hParser, Config_End);
2777
2778 new SMCError:result = SMC_ParseFile(hParser, m_szFile, line, col);
2779 CloseHandle(hParser);
2780
2781 if (result != SMCError_Okay)
2782 {
2783 SMC_GetErrorString(result, error, sizeof(error));
2784 LogError("%s on line %d, col %d of %s", error, line, col, m_szFile);
2785 }
2786
2787}
2788
2789public SMCResult:Config_NewSection(Handle:parser, const String:section[], bool:quotes)
2790{
2791 if (StrEqual(section, "Core"))
2792 {
2793 return SMCParse_Continue;
2794 }
2795 return SMCParse_Continue;
2796}
2797
2798public SMCResult:Config_KeyValue(Handle:parser, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes)
2799{
2800 if(StrEqual(key, "PublicChatTrigger", false))
2801 PublicChatTrigger = value[0];
2802 else if(StrEqual(key, "SilentChatTrigger", false))
2803 SilentChatTrigger = value[0];
2804
2805 return SMCParse_Continue;
2806}
2807
2808public SMCResult:Config_EndSection(Handle:parser)
2809{
2810 return SMCParse_Continue;
2811}
2812
2813public Config_End(Handle:parser, bool:halted, bool:failed)
2814{
2815}
2816
2817public Store_ReloadConfig()
2818{
2819 g_iItems = 0;
2820
2821 for(new i=0;i<g_iTypeHandlers;++i)
2822 {
2823 if(g_eTypeHandlers[i][fnReset] != INVALID_FUNCTION)
2824 {
2825 Call_StartFunction(g_eTypeHandlers[i][hPlugin], g_eTypeHandlers[i][fnReset]);
2826 Call_Finish();
2827 }
2828 }
2829
2830 if(strcmp(g_eCvars[g_cvarItemSource][sCache], "database")==0)
2831 {
2832 decl String:m_szQuery[64];
2833 Format(STRING(m_szQuery), "SELECT * FROM %s WHERE supported_games LIKE \"%%%s%%\" OR supported_games = \"\"", g_eCvars[g_cvarItemsTable][sCache], g_szGameDir);
2834 SQL_TQuery(g_hDatabase, SQLCallback_ReloadConfig, m_szQuery);
2835 }
2836 else
2837 {
2838 new String:m_szFile[PLATFORM_MAX_PATH];
2839 BuildPath(Path_SM, STRING(m_szFile), "configs/store/items.txt");
2840 new Handle:m_hKV = CreateKeyValues("Store");
2841 FileToKeyValues(m_hKV, m_szFile);
2842 if (!KvGotoFirstSubKey(m_hKV))
2843 {
2844
2845 SetFailState("Failed to read configs/store/items.txt");
2846 }
2847 Store_WalkConfig(m_hKV);
2848 CloseHandle(m_hKV);
2849 }
2850}
2851
2852Store_WalkConfig(&Handle:kv, parent=-1)
2853{
2854 decl String:m_szType[32];
2855 decl String:m_szGame[64];
2856 decl String:m_szFlags[64];
2857 decl m_iHandler;
2858 decl bool:m_bSuccess;
2859 do
2860 {
2861 if(g_iItems == STORE_MAX_ITEMS)
2862 continue;
2863 if (KvGetNum(kv, "enabled", 1) && KvGetNum(kv, "type", -1)==-1 && KvGotoFirstSubKey(kv))
2864 {
2865 KvGoBack(kv);
2866 KvGetSectionName(kv, g_eItems[g_iItems][szName], 64);
2867 KvGetSectionName(kv, g_eItems[g_iItems][szUniqueId], 64);
2868 ReplaceString(g_eItems[g_iItems][szName], 64, "\\n", "\n");
2869 KvGetString(kv, "shortcut", g_eItems[g_iItems][szShortcut], 64);
2870 KvGetString(kv, "flag", STRING(m_szFlags));
2871 KvGetString(kv, "games", STRING(m_szGame));
2872 if(m_szGame[0] != 0 && StrContains(m_szGame, g_szGameDir)==-1)
2873 continue;
2874 g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlags);
2875 g_eItems[g_iItems][iPrice] = KvGetNum(kv, "price", -1);
2876 g_eItems[g_iItems][bBuyable] = (KvGetNum(kv, "buyable", 1)?true:false);
2877 g_eItems[g_iItems][bIgnoreVIP] = (KvGetNum(kv, "ignore_vip", 0)?true:false);
2878 g_eItems[g_iItems][iHandler] = g_iPackageHandler;
2879 KvGotoFirstSubKey(kv);
2880
2881 g_eItems[g_iItems][iParent] = parent;
2882
2883 Store_WalkConfig(kv, g_iItems++);
2884 KvGoBack(kv);
2885 }
2886 else
2887 {
2888 if(!KvGetNum(kv, "enabled", 1))
2889 continue;
2890
2891 KvGetString(kv, "games", STRING(m_szGame));
2892 if(m_szGame[0] != 0 && StrContains(m_szGame, g_szGameDir)==-1)
2893 continue;
2894
2895 g_eItems[g_iItems][iParent] = parent;
2896 KvGetSectionName(kv, g_eItems[g_iItems][szName], ITEM_NAME_LENGTH);
2897 g_eItems[g_iItems][iPrice] = KvGetNum(kv, "price");
2898 g_eItems[g_iItems][bBuyable] = KvGetNum(kv, "buyable", 1)?true:false;
2899 g_eItems[g_iItems][bIgnoreVIP] = (KvGetNum(kv, "ignore_vip", 0)?true:false);
2900
2901
2902 KvGetString(kv, "type", STRING(m_szType));
2903 m_iHandler = Store_GetTypeHandler(m_szType);
2904 if(m_iHandler == -1)
2905 continue;
2906
2907 KvGetString(kv, "flag", STRING(m_szFlags));
2908 g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlags);
2909 g_eItems[g_iItems][iHandler] = m_iHandler;
2910
2911 if(KvGetNum(kv, "unique_id", -1)==-1)
2912 KvGetString(kv, g_eTypeHandlers[m_iHandler][szUniqueKey], g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);
2913 else
2914 KvGetString(kv, "unique_id", g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);
2915
2916 if(KvJumpToKey(kv, "Plans"))
2917 {
2918 KvGotoFirstSubKey(kv);
2919 new index=0;
2920 do
2921 {
2922 KvGetSectionName(kv, g_ePlans[g_iItems][index][szName], ITEM_NAME_LENGTH);
2923 g_ePlans[g_iItems][index][iPrice] = KvGetNum(kv, "price");
2924 g_ePlans[g_iItems][index][iTime] = KvGetNum(kv, "time");
2925 ++index;
2926 } while (KvGotoNextKey(kv));
2927
2928 g_eItems[g_iItems][iPlans]=index;
2929
2930 KvGoBack(kv);
2931 KvGoBack(kv);
2932 }
2933
2934 if(g_eItems[g_iItems][hAttributes])
2935 CloseHandle(g_eItems[g_iItems][hAttributes]);
2936 g_eItems[g_iItems][hAttributes] = INVALID_HANDLE;
2937 if(KvJumpToKey(kv, "Attributes"))
2938 {
2939 g_eItems[g_iItems][hAttributes] = CreateTrie();
2940
2941 KvGotoFirstSubKey(kv, false);
2942
2943 new String:m_szAttribute[64];
2944 new String:m_szValue[64];
2945 do
2946 {
2947 KvGetSectionName(kv, STRING(m_szAttribute));
2948 KvGetString(kv, NULL_STRING, STRING(m_szValue));
2949 SetTrieString(g_eItems[g_iItems][hAttributes], m_szAttribute, m_szValue);
2950 } while (KvGotoNextKey(kv, false));
2951
2952 KvGoBack(kv);
2953 KvGoBack(kv);
2954 }
2955
2956 m_bSuccess = true;
2957 if(g_eTypeHandlers[m_iHandler][fnConfig]!=INVALID_FUNCTION)
2958 {
2959 Call_StartFunction(g_eTypeHandlers[m_iHandler][hPlugin], g_eTypeHandlers[m_iHandler][fnConfig]);
2960 Call_PushCellRef(kv);
2961 Call_PushCell(g_iItems);
2962 Call_Finish(m_bSuccess);
2963 }
2964
2965 if(m_bSuccess)
2966 ++g_iItems;
2967 }
2968 } while (KvGotoNextKey(kv));
2969}
2970
2971public Store_GetTypeHandler(String:type[])
2972{
2973 for(new i=0;i<g_iTypeHandlers;++i)
2974 {
2975 if(strcmp(g_eTypeHandlers[i][szType], type)==0)
2976 return i;
2977 }
2978 return -1;
2979}
2980
2981public Store_GetMenuHandler(String:id[])
2982{
2983 for(new i=0;i<g_iMenuHandlers;++i)
2984 {
2985 if(strcmp(g_eMenuHandlers[i][szIdentifier], id)==0)
2986 return i;
2987 }
2988 return -1;
2989}
2990
2991public bool:Store_IsEquipped(client, itemid)
2992{
2993 for(new i=0;i<STORE_MAX_SLOTS;++i)
2994 if(g_eClients[client][aEquipment][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+i] == itemid)
2995 return true;
2996 return false;
2997}
2998
2999public Store_GetExpiration(client, itemid)
3000{
3001 new uid = Store_GetClientItemId(client, itemid);
3002 if(uid<0)
3003 return 0;
3004 return g_eClientItems[client][uid][iDateOfExpiration];
3005}
3006
3007Store_UseItem(client, itemid, bool:synced=false, slot=0)
3008{
3009 new m_iSlot = slot;
3010 if(g_eTypeHandlers[g_eItems[itemid][iHandler]][fnUse] != INVALID_FUNCTION)
3011 {
3012 new m_iReturn = -1;
3013 Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnUse]);
3014 Call_PushCell(client);
3015 Call_PushCell(itemid);
3016 Call_Finish(m_iReturn);
3017
3018 if(m_iReturn != -1)
3019 m_iSlot = m_iReturn;
3020 }
3021
3022 if(g_eTypeHandlers[g_eItems[itemid][iHandler]][bEquipable])
3023 {
3024 g_eClients[client][aEquipment][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot]=itemid;
3025 if(synced)
3026 g_eClients[client][aEquipmentSynced][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot]=itemid;
3027 }
3028 else if(m_iSlot == 0)
3029 {
3030 Store_RemoveItem(client, itemid);
3031 return 1;
3032 }
3033 return 0;
3034}
3035
3036Store_UnequipItem(client, itemid, bool:fn=true)
3037{
3038 new m_iSlot = 0;
3039 if(fn && itemid > 0 && g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
3040 {
3041 Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove]);
3042 Call_PushCell(client);
3043 Call_PushCell(itemid);
3044 Call_Finish(m_iSlot);
3045 }
3046
3047 decl m_iId;
3048 if(g_eItems[itemid][iHandler] != g_iPackageHandler)
3049 {
3050 m_iId = g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot;
3051 if(g_eClients[client][aEquipmentSynced][m_iId]==-2)
3052 g_eClients[client][aEquipment][m_iId]=-2;
3053 else
3054 g_eClients[client][aEquipment][m_iId]=-1;
3055 }
3056 else
3057 {
3058 for(new i=0;i<STORE_MAX_HANDLERS;++i)
3059 {
3060 for(new a=0;i<STORE_MAX_SLOTS;++i)
3061 {
3062 if(g_eClients[client][aEquipment][i+a] < 0)
3063 continue;
3064 m_iId = i*STORE_MAX_SLOTS+a;
3065 if(Store_IsItemInBoughtPackage(client, g_eClients[client][aEquipment][m_iId], itemid))
3066 if(g_eClients[client][aEquipmentSynced][m_iId]==-2)
3067 g_eClients[client][aEquipment][m_iId]=-2;
3068 else
3069 g_eClients[client][aEquipment][m_iId]=-1;
3070 }
3071 }
3072 }
3073}
3074
3075Store_GetEquippedItemFromHandler(client, handler, slot=0)
3076{
3077 return g_eClients[client][aEquipment][handler*STORE_MAX_SLOTS+slot];
3078}
3079
3080Store_PackageHasClientItem(client, packageid, bool:invmode=false)
3081{
3082 new m_iFlags = GetUserFlagBits(client);
3083 if(!g_eCvars[g_cvarShowVIP][aCache] && !GetClientPrivilege(client, g_eItems[packageid][iFlagBits], m_iFlags))
3084 return false;
3085 for(new i=0;i<g_iItems;++i)
3086 if(g_eItems[i][iParent] == packageid && (g_eCvars[g_cvarShowVIP][aCache] || GetClientPrivilege(client, g_eItems[i][iFlagBits], m_iFlags)) && (invmode && Store_HasClientItem(client, i) || !invmode))
3087 if((g_eItems[i][iHandler] == g_iPackageHandler && Store_PackageHasClientItem(client, i, invmode)) || g_eItems[i][iHandler] != g_iPackageHandler)
3088 return true;
3089 return false;
3090}
3091
3092Store_LogMessage(client, credits, const String:message[], ...)
3093{
3094 if(!g_eCvars[g_cvarLogging][aCache])
3095 return;
3096
3097 decl String:m_szReason[256];
3098 VFormat(STRING(m_szReason), message, 4);
3099
3100 if(g_eCvars[g_cvarLogging][aCache] == 1)
3101 {
3102 LogToOpenFileEx(g_hLogFile, "%N's credits have changed by %d. Reason: %s", client, credits, m_szReason);
3103 } else if(g_eCvars[g_cvarLogging][aCache] == 2)
3104 {
3105 decl String:m_szQuery[256];
3106 Format(STRING(m_szQuery), "INSERT INTO store_logs (player_id, credits, reason, date) VALUES(%d, %d, \"%s\", %d)", g_eClients[client][iId], credits, m_szReason, GetTime());
3107 SQL_TVoid(g_hDatabase, m_szQuery);
3108 }
3109}
3110
3111Store_GetLowestPrice(itemid)
3112{
3113 if(g_eItems[itemid][iPlans]==0)
3114 return g_eItems[itemid][iPrice];
3115
3116 new m_iLowest=g_ePlans[itemid][0][iPrice];
3117 for(new i=1;i<g_eItems[itemid][iPlans];++i)
3118 {
3119 if(m_iLowest>g_ePlans[itemid][i][iPrice])
3120 m_iLowest = g_ePlans[itemid][i][iPrice];
3121 }
3122 return m_iLowest;
3123}
3124
3125Store_GetClientItemPrice(client, itemid)
3126{
3127 new uid = Store_GetClientItemId(client, itemid);
3128 if(uid<0)
3129 return 0;
3130
3131 if(g_eClientItems[client][uid][iPriceOfPurchase]==0)
3132 return g_eItems[itemid][iPrice];
3133
3134 return g_eClientItems[client][uid][iPriceOfPurchase];
3135}
3136
3137public Store_OnPaymentReceived(FriendID, quanity, Handle:data)
3138{
3139 LoopIngamePlayers(i)
3140 {
3141 if(GetFriendID(i)==FriendID)
3142 {
3143 Store_SaveClientData(i);
3144
3145 new m_unMod = FriendID % 2;
3146 new m_unAccountID = (FriendID-m_unMod)/2;
3147
3148 decl String:m_szQuery[256];
3149 Format(STRING(m_szQuery), "SELECT * FROM store_players WHERE `authid`=\"%d:%d\"", m_unMod, m_unAccountID);
3150 SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Credits, m_szQuery, GetClientUserId(i));
3151 break;
3152 }
3153 }
3154}