Raised This Month: $32 Target: $400
 8% 

Fatal Error 196 / Deprecated Syntax


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
AcridGamer
Junior Member
Join Date: Jul 2018
Location: Romania
Old 11-28-2021 , 06:01   Fatal Error 196 / Deprecated Syntax
Reply With Quote #1

Hello, i m trying to compile this 3 plugins but i receive "addons\sourcemod\scripting\include\functions .inc(360) : fatal error 196: deprecated syntax; see https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Typedefs"



This is line 360 from functions.inc
Quote:
typeset public NativeCall(Handle:plugin, numParams);
This is 1 from plugins (store)
Quote:
#pragma semicolon 1

#define PLUGIN_NAME "Thirdperson Mode"
#define PLUGIN_AUTHOR "Zephyrus"
#define PLUGIN_DESCRIPTION "Thirdperson mode"
#define PLUGIN_VERSION "1.0"
#define PLUGIN_URL ""

#include <sourcemod>
#include <sdktools>
#include <zephstocks>

new bool:g_bThirdperson[MAXPLAYERS+1] = {false,...};

public Plugin:myinfo =
{
name = PLUGIN_NAME,
author = PLUGIN_AUTHOR,
description = PLUGIN_DESCRIPTION,
version = PLUGIN_VERSION,
url = PLUGIN_URL
};

public OnPluginStart()
{
IdentifyGame();
HookEvent("player_spawn", Event_PlayerSpawn);
RegConsoleCmd("sm_tp", Command_TP);
RegConsoleCmd("sm_fp", Command_FP);
}

public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
CreateNative("IsPlayerInTP", Native_IsPlayerInTP);
CreateNative("TogglePlayerTP", Native_TogglePlayerTP);

return APLRes_Success;
}

public Native_IsPlayerInTP(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
return g_bThirdperson[client];
}

public Native_TogglePlayerTP(Handle:plugin, numParams)
{
new client = GetNativeCell(1);
g_bThirdperson[client] = !g_bThirdperson[client];
ToggleThirdperson(client);
}

public OnClientConnected(client)
{
g_bThirdperson[client] = false;
}

public Action:Command_TP(client, args)
{
g_bThirdperson[client] = !g_bThirdperson[client];
ToggleThirdperson(client);
return Plugin_Handled;
}

public Action:Command_FP(client, args)
{
g_bThirdperson[client] = false;
SetThirdperson(client, false);
return Plugin_Handled;
}

public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));

if(!client || !IsClientInGame(client) || !IsPlayerAlive(client))
return Plugin_Handled;

if(g_bThirdperson[client])
SetThirdperson(client, true);

return Plugin_Handled;
}

stock ToggleThirdperson(client)
{
if(g_bThirdperson[client])
SetThirdperson(client, true);
else
SetThirdperson(client, false);
}

stock SetThirdperson(client, bool:tp)
{
if(g_bCSGO)
{
static Handle:m_hAllowTP = INVALID_HANDLE;
if(m_hAllowTP == INVALID_HANDLE)
m_hAllowTP = FindConVar("sv_allow_thirdperson");

SetConVarInt(m_hAllowTP, 1);

if(tp)
ClientCommand(client, "thirdperson");
else
ClientCommand(client, "firstperson");
}
else if(g_bTF)
{
if(tp)
SetVariantInt(1);
else
SetVariantInt(0);
AcceptEntityInput(client, "SetForcedTauntCam");
}
}
__________________

Last edited by AcridGamer; 11-28-2021 at 06:03.
AcridGamer is offline
PC Gamer
Veteran Member
Join Date: Mar 2014
Old 11-28-2021 , 06:55   Re: Fatal Error 196 / Deprecated Syntax
Reply With Quote #2

Here's a possible solution for updating the part of functions.inc include file giving you the error:
PHP Code:
/**
 * Defines a native function.
 *
 * It is not necessary to validate the parameter count 
 *
 * @param plugin            Handle of the calling plugin.
 * @param numParams            Number of parameters passed to the native.
 * @return                     Value for the native call to return.
 */
typedef NativeCall = function int (Handle pluginint numParams); 
I found this in the github store repository of the talented Drixevel. Here's a link: https://forums.alliedmods.net/showthread.php?t=255418
PC Gamer is offline
AcridGamer
Junior Member
Join Date: Jul 2018
Location: Romania
Old 11-28-2021 , 07:12   Re: Fatal Error 196 / Deprecated Syntax
Reply With Quote #3

Quote:
Originally Posted by PC Gamer View Post
Here's a possible solution for updating the part of functions.inc include file giving you the error:
PHP Code:
/**
 * Defines a native function.
 *
 * It is not necessary to validate the parameter count 
 *
 * @param plugin            Handle of the calling plugin.
 * @param numParams            Number of parameters passed to the native.
 * @return                     Value for the native call to return.
 */
typedef NativeCall = function int (Handle pluginint numParams); 
I found this in the github store repository of the talented Drixevel. Here's a link: https://forums.alliedmods.net/showthread.php?t=255418
Not working, same error
__________________
AcridGamer is offline
Silvers
SourceMod Plugin Approver
Join Date: Aug 2010
Location: SpaceX
Old 11-28-2021 , 08:22   Re: Fatal Error 196 / Deprecated Syntax
Reply With Quote #4

Looks like you didn't update the include files correctly, SourceMod 1.10 has the correct version of "functions.inc". Re-install the sourcemod include files.
__________________
Silvers is offline
AcridGamer
Junior Member
Join Date: Jul 2018
Location: Romania
Old 11-28-2021 , 08:41   Re: Fatal Error 196 / Deprecated Syntax
Reply With Quote #5

Quote:
Originally Posted by Silvers View Post
Looks like you didn't update the include files correctly, SourceMod 1.10 has the correct version of "functions.inc". Re-install the sourcemod include files.
This is the new error
HTML Code:
//// store.sp
//
// store.sp(13) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(15) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(15) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(16) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(17) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(18) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(19) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(24) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(28) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(38) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(41) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(48) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(57) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(64) : error 153: Array-based enum structs have been removed. See https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Enum_Structs
// store.sp(189) : warning 217: inconsistent indentation (did you mix tabs and spaces?)
// store.sp(200) : warning 217: inconsistent indentation (did you mix tabs and spaces?)
// store.sp(677) : error 157: 'object' is a reserved keyword
// store.sp(685) : error 029: invalid expression, assumed zero
// store.sp(697) : error 157: 'object' is a reserved keyword
// store.sp(705) : error 029: invalid expression, assumed zero
// store.sp(718) : error 157: 'object' is a reserved keyword
// store.sp(728) : error 029: invalid expression, assumed zero
// store.sp(728) : error 029: invalid expression, assumed zero
// store.sp(730) : error 029: invalid expression, assumed zero
// store.sp(741) : error 157: 'object' is a reserved keyword
// store.sp(750) : error 029: invalid expression, assumed zero
// store.sp(750) : error 029: invalid expression, assumed zero
// store.sp(752) : error 029: invalid expression, assumed zero
//
// 26 Errors.
//
// Compilation Time: 0.17 sec
// ----------------------------------------
This is the sp file

Code:
#pragma semicolon 1

//////////////////////////////
//		DEFINITIONS			//
//////////////////////////////

#define PLUGIN_NAME "Store - The Resurrection"
#define PLUGIN_AUTHOR "Zephyrus"
#define PLUGIN_DESCRIPTION "A completely new Store system."
#define PLUGIN_VERSION "1.0"
#define PLUGIN_URL ""

#define SERVER_LOCK_IP ""

//////////////////////////////
//			INCLUDES		//
//////////////////////////////

#include <sourcemod>
#include <sdktools>

#undef REQUIRE_EXTENSIONS
#undef REQUIRE_PLUGIN
#include <store>
#include <zephstocks>
#include <donate>
#include <adminmenu>
#if !defined STANDALONE_BUILD
#include <sdkhooks>
#include <cstrike>
#include <tf2>
#include <tf2_stocks>
#include <tf2items>
#include <gifts>
#include <scp>
#include <thirdperson>
#include <saxtonhale>
#endif

//////////////////////////////
//			ENUMS			//
//////////////////////////////

enum Client
{
	iId,
	iUserId,
	String:szAuthId[32],
	String:szName[64],
	String:szNameEscaped[128],
	iCredits,
	iOriginalCredits,
	iDateOfJoin,
	iDateOfLastJoin,
	iItems,
	aEquipment[STORE_MAX_HANDLERS*STORE_MAX_SLOTS],
	aEquipmentSynced[STORE_MAX_HANDLERS*STORE_MAX_SLOTS],
	Handle:hCreditTimer,
	bool:bLoaded
}

enum Menu_Handler
{
	String:szIdentifier[64],
	Handle:hPlugin,
	Function:fnMenu,
	Function:fnHandler
}

//////////////////////////////////
//		GLOBAL VARIABLES		//
//////////////////////////////////

new GAME_CSS = false;
new GAME_CSGO = false;
new GAME_DOD = false;
new GAME_TF2 = false;
new GAME_L4D = false;
new GAME_L4D2 = false;

new String:g_szGameDir[64];

new Handle:g_hDatabase = INVALID_HANDLE;
new Handle:g_hAdminMenu = INVALID_HANDLE;
new Handle:g_hLogFile = INVALID_HANDLE;

new g_cvarDatabaseEntry = -1;
new g_cvarDatabaseRetries = -1;
new g_cvarDatabaseTimeout = -1;
new g_cvarItemSource = -1;
new g_cvarItemsTable = -1;
new g_cvarStartCredits = -1;
new g_cvarCreditTimer = -1;
new g_cvarCreditAmountActive = -1;
new g_cvarCreditAmountInactive = -1;
new g_cvarCreditAmountKill = -1;
new g_cvarRequiredFlag = -1;
new g_cvarVIPFlag = -1;
new g_cvarSellEnabled = -1;
new g_cvarGiftEnabled = -1;
new g_cvarCreditGiftEnabled = -1;
new g_cvarSellRatio = -1;
new g_cvarConfirmation = -1;
new g_cvarAdminFlag = -1;
new g_cvarSaveOnDeath = -1;
new g_cvarCreditMessages = -1;
new g_cvarShowVIP = -1;
new g_cvarLogging = -1;
new g_cvarSilent = -1;

new g_eItems[STORE_MAX_ITEMS][Store_Item];
new g_eClients[MAXPLAYERS+1][Client];
new g_eClientItems[MAXPLAYERS+1][STORE_MAX_ITEMS][Client_Item];
new g_eTypeHandlers[STORE_MAX_HANDLERS][Type_Handler];
new g_eMenuHandlers[STORE_MAX_HANDLERS][Menu_Handler];
new g_ePlans[STORE_MAX_ITEMS][STORE_MAX_PLANS][Item_Plan];

new g_iItems = 0;
new g_iTypeHandlers = 0;
new g_iMenuHandlers = 0;
new g_iMenuBack[MAXPLAYERS+1];
new g_iLastSelection[MAXPLAYERS+1];
new g_iSelectedItem[MAXPLAYERS+1];
new g_iSelectedPlan[MAXPLAYERS+1];
new g_iMenuClient[MAXPLAYERS+1];
new g_iMenuNum[MAXPLAYERS+1];
new g_iSpam[MAXPLAYERS+1];
new g_iPackageHandler = -1;
new g_iDatabaseRetries = 0;

new bool:g_bInvMode[MAXPLAYERS+1];
new bool:g_bMySQL = false;

new String:g_szClientData[MAXPLAYERS+1][256];

new TopMenuObject:g_eStoreAdmin;

new PublicChatTrigger = 0;
new SilentChatTrigger = 0;

//////////////////////////////
//			MODULES			//
//////////////////////////////

#if !defined STANDALONE_BUILD
#include "store/hats.sp"
#include "store/tracers.sp"
#include "store/playerskins.sp"
#include "store/trails.sp"
#include "store/grenskins.sp"
#include "store/grentrails.sp"
#include "store/weaponcolors.sp"
#include "store/tfsupport.sp"
#include "store/paintball.sp"
#include "store/betting.sp"
#include "store/watergun.sp"
#include "store/gifts.sp"
#include "store/scpsupport.sp"
#include "store/weapons.sp"
#include "store/help.sp"
#include "store/jetpack.sp"
#include "store/bunnyhop.sp"
#include "store/lasersight.sp"
#include "store/health.sp"
#include "store/speed.sp"
#include "store/gravity.sp"
#include "store/invisibility.sp"
#include "store/commands.sp"
#include "store/doors.sp"
#include "store/knife.sp"
#include "store/zrclass.sp"
#include "store/jihad.sp"
#include "store/godmode.sp"
#include "store/sounds.sp"
#include "store/attributes.sp"
#include "store/respawn.sp"
#include "store/pets.sp"
#include "store/sprays.sp"
#include "store/weaponskins.sp"
#include "store/admin.sp"
#endif

//////////////////////////////////
//		PLUGIN DEFINITION		//
//////////////////////////////////

public Plugin:myinfo = 
{
	name = PLUGIN_NAME,
	author = PLUGIN_AUTHOR,
	description = PLUGIN_DESCRIPTION,
	version = PLUGIN_VERSION,
	url = PLUGIN_URL
};

//////////////////////////////
//		PLUGIN FORWARDS		//
//////////////////////////////

