diff --git a/README.md b/README.md index 6e6c75d4..56fc4ebc 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ shavit-zones - wouldn't really call it required but it's actually needed to get # Todo for 1.5b release (out of beta!) - [x] Migrate every menu to the new syntax. +- [ ] Migrate DBI to the new syntax. ~ shavit-core: - [x] Fix chat colors for CS:S. @@ -88,7 +89,7 @@ shavit-zones - wouldn't really call it required but it's actually needed to get - [ ] Optimize `InsideZone()` so `CreateZonePoints()` will not be needed for simple (not rotated) zones. ~ shavit-stats -- [ ] Make style names editable from shavit.inc (like I did to the rest of modules) - either that or integrate the whole module into shavit-wr. +- [x] Make style names editable from shavit.inc (like I did to the rest of modules) (dynamic!) ~ [NEW PLUGIN] shavit-ranks: - [ ] Create table. diff --git a/scripting/shavit-stats.sp b/scripting/shavit-stats.sp index 88708b33..3b39a37a 100644 --- a/scripting/shavit-stats.sp +++ b/scripting/shavit-stats.sp @@ -19,18 +19,30 @@ */ #include + +#define USES_STYLE_NAMES +#define USES_SHORT_STYLE_NAMES #include #pragma semicolon 1 #pragma dynamic 131072 // let's make stuff faster #pragma newdecls required // We're at 2015 :D +// macros +#define MAPSDONE 0 +#define MAPSLEFT 1 + // database handle Database gH_SQL = null; // table prefix char gS_MySQLPrefix[32]; +// cache +int gI_MapType[MAXPLAYERS+1]; +int gI_Target[MAXPLAYERS+1]; +BhopStyle gBS_Style[MAXPLAYERS+1]; + public Plugin myinfo = { name = "[shavit] Player Stats", @@ -57,12 +69,6 @@ public void OnPluginStart() RegConsoleCmd("sm_profile", Command_Profile, "Show the player's profile. Usage: sm_profile [target]"); RegConsoleCmd("sm_stats", Command_Profile, "Show the player's profile. Usage: sm_profile [target]"); - RegConsoleCmd("sm_mapsdone", Command_Mapsdone, "Show maps that the player have done already. Usage: sm_mapsdone [target]"); - RegConsoleCmd("sm_mapsleft", Command_Mapsleft, "Show maps that the player doesn't have them cleared yet. Usage: sm_mapsleft [target]"); - - RegConsoleCmd("sm_mapsdonesw", Command_MapsdoneSW, "[SW] Show maps done. Usage: sm_mapsdonesw [target]"); - RegConsoleCmd("sm_mapsleftsw", Command_MapsleftSW, "[SW] Show maps that the player doesn't have them cleared yet. Usage: sm_mapsleftsw [target]"); - LoadTranslations("common.phrases"); } @@ -82,6 +88,8 @@ public Action SetSQLInfo() if(gH_SQL == null) { + Shavit_GetDB(gH_SQL); + fTime = 0.5; } @@ -105,114 +113,6 @@ public Action SetSQLInfo() return Plugin_Continue; } -public Action Command_Mapsdone(int client, int args) -{ - if(!IsValidClient(client)) - { - return Plugin_Handled; - } - - int target = client; - - if(args > 0) - { - char[] sArgs = new char[64]; - GetCmdArgString(sArgs, 64); - - target = FindTarget(client, sArgs, true, false); - - if(target == -1) - { - return Plugin_Handled; - } - } - - ShowMaps(client, target, "mapsdone"); - - return Plugin_Handled; -} - -public Action Command_Mapsleft(int client, int args) -{ - if(!IsValidClient(client)) - { - return Plugin_Handled; - } - - int target = client; - - if(args > 0) - { - char[] sArgs = new char[64]; - GetCmdArgString(sArgs, 64); - - target = FindTarget(client, sArgs, true, false); - - if(target == -1) - { - return Plugin_Handled; - } - } - - ShowMaps(client, target, "mapsleft"); - - return Plugin_Handled; -} - -public Action Command_MapsdoneSW(int client, int args) -{ - if(!IsValidClient(client)) - { - return Plugin_Handled; - } - - int target = client; - - if(args > 0) - { - char[] sArgs = new char[64]; - GetCmdArgString(sArgs, 64); - - target = FindTarget(client, sArgs, true, false); - - if(target == -1) - { - return Plugin_Handled; - } - } - - ShowMaps(client, target, "mapsdonesw"); - - return Plugin_Handled; -} - -public Action Command_MapsleftSW(int client, int args) -{ - if(!IsValidClient(client)) - { - return Plugin_Handled; - } - - int target = client; - - if(args > 0) - { - char[] sArgs = new char[64]; - GetCmdArgString(sArgs, 64); - - target = FindTarget(client, sArgs, true, false); - - if(target == -1) - { - return Plugin_Handled; - } - } - - ShowMaps(client, target, "mapsleftsw"); - - return Plugin_Handled; -} - public Action Command_Profile(int client, int args) { if(!IsValidClient(client)) @@ -235,21 +135,50 @@ public Action Command_Profile(int client, int args) } } + gI_Target[client] = target; + + return ShowStyleMenu(client); +} + +public Action ShowStyleMenu(int client) +{ + if(!IsValidClient(client)) + { + return Plugin_Handled; + } + + if(!IsValidClient(gI_Target[client])) + { + Shavit_PrintToChat(client, "The target has disconnected."); + + return Plugin_Handled; + } + char[] sAuthID = new char[32]; - GetClientAuthId(target, AuthId_Steam3, sAuthID, 32); + GetClientAuthId(gI_Target[client], AuthId_Steam3, sAuthID, 32); Menu m = new Menu(MenuHandler_Profile); - m.SetTitle("%N's profile.\nSteamID3: %s", target, sAuthID); + m.SetTitle("%N's profile.\nSteamID3: %s", gI_Target[client], sAuthID); - m.AddItem("mapsdone", "Maps done (Forwards)"); - m.AddItem("mapsleft", "Maps left (Forwards)"); - m.AddItem("mapsdonesw", "Maps done (Sideways)"); - m.AddItem("mapsleftsw", "Maps left (Sideways)"); + for(int i = 0; i < sizeof(gS_BhopStyles); i++) + { + char[] sInfo = new char[32]; + FormatEx(sInfo, 32, "mapsdone;%d", i); - char[] sTarget = new char[8]; - IntToString(target, sTarget, 8); + char[] sDisplay = new char[32]; + FormatEx(sDisplay, 32, "[%s] Maps done", gS_BhopStyles[i]); + m.AddItem(sInfo, sDisplay); - m.AddItem("id", sTarget, ITEMDRAW_IGNORE); + FormatEx(sInfo, 32, "mapsleft;%d", i); + FormatEx(sDisplay, 32, "[%s] Maps left", gS_BhopStyles[i]); + m.AddItem(sInfo, sDisplay); + } + + // should NEVER happen + if(m.ItemCount == 0) + { + m.AddItem("-1", "Nothing"); + } m.ExitButton = true; @@ -262,26 +191,21 @@ public int MenuHandler_Profile(Menu m, MenuAction action, int param1, int param2 { if(action == MenuAction_Select) { - char[] info = new char[16]; - - int target; - - for(int i = 0; i < m.ItemCount; i++) + if(!IsValidClient(gI_Target[param1])) { - char[] data = new char[8]; - m.GetItem(i, info, 16, _, data, 8); - - if(StrEqual(info, "id")) - { - target = StringToInt(data); - - break; - } + return 0; } - m.GetItem(param2, info, 16); + char[] sInfo = new char[32]; + m.GetItem(param2, sInfo, 32); - ShowMaps(param1, target, info); + char[][] sSplit = new char[2][16]; + ExplodeString(sInfo, ";", sSplit, 2, 16); + + gI_MapType[param1] = StrEqual(sSplit[0], "mapsdone")? MAPSDONE:MAPSLEFT; + gBS_Style[param1] = view_as(StringToInt(sSplit[1])); + + ShowMaps(param1); } else if(action == MenuAction_End) @@ -292,64 +216,65 @@ public int MenuHandler_Profile(Menu m, MenuAction action, int param1, int param2 return 0; } -// mapsleft - https://forums.alliedmods.net/showpost.php?p=2106711&postcount=4 -public void ShowMaps(int client, int target, const char[] category) +public Action Timer_DBFailure(Handle timer, any data) { + int client = GetClientFromSerial(data); + + if(!client) + { + return Plugin_Stop; + } + + ShowMaps(client); + + return Plugin_Stop; +} + +public void ShowMaps(int client) +{ + if(!IsValidClient(gI_Target[client])) + { + return; + } + + // database not found, display with a 3 seconds delay + if(gH_SQL == null) + { + CreateTimer(3.0, Timer_DBFailure, GetClientSerial(client)); + + return; + } + char[] sAuth = new char[32]; - GetClientAuthId(target, AuthId_Steam3, sAuth, 32); + GetClientAuthId(gI_Target[client], AuthId_Steam3, sAuth, 32); char[] sQuery = new char[256]; - if(StrContains(category, "done") != -1) + if(gI_MapType[client] == MAPSDONE) { - FormatEx(sQuery, 256, "SELECT map, time, jumps FROM %splayertimes WHERE auth = '%s' AND style = %d ORDER BY map;", gS_MySQLPrefix, sAuth, StrEqual(category, "mapsdone")? 0:1); + FormatEx(sQuery, 256, "SELECT map, time, jumps, id FROM %splayertimes WHERE auth = '%s' AND style = %d ORDER BY map;", gS_MySQLPrefix, sAuth, view_as(gBS_Style[client])); } else { - FormatEx(sQuery, 256, "SELECT DISTINCT m.map FROM %smapzones m LEFT JOIN %splayertimes r ON r.map = m.map AND r.auth = '%s' AND r.style = %d WHERE r.map IS NULL ORDER BY m.map;", gS_MySQLPrefix, gS_MySQLPrefix, sAuth, StrEqual(category, "mapsleft")? 0:1); - // PrintToConsole(client, sQuery); + FormatEx(sQuery, 256, "SELECT DISTINCT m.map FROM %smapzones m LEFT JOIN %splayertimes r ON r.map = m.map AND r.auth = '%s' AND r.style = %d WHERE r.map IS NULL ORDER BY m.map;", gS_MySQLPrefix, gS_MySQLPrefix, sAuth, view_as(gBS_Style[client])); } - DataPack datapack = new DataPack(); - datapack.WriteCell(GetClientSerial(client)); - datapack.WriteCell(GetClientSerial(target)); - datapack.WriteString(category); - - gH_SQL.Query(ShowMapsCallback, sQuery, datapack, DBPrio_High); + gH_SQL.Query(ShowMapsCallback, sQuery, GetClientSerial(client), DBPrio_High); } public void ShowMapsCallback(Handle owner, Handle hndl, const char[] error, any data) { if(hndl == null) { - delete view_as(data); - LogError("Timer (ShowMaps SELECT) SQL query failed. Reason: %s", error); return; } - ResetPack(data); + int client = GetClientFromSerial(data); - int clientserial = ReadPackCell(data); - int targetserial = ReadPackCell(data); - - char[] sCategory = new char[16]; - ReadPackString(data, sCategory, 16); - - delete view_as(data); - - int client = GetClientFromSerial(clientserial); - - if(!IsValidClient(client)) - { - return; - } - - int target = GetClientFromSerial(targetserial); - - if(!IsValidClient(client)) + if(!IsValidClient(client) || !IsValidClient(gI_Target[client])) { return; } @@ -358,24 +283,14 @@ public void ShowMapsCallback(Handle owner, Handle hndl, const char[] error, any char[] sTitle = new char[64]; - if(StrEqual(sCategory, "mapsdone")) + if(gI_MapType[client] == MAPSDONE) { - FormatEx(sTitle, 32, "Maps done for %N: (%d)", target, rows); + FormatEx(sTitle, 32, "[%s] Maps done for %N: (%d)", gS_ShortBhopStyles[client], gI_Target[client], rows); } - else if(StrEqual(sCategory, "mapsleft")) + else { - FormatEx(sTitle, 32, "Maps left for %N: (%d)", target, rows); - } - - else if(StrEqual(sCategory, "mapsdonesw")) - { - FormatEx(sTitle, 32, "[SW] Maps done for %N: (%d)", target, rows); - } - - else if(StrEqual(sCategory, "mapsleftsw")) - { - FormatEx(sTitle, 32, "[SW] Maps left for %N: (%d)", target, rows); + FormatEx(sTitle, 32, "[%s] Maps left for %N: (%d)", gS_ShortBhopStyles[client], gI_Target[client], rows); } Menu m = new Menu(MenuHandler_ShowMaps); @@ -386,9 +301,11 @@ public void ShowMapsCallback(Handle owner, Handle hndl, const char[] error, any char[] sMap = new char[128]; SQL_FetchString(hndl, 0, sMap, 128); + char[] sRecordID = new char[16]; + char[] sDisplay = new char[192]; - if(StrContains(sCategory, "done") != -1) + if(gI_MapType[client] == MAPSDONE) { float time = SQL_FetchFloat(hndl, 1); int jumps = SQL_FetchInt(hndl, 2); @@ -397,30 +314,140 @@ public void ShowMapsCallback(Handle owner, Handle hndl, const char[] error, any FormatSeconds(time, sTime, 32); FormatEx(sDisplay, 192, "%s - %s (%d jumps)", sMap, sTime, jumps); + + int recordid = SQL_FetchInt(hndl, 3); + IntToString(recordid, sRecordID, 16); } else { strcopy(sDisplay, 192, sMap); + strcopy(sRecordID, 16, "nope"); } - // adding map as info, may be used in the future - m.AddItem(sMap, sDisplay); + m.AddItem(sRecordID, sDisplay); } - if(!GetMenuItemCount(m)) + if(m.ItemCount == 0) { m.AddItem("nope", "No results."); } - m.ExitButton = true; + m.ExitBackButton = true; m.Display(client, 60); } public int MenuHandler_ShowMaps(Menu m, MenuAction action, int param1, int param2) { - if(action == MenuAction_End) + if(action == MenuAction_Select) + { + char[] sInfo = new char[16]; + m.GetItem(param2, sInfo, 16); + + if(StrEqual(sInfo, "nope")) + { + ShowStyleMenu(param1); + + return 0; + } + + char[] sQuery = new char[512]; + FormatEx(sQuery, 512, "SELECT u.name, p.time, p.jumps, p.style, u.auth, p.date, p.map FROM %splayertimes p JOIN %susers u ON p.auth = u.auth WHERE p.id = '%s' LIMIT 1;", gS_MySQLPrefix, gS_MySQLPrefix, sInfo); + + gH_SQL.Query(SQL_SubMenu_Callback, sQuery, GetClientSerial(param1)); + } + + else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) + { + ShowStyleMenu(param1); + } + + else if(action == MenuAction_End) + { + delete m; + } + + return 0; +} + +public void SQL_SubMenu_Callback(Handle owner, Handle hndl, const char[] error, any data) +{ + if(hndl == null) + { + LogError("Timer (STATS SUBMENU) SQL query failed. Reason: %s", error); + + return; + } + + int client = GetClientFromSerial(data); + + if(!client) + { + return; + } + + Menu m = new Menu(SubMenu_Handler); + + char[] sName = new char[MAX_NAME_LENGTH]; + char[] sAuthID = new char[32]; + char[] sMap = new char[256]; + + if(SQL_FetchRow(hndl)) + { + // 0 - name + SQL_FetchString(hndl, 0, sName, MAX_NAME_LENGTH); + + // 1 - time + float fTime = SQL_FetchFloat(hndl, 1); + char[] sTime = new char[16]; + FormatSeconds(fTime, sTime, 16); + + char[] sDisplay = new char[128]; + FormatEx(sDisplay, 128, "Time: %s", sTime); + m.AddItem("-1", sDisplay); + + // 2 - jumps + int iJumps = SQL_FetchInt(hndl, 2); + FormatEx(sDisplay, 128, "Jumps: %d", iJumps); + m.AddItem("-1", sDisplay); + + // 3 - style + int iStyle = SQL_FetchInt(hndl, 3); + FormatEx(sDisplay, 128, "Style: %s", gS_BhopStyles[iStyle]); + m.AddItem("-1", sDisplay); + + // 4 - steamid3 + SQL_FetchString(hndl, 4, sAuthID, 32); + + // 5 - date + char[] sDate = new char[32]; + SQL_FetchString(hndl, 5, sDate, 32); + FormatEx(sDisplay, 128, "Date: %s", sDate); + m.AddItem("-1", sDisplay); + + // 6 - map + SQL_FetchString(hndl, 6, sMap, 256); + } + + char[] sFormattedTitle = new char[256]; + FormatEx(sFormattedTitle, 256, "%s %s\n--- %s:", sName, sAuthID, sMap); + + m.SetTitle(sFormattedTitle); + + m.ExitBackButton = true; + + m.Display(client, 20); +} + +public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2) +{ + if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) + { + ShowMaps(param1); + } + + else if(action == MenuAction_End) { delete m; } diff --git a/scripting/shavit-wr.sp b/scripting/shavit-wr.sp index c51c68f3..f69fb142 100644 --- a/scripting/shavit-wr.sp +++ b/scripting/shavit-wr.sp @@ -843,7 +843,7 @@ public void SQL_WR_Callback(Handle owner, Handle hndl, const char[] error, any d char[] sFormattedTitle = new char[192]; - if(!GetMenuItemCount(m)) + if(m.ItemCount == 0) { FormatEx(sFormattedTitle, 192, "Records for %s", sMap); @@ -930,12 +930,8 @@ public void SQL_SubMenu_Callback(Handle owner, Handle hndl, const char[] error, char[] sName = new char[MAX_NAME_LENGTH]; char[] sAuthID = new char[32]; - int iCount = 0; - - while(SQL_FetchRow(hndl)) + if(SQL_FetchRow(hndl)) { - iCount++; - // 0 - name SQL_FetchString(hndl, 0, sName, MAX_NAME_LENGTH); @@ -973,14 +969,14 @@ public void SQL_SubMenu_Callback(Handle owner, Handle hndl, const char[] error, m.SetTitle(sFormattedTitle); - m.ExitButton = true; + m.ExitBackButton = true; m.Display(client, 20); } public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2) { - if(((action == MenuAction_Cancel && (param2 == MenuCancel_ExitBack && param2 != MenuCancel_Exit)) || action == MenuAction_Select) && IsValidClient(param1)) + if((action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) || action == MenuAction_Select) { StartWRMenu(param1, gS_ClientMap[param1], view_as(gBS_LastWR[param1])); } diff --git a/scripting/shavit-zones.sp b/scripting/shavit-zones.sp index 41ef83d1..7e091fc6 100644 --- a/scripting/shavit-zones.sp +++ b/scripting/shavit-zones.sp @@ -184,6 +184,8 @@ public Action SetSQLInfo() if(gH_SQL == null) { + Shavit_GetDB(gH_SQL); + fTime = 0.5; } @@ -571,7 +573,7 @@ public Action Command_DeleteZone(int client, int args) } } - if(!GetMenuItemCount(menu)) + if(menu.ItemCount == 0) { menu.AddItem("-1", "No zones found."); }