/*
+--------------------------------------+
| DeathRun Timer - 2015-2016 |
| |
| Author: |
| deniS[MD] a.k.a icimaro1337 |
| Credits: |
| xPaw[EE] |
| Mistrick[RU] |
| Keniski[RU] |
| Klippy[RS] |
+--------------------------------------+
*/
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
#include <nvault>
#include <sqlx>
#include <geoip>
#include <dhudmessage>
#pragma semicolon 1
// Here you can configure main settings
#define TASK_START
new const g_szPrefix[] = "Force Gaming";
const maxplayers = 32;
new g_maxplayers;
#define ADMIN_ACCESS ADMIN_CVAR
// Here you stop
/* Macro */
#define set_bit(%1,%2) (%1 |= (1<<%2))
#define get_bit(%1,%2) (%1 & (1<<%2))
#define clr_bit(%1,%2) (%1 &= ~(1<<%2))
#define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && get_bit(g_bConnected, %1))
/* Macro */
new const g_szVersion[] = "0.1";
new const g_szTableName[] = "ZERECORDS_STATS";
new g_pWebLink;
new Handle:g_hSqlTuple;
new bool:g_bSqlite;
new g_szMapName[64];
new Trie:g_tStarts, Trie:g_tStops;
new bool:g_bTimerFound;
enum _:eTimer
{
START,
STOP
};
new g_szTimerModels[eTimer][] =
{
"sprites/FG_ze/FG_meta_starts.spr",
"models/FG_ze/FG_meta.mdl"
};
new g_szTimerName[eTimer][] =
{
"Start",
"Stop"
};
new g_iTimer[eTimer];
new Float:g_vTimerOrigin[eTimer][3];
new g_iTimerAngles[eTimer];
new Float:g_flTimerAngles[4] =
{
0.0,
90.0,
180.0,
270.0
};
new g_iPlayerTimer[33];
new g_bConnected, g_bAlive, g_bStarted;
new Float:g_flStartTime[33], Float:g_flFinishTime[33];
new g_iVault;
new g_iMsgRoundTime;
new g_iHudSyncObj;
public plugin_precache()
{
for (new i = 0; i < eTimer; i++)
precache_model(g_szTimerModels[i]);
}
public plugin_init()
{
register_plugin("DeathRun Timer", g_szVersion, "deniS");
g_pWebLink = register_cvar("ze_timer_web_link", "http://www.fgaming.pro/records");// link to web files
register_cvar("ze_timer_sql_host", "127.0.0.1");
register_cvar("ze_timer_sql_user", "records_user");
register_cvar("ze_timer_sql_pass", "records_user");
register_cvar("ze_timer_sql_db", "records"); /* If you don't have web server, you can use local stats, just add .db like deathrun_stats.db and enable sqlite module! */
g_maxplayers = get_maxplayers();
get_mapname(g_szMapName, charsmax(g_szMapName));
g_tStarts = TrieCreate();
g_tStops = TrieCreate();
new i, iSize;
new const szStarts[][] =
{
"counter_start", "clockstartbutton", "firsttimerelay", "but_start", "counter_start_button",
"multi_start", "timer_startbutton", "start_timer_emi", "gogogo"
};
iSize = sizeof(szStarts);
for (i = 0; i < iSize; i++)
TrieSetCell(g_tStarts, szStarts[i], 1);
new const szStops[][] =
{
"counter_off", "clockstopbutton", "clockstop", "but_stop", "counter_stop_button",
"multi_stop", "stop_counter", "m_counter_end_emi"
};
iSize = sizeof(szStops);
for (i = 0; i < iSize; i++)
TrieSetCell(g_tStops, szStops[i], 1);
new iEntity = -1;
while ((iEntity = find_ent_by_class(iEntity, "func_button")) != 0)
{
new szTargetName[64];
entity_get_string(iEntity, EV_SZ_targetname, szTargetName, charsmax(szTargetName));
if (TrieKeyExists(g_tStarts, szTargetName) || TrieKeyExists(g_tStops, szTargetName))
{
if (!g_bTimerFound)
g_bTimerFound = true;
break;
}
}
if (!g_bTimerFound)
{
TrieDestroy(g_tStarts);
TrieDestroy(g_tStops);
new szFile[96];
formatex(szFile, charsmax(szFile), "%s", g_szMapName);
g_iVault = nvault_open(szFile);
//Make the plugin error if vault did not successfully open
if ( g_iVault == INVALID_HANDLE )
server_print( "Error opening nVault." );
else
server_print("nVault Opened.");
LoadTimers();
}
//iEntity = create_entity("info_target");
/*if (iEntity)
{
entity_set_float(iEntity, EV_FL_nextthink, get_gametime() + 0.5);
entity_set_string(iEntity, EV_SZ_classname, "_TimerThink");
register_think("_TimerThink", "TimerThink");
}*/
g_iMsgRoundTime = get_user_msgid("RoundTime");
RegisterHam(Ham_Spawn, "player", "HamSpawnPlayer_Post", true);
RegisterHam(Ham_Killed, "player", "HamKilledPlayer_Post", true);
//RegisterHam(Ham_Use, "func_button", "HamUseFuncButton_Pre", false);
register_forward(FM_Touch, "fw_Touch");
register_event("HLTV", "event_round_start", "a", "1=0", "2=0");
register_clcmd("say /timer", "ClCmdTimer");
register_clcmd("say_team /timer", "ClCmdTimer");
register_clcmd("say /best", "ClCmdBest");
register_clcmd("say_team /best", "ClCmdBest");
g_iHudSyncObj = CreateHudSyncObj();
}
// Event Round Start
public event_round_start()
{
for(new i = 0; i < g_maxplayers; i++)
{
if(!is_user_valid_connected(i))
return;
Timer_Start(i);
}
}
public plugin_cfg()
{
set_task(0.5, "DB_Init");
}
public DB_Init()
{
state mysql;
new szDB[64];
get_cvar_string("ze_timer_sql_db", szDB, charsmax(szDB));
if (contain(szDB, ".") > 0)
{
state sqlite;
g_bSqlite = true;
}
SQL_Init();
}
SQL_Init()<mysql>
{
new szHost[64], szUser[64], szPass[64], szDB[64];
get_cvar_string("ze_timer_sql_host", szHost, charsmax(szHost));
get_cvar_string("ze_timer_sql_user", szUser, charsmax(szUser));
get_cvar_string("ze_timer_sql_pass", szPass, charsmax(szPass));
get_cvar_string("ze_timer_sql_db", szDB, charsmax(szDB));
g_hSqlTuple = SQL_MakeDbTuple(szHost, szUser, szPass, szDB);
new szQuery[512];
formatex
(
szQuery, charsmax(szQuery),
"CREATE TABLE IF NOT EXISTS `%s` \
( \
`ID` INT NOT NULL AUTO_INCREMENT, \
\
`MAPNAME` VARCHAR(64) NOT NULL, \
`AUTHID` VARCHAR(32) NOT NULL, \
`NICKNAME` VARCHAR(64) NOT NULL, \
`IP` VARCHAR(45) NOT NULL, \
`COUNTRY_FULL` VARCHAR(45) NOT NULL, \
`COUNTRY_SHORT` VARCHAR(3) NOT NULL, \
`TIME` DOUBLE NOT NULL, \
`DATE` DATETIME NOT NULL, \
\
PRIMARY KEY(`ID`) \
)",
g_szTableName
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
}
SQL_Init()<sqlite>
{
SQL_SetAffinity("sqlite");
new szDataDir[128];
get_localinfo("amxx_datadir", szDataDir, charsmax(szDataDir));
new szDB[64];
get_cvar_string("ze_timer_sql_db", szDB, charsmax(szDB));
new szFile[196];
formatex(szFile, charsmax(szFile), "%s/%s", szDataDir, szDB);
if (!file_exists(szFile))
{
new fp = fopen(szFile, "w");
if (!fp)
{
log_amx("[%s] SQL_Init()<sqlite>: File ^"%s^" not found and can't be created!", g_szPrefix, szFile);
return;
}
else
fclose(fp);
}
g_hSqlTuple = SQL_MakeDbTuple("", "", "", szFile, 0);
new szQuery[512];
formatex
(
szQuery, charsmax(szQuery),
"CREATE TABLE IF NOT EXISTS `%s` \
( \
`MAPNAME` TEXT NOT NULL, \
`AUTHID` TEXT NOT NULL, \
`NICKNAME` TEXT NOT NULL, \
`IP` TEXT NOT NULL, \
`COUNTRY_FULL` TEXT NOT NULL, \
`COUNTRY_SHORT` TEXT NOT NULL, \
`TIME` REAL NOT NULL, \
`DATE` DATETIME NOT NULL \
)",
g_szTableName
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
}
public client_putinserver(id)
{
set_bit(g_bConnected, id);
}
public client_disconnect(id)
{
clr_bit(g_bConnected, id);
if (get_bit(g_bAlive, id))
clr_bit(g_bAlive, id);
if (get_bit(g_bStarted, id))
clr_bit(g_bStarted, id);
if (g_flStartTime[id] != 0.0)
g_flStartTime[id] = 0.0;
if (g_flFinishTime[id] != 0.0)
g_flFinishTime[id] = 0.0;
}
public HamSpawnPlayer_Post(id)
{
if(!is_user_valid_connected(id))
return ;
set_bit(g_bAlive, id);
if (get_bit(g_bStarted, id))
{
clr_bit(g_bStarted, id);
g_flStartTime[id] = 0.0;
Timer_Start(id);
}
}
public HamKilledPlayer_Post(id)
{
if(!is_user_valid_connected(id))
return ;
clr_bit(g_bAlive, id);
if (get_bit(g_bStarted, id))
{
clr_bit(g_bStarted, id);
g_flStartTime[id] = 0.0;
}
}
public fw_Touch(ent, victim) {
if (!get_bit(g_bAlive, victim))
return(HAM_IGNORED);
if (!pev_valid(ent))
return FMRES_IGNORED;
/*new EntClassName[32]
entity_get_string(ent, EV_SZ_classname, EntClassName, charsmax(EntClassName))
if(equal(EntClassName, "meta") && is_user_alive(victim) && !g_touched[victim])
load_record(victim)*/
if (g_bTimerFound)
{
new szTarget[32];
entity_get_string(ent, EV_SZ_target, szTarget, charsmax(szTarget));
if (TrieKeyExists(g_tStarts, szTarget))
Timer_Start(victim);
else if (TrieKeyExists(g_tStops, szTarget))
Timer_Stop(victim);
}
else
{
if (ent == g_iTimer[START])
Timer_Start(victim);
else if (ent == g_iTimer[STOP])
Timer_Stop(victim);
}
return FMRES_IGNORED;
}
Timer_Start(id)
{
set_dhudmessage(255, 0, 0, -1.0, 0.90, 2, _, 3.0, 0.1, 1.5, false);
if (!get_bit(g_bStarted, id))
{
set_bit(g_bStarted, id);
show_dhudmessage(id, "Tiempo Iniciado!");
}
else
show_dhudmessage(id, "Tiempo Iniciado!");
g_flStartTime[id] = get_gametime();
}
Timer_Stop(id)
{
if (!get_bit(g_bStarted, id))
return;
clr_bit(g_bStarted, id);
g_flFinishTime[id] = get_gametime() - g_flStartTime[id];
g_flStartTime[id] = 0.0;
/*message_begin(MSG_ONE_UNRELIABLE, g_iMsgRoundTime, _, id);
write_short(1);
message_end();*/
new szTime[17];
ClimbtimeToString(g_flFinishTime[id], szTime, charsmax(szTime));
client_print(id, print_chat, "[%s] Llegaste a la meta en %s!", g_szPrefix, szTime);
new iPlayers[maxplayers], iNum;
get_players(iPlayers, iNum, "ch");
if (iNum)
{
new szName[32];
get_user_name(id, szName, charsmax(szName));
new iPlayer;
for (new i = 0; i < iNum; i++)
{
if(!is_user_valid_connected(i))
return;
iPlayer = iPlayers[i];
if (iPlayer == id)
continue;
}
}
new szAuthID[32];
get_user_authid(id, szAuthID, charsmax(szAuthID));
new szQuery[512], cData[1]; cData[0] = id;
formatex
(
szQuery, charsmax(szQuery),
"SELECT \
`TIME` \
FROM \
`%s` \
WHERE \
`MAPNAME` = '%s' \
AND \
`AUTHID` = '%s'",
g_szTableName,
g_szMapName,
szAuthID
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_QueryTop_Handler", szQuery, cData, sizeof(cData));
}
public Sql_QueryTop_Handler(iFailState, Handle:hQuery, szError[], iError, cData[], iSize)
{
if (iFailState != TQUERY_SUCCESS)
{
log_amx("[%s] Sql_IgnoredQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
return;
}
new id = cData[0];
if (!get_bit(g_bConnected, id))
return;
new szAuthID[32], szName[64], szIP[32], szCountryFull[45], szCountryShort[3], szDate[32];
get_user_authid(id, szAuthID, charsmax(szAuthID));
get_user_name(id, szName, charsmax(szName));
get_user_ip(id, szIP, charsmax(szIP), 1);
geoip_country(szIP, szCountryFull, charsmax(szCountryFull));
geoip_code2(szIP, szCountryShort);
get_time("%Y%m%d%H%M%S", szDate, charsmax(szDate));
SQL_PrepareString(szName, szName, charsmax(szName));
new szQuery[512];
if (SQL_NumResults(hQuery))
{
new Float:flOldTime, Float:flResult, szTime[17];
SQL_ReadResult(hQuery, 0, flOldTime);
if (g_flFinishTime[id] < flOldTime)
{
flResult = flOldTime - g_flFinishTime[id];
ClimbtimeToString(flResult, szTime, charsmax(szTime));
client_print(id, print_chat, "[%s] Mejoraste tu tiempo por %s milisegundos!", g_szPrefix, szTime);
formatex
(
szQuery, charsmax(szQuery),
"UPDATE `%s` \
SET \
`NICKNAME` = '%s', \
`IP` = '%s', \
`COUNTRY_FULL` = '%s', \
`COUNTRY_SHORT` = '%s', \
`TIME` = '%f', \
`DATE` = '%s' \
WHERE \
`MAPNAME` = '%s' \
AND \
`AUTHID` = '%s'",
g_szTableName,
szName,
szIP,
szCountryFull,
szCountryShort,
g_flFinishTime[id],
szDate,
g_szMapName,
szAuthID
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
formatex
(
szQuery, charsmax(szQuery),
"SELECT \
`AUTHID` \
FROM \
`%s` \
WHERE \
MAPNAME='%s' \
ORDER BY \
`TIME` \
LIMIT 15",
g_szTableName,
g_szMapName
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_GetPlaceQuery_Handler", szQuery, cData, sizeof(cData[]));
}
else
{
flResult = g_flFinishTime[id] - flOldTime;
ClimbtimeToString(flResult, szTime, charsmax(szTime));
client_print(id, print_chat, "[%s] Fallaste tu tiempo por %s milisegundos!", g_szPrefix, szTime);
}
}
else
{
formatex
(
szQuery, charsmax(szQuery),
"INSERT INTO `%s` \
( \
`MAPNAME`, \
`AUTHID`, \
`NICKNAME`, \
`IP`, \
`COUNTRY_FULL`, \
`COUNTRY_SHORT`, \
`TIME`, \
`DATE` \
) \
\
VALUES \
( \
'%s', \
'%s', \
'%s', \
'%s', \
'%s', \
'%s', \
'%f', \
'%s' \
)",
g_szTableName,
g_szMapName,
szAuthID,
szName,
szIP,
szCountryFull,
szCountryShort,
g_flFinishTime[id],
szDate
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
formatex
(
szQuery, charsmax(szQuery),
"SELECT \
`AUTHID` \
FROM \
`%s` \
WHERE \
MAPNAME='%s' \
ORDER BY \
`TIME` \
LIMIT 15",
g_szTableName,
g_szMapName
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_GetPlaceQuery_Handler", szQuery, cData, sizeof(cData[]));
}
g_flFinishTime[id] = 0.0;
}
public Sql_GetPlaceQuery_Handler(iFailState, Handle:hQuery, szError, iError, cData[], iSize)
{
if (iFailState != TQUERY_SUCCESS)
{
log_amx("[%s] Sql_GetPlaceQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
return;
}
new id = cData[0];
if (!get_bit(g_bConnected, id))
return;
new szAuthID[32];
get_user_authid(id, szAuthID, charsmax(szAuthID));
new i, szAuthID_SQL[32];
while(SQL_MoreResults(hQuery))
{
i++;
SQL_ReadResult(hQuery, 0, szAuthID_SQL, charsmax(szAuthID_SQL));
if (equal(szAuthID, szAuthID_SQL))
{
client_print(id, print_chat, "[%s] Estas de lugar %d En el top de este mapa!", g_szPrefix, i);
new iPlayers[maxplayers], iNum;
get_players(iPlayers, iNum, "ch");
if (iNum)
{
new szName[32];
get_user_name(id, szName, charsmax(szName));
new iPlayer;
for (new i = 0; i < iNum; i++)
{
if(is_user_valid_connected(i))
return;
iPlayer = iPlayers[i];
if (iPlayer == id)
continue;
}
}
break;
}
SQL_NextRow(hQuery);
}
}
public Sql_IgnoredQuery_Handler(iFailState, Handle:hQuery, szError[], iError, cData[], iSize)
{
if (iFailState != TQUERY_SUCCESS)
{
log_amx("[%s] Sql_IgnoredQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
return;
}
}
public ClCmdBest(id)
{
if (!g_bSqlite)
{
new szWebLink[128];
get_pcvar_string(g_pWebLink, szWebLink, charsmax(szWebLink));
new szMotd[256];
formatex(szMotd, charsmax(szMotd), "<META HTTP-EQUIV=^"REFRESH^" CONTENT=^"0;URL=%s/maptop.php?mapname=%s^">", szWebLink, g_szMapName);
show_motd(id, szMotd, "DR - Map Top");
}
else
{
new szQuery[512], cData[1]; cData[0] = id;
formatex
(
szQuery, charsmax(szQuery),
"SELECT \
`NICKNAME`, \
`TIME` \
FROM \
`%s` \
WHERE \
`MAPNAME` = '%s' \
ORDER BY \
`TIME` \
LIMIT 15",
g_szTableName,
g_szMapName
);
SQL_ThreadQuery(g_hSqlTuple, "Sql_LoadTopQuery_Handler", szQuery, cData, sizeof(cData));
}
}
public Sql_LoadTopQuery_Handler(iFailState, Handle:hQuery, szError, iError, cData[], iSize)
{
if (iFailState != TQUERY_SUCCESS)
{
log_amx("[%s] Sql_GetPlaceQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
return;
}
new id = cData[0];
if (!get_bit(g_bConnected, id))
return;
new szMotd[1536], iSize = charsmax(szMotd);
new iLen = formatex
(
szMotd, iSize,
"<!DOCTYPE HTML> \
<html> \
<head> \
<style type=^"text/css^"> \
body \
{ \
background: #000; \
margin: 8px; \
color: #FFB000; \
font: normal 16px/20px Verdana, Tahoma, sans-serif; \
text-align: center; \
} \
th:nth-child(2){ text-align: left; } \
td:nth-child(2){ text-align: left; } \
</style> \
</head> \
<body>"
);
iLen += formatex
(
szMotd[iLen], iSize - iLen,
"<table align=^"center^" width=^"90%%^"> \
<tr> \
<th width=^"5%%^">#</th>\
<th width=^"40%%^">Player</th>\
<th width=^"20%%^">Time</th>\
</tr> \
"
);
new i = 1;
new Float:flTime, szName[32], szTime[32];
while (SQL_MoreResults(hQuery))
{
SQL_ReadResult(hQuery, 0, szName, 31);
SQL_ReadResult(hQuery, 1, flTime);
ClimbtimeToString(flTime, szTime, 16);
iLen += formatex
(
szMotd[iLen], iSize - iLen,
"<tr> \
<td>%d</td> \
<td>%s</td> \
<td>%s</td> \
</tr>",
i,
szName,
szTime
);
i++;
SQL_NextRow(hQuery);
}
formatex
(
szMotd[iLen], iSize - iLen,
"</table> \
</body> \
</html>"
);
show_motd(id, szMotd, "DR - Map Top");
}
stock SQL_PrepareString(const szQuery[], szOutPut[], iSize)
{
copy(szOutPut, iSize, szQuery);
replace_all(szOutPut, iSize, "'", "\'");
replace_all(szOutPut, iSize, "`", "\`");
replace_all(szOutPut, iSize, "\\", "\\\\");
}
ClimbtimeToString(Float:flClimbTime, szOutPut[], iLen)
{
new iMinutes = floatround(flClimbTime / 60.0, floatround_floor);
new iSeconds = floatround(flClimbTime - iMinutes * 60, floatround_floor);
new iMiliSeconds = floatround((flClimbTime - (iMinutes * 60 + iSeconds)) * 100, floatround_floor);
formatex(szOutPut, iLen, "%02i:%02i.%02i", iMinutes, iSeconds, iMiliSeconds);
}
public ClCmdTimer(id)
{
if (~get_user_flags(id) & ADMIN_ACCESS)
{
client_print(id, print_chat, "[%s] You don't have enought access!", g_szPrefix);
return(PLUGIN_HANDLED);
}
if (g_bTimerFound)
{
client_print(id, print_chat, "[%s] This map already have timers!", g_szPrefix);
return(PLUGIN_HANDLED);
}
if (!get_bit(g_bAlive, id))
{
client_print(id, print_chat, "[%s] You should be alive!", g_szPrefix);
return(PLUGIN_HANDLED);
}
TimerMenu(id);
return(PLUGIN_HANDLED);
}
public TimerMenu(id)
{
new iMenu = menu_create("\r[ZE]\y Timer Menu", "TimerMenu_Handler");
menu_additem(iMenu, "Create");
menu_additem(iMenu, "Rotate^n");
menu_additem(iMenu, "Save^n");
new szMenuItem[64];
formatex(szMenuItem, charsmax(szMenuItem), "Timer - (\y%s\w)", g_szTimerName[g_iPlayerTimer[id]]);
menu_additem(iMenu, szMenuItem);
menu_display(id, iMenu);
}
public TimerMenu_Handler(id, iMenu, iItem)
{
if (iItem == MENU_EXIT)
{
menu_destroy(iMenu);
return(PLUGIN_HANDLED);
}
switch (iItem)
{
case 0: create_timer(id, g_iPlayerTimer[id]);
case 1:
{
if (is_valid_ent(g_iTimer[g_iPlayerTimer[id]]))
{
switch (g_iTimerAngles[g_iPlayerTimer[id]])
{
case 3: g_iTimerAngles[g_iPlayerTimer[id]] = 0;
case 0, 1, 2: g_iTimerAngles[g_iPlayerTimer[id]]++;
}
new Float:vAngles[3];
vAngles[1] = g_flTimerAngles[g_iTimerAngles[g_iPlayerTimer[id]]];
entity_set_vector(g_iTimer[g_iPlayerTimer[id]], EV_VEC_angles, vAngles);
}
}
case 2:
{
if (is_valid_ent(g_iTimer[g_iPlayerTimer[id]]))
{
if (g_iVault == INVALID_HANDLE)
return(PLUGIN_HANDLED);
new szData[128], iTimestamp;
if (nvault_lookup(g_iVault, g_szTimerName[g_iPlayerTimer[id]], szData, charsmax(szData), iTimestamp))
nvault_remove(g_iVault, g_szTimerName[g_iPlayerTimer[id]]);
formatex(szData, charsmax(szData), "^"%.1f^" ^"%.1f^" ^"%.1f^" ^"%d^"", g_vTimerOrigin[g_iPlayerTimer[id]][0], g_vTimerOrigin[g_iPlayerTimer[id]][1], g_vTimerOrigin[g_iPlayerTimer[id]][2], g_iTimerAngles[g_iPlayerTimer[id]]);
nvault_set(g_iVault, g_szTimerName[g_iPlayerTimer[id]], szData);
client_print(id, print_chat, "[%s] Timer (%s) saved!", g_szPrefix, g_szTimerName[g_iPlayerTimer[id]]);
}
}
case 3:
{
switch (g_iPlayerTimer[id])
{
case START: g_iPlayerTimer[id] = STOP;
case STOP: g_iPlayerTimer[id] = START;
}
}
}
ClCmdTimer(id);
return(PLUGIN_HANDLED);
}
LoadTimers()
{
if (g_iVault == INVALID_HANDLE)
return;
for (new i = 0; i < 2; i++)
{
new szData[128], iTimestamp;
if (nvault_lookup(g_iVault, g_szTimerName[i], szData, charsmax(szData), iTimestamp))
{
new szOrigin[3][17], szAngles[2];
parse(szData, szOrigin[0], charsmax(szOrigin[]), szOrigin[1], charsmax(szOrigin[]), szOrigin[2], charsmax(szOrigin[]), szAngles, charsmax(szAngles));
for (new x = 0; x < 3; x++)
g_vTimerOrigin[i][x] = str_to_float(szOrigin[x]);
g_iTimerAngles[i] = str_to_num(szAngles);
create_timer(0, i, g_vTimerOrigin[i]);
}
else
continue;
}
}
stock create_timer(id, iType, Float:vOrigin[3] = {0.0, 0.0, 0.0})
{
if (!g_iTimer[iType])
{
new iEntity = create_entity("func_button");
if (!is_valid_ent(iEntity))
return;
new szClassName[32];
formatex(szClassName, charsmax(szClassName), "Timer_%s", g_szTimerName[iType]);
entity_set_string(iEntity, EV_SZ_classname, szClassName);
entity_set_int(iEntity, EV_INT_solid, SOLID_TRIGGER);
entity_set_int(iEntity, EV_INT_movetype, MOVETYPE_NONE);
entity_set_model(iEntity, g_szTimerModels[iType]);
entity_set_size(iEntity, Float:{-150.0, -1.0, -150.0}, Float:{150.0, 1.0, 150.0});
g_iTimer[iType] = iEntity;
}
if (id)
{
new vOriginI[3];
get_user_origin(id, vOriginI, 3);
new Float:vOriginF[3];
IVecFVec(vOriginI, vOriginF);
entity_set_origin(g_iTimer[iType], vOriginF);
for (new i = 0; i < 3; i++)
g_vTimerOrigin[iType][i] = vOriginF[i];
}
else
entity_set_origin(g_iTimer[iType], vOrigin);
new Float:vAngles[3];
vAngles[1] = g_flTimerAngles[g_iTimerAngles[iType]];
entity_set_vector(g_iTimer[iType], EV_VEC_angles, vAngles);
drop_to_floor(g_iTimer[iType]);
}
public plugin_end()
{
if (g_bTimerFound)
{
TrieDestroy(g_tStarts);
TrieDestroy(g_tStops);
}
else
{
if (g_iVault != INVALID_HANDLE)
nvault_close(g_iVault);
}
SQL_FreeHandle(g_hSqlTuple);
}