From 898f86f88813c7dc04cf4ae97a10996807a6384b Mon Sep 17 00:00:00 2001 From: Juzlus Date: Fri, 12 Sep 2025 02:24:04 +0200 Subject: [PATCH] v1.0.4 --- .../Classes/WasdManager.cs | 66 ++ WASDMenuAPI - SRC Files/Classes/WasdMenu.cs | 25 + .../Classes/WasdMenuOption.cs | 13 + .../Classes/WasdMenuPlayer.cs | 229 ++++++ .../Interfaces/IWasdMenu.cs | 13 + .../Interfaces/IWasdMenuManager.cs | 21 + .../Interfaces/IWasdMenuOption.cs | 11 + WASDMenuAPI - SRC Files/WASDMenuAPI.cs | 73 ++ WASDMenuAPI - SRC Files/WASDMenuAPI.csproj | 13 + WASDMenuAPI - SRC Files/WASDMenuAPI.sln | 25 + .../jRandomSkills.csproj | 7 + .../src/command/Command.cs | 36 +- .../src/jRandomSkills.cs | 5 +- jRandomSkills - SRC Files/src/lang/en.json | 48 +- jRandomSkills - SRC Files/src/lang/pl.json | 48 +- jRandomSkills - SRC Files/src/lang/pt-br.json | 48 +- jRandomSkills - SRC Files/src/lang/zh.json | 20 +- .../src/player/ISkill.cs | 43 +- .../src/player/PlayerEvents.cs | 708 ++++++++++++------ .../src/player/PlayerOnTick.cs | 7 +- .../src/player/skills/Aimbot.cs | 18 +- .../src/player/skills/Anomaly.cs | 74 +- .../src/player/skills/AntyFlash.cs | 50 +- .../src/player/skills/AntyHead.cs | 27 +- .../src/player/skills/AreaReaper.cs | 44 +- .../src/player/skills/Armored.cs | 35 +- .../src/player/skills/Assassin.cs | 30 +- .../src/player/skills/Astronaut.cs | 31 +- .../src/player/skills/Baseball.cs | 117 ++- .../src/player/skills/Behind.cs | 44 +- .../src/player/skills/BladeMaster.cs | 54 +- .../src/player/skills/BunnyHop.cs | 5 +- .../src/player/skills/C4Camouflage.cs | 109 +-- .../src/player/skills/Catapult.cs | 52 +- .../src/player/skills/Chicken.cs | 87 +-- .../src/player/skills/ChillOut.cs | 34 +- .../src/player/skills/Cutter.cs | 26 +- .../src/player/skills/Darkness.cs | 67 +- .../src/player/skills/Deactivator.cs | 62 +- .../src/player/skills/Deaf.cs | 78 +- .../src/player/skills/Disarmament.cs | 55 +- .../src/player/skills/Distancer.cs | 33 +- .../src/player/skills/Dracula.cs | 22 +- .../src/player/skills/Duplicator.cs | 67 +- .../src/player/skills/Dwarf.cs | 52 +- .../src/player/skills/EnemySpawn.cs | 55 +- .../src/player/skills/ExplosiveShot.cs | 30 +- .../src/player/skills/FalconEye.cs | 54 +- .../src/player/skills/Flash.cs | 56 +- .../src/player/skills/Fortnite.cs | 73 +- .../src/player/skills/FragileBomb.cs | 44 +- .../src/player/skills/FriendlyFire.cs | 34 +- .../src/player/skills/FrozenDecoy.cs | 88 +-- .../src/player/skills/Gambler.cs | 112 +++ .../src/player/skills/Ghost.cs | 107 +-- .../src/player/skills/Glaz.cs | 51 +- .../src/player/skills/Glitch.cs | 53 +- .../src/player/skills/Glue.cs | 30 +- .../src/player/skills/GodMode.cs | 60 +- .../src/player/skills/HealingSmoke.cs | 130 ++-- .../src/player/skills/Hermit.cs | 82 +- .../src/player/skills/HolyHandGrenade.cs | 50 +- .../src/player/skills/Impostor.cs | 19 - .../src/player/skills/InfiniteAmmo.cs | 58 +- .../src/player/skills/Jackal.cs | 43 +- .../src/player/skills/Jammer.cs | 54 +- .../src/player/skills/Jester.cs | 123 +++ .../src/player/skills/JumpBan.cs | 81 +- .../src/player/skills/JumpingJack.cs | 18 +- .../src/player/skills/KillerFlash.cs | 39 +- .../src/player/skills/LifeSwap.cs | 51 +- .../src/player/skills/LongKnife.cs | 80 +- .../src/player/skills/LongZeus.cs | 94 +-- .../src/player/skills/Magnifier.cs | 53 +- .../src/player/skills/Medic.cs | 52 +- .../src/player/skills/MoneySwap.cs | 52 +- .../src/player/skills/Muhammed.cs | 20 +- .../src/player/skills/Ninja.cs | 102 +-- .../src/player/skills/NoNades.cs | 27 +- .../src/player/skills/NoRecoil.cs | 44 +- .../src/player/skills/Noclip.cs | 54 +- .../src/player/skills/None.cs | 5 +- .../src/player/skills/OneShot.cs | 13 +- .../src/player/skills/OnlyHead.cs | 27 +- .../src/player/skills/PawelJumper.cs | 23 +- .../src/player/skills/Phoenix.cs | 46 +- .../src/player/skills/Pilot.cs | 42 +- .../src/player/skills/Planter.cs | 37 +- .../src/player/skills/Poison.cs | 70 +- .../src/player/skills/PrimaryBan.cs | 69 +- .../src/player/skills/Prosthesis.cs | 27 +- .../src/player/skills/PsychicDefusing.cs | 141 ++-- .../src/player/skills/Push.cs | 50 +- .../src/player/skills/Pyro.cs | 37 +- .../src/player/skills/QuickShot.cs | 4 +- .../src/player/skills/RadarHack.cs | 4 +- .../src/player/skills/Rambo.cs | 15 - .../src/player/skills/RandomWeapon.cs | 54 +- .../src/player/skills/ReZombie.cs | 86 +-- .../src/player/skills/ReactiveArmor.cs | 81 +- .../src/player/skills/Regeneration.cs | 4 +- .../src/player/skills/Replicator.cs | 66 +- .../src/player/skills/Retreat.cs | 54 +- .../src/player/skills/ReturnToSender.cs | 40 +- .../src/player/skills/RichBoy.cs | 20 +- .../src/player/skills/RobinHood.cs | 24 +- .../src/player/skills/Rubber.cs | 52 +- .../src/player/skills/Saper.cs | 60 +- .../src/player/skills/SecondLife.cs | 59 +- .../src/player/skills/Shade.cs | 46 +- .../src/player/skills/ShortBomb.cs | 22 +- .../src/player/skills/Silent.cs | 30 +- .../src/player/skills/SniperElite.cs | 41 +- .../src/player/skills/Soldier.cs | 34 +- .../src/player/skills/SoundMaker.cs | 67 +- .../src/player/skills/Spectator.cs | 54 +- .../src/player/skills/SwapPosition.cs | 61 +- .../src/player/skills/Teleporter.cs | 23 +- .../src/player/skills/Thief.cs | 66 +- .../src/player/skills/ThirdEye.cs | 32 +- .../src/player/skills/Thorns.cs | 27 +- .../src/player/skills/ToxicSmoke.cs | 138 ++-- .../src/player/skills/Wallhack.cs | 46 +- .../src/player/skills/Watchmaker.cs | 74 +- .../src/player/skills/WeaponsSwap.cs | 69 +- .../src/player/skills/Zeus.cs | 76 +- jRandomSkills - SRC Files/src/utils/Config.cs | 2 + .../src/utils/SkillUtils.cs | 72 ++ .../plugins/jRandomSkills/Config.json | 18 + .../plugins/jRandomSkills/WASDMenuAPI.dll | Bin 0 -> 15360 bytes .../plugins/jRandomSkills/jRandomSkills.dll | Bin 379392 -> 344576 bytes .../plugins/jRandomSkills/lang/en.json | 48 +- .../plugins/jRandomSkills/lang/pl.json | 48 +- .../plugins/jRandomSkills/lang/pt-br.json | 48 +- .../plugins/jRandomSkills/lang/zh.json | 20 +- readme-pl.md | 28 +- readme.md | 28 +- 137 files changed, 3553 insertions(+), 3780 deletions(-) create mode 100644 WASDMenuAPI - SRC Files/Classes/WasdManager.cs create mode 100644 WASDMenuAPI - SRC Files/Classes/WasdMenu.cs create mode 100644 WASDMenuAPI - SRC Files/Classes/WasdMenuOption.cs create mode 100644 WASDMenuAPI - SRC Files/Classes/WasdMenuPlayer.cs create mode 100644 WASDMenuAPI - SRC Files/Interfaces/IWasdMenu.cs create mode 100644 WASDMenuAPI - SRC Files/Interfaces/IWasdMenuManager.cs create mode 100644 WASDMenuAPI - SRC Files/Interfaces/IWasdMenuOption.cs create mode 100644 WASDMenuAPI - SRC Files/WASDMenuAPI.cs create mode 100644 WASDMenuAPI - SRC Files/WASDMenuAPI.csproj create mode 100644 WASDMenuAPI - SRC Files/WASDMenuAPI.sln create mode 100644 jRandomSkills - SRC Files/src/player/skills/Gambler.cs create mode 100644 jRandomSkills - SRC Files/src/player/skills/Jester.cs create mode 100644 jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll diff --git a/WASDMenuAPI - SRC Files/Classes/WasdManager.cs b/WASDMenuAPI - SRC Files/Classes/WasdManager.cs new file mode 100644 index 0000000..f6322ea --- /dev/null +++ b/WASDMenuAPI - SRC Files/Classes/WasdManager.cs @@ -0,0 +1,66 @@ +using CounterStrikeSharp.API.Core; +using WASDSharedAPI; + +namespace WASDMenuAPI.Classes; + +public class WasdManager : IWasdMenuManager +{ + public void OpenMainMenu(CCSPlayerController? player, IWasdMenu? menu) + { + if(player == null) + return; + WASDMenuAPI.Players[player.SteamID].OpenMainMenu((WasdMenu?)menu); + } + + public void CloseMenu(CCSPlayerController? player) + { + if(player == null) + return; + WASDMenuAPI.Players[player.SteamID].OpenMainMenu(null); + } + + public void CloseSubMenu(CCSPlayerController? player) + { + if(player == null) + return; + WASDMenuAPI.Players[player.SteamID].CloseSubMenu(); + } + + public void CloseAllSubMenus(CCSPlayerController? player) + { + if(player == null) + return; + WASDMenuAPI.Players[player.SteamID].CloseAllSubMenus(); + } + + public void OpenSubMenu(CCSPlayerController? player, IWasdMenu? menu) + { + if (player == null) + return; + WASDMenuAPI.Players[player.SteamID].OpenSubMenu(menu); + } + + public IWasdMenu CreateMenu(string title = "", string controlText = "") + { + WasdMenu menu = new WasdMenu + { + Title = title, + ControlText = controlText + }; + return menu; + } + + public bool HasMenu(CCSPlayerController? player) + { + if (player == null) + return false; + return WASDMenuAPI.Players.ContainsKey(player.SteamID); + } + + public void UpdateActiveMenu(CCSPlayerController? player, Dictionary> list) + { + if (player == null) + return; + WASDMenuAPI.Players[player.SteamID].UpdateActiveMenu(list); + } +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Classes/WasdMenu.cs b/WASDMenuAPI - SRC Files/Classes/WasdMenu.cs new file mode 100644 index 0000000..b84d9be --- /dev/null +++ b/WASDMenuAPI - SRC Files/Classes/WasdMenu.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API.Core; +using WASDSharedAPI; + +namespace WASDMenuAPI.Classes; + +public class WasdMenu : IWasdMenu +{ + public string Title { get; set; } = ""; + public string ControlText { get; set; } = ""; + public LinkedList? Options { get; set; } = new(); + public LinkedListNode? Prev { get; set; } = null; + public LinkedListNode Add(string display, Action onChoice) + { + if (Options == null) + Options = new(); + WasdMenuOption newOption = new WasdMenuOption + { + OptionDisplay = display, + OnChoose = onChoice, + Index = Options.Count, + Parent = this + }; + return Options.AddLast(newOption); + } +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Classes/WasdMenuOption.cs b/WASDMenuAPI - SRC Files/Classes/WasdMenuOption.cs new file mode 100644 index 0000000..fcc5daa --- /dev/null +++ b/WASDMenuAPI - SRC Files/Classes/WasdMenuOption.cs @@ -0,0 +1,13 @@ +using CounterStrikeSharp.API.Core; +using WASDMenuAPI.Classes; +using WASDSharedAPI; + +namespace WASDMenuAPI; + +public class WasdMenuOption : IWasdMenuOption +{ + public IWasdMenu? Parent { get; set; } + public string? OptionDisplay { get; set; } + public Action? OnChoose { get; set; } + public int Index { get; set; } +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Classes/WasdMenuPlayer.cs b/WASDMenuAPI - SRC Files/Classes/WasdMenuPlayer.cs new file mode 100644 index 0000000..6056ba9 --- /dev/null +++ b/WASDMenuAPI - SRC Files/Classes/WasdMenuPlayer.cs @@ -0,0 +1,229 @@ +using System.Text; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using WASDMenuAPI.Classes; +using WASDSharedAPI; + +namespace WASDMenuAPI; + +public class WasdMenuPlayer +{ + public CCSPlayerController player { get; set; } + public WasdMenu? MainMenu = null; + public LinkedListNode? CurrentChoice = null; + public LinkedListNode? MenuStart = null; + public string CenterHtml = ""; + public int VisibleOptions = 3; + public PlayerButtons Buttons { get; set; } + + public int scrollIndex = 0; + public int maxLength = 21; + public int scrollJump = 3; + + public void OpenMainMenu(WasdMenu? menu) + { + if (menu == null) + { + MainMenu = null; + CurrentChoice = null; + CenterHtml = ""; + return; + } + MainMenu = menu; + CurrentChoice = MainMenu.Options?.First; + MenuStart = CurrentChoice; + UpdateCenterHtml(); + } + + public void OpenSubMenu(IWasdMenu? menu) + { + if (menu == null) + { + CurrentChoice = MainMenu?.Options?.First; + MenuStart = CurrentChoice; + UpdateCenterHtml(); + return; + } + + CurrentChoice = menu.Options?.First; + MenuStart = CurrentChoice; + UpdateCenterHtml(); + } + public void GoBackToPrev(LinkedListNode? menu) + { + if (menu == null) + { + CurrentChoice = MainMenu?.Options?.First; + MenuStart = CurrentChoice; + UpdateCenterHtml(); + return; + } + + CurrentChoice = menu; + if (CurrentChoice.Value.Index >= 5 ) + { + MenuStart = CurrentChoice; + for (int i = 0; i < VisibleOptions; i++) + { + MenuStart = MenuStart?.Previous; + } + } + else + MenuStart = CurrentChoice.List?.First; + UpdateCenterHtml(); + } + + public void CloseSubMenu() + { + if (CurrentChoice?.Value.Parent?.Prev == null) + return; + GoBackToPrev(CurrentChoice?.Value.Parent.Prev); + } + + public void CloseAllSubMenus() + { + OpenSubMenu(null); + } + + public void Choose() + { + CurrentChoice?.Value.OnChoose?.Invoke(player, CurrentChoice.Value); + } + + public void ScrollDown() + { + if(CurrentChoice == null || MainMenu == null) + return; + scrollIndex = 0; + CurrentChoice = CurrentChoice.Next ?? CurrentChoice.List?.First; + MenuStart = CurrentChoice!.Value.Index >= VisibleOptions ? MenuStart!.Next : CurrentChoice.List?.First; + UpdateCenterHtml(); + } + + public void ScrollUp() + { + if(CurrentChoice == null || MainMenu == null) + return; + scrollIndex = 0; + CurrentChoice = CurrentChoice.Previous ?? CurrentChoice.List?.Last; + if (CurrentChoice == CurrentChoice?.List?.Last && CurrentChoice?.Value.Index >= VisibleOptions) + { + MenuStart = CurrentChoice; + for (int i = 0; i < VisibleOptions - 1; i++) + MenuStart = MenuStart?.Previous; + } + else + MenuStart = CurrentChoice!.Value.Index >= VisibleOptions ? MenuStart!.Previous : CurrentChoice.List?.First; + UpdateCenterHtml(); + } + + private void UpdateCenterHtml() + { + if (CurrentChoice == null || MainMenu == null || MenuStart == null) + return; + + StringBuilder builder = new(); + string endControl = ""; + LinkedListNode? option = MenuStart; + + if (option?.Value?.Parent?.Title != "") + builder.AppendLine($"{option.Value.Parent?.Title}
"); + + if (option?.Value?.Parent?.ControlText != "") + endControl = option?.Value?.Parent?.ControlText ?? ""; + + int shown = 0; + int maxOptions = VisibleOptions; + + while (shown < maxOptions && option != null && option.Value != null) + { + /* if (shown == maxOptions - 1 && option.Next != null) + { + builder.AppendLine( + $"
"); + break; + }*/ + string text = option.Value.OptionDisplay!; + if (option == CurrentChoice) + { + if (text.Length > maxLength) + { + if (scrollIndex >= text.Length - maxLength) + { + text = text.Substring(scrollIndex); + if (Server.TickCount % 32 == 0) + scrollIndex = 0; + } + else + { + text = text.Substring(scrollIndex, maxLength); + if (Server.TickCount % 32 == 0) + scrollIndex += scrollJump; + } + } + + builder.AppendLine($"
[ {text} ]
"); + } + else + builder.AppendLine($"{text.Substring(0, maxLength)}
"); + + option = option.Next; + shown++; + } + + if (!string.IsNullOrEmpty(endControl)) + builder.AppendLine(endControl); + + builder.AppendLine(""); + CenterHtml = builder.ToString(); + } + + public void UpdateActiveMenu(Dictionary> list) + { + if (list.Count == 0) + { + OpenMainMenu(null); + return; + } + + if (MainMenu == null || MainMenu.Options == null) + return; + + MainMenu.Options.Clear(); + bool choiceExists = false; + + foreach (var item in list) + { + WasdMenuOption newOption = new WasdMenuOption + { + OptionDisplay = item.Key, + OnChoose = item.Value, + Index = MainMenu.Options.Count, + Parent = MainMenu + }; + MainMenu.Options.AddLast(newOption); + + if (CurrentChoice?.Value?.OptionDisplay == item.Key) + { + CurrentChoice = MainMenu.Options?.Last; + choiceExists = true; + } + } + if (!choiceExists) + CurrentChoice = MainMenu.Options?.First; + + if (CurrentChoice != null) + { + if (CurrentChoice.Value.Index >= VisibleOptions) + { + MenuStart = CurrentChoice; + for (int i = 0; i < VisibleOptions - 1; i++) + MenuStart = MenuStart?.Previous; + } + else + MenuStart = MainMenu.Options?.First; + } + + UpdateCenterHtml(); + } +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Interfaces/IWasdMenu.cs b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenu.cs new file mode 100644 index 0000000..b884854 --- /dev/null +++ b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenu.cs @@ -0,0 +1,13 @@ +using CounterStrikeSharp.API.Core; + +namespace WASDSharedAPI; + +public interface IWasdMenu +{ + public string? Title { get; set; } + public string? ControlText { get; set; } + public LinkedList? Options { get; set; } + // previous option node + public LinkedListNode? Prev { get; set; } + public LinkedListNode Add(string display, Action onChoice); +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuManager.cs b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuManager.cs new file mode 100644 index 0000000..b895851 --- /dev/null +++ b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuManager.cs @@ -0,0 +1,21 @@ +using CounterStrikeSharp.API.Core; + +namespace WASDSharedAPI; + +public interface IWasdMenuManager +{ + //open the menu as main menu + public void OpenMainMenu(CCSPlayerController? player, IWasdMenu? menu); + //close all menus + public void CloseMenu(CCSPlayerController? player); + //close current submenu and go to previous menu/submenu + public void CloseSubMenu(CCSPlayerController? player); + //close all submenus and go to main menu + public void CloseAllSubMenus(CCSPlayerController? player); + //open menu as submenu + public void OpenSubMenu(CCSPlayerController? player, IWasdMenu? menu); + //create new menu object + public IWasdMenu CreateMenu(string title = "", string ControlText = ""); + public bool HasMenu(CCSPlayerController? player); + public void UpdateActiveMenu(CCSPlayerController? player, Dictionary> list); +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuOption.cs b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuOption.cs new file mode 100644 index 0000000..be5bedb --- /dev/null +++ b/WASDMenuAPI - SRC Files/Interfaces/IWasdMenuOption.cs @@ -0,0 +1,11 @@ +using CounterStrikeSharp.API.Core; + +namespace WASDSharedAPI; + +public interface IWasdMenuOption +{ + public IWasdMenu? Parent { get; set; } + public string? OptionDisplay { get; set; } + public Action? OnChoose { get; set; } + public int Index { get; set; } +} \ No newline at end of file diff --git a/WASDMenuAPI - SRC Files/WASDMenuAPI.cs b/WASDMenuAPI - SRC Files/WASDMenuAPI.cs new file mode 100644 index 0000000..0f1897c --- /dev/null +++ b/WASDMenuAPI - SRC Files/WASDMenuAPI.cs @@ -0,0 +1,73 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using WASDMenuAPI.Classes; + +namespace WASDMenuAPI; + +public class WASDMenuAPI +{ + public string ModuleName => "WASDMenuAPI"; + public string ModuleVersion => "1.0.2"; + public string ModuleAuthor => "Interesting"; + + public static readonly Dictionary Players = []; + + public static void LoadPlugin(BasePlugin basePlugin, bool hotReload) + { + var wasdMenuManager = new WasdManager(); + basePlugin.RegisterEventHandler((@event, info) => + { + if (@event.Userid != null) + Players[@event.Userid.SteamID] = new WasdMenuPlayer + { + player = @event.Userid, + Buttons = 0 + }; + return HookResult.Continue; + }); + basePlugin.RegisterEventHandler((@event, info) => + { + if (@event.Userid != null) Players.Remove(@event.Userid.SteamID); + return HookResult.Continue; + }); + + basePlugin.RegisterListener(OnTick); + + if(hotReload) + foreach (var pl in Utilities.GetPlayers()) + { + Players[pl.SteamID] = new WasdMenuPlayer + { + player = pl, + Buttons = pl.Buttons + }; + } + } + + public static void OnTick() + { + foreach (var player in Players.Values.Where(p => p.MainMenu != null)) + { + if ((player.Buttons & PlayerButtons.Forward) == 0 && (player.player.Buttons & PlayerButtons.Forward) != 0) + { + player.ScrollUp(); + } + else if((player.Buttons & PlayerButtons.Back) == 0 && (player.player.Buttons & PlayerButtons.Back) != 0) + { + player.ScrollDown(); + } + else if((player.Buttons & PlayerButtons.Use) == 0 && (player.player.Buttons & PlayerButtons.Use) != 0) + { + player.Choose(); + } + + player.Buttons = player.player.Buttons; + if(player.CenterHtml != "") + Server.NextFrame(() => + player.player.PrintToCenterHtml(player.CenterHtml) + ); + } + } + + +} diff --git a/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj b/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj new file mode 100644 index 0000000..31757ff --- /dev/null +++ b/WASDMenuAPI - SRC Files/WASDMenuAPI.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/WASDMenuAPI - SRC Files/WASDMenuAPI.sln b/WASDMenuAPI - SRC Files/WASDMenuAPI.sln new file mode 100644 index 0000000..0d39d89 --- /dev/null +++ b/WASDMenuAPI - SRC Files/WASDMenuAPI.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WASDMenuAPI", "WASDMenuAPI.csproj", "{0119D01B-2F71-4918-B638-795C423E143F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0119D01B-2F71-4918-B638-795C423E143F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0119D01B-2F71-4918-B638-795C423E143F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0119D01B-2F71-4918-B638-795C423E143F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0119D01B-2F71-4918-B638-795C423E143F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {33517EB0-9056-4518-864C-37D0AFF4124B} + EndGlobalSection +EndGlobal diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj index b07a38b..725b60b 100644 --- a/jRandomSkills - SRC Files/jRandomSkills.csproj +++ b/jRandomSkills - SRC Files/jRandomSkills.csproj @@ -8,6 +8,7 @@ + @@ -17,6 +18,12 @@ + + + F:\CS2 Server\server\game\csgo\addons\counterstrikesharp\plugins\jRandomSkills\WASDMenuAPI.dll + + + True diff --git a/jRandomSkills - SRC Files/src/command/Command.cs b/jRandomSkills - SRC Files/src/command/Command.cs index e45902b..cc35b03 100644 --- a/jRandomSkills - SRC Files/src/command/Command.cs +++ b/jRandomSkills - SRC Files/src/command/Command.cs @@ -48,7 +48,7 @@ namespace jRandomSkills { if (player == null) return; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo == null) return; + if (playerInfo == null || playerInfo.IsDrawing) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; @@ -69,7 +69,7 @@ namespace jRandomSkills if (player == null || !AdminManager.PlayerHasPermissions(player, config.SetSkillCommands.Permissions)) return; var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => !p.IsBot && (p.SteamID.ToString().Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase) - || p.PlayerName.Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase)) ); + || p.PlayerName.Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase))); if (command.ArgCount < 2) { @@ -106,6 +106,9 @@ namespace jRandomSkills skillPlayer.SpecialSkill = src.player.Skills.None; Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); + if (skill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skill.Name}{ChatColors.Lime}: {skill.Description}", false); + player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); SkillUtils.PrintToChat(player, $"{Localization.GetTranslation("done_setskill")}: {ChatColors.LightRed}{skill.Name} {ChatColors.Lime}{Localization.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); @@ -175,17 +178,21 @@ namespace jRandomSkills private static void StartGame(CommandInfo command) { int cheats = command.GetArg(1) == "sv" ? 1 : 0; - Server.ExecuteCommand($"mp_freezetime {(cheats == 1 ? 0 : 5)}"); - Server.ExecuteCommand("mp_warmup_end"); - Server.ExecuteCommand("mp_restartgame 1"); + Server.ExecuteCommand($"mp_freezetime {(cheats == 1 ? 0 : 15)}"); + Server.ExecuteCommand("mp_overtime_enable 1"); + Server.ExecuteCommand($"sv_cheats {cheats}"); + Server.ExecuteCommand("mp_forcecamera 0"); - Instance.AddTimer(2.0f, () => { + if (Instance?.GameRules?.WarmupPeriod == true) + { + Server.ExecuteCommand("mp_warmup_end"); Server.PrintToChatAll($" {ChatColors.Green}{Localization.GetTranslation("game_start")}"); - Server.ExecuteCommand("mp_forcecamera 0"); - Server.ExecuteCommand($"mp_freezetime {(cheats == 1 ? 0 : 5)}"); - Server.ExecuteCommand("mp_overtime_enable 1"); - Server.ExecuteCommand($"sv_cheats {cheats}"); - }); + } + else + { + Server.ExecuteCommand("mp_restartgame 2"); + Instance?.AddTimer(2.0f, () => Server.PrintToChatAll($" {ChatColors.Green}{Localization.GetTranslation("game_start")}")); + } } [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] @@ -251,7 +258,7 @@ namespace jRandomSkills private static void Pause() { Server.PrintToChatAll($" {(gamePaused ? ChatColors.Green : ChatColors.Red)}{Localization.GetTranslation(gamePaused ? "unpause" : "pause")}"); - Server.ExecuteCommand( gamePaused ? "mp_unpause_match" : "mp_pause_match"); + Server.ExecuteCommand(gamePaused ? "mp_unpause_match" : "mp_pause_match"); gamePaused = !gamePaused; } @@ -299,7 +306,7 @@ namespace jRandomSkills Server.ExecuteCommand(param); } - [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] + [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] private static void Command_SetStaticSkill(CCSPlayerController? player, CommandInfo command) { Debug.WriteToDebug($"Player {player?.PlayerPawn} used the css_setstaticskill {command.ArgString} command."); @@ -348,6 +355,9 @@ namespace jRandomSkills Event.staticSkills.Add(targetPlayer.SteamID, skill); Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); + if (skill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skill.Name}{ChatColors.Lime}: {skill.Description}", false); + player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); SkillUtils.PrintToChat(player, $"{Localization.GetTranslation("done_setskill")}: {ChatColors.LightRed}{skill.Name} {ChatColors.Lime}{Localization.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index ee1be57..9443f4f 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Commands; using jRandomSkills.src.player; using jRandomSkills.src.utils; using System.Reflection; +using WASDSharedAPI; namespace jRandomSkills { @@ -19,6 +20,7 @@ namespace jRandomSkills public List SkillPlayer { get; } = []; public Random Random { get; } = new Random(); public CCSGameRules? GameRules { get; set; } + public IWasdMenuManager? MenuManager; public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleAuthor => "D3X, Juzlus"; @@ -32,9 +34,10 @@ namespace jRandomSkills Config.Initialize(); Localization.Load(); Debug.Load(); - Event.Load(); PlayerOnTick.Load(); + Event.Load(); Command.Load(); + WASDMenuAPI.WASDMenuAPI.LoadPlugin(Instance, hotReload); LoadAllSkills(); } diff --git a/jRandomSkills - SRC Files/src/lang/en.json b/jRandomSkills - SRC Files/src/lang/en.json index 54a88e7..c9938d1 100644 --- a/jRandomSkills - SRC Files/src/lang/en.json +++ b/jRandomSkills - SRC Files/src/lang/en.json @@ -18,7 +18,7 @@ "areareaper_desc": "You can choose a bomb site to deactivate", "areareaper_incorrect_site": "No such bomb site found.", "areareaper_no_site": "No bomb sites found.", - "areareaper_select_info": "Choose the bomb site you want to deactivate:", + "areareaper_select_info": "Select site to deactivate:", "areareaper_site_disabled": "Bomb site {0} has been deactivated - no bombs can be planted there!", "areareaper_used_info": "Your skill has already been used.", @@ -66,19 +66,19 @@ "darkness_desc": "Applies a darkness effect to a chosen enemy", "darkness_enemy_info": "Let the lights go out.", "darkness_player_info": "Darkness has overtaken player '{0}'.", - "darkness_select_info": "Choose the player you want to apply the darkness effect to:", + "darkness_select_info": "Select player for darkness:", "deactivator": "Deactivator", "deactivator_desc": "Choose a player whose skill you want to disable", "deactivator_enemy_info": "Your skill has been disabled.", "deactivator_player_info": "Player '{0}'s skill has been disabled.", - "deactivator_select_info": "Choose the player whose skill you want to disable:", + "deactivator_select_info": "Disable a player's skill:", "deaf": "Deaf", "deaf_desc": "Choose a player to mute all sounds for", "deaf_enemy_info": "Your headphones have left the game.", "deaf_player_info": "Sound has been disabled for player '{0}'.", - "deaf_select_info": "Choose the player for whom you want to mute all sounds:", + "deaf_select_info": "Mute all sounds for player:", "disarmament": "Disarmament", "disarmament_desc": "You have a random chance to make an enemy drop their weapon on hit", @@ -93,7 +93,7 @@ "duplicator": "Duplicator", "duplicator_desc": "Choose a player to copy their skill", "duplicator_player_info": "Player '{0}'s skill has been copied.", - "duplicator_select_info": "Choose the player whose skill you want to copy:", + "duplicator_select_info": "Copy a player's skill:", "dwarf": "Dwarf", "dwarf_desc": "Random character size at the start of the round", @@ -129,6 +129,11 @@ "frozendecoy": "Freezing Decoy", "frozendecoy_desc": "Your decoy freezes all nearby players", + "gambler": "Gambler", + "gambler_desc": "Select a skill from the list provided.", + "gambler_select_info": "Select your skill:", + "gambler_more": "Refresh for $100", + "ghost": "Ghost", "ghost_desc": "You are completely invisible", @@ -139,7 +144,7 @@ "glitch_desc": "Disables the radar for a chosen enemy", "glitch_enemy_info": "Your radar has been disabled.", "glitch_player_info": "Player '{0}'s radar has been disabled.", - "glitch_select_info": "Choose the player whose radar you want to disable:", + "glitch_select_info": "Turn off player's radar:", "glue": "Glue", "glue_desc": "Your grenades stick to walls", @@ -171,13 +176,19 @@ "jammer_desc": "Choose a player to disable their crosshair", "jammer_enemy_info": "Your crosshair has been disabled.", "jammer_player_info": "Player '{0}'s crosshair has been disabled.", - "jammer_select_info": "Choose the player whose crosshair you want to disable:", + "jammer_select_info": "Disable player's crosshair:", + + "jester": "Jester", + "jester_desc": "In jester mode, you cannot get or take any damage. This mode changes every few seconds.", + "jester_mode": "Jester Mode", + "jester_on": "ON", + "jester_off": "OFF", "jumpban": "Legless", "jumpban_desc": "Choose a player who cannot jump", "jumpban_enemy_info": "Someone cut off your legs.", "jumpban_player_info": "Player '{0}' can no longer jump.", - "jumpban_select_info": "Choose the player who cannot jump:", + "jumpban_select_info": "Ban player from jumping:", "jumpingjack": "Jumping Jack", "jumpingjack_desc": "Jumping restores health", @@ -189,7 +200,7 @@ "lifeswap_desc": "Choose a player to swap health with", "lifeswap_enemy_info": "Someone borrowed your health.", "lifeswap_player_info": "You swapped health with player '{0}'.", - "lifeswap_select_info": "Choose the player to swap health with:", + "lifeswap_select_info": "Swap health with player:", "longknife": "Long Knife", "longknife_desc": "A primary knife attack deals damage regardless of distance", @@ -201,7 +212,7 @@ "magnifier_desc": "Forces the enemy's screen to zoom in, reducing their field of view", "magnifier_enemy_info": "Your field of view has been distorted!", "magnifier_player_info": "Player '{0}' has been forced into zoom mode.", - "magnifier_select_info": "Select the player whose screen you want to magnify:", + "magnifier_select_info": "Magnify player's screen:", "medic": "Medic", "medic_desc": "Click [css_useSkill] to use a healing charge that restores 50 health", @@ -210,7 +221,7 @@ "moneyswap_desc": "Choose a player to swap money with", "moneyswap_enemy_info": "The tax office got you.", "moneyswap_player_info": "You swapped money with player '{0}'.", - "moneyswap_select_info": "Choose the player to swap money with:", + "moneyswap_select_info": "Swap money with player:", "muhammed": "Muhammed", "muhammed_desc": "You explode upon death, killing nearby players", @@ -257,13 +268,13 @@ "poison_desc": "Choose a player who will take damage every few seconds", "poison_enemy_info": "You have been poisoned.", "poison_player_info": "Player '{0}' has been poisoned.", - "poison_select_info": "Choose the player who will take damage every few seconds:", + "poison_select_info": "Poison a player:", "primaryban": "No Rifles", "primaryban_desc": "Choose a player who cannot use rifles", "primaryban_enemy_info": "You can no longer use rifles.", "primaryban_player_info": "Player '{0}' can no longer use rifles.", - "primaryban_select_info": "Choose the player to ban from using rifles:", + "primaryban_select_info": "Ban rifles for player:", "prosthesis": "Prosthesis", "prosthesis_desc": "Arms and legs are bulletproof", @@ -353,7 +364,7 @@ "thief_desc": "You can steal a skill from a chosen player", "thief_enemy_info": "Your skill has been stolen.", "thief_player_info": "Player '{0}'s skill has been stolen.", - "thief_select_info": "Choose the player whose skill you want to steal:", + "thief_select_info": "Steal a player's skill:", "thirdeye": "Third Eye", "thirdeye_desc": "Click [css_useSkill] to activate third-person view", @@ -394,7 +405,7 @@ "no_player": "No matching player found.", "duplicate_player": "More than one player found with the same name.", "selectplayerskill_command": "Type /t", - "selectplayerskill_incorrect_enemy_index": "No player found with that index.", + "selectplayerskill_incorrect_enemy_index": "No players were found to select.", "skill_not_found_setskill": "No such CHATCOLORS.REDskill found", "player_not_found_setskill": "No such CHATCOLORS.REDplayer found", @@ -420,7 +431,12 @@ "vote_alredy_voted": "You have already voted!", "vote_vote": "Vote", + "bombsite_a": "Bombsite A", + "bombsite_b": "Bombsite B", + "teammate_skills": "Your teammates' skills", "summary_start": "======SUMMARY=OF=THE=LAST=ROUND======", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - Scroll | E - Select
" } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/lang/pl.json b/jRandomSkills - SRC Files/src/lang/pl.json index 62ec12e..cbe52c8 100644 --- a/jRandomSkills - SRC Files/src/lang/pl.json +++ b/jRandomSkills - SRC Files/src/lang/pl.json @@ -18,7 +18,7 @@ "areareaper_desc": "Możesz wybrać strefę detonacji, którą chcesz dezaktywować", "areareaper_incorrect_site": "Nie znaleziono takiej strefy detonacji.", "areareaper_no_site": "Nie znaleziono żadnej strefy detonacji.", - "areareaper_select_info": "Wybierz strefę detonacji, którą chcesz dezaktywować:", + "areareaper_select_info": "Wybierz strefę do dezaktyw.:", "areareaper_site_disabled": "Strefa detonacji {0} została dezaktywowana - nie można na niej podłożyć bomby!", "areareaper_used_info": "Twoja moc została już wykorzystana.", @@ -66,19 +66,19 @@ "darkness_desc": "Nadaje efekt ciemności wybranemu przeciwnikowi", "darkness_enemy_info": "Niech zgasną światła.", "darkness_player_info": "Ciemność opanowała gracza '{0}'.", - "darkness_select_info": "Wybierz gracza, któremu chcesz nadać efekt ciemności:", + "darkness_select_info": "Nałóż efekt ciemności:", "deactivator": "Deaktywator", "deactivator_desc": "Wybierasz gracza, którego supermoc chcesz wyłączyć", "deactivator_enemy_info": "Twoja supermoc została wyłączona.", "deactivator_player_info": "Moc gracza '{0}' została wyłączona.", - "deactivator_select_info": "Wybierz gracza, którego supermoc chcesz wyłączyć:", + "deactivator_select_info": "Wyłącz moc gracza:", "deaf": "Głuchy", "deaf_desc": "Wybierasz gracza, dla którego chcesz wyłączyć wszystkie dźwięki", "deaf_enemy_info": "Słuchawki opuściły grę.", "deaf_player_info": "Dźwięk został wyłączony dla gracza '{0}'.", - "deaf_select_info": "Wybierz gracza, dla którego chcesz wyłączyć wszystkie dźwięki:", + "deaf_select_info": "Wycisz dźwięki gracza:", "disarmament": "Rozbrojenie", "disarmament_desc": "Masz losową szanse na wyrzucenie broni wroga po trafieniu", @@ -93,7 +93,7 @@ "duplicator": "Duplikator", "duplicator_desc": "Wybierasz gracza, od którego chcesz skopiować supermoc", "duplicator_player_info": "Moc gracza '{0}' została skopiowana.", - "duplicator_select_info": "Wybierz gracza, od którego chcesz skopiować supermoc:", + "duplicator_select_info": "Skopiuj moc gracza:", "dwarf": "Mini Majk", "dwarf_desc": "Losowa wielkość postaci na początku rundy", @@ -129,6 +129,11 @@ "frozendecoy": "Zamrażający Wabik", "frozendecoy_desc": "Twój decoy zamraża wszystkich graczy w pobliżu", + "gambler": "Hazardzista", + "gambler_desc": "Wybierz umiejętność z podanej listy.", + "gambler_select_info": "Wybierz umiejętność:", + "gambler_more": "Odśwież za $100", + "ghost": "Duszek", "ghost_desc": "Jesteś całkowicie niewidzialny", @@ -139,7 +144,7 @@ "glitch_desc": "Wyłączasz radar wybranemu przeciwnikowi", "glitch_enemy_info": "Twój radar został wyłączony.", "glitch_player_info": "Radar gracza '{0}' został wyłączony.", - "glitch_select_info": "Wybierz gracza, dla którego chcesz wyłączyć radar:", + "glitch_select_info": "Wyłącz radar dla gracza:", "glue": "Klej", "glue_desc": "Twoje granaty przyklejają się do ścian", @@ -171,13 +176,19 @@ "jammer_desc": "Wybierasz gracza, dla którego chcesz wyłączyć celownik", "jammer_enemy_info": "Twój celownik został wyłączony.", "jammer_player_info": "Celownik gracza '{0}' została wyłączona.", - "jammer_select_info": "Wybierz gracza, dla którego chcesz wyłączyć celownik:", + "jammer_select_info": "Wyłącz celownik dla gracza:", + + "jester": "Błazen", + "jester_desc": "W trybie błazna nie możesz zadawać ani otrzymywać obrażeń. Tryb zmienia się co kilka sekund.", + "jester_mode": "Tryb Błazna", + "jester_on": "WŁ.", + "jester_off": "WYŁ.", "jumpban": "Beznogi", "jumpban_desc": "Wybierasz gracza, który nie będzie mógł skakać", "jumpban_enemy_info": "Ktoś odciął ci nogi.", "jumpban_player_info": "Gracz '{0}' nie może teraz skakać.", - "jumpban_select_info": "Wybierz gracza, który nie będzie mógł skakać:", + "jumpban_select_info": "Zablokuj skok dla gracza:", "jumpingjack": "Pajacyk", "jumpingjack_desc": "Skakanie przywraca zdrowie", @@ -189,7 +200,7 @@ "lifeswap_desc": "Wybierasz gracza, z którym chcesz wymienić się zdrowiem", "lifeswap_enemy_info": "Ktoś pożyczył sobie twoje zdrowie.", "lifeswap_player_info": "Wymieniłeś się zdrowiem z graczem '{0}'.", - "lifeswap_select_info": "Wybierz gracza, z którym chcesz wymienić się zdrowiem:", + "lifeswap_select_info": "Zamień się zdrowiem z graczem:", "longknife": "Długi Nóż", "longknife_desc": "Podstawowy atak nożem zadaje obrażenia niezależnie od odległości", @@ -201,7 +212,7 @@ "magnifier_desc": "Przybiżasz ekran wybranemu przeciwnikowi", "magnifier_enemy_info": "Twoje pole widzenia zostało zniekształcone!", "magnifier_player_info": "Gracz '{0}' został zmuszony do przejścia w tryb powiększenia.", - "magnifier_select_info": "Wybierz gracza, którego ekran chcesz powiększyć:", + "magnifier_select_info": "Powiększ ekran gracza:", "medic": "Medyk", "medic_desc": "Kliknij [css_useSkill], aby użyć ładunku leczniczego, który przywraca 50 punktów zdrowia", @@ -210,7 +221,7 @@ "moneyswap_desc": "Wybierasz gracza, z którym chcesz zamienić się pieniędzmi", "moneyswap_enemy_info": "Urząd skarbowy cię dopadł.", "moneyswap_player_info": "Wymieniłeś swoje pieniądze z graczem '{0}'.", - "moneyswap_select_info": "Wybierz gracza, z którym chcesz zamienić się pieniędzmi:", + "moneyswap_select_info": "Zamień się kasą z graczem:", "muhammed": "Muhammed", "muhammed_desc": "Po śmierci eksplodujesz i zabijasz graczy znajdujących się w zasięgu", @@ -257,13 +268,13 @@ "poison_desc": "Wybierasz gracza, który co kilka sekund będzie otrzymywał obrażenia", "poison_enemy_info": "Zostałeś otruty.", "poison_player_info": "Gracz '{0}' został otruty.", - "poison_select_info": "Wybierz gracza, który co kilka sekund będzie otrzymywał obrażenia:", + "poison_select_info": "Zatruj gracza:", "primaryban": "Brak Karabinów", "primaryban_desc": "Wybierasz gracza, który nie może używać karabinów", "primaryban_enemy_info": "Nie możesz już używać karabinów.", "primaryban_player_info": "Gracz '{0}' nie może już używać karabinów.", - "primaryban_select_info": "Wybierz gracza, któremu chcesz zabronić używania karabinów:", + "primaryban_select_info": "Zablokuj karabiny dla gracza:", "prosthesis": "Proteza", "prosthesis_desc": "Ramiona i nogi są kuloodporne", @@ -353,7 +364,7 @@ "thief_desc": "Możesz ukraść supermoc wybranemu graczowi", "thief_enemy_info": "Twoja supermoc została skradziona.", "thief_player_info": "Moc gracza '{0}' została skradziona.", - "thief_select_info": "Wybierz gracza, którego supermoc chcesz ukraść:", + "thief_select_info": "Ukradnij moc gracza:", "thirdeye": "Trzecie Oko", "thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę", @@ -394,7 +405,7 @@ "no_player": "Nie znaleziono pasującego gracza.", "duplicate_player": "Znaleziono więcej niż jednego gracza o tej samej nazwie.", "selectplayerskill_command": "Wpisz /t", - "selectplayerskill_incorrect_enemy_index": "Nie znaleziono gracza o takim index'ie.", + "selectplayerskill_incorrect_enemy_index": "Nie znaleziono graczy do wyboru.", "skill_not_found_setskill": "Nie znaleziono takiej CHATCOLORS.REDsupermocy", "player_not_found_setskill": "Nie znaleziono takiego CHATCOLORS.REDgracza", @@ -420,7 +431,12 @@ "vote_alredy_voted": "Już zagłosowałeś!", "vote_vote": "Głosowanie", + "bombsite_a": "Strefa detonacji A", + "bombsite_b": "Strefa detonacji B", + "teammate_skills": "Supermoce twoich sojuszników", "summary_start": "======PODSUMOWANIE=Z=OSTATNIEJ=RUNDY======", - "summary_end": "============================================" + "summary_end": "============================================", + + "menu_controlls": "W/S – Przewijanie | E - Wybierz
" } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/lang/pt-br.json b/jRandomSkills - SRC Files/src/lang/pt-br.json index 4800a5f..cfe3369 100644 --- a/jRandomSkills - SRC Files/src/lang/pt-br.json +++ b/jRandomSkills - SRC Files/src/lang/pt-br.json @@ -18,7 +18,7 @@ "areareaper_desc": "Você pode escolher um local de bomba para desativar", "areareaper_incorrect_site": "Nenhum local de bomba encontrado.", "areareaper_no_site": "Nenhum local de bomba encontrado.", - "areareaper_select_info": "Escolha o local de bomba que deseja desativar:", + "areareaper_select_info": "Escolha área p/ desativar:", "areareaper_site_disabled": "Local de bomba {0} foi desativado - nenhuma bomba pode ser plantada lá!", "areareaper_used_info": "Seu poder já foi usado.", @@ -66,19 +66,19 @@ "darkness_desc": "Aplica um efeito de escuridão a um inimigo escolhido", "darkness_enemy_info": "Que as luzes se apaguem.", "darkness_player_info": "A escuridão tomou conta do jogador '{0}'.", - "darkness_select_info": "Escolha o jogador ao qual deseja aplicar o efeito de escuridão:", + "darkness_select_info": "Escolha jogador: escuridão:", "deactivator": "Desativador", "deactivator_desc": "Escolha um jogador cuja habilidade você deseja desativar", "deactivator_enemy_info": "Sua habilidade foi desativada.", "deactivator_player_info": "A habilidade do jogador '{0}' foi desativada.", - "deactivator_select_info": "Escolha o jogador cuja habilidade você deseja desativar:", + "deactivator_select_info": "Desativar skill do jogador:", "deaf": "Surdo", "deaf_desc": "Escolha um jogador para silenciar todos os sons", "deaf_enemy_info": "Seus fones de ouvido saíram do jogo.", "deaf_player_info": "O som foi desativado para o jogador '{0}'.", - "deaf_select_info": "Escolha o jogador para quem deseja silenciar todos os sons:", + "deaf_select_info": "Silenciar jogador:", "disarmament": "Desarmamento", "disarmament_desc": "Você tem uma chance aleatória de fazer um inimigo largar sua arma ao acertá-lo", @@ -93,7 +93,7 @@ "duplicator": "Duplicador", "duplicator_desc": "Escolha um jogador para copiar sua habilidade", "duplicator_player_info": "A habilidade do jogador '{0}' foi copiada.", - "duplicator_select_info": "Escolha o jogador cuja habilidade você deseja copiar:", + "duplicator_select_info": "Copiar skill do jogador:", "dwarf": "Anão", "dwarf_desc": "Tamanho de personagem aleatório no início da rodada", @@ -129,6 +129,11 @@ "frozendecoy": "Chamariz Congelante", "frozendecoy_desc": "Seu chamariz congela todos os jogadores próximos", + "gambler": "Apostador", + "gambler_desc": "Selecione uma habilidade da lista.", + "gambler_select_info": "Escolha sua habilidade:", + "gambler_more": "Atualizar por $100", + "ghost": "Fantasma", "ghost_desc": "Você é completamente invisível", @@ -139,7 +144,7 @@ "glitch_desc": "Desativa o radar de um inimigo escolhido", "glitch_enemy_info": "Seu radar foi desativado.", "glitch_player_info": "O radar do jogador '{0}' foi desativado.", - "glitch_select_info": "Escolha o jogador cujo radar você deseja desativar:", + "glitch_select_info": "Desativar radar do jogador:", "glue": "Cola", "glue_desc": "Suas granadas grudam nas paredes", @@ -171,13 +176,19 @@ "jammer_desc": "Escolha um jogador para desativar sua mira", "jammer_enemy_info": "Sua mira foi desativada.", "jammer_player_info": "A mira do jogador '{0}' foi desativada.", - "jammer_select_info": "Escolha o jogador cuja mira você deseja desativar:", + "jammer_select_info": "Desativar mira do jogador:", + + "jester": "Bobo", + "jester_desc": "No modo bobo você não pode causar nem receber dano. Esse modo muda a cada poucos segundos.", + "jester_mode": "Modo Bobo", + "jester_on": "LIG.", + "jester_off": "DESL.", "jumpban": "Sem Pernas", "jumpban_desc": "Escolha um jogador que não poderá pular", "jumpban_enemy_info": "Alguém cortou suas pernas.", "jumpban_player_info": "O jogador '{0}' não pode mais pular.", - "jumpban_select_info": "Escolha o jogador que não poderá pular:", + "jumpban_select_info": "Banir pulo do jogador:", "jumpingjack": "Pula-Pula", "jumpingjack_desc": "Pular restaura saúde", @@ -189,7 +200,7 @@ "lifeswap_desc": "Escolha um jogador para trocar saúde com ele", "lifeswap_enemy_info": "Alguém pegou sua saúde emprestada.", "lifeswap_player_info": "Você trocou saúde com o jogador '{0}'.", - "lifeswap_select_info": "Escolha o jogador com quem deseja trocar saúde:", + "lifeswap_select_info": "Trocar vida com jogador:", "longknife": "Faca Longa", "longknife_desc": "Um ataque com faca primária causa dano independentemente da distância", @@ -201,7 +212,7 @@ "magnifier_desc": "Força a tela do inimigo a ampliar, reduzindo seu campo de visão", "magnifier_enemy_info": "Seu campo de visão foi distorcido!", "magnifier_player_info": "O jogador ‘{0}’ foi forçado a entrar no modo de zoom.", - "magnifier_select_info": "Selecione o jogador cuja tela você deseja ampliar:", + "magnifier_select_info": "Ampliar tela do jogador:", "medic": "Médico", "medic_desc": "Clique em [css_useSkill] para usar uma carga de cura que restaura 50 de saúde", @@ -210,7 +221,7 @@ "moneyswap_desc": "Escolha um jogador para trocar dinheiro com ele", "moneyswap_enemy_info": "A receita federal te pegou.", "moneyswap_player_info": "Você trocou dinheiro com o jogador '{0}'.", - "moneyswap_select_info": "Escolha o jogador com quem deseja trocar dinheiro:", + "moneyswap_select_info": "Trocar dinheiro c/ jogador:", "muhammed": "Muhammed", "muhammed_desc": "Você explode ao morrer, matando jogadores próximos", @@ -257,13 +268,13 @@ "poison_desc": "Escolha um jogador que receberá dano a cada poucos segundos", "poison_enemy_info": "Você foi envenenado.", "poison_player_info": "O jogador '{0}' foi envenenado.", - "poison_select_info": "Escolha o jogador que receberá dano a cada poucos segundos:", + "poison_select_info": "Envenenar jogador:", "primaryban": "Sem Rifles", "primaryban_desc": "Escolha um jogador que não poderá usar rifles", "primaryban_enemy_info": "Você não pode mais usar rifles.", "primaryban_player_info": "O jogador '{0}' não pode mais usar rifles.", - "primaryban_select_info": "Escolha o jogador para proibir de usar rifles:", + "primaryban_select_info": "Banir rifles do jogador:", "prosthesis": "Prótese", "prosthesis_desc": "Braços e pernas são à prova de balas", @@ -353,7 +364,7 @@ "thief_desc": "Você pode roubar uma habilidade de um jogador escolhido", "thief_enemy_info": "Sua habilidade foi roubada.", "thief_player_info": "A habilidade do jogador '{0}' foi roubada.", - "thief_select_info": "Escolha o jogador cuja habilidade você deseja roubar:", + "thief_select_info": "Roubar skill do jogador:", "thirdeye": "Terceiro Olho", "thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa", @@ -394,7 +405,7 @@ "no_player": "Nenhum jogador correspondente encontrado.", "duplicate_player": "Mais de um jogador encontrado com o mesmo nome.", "selectplayerskill_command": "Digite /t", - "selectplayerskill_incorrect_enemy_index": "Nenhum jogador encontrado com esse índice.", + "selectplayerskill_incorrect_enemy_index": "Não foram encontrados jogadores para selecionar.", "skill_not_found_setskill": "Nenhuma habilidade CHATCOLORS.RED encontrada", "player_not_found_setskill": "Nenhum jogador CHATCOLORS.RED encontrado", @@ -420,7 +431,12 @@ "vote_alredy_voted": "Você já votou!", "vote_vote": "Votar", + "bombsite_a": "Zona de detonação A", + "bombsite_b": "Zona de detonação B", + "teammate_skills": "Habilidades dos seus companheiros de equipe", "summary_start": "=======RESUMO=DA=ÚLTIMA=RODADA=======", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - Rolar | E - Selecionar
" } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/lang/zh.json b/jRandomSkills - SRC Files/src/lang/zh.json index 84855f6..a4aed64 100644 --- a/jRandomSkills - SRC Files/src/lang/zh.json +++ b/jRandomSkills - SRC Files/src/lang/zh.json @@ -129,6 +129,11 @@ "frozendecoy": "冰冻诱饵", "frozendecoy_desc": "你的诱饵弹会冻结附近的所有玩家", + "gambler": "赌徒", + "gambler_desc": "从提供的列表中选择一个技能。", + "gambler_select_info": "选择你的技能:", + "gambler_more": "刷新 $100", + "ghost": "幽灵", "ghost_desc": "你完全隐形", @@ -173,6 +178,12 @@ "jammer_player_info": "玩家 '{0}' 的准星已被禁用。", "jammer_select_info": "选择你想禁用其准星的玩家:", + "jester": "小丑", + "jester_desc": "在小丑模式下,你不能造成或受到任何伤害。此模式每隔几秒会变化。", + "jester_mode": "小丑模式", + "jester_on": "开", + "jester_off": "关", + "jumpban": "无腿", "jumpban_desc": "选择一个玩家使其无法跳跃", "jumpban_enemy_info": "有人切断了你的腿。", @@ -394,7 +405,7 @@ "no_player": "未找到匹配的玩家。", "duplicate_player": "找到多个同名玩家。", "selectplayerskill_command": "输入 /t", - "selectplayerskill_incorrect_enemy_index": "未找到该索引的玩家。", + "selectplayerskill_incorrect_enemy_index": "未找到可供选择的玩家。", "skill_not_found_setskill": "未找到 CHATCOLORS.RED 技能", "player_not_found_setskill": "未找到 CHATCOLORS.RED 玩家", @@ -420,7 +431,12 @@ "vote_alredy_voted": "您已投票!", "vote_vote": "投票", + "bombsite_a": "爆轰区A", + "bombsite_b": "爆轰区B", + "teammate_skills": "你队友的技能", "summary_start": "=============上一回合总结==============", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - 滚动 | E - 选择
" } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/ISkill.cs b/jRandomSkills - SRC Files/src/player/ISkill.cs index ee6c6e3..c699e10 100644 --- a/jRandomSkills - SRC Files/src/player/ISkill.cs +++ b/jRandomSkills - SRC Files/src/player/ISkill.cs @@ -1,14 +1,47 @@ using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; +using CounterStrikeSharp.API.Modules.UserMessages; namespace jRandomSkills.src.player; public interface ISkill { public static void LoadSkill() { } - public static void EnableSkill(CCSPlayerController player) { } - public static void DisableSkill(CCSPlayerController player) { } - public static void UseSkill(CCSPlayerController player) { } - public static void TypeSkill(CCSPlayerController player, string[] commands) { } + public static void EnableSkill(CCSPlayerController _) { } + public static void DisableSkill(CCSPlayerController _) { } + public static void UseSkill(CCSPlayerController _) { } + public static void TypeSkill(CCSPlayerController _, string[] __) { } + + public static void OnTakeDamage(DynamicHook _) { } + public static void OnEntitySpawned(CEntityInstance _) { } + public static void OnTick() { } + public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList _) { } + + public static void NewRound() { } + public static void PlayerMakeSound(UserMessage _) { } + public static void PlayerBlind(EventPlayerBlind _) { } + public static void PlayerHurt(EventPlayerHurt _) { } + public static void PlayerDeath(EventPlayerDeath _) { } + public static void PlayerJump(EventPlayerJump _) { } + + public static void WeaponFire(EventWeaponFire _) { } + public static void WeaponEquip(EventItemEquip _) { } + public static void WeaponPickup(EventItemPickup _) { } + public static void WeaponReload(EventWeaponReload _) { } + public static void GrenadeThrown(EventGrenadeThrown _) { } + + public static void BombBeginplant(EventBombBeginplant _) { } + public static void BombPlanted(EventBombPlanted _) { } + public static void BombBegindefuse(EventBombBegindefuse _) { } + + public static void DecoyStarted(EventDecoyStarted _) { } + public static void DecoyDetonate(EventDecoyDetonate _) { } + + public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate _) { } + public static void SmokegrenadeExpired(EventSmokegrenadeExpired _) { } + + public class SkillConfig { } } public enum Skills @@ -48,6 +81,7 @@ public enum Skills FragileBomb, FriendlyFire, FrozenDecoy, + Gambler, Ghost, Glaz, Glitch, @@ -60,6 +94,7 @@ public enum Skills InfiniteAmmo, Jackal, Jammer, + Jester, JumpBan, JumpingJack, KillerFlash, diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index 425529c..2b4352f 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -1,297 +1,513 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; +using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; using System.Text.RegularExpressions; -using static jRandomSkills.Config; +using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills { public static partial class Event { - private static readonly jSkill_SkillInfo noneSkill = new(Skills.None, Config.GetValue(Skills.None, "color"), false); + public static bool enableTransmit = false; + public static readonly jSkill_SkillInfo noneSkill = new(Skills.None, Config.GetValue(Skills.None, "color"), false); private static jSkill_SkillInfo ctSkill = noneSkill; private static jSkill_SkillInfo tSkill = noneSkill; private static jSkill_SkillInfo allSkill = noneSkill; private static List debugSkills = new(SkillData.Skills); + public static readonly Config.DefaultSkillInfo[] terroristSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == (int)CsTeam.Terrorist).ToArray(); + public static readonly Config.DefaultSkillInfo[] counterterroristSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == (int)CsTeam.CounterTerrorist).ToArray(); + private static readonly Config.DefaultSkillInfo[] allTeamsSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == 0).ToArray(); + private static readonly Dictionary> playersSkills = []; public static readonly Dictionary staticSkills = []; public static void Load() { - Instance.RegisterEventHandler((@event, info) => + Instance.RegisterEventHandler(PlayerConnectFull); + Instance.RegisterEventHandler(PlayerDisconnect); + Instance.RegisterEventHandler(RoundStart); + Instance.RegisterEventHandler(RoundEnd); + + Instance.RegisterEventHandler(PlayerDeath); + Instance.RegisterEventHandler(PlayerBlind); + Instance.RegisterEventHandler(PlayerHurt); + Instance.RegisterEventHandler(PlayerJump); + + Instance.RegisterEventHandler(WeaponFire); + Instance.RegisterEventHandler(WeaponEquip); + Instance.RegisterEventHandler(WeaponPickup); + Instance.RegisterEventHandler(WeaponReload); + Instance.RegisterEventHandler(GrenadeThrown); + + Instance.RegisterEventHandler(BombBeginplant); + Instance.RegisterEventHandler(BombPlanted); + Instance.RegisterEventHandler(BombBegindefuse); + + Instance.RegisterEventHandler(DecoyStarted); + Instance.RegisterEventHandler(DecoyDetonate); + + Instance.RegisterEventHandler(SmokegrenadeDetonate); + Instance.RegisterEventHandler(SmokegrenadeExpired); + + Instance.RegisterListener(CheckUseSkill); + Instance.RegisterListener(EntitySpawned); + Instance.RegisterListener(OnTick); + + Instance.HookUserMessage(208, PlayerMakeSound); + VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); + } + + private static HookResult PlayerMakeSound(UserMessage um) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerMakeSound", [um]); + return HookResult.Continue; + } + + private static HookResult WeaponFire(EventWeaponFire @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponFire", [@event]); + return HookResult.Continue; + } + + private static HookResult WeaponEquip(EventItemEquip @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponEquip", [@event]); + return HookResult.Continue; + } + + private static HookResult WeaponPickup(EventItemPickup @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponPickup", [@event]); + return HookResult.Continue; + } + + private static HookResult WeaponReload(EventWeaponReload @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponReload", [@event]); + return HookResult.Continue; + } + + private static HookResult GrenadeThrown(EventGrenadeThrown @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "GrenadeThrown", [@event]); + return HookResult.Continue; + } + + private static HookResult BombBeginplant(EventBombBeginplant @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "BombBeginplant", [@event]); + return HookResult.Continue; + } + + private static HookResult BombPlanted(EventBombPlanted @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "BombPlanted", [@event]); + return HookResult.Continue; + } + + private static HookResult BombBegindefuse(EventBombBegindefuse @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "BombBegindefuse", [@event]); + return HookResult.Continue; + } + + private static HookResult DecoyStarted(EventDecoyStarted @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyStarted", [@event]); + return HookResult.Continue; + } + + private static HookResult DecoyDetonate(EventDecoyDetonate @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyDetonate", [@event]); + return HookResult.Continue; + } + + private static HookResult SmokegrenadeDetonate(EventSmokegrenadeDetonate @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeDetonate", [@event]); + return HookResult.Continue; + } + + private static HookResult SmokegrenadeExpired(EventSmokegrenadeExpired @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeExpired", [@event]); + return HookResult.Continue; + } + + private static HookResult PlayerHurt(EventPlayerHurt @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerHurt", [@event]); + return HookResult.Continue; + } + + private static HookResult PlayerJump(EventPlayerJump @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerJump", [@event]); + return HookResult.Continue; + } + + private static HookResult PlayerBlind(EventPlayerBlind @event, GameEventInfo info) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerBlind", [@event]); + return HookResult.Continue; + } + + private static HookResult OnTakeDamage(DynamicHook h) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "OnTakeDamage", [h]); + return HookResult.Continue; + } + + private static void OnTick() + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "OnTick"); + } + + private static HookResult PlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return HookResult.Continue; + + Instance.SkillPlayer.Add(new jSkill_PlayerInfo { - var player = @event.Userid; - - if (player == null || !player.IsValid) return HookResult.Continue; - - Instance.SkillPlayer.Add(new jSkill_PlayerInfo - { - SteamID = player.SteamID, - PlayerName = player.PlayerName, - Skill = Skills.None, - SpecialSkill = Skills.None, - IsDrawing = false, - SkillChance = 1, - }); - - const string defaultWelcomeMsg = "Welcome {PLAYER}, to the {SERVER_NAME} server!\n" - + "The current version of the jRandomSkills: {VERSION} ({SKILLS_COUNT} skills).\n\n" - + "Original plugin created by:\n{AUTHOR1}\n" - + "Modified and improved by:\n{AUTHOR2}"; - string langWelcomeMsg = Localization.GetTranslation("welcome_message", "welcome"); - string welcomeMsg = MyRegex().IsMatch(langWelcomeMsg) && MyRegex1().IsMatch(langWelcomeMsg) ? langWelcomeMsg : defaultWelcomeMsg; - - foreach (string line in welcomeMsg.Split("\n")) - player.PrintToChat($" {ChatColors.Green}" + line.Replace("{PLAYER}", $" {ChatColors.Red}{player.PlayerName}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) - .Replace("{SERVER_NAME}", $" {ChatColors.Red}{ConVar.Find("hostname")?.StringValue ?? "Default Server"}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) - .Replace("{VERSION}", $" {ChatColors.Red}v{Instance.ModuleVersion}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) - .Replace("{SKILLS_COUNT}", $" {ChatColors.Red}{SkillData.Skills.Count - 1}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) - .Replace("{AUTHOR1}", $" {ChatColors.Red}Jakub Bartosik (D3X){ChatColors.Green} ({ChatColors.Red}https://github.com/jakubbartosik/dRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase) - .Replace("{AUTHOR2}", $" {ChatColors.Red}Juzlus{ChatColors.Green} ({ChatColors.Red}https://github.com/Juzlus/jRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase)); - - return HookResult.Continue; + SteamID = player.SteamID, + PlayerName = player.PlayerName, + Skill = Skills.None, + SpecialSkill = Skills.None, + IsDrawing = false, + SkillChance = 1, }); - Instance.RegisterEventHandler((@event, info) => + const string defaultWelcomeMsg = "Welcome {PLAYER}, to the {SERVER_NAME} server!\n" + + "The current version of the jRandomSkills: {VERSION} ({SKILLS_COUNT} skills).\n\n" + + "Original plugin created by:\n{AUTHOR1}\n" + + "Modified and improved by:\n{AUTHOR2}"; + string langWelcomeMsg = Localization.GetTranslation("welcome_message", "welcome"); + string welcomeMsg = MyRegex().IsMatch(langWelcomeMsg) && MyRegex1().IsMatch(langWelcomeMsg) ? langWelcomeMsg : defaultWelcomeMsg; + + foreach (string line in welcomeMsg.Split("\n")) + player.PrintToChat($" {ChatColors.Green}" + line.Replace("{PLAYER}", $" {ChatColors.Red}{player.PlayerName}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) + .Replace("{SERVER_NAME}", $" {ChatColors.Red}{ConVar.Find("hostname")?.StringValue ?? "Default Server"}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) + .Replace("{VERSION}", $" {ChatColors.Red}v{Instance.ModuleVersion}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) + .Replace("{SKILLS_COUNT}", $" {ChatColors.Red}{SkillData.Skills.Count - 1}{ChatColors.Green}", StringComparison.OrdinalIgnoreCase) + .Replace("{AUTHOR1}", $" {ChatColors.Red}Jakub Bartosik (D3X){ChatColors.Green} ({ChatColors.Red}https://github.com/jakubbartosik/dRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase) + .Replace("{AUTHOR2}", $" {ChatColors.Red}Juzlus{ChatColors.Green} ({ChatColors.Red}https://github.com/Juzlus/jRandomSkills{ChatColors.Green})", StringComparison.OrdinalIgnoreCase)); + + return HookResult.Continue; + } + + private static HookResult PlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo info) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return HookResult.Continue; + + var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (skillPlayer != null) + Instance.SkillPlayer.Remove(skillPlayer); + return HookResult.Continue; + } + + private static HookResult RoundStart(EventRoundStart @event, GameEventInfo info) + { + enableTransmit = false; + Instance.AddTimer(.1f, () => DisableAll()); + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { - var player = @event.Userid; - - if (player == null || !player.IsValid) return HookResult.Continue; - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (skillPlayer != null) - { - Instance.SkillPlayer.Remove(skillPlayer); - } + if (skillPlayer == null) continue; + skillPlayer.IsDrawing = true; + } - return HookResult.Continue; - }); + Instance.RemoveListener(CheckTransmit); + int freezetime = ConVar.Find("mp_freezetime")?.GetPrimitiveValue() ?? 0; + Instance.AddTimer(Math.Max(freezetime - Config.LoadedConfig.Settings.SkillTimeBeforeStart, 0) + .3f, SetSkill); + return HookResult.Continue; + } - Instance.RegisterEventHandler((@event, info) => + private static void DisableAll() + { + foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot)) { - foreach (var player in Utilities.GetPlayers()) - { - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (skillPlayer != null) - skillPlayer.IsDrawing = true; - } + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null) return; + Instance.SkillAction(playerInfo.Skill.ToString(), "DisableSkill", [player]); + Instance.SkillAction(playerInfo.Skill.ToString(), "NewRound"); + } + } - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => + private static HookResult RoundEnd(EventRoundEnd @event, GameEventInfo info) + { + foreach (var player in Utilities.GetPlayers()) { - foreach (var player in Utilities.GetPlayers()) + Instance.AddTimer(0.5f, () => { - Instance.AddTimer(0.5f, () => + var _players = Utilities.GetPlayers().Where(p => p.IsValid).OrderBy(p => p.Team); + + string skillsText = ""; + foreach (var _player in _players) { - var _players = Utilities.GetPlayers().Where(p => p.IsValid).OrderBy(p => p.Team); - - string skillsText = ""; - foreach (var _player in _players) + var _playerSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == _player.SteamID); + if (_playerSkill != null) { - var _playerSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == _player.SteamID); - if (_playerSkill != null) + var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == _playerSkill.Skill); + var specialSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == _playerSkill.SpecialSkill); + if (skillInfo == null) continue; + skillsText += $" {ChatColors.DarkRed}{_player.PlayerName}{ChatColors.Lime}: {(_playerSkill.SpecialSkill == Skills.None || specialSkillInfo == null ? skillInfo.Name : $"{specialSkillInfo.Name} -> {skillInfo.Name}")}\n"; + } + } + + if (Config.LoadedConfig.Settings.SummaryAfterTheRound && !string.IsNullOrEmpty(skillsText)) + { + player.PrintToChat(" "); + player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_start")}"); + foreach (string text in skillsText.Split("\n")) + if (!string.IsNullOrEmpty(text)) + player.PrintToChat(text); + player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_end")}"); + player.PrintToChat(" \n"); + } + }); + } + return HookResult.Continue; + } + + private static HookResult PlayerDeath(EventPlayerDeath @event, GameEventInfo info) + { + var victim = @event.Userid; + var attacker = @event.Attacker; + if (victim == null || attacker == null) return HookResult.Continue; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim.SteamID); + if (playerInfo == null || playerInfo.IsDrawing) return HookResult.Continue; + Instance.SkillAction(playerInfo.Skill.ToString(), "PlayerDeath", [@event]); + Instance.SkillAction(playerInfo.Skill.ToString(), "DisableSkill", [victim]); + + if (victim == attacker) return HookResult.Continue; + if (Config.LoadedConfig.Settings.KillerSkillInfo) + { + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + if (attackerInfo != null) + { + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.Skill); + var specialSkillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.SpecialSkill); + if (skillData == null || specialSkillData == null) return HookResult.Continue; + string skillDesc = skillData.Description; + + SkillUtils.PrintToChat(victim, $"{Localization.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}:", false); + SkillUtils.PrintToChat(victim, $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? skillData.Name : $"{specialSkillData.Name} -> {skillData.Name}")}{ChatColors.Lime} - {skillDesc}", false); + } + } + return HookResult.Continue; + } + + private static void CheckUseSkill(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released) + { + string? button = Config.LoadedConfig.Settings.AlternativeSkillButton; + if (string.IsNullOrEmpty(button)) return; + + if (Enum.TryParse(button, out var skillButton)) + { + if (pressed != skillButton) return; + } else return; + + if (player == null) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null || playerInfo.IsDrawing) return; + + var playerPawn = player.PlayerPawn.Value; + if (playerPawn?.CBodyComponent == null) return; + if (!player.IsValid || !player.PawnIsAlive) return; + + Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill} by PlayerButtons: {pressed}"); + Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]); + } + + private static void EntitySpawned(CEntityInstance entity) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "OnEntitySpawned", [entity]); + } + + private static void SetSkill() + { + var validPlayers = Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p .Team is CsTeam.CounterTerrorist or CsTeam.Terrorist).ToList(); + + if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.TeamSkills) + { + List tSkills = new(SkillData.Skills); + tSkills.RemoveAll(s => s.Skill == tSkill.Skill || s.Skill == Skills.None || counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + tSkill = tSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : tSkills[Instance.Random.Next(tSkills.Count)]; + + List ctSkills = new(SkillData.Skills); + ctSkills.RemoveAll(s => s.Skill == ctSkill.Skill || s.Skill == Skills.None || terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + ctSkill = ctSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : ctSkills[Instance.Random.Next(ctSkills.Count)]; + } + else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.SameSkills) + { + List allSkills = new(SkillData.Skills); + allSkills.RemoveAll(s => s.Skill == allSkill.Skill || s.Skill == Skills.None || !allTeamsSkills.Any(s2 => s2.Name == s.Skill.ToString())); + allSkill = allSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : allSkills[Instance.Random.Next(allSkills.Count)]; + } + else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.Debug && debugSkills.Count == 0) + debugSkills = new(SkillData.Skills); + + foreach (var player in validPlayers) + { + if (player == null) continue; + var teammates = validPlayers.Where(p => p.Team == player.Team && p != player); + string teammateSkills = ""; + + var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (skillPlayer == null) continue; + + if (player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) + { + skillPlayer.Skill = Skills.None; + continue; + } + + skillPlayer.IsDrawing = false; + jSkill_SkillInfo randomSkill = new(Skills.None, Config.GetValue(Skills.None, "color"), false); + + if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false) + { + Config.GameModes gameMode = (Config.GameModes)Config.LoadedConfig.Settings.GameMode; + if (staticSkills.TryGetValue(player.SteamID, out var staticSkill)) + randomSkill = staticSkill; + else if (gameMode == Config.GameModes.Normal || gameMode == Config.GameModes.NoRepeat) + { + List skillList = new(SkillData.Skills); + skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill || s?.Skill == Skills.None); + + if (validPlayers.Count(p => p.Team == player.Team) == 1) + { + Config.DefaultSkillInfo[] skillsNeedsTeammates = Config.LoadedConfig.SkillsInfo.Where(s => s.NeedsTeammates).ToArray(); + skillList.RemoveAll(s => skillsNeedsTeammates.Any(s2 => s2.Name == s.Skill.ToString())); + } + + if (player.Team == CsTeam.Terrorist) + skillList.RemoveAll(s => counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + else + skillList.RemoveAll(s => terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + + if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.SteamID, out List? skills)) + { + skillList.RemoveAll(s => skills.Any(s2 => s2.Skill == s.Skill)); + if (skillList.Count == 0) skills.Clear(); + } + + randomSkill = skillList.Count == 0 ? noneSkill : skillList[Instance.Random.Next(skillList.Count)]; + if (gameMode == Config.GameModes.NoRepeat) + { + if (playersSkills.TryGetValue(player.SteamID, out List? value)) + value.Add(randomSkill); + else + playersSkills.Add(player.SteamID, [randomSkill]); + } + } + else if (gameMode == Config.GameModes.TeamSkills) + randomSkill = player.Team == CsTeam.Terrorist ? tSkill : ctSkill; + else if (gameMode == Config.GameModes.SameSkills) + randomSkill = allSkill; + else if (gameMode == Config.GameModes.Debug) + { + if (debugSkills.Count == 0) + debugSkills = new List(SkillData.Skills); + randomSkill = debugSkills[0]; + debugSkills.RemoveAt(0); + player.PrintToChat($"{SkillData.Skills.Count - debugSkills.Count}/{SkillData.Skills.Count}"); + } + } + + if (randomSkill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{randomSkill.Name}{ChatColors.Lime}: {randomSkill.Description}", false); + + skillPlayer.Skill = randomSkill.Skill; + skillPlayer.SpecialSkill = Skills.None; + Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", new [] { player }); + Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{randomSkill.Name}\"."); + + if (Config.LoadedConfig.Settings.TeamMateSkillInfo) + { + Instance?.AddTimer(0.5f, () => + { + foreach (var teammate in teammates) + { + var teammateSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID)?.Skill; + if (teammateSkill != null) { - var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == _playerSkill.Skill); - var specialSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == _playerSkill.SpecialSkill); - if (skillInfo == null) continue; - skillsText += $" {ChatColors.DarkRed}{_player.PlayerName}{ChatColors.Lime}: {(_playerSkill.SpecialSkill == Skills.None || specialSkillInfo == null ? skillInfo.Name : $"{specialSkillInfo.Name} -> {skillInfo.Name}")}\n"; + var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == teammateSkill); + teammateSkills += $" {ChatColors.DarkRed}{teammate.PlayerName}{ChatColors.Lime}: {(skillInfo == null ? Skills.None : skillInfo.Name)}\n"; } } - if (Config.LoadedConfig.Settings.SummaryAfterTheRound && !string.IsNullOrEmpty(skillsText)) + if (!string.IsNullOrEmpty(teammateSkills)) { - player.PrintToChat(" "); - player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_start")}"); - foreach (string text in skillsText.Split("\n")) + SkillUtils.PrintToChat(player, $" {ChatColors.Lime}{Localization.GetTranslation("teammate_skills")}:", false); + foreach (string text in teammateSkills.Split("\n")) if (!string.IsNullOrEmpty(text)) player.PrintToChat(text); - player.PrintToChat($" {ChatColors.Lime}{Localization.GetTranslation("summary_end")}"); - player.PrintToChat(" \n"); } }); } + } + if (enableTransmit) + Instance?.RegisterListener(CheckTransmit); + } - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - Config.DefaultSkillInfo[] terroristSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == (int)CsTeam.Terrorist).ToArray(); - Config.DefaultSkillInfo[] counterterroristSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == (int)CsTeam.CounterTerrorist).ToArray(); - Config.DefaultSkillInfo[] allTeamsSkills = Config.LoadedConfig.SkillsInfo.Where(s => s.OnlyTeam == 0).ToArray(); - - if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.TeamSkills) - { - List tSkills = new(SkillData.Skills); - tSkills.RemoveAll(s => s.Skill == tSkill.Skill || s.Skill == Skills.None || counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - tSkill = tSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : tSkills[Instance.Random.Next(tSkills.Count)]; - - List ctSkills = new(SkillData.Skills); - ctSkills.RemoveAll(s => s.Skill == ctSkill.Skill || s.Skill == Skills.None || terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - ctSkill = ctSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : ctSkills[Instance.Random.Next(ctSkills.Count)]; - } - else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.SameSkills) - { - List allSkills = new(SkillData.Skills); - allSkills.RemoveAll(s => s.Skill == allSkill.Skill || s.Skill == Skills.None || !allTeamsSkills.Any(s2 => s2.Name == s.Skill.ToString())); - allSkill = allSkills.Count == 0 ? new(Skills.None, Config.GetValue(Skills.None, "color"), false) : allSkills[Instance.Random.Next(allSkills.Count)]; - } - else if (Config.LoadedConfig.Settings.GameMode == (int)Config.GameModes.Debug && debugSkills.Count == 0) - debugSkills = new(SkillData.Skills); - - foreach (var player in Utilities.GetPlayers()) - { - var playerTeam = player.Team; - var teammates = Utilities.GetPlayers().Where(p => p.Team == playerTeam && p != player); - string teammateSkills = ""; - - var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (skillPlayer != null) - { - skillPlayer.IsDrawing = false; - jSkill_SkillInfo randomSkill = new(Skills.None, Config.GetValue(Skills.None, "color"), false); - - if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false) - { - Config.GameModes gameMode = (Config.GameModes)Config.LoadedConfig.Settings.GameMode; - if (staticSkills.TryGetValue(player.SteamID, out var staticSkill)) - randomSkill = staticSkill; - else if (gameMode == Config.GameModes.Normal || gameMode == Config.GameModes.NoRepeat) - { - List skillList = new(SkillData.Skills); - skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill || s?.Skill == Skills.None); - - if (Utilities.GetPlayers().FindAll(p => p.Team == player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).Count == 1) - { - Config.DefaultSkillInfo[] skillsNeedsTeammates = Config.LoadedConfig.SkillsInfo.Where(s => s.NeedsTeammates).ToArray(); - skillList.RemoveAll(s => skillsNeedsTeammates.Any(s2 => s2.Name == s.Skill.ToString())); - } - - if (player.Team == CsTeam.Terrorist) - skillList.RemoveAll(s => counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - else - skillList.RemoveAll(s => terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - - if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.SteamID, out List? skills)) - { - skillList.RemoveAll(s => skills.Any(s2 => s2.Skill == s.Skill)); - if (skillList.Count == 0) skills.Clear(); - } - - randomSkill = skillList.Count == 0 ? noneSkill : skillList[Instance.Random.Next(skillList.Count)]; - if (gameMode == Config.GameModes.NoRepeat) - { - if (playersSkills.TryGetValue(player.SteamID, out List? value)) - value.Add(randomSkill); - else - playersSkills.Add(player.SteamID, [randomSkill]); - } - } - else if (gameMode == Config.GameModes.TeamSkills) - randomSkill = player.Team == CsTeam.Terrorist ? tSkill : ctSkill; - else if (gameMode == Config.GameModes.SameSkills) - randomSkill = allSkill; - else if (gameMode == Config.GameModes.Debug) - { - if (debugSkills.Count == 0) - debugSkills = new List(SkillData.Skills); - randomSkill = debugSkills[0]; - debugSkills.RemoveAt(0); - player.PrintToChat($"{SkillData.Skills.Count - debugSkills.Count}/{SkillData.Skills.Count}"); - } - } - - skillPlayer.Skill = randomSkill.Skill; - skillPlayer.SpecialSkill = Skills.None; - Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{randomSkill.Name}\"."); - - if (randomSkill.Display) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{randomSkill.Name}{ChatColors.Lime}: {randomSkill.Description}", false); - - if (Config.LoadedConfig.Settings.TeamMateSkillInfo) - { - Instance?.AddTimer(0.5f, () => - { - foreach (var teammate in teammates) - { - var teammateSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID)?.Skill; - if (teammateSkill != null) - { - var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == teammateSkill); - teammateSkills += $" {ChatColors.DarkRed}{teammate.PlayerName}{ChatColors.Lime}: {(skillInfo == null ? Skills.None : skillInfo.Name)}\n"; - } - } - - if (!string.IsNullOrEmpty(teammateSkills)) - { - SkillUtils.PrintToChat(player, $" {ChatColors.Lime}{Localization.GetTranslation("teammate_skills")}:", false); - foreach (string text in teammateSkills.Split("\n")) - if (!string.IsNullOrEmpty(text)) - player.PrintToChat(text); - } - }); - } - } - } - - return HookResult.Continue; - }); - - - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - var attacker = @event.Attacker; - - if (victim == null || attacker == null || victim == attacker) return HookResult.Continue; - - if(Config.LoadedConfig.Settings.KillerSkillInfo) - { - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (attackerInfo != null) - { - var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.Skill); - var specialSkillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.SpecialSkill); - if (skillData == null || specialSkillData == null) return HookResult.Continue; - string skillDesc = skillData.Description; - - SkillUtils.PrintToChat(victim, $"{Localization.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}:", false); - SkillUtils.PrintToChat(victim, $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? skillData.Name : $"{specialSkillData.Name} -> {skillData.Name}")}{ChatColors.Lime} - {skillDesc}", false); - } - } - - return HookResult.Continue; - }); - - Instance.RegisterListener((CCSPlayerController player, PlayerButtons pressed, PlayerButtons released) => - { - string? button = Config.LoadedConfig.Settings.AlternativeSkillButton; - if (string.IsNullOrEmpty(button)) return; - - if (Enum.TryParse(button, out var skillButton)) - { - if (pressed != skillButton) return; - } else return; - - if (player == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo == null) return; - - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; - - Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill} by PlayerButtons: {pressed}"); - Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]); - }); + public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) + { + foreach (var playerSkill in Instance.SkillPlayer) + if (!playerSkill.IsDrawing) + Instance.SkillAction(playerSkill.Skill.ToString(), "CheckTransmit", [infoList]); } [GeneratedRegex(@"\{AUTHOR1\}", RegexOptions.IgnoreCase, "pl-PL")] diff --git a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs index f177ed9..eb32f6c 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs @@ -84,14 +84,17 @@ namespace jRandomSkills var observeredPlayerSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == observedPlayer.SteamID); if (observeredPlayerSkill == null) return; - + var observeredPlayerSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == observeredPlayerSkill.Skill); if (observeredPlayerSkillInfo == null) return; var observeredPlayerSpecialSkillInfo = SkillData.Skills.FirstOrDefault(s => s.Skill == observeredPlayerSkill.SpecialSkill); if (observeredPlayerSpecialSkillInfo == null) return; - infoLine = $"{Localization.GetTranslation("observer_skill")} {observeredPlayerSkill.PlayerName}:
"; + string pName = observeredPlayerSkill.PlayerName; + if (pName.Length > 18) + pName = $"{pName.Substring(0, 17)}..."; + infoLine = $"{Localization.GetTranslation("observer_skill")} {pName}:
"; skillLine = $"{(observeredPlayerSkill.SpecialSkill == Skills.None ? observeredPlayerSkillInfo.Name : $"{observeredPlayerSpecialSkillInfo.Name}({observeredPlayerSkillInfo.Name})")}
"; } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs b/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs index 5c6fcf5..c6e3df5 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs @@ -1,5 +1,4 @@ using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -16,31 +15,30 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); CCSPlayerPawn victimPawn = new(param.Handle); if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return HookResult.Continue; + return; if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); CCSPlayerController victim = victimPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (playerInfo == null) return HookResult.Continue; + if (playerInfo == null) return; if (attacker.PawnIsAlive) { @@ -60,8 +58,12 @@ namespace jRandomSkills } } } + } - return HookResult.Continue; + public static void DisableSkill(CCSPlayerController _) + { + foreach (var hit in hitGroups) + Marshal.WriteInt32(hit.Key, 56, hit.Value); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs b/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs index 1625fd9..38cd2d4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -19,64 +18,37 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + { + UpdateHUD(player, skillInfo); + if (Server.TickCount % tickRate != 0) return; + var pawn = player.PlayerPawn.Value; + if (pawn != null && pawn.IsValid && pawn.AbsOrigin != null) { - UpdateHUD(player, skillInfo); - if (Server.TickCount % tickRate != 0) return; - var pawn = player.PlayerPawn.Value; - if (pawn != null && pawn.IsValid && pawn.AbsOrigin != null) + if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue; + skillInfo.LastPositions.Add(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z)); + skillInfo.LastRotations.Add(new QAngle(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z)); + if (skillInfo.LastRotations.Count > maxSize) { - if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue; - skillInfo.LastPositions.Add(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z)); - skillInfo.LastRotations.Add(new QAngle(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z)); - if (skillInfo.LastRotations.Count > maxSize) - { - skillInfo.LastPositions.RemoveAt(0); - skillInfo.LastRotations.RemoveAt(0); - } + skillInfo.LastPositions.RemoveAt(0); + skillInfo.LastRotations.RemoveAt(0); } } - } - }); + } + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs b/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs index 7b9ca80..1aa710c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; @@ -14,44 +13,25 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + public static void PlayerBlind(EventPlayerBlind @event) + { + var player = @event.Userid; + var attacker = @event.Attacker; + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + if (attacker == null || !attacker.IsValid) return; - return HookResult.Continue; - }); + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid) return; - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - var attacker = @event.Attacker; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return HookResult.Continue; - if (attacker == null || !attacker.IsValid) return HookResult.Continue; - - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - - if (playerInfo?.Skill == skillName) - playerPawn.FlashDuration = 0.0f; - else if (attackerInfo?.Skill == skillName) - playerPawn.FlashDuration = 7.0f; - - return HookResult.Continue; - }); + if (playerInfo?.Skill == skillName) + playerPawn.FlashDuration = 0.0f; + else if (attackerInfo?.Skill == skillName) + playerPawn.FlashDuration = 7.0f; } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs b/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs index a099066..0b49459 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs @@ -12,25 +12,18 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - int hitgroup = @event.Hitgroup; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + int hitgroup = @event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - - if (playerInfo?.Skill == skillName && hitgroup == (int)HitGroup_t.HITGROUP_HEAD) - { - ApplyIronHeadEffect(victim!, @event.DmgHealth); - return HookResult.Stop; - } - - return HookResult.Continue; - }); + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (playerInfo?.Skill == skillName && hitgroup == (int)HitGroup_t.HITGROUP_HEAD) + ApplyIronHeadEffect(victim!, @event.DmgHealth); } private static void ApplyIronHeadEffect(CCSPlayerController victim, float damage) diff --git a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs index aab7ad2..3d76682 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs @@ -16,32 +16,13 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - EnableBombsite(); - }); - - return HookResult.Continue; - }); + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + Instance.AddTimer(0.1f, EnableBombsite); } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -78,19 +59,16 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("areareaper") + ":", false); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("areareaper_select_info")}"); - player.PrintToChat($" {ChatColors.Green}· {ChatColors.Red}/t {ChatColors.Green}A"); - player.PrintToChat($" {ChatColors.Green}· {ChatColors.Red}/t {ChatColors.Green}B"); + HashSet<(string, string)> menuItems = [(Localization.GetTranslation("bombsite_a"), "a"), (Localization.GetTranslation("bombsite_b"), "b")]; + SkillUtils.CreateMenu(player, menuItems); } -#pragma warning disable IDE0060 // Usuń nieużywany parametr public static void DisableSkill(CCSPlayerController player) -#pragma warning restore IDE0060 // Usuń nieużywany parametr { - if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) - return; + SkillUtils.CloseMenu(player); + if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return; EnableBombsite(); + } private static void EnableBombsite() diff --git a/jRandomSkills - SRC Files/src/player/skills/Armored.cs b/jRandomSkills - SRC Files/src/player/skills/Armored.cs index 2d8d5c1..08a534a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Armored.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Armored.cs @@ -1,6 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -16,25 +14,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -48,36 +27,34 @@ namespace jRandomSkills SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("armored")}{ChatColors.Lime}: " + Localization.GetTranslation("armored_desc2", newScale), false); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); CCSPlayerPawn victimPawn = new(param.Handle); if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return HookResult.Continue; + return; if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); CCSPlayerController victim = victimPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim.SteamID); - if (playerInfo == null) return HookResult.Continue; + if (playerInfo == null) return; if (playerInfo.Skill == skillName && victim.PawnIsAlive) { float? skillChance = playerInfo.SkillChance; param2.Damage *= skillChance ?? 1f; } - - return HookResult.Continue; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#d1430a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = .65f, float chanceTo = .85f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Assassin.cs b/jRandomSkills - SRC Files/src/player/skills/Assassin.cs index d2ba9d9..344dc56 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Assassin.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Assassin.cs @@ -15,26 +15,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var damage = @event.DmgHealth; - var victim = @event.Userid; - var attacker = @event.Attacker; - var weapon = @event.Weapon; - HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; + public static void PlayerHurt(EventPlayerHurt @event) + { + var damage = @event.DmgHealth; + var victim = @event.Userid; + var attacker = @event.Attacker; + var weapon = @event.Weapon; + HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - if (nades.Contains(weapon)) return HookResult.Continue; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + if (nades.Contains(weapon)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (playerInfo?.Skill != skillName) return; - if (IsBehind(attacker!, victim!)) - SkillUtils.TakeHealth(victim!.PlayerPawn.Value, (int)(damage * (damageMultiplier - 1f))); - - return HookResult.Continue; - }); + if (IsBehind(attacker!, victim!)) + SkillUtils.TakeHealth(victim!.PlayerPawn.Value, (int)(damage * (damageMultiplier - 1f))); } private static bool IsBehind(CCSPlayerController attacker, CCSPlayerController victim) diff --git a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs index 03711a6..b84953f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs @@ -14,31 +14,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var playerPawn = player.PlayerPawn.Value; - - if (playerInfo?.Skill == skillName && playerPawn != null) - { - EnableSkill(player); - } - } - }); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - DisableSkill(player); - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -46,6 +21,12 @@ namespace jRandomSkills ApplyGravityModifier(player); } + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + DisableSkill(player); + } + public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs index b058f21..0131df0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs @@ -18,77 +18,56 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - var attacker = @event.Attacker; - var weapon = @event.Weapon; - - if (weapon != "decoy") return HookResult.Continue; - if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return HookResult.Continue; - - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (attackerInfo?.Skill != skillName) return HookResult.Continue; - - SkillUtils.TakeHealth(victim!.PlayerPawn.Value, damageDeal); - return HookResult.Continue; - }); - - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (name != "decoy_projectile") - return; - - var decoy = @event.As(); - if (decoy == null || !decoy.IsValid || decoy.OwnerEntity == null || decoy.OwnerEntity.Value == null || !decoy.OwnerEntity.Value.IsValid) return; - - var pawn = decoy.OwnerEntity.Value.As(); - if (pawn == null || !pawn.IsValid || pawn.Controller == null || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; - - var player = pawn.Controller.Value.As(); - if (player == null || !player.IsValid) return; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return; - decoys.Add(decoy); - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var decoy = decoys.FirstOrDefault(d => d.Index == @event.Entityid); - if (decoy != null && decoy.IsValid) - decoy.Remove(); - - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + var attacker = @event.Attacker; + var weapon = @event.Weapon; + + if (weapon != "decoy") return; + if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return; + + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (attackerInfo?.Skill != skillName) return; + + SkillUtils.TakeHealth(victim!.PlayerPawn.Value, damageDeal); + } + + public static void OnEntitySpawned(CEntityInstance entity) + { + var name = entity.DesignerName; + if (name != "decoy_projectile") + return; + + var decoy = entity.As(); + if (decoy == null || !decoy.IsValid || decoy.OwnerEntity == null || decoy.OwnerEntity.Value == null || !decoy.OwnerEntity.Value.IsValid) return; + + var pawn = decoy.OwnerEntity.Value.As(); + if (pawn == null || !pawn.IsValid || pawn.Controller == null || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; + + var player = pawn.Controller.Value.As(); + if (player == null || !player.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + decoys.Add(decoy); + } + + public static void DecoyStarted(EventDecoyStarted @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + + var decoy = decoys.FirstOrDefault(d => d.Index == @event.Entityid); + if (decoy != null && decoy.IsValid) + decoy.Remove(); + } + + public static void OnTick() { foreach (var decoy in decoys) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Behind.cs b/jRandomSkills - SRC Files/src/player/skills/Behind.cs index 281fdaa..93f2049 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Behind.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Behind.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,42 +13,19 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event!.Attacker; + var victim = @event!.Userid; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event!.Attacker; - var victim = @event!.Userid; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) - return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) - { - if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - RotateEnemy(victim); - } - - return HookResult.Continue; - }); + if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) + if (Instance.Random.NextDouble() <= playerInfo.SkillChance) + RotateEnemy(victim); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs b/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs index e7f39ed..28fe9ce 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs @@ -16,38 +16,38 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + int damage = @event.DmgHealth; + HitGroup_t hitGroup = (HitGroup_t)@event.Hitgroup; + string weapon = @event.Weapon; + + if (noReflectionWeapon.Contains(weapon) || !Instance.IsPlayerValid(victim)) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo == null || victimInfo.Skill != skillName) return; + + int chance = Instance.Random.Next(0, 101); + if (hitGroup == HitGroup_t.HITGROUP_LEFTLEG || hitGroup == HitGroup_t.HITGROUP_RIGHTLEG) { - var victim = @event.Userid; - int damage = @event.DmgHealth; - HitGroup_t hitGroup = (HitGroup_t)@event.Hitgroup; - string weapon = @event.Weapon; + if (chance > legReflectionChance) + return; + } + else + if (chance > torseReflectionChance) + return; - if (noReflectionWeapon.Contains(weapon) || !Instance.IsPlayerValid(victim)) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return HookResult.Continue; + var pawn = victim!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; - int chance = Instance.Random.Next(0, 101); - if (hitGroup == HitGroup_t.HITGROUP_LEFTLEG || hitGroup == HitGroup_t.HITGROUP_RIGHTLEG) - { - if (chance > legReflectionChance) - return HookResult.Continue; - } - else - if (chance > torseReflectionChance) - return HookResult.Continue; + var weaponServices = pawn.WeaponServices; + if (weaponServices == null) return; + if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife") + return; - var pawn = victim!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return HookResult.Continue; - - var weaponServices = pawn.WeaponServices; - if (weaponServices == null) return HookResult.Continue; - if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife") return HookResult.Continue; - - RestoreHealth(victim, damage); - return HookResult.Stop; - }); + RestoreHealth(victim, damage); } private static void RestoreHealth(CCSPlayerController victim, float damage) diff --git a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs index 2042e85..c243ddf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,10 +16,9 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { @@ -34,6 +32,7 @@ namespace jRandomSkills { var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; + if (JumpBan.bannedPlayers.ContainsKey(playerPawn)) return; var flags = (PlayerFlags)playerPawn.Flags; var buttons = player.Buttons; diff --git a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs index 2599a54..69ab6c3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs +++ b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs @@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -12,89 +11,41 @@ namespace jRandomSkills public class C4Camouflage : ISkill { private const Skills skillName = Skills.C4Camouflage; - private static bool exists = false; private static readonly Dictionary> invisibleEntities = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; + EnableSkill(player!); + } + + public static void WeaponEquip(EventItemEquip @event) + { + var player = @event.Userid; + var weapon = @event.Item; + + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; + + if (weapon == "c4") { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - DisableSkill(player); - if (!Instance.IsPlayerValid(player)) continue; - var playerPawn = player.PlayerPawn?.Value; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => + SetPlayerVisibility(player!, false); + SetWeaponVisibility(player!, false); + } + else { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - EnableSkill(player!); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - var weapon = @event.Item; - - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - if (weapon == "c4") - { - SetPlayerVisibility(player!, false); - SetWeaponVisibility(player!, false); - } - else - { - SetPlayerVisibility(player!, true); - SetWeaponVisibility(player!, true); - } - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - } - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); + SetPlayerVisibility(player!, true); + SetWeaponVisibility(player!, true); + } } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -111,10 +62,7 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; - + Event.enableTransmit = true; if (player == null || !player.IsValid) return; var playerPawn = player.PlayerPawn.Value; @@ -129,7 +77,6 @@ namespace jRandomSkills SetWeaponVisibility(player, false); } - public static void DisableSkill(CCSPlayerController player) { SetPlayerVisibility(player, true); diff --git a/jRandomSkills - SRC Files/src/player/skills/Catapult.cs b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs index cdde229..b7690cc 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Catapult.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,46 +13,23 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + + if (attackerInfo?.Skill == skillName && victim!.PawnIsAlive) + if (Instance.Random.NextDouble() <= attackerInfo.SkillChance) { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - if (attackerInfo?.Skill == skillName && victim!.PawnIsAlive) - { - if (Instance.Random.NextDouble() <= attackerInfo.SkillChance) - { - var victimPawn = victim.PlayerPawn?.Value; - if (victimPawn != null) - { - victimPawn.AbsVelocity.Z = 300f; - } - } + var victimPawn = victim.PlayerPawn?.Value; + if (victimPawn != null) + victimPawn.AbsVelocity.Z = 300f; } - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs index d9d73ae..a0485bf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; using jRandomSkills.src.utils; using CounterStrikeSharp.API.Core.Attributes; @@ -13,8 +12,6 @@ namespace jRandomSkills public class Chicken : ISkill { private const Skills skillName = Skills.Chicken; - private static bool roundEnd = false; - private static bool exists = false; private static readonly string[] disabledWeapons = [ "weapon_ak47", "weapon_m4a4", "weapon_m4a1", "weapon_m4a1_silencer", @@ -30,70 +27,21 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - roundEnd = false; - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + } - return HookResult.Continue; - }); + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SetWeaponAttack(player, false); + } - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - DisableSkill(player); - } - roundEnd = true; - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - SetWeaponAttack(player, true); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - SetWeaponAttack(player, false); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + SetWeaponAttack(player, true); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -112,10 +60,7 @@ namespace jRandomSkills var playerPawn = player.PlayerPawn?.Value; if (playerPawn != null && playerPawn.IsValid) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; - + Event.enableTransmit = true; playerPawn.VelocityModifier = 1.1f; playerPawn.Health = 50; @@ -165,7 +110,7 @@ namespace jRandomSkills private static void SetWeaponAttack(CCSPlayerController player, bool disableWeapon) { - if (roundEnd || player == null || !player.IsValid) return; + if (player == null || !player.IsValid) return; var pawn = player?.PlayerPawn?.Value; if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null || pawn.WeaponServices.MyWeapons == null) return; @@ -200,7 +145,7 @@ namespace jRandomSkills Instance.AddTimer(1f, () => chickens.TryAdd(player, chickenModel)); } - private static void OnTick() + public static void OnTick() { foreach (var valuePair in chickens) { diff --git a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs index 80876dc..864705e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs @@ -14,28 +14,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => + } + + public static void BombBeginplant(EventBombBeginplant @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + + var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName); + if (anyChillOut != null) { - var player = @event.Userid; - - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - - var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName); - if (anyChillOut != null) + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); + if (bombEntities.Count != 0) { - var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); - - if (bombEntities.Count != 0) - { - var bomb = bombEntities.FirstOrDefault(); - if (bomb != null) - bomb.ArmedTime = Server.CurrentTime + bombArmedTime; - } + var bomb = bombEntities.FirstOrDefault(); + if (bomb != null) + bomb.ArmedTime = Server.CurrentTime + bombArmedTime; } - - return HookResult.Continue; - }); + } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#343deb", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool needsTeammates = false, float bombArmedTime = 10f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Cutter.cs b/jRandomSkills - SRC Files/src/player/skills/Cutter.cs index b89db55..5403b4c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Cutter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Cutter.cs @@ -12,23 +12,21 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var damage = @event.DmgHealth; - var attacker = @event.Attacker; - var victim = @event.Userid; - var weapon = @event.Weapon; + public static void PlayerHurt(EventPlayerHurt @event) + { + var damage = @event.DmgHealth; + var attacker = @event.Attacker; + var victim = @event.Userid; + var weapon = @event.Weapon; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (playerInfo?.Skill != skillName) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - if (weapon == "knife") - SkillUtils.TakeHealth(victim!.PlayerPawn.Value, 9999); - return HookResult.Continue; - }); + if (weapon == "knife") + SkillUtils.TakeHealth(victim!.PlayerPawn.Value, 9999); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#88a31a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Darkness.cs b/jRandomSkills - SRC Files/src/player/skills/Darkness.cs index 8a3b907..12258c2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Darkness.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Darkness.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using System.Collections.Generic; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,40 +17,33 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in defaultPostProcessings.Keys) + DisableSkill(player); + foreach (var postProcessing in newPostProcessing) + postProcessing.Remove(); + newPostProcessing.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in defaultPostProcessings.Keys) - DisableSkill(player); - foreach (var postProcessing in newPostProcessing) - postProcessing.Remove(); - newPostProcessing.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - SetUpPostProcessing(player, true); - return HookResult.Continue; - }); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -87,23 +79,20 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("darkness") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("darkness_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { SetUpPostProcessing(player, true); + SkillUtils.CloseMenu(player); } private static void SetUpPostProcessing(CCSPlayerController player, bool dontCreateNew = false) diff --git a/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs b/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs index d06ad3c..c356d39 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs @@ -13,34 +13,39 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + if (enemies.Length > 0) { - foreach (var player in Utilities.GetPlayers()) + HashSet<(string, string)> menuItems = []; + foreach (var enemy in enemies) { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); + var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); + if (skillData == null) continue; + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); + SkillUtils.CreateMenu(player, menuItems); } - return HookResult.Continue; - }); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -68,24 +73,22 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - SkillUtils.PrintToChat(player, Localization.GetTranslation("deactivator") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("deactivator_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { + HashSet<(string, string)> menuItems = []; foreach (var enemy in enemies) { var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}: {ChatColors.Red}{skillData.Name}"); + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); } + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) @@ -93,6 +96,7 @@ namespace jRandomSkills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null) return; playerInfo.SpecialSkill = Skills.None; + SkillUtils.CloseMenu(player); } private static void DeacitvateSkill(CCSPlayerController player, CCSPlayerController enemy) diff --git a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs index 421e58a..faa37c0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; @@ -14,50 +15,38 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - deafPlayers.Clear(); - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; + public static void NewRound() + { + foreach (var player in deafPlayers) DisableSkill(player); - return HookResult.Continue; - }); + deafPlayers.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } - Instance.RegisterEventHandler((@event, info) => + public static void PlayerMakeSound(UserMessage um) + { + foreach (var player in deafPlayers) + um.Recipients.Remove(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - foreach (var player in deafPlayers) - DisableSkill(player); - return HookResult.Continue; - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - Instance.HookUserMessage(208, um => - { - var soundevent = um.ReadUInt("soundevent_hash"); - var userIndex = um.ReadUInt("source_entity_index"); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - foreach (var player in deafPlayers) - um.Recipients.Remove(player); - - return HookResult.Continue; - }, HookMode.Pre); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -93,23 +82,20 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("deaf") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("deaf_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { deafPlayers.Remove(player); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dae01f", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs index bc1aae9..60c9d9e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,47 +13,29 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + + if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) { - Instance.AddTimer(0.1f, () => + if (Instance.Random.NextDouble() <= playerInfo?.SkillChance) { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; + var weaponServices = victim.PlayerPawn?.Value?.WeaponServices; + if (weaponServices?.ActiveWeapon == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) - { - if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - { - var weaponServices = victim.PlayerPawn?.Value?.WeaponServices; - if (weaponServices?.ActiveWeapon == null) return HookResult.Continue; - - var weaponName = weaponServices?.ActiveWeapon?.Value?.DesignerName; - if (weaponName != null && !weaponName.Contains("weapon_knife") && !weaponName.Contains("weapon_c4")) - victim.ExecuteClientCommand("slot3"); - //victim.DropActiveWeapon(); - } + var weaponName = weaponServices?.ActiveWeapon?.Value?.DesignerName; + if (weaponName != null && !weaponName.Contains("weapon_knife") && !weaponName.Contains("weapon_c4")) + victim.ExecuteClientCommand("slot3"); + //victim.DropActiveWeapon(); } - return HookResult.Continue; - }); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Distancer.cs b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs index fec7440..b04d44a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Distancer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static jRandomSkills.jRandomSkills; namespace jRandomSkills { @@ -15,34 +14,14 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in distancerPlayers) - DisableSkill(player); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() + { + distancerPlayers.Clear(); + } + + public static void OnTick() { foreach (var player in distancerPlayers) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs index 3261957..3fcb8c8 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs @@ -14,22 +14,18 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; + } - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) - { - HealAttacker(attacker!, @event.DmgHealth); - } - return HookResult.Continue; - }); + if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) + HealAttacker(attacker!, @event.DmgHealth); } private static void HealAttacker(CCSPlayerController attacker, float damage) diff --git a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs index 9cc1211..00289d0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs @@ -13,23 +13,39 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + if (enemies.Length > 0) + { + HashSet<(string, string)> menuItems = []; + foreach (var enemy in enemies) + { + var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); + if (skillData == null) continue; + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); + } + SkillUtils.CreateMenu(player, menuItems); + } + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -57,24 +73,22 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - SkillUtils.PrintToChat(player, Localization.GetTranslation("duplicator") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("duplicator_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { + HashSet<(string, string)> menuItems = []; foreach (var enemy in enemies) { var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}: {ChatColors.Red}{skillData.Name}"); + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); } + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) @@ -82,6 +96,7 @@ namespace jRandomSkills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null) return; playerInfo.SpecialSkill = Skills.None; + SkillUtils.CloseMenu(player); } private static void DuplicateSkill(CCSPlayerController player, CCSPlayerController enemy) @@ -91,10 +106,12 @@ namespace jRandomSkills if (playerInfo != null && enemyInfo != null) { - playerInfo.Skill = enemyInfo.Skill; - playerInfo.SpecialSkill = skillName; - Instance.SkillAction(enemyInfo.Skill.ToString(), "EnableSkill", [player]); - + Instance.AddTimer(.1f, () => + { + playerInfo.Skill = enemyInfo.Skill; + playerInfo.SpecialSkill = skillName; + Instance.SkillAction(enemyInfo.Skill.ToString(), "EnableSkill", [player]); + }); player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("duplicator_player_info", enemy.PlayerName)); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs b/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs index 7f1ef0f..0faca5c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs @@ -14,49 +14,18 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - player.Respawn(); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - DisableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - DisableSkill(player); - return HookResult.Continue; - }); } - public static void EnableSkill(CCSPlayerController player) + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + { + if (!Instance.IsPlayerValid(player)) continue; + DisableSkill(player); + } + } + + public static unsafe void EnableSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn?.Value; if (playerPawn != null && player.IsValid) @@ -67,6 +36,7 @@ namespace jRandomSkills // playerPawn.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = newSize; if (playerPawn.CBodyComponent == null || playerPawn.CBodyComponent.SceneNode == null) return; playerPawn.CBodyComponent.SceneNode.Scale = newSize; + Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent"); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("dwarf")}{ChatColors.Lime}: " + Localization.GetTranslation("dwarf_desc2", newSize), false); } diff --git a/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs b/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs index 35f44f0..e7ec994 100644 --- a/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs +++ b/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,52 +16,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs index e6b2b29..d6c0ead 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -18,24 +17,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); } public static void EnableSkill(CCSPlayerController player) @@ -65,28 +46,27 @@ namespace jRandomSkills heProjectile.DetonateTime = 0; } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); if (attackerPawn.DesignerName != "player") - return HookResult.Continue; + return; if (attackerPawn == null || attackerPawn.Controller?.Value == null) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (playerInfo == null || playerInfo.Skill != skillName) return HookResult.Continue; + if (playerInfo == null || playerInfo.Skill != skillName) return; if (Instance.Random.NextDouble() <= playerInfo.SkillChance) SpawnExplosion(param2.DamagePosition); - return HookResult.Continue; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float damage = 10f, float damageRadius = 190f, float chanceFrom = .15f, float chanceTo = .3f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs index bab7080..f611b06 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs @@ -10,56 +10,40 @@ namespace jRandomSkills public class FalconEye : ISkill { private const Skills skillName = Skills.FalconEye; - private static bool blocked = false; private static readonly float distance = Config.GetValue(skillName, "distance"); private static readonly Dictionary cameras = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - blocked = true; - foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out _)) - DisableSkill(player); + public static void NewRound() + { + foreach (var camera in cameras) + camera.Value.Item2.Remove(); + cameras.Clear(); + } - foreach (var camera in cameras) - camera.Value.Item2.Remove(); - cameras.Clear(); - return HookResult.Continue; - }); + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - Instance.RegisterEventHandler((@event, info) => - { - blocked = false; - return HookResult.Continue; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return ; - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + var pawn = player!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var pawn = player!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return HookResult.Continue; - - if (cameras.TryGetValue(player!.SteamID, out var cameraInfo) && cameraInfo.Item1 == pawn.CameraServices.ViewEntity.Raw) - BlockWeapon(player, true); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + if (cameras.TryGetValue(player!.SteamID, out var cameraInfo) && cameraInfo.Item1 == pawn.CameraServices.ViewEntity.Raw) + BlockWeapon(player, true); } public static void UseSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null || blocked) return; + if (playerPawn?.CBodyComponent == null) return; ChangeCamera(player); } @@ -68,7 +52,7 @@ namespace jRandomSkills ChangeCamera(player, true); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) diff --git a/jRandomSkills - SRC Files/src/player/skills/Flash.cs b/jRandomSkills - SRC Files/src/player/skills/Flash.cs index b1d525d..66f3b60 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Flash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Flash.cs @@ -1,9 +1,9 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -15,50 +15,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - Instance.RegisterListener(UpdateSpeed); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid) continue; + public static void PlayerMakeSound(UserMessage um) + { + var soundevent = um.ReadUInt("soundevent_hash"); + var userIndex = um.ReadUInt("source_entity_index"); - playerPawn.VelocityModifier = 1; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); + if (userIndex == 0) return; + if (!Instance.footstepSoundEvents.Contains(soundevent)) return; - Instance.HookUserMessage(208, um => - { - var soundevent = um.ReadUInt("soundevent_hash"); - var userIndex = um.ReadUInt("source_entity_index"); + var player = Utilities.GetPlayers().FirstOrDefault(p => p.Pawn?.Value != null && p.Pawn.Value.IsValid && p.Pawn.Value.Index == userIndex); + if (!Instance.IsPlayerValid(player)) return; - if (userIndex == 0) return HookResult.Continue; - if (!Instance.footstepSoundEvents.Contains(soundevent)) return HookResult.Continue; - - var player = Utilities.GetPlayers().FirstOrDefault(p => p.Pawn?.Value != null && p.Pawn.Value.IsValid && p.Pawn.Value.Index == userIndex); - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - if (player!.Buttons.HasFlag(PlayerButtons.Speed) || player.Buttons.HasFlag(PlayerButtons.Duck)) - { - um.Recipients.Clear(); - return HookResult.Handled; - } - - return HookResult.Continue; - }, HookMode.Pre); + if (player!.Buttons.HasFlag(PlayerButtons.Speed) || player.Buttons.HasFlag(PlayerButtons.Duck)) + um.Recipients.Clear(); } public static void EnableSkill(CCSPlayerController player) @@ -85,7 +59,7 @@ namespace jRandomSkills playerPawn.VelocityModifier = 1; } - private static void UpdateSpeed() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs index 0843be1..3046bea 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -23,57 +22,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + Instance.RegisterListener((ResourceManifest manifest) => manifest.AddResource(propModel)); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + barricades.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - barricades.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); - - Instance.RegisterListener((ResourceManifest manifest) => - { - manifest.AddResource(propModel); - }); - - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) @@ -153,19 +119,19 @@ namespace jRandomSkills }); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; - if (string.IsNullOrEmpty(param.Entity.Name)) return HookResult.Continue; - if (!param.Entity.Name.StartsWith("FortniteWall")) return HookResult.Continue; + if (string.IsNullOrEmpty(param.Entity.Name)) return; + if (!param.Entity.Name.StartsWith("FortniteWall")) return; var box = param.As(); - if (box == null || !box.IsValid) return HookResult.Continue; + if (box == null || !box.IsValid) return; box.EmitSound("Wood_Plank.BulletImpact", volume: 1f); if (barricades.TryGetValue(box.Index, out int health)) @@ -175,7 +141,6 @@ namespace jRandomSkills if (health <= 0) box.Remove(); } else box.Remove(); - return HookResult.Continue; } public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs index 6e0cee6..335f414 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs @@ -1,7 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -22,25 +21,21 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - bombHealth = maxBombHealth; - plantedC4 = null; - triggerC4 = null; - return HookResult.Continue; - }); + public static void NewRound() + { + bombHealth = maxBombHealth; + plantedC4 = null; + triggerC4 = null; + } - Instance.RegisterEventHandler((@event, info) => - { - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb == null) return HookResult.Continue; - plantedC4 = plantedBomb; - CreateTrigger(); - return HookResult.Continue; - }); - - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); + public static void BombPlanted(EventBombPlanted _) + { + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb == null) return; + plantedC4 = plantedBomb; + CreateTrigger(); } private static void CreateTrigger() @@ -82,38 +77,37 @@ namespace jRandomSkills SkillUtils.TerminateRound(CsTeam.CounterTerrorist); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); if (attackerPawn.DesignerName != "player" || param.DesignerName != "trigger_multiple") - return HookResult.Continue; + return; CTriggerMultiple trigger = new(param.Handle); if (attackerPawn == null || attackerPawn.Controller?.Value == null || trigger == null || !trigger.Globalname.StartsWith("planted_bomb_prop_")) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (playerInfo == null || playerInfo.Skill != skillName) return HookResult.Continue; + if (playerInfo == null || playerInfo.Skill != skillName) return; bombHealth -= (int)param2.TotalledDamage; if (bombHealth <= 0) { RemoveBomb(); - return HookResult.Continue; + return; } Server.PrintToChatAll($" {ChatColors.Gold}{Localization.GetTranslation("fragilebomb_bomb_health")}: {ChatColors.Red}{bombHealth}{ChatColors.Gold}/{ChatColors.Green}{maxBombHealth}"); - return HookResult.Continue; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool needsTeammates = false, int maxBombHealth = 1000) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs index 39c2d58..464c496 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs @@ -15,29 +15,27 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var damage = @event.DmgHealth; - var victim = @event.Userid; - var attacker = @event.Attacker; - var weapon = @event.Weapon; - HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; + public static void PlayerHurt(EventPlayerHurt @event) + { + var damage = @event.DmgHealth; + var victim = @event.Userid; + var attacker = @event.Attacker; + var weapon = @event.Weapon; + HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; - if (nades.Contains(weapon)) return HookResult.Continue; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; + if (nades.Contains(weapon)) return; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (playerInfo?.Skill != skillName || attacker!.Team != victim!.Team) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (playerInfo?.Skill != skillName || attacker!.Team != victim!.Team) return; - Server.ExecuteCommand("mp_autokick 0"); + Server.ExecuteCommand("mp_autokick 0"); - var pawn = victim.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return HookResult.Continue; - SkillUtils.AddHealth(pawn, damage + (int)(damage * healthMultiplier), pawn.MaxHealth); - - return HookResult.Continue; - }); + var pawn = victim.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + SkillUtils.AddHealth(pawn, damage + (int)(damage * healthMultiplier), pawn.MaxHealth); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = true, float healthMultiplier = 1.5f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs b/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs index 16120a1..cd80bec 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,64 +17,45 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - decoys.Clear(); - return HookResult.Continue; - }); + public static void NewRound() + { + decoys.Clear(); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => + public static void DecoyStarted(EventDecoyStarted @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + decoys.Add(new Vector(@event.X, @event.Y, @event.Z)); + } + + public static void DecoyDetonate(EventDecoyDetonate @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + decoys.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); + } + + public static void OnTick() + { + foreach (Vector decoyPos in decoys) + foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist || p.Team == CsTeam.CounterTerrorist)) { - foreach (var player in Utilities.GetPlayers()) + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; + double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin); + if (distance <= decoyRadius) { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); + double modifier = Math.Clamp(distance / decoyRadius, 0f, 1f); + pawn.VelocityModifier = (float)Math.Pow(modifier, slownessMultiplier); } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - decoys.Add(new Vector(@event.X, @event.Y, @event.Z)); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - decoys.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (Vector decoyPos in decoys) - foreach (var player in Utilities.GetPlayers()) - { - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin); - if (distance <= decoyRadius) - { - double modifier = Math.Clamp(distance / decoyRadius, 0f, 1f); - pawn.VelocityModifier = (float)Math.Pow(modifier, slownessMultiplier); - } - } - }); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Gambler.cs b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs new file mode 100644 index 0000000..e803fec --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs @@ -0,0 +1,112 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using jRandomSkills.src.player; +using jRandomSkills.src.utils; +using static jRandomSkills.jRandomSkills; + +namespace jRandomSkills +{ + public class Gambler : ISkill + { + private const Skills skillName = Skills.Gambler; + private static readonly int refreshPrice = Config.GetValue(skillName, "refreshPrice"); + + public static void LoadSkill() + { + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } + + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void TypeSkill(CCSPlayerController player, string[] commands) + { + if (player == null || !player.IsValid || !player.PawnIsAlive) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + + if (playerInfo.SkillChance == 1) + { + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("areareaper_used_info")}"); + return; + } + + var skill = SkillData.Skills.FirstOrDefault(s => s.Name.Equals(commands[0], StringComparison.OrdinalIgnoreCase) || s.Skill.ToString().Equals(commands[0], StringComparison.OrdinalIgnoreCase)); + if (skill == null) + { + player.PrintToChat($" {ChatColors.Red}" + Localization.GetTranslation("skill_not_found_setskill")); + return; + } + + if (skill.Skill == skillName) + TakeMoney(player); + Instance.AddTimer(.1f, () => + { + playerInfo.Skill = skill.Skill; + playerInfo.SkillChance = 1; + Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); + }); + } + + private static void TakeMoney(CCSPlayerController player) + { + if (player == null || !player.IsValid || player.InGameMoneyServices == null) return; + var account = player.InGameMoneyServices.Account; + player.InGameMoneyServices.Account = Math.Max(0, account - refreshPrice); + Utilities.SetStateChanged(player, "CCSPlayerController", "m_pInGameMoneyServices"); + } + + public static void EnableSkill(CCSPlayerController player) + { + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null) return; + playerInfo.SkillChance = 0; + + var skills = GetSkills(player); + var firstSkill = skills[Instance.Random.Next(skills.Count)]; + skills.Remove(firstSkill); + var secondSkill = skills[Instance.Random.Next(skills.Count)]; + + HashSet<(string, string)> menuItems = [(firstSkill.Name, firstSkill.Skill.ToString()), + (secondSkill.Name, secondSkill.Skill.ToString()), + (Localization.GetTranslation("gambler_more"), skillName.ToString())]; + SkillUtils.CreateMenu(player, menuItems); + } + + public static void DisableSkill(CCSPlayerController player) + { + SkillUtils.CloseMenu(player); + } + + private static List GetSkills(CCSPlayerController player) + { + var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (skillPlayer == null) return [Event.noneSkill]; + + List skillList = new(SkillData.Skills); + skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill || s?.Skill == Skills.None); + + if (Utilities.GetPlayers().FindAll(p => p.Team == player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).Count == 1) + { + Config.DefaultSkillInfo[] skillsNeedsTeammates = Config.LoadedConfig.SkillsInfo.Where(s => s.NeedsTeammates).ToArray(); + skillList.RemoveAll(s => skillsNeedsTeammates.Any(s2 => s2.Name == s.Skill.ToString())); + } + + if (player.Team == CsTeam.Terrorist) + skillList.RemoveAll(s => Event.counterterroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + else + skillList.RemoveAll(s => Event.terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); + + return skillList.Count == 0 ? [Event.noneSkill] : skillList; + } + + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#7eff47", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int refreshPrice = 150) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) + { + public int RefreshPrice { get; set; } = refreshPrice; + } + } +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs index 2969798..59b49c9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs @@ -6,7 +6,6 @@ using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -14,8 +13,6 @@ namespace jRandomSkills public class Ghost : ISkill { private const Skills skillName = Skills.Ghost; - private static bool roundEnd = false; - private static bool exists = false; private static readonly string[] disabledWeapons = [ "weapon_deagle", "weapon_revolver", "weapon_glock", "weapon_usp_silencer", @@ -36,83 +33,34 @@ namespace jRandomSkills return; SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - roundEnd = false; - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SetWeaponAttack(player, false); + } - return HookResult.Continue; - }); + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - } - roundEnd = true; - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); + if (playerInfo?.Skill != skillName) return; + SetWeaponVisibility(player!, false); + SetWeaponAttack(player!, true); + } - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null) return HookResult.Continue; + public static void WeaponEquip(EventItemEquip @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill != skillName) return HookResult.Continue; - SetWeaponVisibility(player!, false); - SetWeaponAttack(player!, true); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill != skillName) return HookResult.Continue; - SetWeaponVisibility(player!, false); - SetWeaponAttack(player!, true); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - SetWeaponAttack(player, false); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + if (playerInfo?.Skill != skillName) return; + SetWeaponVisibility(player!, false); + SetWeaponAttack(player!, true); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -129,10 +77,7 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; - + Event.enableTransmit = true; SetPlayerVisibility(player, false); SetWeaponVisibility(player, false); SetWeaponAttack(player, true); @@ -146,7 +91,7 @@ namespace jRandomSkills invisibleEntities.Remove(player.SteamID); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { @@ -207,7 +152,7 @@ namespace jRandomSkills private static void SetWeaponAttack(CCSPlayerController player, bool disableWeapon) { - if (roundEnd || player == null || !player.IsValid) return; + if (player == null || !player.IsValid) return; var pawn = player?.PlayerPawn?.Value; if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Glaz.cs b/jRandomSkills - SRC Files/src/player/skills/Glaz.cs index 0e46c35..e6e23bd 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glaz.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glaz.cs @@ -11,49 +11,26 @@ namespace jRandomSkills public class Glaz : ISkill { private const Skills skillName = Skills.Glaz; - private static bool exists = false; private readonly static List smokes = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, @info) => - { - smokes.Clear(); - Instance.AddTimer(2f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; + public static void NewRound() + { + smokes.Clear(); + } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - return HookResult.Continue; - }); + public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) + { + smokes.Add(@event.Entityid); + } - Instance.RegisterEventHandler((@event, @info) => - { - smokes.Clear(); - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - smokes.Add(@event.Entityid); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - smokes.Remove(@event.Entityid); - return HookResult.Continue; - }); + public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event) + { + smokes.Remove(@event.Entityid); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -74,9 +51,7 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; + Event.enableTransmit = true; SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Glitch.cs b/jRandomSkills - SRC Files/src/player/skills/Glitch.cs index a8fa430..a0b5a91 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glitch.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glitch.cs @@ -14,30 +14,30 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + glitchedPlayers.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in glitchedPlayers) - DisableSkill(player); - return HookResult.Continue; - }); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -74,24 +74,21 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("glitch") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("glitch_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { player.ReplicateConVar("sv_disable_radar", "0"); glitchedPlayers.Remove(player); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Glue.cs b/jRandomSkills - SRC Files/src/player/skills/Glue.cs index c2612e2..3bed166 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glue.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glue.cs @@ -12,26 +12,26 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (!name.EndsWith("_projectile")) - return; + public static void OnEntitySpawned(CEntityInstance entity) + { + var name = entity.DesignerName; + if (!name.EndsWith("_projectile")) + return; - var grenade = @event.As(); - if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; + var grenade = entity.As(); + if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; - var pawn = grenade.OwnerEntity.Value.As(); - if (pawn == null || !pawn.IsValid || pawn.Controller == null || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; + var pawn = grenade.OwnerEntity.Value.As(); + if (pawn == null || !pawn.IsValid || pawn.Controller == null || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; - var player = pawn.Controller.Value.As(); - if (player == null || !player.IsValid) return; + var player = pawn.Controller.Value.As(); + if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return; - grenade.Bounces = 555; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + grenade.Bounces = 555; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fff52e", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs index 2b5e303..e8d6ad7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs +++ b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,51 +17,11 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + public static void NewRound() + { + SkillPlayerInfo.Clear(); } public static void EnableSkill(CCSPlayerController player) @@ -75,6 +34,17 @@ namespace jRandomSkills }; } + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) + { + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } + } + public static void DisableSkill(CCSPlayerController player) { SkillPlayerInfo.Remove(player.SteamID); diff --git a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs index a9dccdf..6520f20 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,84 +17,65 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + smokes.Clear(); + } + + public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + smokes.Add(new Vector(@event.X, @event.Y, @event.Z)); + } + + public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + smokes.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); + } + + public static void OnEntitySpawned(CEntityInstance entity) + { + var name = entity.DesignerName; + if (name != "smokegrenade_projectile") return; + + var grenade = entity.As(); + if (grenade == null || !grenade.IsValid || grenade.OwnerEntity == null || !grenade.OwnerEntity.IsValid || grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; + + var pawn = grenade.OwnerEntity.Value.As(); + if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; + + var player = pawn.Controller.Value.As(); + if (player == null || !player.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + + Server.NextFrame(() => { - smokes.Clear(); - return HookResult.Continue; + var smoke = entity.As(); + smoke.SmokeColor.X = 0; + smoke.SmokeColor.Y = 255; + smoke.SmokeColor.Z = 0; }); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - smokes.Add(new Vector(@event.X, @event.Y, @event.Z)); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - smokes.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); - return HookResult.Continue; - }); - - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (name != "smokegrenade_projectile") return; - - var grenade = @event.As(); - if (grenade == null || !grenade.IsValid || grenade.OwnerEntity == null || !grenade.OwnerEntity.IsValid || grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; - - var pawn = grenade.OwnerEntity.Value.As(); - if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; - - var player = pawn.Controller.Value.As(); - if (player == null || !player.IsValid) return; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return; - - Server.NextFrame(() => - { - var smoke = @event.As(); - smoke.SmokeColor.X = 0; - smoke.SmokeColor.Y = 255; - smoke.SmokeColor.Z = 0; - }); - }); - - Instance.RegisterListener(() => - { - foreach (Vector smokePos in smokes) - foreach (var player in Utilities.GetPlayers()) - if (Server.TickCount % 17 == 0) - if (player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid && player.PlayerPawn.Value.AbsOrigin != null) - if (SkillUtils.GetDistance(smokePos, player.PlayerPawn.Value.AbsOrigin) <= smokeRadius) - AddHealth(player.PlayerPawn.Value, smokeHeal); - }); + public static void OnTick() + { + foreach (Vector smokePos in smokes) + foreach (var player in Utilities.GetPlayers()) + if (Server.TickCount % 17 == 0) + if (player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid && player.PlayerPawn.Value.AbsOrigin != null) + if (SkillUtils.GetDistance(smokePos, player.PlayerPawn.Value.AbsOrigin) <= smokeRadius) + AddHealth(player.PlayerPawn.Value, smokeHeal); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Hermit.cs b/jRandomSkills - SRC Files/src/player/skills/Hermit.cs index 8774685..307f802 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Hermit.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Hermit.cs @@ -11,41 +11,15 @@ namespace jRandomSkills private const Skills skillName = Skills.Hermit; private static readonly Dictionary dictionary = new() { - { "weapon_glock", 120 }, - { "weapon_usp_silencer", 24 }, - { "weapon_hkp2000", 52 }, - { "weapon_p250", 26 }, - { "weapon_cz75", 12 }, - { "weapon_deagle", 35 }, - { "weapon_fiveseven", 100 }, - { "weapon_elite", 120 }, - { "weapon_tec9", 90 }, - { "weapon_revolver", 8 }, - { "weapon_mac10", 100 }, - { "weapon_mp9", 120 }, - { "weapon_mp7", 120 }, - { "weapon_mp5", 120 }, - { "weapon_mp5sd", 120 }, - { "weapon_ump45", 100 }, - { "weapon_p90", 100 }, - { "weapon_bizon", 120 }, - { "weapon_ak47", 90 }, - { "weapon_m4a1", 90 }, - { "weapon_m4a1_silencer", 80 }, - { "weapon_galilar", 90 }, - { "weapon_famas", 90 }, - { "weapon_aug", 90 }, - { "weapon_sg556", 90 }, - { "weapon_ssg08", 90 }, - { "weapon_awp", 30 }, - { "weapon_scar20", 90 }, - { "weapon_g3sg1", 90 }, - { "weapon_nova", 32 }, - { "weapon_xm1014", 32 }, - { "weapon_sawedoff", 32 }, - { "weapon_mag7", 32 }, - { "weapon_m249", 200 }, - { "weapon_negev", 300 } + { "weapon_glock", 120 }, { "weapon_usp_silencer", 24 }, { "weapon_hkp2000", 52 }, { "weapon_p250", 26 }, + { "weapon_cz75", 12 }, { "weapon_deagle", 35 }, { "weapon_fiveseven", 100 }, { "weapon_elite", 120 }, + { "weapon_tec9", 90 }, { "weapon_revolver", 8 }, { "weapon_mac10", 100 }, { "weapon_mp9", 120 }, + { "weapon_mp7", 120 }, { "weapon_mp5", 120 }, { "weapon_mp5sd", 120 }, { "weapon_ump45", 100 }, + { "weapon_p90", 100 }, { "weapon_bizon", 120 }, { "weapon_ak47", 90 }, { "weapon_m4a1", 90 }, + { "weapon_m4a1_silencer", 80 }, { "weapon_galilar", 90 }, { "weapon_famas", 90 }, { "weapon_aug", 90 }, + { "weapon_sg556", 90 }, { "weapon_ssg08", 90 }, { "weapon_awp", 30 }, { "weapon_scar20", 90 }, + { "weapon_g3sg1", 90 }, { "weapon_nova", 32 }, { "weapon_xm1014", 32 }, { "weapon_sawedoff", 32 }, + { "weapon_mag7", 32 }, { "weapon_m249", 200 }, { "weapon_negev", 300 } }; private static readonly Dictionary maxReserveAmmo = dictionary; @@ -54,31 +28,29 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - if (!Instance.IsPlayerValid(attacker)) return HookResult.Continue; + } - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (attackerInfo?.Skill != skillName) return HookResult.Continue; + public static void PlayerDeath(EventPlayerDeath @event) + { + var attacker = @event.Attacker; + if (!Instance.IsPlayerValid(attacker)) return; - var pawn = attacker!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return HookResult.Continue; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (attackerInfo?.Skill != skillName) return; - var weapon = pawn.WeaponServices.ActiveWeapon.Value; - if (weapon == null || !weapon.IsValid || weapon.VData == null) return HookResult.Continue; + var pawn = attacker!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return; - var maxReserveAmmoClip = maxReserveAmmo.TryGetValue(weapon.DesignerName, out var reserve) ? reserve : 100; - weapon.Clip1 = weapon.VData.MaxClip1; - weapon.ReserveAmmo.Fill(maxReserveAmmoClip); - - Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_iClip1"); - Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_pReserveAmmo"); - SkillUtils.AddHealth(pawn, healthToAdd); + var weapon = pawn.WeaponServices.ActiveWeapon.Value; + if (weapon == null || !weapon.IsValid || weapon.VData == null) return; - return HookResult.Continue; - }); + var maxReserveAmmoClip = maxReserveAmmo.TryGetValue(weapon.DesignerName, out var reserve) ? reserve : 100; + weapon.Clip1 = weapon.VData.MaxClip1; + weapon.ReserveAmmo.Fill(maxReserveAmmoClip); + + Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_iClip1"); + Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_pReserveAmmo"); + SkillUtils.AddHealth(pawn, healthToAdd); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ded678", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int healthToAdd = 25) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs index e14d7a8..8bd53c0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs @@ -16,44 +16,28 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void OnEntitySpawned(CEntityInstance @event) + { + var name = @event.DesignerName; + if (!name.EndsWith("hegrenade_projectile")) + return; + + Server.NextFrame(() => { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + var hegrenade = @event.As(); + if (hegrenade == null || !hegrenade.IsValid) return; - return HookResult.Continue; - }); + var playerPawn = hegrenade.Thrower.Value; + if (playerPawn == null || !playerPawn.IsValid) return; - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (!name.EndsWith("hegrenade_projectile")) - return; + var player = Utilities.GetPlayers().FirstOrDefault(p => p.PlayerPawn.Index == playerPawn.Index); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - Server.NextFrame(() => - { - var hegrenade = @event.As(); - if (hegrenade == null || !hegrenade.IsValid) return; - - var playerPawn = hegrenade.Thrower.Value; - if (playerPawn == null || !playerPawn.IsValid) return; - - var player = Utilities.GetPlayers().FirstOrDefault(p => p.PlayerPawn.Index == playerPawn.Index); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return; - - hegrenade.Damage *= damageMultiplier; - hegrenade.DmgRadius *= damageRadiusMultiplier; - }); + hegrenade.Damage *= damageMultiplier; + hegrenade.DmgRadius *= damageRadiusMultiplier; }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs index 02c7f93..39956b9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs @@ -16,25 +16,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - string model = GetEnemyModel(player); - SetPlayerModel(player, model); - } - } - }); - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs b/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs index 12d1781..805b9dd 100644 --- a/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs +++ b/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs @@ -12,48 +12,38 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; + public static void WeaponFire(EventWeaponFire @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + ApplyInfiniteAmmo(player!); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + } - if (playerInfo?.Skill == skillName) - ApplyInfiniteAmmo(player!); + public static void GrenadeThrown(EventGrenadeThrown @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - return HookResult.Continue; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + player!.GiveNamedItem($"weapon_{@event.Weapon}"); - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; + } - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + public static void WeaponReload(EventWeaponReload @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill == skillName) - player!.GiveNamedItem($"weapon_{@event.Weapon}"); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill == skillName) - ApplyInfiniteAmmo(player!); - - return HookResult.Continue; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + ApplyInfiniteAmmo(player!); } private static void ApplyInfiniteAmmo(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs index a56247f..87c380e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs @@ -18,39 +18,20 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var beams in stepBeams.Values) - foreach (var beam in beams) - if (beam != null && beam.IsValid) - beam.Remove(); - stepBeams.Clear(); - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() + { + foreach (var beams in stepBeams.Values) + foreach (var beam in beams) + if (beam != null && beam.IsValid) + beam.Remove(); + stepBeams.Clear(); + Instance.RemoveListener(CheckTransmit); + exists = false; + } + + public static void OnTick() { if (Server.TickCount % 8 != 0) return; foreach (var step in stepBeams.ToList()) diff --git a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs index 7c6cef3..9c2628c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs @@ -15,30 +15,31 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in jammedPlayers) + SetCrosshair(player, true); + jammedPlayers.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in jammedPlayers) - SetCrosshair(player, true); - jammedPlayers.Clear(); - return HookResult.Continue; - }); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -85,24 +86,21 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("jammer") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("jammer_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { SetCrosshair(player, true); jammedPlayers.Remove(player); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#42f5a7", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Jester.cs b/jRandomSkills - SRC Files/src/player/skills/Jester.cs new file mode 100644 index 0000000..f4294b3 --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/Jester.cs @@ -0,0 +1,123 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using jRandomSkills.src.player; +using jRandomSkills.src.utils; +using System.Drawing; +using static jRandomSkills.jRandomSkills; + +namespace jRandomSkills +{ + public class Jester : ISkill + { + private const Skills skillName = Skills.Jester; + private static bool jesterMode = false; + private static bool jesterStarted = false; + private static readonly float minTime = Config.GetValue(skillName, "minTime"); + private static readonly float maxTime = Config.GetValue(skillName, "maxTime"); + + public static void LoadSkill() + { + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } + + public static void NewRound() + { + jesterStarted = false; + } + + public static void PlayerHurt(EventPlayerHurt @event) + { + if (!jesterMode) return; + var attacker = @event.Attacker; + var victim = @event.Userid; + int hitgroup = @event.Hitgroup; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + + if (attackerInfo?.Skill == skillName || victimInfo?.Skill == skillName) + RestoreHealth(victim!, @event.DmgHealth); + } + + private static void RestoreHealth(CCSPlayerController victim, float damage) + { + var playerPawn = victim.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid) return; + var newHealth = playerPawn.Health + damage; + + if (newHealth > 100) + newHealth = 100; + + playerPawn.Health = (int)newHealth; + } + + public static void EnableSkill(CCSPlayerController _) + { + if (!jesterStarted) + { + float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; + Instance.AddTimer(wait, ChangeMode); + jesterStarted = true; + } + } + + private static void ChangeMode() + { + if (Instance.SkillPlayer.Any(p => p.Skill == skillName)) + { + jesterMode = !jesterMode; + foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot && p.PawnIsAlive)) + { + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + { + SetPlayerColor(player.PlayerPawn.Value); + player.ExecuteClientCommand("play sounds/weapons/taser/taser_charge_ready"); + } + } + float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; + Instance.AddTimer(wait, ChangeMode); + } + } + + private static void SetPlayerColor(CCSPlayerPawn pawn) + { + var color = jesterMode ? Color.FromArgb(255, 128, 0, 128) : Color.FromArgb(255, 255, 255, 255); + pawn.Render = color; + Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender"); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot && p.PawnIsAlive)) + { + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + UpdateHUD(player); + } + } + + private static void UpdateHUD(CCSPlayerController player) + { + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); + if (skillData == null) return; + + string infoLine = $"{Localization.GetTranslation("your_skill")}:
"; + string skillLine = $"{skillData.Name}
"; + string remainingLine = $"{Localization.GetTranslation("jester_mode")}: {Localization.GetTranslation(jesterMode ? "jester_on" : "jester_off")}
"; + + var hudContent = infoLine + skillLine + remainingLine; + player.PrintToCenterHtml(hudContent); + } + + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8f108f", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float minTime = 10f, float maxTime = 25f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) + { + public float MinTime { get; set; } = minTime; + public float MaxTime { get; set; } = maxTime; + } + } +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs index 6dbd7ae..e5854e1 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs @@ -10,54 +10,50 @@ namespace jRandomSkills public class JumpBan : ISkill { private const Skills skillName = Skills.JumpBan; - private static readonly Dictionary bannedPlayers = []; + public static readonly Dictionary bannedPlayers = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - bannedPlayers.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return HookResult.Continue; - if (!bannedPlayers.TryGetValue(player.PlayerPawn.Value, out _)) return HookResult.Continue; - bannedPlayers[player.PlayerPawn.Value] = Server.TickCount + 10; - return HookResult.Stop; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() + { + bannedPlayers.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void PlayerJump(EventPlayerJump @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + if (!bannedPlayers.TryGetValue(player.PlayerPawn.Value, out _)) return; + bannedPlayers[player.PlayerPawn.Value] = Server.TickCount + 10; + } + + public static void OnTick() { foreach (var item in bannedPlayers) { var pawn = item.Key; var time = item.Value; if (time > Server.TickCount) - pawn.AbsVelocity.Z = -100; + if (pawn != null && pawn.IsValid) + pawn.AbsVelocity.Z = -100; + } + + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) + { + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); } } @@ -94,24 +90,21 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("jumpban") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("jumpban_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; bannedPlayers.Remove(player.PlayerPawn.Value); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b01e5d", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs b/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs index ba58cd7..f7fd383 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs @@ -13,17 +13,15 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - SkillUtils.AddHealth(player.PlayerPawn.Value, addHealth); - return HookResult.Continue; - }); + public static void PlayerJump(EventPlayerJump @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + SkillUtils.AddHealth(player.PlayerPawn.Value, addHealth); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a86eff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int healthToAdd = 3) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs b/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs index de64fa1..b85ec6d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs @@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; +using Microsoft.Extensions.Logging; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -15,37 +16,19 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + public static void PlayerBlind(EventPlayerBlind @event) + { + var player = @event.Userid; + var attacker = @event.Attacker; + if (!Instance.IsPlayerValid(player) || !Instance.IsPlayerValid(attacker)) return; - return HookResult.Continue; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - var attacker = @event.Attacker; - if (!Instance.IsPlayerValid(player) || !Instance.IsPlayerValid(attacker)) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - if (attackerInfo?.Skill == skillName && playerInfo?.Skill != Skills.AntyFlash && player!.PlayerPawn.Value!.FlashDuration >= flashDuration) - player?.PlayerPawn?.Value?.CommitSuicide(false, true); - - return HookResult.Continue; - }); + if (attackerInfo?.Skill == skillName && playerInfo?.Skill != Skills.AntyFlash && player!.PlayerPawn.Value!.FlashDuration >= flashDuration) + player?.PlayerPawn?.Value?.CommitSuicide(false, true); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs b/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs index c7a8be6..1d3a3ce 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs @@ -13,23 +13,29 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + + HashSet<(string, string)> menuItems = enemies.Select(e => ($"{e.PlayerName} : {e.PawnHealth} HP", e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -65,18 +71,14 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("lifeswap") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("lifeswap_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => ($"{e.PlayerName} : {e.PawnHealth} HP", e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } private static void SwapHealth(CCSPlayerController player, CCSPlayerController enemy) @@ -92,6 +94,11 @@ namespace jRandomSkills Utilities.SetStateChanged(enemyPawn, "CBaseEntity", "m_iHealth"); } + public static void DisableSkill(CCSPlayerController player) + { + SkillUtils.CloseMenu(player); + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a3651a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) { } diff --git a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs index c9bf356..c4a350d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs @@ -1,5 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using CS2TraceRay.Class; @@ -16,52 +15,51 @@ namespace jRandomSkills private const Skills skillName = Skills.LongKnife; private static readonly float maxDistance = Config.GetValue(skillName, "maxDistance"); - public unsafe static void LoadSkill() + public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public unsafe static void WeaponFire(EventWeaponFire @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; + + var pawn = player!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.WeaponServices == null) return; + + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_knife") return; + + Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); + Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * maxDistance; + + Ray ray = new(Vector3.Zero); + CTraceFilter filter = new(pawn.Index, pawn.Index) { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + m_nObjectSetMask = 0xf, + m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, + m_nInteractsWith = pawn.GetInteractsWith(), + m_nInteractsExclude = 0, + m_nBits = 11, + m_bIterateEntities = true, + m_bHitTriggers = false, + m_nInteractsAs = 0x40000 + }; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; + filter.m_nHierarchyIds[0] = pawn.GetHierarchyId(); + filter.m_nHierarchyIds[1] = 0; + CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); - var pawn = player!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.WeaponServices == null) return HookResult.Continue; + if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) + return; - var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; - if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_knife") return HookResult.Continue; - - Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * maxDistance; - - Ray ray = new(Vector3.Zero); - CTraceFilter filter = new(pawn.Index, pawn.Index) - { - m_nObjectSetMask = 0xf, - m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, - m_nInteractsWith = pawn.GetInteractsWith(), - m_nInteractsExclude = 0, - m_nBits = 11, - m_bIterateEntities = true, - m_bHitTriggers = false, - m_nInteractsAs = 0x40000 - }; - - filter.m_nHierarchyIds[0] = pawn.GetHierarchyId(); - filter.m_nHierarchyIds[1] = 0; - CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); - - if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) - return HookResult.Continue; - - if (target.Handle == player.Handle || target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid || trace.Distance() <= 70) return HookResult.Continue; - target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker"); - SkillUtils.TakeHealth(target.PlayerPawn.Value, Instance.Random.Next(21, 34)); - return HookResult.Continue; - }); + if (target.Handle == player.Handle || target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid || trace.Distance() <= 70) return; + target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker"); + SkillUtils.TakeHealth(target.PlayerPawn.Value, Instance.Random.Next(21, 34)); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#c9f8ff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float maxDistance = 4096f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs index 3caf629..51921d3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs @@ -1,5 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using CS2TraceRay.Class; @@ -16,67 +15,50 @@ namespace jRandomSkills private const Skills skillName = Skills.LongZeus; private static readonly float maxDistance = Config.GetValue(skillName, "maxDistance"); - public unsafe static void LoadSkill() + public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public unsafe static void WeaponFire(EventWeaponFire @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; + + var pawn = player!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.WeaponServices == null) return; + + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_taser") return; + + Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); + Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * maxDistance; + + Ray ray = new(Vector3.Zero); + CTraceFilter filter = new(pawn.Index, pawn.Index) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + m_nObjectSetMask = 0xf, + m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, + m_nInteractsWith = pawn.GetInteractsWith(), + m_nInteractsExclude = 0, + m_nBits = 11, + m_bIterateEntities = true, + m_bHitTriggers = false, + m_nInteractsAs = 0x40000 + }; - return HookResult.Continue; - }); + filter.m_nHierarchyIds[0] = pawn.GetHierarchyId(); + filter.m_nHierarchyIds[1] = 0; + CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) + return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var pawn = player!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.WeaponServices == null) return HookResult.Continue; - - var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; - if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_taser") return HookResult.Continue; - - Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * maxDistance; - - Ray ray = new(Vector3.Zero); - CTraceFilter filter = new(pawn.Index, pawn.Index) - { - m_nObjectSetMask = 0xf, - m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, - m_nInteractsWith = pawn.GetInteractsWith(), - m_nInteractsExclude = 0, - m_nBits = 11, - m_bIterateEntities = true, - m_bHitTriggers = false, - m_nInteractsAs = 0x40000 - }; - - filter.m_nHierarchyIds[0] = pawn.GetHierarchyId(); - filter.m_nHierarchyIds[1] = 0; - CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); - - if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) - return HookResult.Continue; - - if (target.Handle == player.Handle) return HookResult.Continue; - SkillUtils.TakeHealth(target.PlayerPawn.Value, 9999); - return HookResult.Continue; - }); + if (target.Handle == player.Handle) return; + SkillUtils.TakeHealth(target.PlayerPawn.Value, 9999); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs index 4103a0a..89d344f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs @@ -15,30 +15,30 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + playersFOV.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in playersFOV.Keys) - DisableSkill(player); - return HookResult.Continue; - }); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -79,18 +79,14 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("magnifier") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("magnifier_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) @@ -101,6 +97,7 @@ namespace jRandomSkills Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); } playersFOV.Remove(player); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9ba882", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, uint customFOV = 50) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Medic.cs b/jRandomSkills - SRC Files/src/player/skills/Medic.cs index f99229c..f2dce9b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Medic.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Medic.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -19,49 +18,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs b/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs index ec6f257..07a6eec 100644 --- a/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs @@ -13,23 +13,29 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + + HashSet<(string, string)> menuItems = enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account)}$", e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -65,19 +71,14 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("moneyswap") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("moneyswap_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - if (enemy != null && enemy.IsValid && enemy.InGameMoneyServices != null) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}: ${enemy.InGameMoneyServices.Account}"); + HashSet<(string, string)> menuItems = enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account)}$", e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } private static void SwapMoney(CCSPlayerController player, CCSPlayerController enemy) @@ -96,6 +97,11 @@ namespace jRandomSkills Utilities.SetStateChanged(enemy, "CCSPlayerController", "m_pInGameMoneyServices"); } + public static void DisableSkill(CCSPlayerController player) + { + SkillUtils.CloseMenu(player); + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#52f54c", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) { } diff --git a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs index fd09fdc..ea7f5d4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs @@ -1,7 +1,9 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; +using Microsoft.Extensions.Logging; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -15,18 +17,16 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!IsDeadPlayerValid(player)) return HookResult.Continue; + } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill == skillName) - SpawnExplosion(player!); + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (!IsDeadPlayerValid(player)) return; - return HookResult.Continue; - }); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) + SpawnExplosion(player!); } private static void SpawnExplosion(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs index 68fd922..0529f56 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs @@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -12,7 +11,6 @@ namespace jRandomSkills public class Ninja : ISkill { private const Skills skillName = Skills.Ninja; - private static bool exists = false; private static readonly float idlePercentInvisibility = Config.GetValue(skillName, "idlePercentInvisibility"); private static readonly float duckPercentInvisibility = Config.GetValue(skillName, "duckPercentInvisibility"); private static readonly float knifePercentInvisibility = Config.GetValue(skillName, "knifePercentInvisibility"); @@ -22,83 +20,31 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - DisableSkill(player); - if (!Instance.IsPlayerValid(player)) continue; - var playerPawn = player.PlayerPawn?.Value; + public static void NewRound() + { + invisibilityChanged.Clear(); + } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + public static void WeaponEquip(EventItemEquip @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - return HookResult.Continue; - }); + if (playerInfo?.Skill != skillName) return; + UpdateNinja(player); + } - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - DisableSkill(player); - invisibilityChanged.Clear(); - return HookResult.Continue; - }); + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill != skillName) return HookResult.Continue; - UpdateNinja(player); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill != skillName) return HookResult.Continue; - UpdateNinja(player); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - DisableSkill(player); - } - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + if (playerInfo?.Skill != skillName) return; + UpdateNinja(player); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -113,7 +59,7 @@ namespace jRandomSkills } } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { @@ -123,11 +69,9 @@ namespace jRandomSkills } } - public static void EnableSkill(CCSPlayerController player) + public static void EnableSkill(CCSPlayerController _) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; + Event.enableTransmit = true; } public static void DisableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/NoNades.cs b/jRandomSkills - SRC Files/src/player/skills/NoNades.cs index 2602f2d..98a56ba 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoNades.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoNades.cs @@ -12,25 +12,20 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var damage = @event.DmgHealth; - var player = @event.Userid; - var weapon = @event.Weapon; + public static void PlayerHurt(EventPlayerHurt @event) + { + var damage = @event.DmgHealth; + var player = @event.Userid; + var weapon = @event.Weapon; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - if (weapon == "hegrenade" || weapon == "inferno") - { - SkillUtils.AddHealth(player!.PlayerPawn.Value, damage); - damage = 0; - return HookResult.Stop; - } - return HookResult.Continue; - }); + if (weapon == "hegrenade" || weapon == "inferno") + SkillUtils.AddHealth(player!.PlayerPawn.Value, damage); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a38c1a", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs index 70b6d7f..f7520c0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -14,43 +13,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - Server.ExecuteCommand("weapon_accuracy_nospread 0"); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - public static void EnableSkill(CCSPlayerController player) - { - Server.ExecuteCommand("weapon_accuracy_nospread 1"); - } - - public static void DisableSkill(CCSPlayerController player) + public static void NewRound() { Server.ExecuteCommand("weapon_accuracy_nospread 0"); } - private static void OnTick() + public static void EnableSkill(CCSPlayerController _) + { + Server.ExecuteCommand("weapon_accuracy_nospread 1"); + } + + public static void DisableSkill(CCSPlayerController _) + { + Server.ExecuteCommand("weapon_accuracy_nospread 0"); + } + + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs index 6671767..6b71602 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,51 +17,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/None.cs b/jRandomSkills - SRC Files/src/player/skills/None.cs index 6769331..16995fe 100644 --- a/jRandomSkills - SRC Files/src/player/skills/None.cs +++ b/jRandomSkills - SRC Files/src/player/skills/None.cs @@ -12,11 +12,8 @@ namespace jRandomSkills SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); } - public class SkillConfig : Config.DefaultSkillInfo + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FFFFFF", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) { - public SkillConfig(Skills skill = skillName, bool active = true, string color = "#FFFFFF", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : base(skill, active, color, onlyTeam, needsTeammates) - { - } } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/OneShot.cs b/jRandomSkills - SRC Files/src/player/skills/OneShot.cs index ad84b18..a8c39b4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/OneShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/OneShot.cs @@ -1,5 +1,4 @@ using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,35 +13,33 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new CCSPlayerPawn(param2.Attacker.Value.Handle); CCSPlayerPawn victimPawn = new CCSPlayerPawn(param.Handle); if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return HookResult.Continue; + return; if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); CCSPlayerController victim = victimPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (playerInfo == null) return HookResult.Continue; + if (playerInfo == null) return; if (playerInfo.Skill == skillName && attacker.PawnIsAlive) param2.Damage = 1000f; - return HookResult.Changed; } public class SkillConfig : Config.DefaultSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs b/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs index beee8e9..7009f5b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs +++ b/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs @@ -13,23 +13,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - int damage = @event.DmgHealth; - var hitgroup = (HitGroup_t)@event.Hitgroup; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + int damage = @event.DmgHealth; + var hitgroup = (HitGroup_t)@event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return HookResult.Continue; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo == null || victimInfo.Skill != skillName) return; - HitGroup_t[] disabledHitbox = [HitGroup_t.HITGROUP_LEFTARM, HitGroup_t.HITGROUP_RIGHTARM, HitGroup_t.HITGROUP_LEFTLEG, HitGroup_t.HITGROUP_RIGHTLEG]; - if (hitgroup != HitGroup_t.HITGROUP_HEAD) - RestoreHealth(victim!, damage); - return HookResult.Stop; - }); + HitGroup_t[] disabledHitbox = [HitGroup_t.HITGROUP_LEFTARM, HitGroup_t.HITGROUP_RIGHTARM, HitGroup_t.HITGROUP_LEFTLEG, HitGroup_t.HITGROUP_RIGHTLEG]; + if (hitgroup != HitGroup_t.HITGROUP_HEAD) + RestoreHealth(victim!, damage); } private static void RestoreHealth(CCSPlayerController victim, float damage) diff --git a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs index 28c686c..1050cbb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -21,19 +20,17 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - Instance.RegisterListener(() => + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - GiveAdditionalJump(player); - } - } - }); + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + GiveAdditionalJump(player); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs index 11c7e12..22a201e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,42 +13,23 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) { - Instance.AddTimer(0.1f, () => + if (Instance.Random.NextDouble() <= playerInfo.SkillChance) { - foreach (var player in Utilities.GetPlayers()) - { - if (!IsDeadPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - { - player.Respawn(); - Instance.AddTimer(.2f, () => player.Respawn()); - SkillUtils.PrintToChat(player, Localization.GetTranslation("phoenix_respawn"), false); ; - } + player.Respawn(); + Instance.AddTimer(.2f, () => player.Respawn()); + SkillUtils.PrintToChat(player, Localization.GetTranslation("phoenix_respawn"), false); ; } - - return HookResult.Continue; - }); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Pilot.cs b/jRandomSkills - SRC Files/src/player/skills/Pilot.cs index 73c6b44..3fc9159 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Pilot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Pilot.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,42 +16,21 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); + } - return HookResult.Continue; - }); + public static void NewRound() + { + PlayerPilotInfo.Clear(); + } - Instance.RegisterEventHandler((@event, info) => + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - PlayerPilotInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - HandlePilot(player); - } - }); + HandlePilot(player); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Planter.cs b/jRandomSkills - SRC Files/src/player/skills/Planter.cs index 0c11854..8f3c318 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Planter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Planter.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -16,33 +15,19 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, @info) => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - Schema.SetSchemaValue(player!.PlayerPawn!.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", false); - } - return HookResult.Continue; - }); + public static void BombPlanted(EventBombPlanted @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + extraC4BlowTime); - - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null) + Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + extraC4BlowTime); } public static void DisableSkill(CCSPlayerController player) @@ -51,7 +36,7 @@ namespace jRandomSkills Schema.SetSchemaValue(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", false); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Poison.cs b/jRandomSkills - SRC Files/src/player/skills/Poison.cs index 8643db5..c67cb7c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Poison.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Poison.cs @@ -17,41 +17,36 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach (var player in poisonedPlayers) - DisableSkill(player); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() { - if (Server.TickCount % (int)(64 * cooldown) != 0) return; - foreach (var player in poisonedPlayers) + poisonedPlayers.Clear(); + } + + public static void OnTick() + { + if (Server.TickCount % (int)(64 * cooldown) == 0) { - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) continue; - SkillUtils.TakeHealth(pawn, healthToDamage); + foreach (var player in poisonedPlayers) + { + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + SkillUtils.TakeHealth(pawn, healthToDamage); + } + } + + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) + { + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); } } @@ -88,23 +83,20 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("poison") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("poison_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { poisonedPlayers.Remove(player); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#902eff", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float cooldown = 1, int damage = 1) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs index 68cbc38..074c795 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs @@ -20,38 +20,38 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + bannedPlayers.Clear(); + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); + } + + public static void WeaponEquip(EventItemEquip @event) + { + var player = @event.Userid; + var weapon = @event.Item; + if (player == null || !player.IsValid) return; + if (!bannedPlayers.Contains(player.SteamID) || !disabledWeapons.Contains(weapon)) return; + player.ExecuteClientCommand("slot3"); + } + + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); - Instance.RegisterEventHandler((@event, info) => - { - bannedPlayers.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - var weapon = @event.Item; - if (player == null || !player.IsValid) return HookResult.Continue; - if (!bannedPlayers.Contains(player.SteamID) || !disabledWeapons.Contains(weapon)) return HookResult.Continue; - player.ExecuteClientCommand("slot3"); - return HookResult.Stop; - }); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.UpdateMenu(player, menuItems); + } } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -98,23 +98,20 @@ namespace jRandomSkills if (playerInfo == null) return; playerInfo.SkillChance = 0; - SkillUtils.PrintToChat(player, Localization.GetTranslation("primaryban") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("primaryban_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { - foreach (var enemy in enemies) - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}"); + HashSet<(string, string)> menuItems = enemies.Select(e => (e.PlayerName, e.Index.ToString())).ToHashSet(); + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) { bannedPlayers.Remove(player.SteamID); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ffc061", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs b/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs index 2e72069..9f4a9c7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs @@ -13,23 +13,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - int damage = @event.DmgHealth; - var hitgroup = (HitGroup_t)@event.Hitgroup; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + int damage = @event.DmgHealth; + var hitgroup = (HitGroup_t)@event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return HookResult.Continue; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo == null || victimInfo.Skill != skillName) return; - HitGroup_t[] disabledHitbox = [HitGroup_t.HITGROUP_LEFTARM, HitGroup_t.HITGROUP_RIGHTARM, HitGroup_t.HITGROUP_LEFTLEG, HitGroup_t.HITGROUP_RIGHTLEG]; - if (disabledHitbox.Contains(hitgroup)) - RestoreHealth(victim!, damage); - return HookResult.Stop; - }); + HitGroup_t[] disabledHitbox = [HitGroup_t.HITGROUP_LEFTARM, HitGroup_t.HITGROUP_RIGHTARM, HitGroup_t.HITGROUP_LEFTLEG, HitGroup_t.HITGROUP_RIGHTLEG]; + if (disabledHitbox.Contains(hitgroup)) + RestoreHealth(victim!, damage); } private static void RestoreHealth(CCSPlayerController victim, float damage) diff --git a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs index 4365af1..a5a11b2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -20,90 +19,70 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + bombLocation = null; + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + SkillPlayerInfo.Remove(pawn); + } + + public static void BombPlanted(EventBombPlanted _) + { + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null) + bombLocation = plantedBomb.AbsOrigin; + } + + public static void OnTick() + { + if (bombLocation == null) return; + foreach (var skillInfo in SkillPlayerInfo) { - Instance.AddTimer(0.1f, () => + var player = skillInfo.Key; + var info = skillInfo.Value; + + if (player.AbsOrigin == null || SkillUtils.GetDistance(player.AbsOrigin, bombLocation) > maxDefusingRange) { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - bombLocation = null; - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(pawn); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb != null) - bombLocation = plantedBomb.AbsOrigin; - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - if (bombLocation == null) return; - foreach (var skillInfo in SkillPlayerInfo) - { - var player = skillInfo.Key; - var info = skillInfo.Value; - - if (player.AbsOrigin == null || SkillUtils.GetDistance(player.AbsOrigin, bombLocation) > maxDefusingRange) - { - info.Defusing = false; - info.DefusingTime = defusingTime; - continue; - } - - if (!info.Defusing) - player.EmitSound("c4.disarmstart"); - info.Defusing = true; - info.DefusingTime -= (1f / tickRate); - - if (info.DefusingTime <= 0) - { - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb != null) - { - plantedBomb.Remove(); - SkillUtils.TerminateRound(CsTeam.CounterTerrorist); - } - - SkillPlayerInfo.Clear(); - } - - var playerController = player.Controller.Value; - if (playerController == null || !player.Controller.IsValid) return; - UpdateHUD(playerController.As(), info); + info.Defusing = false; + info.DefusingTime = defusingTime; + continue; } - }); + + if (!info.Defusing) + player.EmitSound("c4.disarmstart"); + info.Defusing = true; + info.DefusingTime -= (1f / tickRate); + + if (info.DefusingTime <= 0) + { + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null) + { + plantedBomb.Remove(); + SkillUtils.TerminateRound(CsTeam.CounterTerrorist); + } + + SkillPlayerInfo.Clear(); + } + + var playerController = player.Controller.Value; + if (playerController == null || !player.Controller.IsValid) return; + UpdateHUD(playerController.As(), info); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Push.cs b/jRandomSkills - SRC Files/src/player/skills/Push.cs index 37ed4ac..db05d9d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Push.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Push.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -16,42 +15,23 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + } - Instance.RegisterEventHandler((@event, info) => + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) + return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + + if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event!.Attacker; - var victim = @event!.Userid; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) - return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) - { - if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - PushEnemy(victim, attacker!.PlayerPawn.Value!.EyeAngles); - } - - return HookResult.Continue; - }); + if (Instance.Random.NextDouble() <= playerInfo.SkillChance) + PushEnemy(victim, attacker!.PlayerPawn.Value!.EyeAngles); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs index 4cc479d..0c54dd0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs @@ -15,36 +15,19 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + int damage = @event.DmgHealth; + string weapon = @event.Weapon; - return HookResult.Continue; - }); + if (weapon != "inferno" || !Instance.IsPlayerValid(victim)) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo == null || victimInfo.Skill != skillName) return ; - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - int damage = @event.DmgHealth; - string weapon = @event.Weapon; - - if (weapon != "inferno" || !Instance.IsPlayerValid(victim)) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return HookResult.Continue; - - RestoreHealth(victim!, damage * regenerationMultiplier); - return HookResult.Stop; - }); + RestoreHealth(victim!, damage * regenerationMultiplier); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs index bf73ffa..dbc44d7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -14,10 +13,9 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { diff --git a/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs b/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs index c42689b..954d159 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -14,10 +13,9 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - Instance.RegisterListener(CheckRadarowiec); } - private static void CheckRadarowiec() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Rambo.cs b/jRandomSkills - SRC Files/src/player/skills/Rambo.cs index e912568..8ed1a7f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Rambo.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Rambo.cs @@ -15,21 +15,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs index 210cadd..99b797c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs @@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; using System.Collections.Immutable; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -26,51 +25,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs index 08e5423..739f96b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs @@ -16,51 +16,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - var weapon = @event.Item; - if (player == null || !player.IsValid) return HookResult.Continue; - if (!zombies.Contains(player) || weapon == "c4") return HookResult.Continue; - player.ExecuteClientCommand("slot3"); - return HookResult.Stop; - }); - - Instance.RegisterEventHandler((@event, info) => - { - foreach(var player in zombies) - DisableSkill(player); - zombies.Clear(); - return HookResult.Stop; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.Contains(player)) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var pawn = player.PlayerPawn.Value; - if (pawn.AbsOrigin == null) return HookResult.Continue; - Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); - QAngle deadRotation = new(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z); - - player.Respawn(); - Instance.AddTimer(.2f, () => { - player.Respawn(); - zombies.Add(player); - SetPlayerColor(pawn, false); - SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth); - pawn.Teleport(deadPosition, deadRotation); - player.ExecuteClientCommand("slot3"); - Instance.AddTimer(1, () => player.ExecuteClientCommand("slot3")); - }); - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -75,6 +30,47 @@ namespace jRandomSkills SetPlayerColor(player.PlayerPawn.Value, true); } + public static void WeaponEquip(EventItemEquip @event) + { + var player = @event.Userid; + var weapon = @event.Item; + if (player == null || !player.IsValid) return; + if (!zombies.Contains(player) || weapon == "c4") return; + player.ExecuteClientCommand("slot3"); + } + + public static void NewRound() + { + foreach (var player in zombies) + DisableSkill(player); + zombies.Clear(); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.Contains(player)) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + + var pawn = player.PlayerPawn.Value; + if (pawn.AbsOrigin == null) return; + Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); + QAngle deadRotation = new(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z); + + player.Respawn(); + Instance.AddTimer(.2f, () => { + player.Respawn(); + zombies.Add(player); + SetPlayerColor(pawn, false); + SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth); + pawn.Teleport(deadPosition, deadRotation); + player.ExecuteClientCommand("slot3"); + Instance.AddTimer(1, () => player.ExecuteClientCommand("slot3")); + }); + } + private static void SetPlayerColor(CCSPlayerPawn pawn, bool normal) { var color = normal ? Color.FromArgb(255, 255, 255, 255) : Color.FromArgb(255, 255, 0, 0); diff --git a/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs b/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs index 095f878..faabb2e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,68 +16,38 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } + } - return HookResult.Continue; - }); + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + int damage = @event.DmgHealth; - Instance.RegisterListener(() => + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; + if (SkillPlayerInfo.TryGetValue(victim!.SteamID, out var skillInfo)) { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - int damage = @event.DmgHealth; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return HookResult.Continue; - if (SkillPlayerInfo.TryGetValue(victim!.SteamID, out var skillInfo)) - { - if (!victim.IsValid || !victim.PawnIsAlive || !skillInfo.CanUse) return HookResult.Continue; - skillInfo.CanUse = false; - skillInfo.Cooldown = DateTime.Now; - RestoreHealth(victim, damage); - return HookResult.Stop; - } - - return HookResult.Continue; - }); + if (!victim.IsValid || !victim.PawnIsAlive || !skillInfo.CanUse) return; + skillInfo.CanUse = false; + skillInfo.Cooldown = DateTime.Now; + RestoreHealth(victim, damage); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs b/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs index d0ffde9..7710f44 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs @@ -1,5 +1,4 @@ using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using static jRandomSkills.jRandomSkills; @@ -15,10 +14,9 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void OnTick() { if (Server.TickCount % (int)(64 * cooldown) != 0) return; foreach (var player in Utilities.GetPlayers()) diff --git a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs index 8ae04fa..fa66000 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs @@ -1,11 +1,9 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -19,51 +17,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); - - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) @@ -144,27 +113,26 @@ namespace jRandomSkills replica.AcceptInput("EnableCollision"); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); - if (string.IsNullOrEmpty(param.Entity.Name)) return HookResult.Continue; - if (!param.Entity.Name.StartsWith("Replica_")) return HookResult.Continue; + if (string.IsNullOrEmpty(param.Entity.Name)) return; + if (!param.Entity.Name.StartsWith("Replica_")) return; var replica = param.As(); - if (replica == null || !replica.IsValid) return HookResult.Continue; + if (replica == null || !replica.IsValid) return; replica.EmitSound("GlassBottle.BulletImpact", volume: 1f); var attackerTeam = attackerPawn.TeamNum; var replicaTeam = replica.Globalname.EndsWith("CT") ? 3 : 2; SkillUtils.TakeHealth(attackerPawn, attackerTeam != replicaTeam ? 15 : 5); replica.Remove(); - return HookResult.Continue; } public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/Retreat.cs b/jRandomSkills - SRC Files/src/player/skills/Retreat.cs index dbde6cd..e88d1fb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Retreat.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Retreat.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,51 +16,22 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs index 9f3cbd9..1535400 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs @@ -14,32 +14,30 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - playersToSender.Clear(); - return HookResult.Continue; - }); + public static void NewRound() + { + playersToSender.Clear(); + } - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - int damage = @event.DmgHealth; + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + int damage = @event.DmgHealth; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (attackerInfo == null || attackerInfo.Skill != skillName) return HookResult.Continue; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (attackerInfo == null || attackerInfo.Skill != skillName) return; - if (playersToSender.TryGetValue(victim!.Handle, out _)) - return HookResult.Continue; + if (playersToSender.TryGetValue(victim!.Handle, out _)) + return; - var spawn = GetSpawnVector(victim); - if (spawn == null) return HookResult.Continue; - victim!.PlayerPawn!.Value!.Teleport(spawn); - playersToSender.Add(victim.Handle); - return HookResult.Stop; - }); + var spawn = GetSpawnVector(victim); + if (spawn == null) return; + victim!.PlayerPawn!.Value!.Teleport(spawn); + playersToSender.Add(victim.Handle); } public static void DisableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs b/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs index b2c5d45..f73cad6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs @@ -15,25 +15,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - - if (playerInfo?.Skill == skillName) - { - int moneyBonus = Instance.Random.Next(minMoney, maxMoney); - playerInfo.SkillChance = moneyBonus; - AddMoney(player, moneyBonus); - } - } - }); - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -50,6 +31,7 @@ namespace jRandomSkills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null) return; AddMoney(player, -(int)(playerInfo.SkillChance ?? 0)); + playerInfo.SkillChance = 0; } private static void AddMoney(CCSPlayerController player, int money) diff --git a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs index 40da2f7..f4bfbd9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs @@ -14,22 +14,20 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - var attacker = @event.Attacker; - var damage = @event.DmgHealth; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; + } - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (attackerInfo?.Skill != skillName) return HookResult.Continue; + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + var attacker = @event.Attacker; + var damage = @event.DmgHealth; + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - int moneyToSteal = damage * moneyMultiplier; - StealMoney(victim!, attacker!, moneyToSteal); + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (attackerInfo?.Skill != skillName) return; - return HookResult.Continue; - }); + int moneyToSteal = damage * moneyMultiplier; + StealMoney(victim!, attacker!, moneyToSteal); } private static void StealMoney(CCSPlayerController victim, CCSPlayerController attacker, int money) diff --git a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs index 6de65f1..48bd1d4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs @@ -17,36 +17,32 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; - - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - - var victimPawn = victim!.PlayerPawn.Value; - if (victimPawn == null || !victimPawn.IsValid) return HookResult.Continue; - - if (attackerInfo?.Skill == skillName) - if (playersToSlow.ContainsKey(victimPawn)) - playersToSlow[victimPawn] = Server.TickCount + (64 * rubberTime); - else playersToSlow.TryAdd(victimPawn, Server.TickCount + (64 * rubberTime)); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - playersToSlow.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() + { + playersToSlow.Clear(); + } + + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + + var victimPawn = victim!.PlayerPawn.Value; + if (victimPawn == null || !victimPawn.IsValid) return; + + if (attackerInfo?.Skill == skillName) + if (playersToSlow.ContainsKey(victimPawn)) + playersToSlow[victimPawn] = Server.TickCount + (64 * rubberTime); + else playersToSlow.TryAdd(victimPawn, Server.TickCount + (64 * rubberTime)); + + } + + public static void OnTick() { foreach(var item in playersToSlow) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Saper.cs b/jRandomSkills - SRC Files/src/player/skills/Saper.cs index 437f3be..2798f72 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Saper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Saper.cs @@ -13,54 +13,42 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => + } + + public static void BombBegindefuse(EventBombBegindefuse @event) + { + var player = @event.Userid; + if (Instance.IsPlayerValid(player)) { - var player = @event.Userid; - - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); if (playerInfo?.Skill == skillName) { - var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); - - if (bombEntities.Count != 0) - { - var bomb = bombEntities.FirstOrDefault(); - if (bomb != null) - { - bomb.BombPlacedAnimation = false; - bomb.ArmedTime = 0.0f; - } - } + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null) + Server.NextFrame(() => plantedBomb.DefuseCountDown = 0); } + } + } - return HookResult.Continue; - }); + public static void BombBeginplant(EventBombBeginplant @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - Instance.RegisterEventHandler((@event, info) => + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill == skillName) { - var player = @event.Userid; - - if (Instance.IsPlayerValid(player)) + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); + if (bombEntities.Count != 0) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill == skillName) + var bomb = bombEntities.FirstOrDefault(); + if (bomb != null) { - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb != null) - { - Server.NextFrame(() => - { - plantedBomb.DefuseCountDown = 0; - }); - } + bomb.BombPlacedAnimation = false; + bomb.ArmedTime = 0.0f; } } - - return HookResult.Continue; - }); + } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8A2BE2", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs index 913d1d4..5754129 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs @@ -15,50 +15,31 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (player == null || !player.IsValid || player.PlayerPawn?.Value == null) continue; + public static void NewRound() + { + secondLifePlayers.Clear(); + } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + int damage = @event.DmgHealth; - return HookResult.Continue; - }); + if (!Instance.IsPlayerValid(victim)) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo == null || victimInfo.Skill != skillName) return; - Instance.RegisterEventHandler((@event, info) => - { - secondLifePlayers.Clear(); - return HookResult.Continue; - }); + var victimPawn = victim!.PlayerPawn.Value; + if (victimPawn!.Health > 0 || secondLifePlayers.TryGetValue(victim.Handle, out _) == true) + return; - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - int damage = @event.DmgHealth; - - if (!Instance.IsPlayerValid(victim)) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return HookResult.Continue; - - var victimPawn = victim!.PlayerPawn.Value; - if (victimPawn!.Health > 0 || secondLifePlayers.TryGetValue(victim.Handle, out _) == true) - return HookResult.Continue; - - secondLifePlayers.Add(victim.Handle); - SetHealth(victim, secondLifeHealth); - var spawn = GetSpawnVector(victim); - if (spawn != null) - victimPawn.Teleport(spawn, victimPawn.AbsRotation, null); - return HookResult.Stop; - }); + secondLifePlayers.Add(victim.Handle); + SetHealth(victim, secondLifeHealth); + var spawn = GetSpawnVector(victim); + if (spawn != null) + victimPawn.Teleport(spawn, victimPawn.AbsRotation, null); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Shade.cs b/jRandomSkills - SRC Files/src/player/skills/Shade.cs index 7246ec0..6de2739 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Shade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Shade.cs @@ -7,7 +7,6 @@ using CS2TraceRay.Struct; using jRandomSkills.src.player; using jRandomSkills.src.utils; using System.Numerics; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; @@ -22,35 +21,25 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; + } - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return HookResult.Continue; + public static void NewRound() + { + noSpace.Clear(); + } - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; - if (attackerInfo?.Skill == skillName) - TeleportAttackerBehindVictim(attacker!, victim!); + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; - return HookResult.Continue; - }); + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - Instance.RegisterEventHandler((@event, info) => - { - noSpace.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var item in noSpace) - if (item.Value >= Server.TickCount) - UpdateHUD(item.Key); - }); + if (attackerInfo?.Skill == skillName) + TeleportAttackerBehindVictim(attacker!, victim!); } public static void DisableSkill(CCSPlayerController player) @@ -58,6 +47,13 @@ namespace jRandomSkills noSpace.Remove(player); } + public static void OnTick() + { + foreach (var item in noSpace) + if (item.Value >= Server.TickCount) + UpdateHUD(item.Key); + } + private static void UpdateHUD(CCSPlayerController player) { var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); diff --git a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs index 933b9ec..966e14a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs @@ -14,21 +14,19 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + public static void BombPlanted(EventBombPlanted @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + detonationTime); - - return HookResult.Continue; - }); + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null) + Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + detonationTime); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f5b74c", CsTeam onlyTeam = CsTeam.Terrorist, bool needsTeammates = false, int detonationTime = 20) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/Silent.cs b/jRandomSkills - SRC Files/src/player/skills/Silent.cs index fad4919..79df00e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Silent.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Silent.cs @@ -1,5 +1,5 @@ using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using static jRandomSkills.jRandomSkills; @@ -13,26 +13,24 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.HookUserMessage(208, um => - { - var soundevent = um.ReadUInt("soundevent_hash"); - var userIndex = um.ReadUInt("source_entity_index"); + public static void PlayerMakeSound(UserMessage um) + { + var soundevent = um.ReadUInt("soundevent_hash"); + var userIndex = um.ReadUInt("source_entity_index"); + if (userIndex == 0) return; - if (userIndex == 0) return HookResult.Continue; + if (!Instance.footstepSoundEvents.Contains(soundevent) && !Instance.silentSoundEvents.Contains(soundevent)) + return; - if (!Instance.footstepSoundEvents.Contains(soundevent) && !Instance.silentSoundEvents.Contains(soundevent)) - return HookResult.Continue; + var player = Utilities.GetPlayers().FirstOrDefault(p => p.Pawn?.Value != null && p.Pawn.Value.IsValid && p.Pawn.Value.Index == userIndex); + if (!Instance.IsPlayerValid(player)) return; - var player = Utilities.GetPlayers().FirstOrDefault(p => p.Pawn?.Value != null && p.Pawn.Value.IsValid && p.Pawn.Value.Index == userIndex); - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - um.Recipients.Clear(); - return HookResult.Handled; - }, HookMode.Pre); + um.Recipients.Clear(); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#333333", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs index abe4937..be7caa6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs @@ -19,38 +19,21 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); + public static void NewRound() + { + sniperElites.Clear(); + } - return HookResult.Continue; - }); + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + sniperElites.Remove(player.SteamID); - Instance.RegisterEventHandler((@event, info) => - { - sniperElites.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - sniperElites.Remove(player.SteamID); - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs index b00c922..60fdf05 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs @@ -1,6 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -16,24 +14,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); - VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -46,36 +26,34 @@ namespace jRandomSkills SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{Localization.GetTranslation("soldier")}{ChatColors.Lime}: " + Localization.GetTranslation("soldier_desc2", newScale), false); } - private static HookResult OnTakeDamage(DynamicHook h) + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return HookResult.Continue; + return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); CCSPlayerPawn victimPawn = new(param.Handle); if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return HookResult.Continue; + return; if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) - return HookResult.Continue; + return; CCSPlayerController attacker = attackerPawn.Controller.Value.As(); CCSPlayerController victim = victimPawn.Controller.Value.As(); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); - if (playerInfo == null) return HookResult.Continue; + if (playerInfo == null) return; if (playerInfo.Skill == skillName && attacker.PawnIsAlive) { float? skillChance = playerInfo.SkillChance; param2.Damage *= skillChance ?? 1f; } - - return HookResult.Continue; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#09ba00", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float chanceFrom = 1.15f, float chanceTo = 1.35f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs b/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs index 3b49863..aaab644 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,49 +16,11 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - UpdateHUD(player, skillInfo); - } - }); + public static void NewRound() + { + SkillPlayerInfo.Clear(); } public static void EnableSkill(CCSPlayerController player) @@ -77,6 +38,26 @@ namespace jRandomSkills SkillPlayerInfo.Remove(player.SteamID); } + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + SkillPlayerInfo.Remove(player.SteamID); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) + { + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + UpdateHUD(player, skillInfo); + } + } + private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) { float cooldown = 0; diff --git a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs index 684f08f..caf8cbf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs @@ -10,54 +10,38 @@ namespace jRandomSkills public class Spectator : ISkill { private const Skills skillName = Skills.Spectator; - private static bool blocked = false; private static readonly float distance = Config.GetValue(skillName, "distance"); private static readonly Dictionary cameras = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - blocked = true; - foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out _)) - DisableSkill(player); + public static void NewRound() + { + foreach (var camera in cameras) + camera.Value.Item2.Remove(); + cameras.Clear(); + } - foreach (var camera in cameras) - camera.Value.Item2.Remove(); - cameras.Clear(); - return HookResult.Continue; - }); + public static void WeaponPickup(EventItemPickup @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (playerInfo?.Skill != skillName) return; - Instance.RegisterEventHandler((@event, info) => - { - blocked = false; - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - - var pawn = player!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return HookResult.Continue; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item1 != pawn.CameraServices.ViewEntity.Raw) - BlockWeapon(player, true); - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + var pawn = player!.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item1 != pawn.CameraServices.ViewEntity.Raw) + BlockWeapon(player, true); } public static void UseSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null || blocked) return; + if (playerPawn?.CBodyComponent == null) return; ChangeCamera(player); } @@ -66,7 +50,7 @@ namespace jRandomSkills ChangeCamera(player, true); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) diff --git a/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs b/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs index 63b7027..fac4e05 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,55 +16,25 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void NewRound() + { + SkillPlayerInfo.Clear(); + } + + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - if (skillInfo.LastClick.AddSeconds(4) >= DateTime.Now) - UpdateHUD(player, skillInfo, true); - else - UpdateHUD(player, skillInfo, false); - } - }); + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (skillInfo.LastClick.AddSeconds(4) >= DateTime.Now) + UpdateHUD(player, skillInfo, true); + else + UpdateHUD(player, skillInfo, false); + } } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs index 0a71943..0a32317 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs @@ -13,23 +13,18 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var victim = @event.Userid; - var attacker = @event.Attacker; + } - if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return HookResult.Continue; + public static void PlayerHurt(EventPlayerHurt @event) + { + var victim = @event.Userid; + var attacker = @event.Attacker; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return; + var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); - if (attackerInfo?.Skill == skillName) - { - TeleportPlayers(attacker!, victim!); - } - - return HookResult.Continue; - }); + if (attackerInfo?.Skill == skillName) + TeleportPlayers(attacker!, victim!); } private static void TeleportPlayers(CCSPlayerController attacker, CCSPlayerController victim) diff --git a/jRandomSkills - SRC Files/src/player/skills/Thief.cs b/jRandomSkills - SRC Files/src/player/skills/Thief.cs index 0ab1717..e758fe0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thief.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thief.cs @@ -13,23 +13,39 @@ namespace jRandomSkills public static void LoadSkill() { - SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color"), false); + SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => + public static void OnTick() + { + if (Server.TickCount % 32 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); + if (!SkillUtils.HasMenu(player)) continue; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - return HookResult.Continue; - }); + if (playerInfo == null || playerInfo.Skill != skillName) continue; + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + if (enemies.Length > 0) + { + HashSet<(string, string)> menuItems = []; + foreach (var enemy in enemies) + { + var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); + if (skillData == null) continue; + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); + } + SkillUtils.CreateMenu(player, menuItems); + } + } + } + + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + SkillUtils.CloseMenu(player); } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -57,24 +73,22 @@ namespace jRandomSkills public static void EnableSkill(CCSPlayerController player) { - SkillUtils.PrintToChat(player, Localization.GetTranslation("thief") + ":", false); - - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("thief_select_info")}"); - var enemies = Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator).ToArray(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { + HashSet<(string, string)> menuItems = []; foreach (var enemy in enemies) { var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; - player.PrintToChat($" {ChatColors.Green}⠀⠀⠀[{ChatColors.Red}{enemy.Index}{ChatColors.Green}] {enemy.PlayerName}: {ChatColors.Red}{skillData.Name}"); + menuItems.Add(($"{enemy.PlayerName} : {skillData.Name}", enemy.Index.ToString())); } + SkillUtils.CreateMenu(player, menuItems); } else - player.PrintToChat($" {ChatColors.Red}⠀⠀⠀{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); - player.PrintToChat($" {ChatColors.Green}{Localization.GetTranslation("selectplayerskill_command")} {ChatColors.Red}index"); + player.PrintToChat($" {ChatColors.Red}{Localization.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } public static void DisableSkill(CCSPlayerController player) @@ -82,6 +96,7 @@ namespace jRandomSkills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null) return; playerInfo.SpecialSkill = Skills.None; + SkillUtils.CloseMenu(player); } private static void DeacitvateSkill(CCSPlayerController player, CCSPlayerController enemy) @@ -92,9 +107,12 @@ namespace jRandomSkills if (playerInfo != null) { - playerInfo.Skill = enemyInfo.Skill; - playerInfo.SpecialSkill = skillName; - Instance.SkillAction(enemyInfo.Skill.ToString(), "EnableSkill", [player]); + Instance.AddTimer(.1f, () => + { + playerInfo.Skill = enemyInfo.Skill; + playerInfo.SpecialSkill = skillName; + Instance.SkillAction(enemyInfo.Skill.ToString(), "EnableSkill", [player]); + }); player.PrintToChat($" {ChatColors.Green}" + Localization.GetTranslation("thief_player_info", enemy.PlayerName)); } diff --git a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs index 8efd738..f213201 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs @@ -3,47 +3,31 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using System.Drawing; -using static jRandomSkills.jRandomSkills; namespace jRandomSkills { public class ThirdEye : ISkill { private const Skills skillName = Skills.ThirdEye; - private static bool blocked = false; private static readonly float distance = Config.GetValue(skillName, "distance"); private static readonly Dictionary cameras = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - blocked = true; - foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out _)) - DisableSkill(player); - - foreach (var camera in cameras) - camera.Value.Item2.Remove(); - cameras.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - blocked = false; - return HookResult.Continue; - }); - - Instance.RegisterListener(OnTick); + public static void NewRound() + { + foreach (var camera in cameras) + camera.Value.Item2.Remove(); + cameras.Clear(); } public static void UseSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null || blocked) return; + if (playerPawn?.CBodyComponent == null) return; ChangeCamera(player); } @@ -52,7 +36,7 @@ namespace jRandomSkills ChangeCamera(player, true); } - private static void OnTick() + public static void OnTick() { foreach (var player in Utilities.GetPlayers()) if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) diff --git a/jRandomSkills - SRC Files/src/player/skills/Thorns.cs b/jRandomSkills - SRC Files/src/player/skills/Thorns.cs index 53ab4e1..2c09c30 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thorns.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thorns.cs @@ -13,21 +13,20 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - var attacker = @event.Attacker; - var victim = @event.Userid; + } - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return HookResult.Continue; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo?.Skill == skillName && victim!.PawnIsAlive && attacker!.PawnIsAlive) - { - SkillUtils.TakeHealth(attacker.PlayerPawn.Value, (int)(@event.DmgHealth * healthTakenScale)); - attacker.EmitSound("Player.DamageBody.Onlooker"); - } - return HookResult.Continue; - }); + public static void PlayerHurt(EventPlayerHurt @event) + { + var attacker = @event.Attacker; + var victim = @event.Userid; + + if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; + var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victimInfo?.Skill == skillName && victim!.PawnIsAlive && attacker!.PawnIsAlive) + { + SkillUtils.TakeHealth(attacker.PlayerPawn.Value, (int)(@event.DmgHealth * healthTakenScale)); + attacker.EmitSound("Player.DamageBody.Onlooker"); + } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#962631", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, float healthTakenScale = .3f) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) diff --git a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs index 1d6bdf3..151124a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -18,85 +17,11 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - smokes.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - smokes.Add(new Vector(@event.X, @event.Y, @event.Z)); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return HookResult.Continue; - smokes.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); - return HookResult.Continue; - }); - - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (name != "smokegrenade_projectile") return; - - var grenade = @event.As(); - if (grenade == null || !grenade.IsValid || grenade.OwnerEntity == null || !grenade.OwnerEntity.IsValid || grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; - - var pawn = grenade.OwnerEntity.Value.As(); - if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; - - var player = pawn.Controller.Value.As(); - if (player == null || !player.IsValid) return; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return; - - Server.NextFrame(() => - { - var smoke = @event.As(); - smoke.SmokeColor.X = 255; - smoke.SmokeColor.Y = 0; - smoke.SmokeColor.Z = 255; - }); - }); - - Instance.RegisterListener(() => - { - foreach (Vector smokePos in smokes) - foreach (var player in Utilities.GetPlayers()) - if (Server.TickCount % 17 == 0) - if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) - if (player.PlayerPawn.Value.LifeState == (byte)LifeState_t.LIFE_ALIVE && player.PlayerPawn.Value.AbsOrigin != null) - if (SkillUtils.GetDistance(smokePos, player.PlayerPawn.Value.AbsOrigin) <= smokeRadius) - AddHealth(player.PlayerPawn.Value, -smokeDamage); - }); + public static void NewRound() + { + smokes.Clear(); } public static void EnableSkill(CCSPlayerController player) @@ -104,6 +29,50 @@ namespace jRandomSkills SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade); } + public static void OnEntitySpawned(CEntityInstance entity) + { + var name = entity.DesignerName; + if (name != "smokegrenade_projectile") return; + + var grenade = entity.As(); + if (grenade == null || !grenade.IsValid || grenade.OwnerEntity == null || !grenade.OwnerEntity.IsValid || grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; + + var pawn = grenade.OwnerEntity.Value.As(); + if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; + + var player = pawn.Controller.Value.As(); + if (player == null || !player.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + + Server.NextFrame(() => + { + var smoke = entity.As(); + smoke.SmokeColor.X = 255; + smoke.SmokeColor.Y = 0; + smoke.SmokeColor.Z = 255; + }); + } + + public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + smokes.Add(new Vector(@event.X, @event.Y, @event.Z)); + } + + public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return; + smokes.RemoveAll(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z); + } + private static void AddHealth(CCSPlayerPawn player, int health) { if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) @@ -117,6 +86,17 @@ namespace jRandomSkills player.CommitSuicide(false, true); } + public static void OnTick() + { + foreach (Vector smokePos in smokes) + foreach (var player in Utilities.GetPlayers()) + if (Server.TickCount % 17 == 0) + if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) + if (player.PlayerPawn.Value.LifeState == (byte)LifeState_t.LIFE_ALIVE && player.PlayerPawn.Value.AbsOrigin != null) + if (SkillUtils.GetDistance(smokePos, player.PlayerPawn.Value.AbsOrigin) <= smokeRadius) + AddHealth(player.PlayerPawn.Value, -smokeDamage); + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false, int smokeDamage = 2, float smokeRadius = 180) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) { public int SmokeDamage { get; set; } = smokeDamage; diff --git a/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs b/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs index de951be..873a5fd 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs @@ -11,43 +11,11 @@ namespace jRandomSkills public class Wallhack : ISkill { private const Skills skillName = Skills.Wallhack; - private static bool exists = false; private static readonly List<(CDynamicProp, CDynamicProp)> glows = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, @info) => - { - glows.Clear(); - Instance.AddTimer(2f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - EnableSkill(player); - } - }); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, @info) => - { - foreach (var glow in glows) - { - glow.Item1.Remove(); - glow.Item2.Remove(); - } - glows.Clear(); - - Instance.RemoveListener(CheckTransmit); - exists = false; - return HookResult.Continue; - }); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -71,11 +39,19 @@ namespace jRandomSkills } } + public static void NewRound() + { + foreach (var glow in glows) + { + glow.Item1.Remove(); + glow.Item2.Remove(); + } + glows.Clear(); + } + public static void EnableSkill(CCSPlayerController player) { - if (!exists) - Instance.RegisterListener(CheckTransmit); - exists = true; + Event.enableTransmit = true; SetGlowEffectForEnemies(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs index 592c430..024d0ff 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -17,46 +16,43 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - bombPlanted = false; - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - bombPlanted = true; - return HookResult.Continue; - }); - - Instance.RegisterListener(@event => - { - var name = @event.DesignerName; - if (!name.EndsWith("_projectile")) - return; - - var grenade = @event.As(); - if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; - - var pawn = grenade.OwnerEntity.Value.As(); - if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; - var player = pawn.Controller.Value.As(); - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName || Instance.GameRules == null) return; - - Instance.GameRules.RoundTime += player.Team == CsTeam.Terrorist ? roundTime : -roundTime; - if (player.Team == CsTeam.Terrorist) - Server.PrintToChatAll($" {ChatColors.Orange}{Localization.GetTranslation("watchmaker_tt", roundTime)}"); - else - Server.PrintToChatAll($" {ChatColors.LightBlue}{Localization.GetTranslation("watchmaker_ct", roundTime)}"); - }); - - Instance.RegisterListener(OnTick); } - private static void OnTick() + public static void NewRound() + { + bombPlanted = false; + } + + public static void BombPlanted(EventBombPlanted _) + { + bombPlanted = true; + } + + public static void OnEntitySpawned(CEntityInstance entity) + { + if (bombPlanted) return; + var name = entity.DesignerName; + if (!name.EndsWith("_projectile")) + return; + + var grenade = entity.As(); + if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; + + var pawn = grenade.OwnerEntity.Value.As(); + if (pawn == null || !pawn.IsValid || pawn.Controller == null || !pawn.Controller.IsValid || pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; + var player = pawn.Controller.Value.As(); + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName || Instance.GameRules == null) return; + + Instance.GameRules.RoundTime += player.Team == CsTeam.Terrorist ? roundTime : -roundTime; + if (player.Team == CsTeam.Terrorist) + Server.PrintToChatAll($" {ChatColors.Orange}{Localization.GetTranslation("watchmaker_tt", roundTime)}"); + else + Server.PrintToChatAll($" {ChatColors.LightBlue}{Localization.GetTranslation("watchmaker_ct", roundTime)}"); + } + + public static void OnTick() { if (bombPlanted) return; foreach (var player in Utilities.GetPlayers()) diff --git a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs index 8de19b4..32f9e44 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; using jRandomSkills.src.utils; -using static CounterStrikeSharp.API.Core.Listeners; using static jRandomSkills.jRandomSkills; namespace jRandomSkills @@ -24,57 +23,11 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); + } - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - { - EnableSkill(player); - } - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - SkillPlayerInfo.Clear(); - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo == null) return HookResult.Continue; - - if (playerInfo.Skill == skillName) - SkillPlayerInfo.Remove(player.SteamID); - - return HookResult.Continue; - }); - - Instance.RegisterListener(() => - { - foreach (var player in Utilities.GetPlayers()) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - if (skillInfo.LastClick.AddSeconds(4) >= DateTime.Now) - UpdateHUD(player, skillInfo, true); - else - UpdateHUD(player, skillInfo, false); - } - }); + public static void NewRound() + { + SkillPlayerInfo.Clear(); } public static void EnableSkill(CCSPlayerController player) @@ -95,6 +48,20 @@ namespace jRandomSkills SkillPlayerInfo.Remove(player.SteamID); } + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) + { + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == skillName) + if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (skillInfo.LastClick.AddSeconds(4) >= DateTime.Now) + UpdateHUD(player, skillInfo, true); + else + UpdateHUD(player, skillInfo, false); + } + } + private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo, bool showInfo) { float cooldown = 0; diff --git a/jRandomSkills - SRC Files/src/player/skills/Zeus.cs b/jRandomSkills - SRC Files/src/player/skills/Zeus.cs index f5d4c33..80c182f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Zeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Zeus.cs @@ -1,5 +1,4 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; @@ -14,51 +13,6 @@ namespace jRandomSkills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, Config.GetValue(skillName, "color")); - - Instance.RegisterEventHandler((@event, info) => - { - Instance.AddTimer(0.1f, () => - { - foreach (var player in Utilities.GetPlayers()) - { - if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) continue; - EnableSkill(player); - } - }); - - return HookResult.Continue; - }); - - Instance.RegisterEventHandler((@event, info) => - { - var player = @event.Userid; - if (!Instance.IsPlayerValid(player)) return HookResult.Continue; - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - - if (playerInfo?.Skill == skillName) - { - var pawn = player!.PlayerPawn!.Value!; - if (pawn.WeaponServices == null || pawn.WeaponServices.ActiveWeapon == null || !pawn.WeaponServices.ActiveWeapon.IsValid) return HookResult.Continue; - if (pawn.WeaponServices.ActiveWeapon.Value == null || !pawn.WeaponServices.ActiveWeapon.Value.IsValid) return HookResult.Continue; - - var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; - if (activeWeapon.DesignerName != "weapon_taser") return HookResult.Continue; - var taser = activeWeapon.As(); - Instance.AddTimer(.1f, () => - { - if (taser.IsValid) - { - taser.LastAttackTick = 0; - taser.FireTime = 0; - } - }); - } - - return HookResult.Continue; - }); } public static void EnableSkill(CCSPlayerController player) @@ -66,6 +20,34 @@ namespace jRandomSkills SkillUtils.TryGiveWeapon(player, CsItem.Zeus); } + public static void WeaponFire(EventWeaponFire @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + + if (playerInfo?.Skill == skillName) + { + var pawn = player!.PlayerPawn!.Value!; + if (pawn.WeaponServices == null || pawn.WeaponServices.ActiveWeapon == null || !pawn.WeaponServices.ActiveWeapon.IsValid) return; + if (pawn.WeaponServices.ActiveWeapon.Value == null || !pawn.WeaponServices.ActiveWeapon.Value.IsValid) return; + + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon.DesignerName != "weapon_taser") return; + var taser = activeWeapon.As(); + Instance.AddTimer(.1f, () => + { + if (taser.IsValid) + { + taser.LastAttackTick = 0; + taser.FireTime = 0; + } + }); + } + + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fbff00", CsTeam onlyTeam = CsTeam.None, bool needsTeammates = false) : Config.DefaultSkillInfo(skill, active, color, onlyTeam, needsTeammates) { } diff --git a/jRandomSkills - SRC Files/src/utils/Config.cs b/jRandomSkills - SRC Files/src/utils/Config.cs index d10de69..5b8984c 100644 --- a/jRandomSkills - SRC Files/src/utils/Config.cs +++ b/jRandomSkills - SRC Files/src/utils/Config.cs @@ -141,6 +141,7 @@ namespace jRandomSkills public bool SummaryAfterTheRound { get; set; } public bool DebugMode { get; set; } public string? AlternativeSkillButton { get; set; } + public float SkillTimeBeforeStart { get; set; } public NormalCommand SetSkillCommands { get; set; } public NormalCommand SkillsListCommands { get; set; } public NormalCommand UseSkillCommands { get; set; } @@ -163,6 +164,7 @@ namespace jRandomSkills SummaryAfterTheRound = true; DebugMode = true; AlternativeSkillButton = null; + SkillTimeBeforeStart = 7; SetSkillCommands = new NormalCommand("ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "@jRandmosSkills/admin"); SkillsListCommands = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandmosSkills/admin"); diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index 275b4dd..76940fd 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -6,7 +6,10 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.player; +using jRandomSkills.src.utils; using System.Runtime.InteropServices; +using WASDMenuAPI.Classes; +using WASDSharedAPI; namespace jRandomSkills { @@ -112,6 +115,75 @@ namespace jRandomSkills return designerName; } + private static IWasdMenuManager? GetMenuManager() + { + if (jRandomSkills.Instance.MenuManager == null) + jRandomSkills.Instance.MenuManager = new WasdManager(); + return jRandomSkills.Instance.MenuManager; + } + + public static void CloseMenu(CCSPlayerController? player) + { + var manager = GetMenuManager(); + if (manager == null) return; + manager.CloseMenu(player); + } + + public static bool HasMenu(CCSPlayerController? player) + { + var manager = GetMenuManager(); + if (manager == null) return false; + return manager.HasMenu(player); + } + + public static void UpdateMenu(CCSPlayerController? player, HashSet<(string, string)> items) + { + if (player == null) return; + + var manager = GetMenuManager(); + if (manager == null) return; + + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null) return; + + Dictionary> list = []; + foreach (var item in items) + list.Add(item.Item1, (p, option) => + { + jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { item.Item2 }]); + manager.CloseMenu(p); + }); + + manager.UpdateActiveMenu(player, list); + } + + public static void CreateMenu(CCSPlayerController? player, HashSet<(string, string)> enemies) + { + if (player == null || !player.IsValid) return; + + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null) return; + + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill); + if (skillData == null) return; + + string infoLine = $"{Localization.GetTranslation("your_skill")}:
"; + string skillLine = $"{skillData.Name}
" + + $"{Localization.GetTranslation($"{playerInfo.Skill.ToString().ToLower()}_select_info")}"; + + var manager = GetMenuManager(); + if (manager == null) return; + + IWasdMenu menu = manager.CreateMenu(infoLine + skillLine, "W/S - Scroll | E - Select
"); + foreach (var enemy in enemies) + menu.Add(enemy.Item1, (p, option) => + { + jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [p, new[] { enemy.Item2 }]); + manager.CloseMenu(p); + }); + manager.OpenMainMenu(player, menu); + } + public static void SetTeamScores(short ctScore, short tScore, RoundEndReason roundEndReason) { if (jRandomSkills.Instance == null || jRandomSkills.Instance.GameRules == null) return; diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/Config.json b/jRandomSkills - Server Files/plugins/jRandomSkills/Config.json index 3e4cf69..12d3754 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/Config.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/Config.json @@ -7,6 +7,7 @@ "SummaryAfterTheRound": true, "DebugMode": true, "AlternativeSkillButton": null, + "SkillTimeBeforeStart": 7.0, "SetSkillCommands": { "Alias": "ustawskill, ustaw_skill, setskill, set_skill, definirhabilidade, configurarhabilidade, 设置技能, 配置技能", "Permissions": "@jRandmosSkills/admin" @@ -373,6 +374,14 @@ "Active": true, "Name": "FrozenDecoy" }, + { + "RefreshPrice": 150, + "NeedsTeammates": false, + "OnlyTeam": 0, + "Color": "#7eff47", + "Active": true, + "Name": "Gambler" + }, { "NeedsTeammates": false, "OnlyTeam": 0, @@ -465,6 +474,15 @@ "Active": true, "Name": "Jammer" }, + { + "MinTime": 10.0, + "MaxTime": 25.0, + "NeedsTeammates": false, + "OnlyTeam": 0, + "Color": "#8f108f", + "Active": true, + "Name": "Jester" + }, { "NeedsTeammates": false, "OnlyTeam": 0, diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll new file mode 100644 index 0000000000000000000000000000000000000000..6004f5793e9527bb374bcaa5a9eaa12fd7c657a5 GIT binary patch literal 15360 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 IACJKQ0wAaYGynhq literal 0 HcmV?d00001 diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll index 0a03c1c322731c3d780c104888371a25846ac94d..0e88154bfc4a23a6e0bf326a215d79cfc4182518 100644 GIT binary patch literal 344576 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 diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/en.json b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/en.json index 54a88e7..c9938d1 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/en.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/en.json @@ -18,7 +18,7 @@ "areareaper_desc": "You can choose a bomb site to deactivate", "areareaper_incorrect_site": "No such bomb site found.", "areareaper_no_site": "No bomb sites found.", - "areareaper_select_info": "Choose the bomb site you want to deactivate:", + "areareaper_select_info": "Select site to deactivate:", "areareaper_site_disabled": "Bomb site {0} has been deactivated - no bombs can be planted there!", "areareaper_used_info": "Your skill has already been used.", @@ -66,19 +66,19 @@ "darkness_desc": "Applies a darkness effect to a chosen enemy", "darkness_enemy_info": "Let the lights go out.", "darkness_player_info": "Darkness has overtaken player '{0}'.", - "darkness_select_info": "Choose the player you want to apply the darkness effect to:", + "darkness_select_info": "Select player for darkness:", "deactivator": "Deactivator", "deactivator_desc": "Choose a player whose skill you want to disable", "deactivator_enemy_info": "Your skill has been disabled.", "deactivator_player_info": "Player '{0}'s skill has been disabled.", - "deactivator_select_info": "Choose the player whose skill you want to disable:", + "deactivator_select_info": "Disable a player's skill:", "deaf": "Deaf", "deaf_desc": "Choose a player to mute all sounds for", "deaf_enemy_info": "Your headphones have left the game.", "deaf_player_info": "Sound has been disabled for player '{0}'.", - "deaf_select_info": "Choose the player for whom you want to mute all sounds:", + "deaf_select_info": "Mute all sounds for player:", "disarmament": "Disarmament", "disarmament_desc": "You have a random chance to make an enemy drop their weapon on hit", @@ -93,7 +93,7 @@ "duplicator": "Duplicator", "duplicator_desc": "Choose a player to copy their skill", "duplicator_player_info": "Player '{0}'s skill has been copied.", - "duplicator_select_info": "Choose the player whose skill you want to copy:", + "duplicator_select_info": "Copy a player's skill:", "dwarf": "Dwarf", "dwarf_desc": "Random character size at the start of the round", @@ -129,6 +129,11 @@ "frozendecoy": "Freezing Decoy", "frozendecoy_desc": "Your decoy freezes all nearby players", + "gambler": "Gambler", + "gambler_desc": "Select a skill from the list provided.", + "gambler_select_info": "Select your skill:", + "gambler_more": "Refresh for $100", + "ghost": "Ghost", "ghost_desc": "You are completely invisible", @@ -139,7 +144,7 @@ "glitch_desc": "Disables the radar for a chosen enemy", "glitch_enemy_info": "Your radar has been disabled.", "glitch_player_info": "Player '{0}'s radar has been disabled.", - "glitch_select_info": "Choose the player whose radar you want to disable:", + "glitch_select_info": "Turn off player's radar:", "glue": "Glue", "glue_desc": "Your grenades stick to walls", @@ -171,13 +176,19 @@ "jammer_desc": "Choose a player to disable their crosshair", "jammer_enemy_info": "Your crosshair has been disabled.", "jammer_player_info": "Player '{0}'s crosshair has been disabled.", - "jammer_select_info": "Choose the player whose crosshair you want to disable:", + "jammer_select_info": "Disable player's crosshair:", + + "jester": "Jester", + "jester_desc": "In jester mode, you cannot get or take any damage. This mode changes every few seconds.", + "jester_mode": "Jester Mode", + "jester_on": "ON", + "jester_off": "OFF", "jumpban": "Legless", "jumpban_desc": "Choose a player who cannot jump", "jumpban_enemy_info": "Someone cut off your legs.", "jumpban_player_info": "Player '{0}' can no longer jump.", - "jumpban_select_info": "Choose the player who cannot jump:", + "jumpban_select_info": "Ban player from jumping:", "jumpingjack": "Jumping Jack", "jumpingjack_desc": "Jumping restores health", @@ -189,7 +200,7 @@ "lifeswap_desc": "Choose a player to swap health with", "lifeswap_enemy_info": "Someone borrowed your health.", "lifeswap_player_info": "You swapped health with player '{0}'.", - "lifeswap_select_info": "Choose the player to swap health with:", + "lifeswap_select_info": "Swap health with player:", "longknife": "Long Knife", "longknife_desc": "A primary knife attack deals damage regardless of distance", @@ -201,7 +212,7 @@ "magnifier_desc": "Forces the enemy's screen to zoom in, reducing their field of view", "magnifier_enemy_info": "Your field of view has been distorted!", "magnifier_player_info": "Player '{0}' has been forced into zoom mode.", - "magnifier_select_info": "Select the player whose screen you want to magnify:", + "magnifier_select_info": "Magnify player's screen:", "medic": "Medic", "medic_desc": "Click [css_useSkill] to use a healing charge that restores 50 health", @@ -210,7 +221,7 @@ "moneyswap_desc": "Choose a player to swap money with", "moneyswap_enemy_info": "The tax office got you.", "moneyswap_player_info": "You swapped money with player '{0}'.", - "moneyswap_select_info": "Choose the player to swap money with:", + "moneyswap_select_info": "Swap money with player:", "muhammed": "Muhammed", "muhammed_desc": "You explode upon death, killing nearby players", @@ -257,13 +268,13 @@ "poison_desc": "Choose a player who will take damage every few seconds", "poison_enemy_info": "You have been poisoned.", "poison_player_info": "Player '{0}' has been poisoned.", - "poison_select_info": "Choose the player who will take damage every few seconds:", + "poison_select_info": "Poison a player:", "primaryban": "No Rifles", "primaryban_desc": "Choose a player who cannot use rifles", "primaryban_enemy_info": "You can no longer use rifles.", "primaryban_player_info": "Player '{0}' can no longer use rifles.", - "primaryban_select_info": "Choose the player to ban from using rifles:", + "primaryban_select_info": "Ban rifles for player:", "prosthesis": "Prosthesis", "prosthesis_desc": "Arms and legs are bulletproof", @@ -353,7 +364,7 @@ "thief_desc": "You can steal a skill from a chosen player", "thief_enemy_info": "Your skill has been stolen.", "thief_player_info": "Player '{0}'s skill has been stolen.", - "thief_select_info": "Choose the player whose skill you want to steal:", + "thief_select_info": "Steal a player's skill:", "thirdeye": "Third Eye", "thirdeye_desc": "Click [css_useSkill] to activate third-person view", @@ -394,7 +405,7 @@ "no_player": "No matching player found.", "duplicate_player": "More than one player found with the same name.", "selectplayerskill_command": "Type /t", - "selectplayerskill_incorrect_enemy_index": "No player found with that index.", + "selectplayerskill_incorrect_enemy_index": "No players were found to select.", "skill_not_found_setskill": "No such CHATCOLORS.REDskill found", "player_not_found_setskill": "No such CHATCOLORS.REDplayer found", @@ -420,7 +431,12 @@ "vote_alredy_voted": "You have already voted!", "vote_vote": "Vote", + "bombsite_a": "Bombsite A", + "bombsite_b": "Bombsite B", + "teammate_skills": "Your teammates' skills", "summary_start": "======SUMMARY=OF=THE=LAST=ROUND======", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - Scroll | E - Select
" } \ No newline at end of file diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pl.json b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pl.json index 62ec12e..cbe52c8 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pl.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pl.json @@ -18,7 +18,7 @@ "areareaper_desc": "Możesz wybrać strefę detonacji, którą chcesz dezaktywować", "areareaper_incorrect_site": "Nie znaleziono takiej strefy detonacji.", "areareaper_no_site": "Nie znaleziono żadnej strefy detonacji.", - "areareaper_select_info": "Wybierz strefę detonacji, którą chcesz dezaktywować:", + "areareaper_select_info": "Wybierz strefę do dezaktyw.:", "areareaper_site_disabled": "Strefa detonacji {0} została dezaktywowana - nie można na niej podłożyć bomby!", "areareaper_used_info": "Twoja moc została już wykorzystana.", @@ -66,19 +66,19 @@ "darkness_desc": "Nadaje efekt ciemności wybranemu przeciwnikowi", "darkness_enemy_info": "Niech zgasną światła.", "darkness_player_info": "Ciemność opanowała gracza '{0}'.", - "darkness_select_info": "Wybierz gracza, któremu chcesz nadać efekt ciemności:", + "darkness_select_info": "Nałóż efekt ciemności:", "deactivator": "Deaktywator", "deactivator_desc": "Wybierasz gracza, którego supermoc chcesz wyłączyć", "deactivator_enemy_info": "Twoja supermoc została wyłączona.", "deactivator_player_info": "Moc gracza '{0}' została wyłączona.", - "deactivator_select_info": "Wybierz gracza, którego supermoc chcesz wyłączyć:", + "deactivator_select_info": "Wyłącz moc gracza:", "deaf": "Głuchy", "deaf_desc": "Wybierasz gracza, dla którego chcesz wyłączyć wszystkie dźwięki", "deaf_enemy_info": "Słuchawki opuściły grę.", "deaf_player_info": "Dźwięk został wyłączony dla gracza '{0}'.", - "deaf_select_info": "Wybierz gracza, dla którego chcesz wyłączyć wszystkie dźwięki:", + "deaf_select_info": "Wycisz dźwięki gracza:", "disarmament": "Rozbrojenie", "disarmament_desc": "Masz losową szanse na wyrzucenie broni wroga po trafieniu", @@ -93,7 +93,7 @@ "duplicator": "Duplikator", "duplicator_desc": "Wybierasz gracza, od którego chcesz skopiować supermoc", "duplicator_player_info": "Moc gracza '{0}' została skopiowana.", - "duplicator_select_info": "Wybierz gracza, od którego chcesz skopiować supermoc:", + "duplicator_select_info": "Skopiuj moc gracza:", "dwarf": "Mini Majk", "dwarf_desc": "Losowa wielkość postaci na początku rundy", @@ -129,6 +129,11 @@ "frozendecoy": "Zamrażający Wabik", "frozendecoy_desc": "Twój decoy zamraża wszystkich graczy w pobliżu", + "gambler": "Hazardzista", + "gambler_desc": "Wybierz umiejętność z podanej listy.", + "gambler_select_info": "Wybierz umiejętność:", + "gambler_more": "Odśwież za $100", + "ghost": "Duszek", "ghost_desc": "Jesteś całkowicie niewidzialny", @@ -139,7 +144,7 @@ "glitch_desc": "Wyłączasz radar wybranemu przeciwnikowi", "glitch_enemy_info": "Twój radar został wyłączony.", "glitch_player_info": "Radar gracza '{0}' został wyłączony.", - "glitch_select_info": "Wybierz gracza, dla którego chcesz wyłączyć radar:", + "glitch_select_info": "Wyłącz radar dla gracza:", "glue": "Klej", "glue_desc": "Twoje granaty przyklejają się do ścian", @@ -171,13 +176,19 @@ "jammer_desc": "Wybierasz gracza, dla którego chcesz wyłączyć celownik", "jammer_enemy_info": "Twój celownik został wyłączony.", "jammer_player_info": "Celownik gracza '{0}' została wyłączona.", - "jammer_select_info": "Wybierz gracza, dla którego chcesz wyłączyć celownik:", + "jammer_select_info": "Wyłącz celownik dla gracza:", + + "jester": "Błazen", + "jester_desc": "W trybie błazna nie możesz zadawać ani otrzymywać obrażeń. Tryb zmienia się co kilka sekund.", + "jester_mode": "Tryb Błazna", + "jester_on": "WŁ.", + "jester_off": "WYŁ.", "jumpban": "Beznogi", "jumpban_desc": "Wybierasz gracza, który nie będzie mógł skakać", "jumpban_enemy_info": "Ktoś odciął ci nogi.", "jumpban_player_info": "Gracz '{0}' nie może teraz skakać.", - "jumpban_select_info": "Wybierz gracza, który nie będzie mógł skakać:", + "jumpban_select_info": "Zablokuj skok dla gracza:", "jumpingjack": "Pajacyk", "jumpingjack_desc": "Skakanie przywraca zdrowie", @@ -189,7 +200,7 @@ "lifeswap_desc": "Wybierasz gracza, z którym chcesz wymienić się zdrowiem", "lifeswap_enemy_info": "Ktoś pożyczył sobie twoje zdrowie.", "lifeswap_player_info": "Wymieniłeś się zdrowiem z graczem '{0}'.", - "lifeswap_select_info": "Wybierz gracza, z którym chcesz wymienić się zdrowiem:", + "lifeswap_select_info": "Zamień się zdrowiem z graczem:", "longknife": "Długi Nóż", "longknife_desc": "Podstawowy atak nożem zadaje obrażenia niezależnie od odległości", @@ -201,7 +212,7 @@ "magnifier_desc": "Przybiżasz ekran wybranemu przeciwnikowi", "magnifier_enemy_info": "Twoje pole widzenia zostało zniekształcone!", "magnifier_player_info": "Gracz '{0}' został zmuszony do przejścia w tryb powiększenia.", - "magnifier_select_info": "Wybierz gracza, którego ekran chcesz powiększyć:", + "magnifier_select_info": "Powiększ ekran gracza:", "medic": "Medyk", "medic_desc": "Kliknij [css_useSkill], aby użyć ładunku leczniczego, który przywraca 50 punktów zdrowia", @@ -210,7 +221,7 @@ "moneyswap_desc": "Wybierasz gracza, z którym chcesz zamienić się pieniędzmi", "moneyswap_enemy_info": "Urząd skarbowy cię dopadł.", "moneyswap_player_info": "Wymieniłeś swoje pieniądze z graczem '{0}'.", - "moneyswap_select_info": "Wybierz gracza, z którym chcesz zamienić się pieniędzmi:", + "moneyswap_select_info": "Zamień się kasą z graczem:", "muhammed": "Muhammed", "muhammed_desc": "Po śmierci eksplodujesz i zabijasz graczy znajdujących się w zasięgu", @@ -257,13 +268,13 @@ "poison_desc": "Wybierasz gracza, który co kilka sekund będzie otrzymywał obrażenia", "poison_enemy_info": "Zostałeś otruty.", "poison_player_info": "Gracz '{0}' został otruty.", - "poison_select_info": "Wybierz gracza, który co kilka sekund będzie otrzymywał obrażenia:", + "poison_select_info": "Zatruj gracza:", "primaryban": "Brak Karabinów", "primaryban_desc": "Wybierasz gracza, który nie może używać karabinów", "primaryban_enemy_info": "Nie możesz już używać karabinów.", "primaryban_player_info": "Gracz '{0}' nie może już używać karabinów.", - "primaryban_select_info": "Wybierz gracza, któremu chcesz zabronić używania karabinów:", + "primaryban_select_info": "Zablokuj karabiny dla gracza:", "prosthesis": "Proteza", "prosthesis_desc": "Ramiona i nogi są kuloodporne", @@ -353,7 +364,7 @@ "thief_desc": "Możesz ukraść supermoc wybranemu graczowi", "thief_enemy_info": "Twoja supermoc została skradziona.", "thief_player_info": "Moc gracza '{0}' została skradziona.", - "thief_select_info": "Wybierz gracza, którego supermoc chcesz ukraść:", + "thief_select_info": "Ukradnij moc gracza:", "thirdeye": "Trzecie Oko", "thirdeye_desc": "Kliknij [css_useSkill], aby aktywować trzecią osobę", @@ -394,7 +405,7 @@ "no_player": "Nie znaleziono pasującego gracza.", "duplicate_player": "Znaleziono więcej niż jednego gracza o tej samej nazwie.", "selectplayerskill_command": "Wpisz /t", - "selectplayerskill_incorrect_enemy_index": "Nie znaleziono gracza o takim index'ie.", + "selectplayerskill_incorrect_enemy_index": "Nie znaleziono graczy do wyboru.", "skill_not_found_setskill": "Nie znaleziono takiej CHATCOLORS.REDsupermocy", "player_not_found_setskill": "Nie znaleziono takiego CHATCOLORS.REDgracza", @@ -420,7 +431,12 @@ "vote_alredy_voted": "Już zagłosowałeś!", "vote_vote": "Głosowanie", + "bombsite_a": "Strefa detonacji A", + "bombsite_b": "Strefa detonacji B", + "teammate_skills": "Supermoce twoich sojuszników", "summary_start": "======PODSUMOWANIE=Z=OSTATNIEJ=RUNDY======", - "summary_end": "============================================" + "summary_end": "============================================", + + "menu_controlls": "W/S – Przewijanie | E - Wybierz
" } \ No newline at end of file diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pt-br.json b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pt-br.json index 4800a5f..cfe3369 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pt-br.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/pt-br.json @@ -18,7 +18,7 @@ "areareaper_desc": "Você pode escolher um local de bomba para desativar", "areareaper_incorrect_site": "Nenhum local de bomba encontrado.", "areareaper_no_site": "Nenhum local de bomba encontrado.", - "areareaper_select_info": "Escolha o local de bomba que deseja desativar:", + "areareaper_select_info": "Escolha área p/ desativar:", "areareaper_site_disabled": "Local de bomba {0} foi desativado - nenhuma bomba pode ser plantada lá!", "areareaper_used_info": "Seu poder já foi usado.", @@ -66,19 +66,19 @@ "darkness_desc": "Aplica um efeito de escuridão a um inimigo escolhido", "darkness_enemy_info": "Que as luzes se apaguem.", "darkness_player_info": "A escuridão tomou conta do jogador '{0}'.", - "darkness_select_info": "Escolha o jogador ao qual deseja aplicar o efeito de escuridão:", + "darkness_select_info": "Escolha jogador: escuridão:", "deactivator": "Desativador", "deactivator_desc": "Escolha um jogador cuja habilidade você deseja desativar", "deactivator_enemy_info": "Sua habilidade foi desativada.", "deactivator_player_info": "A habilidade do jogador '{0}' foi desativada.", - "deactivator_select_info": "Escolha o jogador cuja habilidade você deseja desativar:", + "deactivator_select_info": "Desativar skill do jogador:", "deaf": "Surdo", "deaf_desc": "Escolha um jogador para silenciar todos os sons", "deaf_enemy_info": "Seus fones de ouvido saíram do jogo.", "deaf_player_info": "O som foi desativado para o jogador '{0}'.", - "deaf_select_info": "Escolha o jogador para quem deseja silenciar todos os sons:", + "deaf_select_info": "Silenciar jogador:", "disarmament": "Desarmamento", "disarmament_desc": "Você tem uma chance aleatória de fazer um inimigo largar sua arma ao acertá-lo", @@ -93,7 +93,7 @@ "duplicator": "Duplicador", "duplicator_desc": "Escolha um jogador para copiar sua habilidade", "duplicator_player_info": "A habilidade do jogador '{0}' foi copiada.", - "duplicator_select_info": "Escolha o jogador cuja habilidade você deseja copiar:", + "duplicator_select_info": "Copiar skill do jogador:", "dwarf": "Anão", "dwarf_desc": "Tamanho de personagem aleatório no início da rodada", @@ -129,6 +129,11 @@ "frozendecoy": "Chamariz Congelante", "frozendecoy_desc": "Seu chamariz congela todos os jogadores próximos", + "gambler": "Apostador", + "gambler_desc": "Selecione uma habilidade da lista.", + "gambler_select_info": "Escolha sua habilidade:", + "gambler_more": "Atualizar por $100", + "ghost": "Fantasma", "ghost_desc": "Você é completamente invisível", @@ -139,7 +144,7 @@ "glitch_desc": "Desativa o radar de um inimigo escolhido", "glitch_enemy_info": "Seu radar foi desativado.", "glitch_player_info": "O radar do jogador '{0}' foi desativado.", - "glitch_select_info": "Escolha o jogador cujo radar você deseja desativar:", + "glitch_select_info": "Desativar radar do jogador:", "glue": "Cola", "glue_desc": "Suas granadas grudam nas paredes", @@ -171,13 +176,19 @@ "jammer_desc": "Escolha um jogador para desativar sua mira", "jammer_enemy_info": "Sua mira foi desativada.", "jammer_player_info": "A mira do jogador '{0}' foi desativada.", - "jammer_select_info": "Escolha o jogador cuja mira você deseja desativar:", + "jammer_select_info": "Desativar mira do jogador:", + + "jester": "Bobo", + "jester_desc": "No modo bobo você não pode causar nem receber dano. Esse modo muda a cada poucos segundos.", + "jester_mode": "Modo Bobo", + "jester_on": "LIG.", + "jester_off": "DESL.", "jumpban": "Sem Pernas", "jumpban_desc": "Escolha um jogador que não poderá pular", "jumpban_enemy_info": "Alguém cortou suas pernas.", "jumpban_player_info": "O jogador '{0}' não pode mais pular.", - "jumpban_select_info": "Escolha o jogador que não poderá pular:", + "jumpban_select_info": "Banir pulo do jogador:", "jumpingjack": "Pula-Pula", "jumpingjack_desc": "Pular restaura saúde", @@ -189,7 +200,7 @@ "lifeswap_desc": "Escolha um jogador para trocar saúde com ele", "lifeswap_enemy_info": "Alguém pegou sua saúde emprestada.", "lifeswap_player_info": "Você trocou saúde com o jogador '{0}'.", - "lifeswap_select_info": "Escolha o jogador com quem deseja trocar saúde:", + "lifeswap_select_info": "Trocar vida com jogador:", "longknife": "Faca Longa", "longknife_desc": "Um ataque com faca primária causa dano independentemente da distância", @@ -201,7 +212,7 @@ "magnifier_desc": "Força a tela do inimigo a ampliar, reduzindo seu campo de visão", "magnifier_enemy_info": "Seu campo de visão foi distorcido!", "magnifier_player_info": "O jogador ‘{0}’ foi forçado a entrar no modo de zoom.", - "magnifier_select_info": "Selecione o jogador cuja tela você deseja ampliar:", + "magnifier_select_info": "Ampliar tela do jogador:", "medic": "Médico", "medic_desc": "Clique em [css_useSkill] para usar uma carga de cura que restaura 50 de saúde", @@ -210,7 +221,7 @@ "moneyswap_desc": "Escolha um jogador para trocar dinheiro com ele", "moneyswap_enemy_info": "A receita federal te pegou.", "moneyswap_player_info": "Você trocou dinheiro com o jogador '{0}'.", - "moneyswap_select_info": "Escolha o jogador com quem deseja trocar dinheiro:", + "moneyswap_select_info": "Trocar dinheiro c/ jogador:", "muhammed": "Muhammed", "muhammed_desc": "Você explode ao morrer, matando jogadores próximos", @@ -257,13 +268,13 @@ "poison_desc": "Escolha um jogador que receberá dano a cada poucos segundos", "poison_enemy_info": "Você foi envenenado.", "poison_player_info": "O jogador '{0}' foi envenenado.", - "poison_select_info": "Escolha o jogador que receberá dano a cada poucos segundos:", + "poison_select_info": "Envenenar jogador:", "primaryban": "Sem Rifles", "primaryban_desc": "Escolha um jogador que não poderá usar rifles", "primaryban_enemy_info": "Você não pode mais usar rifles.", "primaryban_player_info": "O jogador '{0}' não pode mais usar rifles.", - "primaryban_select_info": "Escolha o jogador para proibir de usar rifles:", + "primaryban_select_info": "Banir rifles do jogador:", "prosthesis": "Prótese", "prosthesis_desc": "Braços e pernas são à prova de balas", @@ -353,7 +364,7 @@ "thief_desc": "Você pode roubar uma habilidade de um jogador escolhido", "thief_enemy_info": "Sua habilidade foi roubada.", "thief_player_info": "A habilidade do jogador '{0}' foi roubada.", - "thief_select_info": "Escolha o jogador cuja habilidade você deseja roubar:", + "thief_select_info": "Roubar skill do jogador:", "thirdeye": "Terceiro Olho", "thirdeye_desc": "Clique em [css_useSkill] para ativar a visão em terceira pessoa", @@ -394,7 +405,7 @@ "no_player": "Nenhum jogador correspondente encontrado.", "duplicate_player": "Mais de um jogador encontrado com o mesmo nome.", "selectplayerskill_command": "Digite /t", - "selectplayerskill_incorrect_enemy_index": "Nenhum jogador encontrado com esse índice.", + "selectplayerskill_incorrect_enemy_index": "Não foram encontrados jogadores para selecionar.", "skill_not_found_setskill": "Nenhuma habilidade CHATCOLORS.RED encontrada", "player_not_found_setskill": "Nenhum jogador CHATCOLORS.RED encontrado", @@ -420,7 +431,12 @@ "vote_alredy_voted": "Você já votou!", "vote_vote": "Votar", + "bombsite_a": "Zona de detonação A", + "bombsite_b": "Zona de detonação B", + "teammate_skills": "Habilidades dos seus companheiros de equipe", "summary_start": "=======RESUMO=DA=ÚLTIMA=RODADA=======", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - Rolar | E - Selecionar
" } \ No newline at end of file diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/zh.json b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/zh.json index 84855f6..a4aed64 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/lang/zh.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/lang/zh.json @@ -129,6 +129,11 @@ "frozendecoy": "冰冻诱饵", "frozendecoy_desc": "你的诱饵弹会冻结附近的所有玩家", + "gambler": "赌徒", + "gambler_desc": "从提供的列表中选择一个技能。", + "gambler_select_info": "选择你的技能:", + "gambler_more": "刷新 $100", + "ghost": "幽灵", "ghost_desc": "你完全隐形", @@ -173,6 +178,12 @@ "jammer_player_info": "玩家 '{0}' 的准星已被禁用。", "jammer_select_info": "选择你想禁用其准星的玩家:", + "jester": "小丑", + "jester_desc": "在小丑模式下,你不能造成或受到任何伤害。此模式每隔几秒会变化。", + "jester_mode": "小丑模式", + "jester_on": "开", + "jester_off": "关", + "jumpban": "无腿", "jumpban_desc": "选择一个玩家使其无法跳跃", "jumpban_enemy_info": "有人切断了你的腿。", @@ -394,7 +405,7 @@ "no_player": "未找到匹配的玩家。", "duplicate_player": "找到多个同名玩家。", "selectplayerskill_command": "输入 /t", - "selectplayerskill_incorrect_enemy_index": "未找到该索引的玩家。", + "selectplayerskill_incorrect_enemy_index": "未找到可供选择的玩家。", "skill_not_found_setskill": "未找到 CHATCOLORS.RED 技能", "player_not_found_setskill": "未找到 CHATCOLORS.RED 玩家", @@ -420,7 +431,12 @@ "vote_alredy_voted": "您已投票!", "vote_vote": "投票", + "bombsite_a": "爆轰区A", + "bombsite_b": "爆轰区B", + "teammate_skills": "你队友的技能", "summary_start": "=============上一回合总结==============", - "summary_end": "=======================================" + "summary_end": "=======================================", + + "menu_controlls": "W/S - 滚动 | E - 选择
" } \ No newline at end of file diff --git a/readme-pl.md b/readme-pl.md index d7e008a..1c0fb7b 100644 --- a/readme-pl.md +++ b/readme-pl.md @@ -37,7 +37,7 @@ Dołącz do serwera testowego 3v3 i wypróbuj plugin jRandomSkills: Kupujesz serwer na pukawce? Skorzystaj z mojego [kodu polecającego](https://pukawka.pl/pp,juzlus.html). -## ✨ Aktualne Supermoce (104) +## ✨ Aktualne Supermoce (106)
Poniższa tabela przedstawia wszystkie dostępne supermoce w grze, wraz z ich opisami. @@ -77,6 +77,7 @@ Kupujesz serwer na pukawce? Skorzystaj z mojego [kodu polecającego](https://puk | Krucha Bomba | Strzelanie do bomby powoduje jej uszkodzenie | - | | Ogień Przyjacielski | Strzelanie do członków drużyny leczy ich | - | | Zamrażający Wabik | Twój decoy zamraża wszystkich graczy w pobliżu | - | +| Hazardzista | Wybierz umiejętność z podanej listy | - | | Duszek | Jesteś całkowicie niewidzialny | - | | Glaz | Nie widzisz granatów dymnych | - | | Glitch | Wyłączasz radar wybranemu przeciwnikowi | - | @@ -89,6 +90,7 @@ Kupujesz serwer na pukawce? Skorzystaj z mojego [kodu polecającego](https://puk | Nieskończone Ammo | Otrzymujesz nieskończoną ilość amunicji do wszystkich broni | - | | Stópkarz | Wybierasz gracza, który pozostawi za sobą ślad | - | | Zakłócacz | Wybierasz gracza, dla którego chcesz wyłączyć celownik | - | +| Błazen | W trybie błazna nie możesz zadawać ani otrzymywać obrażeń. Tryb zmienia się co kilka sekund | (10 - 25) s | | Beznogi | Wybierasz gracza, który nie będzie mógł skakać | - | | Pajacyk | Skakanie przywraca zdrowie | - | | Zabójczy Flash | Każdy całkowicie oślepiony twoim granatem umiera (również ty) | - | @@ -240,6 +242,8 @@ Wszystkie sypermoce można dostosować w pliku **`Config.cfg`** znajdującym si // "Alt2", "Speed", "Walk", "Zoom", "Weapon1", // "Weapon2", "Bullrush", "Grenade1", "Grenade2", // "Attack3", "Scoreboard", "Inspect" + "SkillTimeBeforeStart": 7.0, // Ile sekund przed końcem freeze time należy zakończyć + // losowanie umiejętności? (freezetime - SkillTimeBeforeStart) ... }, "SkillsInfo": [ @@ -260,12 +264,34 @@ Wszystkie sypermoce można dostosować w pliku **`Config.cfg`** znajdującym si ## 🔗 Uwzględniona Zależność Plugin korzysta z zawartości następujących projektów: +- [dRandomSkills](https://github.com/jakubbartosik/dRandomSkills) by [Jakub Bartosik (D3X)](https://github.com/jakubbartosik) - system losowych umiejętności - [CS2TraceRay](https://github.com/schwarper/CS2TraceRay) autorstwa [schwarper](https://github.com/schwarper) - system śledzenia promieni (Trace Ray) - [CS2FlashingHtmlHudFix](https://github.com/girlglock/CS2FlashingHtmlHudFix) autorstwa [girlglock](https://github.com/girlglock) - poprawka migotania okienka z supermocą - [ChaseMod](https://github.com/ipsvn/ChaseMod/blob/master/Utils/Memory/CCSMatch.cs) autorstwa [ipsvn](https://github.com/ipsvn) - ustawianie wyniku rund +- [WASDMenuAPI](https://github.com/Interesting-exe/WASDMenuAPI) by [Interesting-exe](https://github.com/Interesting-exe) - API do łatwego tworzenia menu za pomocą klawiszy WASD ## 📋 Lista Zmian +
+v1.1.4 + +- #### Ogólne: + - ###### Do pliku konfiguracyjnego dodano opcję `SkillTimeBeforeStart`, która określa, na ile sekund przed końcem freezetime powinno się zakończyć losowanie umiejętności. + - ###### Umiejętności nie są już wyłączane pod koniec rundy. + - ###### Zmieniono logikę przyznawania umiejętności. + - ###### Zbyt długie pseudonimy są skracane podczas oglądania graczy. + - ###### Wybór gracza został zmieniony z Chat Menu na WSAD Menu. + - ###### Opisy umiejętności z wyborem gracza zostały skrócone. +- #### Poprawki mocy: + - ##### Beznogi + - ###### Umiejętność Beznogi całkowicie wyłącza umiejętność Królik. +- #### Nowe moce: + - ##### Błazen: + - ###### W trybie błazna nie możesz zadawać ani otrzymywać obrażeń. Tryb zmienia się co kilka sekund. + - ##### Hazardzista: + - ###### Wybierz umiejętność z podanej listy. +
+
v1.1.3 diff --git a/readme.md b/readme.md index ebcefe6..8e6791f 100644 --- a/readme.md +++ b/readme.md @@ -38,7 +38,7 @@ Join the 3v3 test server and try out the jRandomSkills plugin: Buying a server on pukawka? Use my [referral code](https://pukawka.pl/pp,juzlus.html). -## ✨ Current Skills (104) +## ✨ Current Skills (106)
The table below lists all available skills in the game, along with their descriptions. @@ -78,6 +78,7 @@ Buying a server on pukawka? Use my [referral code](https://pukawka.pl/pp,juzlus. | Fragile Bomb | Shooting the bomb damages it | - | | Friendly Fire | Shooting teammates heals them | - | | Freezing Decoy | Your decoy freezes all nearby players | - | +| Gambler | Select a skill from the list provided | - | | Ghost | You are completely invisible | - | | Glaz | You can see through smoke grenades | - | | Glitch | Disables the radar for a chosen enemy | - | @@ -90,6 +91,7 @@ Buying a server on pukawka? Use my [referral code](https://pukawka.pl/pp,juzlus. | Infinite Ammo | You receive infinite ammo for all your weapons | - | | Tracker | Choose a player who will leave a trail behind them | - | | Jammer | Choose a player to disable their crosshair | - | +| Jester | In jester mode, you cannot get or take any damage. This mode changes every few seconds | (10 - 25) s | | Legless | Choose a player who cannot jump | - | | Jumping Jack | Jumping restores health | - | | Killer Flash | Anyone fully blinded by your flashbang dies (including you) | - | @@ -240,6 +242,8 @@ All skills can be customized in the **`Config.cfg`** file located in the **`game // "Alt2", "Speed", "Walk", "Zoom", "Weapon1", // "Weapon2", "Bullrush", "Grenade1", "Grenade2", // "Attack3", "Scoreboard", "Inspect" + "SkillTimeBeforeStart": 7.0, // How many seconds before freeze time ends should skills + // drawing be completed? (freezetime - SkillTimeBeforeStart) ... }, "SkillsInfo": [ @@ -260,12 +264,34 @@ All skills can be customized in the **`Config.cfg`** file located in the **`game ## 🔗 Dependency Includes This plugin uses content from the following projects: +- [dRandomSkills](https://github.com/jakubbartosik/dRandomSkills) by [Jakub Bartosik (D3X)](https://github.com/jakubbartosik) - random skills system - [CS2TraceRay](https://github.com/schwarper/CS2TraceRay) by [schwarper](https://github.com/schwarper) - Trace Ray system - [CS2FlashingHtmlHudFix](https://github.com/girlglock/CS2FlashingHtmlHudFix) by [girlglock](https://github.com/girlglock) - a fix for window flickering - [ChaseMod](https://github.com/ipsvn/ChaseMod/blob/master/Utils/Memory/CCSMatch.cs) by [ipsvn](https://github.com/ipsvn) - round score management +- [WASDMenuAPI](https://github.com/Interesting-exe/WASDMenuAPI) by [Interesting-exe](https://github.com/Interesting-exe) - API to easily create WASD menus ## 📋 Changelog +
+v1.1.4 + +- #### General: + - ###### The `SkillTimeBeforeStart` option has been added to the config file, which specifies how many seconds before the end of freeze time the skills drawing should stop. + - ###### Skills are no longer disabled at the end of the round. + - ###### The logic for granting skills has been changed. + - ###### Nicknames that are too long are shortened when spectating players. + - ###### The player selection has been changed via the Chat Menu to the WSAD Menu. + - ###### Skill descriptions with player selection have been shortened. +- #### Skill improvements: + - ##### Legless + - ###### Legless's skill completely disables Bunny's skill. +- #### New skills: + - ##### Jester: + - ###### In jester mode, you cannot get or take any damage. This mode changes every few seconds. + - ##### Gambler: + - ###### Select a skill from the list provided. +
+
v1.1.3