1358 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			SourcePawn
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1358 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			SourcePawn
		
	
	
		
			Executable File
		
	
	
	
	
| #pragma semicolon 1
 | |
| #define DEBUG
 | |
| #define PLUGIN_AUTHOR "jenz"
 | |
| #define PLUGIN_VERSION "1.9"
 | |
| #define g_dLength 400
 | |
| #define g_dIndex 65
 | |
| #include <sourcemod>
 | |
| #include <morecolors>
 | |
| #include <clientprefs>
 | |
| #include <unloze_zones>
 | |
| #include <unloze_racetimer_specialmaps>
 | |
| #include <unloze_racetimer_antizones>
 | |
| #include <cstrike>
 | |
| #include <sdktools>
 | |
| #include <sdkhooks>
 | |
| #include <PlayerManager>
 | |
| #include <outputinfo>
 | |
| #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];
 | |
| float g_fStartTime[MAXPLAYERS + 1];
 | |
| char g_csTime_record[MAXPLAYERS + 1][65];
 | |
| char g_csSID[MAXPLAYERS + 1][65];
 | |
| float g_fClientVectors[MAXPLAYERS + 1][3];
 | |
| float g_fClient_End_time[MAXPLAYERS + 1];
 | |
| int g_iClientFrames[MAXPLAYERS + 1];
 | |
| int g_iClientSpeedInterval[MAXPLAYERS + 1];
 | |
| int g_iClientChecking[MAXPLAYERS + 1];
 | |
| bool g_bClientsIgnoring[MAXPLAYERS + 1];
 | |
| bool g_bDisplaySpecial;
 | |
| bool g_bHumansAllowedTime[MAXPLAYERS + 1];
 | |
| bool g_bhumans_finished[MAXPLAYERS + 1];
 | |
| bool g_bHideTimer[MAXPLAYERS + 1];
 | |
| bool g_bEventBool = false;
 | |
| bool g_bClient_allowed_to_leave_again[MAXPLAYERS + 1];
 | |
| Handle g_hClientCookie = INVALID_HANDLE;
 | |
| Database g_dDatabase;
 | |
| Handle hText;
 | |
| 
 | |
| int player_stage[MAXPLAYERS + 1];
 | |
| Handle g_hAlterTableTimer = null;
 | |
| 
 | |
| public Plugin myinfo = 
 | |
| {
 | |
| 	name = "UNLOZE_racetimer_css",
 | |
| 	author = PLUGIN_AUTHOR,
 | |
| 	description = "tracks times on race maps on ze",
 | |
| 	version = PLUGIN_VERSION,
 | |
| 	url = "www.unloze.com"
 | |
| };
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPluginStart()
 | |
| {
 | |
|     //cmds
 | |
|     RegConsoleCmd("sm_toptime", cmd_timerCheckTop, "checking top 10");
 | |
|     RegConsoleCmd("sm_ignoretimer", cmd_timerIgnoreTime, "All racetimer will be ignored for you");
 | |
|     RegConsoleCmd("sm_ignoretime", cmd_timerIgnoreTime, "All racetimer will be ignored for you");
 | |
|     RegConsoleCmd("sm_mytime", cmd_timerCheckSelf, "checking your personal time");
 | |
|     RegConsoleCmd("sm_stages", cmd_timerCheckStage, "Checking race stages");
 | |
|     RegConsoleCmd("sm_hidetimer", cmd_hideTimerHUD, "Hides timer HUD");
 | |
|     RegAdminCmd("sm_cleantime", Cmd_timeReset, ADMFLAG_GENERIC);
 | |
|     //hooks
 | |
|     HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
 | |
|     HookEntityOutput("trigger_multiple", "OnTrigger", Trigger_Multiple);
 | |
|     HookEntityOutput("trigger_multiple", "OnStartTouch", Trigger_Multiple);
 | |
|     HookEntityOutput("trigger_teleport", "OnTrigger", trigger_teleport);
 | |
|     HookEntityOutput("trigger_teleport", "OnStartTouch", trigger_teleport);
 | |
|     //DB
 | |
|     if (!g_dDatabase)
 | |
|     {
 | |
|         Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
 | |
|     }
 | |
| 
 | |
|     //HUD
 | |
|     hText = CreateHudSynchronizer();
 | |
|     //Just constantly reruns the alter table query to handle new zones, less lazy solution would just be adding a forward for when zones were renamed
 | |
|     g_hAlterTableTimer = CreateTimer(10.00, Timer_alter_tables, _, TIMER_REPEAT);
 | |
|     //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);
 | |
|     }
 | |
|     g_bDisplaySpecial = unloze_gBSpecialMapDisplay();
 | |
| }
 | |
| 
 | |
| public Action allow_leaving_again(Handle hTimer, int Serial)
 | |
