diff --git a/addons/sourcemod/configs/shavit-styles.cfg b/addons/sourcemod/configs/shavit-styles.cfg index 7dd613a6..b1770c94 100644 --- a/addons/sourcemod/configs/shavit-styles.cfg +++ b/addons/sourcemod/configs/shavit-styles.cfg @@ -42,6 +42,7 @@ "block_d" "0" // Block +moveright (D). "block_use" "0" // Block +use (E). "force_hsw" "0" // Force half-sideways gameplay. 1 for regular HSW and 2 for surf-HSW. + "force_groundkeys" "0" // Forces the above settings even while on ground. e.g. enabling this will not allow W/D or W/A prestrafing when playing styles that disable the keys. "block_pleft" "0" // Block +left. 2 to stop timer. "block_pright" "0" // Block +right. 2 to stop timer. "block_pstrafe" "0" // Prevent button inconsistencies (including +pstrafe). May have false positives when players lag. Will prevent some strafe hacks too. Set this to 2 to also stop the timer. diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 2fb09475..093f3f59 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -23,7 +23,7 @@ #endif #define _shavit_included -#define SHAVIT_VERSION "2.5.3" +#define SHAVIT_VERSION "2.5.4" #define STYLE_LIMIT 256 #define MAX_ZONES 64 #define MAX_NAME_LENGTH_SQL 32 @@ -168,6 +168,7 @@ enum struct stylesettings_t bool bInaccessible; int iEnabled; bool bKZCheckpoints; + bool bForceKeysOnGround; } enum struct chatstrings_t diff --git a/addons/sourcemod/scripting/shavit-chat.sp b/addons/sourcemod/scripting/shavit-chat.sp index 0828bac4..68d88b0e 100644 --- a/addons/sourcemod/scripting/shavit-chat.sp +++ b/addons/sourcemod/scripting/shavit-chat.sp @@ -1253,11 +1253,7 @@ void FormatRandom(char[] buffer, int size) { if(IsSource2013(gEV_Type)) { - int color = ((RealRandomInt(0, 255) & 0xFF) << 16); - color |= ((RealRandomInt(0, 255) & 0xFF) << 8); - color |= (RealRandomInt(0, 255) & 0xFF); - - FormatEx(temp, 8, "\x07%06X", color); + FormatEx(temp, 8, "\x07%06X", RealRandomInt(0, 0xFFFFFF)); } else diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 8eaee899..bbc73d0b 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -469,6 +469,11 @@ public Action Command_StartTimer(int client, int args) if(gCV_AllowTimerWithoutZone.BoolValue || (gB_Zones && (Shavit_ZoneExists(Zone_Start, track) || gB_KZMap))) { + if(!Shavit_StopTimer(client, false)) + { + return Plugin_Handled; + } + Call_StartForward(gH_Forwards_OnRestart); Call_PushCell(client); Call_PushCell(track); @@ -1988,6 +1993,7 @@ bool LoadStyles() gA_StyleSettings[i].bInaccessible = view_as(kv.GetNum("inaccessible", false)); gA_StyleSettings[i].iEnabled = kv.GetNum("enabled", 1); gA_StyleSettings[i].bKZCheckpoints = view_as(kv.GetNum("kzcheckpoints", 0)); + gA_StyleSettings[i].bForceKeysOnGround = view_as(kv.GetNum("force_groundkeys", 0)); // if this style is disabled, we will force certain settings if(gA_StyleSettings[i].iEnabled <= 0) @@ -2484,7 +2490,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 buttons &= ~IN_USE; } - if(iGroundEntity == -1) + if(iGroundEntity == -1 || gA_StyleSettings[gA_Timers[client].iStyle].bForceKeysOnGround) { if(gA_StyleSettings[gA_Timers[client].iStyle].bBlockW && ((buttons & IN_FORWARD) > 0 || vel[0] > 0.0)) { diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index b590af86..81fd0e41 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -108,6 +108,7 @@ int gI_AdvertisementsCycle = 0; char gS_CurrentMap[192]; int gI_Style[MAXPLAYERS+1]; Function gH_AfterWarningMenu[MAXPLAYERS+1]; +bool gB_ClosedKZCP[MAXPLAYERS+1]; player_cpcache_t gA_CheckpointsCache[MAXPLAYERS+1]; int gI_CheckpointsSettings[MAXPLAYERS+1]; @@ -342,7 +343,7 @@ public void OnPluginStart() // crons CreateTimer(10.0, Timer_Cron, 0, TIMER_REPEAT); - CreateTimer(1.0, Timer_PersistKZCP, 0, TIMER_REPEAT); + CreateTimer(0.5, Timer_PersistKZCP, 0, TIMER_REPEAT); if(gEV_Type != Engine_TF2) { @@ -786,7 +787,10 @@ public Action Timer_PersistKZCP(Handle Timer) { for(int i = 1; i <= MaxClients; i++) { - if(gA_StyleSettings[gI_Style[i]].bKZCheckpoints && GetClientMenu(i) == MenuSource_None) + if(!gB_ClosedKZCP[i] && + gA_StyleSettings[gI_Style[i]].bKZCheckpoints + && GetClientMenu(i) == MenuSource_None && + IsClientInGame(i) && IsPlayerAlive(i)) { OpenKZCPMenu(i); } @@ -1085,6 +1089,8 @@ public void OnClientPutInServer(int client) gB_SaveStates[client] = false; delete gA_SaveFrames[client]; + + gB_ClosedKZCP[client] = false; } public void OnClientDisconnect(int client) @@ -1814,10 +1820,10 @@ void OpenKZCPMenu(int client) if((Shavit_CanPause(client) & CPR_ByConVar) == 0) { FormatEx(sDisplay, 64, "%T", "MiscCheckpointPause", client); - menu.AddItem("pause", sDisplay, (Shavit_GetTimerStatus(client) != Timer_Stopped)? ITEMDRAW_DEFAULT:ITEMDRAW_DISABLED); + menu.AddItem("pause", sDisplay); } - menu.ExitButton = false; + menu.ExitButton = true; menu.Display(client, MENU_TIME_FOREVER); } @@ -1887,6 +1893,14 @@ public int MenuHandler_KZCheckpoints(Menu menu, MenuAction action, int param1, i OpenCheckpointsMenu(param1); } + else if(action == MenuAction_Cancel) + { + if(param2 == MenuCancel_Exit) + { + gB_ClosedKZCP[param1] = true; + } + } + else if(action == MenuAction_End) { delete menu; @@ -1937,9 +1951,11 @@ void OpenNormalCPMenu(int client) FormatEx(sDisplay, 64, "%T", "MiscCheckpointPrevious", client); menu.AddItem("prev", sDisplay); - FormatEx(sDisplay, 64, "%T", "MiscCheckpointNext", client); + FormatEx(sDisplay, 64, "%T\n ", "MiscCheckpointNext", client); menu.AddItem("next", sDisplay); + menu.AddItem("spacer", "", ITEMDRAW_NOTEXT); + FormatEx(sDisplay, 64, "%T", "MiscCheckpointReset", client); menu.AddItem("reset", sDisplay); @@ -1964,88 +1980,92 @@ public int MenuHandler_Checkpoints(Menu menu, MenuAction action, int param1, int { if(action == MenuAction_Select) { + char sInfo[16]; + menu.GetItem(param2, sInfo, 16); + int iMaxCPs = GetMaxCPs(param1); int iCurrent = gA_CheckpointsCache[param1].iCurrentCheckpoint; - switch(param2) + if(StrEqual(sInfo, "save")) { - case 0: + bool bSegmenting = CanSegment(param1); + bool bOverflow = gA_CheckpointsCache[param1].iCheckpoints >= iMaxCPs; + + if(!bSegmenting) { - bool bSegmenting = CanSegment(param1); - bool bOverflow = gA_CheckpointsCache[param1].iCheckpoints >= iMaxCPs; - - if(!bSegmenting) + // fight an exploit + if(bOverflow) { - // fight an exploit - if(bOverflow) - { - return 0; - } - - if(SaveCheckpoint(param1, gA_CheckpointsCache[param1].iCheckpoints + 1)) - { - gA_CheckpointsCache[param1].iCurrentCheckpoint = ++gA_CheckpointsCache[param1].iCheckpoints; - } + return 0; } - - else + + if(SaveCheckpoint(param1, gA_CheckpointsCache[param1].iCheckpoints + 1)) { - SaveCheckpoint(param1, gA_CheckpointsCache[param1].iCheckpoints + 1, bOverflow); - gA_CheckpointsCache[param1].iCurrentCheckpoint = (bOverflow)? iMaxCPs:++gA_CheckpointsCache[param1].iCheckpoints; + gA_CheckpointsCache[param1].iCurrentCheckpoint = ++gA_CheckpointsCache[param1].iCheckpoints; } } - - case 1: + + else { - TeleportToCheckpoint(param1, iCurrent, true); + SaveCheckpoint(param1, gA_CheckpointsCache[param1].iCheckpoints + 1, bOverflow); + gA_CheckpointsCache[param1].iCurrentCheckpoint = (bOverflow)? iMaxCPs:++gA_CheckpointsCache[param1].iCheckpoints; } + } - case 2: + else if(StrEqual(sInfo, "tele")) + { + TeleportToCheckpoint(param1, iCurrent, true); + } + + else if(StrEqual(sInfo, "prev")) + { + if(iCurrent > 1) { - if(iCurrent > 1) - { - gA_CheckpointsCache[param1].iCurrentCheckpoint--; - } + gA_CheckpointsCache[param1].iCurrentCheckpoint--; } + } - case 3: + else if(StrEqual(sInfo, "next")) + { + cp_cache_t cpcache; + + if(iCurrent++ < iMaxCPs && GetCheckpoint(param1, iCurrent, cpcache)) { - cp_cache_t cpcache; - - if(iCurrent++ < iMaxCPs && GetCheckpoint(param1, iCurrent, cpcache)) - { - gA_CheckpointsCache[param1].iCurrentCheckpoint++; - } + gA_CheckpointsCache[param1].iCurrentCheckpoint++; } + } - case 4: - { - ResetCheckpoints(param1); - } + else if(StrEqual(sInfo, "reset")) + { + ConfirmCheckpointsDeleteMenu(param1); - default: - { - char sInfo[8]; - menu.GetItem(param2, sInfo, 8); - - char sCookie[8]; - gI_CheckpointsSettings[param1] ^= StringToInt(sInfo); - IntToString(gI_CheckpointsSettings[param1], sCookie, 16); + return 0; + } - SetClientCookie(param1, gH_CheckpointsCookie, sCookie); - } + else if(!StrEqual(sInfo, "spacer")) + { + char sCookie[8]; + gI_CheckpointsSettings[param1] ^= StringToInt(sInfo); + IntToString(gI_CheckpointsSettings[param1], sCookie, 16); + + SetClientCookie(param1, gH_CheckpointsCookie, sCookie); } OpenCheckpointsMenu(param1); } - else if(action == MenuAction_DisplayItem && param2 >= 5) + else if(action == MenuAction_DisplayItem) { char sInfo[16]; char sDisplay[64]; int style = 0; menu.GetItem(param2, sInfo, 16, style, sDisplay, 64); + if(StringToInt(sInfo) == 0) + { + return 0; + } + Format(sDisplay, 64, "[%s] %s", ((gI_CheckpointsSettings[param1] & StringToInt(sInfo)) > 0)? "x":" ", sDisplay); return RedrawMenuItem(sDisplay); @@ -2059,6 +2079,45 @@ public int MenuHandler_Checkpoints(Menu menu, MenuAction action, int param1, int return 0; } +void ConfirmCheckpointsDeleteMenu(int client) +{ + Menu hMenu = new Menu(MenuHandler_CheckpointsDelete); + hMenu.SetTitle("%T\n ", "ClearCPWarning", client); + + char sDisplay[64]; + FormatEx(sDisplay, 64, "%T", "ClearCPYes", client); + hMenu.AddItem("yes", sDisplay); + + FormatEx(sDisplay, 64, "%T", "ClearCPNo", client); + hMenu.AddItem("no", sDisplay); + + hMenu.ExitButton = true; + hMenu.Display(client, 60); +} + +public int MenuHandler_CheckpointsDelete(Menu menu, MenuAction action, int param1, int param2) +{ + if(action == MenuAction_Select) + { + char sInfo[8]; + menu.GetItem(param2, sInfo, 8); + + if(StrEqual(sInfo, "yes")) + { + ResetCheckpoints(param1); + } + + OpenCheckpointsMenu(param1); + } + + else if(action == MenuAction_End) + { + delete menu; + } + + return 0; +} + bool SaveCheckpoint(int client, int index, bool overflow = false) { // ??? @@ -2093,12 +2152,21 @@ bool SaveCheckpoint(int client, int index, bool overflow = false) return false; } - if(gA_StyleSettings[gI_Style[client]].bKZCheckpoints && - ((iFlags & FL_ONGROUND) == 0 || client != target)) + if(gA_StyleSettings[gI_Style[client]].bKZCheckpoints) { - Shavit_PrintToChat(client, "%T", "CommandSaveCPKZInvalid", client); + if((iFlags & FL_ONGROUND) == 0 || client != target) + { + Shavit_PrintToChat(client, "%T", "CommandSaveCPKZInvalid", client); - return false; + return false; + } + + else if(Shavit_InsideZone(client, Zone_Start, -1)) + { + Shavit_PrintToChat(client, "%T", "CommandSaveCPKZZone", client); + + return false; + } } Action result = Plugin_Continue; @@ -2483,7 +2551,7 @@ void OpenStopWarningMenu(int client, StopTimerCallback after) gH_AfterWarningMenu[client] = after; Menu hMenu = new Menu(MenuHandler_StopWarning); - hMenu.SetTitle("%T\n", "StopTimerWarning", client); + hMenu.SetTitle("%T\n ", "StopTimerWarning", client); char sDisplay[64]; FormatEx(sDisplay, 64, "%T", "StopTimerYes", client); @@ -2774,7 +2842,10 @@ public void Shavit_OnWorldRecord(int client, int style, float time, int jumps, i public void Shavit_OnRestart(int client, int track) { - if(gA_StyleSettings[gI_Style[client]].bKZCheckpoints && GetClientMenu(client, null) == MenuSource_None) + if(!gB_ClosedKZCP[client] && + gA_StyleSettings[gI_Style[client]].bKZCheckpoints && + GetClientMenu(client, null) == MenuSource_None && + IsPlayerAlive(client) && GetClientTeam(client) >= 2) { OpenKZCPMenu(client); } @@ -2898,7 +2969,10 @@ public void Player_Spawn(Event event, const char[] name, bool dontBroadcast) UpdateClanTag(client); // refreshes kz cp menu if there is nothing open - if(gA_StyleSettings[gI_Style[client]].bKZCheckpoints && GetClientMenu(client, null) == MenuSource_None) + if(!gB_ClosedKZCP[client] && + gA_StyleSettings[gI_Style[client]].bKZCheckpoints && + GetClientMenu(client, null) == MenuSource_None && + IsPlayerAlive(client) && GetClientTeam(client) >= 2) { OpenKZCPMenu(client); } diff --git a/addons/sourcemod/scripting/shavit-wr.sp b/addons/sourcemod/scripting/shavit-wr.sp index 2fdc0fae..967b15da 100644 --- a/addons/sourcemod/scripting/shavit-wr.sp +++ b/addons/sourcemod/scripting/shavit-wr.sp @@ -1570,8 +1570,9 @@ public Action Command_RecentRecords(int client, int args) FormatEx(sQuery, 512, "SELECT a.id, a.map, u.name, a.time, a.style, a.track FROM %splayertimes a " ... - "JOIN (SELECT MIN(time) time, map, style, track FROM %splayertimes GROUP by map, style, track ORDER BY date DESC) b " ... + "JOIN (SELECT MIN(time) time, map, style, track FROM %splayertimes GROUP by map, style, track) b " ... "JOIN %susers u ON a.time = b.time AND a.auth = u.auth AND a.map = b.map AND a.style = b.style AND a.track = b.track " ... + "ORDER BY a.date DESC " ... "LIMIT 100;", gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix); gH_SQL.Query(SQL_RR_Callback, sQuery, GetClientSerial(client), DBPrio_Low); @@ -1743,7 +1744,7 @@ public void SQL_SubMenu_Callback(Database db, DBResultSet results, const char[] int jumps = results.FetchInt(2); float perfs = results.FetchFloat(9); - if(gA_StyleSettings[style].bAutobhop && perfs > 0.0) + if(gA_StyleSettings[style].bAutobhop) { FormatEx(sDisplay, 128, "%T: %d", "WRJumps", client, jumps); } diff --git a/addons/sourcemod/translations/shavit-misc.phrases.txt b/addons/sourcemod/translations/shavit-misc.phrases.txt index c869fbd5..f85eb5a5 100644 --- a/addons/sourcemod/translations/shavit-misc.phrases.txt +++ b/addons/sourcemod/translations/shavit-misc.phrases.txt @@ -13,7 +13,11 @@ } "CommandSaveCPKZInvalid" { - "en" "You cannot perform this when airborne or while watching another player." + "en" "You cannot perform this action when airborne or while watching another player." + } + "CommandSaveCPKZZone" + { + "en" "You cannot perform this action while in the start zone." } "CommandTeleCPInvalid" { @@ -118,6 +122,18 @@ { "en" "No, keep my timer running." } + "ClearCPWarning" + { + "en" "Are you sure you want to clear your checkpoints?" + } + "ClearCPYes" + { + "en" "Yes, and I know this action cannot be reversed." + } + "ClearCPNo" + { + "en" "No." + } "TeleportMenuTitle" { "en" "Teleport to:"