public OnPluginStart()
{
	RegPluginLibrary("store_zephyrus");

	if(strcmp(SERVER_LOCK_IP, "") != 0)
	{
		new String:m_szIP[64];
		new m_unIP = GetConVarInt(FindConVar("hostip"));
		Format(STRING(m_szIP), "%d.%d.%d.%d:%d", (m_unIP >> 24) & 0x000000FF, (m_unIP >> 16) & 0x000000FF, (m_unIP >> 8) & 0x000000FF, m_unIP & 0x000000FF, GetConVarInt(FindConVar("hostport")));

		if(strcmp(SERVER_LOCK_IP, m_szIP)!=0)
			SetFailState("GTFO");
	}

	// Identify the game
	GetGameFolderName(STRING(g_szGameDir));
	
	if(strcmp(g_szGameDir, "cstrike")==0)
		GAME_CSS = true;
	else if(strcmp(g_szGameDir, "csgo")==0)
		GAME_CSGO = true;
	else if(strcmp(g_szGameDir, "dod")==0)
		GAME_DOD = true;
	else if(strcmp(g_szGameDir, "tf")==0)
		GAME_TF2 = true;
	else if(strcmp(g_szGameDir, "l4d")==0)
		GAME_L4D = true;
	else if(strcmp(g_szGameDir, "l4d2")==0)
		GAME_L4D2 = true;
	else
	{
		SetFailState("This game is not be supported. Please contact the author for support.");
	}

	// Supress warnings about unused variables.....
	if(GAME_DOD || GAME_L4D || GAME_L4D2 || g_bL4D || g_bL4D2 || g_bND) {}

	// Setting default values
	for(new i=1;i<=MaxClients;++i)
	{
		g_eClients[i][iCredits] = -1;
		g_eClients[i][iOriginalCredits] = 0;
		g_eClients[i][iItems] = -1;
		g_eClients[i][hCreditTimer] = INVALID_HANDLE;
	}

	// Register ConVars
	g_cvarDatabaseEntry = RegisterConVar("sm_store_database", "storage-local", "Name of the default store database entry", TYPE_STRING);
	g_cvarDatabaseRetries = RegisterConVar("sm_store_database_retries", "4", "Number of retries if the connection fails to estabilish with timeout", TYPE_INT);
	g_cvarDatabaseTimeout = RegisterConVar("sm_store_database_timeout", "10", "Timeout in seconds to wait for database connection before retry", TYPE_FLOAT);
	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);
	g_cvarItemsTable = RegisterConVar("sm_store_items_table", "store_menu", "Name of the items table", TYPE_STRING);
	g_cvarStartCredits = RegisterConVar("sm_store_startcredits", "50", "Number of credits a client starts with", TYPE_INT);
	g_cvarCreditTimer = RegisterConVar("sm_store_credit_interval", "60", "Interval in seconds to give out credits", TYPE_FLOAT, ConVar_CreditTimer);
	g_cvarCreditAmountActive = RegisterConVar("sm_store_credit_amount_active", "1", "Number of credits to give out for active players", TYPE_INT, ConVar_CreditTimer);
	g_cvarCreditAmountInactive = RegisterConVar("sm_store_credit_amount_inactive", "1", "Number of credits to give out for inactive players (spectators)", TYPE_INT, ConVar_CreditTimer);
	g_cvarCreditAmountKill = RegisterConVar("sm_store_credit_amount_kill", "5", "Number of credits to give out for killing a player", TYPE_INT, ConVar_CreditTimer);
	g_cvarRequiredFlag = RegisterConVar("sm_store_required_flag", "", "Flag to access the !store menu", TYPE_FLAG);
	g_cvarVIPFlag = RegisterConVar("sm_store_vip_flag", "", "Flag for VIP access (all items unlocked). Leave blank to disable.", TYPE_FLAG);
	g_cvarAdminFlag = RegisterConVar("sm_store_admin_flag", "z", "Flag for admin access. Leave blank to disable.", TYPE_FLAG);
	g_cvarSellEnabled = RegisterConVar("sm_store_enable_selling", "1", "Enable/disable selling of already bought items.", TYPE_INT);
	g_cvarGiftEnabled = RegisterConVar("sm_store_enable_gifting", "1", "Enable/disable gifting of already bought items. [1=everyone, 2=admins only]", TYPE_INT);
	g_cvarCreditGiftEnabled = RegisterConVar("sm_store_enable_credit_gifting", "1", "Enable/disable gifting of credits.", TYPE_INT);
	g_cvarSellRatio = RegisterConVar("sm_store_sell_ratio", "0.50", "Ratio of the original price to get for selling an item.", TYPE_FLOAT);
	g_cvarConfirmation = RegisterConVar("sm_store_confirmation_windows", "1", "Enable/disable confirmation windows.", TYPE_INT);
	g_cvarSaveOnDeath = RegisterConVar("sm_store_save_on_death", "0", "Enable/disable client data saving on client death.", TYPE_INT);
	g_cvarCreditMessages = RegisterConVar("sm_store_credit_messages", "1", "Enable/disable messages when a player earns credits.", TYPE_INT);
	g_cvarChatTag = RegisterConVar("sm_store_chat_tag", "[xMas] ", "The chat tag to use for displaying messages.", TYPE_STRING);
	g_cvarShowVIP = RegisterConVar("sm_store_show_vip_items", "0", "If you enable this VIP items will be shown in grey.", TYPE_INT);
	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);
	g_cvarSilent = RegisterConVar("sm_store_silent_givecredits", "0", "Controls the give credits message visibility. 0 = public 1 = private 2 = no message", TYPE_INT);

	// Register Commands
	RegConsoleCmd("sm_store", Command_Store);
	RegConsoleCmd("sm_shop", Command_Store);
	RegConsoleCmd("sm_inv", Command_Inventory);
	RegConsoleCmd("sm_inventory", Command_Inventory);
	RegConsoleCmd("sm_gift", Command_Gift);
	RegConsoleCmd("sm_givecredits", Command_GiveCredits);
	RegConsoleCmd("sm_resetplayer", Command_ResetPlayer);
	RegConsoleCmd("sm_credits", Command_Credits);
	
	// Hook events
	HookEvent("player_death", Event_PlayerDeath);
	HookEvent("player_spawn", Event_PlayerSpawn);
	
	// Load the translations file
	LoadTranslations("store.phrases");

	// Initiaze the fake package handler
	g_iPackageHandler = Store_RegisterHandler("package", "", INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION, INVALID_FUNCTION);

	// Initialize the modules	
#if !defined STANDALONE_BUILD
	Hats_OnPluginStart();
	Tracers_OnPluginStart();
	Trails_OnPluginStart();
	PlayerSkins_OnPluginStart();
	GrenadeSkins_OnPluginStart();
	GrenadeTrails_OnPluginStart();
	WeaponColors_OnPluginStart();
	TFSupport_OnPluginStart();
	Paintball_OnPluginStart();
	Watergun_OnPluginStart();
	Betting_OnPluginStart();
	Gifts_OnPluginStart();
	SCPSupport_OnPluginStart();
	Weapons_OnPluginStart();
	Help_OnPluginStart();
	Jetpack_OnPluginStart();
	Bunnyhop_OnPluginStart();
	LaserSight_OnPluginStart();
	Health_OnPluginStart();
	Gravity_OnPluginStart();
	Speed_OnPluginStart();
	Invisibility_OnPluginStart();
	Commands_OnPluginStart();
	Doors_OnPluginStart();
	ZRClass_OnPluginStart();
	Jihad_OnPluginStart();
	Knives_OnPluginStart();
	Godmode_OnPluginStart();
	Sounds_OnPluginStart();
	Attributes_OnPluginStart();
	Respawn_OnPluginStart();
	Pets_OnPluginStart();
	Sprays_OnPluginStart();
	WeaponSkins_OnPluginStart();
	AdminGroup_OnPluginStart();
#endif

	new Handle:topmenu;
	if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
		OnAdminMenuReady(topmenu);

	// Load the config file
	Store_ReloadConfig();
	
	// After every module was loaded we are ready to generate the cfg
	AutoExecConfig();

	// Read core.cfg for chat triggers
	ReadCoreCFG();

	// Add a say command listener for shortcuts
	AddCommandListener(Command_Say, "say");

	LoopIngamePlayers(client)
	{
		OnClientConnected(client);
		OnClientPostAdminCheck(client);
		OnClientPutInServer(client);
	}

}

public OnAllPluginsLoaded()
{
	CreateTimer(1.0, LoadConfig);

	if(GetFeatureStatus(FeatureType_Native, "Donate_RegisterHandler")==FeatureStatus_Available)
		Donate_RegisterHandler("Store", Store_OnPaymentReceived);
}

public Action:LoadConfig(Handle:timer, any:data)
{
	// Load the config file
	Store_ReloadConfig();
}

public OnPluginEnd()
{
	LoopIngamePlayers(i)
		if(g_eClients[i][bLoaded])
			OnClientDisconnect(i);

	if(GetFeatureStatus(FeatureType_Native, "Donate_RemoveHandler")==FeatureStatus_Available)
		Donate_RemoveHandler("Store");
}

public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
	CreateNative("Store_RegisterHandler", Native_RegisterHandler);
	CreateNative("Store_RegisterMenuHandler", Native_RegisterMenuHandler);
	CreateNative("Store_SetDataIndex", Native_SetDataIndex);
	CreateNative("Store_GetDataIndex", Native_GetDataIndex);
	CreateNative("Store_GetEquippedItem", Native_GetEquippedItem);
	CreateNative("Store_IsClientLoaded", Native_IsClientLoaded);
	CreateNative("Store_DisplayPreviousMenu", Native_DisplayPreviousMenu);
	CreateNative("Store_SetClientMenu", Native_SetClientMenu);
	CreateNative("Store_GetClientCredits", Native_GetClientCredits);
	CreateNative("Store_SetClientCredits", Native_SetClientCredits);
	CreateNative("Store_IsClientVIP", Native_IsClientVIP);
	CreateNative("Store_IsItemInBoughtPackage", Native_IsItemInBoughtPackage);
	CreateNative("Store_DisplayConfirmMenu", Native_DisplayConfirmMenu);
	CreateNative("Store_ShouldConfirm", Native_ShouldConfirm);
	CreateNative("Store_GetItem", Native_GetItem);
	CreateNative("Store_GetHandler", Native_GetHandler);
	CreateNative("Store_GiveItem", Native_GiveItem);
	CreateNative("Store_RemoveItem", Native_RemoveItem);
	CreateNative("Store_GetClientItem", Native_GetClientItem);
	CreateNative("Store_GetClientTarget", Native_GetClientTarget);
	CreateNative("Store_GiveClientItem", Native_GiveClientItem);
	CreateNative("Store_HasClientItem", Native_HasClientItem);
	CreateNative("Store_IterateEquippedItems", Native_IterateEquippedItems);

#if !defined STANDALONE_BUILD
	MarkNativeAsOptional("ZR_IsClientZombie");
	MarkNativeAsOptional("ZR_IsClientHuman");
	MarkNativeAsOptional("ZR_GetClassByName");
	MarkNativeAsOptional("ZR_SelectClientClass");
	MarkNativeAsOptional("HideTrails_ShouldHide");
#endif
	return APLRes_Success;
} 

#if !defined STANDALONE_BUILD
public OnLibraryAdded(const String:name[])
{
	PlayerSkins_OnLibraryAdded(name);
	ZRClass_OnLibraryAdded(name);
}
#endif

//////////////////////////////
//		 ADMIN MENUS		//
//////////////////////////////

public OnAdminMenuReady(Handle:topmenu)
{
	if (topmenu == g_hAdminMenu)
		return;
	g_hAdminMenu = topmenu;

	g_eStoreAdmin = AddToTopMenu(g_hAdminMenu, "Store Admin", TopMenuObject_Category, CategoryHandler_StoreAdmin, INVALID_TOPMENUOBJECT);
	AddToTopMenu(g_hAdminMenu, "sm_store_resetdb", TopMenuObject_Item, AdminMenu_ResetDb, g_eStoreAdmin, "sm_store_resetdb", g_eCvars[g_cvarAdminFlag][aCache]);
	AddToTopMenu(g_hAdminMenu, "sm_store_resetplayer", TopMenuObject_Item, AdminMenu_ResetPlayer, g_eStoreAdmin, "sm_store_resetplayer", g_eCvars[g_cvarAdminFlag][aCache]);
	AddToTopMenu(g_hAdminMenu, "sm_store_givecredits", TopMenuObject_Item, AdminMenu_GiveCredits, g_eStoreAdmin, "sm_store_givecredits", g_eCvars[g_cvarAdminFlag][aCache]);
	AddToTopMenu(g_hAdminMenu, "sm_store_viewinventory", TopMenuObject_Item, AdminMenu_ViewInventory, g_eStoreAdmin, "sm_store_viewinventory", g_eCvars[g_cvarAdminFlag][aCache]);
}

public CategoryHandler_StoreAdmin(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, String:buffer[], maxlength)
{
	if (action == TopMenuAction_DisplayTitle || action == TopMenuAction_DisplayOption)
		Format(buffer, maxlength, "Magazin Admin");
}

//////////////////////////////
//		Reset database		//
//////////////////////////////

public AdminMenu_ResetDb(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
{
	if (action == TopMenuAction_DisplayOption)
	{
		Format(buffer, maxlength, "Reseteaza Baza Date");
	}
	else if (action == TopMenuAction_SelectOption)
	{
		g_iMenuNum[client] = 0;
		Store_DisplayConfirmMenu(client, "Doriti sa resetati baza de date?", FakeMenuHandler_ResetDatabase, 0);
	}
}

public FakeMenuHandler_ResetDatabase(Handle:menu, MenuAction:action, client, param2)
{
	SQL_TVoid(g_hDatabase, "DROP TABLE store_players");
	SQL_TVoid(g_hDatabase, "DROP TABLE store_items");
	SQL_TVoid(g_hDatabase, "DROP TABLE store_equipment");
	ServerCommand("_restart");
}

//////////////////////////////
//		Reset player		//
//////////////////////////////

public AdminMenu_ResetPlayer(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
{
	if (action == TopMenuAction_DisplayOption)
	{
		Format(buffer, maxlength, "Reseteaza Jucator");
	}
	else if (action == TopMenuAction_SelectOption)
	{
		g_iMenuNum[client] = 4;
		new Handle:m_hMenu = CreateMenu(MenuHandler_ResetPlayer);
		SetMenuTitle(m_hMenu, "Alege Jucator");
		SetMenuExitBackButton(m_hMenu, true);
		LoopAuthorizedPlayers(i)
		{
			decl String:m_szName[64];
			decl String:m_szAuthId[32];
			GetClientName(i, STRING(m_szName));
			GetLegacyAuthString(i, STRING(m_szAuthId));
			AddMenuItem(m_hMenu, m_szAuthId, m_szName);
		}
		DisplayMenu(m_hMenu, client, 0);
	}
}

public MenuHandler_ResetPlayer(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		if(menu == INVALID_HANDLE)
			FakeClientCommandEx(client, "sm_resetplayer \"%s\"", g_szClientData[client]);
		else
		{
			decl style;
			decl String:m_szName[64];
			GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]), style, STRING(m_szName));

			decl String:m_szTitle[256];
			Format(STRING(m_szTitle), "Resetati %s?", m_szName);
			Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_ResetPlayer, 0);
		}
	}
	else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
		RedisplayAdminMenu(g_hAdminMenu, client);
}

//////////////////////////////
//		Give credits		//
//////////////////////////////

public AdminMenu_GiveCredits(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
{
	if (action == TopMenuAction_DisplayOption)
	{
		Format(buffer, maxlength, "Ofera Credite");
	}
	else if (action == TopMenuAction_SelectOption)
	{
		g_iMenuNum[client] = 5;
		new Handle:m_hMenu = CreateMenu(MenuHandler_GiveCredits);
		SetMenuTitle(m_hMenu, "Alegeti Jucator");
		SetMenuExitBackButton(m_hMenu, true);
		LoopAuthorizedPlayers(i)
		{
			decl String:m_szName[64];
			decl String:m_szAuthId[32];
			GetClientName(i, STRING(m_szName));
			GetLegacyAuthString(i, STRING(m_szAuthId));
			AddMenuItem(m_hMenu, m_szAuthId, m_szName);
		}
		DisplayMenu(m_hMenu, client, 0);
	}
}

public MenuHandler_GiveCredits(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		if(param2 != -1)
			GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]));
		new Handle:m_hMenu = CreateMenu(MenuHandler_GiveCredits2);

		new target = GetClientBySteamID(g_szClientData[client]);
		if(target == 0)
		{
			AdminMenu_GiveCredits(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
			return;
		}

		SetMenuTitle(m_hMenu, "Alegeti Suma \n%N - %d credits", target, g_eClients[target][iCredits]);
		SetMenuExitBackButton(m_hMenu, true);
		AddMenuItem(m_hMenu, "-100", "-100");
		AddMenuItem(m_hMenu, "50", "50");
		AddMenuItem(m_hMenu, "100", "100");
		AddMenuItem(m_hMenu, "200", "200");
		AddMenuItem(m_hMenu, "500", "500");
		AddMenuItem(m_hMenu, "1000", "1000");
		DisplayMenu(m_hMenu, client, 0);
	}
	else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
		RedisplayAdminMenu(g_hAdminMenu, client);
}