| {
 | |
|     int client; 
 | |
|     if ((client = GetClientFromSerial(Serial)) == 0)
 | |
|     {
 | |
|         return Plugin_Handled;
 | |
|     }
 | |
|     if (IsValidClient(client))
 | |
|     {
 | |
|         g_bClient_allowed_to_leave_again[client] = true;
 | |
|     }
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| public Action Timer_alter_tables(Handle hTimer)
 | |
| {
 | |
|     if (g_dDatabase)
 | |
|     {
 | |
|         startTimer();
 | |
|     }
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| 
 | |
| public void trigger_teleport(const char[] output, int entity_index, int client, float delay)
 | |
| {
 | |
|     if (IsValidEdict(entity_index) && IsValidClient(client) && g_bHumansAllowedTime[client])
 | |
| 	{
 | |
|         //if its surf maps there most likely are needed teleports
 | |
| 		if (StrContains(g_cMapname, "surf", false) == -1)
 | |
| 		{
 | |
|             g_bHumansAllowedTime[client] = false;
 | |
|             g_bhumans_finished[client] = false;
 | |
|             resetClientVectors(client);
 | |
|             g_bClient_allowed_to_leave_again[client] = false;
 | |
|             PrintToChat(client, "Disabled timer due to potential teleport abuse, type 1.");
 | |
|             CreateTimer(1.0, allow_leaving_again, GetClientSerial(client));
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| public void Trigger_Multiple(const char[] output, int entity_index, int client, float delay)
 | |
| {
 | |
|     if (IsValidEdict(entity_index) && origin_command_check(entity_index) && IsValidClient(client) && g_bHumansAllowedTime[client])
 | |
|     {
 | |
|         if (StrContains(g_cMapname, "surf", false) == -1)
 | |
|         {
 | |
|             g_bHumansAllowedTime[client] = false;
 | |
|             g_bhumans_finished[client] = false;
 | |
|             resetClientVectors(client);
 | |
|             g_bClient_allowed_to_leave_again[client] = false;
 | |
|             PrintToChat(client, "Disabled timer due to potential teleport abuse, type 1.");
 | |
|             CreateTimer(1.0, allow_leaving_again, GetClientSerial(client));
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| public bool origin_command_check(int entity_index)
 | |
| {
 | |
|         int count_trigger = GetOutputCount(entity_index, "m_OnTrigger");
 | |
|         int count_starttouch = GetOutputCount(entity_index, "m_OnStartTouch");
 | |
|         for     (int i = 0; i < count_trigger; i++)
 | |
|         {
 | |
|             char buffer[g_dLength];
 | |
|             GetOutputParameter(entity_index, "m_OnTrigger", i, buffer, sizeof(buffer));
 | |
|             if (StrContains(buffer, "origin", true) != -1)
 | |
|                 return true;
 | |
|         }
 | |
|         for(int i = 0; i < count_starttouch; i++)
 | |
|         {
 | |
|             char buffer[g_dLength];
 | |
|             GetOutputParameter(entity_index, "m_OnStartTouch", i, buffer, sizeof(buffer));
 | |
|             if (StrContains(buffer, "origin", true) != -1)
 | |
|                 return true;
 | |
|         }
 | |
|         return false;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
 | |
| {
 | |
|     if(!db || strlen(error))
 | |
|     {
 | |
|         LogError("Database error: %s", error);
 | |
|         return;
 | |
|     }
 | |
|     g_dDatabase = db;
 | |
|     //create tables
 | |
|     char sQuery[g_dLength];
 | |
|     Format(sQuery, sizeof(sQuery), "CREATE TABLE IF NOT EXISTS `zetimer_table_new` (`steam_auth` VARCHAR(254) NOT NULL, `name` VARCHAR(254) NOT NULL, PRIMARY KEY (`steam_auth`))");
 | |
|     g_dDatabase.Query(SQL_OnConnectFinished, sQuery, _, DBPrio_Normal);
 | |
| }
 | |
| 
 | |
| public void SQL_OnConnectFinished(Database db, DBResultSet results, const char[] error, any data)
 | |
| {
 | |
|     if(!db || strlen(error))
 | |
|     {
 | |
|             delete results;
 | |
|             LogError("Database error: %s", error);
 | |
|             return;
 | |
|     }
 | |
|     static Handle hHostName;
 | |
|     if((hHostName = FindConVar("hostname")) == INVALID_HANDLE)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     char line[g_dLength];
 | |
|     GetConVarString(hHostName, line, sizeof(line));
 | |
|     if (StrContains(line, "EVENT", false) > -1)
 | |
|         g_bEventBool = true;
 | |
|     else
 | |
|         g_bEventBool = false;
 | |
|     g_bDisplaySpecial = unloze_gBSpecialMapDisplay();
 | |
|     GetCurrentMap(g_cMapname, sizeof(g_cMapname));
 | |
|     startTimer();
 | |
| 
 | |
|     for(int i = 1; i <= MaxClients; i++)
 | |
|         if (IsValidClient(i))
 | |
|             OnClientPostAdminCheck(i);
 | |
|     AddBinarySearchIndex();
 | |
|     delete results;
 | |
| }
 | |
| 
 | |
| public void MYSQLCheckMapEntry()
 | |
| {
 | |
|     int l_iRaceCount;
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     char sQuery[g_dLength];
 | |
|     if (l_iZoneCount == 1)
 | |
|     {
 | |
|         Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table_new` ADD COLUMN IF NOT EXISTS `%s` REAL DEFAULT 0.000 NOT NULL", g_cMapname);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteString(sQuery);
 | |
|         g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         for (int iterator = 0; iterator <= l_iZoneCount; iterator++)
 | |
|         {
 | |
|             char zoneIndexName[512];
 | |
|             ZoneNameBasedOnIndex(iterator, zoneIndexName);
 | |
|             if (StrContains(zoneIndexName, "ZONE_PREFIX_RACE") > -1)
 | |
|             {
 | |
|                 l_iRaceCount++;
 | |
|                 Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table_new` ADD COLUMN IF NOT EXISTS `%sS%i` REAL DEFAULT 0.000 NOT NULL", g_cMapname, l_iRaceCount);
 | |
|                 DataPack hDataPack = new DataPack();
 | |
|                 hDataPack.WriteString(sQuery);
 | |
|                 g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     delete results;
 | |
|     if (!db || strlen(error))
 | |
|     {
 | |
|         char sQuery[g_dLength];
 | |
|         ResetPack(data);
 | |
|         data.ReadString(sQuery, sizeof(sQuery));
 | |
|         LogError("Query error 3: %s", error); 
 | |
|         LogError("actual query: %s", sQuery);
 | |
|     }
 | |
|     delete data;
 | |
| }
 | |
| 
 | |
| //a mysql table can max have 64 keys attached to it without recompiling. Therefore dropping and attaching binary tree index on the given map start
 | |
| //also check that racezones actually exist before making a binary tree index
 | |
| //2025: i eventually want to remake most of the race timer but i dont really have time. therefore i am changing this
 | |
| // with the simple assumption that the plugin only needs to index columns on main ze (port 27015) i will just skip deleting and creating indexes
 | |
| //for dev and ze2 server.
 | |
| public void AddBinarySearchIndex()
 | |
| {
 | |
|     int i_port = GetConVarInt(FindConVar("hostport"));
 | |
|     //only do stuff on ze
 | |
|     if (i_port != 27015)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     int race_zone_count = GetTotalRaceZones();
 | |
|     int l_iZoneCount = unloze_zoneCount(); //need this to check if its one zone or actually two zones with a ZONE_PREFIX_RACE and ZONE_PREFIX_START
 | |
| 
 | |
|     char sQuery[g_dLength];
 | |
|     GetCurrentMap(g_cMapname, sizeof(g_cMapname));
 | |
|     //LogError("race_zone_count: %i. map: %s. l_iZoneCount: %i", race_zone_count, g_cMapname, l_iZoneCount);
 | |
| 
 | |
|     //if admins dont make dumb random zones without any meaning it works fine probably(?)
 | |
|     if (race_zone_count == 1 && l_iZoneCount == 1) //there is a ZONE_PREFIX_RACE and its also the only zone on the map.
 | |
|     {
 | |
|         Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table_new` add INDEX if not exists `%s` (`%s`)", g_cMapname, g_cMapname);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteString(sQuery);
 | |
|         //LogError("Create index query: %s", sQuery);
 | |
|         g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_High);
 | |
|     }
 | |
|     else if (race_zone_count > 0) //finally fixing the false created indexes.
 | |
|     {
 | |
|         for (int i = 1; i <= race_zone_count; i++)
 | |
|         {
 | |
|             Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table_new` add INDEX if not exists `%sS%i` (`%sS%i`)", g_cMapname, i, g_cMapname, i);
 | |
|             //LogError("Create index query iteration: %s", sQuery);
 | |
|             DataPack hDataPack = new DataPack();
 | |
|             hDataPack.WriteString(sQuery);
 | |
|             g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_High);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| //2025 edit: as said above its not great, will be kept however until the eventual remake of the racetimer. 
 | |
| public void RemoveBinarySearchIndex()
 | |
| {
 | |
|     int i_port = GetConVarInt(FindConVar("hostport"));
 | |
|     //only do stuff on ze
 | |
|     if (i_port != 27015)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     //lazy change, just take all indexes from the table that are not the primary key. its what we care about.
 | |
|     char sQuery[g_dLength];
 | |
|     Format(sQuery, sizeof(sQuery), "SELECT `INDEX_NAME` FROM `information_schema`.`STATISTICS` WHERE `TABLE_SCHEMA` = 'unloze_racetimer_css' AND `TABLE_NAME` = 'zetimer_table_new' AND `INDEX_NAME` != 'PRIMARY'");
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteString(sQuery);
 | |
|     g_dDatabase.Query(SQL_GetAllIndexes, sQuery, hDataPack, DBPrio_Normal);
 | |
| }
 | |
| 
 | |
| public void SQL_GetAllIndexes(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     ResetPack(data);
 | |
|     if (!db || strlen(error))
 | |
|     {
 | |
|         char sQuery[g_dLength]; 
 | |
|         data.ReadString(sQuery, sizeof(sQuery));
 | |
|         LogError("Query error in SQL_GetAllIndexes: %s", error);
 | |
|         LogError("actual query: %s", sQuery);
 | |
|         delete data;
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     delete data;
 | |
| 
 | |
|     while (results.RowCount && results.FetchRow())
 | |
|     {
 | |
|         char index_name[256];
 | |
|         results.FetchString(0, index_name, sizeof(index_name));
 | |
|         //LogError("here mapname: %s", index_name);
 | |
|         //just drop the indexes
 | |
|         char sQuery[g_dLength];
 | |
|         Format(sQuery, sizeof(sQuery), "ALTER TABLE `zetimer_table_new` drop INDEX if exists `%s`", index_name);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteString(sQuery);
 | |
|         g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
|     }
 | |
|     delete results;
 | |
| }
 | |
| 
 | |
| public void OnMapEnd()
 | |
| {
 | |
|     if (g_dDatabase)
 | |
|         RemoveBinarySearchIndex(); 
 | |
| }
 | |
| 
 | |
| public void OnMapStart()
 | |
| {	
 | |
|     if (!g_dDatabase)
 | |
|         Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
 | |
|     else
 | |
|     {
 | |
|         AddBinarySearchIndex();
 | |
|         static Handle hHostName;
 | |
|         if((hHostName = FindConVar("hostname")) == INVALID_HANDLE)
 | |
|             return;
 | |
|         char line[g_dLength];
 | |
|         GetConVarString(hHostName, line, sizeof(line));
 | |
|         if (StrContains(line, "EVENT", false) > -1)
 | |
|             g_bEventBool = true;
 | |
|         else
 | |
|             g_bEventBool = false;
 | |
|         g_bDisplaySpecial = unloze_gBSpecialMapDisplay();
 | |
|         GetCurrentMap(g_cMapname, sizeof(g_cMapname));
 | |
|     }
 | |
|     Format(g_cSpecialMapStart, sizeof(g_cSpecialMapStart), "");
 | |
|     Format(g_cSpecialMapEnd, sizeof(g_cSpecialMapEnd), "");
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPluginEnd()
 | |
| {
 | |
|     CloseHandle(hText);
 | |
|     if (g_hAlterTableTimer != null)
 | |
|         delete g_hAlterTableTimer;
 | |
|     RemoveBinarySearchIndex(); 
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| 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 void Event_RoundStart(Handle event, const char[] name, bool dontBroadcast)
 | |
| {
 | |
|     Format(g_cSpecialMapStart, sizeof(g_cSpecialMapStart), "");
 | |
|     Format(g_cSpecialMapEnd, sizeof(g_cSpecialMapEnd), "");
 | |
|     int race_zone_count = GetTotalRaceZones();
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     if (!race_zone_count)
 | |
|         return;
 | |
|     for (int i = 1; i <= MaxClients; i++)
 | |
|         if (IsValidClient(i) && !IsFakeClient(i))
 | |
|         {
 | |
|             g_bhumans_finished[i] = false;
 | |
|             g_fClient_End_time[i] = 0.0;
 | |
|             resetClientVectors(i);
 | |
|             char first_zone[512];
 | |
|             ZoneNameBasedOnIndex(0, first_zone);
 | |
|             g_bClient_allowed_to_leave_again[i] = true;
 | |
|             g_bHumansAllowedTime[i] = false;
 | |
|             if (l_iZoneCount == 1 && race_zone_count == 1)
 | |
|             {
 | |
|                 g_bHumansAllowedTime[i] = true;
 | |
|                 PrintToChat(i, "Started timer: There is only a finish zone");
 | |
|                 g_fStartTime[i] = GetEngineTime();
 | |
|                 mysql_get_player_time(i, 0);
 | |
|             }
 | |
|         }
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnClientPostAdminCheck(int client)
 | |
| {
 | |
|     GetClientAuthId(client, AuthId_Steam2, g_csSID[client], sizeof(g_csSID[]));
 | |
|     resetClient(client);
 | |
|     insertPlayerMYSQL(client);
 | |
|     client_ignoring_racetimer(client);
 | |
| }
 | |
| 
 | |
| public void client_ignoring_racetimer(int client)
 | |
| {
 | |
|     char query[g_dLength];
 | |
|     Format(query, sizeof(query), "SELECT is_ignoring FROM `zetimer_table_new_ignoring` where steam_auth = '%s'", g_csSID[client]);
 | |
| 
 | |
|     g_dDatabase.Query(SQL_OnQueryCompleted_ignoring, query, GetClientSerial(client));
 | |
| }
 | |
| 
 | |
| public void SQL_OnQueryCompleted_ignoring(Database db, DBResultSet results, const char[] error, int Serial)
 | |
| {
 | |
|     if (!db)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     int client; 
 | |
|     if ((client = GetClientFromSerial(Serial)) == 0)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     if (!IsValidClient(client))
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     int val = 0;
 | |
|     if (results.RowCount && results.FetchRow())
 | |
|         val = results.FetchInt(0);
 | |
|     g_bClientsIgnoring[client] = false;
 | |
|     if (val == 1)
 | |
|     {
 | |
|         g_bClientsIgnoring[client] = true;
 | |
|     }
 | |
|     delete results;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnClientCookiesCached(int client)
 | |
| {
 | |
| 	char sValue[8];
 | |
| 	GetClientCookie(client, g_hClientCookie, sValue, sizeof(sValue));
 | |
| 	g_bHideTimer[client] = (sValue[0] != '\0' && !!StringToInt(sValue));
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnClientDisconnect(int client)
 | |
| {
 | |
|     Format(g_csSID[client], sizeof(g_csSID[]), "");
 | |
|     resetClient(client);
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void resetClient(int client)
 | |
| {
 | |
|     if (0 < client <= MaxClients)
 | |
|     {
 | |
|         g_iClientChecking[client] = 0; 
 | |
|         g_bClientsIgnoring[client] = false;
 | |
|         g_bHumansAllowedTime[client] = false;
 | |
|         g_bhumans_finished[client] = false;
 | |
|         g_fClient_End_time[client] = 0.0;
 | |
|         g_bClient_allowed_to_leave_again[client] = false;
 | |
|         resetClientVectors(client);
 | |
|         g_fStartTime[client] = 0.0;
 | |
|         player_stage[client] = 0;
 | |
|         Format(g_csTime_record[client], sizeof(g_csTime_record[]), "0.000");
 | |
|     }
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
 | |
| {
 | |
|     if (!IsValidClient(client))
 | |
|         return;
 | |
|     if (!g_bHumansAllowedTime[client])
 | |
|         return;
 | |
|     //checks if event is going on
 | |
|     if (g_bEventBool)
 | |
|     {
 | |
|         g_bHumansAllowedTime[client] = false;
 | |
|         PrintToChat(client, "Disabling timer due to map being marked as event map.");
 | |
|         return;
 | |
|     }	
 | |
|     if (!IsPlayerAlive(client))
 | |
|     {
 | |
|         g_bHumansAllowedTime[client] = false;
 | |
|         g_bhumans_finished[client] = false;
 | |
|         resetClientVectors(client);
 | |
|         PrintToChat(client, "Disabled timer due to dying.");
 | |
|         return;
 | |
|     }
 | |
|     if (GetClientTeam(client) == CS_TEAM_CT)
 | |
|     {
 | |
|         float clientVectors[3];
 | |
|         GetClientAbsOrigin(client, clientVectors);
 | |
|         if (checkClientOrigin(g_fClientVectors[client], clientVectors, client))
 | |
|         {
 | |
|             g_bHumansAllowedTime[client] = false;
 | |
|             g_bhumans_finished[client] = false;
 | |
|             resetClientVectors(client);
 | |
|             g_bClient_allowed_to_leave_again[client] = false;
 | |
|             PrintToChat(client, "Disabled timer due to potential teleport abuse, type 2.");
 | |
|             CreateTimer(1.0, allow_leaving_again, GetClientSerial(client));
 | |
|             return;
 | |
|         }
 | |
|         int frameCap = 11;
 | |
|         if (g_bhumans_finished[client])
 | |
|             g_iClientFrames[client] = 11;
 | |
|         if (g_iClientFrames[client] >= frameCap)
 | |
|         {
 | |
|             g_iClientFrames[client] = 0;
 | |
|             if (g_bhumans_finished[client])
 | |
|             {
 | |
|                 resetClientVectors(client);
 | |
|                 g_bhumans_finished[client] = false;
 | |
|                 g_bHumansAllowedTime[client] = false;
 | |
|                 FinishedStageRaceZone(client);
 | |
|                 return;
 | |
|             }
 | |
|             int speedCheckerCap = 10;
 | |
|             if (g_iClientSpeedInterval[client] > speedCheckerCap)
 | |
|             {
 | |
|                 g_iClientSpeedInterval[client] = 0;
 | |
|                 bool bNoclip = (GetEntityMoveType(client) == MOVETYPE_NOCLIP);
 | |
|                 if (bNoclip)
 | |
|                 {
 | |
|                     g_bHumansAllowedTime[client] = false;
 | |
|                     g_bhumans_finished[client] = false;
 | |
|                     resetClientVectors(client);
 | |
|                     PrintToChat(client, "Disabled timer due to Noclip");
 | |
|                     return;
 | |
|                 }
 | |
|                 float speed = GetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue");
 | |
|                 if (speed > 1.0)
 | |
|                 {
 | |
|                     if (StrContains(g_cMapname, "surf", false) == -1)
 | |
|                     {
 | |
|                         g_bHumansAllowedTime[client] = false;
 | |
|                         g_bhumans_finished[client] = false;
 | |
|                         resetClientVectors(client);
 | |
|                         PrintToChat(client, "Disabled timer due to modified run speed");
 | |
|                         return;
 | |
|                     }
 | |
|                 }
 | |
|                 float client_gravity = GetEntityGravity(client);
 | |
|                 ConVar gravity = FindConVar("sv_gravity");
 | |
|                 float gravityFloat = gravity.FloatValue;
 | |
|                 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;
 | |
|                     g_bhumans_finished[client] = false;
 | |
|                     resetClientVectors(client);
 | |
|                     PrintToChat(client, "Disabled timer due to modified gravity");
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
|             g_fClientVectors[client] = clientVectors;
 | |
|             if (hText != INVALID_HANDLE && !g_bHideTimer[client])
 | |
|             {
 | |
|                 SetHudTextParams(0.35, 0.85, 0.1, 125, 255, 255, 85);
 | |
|                 float total_time = client_current_race_time(client);
 | |
|                 if (total_time != -1.0)
 | |
|                     ShowSyncHudText(client, hText, "%N Time: %06.3f\nRecord: %s\nMap: %s\nCourse: %i", client, total_time, g_csTime_record[client], g_cMapname, player_stage[client]);
 | |
|             }
 | |
|             g_iClientSpeedInterval[client]++;
 | |
|         }
 | |
|         g_iClientFrames[client]++;
 | |
|     }
 | |
|     else 
 | |
|     {
 | |
|         //is zm
 | |
|         g_bHumansAllowedTime[client] = false;
 | |
|         g_bhumans_finished[client] = false;
 | |
|         //called if teleported to some place far away or teleported from inside start zone to end zone
 | |
|         resetClientVectors(client);
 | |
|         PrintToChat(client, "Disabled timer due to ZM infection.");
 | |
|         return;
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| public float client_current_race_time(int i_client)
 | |
| {
 | |
|     if (g_fStartTime[i_client] == 0.0)
 | |
|         return -1.0;
 | |
|     return GetEngineTime() - g_fStartTime[i_client];
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // 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;
 | |
| 	}
 | |
| 	float teleport_range = 1090450.0;
 | |
| 	int velocityCap = 625;
 | |
| 	float distance = GetVectorDistance(oldVals, newVals, true);
 | |
| 	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;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void unloze_zoneEntry(int client, char[] zone)
 | |
| {
 | |
|     if (g_bClientsIgnoring[client])
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     int zoneIndex = RetrieveZoneIndex(zone);
 | |
|     int race_zone_count = GetTotalRaceZones();
 | |
|     if (!(StrEqual(zone, g_cSpecialMapEnd)) && !race_zone_count)
 | |
|         return;
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
| 	
 | |
|     if (GetClientTeam(client) == CS_TEAM_CT && (g_bHumansAllowedTime[client] || StrEqual(zone, g_cSpecialMapEnd)))
 | |
|     {
 | |
|         if ((StrContains(zone, "ZONE_PREFIX_RACE") > -1) || StrEqual(zone, g_cSpecialMapEnd))
 | |
|         {
 | |
|             if (l_iZoneCount < 2)
 | |
|                 player_stage[client] = 0;
 | |
|             if (player_stage[client] == (zoneIndex / 2) || l_iZoneCount < 2)
 | |
|             {
 | |
|                 g_bhumans_finished[client] = true;
 | |
|                 g_fClient_End_time[client] = client_current_race_time(client);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void unloze_zoneLeave(int client, char[] zone)
 | |
| {
 | |
| 	//only maps with multiple zones need ZONE_PREFIX_START
 | |
|     if (g_bClientsIgnoring[client])
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     int race_zone_count = GetTotalRaceZones();
 | |
|     if (!(StrEqual(zone, g_cSpecialMapStart)) && !race_zone_count)
 | |
|         return;
 | |
| 
 | |
|     if (GetClientTeam(client) == CS_TEAM_CT)
 | |
|     {
 | |
|         if ((StrContains(zone, "ZONE_PREFIX_START") > -1) || StrEqual(zone, g_cSpecialMapStart))
 | |
|         {
 | |
|             if (!IsFakeClient(client) && !PM_IsPlayerSteam(client))
 | |
|             {
 | |
|                 PrintToChat(client, "Not starting timer due to being listed as nosteamer");
 | |
|                 return;
 | |
|             }
 | |
|             if (!g_bClient_allowed_to_leave_again[client])
 | |
|             {
 | |
|                 PrintToChat(client, "Did not start timer due to teleport cooldown.");
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             g_fStartTime[client] = GetEngineTime();
 | |
|             float notRounded = float(RetrieveZoneIndex(zone));
 | |
|             player_stage[client] = RoundToCeil(notRounded / 2);
 | |
|             CPrintToChat(client, "Timer started for Course: %i",  player_stage[client]);
 | |
|             g_bHumansAllowedTime[client] = true;
 | |
|             mysql_get_player_time(client, player_stage[client]);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // 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])
 | |
|     {
 | |
|         g_bHumansAllowedTime[client] = false;
 | |
|         PrintToChat(client, "Disabled Timer due to using illegal shortcut");
 | |
|     }
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // 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;
 | |
| 	if (iterator == -1)
 | |
| 		return 1;
 | |
| 	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]);
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void FinishedStageRaceZone(int client)
 | |
| {
 | |
|     char sName[MAX_NAME_LENGTH];
 | |
|     GetClientName(client, sName, sizeof(sName));
 | |
|     int size2 = 2 * strlen(sName) + 1;
 | |
|     char[] sEscapedName = new char[size2 + 1];
 | |
| 
 | |
|     g_dDatabase.Escape(sName, sEscapedName, size2 + 1);
 | |
| 
 | |
|     if (StrEqual(g_csSID[client], "STEAM_ID_STOP_IGNORING_RETVALS") || StrEqual(g_csSID[client], "STEAM_ID_PENDING"))
 | |
|     {
 | |
|         PrintToChat(client, "Your steam ID is not working, not updating timer");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     float client_time = g_fClient_End_time[client];
 | |
|     if (client_time == -1.0)
 | |
|     {
 | |
|         //if client disconnected we dont want to cary timer over to other client
 | |
|         return;
 | |
|     }
 | |
|     if (l_iZoneCount > 1)
 | |
|         CPrintToChat(client, "{green}[UNLOZE] Stage: %i", player_stage[client]);
 | |
|     CPrintToChat(client, "{green}[UNLOZE] Time: %06.3f", client_time);
 | |
|     int stage = player_stage[client];
 | |
|     char sQuery[g_dLength];
 | |
|     if (StrEqual(g_csTime_record[client], "0.000"))
 | |
|     {
 | |
|         CPrintToChat(client, "{green}[UNLOZE] Your record: None yet\nCommand: !toptime !mytime !stages");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         CPrintToChat(client, "{green}[UNLOZE] Your record: %s\nCommand: !toptime !mytime !stages", g_csTime_record[client]);
 | |
|     }
 | |
|     if (l_iZoneCount < 2)
 | |
|         Format(sQuery, sizeof(sQuery), "UPDATE `zetimer_table_new` SET `%s` = '%06.3f', name = '%s' WHERE steam_auth = '%s'", g_cMapname, client_time, sEscapedName, g_csSID[client]);
 | |
|     else
 | |
|         Format(sQuery, sizeof(sQuery), "UPDATE `zetimer_table_new` SET `%sS%i` = '%06.3f', name = '%s' WHERE steam_auth = '%s'", g_cMapname, stage, client_time, sEscapedName, g_csSID[client]);
 | |
|     int generic_length = 32;
 | |
|     char[][] sPart = new char[2][generic_length];
 | |
|     float old_client_time = 0.0;
 | |
|     if (StrContains(g_csTime_record[client], ":") != -1)
 | |
|     {
 | |
|         ExplodeString(g_csTime_record[client], ":", sPart, 2, generic_length);
 | |
|         old_client_time = (StringToFloat(sPart[0]) * 60) + StringToFloat(sPart[1]);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         old_client_time = StringToFloat(g_csTime_record[client]);
 | |
|     }
 | |
|     if (client_time >= old_client_time && old_client_time > 0.0)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteString(sQuery);
 | |
|     g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void mysql_get_player_time(int client, int stage)
 | |
| {
 | |
|     char query[g_dLength];
 | |
|     if (!stage)
 | |
|     {
 | |
|         Format(query, sizeof(query), "SELECT `%s` FROM `zetimer_table_new` where steam_auth = '%s'", g_cMapname, g_csSID[client]);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteCell(GetClientSerial(client));
 | |
|         g_dDatabase.Query(SQL_OnQueryCompleted_retry, query, hDataPack);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         Format(query, sizeof(query), "SELECT `%sS%i` FROM `zetimer_table_new` where steam_auth = '%s'", g_cMapname, stage, g_csSID[client]);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteCell(GetClientSerial(client));
 | |
|         hDataPack.WriteString(query);
 | |
|         g_dDatabase.Query(SQL_OnQueryCompleted, query, hDataPack);
 | |
|     }
 | |
| }
 | |
| 
 | |
| //we only enter here when stage is 0. that might however be incorrect as it instead might need to be S1. Simply a band aid instead of fixing actual problem.
 | |
| public void SQL_OnQueryCompleted_retry(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     ResetPack(data);
 | |
|     int client_serial = data.ReadCell();
 | |
|     delete data;
 | |
|     if (!db)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     int client; 
 | |
|     if ((client = GetClientFromSerial(client_serial)) == 0)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     if (strlen(error))
 | |
|     {
 | |
|         delete results;
 | |
|         mysql_get_player_time(client, 1);
 | |
|         return;
 | |
|     }
 | |
|     if (results.RowCount && results.FetchRow())
 | |
|         results.FetchString(0, g_csTime_record[client], sizeof(g_csTime_record[]));
 | |
|     delete results;
 | |
| }
 | |
| 
 | |
| public void SQL_OnQueryCompleted(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     ResetPack(data);
 | |
|     int client_serial = data.ReadCell();
 | |
|     if (!db || strlen(error))
 | |
|     {
 | |
|         char sQuery[g_dLength]; 
 | |
|         data.ReadString(sQuery, sizeof(sQuery));
 | |
|         LogError("Query error 1: %s", error);
 | |
|         LogError("actual query: %s", sQuery);
 | |
|         delete data;
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     delete data;
 | |
|     int client; 
 | |
|     if ((client = GetClientFromSerial(client_serial)) == 0)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     if (results.RowCount && results.FetchRow())
 | |
|         results.FetchString(0, g_csTime_record[client], sizeof(g_csTime_record[]));
 | |
|     delete results;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // 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++)
 | |
| 	{
 | |
| 		ZoneNameBasedOnIndex(iterator, l_cIndexName[iterator]);
 | |
| 		if (StrContains(l_cIndexName[iterator], "ZONE_PREFIX_RACE") > -1)
 | |
| 			l_iCountRace++;
 | |
| 	}
 | |
| 	return l_iCountRace;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void insertPlayerMYSQL(int client)
 | |
| {
 | |
|     if (!IsValidClient(client))
 | |
|         return;
 | |
|     char sQuery[g_dLength];
 | |
|     char sName[MAX_NAME_LENGTH];
 | |
|     GetClientName(client, sName, sizeof(sName));
 | |
|     int size2 = 2 * strlen(sName) + 1;
 | |
|     char[] sEscapedName = new char[size2 + 1];
 | |
|     if (!g_dDatabase)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     g_dDatabase.Escape(sName, sEscapedName, size2 + 1);
 | |
|     if (StrEqual(g_csSID[client], "STEAM_ID_STOP_IGNORING_RETVALS") || StrEqual(g_csSID[client], "STEAM_ID_PENDING"))
 | |
|     {
 | |
|             PrintToChat(client, "Your steam ID is not working, not updating timer");
 | |
|             return;
 | |
|     }
 | |
|     Format(sQuery, sizeof(sQuery), "INSERT INTO `zetimer_table_new` (`steam_auth`, `name`) VALUES ('%s', '%s') ON DUPLICATE KEY UPDATE `name` = '%s'", g_csSID[client], sEscapedName, sEscapedName);
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteString(sQuery);
 | |
|     g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public Action cmd_timerIgnoreTime(int client, int args)
 | |
| {	
 | |
|     insert_client_ignoring_racetimer(client);
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| public void insert_client_ignoring_racetimer(int client)
 | |
| {
 | |
|     if (!IsValidClient(client))
 | |
|         return;
 | |
|     if (g_bClientsIgnoring[client])
 | |
|     {
 | |
|         g_bClientsIgnoring[client] = false;
 | |
|         g_bHideTimer[client] = false;
 | |
|         SetClientCookie(client, g_hClientCookie, "0");
 | |
|         PrintToChat(client, "You are now not ignoring the racetimer");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         g_bClientsIgnoring[client] = true;
 | |
|         g_bHideTimer[client] = true;
 | |
|         SetClientCookie(client, g_hClientCookie, "1");
 | |
|         PrintToChat(client, "You are now ignoring the racetimer");
 | |
|     }
 | |
|     char sQuery[g_dLength];
 | |
|     if (!g_dDatabase)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
|     if (StrEqual(g_csSID[client], "STEAM_ID_STOP_IGNORING_RETVALS") || StrEqual(g_csSID[client], "STEAM_ID_PENDING"))
 | |
|     {
 | |
|             PrintToChat(client, "Your steam ID is not working, not updating timer");
 | |
|             return;
 | |
|     }
 | |
|     Format(sQuery, sizeof(sQuery), "INSERT INTO `zetimer_table_new_ignoring` (`steam_auth`, `is_ignoring`) VALUES ('%s', '%i') ON DUPLICATE KEY UPDATE `is_ignoring` = '%i'", g_csSID[client], g_bClientsIgnoring[client], g_bClientsIgnoring[client]);
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteString(sQuery);
 | |
|     g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
 | |
| }
 | |
| public Action cmd_timerCheckTop(int client, int args)
 | |
| {	
 | |
| 	CheckTop(client, 0, 0);
 | |
| 	return Plugin_Handled;
 | |
| }
 | |
| 
 | |
| public void mysql_select_lowest_ordered(int client, int index, int length_increase, Menu menu, int l_iPosition)
 | |
| {
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     char sQuery[g_dLength];
 | |
|     if (l_iZoneCount < 2)
 | |
|         Format(sQuery, sizeof(sQuery), "select name, `%s` from `zetimer_table_new` where `%s` > 0 order by `%s` asc limit 10", g_cMapname, g_cMapname, g_cMapname);
 | |
|     else
 | |
|         Format(sQuery, sizeof(sQuery), "select name, `%sS%i` from `zetimer_table_new` where `%sS%i` > 0 order by `%sS%i` asc limit 10", g_cMapname, index, g_cMapname, index, g_cMapname, index);
 | |
|     //LogMessage("sQuery: %s", sQuery);
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteCell(GetClientSerial(client));
 | |
|     hDataPack.WriteString(sQuery);
 | |
|     hDataPack.WriteCell(index);
 | |
|     hDataPack.WriteCell(menu);
 | |
|     hDataPack.WriteCell(l_iPosition);
 | |
|     hDataPack.WriteCell(length_increase);
 | |
|     g_dDatabase.Query(SQL_Select_Top_Callback, sQuery, hDataPack);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void CheckTop(int client, int index, int autismstate)
 | |
| {
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     if (l_iZoneCount < 1)
 | |
|     {
 | |
|         PrintToChat(client, "No zones active on this map");
 | |
|         return;
 | |
|     }
 | |
|     if (!autismstate)
 | |
|     {
 | |
|         CheckStagesOnMap(client, 0);
 | |
|         return;
 | |
|     }
 | |
|     mysql_select_lowest_ordered(client, index, 0, null, 0);
 | |
| }
 | |
| 
 | |
| public void SQL_Select_Top_Callback(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     ResetPack(data);
 | |
|     int client_serial = data.ReadCell();
 | |
|     char sQuery[g_dLength];
 | |
|     data.ReadString(sQuery, sizeof(sQuery));
 | |
|     if (!db || strlen(error))
 | |
|     {
 | |
|             LogError("Query error 2: %s", error);   
 | |
|             LogError("actual query: %s", sQuery);
 | |
|             delete data;
 | |
|             delete results;
 | |
|             return;
 | |
|     }
 | |
|     int index = data.ReadCell();
 | |
|     Menu menu = data.ReadCell();
 | |
|     int l_iPosition = data.ReadCell();
 | |
|     int length_increase = data.ReadCell();
 | |
|     length_increase++;
 | |
|     delete data;
 | |
|     int iclient;
 | |
|     if ((iclient = GetClientFromSerial(client_serial)) == 0)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     //Player Name
 | |
|     char[] g_cPlayerName = new char[MAX_NAME_LENGTH];
 | |
|     char g_cContent[g_dLength];
 | |
|     if (menu == null)
 | |
|     {
 | |
|         menu = new Menu(MenuHandler1);
 | |
|         menu.SetTitle("Maptimer: %s", g_cMapname);
 | |
|     }
 | |
|     if (results != INVALID_HANDLE)
 | |
|     {
 | |
|         while (results.RowCount > 0 && results.FetchRow() && l_iPosition < 10)
 | |
|         {
 | |
|             l_iPosition++;
 | |
|             results.FetchString(0, g_cPlayerName, MAX_NAME_LENGTH);
 | |
|             float fTime = results.FetchFloat(1);
 | |
|             Format(g_cContent, sizeof(g_cContent), "#%i: Time: %06.3f - %s", l_iPosition, fTime, g_cPlayerName);
 | |
|             menu.AddItem("-1", g_cContent, ITEMDRAW_DISABLED);
 | |
|         }
 | |
|         delete results;
 | |
|         if (!l_iPosition)
 | |
|         {
 | |
|             menu.AddItem("-1", "No results. Commands: !toptime !stages", ITEMDRAW_DISABLED);
 | |
|         }
 | |
|         else if (l_iPosition < 10)
 | |
|         {
 | |
|             //did 2 mins googling but found nothing about menus needing to be cleaned
 | |
|             mysql_select_lowest_ordered(iclient, index, length_increase, menu, l_iPosition);
 | |
|             return;
 | |
|         }
 | |
|         menu.ExitButton = true;
 | |
|         menu.Display(iclient, 0);
 | |
|     }
 | |
|     delete results;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------	
 | |
| public int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)
 | |
| {
 | |
| 	if (action == MenuAction_End)
 | |
| 		delete menu;
 | |
|     return 0;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public Action Cmd_timeReset(int client, int args)
 | |
| {
 | |
| 	if (!IsValidClient(client))
 | |
| 		return Plugin_Handled;
 | |
| 	if (args != 2)
 | |
| 	{
 | |
| 		ReplyToCommand(client, "[SM] Usage cleantime <target> <course>");
 | |
| 		return Plugin_Handled;
 | |
| 	}
 | |
| 	char sTarget[65];
 | |
| 	GetCmdArg(1, sTarget, sizeof(sTarget));
 | |
| 	int targetID = FindTarget(client, sTarget, false);
 | |
| 	if(targetID == -1)
 | |
| 		return Plugin_Handled;
 | |
| 	GetCmdArg(2, sTarget, sizeof(sTarget));
 | |
| 	deleteClientTime(g_csSID[targetID], StringToInt(sTarget));
 | |
| 	return Plugin_Handled;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------	
 | |
| public Action cmd_hideTimerHUD(int client, int args)
 | |
| {
 | |
| 	if (!g_bHideTimer[client])
 | |
| 	{
 | |
| 		g_bHideTimer[client] = true;
 | |
| 		SetClientCookie(client, g_hClientCookie, "1");
 | |
| 		PrintToChat(client, "Disabled timer HUD");
 | |
| 	} else { g_bHideTimer[client] = false; PrintToChat(client, "Enabled timer HUD"); SetClientCookie(client, g_hClientCookie, "0"); }
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------	
 | |
| 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_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++;
 | |
|         Format(l_cMenuContent, sizeof(l_cMenuContent), "Stage: %i", l_iCount);
 | |
|         StageMenu.AddItem("", l_cMenuContent);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         int zone_reached = 0;
 | |
|         for (int Iterator = 0; Iterator <= l_iZoneCount; Iterator++)
 | |
|         {
 | |
|             char zoneIndexName[512];
 | |
|             ZoneNameBasedOnIndex(Iterator, zoneIndexName);
 | |
|             if (StrContains(zoneIndexName, "ZONE_PREFIX_RACE") > -1)
 | |
|             {
 | |
|                 char local_c[g_dLength];
 | |
|                 Format(local_c, sizeof(local_c), "%s", zoneIndexName[strlen("ZONE_PREFIX_RACE") + 1]);
 | |
|                 int prev = zone_reached;
 | |
|                 zone_reached = StringToInt(local_c);
 | |
|                 if (zone_reached == prev)
 | |
|                 {
 | |
|                     continue;
 | |
|                 }
 | |
|                 l_iCount++;
 | |
|                 Format(l_cMenuContent, sizeof(l_cMenuContent), "Stage: %i", l_iCount);
 | |
|                 StageMenu.AddItem("", l_cMenuContent);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     StageMenu.ExitButton = true;
 | |
|     StageMenu.Display(client, 0);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // 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);
 | |
| 	}
 | |
|     return 0;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose: 
 | |
| //----------------------------------------------------------------------------------------------------	
 | |
| public Action cmd_timerCheckSelf(int client, int args)
 | |
| {
 | |
| 	Checkself(client);
 | |
| 	return Plugin_Handled;
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void deleteClientTime(char[] steam2, int stage)
 | |
| {
 | |
|     char l_cQuery[g_dLength];
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     if (l_iZoneCount > 1)
 | |
|         Format(l_cQuery, sizeof(l_cQuery), "UPDATE `zetimer_table_new` SET `%sS%i` = 0.000 WHERE steam_auth = '%s'", g_cMapname, stage, steam2);
 | |
|     else
 | |
|         Format(l_cQuery, sizeof(l_cQuery), "UPDATE `zetimer_table_new` SET `%s` = 0.000 WHERE steam_auth = '%s'", g_cMapname, steam2);
 | |
|     DataPack hDataPack = new DataPack();
 | |
|     hDataPack.WriteString(l_cQuery);
 | |
|     g_dDatabase.Query(SQL_FinishedQuery, l_cQuery, hDataPack, DBPrio_Normal);
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void Checkself(int client)
 | |
| {
 | |
|     int l_iZoneCount = unloze_zoneCount();
 | |
|     char l_cQuery[g_dLength];
 | |
|     if (l_iZoneCount < 1)
 | |
|     {
 | |
|         PrintToChat(client, "No zones active on this map");
 | |
|         return;
 | |
|     }
 | |
|     if (l_iZoneCount < 2)
 | |
|     {
 | |
|         Format(l_cQuery, sizeof(l_cQuery), "SELECT name, `%s` FROM `zetimer_table_new` WHERE steam_auth = '%s'", g_cMapname, g_csSID[client]);
 | |
|         DataPack hDataPack = new DataPack();
 | |
|         hDataPack.WriteCell(GetClientSerial(client));
 | |
|         hDataPack.WriteString(l_cQuery);
 | |
|         g_dDatabase.Query(SQL_CheckSelf, l_cQuery, hDataPack);
 | |
|     }
 | |
|     else
 | |
|         CheckStagesOnMap(client, 1);
 | |
| }
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void CheckStageSelf(int client, int selection)
 | |
| {
 | |
| 	char l_cQuery[g_dLength];
 | |
| 	Format(l_cQuery, sizeof(l_cQuery), "SELECT name, `%sS%i` FROM `zetimer_table_new` WHERE steam_auth = '%s'", g_cMapname, selection, g_csSID[client]);
 | |
| 	DataPack hDataPack = new DataPack();
 | |
| 	hDataPack.WriteCell(GetClientSerial(client));
 | |
| 	hDataPack.WriteString(l_cQuery);
 | |
| 	g_dDatabase.Query(SQL_CheckSelf, l_cQuery, hDataPack);
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| public void SQL_CheckSelf(Database db, DBResultSet results, const char[] error, DataPack data)
 | |
| {
 | |
|     ResetPack(data);
 | |
|     int client_serial = data.ReadCell();
 | |
|     if (!db || strlen(error))
 | |
|     {
 | |
|         char sQuery[g_dLength];
 | |
|         data.ReadString(sQuery, sizeof(sQuery));
 | |
|         LogError("Query error 4: %s", error);   
 | |
|         LogError("actual query: %s", sQuery);
 | |
|         delete data;
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     delete data;
 | |
|     char l_cMessageContent[g_dLength];
 | |
|     char[] l_cPlayerName = new char[MAX_NAME_LENGTH];
 | |
|     int iclient;
 | |
|     if ((iclient = GetClientFromSerial(client_serial)) == 0)
 | |
|     {
 | |
|         delete results;
 | |
|         return;
 | |
|     }
 | |
|     if (results.RowCount && results.FetchRow())
 | |
|     {
 | |
|         results.FetchString(0, l_cPlayerName, MAX_NAME_LENGTH);
 | |
|         float fTime = results.FetchFloat(1);
 | |
|         if (fTime == 0.0)
 | |
|         {
 | |
|             CPrintToChat(iclient, "You have no time yet!");
 | |
|             delete results;
 | |
|             return;
 | |
|         }
 | |
|         fTime += 0.001;
 | |
|         Format(l_cMessageContent, sizeof(l_cMessageContent), "%06.3f - %s", fTime, l_cPlayerName);
 | |
|         CPrintToChat(iclient, "Your best time: %s", l_cMessageContent);
 | |
|     }
 | |
|     else
 | |
|         CPrintToChat(iclient, "You have no time yet!");
 | |
|     delete results;
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| // Purpose:
 | |
| //----------------------------------------------------------------------------------------------------
 | |
| stock bool IsValidClient(int client)
 | |
| {
 | |
| 	if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
 | |
| 		return true;
 | |
| 	return false;
 | |
| }
 |