From 17ef0f7690eb69e5eff0e8c6186ee01e1d7f0a86 Mon Sep 17 00:00:00 2001 From: pdtttt Date: Tue, 20 Jan 2026 17:01:17 -0800 Subject: [PATCH 1/4] Initial Rebase Snapshot of dev as a single commit on top of origin/dev (779a9d9). --- .github/workflows/nightly.yml | 8 +- .gitignore | 4 + README.md | 66 +- SharpTimer-main.sln | 22 +- SharpTimerAPI-Example/SharpTimer-Example.cs | 119 + .../SharpTimer-Example.csproj | 20 + SharpTimerAPI/Events/FinishMapEvent.cs | 5 + .../Events/ISharpTimerPlayerEvent.cs | 9 + SharpTimerAPI/Events/StartTimerEvent.cs | 5 + SharpTimerAPI/ISharpTimerDatabase.cs | 20 + SharpTimerAPI/ISharpTimerEventSender.cs | 12 + SharpTimerAPI/ISharpTimerManager.cs | 15 + SharpTimerAPI/SharpTimerAPI.csproj | 18 + cfg/SharpTimer/MapData/MapExecs/bhop_.cfg | 15 +- .../MapData/MapExecs/de_example.cfg | 4 + cfg/SharpTimer/MapData/MapExecs/kz_.cfg | 134 - .../MapData/MapExecs/kz_example.cfg | 4 - cfg/SharpTimer/MapData/MapExecs/surf_.cfg | 11 +- cfg/SharpTimer/MapData/MapExecs/vnl_.cfg | 16 +- cfg/SharpTimer/MapData/local_data/kz_.json | 2855 ----------------- cfg/SharpTimer/MapData/local_data/surf_.json | 2 +- cfg/SharpTimer/config.cfg | 61 +- cfg/SharpTimer/custom_exec.cfg | 2 - lang/en.json | 15 +- lang/fi.json | 84 +- lang/fr.json | 13 +- lang/ko.json | 11 +- lang/nb.json | 16 +- lang/pl.json | 15 +- lang/sk.json | 189 +- lang/sv.json | 84 +- lang/tr.json | 11 +- lang/zh-Hans.json | 11 +- remote_data/kz_.json | 2855 ----------------- src/API/SharpTimerAPI.cs | 80 + src/API/TagsApi.dll | Bin 0 -> 8704 bytes src/Commands/ChatCommands.cs | 22 +- src/Commands/ConfigConvars.cs | 50 +- src/DB/DatabaseUtils.cs | 18 +- src/DB/Migration.cs | 2 +- src/Extensions/CUserCmd.cs | 11 +- src/Extensions/FixVectorLeaks.cs | 280 ++ src/Extensions/ForceFullUpdate.cs | 12 +- src/Features/Anticheat.cs | 19 +- src/Features/DiscordWebhook.cs | 26 +- src/Features/FakeZoneTool.cs | 135 +- src/Features/GlobalAPI.cs | 166 +- src/Features/JumpStats.cs | 505 --- src/Features/Points.cs | 4 +- .../Damage.cs => Features/RemoveDamage.cs} | 59 +- src/Features/ReplayUtils.cs | 32 +- src/Features/Styles.cs | 4 +- src/Player/PlayerChecks.cs | 108 +- src/Player/PlayerEvents.cs | 191 +- src/Player/PlayerScoreboard.cs | 2 +- src/Player/PlayerTimers.cs | 2 +- src/Plugin/Classes.cs | 91 +- src/Plugin/Globals.cs | 96 +- src/Plugin/Plugin.cs | 750 +++++ src/Plugin/Utils.cs | 1 - src/SharpTimer.cs | 8 +- src/SharpTimer.csproj | 30 + src/{Hooks => Triggers}/TriggerHooks.cs | 106 +- src/Triggers/TriggerUtils.cs | 170 +- 64 files changed, 2269 insertions(+), 7442 deletions(-) create mode 100644 SharpTimerAPI-Example/SharpTimer-Example.cs create mode 100644 SharpTimerAPI-Example/SharpTimer-Example.csproj create mode 100644 SharpTimerAPI/Events/FinishMapEvent.cs create mode 100644 SharpTimerAPI/Events/ISharpTimerPlayerEvent.cs create mode 100644 SharpTimerAPI/Events/StartTimerEvent.cs create mode 100644 SharpTimerAPI/ISharpTimerDatabase.cs create mode 100644 SharpTimerAPI/ISharpTimerEventSender.cs create mode 100644 SharpTimerAPI/ISharpTimerManager.cs create mode 100644 SharpTimerAPI/SharpTimerAPI.csproj create mode 100644 cfg/SharpTimer/MapData/MapExecs/de_example.cfg delete mode 100644 cfg/SharpTimer/MapData/MapExecs/kz_.cfg delete mode 100644 cfg/SharpTimer/MapData/MapExecs/kz_example.cfg delete mode 100644 cfg/SharpTimer/MapData/local_data/kz_.json delete mode 100644 remote_data/kz_.json create mode 100644 src/API/SharpTimerAPI.cs create mode 100644 src/API/TagsApi.dll create mode 100644 src/Extensions/FixVectorLeaks.cs delete mode 100644 src/Features/JumpStats.cs rename src/{Hooks/Damage.cs => Features/RemoveDamage.cs} (58%) create mode 100644 src/Plugin/Plugin.cs create mode 100644 src/SharpTimer.csproj rename src/{Hooks => Triggers}/TriggerHooks.cs (74%) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 56dcf408..711f2c4c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,4 +1,4 @@ -name: Build and Publish C# Project +name: Build and Publish C# Project on: push: @@ -36,13 +36,13 @@ jobs: ${{ runner.os }}-dotnet- - name: Restore dependencies - run: dotnet restore SharpTimer.csproj + run: dotnet restore SharpTimer-main.sln - name: Build the project - run: dotnet build --configuration Release SharpTimer.csproj + run: dotnet build --configuration Release SharpTimer-main.sln - name: Publish the project - run: dotnet publish --configuration Release --output ./publish SharpTimer.csproj + run: dotnet publish --configuration Release --output ./publish src/SharpTimer.csproj - name: Move files run: | diff --git a/.gitignore b/.gitignore index 18b94464..c2859733 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ CounterStrikeSharp.API.dll .vscode/ .vs/ /.idea +/src/SharpTimer.csproj.user +/src/Properties/PublishProfiles/FolderProfile.pubxml +/src/Properties/PublishProfiles/FolderProfile.pubxml.user +/Build \ No newline at end of file diff --git a/README.md b/README.md index 9ac8fdd5..7435b60f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,10 @@ - -
- -![GitHub Repo stars](https://img.shields.io/github/stars/Letaryat/poor-sharptimer?style=for-the-badge) -![GitHub all releases](https://img.shields.io/github/downloads/Letaryat/poor-sharptimer/total?style=for-the-badge) -
+# SharpTimer +SharpTimer is a "simple" Surf/Bhop/MG/Deathrun/etc. CS2 Timer plugin using CounterStrikeSharp
> [!NOTE] -> The original creator of SharpTimer is [Dea](https://github.com/girlglock), who discontinued support for the project after version 0.2.6. This fork is now maintaned by the community, mainly [rcnoob](https://github.com/rcnoob). - - +> The original creator of SharpTimer is dea_bb, who discontinued support for the project after version 0.2.6. This fork is now maintaned by the community, mainly [rcnoob](https://github.com/rcnoob). -## **Join Our Discord For Support** - - +[**Discord**](https://discord.com/invite/SmQXeyMcny)
@@ -22,11 +14,6 @@ Badge

- -# SharpTimer -SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using CounterStrikeSharp
- - ## Features
Timer, speedometer and key input with color customization @@ -51,10 +38,6 @@ SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using Co Discord Webhook
-
- JumpStats -
-
Map CFGs
@@ -82,15 +65,13 @@ SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using Co
- KZ Checkpoint system (disabled by default, check config) + Checkpoint system (disabled by default, check config)


-

( back to top )

- ## Dependencies [**MetaMod**](https://cs2.poggu.me/metamod/installation/) @@ -105,15 +86,17 @@ SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using Co [**Web panel** *(optional but recommended)*](https://github.com/Letaryat/sharptimer-web-panel) +[**SharpTimer-WallLists** *(optional but recommended)*](https://github.com/M-archand/SharpTimer-WallLists) + [**CS2-TeleportAnglesFix** *(optional but recommended)*](https://github.com/M-archand/CS2-TeleportAnglesFix) [**STFixes** *(optional but recommended)*](https://github.com/rcnoob/STFixes) -[**Flashing HUD Fix** *(optional but recommended)*](https://github.com/M-archand/CS2FlashingHtmlHudFix) +[**CS#-Fixes** *(optional but recommended)*](https://github.com/CharlesBarone/CSSharp-Fixes) -[**SharpTimer-WallLists** *(optional)*](https://github.com/SharpTimer/WallLists) +[**Flashing HUD Fix** *(optional but recommended)*](https://github.com/deabb/CS2FlashingHtmlHudFix) -[**SharpTimer-Trails** *(optional)*](https://github.com/SharpTimer/Trails) +[**Flashing HUD Fix (alt)** *(optional but recommended)*](https://gitlab.com/dea_bb/FlashingXMLHintFix) ## Install @@ -142,7 +125,7 @@ SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using Co - [x] Zones - [x] Hook common triggers by default - [x] Manual Zones - - [x] Hook Bonus Zones Triggers (KZ & Surf) + - [x] Hook Bonus Zones Triggers (Surf) - [x] Player PBs - [x] Save to Json - [x] Save to MySQL @@ -161,30 +144,19 @@ SharpTimer is a "simple" Surf/KZ/Bhop/MG/Deathrun/etc. CS2 Timer plugin using Co - [x] Player Server Stats - [x] Player Map Stats - [x] Replays -- [x] Jumpstats - - [x] Distance - - [x] Pre - - [x] Max - - [x] Height - - [x] Width - - [ ] Sync - - [ ] Jump Types - - [x] Long Jump - - [x] BunnyHop - - [x] MultiBunnyHop - - [x] Jump Bug - - [ ] Edge Bug - - [ ] Ladder Jump -- [X] Silly Stuff +- [ ] Silly Stuff - [x] Color customization - [x] Special Tester Gifs - [x] Custom Player Gifs - [x] Dioscord Webhook - - [X] Strafe Sync Bar on HUD + - [ ] Strafe Sync Bar on HUD + ## Authors: -[Deana](https://twitter.com/girlglock) +original creator: [DEA_BB](https://twitter.com/dea_bb) + +sharptimer team: [Letaryat](https://github.com/Letaryat) [rcnoob](https://github.com/rcnoob) - -

( back to top )

+[exkludera](https://github.com/exkludera) +[Marchand](https://github.com/M-archand) \ No newline at end of file diff --git a/SharpTimer-main.sln b/SharpTimer-main.sln index 8379e308..667b6ef9 100644 --- a/SharpTimer-main.sln +++ b/SharpTimer-main.sln @@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpTimer", "SharpTimer.csproj", "{8E786DDC-5BDE-462A-AC36-BB39D6D1560D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpTimerAPI", "SharpTimerAPI\SharpTimerAPI.csproj", "{A950E141-B4D1-4338-9238-A1592AA42E1A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpTimer", "src\SharpTimer.csproj", "{09BD8C5E-A95F-4C42-9090-FD35ECEAF518}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpTimer-Example", "SharpTimerAPI-Example\SharpTimer-Example.csproj", "{FF468BD2-D94C-467F-A6FD-DE4CB4C71D69}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,10 +15,18 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8E786DDC-5BDE-462A-AC36-BB39D6D1560D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8E786DDC-5BDE-462A-AC36-BB39D6D1560D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8E786DDC-5BDE-462A-AC36-BB39D6D1560D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8E786DDC-5BDE-462A-AC36-BB39D6D1560D}.Release|Any CPU.Build.0 = Release|Any CPU + {A950E141-B4D1-4338-9238-A1592AA42E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A950E141-B4D1-4338-9238-A1592AA42E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A950E141-B4D1-4338-9238-A1592AA42E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A950E141-B4D1-4338-9238-A1592AA42E1A}.Release|Any CPU.Build.0 = Release|Any CPU + {09BD8C5E-A95F-4C42-9090-FD35ECEAF518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09BD8C5E-A95F-4C42-9090-FD35ECEAF518}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09BD8C5E-A95F-4C42-9090-FD35ECEAF518}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09BD8C5E-A95F-4C42-9090-FD35ECEAF518}.Release|Any CPU.Build.0 = Release|Any CPU + {FF468BD2-D94C-467F-A6FD-DE4CB4C71D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF468BD2-D94C-467F-A6FD-DE4CB4C71D69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF468BD2-D94C-467F-A6FD-DE4CB4C71D69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF468BD2-D94C-467F-A6FD-DE4CB4C71D69}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SharpTimerAPI-Example/SharpTimer-Example.cs b/SharpTimerAPI-Example/SharpTimer-Example.cs new file mode 100644 index 00000000..452106a1 --- /dev/null +++ b/SharpTimerAPI-Example/SharpTimer-Example.cs @@ -0,0 +1,119 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Utils; +using Microsoft.Extensions.Logging; +using SharpTimerAPI; + +public class SharpTimer_Example : BasePlugin +{ + public override string ModuleName => "SharpTimer API Example"; + public override string ModuleVersion => ""; + public override string ModuleAuthor => ""; + + public ISharpTimerEventSender? eventSender { get; set; } + public ISharpTimerManager? timerManager { get; set; } + public ISharpTimerDatabase? databaseManager { get; set; } + + public override void Load(bool hotReload) + { + AddCommand("css_SharpTimerAPI_TimerCheck", "", Command_API_TimerCheck); + AddCommand("css_SharpTimerAPI_ToggleTimer", "", Command_API_ToggleTimer); + AddCommand("css_SharpTimerAPI_GetSR", "", Command_API_GetSR); + + RegisterEventHandler(EventPlayerDeath); + } + + public override void Unload(bool hotReload) + { + RemoveCommand("css_SharpTimerAPI_TimerCheck", Command_API_TimerCheck); + RemoveCommand("css_SharpTimerAPI_ToggleTimer", Command_API_ToggleTimer); + RemoveCommand("css_SharpTimerAPI_GetSR", Command_API_GetSR); + + DeregisterEventHandler(EventPlayerDeath); + } + + public override void OnAllPluginsLoaded(bool hotReload) + { + eventSender = ISharpTimerEventSender.Capability.Get(); + timerManager = ISharpTimerManager.Capability.Get(); + databaseManager = ISharpTimerDatabase.Capability.Get(); + + if (eventSender == null || timerManager == null || databaseManager == null) + { + Logger.LogError("Error: Could not load SharpTimerAPI! Ensure everything is installed properly."); + return; + } + } + + public void Command_API_TimerCheck(CCSPlayerController? player, CommandInfo command) + { + if (player == null) + return; + + if (timerManager == null) + { + Logger.LogError("Error: ISharpTimerManager not loaded! Ensure everything is installed properly."); + return; + } + + command.ReplyToCommand($" {ChatColors.LightPurple}[SharpTimer-Example] {ChatColors.Grey}Timer: " + (timerManager.IsTimerOn(player) ? $"{ChatColors.Green}ON" : $"{ChatColors.Red}OFF")); + } + + public void Command_API_ToggleTimer(CCSPlayerController? player, CommandInfo command) + { + if (player == null) + return; + + if (timerManager == null) + { + Logger.LogError("Error: ISharpTimerManager not loaded! Ensure everything is installed properly."); + return; + } + + timerManager.ToggleTimer(player); + + command.ReplyToCommand($" {ChatColors.LightPurple}[SharpTimer-Example] {ChatColors.Grey}Timer has been toggeled: " + (timerManager.IsTimerOn(player) ? $"{ChatColors.Green}ON" : $"{ChatColors.Red}OFF")); + } + + public void Command_API_GetSR(CCSPlayerController? player, CommandInfo command) + { + if (player == null) + return; + + if (databaseManager == null) + { + Logger.LogError("Error: ISharpTimerDatabase not loaded! Ensure everything is installed properly."); + return; + } + + var record = databaseManager.GetSortedRecordsFromDatabase(1, 0, Server.MapName, 0).Result.FirstOrDefault().Value; + + string formattedTime; + + TimeSpan timeSpan = TimeSpan.FromSeconds(record.TimerTicks / 64.0); + string milliseconds = $"{record.TimerTicks % 64 * (1000.0 / 64.0):000}"; + int totalMinutes = (int)timeSpan.TotalMinutes; + + if (totalMinutes >= 60) + formattedTime = $"{totalMinutes / 60:D1}:{totalMinutes % 60:D2}:{timeSpan.Seconds:D2}.{milliseconds}"; + else + formattedTime = $"{totalMinutes:D1}:{timeSpan.Seconds:D2}.{milliseconds}"; + + command.ReplyToCommand($" {ChatColors.LightPurple}[SharpTimer-Example] {ChatColors.Grey}player: {ChatColors.White}{record.PlayerName} {ChatColors.Grey}has the SR on {ChatColors.White}{Server.MapName} {ChatColors.Grey}with time: {ChatColors.White}{formattedTime}"); + } + + + public HookResult EventPlayerDeath(EventPlayerDeath @event, GameEventInfo gameEventInfo) + { + var player = @event.Userid; + if (player == null || player.IsBot) + return HookResult.Continue; + + timerManager?.RestartTimer(player); + + player.PrintToChat($" {ChatColors.LightPurple}[SharpTimer-Example] {ChatColors.Red}Timer has been reset, because you died :("); + + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/SharpTimerAPI-Example/SharpTimer-Example.csproj b/SharpTimerAPI-Example/SharpTimer-Example.csproj new file mode 100644 index 00000000..a139137a --- /dev/null +++ b/SharpTimerAPI-Example/SharpTimer-Example.csproj @@ -0,0 +1,20 @@ + + + net8.0 + enable + enable + false + $(ProjectDir)..\Build\plugins\SharpTimer-Example\ + false + + + + + + + + + + + + diff --git a/SharpTimerAPI/Events/FinishMapEvent.cs b/SharpTimerAPI/Events/FinishMapEvent.cs new file mode 100644 index 00000000..74a6282d --- /dev/null +++ b/SharpTimerAPI/Events/FinishMapEvent.cs @@ -0,0 +1,5 @@ +using CounterStrikeSharp.API.Core; + +namespace SharpTimerAPI.Events; + +public record FinishMapEvent(CCSPlayerController? Player, bool IsSr, bool IsPb, int Tier) : ISharpTimerPlayerEvent; \ No newline at end of file diff --git a/SharpTimerAPI/Events/ISharpTimerPlayerEvent.cs b/SharpTimerAPI/Events/ISharpTimerPlayerEvent.cs new file mode 100644 index 00000000..2fea410e --- /dev/null +++ b/SharpTimerAPI/Events/ISharpTimerPlayerEvent.cs @@ -0,0 +1,9 @@ +using CounterStrikeSharp.API.Core; + +namespace SharpTimerAPI.Events; +using CounterStrikeSharp; + +public interface ISharpTimerPlayerEvent +{ + public CCSPlayerController? Player { get;} +} \ No newline at end of file diff --git a/SharpTimerAPI/Events/StartTimerEvent.cs b/SharpTimerAPI/Events/StartTimerEvent.cs new file mode 100644 index 00000000..4572c73f --- /dev/null +++ b/SharpTimerAPI/Events/StartTimerEvent.cs @@ -0,0 +1,5 @@ +using CounterStrikeSharp.API.Core; + +namespace SharpTimerAPI.Events; + +public record StartTimerEvent(CCSPlayerController? Player) : ISharpTimerPlayerEvent; \ No newline at end of file diff --git a/SharpTimerAPI/ISharpTimerDatabase.cs b/SharpTimerAPI/ISharpTimerDatabase.cs new file mode 100644 index 00000000..148f90f7 --- /dev/null +++ b/SharpTimerAPI/ISharpTimerDatabase.cs @@ -0,0 +1,20 @@ +using CounterStrikeSharp.API.Core.Capabilities; + +namespace SharpTimerAPI; + +public interface ISharpTimerDatabase +{ + public static readonly PluginCapability Capability = new("sharptimer:database"); + + public class PlayerRecord + { + public int RecordID { get; set; } + public string? PlayerName { get; set; } + public string? SteamID { get; set; } + public string? MapName { get; set; } + public int TimerTicks { get; set; } + public bool Replay { get; set; } + } + public Task> GetSortedRecordsFromDatabase(int limit = 0, int bonusX = 0, string mapName = "", int style = 0); + public Task> GetAllSortedRecordsFromDatabase(int limit = 0, int bonusX = 0, int style = 0); +} \ No newline at end of file diff --git a/SharpTimerAPI/ISharpTimerEventSender.cs b/SharpTimerAPI/ISharpTimerEventSender.cs new file mode 100644 index 00000000..f0911863 --- /dev/null +++ b/SharpTimerAPI/ISharpTimerEventSender.cs @@ -0,0 +1,12 @@ +using CounterStrikeSharp.API.Core.Capabilities; +using SharpTimerAPI.Events; + +namespace SharpTimerAPI; + +public interface ISharpTimerEventSender +{ + public static readonly PluginCapability Capability = new("sharptimer:event_sender"); + + public event EventHandler STEventSender; + public void TriggerEvent(ISharpTimerPlayerEvent @event); +} \ No newline at end of file diff --git a/SharpTimerAPI/ISharpTimerManager.cs b/SharpTimerAPI/ISharpTimerManager.cs new file mode 100644 index 00000000..24f40ce6 --- /dev/null +++ b/SharpTimerAPI/ISharpTimerManager.cs @@ -0,0 +1,15 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; + +namespace SharpTimerAPI; + +public interface ISharpTimerManager +{ + public static readonly PluginCapability Capability = new("sharptimer:manager"); + + public void RestartTimer(CCSPlayerController player); + public bool IsTimerOn(CCSPlayerController player); + public void ToggleTimer(CCSPlayerController player); + public void BlockTimerCmd(CCSPlayerController player, bool block); + public void BlockRespawnCmd(CCSPlayerController player, bool block); +} \ No newline at end of file diff --git a/SharpTimerAPI/SharpTimerAPI.csproj b/SharpTimerAPI/SharpTimerAPI.csproj new file mode 100644 index 00000000..298f8d3c --- /dev/null +++ b/SharpTimerAPI/SharpTimerAPI.csproj @@ -0,0 +1,18 @@ + + + net8.0 + enable + enable + false + $(ProjectDir)..\Build\shared\SharpTimerAPI\ + false + + + + + + + + + + diff --git a/cfg/SharpTimer/MapData/MapExecs/bhop_.cfg b/cfg/SharpTimer/MapData/MapExecs/bhop_.cfg index add21e10..4726d4e7 100644 --- a/cfg/SharpTimer/MapData/MapExecs/bhop_.cfg +++ b/cfg/SharpTimer/MapData/MapExecs/bhop_.cfg @@ -37,7 +37,6 @@ sv_accelerate 5.000000 sv_maxvelocity 99999.000000 sv_air_max_wishspeed 30.000000 sv_gravity 800.000000 -sv_standable_normal 0.700000 sv_wateraccelerate 10.000000 //Team & Map Settings @@ -58,7 +57,7 @@ mp_friendlyfire false mp_limitteams 0 mp_randomspawn 0 mp_randomspawn_los false -mp_solid_teammates 2 +mp_solid_teammates 0 mp_spectators_max 64 mp_suicide_penalty true mp_team_timeout_max 1 @@ -77,7 +76,6 @@ mp_teamcashawards false mp_playercashawards false mp_weapons_allow_map_placed true mp_weapons_allow_zeus 2 -mp_weapons_glow_on_ground false sv_infinite_ammo 0 mp_ct_default_secondary weapon_hkp2000 mp_t_default_secondary weapon_glock @@ -102,11 +100,12 @@ sv_ignoregrenaderadio false sv_talk_enemy_dead true sv_talk_enemy_living true + //Misc -CS_WarnFriendlyDamageInterval 3 -sv_gameinstructor_enable false mp_disconnect_kills_players true -Bot Settings + + +// Bot Settings bot_controllable true bot_quota_mode fill bot_quota 0 @@ -130,6 +129,4 @@ sharptimer_rank_enabled true sharptimer_checkpoints_enabled true sharptimer_remove_checkpoints_restrictions true -sharptimer_checkpoints_only_when_timer_stopped true - -sharptimer_jumpstats_enabled false \ No newline at end of file +sharptimer_checkpoints_only_when_timer_stopped true \ No newline at end of file diff --git a/cfg/SharpTimer/MapData/MapExecs/de_example.cfg b/cfg/SharpTimer/MapData/MapExecs/de_example.cfg new file mode 100644 index 00000000..ad385b0c --- /dev/null +++ b/cfg/SharpTimer/MapData/MapExecs/de_example.cfg @@ -0,0 +1,4 @@ +//These Commands will exec whenever the server Loads the map "de_example" + +mp_timelimit 60 +sv_airaccelerate 100 \ No newline at end of file diff --git a/cfg/SharpTimer/MapData/MapExecs/kz_.cfg b/cfg/SharpTimer/MapData/MapExecs/kz_.cfg deleted file mode 100644 index f409f0eb..00000000 --- a/cfg/SharpTimer/MapData/MapExecs/kz_.cfg +++ /dev/null @@ -1,134 +0,0 @@ -// Round Settings -mp_roundtime 30 -mp_roundtime_defuse 30 -mp_roundtime_hostage 30 -mp_timelimit 30 -mp_maxrounds 0 -mp_freezetime 0 -mp_halftime false -mp_overtime_enable false -mp_round_restart_delay 0 -mp_team_intro_time 0 -mp_team_timeout_max 0 -mp_technical_timeout_per_team 0 -sv_warmup_to_freezetime_delay 0 -mp_buytime 0 -mp_ignore_round_win_conditions true -mp_respawn_immunitytime -1 -mp_respawn_on_death_ct true -mp_respawn_on_death_t true -mp_warmuptime 0 -mp_warmup_end - -sv_airaccelerate 100.000000 -sv_enablebunnyhopping false -sv_autobunnyhopping false -sv_falldamage_scale 0.000000 -sv_staminajumpcost 0.000000 -sv_staminalandcost 0.000000 -sv_timebetweenducks 0.000000 -sv_staminarecoveryrate 60.000000 -sv_staminamax 0.000000 -sv_ladder_scale_speed 1.000000 -sv_jump_impulse 301.993378 -sv_friction 5.000000 -sv_accelerate_use_weapon_speed false -sv_accelerate 6.500000 -sv_maxvelocity 2000.000000 -sv_air_max_wishspeed 30.000000 -sv_gravity 800.000000 -sv_standable_normal 0.700000 -sv_wateraccelerate 10.000000 - -ff_damage_reduction_bullets 0.000000 -ff_damage_reduction_grenade 0.000000 -ff_damage_reduction_grenade_self 0.000000 -ff_damage_reduction_other 0.000000 -mp_damage_headshot_only true -mp_damage_scale_ct_head 1.000000 -mp_damage_scale_t_head 1.000000 -mp_damage_scale_ct_body 1.000000 -mp_damage_scale_t_body 1.000000 -mp_autokick false -mp_autoteambalance true -mp_forcecamera 0 -mp_force_pick_time 15.000000 -mp_friendlyfire false -mp_limitteams 0 -mp_randomspawn 0 -mp_randomspawn_los false -mp_solid_teammates 2 -mp_spectators_max 64 -mp_suicide_penalty true -mp_team_timeout_max 1 -mp_teamname_1 "SHARPTIMER" -mp_teamname_2 "X.COM/DEAFPS_" -sv_falldamage_scale 0.000000 -sv_show_teammate_death_notification false -sv_disable_radar 1 - -mp_afterroundmoney 0 -mp_free_armor 1 -mp_maxmoney 0 -mp_startmoney 1000 -mp_teamcashawards false -mp_playercashawards false -mp_weapons_allow_map_placed true -mp_weapons_allow_zeus 2 -mp_weapons_glow_on_ground false -sv_infinite_ammo 0 -mp_ct_default_secondary weapon_hkp2000 -mp_t_default_secondary weapon_glock -mp_drop_knife_enable true -mp_weapons_allow_map_placed false -mp_death_drop_gun 0 - -sv_workshop_allow_other_maps true -mp_endmatch_votenextmap false -mp_endmatch_votenextmap_keepcurrent true -mp_match_end_changelevel false -mp_match_end_restart false -mp_match_restart_delay 10 -sv_allow_votes true - -sv_auto_full_alltalk_during_warmup_half_end false -sv_deadtalk true -sv_full_alltalk false -sv_ignoregrenaderadio false -sv_talk_enemy_dead true -sv_talk_enemy_living true - -CS_WarnFriendlyDamageInterval 99999 -sv_gameinstructor_enable false -mp_disconnect_kills_players true - -bot_controllable false -bot_quota_mode fill -bot_quota 1 - -// SharpTimer Settings -sharptimer_remove_legs true -sharptimer_remove_collision true -sharptimer_remove_damage true -sharptimer_kill_pointservercommand_entities true - -sharptimer_use2Dspeed_enabled false -sharptimer_disable_telehop true -sharptimer_max_start_speed_enabled true -sharptimer_max_start_speed 320 -sharptimer_force_knife_speed true -sharptimer_forced_player_speed 260 - -sharptimer_respawn_enabled true -sharptimer_top_enabled true -sharptimer_rank_enabled true - -sharptimer_checkpoints_enabled true -sharptimer_remove_checkpoints_restrictions false -sharptimer_checkpoints_only_when_timer_stopped false - -sharptimer_jumpstats_enabled true -sharptimer_jumpstats_min_distance 175.0 -sharptimer_jumpstats_max_vert 32.0 -sharptimer_jumpstats_movement_unlocker_cap true -sharptimer_jumpstats_movement_unlocker_cap_value 250.0 \ No newline at end of file diff --git a/cfg/SharpTimer/MapData/MapExecs/kz_example.cfg b/cfg/SharpTimer/MapData/MapExecs/kz_example.cfg deleted file mode 100644 index 93a7003a..00000000 --- a/cfg/SharpTimer/MapData/MapExecs/kz_example.cfg +++ /dev/null @@ -1,4 +0,0 @@ -//These Commands will exec whenever the server Loads the map "kz_example" - -mp_timelimit 60 -sv_airaccelerate 100 \ No newline at end of file diff --git a/cfg/SharpTimer/MapData/MapExecs/surf_.cfg b/cfg/SharpTimer/MapData/MapExecs/surf_.cfg index 7d9e323a..f24281fd 100644 --- a/cfg/SharpTimer/MapData/MapExecs/surf_.cfg +++ b/cfg/SharpTimer/MapData/MapExecs/surf_.cfg @@ -38,8 +38,8 @@ sv_accelerate 6.5 sv_maxvelocity 9876.0 sv_air_max_wishspeed 30.000000 sv_gravity 800.0 -sv_standable_normal 0.7 sv_wateraccelerate 10.0 +sv_jump_precision_enable false // Team & Map Settings @@ -60,12 +60,12 @@ mp_friendlyfire 0 mp_limitteams 0 mp_randomspawn 0 mp_randomspawn_los 0 -mp_solid_teammates 1 +mp_solid_teammates 0 mp_spectators_max 64 mp_suicide_penalty false mp_team_timeout_max 0 mp_teamname_1 "SHARPTIMER" -mp_teamname_2 "X.COM/DEAFPS_" +mp_teamname_2 "SHARPTIMER" sv_falldamage_scale 0 sv_show_teammate_death_notification 0 sv_disable_radar 1 @@ -110,10 +110,11 @@ sv_ignoregrenaderadio true sv_talk_enemy_dead true sv_talk_enemy_living true + // Misc -CS_WarnFriendlyDamageInterval 99999 mp_disconnect_kills_players true + // Bot Settings bot_controllable 0 bot_quota_mode fill @@ -139,5 +140,3 @@ sharptimer_rank_enabled true sharptimer_checkpoints_enabled true sharptimer_remove_checkpoints_restrictions true sharptimer_checkpoints_only_when_timer_stopped true - -sharptimer_jumpstats_enabled false diff --git a/cfg/SharpTimer/MapData/MapExecs/vnl_.cfg b/cfg/SharpTimer/MapData/MapExecs/vnl_.cfg index 3554a29e..a79d6606 100644 --- a/cfg/SharpTimer/MapData/MapExecs/vnl_.cfg +++ b/cfg/SharpTimer/MapData/MapExecs/vnl_.cfg @@ -39,7 +39,6 @@ sv_accelerate 5.500000 sv_maxvelocity 3500.000000 sv_air_max_wishspeed 30.000000 sv_gravity 800.000000 -sv_standable_normal 0.700000 sv_wateraccelerate 10.000000 @@ -61,7 +60,7 @@ mp_friendlyfire 0 mp_limitteams 0 mp_randomspawn 0 mp_randomspawn_los 0 -mp_solid_teammates 1 +mp_solid_teammates 0 mp_spectators_max 64 mp_suicide_penalty false mp_team_timeout_max 0 @@ -81,7 +80,6 @@ mp_teamcashawards false mp_playercashawards false mp_weapons_allow_map_placed false mp_weapons_allow_zeus 0 -mp_weapons_glow_on_ground 0 sv_infinite_ammo 2 mp_ct_default_secondary weapon_usp_silencer mp_t_default_secondary weapon_usp_silencer @@ -114,9 +112,7 @@ sv_talk_enemy_dead true sv_talk_enemy_living true -// Misc -CS_WarnFriendlyDamageInterval 99999 -sv_gameinstructor_enable 0 +// Misc mp_disconnect_kills_players true @@ -145,10 +141,4 @@ sharptimer_rank_enabled true sharptimer_checkpoints_enabled true sharptimer_remove_checkpoints_restrictions false -sharptimer_checkpoints_only_when_timer_stopped false - -sharptimer_jumpstats_enabled true -sharptimer_jumpstats_min_distance 175.0 -sharptimer_jumpstats_max_vert 32.0 -sharptimer_jumpstats_movement_unlocker_cap true -sharptimer_jumpstats_movement_unlocker_cap_value 250.0 \ No newline at end of file +sharptimer_checkpoints_only_when_timer_stopped false \ No newline at end of file diff --git a/cfg/SharpTimer/MapData/local_data/kz_.json b/cfg/SharpTimer/MapData/local_data/kz_.json deleted file mode 100644 index f8f50d84..00000000 --- a/cfg/SharpTimer/MapData/local_data/kz_.json +++ /dev/null @@ -1,2855 +0,0 @@ -{ - "kz_11342": { - "Tier": 1 - }, - "kz_11735": { - "Tier": 1 - }, - "kz_8b1_brickngrass": { - "Tier": 1 - }, - "kz_adeline": { - "Tier": 1 - }, - "kz_alt_cargo": { - "Tier": 1 - }, - "kz_autobadges": { - "Tier": 1 - }, - "kz_baxter": { - "Tier": 1 - }, - "kz_beanguy_v2": { - "Tier": 1 - }, - "kz_beginnerblock": { - "Tier": 1 - }, - "kz_blocks2006": { - "Tier": 1 - }, - "kz_boomblock": { - "Tier": 1 - }, - "kz_breezeblocks": { - "Tier": 1 - }, - "kz_brightblock": { - "Tier": 1 - }, - "kz_cartooncastle": { - "Tier": 1 - }, - "kz_caulis_v2": { - "Tier": 1 - }, - "kz_cellblock_go2": { - "Tier": 1 - }, - "kz_cheetos_fix": { - "Tier": 1 - }, - "kz_chessblock": { - "Tier": 1 - }, - "kz_chrysoprase": { - "Tier": 1 - }, - "kz_cliffhanger": { - "Tier": 1 - }, - "kz_conifer": { - "Tier": 1 - }, - "kz_cranking_the_hog": { - "Tier": 1 - }, - "kz_cratespeed": { - "Tier": 1 - }, - "kz_crate_delight": { - "Tier": 1 - }, - "kz_cybersand": { - "Tier": 1 - }, - "kz_dakow": { - "Tier": 1 - }, - "kz_dale": { - "Tier": 1 - }, - "kz_daniel": { - "Tier": 1 - }, - "kz_dark_fury": { - "Tier": 1 - }, - "kz_delphinium": { - "Tier": 1 - }, - "kz_de_bhop": { - "Tier": 1 - }, - "kz_ea_beneath": { - "Tier": 1 - }, - "kz_emblem_bonus": { - "Tier": 1 - }, - "kz_eros_v2": { - "Tier": 1 - }, - "kz_exoteric": { - "Tier": 1 - }, - "kz_fastmap": { - "Tier": 1 - }, - "kz_fikablock": { - "Tier": 1 - }, - "kz_flying_rabbits": { - "Tier": 1 - }, - "kz_forestrace": { - "Tier": 1 - }, - "kz_frozen": { - "Tier": 1 - }, - "kz_galaxy_go2": { - "Tier": 1 - }, - "kz_ghat": { - "Tier": 1 - }, - "kz_giantbean": { - "Tier": 1 - }, - "kz_gigablock": { - "Tier": 1 - }, - "kz_gkd_v2": { - "Tier": 1 - }, - "kz_haki_v2": { - "Tier": 1 - }, - "kz_hb_3kliksphilip": { - "Tier": 1 - }, - "kz_hillside": { - "Tier": 1 - }, - "kz_huber": { - "Tier": 1 - }, - "kz_hyroblock": { - "Tier": 1 - }, - "kz_intercourse!": { - "Tier": 1 - }, - "kz_j2s_westbl0ck": { - "Tier": 1 - }, - "kz_janpu_final_fix": { - "Tier": 1 - }, - "kz_kiwifactory": { - "Tier": 1 - }, - "kz_kzra_oddland": { - "Tier": 1 - }, - "kz_kzra_shortclimb_v2": { - "Tier": 1 - }, - "kz_kzra_suhu": { - "Tier": 1 - }, - "kz_kzro_2boxes1room": { - "Tier": 1 - }, - "kz_kzro_beknowater": { - "Tier": 1 - }, - "kz_kzro_darkhole": { - "Tier": 1 - }, - "kz_kzro_fastcliff": { - "Tier": 1 - }, - "kz_kzro_shima_v2": { - "Tier": 1 - }, - "kz_kzro_smallcanyon": { - "Tier": 1 - }, - "kz_kzro_speedcavescape": { - "Tier": 1 - }, - "kz_kzro_syotiles": { - "Tier": 1 - }, - "kz_kzro_yaruna": { - "Tier": 1 - }, - "kz_layercake": { - "Tier": 1 - }, - "kz_littlerock_v2": { - "Tier": 1 - }, - "kz_luonto": { - "Tier": 1 - }, - "kz_mac": { - "Tier": 1 - }, - "kz_man_everest_fix": { - "Tier": 1 - }, - "kz_megabhop_v2": { - "Tier": 1 - }, - "kz_micropenis": { - "Tier": 1 - }, - "kz_minimountain_f": { - "Tier": 1 - }, - "kz_morebricks_msq": { - "Tier": 1 - }, - "kz_mz": { - "Tier": 1 - }, - "kz_natureblock_scte": { - "Tier": 1 - }, - "kz_nature_remaster": { - "Tier": 1 - }, - "kz_obsidian": { - "Tier": 1 - }, - "kz_owtetad": { - "Tier": 1 - }, - "kz_phamous": { - "Tier": 1 - }, - "kz_pharos_fix": { - "Tier": 1 - }, - "kz_phaztec": { - "Tier": 1 - }, - "kz_piranha": { - "Tier": 1 - }, - "kz_prolific": { - "Tier": 1 - }, - "kz_quickshot": { - "Tier": 1 - }, - "kz_rainrun_kn_f": { - "Tier": 1 - }, - "kz_redline": { - "Tier": 1 - }, - "kz_rocks_global": { - "Tier": 1 - }, - "kz_rush2suck": { - "Tier": 1 - }, - "kz_sanctuary": { - "Tier": 1 - }, - "kz_sandstone_mq": { - "Tier": 1 - }, - "kz_simplicity_v2": { - "Tier": 1 - }, - "kz_sp1_kyuubisroom": { - "Tier": 1 - }, - "kz_spiritblockv2": { - "Tier": 1 - }, - "kz_sukblock_v2_fixed": { - "Tier": 1 - }, - "kz_summercliff2": { - "Tier": 1 - }, - "kz_terablock": { - "Tier": 1 - }, - "kz_tomb_fix": { - "Tier": 1 - }, - "kz_tradeblock": { - "Tier": 1 - }, - "kz_violet_fix": { - "Tier": 1 - }, - "kz_woodstock_v2": { - "Tier": 1 - }, - "kz_xand": { - "Tier": 1 - }, - "kz_xmas2008": { - "Tier": 1 - }, - "kz_xmas2009": { - "Tier": 1 - }, - "kz_za_tileblock": { - "Tier": 1 - }, - "skz_map": { - "Tier": 1 - }, - "vnl_whiterun": { - "Tier": 1 - }, - "xc_cliffjump_fix": { - "Tier": 1 - }, - "xc_dtt_nasty": { - "Tier": 1 - }, - "kz_kzro_justgrab": { - "Tier": 1 - }, - "kz_sloth": { - "Tier": 1 - }, - "kz_leto_v2": { - "Tier": 1 - }, - "kz_ronja": { - "Tier": 1 - }, - "bkz_kartrider": { - "Tier": 1 - }, - "kz_kiwimirific": { - "Tier": 1 - }, - "kz_smb": { - "Tier": 1 - }, - "kz_something": { - "Tier": 1 - }, - "kz_kays": { - "Tier": 1 - }, - "kz_ghs": { - "Tier": 1 - }, - "kz_lmn": { - "Tier": 1 - }, - "kz_apiisnotresponding": { - "Tier": 1 - }, - "kz_automata": { - "Tier": 1 - }, - "kz_grotto": { - "Tier": 2 - }, - "bkz_blackrockshooter_vzp": { - "Tier": 2 - }, - "bkz_bonus_z1": { - "Tier": 2 - }, - "bkz_cauz_final": { - "Tier": 2 - }, - "bkz_caves": { - "Tier": 2 - }, - "bkz_cg_coldbhop": { - "Tier": 2 - }, - "bkz_chillhop": { - "Tier": 2 - }, - "bkz_dydhop": { - "Tier": 2 - }, - "bkz_goldbhop": { - "Tier": 2 - }, - "bkz_goldbhop": { - "Tier": 2 - }, - "bkz_hellokitty_v2": { - "Tier": 2 - }, - "bkz_impulse": { - "Tier": 2 - }, - "bkz_itz_h25l": { - "Tier": 2 - }, - "bkz_levite_v2": { - "Tier": 2 - }, - "bkz_lewlysex": { - "Tier": 2 - }, - "bkz_measure": { - "Tier": 2 - }, - "bkz_measure2_b03": { - "Tier": 2 - }, - "bkz_nocturns_blue_gfix": { - "Tier": 2 - }, - "bkz_volcanohop": { - "Tier": 2 - }, - "kz_16pillars": { - "Tier": 2 - }, - "kz_420b": { - "Tier": 2 - }, - "kz_4u_nature": { - "Tier": 2 - }, - "kz_7in1": { - "Tier": 2 - }, - "kz_adventure_v2": { - "Tier": 2 - }, - "kz_after_agitation_easy_fix": { - "Tier": 2 - }, - "kz_akrh_warehouse_v3": { - "Tier": 2 - }, - "kz_alfama": { - "Tier": 2 - }, - "kz_alouette_fix": { - "Tier": 2 - }, - "kz_alt_aztec": { - "Tier": 2 - }, - "kz_ancient_v3": { - "Tier": 2 - }, - "kz_antigeneric": { - "Tier": 2 - }, - "kz_antiquity": { - "Tier": 2 - }, - "kz_anus": { - "Tier": 2 - }, - "kz_ashen": { - "Tier": 2 - }, - "kz_asphyxiate": { - "Tier": 2 - }, - "kz_asteroid_field": { - "Tier": 2 - }, - "kz_avalon": { - "Tier": 2 - }, - "kz_aztec": { - "Tier": 2 - }, - "kz_babycat_fix": { - "Tier": 2 - }, - "kz_basicnoon": { - "Tier": 2 - }, - "kz_betterdunjun": { - "Tier": 2 - }, - "kz_bhop_lego": { - "Tier": 2 - }, - "kz_bhop_lj": { - "Tier": 2 - }, - "kz_bhop_monsterjam": { - "Tier": 2 - }, - "kz_bhop_watertemple": { - "Tier": 2 - }, - "kz_bir_dont_fix": { - "Tier": 2 - }, - "kz_bluerace_v2": { - "Tier": 2 - }, - "kz_brickblock_v2": { - "Tier": 2 - }, - "kz_bridge17_fix": { - "Tier": 2 - }, - "kz_canyon": { - "Tier": 2 - }, - "kz_cargo": { - "Tier": 2 - }, - "kz_carp_v2": { - "Tier": 2 - }, - "kz_castlehops_v3": { - "Tier": 2 - }, - "kz_catharsis_global": { - "Tier": 2 - }, - "kz_cdr_myst": { - "Tier": 2 - }, - "kz_checkmate": { - "Tier": 2 - }, - "kz_cheese": { - "Tier": 2 - }, - "kz_christmas": { - "Tier": 2 - }, - "kz_chunky_peanut_butter": { - "Tier": 2 - }, - "kz_combobreaker": { - "Tier": 2 - }, - "kz_combohop_c02": { - "Tier": 2 - }, - "kz_comboya": { - "Tier": 2 - }, - "kz_complex": { - "Tier": 2 - }, - "kz_comp_global": { - "Tier": 2 - }, - "kz_concretejungle": { - "Tier": 2 - }, - "kz_construction": { - "Tier": 2 - }, - "kz_cousucks": { - "Tier": 2 - }, - "kz_cuberunfast": { - "Tier": 2 - }, - "kz_dimensions_v1": { - "Tier": 2 - }, - "kz_doubletake": { - "Tier": 2 - }, - "kz_doveen": { - "Tier": 2 - }, - "kz_dryness": { - "Tier": 2 - }, - "kz_dungeon": { - "Tier": 2 - }, - "kz_dvn_cube_fixed": { - "Tier": 2 - }, - "kz_dvn_dull": { - "Tier": 2 - }, - "kz_dvn_redcarpet": { - "Tier": 2 - }, - "kz_dzy_beyond_v2": { - "Tier": 2 - }, - "kz_echo": { - "Tier": 2 - }, - "kz_edp445": { - "Tier": 2 - }, - "kz_egyptmap": { - "Tier": 2 - }, - "kz_eimeristzurueck": { - "Tier": 2 - }, - "kz_emblem": { - "Tier": 2 - }, - "kz_ephemeral": { - "Tier": 2 - }, - "kz_epusbridge": { - "Tier": 2 - }, - "kz_erbajerb": { - "Tier": 2 - }, - "kz_excavate": { - "Tier": 2 - }, - "kz_experiment": { - "Tier": 2 - }, - "kz_ext_bblocks": { - "Tier": 2 - }, - "kz_fabrik": { - "Tier": 2 - }, - "kz_fas2map": { - "Tier": 2 - }, - "kz_fatigue_v2": { - "Tier": 2 - }, - "kz_final_ascension": { - "Tier": 2 - }, - "kz_floatingislands": { - "Tier": 2 - }, - "kz_foggywarehouse_v2": { - "Tier": 2 - }, - "kz_forgettable": { - "Tier": 2 - }, - "kz_freezing_ridge": { - "Tier": 2 - }, - "kz_fury": { - "Tier": 2 - }, - "kz_gary": { - "Tier": 2 - }, - "kz_generic": { - "Tier": 2 - }, - "kz_genesis": { - "Tier": 2 - }, - "kz_gfy_limit": { - "Tier": 2 - }, - "kz_ggurk": { - "Tier": 2 - }, - "kz_glassesospa_v1": { - "Tier": 2 - }, - "kz_glide": { - "Tier": 2 - }, - "kz_goldenroad": { - "Tier": 2 - }, - "kz_hate": { - "Tier": 2 - }, - "kz_hb_anduu": { - "Tier": 2 - }, - "kz_hb_bacon": { - "Tier": 2 - }, - "kz_hb_fyksen": { - "Tier": 2 - }, - "kz_highland": { - "Tier": 2 - }, - "kz_holdmyhand": { - "Tier": 2 - }, - "kz_holmu1": { - "Tier": 2 - }, - "kz_iluvprok_global": { - "Tier": 2 - }, - "kz_j2s_cupblock_fix2": { - "Tier": 2 - }, - "kz_j2s_tetris": { - "Tier": 2 - }, - "kz_johndoe": { - "Tier": 2 - }, - "kz_jump_n_run": { - "Tier": 2 - }, - "kz_kiwionerous": { - "Tier": 2 - }, - "kz_kiwitown": { - "Tier": 2 - }, - "kz_kohze_sucks": { - "Tier": 2 - }, - "kz_kzra_cliffy": { - "Tier": 2 - }, - "kz_kzra_fustcaves": { - "Tier": 2 - }, - "kz_kzra_greycliff": { - "Tier": 2 - }, - "kz_kzra_stonebhop": { - "Tier": 2 - }, - "kz_kzra_stoneishbhop": { - "Tier": 2 - }, - "kz_kzra_undercastle": { - "Tier": 2 - }, - "kz_kzro_basalt": { - "Tier": 2 - }, - "kz_kzro_brickstgrass_v2": { - "Tier": 2 - }, - "kz_kzro_bronea": { - "Tier": 2 - }, - "kz_kzro_cavernste_v2": { - "Tier": 2 - }, - "kz_kzro_cryscosrun": { - "Tier": 2 - }, - "kz_kzro_excitedbhop": { - "Tier": 2 - }, - "kz_kzro_gohome": { - "Tier": 2 - }, - "kz_kzro_greybrickbhop": { - "Tier": 2 - }, - "kz_kzro_jaashs": { - "Tier": 2 - }, - "kz_kzro_mountainbhop": { - "Tier": 2 - }, - "kz_kzro_mountainhaya": { - "Tier": 2 - }, - "kz_kzro_mountainsein": { - "Tier": 2 - }, - "kz_kzro_mountainsnow": { - "Tier": 2 - }, - "kz_kzro_sunmountainset": { - "Tier": 2 - }, - "kz_kzro_whiterock": { - "Tier": 2 - }, - "kz_kzse_aztectemple": { - "Tier": 2 - }, - "kz_lazy": { - "Tier": 2 - }, - "kz_lego": { - "Tier": 2 - }, - "kz_levels": { - "Tier": 2 - }, - "kz_lookout": { - "Tier": 2 - }, - "kz_machinery": { - "Tier": 2 - }, - "kz_matilda_np": { - "Tier": 2 - }, - "kz_memento": { - "Tier": 2 - }, - "kz_metalrun_global": { - "Tier": 2 - }, - "kz_mike_v4": { - "Tier": 2 - }, - "kz_minimalism": { - "Tier": 2 - }, - "kz_minimal_combo": { - "Tier": 2 - }, - "kz_moorerutan": { - "Tier": 2 - }, - "kz_msp_comatose": { - "Tier": 2 - }, - "kz_nassau": { - "Tier": 2 - }, - "kz_nb_final": { - "Tier": 2 - }, - "kz_nuclear": { - "Tier": 2 - }, - "kz_oldstuff": { - "Tier": 2 - }, - "kz_ominous2": { - "Tier": 2 - }, - "kz_overjoyed": { - "Tier": 2 - }, - "kz_paintball_tv_fix": { - "Tier": 2 - }, - "kz_paradise": { - "Tier": 2 - }, - "kz_peak_global": { - "Tier": 2 - }, - "kz_perfunctory": { - "Tier": 2 - }, - "kz_perf_darkcave": { - "Tier": 2 - }, - "kz_pharaoh": { - "Tier": 2 - }, - "kz_pianoclimb": { - "Tier": 2 - }, - "kz_plains": { - "Tier": 2 - }, - "kz_portal_fix": { - "Tier": 2 - }, - "kz_prima": { - "Tier": 2 - }, - "kz_prismus": { - "Tier": 2 - }, - "kz_project": { - "Tier": 2 - }, - "kz_psyk": { - "Tier": 2 - }, - "kz_psytime": { - "Tier": 2 - }, - "kz_quick7_v2": { - "Tier": 2 - }, - "kz_quicksand": { - "Tier": 2 - }, - "kz_rcn_impermanence": { - "Tier": 2 - }, - "kz_redemption": { - "Tier": 2 - }, - "kz_refract": { - "Tier": 2 - }, - "kz_remedy_v2": { - "Tier": 2 - }, - "kz_retreat": { - "Tier": 2 - }, - "kz_rockclimb": { - "Tier": 2 - }, - "kz_rumzor": { - "Tier": 2 - }, - "kz_serenity": { - "Tier": 2 - }, - "kz_shaft_fix": { - "Tier": 2 - }, - "kz_signs_v2": { - "Tier": 2 - }, - "kz_skyhotel": { - "Tier": 2 - }, - "kz_skytower": { - "Tier": 2 - }, - "kz_slumpfrageous": { - "Tier": 2 - }, - "kz_snowman_v2": { - "Tier": 2 - }, - "kz_sonder": { - "Tier": 2 - }, - "kz_sp1_aoirobhop": { - "Tier": 2 - }, - "kz_sp1_blueconcrete": { - "Tier": 2 - }, - "kz_sp1_candles": { - "Tier": 2 - }, - "kz_sp1_castaway": { - "Tier": 2 - }, - "kz_sp1_greyconcrete": { - "Tier": 2 - }, - "kz_sp1_inverseblocks": { - "Tier": 2 - }, - "kz_sp1_perf2win": { - "Tier": 2 - }, - "kz_sp1_redbrickbhop": { - "Tier": 2 - }, - "kz_sp1_redconcrete": { - "Tier": 2 - }, - "kz_sp1_siedlungclimb": { - "Tier": 2 - }, - "kz_sp1_whiteblocks": { - "Tier": 2 - }, - "kz_spaceladders_v2": { - "Tier": 2 - }, - "kz_spire": { - "Tier": 2 - }, - "kz_splifff": { - "Tier": 2 - }, - "kz_splopkopsc_loverick": { - "Tier": 2 - }, - "kz_sqrdsucks": { - "Tier": 2 - }, - "kz_streetblock": { - "Tier": 2 - }, - "kz_stuff_final": { - "Tier": 2 - }, - "kz_symmetry": { - "Tier": 2 - }, - "kz_thinkblock": { - "Tier": 2 - }, - "kz_toonadventure": { - "Tier": 2 - }, - "kz_toonrun_final": { - "Tier": 2 - }, - "kz_toughluck_fix": { - "Tier": 2 - }, - "kz_tour_de_nuke_rt": { - "Tier": 2 - }, - "kz_twiivo": { - "Tier": 2 - }, - "kz_unity_u01": { - "Tier": 2 - }, - "kz_unknownspace": { - "Tier": 2 - }, - "kz_vci_apprentice": { - "Tier": 2 - }, - "kz_warehouse": { - "Tier": 2 - }, - "kz_wasabi": { - "Tier": 2 - }, - "kz_weebfactory_censored": { - "Tier": 2 - }, - "kz_weightless": { - "Tier": 2 - }, - "kz_wetbricks": { - "Tier": 2 - }, - "kz_whereyoufrom": { - "Tier": 2 - }, - "kz_woodstonegrass_final": { - "Tier": 2 - }, - "kz_woodworld": { - "Tier": 2 - }, - "kz_xmas2020": { - "Tier": 2 - }, - "kz_xtremeblock_v2": { - "Tier": 2 - }, - "xc_lucid_global": { - "Tier": 2 - }, - "xc_minecraft3_global": { - "Tier": 2 - }, - "xc_minecraft4": { - "Tier": 2 - }, - "xc_powerblock_rc1": { - "Tier": 2 - }, - "xc_skycastle": { - "Tier": 2 - }, - "xc_supermario_gfix": { - "Tier": 2 - }, - "kz_kzro_wallblocks": { - "Tier": 2 - }, - "kz_sp1_greyhollowrock": { - "Tier": 2 - }, - "kz_sp1_kansopyon": { - "Tier": 2 - }, - "kz_sp1_parallelblocks": { - "Tier": 2 - }, - "kz_sp1_rockcanyonblocks": { - "Tier": 2 - }, - "kz_sunstone": { - "Tier": 2 - }, - "bkz_greed": { - "Tier": 2 - }, - "kz_lust": { - "Tier": 2 - }, - "kz_moorish": { - "Tier": 2 - }, - "kz_opus": { - "Tier": 2 - }, - "kz_souljaboy": { - "Tier": 2 - }, - "kz_communityblock": { - "Tier": 2 - }, - "kz_comp_2022": { - "Tier": 2 - }, - "kz_sp1_shouryokou": { - "Tier": 2 - }, - "kz_sp1_spreadblocks": { - "Tier": 2 - }, - "kz_sp1_uchuunookuheki": { - "Tier": 2 - }, - "kz_victoria": { - "Tier": 2 - }, - "bkz_canadaszn": { - "Tier": 2 - }, - "kz_bing": { - "Tier": 2 - }, - "kz_greyorgray": { - "Tier": 2 - }, - "kz_cajou": { - "Tier": 2 - }, - "kz_tranquillity": { - "Tier": 2 - }, - "kz_delirium": { - "Tier": 2 - }, - "kz_devon": { - "Tier": 2 - }, - "kz_cf_snakeskin": { - "Tier": 2 - }, - "kz_glow": { - "Tier": 2 - }, - "kz_xmas2022": { - "Tier": 2 - }, - "kz_igneous": { - "Tier": 2 - }, - "kz_acores": { - "Tier": 2 - }, - "kz_desolate": { - "Tier": 2 - }, - "kz_silk": { - "Tier": 2 - }, - "kz_ehcivec": { - "Tier": 2 - }, - "kz_eilrahc": { - "Tier": 2 - }, - "kz_frenzy": { - "Tier": 2 - }, - "kz_hypothermia": { - "Tier": 2 - }, - "kz_kogamaostry": { - "Tier": 2 - }, - "kz_tmnf_e05": { - "Tier": 2 - }, - "vnl_ll_nuke": { - "Tier": 2 - }, - "kz_cakewalk": { - "Tier": 3 - }, - "kz_dontstop": { - "Tier": 3 - }, - "kz_fapzor": { - "Tier": 3 - }, - "kz_pogo": { - "Tier": 3 - }, - "kz_sahara": { - "Tier": 3 - }, - "kz_uninspired_trash": { - "Tier": 3 - }, - "kz_zephyr_v2": { - "Tier": 3 - }, - "kzpro_justrun_sp": { - "Tier": 3 - }, - "kz_21loop_final_fix": { - "Tier": 3 - }, - "kz_2fast": { - "Tier": 3 - }, - "kz_2seasons_spring_final": { - "Tier": 3 - }, - "kz_abandoned": { - "Tier": 3 - }, - "kz_adv_cursedjourney": { - "Tier": 3 - }, - "kz_ahful": { - "Tier": 3 - }, - "kz_alice_fix": { - "Tier": 3 - }, - "kz_allure": { - "Tier": 3 - }, - "kz_amber_od": { - "Tier": 3 - }, - "kz_arbitrary_words": { - "Tier": 3 - }, - "kz_arcadium": { - "Tier": 3 - }, - "kz_arcturus": { - "Tier": 3 - }, - "kz_arrebol": { - "Tier": 3 - }, - "kz_athena": { - "Tier": 3 - }, - "kz_autumn_valley_fix": { - "Tier": 3 - }, - "kz_bacho": { - "Tier": 3 - }, - "kz_basics_b02": { - "Tier": 3 - }, - "kz_beyond_fix": { - "Tier": 3 - }, - "kz_bhop_mosaic_od2": { - "Tier": 3 - }, - "kz_bhop_sakura": { - "Tier": 3 - }, - "kz_bible_black": { - "Tier": 3 - }, - "kz_bigcastle": { - "Tier": 3 - }, - "kz_binseebak": { - "Tier": 3 - }, - "kz_bionic": { - "Tier": 3 - }, - "kz_blatherskite_v1": { - "Tier": 3 - }, - "kz_blindcity_easy_fix": { - "Tier": 3 - }, - "kz_blockhardy2k": { - "Tier": 3 - }, - "kz_bloodline": { - "Tier": 3 - }, - "kz_bombu": { - "Tier": 3 - }, - "kz_bored": { - "Tier": 3 - }, - "kz_buildings_final": { - "Tier": 3 - }, - "kz_burnished": { - "Tier": 3 - }, - "kz_byrem": { - "Tier": 3 - }, - "kz_camembert": { - "Tier": 3 - }, - "kz_cascade_v4": { - "Tier": 3 - }, - "kz_cataclysm": { - "Tier": 3 - }, - "kz_catalyst_gfix": { - "Tier": 3 - }, - "kz_celestial": { - "Tier": 3 - }, - "kz_cereal": { - "Tier": 3 - }, - "kz_cg_brick_rmk": { - "Tier": 3 - }, - "kz_cg_lighthops": { - "Tier": 3 - }, - "kz_chinablock": { - "Tier": 3 - }, - "kz_coastline_fix": { - "Tier": 3 - }, - "kz_colorcode": { - "Tier": 3 - }, - "kz_colors_v2": { - "Tier": 3 - }, - "kz_concept": { - "Tier": 3 - }, - "kz_conrun_scrub": { - "Tier": 3 - }, - "kz_conspiracy": { - "Tier": 3 - }, - "kz_coronado_fix": { - "Tier": 3 - }, - "kz_correguachin_reisido": { - "Tier": 3 - }, - "kz_crash_fix": { - "Tier": 3 - }, - "kz_crypt_final": { - "Tier": 3 - }, - "kz_crysis": { - "Tier": 3 - }, - "kz_cyb_adrenaline_fix": { - "Tier": 3 - }, - "kz_dank_stacks": { - "Tier": 3 - }, - "kz_date2": { - "Tier": 3 - }, - "kz_default": { - "Tier": 3 - }, - "kz_dejavu": { - "Tier": 3 - }, - "kz_depot": { - "Tier": 3 - }, - "kz_diajonal": { - "Tier": 3 - }, - "kz_district_d01": { - "Tier": 3 - }, - "kz_drops_od": { - "Tier": 3 - }, - "kz_duality_v2": { - "Tier": 3 - }, - "kz_dust": { - "Tier": 3 - }, - "kz_dzy_reach_v2": { - "Tier": 3 - }, - "kz_edifice": { - "Tier": 3 - }, - "kz_egyptianbox": { - "Tier": 3 - }, - "kz_emptiness": { - "Tier": 3 - }, - "kz_erinome": { - "Tier": 3 - }, - "kz_excape": { - "Tier": 3 - }, - "kz_exemplum_fix": { - "Tier": 3 - }, - "kz_exps_cursedjourney": { - "Tier": 3 - }, - "kz_farm_v2": { - "Tier": 3 - }, - "kz_fastcombomap": { - "Tier": 3 - }, - "kz_fastcombowombo_v2": { - "Tier": 3 - }, - "kz_forchi": { - "Tier": 3 - }, - "kz_fused": { - "Tier": 3 - }, - "kz_futureblock": { - "Tier": 3 - }, - "kz_gallus": { - "Tier": 3 - }, - "kz_comboking7k": { - "Tier": 3 - }, - "kz_goldentabby": { - "Tier": 3 - }, - "kz_gonbe": { - "Tier": 3 - }, - "kz_green": { - "Tier": 3 - }, - "kz_halicarnassus_fs": { - "Tier": 3 - }, - "kz_hammer": { - "Tier": 3 - }, - "kz_hb_smieszneznaczki": { - "Tier": 3 - }, - "kz_heatvents_mq": { - "Tier": 3 - }, - "kz_hek": { - "Tier": 3 - }, - "kz_hellinashop": { - "Tier": 3 - }, - "kz_hikari_od": { - "Tier": 3 - }, - "kz_holyspace": { - "Tier": 3 - }, - "kz_how2slide_fix": { - "Tier": 3 - }, - "kz_hydromancy": { - "Tier": 3 - }, - "kz_ickkck": { - "Tier": 3 - }, - "kz_illusion_gfix": { - "Tier": 3 - }, - "kz_innit": { - "Tier": 3 - }, - "kz_island": { - "Tier": 3 - }, - "kz_itz_transcendent": { - "Tier": 3 - }, - "kz_jg_ditch": { - "Tier": 3 - }, - "kz_kat_colorblind": { - "Tier": 3 - }, - "kz_kzinga_fixed": { - "Tier": 3 - }, - "kz_kzra_bars": { - "Tier": 3 - }, - "kz_kzra_coast": { - "Tier": 3 - }, - "kz_kzra_hohum": { - "Tier": 3 - }, - "kz_kzra_morath": { - "Tier": 3 - }, - "kz_kzra_rockloy": { - "Tier": 3 - }, - "kz_kzra_rocky": { - "Tier": 3 - }, - "kz_kzra_skaxis": { - "Tier": 3 - }, - "kz_kzra_voovblock": { - "Tier": 3 - }, - "kz_kzra_whitesquare": { - "Tier": 3 - }, - "kz_kzro_cavehole": { - "Tier": 3 - }, - "kz_kzro_sekiseibhop": { - "Tier": 3 - }, - "kz_kzro_slidesmear": { - "Tier": 3 - }, - "kz_lair": { - "Tier": 3 - }, - "kz_lavablock_global": { - "Tier": 3 - }, - "kz_legoland": { - "Tier": 3 - }, - "kz_lego_two_redux_v3": { - "Tier": 3 - }, - "kz_life_final": { - "Tier": 3 - }, - "kz_linoleum": { - "Tier": 3 - }, - "kz_loftroofs": { - "Tier": 3 - }, - "kz_longjumps_easy": { - "Tier": 3 - }, - "kz_lost_marketplace_gfix": { - "Tier": 3 - }, - "kz_magus": { - "Tier": 3 - }, - "kz_megalodon": { - "Tier": 3 - }, - "kz_microwave": { - "Tier": 3 - }, - "kz_milehigh": { - "Tier": 3 - }, - "kz_moonlight": { - "Tier": 3 - }, - "kz_morestairs_msq": { - "Tier": 3 - }, - "kz_motivated": { - "Tier": 3 - }, - "kz_nightfall": { - "Tier": 3 - }, - "kz_nightmare_v2": { - "Tier": 3 - }, - "kz_nyc_v1": { - "Tier": 3 - }, - "kz_oasis": { - "Tier": 3 - }, - "kz_olympus": { - "Tier": 3 - }, - "kz_openspace": { - "Tier": 3 - }, - "kz_orangejuice_v2": { - "Tier": 3 - }, - "kz_orbolution_v2": { - "Tier": 3 - }, - "kz_otakuroom": { - "Tier": 3 - }, - "kz_overgrowth": { - "Tier": 3 - }, - "kz_persona_is_a_dictator": { - "Tier": 3 - }, - "kz_pineforest_v2": { - "Tier": 3 - }, - "kz_pixelrun_v2": { - "Tier": 3 - }, - "kz_pollution": { - "Tier": 3 - }, - "kz_porridge": { - "Tier": 3 - }, - "kz_prekeeper": { - "Tier": 3 - }, - "kz_progressive": { - "Tier": 3 - }, - "kz_quadrablock": { - "Tier": 3 - }, - "kz_quadrant_fix": { - "Tier": 3 - }, - "kz_quixotic": { - "Tier": 3 - }, - "kz_railings": { - "Tier": 3 - }, - "kz_rcn_optimisery": { - "Tier": 3 - }, - "kz_reach_v2": { - "Tier": 3 - }, - "kz_refuge": { - "Tier": 3 - }, - "kz_research": { - "Tier": 3 - }, - "kz_rise": { - "Tier": 3 - }, - "kz_rockjungle_v2": { - "Tier": 3 - }, - "kz_roman": { - "Tier": 3 - }, - "kz_sandstorm_ez": { - "Tier": 3 - }, - "kz_sandyhill_hoc": { - "Tier": 3 - }, - "kz_shortcut_tx": { - "Tier": 3 - }, - "kz_skybridge": { - "Tier": 3 - }, - "kz_slate": { - "Tier": 3 - }, - "kz_slide_kissa": { - "Tier": 3 - }, - "kz_slide_koira": { - "Tier": 3 - }, - "kz_slide_or_dont": { - "Tier": 3 - }, - "kz_slide_pallokala": { - "Tier": 3 - }, - "kz_smallcastle": { - "Tier": 3 - }, - "kz_smallmap": { - "Tier": 3 - }, - "kz_sn_desert": { - "Tier": 3 - }, - "kz_solidarity_v2": { - "Tier": 3 - }, - "kz_sp1_behold": { - "Tier": 3 - }, - "kz_sp1_driedblocks": { - "Tier": 3 - }, - "kz_sp1_greenconcrete": { - "Tier": 3 - }, - "kz_sp1_hallwaybhop": { - "Tier": 3 - }, - "kz_sp1_purpose": { - "Tier": 3 - }, - "kz_spacus": { - "Tier": 3 - }, - "kz_stepblock": { - "Tier": 3 - }, - "kz_stepup": { - "Tier": 3 - }, - "kz_structures": { - "Tier": 3 - }, - "kz_strun_mq": { - "Tier": 3 - }, - "kz_superstructure": { - "Tier": 3 - }, - "kz_surf_ace": { - "Tier": 3 - }, - "kz_symbiosis_final": { - "Tier": 3 - }, - "kz_synergy_ez": { - "Tier": 3 - }, - "kz_synthesis_v2": { - "Tier": 3 - }, - "kz_sz_goldenbean": { - "Tier": 3 - }, - "kz_talltreeforest_v3": { - "Tier": 3 - }, - "kz_talmaniac": { - "Tier": 3 - }, - "kz_timescape_zero": { - "Tier": 3 - }, - "kz_tron_global": { - "Tier": 3 - }, - "kz_twilight_od": { - "Tier": 3 - }, - "kz_twister": { - "Tier": 3 - }, - "kz_unity_collab": { - "Tier": 3 - }, - "kz_verv3_gg": { - "Tier": 3 - }, - "kz_village": { - "Tier": 3 - }, - "kz_vittu_mika_persse": { - "Tier": 3 - }, - "kz_void": { - "Tier": 3 - }, - "kz_waterhole": { - "Tier": 3 - }, - "kz_whatever_v2": { - "Tier": 3 - }, - "kz_yes": { - "Tier": 3 - }, - "kz_zhop_son_fix": { - "Tier": 3 - }, - "kz_zxp_interstellar_v2": { - "Tier": 3 - }, - "vnl_slidegarden": { - "Tier": 3 - }, - "vnl_undefined": { - "Tier": 3 - }, - "xc_alt_nephilim": { - "Tier": 3 - }, - "xc_dreamland2": { - "Tier": 3 - }, - "xc_fox_shrine_japan_fr": { - "Tier": 3 - }, - "xc_karo4": { - "Tier": 3 - }, - "xc_minecraft2_global": { - "Tier": 3 - }, - "xc_nephilim": { - "Tier": 3 - }, - "xc_secret_valley_global_fix": { - "Tier": 3 - }, - "xc_umbrella_global": { - "Tier": 3 - }, - "kz_sp1_xmas2021": { - "Tier": 3 - }, - "kz_kzro_tamlair": { - "Tier": 3 - }, - "kz_maya": { - "Tier": 3 - }, - "kz_sp1_rengapyon": { - "Tier": 3 - }, - "skz_pride": { - "Tier": 3 - }, - "kz_invision": { - "Tier": 3 - }, - "kz_tq": { - "Tier": 3 - }, - "kz_difficultas_discendi": { - "Tier": 3 - }, - "kz_nebula": { - "Tier": 3 - }, - "kz_chillin": { - "Tier": 3 - }, - "kz_slide_bozo": { - "Tier": 3 - }, - "kz_bhop_proxy_null": { - "Tier": 3 - }, - "kz_slide_leto": { - "Tier": 3 - }, - "kz_lovesick": { - "Tier": 3 - }, - "kz_vnl_crimdaughter": { - "Tier": 3 - }, - "kz_hideous": { - "Tier": 3 - }, - "kz_vnl_crimstmas": { - "Tier": 3 - }, - "kz_cf_slide": { - "Tier": 3 - }, - "kz_tangent": { - "Tier": 3 - }, - "kz_cf_hestia": { - "Tier": 3 - }, - "kz_mediumcastle": { - "Tier": 3 - }, - "kz_pamehcilc": { - "Tier": 3 - }, - "kz_prefix_cliche": { - "Tier": 3 - }, - "vnl_lea": { - "Tier": 3 - }, - "bkz_cauz_short": { - "Tier": 4 - }, - "bkz_evanstep": { - "Tier": 4 - }, - "bkz_iota_v3": { - "Tier": 4 - }, - "kzpro_concrete_c02": { - "Tier": 4 - }, - "kz_2seasons_winter_final": { - "Tier": 4 - }, - "kz_aaaa": { - "Tier": 4 - }, - "kz_abstruse_od2": { - "Tier": 4 - }, - "kz_andromeda": { - "Tier": 4 - }, - "kz_another_climb_map": { - "Tier": 4 - }, - "kz_antimony": { - "Tier": 4 - }, - "kz_ascend_hv": { - "Tier": 4 - }, - "kz_atelectasis_sct": { - "Tier": 4 - }, - "kz_atlantis_od3": { - "Tier": 4 - }, - "kz_azure": { - "Tier": 4 - }, - "kz_banjo": { - "Tier": 4 - }, - "kz_betapmaps": { - "Tier": 4 - }, - "kz_bhop_badges3": { - "Tier": 4 - }, - "kz_bhop_benchmark": { - "Tier": 4 - }, - "kz_bhop_composure_f": { - "Tier": 4 - }, - "kz_bhop_dusk": { - "Tier": 4 - }, - "kz_bhop_essence": { - "Tier": 4 - }, - "kz_bhop_lucid": { - "Tier": 4 - }, - "kz_bhop_northface": { - "Tier": 4 - }, - "kz_bhop_nothing": { - "Tier": 4 - }, - "kz_bhop_rotebal3": { - "Tier": 4 - }, - "kz_bhop_skyworld": { - "Tier": 4 - }, - "kz_bhop_zenith": { - "Tier": 4 - }, - "kz_birrita_fix": { - "Tier": 4 - }, - "kz_blindcity_hard_final": { - "Tier": 4 - }, - "kz_bluehop_mq": { - "Tier": 4 - }, - "kz_bluuu": { - "Tier": 4 - }, - "kz_bounce": { - "Tier": 4 - }, - "kz_cabin_fix": { - "Tier": 4 - }, - "kz_carbon": { - "Tier": 4 - }, - "kz_cdr_rustenborg": { - "Tier": 4 - }, - "kz_cdr_slash_final": { - "Tier": 4 - }, - "kz_chopchop": { - "Tier": 4 - }, - "kz_citadel": { - "Tier": 4 - }, - "kz_civilizations": { - "Tier": 4 - }, - "kz_communityjump3": { - "Tier": 4 - }, - "kz_conrun_mq": { - "Tier": 4 - }, - "kz_divided": { - "Tier": 4 - }, - "kz_dontjump": { - "Tier": 4 - }, - "kz_dyd_ladderjumps": { - "Tier": 4 - }, - "kz_epiphany_v2": { - "Tier": 4 - }, - "kz_eudora": { - "Tier": 4 - }, - "kz_eventide": { - "Tier": 4 - }, - "kz_everything": { - "Tier": 4 - }, - "kz_evilcorp": { - "Tier": 4 - }, - "kz_flabbergast": { - "Tier": 4 - }, - "kz_forgotten": { - "Tier": 4 - }, - "kz_free_ahful": { - "Tier": 4 - }, - "kz_f_salted_banana": { - "Tier": 4 - }, - "kz_shark_gc": { - "Tier": 4 - }, - "kz_gfy_blueberry": { - "Tier": 4 - }, - "kz_gfy_devcastle": { - "Tier": 4 - }, - "kz_gfy_final": { - "Tier": 4 - }, - "kz_gfy_fortroca": { - "Tier": 4 - }, - "kz_gfy_strawberry_": { - "Tier": 4 - }, - "kz_gfy_tech": { - "Tier": 4 - }, - "kz_gitgud_final": { - "Tier": 4 - }, - "kz_gloom": { - "Tier": 4 - }, - "kz_gobbledygook": { - "Tier": 4 - }, - "kz_goodluck_p": { - "Tier": 4 - }, - "kz_grass_hard": { - "Tier": 4 - }, - "kz_gy_agitation": { - "Tier": 4 - }, - "kz_haste": { - "Tier": 4 - }, - "kz_hb_lowlita": { - "Tier": 4 - }, - "kz_hb_lrs": { - "Tier": 4 - }, - "kz_headbongo": { - "Tier": 4 - }, - "kz_heaven_od": { - "Tier": 4 - }, - "kz_insomnia_fix": { - "Tier": 4 - }, - "kz_inspired": { - "Tier": 4 - }, - "kz_internatus": { - "Tier": 4 - }, - "kz_kiwi_lars": { - "Tier": 4 - }, - "kz_kzra_slidely": { - "Tier": 4 - }, - "kz_kzra_slidepuf": { - "Tier": 4 - }, - "kz_kzro_chairs": { - "Tier": 4 - }, - "kz_ladderall": { - "Tier": 4 - }, - "kz_ladderhell_fix": { - "Tier": 4 - }, - "kz_lastwork_p1": { - "Tier": 4 - }, - "kz_loathe": { - "Tier": 4 - }, - "kz_longjumps_space": { - "Tier": 4 - }, - "kz_lume": { - "Tier": 4 - }, - "kz_luv_less": { - "Tier": 4 - }, - "kz_malignom_short": { - "Tier": 4 - }, - "kz_mandelbrot": { - "Tier": 4 - }, - "kz_meander": { - "Tier": 4 - }, - "kz_mescaline_f": { - "Tier": 4 - }, - "kz_module": { - "Tier": 4 - }, - "kz_mushrruption_v8": { - "Tier": 4 - }, - "kz_neon_portal": { - "Tier": 4 - }, - "kz_nieh": { - "Tier": 4 - }, - "kz_nightcastle": { - "Tier": 4 - }, - "kz_nymph": { - "Tier": 4 - }, - "kz_pamxul_wip": { - "Tier": 4 - }, - "kz_pantheism_p02": { - "Tier": 4 - }, - "kz_prototype": { - "Tier": 4 - }, - "kz_rectangle": { - "Tier": 4 - }, - "kz_return": { - "Tier": 4 - }, - "kz_reverse": { - "Tier": 4 - }, - "kz_rompenutrias_asheglado": { - "Tier": 4 - }, - "kz_rush2sk8": { - "Tier": 4 - }, - "kz_scum": { - "Tier": 4 - }, - "kz_sendhelp_final": { - "Tier": 4 - }, - "kz_simplejourney": { - "Tier": 4 - }, - "kz_sky_lake": { - "Tier": 4 - }, - "kz_slide_0x7_n1m0": { - "Tier": 4 - }, - "kz_slide_concrete": { - "Tier": 4 - }, - "kz_slide_dydanhomon": { - "Tier": 4 - }, - "kz_slide_pisauva": { - "Tier": 4 - }, - "kz_slide_svn_temple": { - "Tier": 4 - }, - "kz_slide_vaahtera": { - "Tier": 4 - }, - "kz_south": { - "Tier": 4 - }, - "kz_sp1_hiragana": { - "Tier": 4 - }, - "kz_stranded": { - "Tier": 4 - }, - "kz_suomi": { - "Tier": 4 - }, - "kz_surf_blue": { - "Tier": 4 - }, - "kz_surf_kim_hana_gl": { - "Tier": 4 - }, - "kz_swamped_v3": { - "Tier": 4 - }, - "kz_theaquila": { - "Tier": 4 - }, - "kz_trashsurf": { - "Tier": 4 - }, - "kz_trazodon_fix": { - "Tier": 4 - }, - "kz_tribute": { - "Tier": 4 - }, - "kz_variety_fix": { - "Tier": 4 - }, - "kz_why": { - "Tier": 4 - }, - "kz_yanse": { - "Tier": 4 - }, - "kz_yoink": { - "Tier": 4 - }, - "kz_zhop_freestyle": { - "Tier": 4 - }, - "kz_zhop_function3": { - "Tier": 4 - }, - "kz_ziggurath_final": { - "Tier": 4 - }, - "kz_zoomer_fix": { - "Tier": 4 - }, - "kz_zxp_final4": { - "Tier": 4 - }, - "kz_zxp_undia": { - "Tier": 4 - }, - "vnl_cat": { - "Tier": 4 - }, - "vnl_invasion": { - "Tier": 4 - }, - "kz_winterize": { - "Tier": 4 - }, - "kz_envy": { - "Tier": 4 - }, - "kz_gluttony": { - "Tier": 4 - }, - "kz_question": { - "Tier": 4 - }, - "kz_slide_cave": { - "Tier": 4 - }, - "kz_xiaobitu": { - "Tier": 4 - }, - "kz_bhop_horseshit_9": { - "Tier": 4 - }, - "kz_demonhours": { - "Tier": 4 - }, - "kz_slide_piss": { - "Tier": 4 - }, - "kz_nomibo": { - "Tier": 4 - }, - "kz_vnl_crimson": { - "Tier": 4 - }, - "kz_itz_updown": { - "Tier": 4 - }, - "kz_sxb_poi": { - "Tier": 4 - }, - "kz_bhop_exodus": { - "Tier": 4 - }, - "kz_euclide_illusionary": { - "Tier": 4 - }, - "kz_sp1_saishuu": { - "Tier": 4 - }, - "kz_vnl_crimdaddy": { - "Tier": 4 - }, - "vnl_caverun": { - "Tier": 4 - }, - "bkz_apricity_v3": { - "Tier": 5 - }, - "bkz_fear4": { - "Tier": 5 - }, - "bkz_underground_crypt_v3": { - "Tier": 5 - }, - "kzpro_gull_pidr_reborn": { - "Tier": 5 - }, - "kz_aether_fix": { - "Tier": 5 - }, - "kz_alfie": { - "Tier": 5 - }, - "kz_alpha": { - "Tier": 5 - }, - "kz_altum_od": { - "Tier": 5 - }, - "kz_antharas": { - "Tier": 5 - }, - "kz_armored_core": { - "Tier": 5 - }, - "kz_avoria": { - "Tier": 5 - }, - "kz_backwards": { - "Tier": 5 - }, - "kz_bananaysoda_v2": { - "Tier": 5 - }, - "kz_bhop_badges2": { - "Tier": 5 - }, - "kz_carpet": { - "Tier": 5 - }, - "kz_choka_fix": { - "Tier": 5 - }, - "kz_custos": { - "Tier": 5 - }, - "kz_dethroned": { - "Tier": 5 - }, - "kz_failed_fastrun_rt": { - "Tier": 5 - }, - "kz_hb_fafnir": { - "Tier": 5 - }, - "kz_high_socks": { - "Tier": 5 - }, - "kz_hitech": { - "Tier": 5 - }, - "kz_imaginary_final": { - "Tier": 5 - }, - "kz_kiwitech": { - "Tier": 5 - }, - "kz_kzro_hexonay": { - "Tier": 5 - }, - "kz_kzro_mountainroad": { - "Tier": 5 - }, - "kz_ladderdespair": { - "Tier": 5 - }, - "kz_list_gnida_v2": { - "Tier": 5 - }, - "kz_lovely": { - "Tier": 5 - }, - "kz_modernvomit": { - "Tier": 5 - }, - "kz_nix_od": { - "Tier": 5 - }, - "kz_noobfort": { - "Tier": 5 - }, - "kz_okaychamp": { - "Tier": 5 - }, - "kz_simple_sp": { - "Tier": 5 - }, - "kz_slide_isnt_kz": { - "Tier": 5 - }, - "kz_slide_purple_x": { - "Tier": 5 - }, - "kz_slide_rovod": { - "Tier": 5 - }, - "kz_sp1_icecave": { - "Tier": 5 - }, - "kz_sp1_katakana": { - "Tier": 5 - }, - "kz_strafehop_fix": { - "Tier": 5 - }, - "kz_synergy_x": { - "Tier": 5 - }, - "kz_technical_difficulties": { - "Tier": 5 - }, - "kz_techtonic_v2_ldr": { - "Tier": 5 - }, - "skz_bananaysoda_2": { - "Tier": 5 - }, - "skz_sati": { - "Tier": 5 - }, - "skz_sequence_shot": { - "Tier": 5 - }, - "kz_sp1_vines": { - "Tier": 5 - }, - "kz_bhop_mentalism": { - "Tier": 5 - }, - "kz_dishonest": { - "Tier": 5 - }, - "kz_mess": { - "Tier": 5 - }, - "kz_sc_collapse": { - "Tier": 5 - }, - "kz_sc_surf": { - "Tier": 5 - }, - "kz_unnamed": { - "Tier": 5 - }, - "vnl_simplebrickrooms": { - "Tier": 5 - }, - "kz_bhop_algetic": { - "Tier": 5 - }, - "kz_sc_ruins": { - "Tier": 5 - }, - "kz_auuughh": { - "Tier": 5 - }, - "kz_gus_sct2": { - "Tier": 5 - }, - "kz_slide_wasteland": { - "Tier": 5 - }, - "kz_kiwiqualia": { - "Tier": 5 - }, - "kz_simplyhard": { - "Tier": 5 - }, - "kz_slide_era": { - "Tier": 5 - }, - "kz_hoist_fix": { - "Tier": 5 - }, - "kz_persona_is_a_furry": { - "Tier": 5 - }, - "kz_ggsh": { - "Tier": 5 - }, - "vnl_farewell_fix": { - "Tier": 5 - }, - "kz_sxb_biewan": { - "Tier": 5 - }, - "kz_hope": { - "Tier": 5 - }, - "kz_rlk": { - "Tier": 5 - }, - "kz_sxb_despacito": { - "Tier": 5 - }, - "kz_sxb_remake": { - "Tier": 5 - }, - "kzpro_psilocybin": { - "Tier": 6 - }, - "kz_afterlife": { - "Tier": 6 - }, - "kz_alien_city": { - "Tier": 6 - }, - "kz_angina_final": { - "Tier": 6 - }, - "kz_bhop_koki_niwa": { - "Tier": 6 - }, - "kz_blackness": { - "Tier": 6 - }, - "kz_chloroplast": { - "Tier": 6 - }, - "kz_continuum": { - "Tier": 6 - }, - "kz_drunkards": { - "Tier": 6 - }, - "kz_erratum_v2": { - "Tier": 6 - }, - "kz_gemischte_gefuehlslagen": { - "Tier": 6 - }, - "kz_goquicklol_v2": { - "Tier": 6 - }, - "kz_kareful": { - "Tier": 6 - }, - "kz_kiwi_cod": { - "Tier": 6 - }, - "kz_kzro_hardvalley": { - "Tier": 6 - }, - "kz_kzro_skyrocks": { - "Tier": 6 - }, - "kz_lionheart": { - "Tier": 6 - }, - "kz_mieszaneuczucia": { - "Tier": 6 - }, - "kz_neoncity_z": { - "Tier": 6 - }, - "kz_oloramasa": { - "Tier": 6 - }, - "kz_p1": { - "Tier": 6 - }, - "kz_pendulum": { - "Tier": 6 - }, - "kz_portalclimb": { - "Tier": 6 - }, - "kz_procrastination_f": { - "Tier": 6 - }, - "kz_psychosomatic": { - "Tier": 6 - }, - "kz_purgatory": { - "Tier": 6 - }, - "kz_retribution_v2_final": { - "Tier": 6 - }, - "kz_shell": { - "Tier": 6 - }, - "kz_slidebober": { - "Tier": 6 - }, - "kz_slidemap_fix": { - "Tier": 6 - }, - "kz_slide_deee": { - "Tier": 6 - }, - "kz_slide_svn_extreme": { - "Tier": 6 - }, - "kz_slowrun_global_fix": { - "Tier": 6 - }, - "kz_sp1_bloodyljs_v2": { - "Tier": 6 - }, - "kz_spacemario_h": { - "Tier": 6 - }, - "kz_surf_larry": { - "Tier": 6 - }, - "kz_zaloopazxc": { - "Tier": 6 - }, - "skz_makalaka": { - "Tier": 6 - }, - "skz_odious_v2": { - "Tier": 6 - }, - "vnl_oy_lj": { - "Tier": 6 - }, - "kz_bhop_slide": { - "Tier": 6 - }, - "kz_func_detail_v2": { - "Tier": 6 - }, - "kz_dabitu_fix2": { - "Tier": 6 - }, - "kz_d_decompile": { - "Tier": 6 - }, - "kz_rarkovosis": { - "Tier": 6 - }, - "kz_bozo": { - "Tier": 6 - }, - "kz_cthulhu": { - "Tier": 6 - }, - "kz_kukkojapallokidutus": { - "Tier": 6 - }, - "kz_lastwork_p2": { - "Tier": 6 - }, - "kz_scicret": { - "Tier": 6 - }, - "kz_wafflehouse_easy": { - "Tier": 6 - }, - "kz_kiwimind": { - "Tier": 6 - }, - "kz_ltt": { - "Tier": 6 - }, - "kz_mazemerized": { - "Tier": 6 - }, - "kz_slide_red": { - "Tier": 6 - }, - "kz_surf_abaddon": { - "Tier": 6 - }, - "kz_sxb_makabaka": { - "Tier": 6 - }, - "kz_sxb_xbcmzl": { - "Tier": 6 - }, - "kz_climb": { - "Tier": 6 - }, - "kz_divert": { - "Tier": 6 - }, - "kz_dystopia_h": { - "Tier": 6 - }, - "kz_hemochromatosis": { - "Tier": 6 - }, - "kz_maxine": { - "Tier": 6 - }, - "kz_monstrosity": { - "Tier": 6 - }, - "kz_nbdy_maps": { - "Tier": 6 - }, - "kz_thrombosis": { - "Tier": 6 - }, - "kz_zhongbitu": { - "Tier": 6 - }, - "kz_unmake": { - "Tier": 7 - }, - "kzpro_wrath": { - "Tier": 7 - }, - "kz_kiwideath": { - "Tier": 7 - }, - "kz_spacemario_xt": { - "Tier": 7 - }, - "kz_sp1_strafechampion": { - "Tier": 7 - }, - "kz_ladderhorror": { - "Tier": 7 - }, - "kz_slowerrun": { - "Tier": 7 - }, - "kz_wafflehouse_hard": { - "Tier": 7 - }, - "kz_kiwipsychosis": { - "Tier": 7 - }, - "vnl_sewers": { - "Tier": 7 - }, - "kz_kiwislide": { - "Tier": 7 - }, - "kz_w1_holiday": { - "Tier": 7 - }, - "kz_tense": { - "Tier": 7 - }, - "kz_cf_foliage": { - "Tier": 7 - }, - "kz_kiwiexophoric": { - "Tier": 7 - }, - "kz_kiwi_hym": { - "Tier": 7 - }, - "kz_sandbox": { - "Tier": 7 - }, - "kz_wafflehouse_x": { - "Tier": 7 - } -} diff --git a/cfg/SharpTimer/MapData/local_data/surf_.json b/cfg/SharpTimer/MapData/local_data/surf_.json index ac69bd3d..0b8829e4 100644 --- a/cfg/SharpTimer/MapData/local_data/surf_.json +++ b/cfg/SharpTimer/MapData/local_data/surf_.json @@ -3491,4 +3491,4 @@ "Tier": 8, "Type": "Staged" } -} \ No newline at end of file +} diff --git a/cfg/SharpTimer/config.cfg b/cfg/SharpTimer/config.cfg index 7f20838d..6c6f90de 100644 --- a/cfg/SharpTimer/config.cfg +++ b/cfg/SharpTimer/config.cfg @@ -24,7 +24,7 @@ sharptimer_discordwebhook_print_pb true sharptimer_connectmsg_enabled true // Whether connect/disconnect messages are enabled by default or not. Default value : true sharptimer_connect_commands_msg_enabled true // Whether commands on join messages are enabled by default or not. Default value : true sharptimer_kill_pointservercommand_entities true // If "true" the plugin will kill all point_servercommand ents on map start (necessary to make xplay maps playable. 🖕 @xplay). Default value : true -sharptimer_custom_map_cfgs_enabled true // Whether Custom Map .cfg files should be executed for the corresponding maps (found in cfg/SharpTimer/MapData/MapExecs/kz_example.cfg). Default value : true +sharptimer_custom_map_cfgs_enabled true // Whether Custom Map .cfg files should be executed for the corresponding maps (found in cfg/SharpTimer/MapData/MapExecs/de_example.cfg). Default value : true sharptimer_command_spam_cooldown 0.5 // Defines the time in seconds between commands can be called. Default value : 0.5 sharptimer_remove_legs true // Whether Legs should be removed or not. Default value : true sharptimer_remove_collision true // Whether player collision should be removed or not. Default value : true @@ -32,9 +32,9 @@ sharptimer_remove_damage true sharptimer_remove_crouch_fatigue true // Whether the player should get no crouch fatigue or not. Default value : true sharptimer_bhop_block_ticks 16 // Ticks allowed on bhop_block. Default value : 16 sharptimer_spawn_on_respawnpos false // Teleports player to respawnpos on spawn. Default value : false -sharptimer_stage_times_enabled true // Whether stage time records are enabled by default or not. Default value : true sharptimer_enable_checkpoint_verification true // Enable or disable checkpoint verification system. Default value : true (set to false if experiencing "current checkpoint does not match final" issue) sharptimer_apply_infinite_ammo true // Enable or disable infinite ammo. Default value: true +sharptimer_print_start_speed true // Whether the start speed should be printed to chat when the player leaves the start zone. Default value: true sharptimer_stage_times_path csgo cfg SharpTimer PlayerStageData // Path to the stage times folder. Default value : csgo cfg SharpTimer PlayerStageData //PERFORMANCE @@ -45,12 +45,12 @@ sharptimer_hud_updates_per_second 64 //ZONES -sharptimer_zones_box false // Make Zone a 3D Box. Default value : false +sharptimer_zones_box false // Make Zone a 3D Box. Default value : false sharptimer_override_beam_colors_enabled false // Whether Trigger Beams should use the colors below or not. If false plugin uses sharptimer_hud_primary_color -sharptimer_start_beam_color #00FF00 // Start Zone color. Default Value : #00FF00 (green hex code) -sharptimer_end_beam_color #FF0000 // End Zone color. Default Value : #FF0000 (red hex code) +sharptimer_start_beam_color #00FF00 // Start Zone color. Default Value : #00FF00 (green hex code) +sharptimer_end_beam_color #FF0000 // End Zone color. Default Value : #FF0000 (red hex code) sharptimer_allow_startzone_jump true // Allow jumping in startzone. Default value : true (NEGATIVE PERFORMANCE IMPACT) -sharptimer_fake_zones_height 50 // Fake Zones height in units. Default value : 50 +sharptimer_fake_zones_height 50 // Fake Zones height in units. Default value : 50 //STYLES @@ -90,16 +90,16 @@ sharptimer_forced_player_speed 250 //HUD sharptimer_hud_primary_color #00FF00 // Primary Color for Timer HUD (you can use hex codes too). Default value : #00FF00 (green) sharptimer_hud_secondary_color #FFA500 // Secondary Color for Timer HUD (you can use hex codes too). Default value : #FFA500 (orange) -sharptimer_hud_secondary_color_dynamic false // False = Use the sharptimer_hud_secondary_color color. True = Use dynamic color based on player velocity (surf only). Default value: false +sharptimer_hud_secondary_color_dynamic False // False = Use the sharptimer_hud_secondary_color color. True = Use dynamic color based on player velocity (surf only). Default value: false sharptimer_hud_tertiary_color #FFFFFF // Tertiary Color for Timer HUD (you can use hex codes too). Default value : #FFFFFF (white) sharptimer_enable_timer_hud true // If Timer Hud should be globally enabled or not. Default value : true sharptimer_enable_keys_hud true // If Keys Hud should be globally enabled or not. Default value : true sharptimer_enable_rankicons_hud true // If Rank Icons Hud should be globally enabled or not. Default value : true sharptimer_enable_velocity_hud true // If Speed Velocity Hud should be globally enabled or not. Default value : true sharptimer_enable_strafesync_hud true // If Stafe Sync % Hud should be globally enabled or not. Default value : true -sharptimer_enable_map_tier_hud true // If Map Tier Hud should be globally enabled or not. Default value : true -sharptimer_enable_map_type_hud true // If Map Type Hud should be globally enabled or not. Default value : true -sharptimer_enable_map_name_hud true // If Map Name Hud should be globally enabled or not. Default value : true +sharptimer_enable_map_tier_hud true // If Map Tier Hud should be globally enabled or not. Default value : true +sharptimer_enable_map_type_hud true // If Map Type Hud should be globally enabled or not. Default value : true +sharptimer_enable_map_name_hud true // If Map Name Hud should be globally enabled or not. Default value : true //BASIC COMMANDS @@ -112,6 +112,7 @@ sharptimer_help_enabled true sharptimer_enable_noclip false // Whether !noclip/!nc is enabled by default or not. Default value : false sharptimer_rs_enabled_onlinear false // Whether !rs will reset players on linear maps. Default value : false + //GLOBAL RANK POINTS sharptimer_global_rank_points_enabled false // Whether the plugin should reward players with global points for completing maps. MySQL Requierd. Default value : false sharptimer_display_rank_tags_chat true // Whether the plugin should display rank tags infront of players names in chat or not. Default value : true @@ -147,12 +148,14 @@ sharptimer_global_rank_group3_percentile 12.5 sharptimer_global_rank_group4_percentile 25 // The top % of record holders in group no4. Default value : 25 sharptimer_global_rank_group5_percentile 50 // The top % of record holders in group no5. Default value : 50 + //REPLAYS -sharptimer_replays_enabled false // Whether replays should be enabled or not. This option might be performance taxing and use more ram & cpu. Default value: false -sharptimer_replay_max_length 300 // The maximum length for a Replay to be saved in seconds. Anything longer will be discarded Default value: 300 -sharptimer_replay_bot_enabled false // Whether a looping Server Record bot should be spawned in or not (requires navmesh fix). Default value: false -sharptimer_replay_bot_name SERVER RECORD REPLAY // What the name of the Replay Record bot should be. Default value: SERVER RECORD REPLAY -sharptimer_replay_data_directory csgo/cfg/SharpTimer/PlayerReplayData // Directory for replay data. Prepended with game dir. Default value: csgo cfg SharpTimer PlayerReplayData +sharptimer_replays_enabled false // Whether replays should be enabled or not. This option might be performance taxing and use more ram & cpu. Default value : false +sharptimer_replay_only_sr false // Only saves SR replay if true. Default value: false +sharptimer_replay_max_length 300 // The maximum length for a Replay to be saved in seconds. Anything longer will be discarded Default value : 300 +sharptimer_replay_bot_enabled false // Whether a looping Server Record bot should be spawned in or not (requires navmesh fix). Default value : false +sharptimer_replay_bot_name SERVER RECORD REPLAY // What the name of the Replay Record bot should be. Default value : SERVER RECORD REPLAY +sharptimer_replay_data_directory csgo/cfg/SharpTimer/PlayerReplayData // Directory for replay data. Prepended with game dir. Default value: csgo/cfg/SharpTimer/PlayerReplayData //CHECKPOINTS/SAVELOC @@ -161,22 +164,20 @@ sharptimer_remove_checkpoints_restrictions false sharptimer_checkpoints_only_when_timer_stopped false // Will only allow checkpoints/locs if timer is stopped using !timer -//JUMPSTATS (KZ) -sharptimer_jumpstats_enabled false // Whether JumpStats are enabled or not. Default value : false -sharptimer_jumpstats_min_distance 175.0 // Defines the minimum distance for a jumpstat to be printed to chat. Default value : 175.0 -sharptimer_jumpstats_max_vert 32.0 // Defines the max vertical distance for a jumpstat to not be printed to chat. Default value : 32.0 -sharptimer_jumpstats_movement_unlocker_cap true // Intended for taming movement unlocker, caps speed on the second tick of a player being on the ground. Default value : true -sharptimer_jumpstats_movement_unlocker_cap_value 250.0 // Speed cap value which will kick in on the second tick of the player being on the ground. Default value : 250.0 +//STAGES +sharptimer_stage_times_enabled true // Whether stage time records are enabled by default or not. Default value : true +sharptimer_stage_sr_enabled true // Whether stage time server records are enabled by default or not. Default value : true //SOUNDS -sharptimer_enable_sounds_by_default false // Whether to enable sounds for players by default. Default value : false -sharptimer_sound_timer sounds/ui/counter_beep.vsnd // Defines Timer sound. Default value : sounds/ui/counter_beep.vsnd (old: sounds/ui/csgo_ui_button_rollover_large.vsnd) -sharptimer_sound_respawn sounds/buttons/button9.vsnd // Defines Respawn sound. Default value : sounds/buttons/button9.vsnd (old: sounds/buttons/button8.vsnd) -sharptimer_sound_checkpoint sounds/ui/buttonclick.vsnd // Defines Checkpoint sound. Default value : sounds/ui/buttonclick.vsnd (old: sounds/ui/counter_beep.vsnd) -sharptimer_sound_checkpoint_error sounds/ui/weapon_cant_buy.vsnd // Defines Checkpoint Error sound. Default value : sounds/ui/weapon_cant_buy.vsnd -sharptimer_sound_teleport sounds/buttons/blip1.vsnd // Defines Teleport sound. Default value : sounds/buttons/blip1.vsnd (old: sounds/ui/buttonclick.vsnd) -sharptimer_sound_pb sounds/buttons/bell1.vsnd // Defines PB Sound. Default value : sounds/buttons/bell1.vsnd -sharptimer_sound_sr sounds/ui/panorama/round_report_round_won_01.vsnd // Defines SR Sound. Default value : sounds/ui/panorama/round_report_round_won_01.vsnd -sharptimer_sound_sr_all_players true // Whether to play SR sound for all players. Default value : true +sharptimer_enable_sounds_by_default false // Whether to enable sounds for players by default. Default value : false +sharptimer_sound_timer sounds/ui/counter_beep.vsnd // Defines Timer sound. Default value : sounds/ui/counter_beep.vsnd (old: sounds/ui/csgo_ui_button_rollover_large.vsnd) +sharptimer_sound_respawn sounds/buttons/button9.vsnd // Defines Respawn sound. Default value : sounds/buttons/button9.vsnd (old: sounds/buttons/button8.vsnd) +sharptimer_sound_checkpoint sounds/ui/buttonclick.vsnd // Defines Checkpoint sound. Default value : sounds/ui/buttonclick.vsnd (old: sounds/ui/counter_beep.vsnd) +sharptimer_sound_checkpoint_error sounds/ui/weapon_cant_buy.vsnd // Defines Checkpoint Error sound. Default value : sounds/ui/weapon_cant_buy.vsnd +sharptimer_sound_teleport sounds/buttons/blip1.vsnd // Defines Teleport sound. Default value : sounds/buttons/blip1.vsnd (old: sounds/ui/buttonclick.vsnd) +sharptimer_sound_pb sounds/buttons/bell1.vsnd // Defines PB Sound. Default value : sounds/buttons/bell1.vsnd +sharptimer_sound_sr sounds/ui/panorama/round_report_round_won_01.vsnd // Defines SR Sound. Default value : sounds/ui/panorama/round_report_round_won_01.vsnd +sharptimer_sound_sr_all_players true // Whether to play SR sound for all players. Default value : true sharptimer_sound_stage_all_players true // Whether to play stage record sound for all players. Default value : true +sharptimer_enable_soundevents false // When enabled it will play soundevents (not .vsnd files), recommended to keep disabled. Default value : false \ No newline at end of file diff --git a/cfg/SharpTimer/custom_exec.cfg b/cfg/SharpTimer/custom_exec.cfg index 1cf0b838..a895320a 100644 --- a/cfg/SharpTimer/custom_exec.cfg +++ b/cfg/SharpTimer/custom_exec.cfg @@ -1,4 +1,2 @@ //Add your desired server settings here -//Example KZ cfg: https://github.com/deafps/cs-cfg/blob/main/kz.cfg -//Example Surf cfg: https://github.com/deafps/cs-cfg/blob/main/surf.cfg //All commands here will be executed on Map Start \ No newline at end of file diff --git a/lang/en.json b/lang/en.json index fcd9f595..302abfd6 100644 --- a/lang/en.json +++ b/lang/en.json @@ -70,8 +70,6 @@ "hud_hidden": "Hud is now: {red}Hidden", "keys_shown": "Keys is now: {green}Shown", "keys_hidden": "Keys is now: {red}Hidden", - "jumpstats_shown": "Jump Stats are now: {green}Shown", - "jumpstats_hidden": "Jump Stats are now: {red}Hidden", "sounds_on": "Sounds are now: {green}ON", "sounds_off": "Sounds are now: {red}OFF", @@ -105,10 +103,6 @@ "goto_player": "Teleporting to {lime}{0}", "goto_player_not_found": "{lightred}Player name not found! If the name contains spaces please try {lime}!goto 'some name'", - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Height: {lime}{0}{grey} | Width: {lime}{1}{grey} | WT: {lime}{2}{grey} | Sync: {lime}{3}%", - //ad messages "ad_see_all_commands": "{primary}Type !sthelp{default} to see all commands!", "ad_replay_pb": "Type {primary}!replaypb{default} to watch a replay of your personal best run!", @@ -131,7 +125,6 @@ "ad_hud": "Type {primary}!hud{default} to toggle timer hud!", "ad_keys": "Type {primary}!keys{default} to toggle hud keys!", "ad_styles": "Type {primary}!styles{default} to list all available styles!", - "ad_jumpstats": "Type {primaryChatColor}!jumpstats{default} to toggle JumpStats!", //other "command_cooldown": "Command is on cooldown. Chill...", @@ -144,12 +137,13 @@ "connected_message_first": "Player {red}{0} {default}connected for the first time!", "disconnect_message": "Player {red}{0} {default}disconnected!", "afk_message": "{red}You are about to be moved to AFK!", + "start_speed": "Start speed:", //Error "error_savingtime": "Error Saving Time: Player time is 0 ticks", - "error_stagenotmatchfinalone": "Error Saving Time: Player current stage does not match final one{0}", + "error_stagenotmatchfinalone": "Error Saving Time: Player current stage does not match final one", "error_checkpointnotmatchfinalone": "Error Saving Time: Player current checkpoint does not match final one{0}", - + //help console Localizer "Check_console": "Check your console for a list of available commands!", "console_r": "• !r (css_r) - Respawns you", @@ -179,8 +173,7 @@ "console_replaypb": "• !replaypb (css_replaypb) - Replay your pb for the current map", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Replay a top 10 server bonus record", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Replay your pb for a bonus", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Toggles JumpStats", "console_hideweapon": "• !hideweapon (css_hideweapon) - Toggles weapon visibility", "console_spec": "• !spec (css_spec) - Moves you to Spectator or back to a team", "console_styles": "• !styles (css_styles) - List all styles" -} +} \ No newline at end of file diff --git a/lang/fi.json b/lang/fi.json index b09e54ce..f9012d72 100644 --- a/lang/fi.json +++ b/lang/fi.json @@ -36,6 +36,7 @@ "current_rank": "Sijoituksesi on nyt {0}{1}{lime}", "current_rank_points": "{default}({lime}{0}{default}) [{lime}{1}{default}]", "current_pb": "Ennätyksesi kentällä {lime}{0}{default}: {lime}{1}{default} [{lime}{2}{default}]", + "current_bonus_pb": "Ennätyksesi kentällä {lime}Boonus {0}{default}: {lime}{1}{default} [{lime}{2}{default}]", "current_sr": "Palvelin Ennätys kentällä {lime}{0}{white}:", "current_sr_player": "{lime}{0} {white}- {lime}{1}", "reached_max_free": "Olet saavuttanut maksimi ilmaiset piste palkintosi kentälle {lime}{0}{default}!", @@ -100,44 +101,49 @@ "error_occured": "{lightred}Tapahtui virhe.", "info_version": "Tällä palvelimella on käytössä SharpTimer v{0}", "info_os": "OS: {0}", - "info_runtime": "Runtime: {0}", - - // Error - "error_savingtime": "Virhe tallentaessa aikaa: Pelaajan aika on 0 tikkiä", - "error_stagenotmatchfinalone": "Virhe tallentaessa aikaa: Pelaajan nykyinen vaihe ei vastaa viimeistä vaihetta {0}", - "error_checkpointnotmatchfinalone": "Virhe tallentaessa aikaa: Pelaajan nykyinen tarkistuskohta ei vastaa viimeistä tarkistuspistettä {0}", + "info_runtime": "Suoritusaika: {0}", + "connect_message": "Pelaaja {red}{0} {default}yhdistyi!", + "connected_message": "Pelaaja {red}{0} {default}yhdistyi {1}. kerran!", + "connected_message_first": "Pelaaja {red}{0} {default}yhdistyi ensimmäistä kertaa!", + "disconnect_message": "Pelaaja {red}{0} {default}yhdistyi!", + "afk_message": "{red}Olet siirtymässä AFK-tilaan!", + "start_speed": "Aloitusnopeus:", - // help console Localizer - "Check_console": "Tarkista konsolisi saatavilla olevien komentojen luettelon!", - "console_r": "• !r (css_r) - Herättää sinut henkiin", - "console_rb": "• !rb <#> / !b <#> (css_rb / css_b) - Herättää sinut bonukseen", - "console_setresp": "• !setresp / !startpos (css_setresp / css_startpos) - Tallenna mukautettu herätyspiste aloitustunnisteen sisälle", - "console_top": "• !top (css_top) - Listaa kymmenen parasta tulosta tällä kartalla", - "console_topbonus": "• !topbonus <#> (css_topbonus) - Listaa kymmenen parasta bonus-tulosta", - "console_rank": "• !rank (css_rank) - Näyttää nykyisen tason ja parhaat tulokset", - "console_ranks": "• !ranks (css_ranks) - Näyttää serverin tasoluettelon", - "console_points": "• !points (css_points) - Tulostaa kymmenen parasta pistettä", - "console_goto": "• !goto (css_goto) - Teleporttaa sinut toiseen pelaajaan", - "console_stage": "• !stage <#> (css_stage) - Teleporttaa sinut vaiheeseen", - "console_sounds": "• !sounds (css_sounds) - Kytke ajastimen äänet päälle/pois!", - "console_hud": "• !hud (css_hud) - Kytke ajastimen HUD päälle/pois!", - "console_keys": "• !keys (css_keys) - Kytke HUD-näppäimet päälle/pois!", - "console_fov": "• !fov <0-140> (css_fov) - Muuta näkökenttääsi!", - "console_saveloc": "• !saveloc (css_saveloc) - Tallentaa sijainnin", - "console_loadloc": "• !loadloc (css_loadloc) - Teleporttaa sinut viimeiselle sijainnille", - "console_prevloc": "• !prevloc (css_prevloc) - Teleporttaa sinut edelliselle sijainnille", - "console_nextloc": "• !nextloc (css_nextloc) - Teleporttaa sinut seuraavalle sijainnille", - "console_cp": "• !cp (css_cp) - Asettaa tarkistuspisteen", - "console_tp": "• !tp (css_tp) - Teleporttaa sinut viimeiselle tarkistuspisteelle", - "console_prevcp": "• !prevcp (css_prevcp) - Teleporttaa sinut edelliselle tarkistuspisteelle", - "console_nextcp": "• !nextcp (css_nextcp) - Teleporttaa sinut seuraavalle tarkistuspisteelle", - "console_replay": "• !replay / !replaysr (css_replay / css_replaysr) - Toistaa nykyisen kartan serveritulos", - "console_replaytop": "• !replaytop [1-10] (css_replaytop) - Toistaa kymmenen parasta serverin kartan tulosta", - "console_replaypb": "• !replaypb (css_replaypb) - Toistaa sinun parhaat tuloksesi nykyiseltä kartalta", - "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus-vaihe] (css_replaybonus) - Toistaa kymmenen parasta serverin bonus-tulosta", - "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Toistaa sinun parhaat tuloksesi bonus-vaiheessa", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Vaihtaa JumpStatsin päälle/pois", - "console_hideweapon": "• !hideweapon (css_hideweapon) - Vaihtaa aseen näkyvyyden päälle/pois", - "console_spec": "• !spec (css_spec) - Siirtää sinut katselijaksi tai takaisin tiimiin", - "console_styles": "• !styles (css_styles) - Listaa kaikki tyylit" + // Error + "error_savingtime": "Virhe tallentaessa aikaa: Pelaajan aika on 0 tikkiä", + "error_stagenotmatchfinalone": "Virhe tallentaessa aikaa: Pelaajan nykyinen vaihe ei vastaa viimeistä vaihetta", + "error_checkpointnotmatchfinalone": "Virhe tallentaessa aikaa: Pelaajan nykyinen tarkistuskohta ei vastaa viimeistä tarkistuspistettä {0}", + + // help console Localizer + "Check_console": "Tarkista konsolisi saatavilla olevien komentojen luettelon!", + "console_r": "• !r (css_r) - Herättää sinut henkiin", + "console_rb": "• !rb <#> / !b <#> (css_rb / css_b) - Herättää sinut bonukseen", + "console_setresp": "• !setresp / !startpos (css_setresp / css_startpos) - Tallenna mukautettu herätyspiste aloitustunnisteen sisälle", + "console_top": "• !top (css_top) - Listaa kymmenen parasta tulosta tällä kartalla", + "console_topbonus": "• !topbonus <#> (css_topbonus) - Listaa kymmenen parasta bonus-tulosta", + "console_rank": "• !rank (css_rank) - Näyttää nykyisen tason ja parhaat tulokset", + "console_ranks": "• !ranks (css_ranks) - Näyttää serverin tasoluettelon", + "console_points": "• !points (css_points) - Tulostaa kymmenen parasta pistettä", + "console_goto": "• !goto (css_goto) - Teleporttaa sinut toiseen pelaajaan", + "console_stage": "• !stage <#> (css_stage) - Teleporttaa sinut vaiheeseen", + "console_sounds": "• !sounds (css_sounds) - Kytke ajastimen äänet päälle/pois!", + "console_hud": "• !hud (css_hud) - Kytke ajastimen HUD päälle/pois!", + "console_keys": "• !keys (css_keys) - Kytke HUD-näppäimet päälle/pois!", + "console_fov": "• !fov <0-140> (css_fov) - Muuta näkökenttääsi!", + "console_saveloc": "• !saveloc (css_saveloc) - Tallentaa sijainnin", + "console_loadloc": "• !loadloc (css_loadloc) - Teleporttaa sinut viimeiselle sijainnille", + "console_prevloc": "• !prevloc (css_prevloc) - Teleporttaa sinut edelliselle sijainnille", + "console_nextloc": "• !nextloc (css_nextloc) - Teleporttaa sinut seuraavalle sijainnille", + "console_cp": "• !cp (css_cp) - Asettaa tarkistuspisteen", + "console_tp": "• !tp (css_tp) - Teleporttaa sinut viimeiselle tarkistuspisteelle", + "console_prevcp": "• !prevcp (css_prevcp) - Teleporttaa sinut edelliselle tarkistuspisteelle", + "console_nextcp": "• !nextcp (css_nextcp) - Teleporttaa sinut seuraavalle tarkistuspisteelle", + "console_replay": "• !replay / !replaysr (css_replay / css_replaysr) - Toistaa nykyisen kartan serveritulos", + "console_replaytop": "• !replaytop [1-10] (css_replaytop) - Toistaa kymmenen parasta serverin kartan tulosta", + "console_replaypb": "• !replaypb (css_replaypb) - Toistaa sinun parhaat tuloksesi nykyiseltä kartalta", + "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus-vaihe] (css_replaybonus) - Toistaa kymmenen parasta serverin bonus-tulosta", + "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Toistaa sinun parhaat tuloksesi bonus-vaiheessa", + "console_hideweapon": "• !hideweapon (css_hideweapon) - Vaihtaa aseen näkyvyyden päälle/pois", + "console_spec": "• !spec (css_spec) - Siirtää sinut katselijaksi tai takaisin tiimiin", + "console_styles": "• !styles (css_styles) - Listaa kaikki tyylit" } diff --git a/lang/fr.json b/lang/fr.json index 6d9b221b..c4a716b7 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -60,8 +60,6 @@ "hud_hidden": "L'Hud est maintenant: {red}Caché", "keys_shown": "Les touches sont maintenant: {green}Affiché", "keys_hidden": "Les touches sont maintenant: {red}Caché", - "jumpstats_shown": "Les statistiques de saut sont maintenant: {green}Affiché", - "jumpstats_hidden": "Les statistiques de saut sont maintenant: {red}Caché", "sounds_on": "Les sons sont maintenant: {green}Activé", "sounds_off": "Les sons sont maintenant: {red}Désactivé", @@ -94,10 +92,6 @@ "goto_player": "Téléportation vers {lime}{0}", "goto_player_not_found": "{lightred}Le nom du joueur n'a pas été trouvé ! Si le nom contient des espaces, essayez {lime}!goto 'joueur lambda'", - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Hauteur: {lime}{0}{grey} | Largeur: {lime}{1}{grey} | WT: {lime}{2}{grey} | Sync: {lime}{3}%", - //other "command_cooldown": "La commande est en attente. Chill...", "error_occured": "{lightred}Une erreur s'est produite.", @@ -108,10 +102,12 @@ "connected_message": "Joueur {red}{0} {default}connecté pour la {1} fois!", "connected_message_first": "Le joueur {red}{0} {default} s'est connecté pour la première fois!", "disconnect_message": "Joueur {red}{0} {default}déconnecté!", + "afk_message": "{red}Vous allez être déplacé vers l'AFK !", + "start_speed": "Vitesse de départ:", // Error "error_savingtime": "Erreur de sauvegarde du temps : Le temps du joueur est de 0 ticks", - "error_stagenotmatchfinalone": "Erreur de sauvegarde du temps : Le niveau actuel du joueur ne correspond pas au dernier niveau {0}", + "error_stagenotmatchfinalone": "Erreur de sauvegarde du temps : Le niveau actuel du joueur ne correspond pas au dernier niveau", "error_checkpointnotmatchfinalone": "Erreur de sauvegarde du temps : Le point de contrôle actuel du joueur ne correspond pas au dernier point de contrôle {0}", // help console Localizer @@ -143,8 +139,7 @@ "console_replaypb": "• !replaypb (css_replaypb) - Rejoue votre meilleur temps pour la carte actuelle", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Rejoue un des 10 meilleurs records de bonus sur le serveur", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Rejoue votre meilleur temps pour un bonus", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Active/désactive les statistiques de saut", "console_hideweapon": "• !hideweapon (css_hideweapon) - Active/désactive la visibilité de l'arme", "console_spec": "• !spec (css_spec) - Vous place en spectateur ou vous ramène dans une équipe", "console_styles": "• !styles (css_styles) - Liste tous les styles" -} +} \ No newline at end of file diff --git a/lang/ko.json b/lang/ko.json index 6debb2a4..dbb9512c 100644 --- a/lang/ko.json +++ b/lang/ko.json @@ -67,8 +67,6 @@ "hud_hidden": "HUD: {red}숨겨짐", "keys_shown": "키: {green}표시됨", "keys_hidden": "키: {red}숨겨짐", - "jumpstats_shown": "점프 통계: {green}표시됨", - "jumpstats_hidden": "점프 통계: {red}숨겨짐", "sounds_on": "소리: {green}켜짐", "sounds_off": "소리: {red}꺼짐", @@ -102,10 +100,6 @@ "goto_player": "{lime}{0}으로 이동 중", "goto_player_not_found": "{lightred}플레이어 이름을 찾을 수 없습니다! 이름에 공백이 포함된 경우 {lime}!goto '이름'을 시도해보세요", - // 점프 통계 - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}높이: {lime}{0}{grey} | 폭: {lime}{1}{grey} | WT: {lime}{2}{grey} | 동기화: {lime}{3}%", - // 광고 메시지 "ad_see_all_commands": "{primary}!sthelp{default}를 입력하여 모든 명령어를 확인하세요!", "ad_replay_pb": "{primary}!replaypb{default}를 입력하여 자신의 최고 기록 리플레이를 시청하세요!", @@ -128,7 +122,6 @@ "ad_hud": "{primary}!hud{default}를 입력하여 타이머 HUD를 켜거나 끄세요!", "ad_keys": "{primary}!keys{default}를 입력하여 키 HUD를 켜거나 끄세요!", "ad_styles": "{primary}!styles{default}를 입력하여 사용 가능한 모든 스타일을 확인하세요!", - "ad_jumpstats": "{primaryChatColor}!jumpstats{default}를 입력하여 점프 통계를 켜거나 끄세요!", // 기타 "command_cooldown": "명령어 쿨다운 중입니다. 잠시 기다리세요...", @@ -139,10 +132,11 @@ "connect_message": "{red}{0} {default}플레이어가 연결되었습니다!", "disconnect_message": "{red}{0} {default}플레이어가 연결이 끊어졌습니다!", "afk_message": "{red}곧 AFK로 이동합니다!", + "start_speed": "시작 속도:", // 오류 "error_savingtime": "시간 저장 오류: 플레이어 시간이 0 틱입니다", - "error_stagenotmatchfinalone": "시간 저장 오류: 플레이어의 현재 스테이지가 마지막 스테이지와 일치하지 않습니다{0}", + "error_stagenotmatchfinalone": "시간 저장 오류: 플레이어의 현재 스테이지가 마지막 스테이지와 일치하지 않습니다", "error_checkpointnotmatchfinalone": "시간 저장 오류: 플레이어의 현재 체크포인트가 마지막 체크포인트와 일치하지 않습니다{0}", // 도움말 콘솔 지역화 @@ -174,7 +168,6 @@ "console_replaypb": "• !replaypb (css_replaypb) - 현재 맵의 PB를 재생합니다", "console_replaybonus": "• !replaybonus / !replayb [1-10] [보너스 스테이지] (css_replaybonus) - 서버 상위 10개 보너스 기록을 재생합니다", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - 보너스의 PB를 재생합니다", - "console_jumpstats": "• !jumpstats (css_jumpstats) - 점프 통계를 전환합니다", "console_hideweapon": "• !hideweapon (css_hideweapon) - 무기 가시성을 전환합니다", "console_spec": "• !spec (css_spec) - 관전자 모드로 이동하거나 팀으로 돌아갑니다", "console_styles": "• !styles (css_styles) - 모든 스타일을 나열합니다" diff --git a/lang/nb.json b/lang/nb.json index 9ab06885..0a1cb009 100644 --- a/lang/nb.json +++ b/lang/nb.json @@ -60,8 +60,6 @@ "hud_hidden": "Hud er nå: {red}Gjemt", "keys_shown": "Keys er nå: {green}Vist", "keys_hidden": "Keys er nå: {red}Gjemt", - "jumpstats_shown": "Hoppstatistikk er nå: {green}Vist", - "jumpstats_hidden": "Hoppstatistikk er nå: {red}Gjemt", "sounds_on": "Lyder er nå: {green}PÅ", "sounds_off": "Lyder er nå: {red}AV", @@ -93,10 +91,6 @@ "goto_player": "Teleporterer til {lime}{0}", "goto_player_not_found": "{lightred}Finner ikke spillernavnet! Hvis navnet inneholder mellomrom, prøv {lime}!goto 'et navn'", - - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Høyde: {lime}{0}{grey} | Bredde: {lime}{1}{grey} | WT: {lime}{2}{grey} | Sync: {lime}{3}%", //ad messages "ad_see_all_commands": "{primary}Skriv !sthelp{default} for å se alle kommandoer!", @@ -120,8 +114,7 @@ "ad_hud": "Skriv {primary}!hud{default} for å veksle tidtaker hud!", "ad_keys": "Skriv {primary}!keys{default} for å veksle hud taster!", "ad_styles": "Skriv {primary}!styles{default} for å liste opp alle tilgjengelige stiler!", - "ad_jumpstats": "Skriv {primaryChatColor}!jumpstats{default} for å veksle JumpStats!", - + //other "command_cooldown": "Kommandoen er på nedkjøling. Chill...", "error_occured": "{lightred}Feil oppstod.", @@ -132,10 +125,12 @@ "connected_message": "Spiller {red}{0} {default}koblet til for den {1} gang!", "connected_message_first": "Spiller {red}{0} {default}koblet til for første gang!", "disconnect_message": "Spiller {red}{0} {default}frakoblet!", + "afk_message": "{red}Du er i ferd med å bli flyttet til AFK!", + "start_speed": "Startfart:", // Error "error_savingtime": "Feil ved lagring av tid: Spillerens tid er 0 ticks", - "error_stagenotmatchfinalone": "Feil ved lagring av tid: Spillerens nåværende nivå stemmer ikke overens med siste nivå {0}", + "error_stagenotmatchfinalone": "Feil ved lagring av tid: Spillerens nåværende nivå stemmer ikke overens med siste nivå", "error_checkpointnotmatchfinalone": "Feil ved lagring av tid: Spillerens nåværende sjekkpunkt stemmer ikke overens med siste sjekkpunkt {0}", // help console Localizer @@ -167,9 +162,8 @@ "console_replaypb": "• !replaypb (css_replaypb) - Spill av din PB for det nåværende kartet", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Spill av et av de 10 beste bonus-rekordene på serveren", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Spill av din PB for en bonus", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Bytt JumpStats", "console_hideweapon": "• !hideweapon (css_hideweapon) - Bytt synligheten på våpen", "console_spec": "• !spec (css_spec) - Flytter deg til spekter eller tilbake til et lag", "console_styles": "• !styles (css_styles) - List alle stiler" -} +} \ No newline at end of file diff --git a/lang/pl.json b/lang/pl.json index 0fc635f2..dcc82734 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -60,8 +60,6 @@ "hud_hidden": "Hud zostal: {red}Ukryte", "keys_shown": "Klawisze sa teraz: {green}Pokazane", "keys_hidden": "Klawisze sa teraz: {red}Ukryte", - "jumpstats_shown": "Statystyki skokow zostaly: {green}Pokazane", - "jumpstats_hidden": "Statystyki skokow zostaly: {red}Ukryte", "sounds_on": "Dzwieki zostaly: {green}Wlaczone", "sounds_off": "Dzwieki zostaly: {red}Wylaczone", @@ -94,10 +92,6 @@ "goto_player": "Przeniesiono do {lime}{0}", "goto_player_not_found": "{lightred}Gracz pod dana nazwa nie zostal znaleziony. Jezeli nazwa posiada spacje sprobuj uzyc: {lime}!goto 'some name'", - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Height: {lime}{0}{grey} | Width: {lime}{1}{grey} | WT: {lime}{2}{grey} | Sync: {lime}{3}%", - //other "command_cooldown": "Odczekaj zanim ponownie skorzystasz z komendy!", "error_occured": "{lightred}Wystapil blad.", @@ -108,10 +102,12 @@ "connected_message": "Gracz {red}{0} {default}połączył się {1} raz!", "connected_message_first": "Gracz {red}{0} {default}połączył się po raz pierwszy!", "disconnect_message": "Gracz {red}{0} {default}rozłączył się!", + "afk_message": "{red}Za chwilę zostaniesz przeniesiony do AFK!", + "start_speed": "Prędkość startowa:", - // Error + // Error "error_savingtime": "Błąd zapisywania czasu: Czas gracza wynosi 0 ticks", - "error_stagenotmatchfinalone": "Błąd zapisywania czasu: Aktualny etap gracza nie pasuje do ostatniego {0}", + "error_stagenotmatchfinalone": "Błąd zapisywania czasu: Aktualny etap gracza nie pasuje do ostatniego", "error_checkpointnotmatchfinalone": "Błąd zapisywania czasu: Aktualny punkt kontrolny gracza nie pasuje do ostatniego {0}", // help console Localizer @@ -143,8 +139,7 @@ "console_replaypb": "• !replaypb (css_replaypb) - Odtwarza twój PB na aktualnej mapie", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Odtwarza jeden z 10 najlepszych rekordów bonusowych", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Odtwarza twój PB na bonusie", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Przełącza JumpStats", "console_hideweapon": "• !hideweapon (css_hideweapon) - Przełącza widoczność broni", "console_spec": "• !spec (css_spec) - Przenosi cię do widza lub z powrotem do drużyny", "console_styles": "• !styles (css_styles) - Wyświetla wszystkie style" -} +} \ No newline at end of file diff --git a/lang/sk.json b/lang/sk.json index 7759d322..3be1d518 100644 --- a/lang/sk.json +++ b/lang/sk.json @@ -1,110 +1,110 @@ { - "prefix": "{lime}SharpTimer ●{white}", + "prefix": "{lime}SharpTimer ●{white}", - //timer - "timer_time": "Čas: [{lime}{0}{default}] {1}", - "timer_style": "Štýl: [{lime}{0}{default}]", - "stop_using_timer": "Zastavte svoj časovač pomocou {lime}!timer{default} naprv!", - "timer_enabled": "Časovač: {green}Zapnutý", - "timer_disabled": "Časovač: {red}Vypnutý", - "timer_cancelled": "Časovač bol zrušený z dôvodu nelegálneho pokusu o preskočenie", - "timer_reset": "Resetovali ste sa kvôli nelegálnemu pokusu o preskočenie", + //timer + "timer_time": "Čas: [{lime}{0}{default}] {1}", + "timer_style": "Štýl: [{lime}{0}{default}]", + "stop_using_timer": "Zastavte svoj časovač pomocou {lime}!timer{default} naprv!", + "timer_enabled": "Časovač: {green}Zapnutý", + "timer_disabled": "Časovač: {red}Vypnutý", + "timer_cancelled": "Časovač bol zrušený z dôvodu nelegálneho pokusu o preskočenie", + "timer_reset": "Resetovali ste sa kvôli nelegálnemu pokusu o preskočenie", - //records - "no_records_available": "Pre {0} nie sú dostupné žiadne záznamy", - "no_records_available_bonus": "Pre bonus {0} dňa {1} nie sú k dispozícii žiadne záznamy", - "records_map": "#{0}: {lime}{1} {default}- {2} {lime}{3}", - "new_server_record": "{lime}{0} {white}nastavil nový serverový rekord!", - "new_server_record_bonus": "{lime}{0} {white}nastavil nový serverový rekord na mape {1} (Bonus)!", - "new_pb_record": "{lime}{0} {white}získal nový najlepší čas hráča!", - "new_pb_record_bonus": "{lime}{0} {white}získal nový nalepší čas hráča na mape {1} (Bonus)!", - "map_finish": "{lime}{0} {white}dokončil mapu!", - "map_finish_bonus": "{lime}{0} {white}dokončil Bonus {1}!", - "map_finish_rank": "Hodnosť: [{lime}{0}{default}] Dokončené: [{lime}{1}{default}]", - "top10_records": "Top 10 {0} rekordy pre {1}:", - "top10_records_bonus": "Top 10 {0} rekordy pre bonus {1} na {2}:", + //records + "no_records_available": "Pre {0} nie sú dostupné žiadne záznamy", + "no_records_available_bonus": "Pre bonus {0} dňa {1} nie sú k dispozícii žiadne záznamy", + "records_map": "#{0}: {lime}{1} {default}- {2} {lime}{3}", + "new_server_record": "{lime}{0} {white}nastavil nový serverový rekord!", + "new_server_record_bonus": "{lime}{0} {white}nastavil nový serverový rekord na mape {1} (Bonus)!", + "new_pb_record": "{lime}{0} {white}získal nový najlepší čas hráča!", + "new_pb_record_bonus": "{lime}{0} {white}získal nový nalepší čas hráča na mape {1} (Bonus)!", + "map_finish": "{lime}{0} {white}dokončil mapu!", + "map_finish_bonus": "{lime}{0} {white}dokončil Bonus {1}!", + "map_finish_rank": "Hodnosť: [{lime}{0}{default}] Dokončené: [{lime}{1}{default}]", + "top10_records": "Top 10 {0} rekordy pre {1}:", + "top10_records_bonus": "Top 10 {0} rekordy pre bonus {1} na {2}:", - //stages - "invalid_bonus_stage": "Zadajte platný bonusový stupeň, napr.: {lime}!topbonus 1", - "invalid_bonus_rb": "Zadajte platnú bonusovú fázu, napr.: {lime}!rb ", - "stages_unavalible": "Etapy nedostupné", - "stages_unavalible_respawnpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnStagePos s indexom {0}!", - "stages_enter_valid": "Zadajte platnú fázu, napr.: {lime}!stage ", - "map_no_stages": "{lightred}Aktuálna mapa nemá žiadne fázy!", + //stages + "invalid_bonus_stage": "Zadajte platný bonusový stupeň, napr.: {lime}!topbonus 1", + "invalid_bonus_rb": "Zadajte platnú bonusovú fázu, napr.: {lime}!rb ", + "stages_unavalible": "Etapy nedostupné", + "stages_unavalible_respawnpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnStagePos s indexom {0}!", + "stages_enter_valid": "Zadajte platnú fázu, napr.: {lime}!stage ", + "map_no_stages": "{lightred}Aktuálna mapa nemá žiadne fázy!", - //rank - "current_rank": "Momentálne ste {0}{1}{lime}", - "current_rank_points": "{default}({lime}{0}{default}) [{lime}{1}{default}]", - "current_pb": "Vaša aktuálna PB na {lime}{0}{default}: {lime}{1}{default} [{lime}{2}{default}]", - "current_bonus_pb": "Vaša aktuálna PB na {lime}Bonus {0}{default}: {lime}{1}{default} [{lime}{2}{default}]", - "current_sr": "Aktuálny záznam servera na {lime}{0}{white}:", - "current_sr_player": "{lime}{0} {white}- {lime}{1}", - "reached_max_free": "Dosiahli ste maximálny počet bezplatných odmien vo výške {lime}{0}{default}!", + //rank + "current_rank": "Momentálne ste {0}{1}{lime}", + "current_rank_points": "{default}({lime}{0}{default}) [{lime}{1}{default}]", + "current_pb": "Vaša aktuálna PB na {lime}{0}{default}: {lime}{1}{default} [{lime}{2}{default}]", + "current_bonus_pb": "Vaša aktuálna PB na {lime}Bonus {0}{default}: {lime}{1}{default} [{lime}{2}{default}]", + "current_sr": "Aktuálny záznam servera na {lime}{0}{white}:", + "current_sr_player": "{lime}{0} {white}- {lime}{1}", + "reached_max_free": "Dosiahli ste maximálny počet bezplatných odmien vo výške {lime}{0}{default}!", - //replay - "no_replay": "Momentálne sa neprehráva žiadne prehrávanie", - "end_your_replay": "Najprv ukončite svoje aktuálne prehrávanie {lime}!stopreplay", - "available_replay_cmds": "Dostupné replay príkazy: {lime}!replaypb{default} | {lime}!replaytop <1-10>{default} | {lime}!replaysr{predvolené}", - "no_sr_replay": "Žiadny záznam servera na prehratie!", - "replaying_server_top": "Prehrávanie Top Server Top {0} napíšte {lime}!stop alebo {lime}!stopreplay {default}, aby ste ukončili prehrávanie", - "replaying_pb": "Prehrávanie PB typu {lime}!stop alebo {lime}!stopreplay {default}, aby ste ukončili prehrávanie", - "ending_replay": "Ukončenie opakovaného prehrávania!", - "replay_corrupt": "Zdá sa, že požadované prehratie je poškodené", - "replay_dont_exist": "Požadované prehratie neexistuje", + //replay + "no_replay": "Momentálne sa neprehráva žiadne prehrávanie", + "end_your_replay": "Najprv ukončite svoje aktuálne prehrávanie {lime}!stopreplay", + "available_replay_cmds": "Dostupné replay príkazy: {lime}!replaypb{default} | {lime}!replaytop <1-10>{default} | {lime}!replaysr{predvolené}", + "no_sr_replay": "Žiadny záznam servera na prehratie!", + "replaying_server_top": "Prehrávanie Top Server Top {0} napíšte {lime}!stop alebo {lime}!stopreplay {default}, aby ste ukončili prehrávanie", + "replaying_pb": "Prehrávanie PB typu {lime}!stop alebo {lime}!stopreplay {default}, aby ste ukončili prehrávanie", + "ending_replay": "Ukončenie opakovaného prehrávania!", + "replay_corrupt": "Zdá sa, že požadované prehratie je poškodené", + "replay_dont_exist": "Požadované prehratie neexistuje", - //settings - "hud_shown": "Hud je práve: {green}Zobrazené", - "hud_hidden": "Hud je práve: {red}Skryté", - "keys_shown": "Keys je práve: {green}Zobrazené", - "keys_hidden": "Keys je práve: {red}Skryté", - "jumpstats_shown": "Jump Stats sú práve: {green}Zobrazené", - "jumpstats_hidden": "Jump Stats sú práve: {red}Skryté", - "sounds_on": "Zvuky sú práve: {green}Zapnuté", - "sounds_off": "Zvuky sú práve: {red}Vypnuté", + //settings + "hud_shown": "Hud je práve: {green}Zobrazené", + "hud_hidden": "Hud je práve: {red}Skryté", + "keys_shown": "Keys je práve: {green}Zobrazené", + "keys_hidden": "Keys je práve: {red}Skryté", + "sounds_on": "Zvuky sú práve: {green}Zapnuté", + "sounds_off": "Zvuky sú práve: {red}Vypnuté", - //zones - "no_respawnpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnPos!", - "no_respawnpos_bonus": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnBonusPos!", - "no_respawnpos_bonus_index": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnBonusPos s indexom {0}!", - "no_endpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne koncové miesto!", - "map_using_manual_zones": "Aktuálna mapa používa manuálne zóny", - "saved_custom_respawnpos": "Uložené vlastné RespawnPos počiatočnej zóny!", - "not_inside_startzone": "Nie ste v štartovacej zóne!", + //zones + "no_respawnpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnPos!", + "no_respawnpos_bonus": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnBonusPos!", + "no_respawnpos_bonus_index": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne RespawnBonusPos s indexom {0}!", + "no_endpos": "{lightred}Pre aktuálnu mapu sa nenašlo žiadne koncové miesto!", + "map_using_manual_zones": "Aktuálna mapa používa manuálne zóny", + "saved_custom_respawnpos": "Uložené vlastné RespawnPos počiatočnej zóny!", + "not_inside_startzone": "Nie ste v štartovacej zóne!", - //styles - "styles_list": "Štýl {0}. {lime}{1}", - "style_example": "príklad: {lime}/style 1", - "style_set": "Štýl nastavený na: {lime}{0}", - "style_not_found": "Štýl {0} neexistuje", - "styles_disabled": "Štýly sú momentálne na tomto serveri zakázané", - "styles_not_supported": "Štýly momentálne nie sú podporované na miestnych záznamoch :(", + //styles + "styles_list": "Štýl {0}. {lime}{1}", + "style_example": "príklad: {lime}/style 1", + "style_set": "Štýl nastavený na: {lime}{0}", + "style_not_found": "Štýl {0} neexistuje", + "styles_disabled": "Štýly sú momentálne na tomto serveri zakázané", + "styles_not_supported": "Štýly momentálne nie sú podporované na miestnych záznamoch :(", - //checkpoints - "checkpoint_set": "{0} nastavené! {lime}#{1}", - "no_checkpoint_set": "Nič {0} nenastavené!", - "cant_use_checkpoint": "{lightred}Keď je časovač zapnutý, nemožno použiť {0}, použite {default}!timer", - "cant_use_checkpoint_in_air": "{lightred}Vo vzduchu nie je možné nastaviť {0}", - "used_checkpoint": "Teleportované do nasledujúceho {0}", - "used_recent_checkpoint": "Teleportované na najnovšie {0}", - "used_previous_checkpoint": "Teleportované do predchádzajúceho {0}", + //checkpoints + "checkpoint_set": "{0} nastavené! {lime}#{1}", + "no_checkpoint_set": "Nič {0} nenastavené!", + "cant_use_checkpoint": "{lightred}Keď je časovač zapnutý, nemožno použiť {0}, použite {default}!timer", + "cant_use_checkpoint_in_air": "{lightred}Vo vzduchu nie je možné nastaviť {0}", + "used_checkpoint": "Teleportované do nasledujúceho {0}", + "used_recent_checkpoint": "Teleportované na najnovšie {0}", + "used_previous_checkpoint": "Teleportované do predchádzajúceho {0}", - "goto_player": "Teleportuje sa do {lime}{0}", - "goto_player_not_found": "{lightred}Meno hráča sa nenašlo! Ak názov obsahuje medzery, skúste {lime}!goto 'nejaký názov'", + "goto_player": "Teleportuje sa do {lime}{0}", + "goto_player_not_found": "{lightred}Meno hráča sa nenašlo! Ak názov obsahuje medzery, skúste {lime}!goto 'nejaký názov'", - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Výška: {lime}{0}{grey} | Šírka: {lime}{1}{grey} | WT: {lime}{2}{grey} | Synchronizácia: {lime}{3} %", + //other + "command_cooldown": "Príkaz je v režime cooldown. Kľud...", + "error_occured": "{lightred}Vyskytla sa chyba.", + "info_version": "Tento server používa SharpTimer v{0}", + "info_os": "OS: {0}", + "info_runtime": "Doba behu: {0}", + "connect_message": "Hráč {red}{0} {default}sa pripojil!", + "connected_message": "Hráč {red}{0} {default}sa pripojil po {1}. krát!", + "connected_message_first": "Hráč {red}{0} {default}sa pripojil po prvýkrát!", + "disconnect_message": "Hráč {red}{0} {default}sa odpojil!", + "afk_message": "{red}Čoskoro budete presunutý do AFK!", + "start_speed": "Počiatočná rýchlosť:", - //other - "command_cooldown": "Príkaz je v režime cooldown. Kľud...", - "error_occured": "{lightred}Vyskytla sa chyba.", - "info_version": "Tento server používa SharpTimer v{0}", - "info_os": "OS: {0}", - "info_runtime": "Runtime: {0}", - - // Error + // Error "error_savingtime": "Napaka pri shranjevanju časa: Čas igralca je 0 tics", - "error_stagenotmatchfinalone": "Napaka pri shranjevanju časa: Trenutna stopnja igralca se ne ujema z zadnjo {0}", + "error_stagenotmatchfinalone": "Napaka pri shranjevanju časa: Trenutna stopnja igralca se ne ujema z zadnjo", "error_checkpointnotmatchfinalone": "Napaka pri shranjevanju časa: Trenutna kontrolna točka igralca se ne ujema z zadnjo {0}", // help console Localizer @@ -136,8 +136,7 @@ "console_replaypb": "• !replaypb (css_replaypb) - Predvaja vaš PB za trenutni zemljevid", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Predvaja enega izmed 10 najboljših bonusnih zapisov strežnika", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Predvaja vaš PB za bonus", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Preklopi JumpStats", "console_hideweapon": "• !hideweapon (css_hideweapon) - Preklopi vidnost orožja", "console_spec": "• !spec (css_spec) - Premakne vas v opazovalca ali nazaj v ekipo", "console_styles": "• !styles (css_styles) - Prikazuje vse sloge" -} +} \ No newline at end of file diff --git a/lang/sv.json b/lang/sv.json index d7746a23..d21eb7f6 100644 --- a/lang/sv.json +++ b/lang/sv.json @@ -60,8 +60,6 @@ "hud_hidden": "HUD är nu: {red}Gömd", "keys_shown": "Tangenter är nu: {green}Synliga", "keys_hidden": "Tangenter är nu: {red}Gömda", - "jumpstats_shown": "Jump Stats är nu: {green}Synliga", - "jumpstats_hidden": "Jump Stats är nu: {red}Gömda", "sounds_on": "Ljud är nu: {green}PÅ", "sounds_off": "Ljud är nu: {red}AV", @@ -94,10 +92,6 @@ "goto_player": "Teleporterar till {lime}{0}", "goto_player_not_found": "{lightred}Namnet på spelaren hittades inte! Om namnet innehåller mellanslag, försök {lime}!goto 'spelarens namn'", - //jumpstats - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Height: {lime}{0}{grey} | Width: {lime}{1}{grey} | WT: {lime}{2}{grey} | Sync: {lime}{3}%", - //other "command_cooldown": "Command är på cooldown. Chilla...", "error_occured": "{lightred}Fel uppstod.", @@ -108,43 +102,45 @@ "connected_message": "Spelare {red}{0} {default}ansluten för den {1} gången!", "connected_message_first": "Spleare {red}{0} {default}ansluten för första gången!", "disconnect_message": "Spelare {red}{0} {default}lämnade!", - - // Error - "error_savingtime": "Chyba pri ukladaní času: Čas hráča je 0 tics", - "error_stagenotmatchfinalone": "Chyba pri ukladaní času: Aktuálna fáza hráča sa nezhoduje s konečnou {0}", - "error_checkpointnotmatchfinalone": "Chyba pri ukladaní času: Aktuálna kontrolná bodka hráča sa nezhoduje s konečnou {0}", - // help console Localizer - "Check_console": "Skontrolujte svoju konzolu pre zoznam dostupných príkazov!", - "console_r": "• !r (css_r) - Ožije vás", - "console_rb": "• !rb <#> / !b <#> (css_rb / css_b) - Ožije vás na bonuse", - "console_setresp": "• !setresp / !startpos (css_setresp / css_startpos) - Uloží vlastný bod respawnu v štartovacom spúšťači", - "console_top": "• !top (css_top) - Zobrazí 10 najlepších rekordov na tejto mape", - "console_topbonus": "• !topbonus <#> (css_topbonus) - Zobrazí 10 najlepších bonusových rekordov", - "console_rank": "• !rank (css_rank) - Zobrazí váš aktuálny rank a PB", - "console_ranks": "• !ranks (css_ranks) - Zobrazí zoznam rankov servera", - "console_points": "• !points (css_points) - Zobrazí 10 najlepších bodov", - "console_goto": "• !goto (css_goto) - Teleportuje vás k hráčovi", - "console_stage": "• !stage <#> (css_stage) - Teleportuje vás na scénu", - "console_sounds": "• !sounds (css_sounds) - Prepnúť zvuky časovača!", - "console_hud": "• !hud (css_hud) - Prepnúť HUD časovača!", - "console_keys": "• !keys (css_keys) - Prepnúť tlačidlá HUD!", - "console_fov": "• !fov <0-140> (css_fov) - Zmeniť vaše zorné pole!", - "console_saveloc": "• !saveloc (css_saveloc) - Uloží lokalitu", - "console_loadloc": "• !loadloc (css_loadloc) - Teleportuje vás na poslednú lokalitu", - "console_prevloc": "• !prevloc (css_prevloc) - Teleportuje vás o jednu lokalitu späť", - "console_nextloc": "• !nextloc (css_nextloc) - Teleportuje vás o jednu lokalitu dopredu", - "console_cp": "• !cp (css_cp) - Nastaví kontrolný bod", - "console_tp": "• !tp (css_tp) - Teleportuje vás na posledný kontrolný bod", - "console_prevcp": "• !prevcp (css_prevcp) - Teleportuje vás o jeden kontrolný bod späť", - "console_nextcp": "• !nextcp (css_nextcp) - Teleportuje vás o jeden kontrolný bod dopredu", - "console_replay": "• !replay / !replaysr (css_replay / css_replaysr) - Prehrá aktuálny záznam serverovej mapy", - "console_replaytop": "• !replaytop [1-10] (css_replaytop) - Prehrá top 10 serverových rekordov mapy", - "console_replaypb": "• !replaypb (css_replaypb) - Prehrá váš PB pre aktuálnu mapu", - "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Prehrá top 10 serverových bonusových rekordov", - "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Prehrá váš PB pre bonus", - "console_jumpstats": "• !jumpstats (css_jumpstats) - Prepnúť JumpStats", - "console_hideweapon": "• !hideweapon (css_hideweapon) - Prepnúť viditeľnosť zbrane", - "console_spec": "• !spec (css_spec) - Presunie vás na diváka alebo späť do tímu", - "console_styles": "• !styles (css_styles) - Zobraziť všetky štýly" + "afk_message": "{red}Du är på väg att flyttas till AFK!", + "start_speed": "Startfart:", + + //Error + "error_savingtime": "Error Saving Time: Spelartiden är 0 tick", + "error_stagenotmatchfinalone": "Error Saving Time: Spelarens nuvarande stadium matchar inte det sista", + "error_checkpointnotmatchfinalone": "Error Saving Time: Spelarens aktuella checkpoint matchar inte den sista{0}", + + //help console Localizer + "Check_console": "Kolla din konsol för en lista över tillgängliga kommandon!", + "console_r": "• !r (css_r) - Respawnar dig", + "console_rb": "• !rb <#> / !b <#> (css_rb / css_b) - Respawnar dig till en bonus", + "console_setresp": "• !setresp / !startpos (css_setresp / css_startpos) - Spara en custom respawn plats inom start triggern", + "console_top": "• !top (css_top) - Listar topp 10 rekord på denna karta", + "console_topbonus": "• !topbonus <#> (css_topbonus) - Listar topp 10 rekord på en bonus", + "console_rank": "• !rank (css_rank) - Visar din nuvarande rank och pb", + "console_ranks": "• !ranks (css_ranks) - Visar en lista över serverrankningarna", + "console_points": "• !points (css_points) - Visa topp 10 poäng", + "console_goto": "• !goto (css_goto) - Teleporterar dig till en spelare", + "console_stage": "• !stage <#> (css_stage) - Teleporterar dig till en stage", + "console_sounds": "• !sounds (css_sounds) - Toggla timer ljud!", + "console_hud": "• !hud (css_hud) - Toggla timer hud!", + "console_keys": "• !keys (css_keys) - Toggla hud keys!", + "console_fov": "• !fov <0-140> (css_fov) - Ändra din field of view!", + "console_saveloc": "• !saveloc (css_saveloc) - Spara en Loc", + "console_loadloc": "• !loadloc (css_loadloc) - Teleporterar dig till det sista Loc", + "console_prevloc": "• !prevloc (css_prevloc) - Teleporterar dig en Loc tillbaka", + "console_nextloc": "• !nextloc (css_nextloc) - Teleporterar dig en Loc framåt", + "console_cp": "• !cp (css_cp) - Sätter en Checkpoint", + "console_tp": "• !tp (css_tp) - Teleporterar dig till din sista Checkpoint", + "console_prevcp": "• !prevcp (css_prevcp) - Teleporterar dig en Checkpoint bak", + "console_nextcp": "• !nextcp (css_nextcp) - Teleporterar dig en Checkpoint fram", + "console_replay": "• !replay / !replaysr (css_replay / css_replaysr) - Spela upp nuvarande kartas server rekord", + "console_replaytop": "• !replaytop [1-10] (css_replaytop) - Spela upp en topp 10 server karta rekord", + "console_replaypb": "• !replaypb (css_replaypb) - Spela om din pb för den aktuella kartan", + "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - Spela om ett topp 10-serverbonusrekord", + "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Spela om din pb för en bonus", + "console_hideweapon": "• !hideweapon (css_hideweapon) - Toggla vapnets synlighet", + "console_spec": "• !spec (css_spec) - Flyttar dig till Spectator eller tillbaka till ett lag", + "console_styles": "• !styles (css_styles) - Lista alla styles" } diff --git a/lang/tr.json b/lang/tr.json index d7a53585..016a8647 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -64,8 +64,6 @@ "hud_hidden": "Hud şu anda: {red}Gizli", "keys_shown": "Tușlar şu anda: {green}Gösteriliyor", "keys_hidden": "Tușlar şu anda: {red}Gizli", - "jumpstats_shown": "Jump Stat'ları şu anda: {green}Gösteriliyor", - "jumpstats_hidden": "Jump Stat'ları şu anda: {red}Gizli", "sounds_on": "Sesler şu anda: {green}Açık", "sounds_off": "Sesler şu anda: {red}Kapalı", @@ -99,10 +97,6 @@ "goto_player": "Oyuncuya {lime}{0} ışınlanılıyor", "goto_player_not_found": "{lightred}Oyuncu adı bulunamadı! Eğer adı boşluk içeriyorsa {lime}!goto 'örnek kullanım' şeklinde deneyin", - //jumpstat mesajları - "js_msg1": "{lime}JS: {grey} {0}: {1}{2}{grey} | Pre: {lime}{3}{grey} | Max: {lime}{4}{grey} | Strafes: {lime}{5}", - "js_msg2": "{grey}Yükseklik: {lime}{0}{grey} | Genişlik: {lime}{1}{grey} | WT: {lime}{2}{grey} | Senkronizasyon: {lime}{3}%", - //Reklam mesajları "ad_see_all_commands": "{primary}Tüm komutları görmek için !sthelp yazın{default}", "ad_replay_pb": "Kişisel en iyi rekorunuzun replayını izlemek için {primary}!replaypb yazın{default}", @@ -125,7 +119,6 @@ "ad_hud": "Zamanlayıcı HUD'unu açmak/kapamak için {primary}!hud yazın{default}", "ad_keys": "HUD tuşlarını açmak/kapamak için {primary}!keys yazın{default}", "ad_styles": "Mevcut stilleri listelemek için {primary}!styles yazın{default}", - "ad_jumpstats": "JumpStats'ı açmak/kapamak için {primaryChatColor}!jumpstats yazın{default}", //Diğer "command_cooldown": "Komut bekleme süresinde. Sakin olun...", @@ -138,10 +131,11 @@ "connected_message_first": "Oyuncu {red}{0} {default} ilk kez bağlandı!", "disconnect_message": "Oyuncu {red}{0} {default}çıktı!", "afk_message": "{red}AFK'ya alınmak üzeresiniz!", + "start_speed": "Başlangıç hızı:", //Hata "error_savingtime": "Zaman kaydedilirken hata: Oyuncu zamanı 0 tick", - "error_stagenotmatchfinalone": "Zaman kaydedilirken hata: Oyuncunun geçerli stage'i son stage ile uyuşmuyor{0}", + "error_stagenotmatchfinalone": "Zaman kaydedilirken hata: Oyuncunun geçerli stage'i son stage ile uyuşmuyor", "error_checkpointnotmatchfinalone": "Zaman kaydedilirken hata: Oyuncunun geçerli kontrol noktası son kontrol noktası ile uyuşmuyor{0}", //Yardım konsolu Yerelleştirici @@ -173,7 +167,6 @@ "console_replaypb": "• !replaypb (css_replaypb) - Mevcut haritada kişisel en iyi zamanınızı tekrar oynatır", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus numarası] (css_replaybonus) - Bonus bölgesindeki sunucu replayını tekrar oynatır", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - Bonus bölgesindeki kişisel en iyi zamanınızı tekrar oynatır", - "console_jumpstats": "• !jumpstats (css_jumpstats) - JumpStats'ı açar/kapar", "console_hideweapon": "• !hideweapon (css_hideweapon) - Silah görünürlüğünü açar/kapar", "console_spec": "• !spec (css_spec) - Sizi izleyiciye veya takıma geri taşır", "console_styles": "• !styles (css_styles) - Mevcut stilleri listeler" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 1449a970..4a1b85cc 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -52,8 +52,6 @@ "hud_hidden": "HUD : {red}隐藏", "keys_shown": "按键: {green}显示", "keys_hidden": "按键: {red}隐藏", - "jumpstats_shown": "跳跃统计: {green}显示", - "jumpstats_hidden": "跳跃统计: {red}隐藏", "sounds_on": "声音: {green}打开", "sounds_off": "声音: {red}关闭", "no_respawnpos": "{lightred}当前地图未找到重生位置!", @@ -78,8 +76,6 @@ "used_previous_checkpoint": "已传送至上一个 {0}", "goto_player": "正在传送到 {lime}{0}", "goto_player_not_found": "{lightred}未找到玩家名称!如果名称包含空格,请尝试 {lime}!goto '名称'", - "js_msg1": "{lime}跳跃统计: {grey} {0}: {1}{2}{grey} | 预跳: {lime}{3}{grey} | 最大: {lime}{4}{grey} | 滑动次数: {lime}{5}", - "js_msg2": "{grey}高度: {lime}{0}{grey} | 宽度: {lime}{1}{grey} | 滑动时间: {lime}{2}{grey} | 同步率: {lime}{3}%", "ad_see_all_commands": "{primary}输入 !sthelp{default} 查看所有命令!", "ad_replay_pb": "输入 {primary}!replaypb{default} 观看你个人最佳的重播!", "ad_replay_sr": "输入 {primary}!replay 或 {primary}!replaysr{default} 观看 {primary}{current_map}{default} 的服务器记录重播!", @@ -101,7 +97,6 @@ "ad_hud": "输入 {primary}!hud{default} 启用/禁用计时器 HUD!", "ad_keys": "输入 {primary}!keys{default} 启用/禁用 HUD 按键!", "ad_styles": "输入 {primary}!styles{default} 列出所有可用的风格!", - "ad_jumpstats": "输入 {primaryChatColor}!jumpstats{default} 启用/禁用跳跃统计!", "command_cooldown": "命令正在冷却中,请稍等...", "error_occured": "{lightred}发生错误。", "info_version": "此服务器运行 SharpTimer v{0}", @@ -112,10 +107,11 @@ "connected_message_first": "玩家 {red}{0} {default}首次进入服务器!", "disconnect_message": "玩家 {red}{0} {default}断开连接!", "afk_message": "{red}你即将到达 AFK 检测!", + "start_speed": "起始速度:", //报错 "error_savingtime": "保存时间错误:玩家时间为 0 ticks", - "error_stagenotmatchfinalone": "保存时间错误:玩家当前阶段与最终阶段不匹配{0}", + "error_stagenotmatchfinalone": "保存时间错误:玩家当前阶段与最终阶段不匹配", "error_checkpointnotmatchfinalone": "保存时间错误:玩家当前检查点与最终检查点不匹配{0}", //控制台项 @@ -147,8 +143,7 @@ "console_replaypb": "• !replaypb (css_replaypb) - 回放你在当前地图的个人最好成绩", "console_replaybonus": "• !replaybonus / !replayb [1-10] [bonus stage] (css_replaybonus) - 回放前 10 名的服务器奖励记录", "console_replaybonuspb": "• !replaybonuspb / !replaybpb (css_replaybonuspb) - 回放你在奖励关卡的个人最好成绩", - "console_jumpstats": "• !jumpstats (css_jumpstats) - 切换跳跃统计", "console_hideweapon": "• !hideweapon (css_hideweapon) - 切换武器可见性", "console_spec": "• !spec (css_spec) - 使你进入观战模式或返回队伍", "console_styles": "• !styles (css_styles) - 列出所有样式" -} +} \ No newline at end of file diff --git a/remote_data/kz_.json b/remote_data/kz_.json deleted file mode 100644 index f8f50d84..00000000 --- a/remote_data/kz_.json +++ /dev/null @@ -1,2855 +0,0 @@ -{ - "kz_11342": { - "Tier": 1 - }, - "kz_11735": { - "Tier": 1 - }, - "kz_8b1_brickngrass": { - "Tier": 1 - }, - "kz_adeline": { - "Tier": 1 - }, - "kz_alt_cargo": { - "Tier": 1 - }, - "kz_autobadges": { - "Tier": 1 - }, - "kz_baxter": { - "Tier": 1 - }, - "kz_beanguy_v2": { - "Tier": 1 - }, - "kz_beginnerblock": { - "Tier": 1 - }, - "kz_blocks2006": { - "Tier": 1 - }, - "kz_boomblock": { - "Tier": 1 - }, - "kz_breezeblocks": { - "Tier": 1 - }, - "kz_brightblock": { - "Tier": 1 - }, - "kz_cartooncastle": { - "Tier": 1 - }, - "kz_caulis_v2": { - "Tier": 1 - }, - "kz_cellblock_go2": { - "Tier": 1 - }, - "kz_cheetos_fix": { - "Tier": 1 - }, - "kz_chessblock": { - "Tier": 1 - }, - "kz_chrysoprase": { - "Tier": 1 - }, - "kz_cliffhanger": { - "Tier": 1 - }, - "kz_conifer": { - "Tier": 1 - }, - "kz_cranking_the_hog": { - "Tier": 1 - }, - "kz_cratespeed": { - "Tier": 1 - }, - "kz_crate_delight": { - "Tier": 1 - }, - "kz_cybersand": { - "Tier": 1 - }, - "kz_dakow": { - "Tier": 1 - }, - "kz_dale": { - "Tier": 1 - }, - "kz_daniel": { - "Tier": 1 - }, - "kz_dark_fury": { - "Tier": 1 - }, - "kz_delphinium": { - "Tier": 1 - }, - "kz_de_bhop": { - "Tier": 1 - }, - "kz_ea_beneath": { - "Tier": 1 - }, - "kz_emblem_bonus": { - "Tier": 1 - }, - "kz_eros_v2": { - "Tier": 1 - }, - "kz_exoteric": { - "Tier": 1 - }, - "kz_fastmap": { - "Tier": 1 - }, - "kz_fikablock": { - "Tier": 1 - }, - "kz_flying_rabbits": { - "Tier": 1 - }, - "kz_forestrace": { - "Tier": 1 - }, - "kz_frozen": { - "Tier": 1 - }, - "kz_galaxy_go2": { - "Tier": 1 - }, - "kz_ghat": { - "Tier": 1 - }, - "kz_giantbean": { - "Tier": 1 - }, - "kz_gigablock": { - "Tier": 1 - }, - "kz_gkd_v2": { - "Tier": 1 - }, - "kz_haki_v2": { - "Tier": 1 - }, - "kz_hb_3kliksphilip": { - "Tier": 1 - }, - "kz_hillside": { - "Tier": 1 - }, - "kz_huber": { - "Tier": 1 - }, - "kz_hyroblock": { - "Tier": 1 - }, - "kz_intercourse!": { - "Tier": 1 - }, - "kz_j2s_westbl0ck": { - "Tier": 1 - }, - "kz_janpu_final_fix": { - "Tier": 1 - }, - "kz_kiwifactory": { - "Tier": 1 - }, - "kz_kzra_oddland": { - "Tier": 1 - }, - "kz_kzra_shortclimb_v2": { - "Tier": 1 - }, - "kz_kzra_suhu": { - "Tier": 1 - }, - "kz_kzro_2boxes1room": { - "Tier": 1 - }, - "kz_kzro_beknowater": { - "Tier": 1 - }, - "kz_kzro_darkhole": { - "Tier": 1 - }, - "kz_kzro_fastcliff": { - "Tier": 1 - }, - "kz_kzro_shima_v2": { - "Tier": 1 - }, - "kz_kzro_smallcanyon": { - "Tier": 1 - }, - "kz_kzro_speedcavescape": { - "Tier": 1 - }, - "kz_kzro_syotiles": { - "Tier": 1 - }, - "kz_kzro_yaruna": { - "Tier": 1 - }, - "kz_layercake": { - "Tier": 1 - }, - "kz_littlerock_v2": { - "Tier": 1 - }, - "kz_luonto": { - "Tier": 1 - }, - "kz_mac": { - "Tier": 1 - }, - "kz_man_everest_fix": { - "Tier": 1 - }, - "kz_megabhop_v2": { - "Tier": 1 - }, - "kz_micropenis": { - "Tier": 1 - }, - "kz_minimountain_f": { - "Tier": 1 - }, - "kz_morebricks_msq": { - "Tier": 1 - }, - "kz_mz": { - "Tier": 1 - }, - "kz_natureblock_scte": { - "Tier": 1 - }, - "kz_nature_remaster": { - "Tier": 1 - }, - "kz_obsidian": { - "Tier": 1 - }, - "kz_owtetad": { - "Tier": 1 - }, - "kz_phamous": { - "Tier": 1 - }, - "kz_pharos_fix": { - "Tier": 1 - }, - "kz_phaztec": { - "Tier": 1 - }, - "kz_piranha": { - "Tier": 1 - }, - "kz_prolific": { - "Tier": 1 - }, - "kz_quickshot": { - "Tier": 1 - }, - "kz_rainrun_kn_f": { - "Tier": 1 - }, - "kz_redline": { - "Tier": 1 - }, - "kz_rocks_global": { - "Tier": 1 - }, - "kz_rush2suck": { - "Tier": 1 - }, - "kz_sanctuary": { - "Tier": 1 - }, - "kz_sandstone_mq": { - "Tier": 1 - }, - "kz_simplicity_v2": { - "Tier": 1 - }, - "kz_sp1_kyuubisroom": { - "Tier": 1 - }, - "kz_spiritblockv2": { - "Tier": 1 - }, - "kz_sukblock_v2_fixed": { - "Tier": 1 - }, - "kz_summercliff2": { - "Tier": 1 - }, - "kz_terablock": { - "Tier": 1 - }, - "kz_tomb_fix": { - "Tier": 1 - }, - "kz_tradeblock": { - "Tier": 1 - }, - "kz_violet_fix": { - "Tier": 1 - }, - "kz_woodstock_v2": { - "Tier": 1 - }, - "kz_xand": { - "Tier": 1 - }, - "kz_xmas2008": { - "Tier": 1 - }, - "kz_xmas2009": { - "Tier": 1 - }, - "kz_za_tileblock": { - "Tier": 1 - }, - "skz_map": { - "Tier": 1 - }, - "vnl_whiterun": { - "Tier": 1 - }, - "xc_cliffjump_fix": { - "Tier": 1 - }, - "xc_dtt_nasty": { - "Tier": 1 - }, - "kz_kzro_justgrab": { - "Tier": 1 - }, - "kz_sloth": { - "Tier": 1 - }, - "kz_leto_v2": { - "Tier": 1 - }, - "kz_ronja": { - "Tier": 1 - }, - "bkz_kartrider": { - "Tier": 1 - }, - "kz_kiwimirific": { - "Tier": 1 - }, - "kz_smb": { - "Tier": 1 - }, - "kz_something": { - "Tier": 1 - }, - "kz_kays": { - "Tier": 1 - }, - "kz_ghs": { - "Tier": 1 - }, - "kz_lmn": { - "Tier": 1 - }, - "kz_apiisnotresponding": { - "Tier": 1 - }, - "kz_automata": { - "Tier": 1 - }, - "kz_grotto": { - "Tier": 2 - }, - "bkz_blackrockshooter_vzp": { - "Tier": 2 - }, - "bkz_bonus_z1": { - "Tier": 2 - }, - "bkz_cauz_final": { - "Tier": 2 - }, - "bkz_caves": { - "Tier": 2 - }, - "bkz_cg_coldbhop": { - "Tier": 2 - }, - "bkz_chillhop": { - "Tier": 2 - }, - "bkz_dydhop": { - "Tier": 2 - }, - "bkz_goldbhop": { - "Tier": 2 - }, - "bkz_goldbhop": { - "Tier": 2 - }, - "bkz_hellokitty_v2": { - "Tier": 2 - }, - "bkz_impulse": { - "Tier": 2 - }, - "bkz_itz_h25l": { - "Tier": 2 - }, - "bkz_levite_v2": { - "Tier": 2 - }, - "bkz_lewlysex": { - "Tier": 2 - }, - "bkz_measure": { - "Tier": 2 - }, - "bkz_measure2_b03": { - "Tier": 2 - }, - "bkz_nocturns_blue_gfix": { - "Tier": 2 - }, - "bkz_volcanohop": { - "Tier": 2 - }, - "kz_16pillars": { - "Tier": 2 - }, - "kz_420b": { - "Tier": 2 - }, - "kz_4u_nature": { - "Tier": 2 - }, - "kz_7in1": { - "Tier": 2 - }, - "kz_adventure_v2": { - "Tier": 2 - }, - "kz_after_agitation_easy_fix": { - "Tier": 2 - }, - "kz_akrh_warehouse_v3": { - "Tier": 2 - }, - "kz_alfama": { - "Tier": 2 - }, - "kz_alouette_fix": { - "Tier": 2 - }, - "kz_alt_aztec": { - "Tier": 2 - }, - "kz_ancient_v3": { - "Tier": 2 - }, - "kz_antigeneric": { - "Tier": 2 - }, - "kz_antiquity": { - "Tier": 2 - }, - "kz_anus": { - "Tier": 2 - }, - "kz_ashen": { - "Tier": 2 - }, - "kz_asphyxiate": { - "Tier": 2 - }, - "kz_asteroid_field": { - "Tier": 2 - }, - "kz_avalon": { - "Tier": 2 - }, - "kz_aztec": { - "Tier": 2 - }, - "kz_babycat_fix": { - "Tier": 2 - }, - "kz_basicnoon": { - "Tier": 2 - }, - "kz_betterdunjun": { - "Tier": 2 - }, - "kz_bhop_lego": { - "Tier": 2 - }, - "kz_bhop_lj": { - "Tier": 2 - }, - "kz_bhop_monsterjam": { - "Tier": 2 - }, - "kz_bhop_watertemple": { - "Tier": 2 - }, - "kz_bir_dont_fix": { - "Tier": 2 - }, - "kz_bluerace_v2": { - "Tier": 2 - }, - "kz_brickblock_v2": { - "Tier": 2 - }, - "kz_bridge17_fix": { - "Tier": 2 - }, - "kz_canyon": { - "Tier": 2 - }, - "kz_cargo": { - "Tier": 2 - }, - "kz_carp_v2": { - "Tier": 2 - }, - "kz_castlehops_v3": { - "Tier": 2 - }, - "kz_catharsis_global": { - "Tier": 2 - }, - "kz_cdr_myst": { - "Tier": 2 - }, - "kz_checkmate": { - "Tier": 2 - }, - "kz_cheese": { - "Tier": 2 - }, - "kz_christmas": { - "Tier": 2 - }, - "kz_chunky_peanut_butter": { - "Tier": 2 - }, - "kz_combobreaker": { - "Tier": 2 - }, - "kz_combohop_c02": { - "Tier": 2 - }, - "kz_comboya": { - "Tier": 2 - }, - "kz_complex": { - "Tier": 2 - }, - "kz_comp_global": { - "Tier": 2 - }, - "kz_concretejungle": { - "Tier": 2 - }, - "kz_construction": { - "Tier": 2 - }, - "kz_cousucks": { - "Tier": 2 - }, - "kz_cuberunfast": { - "Tier": 2 - }, - "kz_dimensions_v1": { - "Tier": 2 - }, - "kz_doubletake": { - "Tier": 2 - }, - "kz_doveen": { - "Tier": 2 - }, - "kz_dryness": { - "Tier": 2 - }, - "kz_dungeon": { - "Tier": 2 - }, - "kz_dvn_cube_fixed": { - "Tier": 2 - }, - "kz_dvn_dull": { - "Tier": 2 - }, - "kz_dvn_redcarpet": { - "Tier": 2 - }, - "kz_dzy_beyond_v2": { - "Tier": 2 - }, - "kz_echo": { - "Tier": 2 - }, - "kz_edp445": { - "Tier": 2 - }, - "kz_egyptmap": { - "Tier": 2 - }, - "kz_eimeristzurueck": { - "Tier": 2 - }, - "kz_emblem": { - "Tier": 2 - }, - "kz_ephemeral": { - "Tier": 2 - }, - "kz_epusbridge": { - "Tier": 2 - }, - "kz_erbajerb": { - "Tier": 2 - }, - "kz_excavate": { - "Tier": 2 - }, - "kz_experiment": { - "Tier": 2 - }, - "kz_ext_bblocks": { - "Tier": 2 - }, - "kz_fabrik": { - "Tier": 2 - }, - "kz_fas2map": { - "Tier": 2 - }, - "kz_fatigue_v2": { - "Tier": 2 - }, - "kz_final_ascension": { - "Tier": 2 - }, - "kz_floatingislands": { - "Tier": 2 - }, - "kz_foggywarehouse_v2": { - "Tier": 2 - }, - "kz_forgettable": { - "Tier": 2 - }, - "kz_freezing_ridge": { - "Tier": 2 - }, - "kz_fury": { - "Tier": 2 - }, - "kz_gary": { - "Tier": 2 - }, - "kz_generic": { - "Tier": 2 - }, - "kz_genesis": { - "Tier": 2 - }, - "kz_gfy_limit": { - "Tier": 2 - }, - "kz_ggurk": { - "Tier": 2 - }, - "kz_glassesospa_v1": { - "Tier": 2 - }, - "kz_glide": { - "Tier": 2 - }, - "kz_goldenroad": { - "Tier": 2 - }, - "kz_hate": { - "Tier": 2 - }, - "kz_hb_anduu": { - "Tier": 2 - }, - "kz_hb_bacon": { - "Tier": 2 - }, - "kz_hb_fyksen": { - "Tier": 2 - }, - "kz_highland": { - "Tier": 2 - }, - "kz_holdmyhand": { - "Tier": 2 - }, - "kz_holmu1": { - "Tier": 2 - }, - "kz_iluvprok_global": { - "Tier": 2 - }, - "kz_j2s_cupblock_fix2": { - "Tier": 2 - }, - "kz_j2s_tetris": { - "Tier": 2 - }, - "kz_johndoe": { - "Tier": 2 - }, - "kz_jump_n_run": { - "Tier": 2 - }, - "kz_kiwionerous": { - "Tier": 2 - }, - "kz_kiwitown": { - "Tier": 2 - }, - "kz_kohze_sucks": { - "Tier": 2 - }, - "kz_kzra_cliffy": { - "Tier": 2 - }, - "kz_kzra_fustcaves": { - "Tier": 2 - }, - "kz_kzra_greycliff": { - "Tier": 2 - }, - "kz_kzra_stonebhop": { - "Tier": 2 - }, - "kz_kzra_stoneishbhop": { - "Tier": 2 - }, - "kz_kzra_undercastle": { - "Tier": 2 - }, - "kz_kzro_basalt": { - "Tier": 2 - }, - "kz_kzro_brickstgrass_v2": { - "Tier": 2 - }, - "kz_kzro_bronea": { - "Tier": 2 - }, - "kz_kzro_cavernste_v2": { - "Tier": 2 - }, - "kz_kzro_cryscosrun": { - "Tier": 2 - }, - "kz_kzro_excitedbhop": { - "Tier": 2 - }, - "kz_kzro_gohome": { - "Tier": 2 - }, - "kz_kzro_greybrickbhop": { - "Tier": 2 - }, - "kz_kzro_jaashs": { - "Tier": 2 - }, - "kz_kzro_mountainbhop": { - "Tier": 2 - }, - "kz_kzro_mountainhaya": { - "Tier": 2 - }, - "kz_kzro_mountainsein": { - "Tier": 2 - }, - "kz_kzro_mountainsnow": { - "Tier": 2 - }, - "kz_kzro_sunmountainset": { - "Tier": 2 - }, - "kz_kzro_whiterock": { - "Tier": 2 - }, - "kz_kzse_aztectemple": { - "Tier": 2 - }, - "kz_lazy": { - "Tier": 2 - }, - "kz_lego": { - "Tier": 2 - }, - "kz_levels": { - "Tier": 2 - }, - "kz_lookout": { - "Tier": 2 - }, - "kz_machinery": { - "Tier": 2 - }, - "kz_matilda_np": { - "Tier": 2 - }, - "kz_memento": { - "Tier": 2 - }, - "kz_metalrun_global": { - "Tier": 2 - }, - "kz_mike_v4": { - "Tier": 2 - }, - "kz_minimalism": { - "Tier": 2 - }, - "kz_minimal_combo": { - "Tier": 2 - }, - "kz_moorerutan": { - "Tier": 2 - }, - "kz_msp_comatose": { - "Tier": 2 - }, - "kz_nassau": { - "Tier": 2 - }, - "kz_nb_final": { - "Tier": 2 - }, - "kz_nuclear": { - "Tier": 2 - }, - "kz_oldstuff": { - "Tier": 2 - }, - "kz_ominous2": { - "Tier": 2 - }, - "kz_overjoyed": { - "Tier": 2 - }, - "kz_paintball_tv_fix": { - "Tier": 2 - }, - "kz_paradise": { - "Tier": 2 - }, - "kz_peak_global": { - "Tier": 2 - }, - "kz_perfunctory": { - "Tier": 2 - }, - "kz_perf_darkcave": { - "Tier": 2 - }, - "kz_pharaoh": { - "Tier": 2 - }, - "kz_pianoclimb": { - "Tier": 2 - }, - "kz_plains": { - "Tier": 2 - }, - "kz_portal_fix": { - "Tier": 2 - }, - "kz_prima": { - "Tier": 2 - }, - "kz_prismus": { - "Tier": 2 - }, - "kz_project": { - "Tier": 2 - }, - "kz_psyk": { - "Tier": 2 - }, - "kz_psytime": { - "Tier": 2 - }, - "kz_quick7_v2": { - "Tier": 2 - }, - "kz_quicksand": { - "Tier": 2 - }, - "kz_rcn_impermanence": { - "Tier": 2 - }, - "kz_redemption": { - "Tier": 2 - }, - "kz_refract": { - "Tier": 2 - }, - "kz_remedy_v2": { - "Tier": 2 - }, - "kz_retreat": { - "Tier": 2 - }, - "kz_rockclimb": { - "Tier": 2 - }, - "kz_rumzor": { - "Tier": 2 - }, - "kz_serenity": { - "Tier": 2 - }, - "kz_shaft_fix": { - "Tier": 2 - }, - "kz_signs_v2": { - "Tier": 2 - }, - "kz_skyhotel": { - "Tier": 2 - }, - "kz_skytower": { - "Tier": 2 - }, - "kz_slumpfrageous": { - "Tier": 2 - }, - "kz_snowman_v2": { - "Tier": 2 - }, - "kz_sonder": { - "Tier": 2 - }, - "kz_sp1_aoirobhop": { - "Tier": 2 - }, - "kz_sp1_blueconcrete": { - "Tier": 2 - }, - "kz_sp1_candles": { - "Tier": 2 - }, - "kz_sp1_castaway": { - "Tier": 2 - }, - "kz_sp1_greyconcrete": { - "Tier": 2 - }, - "kz_sp1_inverseblocks": { - "Tier": 2 - }, - "kz_sp1_perf2win": { - "Tier": 2 - }, - "kz_sp1_redbrickbhop": { - "Tier": 2 - }, - "kz_sp1_redconcrete": { - "Tier": 2 - }, - "kz_sp1_siedlungclimb": { - "Tier": 2 - }, - "kz_sp1_whiteblocks": { - "Tier": 2 - }, - "kz_spaceladders_v2": { - "Tier": 2 - }, - "kz_spire": { - "Tier": 2 - }, - "kz_splifff": { - "Tier": 2 - }, - "kz_splopkopsc_loverick": { - "Tier": 2 - }, - "kz_sqrdsucks": { - "Tier": 2 - }, - "kz_streetblock": { - "Tier": 2 - }, - "kz_stuff_final": { - "Tier": 2 - }, - "kz_symmetry": { - "Tier": 2 - }, - "kz_thinkblock": { - "Tier": 2 - }, - "kz_toonadventure": { - "Tier": 2 - }, - "kz_toonrun_final": { - "Tier": 2 - }, - "kz_toughluck_fix": { - "Tier": 2 - }, - "kz_tour_de_nuke_rt": { - "Tier": 2 - }, - "kz_twiivo": { - "Tier": 2 - }, - "kz_unity_u01": { - "Tier": 2 - }, - "kz_unknownspace": { - "Tier": 2 - }, - "kz_vci_apprentice": { - "Tier": 2 - }, - "kz_warehouse": { - "Tier": 2 - }, - "kz_wasabi": { - "Tier": 2 - }, - "kz_weebfactory_censored": { - "Tier": 2 - }, - "kz_weightless": { - "Tier": 2 - }, - "kz_wetbricks": { - "Tier": 2 - }, - "kz_whereyoufrom": { - "Tier": 2 - }, - "kz_woodstonegrass_final": { - "Tier": 2 - }, - "kz_woodworld": { - "Tier": 2 - }, - "kz_xmas2020": { - "Tier": 2 - }, - "kz_xtremeblock_v2": { - "Tier": 2 - }, - "xc_lucid_global": { - "Tier": 2 - }, - "xc_minecraft3_global": { - "Tier": 2 - }, - "xc_minecraft4": { - "Tier": 2 - }, - "xc_powerblock_rc1": { - "Tier": 2 - }, - "xc_skycastle": { - "Tier": 2 - }, - "xc_supermario_gfix": { - "Tier": 2 - }, - "kz_kzro_wallblocks": { - "Tier": 2 - }, - "kz_sp1_greyhollowrock": { - "Tier": 2 - }, - "kz_sp1_kansopyon": { - "Tier": 2 - }, - "kz_sp1_parallelblocks": { - "Tier": 2 - }, - "kz_sp1_rockcanyonblocks": { - "Tier": 2 - }, - "kz_sunstone": { - "Tier": 2 - }, - "bkz_greed": { - "Tier": 2 - }, - "kz_lust": { - "Tier": 2 - }, - "kz_moorish": { - "Tier": 2 - }, - "kz_opus": { - "Tier": 2 - }, - "kz_souljaboy": { - "Tier": 2 - }, - "kz_communityblock": { - "Tier": 2 - }, - "kz_comp_2022": { - "Tier": 2 - }, - "kz_sp1_shouryokou": { - "Tier": 2 - }, - "kz_sp1_spreadblocks": { - "Tier": 2 - }, - "kz_sp1_uchuunookuheki": { - "Tier": 2 - }, - "kz_victoria": { - "Tier": 2 - }, - "bkz_canadaszn": { - "Tier": 2 - }, - "kz_bing": { - "Tier": 2 - }, - "kz_greyorgray": { - "Tier": 2 - }, - "kz_cajou": { - "Tier": 2 - }, - "kz_tranquillity": { - "Tier": 2 - }, - "kz_delirium": { - "Tier": 2 - }, - "kz_devon": { - "Tier": 2 - }, - "kz_cf_snakeskin": { - "Tier": 2 - }, - "kz_glow": { - "Tier": 2 - }, - "kz_xmas2022": { - "Tier": 2 - }, - "kz_igneous": { - "Tier": 2 - }, - "kz_acores": { - "Tier": 2 - }, - "kz_desolate": { - "Tier": 2 - }, - "kz_silk": { - "Tier": 2 - }, - "kz_ehcivec": { - "Tier": 2 - }, - "kz_eilrahc": { - "Tier": 2 - }, - "kz_frenzy": { - "Tier": 2 - }, - "kz_hypothermia": { - "Tier": 2 - }, - "kz_kogamaostry": { - "Tier": 2 - }, - "kz_tmnf_e05": { - "Tier": 2 - }, - "vnl_ll_nuke": { - "Tier": 2 - }, - "kz_cakewalk": { - "Tier": 3 - }, - "kz_dontstop": { - "Tier": 3 - }, - "kz_fapzor": { - "Tier": 3 - }, - "kz_pogo": { - "Tier": 3 - }, - "kz_sahara": { - "Tier": 3 - }, - "kz_uninspired_trash": { - "Tier": 3 - }, - "kz_zephyr_v2": { - "Tier": 3 - }, - "kzpro_justrun_sp": { - "Tier": 3 - }, - "kz_21loop_final_fix": { - "Tier": 3 - }, - "kz_2fast": { - "Tier": 3 - }, - "kz_2seasons_spring_final": { - "Tier": 3 - }, - "kz_abandoned": { - "Tier": 3 - }, - "kz_adv_cursedjourney": { - "Tier": 3 - }, - "kz_ahful": { - "Tier": 3 - }, - "kz_alice_fix": { - "Tier": 3 - }, - "kz_allure": { - "Tier": 3 - }, - "kz_amber_od": { - "Tier": 3 - }, - "kz_arbitrary_words": { - "Tier": 3 - }, - "kz_arcadium": { - "Tier": 3 - }, - "kz_arcturus": { - "Tier": 3 - }, - "kz_arrebol": { - "Tier": 3 - }, - "kz_athena": { - "Tier": 3 - }, - "kz_autumn_valley_fix": { - "Tier": 3 - }, - "kz_bacho": { - "Tier": 3 - }, - "kz_basics_b02": { - "Tier": 3 - }, - "kz_beyond_fix": { - "Tier": 3 - }, - "kz_bhop_mosaic_od2": { - "Tier": 3 - }, - "kz_bhop_sakura": { - "Tier": 3 - }, - "kz_bible_black": { - "Tier": 3 - }, - "kz_bigcastle": { - "Tier": 3 - }, - "kz_binseebak": { - "Tier": 3 - }, - "kz_bionic": { - "Tier": 3 - }, - "kz_blatherskite_v1": { - "Tier": 3 - }, - "kz_blindcity_easy_fix": { - "Tier": 3 - }, - "kz_blockhardy2k": { - "Tier": 3 - }, - "kz_bloodline": { - "Tier": 3 - }, - "kz_bombu": { - "Tier": 3 - }, - "kz_bored": { - "Tier": 3 - }, - "kz_buildings_final": { - "Tier": 3 - }, - "kz_burnished": { - "Tier": 3 - }, - "kz_byrem": { - "Tier": 3 - }, - "kz_camembert": { - "Tier": 3 - }, - "kz_cascade_v4": { - "Tier": 3 - }, - "kz_cataclysm": { - "Tier": 3 - }, - "kz_catalyst_gfix": { - "Tier": 3 - }, - "kz_celestial": { - "Tier": 3 - }, - "kz_cereal": { - "Tier": 3 - }, - "kz_cg_brick_rmk": { - "Tier": 3 - }, - "kz_cg_lighthops": { - "Tier": 3 - }, - "kz_chinablock": { - "Tier": 3 - }, - "kz_coastline_fix": { - "Tier": 3 - }, - "kz_colorcode": { - "Tier": 3 - }, - "kz_colors_v2": { - "Tier": 3 - }, - "kz_concept": { - "Tier": 3 - }, - "kz_conrun_scrub": { - "Tier": 3 - }, - "kz_conspiracy": { - "Tier": 3 - }, - "kz_coronado_fix": { - "Tier": 3 - }, - "kz_correguachin_reisido": { - "Tier": 3 - }, - "kz_crash_fix": { - "Tier": 3 - }, - "kz_crypt_final": { - "Tier": 3 - }, - "kz_crysis": { - "Tier": 3 - }, - "kz_cyb_adrenaline_fix": { - "Tier": 3 - }, - "kz_dank_stacks": { - "Tier": 3 - }, - "kz_date2": { - "Tier": 3 - }, - "kz_default": { - "Tier": 3 - }, - "kz_dejavu": { - "Tier": 3 - }, - "kz_depot": { - "Tier": 3 - }, - "kz_diajonal": { - "Tier": 3 - }, - "kz_district_d01": { - "Tier": 3 - }, - "kz_drops_od": { - "Tier": 3 - }, - "kz_duality_v2": { - "Tier": 3 - }, - "kz_dust": { - "Tier": 3 - }, - "kz_dzy_reach_v2": { - "Tier": 3 - }, - "kz_edifice": { - "Tier": 3 - }, - "kz_egyptianbox": { - "Tier": 3 - }, - "kz_emptiness": { - "Tier": 3 - }, - "kz_erinome": { - "Tier": 3 - }, - "kz_excape": { - "Tier": 3 - }, - "kz_exemplum_fix": { - "Tier": 3 - }, - "kz_exps_cursedjourney": { - "Tier": 3 - }, - "kz_farm_v2": { - "Tier": 3 - }, - "kz_fastcombomap": { - "Tier": 3 - }, - "kz_fastcombowombo_v2": { - "Tier": 3 - }, - "kz_forchi": { - "Tier": 3 - }, - "kz_fused": { - "Tier": 3 - }, - "kz_futureblock": { - "Tier": 3 - }, - "kz_gallus": { - "Tier": 3 - }, - "kz_comboking7k": { - "Tier": 3 - }, - "kz_goldentabby": { - "Tier": 3 - }, - "kz_gonbe": { - "Tier": 3 - }, - "kz_green": { - "Tier": 3 - }, - "kz_halicarnassus_fs": { - "Tier": 3 - }, - "kz_hammer": { - "Tier": 3 - }, - "kz_hb_smieszneznaczki": { - "Tier": 3 - }, - "kz_heatvents_mq": { - "Tier": 3 - }, - "kz_hek": { - "Tier": 3 - }, - "kz_hellinashop": { - "Tier": 3 - }, - "kz_hikari_od": { - "Tier": 3 - }, - "kz_holyspace": { - "Tier": 3 - }, - "kz_how2slide_fix": { - "Tier": 3 - }, - "kz_hydromancy": { - "Tier": 3 - }, - "kz_ickkck": { - "Tier": 3 - }, - "kz_illusion_gfix": { - "Tier": 3 - }, - "kz_innit": { - "Tier": 3 - }, - "kz_island": { - "Tier": 3 - }, - "kz_itz_transcendent": { - "Tier": 3 - }, - "kz_jg_ditch": { - "Tier": 3 - }, - "kz_kat_colorblind": { - "Tier": 3 - }, - "kz_kzinga_fixed": { - "Tier": 3 - }, - "kz_kzra_bars": { - "Tier": 3 - }, - "kz_kzra_coast": { - "Tier": 3 - }, - "kz_kzra_hohum": { - "Tier": 3 - }, - "kz_kzra_morath": { - "Tier": 3 - }, - "kz_kzra_rockloy": { - "Tier": 3 - }, - "kz_kzra_rocky": { - "Tier": 3 - }, - "kz_kzra_skaxis": { - "Tier": 3 - }, - "kz_kzra_voovblock": { - "Tier": 3 - }, - "kz_kzra_whitesquare": { - "Tier": 3 - }, - "kz_kzro_cavehole": { - "Tier": 3 - }, - "kz_kzro_sekiseibhop": { - "Tier": 3 - }, - "kz_kzro_slidesmear": { - "Tier": 3 - }, - "kz_lair": { - "Tier": 3 - }, - "kz_lavablock_global": { - "Tier": 3 - }, - "kz_legoland": { - "Tier": 3 - }, - "kz_lego_two_redux_v3": { - "Tier": 3 - }, - "kz_life_final": { - "Tier": 3 - }, - "kz_linoleum": { - "Tier": 3 - }, - "kz_loftroofs": { - "Tier": 3 - }, - "kz_longjumps_easy": { - "Tier": 3 - }, - "kz_lost_marketplace_gfix": { - "Tier": 3 - }, - "kz_magus": { - "Tier": 3 - }, - "kz_megalodon": { - "Tier": 3 - }, - "kz_microwave": { - "Tier": 3 - }, - "kz_milehigh": { - "Tier": 3 - }, - "kz_moonlight": { - "Tier": 3 - }, - "kz_morestairs_msq": { - "Tier": 3 - }, - "kz_motivated": { - "Tier": 3 - }, - "kz_nightfall": { - "Tier": 3 - }, - "kz_nightmare_v2": { - "Tier": 3 - }, - "kz_nyc_v1": { - "Tier": 3 - }, - "kz_oasis": { - "Tier": 3 - }, - "kz_olympus": { - "Tier": 3 - }, - "kz_openspace": { - "Tier": 3 - }, - "kz_orangejuice_v2": { - "Tier": 3 - }, - "kz_orbolution_v2": { - "Tier": 3 - }, - "kz_otakuroom": { - "Tier": 3 - }, - "kz_overgrowth": { - "Tier": 3 - }, - "kz_persona_is_a_dictator": { - "Tier": 3 - }, - "kz_pineforest_v2": { - "Tier": 3 - }, - "kz_pixelrun_v2": { - "Tier": 3 - }, - "kz_pollution": { - "Tier": 3 - }, - "kz_porridge": { - "Tier": 3 - }, - "kz_prekeeper": { - "Tier": 3 - }, - "kz_progressive": { - "Tier": 3 - }, - "kz_quadrablock": { - "Tier": 3 - }, - "kz_quadrant_fix": { - "Tier": 3 - }, - "kz_quixotic": { - "Tier": 3 - }, - "kz_railings": { - "Tier": 3 - }, - "kz_rcn_optimisery": { - "Tier": 3 - }, - "kz_reach_v2": { - "Tier": 3 - }, - "kz_refuge": { - "Tier": 3 - }, - "kz_research": { - "Tier": 3 - }, - "kz_rise": { - "Tier": 3 - }, - "kz_rockjungle_v2": { - "Tier": 3 - }, - "kz_roman": { - "Tier": 3 - }, - "kz_sandstorm_ez": { - "Tier": 3 - }, - "kz_sandyhill_hoc": { - "Tier": 3 - }, - "kz_shortcut_tx": { - "Tier": 3 - }, - "kz_skybridge": { - "Tier": 3 - }, - "kz_slate": { - "Tier": 3 - }, - "kz_slide_kissa": { - "Tier": 3 - }, - "kz_slide_koira": { - "Tier": 3 - }, - "kz_slide_or_dont": { - "Tier": 3 - }, - "kz_slide_pallokala": { - "Tier": 3 - }, - "kz_smallcastle": { - "Tier": 3 - }, - "kz_smallmap": { - "Tier": 3 - }, - "kz_sn_desert": { - "Tier": 3 - }, - "kz_solidarity_v2": { - "Tier": 3 - }, - "kz_sp1_behold": { - "Tier": 3 - }, - "kz_sp1_driedblocks": { - "Tier": 3 - }, - "kz_sp1_greenconcrete": { - "Tier": 3 - }, - "kz_sp1_hallwaybhop": { - "Tier": 3 - }, - "kz_sp1_purpose": { - "Tier": 3 - }, - "kz_spacus": { - "Tier": 3 - }, - "kz_stepblock": { - "Tier": 3 - }, - "kz_stepup": { - "Tier": 3 - }, - "kz_structures": { - "Tier": 3 - }, - "kz_strun_mq": { - "Tier": 3 - }, - "kz_superstructure": { - "Tier": 3 - }, - "kz_surf_ace": { - "Tier": 3 - }, - "kz_symbiosis_final": { - "Tier": 3 - }, - "kz_synergy_ez": { - "Tier": 3 - }, - "kz_synthesis_v2": { - "Tier": 3 - }, - "kz_sz_goldenbean": { - "Tier": 3 - }, - "kz_talltreeforest_v3": { - "Tier": 3 - }, - "kz_talmaniac": { - "Tier": 3 - }, - "kz_timescape_zero": { - "Tier": 3 - }, - "kz_tron_global": { - "Tier": 3 - }, - "kz_twilight_od": { - "Tier": 3 - }, - "kz_twister": { - "Tier": 3 - }, - "kz_unity_collab": { - "Tier": 3 - }, - "kz_verv3_gg": { - "Tier": 3 - }, - "kz_village": { - "Tier": 3 - }, - "kz_vittu_mika_persse": { - "Tier": 3 - }, - "kz_void": { - "Tier": 3 - }, - "kz_waterhole": { - "Tier": 3 - }, - "kz_whatever_v2": { - "Tier": 3 - }, - "kz_yes": { - "Tier": 3 - }, - "kz_zhop_son_fix": { - "Tier": 3 - }, - "kz_zxp_interstellar_v2": { - "Tier": 3 - }, - "vnl_slidegarden": { - "Tier": 3 - }, - "vnl_undefined": { - "Tier": 3 - }, - "xc_alt_nephilim": { - "Tier": 3 - }, - "xc_dreamland2": { - "Tier": 3 - }, - "xc_fox_shrine_japan_fr": { - "Tier": 3 - }, - "xc_karo4": { - "Tier": 3 - }, - "xc_minecraft2_global": { - "Tier": 3 - }, - "xc_nephilim": { - "Tier": 3 - }, - "xc_secret_valley_global_fix": { - "Tier": 3 - }, - "xc_umbrella_global": { - "Tier": 3 - }, - "kz_sp1_xmas2021": { - "Tier": 3 - }, - "kz_kzro_tamlair": { - "Tier": 3 - }, - "kz_maya": { - "Tier": 3 - }, - "kz_sp1_rengapyon": { - "Tier": 3 - }, - "skz_pride": { - "Tier": 3 - }, - "kz_invision": { - "Tier": 3 - }, - "kz_tq": { - "Tier": 3 - }, - "kz_difficultas_discendi": { - "Tier": 3 - }, - "kz_nebula": { - "Tier": 3 - }, - "kz_chillin": { - "Tier": 3 - }, - "kz_slide_bozo": { - "Tier": 3 - }, - "kz_bhop_proxy_null": { - "Tier": 3 - }, - "kz_slide_leto": { - "Tier": 3 - }, - "kz_lovesick": { - "Tier": 3 - }, - "kz_vnl_crimdaughter": { - "Tier": 3 - }, - "kz_hideous": { - "Tier": 3 - }, - "kz_vnl_crimstmas": { - "Tier": 3 - }, - "kz_cf_slide": { - "Tier": 3 - }, - "kz_tangent": { - "Tier": 3 - }, - "kz_cf_hestia": { - "Tier": 3 - }, - "kz_mediumcastle": { - "Tier": 3 - }, - "kz_pamehcilc": { - "Tier": 3 - }, - "kz_prefix_cliche": { - "Tier": 3 - }, - "vnl_lea": { - "Tier": 3 - }, - "bkz_cauz_short": { - "Tier": 4 - }, - "bkz_evanstep": { - "Tier": 4 - }, - "bkz_iota_v3": { - "Tier": 4 - }, - "kzpro_concrete_c02": { - "Tier": 4 - }, - "kz_2seasons_winter_final": { - "Tier": 4 - }, - "kz_aaaa": { - "Tier": 4 - }, - "kz_abstruse_od2": { - "Tier": 4 - }, - "kz_andromeda": { - "Tier": 4 - }, - "kz_another_climb_map": { - "Tier": 4 - }, - "kz_antimony": { - "Tier": 4 - }, - "kz_ascend_hv": { - "Tier": 4 - }, - "kz_atelectasis_sct": { - "Tier": 4 - }, - "kz_atlantis_od3": { - "Tier": 4 - }, - "kz_azure": { - "Tier": 4 - }, - "kz_banjo": { - "Tier": 4 - }, - "kz_betapmaps": { - "Tier": 4 - }, - "kz_bhop_badges3": { - "Tier": 4 - }, - "kz_bhop_benchmark": { - "Tier": 4 - }, - "kz_bhop_composure_f": { - "Tier": 4 - }, - "kz_bhop_dusk": { - "Tier": 4 - }, - "kz_bhop_essence": { - "Tier": 4 - }, - "kz_bhop_lucid": { - "Tier": 4 - }, - "kz_bhop_northface": { - "Tier": 4 - }, - "kz_bhop_nothing": { - "Tier": 4 - }, - "kz_bhop_rotebal3": { - "Tier": 4 - }, - "kz_bhop_skyworld": { - "Tier": 4 - }, - "kz_bhop_zenith": { - "Tier": 4 - }, - "kz_birrita_fix": { - "Tier": 4 - }, - "kz_blindcity_hard_final": { - "Tier": 4 - }, - "kz_bluehop_mq": { - "Tier": 4 - }, - "kz_bluuu": { - "Tier": 4 - }, - "kz_bounce": { - "Tier": 4 - }, - "kz_cabin_fix": { - "Tier": 4 - }, - "kz_carbon": { - "Tier": 4 - }, - "kz_cdr_rustenborg": { - "Tier": 4 - }, - "kz_cdr_slash_final": { - "Tier": 4 - }, - "kz_chopchop": { - "Tier": 4 - }, - "kz_citadel": { - "Tier": 4 - }, - "kz_civilizations": { - "Tier": 4 - }, - "kz_communityjump3": { - "Tier": 4 - }, - "kz_conrun_mq": { - "Tier": 4 - }, - "kz_divided": { - "Tier": 4 - }, - "kz_dontjump": { - "Tier": 4 - }, - "kz_dyd_ladderjumps": { - "Tier": 4 - }, - "kz_epiphany_v2": { - "Tier": 4 - }, - "kz_eudora": { - "Tier": 4 - }, - "kz_eventide": { - "Tier": 4 - }, - "kz_everything": { - "Tier": 4 - }, - "kz_evilcorp": { - "Tier": 4 - }, - "kz_flabbergast": { - "Tier": 4 - }, - "kz_forgotten": { - "Tier": 4 - }, - "kz_free_ahful": { - "Tier": 4 - }, - "kz_f_salted_banana": { - "Tier": 4 - }, - "kz_shark_gc": { - "Tier": 4 - }, - "kz_gfy_blueberry": { - "Tier": 4 - }, - "kz_gfy_devcastle": { - "Tier": 4 - }, - "kz_gfy_final": { - "Tier": 4 - }, - "kz_gfy_fortroca": { - "Tier": 4 - }, - "kz_gfy_strawberry_": { - "Tier": 4 - }, - "kz_gfy_tech": { - "Tier": 4 - }, - "kz_gitgud_final": { - "Tier": 4 - }, - "kz_gloom": { - "Tier": 4 - }, - "kz_gobbledygook": { - "Tier": 4 - }, - "kz_goodluck_p": { - "Tier": 4 - }, - "kz_grass_hard": { - "Tier": 4 - }, - "kz_gy_agitation": { - "Tier": 4 - }, - "kz_haste": { - "Tier": 4 - }, - "kz_hb_lowlita": { - "Tier": 4 - }, - "kz_hb_lrs": { - "Tier": 4 - }, - "kz_headbongo": { - "Tier": 4 - }, - "kz_heaven_od": { - "Tier": 4 - }, - "kz_insomnia_fix": { - "Tier": 4 - }, - "kz_inspired": { - "Tier": 4 - }, - "kz_internatus": { - "Tier": 4 - }, - "kz_kiwi_lars": { - "Tier": 4 - }, - "kz_kzra_slidely": { - "Tier": 4 - }, - "kz_kzra_slidepuf": { - "Tier": 4 - }, - "kz_kzro_chairs": { - "Tier": 4 - }, - "kz_ladderall": { - "Tier": 4 - }, - "kz_ladderhell_fix": { - "Tier": 4 - }, - "kz_lastwork_p1": { - "Tier": 4 - }, - "kz_loathe": { - "Tier": 4 - }, - "kz_longjumps_space": { - "Tier": 4 - }, - "kz_lume": { - "Tier": 4 - }, - "kz_luv_less": { - "Tier": 4 - }, - "kz_malignom_short": { - "Tier": 4 - }, - "kz_mandelbrot": { - "Tier": 4 - }, - "kz_meander": { - "Tier": 4 - }, - "kz_mescaline_f": { - "Tier": 4 - }, - "kz_module": { - "Tier": 4 - }, - "kz_mushrruption_v8": { - "Tier": 4 - }, - "kz_neon_portal": { - "Tier": 4 - }, - "kz_nieh": { - "Tier": 4 - }, - "kz_nightcastle": { - "Tier": 4 - }, - "kz_nymph": { - "Tier": 4 - }, - "kz_pamxul_wip": { - "Tier": 4 - }, - "kz_pantheism_p02": { - "Tier": 4 - }, - "kz_prototype": { - "Tier": 4 - }, - "kz_rectangle": { - "Tier": 4 - }, - "kz_return": { - "Tier": 4 - }, - "kz_reverse": { - "Tier": 4 - }, - "kz_rompenutrias_asheglado": { - "Tier": 4 - }, - "kz_rush2sk8": { - "Tier": 4 - }, - "kz_scum": { - "Tier": 4 - }, - "kz_sendhelp_final": { - "Tier": 4 - }, - "kz_simplejourney": { - "Tier": 4 - }, - "kz_sky_lake": { - "Tier": 4 - }, - "kz_slide_0x7_n1m0": { - "Tier": 4 - }, - "kz_slide_concrete": { - "Tier": 4 - }, - "kz_slide_dydanhomon": { - "Tier": 4 - }, - "kz_slide_pisauva": { - "Tier": 4 - }, - "kz_slide_svn_temple": { - "Tier": 4 - }, - "kz_slide_vaahtera": { - "Tier": 4 - }, - "kz_south": { - "Tier": 4 - }, - "kz_sp1_hiragana": { - "Tier": 4 - }, - "kz_stranded": { - "Tier": 4 - }, - "kz_suomi": { - "Tier": 4 - }, - "kz_surf_blue": { - "Tier": 4 - }, - "kz_surf_kim_hana_gl": { - "Tier": 4 - }, - "kz_swamped_v3": { - "Tier": 4 - }, - "kz_theaquila": { - "Tier": 4 - }, - "kz_trashsurf": { - "Tier": 4 - }, - "kz_trazodon_fix": { - "Tier": 4 - }, - "kz_tribute": { - "Tier": 4 - }, - "kz_variety_fix": { - "Tier": 4 - }, - "kz_why": { - "Tier": 4 - }, - "kz_yanse": { - "Tier": 4 - }, - "kz_yoink": { - "Tier": 4 - }, - "kz_zhop_freestyle": { - "Tier": 4 - }, - "kz_zhop_function3": { - "Tier": 4 - }, - "kz_ziggurath_final": { - "Tier": 4 - }, - "kz_zoomer_fix": { - "Tier": 4 - }, - "kz_zxp_final4": { - "Tier": 4 - }, - "kz_zxp_undia": { - "Tier": 4 - }, - "vnl_cat": { - "Tier": 4 - }, - "vnl_invasion": { - "Tier": 4 - }, - "kz_winterize": { - "Tier": 4 - }, - "kz_envy": { - "Tier": 4 - }, - "kz_gluttony": { - "Tier": 4 - }, - "kz_question": { - "Tier": 4 - }, - "kz_slide_cave": { - "Tier": 4 - }, - "kz_xiaobitu": { - "Tier": 4 - }, - "kz_bhop_horseshit_9": { - "Tier": 4 - }, - "kz_demonhours": { - "Tier": 4 - }, - "kz_slide_piss": { - "Tier": 4 - }, - "kz_nomibo": { - "Tier": 4 - }, - "kz_vnl_crimson": { - "Tier": 4 - }, - "kz_itz_updown": { - "Tier": 4 - }, - "kz_sxb_poi": { - "Tier": 4 - }, - "kz_bhop_exodus": { - "Tier": 4 - }, - "kz_euclide_illusionary": { - "Tier": 4 - }, - "kz_sp1_saishuu": { - "Tier": 4 - }, - "kz_vnl_crimdaddy": { - "Tier": 4 - }, - "vnl_caverun": { - "Tier": 4 - }, - "bkz_apricity_v3": { - "Tier": 5 - }, - "bkz_fear4": { - "Tier": 5 - }, - "bkz_underground_crypt_v3": { - "Tier": 5 - }, - "kzpro_gull_pidr_reborn": { - "Tier": 5 - }, - "kz_aether_fix": { - "Tier": 5 - }, - "kz_alfie": { - "Tier": 5 - }, - "kz_alpha": { - "Tier": 5 - }, - "kz_altum_od": { - "Tier": 5 - }, - "kz_antharas": { - "Tier": 5 - }, - "kz_armored_core": { - "Tier": 5 - }, - "kz_avoria": { - "Tier": 5 - }, - "kz_backwards": { - "Tier": 5 - }, - "kz_bananaysoda_v2": { - "Tier": 5 - }, - "kz_bhop_badges2": { - "Tier": 5 - }, - "kz_carpet": { - "Tier": 5 - }, - "kz_choka_fix": { - "Tier": 5 - }, - "kz_custos": { - "Tier": 5 - }, - "kz_dethroned": { - "Tier": 5 - }, - "kz_failed_fastrun_rt": { - "Tier": 5 - }, - "kz_hb_fafnir": { - "Tier": 5 - }, - "kz_high_socks": { - "Tier": 5 - }, - "kz_hitech": { - "Tier": 5 - }, - "kz_imaginary_final": { - "Tier": 5 - }, - "kz_kiwitech": { - "Tier": 5 - }, - "kz_kzro_hexonay": { - "Tier": 5 - }, - "kz_kzro_mountainroad": { - "Tier": 5 - }, - "kz_ladderdespair": { - "Tier": 5 - }, - "kz_list_gnida_v2": { - "Tier": 5 - }, - "kz_lovely": { - "Tier": 5 - }, - "kz_modernvomit": { - "Tier": 5 - }, - "kz_nix_od": { - "Tier": 5 - }, - "kz_noobfort": { - "Tier": 5 - }, - "kz_okaychamp": { - "Tier": 5 - }, - "kz_simple_sp": { - "Tier": 5 - }, - "kz_slide_isnt_kz": { - "Tier": 5 - }, - "kz_slide_purple_x": { - "Tier": 5 - }, - "kz_slide_rovod": { - "Tier": 5 - }, - "kz_sp1_icecave": { - "Tier": 5 - }, - "kz_sp1_katakana": { - "Tier": 5 - }, - "kz_strafehop_fix": { - "Tier": 5 - }, - "kz_synergy_x": { - "Tier": 5 - }, - "kz_technical_difficulties": { - "Tier": 5 - }, - "kz_techtonic_v2_ldr": { - "Tier": 5 - }, - "skz_bananaysoda_2": { - "Tier": 5 - }, - "skz_sati": { - "Tier": 5 - }, - "skz_sequence_shot": { - "Tier": 5 - }, - "kz_sp1_vines": { - "Tier": 5 - }, - "kz_bhop_mentalism": { - "Tier": 5 - }, - "kz_dishonest": { - "Tier": 5 - }, - "kz_mess": { - "Tier": 5 - }, - "kz_sc_collapse": { - "Tier": 5 - }, - "kz_sc_surf": { - "Tier": 5 - }, - "kz_unnamed": { - "Tier": 5 - }, - "vnl_simplebrickrooms": { - "Tier": 5 - }, - "kz_bhop_algetic": { - "Tier": 5 - }, - "kz_sc_ruins": { - "Tier": 5 - }, - "kz_auuughh": { - "Tier": 5 - }, - "kz_gus_sct2": { - "Tier": 5 - }, - "kz_slide_wasteland": { - "Tier": 5 - }, - "kz_kiwiqualia": { - "Tier": 5 - }, - "kz_simplyhard": { - "Tier": 5 - }, - "kz_slide_era": { - "Tier": 5 - }, - "kz_hoist_fix": { - "Tier": 5 - }, - "kz_persona_is_a_furry": { - "Tier": 5 - }, - "kz_ggsh": { - "Tier": 5 - }, - "vnl_farewell_fix": { - "Tier": 5 - }, - "kz_sxb_biewan": { - "Tier": 5 - }, - "kz_hope": { - "Tier": 5 - }, - "kz_rlk": { - "Tier": 5 - }, - "kz_sxb_despacito": { - "Tier": 5 - }, - "kz_sxb_remake": { - "Tier": 5 - }, - "kzpro_psilocybin": { - "Tier": 6 - }, - "kz_afterlife": { - "Tier": 6 - }, - "kz_alien_city": { - "Tier": 6 - }, - "kz_angina_final": { - "Tier": 6 - }, - "kz_bhop_koki_niwa": { - "Tier": 6 - }, - "kz_blackness": { - "Tier": 6 - }, - "kz_chloroplast": { - "Tier": 6 - }, - "kz_continuum": { - "Tier": 6 - }, - "kz_drunkards": { - "Tier": 6 - }, - "kz_erratum_v2": { - "Tier": 6 - }, - "kz_gemischte_gefuehlslagen": { - "Tier": 6 - }, - "kz_goquicklol_v2": { - "Tier": 6 - }, - "kz_kareful": { - "Tier": 6 - }, - "kz_kiwi_cod": { - "Tier": 6 - }, - "kz_kzro_hardvalley": { - "Tier": 6 - }, - "kz_kzro_skyrocks": { - "Tier": 6 - }, - "kz_lionheart": { - "Tier": 6 - }, - "kz_mieszaneuczucia": { - "Tier": 6 - }, - "kz_neoncity_z": { - "Tier": 6 - }, - "kz_oloramasa": { - "Tier": 6 - }, - "kz_p1": { - "Tier": 6 - }, - "kz_pendulum": { - "Tier": 6 - }, - "kz_portalclimb": { - "Tier": 6 - }, - "kz_procrastination_f": { - "Tier": 6 - }, - "kz_psychosomatic": { - "Tier": 6 - }, - "kz_purgatory": { - "Tier": 6 - }, - "kz_retribution_v2_final": { - "Tier": 6 - }, - "kz_shell": { - "Tier": 6 - }, - "kz_slidebober": { - "Tier": 6 - }, - "kz_slidemap_fix": { - "Tier": 6 - }, - "kz_slide_deee": { - "Tier": 6 - }, - "kz_slide_svn_extreme": { - "Tier": 6 - }, - "kz_slowrun_global_fix": { - "Tier": 6 - }, - "kz_sp1_bloodyljs_v2": { - "Tier": 6 - }, - "kz_spacemario_h": { - "Tier": 6 - }, - "kz_surf_larry": { - "Tier": 6 - }, - "kz_zaloopazxc": { - "Tier": 6 - }, - "skz_makalaka": { - "Tier": 6 - }, - "skz_odious_v2": { - "Tier": 6 - }, - "vnl_oy_lj": { - "Tier": 6 - }, - "kz_bhop_slide": { - "Tier": 6 - }, - "kz_func_detail_v2": { - "Tier": 6 - }, - "kz_dabitu_fix2": { - "Tier": 6 - }, - "kz_d_decompile": { - "Tier": 6 - }, - "kz_rarkovosis": { - "Tier": 6 - }, - "kz_bozo": { - "Tier": 6 - }, - "kz_cthulhu": { - "Tier": 6 - }, - "kz_kukkojapallokidutus": { - "Tier": 6 - }, - "kz_lastwork_p2": { - "Tier": 6 - }, - "kz_scicret": { - "Tier": 6 - }, - "kz_wafflehouse_easy": { - "Tier": 6 - }, - "kz_kiwimind": { - "Tier": 6 - }, - "kz_ltt": { - "Tier": 6 - }, - "kz_mazemerized": { - "Tier": 6 - }, - "kz_slide_red": { - "Tier": 6 - }, - "kz_surf_abaddon": { - "Tier": 6 - }, - "kz_sxb_makabaka": { - "Tier": 6 - }, - "kz_sxb_xbcmzl": { - "Tier": 6 - }, - "kz_climb": { - "Tier": 6 - }, - "kz_divert": { - "Tier": 6 - }, - "kz_dystopia_h": { - "Tier": 6 - }, - "kz_hemochromatosis": { - "Tier": 6 - }, - "kz_maxine": { - "Tier": 6 - }, - "kz_monstrosity": { - "Tier": 6 - }, - "kz_nbdy_maps": { - "Tier": 6 - }, - "kz_thrombosis": { - "Tier": 6 - }, - "kz_zhongbitu": { - "Tier": 6 - }, - "kz_unmake": { - "Tier": 7 - }, - "kzpro_wrath": { - "Tier": 7 - }, - "kz_kiwideath": { - "Tier": 7 - }, - "kz_spacemario_xt": { - "Tier": 7 - }, - "kz_sp1_strafechampion": { - "Tier": 7 - }, - "kz_ladderhorror": { - "Tier": 7 - }, - "kz_slowerrun": { - "Tier": 7 - }, - "kz_wafflehouse_hard": { - "Tier": 7 - }, - "kz_kiwipsychosis": { - "Tier": 7 - }, - "vnl_sewers": { - "Tier": 7 - }, - "kz_kiwislide": { - "Tier": 7 - }, - "kz_w1_holiday": { - "Tier": 7 - }, - "kz_tense": { - "Tier": 7 - }, - "kz_cf_foliage": { - "Tier": 7 - }, - "kz_kiwiexophoric": { - "Tier": 7 - }, - "kz_kiwi_hym": { - "Tier": 7 - }, - "kz_sandbox": { - "Tier": 7 - }, - "kz_wafflehouse_x": { - "Tier": 7 - } -} diff --git a/src/API/SharpTimerAPI.cs b/src/API/SharpTimerAPI.cs new file mode 100644 index 00000000..9e6d2343 --- /dev/null +++ b/src/API/SharpTimerAPI.cs @@ -0,0 +1,80 @@ +using CounterStrikeSharp.API.Core; +using SharpTimerAPI.Events; +using SharpTimerAPI; + +namespace SharpTimer; + +public class SharpTimerAPI_Manager : ISharpTimerManager +{ + public void RestartTimer(CCSPlayerController player) + { + SharpTimer.Instance.RespawnPlayer(player); + } + + public bool IsTimerOn(CCSPlayerController player) + { + return !SharpTimer.Instance.playerTimers[player.Slot].IsTimerBlocked; + } + + public void ToggleTimer(CCSPlayerController player) + { + //should probably create a method that actually forces timer toggle. + //this one wont toggle if player is in command cd or is mid replay. + SharpTimer.Instance.ForceStopTimer(player, null!); + } + + public void BlockTimerCmd(CCSPlayerController player, bool block) + { + SharpTimer.Instance.playerTimers[player.Slot].TimerCmdBlocked = block; + } + + public void BlockRespawnCmd(CCSPlayerController player, bool block) + { + SharpTimer.Instance.playerTimers[player.Slot].RespawnCmdBlocked = block; + } +} + +public class SharpTimerAPI_EventSender : ISharpTimerEventSender +{ + public void TriggerEvent(ISharpTimerPlayerEvent @event) + { + STEventSender?.Invoke(this, @event); + } + + public event EventHandler? STEventSender; +} + +public class SharpTimerAPI_Database : ISharpTimerDatabase +{ + public async Task> GetSortedRecordsFromDatabase(int limit = 0, int bonusX = 0, string mapName = "", int style = 0) + { + var sortedRecords = await SharpTimer.Instance.GetSortedRecordsFromDatabase(limit, bonusX, mapName, style); + var mappedRecords = sortedRecords.ToDictionary( + kvp => kvp.Key, + kvp => new ISharpTimerDatabase.PlayerRecord + { + RecordID = kvp.Value.RecordID, + PlayerName = kvp.Value.PlayerName, + SteamID = kvp.Value.SteamID, + MapName = kvp.Value.MapName, + TimerTicks = kvp.Value.TimerTicks, + Replay = kvp.Value.Replay + }); + return mappedRecords; + } + + public async Task> GetAllSortedRecordsFromDatabase(int limit = 0, int bonusX = 0, int style = 0) + { + var sortedRecords = await SharpTimer.Instance.GetAllSortedRecordsFromDatabase(limit, bonusX, style); + var mappedRecords = sortedRecords.Select(record => new ISharpTimerDatabase.PlayerRecord + { + RecordID = record.RecordID, + PlayerName = record.PlayerName, + SteamID = record.SteamID, + MapName = record.MapName, + TimerTicks = record.TimerTicks, + Replay = record.Replay + }).ToList(); + return mappedRecords; + } +} diff --git a/src/API/TagsApi.dll b/src/API/TagsApi.dll new file mode 100644 index 0000000000000000000000000000000000000000..ca9eccac1da8fe6dc0404556d79eb6dc9a10cc9f GIT binary patch literal 8704 zcmeHMeQX@%nSW+>XLjviXYC{;KoTazkS|#8IwZtBKJ54-af=h(u$rEdUe}B&|P$*;ZCP2Aaq4-s-|kB2vouS zo@Zvf>uiG5(@EDq?zQJP&)56T^FH&u&pSIaeE+i)A)+XbPd*`f9cOMmf}ajEP`6(D z<5qgD>8(|-D|f!NYHUxzH7brh<(MTSXO_#hXJjqIsg{jG+34SyF-mscO188#cLYO^ z3=rL^MCihQ{m1F>YG>#=V}X()x*8JQmzKM6HgNRdAW8_W`hK&3{g*Zagq&N1CceO? z{9iit!MHn_=pmZmKwR7=h^~OFe+$vr#kx=94Wf9RJ`R3+9iQ~9gC2PADgbmc z*T8RZ(hRtibX+F~PJHVD!4qAMqptP9`=nzPZ5XnzG=YQ1GH}$j9-^&vtdKi7u4wF= zN*eun73eF86p{Yru+>4&io2Moc?MK;{YrK15->PF2$!PkuTvur3jqP*?F)o}0F(0t zLO`H}0wEwkI`|esKoAQBLO_71`xZh#&=d-Uz?2rHB6NQ+HFpD2?0R)ALaN&`5&Q&7nU+z`+HfKnMtM z6a6U&0YOVB5CVeMP#^>Z3qyer&#RB%9yUMB{R5JF!WFg;T%oO*&u&$MJI#5s|K?;W zxiPgdEjgi45wib;ldB&=PQbT*%wu)Na|-1tm&5nWA|l*qT77qhj)LZ8wtCy$L;X0v z0{#f@^XjcdI}4s0SmmA-uQfG+ppTS|6yzDFGa^OHaA29yMjTKP?iYO?2j?R0zoaz$ zC&XKp0n2$PBn#T_H0BX`8i>BB>-6t}w?=-TFQoU7Ejk^J?9p^O5nT@LZz7Dx1y2fE zBF_rFQu=;da3sQ`t)L59GmXbit2+F-fN?rRlGIPD&D2bPgv~0kyf?;LUHVQ(m?n{L zjxznR#`q|ZeZ7eR<0*6u(R)gJ4pQb0fx990oOU1PcNLBV<)LBjYT*wD~vnNl1PZds5~~G~04qJ&ck4Hrw(B zIKGSAW?MGI4il<@wAq#(aQ@w8-4A15kvw4KY|FobLu{qZwj5B8Ne(eP+wu%JB&)R9 zmTK&nsz3c3y& zF_?XB*?060unJ7!9$)q%a_6V9SxVFQ1Ma+% z0QXwJ@f^D7jez4hbkWZOj?{CgWN!srLOl=eS3W0R-%L{3WW{q@D^leC63ij}Q4z4- zBlH7clrCVgC{!@p702vO-&MB>q0bekAlsU^o2|n4nW4=@9x=q2Hz3;)AFw{WJ>PPWJ%sq}{*~GJ#_>3EVB(320T+ z@qNHA0}XN^=>T<5U4vcii|Trzlc+wckfn=gJ@6VD029X#>3usA6YW1o|eRiu%3;bSF?nm0k)u4OCHiuL8YMo|kTh?+R@Ks(1=o0s0o8 zfzeWQ2SsPNx`odG2q*D#SNOcZ{1A=EBMHJq%?#2u3q}zU4Tp{+h6AlP=N0VoM4Cp5 z)u}?c&#ai)Lb2dYLo`?|=O(&BlPq382+MWNDXUR2W|^hSDo1TxwqdN1qB(6j zJIvB0bYtdJV~0%6cC1Tk*yBqohTMUJm}=Q9HV)@szfsN}_1Q(+X;krbE~DC2a0`Cu z8@f$d-uPTh$(_e-vpnCAnn9*f#3KaJmHr{k^18^2uAXN-2VWFIu%s4vk=L=AY1gw# z$x-A-p=8kxyKGTkkrB}yo32>oF_`)M_|7s!?%kEV=~?*^$0Eln+54?Vxo;eJJmT0n zq|iM3M%ASgG}(vSPrdnkuZPUdRz3J;mnwy#w#*)u`Xe-%_>_Cds^$; zZ)K}fQ)aek)nq%W#o~NPuj^W+Y;k(5;ME)M%(@7xSJ!pSbP(G?yneC{*v`J%nBfS6 zaCDdDxLB`^%AxY4?UYPj%x3YjR(*DPvM^P}MCJ_=PJ0-hT25{7QEM_|PFmjdD3-lj zlMfbg=W47UL>Y6`Dw+p{s?&!Pz`e^?b6&0EHmi<7*48wm7P7p?hGB*O{PL-$2#01D z%<^IhijO z$#;ha%GDB<9YQ^3_gj-@wdjplPO0E>js-?ZBtg-VU4r`hGQIDTFtshzB9WQF{ACay$`93 zxKf2zE{bE>yF~TFTxvt{)xxsK3h*d*BTQC;^Ce5-yg}ysBc11_H!U}#w%)35! zp4G|ba<5J{P^x&-c!p@hlnASbK7(@wzf*`d{Nn4+?tb@&1JAtQ_w)BoeXc}NLs8-p zgA@%!TN|^j3>xz*wD^+t+tl{OZN2)E_5r1RG58_1eYicL8LHB%LVB0d9#{3&_$zme z|9#ur&7YAUhf#jOiSqMKl=&z>2q{Wz&RmV??ZY?{sveK%ZOd>hUw{jSS8EcQFX&7C zYc?BErG2<IdCv%Rk&J@?Q!e_t^zxrF41iYElchg z7~?&yw^F$=C@Ht?-;zvWfY!xxJ4t`R2Oy@aW3ihJ1IIxg|f@-ECQ$QmM%<^Omf&Io-9fJH08F-jueo>CIjF%_$Ra z0(b&sDKw5M;d%}#zU{b%J!#02G7c2HJ%$r(v_?s`9M>=%%ivEgZnaXe9qhCG)y3m) zGW-24j|Z5xtB#QiR(KLuS**~)`J0z34j@GSD^)xJbGTI4E>Pr&S5-hGis73xqMkQz z{4FWN^4Po^#z*iX_XvN#2^#G2^p4*wILnEdOLhygRi{>UjP+}h9~xA_)@I%ZvHirl!unT^PrBR-<{|)B|Ug{ z70iphoT5GOlO+FpWc;0hoFm8MhdwgrN8xhU@nbiF{x+^%MI5|3?;2w_gV`x~zgBO5 zaU{YxY`}=!cn@GA3VCEhH~uXAZ9;rf;8}AE?xBTu0%>p?p-)4b6HG&%1+^KPJTL`o z!fwoOFnSSp7y1$`iinDV?3;f#LLchy1-k$BHzf2G@Ul`@?Ed GetPreviousPlayerStageRecordFromDatabase(CCSPlayerControl return 0; } - public async Task GetPlayerPointsFromDatabase(string steamId, string? playerName = null) + public async Task GetPlayerPointsFromDatabase(CCSPlayerController? player, string steamId, string playerName) { SharpTimerDebug("Trying GetPlayerPointsFromDatabase"); int playerPoints = 0; try { + if (!IsAllowedClient(player)) + { + return playerPoints; + } + using (var connection = await OpenConnectionAsync()) { await CreatePlayerStatsTableAsync(connection); diff --git a/src/DB/Migration.cs b/src/DB/Migration.cs index 33c1741e..e1c04ce0 100644 --- a/src/DB/Migration.cs +++ b/src/DB/Migration.cs @@ -95,7 +95,7 @@ version VARCHAR(255) NOT NULL // Update the last applied migration version UpdateLastAppliedVersion(connection, version); - SharpTimerDebug($"Migration \"{version}\" successfully applied."); + Utils.LogDebug($"Migration \"{version}\" successfully applied."); } } } diff --git a/src/Extensions/CUserCmd.cs b/src/Extensions/CUserCmd.cs index 543719a7..1aec4bd1 100644 --- a/src/Extensions/CUserCmd.cs +++ b/src/Extensions/CUserCmd.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using CounterStrikeSharp.API.Modules.Utils; +using FixVectorLeak; public class CUserCmd { @@ -88,7 +89,7 @@ public unsafe void DisableInput(IntPtr userCmd, nint value) { Unsafe.Write((void*)(userCmd + 0x50), Unsafe.Read((void*)(userCmd + 0x50)) & ~(value)); } - public unsafe QAngle? GetViewAngles() + public unsafe QAngle_t? GetViewAngles() { if (Handle == IntPtr.Zero) return null; @@ -97,12 +98,12 @@ public unsafe void DisableInput(IntPtr userCmd, nint value) if (baseCmd == IntPtr.Zero) return null; - var msgQAngle = Unsafe.Read((void*)(baseCmd + 0x40)); - if (msgQAngle == IntPtr.Zero) + var msgQAngle_t = Unsafe.Read((void*)(baseCmd + 0x40)); + if (msgQAngle_t == IntPtr.Zero) return null; - var viewAngles = new QAngle(msgQAngle + 0x18); + var viewAngles = new QAngle_t(msgQAngle_t + 0x18); - return viewAngles.Handle == IntPtr.Zero ? null : viewAngles; + return viewAngles; } } \ No newline at end of file diff --git a/src/Extensions/FixVectorLeaks.cs b/src/Extensions/FixVectorLeaks.cs new file mode 100644 index 00000000..3559d798 --- /dev/null +++ b/src/Extensions/FixVectorLeaks.cs @@ -0,0 +1,280 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Memory; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Numerics; +using CounterStrikeSharp.API.Modules.Utils; + +namespace FixVectorLeak; + +public struct Vector_t : IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators +{ + public float X, Y, Z; + + public const int SIZE = 3; + + public unsafe float this[int i] + { + readonly get + { + if (i < 0 || i > SIZE) + { + throw new IndexOutOfRangeException(); + } + + fixed (void* ptr = &this) + { + return Unsafe.Read(Unsafe.Add(ptr, i)); + } + } + set + { + if (i < 0 || i > SIZE) + { + throw new IndexOutOfRangeException(); + } + + fixed (void* ptr = &this) + { + Unsafe.Write(Unsafe.Add(ptr, i), value); + } + } + } + + public Vector_t() + { + } + + public unsafe Vector_t(nint ptr) : this(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef((void*)ptr), SIZE)) + { + } + + public Vector_t(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public Vector_t(ReadOnlySpan values) + { + if (values.Length < SIZE) + { + throw new ArgumentOutOfRangeException(nameof(values)); + } + + this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + + public readonly float Length() + { + return (float)Math.Sqrt(X * X + Y * Y + Z * Z); + } + + public readonly float Length2D() + { + return (float)Math.Sqrt(X * X + Y * Y); + } + + public readonly bool IsZero(float tolerance = 0.0001f) + { + return Math.Abs(X) <= tolerance && Math.Abs(Y) <= tolerance && Math.Abs(Z) <= tolerance; + } + + public void Scale(float scale) + { + X *= scale; + Y *= scale; + Z *= scale; + } + + public readonly override string ToString() + { + return $"{X:n2} {Y:n2} {Z:n2}"; + } + + public static Vector_t operator +(Vector_t a, Vector_t b) + { + return new Vector_t(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + public static Vector_t operator -(Vector_t a, Vector_t b) + { + return new Vector_t(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + public static Vector_t operator -(Vector_t a) + { + return new Vector_t(-a.X, -a.Y, -a.Z); + } + + public static Vector_t operator *(Vector_t a, float b) + { + return new Vector_t(a.X * b, a.Y * b, a.Z * b); + } + + public static Vector_t operator /(Vector_t a, float b) + { + return new Vector_t(a.X / b, a.Y / b, a.Z / b); + } +} + +public struct QAngle_t : IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators +{ + public float X, Y, Z; + + public const int SIZE = 3; + + public unsafe float this[int i] + { + readonly get + { + if (i < 0 || i > SIZE) + { + throw new IndexOutOfRangeException(); + } + + fixed (void* ptr = &this) + { + return Unsafe.Read(Unsafe.Add(ptr, i)); + } + } + set + { + if (i < 0 || i > SIZE) + { + throw new IndexOutOfRangeException(); + } + + fixed (void* ptr = &this) + { + Unsafe.Write(Unsafe.Add(ptr, i), value); + } + } + } + + public QAngle_t() + { + } + + public unsafe QAngle_t(nint ptr) : this(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef((void*)ptr), SIZE)) + { + } + + public QAngle_t(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public QAngle_t(ReadOnlySpan values) + { + if (values.Length < SIZE) + { + throw new ArgumentOutOfRangeException(nameof(values)); + } + + this = Unsafe.ReadUnaligned(ref Unsafe.As(ref MemoryMarshal.GetReference(values))); + } + + public unsafe (Vector_t fwd, Vector_t right, Vector_t up) AngleVectors() + { + Vector_t fwd = default, right = default, up = default; + + nint pFwd = (nint)Unsafe.AsPointer(ref fwd); + nint pRight = (nint)Unsafe.AsPointer(ref right); + nint pUp = (nint)Unsafe.AsPointer(ref up); + + fixed (void* ptr = &this) + { + NativeAPI.AngleVectors((nint)ptr, pFwd, pRight, pUp); + } + + return (fwd, right, up); + } + + public unsafe void AngleVectors(out Vector_t fwd, out Vector_t right, out Vector_t up) + { + fixed (void* ptr = &this, pFwd = &fwd, pRight = &right, pUp = &up) + { + NativeAPI.AngleVectors((nint)ptr, (nint)pFwd, (nint)pRight, (nint)pUp); + } + } + + public readonly override string ToString() + { + return $"{X:n2} {Y:n2} {Z:n2}"; + } + + public static QAngle_t operator +(QAngle_t a, QAngle_t b) + { + return new QAngle_t(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + public static QAngle_t operator -(QAngle_t a, QAngle_t b) + { + return new QAngle_t(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + public static QAngle_t operator -(QAngle_t a) + { + return new QAngle_t(-a.X, -a.Y, -a.Z); + } + + public static QAngle_t operator *(QAngle_t a, float b) + { + return new QAngle_t(a.X * b, a.Y * b, a.Z * b); + } + + public static QAngle_t operator /(QAngle_t a, float b) + { + return new QAngle_t(a.X / b, a.Y / b, a.Z / b); + } +} + +unsafe static class Extensions +{ + public static void Teleport(this CBaseEntity entity, Vector_t? position = null, QAngle_t? angles = null, Vector_t? velocity = null) + { + Guard.IsValidEntity(entity); + + void* pPos = null, pAng = null, pVel = null; + + // Structs are stored on the stack, GC should not break pointers. + + if (position.HasValue) + { + var pos = position.Value; // Remove nullable wrapper + pPos = &pos; + } + + if (angles.HasValue) + { + var ang = angles.Value; + pAng = ∠ + } + + if (velocity.HasValue) + { + var vel = velocity.Value; + pVel = &vel; + } + + VirtualFunction.CreateVoid(entity.Handle, GameData.GetOffset("CBaseEntity_Teleport"))(entity.Handle, (nint)pPos, + (nint)pAng, (nint)pVel); + } + + public static (Vector_t fwd, Vector_t right, Vector_t up) AngleVectors(this QAngle vec) => vec.ToQAngle_t().AngleVectors(); + public static void AngleVectors(this QAngle vec, out Vector_t fwd, out Vector_t right, out Vector_t up) => vec.ToQAngle_t().AngleVectors(out fwd, out right, out up); + + public static Vector_t ToVector_t(this CounterStrikeSharp.API.Modules.Utils.Vector vec) => new(vec.Handle); + public static QAngle_t ToQAngle_t(this QAngle vec) => new(vec.Handle); +} \ No newline at end of file diff --git a/src/Extensions/ForceFullUpdate.cs b/src/Extensions/ForceFullUpdate.cs index db5fcadc..47042d52 100644 --- a/src/Extensions/ForceFullUpdate.cs +++ b/src/Extensions/ForceFullUpdate.cs @@ -13,7 +13,7 @@ struct CUtlMemory } [StructLayout(LayoutKind.Sequential)] -struct CUtlVector +struct CUtlVector_t { public unsafe nint this[int index] { @@ -46,17 +46,17 @@ public class INetworkGameServer : NativeObject { private static int SlotsOffset = GameData.GetOffset("INetworkGameServer_Slots"); - private CUtlVector Slots; + private CUtlVector_t Slots; public INetworkGameServer(nint ptr) : base(ptr) { - this.Slots = Marshal.PtrToStructure(base.Handle + SlotsOffset); + this.Slots = Marshal.PtrToStructure(base.Handle + SlotsOffset); } - public CServerSideClient? GetClientBySlot(int playerSlot) + public CServerSideClient? GetClientBySlot(int slot) { - if (playerSlot >= 0 && playerSlot < this.Slots.m_iSize) - return this.Slots[playerSlot] == IntPtr.Zero ? null : new CServerSideClient(this.Slots[playerSlot]); + if (slot >= 0 && slot < this.Slots.m_iSize) + return this.Slots[slot] == IntPtr.Zero ? null : new CServerSideClient(this.Slots[slot]); return null; } diff --git a/src/Features/Anticheat.cs b/src/Features/Anticheat.cs index 85bd26c4..ab0e3b6d 100644 --- a/src/Features/Anticheat.cs +++ b/src/Features/Anticheat.cs @@ -4,7 +4,7 @@ using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Utils; +using FixVectorLeak; using static SharpTimer.PlayerTimerInfo; namespace SharpTimer @@ -16,7 +16,7 @@ public partial class SharpTimer // Strafe optimization detection // Store the last 200 viewangles of the player; viewangles are gathered (at fastest) each tick. 200ticks is around 4 strafes - public void ParseStrafes(CCSPlayerController? player, QAngle viewangles) + public void ParseStrafes(CCSPlayerController? player, QAngle_t viewangles) { var playerTimer = playerTimers[player!.Slot]; @@ -80,12 +80,12 @@ public void ParseStrafes(CCSPlayerController? player, QAngle viewangles) playerTimer.YawSpikeFlagged = true; StartStopRecord(player, "Unusually frequent m_yaw accel spikes (Strafe optimizer)"); Server.NextFrame(async () => await DiscordACMessage(player, "Unusually frequent m_yaw accel spikes (Strafe optimizer)")); - SharpTimerConPrint($"::::BEGIN:::: Yaw Accel Spike % of Total"); + Utils.ConPrint($"::::BEGIN:::: Yaw Accel Spike % of Total"); foreach (var percent in playerTimer.YawAccelPercents) { - SharpTimerConPrint($"Spike %: {percent}"); + Utils.ConPrint($"Spike %: {percent}"); } - SharpTimerConPrint($"::::END:::: Yaw Accel Spike % of Total"); + Utils.ConPrint($"::::END:::: Yaw Accel Spike % of Total"); } } @@ -175,8 +175,8 @@ private void StartStopRecord(CCSPlayerController player, string reason) var name = player.PlayerName.Replace(" ", "-").Replace("\\", "-").Replace("/", "-"); var file = $"{currentMapName}_{name}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; - SharpTimerConPrint($"[AC] Unusal input detected, demo will be available at demos/{file} in 60 seconds"); - SharpTimerConPrint($"[AC] Reason: {reason}"); + Utils.ConPrint($"[AC] Unusal input detected, demo will be available at demos/{file} in 60 seconds"); + Utils.ConPrint($"[AC] Reason: {reason}"); Server.ExecuteCommand($"tv_record demos/{file}"); AddTimer(60.0f, () => Server.ExecuteCommand("tv_stoprecord")); }); @@ -198,8 +198,9 @@ public void GetFlaggedCommand(CCSPlayerController? player, CommandInfo command) } Server.NextFrame(() => { - SharpTimerConPrint($"Flagged players: {flaggedPlayers}"); - if (player is not null) player!.PrintToChat($"Flagged players: {flaggedPlayers}"); + Utils.ConPrint($"Flagged players: {flaggedPlayers}"); + if (player is not null) + Utils.PrintToChat(player, $"Flagged players: {flaggedPlayers}"); }); } } diff --git a/src/Features/DiscordWebhook.cs b/src/Features/DiscordWebhook.cs index b788cfb1..c54b155f 100644 --- a/src/Features/DiscordWebhook.cs +++ b/src/Features/DiscordWebhook.cs @@ -27,7 +27,7 @@ private async Task GetDiscordWebhookURLFromConfigFile(string discordURLpath) { try { - using JsonDocument? jsonConfig = await LoadJson(discordURLpath)!; + using JsonDocument? jsonConfig = await Utils.LoadJson(discordURLpath)!; if (jsonConfig != null) { JsonElement root = jsonConfig.RootElement; @@ -37,7 +37,7 @@ T GetPropertyValue(string propertyName, T defaultValue, Func try { return getValue(property); } catch (Exception ex) { - SharpTimerError($"Error parsing {propertyName}: {ex.Message}"); + Utils.LogError($"Error parsing {propertyName}: {ex.Message}"); return defaultValue; } } @@ -82,12 +82,12 @@ T GetPropertyValue(string propertyName, T defaultValue, Func } else { - SharpTimerError($"DiscordWebhookUrl json was null"); + Utils.LogError($"DiscordWebhookUrl json was null"); } } catch (Exception ex) { - SharpTimerError($"Error in GetDiscordWebhookURLFromConfigFile: {ex.Message}"); + Utils.LogError($"Error in GetDiscordWebhookURLFromConfigFile: {ex.Message}"); } } @@ -107,7 +107,7 @@ public async Task DiscordRecordMessage(CCSPlayerController? player, string playe if (string.IsNullOrEmpty(webhookURL) || webhookURL == "your_discord_webhook_url") { - SharpTimerError($"DiscordWebhookUrl was invalid"); + Utils.LogError($"DiscordWebhookUrl was invalid"); return; } @@ -257,12 +257,12 @@ public async Task DiscordRecordMessage(CCSPlayerController? player, string playe if (!response.IsSuccessStatusCode) { - SharpTimerError($"Failed to send message. Status code: {response.StatusCode}"); + Utils.LogError($"Failed to send message. Status code: {response.StatusCode}"); } } catch (Exception ex) { - SharpTimerError($"An error occurred while sending Discord PB message: {ex.Message}"); + Utils.LogError($"An error occurred while sending Discord PB message: {ex.Message}"); } } @@ -274,7 +274,7 @@ public async Task DiscordACMessage(CCSPlayerController? player, string reason) if (string.IsNullOrEmpty(webhookURL)) { - SharpTimerError($"DiscordACWebhookUrl was invalid"); + Utils.LogError($"DiscordACWebhookUrl was invalid"); return; } using var client = new HttpClient(); @@ -351,12 +351,12 @@ public async Task DiscordACMessage(CCSPlayerController? player, string reason) if (!response.IsSuccessStatusCode) { - SharpTimerError($"Failed to send message. Status code: {response.StatusCode}"); + Utils.LogError($"Failed to send message. Status code: {response.StatusCode}"); } } catch (Exception ex) { - SharpTimerError($"An error occurred while sending Discord AC message: {ex.Message}"); + Utils.LogError($"An error occurred while sending Discord AC message: {ex.Message}"); } } @@ -371,7 +371,7 @@ public async Task GetMapImage(int bonusX = 0) } string imageRepo = $"{discordWebhookImageRepoURL}{(bonusX == 0 ? currentMapName : $"{currentMapName}_b{bonusX}")}.jpg"; - string error = $"{discordWebhookImageRepoURL}{(currentMapName!.Contains("surf_") ? "surf404" : $"{(currentMapName!.Contains("kz_") ? "kz404" : $"{(currentMapName!.Contains("bhop_") ? "bhop404" : "404")}")}")}.jpg"; + string error = $"{discordWebhookImageRepoURL}{(currentMapName!.Contains("surf_") ? "surf404" : $"{(currentMapName!.Contains("bhop_") ? "bhop404" : "404")}")}.jpg"; try { using var client = new HttpClient(); @@ -386,7 +386,7 @@ public async Task GetMapImage(int bonusX = 0) } catch (Exception ex) { - SharpTimerError($"Failed to get DiscordWebhook img. {ex.Message}"); + Utils.LogError($"Failed to get DiscordWebhook img. {ex.Message}"); return error; } } @@ -425,7 +425,7 @@ public async Task GetAvatarLink(string xmlUrl) } catch (Exception ex) { - SharpTimerError("GetAvatarLink Error occurred: " + ex.Message); + Utils.LogError("GetAvatarLink Error occurred: " + ex.Message); return "https://cdn.discordapp.com/icons/1196646791450472488/634963a8207fdb1b30bf909d31f05e57.webp"; } } diff --git a/src/Features/FakeZoneTool.cs b/src/Features/FakeZoneTool.cs index fd9db2e2..a4629745 100644 --- a/src/Features/FakeZoneTool.cs +++ b/src/Features/FakeZoneTool.cs @@ -22,6 +22,7 @@ You should have received a copy of the GNU General Public License using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Menu; using CounterStrikeSharp.API.Modules.Utils; +using FixVectorLeak; namespace SharpTimer { @@ -63,7 +64,7 @@ public void AddStartZoneCommand(CCSPlayerController? player) playerTimers[player.Slot].IsAddingStartZone = false; playerTimers[player.Slot].IsAddingEndZone = false; playerTimers[player.Slot].StartZoneC2 = $"{player.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.X} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Y} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Z}"; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Startzone set..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Startzone set..."); } else { @@ -71,8 +72,8 @@ public void AddStartZoneCommand(CCSPlayerController? player) playerTimers[player.Slot].StartZoneC2 = ""; playerTimers[player.Slot].IsAddingStartZone = true; playerTimers[player.Slot].IsAddingEndZone = false; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!1 {ChatColors.Default}again"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!1 {ChatColors.Default}again"); } } @@ -85,7 +86,7 @@ public void AddEndZoneCommand(CCSPlayerController? player) playerTimers[player.Slot].IsAddingStartZone = false; playerTimers[player.Slot].IsAddingEndZone = false; playerTimers[player.Slot].EndZoneC2 = $"{player.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.X} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Y} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Z}"; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Endzone set..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Endzone set..."); } else { @@ -93,8 +94,8 @@ public void AddEndZoneCommand(CCSPlayerController? player) playerTimers[player.Slot].EndZoneC2 = ""; playerTimers[player.Slot].IsAddingStartZone = false; playerTimers[player.Slot].IsAddingEndZone = true; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!2 {ChatColors.Default}again"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!2 {ChatColors.Default}again"); } } @@ -103,12 +104,12 @@ public void AddRespawnPosCommand(CCSPlayerController? player) if (!IsAllowedPlayer(player)) return; // Get the player's current position - Vector currentPosition = player!.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); + Vector_t currentPosition = player!.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t() ?? new Vector_t(0, 0, 0); // Convert position string positionString = $"{currentPosition.X} {currentPosition.Y} {currentPosition.Z}"; playerTimers[player.Slot].RespawnPos = positionString; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}RespawnPos added!"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}RespawnPos added!"); } public void SaveZonesCommand(CCSPlayerController? player) @@ -117,7 +118,7 @@ public void SaveZonesCommand(CCSPlayerController? player) if (playerTimers[player!.Slot].EndZoneC1 == null || playerTimers[player.Slot].EndZoneC2 == null || playerTimers[player.Slot].StartZoneC1 == null || playerTimers[player.Slot].StartZoneC2 == null || playerTimers[player.Slot].RespawnPos == null) { - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Red}Please make sure you have done all 3 zoning steps (startzone, endzone, respawnpos)"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Red}Please make sure you have done all 3 zoning steps (startzone, endzone, respawnpos)"); return; } @@ -136,7 +137,7 @@ public void SaveZonesCommand(CCSPlayerController? player) string updatedJson = JsonSerializer.Serialize(newMapInfo, jsonSerializerOptions); File.WriteAllText(mapdataPath, updatedJson); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Zones saved successfully! {ChatColors.Grey}Reloading data..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Zones saved successfully! {ChatColors.Grey}Reloading data..."); Server.ExecuteCommand("mp_restartgame 1"); } @@ -152,7 +153,7 @@ public void AddBonusStartZoneCommand(CCSPlayerController? player, CommandInfo co playerTimers[player.Slot].IsAddingBonusStartZone = false; playerTimers[player.Slot].IsAddingBonusEndZone = false; playerTimers[player.Slot].BonusStartZoneC2 = $"{player.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.X} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Y} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Z}"; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Bonus Startzone set..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Bonus Startzone set..."); } else { @@ -160,8 +161,8 @@ public void AddBonusStartZoneCommand(CCSPlayerController? player, CommandInfo co playerTimers[player.Slot].BonusStartZoneC2 = ""; playerTimers[player.Slot].IsAddingBonusStartZone = true; playerTimers[player.Slot].IsAddingBonusEndZone = false; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!addbonusstartzone {ChatColors.Default}again"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!addbonusstartzone {ChatColors.Default}again"); } } @@ -177,7 +178,7 @@ public void AddBonusEndZoneCommand(CCSPlayerController? player, CommandInfo comm playerTimers[player.Slot].IsAddingBonusStartZone = false; playerTimers[player.Slot].IsAddingBonusEndZone = false; playerTimers[player.Slot].BonusEndZoneC2 = $"{player.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.X} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Y} {player.Pawn.Value.CBodyComponent?.SceneNode?.AbsOrigin.Z}"; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Bonus Endzone set..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Grey}Bonus Endzone set..."); } else { @@ -185,8 +186,8 @@ public void AddBonusEndZoneCommand(CCSPlayerController? player, CommandInfo comm playerTimers[player.Slot].BonusEndZoneC2 = ""; playerTimers[player.Slot].IsAddingBonusStartZone = false; playerTimers[player.Slot].IsAddingBonusEndZone = true; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!addbonusendzone {ChatColors.Default}again"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Please go to the opposite zone corner now"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}and type {primaryChatColor}!addbonusendzone {ChatColors.Default}again"); } } @@ -198,12 +199,12 @@ public void AddBonusRespawnPosCommand(CCSPlayerController? player, CommandInfo c if (!IsAllowedPlayer(player)) return; // Get the player's current position - Vector currentPosition = player!.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); + Vector_t? currentPosition = player!.Pawn.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t(); // Convert position - string positionString = $"{currentPosition.X} {currentPosition.Y} {currentPosition.Z}"; + string positionString = $"{currentPosition.GetValueOrDefault().X} {currentPosition.GetValueOrDefault().Y} {currentPosition.GetValueOrDefault().Z}"; playerTimers[player.Slot].BonusRespawnPos = positionString; - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Bonus RespawnPos added!"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Bonus RespawnPos added!"); } [ConsoleCommand("css_savebonuszones", "Saves defined zones")] @@ -215,14 +216,14 @@ public void SaveBonusZonesCommand(CCSPlayerController? player, CommandInfo comma if (playerTimers[player!.Slot].BonusEndZoneC1 == null || playerTimers[player.Slot].BonusEndZoneC2 == null || playerTimers[player.Slot].BonusStartZoneC1 == null || playerTimers[player.Slot].BonusStartZoneC2 == null || playerTimers[player.Slot].BonusRespawnPos == null) { - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Red}Please make sure you have done all 3 zoning steps (!addbonusstartzone, !addbonusendzone, !addbonusrespawnpos)"); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Red}Please make sure you have done all 3 zoning steps (!addbonusstartzone, !addbonusendzone, !addbonusrespawnpos)"); return; } if (!int.TryParse(command.ArgString, out int bonusX)) { - SharpTimerDebug("SaveBonusZones failed, not vaild integer."); - player.PrintToChat($" {Localizer["prefix"]} Please enter a valid Bonus stage i.e: {primaryChatColor}!savebonuszones "); + Utils.LogDebug("SaveBonusZones failed, not vaild integer."); + Utils.PrintToChat(player, $"Please enter a valid Bonus stage i.e: {primaryChatColor}!savebonuszones "); return; } @@ -241,7 +242,7 @@ public void SaveBonusZonesCommand(CCSPlayerController? player, CommandInfo comma string updatedJson = JsonSerializer.Serialize(newMapInfo, jsonSerializerOptions); File.WriteAllText(mapdataPath, updatedJson); - player.PrintToChat($" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Bonus {bonusX} Zones saved successfully! {ChatColors.Grey}Reloading data..."); + Utils.PrintToChat(player, $" {ChatColors.LightPurple}[ZONE TOOL] {ChatColors.Default}Bonus {bonusX} Zones saved successfully! {ChatColors.Grey}Reloading data..."); Server.ExecuteCommand("mp_restartgame 1"); } @@ -266,120 +267,120 @@ public void OnTickZoneTool(CCSPlayerController? player) { if (playerTimer.IsAddingStartZone) { - Vector pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); - DrawZoneToolWireframe(ParseVector(playerTimer.StartZoneC1!), pawnPosition, player.Slot); + Vector_t pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t() ?? new Vector_t(0, 0, 0); + DrawZoneToolWireframe(Utils.ParseVector_t(playerTimer.StartZoneC1!), pawnPosition, player.Slot); } else if (playerTimer.IsAddingEndZone) { - Vector pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); - DrawZoneToolWireframe(ParseVector(playerTimer.EndZoneC1!), pawnPosition, player.Slot); + Vector_t pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t() ?? new Vector_t(0, 0, 0); + DrawZoneToolWireframe(Utils.ParseVector_t(playerTimer.EndZoneC1!), pawnPosition, player.Slot); } else if (playerTimer.IsAddingBonusStartZone) { - Vector pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); - DrawZoneToolWireframe(ParseVector(playerTimer.BonusStartZoneC1!), pawnPosition, player.Slot); + Vector_t pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t() ?? new Vector_t(0, 0, 0); + DrawZoneToolWireframe(Utils.ParseVector_t(playerTimer.BonusStartZoneC1!), pawnPosition, player.Slot); } else if (playerTimer.IsAddingBonusEndZone) { - Vector pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin ?? new Vector(0, 0, 0); - DrawZoneToolWireframe(ParseVector(playerTimer.BonusEndZoneC1!), pawnPosition, player.Slot); + Vector_t pawnPosition = player.Pawn?.Value!.CBodyComponent?.SceneNode?.AbsOrigin.ToVector_t() ?? new Vector_t(0, 0, 0); + DrawZoneToolWireframe(Utils.ParseVector_t(playerTimer.BonusEndZoneC1!), pawnPosition, player.Slot); } } } catch (Exception ex) { if (ex.Message != "Invalid game event") - SharpTimerError($"Error in OnTickZoneTool: {ex.Message}"); + Utils.LogError($"Error in OnTickZoneTool: {ex.Message}"); } } - public void DrawZoneToolWireframe(Vector corner1, Vector corner8, int playerSlot) + public void DrawZoneToolWireframe(Vector_t? corner1, Vector_t? corner8, int slot) { try { - Vector corner2 = new(corner1.X, corner8.Y, corner1.Z); - Vector corner3 = new(corner8.X, corner8.Y, corner1.Z); - Vector corner4 = new(corner8.X, corner1.Y, corner1.Z); + Vector_t? corner2 = new(corner1!.Value.X, corner8!.Value.Y, corner1.Value.Z); + Vector_t? corner3 = new(corner8.Value.X, corner8.Value.Y, corner1.Value.Z); + Vector_t? corner4 = new(corner8.Value.X, corner1.Value.Y, corner1.Value.Z); - Vector corner5 = new(corner8.X, corner1.Y, corner8.Z); - Vector corner6 = new(corner1.X, corner1.Y, corner8.Z); - Vector corner7 = new(corner1.X, corner8.Y, corner8.Z); + Vector_t? corner5 = new(corner8.Value.X, corner1.Value.Y, corner8.Value.Z); + Vector_t? corner6 = new(corner1.Value.X, corner1.Value.Y, corner8.Value.Z); + Vector_t? corner7 = new(corner1.Value.X, corner8.Value.Y, corner8.Value.Z); if (corner1 != null && corner2 != null && corner3 != null && corner4 != null && corner5 != null && corner6 != null && corner7 != null && corner8 != null) { // top square - DrawZoneToolWire(corner1, corner2, playerSlot, 1); - DrawZoneToolWire(corner2, corner3, playerSlot, 2); - DrawZoneToolWire(corner3, corner4, playerSlot, 3); - DrawZoneToolWire(corner4, corner1, playerSlot, 4); + DrawZoneToolWire(corner1, corner2, slot, 1); + DrawZoneToolWire(corner2, corner3, slot, 2); + DrawZoneToolWire(corner3, corner4, slot, 3); + DrawZoneToolWire(corner4, corner1, slot, 4); // bottom square - DrawZoneToolWire(corner5, corner6, playerSlot, 5); - DrawZoneToolWire(corner6, corner7, playerSlot, 6); - DrawZoneToolWire(corner7, corner8, playerSlot, 7); - DrawZoneToolWire(corner8, corner5, playerSlot, 8); + DrawZoneToolWire(corner5, corner6, slot, 5); + DrawZoneToolWire(corner6, corner7, slot, 6); + DrawZoneToolWire(corner7, corner8, slot, 7); + DrawZoneToolWire(corner8, corner5, slot, 8); // connect them both to build a cube, - DrawZoneToolWire(corner1, corner6, playerSlot, 9); - DrawZoneToolWire(corner2, corner7, playerSlot, 10); - DrawZoneToolWire(corner3, corner8, playerSlot, 11); - DrawZoneToolWire(corner4, corner5, playerSlot, 12); + DrawZoneToolWire(corner1, corner6, slot, 9); + DrawZoneToolWire(corner2, corner7, slot, 10); + DrawZoneToolWire(corner3, corner8, slot, 11); + DrawZoneToolWire(corner4, corner5, slot, 12); } else { - SharpTimerDebug("One of the vectors is null in DrawZoneToolWireframe"); + Utils.LogDebug("One of the Vector_ts is null in DrawZoneToolWireframe"); } } catch (Exception ex) { - SharpTimerError($"Error in DrawZoneToolWireframe: {ex.Message}"); + Utils.LogError($"Error in DrawZoneToolWireframe: {ex.Message}"); } } - public void DrawZoneToolWire(Vector startPos, Vector endPos, int playerSlot, int wireIndex) + public void DrawZoneToolWire(Vector_t? startPos, Vector_t? endPos, int slot, int wireIndex) { try { - if (playerTimers.ContainsKey(playerSlot) && playerTimers[playerSlot] != null) + if (playerTimers.ContainsKey(slot) && playerTimers[slot] != null) { - if (!playerTimers[playerSlot].ZoneToolWire!.ContainsKey(wireIndex)) + if (!playerTimers[slot].ZoneToolWire!.ContainsKey(wireIndex)) { - playerTimers[playerSlot].ZoneToolWire![wireIndex] = Utilities.CreateEntityByName("beam")!; + playerTimers[slot].ZoneToolWire![wireIndex] = Utilities.CreateEntityByName("beam")!; } else { - playerTimers[playerSlot].ZoneToolWire![wireIndex].Remove(); - playerTimers[playerSlot].ZoneToolWire![wireIndex] = Utilities.CreateEntityByName("beam")!; + playerTimers[slot].ZoneToolWire![wireIndex].Remove(); + playerTimers[slot].ZoneToolWire![wireIndex] = Utilities.CreateEntityByName("beam")!; } - CBeam wire = playerTimers[playerSlot].ZoneToolWire![wireIndex]; + CBeam wire = playerTimers[slot].ZoneToolWire![wireIndex]; if (wire != null) { wire.Render = Color.Green; wire.Width = 1.5f; - wire.Teleport(startPos, new QAngle(0, 0, 0), new Vector(0, 0, 0)); - wire.EndPos.X = endPos.X; - wire.EndPos.Z = endPos.Z; - wire.EndPos.Y = endPos.Y; + wire.Teleport(startPos, new QAngle_t(0, 0, 0), new Vector_t(0, 0, 0)); + wire.EndPos.X = endPos!.Value.X; + wire.EndPos.Z = endPos.Value.Z; + wire.EndPos.Y = endPos.Value.Y; wire.FadeMinDist = 9999; wire.DispatchSpawn(); } else { - SharpTimerDebug($"Failed to create ZoneTool beam for wireIndex {wireIndex}..."); + Utils.LogDebug($"Failed to create ZoneTool beam for wireIndex {wireIndex}..."); } } else { - SharpTimerDebug($"Player slot {playerSlot} not found in the dictionary."); + Utils.LogDebug($"Player slot {slot} not found in the dictionary."); } } catch (Exception ex) { - SharpTimerError($"Error in DrawZoneToolWire: {ex.Message}"); + Utils.LogError($"Error in DrawZoneToolWire: {ex.Message}"); } } } diff --git a/src/Features/GlobalAPI.cs b/src/Features/GlobalAPI.cs index 0608d7ac..19abf424 100644 --- a/src/Features/GlobalAPI.cs +++ b/src/Features/GlobalAPI.cs @@ -39,16 +39,16 @@ public async Task SubmitRecordAsync(object payload) if (response.IsSuccessStatusCode) { - SharpTimerConPrint("Record submitted successfully."); + Utils.ConPrint("Record submitted successfully."); } else { - SharpTimerError($"Failed to submit record. Status code: {response.StatusCode}"); + Utils.LogError($"Failed to submit record. Status code: {response.StatusCode}"); } } catch (Exception ex) { - SharpTimerError($"Error in SubmitRecordAsync: {ex.Message}"); + Utils.LogError($"Error in SubmitRecordAsync: {ex.Message}"); } } @@ -76,7 +76,7 @@ public async Task CheckAddonAsync() workshop_id = currentAddonID }; string jsonPayload = JsonSerializer.Serialize(payload); - SharpTimerDebug($"CheckAddon payload: {jsonPayload}"); + Utils.LogDebug($"CheckAddon payload: {jsonPayload}"); var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); client.DefaultRequestHeaders.Clear(); @@ -92,7 +92,7 @@ public async Task CheckAddonAsync() } catch (Exception ex) { - SharpTimerError($"Error in CheckAddonAsync: {ex.Message}"); + Utils.LogError($"Error in CheckAddonAsync: {ex.Message}"); return false; } } @@ -122,7 +122,7 @@ public async Task CacheGlobalPoints() public async Task> GetTopPointsAsync(int limit = 10) { if (apiKey == "") - return null; + return null!; try { @@ -161,19 +161,19 @@ public async Task> GetTopPointsAsync(int limit = 10) } return player_points; } - return null; + return null!; } } else { - SharpTimerError($"Failed to get top points. Status code: {response.StatusCode}; Message: {response.Content}"); - return null; + Utils.LogError($"Failed to get top points. Status code: {response.StatusCode}; Message: {response.Content}"); + return null!; } } catch (Exception ex) { - SharpTimerError($"Error in GetRecordIDAsync: {ex.Message}"); - return null; + Utils.LogError($"Error in GetRecordIDAsync: {ex.Message}"); + return null!; } } @@ -204,25 +204,25 @@ public async Task GetRecordIDAsync(object payload) } else { - SharpTimerError($"No record ID found"); + Utils.LogError($"No record ID found"); return 0; } } } else { - SharpTimerError($"Failed to retrieve record_id. Status code: {response.StatusCode}; Message: {response.Content}"); + Utils.LogError($"Failed to retrieve record_id. Status code: {response.StatusCode}; Message: {response.Content}"); return 0; } } catch (Exception ex) { - SharpTimerError($"Error in GetRecordIDAsync: {ex.Message}"); + Utils.LogError($"Error in GetRecordIDAsync: {ex.Message}"); return 0; } } - public async Task<(int, int, int)> GetGlobalRank(CCSPlayerController? player) + public async Task<(int, int, int)> GetGlobalRank(CCSPlayerController player) { if (apiKey == "") return (0, 0, 0); @@ -268,19 +268,19 @@ public async Task GetRecordIDAsync(object payload) } else { - SharpTimerError($"Failed to retrieve player rank. Status code: {response.StatusCode}; Message: {response.Content}"); + Utils.LogError($"Failed to retrieve player rank. Status code: {response.StatusCode}; Message: {response.Content}"); return (0, 0, 0); } } catch (Exception ex) { - SharpTimerError($"Error in GetGlobalRankAsync: {ex.Message}"); + Utils.LogError($"Error in GetGlobalRankAsync: {ex.Message}"); return (0, 0, 0); } return (0, 0, 0); } - public async Task PrintGlobalRankAsync(CCSPlayerController? player) + public async Task PrintGlobalRankAsync(CCSPlayerController player) { if (apiKey == "") return; @@ -288,8 +288,8 @@ public async Task PrintGlobalRankAsync(CCSPlayerController? player) var (points, rank, totalPlayers) = await GetGlobalRank(player); Server.NextFrame(() => { - PrintToChat(player, $"{Localizer["total_gpoints"]}: {points}"); - PrintToChat(player, $"{Localizer["grank"]}: {rank}/{totalPlayers}"); + Utils.PrintToChat(player, $"{Localizer["total_gpoints"]}: {points}"); + Utils.PrintToChat(player, $"{Localizer["grank"]}: {rank}/{totalPlayers}"); }); } @@ -313,16 +313,16 @@ public async Task SubmitReplayAsync(object payload) if (response.IsSuccessStatusCode) { - SharpTimerConPrint("Replay uploaded successfully."); + Utils.ConPrint("Replay uploaded successfully."); } else { - SharpTimerError($"Failed to upload replay. Status code: {response.StatusCode}; Message: {response.Content}"); + Utils.LogError($"Failed to upload replay. Status code: {response.StatusCode}; Message: {response.Content}"); } } catch (Exception ex) { - SharpTimerError($"Error in SubmitReplayAsync: {ex.Message}"); + Utils.LogError($"Error in SubmitReplayAsync: {ex.Message}"); } } @@ -335,19 +335,23 @@ public void PrintWorldRecord(CCSPlayerController player) Server.NextFrame(() => { - PrintToChat(player, Localizer["current_wr", currentMapName!]); + Utils.PrintToChat(player, Localizer["current_wr", currentMapName!]); + + if (cache.CachedWorldRecords == null || cache.CachedWorldRecords.Count <= 0) + return; + int position = 1; - foreach (var record in cache.CachedWorldRecords!) + foreach (var record in cache.CachedWorldRecords) { string replayIndicator = record.Value.Replay ? $"{ChatColors.Red}◉" : ""; - PrintToChat(player, $"{Localizer["records_map", position, record.Value.PlayerName!, replayIndicator, FormatTime(record.Value.TimerTicks)]}"); + Utils.PrintToChat(player, $"{Localizer["records_map", position, record.Value.PlayerName!, replayIndicator, Utils.FormatTime(record.Value.TimerTicks)]}"); position++; } }); } catch (Exception ex) { - SharpTimerError($"Error in PrintWorldRecord: {ex.Message}"); + Utils.LogError($"Error in PrintWorldRecord: {ex.Message}"); } } @@ -360,30 +364,34 @@ public void PrintGlobalPoints(CCSPlayerController player) Server.NextFrame(() => { - PrintToChat(player, Localizer["top_10_points"]); + Utils.PrintToChat(player, Localizer["top_10_points"]); + + if (cache.CachedGlobalPoints == null || cache.CachedGlobalPoints.Count <= 0) + return; + int position = 1; - foreach (var p in cache.CachedGlobalPoints!) + foreach (var p in cache.CachedGlobalPoints) { - PrintToChat(player, $"{Localizer["top_10_points_list", position, p.PlayerName!, p.GlobalPoints]}"); + Utils.PrintToChat(player, $"{Localizer["top_10_points_list", position, p.PlayerName!, p.GlobalPoints]}"); position++; } }); } catch (Exception ex) { - SharpTimerError($"Error in PrintGlobalPoints: {ex.Message}"); + Utils.LogError($"Error in PrintGlobalPoints: {ex.Message}"); } } public async Task> GetSortedRecordsFromGlobal(int limit = 0, int bonusX = 0, string mapName = "", int style = 0) { if (apiKey == "") - return null; + return null!; if (globalDisabled) - return null; + return null!; - SharpTimerDebug($"Trying GetSortedRecordsFromGlobal {(bonusX != 0 ? $"bonus {bonusX}" : "")}"); + Utils.LogDebug($"Trying GetSortedRecordsFromGlobal {(bonusX != 0 ? $"bonus {bonusX}" : "")}"); using (var connection = await OpenConnectionAsync()) { string? currentMapNamee; @@ -442,24 +450,24 @@ public async Task> GetSortedRecordsFromGlobal(int sortedRecords = sortedRecords.OrderBy(record => record.Value.TimerTicks) .ToDictionary(record => record.Key, record => record.Value); - SharpTimerDebug("Got sorted records from global"); + Utils.LogDebug("Got sorted records from global"); return sortedRecords; } else { - SharpTimerDebug("No data returned"); + Utils.LogDebug("No data returned"); return sortedRecords; } } } else { - SharpTimerError($"Failed to GetSortedRecordsFromGlobal. Status code: {response.StatusCode}"); + Utils.LogError($"Failed to GetSortedRecordsFromGlobal. Status code: {response.StatusCode}"); } } catch (Exception ex) { - SharpTimerError($"Error in GetSortedRecordsFromGlobal: {ex.Message}"); + Utils.LogError($"Error in GetSortedRecordsFromGlobal: {ex.Message}"); } } return []; @@ -489,12 +497,12 @@ public async Task GetReplayFromGlobal(object payload) } else { - SharpTimerError($"Failed to get global replay. Status code: {response.StatusCode}"); + Utils.LogError($"Failed to get global replay. Status code: {response.StatusCode}"); } } catch (Exception ex) { - SharpTimerError($"Error in GetReplayFromGlobal: {ex.Message}"); + Utils.LogError($"Error in GetReplayFromGlobal: {ex.Message}"); } return ""; } @@ -507,7 +515,7 @@ public async Task GetPreviousPlayerRecordFromGlobal(string steamId, string if (globalDisabled) return 0; - SharpTimerDebug($"Trying to get Previous {(bonusX != 0 ? $"bonus {bonusX} time" : "time")} from global for {playerName}"); + Utils.LogDebug($"Trying to get Previous {(bonusX != 0 ? $"bonus {bonusX} time" : "time")} from global for {playerName}"); try { string currentMapNamee = bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}"; @@ -548,13 +556,13 @@ public async Task GetPreviousPlayerRecordFromGlobal(string steamId, string } else { - SharpTimerConPrint($"No previous record found for steamid: {steamId}"); + Utils.ConPrint($"No previous record found for steamid: {steamId}"); return 0; } } catch (Exception ex) { - SharpTimerError($"Error getting previous player {(bonusX != 0 ? $"bonus {bonusX} time" : "time")} from global: {ex.Message}"); + Utils.LogError($"Error getting previous player {(bonusX != 0 ? $"bonus {bonusX} time" : "time")} from global: {ex.Message}"); } return 0; } @@ -587,6 +595,7 @@ public async Task CheckKeyAsync() } catch (Exception ex) { + Utils.LogError(ex.Message); return false; } } @@ -623,6 +632,7 @@ public async Task CheckHashAsync() } catch (Exception ex) { + Utils.LogError(ex.Message); return false; } } @@ -631,45 +641,53 @@ public async Task CheckHashAsync() { if (!globalDisabled) { - if (IsApproximatelyEqual(ConVar.Find("sv_accelerate")!.GetPrimitiveValue(), 10) - && ((IsApproximatelyEqual(ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue(), 150) && currentMapName!.Contains("surf_")) - || (IsApproximatelyEqual(ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue(), 1000) && currentMapName!.Contains("bhop_"))) - && IsApproximatelyEqual(ConVar.Find("sv_friction")!.GetPrimitiveValue(), (float)5.2) - && IsApproximatelyEqual(ConVar.Find("sv_gravity")!.GetPrimitiveValue(), 800) - && IsApproximatelyEqual(ConVar.Find("sv_ladder_scale_speed")!.GetPrimitiveValue(), 1) - && IsApproximatelyEqual(ConVar.Find("sv_staminajumpcost")!.GetPrimitiveValue(), 0) - && IsApproximatelyEqual(ConVar.Find("sv_staminalandcost")!.GetPrimitiveValue(), 0) - && IsApproximatelyEqual(ConVar.Find("sv_staminamax")!.GetPrimitiveValue(), 0) - && IsApproximatelyEqual(ConVar.Find("sv_staminarecoveryrate")!.GetPrimitiveValue(), 0) - && IsApproximatelyEqual(ConVar.Find("sv_wateraccelerate")!.GetPrimitiveValue(), 10) + var equal = Utils.IsApproximatelyEqual; + + if (equal(ConVar.Find("sv_accelerate")!.GetPrimitiveValue(), 10) + + && ((equal(ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue(), 150) && currentMapName!.Contains("surf_")) || + (equal(ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue(), 1000) && currentMapName!.Contains("bhop_"))) + + && equal(ConVar.Find("sv_friction")!.GetPrimitiveValue(), (float)5.2) + && equal(ConVar.Find("sv_gravity")!.GetPrimitiveValue(), 800) + && equal(ConVar.Find("sv_ladder_scale_speed")!.GetPrimitiveValue(), 1) + && equal(ConVar.Find("sv_staminajumpcost")!.GetPrimitiveValue(), 0) + && equal(ConVar.Find("sv_staminalandcost")!.GetPrimitiveValue(), 0) + && equal(ConVar.Find("sv_staminamax")!.GetPrimitiveValue(), 0) + && equal(ConVar.Find("sv_staminarecoveryrate")!.GetPrimitiveValue(), 0) + && equal(ConVar.Find("sv_wateraccelerate")!.GetPrimitiveValue(), 10) && ConVar.Find("sv_cheats")!.GetPrimitiveValue() == false - && (IsApproximatelyEqual(ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue(), 30) || IsApproximatelyEqual(ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue(), (float)37.41)) - && IsApproximatelyEqual(ConVar.Find("sv_maxspeed")!.GetPrimitiveValue(), 420) + + && (equal(ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue(), 30) || + equal(ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue(), (float)37.41)) + + && equal(ConVar.Find("sv_maxspeed")!.GetPrimitiveValue(), 420) && useCheckpointVerification) { // THICK globalChecksPassed = true; return (true, ConVar.Find("sv_maxvelocity")!.GetPrimitiveValue(), ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue()); } + //Checks failed, disable global api - SharpTimerConPrint($"GLOBAL CHECK FAILED -- Current Values:"); - SharpTimerConPrint($"sv_accelerate: {ConVar.Find("sv_accelerate")!.GetPrimitiveValue()} [should be 10]"); - SharpTimerConPrint($"sv_airaccelerate: {ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue()} [should be 150 for surf_ or 1000 for bhop_]"); - SharpTimerConPrint($"sv_friction: {ConVar.Find("sv_friction")!.GetPrimitiveValue()} [should be 5.2]"); - SharpTimerConPrint($"sv_gravity: {ConVar.Find("sv_gravity")!.GetPrimitiveValue()} [should be 800]"); - SharpTimerConPrint($"sv_ladder_scale_speed: {ConVar.Find("sv_ladder_scale_speed")!.GetPrimitiveValue()} [should be 1]"); - SharpTimerConPrint($"sv_staminajumpcost: {ConVar.Find("sv_staminajumpcost")!.GetPrimitiveValue()} [should be 0]"); - SharpTimerConPrint($"sv_staminalandcost: {ConVar.Find("sv_staminalandcost")!.GetPrimitiveValue()} [should be 0]"); - SharpTimerConPrint($"sv_staminamax: {ConVar.Find("sv_staminamax")!.GetPrimitiveValue()} [should be 0]"); - SharpTimerConPrint($"sv_staminarecoveryrate: {ConVar.Find("sv_staminarecoveryrate")!.GetPrimitiveValue()} [should be 0]"); - SharpTimerConPrint($"sv_wateraccelerate: {ConVar.Find("sv_wateraccelerate")!.GetPrimitiveValue()} [should be 10]"); - SharpTimerConPrint($"sv_maxspeed: {ConVar.Find("sv_maxspeed")!.GetPrimitiveValue()} [should be 420]"); - SharpTimerConPrint($"sharptimer_max_start_speed: {ConVar.Find("sv_maxspeed")!.GetPrimitiveValue()} [should be 420]"); - SharpTimerConPrint($"sv_air_max_wishspeed: {ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue()} [should be 30 or 37.41]"); - SharpTimerConPrint($"sv_cheats: {ConVar.Find("sv_cheats")!.GetPrimitiveValue()} [should be false]"); - SharpTimerConPrint($"Map is properly zoned?: {useTriggers} [should be true]"); - SharpTimerConPrint($"Use checkpoint verification?: {useCheckpointVerification} [should be true]"); - SharpTimerConPrint($"Using StripperCS2 on current map?: {Directory.Exists($"{gameDir}/addons/StripperCS2/maps/{Server.MapName}")} [should be false]"); + Utils.ConPrint($"GLOBAL CHECK FAILED -- Current Values:"); + Utils.ConPrint($"sv_accelerate: {ConVar.Find("sv_accelerate")!.GetPrimitiveValue()} [should be 10]"); + Utils.ConPrint($"sv_airaccelerate: {ConVar.Find("sv_airaccelerate")!.GetPrimitiveValue()} [should be 150 for surf_ or 1000 for bhop_]"); + Utils.ConPrint($"sv_friction: {ConVar.Find("sv_friction")!.GetPrimitiveValue()} [should be 5.2]"); + Utils.ConPrint($"sv_gravity: {ConVar.Find("sv_gravity")!.GetPrimitiveValue()} [should be 800]"); + Utils.ConPrint($"sv_ladder_scale_speed: {ConVar.Find("sv_ladder_scale_speed")!.GetPrimitiveValue()} [should be 1]"); + Utils.ConPrint($"sv_staminajumpcost: {ConVar.Find("sv_staminajumpcost")!.GetPrimitiveValue()} [should be 0]"); + Utils.ConPrint($"sv_staminalandcost: {ConVar.Find("sv_staminalandcost")!.GetPrimitiveValue()} [should be 0]"); + Utils.ConPrint($"sv_staminamax: {ConVar.Find("sv_staminamax")!.GetPrimitiveValue()} [should be 0]"); + Utils.ConPrint($"sv_staminarecoveryrate: {ConVar.Find("sv_staminarecoveryrate")!.GetPrimitiveValue()} [should be 0]"); + Utils.ConPrint($"sv_wateraccelerate: {ConVar.Find("sv_wateraccelerate")!.GetPrimitiveValue()} [should be 10]"); + Utils.ConPrint($"sv_maxspeed: {ConVar.Find("sv_maxspeed")!.GetPrimitiveValue()} [should be 420]"); + Utils.ConPrint($"sharptimer_max_start_speed: {ConVar.Find("sv_maxspeed")!.GetPrimitiveValue()} [should be 420]"); + Utils.ConPrint($"sv_air_max_wishspeed: {ConVar.Find("sv_air_max_wishspeed")!.GetPrimitiveValue()} [should be 30 or 37.41]"); + Utils.ConPrint($"sv_cheats: {ConVar.Find("sv_cheats")!.GetPrimitiveValue()} [should be false]"); + Utils.ConPrint($"Map is properly zoned?: {useTriggers} [should be true]"); + Utils.ConPrint($"Use checkpoint verification?: {useCheckpointVerification} [should be true]"); + Utils.ConPrint($"Using StripperCS2 on current map?: {Directory.Exists($"{gameDir}/addons/StripperCS2/maps/{Server.MapName}")} [should be false]"); globalDisabled = true; globalChecksPassed = false; diff --git a/src/Features/JumpStats.cs b/src/Features/JumpStats.cs deleted file mode 100644 index 8af15d28..00000000 --- a/src/Features/JumpStats.cs +++ /dev/null @@ -1,505 +0,0 @@ -/* -Copyright (C) 2024 Dea Brcka - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Utils; -using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; - -namespace SharpTimer -{ - public partial class SharpTimer - { - //based on https://github.com/deafps/cs2-kz-lua/blob/main/kz.lua - public void OnJumpStatJumped(CCSPlayerController player) - { - if (IsAllowedPlayer(player)) - { - int playerSlot = player.Slot; - playerJumpStats[playerSlot].Jumped = true; - playerJumpStats[playerSlot].OldJumpPos = string.IsNullOrEmpty(playerJumpStats[playerSlot].JumpPos) - ? $"{player.Pawn.Value!.AbsOrigin!.X} {player.Pawn.Value!.AbsOrigin.Y!} {player.Pawn.Value!.AbsOrigin.Z}" - : playerJumpStats[playerSlot].JumpPos; - playerJumpStats[playerSlot].JumpPos = $"{player.Pawn.Value!.AbsOrigin!.X} {player.Pawn.Value!.AbsOrigin.Y!} {player.Pawn.Value!.AbsOrigin.Z!}"; - } - } - - public void OnJumpStatSound(CCSPlayerController player) - { - if (IsAllowedPlayer(player)) - { - int playerSlot = player.Slot; - if (playerJumpStats[playerSlot].Jumped == true && playerJumpStats[playerSlot].FramesOnGround == 0) - { - playerJumpStats[playerSlot].LandedFromSound = true; - Server.NextFrame(() => - { - if (IsAllowedPlayer(player)) playerJumpStats[playerSlot].LandedFromSound = false; - }); - } - } - } - - public void OnJumpStatTick(CCSPlayerController player, Vector velocity, Vector playerpos, QAngle eyeangle, PlayerButtons? buttons) - { - try - { - if (playerJumpStats.TryGetValue(player.Slot, out PlayerJumpStats? playerJumpStat)) - { - playerJumpStat.OnGround = ((PlayerFlags)player.Pawn.Value!.Flags & PlayerFlags.FL_ONGROUND) == PlayerFlags.FL_ONGROUND; //need hull trace for this to detect surf and edgebug etc - - if (playerJumpStat.OnGround) - { - playerJumpStat.FramesOnGround++; - } - else - { - playerJumpStat.FramesOnGround = 0; - OnJumpStatTickInAir(player, playerJumpStat, buttons, playerpos, velocity, eyeangle); - } - - if (playerJumpStat.FramesOnGround == 2) - { - if (movementUnlockerCapEnabled && velocity.Length2D() > movementUnlockerCapValue) - { - float mult = movementUnlockerCapValue / velocity.Length2D(); - velocity.X *= mult; - velocity.Y *= mult; - player.PlayerPawn.Value!.AbsVelocity.X = velocity.X; - player.PlayerPawn.Value!.AbsVelocity.Y = velocity.Y; - } - } - else if (playerJumpStat.FramesOnGround == 1) - { - if (playerJumpStat.Jumped) - { - double distance = Calculate2DDistanceWithVerticalMargins(ParseVector(playerJumpStat.JumpPos!), playerpos); - if (distance != 0 && playerJumpStat.LastFramesOnGround > 2) - { - playerJumpStat.LastJumpType = "LJ"; - PrintJS(player, playerJumpStat, distance, playerpos); - } - else if (distance != 0 && playerJumpStat.LastFramesOnGround <= 2 && (playerJumpStat.LastJumpType == "LJ" || playerJumpStat.LastJumpType == "JB")) - { - playerJumpStat.LastJumpType = "BH"; - PrintJS(player, playerJumpStat, distance, playerpos); - } - else if (distance != 0 && playerJumpStat.LastFramesOnGround <= 2 && (playerJumpStat.LastJumpType == "BH" || playerJumpStat.LastJumpType == "MBH" || playerJumpStat.LastJumpType == "JB")) - { - playerJumpStat.LastJumpType = "MBH"; - PrintJS(player, playerJumpStat, distance, playerpos); - } - } - - playerJumpStat.Jumped = false; - - playerJumpStat.jumpFrames.Clear(); - playerJumpStat.jumpInterp.Clear(); - playerJumpStat.WTicks = 0; - } - else if (playerJumpStat.LandedFromSound == true) //workaround for PlayerFlags.FL_ONGROUND being 1 frame late - { - if (playerJumpStat.Jumped) - { - double distance = Calculate2DDistanceWithVerticalMargins(ParseVector(playerJumpStat.OldJumpPos!), playerpos, true); - if (distance != 0 && !playerJumpStat.LastOnGround && playerJumpStat.LastDucked && ((PlayerFlags)player.Pawn.Value.Flags & PlayerFlags.FL_DUCKING) != PlayerFlags.FL_DUCKING) - { - playerJumpStat.LastJumpType = "JB"; - PrintJS(player, playerJumpStat, distance, playerpos); - playerJumpStat.LastFramesOnGround = playerJumpStat.FramesOnGround; - playerJumpStat.Jumped = true; // assume player jumped again if JB is successful - if (playerTimers[player.Slot].SoundsEnabled == true) player.ExecuteClientCommand($"play player/death_fem_0{new Random().Next(1, 9)}"); - } - } - else - { - playerJumpStat.Jumped = false; - } - playerJumpStat.jumpFrames.Clear(); - playerJumpStat.jumpInterp.Clear(); - playerJumpStat.WTicks = 0; - - playerJumpStat.FramesOnGround++; - } - - playerJumpStat.LastLandedFromSound = playerJumpStat.LandedFromSound; - - playerJumpStat.LastOnGround = playerJumpStat.OnGround; - playerJumpStat.LastDucked = ((PlayerFlags)player.Pawn.Value.Flags & PlayerFlags.FL_DUCKING) == PlayerFlags.FL_DUCKING; - if (playerJumpStat.OnGround) - { - playerJumpStat.LastSpeed = $"{velocity.X} {velocity.Y} {velocity.Z}"; - playerJumpStat.LastFramesOnGround = playerJumpStat.FramesOnGround; - playerJumpStat.LastPosOnGround = $"{playerpos.X} {playerpos.Y} {playerpos.Z}"; - } - } - } - catch (Exception ex) - { - SharpTimerDebug($"Exception in OnJumpStatTick: {ex}"); - } - } - - public void OnJumpStatTickInAir(CCSPlayerController player, PlayerJumpStats playerJumpStat, PlayerButtons? buttons, Vector playerpos, Vector velocity, QAngle eyeangle) - { - try - { - var LastJumpFrame = playerJumpStat.jumpFrames.Count != 0 ? playerJumpStat.jumpFrames.Last() : new PlayerJumpStats.IFrame - { - PositionString = $" ", - SpeedString = $" ", - LastLeft = false, - LastRight = false, - LastLeftRight = false, - MaxHeight = 0, - MaxSpeed = 0 - }; - - bool left = false; - bool right = false; - bool leftRight = false; - if ((buttons & PlayerButtons.Moveleft) != 0 && (buttons & PlayerButtons.Moveright) != 0) - leftRight = true; - else if ((buttons & PlayerButtons.Moveleft) != 0) - left = true; - else if ((buttons & PlayerButtons.Moveright) != 0) - right = true; - - if ((buttons & PlayerButtons.Forward) != 0) - playerJumpStat.WTicks++; - - double maxHeight; - if (IsVectorHigherThan(playerpos, ParseVector(LastJumpFrame.PositionString!))) - maxHeight = playerpos.Z - ParseVector(playerJumpStat.LastPosOnGround ?? "0 0 0").Z; - else - maxHeight = LastJumpFrame?.MaxHeight ?? 0; - - double maxSpeed; - if (velocity.Length2D() > LastJumpFrame!.MaxSpeed) - maxSpeed = velocity.Length2D(); - else - maxSpeed = LastJumpFrame?.MaxSpeed ?? 0; - - var JumpFrame = new PlayerJumpStats.IFrame - { - PositionString = $"{playerpos.X} {playerpos.Y} {playerpos.Z}", - SpeedString = $"{velocity.X} {velocity.Y} {velocity.Z}", - RotationString = $"{eyeangle.X} {eyeangle.Y} {eyeangle.Z}", - LastLeft = left, - LastRight = right, - LastLeftRight = leftRight, - MaxHeight = maxHeight, - MaxSpeed = maxSpeed - }; - - playerJumpStat.jumpFrames.Add(JumpFrame); - } - catch (Exception ex) - { - SharpTimerDebug($"Exception in OnJumpStatTickInAir: {ex}"); - } - } - - public void OnSyncTick(CCSPlayerController player, PlayerButtons? buttons, QAngle eyeangle) - { - try - { - var playerTimer = playerTimers[player.Slot]; - bool strafingLeft = false; - bool strafingRight = false; - // Start with 100% sync initially - if (playerTimers[player.Slot].inStartzone) playerTimer.Sync = 100.00f; - - if ((buttons & PlayerButtons.Moveleft) != 0 && (buttons & PlayerButtons.Moveright) != 0) - { - return; // Ignore if both left and right are pressed - } - else if ((buttons & PlayerButtons.Moveleft) != 0) - { - strafingLeft = true; - } - else if ((buttons & PlayerButtons.Moveright) != 0) - { - strafingRight = true; - } - else - { - return; // Ignore if neither left nor right is pressed - } - - // Add the current eye angle to the rotation history - QAngle newEyeAngle = new QAngle(eyeangle.X, eyeangle.Y, eyeangle.Z); - playerTimer.Rotation.Add(newEyeAngle); - - // Cap rotation history at 1000 entries - if (playerTimer.Rotation.Count > 1000) - { - playerTimer.Rotation.RemoveAt(0); // Remove the oldest entry - } - - // Only proceed if we have enough data points in Rotation - if (playerTimer.Rotation.Count > 1) - { - float previousEyeAngleY = playerTimer.Rotation[playerTimer.Rotation.Count - 2].Y; // Use Rotation.Count - 2 - float currentEyeAngleY = eyeangle.Y; - - // Normalize angle difference to handle wrapping from -180 to 180 - float deltaY = currentEyeAngleY - previousEyeAngleY; - if (deltaY > 180) - { - deltaY -= 360; - } - else if (deltaY < -180) - { - deltaY += 360; - } - - if (Math.Abs(deltaY) < 0.01f) return; - - bool onGround = ((PlayerFlags)player.Pawn.Value!.Flags & PlayerFlags.FL_ONGROUND) == PlayerFlags.FL_ONGROUND; - if (onGround || (!onGround && (buttons & (PlayerButtons.Moveleft | PlayerButtons.Moveright)) == 0)) - { - return; // Ignore calculation if the player is on the ground or airborne without pressing movement buttons - } - else - { - // Increment frames in the air - playerTimer.TotalSync++; - } - - // Determine rotation direction - bool rotatingLeft = deltaY > 0; - bool rotatingRight = deltaY < 0; - - // Add sync frame if strafing and rotating match and the player is airborne - if (!onGround && ((strafingLeft && rotatingLeft) || (strafingRight && rotatingRight))) - { - playerTimer.GoodSync++; // Increment sync frames - } - } - - // Calculate sync percentage - if (playerTimer.TotalSync >= 2) // Adjust threshold as needed - { - playerTimer.Sync = (playerTimer.TotalSync > 0) - ? (playerTimer.GoodSync / (float)playerTimer.TotalSync) * 100 - : 0; - } - } - catch (Exception ex) - { - SharpTimerDebug($"Exception in OnSyncTick: {ex}"); - } - } - - public static char GetJSColor(double distance) - { - if (distance < 230) - { - return ChatColors.Grey; - } - else if (distance < 235) - { - return ChatColors.Blue; - } - else if (distance < 240) - { - return ChatColors.Green; - } - else if (distance < 244) - { - return ChatColors.DarkRed; - } - else if (distance < 246) - { - return ChatColors.Gold; - } - else - { - return ChatColors.Purple; - } - } - - double Calculate2DDistanceWithVerticalMargins(Vector vector1, Vector vector2, bool noVertCheck = false) - { - if (vector1 == null || vector2 == null) - { - return 0; - } - - float verticalDistance = Math.Abs(vector1.Z - vector2.Z); - - if (verticalDistance >= 32 && noVertCheck == false) - { - return 0; - } - - double distance2D = Distance(vector1, vector2); - - if (distance2D > jumpStatsMinDist || noVertCheck == true) - { - double result = distance2D + 16.0f; - return result; - } - else - { - return 0; - } - } - - public static (int lastLeftGroups, int leftSync, int leftFrames) CountLeftGroupsAndSync(PlayerJumpStats playerJumpStat, bool timersync) - { - int lastLeftGroups = 0; - int leftSync = 0; - int leftFrames = 0; - bool inGroup = false; - QAngle previousRotation = null!; - - var frames = timersync ? playerJumpStat.timerSyncFrames : playerJumpStat.jumpFrames; - foreach (var frame in frames) - { - if (frame.LastLeftRight || frame.LastRight) - { - if (inGroup) - lastLeftGroups++; - inGroup = false; - } - else if (frame.LastLeft) - { - inGroup = true; - leftFrames++; - if (previousRotation != null && ParseQAngle(frame.RotationString!).Y > previousRotation.Y) - leftSync++; - } - previousRotation = ParseQAngle(frame.RotationString!); - } - - if (inGroup) - lastLeftGroups++; - - return (lastLeftGroups, leftSync, leftFrames); - } - - public static (int lastRightGroups, int rightSync, int rightFrames) CountRightGroupsAndSync(PlayerJumpStats playerJumpStat, bool timersync) - { - int lastRightGroups = 0; - int rightSync = 0; - int rightFrames = 0; - bool inGroup = false; - QAngle previousRotation = null!; - - var frames = timersync ? playerJumpStat.timerSyncFrames : playerJumpStat.jumpFrames; - foreach (var frame in frames) - { - if (frame.LastLeftRight || frame.LastLeft) - { - if (inGroup) - lastRightGroups++; - inGroup = false; - - } - else if (frame.LastRight) - { - inGroup = true; - rightFrames++; - if (previousRotation != null && ParseQAngle(frame.RotationString!).Y < previousRotation.Y) - rightSync++; - } - previousRotation = ParseQAngle(frame.RotationString!); - } - - if (inGroup) - lastRightGroups++; - - return (lastRightGroups, rightSync, rightFrames); - } - - public static float GetMaxWidth(Vector playerpos, PlayerJumpStats playerJumpStat) - { - InterpolateVectors(ParseVector(playerJumpStat.JumpPos!), playerpos, playerJumpStat); - - float distance = 0; - for (int jumpFrameIndex = 0; jumpFrameIndex < Math.Min(playerJumpStat.jumpFrames.Count, playerJumpStat.jumpInterp.Count); jumpFrameIndex++) - { - var frame = playerJumpStat.jumpFrames[jumpFrameIndex]; - float width = (float)Distance2D(ParseVector(frame.PositionString!), ParseVector(playerJumpStat.jumpInterp[jumpFrameIndex].InterpString!)); - if (width > distance) distance = width; - } - - return (float)Math.Round(distance, 2); - } - - public static void InterpolateVectors(Vector vector1, Vector vector2, PlayerJumpStats playerJumpStat) - { - int numInterpolations = playerJumpStat.jumpFrames.Count; - float stepX = (vector2.X - vector1.X) / (numInterpolations + 1); - float stepY = (vector2.Y - vector1.Y) / (numInterpolations + 1); - float stepZ = (vector2.Z - vector1.Z) / (numInterpolations + 1); - - for (int i = 0; i < numInterpolations; i++) - { - float interpolatedX = vector1.X + stepX * (i + 1); - float interpolatedY = vector1.Y + stepY * (i + 1); - float interpolatedZ = vector1.Z + stepZ * (i + 1); - - var interpFrame = new PlayerJumpStats.JumpInterp - { - InterpString = $"{interpolatedX} {interpolatedY} {interpolatedZ}" - }; - - playerJumpStat.jumpInterp.Add(interpFrame); - } - } - - public void InvalidateJS(int playerSlot) - { - try - { - if (playerJumpStats.TryGetValue(playerSlot, out PlayerJumpStats? value)) - { - value.LastFramesOnGround = 0; - value.Jumped = false; - } - } - catch(Exception ex) - { - // Suppress trigger_teleport null reference exceptions (the player has likely disconnected) - } - } - - public void PrintJS(CCSPlayerController player, PlayerJumpStats playerJumpStat, double distance, Vector playerpos) - { - if (playerTimers[player.Slot].HideJumpStats == true) return; - - char color = GetJSColor(distance); - - var (lStrafes, lSync, lFrames) = CountLeftGroupsAndSync(playerJumpStat, false); - var (rStrafes, rSync, rFrames) = CountRightGroupsAndSync(playerJumpStat, false); - - int strafes = rStrafes + lStrafes; - int strafeFrames = rFrames + lFrames; - int syncedFrames = rSync + lSync; - - double sync = (strafeFrames != 0) ? Math.Round(syncedFrames * 100f / strafeFrames, 2) : 0; - - PrintToChat(player, Localizer["js_msg1", playerJumpStat.LastJumpType!, color, Math.Round(distance, 2), Math.Round(ParseVector(playerJumpStat.LastSpeed!).Length2D(), 2), Math.Round(playerJumpStat.jumpFrames.Last().MaxSpeed, 2), strafes]); - PrintToChat(player, Localizer["js_msg2", Math.Round(playerJumpStat.jumpFrames.Last().MaxHeight, 2), GetMaxWidth(playerpos, playerJumpStat), playerJumpStat.WTicks, sync]); - - player.PrintToConsole($"-----------------------------------------------------------------------------------------------------------------------"); - player.PrintToConsole($" {Localizer["js_msg1", playerJumpStat.LastJumpType!, color, Math.Round(distance, 2), Math.Round(ParseVector(playerJumpStat.LastSpeed!).Length2D(), 2), Math.Round(playerJumpStat.jumpFrames.Last().MaxSpeed, 2), strafes]}"); - player.PrintToConsole($" {Localizer["js_msg2", Math.Round(playerJumpStat.jumpFrames.Last().MaxHeight, 2), GetMaxWidth(playerpos, playerJumpStat), playerJumpStat.WTicks, sync]}"); - } - } -} diff --git a/src/Features/Points.cs b/src/Features/Points.cs index 14105b3f..b853dd16 100644 --- a/src/Features/Points.cs +++ b/src/Features/Points.cs @@ -36,10 +36,10 @@ public async Task CalculateTier(int completions, string mapname) string? _; if(disableRemoteData) - (tier, _) = await FindMapInfoFromLocal(GetMapInfoSource(), mapname); + (tier, _) = await Utils.FindMapInfoFromLocal(Utils.GetMapInfoSource(), mapname); else - (tier, _) = await FindMapInfoFromHTTP(GetMapInfoSource(), mapname); + (tier, _) = await Utils.FindMapInfoFromHTTP(Utils.GetMapInfoSource(), mapname); if (tier != null) { diff --git a/src/Hooks/Damage.cs b/src/Features/RemoveDamage.cs similarity index 58% rename from src/Hooks/Damage.cs rename to src/Features/RemoveDamage.cs index 7b8ff257..dd0abfa6 100644 --- a/src/Hooks/Damage.cs +++ b/src/Features/RemoveDamage.cs @@ -22,56 +22,73 @@ You should have received a copy of the GNU General Public License namespace SharpTimer { - public partial class SharpTimer + public class RemoveDamage { - public void DamageHook() + private readonly SharpTimer Plugin; + private readonly Utils Utils; + + public RemoveDamage(SharpTimer plugin) + { + Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin)); + Utils = plugin.Utils ?? throw new ArgumentNullException(nameof(plugin.Utils)); + } + + public void Hook() { + Utils.LogDebug("Hook RemoveDamage"); + try { - SharpTimerDebug("Init Damage hook..."); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + if (Plugin.isLinux) { - SharpTimerDebug("Trying to register Linux Damage hook..."); - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(this.OnTakeDamage, HookMode.Pre); + Utils.LogDebug("Trying to register Linux Damage hook..."); + VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); } else { - SharpTimerDebug("Trying to register Windows Damage hook..."); - RegisterEventHandler(OnPlayerHurt, HookMode.Pre); + Utils.LogDebug("Trying to register Windows Damage hook..."); + Plugin.RegisterEventHandler(OnPlayerHurt, HookMode.Pre); } } catch (Exception ex) { if (ex.Message == "Invalid function pointer") - SharpTimerError($"Error in DamageHook: Conflict between cs2fixes and SharpTimer"); + Utils.LogError($"Error in DamageHook: Conflict between cs2fixes and SharpTimer"); else - SharpTimerError($"Error in DamageHook: {ex.Message}"); + Utils.LogError($"Error in DamageHook: {ex.Message}"); } } - public void DamageUnHook() + public void Unhook() { + Utils.LogDebug("Unhook RemoveDamage"); + try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Unhook(OnTakeDamage, HookMode.Pre); } + else + { + Plugin.DeregisterEventHandler(OnPlayerHurt, HookMode.Pre); + } } catch (Exception ex) { if (ex.Message == "Invalid function pointer") - SharpTimerError($"Error in DamageUnHook: Conflict between cs2fixes and SharpTimer"); + Utils.LogError($"Error in DamageUnHook: Conflict between cs2fixes and SharpTimer"); else - SharpTimerError($"Error in DamageUnHook: {ex.Message}"); + Utils.LogError($"Error in DamageUnHook: {ex.Message}"); } } - HookResult OnTakeDamage(DynamicHook h) + private HookResult OnTakeDamage(DynamicHook hook) { - var ent = h.GetParam(0); - var info = h.GetParam(1); - if(disableDamage) h.GetParam(1).Damage = 0; + var ent = hook.GetParam(0); + var info = hook.GetParam(1); + + if (Plugin.disableDamage) hook.GetParam(1).Damage = 0; if (!ent.IsValid || !info.Attacker.IsValid) return HookResult.Continue; @@ -82,16 +99,16 @@ HookResult OnTakeDamage(DynamicHook h) return HookResult.Continue; } - HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info) + private HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info) { - if (disableDamage == true) + if (Plugin.disableDamage == true) { var player = @event.Userid; if (!player!.IsValid) return HookResult.Continue; - Vector playerSpeed = player!.PlayerPawn.Value!.AbsVelocity ?? new Vector(0, 0, 0); + Vector playerSpeed = player!.PlayerPawn.Value!.AbsVelocity; player.PlayerPawn.Value.Health = int.MaxValue; player.PlayerPawn.Value.ArmorValue = int.MaxValue; @@ -101,7 +118,7 @@ HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info) Server.NextFrame(() => { - if (IsAllowedPlayer(player)) AdjustPlayerVelocity(player, playerSpeed.Length(), true); + if (Plugin.IsAllowedPlayer(player)) Plugin.AdjustPlayerVelocity(player, playerSpeed.Length(), true); }); } diff --git a/src/Features/ReplayUtils.cs b/src/Features/ReplayUtils.cs index aede7b86..adbe62b2 100644 --- a/src/Features/ReplayUtils.cs +++ b/src/Features/ReplayUtils.cs @@ -169,7 +169,7 @@ private void OnRecordingStop(CCSPlayerController player) SharpTimerError($"Error in OnRecordingStop: {ex.Message}"); } } - + public async Task DumpReplayToJson(CCSPlayerController player, string steamID, int playerSlot, int bonusX = 0, int style = 0) { await Task.Run(() => @@ -182,10 +182,10 @@ await Task.Run(() => string fileName = $"{steamID}_replay.json"; string playerReplaysDirectory; - if(style != 0) playerReplaysDirectory = Path.Join(this.playerReplaysPath, bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style)); - else playerReplaysDirectory = Path.Join(this.playerReplaysPath, bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}"); - string replayFilePath = Path.Join(playerReplaysDirectory, fileName); - + if (style != 0) playerReplaysDirectory = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style)); + else playerReplaysDirectory = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}"); + string playerReplaysPath = Path.Join(playerReplaysDirectory, fileName); + try { if (!Directory.Exists(playerReplaysDirectory)) @@ -199,7 +199,7 @@ await Task.Run(() => .Select((frame, index) => new IndexedReplayFrames { Index = index, Frame = frame }) .ToList(); - using (Stream stream = new FileStream(replayFilePath, FileMode.Create)) + using (Stream stream = new FileStream(playerReplaysPath, FileMode.Create)) { JsonSerializer.Serialize(stream, indexedReplayFrames); } @@ -223,9 +223,9 @@ await Task.Run(() => string fileName = $"{steamID}_replay.dat"; string playerReplaysDirectory; - if(style != 0) playerReplaysDirectory = Path.Join(this.playerReplaysPath, bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style)); - else playerReplaysDirectory = Path.Join(this.playerReplaysPath, bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}"); - string replayFilePath = Path.Join(playerReplaysDirectory, fileName); + if (style != 0) playerReplaysDirectory = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style)); + else playerReplaysDirectory = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? $"{currentMapName}" : $"{currentMapName}_bonus{bonusX}"); + string playerReplaysPath = Path.Join(playerReplaysDirectory, fileName); try { @@ -240,7 +240,7 @@ await Task.Run(() => .Select((frame, index) => new IndexedReplayFrames { Index = index, Frame = frame }) .ToList(); - using Stream stream = new FileStream(replayFilePath, FileMode.Create); + using Stream stream = new FileStream(playerReplaysPath, FileMode.Create); BinaryWriter writer = new BinaryWriter(stream); writer.Write(REPLAY_VERSION); @@ -298,8 +298,8 @@ private async Task ReadReplayFromJson(CCSPlayerController player, string steamId SharpTimerDebug($"Reading replay from JSON"); string fileName = $"{steamId}_replay.json"; string playerReplaysPath; - if(style != 0) playerReplaysPath = Path.Join(this.playerReplaysPath, bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style), fileName); - else playerReplaysPath = Path.Join(this.playerReplaysPath, bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", fileName); + if (style != 0) playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style), fileName); + else playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", fileName); try { @@ -350,8 +350,8 @@ private async Task ReadReplayFromBinary(CCSPlayerController player, string steam SharpTimerDebug($"Reading replay from Binary"); string fileName = $"{steamId}_replay.dat"; string playerReplaysPath; - if(style != 0) playerReplaysPath = Path.Join(this.playerReplaysPath, bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style), fileName); - else playerReplaysPath = Path.Join(this.playerReplaysPath, bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", fileName); + if (style != 0) playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", GetNamedStyle(style), fileName); + else playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}", fileName); try { @@ -566,8 +566,8 @@ public async Task CheckSRReplay(string topSteamID = "x", int bonusX = 0, i string ext = useBinaryReplays ? "dat" : "json"; string fileName = $"{(topSteamID == "x" ? $"{srSteamID}" : $"{topSteamID}")}_replay.{ext}"; string playerReplaysPath; - if(style != 0) playerReplaysPath = Path.Join(this.playerReplaysPath, (bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}"), GetNamedStyle(style), fileName); - else playerReplaysPath = Path.Join(this.playerReplaysPath, (bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}"), fileName); + if (style != 0) playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", (bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}"), GetNamedStyle(style), fileName); + else playerReplaysPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerReplayData", (bonusX == 0 ? currentMapName : $"{currentMapName}_bonus{bonusX}"), fileName); try { diff --git a/src/Features/Styles.cs b/src/Features/Styles.cs index 9f93a421..5dd872c6 100644 --- a/src/Features/Styles.cs +++ b/src/Features/Styles.cs @@ -1,5 +1,5 @@ using CounterStrikeSharp.API.Core; -using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; +using FixVectorLeak; namespace SharpTimer { @@ -138,7 +138,7 @@ public void SetTAS(CCSPlayerController player) playerTimers[player.Slot].changedStyle = true; } - public void SetVelocity(CCSPlayerController player, Vector currentVel, int desiredVel) + public void SetVelocity(CCSPlayerController player, Vector_t currentVel, int desiredVel) { if(currentVel.X > desiredVel) player!.PlayerPawn.Value!.AbsVelocity.X = desiredVel; if(currentVel.X < -desiredVel) player!.PlayerPawn.Value!.AbsVelocity.X = -desiredVel; diff --git a/src/Player/PlayerChecks.cs b/src/Player/PlayerChecks.cs index dc116b0f..da9ccf17 100644 --- a/src/Player/PlayerChecks.cs +++ b/src/Player/PlayerChecks.cs @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License using System.Text.Json; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Utils; +using FixVectorLeak; namespace SharpTimer { @@ -23,50 +23,44 @@ public partial class SharpTimer { public bool IsAllowedPlayer(CCSPlayerController? player) { - if (player == null || !player.IsValid || player.Pawn == null || !player.PlayerPawn.IsValid || !player.PawnIsAlive || playerTimers[player.Slot].IsNoclip) - { + if (player == null) return false; - } - int playerSlot = player.Slot; + if (playerTimers.TryGetValue(player.Slot, out var playTimer)) + { + if (playTimer.IsNoclip) + return false; + } - CsTeam teamNum = (CsTeam)player.TeamNum; + bool isConnected = connectedPlayers.ContainsKey(player.Slot) && playerTimers.ContainsKey(player.Slot); bool isAlive = player.PawnIsAlive; - bool isTeamValid = teamNum == CsTeam.CounterTerrorist || teamNum == CsTeam.Terrorist; + bool isTeamValid = player.TeamCT() || player.TeamT(); - bool isTeamSpectatorOrNone = teamNum != CsTeam.Spectator && teamNum != CsTeam.None; - bool isConnected = connectedPlayers.ContainsKey(playerSlot) && playerTimers.ContainsKey(playerSlot); - bool isConnectedJS = !jumpStatsEnabled || playerJumpStats.ContainsKey(playerSlot); - - return isTeamValid && isTeamSpectatorOrNone && isConnected && isConnectedJS && isAlive; + return isConnected && isAlive && isTeamValid; } private bool IsAllowedSpectator(CCSPlayerController? player) { - if (player == null || !player.IsValid || player.IsBot) - { + if (player == null) return false; - } - CsTeam teamNum = (CsTeam)player.TeamNum; - bool isTeamValid = teamNum == CsTeam.Spectator; bool isConnected = connectedPlayers.ContainsKey(player.Slot) && playerTimers.ContainsKey(player.Slot); bool isObservingValid = player.Pawn?.Value!.ObserverServices?.ObserverTarget != null && - specTargets.ContainsKey(player.Pawn.Value.ObserverServices.ObserverTarget.Index); + specTargets.ContainsKey(player.Pawn.Value.ObserverServices.ObserverTarget.Index); - return isTeamValid && isConnected && isObservingValid; + return isConnected && isObservingValid; } - public bool IsAllowedClient(CCSPlayerController? player) + public bool IsPlayerOrSpectator(CCSPlayerController? player) { - if (player == null || !player.IsValid || player.Pawn == null || !player.PlayerPawn.IsValid) + if (player == null) return false; - return true; + return IsAllowedPlayer(player) || IsAllowedSpectator(player); } - async Task IsPlayerATester(string steamId64, int playerSlot) + async Task IsPlayerATester(string steamId64, int slot) { try { @@ -74,7 +68,7 @@ async Task IsPlayerATester(string steamId64, int playerSlot) using (JsonDocument jsonDocument = JsonDocument.Parse(response)) { - if (playerTimers.TryGetValue(playerSlot, out PlayerTimerInfo? playerTimer)) + if (playerTimers.TryGetValue(slot, out PlayerTimerInfo? playerTimer)) { playerTimer.IsTester = jsonDocument.RootElement.TryGetProperty(steamId64, out JsonElement steamData); @@ -93,13 +87,13 @@ async Task IsPlayerATester(string steamId64, int playerSlot) } else { - SharpTimerError($"Error in IsPlayerATester: player not on server anymore"); + Utils.LogError($"Error in IsPlayerATester: player not on server anymore"); } } } catch (Exception ex) { - SharpTimerError($"Error in IsPlayerATester: {ex.Message}"); + Utils.LogError($"Error in IsPlayerATester: {ex.Message}"); } } @@ -121,7 +115,7 @@ async Task GetTesterBigGif(string steamId64) } catch (Exception ex) { - SharpTimerError($"Error in GetTesterBigGif: {ex.Message}"); + Utils.LogError($"Error in GetTesterBigGif: {ex.Message}"); return ""; } } @@ -144,7 +138,7 @@ async Task GetTesterSmolGif(string steamId64) } catch (Exception ex) { - SharpTimerError($"Error in GetTesterSmolGif: {ex.Message}"); + Utils.LogError($"Error in GetTesterSmolGif: {ex.Message}"); return ""; } } @@ -165,12 +159,13 @@ async Task IsSteamIDaTester(string steamId64) } catch (Exception ex) { - SharpTimerError($"Error in IsSteamIDaTester: {ex.Message}"); + Utils.LogError($"Error in IsSteamIDaTester: {ex.Message}"); return false; } } - private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) + + private void CheckPlayerCoords(CCSPlayerController? player, Vector_t playerSpeed) { try { @@ -179,20 +174,20 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) return; } - Vector incorrectVector = new(0, 0, 0); - Vector? playerPos = player.Pawn?.Value!.CBodyComponent?.SceneNode!.AbsOrigin; + Vector_t incorrectVector = new(0, 0, 0); + Vector_t playerPos = player.Pawn?.Value!.CBodyComponent?.SceneNode!.AbsOrigin.ToVector_t() ?? new(); bool isInsideStartBox = false; bool isInsideEndBox = false; - if (playerPos == null || currentMapStartC1 == incorrectVector || currentMapStartC2 == incorrectVector || - currentMapEndC1 == incorrectVector || currentMapEndC2 == incorrectVector) + if (playerPos.Equals(incorrectVector) || currentMapStartC1.Equals(incorrectVector) || currentMapStartC2.Equals(incorrectVector) || + currentMapEndC1.Equals(incorrectVector) || currentMapEndC2.Equals(incorrectVector)) { return; } if (!useTriggersAndFakeZones) { - isInsideStartBox = IsVectorInsideBox(playerPos, currentMapStartC1, currentMapStartC2); - isInsideEndBox = IsVectorInsideBox(playerPos, currentMapEndC1, currentMapEndC2); + isInsideStartBox = Utils.IsVectorInsideBox(playerPos, currentMapStartC1, currentMapStartC2); + isInsideEndBox = Utils.IsVectorInsideBox(playerPos, currentMapEndC1, currentMapEndC2); } bool[] isInsideBonusStartBox = new bool[11]; bool[] isInsideBonusEndBox = new bool[11]; @@ -209,13 +204,13 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) currentBonusEndC1 == null || currentBonusEndC1.Length <= bonus || currentBonusEndC2 == null || currentBonusEndC2.Length <= bonus) { - SharpTimerError($"Invalid bonus coordinates for bonus {bonus}"); + Utils.LogError($"Invalid bonus coordinates for bonus {bonus}"); } else { - isInsideBonusStartBox[bonus] = IsVectorInsideBox(playerPos, currentBonusStartC1[bonus], currentBonusStartC2[bonus]); - isInsideBonusEndBox[bonus] = IsVectorInsideBox(playerPos, currentBonusEndC1[bonus], currentBonusEndC2[bonus]); + isInsideBonusStartBox[bonus] = Utils.IsVectorInsideBox(playerPos, currentBonusStartC1[bonus], currentBonusStartC2[bonus]); + isInsideBonusEndBox[bonus] = Utils.IsVectorInsideBox(playerPos, currentBonusEndC1[bonus], currentBonusEndC2[bonus]); } } } @@ -229,7 +224,7 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) } else if (isInsideStartBox) { - if(playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) + if (playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) { playerTimer.inStartzone = true; InvalidateTimer(player); @@ -265,7 +260,7 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) currentBonusEndC1 == null || currentBonusEndC1.Length <= bonus || currentBonusEndC2 == null || currentBonusEndC2.Length <= bonus) { - SharpTimerError($"Invalid bonus coordinates for bonus {bonus}"); + Utils.LogError($"Invalid bonus coordinates for bonus {bonus}"); } else @@ -277,7 +272,7 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) } else if (isInsideBonusStartBox[bonus]) { - if(playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) + if (playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) { playerTimer.inStartzone = true; } @@ -294,11 +289,11 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) } else if (!isInsideBonusStartBox[bonus]) { - if(playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) + if (playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? playerTimer)) { playerTimer.inStartzone = false; } - + } } } @@ -307,16 +302,25 @@ private void CheckPlayerCoords(CCSPlayerController? player, Vector playerSpeed) } catch (Exception ex) { - SharpTimerError($"Error in CheckPlayerCoords: {ex.Message}"); + Utils.LogError($"Error in CheckPlayerCoords: {ex.Message}"); } } - public bool CommandCooldown(CCSPlayerController? player) + public bool CommandCooldown(CCSPlayerController player) { - if (playerTimers[player!.Slot].TicksSinceLastCmd < cmdCooldown) + if (playerTimers.TryGetValue(player.Slot, out var playerTimer)) { - PrintToChat(player, Localizer["command_cooldown"]); - return true; + double secondsRemaining = (playerTimer.CmdCooldown - DateTime.Now).TotalSeconds; + if (secondsRemaining > 0) + { + Utils.PrintToChat(player, Localizer["command_cooldown", secondsRemaining]); + return true; + } + else + { + playerTimer.CmdCooldown = DateTime.Now.AddSeconds(cmdCooldown); + return false; + } } return false; } @@ -325,7 +329,7 @@ public bool IsTimerBlocked(CCSPlayerController? player) { if (!playerTimers[player!.Slot].IsTimerBlocked) { - PrintToChat(player, Localizer["stop_using_timer"]); + Utils.PrintToChat(player, Localizer["stop_using_timer"]); return true; } return false; @@ -335,7 +339,7 @@ public bool ReplayCheck(CCSPlayerController? player) { if (playerTimers[player!.Slot].IsReplaying) { - PrintToChat(player, Localizer["end_your_replay"]); + Utils.PrintToChat(player, Localizer["end_your_replay"]); return true; } return false; @@ -347,7 +351,7 @@ public bool CanCheckpoint(CCSPlayerController? player) { if (playerTimers[player.Slot].currentStyle == 12) return true; - PrintToChat(player, Localizer["cant_use_checkpoint", (currentMapName!.Contains("surf_") ? "loc" : "checkpoint")]); + Utils.PrintToChat(player, Localizer["cant_use_checkpoint", (currentMapName!.Contains("surf_") ? "loc" : "checkpoint")]); PlaySound(player, cpSoundError); return false; } diff --git a/src/Player/PlayerEvents.cs b/src/Player/PlayerEvents.cs index ca8a68f9..92727984 100644 --- a/src/Player/PlayerEvents.cs +++ b/src/Player/PlayerEvents.cs @@ -13,13 +13,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; -using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Utils; -using CounterStrikeSharp.API.Modules.Cvars; namespace SharpTimer { @@ -31,121 +27,98 @@ private void OnPlayerConnect(CCSPlayerController? player, bool isForBot = false) { if (player == null) { - SharpTimerError("Player object is null."); + Utils.LogError("Player object is null."); return; } if (player.PlayerPawn == null) { - SharpTimerError("PlayerPawn is null."); + Utils.LogError("PlayerPawn is null."); return; } if (player.PlayerPawn.Value!.MovementServices == null) { - SharpTimerError("MovementServices is null."); + Utils.LogError("MovementServices is null."); return; } - int playerSlot = player.Slot; - string steamID = player.SteamID.ToString(); + int slot = player.Slot; string playerName = player.PlayerName; try { - connectedPlayers[playerSlot] = new CCSPlayerController(player.Handle); - playerTimers[playerSlot] = new PlayerTimerInfo(); - playerJumpStats[playerSlot] = new PlayerJumpStats(); - if (enableReplays) playerReplays[playerSlot] = new PlayerReplays(); - playerTimers[playerSlot].MovementService = new CCSPlayer_MovementServices(player.PlayerPawn.Value.MovementServices!.Handle); - playerTimers[playerSlot].StageTimes = new Dictionary(); - playerTimers[playerSlot].StageVelos = new Dictionary(); - if (AdminManager.PlayerHasPermissions(player, "@css/root")) playerTimers[playerSlot].ZoneToolWire = new Dictionary(); - playerTimers[playerSlot].CurrentMapStage = 0; - playerTimers[playerSlot].CurrentMapCheckpoint = 0; - SetNormalStyle(player); - playerTimers[playerSlot].IsRecordingReplay = false; - playerTimers[playerSlot].SetRespawnPos = null; - playerTimers[playerSlot].SetRespawnAng = null; - playerTimers[playerSlot].SoundsEnabled = soundsEnabledByDefault; - - if (isForBot == false) _ = Task.Run(async () => await IsPlayerATester(steamID, playerSlot)); - - //PlayerSettings - if (enableDb) _ = Task.Run(async () => await GetPlayerStats(player, steamID, playerName, playerSlot, true)); - - if (connectMsgEnabled == true && !enableDb) PrintToChatAll(Localizer["connect_message", player.PlayerName]); - if (cmdJoinMsgEnabled == true && isForBot == false) PrintAllEnabledCommands(player); - - SharpTimerDebug($"Added player {player.PlayerName} with UserID {player.UserId} to connectedPlayers"); - SharpTimerDebug($"Total players connected: {connectedPlayers.Count}"); - SharpTimerDebug($"Total playerTimers: {playerTimers.Count}"); - SharpTimerDebug($"Total playerReplays: {playerReplays.Count}"); - - if (removeLegsEnabled == true) + connectedPlayers[slot] = new CCSPlayerController(player.Handle); + playerTimers[slot] = new PlayerTimerInfo(); + + if (playerTimers.TryGetValue(slot, out var playerTime)) { - player.PlayerPawn.Value.Render = Color.FromArgb(254, 254, 254, 254); - Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseModelEntity", "m_clrRender"); + if (enableReplays) + playerReplays[slot] = new PlayerReplays(); + + if (AdminManager.PlayerHasPermissions(player, "@css/root")) + playerTime.ZoneToolWire = new Dictionary(); + + playerTime.MovementService = new CCSPlayer_MovementServices(player.PlayerPawn.Value.MovementServices!.Handle); + playerTime.StageTimes = new Dictionary(); + playerTime.StageVelos = new Dictionary(); + playerTime.CurrentMapStage = 0; + playerTime.CurrentMapCheckpoint = 0; + playerTime.IsRecordingReplay = false; + playerTime.SetRespawnPos = null; + playerTime.SetRespawnAng = null; + playerTime.SoundsEnabled = soundsEnabledByDefault; + + SetNormalStyle(player); + } + + if (isForBot == false) + { + string steamID = player.SteamID.ToString(); + + _ = Task.Run(async () => await IsPlayerATester(steamID, slot)); + + if (enableDb) + _ = Task.Run(async () => await GetPlayerStats(player, steamID, playerName, slot, true)); + + if (cmdJoinMsgEnabled == true) + PrintAllEnabledCommands(player); + + if (connectMsgEnabled == true && !enableDb) + Utils.PrintToChatAll(Localizer["connect_message", player.PlayerName]); } + + Utils.LogDebug($"Added player {player.PlayerName} with UserID {player.UserId} to connectedPlayers"); + Utils.LogDebug($"Total players connected: {connectedPlayers.Count}"); + Utils.LogDebug($"Total playerTimers: {playerTimers.Count}"); + Utils.LogDebug($"Total playerReplays: {playerReplays.Count}"); } finally { - if (connectedPlayers[playerSlot] == null) - { - connectedPlayers.Remove(playerSlot); - } + if (connectedPlayers[slot] == null) + connectedPlayers.Remove(slot); - if (playerTimers[playerSlot] == null) + if (playerTimers[slot] == null) { - playerTimers.Remove(playerSlot); + playerTimers.Remove(slot); } } } catch (Exception ex) { - SharpTimerError($"Error in OnPlayerConnect: {ex.Message}"); + Utils.LogError($"Error in OnPlayerConnect: {ex.Message}"); } } - private void OnPlayerSpawn(CCSPlayerController? player) - { - //just.. dont ask. - AddTimer(0f, () => - { - if (spawnOnRespawnPos == true && currentRespawnPos != null) - player!.PlayerPawn.Value!.Teleport(currentRespawnPos!, null, null); - }); - - if (enableReplays && enableSRreplayBot && connectedReplayBots.Count == 0) - { - AddTimer(5.0f, () => - { - if (ConVar.Find("mp_force_pick_time")!.GetPrimitiveValue() == 1.0 && ConVar.Find("mp_humanteam")!.StringValue == "ct") - _ = Task.Run(async () => await SpawnReplayBot()); - else - { - SharpTimerError("Couldnt Spawn Replay bot! Please make sure you have the following in your custom_exec.cfg\n" - + "mp_force_pick_time 1\n" - + "mp_humanteam ct\n"); - } - }); - } - } - private void OnPlayerDisconnect(CCSPlayerController? player, bool isForBot = false) { if (player == null) return; try { - if (isForBot == true && connectedReplayBots.TryGetValue(player.Slot, out var connectedReplayBot)) - { - connectedReplayBots.Remove(player.Slot); - SharpTimerDebug($"Removed bot {connectedReplayBot.PlayerName} with UserID {connectedReplayBot.UserId} from connectedReplayBots."); - } if (connectedPlayers.TryGetValue(player.Slot, out var connectedPlayer)) { - + connectedPlayers.Remove(player.Slot); //schizo removing data from memory @@ -156,13 +129,6 @@ private void OnPlayerDisconnect(CCSPlayerController? player, bool isForBot = fal playerCheckpoints[player.Slot] = new List(); playerCheckpoints.Remove(player.Slot); - //schizo removing replay bots after last dc - AddTimer(5.0f, () => - { - if(Utilities.GetPlayers().Count == 0) - connectedReplayBots = []; - }); - specTargets.Remove(player.Pawn.Value!.EntityHandle.Index); if (enableReplays) @@ -172,61 +138,22 @@ private void OnPlayerDisconnect(CCSPlayerController? player, bool isForBot = fal playerReplays.Remove(player.Slot); } - SharpTimerDebug($"Removed player {connectedPlayer.PlayerName} with UserID {connectedPlayer.UserId} from connectedPlayers."); - SharpTimerDebug($"Removed specTarget index {player.Pawn.Value.EntityHandle.Index} from specTargets."); - SharpTimerDebug($"Total players connected: {connectedPlayers.Count}"); - SharpTimerDebug($"Total playerTimers: {playerTimers.Count}"); - SharpTimerDebug($"Total specTargets: {specTargets.Count}"); + Utils.LogDebug($"Removed player {connectedPlayer.PlayerName} with UserID {connectedPlayer.UserId} from connectedPlayers."); + Utils.LogDebug($"Removed specTarget index {player.Pawn.Value.EntityHandle.Index} from specTargets."); + Utils.LogDebug($"Total players connected: {connectedPlayers.Count}"); + Utils.LogDebug($"Total playerTimers: {playerTimers.Count}"); + Utils.LogDebug($"Total specTargets: {specTargets.Count}"); if (connectMsgEnabled == true && isForBot == false) { - PrintToChatAll(Localizer["disconnect_message", connectedPlayer.PlayerName]); + Utils.PrintToChatAll(Localizer["disconnect_message", connectedPlayer.PlayerName]); } } } catch (Exception ex) { - SharpTimerError($"Error in OnPlayerDisconnect (probably replay bot related lolxd): {ex.Message}"); - } - } - - private HookResult OnPlayerChat(CCSPlayerController? player, CommandInfo message) - { - if (displayChatTags == false) - return HookResult.Continue; - - string msg; - - if (player == null || !player.IsValid || player.IsBot || string.IsNullOrEmpty(message.GetArg(1))) - return HookResult.Handled; - else - msg = message.GetArg(1); - - playerTimers[player.Slot].AFKTicks = 0; - - if (msg.Length > 0 && (msg[0] == '!' || msg[0] == '/' || msg[0] == '.')) - return HookResult.Continue; - else - { - string rankColor = GetRankColorForChat(player); - - if (playerTimers.TryGetValue(player.Slot, out PlayerTimerInfo? value)) - { - string deadText = player.PawnIsAlive ? "" : $"{ChatColors.Grey}*DEAD* "; - string vipText = (value.IsVip ? $"{ChatColors.Magenta}{customVIPTag} " : ""); - if (player.Team == CsTeam.Terrorist) - Server.PrintToChatAll($" {deadText}{vipText}{rankColor}{value.CachedRank} {ChatColors.ForTeam(CsTeam.Terrorist)}{player.PlayerName} {ChatColors.Default}: {msg}"); - if (player.Team == CsTeam.CounterTerrorist) - Server.PrintToChatAll($" {deadText}{vipText}{rankColor}{value.CachedRank} {ChatColors.ForTeam(CsTeam.CounterTerrorist)}{player.PlayerName} {ChatColors.Default}: {msg}"); - if (player.Team == CsTeam.Spectator) - Server.PrintToChatAll($" {ChatColors.Grey}*SPEC* {ChatColors.ForTeam(CsTeam.Spectator)}{player.PlayerName} {ChatColors.Default}: {msg}"); - if (player.Team == CsTeam.None) - Server.PrintToChatAll($" {ChatColors.ForTeam(CsTeam.None)}{player.PlayerName} {ChatColors.Default}: {msg}"); - } - - return HookResult.Handled; + Utils.LogError($"Error in OnPlayerDisconnect (probably replay bot related lolxd): {ex.Message}"); } - } } } \ No newline at end of file diff --git a/src/Player/PlayerScoreboard.cs b/src/Player/PlayerScoreboard.cs index 10aa4fa8..3c224b96 100644 --- a/src/Player/PlayerScoreboard.cs +++ b/src/Player/PlayerScoreboard.cs @@ -39,7 +39,7 @@ private void assignScoreboard(CCSPlayerController player) { if (!cachedPlacements.TryGetValue(slot, out var placement)) fetchPlayerPlacement(slot, player.SteamID.ToString()); else - player.Score = -(placement == 0 ? 99999 : placement); + player.Score = -placement; if (stageTriggerCount <= 1) { // Linear map, show checkpoints matchStats.Kills = timer.CurrentMapCheckpoint; diff --git a/src/Player/PlayerTimers.cs b/src/Player/PlayerTimers.cs index 8cf6ca25..63a9b618 100644 --- a/src/Player/PlayerTimers.cs +++ b/src/Player/PlayerTimers.cs @@ -496,7 +496,7 @@ public async Task DumpPlayerStageTimesToJson(CCSPlayerController? player, string if (!IsAllowedPlayer(player)) return; string fileName = $"{currentMapName!.ToLower()}_stage_times.json"; - string playerStageRecordsPath = Path.Join(playerStagesPath, fileName); + string playerStageRecordsPath = Path.Join(gameDir, "csgo", "cfg", "SharpTimer", "PlayerStageData", fileName); try { diff --git a/src/Plugin/Classes.cs b/src/Plugin/Classes.cs index 86746d41..4ccb10a3 100644 --- a/src/Plugin/Classes.cs +++ b/src/Plugin/Classes.cs @@ -16,7 +16,11 @@ You should have received a copy of the GNU General Public License using System.Text.Json.Serialization; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Utils; +using SharpTimerAPI; +using SharpTimerAPI.Events; +using FixVectorLeak; namespace SharpTimer { @@ -25,14 +29,11 @@ public class EntityCache { public List Triggers { get; private set; } public List InfoTeleportDestinations { get; private set; } - public List InfoTargetEntities { get; private set; } public EntityCache() { - Triggers = []; - InfoTeleportDestinations = []; - InfoTargetEntities = []; - UpdateCache(); + Triggers = new(); + InfoTeleportDestinations = new(); } public void UpdateCache() @@ -161,7 +162,7 @@ public enum CurrentMode public double Sync { get; set; } public int GoodSync { get; set; } public int TotalSync { get; set; } - public List Rotation { get; set; } = new List(); + public List Rotation { get; set; } = new List(); //player settings/stats public bool Azerty { get; set; } @@ -172,11 +173,9 @@ public enum CurrentMode public bool GivenWeapon { get; set; } public bool SoundsEnabled { get; set; } public bool BindsDisabled { get; set; } - public bool HideJumpStats { get; set; } public int PlayerFov { get; set; } public int TimesConnected { get; set; } - public int TicksSinceLastCmd { get; set; } - public int TicksSinceLastRankUpdate { get; set; } + public DateTime CmdCooldown { get; set; } //super special stuff for testers public bool IsTester { get; set; } @@ -208,6 +207,9 @@ public enum CurrentMode //set respawn public string? SetRespawnPos { get; set; } public string? SetRespawnAng { get; set; } + //api stuff + public bool RespawnCmdBlocked { get; set; } + public bool TimerCmdBlocked { get; set; } public class ViewAngle { @@ -215,7 +217,7 @@ public class ViewAngle public float Y { get; set; } public float Z { get; set; } - public ViewAngle (QAngle angles) + public ViewAngle (QAngle_t angles) { X = angles.X; Y = angles.Y; @@ -247,45 +249,6 @@ public class CurrentZoneInfo public int CurrentBonusNumber { get; set; } } - public class PlayerJumpStats - { - public int FramesOnGround { get; set; } - public int LastFramesOnGround { get; set; } - public bool OnGround { get; set; } - public bool LastOnGround { get; set; } - public string? LastPosOnGround { get; set; } - public string? LastSpeed { get; set; } - public string? JumpPos { get; set; } - public string? OldJumpPos { get; set; } - public string? JumpSpeed { get; set; } - public bool Jumped { get; set; } - public string? LastJumpType { get; set; } - public bool LastDucked { get; set; } - public bool LandedFromSound { get; set; } - public bool LastLandedFromSound { get; set; } - public int WTicks { get; set; } - - public List