huge rework on shavit-stats and add 'last login' (#149)

This commit is contained in:
shavitush 2016-08-05 05:13:23 +03:00
parent 30433ff79a
commit 3c0f2a857f
8 changed files with 317 additions and 167 deletions

View File

@ -91,6 +91,7 @@ Core
- [x] Add low gravity styles (0.6).
- [x] Better implementation of autobhop and +ds (doublestep fix).
- [x] Save autobhop/styles to clientprefs.
- [x] Add `lastlogin` column to `users`.
- [ ] Add bonus timer.
HUD
@ -128,7 +129,11 @@ Stats
- [x] Generate mapsdone points on the fly.
- [x] Add map rank to mapsdone.
- [x] Show strafes/sync in mapsdone submenu.
- [x] Redo *everything*.
- [x] Add 'last online' field.
- [x] Add `Shavit_GetWRCount(int client)`.
- [ ] Rework on points sorting and show weighting percentages.
- [ ] Stop calculating points on the fly and grab everything from the table.
Miscellaneous
--
@ -167,6 +172,8 @@ Rankings **(NEW!)**
- [x] Add natives. `float Shavit_GetPoints(int client)` `int Shavit_GetRank(int client)` `void Shavit_GetMapValues(float &points, float &idealtime)`
- [x] Add native that checks the total amount of players with over 0 points.
- [x] Add map tiers. `sm_tier` `sm_settier`
- [ ] Redirect to stats menu from `sm_top`.
- [ ] Deprecate the tables, use a `playertimes` column for map points and a `users` column for total points.
- [ ] Find a way to update newly calculated points for all records on a map with the least amount of queries possible.
- [ ] Remove idealtime and use the WR time for the default time instead.
- [ ] Remove deleted records from `playerpoints`.
@ -212,6 +219,8 @@ World Records
- [x] Calculate points on the fly (sub-menu) instead of grabbing them from `playerpoints`.
- [x] Add `sm_recent` `sm_recentrecords` `sm_rr`.
- [x] Add strafes/sync to the WR menu where available.
- [x] Add 'player stats' to submenu.
- [ ] Grab points from `playertimes` instead of calculating on the fly.
- [ ] Add `sm_bwr` `sm_bonuswr` `sm_bonusworldrecord`.
Time Limits

View File

@ -734,6 +734,25 @@ native int Shavit_ForceHUDUpdate(int client, bool spectators);
*/
native int Shavit_FormatChat(int client, const char[] message, const bool team, char[] buffer, int maxlen);
/**
* Opens the stats menu for a client.
*
* @param client Client index.
* @param authid Target SteamID3 to use.
* @noreturn
*/
native void Shavit_OpenStatsMenu(int client, const char[] authid);
/**
* Retrieves the amount of #1 records a player has.
* Result will depend on the value of `shavit_stats_mvprankones`.
* Called from shavit-stats.
*
* @param client Client index.
* @noreturn
*/
native int Shavit_GetWRCount(int client);
/**
* Use this native when printing anything in chat if it's related to the timer.
* This native will auto-assign colors and a chat prefix.
@ -797,12 +816,14 @@ public void __pl_shavit_SetNTVOptional()
MarkNativeAsOptional("Shavit_GetSync");
MarkNativeAsOptional("Shavit_GetTimer");
MarkNativeAsOptional("Shavit_GetTimerStatus");
MarkNativeAsOptional("Shavit_GetWRCount");
MarkNativeAsOptional("Shavit_GetWRName");
MarkNativeAsOptional("Shavit_GetWRRecordID");
MarkNativeAsOptional("Shavit_GetWRTime");
MarkNativeAsOptional("Shavit_InsideZone");
MarkNativeAsOptional("Shavit_IsClientCreatingZone");
MarkNativeAsOptional("Shavit_IsReplayDataLoaded");
MarkNativeAsOptional("Shavit_OpenStatsMenu");
MarkNativeAsOptional("Shavit_PauseTimer");
MarkNativeAsOptional("Shavit_PrintToChat");
MarkNativeAsOptional("Shavit_RestartTimer");

View File

@ -147,7 +147,7 @@ public void OnClientSettingsChanged(int client)
public void UpdateClanTag(int client)
{
if(strlen(gS_Cached_ClanTag[client]) > 0)
if(IsValidClient(client) && strlen(gS_Cached_ClanTag[client]) > 0)
{
CS_SetClientClanTag(client, gS_Cached_ClanTag[client]);
}

View File

@ -43,6 +43,7 @@ EngineVersion gEV_Type = Engine_Unknown;
// database handle
Database gH_SQL = null;
bool gB_MySQL = false;
// forwards
Handle gH_Forwards_Start = null;
@ -893,7 +894,7 @@ public void OnClientPutInServer(int client)
}
char[] sQuery = new char[512];
FormatEx(sQuery, 512, "REPLACE INTO %susers (auth, name, country, ip) VALUES ('%s', '%s', '%s', '%s');", gS_MySQLPrefix, sAuthID3, sEscapedName, sCountry, sIP);
FormatEx(sQuery, 512, "REPLACE INTO %susers (auth, name, country, ip, lastlogin) VALUES ('%s', '%s', '%s', '%s', %d);", gS_MySQLPrefix, sAuthID3, sEscapedName, sCountry, sIP, GetTime());
gH_SQL.Query(SQL_InsertUser_Callback, sQuery, GetClientSerial(client));
}
@ -904,7 +905,7 @@ public void SQL_InsertUser_Callback(Database db, DBResultSet results, const char
{
int client = GetClientFromSerial(data);
if(!client)
if(client == 0)
{
LogError("Timer error! Failed to insert a disconnected player's data to the table. Reason: %s", error);
}
@ -973,8 +974,12 @@ public void SQL_DBConnect()
// support unicode names
gH_SQL.SetCharset("utf8");
char[] sDriver = new char[8];
gH_SQL.Driver.GetIdentifier(sDriver, 8);
gB_MySQL = StrEqual(sDriver, "mysql", false);
char[] sQuery = new char[256];
FormatEx(sQuery, 256, "CREATE TABLE IF NOT EXISTS `%susers` (`auth` VARCHAR(32) NOT NULL, `name` VARCHAR(32), `country` VARCHAR(128), `ip` VARCHAR(64), PRIMARY KEY (`auth`));", gS_MySQLPrefix);
FormatEx(sQuery, 256, "CREATE TABLE IF NOT EXISTS `%susers` (`auth` VARCHAR(32) NOT NULL, `name` VARCHAR(32), `country` VARCHAR(128), `ip` VARCHAR(64), `lastlogin` %s NOT NULL DEFAULT -1, PRIMARY KEY (`auth`));", gS_MySQLPrefix, gB_MySQL? "INT":"INTEGER");
// CREATE TABLE IF NOT EXISTS
gH_SQL.Query(SQL_CreateTable_Callback, sQuery);
@ -988,6 +993,30 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha
return;
}
char[] sQuery = new char[64];
FormatEx(sQuery, 64, "SELECT lastlogin FROM %susers LIMIT 1;", gS_MySQLPrefix);
gH_SQL.Query(SQL_TableMigration1_Callback, sQuery, 0, DBPrio_High);
}
public void SQL_TableMigration1_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
char[] sQuery = new char[128];
FormatEx(sQuery, 128, "ALTER TABLE `%susers` ADD %s;", gS_MySQLPrefix, gB_MySQL? "(`lastlogin` INT NOT NULL DEFAULT -1)":"COLUMN `lastlogin` INTEGER NOT NULL DEFAULT -1");
gH_SQL.Query(SQL_AlterTable1_Callback, sQuery);
}
}
public void SQL_AlterTable1_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
LogError("Timer error! Table alteration 1 (core) failed. Reason: %s", error);
return;
}
}
public void PreThink(int client)

View File

@ -65,6 +65,9 @@ bool gB_MySQL = false;
// table prefix
char gS_MySQLPrefix[32];
// modules
bool gB_Stats = false;
public Plugin myinfo =
{
name = "[shavit] Rankings",
@ -137,6 +140,25 @@ public void OnPluginStart()
gCV_TopAmount = CreateConVar("shavit_rankings_topamount", "100", "Amount of people to show within the sm_top menu.", 0, true, 1.0, false);
AutoExecConfig();
// modules
gB_Stats = LibraryExists("shavit-stats");
}
public void OnLibraryAdded(const char[] name)
{
if(StrEqual(name, "shavit-stats"))
{
gB_Stats = true;
}
}
public void OnLibraryRemoved(const char[] name)
{
if(StrEqual(name, "shavit-stats"))
{
gB_Stats = false;
}
}
public void OnClientAuthorized(int client, const char[] auth)
@ -382,7 +404,7 @@ public Action Command_Top(int client, int args)
public Action ShowTopMenu(int client)
{
char[] sQuery = new char[192];
FormatEx(sQuery, 192, "SELECT u.name, %s points FROM %susers u JOIN %suserpoints up ON up.auth = u.auth WHERE up.points > 0.0 ORDER BY up.points DESC LIMIT %d;", gB_MySQL? "FORMAT(up.points, 2)":"up.points", gS_MySQLPrefix, gS_MySQLPrefix, gCV_TopAmount.IntValue);
FormatEx(sQuery, 192, "SELECT u.name, %s points, u.auth FROM %susers u JOIN %suserpoints up ON up.auth = u.auth WHERE up.points > 0.0 ORDER BY up.points DESC LIMIT %d;", gB_MySQL? "FORMAT(up.points, 2)":"up.points", gS_MySQLPrefix, gS_MySQLPrefix, gCV_TopAmount.IntValue);
gH_SQL.Query(SQL_ShowTopMenu_Callback, sQuery, GetClientSerial(client));
@ -423,8 +445,6 @@ public void SQL_ShowTopMenu_Callback(Database db, DBResultSet results, const cha
results.FetchString(0, sName, MAX_NAME_LENGTH);
int iRank = ++count;
char[] sRank = new char[6];
IntToString(iRank, sRank, 6); // info string for future purposes
char[] sDisplay = new char[64];
@ -441,7 +461,10 @@ public void SQL_ShowTopMenu_Callback(Database db, DBResultSet results, const cha
FormatEx(sDisplay, 64, "#%d - %s (%.02f points)", iRank, sName, results.FetchFloat(1));
}
m.AddItem(sRank, sDisplay);
char[] sAuthID = new char[32];
results.FetchString(2, sAuthID, 32);
m.AddItem(sAuthID, sDisplay);
}
}
@ -452,8 +475,18 @@ public void SQL_ShowTopMenu_Callback(Database db, DBResultSet results, const cha
public int MenuHandler_TopMenu(Menu m, MenuAction action, int param1, int param2)
{
// *eventually* add some shavit-stats call here, to show the player's profile
if(action == MenuAction_End)
if(action == MenuAction_Select && gB_Stats)
{
char[] sInfo = new char[32];
m.GetItem(param2, sInfo, 32);
if(StringToInt(sInfo) != -1)
{
Shavit_OpenStatsMenu(param1, sInfo);
}
}
else if(action == MenuAction_End)
{
delete m;
}

View File

@ -47,11 +47,10 @@ char gS_MySQLPrefix[32];
// cache
int gI_MapType[MAXPLAYERS+1];
int gI_Target[MAXPLAYERS+1];
BhopStyle gBS_Style[MAXPLAYERS+1];
char gS_TargetAuth[MAXPLAYERS+1][32];
char gS_TargetName[MAXPLAYERS+1][MAX_NAME_LENGTH];
int gI_WRAmount[MAXPLAYERS+1];
int gI_ClearCount[MAXPLAYERS+1];
int gI_TotalMaps = 0;
// cvars
ConVar gCV_MVPRankOnes = null;
@ -65,6 +64,17 @@ public Plugin myinfo =
url = "https://github.com/shavitush/bhoptimer"
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
// natives
CreateNative("Shavit_OpenStatsMenu", Native_OpenStatsMenu);
CreateNative("Shavit_GetWRCount", Native_GetWRConut);
RegPluginLibrary("shavit-stats");
return APLRes_Success;
}
public void OnAllPluginsLoaded()
{
if(!LibraryExists("shavit-wr"))
@ -99,29 +109,6 @@ public void OnPluginStart()
SetSQLInfo();
}
public void OnMapStart()
{
char[] sQuery = new char[256];
FormatEx(sQuery, 256, "SELECT COUNT(*) FROM (SELECT id FROM %smapzones GROUP BY map) s;", gS_MySQLPrefix);
gH_SQL.Query(SQL_GetTotalMaps_Callback, sQuery);
}
public void SQL_GetTotalMaps_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
LogError("Timer (get total maps) SQL query failed. You might be missing shavit-zones. Reason: %s", error);
return;
}
if(results.FetchRow())
{
gI_TotalMaps = results.FetchInt(0);
}
}
public void OnClientPutInServer(int client)
{
gI_WRAmount[client] = 0;
@ -195,8 +182,7 @@ public void SQL_SetPrefix()
public void Player_Event(Event event, const char[] name, bool dontBroadcast)
{
int userid = event.GetInt("userid");
int client = GetClientOfUserId(userid);
int client = GetClientOfUserId(event.GetInt("userid"));
if(IsValidClient(client))
{
@ -245,9 +231,6 @@ public void UpdateWRs(int client)
}
gH_SQL.Query(SQL_GetWRs_Callback, sQuery, GetClientSerial(client));
FormatEx(sQuery, 256, "SELECT COUNT(*) FROM (SELECT id FROM %splayertimes WHERE auth = '%s' GROUP BY map) s LIMIT 1;", gS_MySQLPrefix, sAuthID);
gH_SQL.Query(SQL_GetClears_Callback, sQuery, GetClientSerial(client));
}
}
@ -277,28 +260,6 @@ public void SQL_GetWRs_Callback(Database db, DBResultSet results, const char[] e
gI_WRAmount[client] = iWRs;
}
public void SQL_GetClears_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
LogError("Timer (get clear amount) SQL query failed. Reason: %s", error);
return;
}
int client = GetClientFromSerial(data);
if(client == 0)
{
return;
}
if(results.FetchRow())
{
gI_ClearCount[client] = results.FetchInt(0);
}
}
public Action Command_Profile(int client, int args)
{
if(!IsValidClient(client))
@ -321,48 +282,109 @@ public Action Command_Profile(int client, int args)
}
}
gI_Target[client] = target;
GetClientAuthId(target, AuthId_Steam3, gS_TargetAuth[client], 32);
return ShowStyleMenu(client);
return OpenStatsMenu(client, gS_TargetAuth[client]);
}
public Action ShowStyleMenu(int client)
public Action OpenStatsMenu(int client, const char[] authid)
{
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(gI_Target[client], AuthId_Steam3, sAuthID, 32);
char[] sRankingString = new char[128];
// big ass query, looking for optimizations
char[] sQuery = new char[2048];
if(gB_Rankings)
{
FormatEx(sRankingString, 128, "\nRank: %d/%d\nPoints: %d", Shavit_GetRank(gI_Target[client]), Shavit_GetRankedPlayers(), RoundToFloor(Shavit_GetPoints(gI_Target[client])));
FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.country, d.lastlogin, e.rank, f.points FROM " ...
"(SELECT COUNT(*) clears FROM (SELECT id FROM %splayertimes WHERE auth = '%s' GROUP BY map) s LIMIT 1) a " ...
"JOIN (SELECT COUNT(*) maps FROM (SELECT id FROM %smapzones GROUP BY map) s LIMIT 1) b " ...
"JOIN (SELECT COUNT(*) wrs FROM (SELECT s.auth FROM (SELECT style, auth, MIN(time) FROM %splayertimes GROUP BY map, style) s WHERE style = 0) ss WHERE ss.auth = '%s' LIMIT 1) c " ...
"JOIN (SELECT name, country, lastlogin FROM %susers WHERE auth = '%s' LIMIT 1) d " ...
"JOIN (SELECT COUNT(*) rank FROM %suserpoints up LEFT JOIN %susers u ON up.auth = u.auth WHERE up.points >= (SELECT points FROM %suserpoints WHERE auth = '%s' LIMIT 1) ORDER BY up.points DESC LIMIT 1) e " ...
"JOIN (SELECT points FROM %suserpoints WHERE auth = '%s' LIMIT 1) f " ...
"LIMIT 1;", gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, authid, gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, authid, gS_MySQLPrefix, authid);
}
char[] sCountry = new char[64];
GetClientIP(gI_Target[client], sCountry, 64);
if(!GeoipCountry(sCountry, sCountry, 64))
else
{
strcopy(sCountry, 64, "Local Area Network");
FormatEx(sQuery, 2048, "SELECT a.clears, b.maps, c.wrs, d.name, d.country, d.lastlogin FROM " ...
"(SELECT COUNT(*) clears FROM (SELECT id FROM %splayertimes WHERE auth = '%s' GROUP BY map) s LIMIT 1) a " ...
"JOIN (SELECT COUNT(*) maps FROM (SELECT id FROM %smapzones GROUP BY map) s LIMIT 1) b " ...
"JOIN (SELECT COUNT(*) wrs FROM (SELECT s.auth FROM (SELECT style, auth, MIN(time) FROM %splayertimes GROUP BY map, style) s WHERE style = 0) ss WHERE ss.auth = '%s' LIMIT 1) c " ...
"JOIN (SELECT name, country, lastlogin FROM %susers WHERE auth = '%s' LIMIT 1) d " ...
"LIMIT 1;", gS_MySQLPrefix, authid, gS_MySQLPrefix, gS_MySQLPrefix, authid, gS_MySQLPrefix, authid);
}
gH_SQL.Query(OpenStatsMenuCallback, sQuery, GetClientSerial(client));
return Plugin_Handled;
}
public void OpenStatsMenuCallback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
LogError("Timer (statsmenu) SQL query failed. Reason: %s", error);
return;
}
int client = GetClientFromSerial(data);
if(client == 0)
{
return;
}
if(results.FetchRow())
{
// create variables
int iClears = results.FetchInt(0);
int iTotalMaps = results.FetchInt(1);
int iWRs = results.FetchInt(2);
results.FetchString(3, gS_TargetName[client], MAX_NAME_LENGTH);
char[] sCountry = new char[64];
results.FetchString(4, sCountry, 64);
int iLastLogin = results.FetchInt(5);
char[] sLastLogin = new char[32];
FormatTime(sLastLogin, 32, "%Y-%m-%d %H:%M:%S", iLastLogin);
Format(sLastLogin, 32, "Last login: %s", (iLastLogin != -1)? sLastLogin:"N/A");
int iRank = -1;
float fPoints = -1.0;
if(gB_Rankings)
{
iRank = results.FetchInt(6);
fPoints = results.FetchFloat(7);
}
char[] sRankingString = new char[64];
if(gB_Rankings)
{
if(iRank > 0 && fPoints > 0.0)
{
FormatEx(sRankingString, 64, "\nRank: #%d/%d\nPoints: %.02f", iRank, Shavit_GetRankedPlayers(), fPoints);
}
else
{
FormatEx(sRankingString, 64, "\nRank: Unranked");
}
}
if(iClears > iTotalMaps)
{
iClears = iTotalMaps;
}
char[] sClearString = new char[128];
FormatEx(sClearString, 128, "Map completions: %d/%d (%.01f%%)", gI_ClearCount[gI_Target[client]], gI_TotalMaps, ((float((gI_ClearCount[gI_Target[client]])) / gI_TotalMaps) * 100.0));
FormatEx(sClearString, 128, "Map completions: %d/%d (%.01f%%)", iClears, iTotalMaps, ((float(iClears) / iTotalMaps) * 100.0));
Menu m = new Menu(MenuHandler_ProfileHandler);
m.SetTitle("%N's profile.\nCountry: %s\n%s\n%s #1 records: %d%s\nSteamID3: %s", gI_Target[client], sCountry, sClearString, (gCV_MVPRankOnes.IntValue == 2)? gS_BhopStyles[0]:"Total", gI_WRAmount[gI_Target[client]], sRankingString, sAuthID);
m.SetTitle("%s's profile. %s\nCountry: %s\n%s\n%s\n[%s] world records: %d%s\n", gS_TargetName[client], gS_TargetAuth[client], sCountry, sLastLogin, sClearString, gS_BhopStyles[0], iWRs, sRankingString);
for(int i = 0; i < sizeof(gS_BhopStyles); i++)
{
@ -382,21 +404,19 @@ public Action ShowStyleMenu(int client)
}
m.ExitButton = true;
m.Display(client, 20);
}
return Plugin_Handled;
else
{
Shavit_PrintToChat(client, "ERROR: Could not open the stats menu.");
}
}
public int MenuHandler_ProfileHandler(Menu m, MenuAction action, int param1, int param2)
{
if(action == MenuAction_Select)
{
if(!IsValidClient(gI_Target[param1]))
{
return 0;
}
char[] sInfo = new char[32];
m.GetItem(param2, sInfo, 32);
@ -424,11 +444,6 @@ public int MenuHandler_TypeHandler(Menu m, MenuAction action, int param1, int pa
{
if(action == MenuAction_Select)
{
if(!IsValidClient(gI_Target[param1]))
{
return 0;
}
char[] sInfo = new char[32];
m.GetItem(param2, sInfo, 32);
gI_MapType[param1] = StringToInt(sInfo);
@ -438,7 +453,7 @@ public int MenuHandler_TypeHandler(Menu m, MenuAction action, int param1, int pa
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
ShowStyleMenu(param1);
OpenStatsMenu(param1, gS_TargetAuth[param1]);
}
else if(action == MenuAction_End)
@ -465,11 +480,6 @@ public Action Timer_DBFailure(Handle timer, any data)
public void ShowMaps(int client)
{
if(!IsValidClient(gI_Target[client]))
{
return;
}
// database not found, display with a 3 seconds delay
if(gH_SQL == null)
{
@ -478,19 +488,16 @@ public void ShowMaps(int client)
return;
}
char[] sAuth = new char[32];
GetClientAuthId(gI_Target[client], AuthId_Steam3, sAuth, 32);
char[] sQuery = new char[512];
if(gI_MapType[client] == MAPSDONE)
{
FormatEx(sQuery, 512, "SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 rank FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style WHERE a.auth = '%s' AND a.style = %d GROUP BY a.map ORDER BY a.map;", gS_MySQLPrefix, gS_MySQLPrefix, sAuth, view_as<int>(gBS_Style[client]));
FormatEx(sQuery, 512, "SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 rank FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style WHERE a.auth = '%s' AND a.style = %d GROUP BY a.map ORDER BY a.map;", gS_MySQLPrefix, gS_MySQLPrefix, gS_TargetAuth[client], view_as<int>(gBS_Style[client]));
}
else
{
FormatEx(sQuery, 512, "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<int>(gBS_Style[client]));
FormatEx(sQuery, 512, "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, gS_TargetAuth[client], view_as<int>(gBS_Style[client]));
}
gH_SQL.Query(ShowMapsCallback, sQuery, GetClientSerial(client), DBPrio_High);
@ -507,7 +514,7 @@ public void ShowMapsCallback(Database db, DBResultSet results, const char[] erro
int client = GetClientFromSerial(data);
if(!IsValidClient(client) || !IsValidClient(gI_Target[client]))
if(client == 0)
{
return;
}
@ -518,12 +525,12 @@ public void ShowMapsCallback(Database db, DBResultSet results, const char[] erro
if(gI_MapType[client] == MAPSDONE)
{
FormatEx(sTitle, 64, "[%s] Maps done for %N: (%d)", gS_ShortBhopStyles[gBS_Style[client]], gI_Target[client], rows);
FormatEx(sTitle, 64, "[%s] Maps done for %s: (%d)", gS_ShortBhopStyles[gBS_Style[client]], gS_TargetName[client], rows);
}
else
{
FormatEx(sTitle, 64, "[%s] Maps left for %N: (%d)", gS_ShortBhopStyles[gBS_Style[client]], gI_Target[client], rows);
FormatEx(sTitle, 64, "[%s] Maps left for %s: (%d)", gS_ShortBhopStyles[gBS_Style[client]], gS_TargetName[client], rows);
}
Menu m = new Menu(MenuHandler_ShowMaps);
@ -599,7 +606,7 @@ public int MenuHandler_ShowMaps(Menu m, MenuAction action, int param1, int param
if(StrEqual(sInfo, "nope"))
{
ShowStyleMenu(param1);
OpenStatsMenu(param1, gS_TargetAuth[param1]);
return 0;
}
@ -612,7 +619,7 @@ public int MenuHandler_ShowMaps(Menu m, MenuAction action, int param1, int param
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
ShowStyleMenu(param1);
OpenStatsMenu(param1, gS_TargetAuth[param1]);
}
else if(action == MenuAction_End)
@ -705,7 +712,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
if(iJumps > 0 || iStrafes > 0)
{
FormatEx(sDisplay, 128, (fSync != -1.0)? "Strafes: %d (%.02f%%)":"Strafes: %d", iStrafes, fSync);
FormatEx(sDisplay, 128, (fSync > 0.0)? "Strafes: %d (%.02f%%)":"Strafes: %d", iStrafes, fSync);
m.AddItem("-1", sDisplay);
}
@ -718,7 +725,6 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
m.SetTitle(sFormattedTitle);
m.ExitBackButton = true;
m.Display(client, 20);
}
@ -736,3 +742,16 @@ public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2)
return 0;
}
public int Native_OpenStatsMenu(Handle handler, int numParams)
{
int client = GetNativeCell(1);
GetNativeString(2, gS_TargetAuth[client], 32);
OpenStatsMenu(client, gS_TargetAuth[client]);
}
public int Native_GetWRConut(Handle handler, int numParams)
{
return gI_WRAmount[GetNativeCell(1)];
}

View File

@ -35,6 +35,7 @@
bool gB_Late = false;
bool gB_Rankings = false;
bool gB_Stats = false;
// forwards
Handle gH_OnWorldRecord = null;
@ -104,12 +105,6 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
return APLRes_Success;
}
public void OnAllPluginsLoaded()
{
// modules
gB_Rankings = LibraryExists("shavit-rankings");
}
public void OnPluginStart()
{
// debug because I was making this all by myself and no one wanted to help me *sniff*
@ -159,6 +154,10 @@ public void OnPluginStart()
strcopy(gS_Color_Better, 16, (evType == Engine_CSS)? "\x07AD3BA6":"\x0C");
strcopy(gS_Color_Worse, 16, (evType == Engine_CSS)? "\x07CCCCCC":"\x08");
// modules
gB_Rankings = LibraryExists("shavit-rankings");
gB_Stats = LibraryExists("shavit-stats");
// mysql
Shavit_GetDB(gH_SQL);
SQL_SetPrefix();
@ -240,6 +239,11 @@ public void OnLibraryAdded(const char[] name)
{
gB_Rankings = true;
}
else if(StrEqual(name, "shavit-stats"))
{
gB_Stats = true;
}
}
public void OnLibraryRemoved(const char[] name)
@ -254,6 +258,11 @@ public void OnLibraryRemoved(const char[] name)
gB_Rankings = false;
}
else if(StrEqual(name, "shavit-stats"))
{
gB_Stats = false;
}
else if(StrEqual(name, "adminmenu"))
{
gH_AdminMenu = null;
@ -626,13 +635,12 @@ public void SQL_OpenDelete_Callback(Database db, DBResultSet results, const char
m.AddItem(sID, sDisplay);
}
if(!iCount)
if(iCount == 0)
{
m.AddItem("-1", "No records found.");
}
m.ExitButton = true;
m.Display(client, 20);
}
@ -981,7 +989,6 @@ public void SQL_WR_Callback(Database db, DBResultSet results, const char[] error
}
m.ExitBackButton = true;
m.Display(client, 20);
}
@ -989,13 +996,21 @@ public int WRMenu_Handler(Menu m, MenuAction action, int param1, int param2)
{
if(action == MenuAction_Select)
{
char[] info = new char[16];
m.GetItem(param2, info, 16);
int id = StringToInt(info);
char[] sInfo = new char[16];
m.GetItem(param2, sInfo, 16);
int id = StringToInt(sInfo);
if(id != -1)
{
OpenSubMenu(param1, id);
}
else
{
ShowWRStyleMenu(param1, gS_ClientMap[param1]);
}
}
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
ShowWRStyleMenu(param1, gS_ClientMap[param1]);
@ -1106,6 +1121,8 @@ public int RRMenu_Handler(Menu m, MenuAction action, int param1, int param2)
char[] sInfo = new char[192];
m.GetItem(param2, sInfo, 192);
if(StringToInt(sInfo) != -1)
{
char[][] sExploded = new char[2][192];
ExplodeString(sInfo, ";", sExploded, 2, 192, true);
@ -1114,6 +1131,12 @@ public int RRMenu_Handler(Menu m, MenuAction action, int param1, int param2)
OpenSubMenu(param1, StringToInt(sExploded[0]));
}
else
{
ShowWRStyleMenu(param1, gS_ClientMap[param1]);
}
}
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
ShowWRStyleMenu(param1, gS_ClientMap[param1]);
@ -1223,6 +1246,8 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
FormatEx(sDisplay, 128, (fSync != -1.0)? "Strafes: %d (%.02f%%)":"Strafes: %d", iStrafes, fSync);
m.AddItem("-1", sDisplay);
}
m.AddItem(sAuthID, "Player stats");
}
else
@ -1247,7 +1272,23 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
public int SubMenu_Handler(Menu m, MenuAction action, int param1, int param2)
{
if((action == MenuAction_Cancel && param2 == MenuCancel_ExitBack) || action == MenuAction_Select)
if(action == MenuAction_Select)
{
char[] sInfo = new char[32];
m.GetItem(param2, sInfo, 32);
if(gB_Stats && StringToInt(sInfo) != -1)
{
Shavit_OpenStatsMenu(param1, sInfo);
}
else
{
StartWRMenu(param1, gS_ClientMap[param1], view_as<int>(gBS_LastWR[param1]));
}
}
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
{
StartWRMenu(param1, gS_ClientMap[param1], view_as<int>(gBS_LastWR[param1]));
}

View File

@ -297,9 +297,7 @@ public int Native_InsideZone(Handle handler, int numParams)
public int Native_IsClientCreatingZone(Handle handler, int numParams)
{
int client = GetNativeCell(1);
return (gI_MapStep[client] != 0);
return (gI_MapStep[GetNativeCell(1)] != 0);
}
public void SetupColors()