public MenuHandler_GiveCredits2(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		decl String:m_szData[11];
		GetMenuItem(menu, param2, STRING(m_szData));
		FakeClientCommand(client, "sm_givecredits \"%s\" %s", g_szClientData[client], m_szData);
		MenuHandler_GiveCredits(INVALID_HANDLE, MenuAction_Select, client, -1);
	}
	else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
		AdminMenu_GiveCredits(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
}

//////////////////////////////
//		View inventory		//
//////////////////////////////

public AdminMenu_ViewInventory(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength)
{
	if (action == TopMenuAction_DisplayOption)
	{
		Format(buffer, maxlength, "Vizualizati Inventar");
	}
	else if (action == TopMenuAction_SelectOption)
	{
		g_iMenuNum[client] = 4;
		new Handle:m_hMenu = CreateMenu(MenuHandler_ViewInventory);
		SetMenuTitle(m_hMenu, "Alege Jucator");
		SetMenuExitBackButton(m_hMenu, true);
		LoopAuthorizedPlayers(i)
		{
			decl String:m_szName[64];
			decl String:m_szAuthId[32];
			GetClientName(i, STRING(m_szName));
			GetLegacyAuthString(i, STRING(m_szAuthId));
			AddMenuItem(m_hMenu, m_szAuthId, m_szName);
		}
		DisplayMenu(m_hMenu, client, 0);
	}
}

public MenuHandler_ViewInventory(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		GetMenuItem(menu, param2, g_szClientData[client], sizeof(g_szClientData[]));
		new target = GetClientBySteamID(g_szClientData[client]);
		if(target == 0)
		{
			AdminMenu_ViewInventory(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
			return;
		}

		g_bInvMode[client]=true;
		g_iMenuClient[client]=target;
		DisplayStoreMenu(client);
	}
	else if (action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
		RedisplayAdminMenu(g_hAdminMenu, client);
}

//////////////////////////////////////
//		REST OF PLUGIN FORWARDS		//
//////////////////////////////////////

public OnMapStart()
{
	for(new i=0;i<g_iTypeHandlers;++i)
	{
		if(g_eTypeHandlers[i][fnMapStart] != INVALID_FUNCTION)
		{
			Call_StartFunction(g_eTypeHandlers[i][hPlugin], g_eTypeHandlers[i][fnMapStart]);
			Call_Finish();
		}
	}
}

public OnConfigsExecuted()
{
	Jetpack_OnConfigsExecuted();
	Jihad_OnConfigsExecuted();

	// Connect to the database
	if(g_hDatabase == INVALID_HANDLE)
		SQL_TConnect(SQLCallback_Connect, g_eCvars[g_cvarDatabaseEntry][sCache]);
	if(g_eCvars[g_cvarDatabaseRetries][aCache] > 0)
		CreateTimer(Float:g_eCvars[g_cvarDatabaseTimeout][aCache], Timer_DatabaseTimeout);

	if(g_eCvars[g_cvarLogging][aCache] == 1)
		if(g_hLogFile == INVALID_HANDLE)
		{
			new String:m_szPath[PLATFORM_MAX_PATH];
			BuildPath(Path_SM, STRING(m_szPath), "logs/store.log.txt");
			g_hLogFile = OpenFile(m_szPath, "w+");
		}
}

#if !defined STANDALONE_BUILD
public OnGameFrame()
{
	Trails_OnGameFrame();
	TFWeapon_OnGameFrame();
	TFHead_OnGameFrame();
}
#endif

#if !defined STANDALONE_BUILD
public OnEntityCreated(entity, const String:classname[])
{
	GrenadeSkins_OnEntityCreated(entity, classname);
	GrenadeTrails_OnEntityCreated(entity, classname);
}
#endif

//////////////////////////////
//			NATIVES			//
//////////////////////////////

public Native_RegisterHandler(Handle:plugin, numParams)
{
	if(g_iTypeHandlers == STORE_MAX_HANDLERS)
		return -1;
		
	decl String:m_szType[32];
	GetNativeString(1, STRING(m_szType));
	new m_iHandler = Store_GetTypeHandler(m_szType);	
	new m_iId = g_iTypeHandlers;
	
	if(m_iHandler != -1)
		m_iId = m_iHandler;
	else
		++g_iTypeHandlers;
	
	g_eTypeHandlers[m_iId][hPlugin] = plugin;
	g_eTypeHandlers[m_iId][fnMapStart] = GetNativeCell(3);
	g_eTypeHandlers[m_iId][fnReset] = GetNativeCell(4);
	g_eTypeHandlers[m_iId][fnConfig] = GetNativeCell(5);
	g_eTypeHandlers[m_iId][fnUse] = GetNativeCell(6);
	g_eTypeHandlers[m_iId][fnRemove] = GetNativeCell(7);
	g_eTypeHandlers[m_iId][bEquipable] = GetNativeCell(8);
	g_eTypeHandlers[m_iId][bRaw] = GetNativeCell(9);
	strcopy(g_eTypeHandlers[m_iId][szType], 32, m_szType);
	GetNativeString(2, g_eTypeHandlers[m_iId][szUniqueKey], 32);

	return m_iId;
}

public Native_RegisterMenuHandler(Handle:plugin, numParams)
{
	if(g_iMenuHandlers == STORE_MAX_HANDLERS)
		return -1;
		
	decl String:m_szIdentifier[64];
	GetNativeString(1, STRING(m_szIdentifier));
	new m_iHandler = Store_GetMenuHandler(m_szIdentifier);	
	new m_iId = g_iMenuHandlers;
	
	if(m_iHandler != -1)
		m_iId = m_iHandler;
	else
		++g_iMenuHandlers;
	
	g_eMenuHandlers[m_iId][hPlugin] = plugin;
	g_eMenuHandlers[m_iId][fnMenu] = GetNativeCell(2);
	g_eMenuHandlers[m_iId][fnHandler] = GetNativeCell(3);
	strcopy(g_eMenuHandlers[m_iId][szIdentifier], 64, m_szIdentifier);

	return m_iId;
}

public Native_SetDataIndex(Handle:plugin, numParams)
{
	g_eItems[GetNativeCell(1)][iData] = GetNativeCell(2);
}

public Native_GetDataIndex(Handle:plugin, numParams)
{
	return g_eItems[GetNativeCell(1)][iData];
}

public Native_GetEquippedItem(Handle:plugin, numParams)
{
	decl String:m_szType[16];
	GetNativeString(2, STRING(m_szType));
	
	new m_iHandler = Store_GetTypeHandler(m_szType);
	if(m_iHandler == -1)
		return -1;
	
	return Store_GetEquippedItemFromHandler(GetNativeCell(1), m_iHandler, GetNativeCell(3));
}

public Native_IsClientLoaded(Handle:plugin, numParams)
{
	return g_eClients[GetNativeCell(1)][bLoaded];
}

public Native_DisplayPreviousMenu(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	if(g_iMenuNum[client] == 1)
		DisplayStoreMenu(client, g_iMenuBack[client], g_iLastSelection[client]);
	else if(g_iMenuNum[client] == 2)
		DisplayItemMenu(client, g_iSelectedItem[client]);
	else if(g_iMenuNum[client] == 3)
		DisplayPlayerMenu(client);
	else if(g_iMenuNum[client] == 4)
		AdminMenu_ResetPlayer(g_hAdminMenu, TopMenuAction_SelectOption, g_eStoreAdmin, client, "", 0);
	else if(g_iMenuNum[client] == 5)
		DisplayPlanMenu(client, g_iSelectedItem[client]);
	else if(g_iMenuNum[client] == 0)
		RedisplayAdminMenu(g_hAdminMenu, client);
}

public Native_SetClientMenu(Handle:plugin, numParams)
{
	g_iMenuNum[GetNativeCell(1)] = GetNativeCell(2);
}

public Native_GetClientCredits(Handle:plugin, numParams)
{
	return g_eClients[GetNativeCell(1)][iCredits];
}

public Native_SetClientCredits(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new m_iCredits = GetNativeCell(2);
	Store_LogMessage(client, m_iCredits-g_eClients[client][iCredits], "Plugin Extern");
	g_eClients[client][iCredits] = m_iCredits;
	return 1;
}

public Native_IsClientVIP(Handle:plugin, numParams)
{
	return (g_eCvars[g_cvarVIPFlag][aCache] != 0 && GetClientPrivilege(GetNativeCell(1), g_eCvars[g_cvarVIPFlag][aCache]));
}

public Native_IsItemInBoughtPackage(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new itemid = GetNativeCell(2);
	new uid = GetNativeCell(3);

	decl m_iParent;
	if(itemid<0)
		m_iParent = g_eItems[itemid][iParent];
	else
		m_iParent = g_eItems[itemid][iParent];
		
	while(m_iParent != -1)
	{
		for(new i=0;i<g_eClients[client][iItems];++i)
			if(((uid == -1 && g_eClientItems[client][i][iUniqueId] == m_iParent) || (uid != -1 && g_eClientItems[client][i][iUniqueId] == uid)) && !g_eClientItems[client][i][bDeleted])
				return true;
		m_iParent = g_eItems[m_iParent][iParent];
	}
	return false;
}

public Native_DisplayConfirmMenu(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	decl String:title[255];
	GetNativeString(2, STRING(title));
	new callback = GetNativeCell(3);
	new data = GetNativeCell(4);

	new Handle:m_hMenu = CreateMenu(MenuHandler_Confirm);
	SetMenuTitle(m_hMenu, title);
	SetMenuExitButton(m_hMenu, false);
	new String:m_szCallback[32];
	new String:m_szData[11];
	Format(STRING(m_szCallback), "%d.%d", plugin, callback);
	IntToString(data, STRING(m_szData));
	AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, m_szCallback, "%t", "Confirm_Yes");
	AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, m_szData, "%t", "Confirm_No");
	DisplayMenu(m_hMenu, client, 0);
}

public Native_ShouldConfirm(Handle:plugin, numParams)
{
	return g_eCvars[g_cvarConfirmation][aCache];
}

public Native_GetItem(Handle:plugin, numParams)
{
	SetNativeArray(2, _:g_eItems[GetNativeCell(1)], sizeof(g_eItems[])); 
}

public Native_GetHandler(Handle:plugin, numParams)
{
	SetNativeArray(2, _:g_eTypeHandlers[GetNativeCell(1)], sizeof(g_eTypeHandlers[])); 
}

public Native_GetClientItem(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new itemid = GetNativeCell(2);

	new uid = Store_GetClientItemId(client, itemid);
	if(uid<0)
		return 0;

	SetNativeArray(3, _:g_eClientItems[client][uid], sizeof(g_eClientItems[][])); 

	return 1;
}

public Native_GiveItem(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new itemid = GetNativeCell(2);
	new purchase = GetNativeCell(3);
	new expiration = GetNativeCell(4);
	new price = GetNativeCell(5);

	new m_iDateOfPurchase = (purchase==0?GetTime():purchase);
	new m_iDateOfExpiration = expiration;

	new m_iId = g_eClients[client][iItems]++;
	g_eClientItems[client][m_iId][iId] = -1;
	g_eClientItems[client][m_iId][iUniqueId] = itemid;
	g_eClientItems[client][m_iId][iDateOfPurchase] = m_iDateOfPurchase;
	g_eClientItems[client][m_iId][iDateOfExpiration] = m_iDateOfExpiration;
	g_eClientItems[client][m_iId][iPriceOfPurchase] = price;
	g_eClientItems[client][m_iId][bSynced] = false;
	g_eClientItems[client][m_iId][bDeleted] = false;
}

public Native_RemoveItem(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new itemid = GetNativeCell(2);
	if(itemid>0 && g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
	{
		Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove]);
		Call_PushCell(client);
		Call_PushCell(itemid);
		Call_Finish();
	}
	
	Store_UnequipItem(client, itemid, false);
	
	new m_iId = Store_GetClientItemId(client, itemid);
	if(m_iId != -1)
		g_eClientItems[client][m_iId][bDeleted] = true;
}

public Native_GetClientTarget(Handle:plugin, numParams)
{
	return g_iMenuClient[GetNativeCell(1)];
}

public Native_GiveClientItem(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new receiver = GetNativeCell(2);
	new itemid = GetNativeCell(3);

	new item = Store_GetClientItemId(client, itemid);
	if(item == -1)
		return 1;

	new m_iId = g_eClientItems[client][item][iUniqueId];
	new target = g_iMenuClient[client];
	g_eClientItems[client][item][bDeleted] = true;
	Store_UnequipItem(client, m_iId);

	g_eClientItems[receiver][g_eClients[receiver][iItems]][iId] = -1;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iUniqueId] = m_iId;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][bSynced] = false;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][bDeleted] = false;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfPurchase] = g_eClientItems[target][item][iDateOfPurchase];
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfExpiration] = g_eClientItems[target][item][iDateOfExpiration];
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iPriceOfPurchase] = g_eClientItems[target][item][iPriceOfPurchase];
	
	++g_eClients[receiver][iItems];

	return 1;
}

public Native_HasClientItem(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new itemid = GetNativeCell(2);

	// Can he even have it?	
	if(!GetClientPrivilege(client, g_eItems[itemid][iFlagBits]))
		return false;

	// Is the item free (available for everyone)?
	if(g_eItems[itemid][iPrice] <= 0 && g_eItems[itemid][iPlans]==0)
		return true;
		
	// Is the client a VIP therefore has access to all the items already?
	if(Store_IsClientVIP(client) && !g_eItems[itemid][bIgnoreVIP])
		return true;
		
	// Can he even have it?	
	if(!GetClientPrivilege(client, g_eItems[itemid][iFlagBits]))
		return false;
		
	// Check if the client actually has the item
	for(new i=0;i<g_eClients[client][iItems];++i)
	{
		if(g_eClientItems[client][i][iUniqueId] == itemid && !g_eClientItems[client][i][bDeleted])
			if(g_eClientItems[client][i][iDateOfExpiration]==0 || (g_eClientItems[client][i][iDateOfExpiration] && GetTime()<g_eClientItems[client][i][iDateOfExpiration]))
				return true;
			else
				return false;
	}
	
	// Check if the item is part of a group the client already has
	if(Store_IsItemInBoughtPackage(client, itemid))
		return true;
		
	return false;
}

