Code:
#include <sourcemod>
#include <addicttime>
#define MAXSERVERS 50
char kvfile[PLATFORM_MAX_PATH];
Handle g_hNamesArray = INVALID_HANDLE;
Handle g_hIPsArray = INVALID_HANDLE;
Handle db = INVALID_HANDLE;
int timeplayed[MAXPLAYERS+1][MAXSERVERS];
int intialTime[MAXPLAYERS+1][MAXSERVERS];
bool g_bLoaded[MAXPLAYERS+1] = {false, ...};
#define HOURS / 3600
#define MINS % 3600 / 60
public Plugin myinfo =
{
name = "Global: Player Alive Times",
author = "Addicted",
version = "1.0",
url = "tgnaddicted.com"
};
public void OnPluginStart()
{
Connect();
g_hNamesArray = CreateArray(64);
g_hIPsArray = CreateArray(64);
BuildPath(Path_SM, kvfile, sizeof(kvfile), "configs/addicted/addicttime.txt");
ReloadServers();
RegConsoleCmd("sm_time", CMD_Time);
RegConsoleCmd("sm_top", CMD_Top);
RegAdminCmd("sm_reloadservers", CMD_Reload, ADMFLAG_ROOT);
CreateTimer(1.0, CountTimes, _, TIMER_REPEAT);
CreateTimer(60.0, UpdateTimes, _, TIMER_REPEAT);
}
public void OnMapStart()
{
ReloadServers();
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("AddictTime_GetTime", Native_GetTime);
RegPluginLibrary("addicttime");
return APLRes_Success;
}
public int Native_GetTime(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if (!IsValidClient(client))
ThrowNativeError(SP_ERROR_INDEX, "Client index %i is invalid", client);
char ip[64];
GetNativeString(2, ip, sizeof(ip));
return timeplayed[client][getID(ip)];
}
stock void Connect()
{
if (SQL_CheckConfig("addicttime"))
SQL_TConnect(OnDatabaseConnect, "addicttime");
else
SetFailState("Can't find 'addicttime' entry in sourcemod/configs/databases.cfg!");
}
public void OnDatabaseConnect(Handle owner, Handle hndl, const char[] error, any data)
{
if (hndl == INVALID_HANDLE)
{
LogError("Failed to connect! Error: %s", error);
PrintToServer("Failed to connect: %s", error);
SetFailState("Failed to connect, SQL Error: %s", error);
return;
}
db = hndl;
SQL_CreateTables();
}
stock void SQL_CreateTables()
{
char sQuery[1256];
Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS addicttime (name VARCHAR(22), steamid VARCHAR(22), PRIMARY KEY (steamid))");
if (db == INVALID_HANDLE)
{
LogError("[AddictTime] Invalid Database!");
return;
}
SQL_TQuery(db, SQLErrorCheckCallback, sQuery);
}
public void SQLErrorCheckCallback(Handle owner, Handle hndl, const char[] error, any data)
{
if (!StrEqual("", error))
LogError("SQL Error: %s", error);
}
public void OnClientPutInServer(int client)
{
if(IsValidClient(client))
{
int len = 0;
char query[1256];
char steamID[64];
GetClientAuthId(client, AuthId_Steam2, steamID, sizeof(steamID));
len += Format(query[len], sizeof(query)-len, "INSERT INTO `addicttime` (");
len += Format(query[len], sizeof(query)-len, "`name`,");
for (int i; i < GetArraySize(g_hNamesArray); i++)
{
char ip[64];
GetArrayString(g_hIPsArray, i, ip, sizeof(ip));
len += Format(query[len], sizeof(query)-len, "`%s`,", ip);
}
len += Format(query[len], sizeof(query)-len, "`steamid`");
len += Format(query[len], sizeof(query)-len, ")");
len += Format(query[len], sizeof(query)-len, "VALUES (");
len += Format(query[len], sizeof(query)-len, "\"%N\",", client);
for (int i; i < GetArraySize(g_hNamesArray); i++)
{
len += Format(query[len], sizeof(query)-len, "0,");
}
len += Format(query[len], sizeof(query)-len, "\"%s\"", steamID);
len += Format(query[len], sizeof(query)-len, ") ON DUPLICATE KEY UPDATE");
len += Format(query[len], sizeof(query)-len, "`name`");
len += Format(query[len], sizeof(query)-len, "= \"%N\"", client);
if (db == INVALID_HANDLE)
{
LogError("[AddictTime] Invalid Database!");
return;
}
SQL_TQuery(db, SQLErrorCheckCallback, query);
Format(query, sizeof(query), "SELECT * FROM `addicttime` WHERE steamid = \"%s\"", steamID);
SQL_TQuery(db, SQLGetTimes, query, client);
}
}
public void SQLGetTimes(Handle owner, Handle hndl, const char[] error, any data)
{
if (!IsValidClient(data))
return;
if (hndl == INVALID_HANDLE)
{
LogError("[AddictTime] Query failed! %s", error);
return;
}
else if (!SQL_GetRowCount(hndl))
return;
SQL_FetchRow(hndl);
for (int i = 2; i < GetArraySize(g_hIPsArray) + 2; i++)
{
char ip[64];
GetArrayString(g_hIPsArray, i-2, ip, sizeof(ip));
timeplayed[data][getID(ip)] = SQL_FetchInt(hndl, i);
intialTime[data][getID(ip)] = SQL_FetchInt(hndl, i);
}
g_bLoaded[data] = true;
}
public void ReloadServers()
{
ClearArray(g_hNamesArray);
ClearArray(g_hIPsArray);
char name[64], ip[64], port[64];
Handle kv = CreateKeyValues("AddictTime");
FileToKeyValues(kv, kvfile);
if(KvGotoFirstSubKey(kv))
{
do
{
KvGetSectionName(kv, name, sizeof(name));
KvGetString(kv, "ip", ip, sizeof(ip));
KvGetString(kv, "port", port, sizeof(port));
Format(ip, sizeof(ip), "%s:%s", ip, port);
PushArrayString(g_hNamesArray, name);
PushArrayString(g_hIPsArray, ip);
} while (KvGotoNextKey(kv));
}
KvRewind(kv);
}
public Action CMD_Reload(int client, int args)
{
ReloadServers();
PrintToChat(client, "[AddictTime] Reloaded Servers!");
}
public Action CMD_Time(int client, int args)
{
int final_target;
Handle MenuHandle = CreateMenu(NoSelectionMenuHandler);
if(args > 0)
{
char buffer[128];
GetCmdArg(1, buffer, sizeof(buffer));
final_target = FindTarget(client, buffer, true, false);
char title[128];
Format(title, sizeof(title), "AddictTime\nTime Alive for %N", final_target);
SetMenuTitle(MenuHandle, title);
}
else
{
final_target = client;
char title[128];
Format(title, sizeof(title), "AddictTime\nTime Alive for %N", final_target);
SetMenuTitle(MenuHandle, title);
}
if (!g_bLoaded[final_target])
{
PrintToChat(client, "[AddictTime] %N's time is not loaded yet... Please reconnect or wait for a map change", final_target);
return Plugin_Handled;
}
int totalTime;
for (int i; i < GetArraySize(g_hNamesArray); i++)
{
char ip[64];
GetArrayString(g_hIPsArray, i, ip, sizeof(ip));
totalTime+= timeplayed[final_target][getID(ip)];
}
char totalDisplay[120];
Format(totalDisplay, sizeof(totalDisplay), "All Servers: %i hours %i mins", totalTime HOURS, totalTime MINS);
AddMenuItem(MenuHandle, "", totalDisplay, ITEMDRAW_DISABLED);
for (int i; i < GetArraySize(g_hNamesArray); i++)
{
char name[64], ip[64], info[120];
GetArrayString(g_hNamesArray, i, name, sizeof(name));
GetArrayString(g_hIPsArray, i, ip, sizeof(ip));
if (IsCurrentServer(ip))
Format(info, sizeof(info), "*%s: %i hours %i mins", name, timeplayed[final_target][getID(ip)] HOURS, timeplayed[final_target][getID(ip)] MINS);
else
Format(info, sizeof(info), "%s: %i hours %i mins", name, timeplayed[final_target][getID(ip)] HOURS, timeplayed[final_target][getID(ip)] MINS);
AddMenuItem(MenuHandle, "", info, ITEMDRAW_DISABLED);
}
DisplayMenu(MenuHandle, client, MENU_TIME_FOREVER);
return Plugin_Handled;
}
public Action CMD_Top(int client, args)
{
if (!IsValidClient(client))
return Plugin_Handled;
Handle hMenu = CreateMenu(TopTimesMenuHandler);
SetMenuTitle(hMenu, "Top Times");
for (int i; i < GetArraySize(g_hNamesArray); i++)
{
char name[64], ip[64], info[120];
GetArrayString(g_hNamesArray, i, name, sizeof(name));
GetArrayString(g_hIPsArray, i, ip, sizeof(ip));
if (IsCurrentServer(ip))
Format(info, sizeof(info), "*%s", name);
else
Format(info, sizeof(info), "%s", name);
AddMenuItem(hMenu, ip, info);
}
DisplayMenu(hMenu, client, MENU_TIME_FOREVER);
return Plugin_Handled;
}
public int TopTimesMenuHandler(Handle menu, MenuAction action, int client, int option)
{
if (action == MenuAction_Select)
{
char info[64];
GetMenuItem(menu, option, info, sizeof(info));
ShowTop(client, info);
}
if (action == MenuAction_End)
{
CloseHandle(menu);
}
}
public void ShowTop(int client, char[] ip)
{
if (!IsValidClient(client))
return;
char sQuery[1256];
Format(sQuery, sizeof(sQuery), "SELECT `name`, `%s` FROM `addicttime` ORDER BY `%s` DESC LIMIT 10", ip, ip);
if (db == INVALID_HANDLE)
{
LogError("[AddictTime] Invalid Database!");
return;
}
Handle datapack = CreateDataPack();
WritePackCell(datapack, client);
WritePackString(datapack, ip);
SQL_TQuery(db, SQLShowTop, sQuery, datapack);
return;
}
public void SQLShowTop(Handle owner, Handle hndl, const char[] error, any pack)
{
char ip[64];
ResetPack(pack);
int client = ReadPackCell(pack);
ReadPackString(pack, ip, sizeof(ip));
if (!IsValidClient(client))
return;
if (hndl == INVALID_HANDLE)
{
LogError("[AddictTime] Query failed! %s", error);
return;
}
else if (!SQL_GetRowCount(hndl))
return;
SQL_FetchRow(hndl);
Handle hMenu = CreateMenu(NoSelectionMenuHandler);
char name[64];
GetArrayString(g_hNamesArray, getID(ip), name, sizeof(name));
SetMenuTitle(hMenu, "Top Times - %s", name);
for (int i = 1; i < 10; i++)
{
char tempName[MAX_NAME_LENGTH], info[64];
SQL_FetchString(hndl, 0, tempName, sizeof(tempName));
int time = SQL_FetchInt(hndl, 1);
Format(info, sizeof(info), "%s - %i hours %i mins", tempName, time HOURS, time MINS);
AddMenuItem(hMenu, "", info, ITEMDRAW_DISABLED);
SQL_FetchRow(hndl);
}
SetMenuPagination(hMenu, MENU_NO_PAGINATION);
SetMenuExitButton(hMenu, true);
DisplayMenu(hMenu, client, MENU_TIME_FOREVER);
}
public int NoSelectionMenuHandler(Handle menu, MenuAction action, int client, int option)
{
if (action == MenuAction_Select)
{
CloseHandle(menu);
}
if (action == MenuAction_End)
{
CloseHandle(menu);
}
}
public Action CountTimes(Handle timer)
{
char ip[64];
for (int i; i < GetArraySize(g_hIPsArray); i++)
{
char tempIP[64];
GetArrayString(g_hIPsArray, i, tempIP, sizeof(tempIP));
if (IsCurrentServer(tempIP))
Format(ip, sizeof(ip), "%s", tempIP);
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i) && IsPlayerAlive(i) && GetClientTeam(i) != 1)
{
timeplayed[i][getID(ip)] += 1;
}
}
public Action UpdateTimes(Handle timer)
{
char ip[64];
for (int i; i < GetArraySize(g_hIPsArray); i++)
{
char tempIP[64];
GetArrayString(g_hIPsArray, i, tempIP, sizeof(tempIP));
if (IsCurrentServer(tempIP))
Format(ip, sizeof(ip), "%s", tempIP);
}
for (int i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i))
{
if (!g_bLoaded[i])
continue;
if (timeplayed[i][getID(ip)] < intialTime[i][getID(ip)])
continue;
if (timeplayed[i][getID(ip)] == 0)
continue;
char steamID[64], sQuery[1256];
GetClientAuthId(i, AuthId_Steam2, steamID, sizeof(steamID));
if (db == INVALID_HANDLE)
{
LogError("[AddictTime] Invalid Database!");
return;
}
Format(sQuery, sizeof(sQuery), "UPDATE `addicttime` SET `%s` = %i WHERE steamid = \"%s\"", ip, timeplayed[i][getID(ip)], steamID);
SQL_TQuery(db, SQLErrorCheckCallback, sQuery);
}
}
}
stock int getID(char[] ip)
{
for (int i; i < GetArraySize(g_hIPsArray); i++)
{
char temp[64];
GetArrayString(g_hIPsArray, i, temp, sizeof(temp));
if (StrEqual(ip, temp))
return i;
}
return -1;
}
stock bool IsCurrentServer(char[] ip)
{
Handle gameIP;
char ServerIp[60];
gameIP = FindConVar("ip");
GetConVarString(gameIP, ServerIp, sizeof(ServerIp));
Format(ServerIp, sizeof(ServerIp), "%s:%i", ServerIp, GetConVarInt(FindConVar("hostport")));
if (StrEqual(ServerIp, ip))
return true;
return false;
}
stock bool IsValidClient(int client)
{
if (client < 1 || client > MaxClients)
return false;
if (!IsClientConnected(client))
return false;
if (!IsClientInGame(client))
return false;
if (IsFakeClient(client))
return false;
return true;
}