/* **TODO:
* @Add commands for checking credits (Admins commands to add/remove creds)
* Events so players can earn credits
* Betting system
*/
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
new Handle:g_hStoreDb;
new Handle:g_StoreMenu = INVALID_HANDLE
new Handle:g_StoreMenuCat;
new Handle:g_kvSkins;
new Handle:g_kvTrails;
new g_iClientSpriteEntIndex[MAXPLAYERS+1];
new Handle:gH_Cvar_PluginEnabled = INVALID_HANDLE;
#define STARTING_CREDITS 10
#define CREDITS_MIN_PLAYERS 4
public Plugin:myinfo =
{
name = "TCH Store",
author = "B-Man",
description = "Store for TCH servers",
version = "0.5",
url = ""
}
public OnPluginStart()
{
gH_Cvar_PluginEnabled = CreateConVar("sm_store_enable", "1", "Enables/Disables Store", FCVAR_PLUGIN, true, 0.0, true, 1.0);
RegConsoleCmd("sm_store", Command_OpenStore);
RegConsoleCmd("sm_credits", Command_Credits);
RegAdminCmd("sm_credits_add", Command_AddCredits, ADMFLAG_RCON, "Add credits");
RegAdminCmd("sm_credits_sub", Command_SubtractCredits, ADMFLAG_RCON, "Subtract Credits");
RegAdminCmd("sm_credits_set", Command_SetCredits, ADMFLAG_RCON, "Set credits");
HookEvent("player_spawn", Event_PlayerSpawn, EventHookMode_Post);
HookEvent("player_death", Hook_PlayerDeath);
HookEvent("round_end", Hook_RoundEnd);
}
public DB_Connect()
{
decl String:sError[256];
g_hStoreDb = SQLite_UseDatabase("tchstore",sError,sizeof(sError));
if(g_hStoreDb == INVALID_HANDLE)
{
SetFailState("[STORE] Unable to connect to the database (%s)",sError);
}
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1200];
sQuery = "CREATE TABLE IF NOT EXISTS [items] ([item_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,[item_type] VARCHAR(50) NOT NULL,[item_cost] INTEGER NOT NULL,[item_name] VARCHAR(50) NOT NULL,[item_data] VARCHAR(255) NULL);";
SQL_FastQuery(g_hStoreDb,sQuery);
sQuery = "CREATE TABLE IF NOT EXISTS [players] ([steamid] VARCHAR(50) UNIQUE NOT NULL PRIMARY KEY,[credits] INTEGER DEFAULT '0' NOT NULL);";
SQL_FastQuery(g_hStoreDb,sQuery);
sQuery = "CREATE TABLE IF NOT EXISTS [purchases] ([steamid] VARCHAR(50) NOT NULL,[item_id] INTEGER NOT NULL);";
SQL_FastQuery(g_hStoreDb,sQuery);
SQL_UnlockDatabase(g_hStoreDb);
}
public OnConfigsExecuted()
{
DB_Connect();
g_kvSkins = CreateKeyValues("Skins");
g_kvTrails = CreateKeyValues("Trails");
// Read the the player's model settings
new String:file[256];
BuildPath(Path_SM, file, 255, "data/store_skins.ini");
FileToKeyValues(g_kvSkins, file);
// Read the the player's trail settings
BuildPath(Path_SM, file, 255, "data/store_trails.ini");
FileToKeyValues(g_kvTrails, file);
CreateTimer(60.0, Timer_TimeCredits, _, TIMER_REPEAT); //Give players a credit every 60 seconds... if they are on a valid team
}
public OnMapStart()
{
//PrecacheModel("models/player/slow/banana_joe/slow.mdl");
}
public OnClientDisconnect(client)
{
Trail_Remove(client);
}
Handle:BuildCategoryMenu(client)
{
new Handle:menu = CreateMenu(Menu_Category);
AddMenuItem(menu, "CreditsHelp", "How do I get credits?");
AddMenuItem(menu, "model", "Skins");
AddMenuItem(menu, "trail", "Trails");
new credits = GetPlayerCredits(client);
new String:title[50];
Format(title, sizeof(title), "Welcome to the store! [Credits: %i]", credits);
SetMenuTitle(menu, title);
return menu;
}
public Menu_Category(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_Select)
{
new String:info[255];
/* Get item info */
new bool:found = GetMenuItem(menu, param2, info, sizeof(info));
if (!found)
return;
if (!StrEqual(info, "CreditsHelp", false))
{
g_StoreMenu = BuildStoreMenu(param1, info);
DisplayMenu(g_StoreMenu, param1, MENU_TIME_FOREVER);
}
else
{
/*new Handle:panel = CreatePanel();
SetPanelTitle(panel, "How you earn credits");
DrawPanelItem(panel, "1 credit per minute\n1 credit = kill\n2 credits = headshot\n3credits = Knife");
SendPanelToClient(panel, param1, PanelHandler1, 20);
CloseHandle(panel);
*/
new Handle:help_Menu = CreateMenu(Menu_NULL);
//SetMenuTitle(help_Menu, "How you earn credits");
AddMenuItem(help_Menu, "", "How to earn credits\n---------\n1 credit per minute\n1 credit for kills\n2 credits for headshots\n3 credits knife kills");
//AddMenuItem(help_Menu, "", "1 credit per minute");
//AddMenuItem(help_Menu, "", "1 credit = Kill");
//AddMenuItem(help_Menu, "", "2 credits = Headshot");
//AddMenuItem(help_Menu, "", "3 credits = Knife");
SetMenuExitButton(help_Menu, false);
DisplayMenu(help_Menu, param1, MENU_TIME_FOREVER);
}
}
}
public Menu_NULL(Handle:menu, MenuAction:action, param1, param2)
{
//DO Nothing
}
Handle:BuildStoreMenu(client, String:type[])
{
/* Create the menu Handle */
new Handle:menu = CreateMenu(Menu_BuyItem);
if (StrContains(type, "model", false) > -1)
AddMenuItem(menu, "NoSkin", "Remove Skin"); //Remove the skin
else if (StrContains(type, "trail", false) > -1)
AddMenuItem(menu, "NoTrail", "Remove Trail"); //Remove the skin
new credits = GetPlayerCredits(client);
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
//SQL
if(g_hStoreDb == INVALID_HANDLE)
{
SetFailState("[STORE] Unable to connect to the database");
}
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT item_type, item_cost, item_name, item_data, purchases.steamid FROM items LEFT OUTER JOIN purchases ON items.item_id = purchases.item_id AND purchases.steamid = '%s' ORDER BY items.item_name ASC", steamId, type);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE || SQL_GetRowCount(query) == 0)
{
new String:error[255];
SQL_GetError(g_hStoreDb, error, sizeof(error));
PrintToServer("Failed to query (error: %s)", error);
PrintToConsole(client, "Failed to query (error: %s)", error);
} else {
new String:itemType[50];
new String:itemName[50];
new String:itemData[255];
new itemCost = 0;
while (SQL_FetchRow(query))
{
SQL_FetchString(query, 0, itemType, sizeof(itemType));
if (StrContains(itemType, type) == -1)
{
continue;
}
itemCost = SQL_FetchInt(query, 1);
SQL_FetchString(query, 2, itemName, sizeof(itemName));
SQL_FetchString(query, 3, itemData, sizeof(itemData));
new String:itemInfo[60];
if (SQL_IsFieldNull(query, 4))
{
Format(itemInfo, sizeof(itemInfo), "%s [%i]", itemName, itemCost);
if (credits < itemCost)
{
AddMenuItem(menu, itemData, itemInfo, ITEMDRAW_DISABLED);
}
else
{
AddMenuItem(menu, itemData, itemInfo);
}
}
else
{
Format(itemInfo, sizeof(itemInfo), "%s [Purchased]", itemName);
AddMenuItem(menu, itemData, itemInfo);
}
}
SQL_UnlockDatabase(g_hStoreDb);
/* Free the Handle */
CloseHandle(query);
}
//AddMenuItem(menu, mapname, mapname);
//AddMenuItem(menu, "TestDisabled", "Test", ITEMDRAW_DISABLED);
/* Finally, set the title */
new String:title[50];
Format(title, sizeof(title), "Welcome to the store! [Credits: %i]", credits);
SetMenuTitle(menu, title);
return menu;
}
public Menu_BuyItem(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_Select)
{
new String:info[255];
/* Get item info */
new bool:found = GetMenuItem(menu, param2, info, sizeof(info));
if (!found)
return;
new String:steamId[25];
GetClientAuthString(param1, steamId, sizeof(steamId));
if(StrContains(info, ".mdl", false) > -1) //its a skin because it contains .mdl
{
if (!StrEqual(info,"") && IsClientConnected(param1))
{
new bool:alreadyPurchased = CheckPurchaseByItemData(info, param1);
if(!alreadyPurchased)
{
SubtractCredits(param1, GetCostByItemData(info));
PurchaseItem(param1, info);
}
KvSetString(g_kvSkins, steamId, info);
if (GetConVarInt(gH_Cvar_PluginEnabled) && IsModelPrecached(info))
{
if (IsPlayerAlive(param1))
{
SetEntityModel(param1, info);
SetEntityRenderColor(param1, 255, 255, 255, 255);
}
new String:item_name[50];
GetItemNameByItemData(info, item_name, sizeof(item_name))
//PrintHintText(param1, "You are now wearing the skin:\n %s", item_name);
SendDialogToOne(param1, 10, "Current skin: [%s]", item_name);
PrintToChat(param1, "\x04[\x03Store\x04]\x01 You are now wearing the skin: \x03%s", item_name);
ShowoffSkin(param1);
}
else
{
if (alreadyPurchased)
{
PrintToChat(param1, "\x04[\x03Store\x04]\x01 Selection successful, although skins are not enabled at this time");
}
else
{
PrintToChat(param1, "\x04[\x03Store\x04]\x01 Purchase successful, although skins are not enabled at this time");
}
}
}
}
else if(StrContains(info, ".vtf", false) > -1 || StrContains(info, ".vmt", false) >-1) //Its a trail since it contains .vmt or .vtf
{
new bool:alreadyPurchased = CheckPurchaseByItemData(info, param1);
if(!alreadyPurchased)
{
SubtractCredits(param1, GetCostByItemData(info));
PurchaseItem(param1, info);
}
KvSetString(g_kvTrails, steamId, info);
Trail_Remove(param1);
new String:item_name[50];
GetItemNameByItemData(info, item_name, sizeof(item_name))
if (GetConVarInt(gH_Cvar_PluginEnabled))
{
CreateTimer(0.2, Timer_AttachTrail, param1, TIMER_FLAG_NO_MAPCHANGE);
PrintToChat(param1, "\x04[\x03Store\x04]\x01 You have equipped the trail: \x03%s", item_name);
}
else
{
if (alreadyPurchased)
PrintToChat(param1, "\x04[\x03Store\x04]\x01 You have equipped the trail: \x03%s", item_name);
else
PrintToChat(param1, "\x04[\x03Store\x04]\x01 You have purchased the trail: \x03%s \x01Although trails are not enabled atg this time", item_name);
}
}
else if (StrEqual(info, "NoTrail"))
{
KvSetString(g_kvTrails, steamId, "");
Trail_Remove(param1);
}
else if (StrEqual(info, "NoSkin"))
{
KvSetString(g_kvSkins, steamId, "");
if (IsPlayerAlive(param1))
{
PrintToChat(param1, "\x04[\x03Store\x04]\x01 Your skil will be removed next time you spawn");
//PrintHintText(param1, "Your skin will be removed next spawn");
}
}
/* Tell the client */
//PrintToConsole(param1, "You selected item: %d (found? %d info: %s)", param2, found, info);
//PrintToConsole(param1, "SteamID: %s", steamId);
}
}
public Action:Command_OpenStore(client, args)
{
g_StoreMenuCat = BuildCategoryMenu(client);
DisplayMenu(g_StoreMenuCat, client, MENU_TIME_FOREVER);
return Plugin_Handled;
}
public Action:Command_Credits(client, args)
{
//PrintHintText(client, "You have %i credits", GetPlayerCredits(client));
new creds = GetPlayerCredits(client);
SendDialogToOne(client, 10, "You have %i credits", creds);
PrintToChat(client, "\x04[\x03Store\x04]\x01 You have \x03%i \x01credits", creds);
return Plugin_Continue;
}
public Action:Command_AddCredits(client, args)
{
new String:s_target[50];
GetCmdArg(1, s_target, sizeof(s_target));
new target = FindTarget(client, s_target, true);
if (IsClientInGame(target))
{
new String:s_amount[9];
GetCmdArg(2, s_amount, sizeof(s_amount));
new amount = StringToInt(s_amount);
if (amount > 0)
{
new String:s_name[50];
GetClientName(target, s_name, sizeof(s_name));
AddCredits(target, amount);
PrintToChat(client, "\x04[\x03Store\x04]\x01 Added \x03%i \x01credits to \x03%s", amount, s_name);
PrintToChat(target, "\x04[\x03Store\x04]\x01 You now have \x03%i \x01credits", GetPlayerCredits(client));
}
}
return Plugin_Continue;
}
public Action:Command_SubtractCredits(client, args)
{
new String:s_target[50];
GetCmdArg(1, s_target, sizeof(s_target));
new target = FindTarget(client, s_target, true);
if (IsClientInGame(target))
{
new String:s_amount[9];
GetCmdArg(2, s_amount, sizeof(s_amount));
new amount = StringToInt(s_amount);
if (amount > 0)
{
new String:s_name[50];
GetClientName(target, s_name, sizeof(s_name));
SubtractCredits(target, amount);
PrintToChat(client, "\x04[\x03Store\x04]\x01 Subtracted \x03%i \x01credits from \x03%s", amount, s_name);
PrintToChat(target, "\x04[\x03Store\x04]\x01 You now have \x03%i \x01credits", GetPlayerCredits(client));
}
}
return Plugin_Continue;
}
public Action:Command_SetCredits(client, args)
{
new String:s_target[50];
GetCmdArg(1, s_target, sizeof(s_target));
new target = FindTarget(client, s_target, true);
if (IsClientInGame(target))
{
new String:s_amount[9];
GetCmdArg(2, s_amount, sizeof(s_amount));
new amount = StringToInt(s_amount);
if (amount > 0)
{
new String:s_name[50];
GetClientName(target, s_name, sizeof(s_name));
SetCredits(target, amount);
PrintToChat(client, "\x04[\x03Store\x04]\x01 Set player \x03%s \x01to \x03%i \x01credits", s_name, amount);
PrintToChat(target, "\x04[\x03Store\x04]\x01 You now have \x03%i \x01credits", GetPlayerCredits(client));
}
}
return Plugin_Continue;
}
public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarInt(gH_Cvar_PluginEnabled))
{
//Skins stuff
// Get the userid and client
new clientId = GetEventInt(event, "userid");
new client = GetClientOfUserId(clientId);
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
new String:model[255];
new String:item_name[50];
//KvJumpToKey(kvSkins, steamId, true);
KvGetString(g_kvSkins, steamId, model, sizeof(model), "");
// Make sure that they have a valid model pref
/*if (!StrEqual(model,"", false) && IsModelPrecached(model))
{
// Set the model
SetEntityModel(client, model);
SetEntityRenderColor(client, 255, 255, 255, 255);
}*/
if (!StrEqual(model,"") && IsModelPrecached(model))
{
SetEntityModel(client, model);
SetEntityRenderColor(client, 255, 255, 255, 255);
GetItemNameByItemData(model, item_name, sizeof(item_name))
//PrintHintText(client, "You are wearing the skin:\n %s", item_name);
SendDialogToOne(client, 15, "Current skin: [%s]", item_name);
PrintToChat(client, "\x04[\x03Store\x04]\x01 Current skin: [\x03%s\x01]", item_name);
}
KvRewind(g_kvSkins);
//Trails stuff
new String:trail[255];
//KvJumpToKey(kvSkins, steamId, true);
KvGetString(g_kvTrails, steamId, trail, sizeof(trail), "");
if (!IsFakeClient(client) && !StrEqual(trail,"", false))
{
CreateTimer(0.2, Timer_AttachTrail, client, TIMER_FLAG_NO_MAPCHANGE);
}
}
}
public Hook_RoundEnd(Handle:event, const String:name[], bool:DontBroadcast)
{
//Remove trails for dead people :)
for (new idx = 1; idx <= MaxClients; idx++)
{
Trail_Remove(idx);
}
}
public Hook_PlayerDeath(Handle:event, const String:name[], bool:DontBroadcast)
{
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
Trail_Remove(victim);
//Win Credits
if (IsFakeClient(victim) || IsFakeClient(attacker))
{
//We dont count bots!
} else if (victim == attacker || attacker == 0)
{
//Suicide
} else if (GetClientTeam(attacker) == GetClientTeam(victim))
{
//Teamkill
} else
{
new credits = 0;
new bool:headshot = GetEventBool(event, "headshot");
credits++;
if (headshot)
credits++;
decl String:weapon[64];
GetEventString(event, "weapon", weapon, sizeof(weapon));
ReplaceString(weapon,sizeof(weapon),"weapon_","");
if(StrEqual(weapon,"knife"))
{
credits = 3;
}
AddCredits(attacker, credits);
}
}
public OnPluginEnd()
{
SaveAndClose();
}
public SaveAndClose()
{
KvRewind(g_kvSkins);
KvRewind(g_kvTrails);
// Write the the player's model settings
new String:file[256];
BuildPath(Path_SM, file, 255, "data/store_skins.ini");
KeyValuesToFile(g_kvSkins, file);
CloseHandle(g_kvSkins);
BuildPath(Path_SM, file, 255, "data/store_trails.ini");
KeyValuesToFile(g_kvTrails, file);
CloseHandle(g_kvTrails);
CloseHandle(g_hStoreDb);
}
public GetPlayerCredits(client)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT credits FROM players WHERE steamid = '%s'", steamId);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE)
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
return 0;
}
if (SQL_GetRowCount(query) == 0)
{
SQL_UnlockDatabase(g_hStoreDb);
AddNewPlayer(client);
CloseHandle(query);
return STARTING_CREDITS;
}
else
{
new itemCost = SQL_FetchInt(query, 0);
SQL_UnlockDatabase(g_hStoreDb);
CloseHandle(query);
return itemCost;
}
}
public GetCostByItemData(String:model[])
{
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT item_cost FROM items WHERE item_data = '%s'", model);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE)
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
return 9999999;
}
new itemCost = SQL_FetchInt(query, 0);
CloseHandle(query);
return itemCost;
}
public SubtractCredits(client, amount)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "UPDATE players SET credits = credits - %i WHERE steamid = '%s'", amount, steamId);
if (!SQL_FastQuery(g_hStoreDb, sQuery))
{
new String:error[255];
SQL_GetError(g_hStoreDb, error, sizeof(error));
PrintToServer("Failed to query (error: %s)", error);
PrintToConsole(client, "Failed to query (error: %s)", error);
}
SQL_UnlockDatabase(g_hStoreDb);
}
public AddCredits(client, amount)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "UPDATE players SET credits = credits + %i WHERE steamid = '%s'", amount, steamId);
if (!SQL_FastQuery(g_hStoreDb, sQuery))
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
}
SQL_UnlockDatabase(g_hStoreDb);
}
public SetCredits(client, amount)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "UPDATE players SET credits = %i WHERE steamid = '%s'", amount, steamId);
if (!SQL_FastQuery(g_hStoreDb, sQuery))
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
}
SQL_UnlockDatabase(g_hStoreDb);
}
public PurchaseItem(client, String:model[])
{
new itemId = GetItemIdByItemData(model);
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "INSERT INTO purchases (steamid, item_id) VALUES ('%s', %i)", steamId, itemId);
if (!SQL_FastQuery(g_hStoreDb, sQuery))
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
}
SQL_UnlockDatabase(g_hStoreDb);
}
public GetItemIdByItemData(String:model[])
{
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT item_id FROM items WHERE item_data = '%s'", model);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE)
{
new String:error[255];
SQL_GetError(g_hStoreDb, error, sizeof(error));
PrintToServer("Failed to query (error: %s)", error);
SQL_UnlockDatabase(g_hStoreDb);
return -1;
}
if (SQL_GetRowCount(query) == 1)
{
SQL_UnlockDatabase(g_hStoreDb);
return SQL_FetchInt(query, 0);
}
SQL_UnlockDatabase(g_hStoreDb);
return -1;
}
public GetItemNameByItemData(String:model[], String:buffer[], buffer_size)
{
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT item_name FROM items WHERE item_data = '%s'", model);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE)
{
new String:error[255];
SQL_GetError(g_hStoreDb, error, sizeof(error));
PrintToServer("Failed to query (error: %s)", error);
SQL_UnlockDatabase(g_hStoreDb);
return false;
}
if (SQL_GetRowCount(query) == 1)
{
SQL_FetchString(query, 0, buffer, buffer_size);
SQL_UnlockDatabase(g_hStoreDb);
return true;
}
SQL_UnlockDatabase(g_hStoreDb);
return false;
}
public bool:CheckPurchaseByItemData(String:model[], client)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "SELECT items.item_name, purchases.steamid FROM items JOIN purchases ON items.item_id = purchases.item_id WHERE items.item_data = '%s' AND purchases.steamid = '%s'", model, steamId);
new Handle:query = SQL_Query(g_hStoreDb, sQuery)
if (query == INVALID_HANDLE)
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
SQL_UnlockDatabase(g_hStoreDb);
return false;
}
if (SQL_GetRowCount(query) == 1)
{
SQL_UnlockDatabase(g_hStoreDb);
CloseHandle(query);
return true;
}
SQL_UnlockDatabase(g_hStoreDb);
CloseHandle(query);
return false;
}
public bool:AddNewPlayer(client)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
SQL_LockDatabase(g_hStoreDb);
new String:sQuery[1000];
Format(sQuery, sizeof(sQuery), "INSERT INTO players (steamid, credits) VALUES ('%s', %i)", steamId, STARTING_CREDITS);
if (!SQL_FastQuery(g_hStoreDb, sQuery))
{
new String:error[255]
SQL_GetError(g_hStoreDb, error, sizeof(error))
PrintToServer("Failed to query (error: %s)", error)
PrintToConsole(client, "Failed to query (error: %s)", error);
SQL_UnlockDatabase(g_hStoreDb);
return false;
}
SQL_UnlockDatabase(g_hStoreDb);
return true;
}
public void:Trail_Attach(client)
{
new String:steamId[25];
GetClientAuthString(client, steamId, sizeof(steamId));
new String:trail[255];
KvGetString(g_kvTrails, steamId, trail, sizeof(trail), "");
if (StrEqual(trail,"", false))
{
return;
}
decl String:sTempName[64];
Format(sTempName, sizeof(sTempName), "PlayerTrail_%d", GetClientUserId(client));
DispatchKeyValue(client, "targetname", sTempName);
new entIndex = CreateEntityByName("env_spritetrail");
if (entIndex > 0 && IsValidEntity(entIndex))
{
// mark that we made a sprite trail for this client
g_iClientSpriteEntIndex[client] = entIndex;
DispatchKeyValue(entIndex, "parentname", sTempName);
DispatchKeyValue(entIndex, "spritename", trail);
SetEntPropFloat(entIndex, Prop_Send, "m_flTextureRes", 0.05);
DispatchKeyValue(entIndex, "renderamt", "255"); //Not sure what this does yet
//DispatchKeyValue(entIndex, "rendercolor", "65 105 225");
DispatchKeyValueFloat(entIndex, "lifetime", 2.0); //4 seconds lifetime?
DispatchKeyValueFloat(entIndex, "startwidth", 15.0);
DispatchKeyValueFloat(entIndex, "endwidth", 5.0);
DispatchKeyValue(entIndex, "rendermode", "5");
DispatchSpawn(entIndex);
new Float:f_origin[3];
GetClientAbsOrigin(client, f_origin);
f_origin[2] += 14.0; // 34
TeleportEntity(entIndex, f_origin, NULL_VECTOR, NULL_VECTOR);
SetVariantString(sTempName);
AcceptEntityInput(entIndex, "SetParent", entIndex, entIndex);
SDKHook(entIndex, SDKHook_SetTransmit, Hook_SetTransmit);
}
}
public void:Trail_Remove(client)
{
new ent = g_iClientSpriteEntIndex[client];
if (ent != 0)
{
if (IsValidEntity(ent))
{
SDKUnhook(ent, SDKHook_SetTransmit, Hook_SetTransmit);
AcceptEntityInput(ent, "Kill");
}
}
}
//This can block trails depending on conditions
public Action:Hook_SetTransmit(entity, client)
{
/* NOT NEEDED, FUTURE USE POSSIBLY
// find entity's owner
new parent = -1;
for (new idx = 1; idx <= MaxClients; idx++)
{
if (g_iClientSpriteEntIndex[idx] == entity)
{
if (IsClientInGame(idx))
{
parent = idx;
}
}
}*/
return Plugin_Continue;
}
public Action:Timer_AttachTrail(Handle:timer, any:client)
{
if (IsClientInGame(client) && IsPlayerAlive(client) && (GetClientTeam(client) > 1))
{
// attach trail to client
Trail_Attach(client);
}
return Plugin_Handled;
}
public ShowoffSkin(client)
{
if (!IsFakeClient (client) && IsClientInGame(client) && IsPlayerAlive(client) && (GetClientTeam(client) > 1))
{
ClientCommand (client, "3rd_on");
CreateTimer(2.0, Timer_ShowoffSkin, client, TIMER_FLAG_NO_MAPCHANGE);
}
}
public Action:Timer_ShowoffSkin(Handle:timer, any:client)
{
if (IsClientInGame(client) && IsPlayerAlive(client) && (GetClientTeam(client) > 1))
{
ClientCommand (client, "3rd_off");
}
return Plugin_Handled;
}
public Action:Timer_TimeCredits(Handle:timer)
{
new i;
for(i=1;i<=MaxClients;i++)
{
if (IsClientInGame(i))
{
AddCredits(i, 1);
}
}
return Plugin_Continue;
}
public OnMapEnd()
{
for (new idx = 1; idx <= MaxClients; idx++)
{
new ent = g_iClientSpriteEntIndex[idx];
if (ent != 0)
{
if (IsValidEntity(ent))
{
SDKUnhook(ent, SDKHook_SetTransmit, Hook_SetTransmit);
AcceptEntityInput(ent, "Kill");
}
}
}
SaveAndClose();
}
SendDialogToOne(client, duration, String:text[], any:...)
{
new String:message[100];
VFormat(message, sizeof(message), text, 4);
new Handle:kv = CreateKeyValues("Stuff", "title", message);
KvSetColor(kv, "color", 0, 191, 255, 255);
KvSetNum(kv, "level", 1);
KvSetNum(kv, "time", duration);
CreateDialog(client, kv, DialogType_Msg);
CloseHandle(kv);
}