public Native_IterateEquippedItems(Handle:plugin, numParams)
{
	new client = GetNativeCell(1);
	new start = GetNativeCellRef(2);
	new bool:attributes = GetNativeCell(3);

	for(new i=start+1;i<STORE_MAX_HANDLERS*STORE_MAX_SLOTS;++i)
	{
		if(g_eClients[client][aEquipment][i] >= 0 && (attributes==false || (attributes && g_eItems[g_eClients[client][aEquipment][i]][hAttributes]!=INVALID_HANDLE)))
		{
			SetNativeCellRef(2, i);
			return g_eClients[client][aEquipment][i];
		}
	}
		
	return -1;
}

//////////////////////////////
//		CLIENT FORWARDS		//
//////////////////////////////

public OnClientConnected(client)
{
	g_iSpam[client] = 0;
	g_eClients[client][iUserId] = GetClientUserId(client);
	g_eClients[client][iCredits] = -1;
	g_eClients[client][iOriginalCredits] = 0;
	g_eClients[client][iItems] = -1;
	g_eClients[client][bLoaded] = false;
	for(new i=0;i<STORE_MAX_HANDLERS;++i)
	{
		for(new a=0;a<STORE_MAX_SLOTS;++a)
		{
			g_eClients[client][aEquipment][i*STORE_MAX_SLOTS+a] = -2;
			g_eClients[client][aEquipmentSynced][i*STORE_MAX_SLOTS+a] = -2;
		}
	}

#if !defined STANDALONE_BUILD
	PlayerSkins_OnClientConnected(client);
	Jetpack_OnClientConnected(client);
	ZRClass_OnClientConnected(client);
	Pets_OnClientConnected(client);
	Sprays_OnClientConnected(client);
#endif
}

public OnClientPostAdminCheck(client)
{
	if(IsFakeClient(client))
		return;
	Store_LoadClientInventory(client);
}

#if !defined STANDALONE_BUILD
public OnClientPutInServer(client)
{
	if(IsFakeClient(client))
		return;
	WeaponColors_OnClientPutInServer(client);
	Knives_OnClientPutInServer(client);
	WeaponSkins_OnClientPutInServer(client);
}
#endif

public OnClientDisconnect(client)
{
	if(IsFakeClient(client))
		return;
	
#if !defined STANDALONE_BUILD
	Betting_OnClientDisconnect(client);
	Pets_OnClientDisconnect(client);
#endif

	Store_SaveClientData(client);
	Store_SaveClientInventory(client);
	Store_SaveClientEquipment(client);
	Store_DisconnectClient(client);
}

public OnClientSettingsChanged(client)
{
	GetClientName(client, g_eClients[client][szName], 64);
	if(g_hDatabase)
		SQL_EscapeString(g_hDatabase, g_eClients[client][szName], g_eClients[client][szNameEscaped], 128);
}

#if !defined STANDALONE_BUILD
public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2])
{
	if(!IsClientInGame(client))
		return Plugin_Continue;

	new Action:m_iRet = Plugin_Continue;

	Jetpack_OnPlayerRunCmd(client, buttons);
	LaserSight_OnPlayerRunCmd(client);
	Pets_OnPlayerRunCmd(client, tickcount);
	Sprays_OnPlayerRunCmd(client, buttons);
	m_iRet = Bunnyhop_OnPlayerRunCmd(client, buttons);

	return m_iRet;
}
#endif

//////////////////////////////
//			EVENTS			//
//////////////////////////////

public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
	new victim = GetClientOfUserId(GetEventInt(event, "userid"));
	new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));

	if(g_eCvars[g_cvarSaveOnDeath][aCache])
	{
		Store_SaveClientData(victim);
		Store_SaveClientInventory(victim);
		Store_SaveClientEquipment(victim);
	}

	if(!attacker || victim == attacker || !IsClientInGame(attacker) || IsFakeClient(attacker))
		return Plugin_Continue;

	if(g_eCvars[g_cvarCreditAmountKill][aCache])
	{
		g_eClients[attacker][iCredits] += g_eCvars[g_cvarCreditAmountKill][aCache];
		if(g_eCvars[g_cvarCreditMessages][aCache])
			Chat(attacker, "%t", "Credits Earned For Killing", g_eCvars[g_cvarCreditAmountKill][aCache], g_eClients[victim][szName]);
		Store_LogMessage(attacker, g_eCvars[g_cvarCreditAmountKill][aCache], "Earned for killing");
	}
		
	return Plugin_Continue;
}

public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));

	if(!IsClientInGame(client))
		return Plugin_Continue;

#if !defined STANDALONE_BUILD
	Health_OnPlayerSpawn(client);
#endif
		
	return Plugin_Continue;
}


//////////////////////////////////
//			COMMANDS	 		//
//////////////////////////////////

public Action:Command_Say(client, const String:command[], argc)
{
	if(argc > 0)
	{
		decl String:m_szArg[65];
		GetCmdArg(1, STRING(m_szArg));
		if(m_szArg[0] == PublicChatTrigger)
		{
			for(new i=0;i<g_iItems;++i)
				if(strcmp(g_eItems[i][szShortcut], m_szArg[1])==0 && g_eItems[i][szShortcut][0] != 0)
				{
					g_bInvMode[client]=false;
					g_iMenuClient[client]=client;
					DisplayStoreMenu(client, i);
					break;
				}
		}
	}
	return Plugin_Continue;
}

public Action:Command_Store(client, params)
{
	if(g_eCvars[g_cvarRequiredFlag][aCache] && !GetClientPrivilege(client, g_eCvars[g_cvarRequiredFlag][aCache]))
	{
		Chat(client, "%t", "Ne cerem scuze dar nu aveti permisiunea necesara!");
		return Plugin_Handled;
	}
	
	if((g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1) || !g_eClients[client][bLoaded])
	{
		Chat(client, "%t", "Inventarul nu a fost preluat!");
		return Plugin_Handled;
	}
	
	g_bInvMode[client]=false;
	g_iMenuClient[client]=client;
	DisplayStoreMenu(client);
	
	return Plugin_Handled;
}

public Action:Command_Inventory(client, params)
{
	if(g_eCvars[g_cvarRequiredFlag][aCache] && !GetClientPrivilege(client, g_eCvars[g_cvarRequiredFlag][aCache]))
	{
		Chat(client, "%t", "Ne cerem scuze dar nu aveti permisiunea necesara!");
		return Plugin_Handled;
	}
	
	if((g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1) || !g_eClients[client][bLoaded])
	{
		Chat(client, "%t", "Inventarul nu a fost preluat!");
		return Plugin_Handled;
	}
	
	g_bInvMode[client]=true;
	g_iMenuClient[client]=client;
	DisplayStoreMenu(client);

	return Plugin_Handled;
}

public Action:Command_Gift(client, params)
{
	if(!g_eCvars[g_cvarCreditGiftEnabled][aCache])
	{
		Chat(client, "%t", "Creditele Cadouri Sunt Dezactivate!");
		return Plugin_Handled;
	}
	
	decl String:m_szTmp[64];
	GetCmdArg(2, STRING(m_szTmp));
	
	new m_iCredits = StringToInt(m_szTmp);
	if(g_eClients[client][iCredits]<m_iCredits || m_iCredits<=0)
	{
		Chat(client, "%t", "Suma Invalida!");
		return Plugin_Handled;
	}

	decl bool:m_bTmp;
	decl m_iTargets[1];
	GetCmdArg(1, STRING(m_szTmp));
	
	new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
	if(m_iClients>2)
	{
		Chat(client, "%t", "Prea multe credite!");
		return Plugin_Handled;
	}
	
	if(m_iClients != 1)
	{
		Chat(client, "%t", "Credite Negasite!");
		return Plugin_Handled;
	}
	
	new m_iReceiver = m_iTargets[0];
	
	g_eClients[client][iCredits] -= m_iCredits;
	g_eClients[m_iReceiver][iCredits] += m_iCredits;
	
	Chat(client, "%t", "Credite Trimise", m_iCredits, g_eClients[m_iReceiver][szName]);
	Chat(m_iReceiver, "%t", "Credite Primite", m_iCredits, g_eClients[client][szName]);

	Store_LogMessage(m_iReceiver, m_iCredits, "Daruit De %N", client);
	Store_LogMessage(client, -m_iCredits, "Daruit Lui %N", m_iReceiver);
	
	return Plugin_Handled;
}

public Action:Command_GiveCredits(client, params)
{
	if(client && !GetClientPrivilege(client, g_eCvars[g_cvarAdminFlag][aCache]))
	{
		Chat(client, "%t", "Ne cerem scuze dar nu aveti permisiunea necesara!");
		return Plugin_Handled;
	}
	
	decl String:m_szTmp[64];
	GetCmdArg(2, STRING(m_szTmp));
	
	new m_iCredits = StringToInt(m_szTmp);

	decl bool:m_bTmp;
	decl m_iTargets[1];
	GetCmdArg(1, STRING(m_szTmp));

	new m_iReceiver = -1;
	if(strncmp(m_szTmp, "STEAM_", 6)==0)
	{
		m_iReceiver = GetClientBySteamID(m_szTmp);
		// SteamID is not ingame
		if(m_iReceiver == 0)
		{
			decl String:m_szQuery[512];
			if(g_bMySQL)
				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);
			else
			{
				Format(STRING(m_szQuery), "INSERT OR IGNORE INTO store_players (authid) VALUES (\"%s\")", m_szTmp[8]);
				SQL_TVoid(g_hDatabase, m_szQuery);
				Format(STRING(m_szQuery), "UPDATE store_players SET credits=credits+%d WHERE authid=\"%s\"", m_iCredits, m_szTmp[8]);
			}
			SQL_TVoid(g_hDatabase, m_szQuery);
			ChatAll("%t", "Credite Acordate", m_szTmp[8], m_iCredits);
			m_iReceiver = -1;
		}
	} else if(strcmp(m_szTmp, "@all")==0)
	{
		LoopIngamePlayers(i)
			FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
	} else if(strcmp(m_szTmp, "@t")==0 || strcmp(m_szTmp, "@red")==0)
	{
		LoopIngamePlayers(i)
			if(GetClientTeam(i)==2)
				FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
	} else if(strcmp(m_szTmp, "@ct")==0 || strcmp(m_szTmp, "@blu")==0)
	{
		LoopIngamePlayers(i)
			if(GetClientTeam(i)==3)
				FakeClientCommandEx(client, "sm_givecredits \"%N\" %d", i, m_iCredits);
	}
	else
	{
		new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
		if(m_iClients>2)
		{
			if(client)
				Chat(client, "%t", "Prea multe credite!");
			else
				ReplyToCommand(client, "%t", "Prea multe credite!");
			return Plugin_Handled;
		} else if(m_iClients != 1)
		{
			if(client)
				Chat(client, "%t", "Credite Negasite!");
			else
				ReplyToCommand(client, "%t", "Credite Negasite!");
			return Plugin_Handled;
		}

		m_iReceiver = m_iTargets[0];
	}
	
	// The player is on the server
	if(m_iReceiver != -1)
	{
		g_eClients[m_iReceiver][iCredits] += m_iCredits;
		if(g_eCvars[g_cvarSilent][aCache] == 1)
		{
			if(client)
				Chat(client, "%t", "Credite Acordate", g_eClients[m_iReceiver][szName], m_iCredits);
			else
				ReplyToCommand(client, "%t", "Credite Acordate", g_eClients[m_iReceiver][szName], m_iCredits);
			Chat(m_iReceiver, "%t", "Credite Acordate", g_eClients[m_iReceiver][szName], m_iCredits);
		}
		else if(g_eCvars[g_cvarSilent][aCache] == 0)
			ChatAll("%t", "Credite Acordate", g_eClients[m_iReceiver][szName], m_iCredits);
		Store_LogMessage(m_iReceiver, m_iCredits, "Oferite De Admin");
	}
	
	return Plugin_Handled;
}

public Action:Command_ResetPlayer(client, params)
{
	if(client && !GetClientPrivilege(client, g_eCvars[g_cvarAdminFlag][aCache]))
	{
		Chat(client, "%t", "Ne cerem scuze dar nu aveti permisiunea necesara!");
		return Plugin_Handled;
	}

	decl String:m_szTmp[64];
	decl bool:m_bTmp;
	decl m_iTargets[1];
	GetCmdArg(1, STRING(m_szTmp));

	new m_iReceiver = -1;
	if(strncmp(m_szTmp, "STEAM_", 6)==0)
	{
		m_iReceiver = GetClientBySteamID(m_szTmp);
		// SteamID is not ingame
		if(m_iReceiver == 0)
		{
			decl String:m_szQuery[512];
			Format(STRING(m_szQuery), "SELECT id, authid FROM store_players WHERE authid=\"%s\"", m_szTmp[9]);
			SQL_TQuery(g_hDatabase, SQLCallback_ResetPlayer, m_szQuery, g_eClients[client][iUserId]);
		}
	}
	else
	{	
		new m_iClients = ProcessTargetString(m_szTmp, 0, m_iTargets, 1, 0, STRING(m_szTmp), m_bTmp);
		if(m_iClients>2)
		{
			Chat(client, "%t", "Prea multe credite!");
			return Plugin_Handled;
		}
		
		if(m_iClients != 1)
		{
			Chat(client, "%t", "Credite Negasite!");
			return Plugin_Handled;
		}

		m_iReceiver = m_iTargets[0];
	}
	
	// The player is on the server
	if(m_iReceiver != -1)
	{
		Store_LogMessage(client, -g_eClients[m_iReceiver][iCredits], "Jucatorul a fost resetat!");
		g_eClients[m_iReceiver][iCredits] = 0;
		for(new i=0;i<g_eClients[m_iReceiver][iItems];++i)
			Store_RemoveItem(m_iReceiver, g_eClientItems[m_iReceiver][i][iUniqueId]);
		ChatAll("%t", "Jucatorul a fost resetat!", g_eClients[m_iReceiver][szName]);
	}
	
	return Plugin_Handled;
}

public Action:Command_Credits(client, params)
{	
	if(g_eClients[client][iCredits] == -1 && g_eClients[client][iItems] == -1)
	{
		Chat(client, "%t", "Inventarul nu a fost preluat!");
		return Plugin_Handled;
	}

	if(g_iSpam[client]<GetTime())
	{
		ChatAll("%t", "Credite Jucator", g_eClients[client][szName], g_eClients[client][iCredits]);
		g_iSpam[client] = GetTime()+30;
	}
	
	return Plugin_Handled;
}

//////////////////////////////
//			MENUS	 		//
//////////////////////////////

