Added perfect jump% measuring for scroll styles.

* Added `oldtime` and `perfs` parameters for forwards that missed them.
* Added `iMeasuredJumps` and `iPerfectJumps` to snapshots.
* Added a database migration to add `perfs` column.
* Added perfect jumps% to CS:S keyhint HUD. Not necessary in CS:GO due to annoying limitations.
* Added perfect jumps% to WR menu.
* Added `Shavit_GetPerfectJumps` native.
This commit is contained in:
shavit 2018-05-02 12:21:16 +03:00
parent 8861c388fe
commit 8c25086471
5 changed files with 154 additions and 34 deletions

View File

@ -145,6 +145,8 @@ enum
fServerTime, fServerTime,
iSHSWCombination, iSHSWCombination,
iTimerTrack, iTimerTrack,
iMeasuredJumps,
iPerfectJumps,
TIMERSNAPSHOT_SIZE TIMERSNAPSHOT_SIZE
}; };
@ -386,9 +388,10 @@ forward Action Shavit_OnFinishPre(int client, any snapshot[TIMERSNAPSHOT_SIZE]);
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured. * @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track. * @param track Timer track.
* @param oldtime The player's best time on the map before this finish. * @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @noreturn * @noreturn
*/ */
forward void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime); forward void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs);
/** /**
* Like Shavit_OnFinish, but after the insertion query was called. * Like Shavit_OnFinish, but after the insertion query was called.
@ -403,9 +406,11 @@ forward void Shavit_OnFinish(int client, int style, float time, int jumps, int s
* @param rank Rank on map. * @param rank Rank on map.
* @param overwrite 1 - brand new record. 2 - update. * @param overwrite 1 - brand new record. 2 - update.
* @param track Timer track. * @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @noreturn * @noreturn
*/ */
forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track); forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track, float oldtime, float perfs);
/** /**
* Called when there's a new WR on the map. * Called when there's a new WR on the map.
@ -418,9 +423,11 @@ forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps,
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured. * @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track. * @param track Timer track.
* @param oldwr Time of the old WR. 0.0 if there's none. * @param oldwr Time of the old WR. 0.0 if there's none.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @noreturn * @noreturn
*/ */
forward void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldwr); forward void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldwr, float oldtime, float perfs);
/** /**
* Called when an admin deletes a WR. * Called when an admin deletes a WR.
@ -520,9 +527,11 @@ forward void Shavit_OnLeaveZone(int client, int type, int track, int id, int ent
* @param strafes Amount of strafes. * @param strafes Amount of strafes.
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured. * @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
* @param track Timer track. * @param track Timer track.
* @param oldtime The player's best time on the map before this finish.
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
* @noreturn * @noreturn
*/ */
forward void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync, int track); forward void Shavit_OnWorstRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs);
/** /**
* Gets called when a map's tier is assigned. * Gets called when a map's tier is assigned.
@ -661,6 +670,15 @@ native TimerStatus Shavit_GetTimerStatus(int client);
*/ */
native int Shavit_GetStrafeCount(int client); native int Shavit_GetStrafeCount(int client);
/**
* Retrieve the perfect jumps percentage for the player.
* Will return 100.0 if no jumps were measured.
*
* @param client Client index.
* @return Perfect jump percentage.
*/
native float Shavit_GetPerfectJumps(int client);
/** /**
* Retrieve strafe sync since timer start. * Retrieve strafe sync since timer start.
* Will return 0.0 if timer isn't running or -1.0 when not measured. * Will return 0.0 if timer isn't running or -1.0 when not measured.
@ -1183,6 +1201,7 @@ public void __pl_shavit_SetNTVOptional()
MarkNativeAsOptional("Shavit_GetHUDSettings"); MarkNativeAsOptional("Shavit_GetHUDSettings");
MarkNativeAsOptional("Shavit_GetMapTier"); MarkNativeAsOptional("Shavit_GetMapTier");
MarkNativeAsOptional("Shavit_GetMapTiers"); MarkNativeAsOptional("Shavit_GetMapTiers");
MarkNativeAsOptional("Shavit_GetPerfectJumps");
MarkNativeAsOptional("Shavit_GetPlayerPB"); MarkNativeAsOptional("Shavit_GetPlayerPB");
MarkNativeAsOptional("Shavit_GetPoints"); MarkNativeAsOptional("Shavit_GetPoints");
MarkNativeAsOptional("Shavit_GetRank"); MarkNativeAsOptional("Shavit_GetRank");

View File

@ -78,6 +78,8 @@ float gF_StrafeWarning[MAXPLAYERS+1];
bool gB_PracticeMode[MAXPLAYERS+1]; bool gB_PracticeMode[MAXPLAYERS+1];
int gI_SHSW_FirstCombination[MAXPLAYERS+1]; int gI_SHSW_FirstCombination[MAXPLAYERS+1];
int gI_Track[MAXPLAYERS+1]; int gI_Track[MAXPLAYERS+1];
int gI_MeasuredJumps[MAXPLAYERS+1];
int gI_PerfectJumps[MAXPLAYERS+1];
StringMap gSM_StyleCommands = null; StringMap gSM_StyleCommands = null;
@ -132,6 +134,7 @@ char gS_ChatStrings[CHATSETTINGS_SIZE][128];
bool gB_StopChatSound = false; bool gB_StopChatSound = false;
bool gB_HookedJump = false; bool gB_HookedJump = false;
char gS_LogPath[PLATFORM_MAX_PATH]; char gS_LogPath[PLATFORM_MAX_PATH];
int gI_GroundTicks[MAXPLAYERS+1];
// flags // flags
int gI_StyleFlag[STYLE_LIMIT]; int gI_StyleFlag[STYLE_LIMIT];
@ -160,6 +163,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
CreateNative("Shavit_GetDatabase", Native_GetDatabase); CreateNative("Shavit_GetDatabase", Native_GetDatabase);
CreateNative("Shavit_GetDB", Native_GetDB); CreateNative("Shavit_GetDB", Native_GetDB);
CreateNative("Shavit_GetGameType", Native_GetGameType); CreateNative("Shavit_GetGameType", Native_GetGameType);
CreateNative("Shavit_GetPerfectJumps", Native_GetPerfectJumps);
CreateNative("Shavit_GetStrafeCount", Native_GetStrafeCount); CreateNative("Shavit_GetStrafeCount", Native_GetStrafeCount);
CreateNative("Shavit_GetStyleCount", Native_GetStyleCount); CreateNative("Shavit_GetStyleCount", Native_GetStyleCount);
CreateNative("Shavit_GetStyleSettings", Native_GetStyleSettings); CreateNative("Shavit_GetStyleSettings", Native_GetStyleSettings);
@ -197,7 +201,7 @@ public void OnPluginStart()
gH_Forwards_Start = CreateGlobalForward("Shavit_OnStart", ET_Event, Param_Cell, Param_Cell); gH_Forwards_Start = CreateGlobalForward("Shavit_OnStart", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_Stop = CreateGlobalForward("Shavit_OnStop", ET_Event, Param_Cell, Param_Cell); gH_Forwards_Stop = CreateGlobalForward("Shavit_OnStop", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_FinishPre = CreateGlobalForward("Shavit_OnFinishPre", ET_Event, Param_Cell, Param_Array); gH_Forwards_FinishPre = CreateGlobalForward("Shavit_OnFinishPre", ET_Event, Param_Cell, Param_Array);
gH_Forwards_Finish = CreateGlobalForward("Shavit_OnFinish", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell); gH_Forwards_Finish = CreateGlobalForward("Shavit_OnFinish", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
gH_Forwards_OnRestart = CreateGlobalForward("Shavit_OnRestart", ET_Event, Param_Cell, Param_Cell); gH_Forwards_OnRestart = CreateGlobalForward("Shavit_OnRestart", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnEnd = CreateGlobalForward("Shavit_OnEnd", ET_Event, Param_Cell, Param_Cell); gH_Forwards_OnEnd = CreateGlobalForward("Shavit_OnEnd", ET_Event, Param_Cell, Param_Cell);
gH_Forwards_OnPause = CreateGlobalForward("Shavit_OnPause", ET_Event, Param_Cell, Param_Cell); gH_Forwards_OnPause = CreateGlobalForward("Shavit_OnPause", ET_Event, Param_Cell, Param_Cell);
@ -955,6 +959,8 @@ public int Native_FinishMap(Handle handler, int numParams)
snapshot[fCurrentTime] = gF_PlayerTimer[client]; snapshot[fCurrentTime] = gF_PlayerTimer[client];
snapshot[iSHSWCombination] = gI_SHSW_FirstCombination[client]; snapshot[iSHSWCombination] = gI_SHSW_FirstCombination[client];
snapshot[iTimerTrack] = gI_Track[client]; snapshot[iTimerTrack] = gI_Track[client];
snapshot[iMeasuredJumps] = gI_MeasuredJumps[client];
snapshot[iPerfectJumps] = gI_PerfectJumps[client];
Action result = Plugin_Continue; Action result = Plugin_Continue;
Call_StartForward(gH_Forwards_FinishPre); Call_StartForward(gH_Forwards_FinishPre);
@ -972,6 +978,7 @@ public int Native_FinishMap(Handle handler, int numParams)
int style = 0; int style = 0;
int track = Track_Main; int track = Track_Main;
float perfs = 100.0;
if(result == Plugin_Continue) if(result == Plugin_Continue)
{ {
@ -981,6 +988,7 @@ public int Native_FinishMap(Handle handler, int numParams)
Call_PushCell(gI_Strafes[client]); Call_PushCell(gI_Strafes[client]);
Call_PushCell((gA_StyleSettings[gI_Style[client]][bSync])? (gI_GoodGains[client] == 0)? 0.0:(gI_GoodGains[client] / float(gI_TotalMeasures[client]) * 100.0):-1.0); Call_PushCell((gA_StyleSettings[gI_Style[client]][bSync])? (gI_GoodGains[client] == 0)? 0.0:(gI_GoodGains[client] / float(gI_TotalMeasures[client]) * 100.0):-1.0);
Call_PushCell(track = gI_Track[client]); Call_PushCell(track = gI_Track[client]);
perfs = (gI_MeasuredJumps[client] == 0)? 100.0:(gI_PerfectJumps[client] / float(gI_MeasuredJumps[client]) * 100.0);
} }
else else
@ -991,6 +999,7 @@ public int Native_FinishMap(Handle handler, int numParams)
Call_PushCell(snapshot[iStrafes]); Call_PushCell(snapshot[iStrafes]);
Call_PushCell((gA_StyleSettings[snapshot[bsStyle]][bSync])? (snapshot[iGoodGains] == 0)? 0.0:(snapshot[iGoodGains] / float(snapshot[iTotalMeasures]) * 100.0):-1.0); Call_PushCell((gA_StyleSettings[snapshot[bsStyle]][bSync])? (snapshot[iGoodGains] == 0)? 0.0:(snapshot[iGoodGains] / float(snapshot[iTotalMeasures]) * 100.0):-1.0);
Call_PushCell(track = snapshot[iTimerTrack]); Call_PushCell(track = snapshot[iTimerTrack]);
perfs = (snapshot[iMeasuredJumps] == 0)? 100.0:(snapshot[iPerfectJumps] / float(snapshot[iMeasuredJumps]) * 100.0);
} }
float oldtime = 0.0; float oldtime = 0.0;
@ -1001,6 +1010,7 @@ public int Native_FinishMap(Handle handler, int numParams)
} }
Call_PushCell(oldtime); Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_Finish(); Call_Finish();
StopTimer(client); StopTimer(client);
@ -1065,6 +1075,13 @@ public int Native_RestartTimer(Handle handler, int numParams)
StartTimer(client, track); StartTimer(client, track);
} }
public int Native_GetPerfectJumps(Handle handler, int numParams)
{
int client = GetNativeCell(1);
return view_as<int>((gI_MeasuredJumps[client] == 0)? 100.0:(gI_PerfectJumps[client] / float(gI_MeasuredJumps[client]) * 100.0));
}
public int Native_GetStrafeCount(Handle handler, int numParams) public int Native_GetStrafeCount(Handle handler, int numParams)
{ {
return gI_Strafes[GetNativeCell(1)]; return gI_Strafes[GetNativeCell(1)];
@ -1132,6 +1149,8 @@ public int Native_SaveSnapshot(Handle handler, int numParams)
snapshot[fCurrentTime] = gF_PlayerTimer[client]; snapshot[fCurrentTime] = gF_PlayerTimer[client];
snapshot[iSHSWCombination] = gI_SHSW_FirstCombination[client]; snapshot[iSHSWCombination] = gI_SHSW_FirstCombination[client];
snapshot[iTimerTrack] = gI_Track[client]; snapshot[iTimerTrack] = gI_Track[client];
snapshot[iMeasuredJumps] = gI_MeasuredJumps[client];
snapshot[iPerfectJumps] = gI_PerfectJumps[client];
return SetNativeArray(2, snapshot, TIMERSNAPSHOT_SIZE); return SetNativeArray(2, snapshot, TIMERSNAPSHOT_SIZE);
} }
@ -1159,6 +1178,8 @@ public int Native_LoadSnapshot(Handle handler, int numParams)
gI_GoodGains[client] = view_as<int>(snapshot[iGoodGains]); gI_GoodGains[client] = view_as<int>(snapshot[iGoodGains]);
gF_PlayerTimer[client] = snapshot[fCurrentTime]; gF_PlayerTimer[client] = snapshot[fCurrentTime];
gI_SHSW_FirstCombination[client] = view_as<int>(snapshot[iSHSWCombination]); gI_SHSW_FirstCombination[client] = view_as<int>(snapshot[iSHSWCombination]);
gI_MeasuredJumps[client] = view_as<int>(snapshot[iMeasuredJumps]);
gI_PerfectJumps[client] = view_as<int>(snapshot[iPerfectJumps]);
} }
public int Native_LogMessage(Handle plugin, int numParams) public int Native_LogMessage(Handle plugin, int numParams)
@ -1229,6 +1250,8 @@ void StartTimer(int client, int track)
gI_SHSW_FirstCombination[client] = -1; gI_SHSW_FirstCombination[client] = -1;
gF_PlayerTimer[client] = 0.0; gF_PlayerTimer[client] = 0.0;
gB_PracticeMode[client] = false; gB_PracticeMode[client] = false;
gI_MeasuredJumps[client] = 0;
gI_PerfectJumps[client] = 0;
SetEntityGravity(client, view_as<float>(gA_StyleSettings[gI_Style[client]][fGravityMultiplier])); SetEntityGravity(client, view_as<float>(gA_StyleSettings[gI_Style[client]][fGravityMultiplier]));
SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", view_as<float>(gA_StyleSettings[gI_Style[client]][fSpeedMultiplier])); SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", view_as<float>(gA_StyleSettings[gI_Style[client]][fSpeedMultiplier]));
@ -2086,15 +2109,40 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fSpeed); SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fSpeed);
} }
int iPButtons = buttons;
if(gA_StyleSettings[gI_Style[client]][bAutobhop] && gB_Auto[client] && (buttons & IN_JUMP) > 0 && mtMoveType == MOVETYPE_WALK && !bInWater) if(gA_StyleSettings[gI_Style[client]][bAutobhop] && gB_Auto[client] && (buttons & IN_JUMP) > 0 && mtMoveType == MOVETYPE_WALK && !bInWater)
{ {
int iOldButtons = GetEntProp(client, Prop_Data, "m_nOldButtons"); int iOldButtons = GetEntProp(client, Prop_Data, "m_nOldButtons");
SetEntProp(client, Prop_Data, "m_nOldButtons", iOldButtons & ~IN_JUMP); SetEntProp(client, Prop_Data, "m_nOldButtons", (iOldButtons & ~IN_JUMP));
iPButtons &= ~IN_JUMP;
} }
else if(gB_DoubleSteps[client] && (buttons & IN_JUMP) == 0) else if(gB_DoubleSteps[client] && (buttons & IN_JUMP) == 0)
{ {
buttons |= IN_JUMP; iPButtons = buttons |= IN_JUMP;
}
// perf jump measuring
if(!bInWater && mtMoveType == MOVETYPE_WALK && iGroundEntity != -1)
{
gI_GroundTicks[client]++;
if((((gI_ButtonCache[client] & IN_JUMP) == 0 && (iPButtons & IN_JUMP) > 0) || iPButtons != buttons) &&
1 <= gI_GroundTicks[client] <= 8)
{
gI_MeasuredJumps[client]++;
if(gI_GroundTicks[client] == 1)
{
gI_PerfectJumps[client]++;
}
}
}
else
{
gI_GroundTicks[client] = 0;
} }
if(bInStart && gB_BlockPreJump && !gA_StyleSettings[gI_Style[client]][bPrespeed] && (vel[2] > 0 || (buttons & IN_JUMP) > 0)) if(bInStart && gB_BlockPreJump && !gA_StyleSettings[gI_Style[client]][bPrespeed] && (vel[2] > 0 || (buttons & IN_JUMP) > 0))
@ -2182,7 +2230,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
} }
} }
gI_ButtonCache[client] = buttons; gI_ButtonCache[client] = iPButtons;
gF_AngleCache[client] = angles[1]; gF_AngleCache[client] = angles[1];
return Plugin_Continue; return Plugin_Continue;

View File

@ -761,7 +761,7 @@ void UpdateHUD(int client)
{ {
if(gA_StyleSettings[style][bSync]) if(gA_StyleSettings[style][bSync])
{ {
Format(sHintText, 512, "%s%s\t%T: %d (%.02f%%)", sHintText, (iSpeed < 1000)? "\t":"", "HudStrafeText", client, strafes, Shavit_GetSync(target)); Format(sHintText, 512, "%s%s\t%T: %d (%.01f%%)", sHintText, (iSpeed < 1000)? "\t":"", "HudStrafeText", client, strafes, Shavit_GetSync(target));
} }
else else
@ -1075,9 +1075,16 @@ void UpdateKeyHint(int client)
if(IsValidClient(target) && (target == client || (gI_HUDSettings[client] & HUD_OBSERVE) > 0)) if(IsValidClient(target) && (target == client || (gI_HUDSettings[client] & HUD_OBSERVE) > 0))
{ {
if((gI_HUDSettings[client] & HUD_SYNC) > 0 && Shavit_GetTimerStatus(target) == Timer_Running && gA_StyleSettings[Shavit_GetBhopStyle(target)][bSync] && !IsFakeClient(target) && (!gB_Zones || !Shavit_InsideZone(target, Zone_Start, -1))) int style = Shavit_GetBhopStyle(target);
if((gI_HUDSettings[client] & HUD_SYNC) > 0 && Shavit_GetTimerStatus(target) == Timer_Running && gA_StyleSettings[style][bSync] && !IsFakeClient(target) && (!gB_Zones || !Shavit_InsideZone(target, Zone_Start, -1)))
{ {
Format(sMessage, 256, "%s%s%T: %.02f", sMessage, (strlen(sMessage) > 0)? "\n\n":"", "HudSync", client, Shavit_GetSync(target)); Format(sMessage, 256, "%s%s%T: %.01f", sMessage, (strlen(sMessage) > 0)? "\n\n":"", "HudSync", client, Shavit_GetSync(target));
if(!gA_StyleSettings[style][bAutobhop])
{
Format(sMessage, 256, "%s\n%T: %.1f", sMessage, "HudPerfs", client, Shavit_GetPerfectJumps(target));
}
} }
if((gI_HUDSettings[client] & HUD_SPECTATORS) > 0) if((gI_HUDSettings[client] & HUD_SPECTATORS) > 0)

View File

@ -131,10 +131,10 @@ public void OnPluginStart()
#endif #endif
// forwards // forwards
gH_OnWorldRecord = CreateGlobalForward("Shavit_OnWorldRecord", 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, 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_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, Param_Cell, Param_Cell);
gH_OnWRDeleted = CreateGlobalForward("Shavit_OnWRDeleted", ET_Event, Param_Cell, Param_Cell, Param_Cell); gH_OnWRDeleted = CreateGlobalForward("Shavit_OnWRDeleted", ET_Event, 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); gH_OnWorstRecord = CreateGlobalForward("Shavit_OnWorstRecord", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
// player commands // player commands
RegConsoleCmd("sm_wr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_wr [map]"); RegConsoleCmd("sm_wr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_wr [map]");
@ -1671,7 +1671,7 @@ public int RRMenu_Handler(Menu m, MenuAction action, int param1, int param2)
void OpenSubMenu(int client, int id) void OpenSubMenu(int client, int id)
{ {
char[] sQuery = new char[512]; 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, p.track 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.perfs, 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 datapack = new DataPack();
datapack.WriteCell(GetClientSerial(client)); datapack.WriteCell(GetClientSerial(client));
@ -1722,19 +1722,30 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
menu.AddItem("-1", sDisplay); menu.AddItem("-1", sDisplay);
// 2 - jumps // 2 - jumps
int style = results.FetchInt(3);
int jumps = results.FetchInt(2); int jumps = results.FetchInt(2);
FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, jumps);
if(gA_StyleSettings[style][bAutobhop])
{
FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, jumps);
}
else
{
float perfs = results.FetchFloat(9);
FormatEx(sDisplay, 128, "%T: %d (%.2f%%)", "WRJumps", client, jumps, perfs);
}
menu.AddItem("-1", sDisplay); menu.AddItem("-1", sDisplay);
// 3 - style // 3 - style
int style = results.FetchInt(3);
FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[style][sStyleName]); FormatEx(sDisplay, 128, "%T: %s", "WRStyle", client, gS_StyleStrings[style][sStyleName]);
menu.AddItem("-1", sDisplay); menu.AddItem("-1", sDisplay);
// 6 - map // 6 - map
results.FetchString(6, sMap, 192); results.FetchString(6, sMap, 192);
float fPoints = results.FetchFloat(9); float fPoints = results.FetchFloat(10);
if(gB_Rankings && fPoints > 0.0) if(gB_Rankings && fPoints > 0.0)
{ {
@ -1784,7 +1795,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[]
menu.AddItem(sInfo, sMenuItem); menu.AddItem(sInfo, sMenuItem);
} }
GetTrackName(client, results.FetchInt(10), sTrack, 32); GetTrackName(client, results.FetchInt(11), sTrack, 32);
} }
else else
@ -1921,12 +1932,12 @@ void SQL_DBConnect()
if(gB_MySQL) if(gB_MySQL)
{ {
FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` CHAR(32), `map` CHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` CHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`)) ENGINE=INNODB;", gS_MySQLPrefix); FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `auth` CHAR(32), `map` CHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` CHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`)) ENGINE=INNODB;", gS_MySQLPrefix);
} }
else else
{ {
FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` CHAR(32), `map` CHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` CHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0);", gS_MySQLPrefix); FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `auth` CHAR(32), `map` CHAR(128), `time` FLOAT, `jumps` INT, `style` TINYINT, `date` CHAR(16), `strafes` INT, `sync` FLOAT, `points` FLOAT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `perfs` FLOAT DEFAULT 0);", gS_MySQLPrefix);
} }
gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0, DBPrio_High); gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0, DBPrio_High);
@ -1966,6 +1977,9 @@ public void SQL_CreateTable_Callback(Database db, DBResultSet results, const cha
FormatEx(sQuery, 64, "SELECT track FROM %splayertimes LIMIT 1;", gS_MySQLPrefix); FormatEx(sQuery, 64, "SELECT track FROM %splayertimes LIMIT 1;", gS_MySQLPrefix);
gH_SQL.Query(SQL_TableMigration4_Callback, sQuery); gH_SQL.Query(SQL_TableMigration4_Callback, sQuery);
FormatEx(sQuery, 64, "SELECT perfs FROM %splayertimes LIMIT 1;", gS_MySQLPrefix);
gH_SQL.Query(SQL_TableMigration5_Callback, sQuery);
} }
public void SQL_TableMigration1_Callback(Database db, DBResultSet results, const char[] error, any data) public void SQL_TableMigration1_Callback(Database db, DBResultSet results, const char[] error, any data)
@ -1996,8 +2010,6 @@ public void SQL_AlterTable1_Callback(Database db, DBResultSet results, const cha
if(results == null) if(results == null)
{ {
LogError("Timer (WR module) error! Times' table migration (1) failed. Reason: %s", error); LogError("Timer (WR module) error! Times' table migration (1) failed. Reason: %s", error);
return;
} }
} }
@ -2006,8 +2018,6 @@ public void SQL_AlterTable2_Callback(Database db, DBResultSet results, const cha
if(results == null) if(results == null)
{ {
LogError("Timer (WR module) error! Times' table migration (2) failed. Reason: %s", error); LogError("Timer (WR module) error! Times' table migration (2) failed. Reason: %s", error);
return;
} }
} }
@ -2026,8 +2036,6 @@ public void SQL_AlterTable3_Callback(Database db, DBResultSet results, const cha
if(results == null) if(results == null)
{ {
LogError("Timer (WR module) error! Times' table migration (3) failed. Reason: %s", error); LogError("Timer (WR module) error! Times' table migration (3) failed. Reason: %s", error);
return;
} }
} }
@ -2038,11 +2046,7 @@ public void SQL_TableMigration4_Callback(Database db, DBResultSet results, const
char[] sQuery = new char[256]; char[] sQuery = new char[256];
FormatEx(sQuery, 256, "ALTER TABLE `%splayertimes` ADD %s;", gS_MySQLPrefix, (gB_MySQL)? "(`track` INT NOT NULL DEFAULT 0)":"COLUMN `track` INT NOT NULL DEFAULT 0"); FormatEx(sQuery, 256, "ALTER TABLE `%splayertimes` ADD %s;", gS_MySQLPrefix, (gB_MySQL)? "(`track` INT NOT NULL DEFAULT 0)":"COLUMN `track` INT NOT NULL DEFAULT 0");
gH_SQL.Query(SQL_AlterTable4_Callback, sQuery); gH_SQL.Query(SQL_AlterTable4_Callback, sQuery);
return;
} }
OnMapStart();
} }
public void SQL_AlterTable4_Callback(Database db, DBResultSet results, const char[] error, any data) public void SQL_AlterTable4_Callback(Database db, DBResultSet results, const char[] error, any data)
@ -2050,6 +2054,26 @@ public void SQL_AlterTable4_Callback(Database db, DBResultSet results, const cha
if(results == null) if(results == null)
{ {
LogError("Timer (WR module) error! Times' table migration (4) failed. Reason: %s", error); LogError("Timer (WR module) error! Times' table migration (4) failed. Reason: %s", error);
}
}
public void SQL_TableMigration5_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
char[] sQuery = new char[256];
if(gB_MySQL)
{
FormatEx(sQuery, 256, "ALTER TABLE `%splayertimes` ADD (`perfs` FLOAT DEFAULT 0);", gS_MySQLPrefix);
}
else
{
FormatEx(sQuery, 256, "ALTER TABLE `%splayertimes` ADD COLUMN `perfs` FLOAT DEFAULT 0;", gS_MySQLPrefix);
}
gH_SQL.Query(SQL_AlterTable5_Callback, sQuery);
return; return;
} }
@ -2057,7 +2081,19 @@ public void SQL_AlterTable4_Callback(Database db, DBResultSet results, const cha
OnMapStart(); OnMapStart();
} }
public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track) public void SQL_AlterTable5_Callback(Database db, DBResultSet results, const char[] error, any data)
{
if(results == null)
{
LogError("Timer (WR module) error! Times' table migration (5) failed. Reason: %s", error);
return;
}
OnMapStart();
}
public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs)
{ {
char[] sTime = new char[32]; char[] sTime = new char[32];
FormatSeconds(time, sTime, 32); FormatSeconds(time, sTime, 32);
@ -2099,6 +2135,8 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st
Call_PushCell(sync); Call_PushCell(sync);
Call_PushCell(track); Call_PushCell(track);
Call_PushCell(oldwr); Call_PushCell(oldwr);
Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_Finish(); Call_Finish();
#if defined DEBUG #if defined DEBUG
@ -2118,6 +2156,8 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st
Call_PushCell(strafes); Call_PushCell(strafes);
Call_PushCell(sync); Call_PushCell(sync);
Call_PushCell(track); Call_PushCell(track);
Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_Finish(); Call_Finish();
} }
@ -2150,14 +2190,14 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st
return; return;
} }
FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track) VALUES ('%s', '%s', %.03f, %d, %d, %d, %d, %.2f, 0.0, %d);", gS_MySQLPrefix, sAuthID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track); FormatEx(sQuery, 512, "INSERT INTO %splayertimes (auth, map, time, jumps, date, style, strafes, sync, points, track, perfs) VALUES ('%s', '%s', %.03f, %d, %d, %d, %d, %.2f, 0.0, %d, %.2f);", gS_MySQLPrefix, sAuthID, gS_Map, time, jumps, GetTime(), style, strafes, sync, track, perfs);
} }
else // update else // update
{ {
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); 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, points = 0.0 WHERE map = '%s' AND auth = '%s' AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, gS_Map, sAuthID, style, track); FormatEx(sQuery, 512, "UPDATE %splayertimes SET time = %.03f, jumps = %d, date = %d, strafes = %d, sync = %.02f, points = 0.0, perfs = %.2f WHERE map = '%s' AND auth = '%s' AND style = %d AND track = %d;", gS_MySQLPrefix, time, jumps, GetTime(), strafes, sync, perfs, gS_Map, sAuthID, style, track);
} }
gH_SQL.Query(SQL_OnFinish_Callback, sQuery, GetClientSerial(client), DBPrio_High); gH_SQL.Query(SQL_OnFinish_Callback, sQuery, GetClientSerial(client), DBPrio_High);
@ -2172,6 +2212,8 @@ public void Shavit_OnFinish(int client, int style, float time, int jumps, int st
Call_PushCell(iRank); Call_PushCell(iRank);
Call_PushCell(overwrite); Call_PushCell(overwrite);
Call_PushCell(track); Call_PushCell(track);
Call_PushCell(oldtime);
Call_PushCell(perfs);
Call_Finish(); Call_Finish();
gF_PlayerRecord[client][style][track] = time; gF_PlayerRecord[client][style][track] = time;

View File

@ -56,6 +56,10 @@
{ {
"en" "Sync" "en" "Sync"
} }
"HudPerfs"
{
"en" "Perfect jumps"
}
"HudPracticeMode" "HudPracticeMode"
{ {
"en" "[PRACTICE]" "en" "[PRACTICE]"