projects-jenz/RaceTimer/scripting/unloze_racetimer_redux.sp

1005 lines
38 KiB
SourcePawn
Raw Normal View History

2019-03-02 15:17:41 +01:00
#pragma semicolon 1
#define DEBUG
#define PLUGIN_AUTHOR "jenz"
#define PLUGIN_VERSION "1.5"
2019-03-02 15:17:41 +01:00
#define g_dLength 256
#define g_dIndex 65
#include <sourcemod>
#include <colorvariables>
2019-08-04 12:59:39 +02:00
#include <clientprefs>
2019-03-02 15:17:41 +01:00
#include <unloze_zones>
#include <unloze_racetimer_specialmaps>
#include <unloze_racetimer_antizones>
#include <cstrike>
#include <sdktools>
#pragma newdecls required
char g_cMapname[g_dLength];
char g_cSpecialMapStart[g_dLength];
char g_cSpecialMapEnd[g_dLength];
static char g_sConfigzones[PLATFORM_MAX_PATH];
int g_iRoundMinutes;
2019-03-02 15:17:41 +01:00
float g_fRoundSeconds;
int g_iMinutesIndividual[MAXPLAYERS + 1];
2019-03-02 15:17:41 +01:00
float g_fSecondsIndividual[MAXPLAYERS + 1];
float g_fClientVectors[MAXPLAYERS + 1][3];
int g_iClientFrames[MAXPLAYERS + 1];
int g_iClientSpeedInterval[MAXPLAYERS + 1];
2019-03-02 15:17:41 +01:00
int g_iClientChecking[MAXPLAYERS + 1];
bool g_bDisplaySpecial;
bool g_bHumansAllowedTime[MAXPLAYERS + 1];
2019-07-24 00:43:06 +02:00
bool g_bHideTimer[MAXPLAYERS + 1];
bool g_bDev[MAXPLAYERS + 1];
2019-08-04 12:59:39 +02:00
Handle g_hClientCookie = INVALID_HANDLE;
2019-03-02 15:17:41 +01:00
Database g_dDatabase;
Handle hText;
float playertime_leaving_zone[MAXPLAYERS + 1];
int player_stage[MAXPLAYERS + 1];
2019-03-02 15:17:41 +01:00
public Plugin myinfo =
{
name = "UNLOZE_racetimer_css",
author = PLUGIN_AUTHOR,
description = "tracers times on race maps",
version = PLUGIN_VERSION,
url = "www.unloze.com"
};
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnPluginStart()
{
//cmds
RegConsoleCmd("sm_toptime", cmd_timerCheckTop, "checking top 10");
RegConsoleCmd("sm_mytime", cmd_timerCheckSelf, "checking your personal time");
RegConsoleCmd("sm_stages", cmd_timerCheckStage, "Checking race stages");
2019-07-24 00:43:06 +02:00
RegConsoleCmd("sm_hidetimer", cmd_hideTimerHUD, "Hides timer HUD");
2019-09-05 23:14:56 +02:00
RegAdminCmd("sm_cleantime", Cmd_timeReset, ADMFLAG_GENERIC);
RegAdminCmd("sm_devtime", Cmd_devtest, ADMFLAG_GENERIC);
2019-03-02 15:17:41 +01:00
//hooks
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
//HUD
hText = CreateHudSynchronizer();
2019-08-04 12:59:39 +02:00
//cookies
g_hClientCookie = RegClientCookie("hide_timer_cookie", "Hides the timer HUD", CookieAccess_Private);
for (int i = MaxClients; i > 0; --i)
{
if (!AreClientCookiesCached(i))
{
continue;
}
OnClientCookiesCached(i);
}
}
2019-03-02 15:17:41 +01:00
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnMapStart()
{
//mysql placed here just in case somebody wants to reset database without having to reload plugin
g_bDisplaySpecial = unloze_gBSpecialMapDisplay();
SQL_StartConnection();
GetCurrentMap(g_cMapname, sizeof(g_cMapname));
CreateTimer(0.1, Timer_CountdownRace, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
startTimer();
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnPluginEnd()
{
CloseHandle(hText);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
2019-03-02 15:17:41 +01:00
public void startTimer()
{
char line[g_dLength];
Handle zonefile = INVALID_HANDLE;
BuildPath(Path_SM, g_sConfigzones, sizeof(g_sConfigzones), "configs/unloze_zones/%s.zones.txt", g_cMapname);
zonefile = OpenFile(g_sConfigzones, "r");
if (zonefile != INVALID_HANDLE)
{
while (!IsEndOfFile(zonefile) && ReadFileLine(zonefile, line, sizeof(line)))
{
if (StrContains(line, "ZONE_PREFIX_RACE", false) > -1 || g_bDisplaySpecial)
{
MYSQLCheckMapEntry();
break;
}
}
}
delete zonefile;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action Timer_CountdownRace(Handle timer, any data)
{
float l_milisecond = 0.0000;
while (l_milisecond < 0.1000)
2019-03-02 15:17:41 +01:00
{
l_milisecond += 0.0001;
g_fRoundSeconds += 0.0001;
if (g_fRoundSeconds > 59.9999)
{
g_iRoundMinutes += 1;
g_fRoundSeconds = 0.0000;
}
2019-03-02 15:17:41 +01:00
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void Event_RoundStart(Handle event, const char[] name, bool dontBroadcast)
{
g_iRoundMinutes = 0;
2019-03-02 15:17:41 +01:00
g_fRoundSeconds = 0.0;
int l_iZoneCount = unloze_zoneCount();
2019-03-02 15:17:41 +01:00
for (int i = 1; i <= MaxClients; i++)
if (IsValidClient(i))
{
resetClientVectors(i);
if (l_iZoneCount != 1)
g_bHumansAllowedTime[i] = false;
else
{
mysql_get_player_time(i, 0);
g_bHumansAllowedTime[i] = true;
}
}
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientPostAdminCheck(int client)
{
resetClient(client);
2019-08-04 12:59:39 +02:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientCookiesCached(int client)
{
char sValue[8];
GetClientCookie(client, g_hClientCookie, sValue, sizeof(sValue));
g_bHideTimer[client] = (sValue[0] != '\0' && !!StringToInt(sValue));
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientDisconnect(int client)
{
resetClient(client);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void resetClient(int client)
{
g_fSecondsIndividual[client] = 0.0;
g_iMinutesIndividual[client] = 0;
2019-03-02 15:17:41 +01:00
g_iClientChecking[client] = 0;
g_bHumansAllowedTime[client] = false;
resetClientVectors(client);
g_bDev[client] = false;
player_stage[client] = 0;
playertime_leaving_zone[client] = 0.0;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
{
2019-08-04 15:56:53 +02:00
if (g_bHumansAllowedTime[client] && (GetClientTeam(client) == CS_TEAM_CT) && IsPlayerAlive(client))
{
int frameCap = 11;
if (g_iClientFrames[client] >= frameCap)
{
g_iClientFrames[client] = 0;
float clientVectors[3];
GetClientAbsOrigin(client, clientVectors);
if (checkClientOrigin(g_fClientVectors[client], clientVectors, client) && !g_bDev[client])
{
g_bHumansAllowedTime[client] = false;
resetClientVectors(client);
PrintToChat(client, "Disabled timer due to potential teleport abuse");
return Plugin_Continue;
}
int speedCheckerCap = 10;
if (g_iClientSpeedInterval[client] > speedCheckerCap && !g_bDev[client])
{
g_iClientSpeedInterval[client] = 0;
bool bNoclip = (GetEntityMoveType(client) == MOVETYPE_NOCLIP);
if (bNoclip)
{
g_bHumansAllowedTime[client] = false;
resetClientVectors(client);
PrintToChat(client, "Disabled timer due to Noclip");
return Plugin_Continue;
}
float speed = GetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue");
if (speed > 1.0)
{
if (StrContains(g_cMapname, "surf", false) == -1)
{
g_bHumansAllowedTime[client] = false;
resetClientVectors(client);
PrintToChat(client, "Disabled timer due to modified run speed");
return Plugin_Continue;
}
}
float client_gravity = GetEntityGravity(client);
ConVar gravity = FindConVar("sv_gravity");
float gravityFloat = gravity.FloatValue;
2019-07-24 01:49:47 +02:00
int minimalPermitedGravity = 610;
//PrintToChat(client, "client_gravity: %f\ngravityFloat: %f", client_gravity, gravityFloat);
if (((client_gravity > 1.3 || client_gravity < 0.6000) && client_gravity != 0.000000) || gravityFloat < minimalPermitedGravity)
{
//PrintToChat(client, "client_gravity: %f\ngravityFloat: %f", client_gravity, gravityFloat);
g_bHumansAllowedTime[client] = false;
resetClientVectors(client);
PrintToChat(client, "Disabled timer due to modified gravity");
return Plugin_Continue;
}
}
g_fClientVectors[client] = clientVectors;
{
2019-07-24 00:43:06 +02:00
if (hText != INVALID_HANDLE && !g_bHideTimer[client])
{
2019-07-24 00:43:06 +02:00
SetHudTextParams(0.35, 0.85, 0.1, 125, 255, 255, 85);
int l_iCalculateMins = CalculateValuesMinutes(client);
float l_fCalculateSecs = CalculateValues(client);
float leftover_seconds = playertime_leaving_zone[client] - RoundToFloor(playertime_leaving_zone[client]);
leftover_seconds = leftover_seconds * 100;
int minutes = RoundToFloor(playertime_leaving_zone[client]);
if (g_bDev[client])
{
//PrintToChat(client, "leftover_seconds: %f", leftover_seconds);
//PrintToChat(client, "minutes: %i", minutes);
}
2019-08-04 15:56:53 +02:00
if (l_fCalculateSecs < 10.0)
{
if (leftover_seconds < 10.0)
2019-08-04 15:56:53 +02:00
{
ShowSyncHudText(client, hText, "%N Time: 0%i:0%.4f\nRecord: 0%i:0%.4f\nMap: %s\nCourse: %i", client, l_iCalculateMins,
l_fCalculateSecs, minutes, leftover_seconds, g_cMapname, player_stage[client]);
}
else
2019-08-04 15:56:53 +02:00
{
ShowSyncHudText(client, hText, "%N Time: 0%i:0%.4f\nRecord: 0%i:%.4f\nMap: %s\nCourse: %i", client, l_iCalculateMins,
l_fCalculateSecs, minutes, leftover_seconds, g_cMapname, player_stage[client]);
2019-08-04 15:56:53 +02:00
}
}
else
{
if (leftover_seconds < 10.0)
2019-08-04 15:56:53 +02:00
{
ShowSyncHudText(client, hText, "%N Time: 0%i:%.4f\nRecord: 0%i:0%.4f\nMap: %s\nCourse: %i", client, l_iCalculateMins,
l_fCalculateSecs, minutes, leftover_seconds, g_cMapname, player_stage[client]);
2019-08-04 15:56:53 +02:00
} else
{
ShowSyncHudText(client, hText, "%N Time: 0%i:%.4f\nRecord: 0%i:%.4f\nMap: %s\nCourse: %i", client, l_iCalculateMins,
l_fCalculateSecs, minutes, leftover_seconds, g_cMapname, player_stage[client]);
2019-08-04 15:56:53 +02:00
}
}
}
}
g_iClientSpeedInterval[client]++;
}
g_iClientFrames[client]++;
2019-03-02 15:17:41 +01:00
}
return Plugin_Continue;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void resetClientVectors(int client)
{
g_fClientVectors[client][0] = 0.000000;
g_fClientVectors[client][1] = 0.000000;
g_fClientVectors[client][2] = 0.000000;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public bool checkClientOrigin(float oldVals[3], float newVals[3], int client)
{
float zero = 0.000000;
if ((oldVals[0] == zero && oldVals[1] == zero && oldVals[2] == zero) || (newVals[0] == zero && newVals[1] == zero && newVals[2] == zero))
{
return false;
}
2019-08-04 15:56:53 +02:00
float teleport_range = 100000.0;
int velocityCap = 325;
float distance = GetVectorDistance(oldVals, newVals, true);
//PrintToChatAll("distance: %f", distance);
bool bInAir = (GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") == -1);
if (distance > teleport_range)
{
if (StrContains(g_cMapname, "surf", false) != -1)
return false;
float fVelocity[3];
GetEntPropVector(client, Prop_Data, "m_vecVelocity", fVelocity);
float currentspeed = SquareRoot(Pow(fVelocity[0],2.0)+Pow(fVelocity[1],2.0));
//PrintToChat(client, "currentspeed: %f", currentspeed);
if (bInAir && currentspeed > velocityCap)
return false;
return true;
}
return false;
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void unloze_zoneEntry(int client, char[] zone)
{
int zoneIndex = RetrieveZoneIndex(zone);
2019-03-02 15:17:41 +01:00
int l_iZoneCount = unloze_zoneCount();
if (((GetClientTeam(client) == CS_TEAM_CT && g_bHumansAllowedTime[client]) && StrContains(zone, "ZONE_PREFIX_RACE") > -1) || StrEqual(zone, g_cSpecialMapEnd))
{
if (IsClientAuthorized(client))
2019-03-02 15:17:41 +01:00
{
if (l_iZoneCount < 2)
{
player_stage[client] = 0;
}
if (player_stage[client] == (zoneIndex / 2) || l_iZoneCount < 2)
{
FinishedStageRaceZone(client);
}
2019-03-02 15:17:41 +01:00
}
if (!g_bDev[client])
g_bHumansAllowedTime[client] = false;
2019-03-02 15:17:41 +01:00
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void unloze_zoneLeave(int client, char[] zone)
{
//only maps with multiple zones need ZONE_PREFIX_START
if (((GetClientTeam(client) == CS_TEAM_CT) && StrContains(zone, "ZONE_PREFIX_START") > -1) || StrEqual(zone, g_cSpecialMapStart))
{
resetClientVectors(client);
2019-03-02 15:17:41 +01:00
g_fSecondsIndividual[client] = g_fRoundSeconds;
g_iMinutesIndividual[client] = g_iRoundMinutes;
float notRounded = float(RetrieveZoneIndex(zone));
player_stage[client] = RoundToCeil(notRounded / 2);
mysql_get_player_time(client, player_stage[client]);
g_bHumansAllowedTime[client] = true;
CPrintToChat(client, "Timer started for Course: %i", player_stage[client]);
2019-03-02 15:17:41 +01:00
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void unloze_zoneCreated()
{
startTimer();
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void CheckIfSpecialRoundZones(char[] resultstart, char[] resultend)
{
Format(g_cSpecialMapStart, sizeof(g_cSpecialMapStart), resultstart);
Format(g_cSpecialMapEnd, sizeof(g_cSpecialMapEnd), resultend);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void CheckifAntiZones(int client, bool reset)
{
if (reset)
g_bHumansAllowedTime[client] = false;
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int RetrieveZoneIndex(char[] zone)
{
//if you leave zone_2 you want the corresponding racezone to be zone_3
int iterator = strlen(zone) - 1;
2020-04-15 01:00:12 +02:00
if (iterator == -1)
return 1;
2019-03-02 15:17:41 +01:00
char l_sZone[g_dIndex];
Format(l_sZone, sizeof(l_sZone), zone);
while (IsCharNumeric(l_sZone[iterator]))
iterator--;
iterator++;
strcopy(l_sZone, sizeof(l_sZone), l_sZone[iterator]);
return StringToInt(l_sZone[iterator]);
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void FinishedStageRaceZone(int client)
{
int l_iZoneCount = unloze_zoneCount();
int l_iCalculateMins;
2019-03-02 15:17:41 +01:00
float l_fCalculateSecs;
float leftover_seconds = playertime_leaving_zone[client] - RoundToFloor(playertime_leaving_zone[client]);
int minutes = RoundToFloor(playertime_leaving_zone[client]);
leftover_seconds = leftover_seconds * 100;
if (g_bDev[client])
PrintToChat(client, "leftover_seconds: %f", leftover_seconds);
2020-04-05 16:43:49 +02:00
if (minutes == 0 && leftover_seconds == 0.0)
CPrintToChat(client, "Your record: None yet \nCommand: !toptime !mytime !stages");
else if (leftover_seconds < 10.0)
CPrintToChat(client, "Your record: 0%i:0%.4f \nCommand: !toptime !mytime !stages", minutes, leftover_seconds);
else
CPrintToChat(client, "Your record: 0%i:%.4f \nCommand: !toptime !mytime !stages", minutes, leftover_seconds);
2019-03-02 15:17:41 +01:00
if (l_iZoneCount < 2)
{
//no start zone, we use round time
CPrintToChat(client, "{green}[UNLOZE] Client: %N Time: 0%i:%.4f", client, g_iRoundMinutes, g_fRoundSeconds);
2020-04-05 00:56:20 +02:00
if (g_iRoundMinutes < minutes)
sendMYSQL(client, g_iRoundMinutes, g_fRoundSeconds, player_stage[client]);
2020-04-05 16:43:49 +02:00
else if (g_iRoundMinutes == minutes && g_fRoundSeconds < leftover_seconds)
2020-04-05 00:56:20 +02:00
sendMYSQL(client, g_iRoundMinutes, g_fRoundSeconds, player_stage[client]);
2020-04-05 16:43:49 +02:00
else if (minutes == 0 && leftover_seconds == 0.0)
sendMYSQL(client, g_iRoundMinutes, g_fRoundSeconds, player_stage[client]);
2019-03-02 15:17:41 +01:00
}
else
{
//uses start zone, we use time when leaving start zone
l_iCalculateMins = CalculateValuesMinutes(client);
l_fCalculateSecs = CalculateValues(client);
2019-03-02 15:17:41 +01:00
//tricking ppl !hehe
CPrintToChat(client, "{green}[UNLOZE] Stage: %i", player_stage[client]);
CPrintToChat(client, "{green}[UNLOZE] Client: %N Time: 0%i:%.4f", client, l_iCalculateMins, l_fCalculateSecs);
2020-04-05 00:56:20 +02:00
if (l_iCalculateMins < minutes)
sendMYSQL(client, l_iCalculateMins, l_fCalculateSecs, player_stage[client]);
2020-04-05 16:43:49 +02:00
else if (l_iCalculateMins == minutes && l_fCalculateSecs < leftover_seconds)
2020-04-05 00:56:20 +02:00
sendMYSQL(client, l_iCalculateMins, l_fCalculateSecs, player_stage[client]);
else if (minutes == 0.0 && leftover_seconds == 0.0)
sendMYSQL(client, l_iCalculateMins, l_fCalculateSecs, player_stage[client]);
2019-03-02 15:17:41 +01:00
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int CalculateValuesMinutes(int client)
{
float l_fRoundSeconds = g_fRoundSeconds;
float l_fRoundSecondsIndividual = g_fSecondsIndividual[client];
int l_iRoundMinutes = g_iRoundMinutes;
int l_iRoundMinutesIndividual = g_iMinutesIndividual[client];
if (l_iRoundMinutesIndividual > l_iRoundMinutes)
return 0;
l_iRoundMinutes = l_iRoundMinutes - l_iRoundMinutesIndividual;
if (l_fRoundSeconds < l_fRoundSecondsIndividual)
l_iRoundMinutes--;
return l_iRoundMinutes;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public float CalculateValues(int client)
2019-03-02 15:17:41 +01:00
{
// 2:24 enter with roundtime 5:29 = 3:05
// 3:01 enter with roundtime 3:59 = 58 sec
//example roundtime is 5 mins 40 seconds, client entered at 4 mins and 50 seconds, so 50 sec race
float l_fRoundSeconds = g_fRoundSeconds;
float l_fRoundSecondsIndividual = g_fSecondsIndividual[client];
float l_fSecAdd;
if (l_fRoundSeconds < l_fRoundSecondsIndividual)
2019-03-02 15:17:41 +01:00
{
2019-08-04 15:56:53 +02:00
while (l_fRoundSecondsIndividual < 59.9)
{
l_fRoundSecondsIndividual++;
l_fSecAdd++;
}
float returnvalue = l_fSecAdd + l_fRoundSeconds;
//PrintToChat(client, "returnvalue float: %f", returnvalue);
return returnvalue;
2019-03-02 15:17:41 +01:00
}
else
{
float returnvalueminus = l_fRoundSeconds - l_fRoundSecondsIndividual;
//PrintToChat(client, "returnvalueminus float: %f", returnvalueminus);
return returnvalueminus;
2019-03-02 15:17:41 +01:00
}
}
public void mysql_get_player_time(int client, int stage)
{
DBResultSet rs;
char query[g_dLength];
char steam_auth[g_dIndex];
GetClientAuthId(client, AuthId_Steam2, steam_auth, sizeof(steam_auth));
if (!stage)
Format(query, sizeof(query), "SELECT `%s` FROM `zetimer_table` where steam_auth = '%s'", g_cMapname, steam_auth);
else
Format(query, sizeof(query), "SELECT `%sS%i` FROM `zetimer_table` where steam_auth = '%s'", g_cMapname, stage, steam_auth);
if ((rs = SQL_Query(g_dDatabase, query)) == null)
{
delete rs;
return;
}
rs.FetchRow();
if (rs.RowCount > 0)
playertime_leaving_zone[client] = rs.FetchFloat(0);
if (g_bDev[client])
{
PrintToChat(client, "query: %s", query);
PrintToChat(client, "playertime_leaving_zone[client]: %f", playertime_leaving_zone[client]);
}
delete rs;
}
2019-03-02 15:17:41 +01:00
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void MYSQLCheckMapEntry()
{
int l_iRaceCount;
int l_iZoneCount = unloze_zoneCount();
char sQuery[g_dLength];
char l_cZoneIndexName[g_dIndex][g_dLength];
if (l_iZoneCount < 2)
{
Format(sQuery, sizeof(sQuery), "SELECT `%s` FROM `zetimer_table` LIMIT 1", g_cMapname);
SQL_TQuery(g_dDatabase, TqueryThreadCallback, sQuery);
}
else
for (int iterator = 0; iterator <= l_iZoneCount; iterator++)
2019-03-02 15:17:41 +01:00
{
if (IsCorrectZone(iterator, l_cZoneIndexName[iterator][g_dLength -1], "ZONE_PREFIX_RACE"))
2019-03-02 15:17:41 +01:00
{
l_iRaceCount++;
Format(sQuery, sizeof(sQuery), "SELECT `%sS%i` FROM `zetimer_table` LIMIT 1", g_cMapname, l_iRaceCount);
SQL_TQuery(g_dDatabase, TqueryThreadCallback, sQuery);
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void TqueryThreadCallback(Handle owner, Handle rs, const char[] error, any data)
{
int l_iRaceCount;
int l_iZoneCount = unloze_zoneCount();
char sQuery[g_dLength];
char l_cZoneIndexName[g_dIndex][g_dLength];
if (rs == null)
{
if (l_iZoneCount == 1)
{
Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table` ADD COLUMN `%s` DECIMAL(8,7) NOT NULL DEFAULT 0.000000", g_cMapname);
2019-03-02 15:17:41 +01:00
SQL_FastQuery(g_dDatabase, sQuery);
}
else
{
//this might seem repetitive but one null check adds all required coloumns
for (int iterator = 0; iterator <= l_iZoneCount; iterator++)
2019-03-02 15:17:41 +01:00
{
if (IsCorrectZone(iterator, l_cZoneIndexName[iterator][g_dLength -1], "ZONE_PREFIX_RACE"))
2019-03-02 15:17:41 +01:00
{
l_iRaceCount++;
Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table` ADD COLUMN `%sS%i` DECIMAL(8,7) NOT NULL DEFAULT 0.000000", g_cMapname, l_iRaceCount);
2019-03-02 15:17:41 +01:00
SQL_FastQuery(g_dDatabase, sQuery);
}
}
}
}
}
//----------------------------------------------------------------------------------------------------
// Purpose: TODO implement if needed
//----------------------------------------------------------------------------------------------------
public int GetTotalRaceZones()
{
int l_iZoneCount = unloze_zoneCount();
char l_cIndexName[g_dLength];
int l_iCountRace;
for (int iterator = 0; iterator < l_iZoneCount; iterator++)
2019-03-02 15:17:41 +01:00
{
ZoneNameBasedOnIndex(iterator, l_cIndexName[iterator]);
if (StrContains(l_cIndexName[iterator], "ZONE_PREFIX_RACE") > -1)
2019-03-02 15:17:41 +01:00
l_iCountRace++;
}
return l_iCountRace;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void sendMYSQL(int client, int minutes, float seconds, int stage)
2019-03-02 15:17:41 +01:00
{
int l_iZoneCount = unloze_zoneCount();
float l_fPlayerTime = float(minutes);
2019-03-02 15:17:41 +01:00
char sSID[g_dIndex];
char l_cClientName[g_dIndex];
char sQuery[g_dLength];
char sQuery2[g_dLength];
2019-03-02 15:17:41 +01:00
char sName[MAX_NAME_LENGTH];
GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
GetClientName(client, sName, sizeof(sName));
int size2 = 2 * strlen(sName) + 1;
char[] sEscapedName = new char[size2 + 1];
SQL_EscapeString(g_dDatabase, sName, sEscapedName, size2 + 1);
Format(l_cClientName, sizeof(l_cClientName), sEscapedName);
//STEAM_ID_STOP_IGNORING_RETVALS might be considered exploit?
if (StrEqual(sSID, "STEAM_ID_STOP_IGNORING_RETVALS") || StrEqual(sSID, "STEAM_ID_PENDING"))
2019-03-02 15:17:41 +01:00
return;
l_fPlayerTime = l_fPlayerTime + (seconds / 100);
if (l_iZoneCount < 2)
{
Format(sQuery2, sizeof(sQuery2), "SELECT %s FROM unloze_racetimer_css.zetimer_table zt where steam_auth = '%s'", g_cMapname, sSID);
2019-03-02 15:17:41 +01:00
Format(sQuery, sizeof(sQuery), "INSERT INTO `zetimer_table` (`steam_auth`, `name`, `%s`) VALUES ('%s', '%s', '%f') ON DUPLICATE KEY UPDATE `name` = '%s', `%s` = '%f'", g_cMapname, sSID, l_cClientName, l_fPlayerTime, l_cClientName, g_cMapname, l_fPlayerTime);
}
2019-03-02 15:17:41 +01:00
else
{
Format(sQuery2, sizeof(sQuery2), "SELECT %sS%i FROM unloze_racetimer_css.zetimer_table zt where steam_auth = '%s'", g_cMapname, stage, sSID);
2019-03-02 15:17:41 +01:00
Format(sQuery, sizeof(sQuery), "INSERT INTO `zetimer_table` (`steam_auth`, `name`, `%sS%i`) VALUES ('%s', '%s', '%f') ON DUPLICATE KEY UPDATE `name` = '%s', `%sS%i` = '%f'", g_cMapname, stage, sSID, l_cClientName, l_fPlayerTime, l_cClientName, g_cMapname, stage, l_fPlayerTime);
}
DBResultSet rs;
if ((rs = SQL_Query(g_dDatabase, sQuery2)) == null)
{
delete rs;
return;
}
rs.FetchRow();
if (!rs.RowCount)
{
delete rs;
return;
}
float oldtime = rs.FetchFloat(0);
bool update_time = l_fPlayerTime < oldtime ? true : false;
if (!update_time)
update_time = oldtime == 0.0 ? true : false;
delete rs;
if (g_bDev[client])
{
PrintToChat(client, "sQuery: %s", sQuery);
PrintToChat(client, "sQuery2: %s", sQuery2);
PrintToChat(client, "update_time: %i", update_time);
PrintToChat(client, "l_fPlayerTime: %f", l_fPlayerTime);
PrintToChat(client, "oldtime: %f", oldtime);
return;
}
if (update_time)
{
SQL_TQuery(g_dDatabase, DummyCallbackSimple, sQuery);
CPrintToChat(client, "Updated timer");
}
//PrintToChatAll("SEND MYSQL sQuery: %s", sQuery);
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void SQL_StartConnection()
{
char error[g_dLength];
if (SQL_CheckConfig("racetimercss"))
g_dDatabase = SQL_Connect("racetimercss", true, error, sizeof(error));
if (g_dDatabase == null)
{
CPrintToChatAll("{green}[UNLOZE] {white}Error! Could not connect to MYSQL-DB!");
}
//create tables
char sQuery[g_dLength];
Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `zetimer_table` (`steam_auth` VARCHAR(254) NOT NULL, `name` VARCHAR(254) NOT NULL, PRIMARY KEY (`steam_auth`))");
SQL_TQuery(g_dDatabase, DummyCallbackSimple, sQuery);
MYSQLCheckMapEntry();
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void DummyCallbackSimple(Handle hOwner, Handle hChild, const char[] err, DataPack pack1)
{
if (hOwner == null || hChild == null)
LogError("Query error. (%s)", err);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action cmd_timerCheckTop(int client, int args)
{
CheckTop(client, 0, 0);
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void CheckTop(int client, int index, int autismstate)
{
int l_iZoneCount = unloze_zoneCount();
char sQuery[g_dLength];
//PrintToChatAll("checktop l_iZoneCount: %i", l_iZoneCount);
if (l_iZoneCount < 1)
2019-03-02 15:17:41 +01:00
{
PrintToChat(client, "No zones active on this map");
2019-03-02 15:17:41 +01:00
return;
}
if (!autismstate)
2019-03-02 15:17:41 +01:00
{
CheckStagesOnMap(client, 0);
return;
}
//we have index now from menu selection
2019-03-02 15:17:41 +01:00
if (l_iZoneCount < 2)
Format(sQuery, sizeof(sQuery), "SELECT name, %s FROM `zetimer_table` WHERE %s > 0.000 ORDER BY %s ASC LIMIT 10", g_cMapname, g_cMapname, g_cMapname);
else
Format(sQuery, sizeof(sQuery), "SELECT name, `%sS%i` FROM `zetimer_table` WHERE `%sS%i` > 0.000 ORDER BY `%sS%i` ASC LIMIT 10", g_cMapname, index, g_cMapname, index, g_cMapname, index);
SQL_TQuery(g_dDatabase, SQL_SelectTop_Callback, sQuery, GetClientUserId(client));
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void SQL_SelectTop_Callback(Handle db, Handle results, const char[] error, any data)
{
int iclient = GetClientOfUserId(data);
2019-03-02 15:17:41 +01:00
int l_iMinutes;
int l_iPosition;
float l_fRecord;
float l_iSeconds;
//Player Name
char[] g_cPlayerName = new char[MAX_NAME_LENGTH];
char g_cContent[g_dLength];
if (iclient == 0)
2019-03-02 15:17:41 +01:00
{
return;
}
Menu menu = new Menu(MenuHandler1);
menu.SetTitle("Maptimer: %s", g_cMapname);
if (results != INVALID_HANDLE)
2019-03-02 15:17:41 +01:00
{
while (SQL_GetRowCount(results) > 0 && SQL_FetchRow(results))
{
l_iPosition++;
SQL_FetchString(results, 0, g_cPlayerName, MAX_NAME_LENGTH);
l_fRecord = SQL_FetchFloat(results, 1);
l_iMinutes = RoundToFloor(l_fRecord);
l_iSeconds = (l_fRecord - l_iMinutes) * 100;
Format(g_cContent, sizeof(g_cContent), "#%i: Time: 0%i:%.4f - %s", l_iPosition, l_iMinutes, l_iSeconds, g_cPlayerName);
menu.AddItem("-1", g_cContent, ITEMDRAW_DISABLED);
}
if (!l_iPosition)
{
menu.AddItem("-1", "No results. Commands: !toptime !stages", ITEMDRAW_DISABLED);
}
menu.ExitButton = true;
menu.Display(iclient, 0);
2019-03-02 15:17:41 +01:00
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)
{
if (action == MenuAction_End)
{
delete menu;
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
2019-09-05 23:14:56 +02:00
//----------------------------------------------------------------------------------------------------
public Action Cmd_devtest(int client, int args)
{
if (!IsValidClient(client))
return Plugin_Handled;
g_bDev[client] = !g_bDev[client];
PrintToChat(client, "dev mode: %i", g_bDev[client]);
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
2019-09-05 23:14:56 +02:00
public Action Cmd_timeReset(int client, int args)
{
if (!IsValidClient(client))
2019-09-05 23:16:38 +02:00
return Plugin_Handled;
2019-09-05 23:14:56 +02:00
if (args != 2)
{
ReplyToCommand(client, "[SM] Usage cleantime <target> <course>");
return Plugin_Handled;
}
char sTarget[65], steam2[64];
GetCmdArg(1, sTarget, sizeof(sTarget));
int targetID = FindTarget(client, sTarget, false);
if(targetID == -1)
return Plugin_Handled;
GetClientAuthId(targetID, AuthId_Steam2, steam2, sizeof(steam2));
GetCmdArg(2, sTarget, sizeof(sTarget));
deleteClientTime(steam2, StringToInt(sTarget));
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
2019-03-02 15:17:41 +01:00
//----------------------------------------------------------------------------------------------------
2019-07-24 00:43:06 +02:00
public Action cmd_hideTimerHUD(int client, int args)
{
if (!g_bHideTimer[client])
{
g_bHideTimer[client] = true;
2019-08-04 12:59:39 +02:00
SetClientCookie(client, g_hClientCookie, "1");
2019-07-24 00:43:06 +02:00
PrintToChat(client, "Disabled timer HUD");
2019-08-04 12:59:39 +02:00
} else { g_bHideTimer[client] = false; PrintToChat(client, "Enabled timer HUD"); SetClientCookie(client, g_hClientCookie, "0"); }
2019-07-24 00:43:06 +02:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
2019-03-02 15:17:41 +01:00
public Action cmd_timerCheckStage(int client, int args)
{
CheckStagesOnMap(client, 0);
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void CheckStagesOnMap(int client, int state)
{
int l_iCount;
int l_iZoneCount = unloze_zoneCount();
Menu StageMenu = CreateMenu(Stage_menu);
char l_cZoneIndexName[g_dIndex][g_dLength];
char l_cMenuContent[g_dLength];
if (!l_iZoneCount)
{
CPrintToChat(client, "[UNLOZE] Map does not support racestage timer");
return;
}
//state 0 == toptime, state 1 == own time
g_iClientChecking[client] = state;
StageMenu.SetTitle("Stages on: %s", g_cMapname);
if (g_bDisplaySpecial)
{
l_iCount++;
2019-03-02 15:17:41 +01:00
Format(l_cMenuContent, sizeof(l_cMenuContent), "Stage: %i", l_iCount);
StageMenu.AddItem("", l_cMenuContent);
}
else
{
for (int Iterator = 0; Iterator <= l_iZoneCount; Iterator++)
2019-03-02 15:17:41 +01:00
{
if (IsCorrectZone(Iterator, l_cZoneIndexName[Iterator][g_dLength -1], "ZONE_PREFIX_RACE"))
2019-03-02 15:17:41 +01:00
{
l_iCount++;
Format(l_cMenuContent, sizeof(l_cMenuContent), "Stage: %i", l_iCount);
StageMenu.AddItem("", l_cMenuContent);
}
}
}
2019-03-02 15:17:41 +01:00
StageMenu.ExitButton = true;
StageMenu.Display(client, 0);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public bool IsCorrectZone(int index, char[] zoneIndexName, char[] zone_prefix)
{
ZoneNameBasedOnIndex(index, zoneIndexName);
if (StrContains(zoneIndexName, zone_prefix) > -1)
{
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int Stage_menu(Menu menu, MenuAction action, int client, int selection)
{
if (action == MenuAction_Select && IsValidClient(client))
{
selection++;
if (!g_iClientChecking[client])
{
CheckTop(client, selection, 1);
}
else
{
CheckStageSelf(client, selection);
}
}
else if (action == MenuAction_End)
{
delete(menu);
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action cmd_timerCheckSelf(int client, int args)
{
Checkself(client);
return Plugin_Handled;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
2019-09-05 23:14:56 +02:00
public void deleteClientTime(char[] steam2, int stage)
{
char l_cQuery[g_dLength];
if (stage > 1)
{
Format(l_cQuery, sizeof(l_cQuery), "UPDATE `zetimer_table` SET `%sS%i` = 0.000 WHERE steam_auth = '%s'", g_cMapname, stage, steam2);
}
else
{
Format(l_cQuery, sizeof(l_cQuery), "UPDATE `zetimer_table` SET `%s` = 0.000 WHERE steam_auth = '%s'", g_cMapname, steam2);
SQL_TQuery(g_dDatabase, DummyCallbackSimple, l_cQuery);
Format(l_cQuery, sizeof(l_cQuery), "UPDATE `zetimer_table` SET `%sS1` = 0.000 WHERE steam_auth = '%s'", g_cMapname, steam2);
}
SQL_TQuery(g_dDatabase, DummyCallbackSimple, l_cQuery);
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
2019-03-02 15:17:41 +01:00
public void Checkself(int client)
{
int l_iZoneCount = unloze_zoneCount();
char l_cQuery[g_dLength];
char l_cSID[g_dIndex];
GetClientAuthId(client, AuthId_Steam2, l_cSID, sizeof(l_cSID));
if (l_iZoneCount < 1)
2019-03-02 15:17:41 +01:00
{
PrintToChat(client, "No zones active on this map");
2019-03-02 15:17:41 +01:00
return;
}
if (l_iZoneCount < 2)
{
Format(l_cQuery, sizeof(l_cQuery), "SELECT name, `%s` FROM `zetimer_table` WHERE steam_auth = '%s'", g_cMapname, l_cSID);
SQL_TQuery(g_dDatabase, TqueryCheckSelf, l_cQuery, GetClientUserId(client));
}
else
{
CheckStagesOnMap(client, 1);
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void CheckStageSelf(int client, int selection)
{
char l_cQuery[g_dLength];
char l_cSID[g_dIndex];
GetClientAuthId(client, AuthId_Steam2, l_cSID, sizeof(l_cSID));
Format(l_cQuery, sizeof(l_cQuery), "SELECT name, `%sS%i` FROM `zetimer_table` WHERE steam_auth = '%s'", g_cMapname, selection, l_cSID);
SQL_TQuery(g_dDatabase, TqueryCheckSelf, l_cQuery, GetClientUserId(client));
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void TqueryCheckSelf(Handle db, Handle rs, const char[] error, any data)
{
int l_iMinutes;
float l_fRecord;
float l_iSeconds;
char l_cMessageContent[g_dLength];
char[] l_cPlayerName = new char[MAX_NAME_LENGTH];
int iclient;
if ((iclient = GetClientOfUserId(data)) == 0)
2019-03-02 15:17:41 +01:00
return;
if (SQL_GetRowCount(rs) > 0 && SQL_FetchRow(rs))
{
SQL_FetchString(rs, 0, l_cPlayerName, MAX_NAME_LENGTH);
l_fRecord = SQL_FetchFloat(rs, 1);
if (l_fRecord == 0.000)
{
CPrintToChat(iclient, "You have no time yet!");
2019-03-02 15:17:41 +01:00
return;
}
l_iMinutes = RoundToFloor(l_fRecord);
l_iSeconds = (l_fRecord - l_iMinutes) * 100;
Format(l_cMessageContent, sizeof(l_cMessageContent), "%i:%.4f - %s", l_iMinutes, l_iSeconds, l_cPlayerName);
CPrintToChat(iclient, "Your best time: 0%s", l_cMessageContent);
2019-03-02 15:17:41 +01:00
}
else
CPrintToChat(iclient, "You have no time yet!");
2019-03-02 15:17:41 +01:00
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
stock bool IsValidClient(int client)
{
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
{
return true;
}
return false;
}