DisplayStoreMenu(client, parent=-1, last=-1)
{
	if(!client || !IsClientInGame(client))
		return;

	g_iMenuNum[client] = 1;
	new target = g_iMenuClient[client];

	new Handle:m_hMenu = CreateMenu(MenuHandler_Store);
	if(parent!=-1)
	{
		SetMenuExitBackButton(m_hMenu, true);
		if(client == target)
			SetMenuTitle(m_hMenu, "%s\n%t", g_eItems[parent][szName], "Credite De Titlu", g_eClients[target][iCredits]);
		else
			SetMenuTitle(m_hMenu, "%N\n%s\n%t", target, g_eItems[parent][szName], "Credite De Titlu", g_eClients[target][iCredits]);
		g_iMenuBack[client] = g_eItems[parent][iParent];
	}
	else if(client == target)
		SetMenuTitle(m_hMenu, "%t\n%t", "Magazin De Titlu", "Credite De Titlu", g_eClients[target][iCredits]);
	else
		SetMenuTitle(m_hMenu, "%N\n%t\n%t", target, "Magazin De Titlu", "Credite De Titlu", g_eClients[target][iCredits]);
	
	decl String:m_szId[11];
	new m_iFlags = GetUserFlagBits(target);
	new m_iPosition = 0;
	
	g_iSelectedItem[client] = parent;
	if(parent != -1)
	{
		if(g_eItems[parent][iPrice]>0)
		{
			if(!Store_IsClientVIP(target) && !Store_IsItemInBoughtPackage(target, parent))
			{
				if(g_eCvars[g_cvarSellEnabled][aCache])
				{
					AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "sell_package", "%t", "Package Sell", RoundToFloor(g_eItems[parent][iPrice]*Float:g_eCvars[g_cvarSellRatio][aCache]));
					++m_iPosition;
				}
				if(g_eCvars[g_cvarGiftEnabled][aCache] == 1 || (g_eCvars[g_cvarGiftEnabled][aCache] == 2 && GetUserFlagBits(client) & g_eCvars[g_cvarAdminFlag][aCache]))
				{
					AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "gift_package", "%t", "Package Gift");
					++m_iPosition;
				}

				for(new i=0;i<g_iMenuHandlers;++i)
				{
					if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
						continue;
					Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnMenu]);
					Call_PushCellRef(m_hMenu);
					Call_PushCell(client);
					Call_PushCell(parent);
					Call_Finish();
				}
			}
		}
	}
	
	for(new i=0;i<g_iItems;++i)
	{
		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]))
		{
			new m_iPrice = Store_GetLowestPrice(i);

			// This is a package
			if(g_eItems[i][iHandler] == g_iPackageHandler)
			{
				if(!Store_PackageHasClientItem(target, i, g_bInvMode[client]))
					continue;

				new m_iStyle = ITEMDRAW_DEFAULT;
				if(g_eCvars[g_cvarShowVIP][aCache] && !GetClientPrivilege(target, g_eItems[i][iFlagBits], m_iFlags))
					m_iStyle = ITEMDRAW_DISABLED;
				
				IntToString(i, STRING(m_szId));
				if(g_eItems[i][iPrice] == -1 || Store_HasClientItem(target, i))
					AddMenuItem(m_hMenu, m_szId, g_eItems[i][szName], m_iStyle);
				else if(!g_bInvMode[client] && g_eItems[i][iPlans]==0 && g_eItems[i][bBuyable])
					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]);
				else if(!g_bInvMode[client])
					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]);
				++m_iPosition;
			}
			// This is a normal item
			else
			{
				IntToString(i, STRING(m_szId));
				if(Store_HasClientItem(target, i))
				{
					if(Store_IsEquipped(target, i))
						InsertMenuItemEx(m_hMenu, m_iPosition, ITEMDRAW_DEFAULT, m_szId, "%t", "Item Equipped", g_eItems[i][szName]);
					else
						InsertMenuItemEx(m_hMenu, m_iPosition, ITEMDRAW_DEFAULT, m_szId, "%t", "Item Bought", g_eItems[i][szName]);
				}
				else if(!g_bInvMode[client])
				{				
					new m_iStyle = ITEMDRAW_DEFAULT;
					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)))
						m_iStyle = ITEMDRAW_DISABLED;
					
					if(!g_eItems[i][bBuyable])
						continue;

					if(g_eItems[i][iPlans]==0)
						AddMenuItemEx(m_hMenu, m_iStyle, m_szId, "%t", "Item Available", g_eItems[i][szName], g_eItems[i][iPrice]);
					else
						AddMenuItemEx(m_hMenu, m_iStyle, m_szId, "%t", "Item Plan Available", g_eItems[i][szName], g_eItems[i][iPrice]);
				}
			}
		}
	}
	
	if(last == -1)
		DisplayMenu(m_hMenu, client, 0);
	else
		DisplayMenuAtItem(m_hMenu, client, (last/GetMenuPagination(m_hMenu))*GetMenuPagination(m_hMenu), 0);
}

public MenuHandler_Store(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		new target = g_iMenuClient[client];
		// Confirmation was given
		if(menu == INVALID_HANDLE)
		{
			if(param2 == 0)
			{
				g_iMenuBack[client]=1;
				new m_iPrice = 0;
				if(g_iSelectedPlan[client]==-1)
					m_iPrice = g_eItems[g_iSelectedItem[client]][iPrice];
				else
					m_iPrice = g_ePlans[g_iSelectedItem[client]][g_iSelectedPlan[client]][iPrice];

				if(g_eClients[target][iCredits]>=m_iPrice && !Store_HasClientItem(target, g_iSelectedItem[client]))
					Store_BuyItem(target, g_iSelectedItem[client], g_iSelectedPlan[client]);

				if(g_eItems[g_iSelectedItem[client]][iHandler] == g_iPackageHandler)
					DisplayStoreMenu(client, g_iSelectedItem[client]);
				else
					DisplayItemMenu(client, g_iSelectedItem[client]);
			}
			else if(param2 == 1)
			{
				Store_SellItem(target, g_iSelectedItem[client]);
				Store_DisplayPreviousMenu(client);
			}
		}
		else
		{
			new String:m_szId[64];
			GetMenuItem(menu, param2, STRING(m_szId));
			
			g_iLastSelection[client]=param2;
			
			// We are selling a package
			if(strcmp(m_szId, "sell_package")==0)
			{
				if(g_eCvars[g_cvarConfirmation][aCache])
				{
					decl String:m_szTitle[128];
					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]));
					Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 1);
					return;
				}
				else
				{
					Store_SellItem(target, g_iSelectedItem[client]);
					Store_DisplayPreviousMenu(client);
				}
			}
			// We are gifting a package
			else if(strcmp(m_szId, "gift_package")==0)
			{
				DisplayPlayerMenu(client);
			}
			// This is menu handler stuff
			else if(!(48 <= m_szId[0] <= 57))
			{
				decl ret;
				for(new i=0;i<g_iMenuHandlers;++i)
				{
					Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnHandler]);
					Call_PushCell(target);
					Call_PushString(m_szId);
					Call_PushCell(g_iSelectedItem[client]);
					Call_Finish(ret);

					if(ret)
						break;
				}
			}
			// We are being boring
			else
			{
				new m_iId = StringToInt(m_szId);
				g_iMenuBack[client]=g_eItems[m_iId][iParent];
				g_iSelectedItem[client] = m_iId;
				g_iSelectedPlan[client] = -1;
				
				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)				{
					if(g_eItems[m_iId][iPlans] > 0)
					{
						DisplayPlanMenu(client, m_iId);
						return;
					}
					else
						if(g_eCvars[g_cvarConfirmation][aCache])
						{
							decl String:m_szTitle[128];
							Format(STRING(m_szTitle), "%t", "Confirm_Buy", g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);
							Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 0);
							return;
						}
						else
							Store_BuyItem(target, m_iId);
				}
				
				if(g_eItems[m_iId][iHandler] != g_iPackageHandler)
				{				
					if(Store_HasClientItem(target, m_iId))
					{
						if(g_eTypeHandlers[g_eItems[m_iId][iHandler]][bRaw])
						{
							Call_StartFunction(g_eTypeHandlers[g_eItems[m_iId][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[m_iId][iHandler]][fnUse]);
							Call_PushCell(target);
							Call_PushCell(m_iId);
							Call_Finish();
						}
						else
							DisplayItemMenu(client, m_iId);
					}
					else
						DisplayStoreMenu(client, g_iMenuBack[client]);					
				}
				else
				{			
					if(Store_HasClientItem(target, m_iId) || g_eItems[m_iId][iPrice] == -1)
						DisplayStoreMenu(client, m_iId);
					else
						DisplayStoreMenu(client, g_eItems[m_iId][iParent]);
				}
			}
		}
	}
	else if(action==MenuAction_Cancel)
		if (param2 == MenuCancel_ExitBack)
			Store_DisplayPreviousMenu(client);
}

public DisplayItemMenu(client, itemid)
{
	g_iMenuNum[client] = 1;
	g_iMenuBack[client] = g_eItems[itemid][iParent];
	new target = g_iMenuClient[client];

	new Handle:m_hMenu = CreateMenu(MenuHandler_Item);
	SetMenuExitBackButton(m_hMenu, true);
	
	new bool:m_bEquipped = Store_IsEquipped(target, itemid);
	new String:m_szTitle[256];
	new idx = 0;
	if(m_bEquipped)
		idx = Format(STRING(m_szTitle), "%t\n%t", "Produs Utilizat", g_eItems[itemid][szName], "Credite De Titlu", g_eClients[target][iCredits]);
	else
		idx = Format(STRING(m_szTitle), "%s\n%t", g_eItems[itemid][szName], "Credite De Titlu", g_eClients[target][iCredits]);

	new m_iExpiration = Store_GetExpiration(target, itemid);
	if(m_iExpiration != 0)
	{
		m_iExpiration = m_iExpiration-GetTime();
		new m_iDays = m_iExpiration/(24*60*60);
		new m_iHours = (m_iExpiration-m_iDays*24*60*60)/(60*60);
		Format(m_szTitle[idx-1], sizeof(m_szTitle)-idx-1, "\n%t", "Expira", m_iDays, m_iHours);
	}
	
	SetMenuTitle(m_hMenu, m_szTitle);
	
	if(g_eTypeHandlers[g_eItems[itemid][iHandler]][bEquipable])
		if(!m_bEquipped)
			AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "0", "%t", "Element Echipat");
		else
			AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "3", "%t", "Element Neechipat");
	else
		AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "0", "%t", "Utilizeaza");
		
	if(!Store_IsClientVIP(target) && !Store_IsItemInBoughtPackage(target, itemid))
	{
		new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, itemid)*Float:g_eCvars[g_cvarSellRatio][aCache]);
		if(m_iCredits!=0)
		{
			new uid = Store_GetClientItemId(client, itemid);
			if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
			{
				new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
				new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
				if(m_iLeft < 0)
					m_iLeft = 0;
				m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
			}

			if(g_eCvars[g_cvarSellEnabled][aCache])
				AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "1", "%t", "Vinde Element", m_iCredits);
			if(g_eCvars[g_cvarGiftEnabled][aCache] == 1 || (g_eCvars[g_cvarGiftEnabled][aCache] == 2 && GetUserFlagBits(client) & g_eCvars[g_cvarAdminFlag][aCache]))
				AddMenuItemEx(m_hMenu, ITEMDRAW_DEFAULT, "2", "%t", "Ofera Element");
		}
	}

	for(new i=0;i<g_iMenuHandlers;++i)
	{
		if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
			continue;
		Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnMenu]);
		Call_PushCellRef(m_hMenu);
		Call_PushCell(client);
		Call_PushCell(itemid);
		Call_Finish();
	}
	
	DisplayMenu(m_hMenu, client, 0);
}

public DisplayPlanMenu(client, itemid)
{
	g_iMenuNum[client] = 1;
	new target = g_iMenuClient[client];

	new Handle:m_hMenu = CreateMenu(MenuHandler_Plan);
	SetMenuExitBackButton(m_hMenu, true);
	
	SetMenuTitle(m_hMenu, "%s\n%t", g_eItems[itemid][szName], "Credite De Titlu", g_eClients[target][iCredits]);
	
	for(new i=0;i<g_eItems[itemid][iPlans];++i)
	{
		AddMenuItemEx(m_hMenu, (g_eClients[target][iCredits]>=g_ePlans[itemid][i][iPrice]?ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED), "", "%t",  "Valabilitate Item", g_ePlans[itemid][i][szName], g_ePlans[itemid][i][iPrice]);
	}
	
	DisplayMenu(m_hMenu, client, 0);
}

public MenuHandler_Plan(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		new target = g_iMenuClient[client];
		g_iSelectedPlan[client]=param2;
		g_iMenuNum[client]=5;

		if(g_eCvars[g_cvarConfirmation][aCache])
		{
			decl String:m_szTitle[128];
			Format(STRING(m_szTitle), "%t", "Confirm_Buy", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType]);
			Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Store, 0);
			return;
		}
		else
		{
			Store_BuyItem(target, g_iSelectedItem[client], param2);
			DisplayItemMenu(client, g_iSelectedItem[client]);
		}
	}
	else if(action==MenuAction_Cancel)
		if (param2 == MenuCancel_ExitBack)
			Store_DisplayPreviousMenu(client);
}

public MenuHandler_Item(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		new target = g_iMenuClient[client];
		// Confirmation was sent
		if(menu == INVALID_HANDLE)
		{
			if(param2 == 0)
			{
				g_iMenuNum[client] = 1;
				Store_SellItem(target, g_iSelectedItem[client]);
				Store_DisplayPreviousMenu(client);
			}
		}
		else
		{
			decl String:m_szId[64];
			GetMenuItem(menu, param2, STRING(m_szId));
			
			new m_iId = StringToInt(m_szId);
			
			// Menu handlers
			if(!(48 <= m_szId[0] <= 57))
			{
				decl ret;
				for(new i=0;i<g_iMenuHandlers;++i)
				{
					if(g_eMenuHandlers[i][hPlugin] == INVALID_HANDLE)
						continue;
					Call_StartFunction(g_eMenuHandlers[i][hPlugin], g_eMenuHandlers[i][fnHandler]);
					Call_PushCell(client);
					Call_PushString(m_szId);
					Call_PushCell(g_iSelectedItem[client]);
					Call_Finish(ret);

					if(ret)
						break;
				}
			}
			// Player wants to equip this item
			else if(m_iId == 0)
			{
				new m_iRet = Store_UseItem(target, g_iSelectedItem[client]);
				if(GetClientMenu(client)==MenuSource_None && m_iRet == 0)
					DisplayItemMenu(client, g_iSelectedItem[client]);
			}
			// Player wants to sell this item
			else if(m_iId == 1)
			{
				if(g_eCvars[g_cvarConfirmation][aCache])
				{
					new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, g_iSelectedItem[client])*Float:g_eCvars[g_cvarSellRatio][aCache]);
					new uid = Store_GetClientItemId(client, g_iSelectedItem[client]);
					if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
					{
						new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
						new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
						if(m_iLeft < 0)
							m_iLeft = 0;
						m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
					}

					decl String:m_szTitle[128];
					Format(STRING(m_szTitle), "%t", "Confirm_Sell", g_eItems[g_iSelectedItem[client]][szName], g_eTypeHandlers[g_eItems[g_iSelectedItem[client]][iHandler]][szType], m_iCredits);
					g_iMenuNum[client] = 2;
					Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Item, 0);
				}
				else
				{
					Store_SellItem(target, g_iSelectedItem[client]);
					Store_DisplayPreviousMenu(client);
				}
			}
			// Player wants to gift this item
			else if(m_iId == 2)
			{
				g_iMenuNum[client] = 2;
				DisplayPlayerMenu(client);
			}
			// Player wants to unequip this item
			else if(m_iId == 3)
			{
				Store_UnequipItem(target, g_iSelectedItem[client]);
				DisplayItemMenu(client, g_iSelectedItem[client]);
			}
		}
	}
	else if(action==MenuAction_Cancel)
		if (param2 == MenuCancel_ExitBack)
			Store_DisplayPreviousMenu(client);
}

