From 7a325a41b5e81fa51dd659061017e762e0bf7742 Mon Sep 17 00:00:00 2001 From: shavitush Date: Sat, 29 Jul 2017 08:21:14 +0300 Subject: [PATCH] Add a more complete version of bonuses. --- scripting/include/shavit.inc | 26 ++- scripting/shavit-core.sp | 6 +- scripting/shavit-hud.sp | 24 +-- scripting/shavit-misc.sp | 6 +- scripting/shavit-sounds.sp | 8 +- scripting/shavit-timelimit.sp | 2 +- scripting/shavit-wr.sp | 347 ++++++++++++++++++++++------------ 7 files changed, 263 insertions(+), 156 deletions(-) diff --git a/scripting/include/shavit.inc b/scripting/include/shavit.inc index 2e2d1bcc..8c27539a 100644 --- a/scripting/include/shavit.inc +++ b/scripting/include/shavit.inc @@ -360,9 +360,10 @@ forward void Shavit_OnFinish(int client, int style, float time, int jumps, int s * @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured. * @param rank Rank on map. * @param overwrite 1 - brand new record. 2 - update. + * @param track Timer track. * @noreturn */ -forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite); +forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track); /** * Called when there's a new WR on the map. @@ -482,9 +483,10 @@ forward void Shavit_OnLeaveZone(int client, int type, int track, int id, int ent * @param jumps Jumps amount. * @param strafes Amount of strafes. * @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured. + * @param track Timer track. * @noreturn */ -forward void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync); +forward void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync, int track); /** * Returns the game type the server is running. @@ -617,9 +619,10 @@ native float Shavit_GetSync(int client); * * @param style Style to get the WR for. * @param time Reference to the time variable. 0.0 will be returned if no records. + * @param track Timer track. * @noreturn */ -native void Shavit_GetWRTime(int style, float &time); +native void Shavit_GetWRTime(int style, float &time, int track); /** * Saves the WR's record ID for the current map on a variable. @@ -627,9 +630,10 @@ native void Shavit_GetWRTime(int style, float &time); * * @param style Style to get the WR for. * @param time Reference to the time variable. 0.0 will be returned if no records. + * @param track Timer track. * @noreturn */ -native void Shavit_GetWRRecordID(int style, int &recordid); +native void Shavit_GetWRRecordID(int style, int &recordid, int track); /** * Saves the WR's player name on the map on a variable. @@ -637,9 +641,10 @@ native void Shavit_GetWRRecordID(int style, int &recordid); * @param style Style to get the WR for. * @param wrname Reference to the name variable. * @param wrmaxlength Max length for the string. + * @param track Timer track. * @noreturn */ -native void Shavit_GetWRName(int style, char[] wrname, int wrmaxlength); +native void Shavit_GetWRName(int style, char[] wrname, int wrmaxlength, int track); /** * Saves the player's personal best time on a variable. @@ -647,26 +652,29 @@ native void Shavit_GetWRName(int style, char[] wrname, int wrmaxlength); * @param client Client index. * @param style Style to get the PB for. * @param time Reference to the time variable. 0.0 will be returned if no personal record. + * @param track Timer track. * @noreturn */ -native void Shavit_GetPlayerPB(int client, int style, float &time); +native void Shavit_GetPlayerPB(int client, int style, float &time, int track); /** - * Get the amount of records on the current map/style. + * Get the amount of records on the current map/style on a track. * * @param style Bhop style. + * @param track Timer track. * @return Amount of records. */ -native int Shavit_GetRecordAmount(int style); +native int Shavit_GetRecordAmount(int style, int track); /** * Calculate potential rank for a given style and time. * * @param style Bhop style. * @param time Time to check for. + * @param track Timer track. * @return Amount of records. */ -native int Shavit_GetRankForTime(int style, float time); +native int Shavit_GetRankForTime(int style, float time, int track); /** * Checks if a mapzone exists. diff --git a/scripting/shavit-core.sp b/scripting/shavit-core.sp index 25ba4e5d..c8e1bd8d 100644 --- a/scripting/shavit-core.sp +++ b/scripting/shavit-core.sp @@ -572,7 +572,7 @@ public Action Command_TogglePause(int client, int args) return Plugin_Handled; } - if(Shavit_InsideZone(client, Zone_Start, -1)) + if(Shavit_InsideZone(client, Zone_Start, gI_Track[client])) { Shavit_PrintToChat(client, "%T", "PauseStartZone", client, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageWarning], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable], gS_ChatStrings[sMessageText]); @@ -689,7 +689,7 @@ public Action Command_Style(int client, int args) if(gB_WR) { - Shavit_GetWRTime(i, time); + Shavit_GetWRTime(i, time, Track_Main); } if(time > 0.0) @@ -1736,7 +1736,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 } int iGroundEntity = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); - bool bInStart = Shavit_InsideZone(client, Zone_Start, Track_Main); + bool bInStart = Shavit_InsideZone(client, Zone_Start, gI_Track[client]); if(gB_TimerEnabled[client] && !gB_ClientPaused[client]) { diff --git a/scripting/shavit-hud.sp b/scripting/shavit-hud.sp index 67de4368..aa2655a8 100644 --- a/scripting/shavit-hud.sp +++ b/scripting/shavit-hud.sp @@ -549,19 +549,21 @@ void UpdateHUD(int client) else if((gI_HUDSettings[client] & HUD_CENTER) > 0) { + int track = Shavit_GetClientTrack(target); + if(!IsFakeClient(target)) { float time = Shavit_GetClientTime(target); int jumps = Shavit_GetClientJumps(target); TimerStatus status = Shavit_GetTimerStatus(target); int strafes = Shavit_GetStrafeCount(target); - int rank = Shavit_GetRankForTime(gBS_Style[target], time); + int rank = Shavit_GetRankForTime(gBS_Style[target], time, track); float fWR = 0.0; - Shavit_GetWRTime(gBS_Style[target], fWR); + Shavit_GetWRTime(gBS_Style[target], fWR, track); float fPB = 0.0; - Shavit_GetPlayerPB(target, gBS_Style[target], fPB); + Shavit_GetPlayerPB(target, gBS_Style[target], fPB, track); char[] sPB = new char[32]; FormatSeconds(fPB, sPB, 32); @@ -608,7 +610,7 @@ void UpdateHUD(int client) if(fPB > 0.0) { - Format(sHintText, 512, "%s%T: %s (#%d)", sHintText, "HudBestText", client, sPB, (Shavit_GetRankForTime(gBS_Style[target], fPB) - 1)); + Format(sHintText, 512, "%s%T: %s (#%d)", sHintText, "HudBestText", client, sPB, (Shavit_GetRankForTime(gBS_Style[target], fPB, track) - 1)); } if(status >= Timer_Running) @@ -661,9 +663,6 @@ void UpdateHUD(int client) FormatEx(sHintText, 16, "%T", "HudPaused", client); } - // Note: If you're contributing a CS:GO version of the track part in the HUD, make sure to move this up somewhere so it's visible by both the CS:S/CS:GO scopes. - int track = Shavit_GetClientTrack(target); - if(track != Track_Main) { char[] sTrack = new char[32]; @@ -697,7 +696,7 @@ void UpdateHUD(int client) float time = (GetEngineTime() - start); float fWR = 0.0; - Shavit_GetWRTime(style, fWR); + Shavit_GetWRTime(style, fWR, Track_Main); // TODO: get timer track from bot here if(time > fWR || !Shavit_IsReplayDataLoaded(style)) { @@ -899,9 +898,10 @@ void UpdateTopLeftHUD(int client, bool wait) if((!wait || gI_Cycle % 25 == 0) && (gI_HUDSettings[client] & HUD_TOPLEFT) > 0) { int target = GetHUDTarget(client); + int track = Shavit_GetClientTrack(target); float fWRTime = 0.0; - Shavit_GetWRTime(gBS_Style[target], fWRTime); + Shavit_GetWRTime(gBS_Style[target], fWRTime, track); if(fWRTime != 0.0) { @@ -909,10 +909,10 @@ void UpdateTopLeftHUD(int client, bool wait) FormatSeconds(fWRTime, sWRTime, 16); char[] sWRName = new char[MAX_NAME_LENGTH]; - Shavit_GetWRName(gBS_Style[target], sWRName, MAX_NAME_LENGTH); + Shavit_GetWRName(gBS_Style[target], sWRName, MAX_NAME_LENGTH, track); float fPBTime = 0.0; - Shavit_GetPlayerPB(target, gBS_Style[target], fPBTime); + Shavit_GetPlayerPB(target, gBS_Style[target], fPBTime, track); char[] sPBTime = new char[16]; FormatSeconds(fPBTime, sPBTime, MAX_NAME_LENGTH); @@ -921,7 +921,7 @@ void UpdateTopLeftHUD(int client, bool wait) if(fPBTime != 0.0) { - FormatEx(sTopLeft, 64, "WR: %s (%s)\n%T: %s (#%d)", sWRTime, sWRName, "HudBestText", client, sPBTime, (Shavit_GetRankForTime(gBS_Style[target], fPBTime) - 1)); + FormatEx(sTopLeft, 64, "WR: %s (%s)\n%T: %s (#%d)", sWRTime, sWRName, "HudBestText", client, sPBTime, (Shavit_GetRankForTime(gBS_Style[target], fPBTime, track) - 1)); } else diff --git a/scripting/shavit-misc.sp b/scripting/shavit-misc.sp index 3c3c75a2..efbb2442 100644 --- a/scripting/shavit-misc.sp +++ b/scripting/shavit-misc.sp @@ -713,7 +713,7 @@ public Action Timer_Advertisement(Handle Timer) void UpdateScoreboard(int client) { float fPB = 0.0; - Shavit_GetPlayerPB(client, 0, fPB); + Shavit_GetPlayerPB(client, 0, fPB, Track_Main); int iScore = (fPB != 0.0 && fPB < 2000)? -RoundToFloor(fPB):-2000; @@ -1695,7 +1695,7 @@ void GetTrackName(int client, int track, char[] output, int size) FormatEx(output, size, "%T", sTrack, client); } -public void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int track) +public void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int strafes, float sync, int track) { char[] sUpperCase = new char[64]; strcopy(sUpperCase, 64, gS_StyleStrings[style][sStyleName]); @@ -1727,7 +1727,7 @@ public void Shavit_OnWorldRecord(int client, int style, float time, int jumps, i else { - Shavit_PrintToChat(i, "%s[%s]%s %T", gS_ChatStrings[sMessageVariable], gS_ChatStrings[sMessageText], "WRNotice", i, gS_ChatStrings[sMessageWarning], sUpperCase); + Shavit_PrintToChat(i, "%s[%s]%s %T", gS_ChatStrings[sMessageVariable], sTrack, gS_ChatStrings[sMessageText], "WRNotice", i, gS_ChatStrings[sMessageWarning], sUpperCase); } } } diff --git a/scripting/shavit-sounds.sp b/scripting/shavit-sounds.sp index 89584858..f09d328d 100644 --- a/scripting/shavit-sounds.sp +++ b/scripting/shavit-sounds.sp @@ -203,10 +203,10 @@ public void OnMapStart() delete fFile; } -public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite) +public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track) { float fOldTime = 0.0; - Shavit_GetPlayerPB(client, style, fOldTime); + Shavit_GetPlayerPB(client, style, fOldTime, track); char[] sSound = new char[PLATFORM_MAX_PATH]; bool bEveryone = false; @@ -242,9 +242,9 @@ public void Shavit_OnFinish_Post(int client, int style, float time, int jumps, i } } -public void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync) +public void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync, int track) { - if(gA_WorstSounds.Length != 0 && Shavit_GetRecordAmount(style) >= gI_MinimumWorst) + if(gA_WorstSounds.Length != 0 && Shavit_GetRecordAmount(style, track) >= gI_MinimumWorst) { char[] sSound = new char[PLATFORM_MAX_PATH]; gA_WorstSounds.GetString(GetRandomInt(0, gA_WorstSounds.Length - 1), sSound, PLATFORM_MAX_PATH); diff --git a/scripting/shavit-timelimit.sp b/scripting/shavit-timelimit.sp index ea533a5e..fe3b8e84 100644 --- a/scripting/shavit-timelimit.sp +++ b/scripting/shavit-timelimit.sp @@ -164,7 +164,7 @@ void StartCalculating() GetCurrentMap(sMap, 256); char sQuery[512]; - FormatEx(sQuery, 512, "SELECT COUNT(*), SUM(t.time) FROM (SELECT r.time, r.style FROM %splayertimes r WHERE r.map = '%s' %sORDER BY r.time LIMIT %d) t;", gS_MySQLPrefix, sMap, (gB_Style)? "AND style = 0 ":"", gI_PlayerAmount); + FormatEx(sQuery, 512, "SELECT COUNT(*), SUM(t.time) FROM (SELECT r.time, r.style FROM %splayertimes r WHERE r.map = '%s' AND r.track = 0 %sORDER BY r.time LIMIT %d) t;", gS_MySQLPrefix, sMap, (gB_Style)? "AND style = 0 ":"", gI_PlayerAmount); #if defined DEBUG PrintToServer(sQuery); diff --git a/scripting/shavit-wr.sp b/scripting/shavit-wr.sp index c40cfd3f..817fedf4 100644 --- a/scripting/shavit-wr.sp +++ b/scripting/shavit-wr.sp @@ -48,19 +48,18 @@ bool gB_MySQL = false; // cache int gBS_LastWR[MAXPLAYERS+1]; char gS_ClientMap[MAXPLAYERS+1][128]; +int gI_LastTrack[MAXPLAYERS+1]; char gS_Map[192]; // blame workshop paths being so fucking long ArrayList gA_ValidMaps = null; int gI_ValidMaps = 1; // current wr stats -float gF_WRTime[STYLE_LIMIT]; -int gI_WRRecordID[STYLE_LIMIT]; -char gS_WRName[STYLE_LIMIT][MAX_NAME_LENGTH]; -int gI_RecordAmount[STYLE_LIMIT]; -ArrayList gA_LeaderBoard[STYLE_LIMIT]; - -// more caching -float gF_PlayerRecord[MAXPLAYERS+1][STYLE_LIMIT]; +float gF_WRTime[STYLE_LIMIT][TRACKS_SIZE]; +int gI_WRRecordID[STYLE_LIMIT][TRACKS_SIZE]; +char gS_WRName[STYLE_LIMIT][MAX_NAME_LENGTH][TRACKS_SIZE]; +int gI_RecordAmount[STYLE_LIMIT][TRACKS_SIZE]; +ArrayList gA_LeaderBoard[STYLE_LIMIT][TRACKS_SIZE]; +float gF_PlayerRecord[MAXPLAYERS+1][STYLE_LIMIT][TRACKS_SIZE]; // admin menu Handle gH_AdminMenu = null; @@ -113,6 +112,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max public void OnPluginStart() { + LoadTranslations("shavit-common.phrases"); LoadTranslations("shavit-wr.phrases"); // debug because I was making this all by myself and no one wanted to help me *sniff* @@ -121,14 +121,19 @@ public void OnPluginStart() #endif // forwards - gH_OnWorldRecord = CreateGlobalForward("Shavit_OnWorldRecord", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); - gH_OnFinish_Post = CreateGlobalForward("Shavit_OnFinish_Post", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + gH_OnWorldRecord = CreateGlobalForward("Shavit_OnWorldRecord", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + gH_OnFinish_Post = CreateGlobalForward("Shavit_OnFinish_Post", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); gH_OnWRDeleted = CreateGlobalForward("Shavit_OnWRDeleted", ET_Event, Param_Cell, Param_Cell); - gH_OnWorstRecord = CreateGlobalForward("Shavit_OnWorstRecord", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + gH_OnWorstRecord = CreateGlobalForward("Shavit_OnWorstRecord", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); // player commands RegConsoleCmd("sm_wr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_wr [map]"); RegConsoleCmd("sm_worldrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_worldrecord [map]"); + + RegConsoleCmd("sm_bwr", Command_WorldRecord_Bonus, "View the leaderboard of a map. Usage: sm_bwr [map]"); + RegConsoleCmd("sm_bworldrecord", Command_WorldRecord_Bonus, "View the leaderboard of a map. Usage: sm_bworldrecord [map]"); + RegConsoleCmd("sm_bonusworldrecord", Command_WorldRecord_Bonus, "View the leaderboard of a map. Usage: sm_bonusworldrecord [map]"); + RegConsoleCmd("sm_recent", Command_RecentRecords, "View the recent #1 times set."); RegConsoleCmd("sm_recentrecords", Command_RecentRecords, "View the recent #1 times set."); RegConsoleCmd("sm_rr", Command_RecentRecords, "View the recent #1 times set."); @@ -162,8 +167,11 @@ public void OnPluginStart() for(int i = 0; i < STYLE_LIMIT; i++) { - gA_LeaderBoard[i] = new ArrayList(); - gI_RecordAmount[i] = 0; + for(int j = 0; j < TRACKS_SIZE; j++) + { + gA_LeaderBoard[i][j] = new ArrayList(); + gI_RecordAmount[i][j] = 0; + } } if(gB_Shavit) @@ -399,12 +407,18 @@ public void Shavit_OnStyleConfigLoaded(int styles) // arrays for(int i = 0; i < styles; i++) { - gA_LeaderBoard[i].Clear(); + for(int j = 0; j < TRACKS_SIZE; j++) + { + gA_LeaderBoard[i][j].Clear(); + } } for(int i = styles; i < STYLE_LIMIT; i++) { - delete gA_LeaderBoard[i]; + for(int j = 0; j < TRACKS_SIZE; j++) + { + delete gA_LeaderBoard[i][j]; + } } gI_Styles = styles; @@ -422,7 +436,10 @@ public void OnClientPutInServer(int client) { for(int i = 0; i < gI_Styles; i++) { - gF_PlayerRecord[client][i] = 0.0; + for(int j = 0; j < TRACKS_SIZE; j++) + { + gF_PlayerRecord[client][i][j] = 0.0; + } } if(!IsClientConnected(client) || IsFakeClient(client) || gH_SQL == null) @@ -439,7 +456,7 @@ void UpdateClientCache(int client) GetClientAuthId(client, AuthId_Steam3, sAuthID, 32); char sQuery[256]; - FormatEx(sQuery, 256, "SELECT time, style FROM %splayertimes WHERE map = '%s' AND auth = '%s';", gS_MySQLPrefix, gS_Map, sAuthID); + FormatEx(sQuery, 256, "SELECT time, style, track FROM %splayertimes WHERE map = '%s' AND auth = '%s';", gS_MySQLPrefix, gS_Map, sAuthID); gH_SQL.Query(SQL_UpdateCache_Callback, sQuery, GetClientSerial(client), DBPrio_High); } @@ -462,13 +479,14 @@ public void SQL_UpdateCache_Callback(Database db, DBResultSet results, const cha while(results.FetchRow()) { int style = results.FetchInt(1); + int track = results.FetchInt(2); - if(style >= gI_Styles || style < 0) + if(style >= gI_Styles || style < 0 || track >= TRACKS_SIZE) { continue; } - gF_PlayerRecord[client][style] = results.FetchFloat(0); + gF_PlayerRecord[client][style][track] = results.FetchFloat(0); } } @@ -480,13 +498,13 @@ void UpdateWRCache() if(gB_MySQL) { - FormatEx(sQuery, 512, "SELECT p.style, p.id, TRUNCATE(LEAST(s.time, p.time), 3), u.name FROM %splayertimes p JOIN(SELECT style, MIN(time) time, map FROM %splayertimes WHERE map = '%s' GROUP BY style ORDER BY date ASC) s ON p.style = s.style AND p.time = s.time AND p.map = s.map JOIN %susers u ON p.auth = u.auth GROUP BY p.style ORDER BY date ASC;", gS_MySQLPrefix, gS_MySQLPrefix, gS_Map, gS_MySQLPrefix); + FormatEx(sQuery, 512, "SELECT p.style, p.id, TRUNCATE(LEAST(s.time, p.time), 3), u.name, p.track FROM %splayertimes p JOIN(SELECT style, MIN(time) time, map, track FROM %splayertimes WHERE map = '%s' GROUP BY style, track ORDER BY date ASC) s ON p.style = s.style AND p.time = s.time AND p.map = s.map JOIN %susers u ON p.auth = u.auth GROUP BY p.style, p.track ORDER BY date ASC;", gS_MySQLPrefix, gS_MySQLPrefix, gS_Map, gS_MySQLPrefix); } // sorry, LEAST() isn't available for SQLITE! else { - FormatEx(sQuery, 512, "SELECT p.style, p.id, s.time, u.name FROM %splayertimes p JOIN(SELECT style, MIN(time) time, map FROM %splayertimes WHERE map = '%s' GROUP BY style) s ON p.style = s.style AND p.time = s.time AND p.map = s.map JOIN %susers u ON p.auth = u.auth GROUP BY p.style;", gS_MySQLPrefix, gS_MySQLPrefix, gS_Map, gS_MySQLPrefix); + FormatEx(sQuery, 512, "SELECT p.style, p.id, s.time, u.name, p.track FROM %splayertimes p JOIN(SELECT style, MIN(time) time, map, track FROM %splayertimes WHERE map = '%s' GROUP BY style, track) s ON p.style = s.style AND p.time = s.time AND p.map = s.map AND s.track = p.track JOIN %susers u ON p.auth = u.auth GROUP BY p.style, p.track;", gS_MySQLPrefix, gS_MySQLPrefix, gS_Map, gS_MySQLPrefix); } gH_SQL.Query(SQL_UpdateWRCache_Callback, sQuery, 0, DBPrio_Low); @@ -506,18 +524,17 @@ public void SQL_UpdateWRCache_Callback(Database db, DBResultSet results, const c // FIELD 1: id // FIELD 2: time - sorted // FIELD 3: name + // FIELD 4: track // reset cache for(int i = 0; i < gI_Styles; i++) { - if(gA_StyleSettings[i][bUnranked]) + for(int j = 0; j < TRACKS_SIZE; j++) { - continue; + strcopy(gS_WRName[i][j], MAX_NAME_LENGTH, "invalid"); + gF_WRTime[i][j] = 0.0; + gI_RecordAmount[i][j] = 0; } - - strcopy(gS_WRName[i], MAX_NAME_LENGTH, "invalid"); - gF_WRTime[i] = 0.0; - gI_RecordAmount[i] = 0; } // setup cache again, dynamically and not hardcoded @@ -525,15 +542,17 @@ public void SQL_UpdateWRCache_Callback(Database db, DBResultSet results, const c { int style = results.FetchInt(0); - if(style >= gI_Styles || style < 0) + if(style >= gI_Styles || style < 0 || gA_StyleSettings[style][bUnranked]) { continue; } - gI_WRRecordID[style] = results.FetchInt(1); - gF_WRTime[style] = results.FetchFloat(2); - results.FetchString(3, gS_WRName[style], MAX_NAME_LENGTH); - ReplaceString(gS_WRName[style], MAX_NAME_LENGTH, "#", "?"); + int track = results.FetchInt(4); + + gI_WRRecordID[style][track] = results.FetchInt(1); + gF_WRTime[style][track] = results.FetchFloat(2); + results.FetchString(3, gS_WRName[style][track], MAX_NAME_LENGTH); + ReplaceString(gS_WRName[style][track], MAX_NAME_LENGTH, "#", "?"); } UpdateLeaderboards(); @@ -541,39 +560,40 @@ public void SQL_UpdateWRCache_Callback(Database db, DBResultSet results, const c public int Native_GetWRTime(Handle handler, int numParams) { - SetNativeCellRef(2, gF_WRTime[GetNativeCell(1)]); + SetNativeCellRef(2, gF_WRTime[GetNativeCell(1)][GetNativeCell(3)]); } public int Native_GetWRRecordID(Handle handler, int numParams) { - SetNativeCellRef(2, gI_WRRecordID[GetNativeCell(1)]); + SetNativeCellRef(2, gI_WRRecordID[GetNativeCell(1)][GetNativeCell(3)]); } public int Native_GetWRName(Handle handler, int numParams) { - SetNativeString(2, gS_WRName[GetNativeCell(1)], GetNativeCell(3)); + SetNativeString(2, gS_WRName[GetNativeCell(1)][GetNativeCell(4)], GetNativeCell(3)); } public int Native_GetPlayerPB(Handle handler, int numParams) { - SetNativeCellRef(3, gF_PlayerRecord[GetNativeCell(1)][GetNativeCell(2)]); + SetNativeCellRef(3, gF_PlayerRecord[GetNativeCell(1)][GetNativeCell(2)][GetNativeCell(4)]); } public int Native_GetRankForTime(Handle handler, int numParams) { int style = GetNativeCell(1); + int track = GetNativeCell(3); - if(gA_LeaderBoard[style].Length == 0) + if(gA_LeaderBoard[style][track].Length == 0) { return 1; } - return GetRankForTime(style, GetNativeCell(2)); + return GetRankForTime(style, GetNativeCell(2), track); } public int Native_GetRecordAmount(Handle handler, int numParams) { - return gI_RecordAmount[GetNativeCell(1)]; + return gI_RecordAmount[GetNativeCell(1)][GetNativeCell(2)]; } #if defined DEBUG @@ -707,7 +727,15 @@ public Action Command_DeleteStyleRecords(int client, int args) char[] sDisplay = new char[64]; FormatEx(sDisplay, 64, "%s (%d %T)", gS_StyleStrings[i][sStyleName], gI_RecordAmount[i], "WRRecord", client); - menu.AddItem(sInfo, sDisplay, (gI_RecordAmount[i] > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); + + int iTotalAmount = 0; + + for(int j = 0; j < TRACKS_SIZE; j++) + { + iTotalAmount += gI_RecordAmount[i][j]; + } + + menu.AddItem(sInfo, sDisplay, (iTotalAmount > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); } if(menu.ItemCount == 0) @@ -731,10 +759,14 @@ public int MenuHandler_DeleteStyleRecords(Menu menu, MenuAction action, int para menu.GetItem(param2, info, 16); int style = StringToInt(info); + int iTotalAmount = 0; - // (gI_RecordAmount[i] == 0) will trigger if the admin uses a cheat that hooks into menus - // and doesn't allow items to be disabled - if(gI_RecordAmount[style] == 0) + for(int j = 0; j < TRACKS_SIZE; j++) + { + iTotalAmount += gI_RecordAmount[style][j]; + } + + if(iTotalAmount == 0) { return 0; } @@ -1004,15 +1036,24 @@ public int DeleteConfirm_Handler(Menu menu, MenuAction action, int param1, int p for(int i = 0; i < gI_Styles; i++) { - if(gA_StyleSettings[i][bUnranked] || gI_WRRecordID[i] != iRecordID) + if(gA_StyleSettings[i][bUnranked]) { continue; } - Call_StartForward(gH_OnWRDeleted); - Call_PushCell(i); - Call_PushCell(iRecordID); - Call_Finish(); + for(int j = 0; j < TRACKS_SIZE; j++) + { + if(gI_WRRecordID[i][j] != iRecordID) + { + continue; + } + + Call_StartForward(gH_OnWRDeleted); + Call_PushCell(i); + Call_PushCell(iRecordID); + // Call_PushCell(j); // TODO: TRACK + Call_Finish(); + } } char[] sQuery = new char[256]; @@ -1112,11 +1153,34 @@ public Action Command_WorldRecord(int client, int args) GuessBestMapName(gS_ClientMap[client], gS_ClientMap[client], 128); } - return ShowWRStyleMenu(client); + return ShowWRStyleMenu(client, Track_Main); } -Action ShowWRStyleMenu(int client) +public Action Command_WorldRecord_Bonus(int client, int args) { + if(!IsValidClient(client)) + { + return Plugin_Handled; + } + + if(args == 0) + { + strcopy(gS_ClientMap[client], 128, gS_Map); + } + + else + { + GetCmdArgString(gS_ClientMap[client], 128); + GuessBestMapName(gS_ClientMap[client], gS_ClientMap[client], 128); + } + + return ShowWRStyleMenu(client, Track_Bonus); +} + +Action ShowWRStyleMenu(int client, int track) +{ + gI_LastTrack[client] = track; + Menu menu = new Menu(MenuHandler_StyleChooser); menu.SetTitle("%T", "WRMenuTitle", client); @@ -1132,10 +1196,10 @@ Action ShowWRStyleMenu(int client) char[] sDisplay = new char[64]; - if(gF_WRTime[i] > 0.0) + if(gF_WRTime[i][track] > 0.0) { char[] sTime = new char[32]; - FormatSeconds(gF_WRTime[i], sTime, 32, false); + FormatSeconds(gF_WRTime[i][track], sTime, 32, false); FormatEx(sDisplay, 64, "%s - WR: %s", gS_StyleStrings[i][sStyleName], sTime); } @@ -1145,7 +1209,7 @@ Action ShowWRStyleMenu(int client) strcopy(sDisplay, 64, gS_StyleStrings[i][sStyleName]); } - menu.AddItem(sInfo, sDisplay, (gI_RecordAmount[i] > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); + menu.AddItem(sInfo, sDisplay, (gI_RecordAmount[i][track] > 0)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); } // should NEVER happen @@ -1185,7 +1249,7 @@ public int MenuHandler_StyleChooser(Menu menu, MenuAction action, int param1, in gBS_LastWR[param1] = iStyle; - StartWRMenu(param1, gS_ClientMap[param1], iStyle); + StartWRMenu(param1, gS_ClientMap[param1], iStyle, gI_LastTrack[param1]); } else if(action == MenuAction_End) @@ -1196,10 +1260,11 @@ public int MenuHandler_StyleChooser(Menu menu, MenuAction action, int param1, in return 0; } -void StartWRMenu(int client, const char[] map, int style) +void StartWRMenu(int client, const char[] map, int style, int track) { DataPack dp = new DataPack(); dp.WriteCell(GetClientSerial(client)); + dp.WriteCell(track); dp.WriteString(map); int iLength = ((strlen(map) * 2) + 1); @@ -1208,7 +1273,7 @@ void StartWRMenu(int client, const char[] map, int style) char[] sQuery = new char[512]; - FormatEx(sQuery, 512, "SELECT p.id, u.name, p.time, p.jumps, p.auth FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE map = '%s' AND style = %d ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_MySQLPrefix, sEscapedMap, style); + FormatEx(sQuery, 512, "SELECT p.id, u.name, p.time, p.jumps, p.auth FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_MySQLPrefix, sEscapedMap, style, track); gH_SQL.Query(SQL_WR_Callback, sQuery, dp, DBPrio_High); return; @@ -1219,6 +1284,7 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error ResetPack(data); int serial = ReadPackCell(data); + int track = ReadPackCell(data); char[] sMap = new char[192]; ReadPackString(data, sMap, 192); @@ -1242,7 +1308,7 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error char[] sAuth = new char[32]; GetClientAuthId(client, AuthId_Steam3, sAuth, 32); - Menu m = new Menu(WRMenu_Handler); + Menu menu = new Menu(WRMenu_Handler); int iCount = 0; int iMyRank = 0; @@ -1271,7 +1337,7 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error char[] sDisplay = new char[128]; FormatEx(sDisplay, 128, "#%d - %s - %s (%d %T)", iCount, sName, sTime, jumps, "WRJumps", client); - m.AddItem(sID, sDisplay); + menu.AddItem(sID, sDisplay); } // check if record exists in the map's top X @@ -1290,13 +1356,13 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error char[] sFormattedTitle = new char[256]; - if(m.ItemCount == 0) + if(menu.ItemCount == 0) { - m.SetTitle("%T", "WRMap", client, sDisplayMap); + menu.SetTitle("%T", "WRMap", client, sDisplayMap); char[] sNoRecords = new char[64]; FormatEx(sNoRecords, 64, "%T", "WRMapNoRecords", client); - m.AddItem("-1", sNoRecords); + menu.AddItem("-1", sNoRecords); } else @@ -1306,7 +1372,7 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error // [32] just in case there are 150k records on a map and you're ranked 100k or something char[] sRanks = new char[32]; - if(gF_PlayerRecord[client][gBS_LastWR[client]] == 0.0) + if(gF_PlayerRecord[client][gBS_LastWR[client]][track] == 0.0) { FormatEx(sRanks, 32, "(%d %T)", iRecords, "WRRecord", client); } @@ -1316,20 +1382,23 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error FormatEx(sRanks, 32, "(#%d/%d)", iMyRank, gI_RecordAmount[gBS_LastWR[client]]); } - FormatEx(sFormattedTitle, 192, "%T %s:\n%s", "WRRecordFor", client, sDisplayMap, sRanks); - m.SetTitle(sFormattedTitle); + char[] sTrack = new char[32]; + GetTrackName(client, track, sTrack, 32); + + FormatEx(sFormattedTitle, 192, "%T %s: [%s]\n%s", "WRRecordFor", client, sDisplayMap, sTrack, sRanks); + menu.SetTitle(sFormattedTitle); } - m.ExitBackButton = true; - m.Display(client, 20); + menu.ExitBackButton = true; + menu.Display(client, 20); } -public int WRMenu_Handler(Menu m, MenuAction action, int param1, int param2) +public int WRMenu_Handler(Menu menu, MenuAction action, int param1, int param2) { if(action == MenuAction_Select) { char[] sInfo = new char[16]; - m.GetItem(param2, sInfo, 16); + menu.GetItem(param2, sInfo, 16); int id = StringToInt(sInfo); if(id != -1) @@ -1339,18 +1408,18 @@ public int WRMenu_Handler(Menu m, MenuAction action, int param1, int param2) else { - ShowWRStyleMenu(param1); + ShowWRStyleMenu(param1, gI_LastTrack[param1]); } } else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) { - ShowWRStyleMenu(param1); + ShowWRStyleMenu(param1, gI_LastTrack[param1]); } else if(action == MenuAction_End) { - delete m; + delete menu; } return 0; @@ -1364,7 +1433,7 @@ public Action Command_RecentRecords(int client, int args) } char[] sQuery = new char[512]; - FormatEx(sQuery, 512, "SELECT p.id, p.map, u.name, MIN(p.time), p.jumps, p.style, p.points FROM %splayertimes p JOIN %susers u ON p.auth = u.auth GROUP BY p.map, p.style ORDER BY date DESC LIMIT %d;", gS_MySQLPrefix, gS_MySQLPrefix, gI_RecentLimit); + FormatEx(sQuery, 512, "SELECT p.id, p.map, u.name, MIN(p.time), p.jumps, p.style, p.points, p.track FROM %splayertimes p JOIN %susers u ON p.auth = u.auth GROUP BY p.map, p.style, p.track ORDER BY date DESC LIMIT %d;", gS_MySQLPrefix, gS_MySQLPrefix, gI_RecentLimit); gH_SQL.Query(SQL_RR_Callback, sQuery, GetClientSerial(client), DBPrio_High); @@ -1409,16 +1478,19 @@ public void SQL_RR_Callback(Database db, DBResultSet results, const char[] error int style = results.FetchInt(5); float fPoints = results.FetchFloat(6); + char[] sTrack = new char[32]; + GetTrackName(client, results.FetchInt(7), sTrack, 32); + char[] sDisplay = new char[192]; if(gB_Rankings && fPoints > 0.0) { - FormatEx(sDisplay, 192, "[%s] %s - %s @ %s (%.03f %T)", gS_StyleStrings[style][sShortName], sDisplayMap, sName, sTime, fPoints, "WRPoints", client); + FormatEx(sDisplay, 192, "[%s] %s - %s @ %s (%.03f %T) [%s]", gS_StyleStrings[style][sShortName], sDisplayMap, sName, sTime, fPoints, "WRPoints", client, sTrack); } else { - FormatEx(sDisplay, 192, "[%s] %s - %s @ %s (%d %T)", gS_StyleStrings[style][sShortName], sDisplayMap, sName, sTime, jumps, "WRJumps", client); + FormatEx(sDisplay, 192, "[%s] %s - %s @ %s (%d %T) [%s]", gS_StyleStrings[style][sShortName], sDisplayMap, sName, sTime, jumps, "WRJumps", client, sTrack); } char[] sInfo = new char[192]; @@ -1457,13 +1529,13 @@ public int RRMenu_Handler(Menu m, MenuAction action, int param1, int param2) else { - ShowWRStyleMenu(param1); + ShowWRStyleMenu(param1, gI_LastTrack[param1]); } } else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) { - ShowWRStyleMenu(param1); + ShowWRStyleMenu(param1, gI_LastTrack[param1]); } else if(action == MenuAction_End) @@ -1477,7 +1549,7 @@ public int RRMenu_Handler(Menu m, MenuAction action, int param1, int param2) void OpenSubMenu(int client, int id) { char[] sQuery = new char[512]; - FormatEx(sQuery, 512, "SELECT u.name, p.time, p.jumps, p.style, u.auth, p.date, p.map, p.strafes, p.sync, p.points FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE p.id = %d LIMIT 1;", gS_MySQLPrefix, gS_MySQLPrefix, id); + FormatEx(sQuery, 512, "SELECT u.name, p.time, p.jumps, p.style, u.auth, p.date, p.map, p.strafes, p.sync, p.points, p.track FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE p.id = %d LIMIT 1;", gS_MySQLPrefix, gS_MySQLPrefix, id); DataPack datapack = new DataPack(); datapack.WriteCell(GetClientSerial(client)); @@ -1505,12 +1577,13 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] return; } - Menu m = new Menu(SubMenu_Handler); + Menu menu = new Menu(SubMenu_Handler); char[] sFormattedTitle = new char[256]; char[] sName = new char[MAX_NAME_LENGTH]; char[] sAuthID = new char[32]; char[] sDisplayMap = new char[192]; + char[] sTrack = new char[32]; if(results.FetchRow()) { @@ -1524,17 +1597,17 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] char[] sDisplay = new char[128]; FormatEx(sDisplay, 128, "%T: %s", "WRTime", client, sTime); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); // 2 - jumps int jumps = results.FetchInt(2); FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, jumps); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); // 3 - style int style = results.FetchInt(3); FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[style][sStyleName]); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); // 6 - map char[] sMap = new char[192]; @@ -1546,7 +1619,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(gB_Rankings && fPoints > 0.0) { FormatEx(sDisplay, 128, "%T: %.03f", "WRPointsCap", client, fPoints); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); } // 4 - steamid3 @@ -1562,7 +1635,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] } FormatEx(sDisplay, 128, "%T: %s", "WRDate", client, sDate); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); int strafes = results.FetchInt(7); float sync = results.FetchFloat(8); @@ -1570,7 +1643,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(jumps > 0 || strafes > 0) { FormatEx(sDisplay, 128, (sync != -1.0)? "%T: %d (%.02f%%)":"%T: %d", "WRStrafes", client, strafes, sync); - m.AddItem("-1", sDisplay); + menu.AddItem("-1", sDisplay); } char[] sMenuItem = new char[64]; @@ -1581,27 +1654,29 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] if(gB_Stats) { - m.AddItem(sInfo, sMenuItem); + menu.AddItem(sInfo, sMenuItem); } if(CheckCommandAccess(client, "sm_delete", ADMFLAG_RCON)) { FormatEx(sMenuItem, 64, "%T", "WRDeleteRecord", client); FormatEx(sInfo, 32, "1;%d", id); - m.AddItem(sInfo, sMenuItem); + menu.AddItem(sInfo, sMenuItem); } + + GetTrackName(client, results.FetchInt(10), sTrack, 32); } else { char[] sMenuItem = new char[64]; FormatEx(sMenuItem, 64, "%T", "DatabaseError", client); - m.AddItem("-1", sMenuItem); + menu.AddItem("-1", sMenuItem); } if(strlen(sName) > 0) { - FormatEx(sFormattedTitle, 256, "%s %s\n--- %s:", sName, sAuthID, sDisplayMap); + FormatEx(sFormattedTitle, 256, "%s %s\n--- %s: [%s]", sName, sAuthID, sDisplayMap, sTrack); } else @@ -1609,9 +1684,9 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] FormatEx(sFormattedTitle, 256, "%T", "Error", client); } - m.SetTitle(sFormattedTitle); - m.ExitBackButton = true; - m.Display(client, 20); + menu.SetTitle(sFormattedTitle); + menu.ExitBackButton = true; + menu.Display(client, 20); } public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2) @@ -1644,13 +1719,13 @@ public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2) else { - StartWRMenu(param1, gS_ClientMap[param1], gBS_LastWR[param1]); + StartWRMenu(param1, gS_ClientMap[param1], gBS_LastWR[param1], Track_Main); // TODO: use client's cached track } } else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) { - StartWRMenu(param1, gS_ClientMap[param1], gBS_LastWR[param1]); + StartWRMenu(param1, gS_ClientMap[param1], gBS_LastWR[param1], Track_Main); // TODO: use client's cached track } else if(action == MenuAction_End) @@ -1820,11 +1895,14 @@ public void SQL_AlterTable4_Callback(Database db, DBResultSet results, const cha } } -public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync) +public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track) { char[] sTime = new char[32]; FormatSeconds(time, sTime, 32); + char[] sTrack = new char[32]; + GetTrackName(LANG_SERVER, track, sTrack, 32); + // 0 - no query // 1 - insert // 2 - update @@ -1835,19 +1913,19 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st overwrite = 0; // ugly way of not writing to database } - else if(gF_PlayerRecord[client][style] == 0.0) + else if(gF_PlayerRecord[client][style][track] == 0.0) { overwrite = 1; } - else if(time <= gF_PlayerRecord[client][style]) + else if(time <= gF_PlayerRecord[client][style][track]) { overwrite = 2; } - if(overwrite > 0 && (time < gF_WRTime[style] || gF_WRTime[style] == 0.0)) // WR? + if(overwrite > 0 && (time < gF_WRTime[style][track] || gF_WRTime[style][track] == 0.0)) // WR? { - gF_WRTime[style] = time; + gF_WRTime[style][track] = time; Call_StartForward(gH_OnWorldRecord); Call_PushCell(client); @@ -1856,12 +1934,13 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st Call_PushCell(jumps); Call_PushCell(strafes); Call_PushCell(sync); + Call_PushCell(track); Call_Finish(); } - int iRank = GetRankForTime(style, time); + int iRank = GetRankForTime(style, time, track); - if(iRank >= gI_RecordAmount[style]) + if(iRank >= gI_RecordAmount[style][track]) { Call_StartForward(gH_OnWorstRecord); Call_PushCell(client); @@ -1870,10 +1949,11 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st Call_PushCell(jumps); Call_PushCell(strafes); Call_PushCell(sync); + Call_PushCell(track); Call_Finish(); } - float fDifference = (gF_PlayerRecord[client][style] - time); + float fDifference = (gF_PlayerRecord[client][style][track] - time); if(fDifference < 0.0) { @@ -1895,23 +1975,21 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st if(overwrite == 1) // insert { - Shavit_PrintToChatAll("%T", "FirstCompletion", LANG_SERVER, gS_ChatStrings[sMessageVariable2], client, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable], iRank, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText]); + Shavit_PrintToChatAll("%s[%s]%s %T", gS_ChatStrings[sMessageVariable], sTrack, gS_ChatStrings[sMessageText], "FirstCompletion", LANG_SERVER, gS_ChatStrings[sMessageVariable2], client, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable], iRank, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText]); - // prevent duplicate records in case there's a long enough lag for the mysql server between two map finishes - // TODO: work on a solution that can function the same while not causing lost records if(gH_SQL == null) { return; } - FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync) VALUES ('%s', '%s', %.03f, %d, %d, %d, %d, %.2f);", gS_MySQLPrefix, sAuthID, gS_Map, time, jumps, GetTime(), style, strafes, sync); + FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, track) VALUES ('%s', '%s', %.03f, %d, %d, %d, %d, %.2f, %d);", gS_MySQLPrefix, sAuthID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track); } else // update { - Shavit_PrintToChatAll("%T", "NotFirstCompletion", LANG_SERVER, gS_ChatStrings[sMessageVariable2], client, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable], iRank, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageWarning], sDifference); + Shavit_PrintToChatAll("%s[%s]%s %T", gS_ChatStrings[sMessageVariable], sTrack, gS_ChatStrings[sMessageText], "NotFirstCompletion", LANG_SERVER, gS_ChatStrings[sMessageVariable2], client, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable], iRank, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageWarning], sDifference); - FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %.03f, jumps = %d, date = %d, strafes = %d, sync = %.02f WHERE map = '%s' AND auth = '%s' AND style = '%d';", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, gS_Map, sAuthID, style); + FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %.03f, jumps = %d, date = %d, strafes = %d, sync = %.02f WHERE map = '%s' AND auth = '%s' AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, gS_Map, sAuthID, style, track); } gH_SQL.Query(SQL_OnFinish_Callback, sQuery, GetClientSerial(client), DBPrio_High); @@ -1925,19 +2003,20 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st Call_PushCell(sync); Call_PushCell(iRank); Call_PushCell(overwrite); + Call_PushCell(track); Call_Finish(); - gF_PlayerRecord[client][style] = time; + gF_PlayerRecord[client][style][track] = time; } else if(overwrite == 0 && !gA_StyleSettings[style][bUnranked]) { - Shavit_PrintToChat(client, "%T", "WorseTime", client, gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText], sDifference); + Shavit_PrintToChat(client, "%s[%s]%s %T", gS_ChatStrings[sMessageVariable], sTrack, gS_ChatStrings[sMessageText], "WorseTime", client, gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText], sDifference); } else { - Shavit_PrintToChat(client, "%T", "UnrankedTime", client, gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText]); + Shavit_PrintToChat(client, "%s[%s]%s] %T", gS_ChatStrings[sMessageVariable], sTrack, gS_ChatStrings[sMessageText], "UnrankedTime", client, gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText], gS_ChatStrings[sMessageVariable2], sTime, gS_ChatStrings[sMessageText], jumps, strafes, sSync, gS_ChatStrings[sMessageText]); } } @@ -1964,9 +2043,8 @@ public void SQL_OnFinish_Callback(Database db, DBResultSet results, const char[] void UpdateLeaderboards() { char[] sQuery = new char[192]; - - FormatEx(sQuery, 192, "SELECT style, time FROM %splayertimes WHERE map = '%s' ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_Map); - gH_SQL.Query(SQL_UpdateLeaderboards_Callback, sQuery, 0, DBPrio_Low); + FormatEx(sQuery, 192, "SELECT style, time, track FROM %splayertimes WHERE map = '%s' ORDER BY time ASC, date ASC;", gS_MySQLPrefix, gS_Map); + gH_SQL.Query(SQL_UpdateLeaderboards_Callback, sQuery, 0); } public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, const char[] error, any data) @@ -1980,20 +2058,24 @@ public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, co for(int i = 0; i < gI_Styles; i++) { - gI_RecordAmount[i] = 0; - gA_LeaderBoard[i].Clear(); + for(int j = 0; j < TRACKS_SIZE; j++) + { + gI_RecordAmount[i][j] = 0; + gA_LeaderBoard[i][j].Clear(); + } } while(results.FetchRow()) { int style = results.FetchInt(0); + int track = results.FetchInt(2); - if(style >= gI_Styles || gA_StyleSettings[style][bUnranked]) + if(style >= gI_Styles || gA_StyleSettings[style][bUnranked] || track >= TRACKS_SIZE) { continue; } - gA_LeaderBoard[style].Push(results.FetchFloat(1)); + gA_LeaderBoard[style][track].Push(results.FetchFloat(1)); } for(int i = 0; i < gI_Styles; i++) @@ -2003,27 +2085,30 @@ public void SQL_UpdateLeaderboards_Callback(Database db, DBResultSet results, co continue; } - SortADTArray(gA_LeaderBoard[i], Sort_Ascending, Sort_Float); - gI_RecordAmount[i] = gA_LeaderBoard[i].Length; + for(int j = 0; j < TRACKS_SIZE; j++) + { + SortADTArray(gA_LeaderBoard[i][j], Sort_Ascending, Sort_Float); + gI_RecordAmount[i][j] = gA_LeaderBoard[i][j].Length; + } } } -int GetRankForTime(int style, float time) +int GetRankForTime(int style, float time, int track) { - if(time < gF_WRTime[style] || gI_RecordAmount[style] <= 0) + if(time < gF_WRTime[style][track] || gI_RecordAmount[style][track] <= 0) { return 1; } - for(int i = 0; i < gI_RecordAmount[style]; i++) + for(int i = 0; i < gI_RecordAmount[style][track]; i++) { - if(time < gA_LeaderBoard[style].Get(i)) + if(time < gA_LeaderBoard[style][track].Get(i)) { return ++i; } } - return (gI_RecordAmount[style] + 1); + return (gI_RecordAmount[style][track] + 1); } void GuessBestMapName(const char[] input, char[] output, int size) @@ -2050,6 +2135,20 @@ void GuessBestMapName(const char[] input, char[] output, int size) } } +void GetTrackName(int client, int track, char[] output, int size) +{ + if(track < 0 || track >= TRACKS_SIZE) + { + FormatEx(output, size, "%T", "Track_Unknown", client); + + return; + } + + static char sTrack[16]; + FormatEx(sTrack, 16, "Track_%d", track); + FormatEx(output, size, "%T", sTrack, client); +} + public void Shavit_OnDatabaseLoaded(Database db) { gH_SQL = db;