public DisplayPlayerMenu(client)
{
	g_iMenuNum[client] = 3;
	new target = g_iMenuClient[client];

	new m_iCount = 0;
	new Handle:m_hMenu = CreateMenu(MenuHandler_Gift);
	SetMenuExitBackButton(m_hMenu, true);
	SetMenuTitle(m_hMenu, "%t\n%t", "Cadou De Titlu", "Credite De Titlu", g_eClients[client][iCredits]);
	
	decl String:m_szID[11];
	decl m_iFlags;
	LoopIngamePlayers(i)
	{
		m_iFlags = GetUserFlagBits(i);
		if(!GetClientPrivilege(i, g_eItems[g_iSelectedItem[client]][iFlagBits], m_iFlags))
			continue;
		if(i != target && IsClientInGame(i) && !Store_HasClientItem(i, g_iSelectedItem[client]))
		{
			IntToString(g_eClients[i][iUserId], STRING(m_szID));
			AddMenuItem(m_hMenu, m_szID, g_eClients[i][szName]);
			++m_iCount;
		}
	}
	
	if(m_iCount == 0)
	{
		CloseHandle(m_hMenu);
		g_iMenuNum[client] = 1;
		DisplayItemMenu(client, g_iSelectedItem[client]);
		Chat(client, "%t", "Cadou Fara Jucator");
	}
	else
		DisplayMenu(m_hMenu, client, 0);
}

public MenuHandler_Gift(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{
		decl m_iItem, m_iReceiver;
		new target = g_iMenuClient[client];
	
		// Confirmation was given
		if(menu == INVALID_HANDLE)
		{
			m_iItem = Store_GetClientItemId(target, g_iSelectedItem[client]);
			m_iReceiver = GetClientOfUserId(param2);
			if(!m_iReceiver)
			{
				Chat(client, "%t", "Jucatorul s-a deconectat!");
				return;
			}
			Store_GiftItem(target, m_iReceiver, m_iItem);
			g_iMenuNum[client] = 1;
			Store_DisplayPreviousMenu(client);
		}
		else
		{
			decl String:m_szId[11];
			GetMenuItem(menu, param2, STRING(m_szId));
			
			new m_iId = StringToInt(m_szId);
			m_iReceiver = GetClientOfUserId(m_iId);
			if(!m_iReceiver)
			{
				Chat(client, "%t", "Jucatorul s-a deconectat!");
				return;
			}
				
			m_iItem = Store_GetClientItemId(target, g_iSelectedItem[client]);
			
			if(g_eCvars[g_cvarConfirmation][aCache])
			{
				decl String:m_szTitle[128];
				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]);
				Store_DisplayConfirmMenu(client, m_szTitle, MenuHandler_Gift, m_iId);
				return;
			}
			else
				Store_GiftItem(target, m_iReceiver, m_iItem);
			Store_DisplayPreviousMenu(client);
		}
	}
	else if(action==MenuAction_Cancel)
		if (param2 == MenuCancel_ExitBack)
			DisplayItemMenu(client, g_iSelectedItem[client]);
}

public MenuHandler_Confirm(Handle:menu, MenuAction:action, client, param2)
{
	if (action == MenuAction_End)
		CloseHandle(menu);
	else if (action == MenuAction_Select)
	{		
		if(param2 == 0)
		{
			decl String:m_szCallback[32];
			decl String:m_szData[11];
			GetMenuItem(menu, 0, STRING(m_szCallback));
			GetMenuItem(menu, 1, STRING(m_szData));
			new m_iPos = FindCharInString(m_szCallback, '.');
			m_szCallback[m_iPos] = 0;
			new Handle:m_hPlugin = Handle:StringToInt(m_szCallback);
			new Function:fnMenuCallback = Function:StringToInt(m_szCallback[m_iPos+1]);
			if(fnMenuCallback != INVALID_FUNCTION)
			{
				Call_StartFunction(m_hPlugin, fnMenuCallback);
				Call_PushCell(INVALID_HANDLE);
				Call_PushCell(MenuAction_Select);
				Call_PushCell(client);
				Call_PushCell(StringToInt(m_szData));
				Call_Finish();
			}
			else
				Store_DisplayPreviousMenu(client);
		}
		else
		{
			Store_DisplayPreviousMenu(client);
		}
	}
}

//////////////////////////////
//			CONVARS	 		//
//////////////////////////////

public ConVar_CreditTimer(index)
{
	new m_bTimer = (FloatCompare(g_eCvars[g_cvarCreditTimer][aCache], 0.0)==0 || g_eCvars[g_cvarCreditAmountActive][aCache]==0);
	for(new i=1;i<=MaxClients;++i)
	{
		ClearTimer(g_eClients[i][hCreditTimer]);
		if(m_bTimer && IsClientInGame(i))
			g_eClients[i][hCreditTimer] = Store_CreditTimer(i);
	}
}

//////////////////////////////
//			TIMERS	 		//
//////////////////////////////

public Action:Timer_CreditTimer(Handle:timer, any:userid)
{
	new client = GetClientOfUserId(userid);
	if(!client || !IsClientInGame(client))
		return Plugin_Continue;
	
	decl m_iCredits;

	if(2<=GetClientTeam(client)<=3)
		m_iCredits = g_eCvars[g_cvarCreditAmountActive][aCache];
	else
		m_iCredits = g_eCvars[g_cvarCreditAmountInactive][aCache];

	if(m_iCredits)
	{
		g_eClients[client][iCredits] += m_iCredits;
		if(g_eCvars[g_cvarCreditMessages][aCache])
			Chat(client, "%t", "Credite castigate pentru activitatea dumneavoastra!", m_iCredits);
		Store_LogMessage(client, m_iCredits, "Pentru Activitate");
	}

	return Plugin_Continue;
}

public Action:Timer_DatabaseTimeout(Handle:timer, any:userid)
{
	// Database is connected successfully
	if(g_hDatabase != INVALID_HANDLE)
		return Plugin_Stop;

	if(g_iDatabaseRetries < g_eCvars[g_cvarDatabaseRetries][aCache])
	{
		SQL_TConnect(SQLCallback_Connect, g_eCvars[g_cvarDatabaseEntry][sCache]);
		CreateTimer(Float:g_eCvars[g_cvarDatabaseTimeout][aCache], Timer_DatabaseTimeout);
		++g_iDatabaseRetries;
	}
	else
	{
		SetFailState("Database connection failed to initialize after %d retrie(s)", g_eCvars[g_cvarDatabaseRetries][aCache]);
	}


	return Plugin_Stop;
}

//////////////////////////////
//		SQL CALLBACKS		//
//////////////////////////////

public SQLCallback_Connect(Handle:owner, Handle:hndl, const String:error[], any:data)
{
	if(hndl==INVALID_HANDLE)
	{
		SetFailState("Failed to connect to SQL database. Error: %s", error);
	}
	else
	{
		// If it's already connected we are good to go
		if(g_hDatabase != INVALID_HANDLE)
			return;
			
		g_hDatabase = hndl;
		decl String:m_szDriver[2];
		SQL_ReadDriver(g_hDatabase, STRING(m_szDriver));
		if(m_szDriver[0] == 'm')
		{
			g_bMySQL = true;
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_players` (\
										  `id` int(11) NOT NULL AUTO_INCREMENT,\
										  `authid` varchar(32) NOT NULL,\
										  `name` varchar(64) NOT NULL,\
										  `credits` int(11) NOT NULL,\
										  `date_of_join` int(11) NOT NULL,\
										  `date_of_last_join` int(11) NOT NULL,\
										  PRIMARY KEY (`id`),\
										  UNIQUE KEY `id` (`id`),\
										  UNIQUE KEY `authid` (`authid`)\
										)");
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_items` (\
										  `id` int(11) NOT NULL AUTO_INCREMENT,\
										  `player_id` int(11) NOT NULL,\
										  `type` varchar(16) NOT NULL,\
										  `unique_id` varchar(256) NOT NULL,\
										  `date_of_purchase` int(11) NOT NULL,\
										  `date_of_expiration` int(11) NOT NULL,\
										  PRIMARY KEY (`id`)\
										)");
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_equipment` (\
										  `player_id` int(11) NOT NULL,\
										  `type` varchar(16) NOT NULL,\
										  `unique_id` varchar(256) NOT NULL,\
										  `slot` int(11) NOT NULL\
										)");
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_logs` (\
										  `id` int(11) NOT NULL AUTO_INCREMENT,\
										  `player_id` int(11) NOT NULL,\
										  `credits` int(11) NOT NULL,\
										  `reason` varchar(256) NOT NULL,\
										  `date` int(11) NOT NULL,\
										  PRIMARY KEY (`id`)\
										)");
			SQL_TQuery(g_hDatabase, SQLCallback_NoError, "ALTER TABLE store_items ADD COLUMN price_of_purchase int(11)");
			decl String:m_szQuery[512];
			Format(STRING(m_szQuery), "CREATE TABLE IF NOT EXISTS `%s` (\
										  `id` int(11) NOT NULL AUTO_INCREMENT,\
										  `parent_id` int(11) NOT NULL DEFAULT '-1',\
										  `item_price` int(32) NOT NULL,\
										  `item_type` varchar(64) NOT NULL,\
										  `item_flag` varchar(64) NOT NULL,\
										  `item_name` varchar(64) NOT NULL,\
										  `additional_info` text NOT NULL,\
										  `item_status` tinyint(1) NOT NULL,\
										  `supported_game` varchar(64) NOT NULL,\
										  PRIMARY KEY (`id`)\
										)", g_eCvars[g_cvarItemsTable][sCache]);
			SQL_TVoid(g_hDatabase, m_szQuery);
		}
		else
		{
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_players` (\
										  `id` INTEGER PRIMARY KEY AUTOINCREMENT,\
										  `authid` varchar(32) NOT NULL,\
										  `name` varchar(64) NOT NULL,\
										  `credits` int(11) NOT NULL,\
										  `date_of_join` int(11) NOT NULL,\
										  `date_of_last_join` int(11) NOT NULL\
										)");
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_items` (\
										  `id` INTEGER PRIMARY KEY AUTOINCREMENT,\
										  `player_id` int(11) NOT NULL,\
										  `type` varchar(16) NOT NULL,\
										  `unique_id` varchar(256) NOT NULL,\
										  `date_of_purchase` int(11) NOT NULL,\
										  `date_of_expiration` int(11) NOT NULL\
										)");
			SQL_TVoid(g_hDatabase, "CREATE TABLE IF NOT EXISTS `store_equipment` (\
										  `player_id` int(11) NOT NULL,\
										  `type` varchar(16) NOT NULL,\
										  `unique_id` varchar(256) NOT NULL,\
										  `slot` int(11) NOT NULL\
										)");
			SQL_TQuery(g_hDatabase, SQLCallback_NoError, "ALTER TABLE store_items ADD COLUMN price_of_purchase int(11)");
			if(strcmp(g_eCvars[g_cvarItemSource][sCache], "database")==0)
			{
	
				SetFailState("Database item source can only be used with MySQL databases");
			}
		}
		
		// Do some housekeeping
		decl String:m_szQuery[256];
		Format(STRING(m_szQuery), "DELETE FROM store_items WHERE `date_of_expiration` <> 0 AND `date_of_expiration` < %d", GetTime());
		SQL_TVoid(g_hDatabase, m_szQuery);
	}
}

public SQLCallback_LoadClientInventory_Credits(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{
		new client = GetClientOfUserId(userid);
		if(!client)
			return;
		
		decl String:m_szQuery[256];
		decl String:m_szSteamID[32];
		new m_iTime = GetTime();
		g_eClients[client][iUserId] = userid;
		g_eClients[client][iItems] = -1;
		GetLegacyAuthString(client, STRING(m_szSteamID), false);
		strcopy(g_eClients[client][szAuthId], 32, m_szSteamID[8]);
		GetClientName(client, g_eClients[client][szName], 64);
		SQL_EscapeString(g_hDatabase, g_eClients[client][szName], g_eClients[client][szNameEscaped], 128);
		
		if(SQL_FetchRow(hndl))
		{
			g_eClients[client][iId] = SQL_FetchInt(hndl, 0);
			g_eClients[client][iCredits] = SQL_FetchInt(hndl, 3);
			g_eClients[client][iOriginalCredits] = SQL_FetchInt(hndl, 3);
			g_eClients[client][iDateOfJoin] = SQL_FetchInt(hndl, 4);
			g_eClients[client][iDateOfLastJoin] = m_iTime;
			
			Format(STRING(m_szQuery), "SELECT * FROM store_items WHERE `player_id`=%d", g_eClients[client][iId]);
			SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Items, m_szQuery, userid);

			Store_LogMessage(client, g_eClients[client][iCredits], "Amount of credits when the player joined");
			
			Store_SaveClientData(client);
		}
		else
		{
			Format(STRING(m_szQuery), "INSERT INTO store_players (`authid`, `name`, `credits`, `date_of_join`, `date_of_last_join`) VALUES(\"%s\", '%s', %d, %d, %d)",
						g_eClients[client][szAuthId], g_eClients[client][szNameEscaped], g_eCvars[g_cvarStartCredits][aCache], m_iTime, m_iTime);
			SQL_TQuery(g_hDatabase, SQLCallback_InsertClient, m_szQuery, userid);
			g_eClients[client][iCredits] = g_eCvars[g_cvarStartCredits][aCache];
			g_eClients[client][iOriginalCredits] = g_eCvars[g_cvarStartCredits][aCache];
			g_eClients[client][iDateOfJoin] = m_iTime;
			g_eClients[client][iDateOfLastJoin] = m_iTime;
			g_eClients[client][bLoaded] = true;
			g_eClients[client][iItems] = 0;

			if(g_eCvars[g_cvarStartCredits][aCache] > 0)
				Store_LogMessage(client, g_eCvars[g_cvarStartCredits][aCache], "Start credits");
		}
		
		g_eClients[client][hCreditTimer] = Store_CreditTimer(client);
	}
}

public SQLCallback_LoadClientInventory_Items(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{	
		new client = GetClientOfUserId(userid);
		if(!client)
			return;

		decl String:m_szQuery[256];
		Format(STRING(m_szQuery), "SELECT * FROM store_equipment WHERE `player_id`=%d", g_eClients[client][iId]);
		SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Equipment, m_szQuery, userid);

		if(!SQL_GetRowCount(hndl))
		{
			g_eClients[client][bLoaded] = true;
			g_eClients[client][iItems] = 0;
			return;
		}
		
		decl String:m_szUniqueId[PLATFORM_MAX_PATH];
		decl String:m_szType[16];
		decl m_iExpiration;
		decl m_iUniqueId;
		new m_iTime = GetTime();
		
		new i = 0;
		while(SQL_FetchRow(hndl))
		{
			m_iUniqueId = -1;
			m_iExpiration = SQL_FetchInt(hndl, 5);
			if(m_iExpiration && m_iExpiration<=m_iTime)
				continue;
			
			SQL_FetchString(hndl, 2, STRING(m_szType));
			SQL_FetchString(hndl, 3, STRING(m_szUniqueId));
			while((m_iUniqueId = Store_GetItemId(m_szType, m_szUniqueId, m_iUniqueId))!=-1)
			{
				g_eClientItems[client][i][iId] = SQL_FetchInt(hndl, 0);
				g_eClientItems[client][i][iUniqueId] = m_iUniqueId;
				g_eClientItems[client][i][bSynced] = true;
				g_eClientItems[client][i][bDeleted] = false;
				g_eClientItems[client][i][iDateOfPurchase] = SQL_FetchInt(hndl, 4);
				g_eClientItems[client][i][iDateOfExpiration] = m_iExpiration;
				g_eClientItems[client][i][iPriceOfPurchase] = SQL_FetchInt(hndl, 6);
			
				++i;
			}
		}
		g_eClients[client][iItems] = i;
	}
}

public SQLCallback_LoadClientInventory_Equipment(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{
		new client = GetClientOfUserId(userid);
		if(!client)
			return;
		
		decl String:m_szUniqueId[PLATFORM_MAX_PATH];
		decl String:m_szType[16];
		decl m_iUniqueId;
		
		while(SQL_FetchRow(hndl))
		{
			SQL_FetchString(hndl, 1, STRING(m_szType));
			SQL_FetchString(hndl, 2, STRING(m_szUniqueId));
			m_iUniqueId = Store_GetItemId(m_szType, m_szUniqueId);
			if(m_iUniqueId == -1)
				continue;
				
			if(!Store_HasClientItem(client, m_iUniqueId))
				Store_UnequipItem(client, m_iUniqueId);
			else
				Store_UseItem(client, m_iUniqueId, true, SQL_FetchInt(hndl, 3));
		}
		g_eClients[client][bLoaded] = true;
	}
}

public SQLCallback_RefreshCredits(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{
		new client = GetClientOfUserId(userid);
		if(!client)
			return;
			
		if(SQL_FetchRow(hndl))
		{
			g_eClients[client][iCredits] = SQL_FetchInt(hndl, 3);
			g_eClients[client][iOriginalCredits] = SQL_FetchInt(hndl, 3);
		}
	}
}

public SQLCallback_InsertClient(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{
		new client = GetClientOfUserId(userid);
		if(!client)
			return;
			
		g_eClients[client][iId] = SQL_GetInsertId(hndl);
	}
}

public SQLCallback_ReloadConfig(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
	{
		SetFailState("Error happened reading the config table. The plugin cannot continue.", error);
	}
	else
	{
		decl String:m_szType[64];
		decl String:m_szFlag[64];
		decl String:m_szInfo[2048];
		decl String:m_szKey[64];
		decl String:m_szValue[256];
		
		decl Handle:m_hKV;
		
		decl bool:m_bSuccess;
		
		decl m_iLength;
		decl m_iHandler;
		new m_iIndex = 0;
	
		while(SQL_FetchRow(hndl))
		{
			if(g_iItems == STORE_MAX_ITEMS)
				return;
				
			if(!SQL_FetchInt(hndl, 7))
				continue;
			
			g_eItems[g_iItems][iId] = SQL_FetchInt(hndl, 0);
			g_eItems[g_iItems][iParent] = SQL_FetchInt(hndl, 1);
			g_eItems[g_iItems][iPrice] = SQL_FetchInt(hndl, 2);
			
			IntToString(g_eItems[g_iItems][iId], g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);
			
			SQL_FetchString(hndl, 3, STRING(m_szType));
			m_iHandler = Store_GetTypeHandler(m_szType);
			if(m_iHandler == -1)
				continue;
			
			g_eItems[g_iItems][iHandler] = m_iHandler;
			
			SQL_FetchString(hndl, 4, STRING(m_szFlag));
			g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlag);
			
			SQL_FetchString(hndl, 5, g_eItems[g_iItems][szName], ITEM_NAME_LENGTH);
			SQL_FetchString(hndl, 6, STRING(m_szInfo));
			
			m_hKV = CreateKeyValues("Additional Info");
			
			m_iLength = strlen(m_szInfo);
			while(m_iIndex != m_iLength)
			{
				m_iIndex += strcopy(m_szKey, StrContains(m_szInfo[m_iIndex], "="), m_szInfo[m_iIndex])+2;
				m_iIndex += strcopy(m_szValue, StrContains(m_szInfo[m_iIndex], "\";"), m_szInfo[m_iIndex])+2; // \"
				
				KvJumpToKey(m_hKV, m_szKey, true);
				KvSetString(m_hKV, m_szKey, m_szValue);
				
				m_bSuccess = true;
				if(g_eTypeHandlers[m_iHandler][fnConfig]!=INVALID_FUNCTION)
				{
					Call_StartFunction(g_eTypeHandlers[m_iHandler][hPlugin], g_eTypeHandlers[m_iHandler][fnConfig]);
					Call_PushCellRef(m_hKV);
					Call_PushCell(g_iItems);
					Call_Finish(m_bSuccess); 
				}
				
				if(m_bSuccess)
					++g_iItems;
			}
			CloseHandle(m_hKV);
		}
	}
}

public SQLCallback_ResetPlayer(Handle:owner, Handle:hndl, const String:error[], any:userid)
{
	if(hndl==INVALID_HANDLE)
		LogError("Error happened. Error: %s", error);
	else
	{
		new client = GetClientOfUserId(userid);

		if(SQL_GetRowCount(hndl))
		{
			SQL_FetchRow(hndl);
			new id = SQL_FetchInt(hndl, 0);
			decl String:m_szAuthId[32];
			SQL_FetchString(hndl, 1, STRING(m_szAuthId));

			decl String:m_szQuery[512];
			Format(STRING(m_szQuery), "DELETE FROM store_players WHERE id=%d", id);
			SQL_TVoid(g_hDatabase, m_szQuery);
			Format(STRING(m_szQuery), "DELETE FROM store_items WHERE player_id=%d", id);
			SQL_TVoid(g_hDatabase, m_szQuery);
			Format(STRING(m_szQuery), "DELETE FROM store_equipment WHERE player_id=%d", id);
			SQL_TVoid(g_hDatabase, m_szQuery);

			ChatAll("%t", "Jucatorul a fost resetat!", m_szAuthId);

		}
		else
			if(client)
				Chat(client, "%t", "Credite Negasite!");
	}
}

//////////////////////////////
//			STOCKS			//
//////////////////////////////

public Store_LoadClientInventory(client)
{
	if(g_hDatabase == INVALID_HANDLE)
	{
		LogError("Database connection is lost or not yet initialized.");
		return;
	}
	
	decl String:m_szQuery[256];
	decl String:m_szAuthId[32];

	GetLegacyAuthString(client, STRING(m_szAuthId));
	if(m_szAuthId[0] == 0)
		return;

	Format(STRING(m_szQuery), "SELECT * FROM store_players WHERE `authid`=\"%s\"", m_szAuthId[8]);

	SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Credits, m_szQuery, g_eClients[client][iUserId]);
}

public Store_SaveClientInventory(client)
{
	if(g_hDatabase == INVALID_HANDLE)
	{
		LogError("Database connection is lost or not yet initialized.");
		return;
	}
	
	// Player disconnected before his inventory was even fetched
	if(g_eClients[client][iCredits]==-1 && g_eClients[client][iItems]==-1)
		return;
	
	decl String:m_szQuery[256];
	decl String:m_szType[16];
	decl String:m_szUniqueId[PLATFORM_MAX_PATH];
	
	for(new i=0;i<g_eClients[client][iItems];++i)
	{
		strcopy(STRING(m_szType), g_eTypeHandlers[g_eItems[g_eClientItems[client][i][iUniqueId]][iHandler]][szType]);
		strcopy(STRING(m_szUniqueId), g_eItems[g_eClientItems[client][i][iUniqueId]][szUniqueId]);
	
		if(!g_eClientItems[client][i][bSynced] && !g_eClientItems[client][i][bDeleted])
		{
			g_eClientItems[client][i][bSynced] = true;
			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]);
			SQL_TVoid(g_hDatabase, m_szQuery);
		} else if(g_eClientItems[client][i][bSynced] && g_eClientItems[client][i][bDeleted])
		{
			// Might have been synced already but ID wasn't acquired
			if(g_eClientItems[client][i][iId]==-1)
				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);
			else
				Format(STRING(m_szQuery), "DELETE FROM store_items WHERE `id`=%d", g_eClientItems[client][i][iId]);
			SQL_TVoid(g_hDatabase, m_szQuery);
		}
	}
}

public Store_SaveClientEquipment(client)
{
	decl String:m_szQuery[256];
	decl m_iId;
	for(new i=0;i<STORE_MAX_HANDLERS;++i)
	{
		for(new a=0;a<STORE_MAX_SLOTS;++a)
		{
			m_iId = i*STORE_MAX_SLOTS+a;
			if(g_eClients[client][aEquipmentSynced][m_iId] == g_eClients[client][aEquipment][m_iId])
				continue;
			else if(g_eClients[client][aEquipmentSynced][m_iId] != -2)
				if(g_eClients[client][aEquipment][m_iId]==-1)
					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);
				else
					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);
				
			else
				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);

			SQL_TVoid(g_hDatabase, m_szQuery);
			g_eClients[client][aEquipmentSynced][m_iId] = g_eClients[client][aEquipment][m_iId];
		}
	}
}

public Store_SaveClientData(client)
{
	if(g_hDatabase == INVALID_HANDLE)
	{
		LogError("Database connection is lost or not yet initialized.");
		return;
	}
	
	if((g_eClients[client][iCredits]==-1 && g_eClients[client][iItems]==-1) || !g_eClients[client][bLoaded])
		return;
	
	decl String:m_szQuery[256];
	if(g_bMySQL)
		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]);
	else
		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]);

	g_eClients[client][iOriginalCredits] = g_eClients[client][iCredits];

	SQL_TVoid(g_hDatabase, m_szQuery);
}

public Store_DisconnectClient(client)
{
	Store_LogMessage(client, g_eClients[client][iCredits], "Amount of credits when the player left");
	g_eClients[client][iCredits] = -1;
	g_eClients[client][iOriginalCredits] = -1;
	g_eClients[client][iItems] = -1;
	g_eClients[client][bLoaded] = false;
	ClearTimer(g_eClients[client][hCreditTimer]);
}

Store_GetItemId(String:type[], String:uid[], start=-1)
{
	for(new i=start+1;i<g_iItems;++i)
		if(strcmp(g_eTypeHandlers[g_eItems[i][iHandler]][szType], type)==0 && strcmp(g_eItems[i][szUniqueId], uid)==0 && g_eItems[i][iPrice] >= 0)
			return i;
	return -1;
}

Store_BuyItem(client, itemid, plan=-1)
{
	if(Store_HasClientItem(client, itemid))
		return;
	
	new m_iPrice = 0;
	if(plan==-1)
		m_iPrice = g_eItems[itemid][iPrice];
	else
		m_iPrice = g_ePlans[itemid][plan][iPrice];	

	if(g_eClients[client][iCredits]<m_iPrice)
		return;
		
	new m_iId = g_eClients[client][iItems]++;
	g_eClientItems[client][m_iId][iId] = -1;
	g_eClientItems[client][m_iId][iUniqueId] = itemid;
	g_eClientItems[client][m_iId][iDateOfPurchase] = GetTime();
	g_eClientItems[client][m_iId][iDateOfExpiration] = (plan==-1?0:(g_ePlans[itemid][plan][iTime]?GetTime()+g_ePlans[itemid][plan][iTime]:0));
	g_eClientItems[client][m_iId][iPriceOfPurchase] = m_iPrice;
	g_eClientItems[client][m_iId][bSynced] = false;
	g_eClientItems[client][m_iId][bDeleted] = false;
	
	g_eClients[client][iCredits] -= m_iPrice;

	Store_LogMessage(client, -g_eItems[itemid][iPrice], "Bought a %s %s", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
	
	Chat(client, "%t", "Articol cumparat prin chat!", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
}

public Store_SellItem(client, itemid)
{	
	new m_iCredits = RoundToFloor(Store_GetClientItemPrice(client, itemid)*Float:g_eCvars[g_cvarSellRatio][aCache]);
	new uid = Store_GetClientItemId(client, itemid);
	if(g_eClientItems[client][uid][iDateOfExpiration] != 0)
	{
		new m_iLength = g_eClientItems[client][uid][iDateOfExpiration]-g_eClientItems[client][uid][iDateOfPurchase];
		new m_iLeft = g_eClientItems[client][uid][iDateOfExpiration]-GetTime();
		if(m_iLeft<0)
			m_iLeft = 0;
		m_iCredits = RoundToCeil(m_iCredits*float(m_iLeft)/float(m_iLength));
	}

	g_eClients[client][iCredits] += m_iCredits;
	Chat(client, "%t", "Item vandut prin chat!", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);
	
	Store_LogMessage(client, m_iCredits, "Sold a %s %s", g_eItems[itemid][szName], g_eTypeHandlers[g_eItems[itemid][iHandler]][szType]);

	Store_RemoveItem(client, itemid);
}

public Store_GiftItem(client, receiver, item)
{
	new m_iId = g_eClientItems[client][item][iUniqueId];
	new target = g_iMenuClient[client];
	g_eClientItems[client][item][bDeleted] = true;
	Store_UnequipItem(client, m_iId);

	g_eClientItems[receiver][g_eClients[receiver][iItems]][iId] = -1;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iUniqueId] = m_iId;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][bSynced] = false;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][bDeleted] = false;
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfPurchase] = g_eClientItems[target][item][iDateOfPurchase];
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iDateOfExpiration] = g_eClientItems[target][item][iDateOfExpiration];
	g_eClientItems[receiver][g_eClients[receiver][iItems]][iPriceOfPurchase] = g_eClientItems[target][item][iPriceOfPurchase];
	
	++g_eClients[receiver][iItems];

	Chat(client, "%t", "Cadou trimit prin chat!", g_eClients[receiver][szName], g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);
	Chat(receiver, "%t", "Cadou primit prin chat!", g_eClients[target][szName], g_eItems[m_iId][szName], g_eTypeHandlers[g_eItems[m_iId][iHandler]][szType]);

	Store_LogMessage(client, 0, "Gifted a %s to %N", g_eItems[m_iId][szName], receiver);
}

public Store_GetClientItemId(client, itemid)
{
	for(new i=0;i<g_eClients[client][iItems];++i)
	{
		if(g_eClientItems[client][i][iUniqueId] == itemid && !g_eClientItems[client][i][bDeleted])
			return i;
	}
		
	return -1;
}

public Handle:Store_CreditTimer(client)
{
	return CreateTimer(g_eCvars[g_cvarCreditTimer][aCache], Timer_CreditTimer, g_eClients[client][iUserId], TIMER_REPEAT);
}

public ReadCoreCFG()
{
	new String:m_szFile[PLATFORM_MAX_PATH];
	BuildPath(Path_SM, STRING(m_szFile), "configs/core.cfg");

	new Handle:hParser = SMC_CreateParser();
	new String:error[128];
	new line = 0;
	new col = 0;

	SMC_SetReaders(hParser, Config_NewSection, Config_KeyValue, Config_EndSection);
	SMC_SetParseEnd(hParser, Config_End);

	new SMCError:result = SMC_ParseFile(hParser, m_szFile, line, col);
	CloseHandle(hParser);

	if (result != SMCError_Okay) 
	{
		SMC_GetErrorString(result, error, sizeof(error));
		LogError("%s on line %d, col %d of %s", error, line, col, m_szFile);
	}

}

public SMCResult:Config_NewSection(Handle:parser, const String:section[], bool:quotes) 
{
    if (StrEqual(section, "Core"))
    {
        return SMCParse_Continue;
    }
    return SMCParse_Continue;
}

public SMCResult:Config_KeyValue(Handle:parser, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes)
{
    if(StrEqual(key, "PublicChatTrigger", false))
        PublicChatTrigger = value[0];
    else if(StrEqual(key, "SilentChatTrigger", false))
        SilentChatTrigger = value[0];
    
    return SMCParse_Continue;
}

public SMCResult:Config_EndSection(Handle:parser) 
{
    return SMCParse_Continue;
}

public Config_End(Handle:parser, bool:halted, bool:failed) 
{
}  

public Store_ReloadConfig()
{
	g_iItems = 0;
	
	for(new i=0;i<g_iTypeHandlers;++i)
	{
		if(g_eTypeHandlers[i][fnReset] != INVALID_FUNCTION)
		{
			Call_StartFunction(g_eTypeHandlers[i][hPlugin], g_eTypeHandlers[i][fnReset]);
			Call_Finish();
		}
	}

	if(strcmp(g_eCvars[g_cvarItemSource][sCache], "database")==0)
	{
		decl String:m_szQuery[64];
		Format(STRING(m_szQuery), "SELECT * FROM %s WHERE supported_games LIKE \"%%%s%%\" OR supported_games = \"\"", g_eCvars[g_cvarItemsTable][sCache], g_szGameDir);
		SQL_TQuery(g_hDatabase, SQLCallback_ReloadConfig, m_szQuery);
	}
	else
	{	
		new String:m_szFile[PLATFORM_MAX_PATH];
		BuildPath(Path_SM, STRING(m_szFile), "configs/store/items.txt");
		new Handle:m_hKV = CreateKeyValues("Store");
		FileToKeyValues(m_hKV, m_szFile);
		if (!KvGotoFirstSubKey(m_hKV))
		{
			
			SetFailState("Failed to read configs/store/items.txt");
		}
		Store_WalkConfig(m_hKV);
		CloseHandle(m_hKV);
	}
}

Store_WalkConfig(&Handle:kv, parent=-1)
{
	decl String:m_szType[32];
	decl String:m_szGame[64];
	decl String:m_szFlags[64];
	decl m_iHandler;
	decl bool:m_bSuccess;
	do
	{
		if(g_iItems == STORE_MAX_ITEMS)
				continue;
		if (KvGetNum(kv, "enabled", 1) && KvGetNum(kv, "type", -1)==-1 && KvGotoFirstSubKey(kv))
		{
			KvGoBack(kv);
			KvGetSectionName(kv, g_eItems[g_iItems][szName], 64);
			KvGetSectionName(kv, g_eItems[g_iItems][szUniqueId], 64);
			ReplaceString(g_eItems[g_iItems][szName], 64, "\\n", "\n");
			KvGetString(kv, "shortcut", g_eItems[g_iItems][szShortcut], 64);
			KvGetString(kv, "flag", STRING(m_szFlags));
			KvGetString(kv, "games", STRING(m_szGame));
			if(m_szGame[0] != 0 && StrContains(m_szGame, g_szGameDir)==-1)
				continue;
			g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlags);
			g_eItems[g_iItems][iPrice] = KvGetNum(kv, "price", -1);
			g_eItems[g_iItems][bBuyable] = (KvGetNum(kv, "buyable", 1)?true:false);
			g_eItems[g_iItems][bIgnoreVIP] = (KvGetNum(kv, "ignore_vip", 0)?true:false);
			g_eItems[g_iItems][iHandler] = g_iPackageHandler;
			KvGotoFirstSubKey(kv);
			
			g_eItems[g_iItems][iParent] = parent;
			
			Store_WalkConfig(kv, g_iItems++);
			KvGoBack(kv);
		}
		else
		{
			if(!KvGetNum(kv, "enabled", 1))
				continue;

			KvGetString(kv, "games", STRING(m_szGame));
			if(m_szGame[0] != 0 && StrContains(m_szGame, g_szGameDir)==-1)
				continue;
				
			g_eItems[g_iItems][iParent] = parent;
			KvGetSectionName(kv, g_eItems[g_iItems][szName], ITEM_NAME_LENGTH);
			g_eItems[g_iItems][iPrice] = KvGetNum(kv, "price");
			g_eItems[g_iItems][bBuyable] = KvGetNum(kv, "buyable", 1)?true:false;
			g_eItems[g_iItems][bIgnoreVIP] = (KvGetNum(kv, "ignore_vip", 0)?true:false);

			
			KvGetString(kv, "type", STRING(m_szType));
			m_iHandler = Store_GetTypeHandler(m_szType);
			if(m_iHandler == -1)
				continue;

			KvGetString(kv, "flag", STRING(m_szFlags));
			g_eItems[g_iItems][iFlagBits] = ReadFlagString(m_szFlags);
			g_eItems[g_iItems][iHandler] = m_iHandler;
			
			if(KvGetNum(kv, "unique_id", -1)==-1)
				KvGetString(kv, g_eTypeHandlers[m_iHandler][szUniqueKey], g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);
			else
				KvGetString(kv, "unique_id", g_eItems[g_iItems][szUniqueId], PLATFORM_MAX_PATH);

			if(KvJumpToKey(kv, "Plans"))
			{
				KvGotoFirstSubKey(kv);
				new index=0;
				do
				{
					KvGetSectionName(kv, g_ePlans[g_iItems][index][szName], ITEM_NAME_LENGTH);
					g_ePlans[g_iItems][index][iPrice] = KvGetNum(kv, "price");
					g_ePlans[g_iItems][index][iTime] = KvGetNum(kv, "time");
					++index;
				} while (KvGotoNextKey(kv));

				g_eItems[g_iItems][iPlans]=index;

				KvGoBack(kv);
				KvGoBack(kv);
			}

			if(g_eItems[g_iItems][hAttributes])
				CloseHandle(g_eItems[g_iItems][hAttributes]);
			g_eItems[g_iItems][hAttributes] = INVALID_HANDLE;
			if(KvJumpToKey(kv, "Attributes"))
			{
				g_eItems[g_iItems][hAttributes] = CreateTrie();

				KvGotoFirstSubKey(kv, false);

				new String:m_szAttribute[64];
				new String:m_szValue[64];
				do
				{
					KvGetSectionName(kv, STRING(m_szAttribute));
					KvGetString(kv, NULL_STRING, STRING(m_szValue));
					SetTrieString(g_eItems[g_iItems][hAttributes], m_szAttribute, m_szValue);
				} while (KvGotoNextKey(kv, false));

				KvGoBack(kv);
				KvGoBack(kv);
			}
			
			m_bSuccess = true;
			if(g_eTypeHandlers[m_iHandler][fnConfig]!=INVALID_FUNCTION)
			{
				Call_StartFunction(g_eTypeHandlers[m_iHandler][hPlugin], g_eTypeHandlers[m_iHandler][fnConfig]);
				Call_PushCellRef(kv);
				Call_PushCell(g_iItems);
				Call_Finish(m_bSuccess); 
			}
			
			if(m_bSuccess)
				++g_iItems;
		}
	} while (KvGotoNextKey(kv));
}

public Store_GetTypeHandler(String:type[])
{
	for(new i=0;i<g_iTypeHandlers;++i)
	{
		if(strcmp(g_eTypeHandlers[i][szType], type)==0)
			return i;
	}
	return -1;
}

public Store_GetMenuHandler(String:id[])
{
	for(new i=0;i<g_iMenuHandlers;++i)
	{
		if(strcmp(g_eMenuHandlers[i][szIdentifier], id)==0)
			return i;
	}
	return -1;
}

public bool:Store_IsEquipped(client, itemid)
{
	for(new i=0;i<STORE_MAX_SLOTS;++i)
		if(g_eClients[client][aEquipment][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+i] == itemid)
			return true;
	return false;
}

public Store_GetExpiration(client, itemid)
{
	new uid = Store_GetClientItemId(client, itemid);
	if(uid<0)
		return 0;
	return g_eClientItems[client][uid][iDateOfExpiration];
}

Store_UseItem(client, itemid, bool:synced=false, slot=0)
{
	new m_iSlot = slot;
	if(g_eTypeHandlers[g_eItems[itemid][iHandler]][fnUse] != INVALID_FUNCTION)
	{
		new m_iReturn = -1;
		Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnUse]);
		Call_PushCell(client);
		Call_PushCell(itemid);
		Call_Finish(m_iReturn);
		
		if(m_iReturn != -1)
			m_iSlot = m_iReturn;
	}

	if(g_eTypeHandlers[g_eItems[itemid][iHandler]][bEquipable])
	{
		g_eClients[client][aEquipment][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot]=itemid;
		if(synced)
			g_eClients[client][aEquipmentSynced][g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot]=itemid;
	}
	else if(m_iSlot == 0)
	{
		Store_RemoveItem(client, itemid);
		return 1;
	}
	return 0;
}

Store_UnequipItem(client, itemid, bool:fn=true)
{
	new m_iSlot = 0;
	if(fn && itemid > 0 && g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove] != INVALID_FUNCTION)
	{
		Call_StartFunction(g_eTypeHandlers[g_eItems[itemid][iHandler]][hPlugin], g_eTypeHandlers[g_eItems[itemid][iHandler]][fnRemove]);
		Call_PushCell(client);
		Call_PushCell(itemid);
		Call_Finish(m_iSlot);
	}

	decl m_iId;
	if(g_eItems[itemid][iHandler] != g_iPackageHandler)
	{
		m_iId = g_eItems[itemid][iHandler]*STORE_MAX_SLOTS+m_iSlot;
		if(g_eClients[client][aEquipmentSynced][m_iId]==-2)
			g_eClients[client][aEquipment][m_iId]=-2;
		else
			g_eClients[client][aEquipment][m_iId]=-1;
	}
	else
	{
		for(new i=0;i<STORE_MAX_HANDLERS;++i)
		{
			for(new a=0;i<STORE_MAX_SLOTS;++i)
			{
				if(g_eClients[client][aEquipment][i+a] < 0)
					continue;
				m_iId = i*STORE_MAX_SLOTS+a;
				if(Store_IsItemInBoughtPackage(client, g_eClients[client][aEquipment][m_iId], itemid))
					if(g_eClients[client][aEquipmentSynced][m_iId]==-2)
						g_eClients[client][aEquipment][m_iId]=-2;
					else
						g_eClients[client][aEquipment][m_iId]=-1;
			}
		}
	}
}

Store_GetEquippedItemFromHandler(client, handler, slot=0)
{
	return g_eClients[client][aEquipment][handler*STORE_MAX_SLOTS+slot];
}

Store_PackageHasClientItem(client, packageid, bool:invmode=false)
{
	new m_iFlags = GetUserFlagBits(client);
	if(!g_eCvars[g_cvarShowVIP][aCache] && !GetClientPrivilege(client, g_eItems[packageid][iFlagBits], m_iFlags))
		return false;
	for(new i=0;i<g_iItems;++i)
		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))
			if((g_eItems[i][iHandler] == g_iPackageHandler && Store_PackageHasClientItem(client, i, invmode)) || g_eItems[i][iHandler] != g_iPackageHandler)
				return true;
	return false;
}

Store_LogMessage(client, credits, const String:message[], ...)
{
	if(!g_eCvars[g_cvarLogging][aCache])
		return;

	decl String:m_szReason[256];
	VFormat(STRING(m_szReason), message, 4);

	if(g_eCvars[g_cvarLogging][aCache] == 1)
	{
		LogToOpenFileEx(g_hLogFile, "%N's credits have changed by %d. Reason: %s", client, credits, m_szReason);
	} else if(g_eCvars[g_cvarLogging][aCache] == 2)
	{
		decl String:m_szQuery[256];
		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());
		SQL_TVoid(g_hDatabase, m_szQuery);
	}
}

Store_GetLowestPrice(itemid)
{
	if(g_eItems[itemid][iPlans]==0)
		return g_eItems[itemid][iPrice];

	new m_iLowest=g_ePlans[itemid][0][iPrice];
	for(new i=1;i<g_eItems[itemid][iPlans];++i)
	{
		if(m_iLowest>g_ePlans[itemid][i][iPrice])
			m_iLowest = g_ePlans[itemid][i][iPrice];
	}
	return m_iLowest;
}

Store_GetClientItemPrice(client, itemid)
{
	new uid = Store_GetClientItemId(client, itemid);
	if(uid<0)
		return 0;
		
	if(g_eClientItems[client][uid][iPriceOfPurchase]==0)
		return g_eItems[itemid][iPrice];

	return g_eClientItems[client][uid][iPriceOfPurchase];
}

public Store_OnPaymentReceived(FriendID, quanity, Handle:data)
{
	LoopIngamePlayers(i)
	{
		if(GetFriendID(i)==FriendID)
		{
			Store_SaveClientData(i);

			new m_unMod = FriendID % 2;
			new m_unAccountID = (FriendID-m_unMod)/2;

			decl String:m_szQuery[256];
			Format(STRING(m_szQuery), "SELECT * FROM store_players WHERE `authid`=\"%d:%d\"", m_unMod, m_unAccountID);
			SQL_TQuery(g_hDatabase, SQLCallback_LoadClientInventory_Credits, m_szQuery, GetClientUserId(i));
			break;
		}
	}
}
__________________
AcridGamer is offline
PC Gamer
Veteran Member
Join Date: Mar 2014
Old 11-28-2021 , 12:54   Re: Fatal Error 196 / Deprecated Syntax
Reply With Quote #6

Good News! Your function.inc error went away.

Bad News: You are now getting errors in your store plugin. My guess is that you updated to the development/experimental version of SourceMod (1.11) instead of the stable release version of SourceMod (1.10).

Possible solutions that may work for you....

1. You can try installing SourceMod 1.10 and then recompile your store plugin to see if it works without error.
2. You can try installing an alternate version of the store plugin that is designed to work with version 1.11 to see if it works without error.

I found this version of the Zephyrus store that claims to work with SourceMod version 1.11 (link: https://github.com/nuclearsilo583/ze...iew-new-syntax ). Note: I have not used this version.

Let us know if either of those options work for you.
PC Gamer is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 04:01.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode