From 46195c2663ee25d276990e2634899052e2b933c3 Mon Sep 17 00:00:00 2001 From: Juzlus Date: Sun, 24 May 2026 23:13:56 +0200 Subject: [PATCH] v1.2.2.b1 --- .../jRandomSkills.csproj | 9 +- .../src/command/Command.cs | 75 +++-- .../src/command/VoteSystem.cs | 4 +- .../src/jRandomSkills.cs | 16 +- .../src/player/BotManager.cs | 77 +++++ jRandomSkills - SRC Files/src/player/Debug.cs | 38 ++- .../src/player/ISkill.cs | 2 - .../src/player/PlayerEvents.cs | 183 +++++++----- .../src/player/PlayerOnTick.cs | 77 +++-- .../src/player/skills/AimLock.cs | 108 ++++--- .../src/player/skills/Aimbot.cs | 63 ++-- .../src/player/skills/Anomaly.cs | 70 +++-- .../src/player/skills/AntyFlash.cs | 21 +- .../src/player/skills/AntyHead.cs | 10 +- .../src/player/skills/AreaReaper.cs | 68 +++-- .../src/player/skills/Armored.cs | 29 +- .../src/player/skills/Assassin.cs | 26 +- .../src/player/skills/Astronaut.cs | 27 +- .../src/player/skills/Bankrupt.cs | 102 ++++--- .../src/player/skills/Baseball.cs | 28 +- .../src/player/skills/Behind.cs | 10 +- .../src/player/skills/BladeMaster.cs | 67 +++-- .../src/player/skills/BunnyHop.cs | 30 +- .../src/player/skills/C4Camouflage.cs | 105 +++++-- .../src/player/skills/CarefulBullets.cs | 97 ++++--- .../src/player/skills/Catapult.cs | 10 +- .../src/player/skills/Chicken.cs | 8 +- .../src/player/skills/ChillOut.cs | 30 +- .../src/player/skills/Cutter.cs | 8 +- .../src/player/skills/Cypher.cs | 47 ++- .../src/player/skills/Darkness.cs | 64 ++-- .../src/player/skills/Dash.cs | 94 +++--- .../src/player/skills/Deactivator.cs | 25 +- .../src/player/skills/Deaf.cs | 34 ++- .../src/player/skills/Disarmament.cs | 10 +- .../src/player/skills/Distancer.cs | 4 +- .../src/player/skills/Dracula.cs | 6 +- .../src/player/skills/Duplicator.cs | 41 +-- .../src/player/skills/Dwarf.cs | 8 +- .../src/player/skills/Earthquake.cs | 221 +++++++------- .../src/player/skills/EnemySpawn.cs | 21 +- .../src/player/skills/ExplosiveShot.cs | 10 +- .../src/player/skills/FalconEye.cs | 28 +- .../src/player/skills/FastReload.cs | 6 +- .../src/player/skills/Flash.cs | 22 +- .../src/player/skills/Fortnite.cs | 32 +- .../src/player/skills/FragileBomb.cs | 8 +- .../src/player/skills/FriendlyFire.cs | 10 +- .../src/player/skills/FrozenDecoy.cs | 20 +- .../src/player/skills/Gambler.cs | 23 +- .../src/player/skills/Ghost.cs | 84 ++++-- .../src/player/skills/Glaz.cs | 6 +- .../src/player/skills/Glitch.cs | 65 +++-- .../src/player/skills/Glue.cs | 5 +- .../src/player/skills/GodMode.cs | 35 ++- .../src/player/skills/Grenadier.cs | 4 +- .../src/player/skills/HealingChicken.cs | 104 ++++--- .../src/player/skills/HealingSmoke.cs | 35 +-- .../src/player/skills/Hermit.cs | 4 +- .../src/player/skills/HolyHandGrenade.cs | 4 +- .../src/player/skills/HomingNades.cs | 21 +- .../src/player/skills/HotBomb.cs | 9 +- .../src/player/skills/Iana.cs | 71 +++-- .../src/player/skills/Illiterate.cs | 16 +- .../src/player/skills/Illusionist.cs | 34 ++- .../src/player/skills/Impostor.cs | 8 +- .../src/player/skills/InfiniteAmmo.cs | 12 +- .../src/player/skills/Jackal.cs | 175 +++++------ .../src/player/skills/Jammer.cs | 43 ++- .../src/player/skills/Jester.cs | 86 +++--- .../src/player/skills/JumpBan.cs | 40 ++- .../src/player/skills/JumpingJack.cs | 11 +- .../src/player/skills/KillerFlash.cs | 10 +- .../src/player/skills/LifeSwap.cs | 19 +- .../src/player/skills/LongKnife.cs | 23 +- .../src/player/skills/LongZeus.cs | 6 +- .../src/player/skills/MagneticDecoy.cs | 18 +- .../src/player/skills/Magneto.cs | 2 +- .../src/player/skills/Magnifier.cs | 67 +++-- .../src/player/skills/Medic.cs | 18 +- .../src/player/skills/Miner.cs | 5 +- .../src/player/skills/MoneySwap.cs | 17 +- .../src/player/skills/Muhammed.cs | 8 +- .../src/player/skills/Mute.cs | 8 +- .../src/player/skills/Ninja.cs | 117 +++++--- .../src/player/skills/NoNades.cs | 6 +- .../src/player/skills/NoRecoil.cs | 8 +- .../src/player/skills/Noclip.cs | 30 +- .../src/player/skills/OneShot.cs | 9 +- .../src/player/skills/OnlyHead.cs | 8 +- .../src/player/skills/PawelJumper.cs | 25 +- .../src/player/skills/Phoenix.cs | 116 ++------ .../src/player/skills/Pilot.cs | 12 +- .../src/player/skills/Planter.cs | 24 +- .../src/player/skills/Poison.cs | 35 ++- .../src/player/skills/PrimaryBan.cs | 46 ++- .../src/player/skills/Prosthesis.cs | 8 +- .../src/player/skills/PsychicDefusing.cs | 12 +- .../src/player/skills/Push.cs | 10 +- .../src/player/skills/Pyro.cs | 9 +- .../src/player/skills/QuickShot.cs | 4 +- .../src/player/skills/RadarHack.cs | 24 +- .../src/player/skills/RandomWeapon.cs | 26 +- .../src/player/skills/ReZombie.cs | 122 ++------ .../src/player/skills/ReactiveArmor.cs | 33 ++- .../src/player/skills/Regeneration.cs | 4 +- .../src/player/skills/Replicator.cs | 28 +- .../src/player/skills/Retreat.cs | 20 +- .../src/player/skills/ReturnToSender.cs | 8 +- .../src/player/skills/RichBoy.cs | 4 +- .../src/player/skills/RobinHood.cs | 6 +- .../src/player/skills/Rubber.cs | 6 +- .../src/player/skills/Saper.cs | 8 +- .../src/player/skills/SecondLife.cs | 7 +- .../src/player/skills/Shade.cs | 14 +- .../src/player/skills/ShortBomb.cs | 6 +- .../src/player/skills/Silent.cs | 7 +- .../src/player/skills/Smoker.cs | 17 +- .../src/player/skills/SniperElite.cs | 68 ++--- .../src/player/skills/Soldier.cs | 15 +- .../src/player/skills/SoundMaker.cs | 78 +++-- .../src/player/skills/Spectator.cs | 62 ++-- .../src/player/skills/SwapPosition.cs | 30 +- .../src/player/skills/Teleporter.cs | 10 +- .../src/player/skills/Thief.cs | 166 +++++++---- .../src/player/skills/ThirdEye.cs | 21 +- .../src/player/skills/Thorns.cs | 27 +- .../src/player/skills/ThrowingKnife.cs | 102 ++++--- .../src/player/skills/ToxicSmoke.cs | 36 +-- .../src/player/skills/Wallhack.cs | 50 ++-- .../src/player/skills/Watchmaker.cs | 5 +- .../src/player/skills/WeaponsSwap.cs | 20 +- .../src/player/skills/Weightless.cs | 5 +- .../src/player/skills/WildThrow.cs | 67 +++-- .../src/player/skills/Zeus.cs | 8 +- jRandomSkills - SRC Files/src/utils/Config.cs | 8 +- .../src/utils/EntityManager.cs | 273 ++++++++++++++++++ .../src/utils/Localization.cs | 2 +- .../src/utils/PlayerManager.cs | 135 +++++++++ .../src/utils/RarityManager.cs | 26 +- .../src/utils/RayTrace.cs | 103 +++++-- .../src/utils/SkillUtils.cs | 134 ++++----- .../tools/RefactorSkills/Program.cs | 148 ++++++++++ .../RefactorSkills/RefactorSkills.csproj | 8 + .../plugins/jRandomSkills/MaxMind.Db.dll | Bin 52224 -> 51200 bytes .../plugins/jRandomSkills/WASDMenuAPI.dll | Bin 16384 -> 16384 bytes .../plugins/jRandomSkills/jRandomSkills.dll | Bin 557568 -> 536064 bytes 147 files changed, 3470 insertions(+), 2161 deletions(-) create mode 100644 jRandomSkills - SRC Files/src/player/BotManager.cs create mode 100644 jRandomSkills - SRC Files/src/utils/EntityManager.cs create mode 100644 jRandomSkills - SRC Files/src/utils/PlayerManager.cs create mode 100644 jRandomSkills - SRC Files/tools/RefactorSkills/Program.cs create mode 100644 jRandomSkills - SRC Files/tools/RefactorSkills/RefactorSkills.csproj diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj index 0953faa..818771c 100644 --- a/jRandomSkills - SRC Files/jRandomSkills.csproj +++ b/jRandomSkills - SRC Files/jRandomSkills.csproj @@ -6,17 +6,20 @@ enable true true + false + + - - + + @@ -29,7 +32,7 @@ - + diff --git a/jRandomSkills - SRC Files/src/command/Command.cs b/jRandomSkills - SRC Files/src/command/Command.cs index 50f922a..623fe45 100644 --- a/jRandomSkills - SRC Files/src/command/Command.cs +++ b/jRandomSkills - SRC Files/src/command/Command.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.menu; using src.player; @@ -76,19 +75,23 @@ namespace src.command [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] private static void Command_UseTypeSkill(CCSPlayerController? player, CommandInfo _) { - if (player == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + player = PlayerManager.GetPlayerEvent(player); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo == null || playerInfo.IsDrawing) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; + + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (SkillsInfo.GetValue(playerInfo.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) return; string[] commands = _.ArgString.Trim().Split(" ", StringSplitOptions.RemoveEmptyEntries); Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill}"); + if (commands == null || commands.Length == 0) Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]); else @@ -100,9 +103,9 @@ namespace src.command { Debug.WriteToDebug($"Player {player?.PlayerName} used the css_setskill {command.ArgString} command."); if (!string.IsNullOrEmpty(config.NormalCommands.SetSkillCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.SetSkillCommand.Permissions)) return; - var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => !p.IsBot + var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => p != null && p.IsValid && (p.SteamID.ToString().Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase) - || p.PlayerName.Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase))); + || p.PlayerName.Equals(command.GetArg(1), StringComparison.OrdinalIgnoreCase))); if (command.ArgCount < 2) { @@ -140,7 +143,7 @@ namespace src.command return; } - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == targetPlayer.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(targetPlayer.Index); if (skillPlayer != null) { Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]); @@ -246,7 +249,7 @@ namespace src.command else { Server.ExecuteCommand("mp_restartgame 2"); - Instance?.AddTimer(2.0f, () => Localization.PrintTranslationToChatAll($" {ChatColors.Green}{{0}}", ["game_start"])); + Instance?.AddTimer(2.0f, () => Localization.PrintTranslationToChatAll($" {ChatColors.Green}{{0}}", ["game_start"]), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } } @@ -269,7 +272,7 @@ namespace src.command foreach (var player in Utilities.GetPlayers()) if (Instance.IsPlayerValid(player) && new CsTeam[] { CsTeam.CounterTerrorist, CsTeam.Terrorist }.Contains(player.Team)) player.SwitchTeam(player.Team == CsTeam.Terrorist ? CsTeam.CounterTerrorist : CsTeam.Terrorist); - Server.ExecuteCommand($"mp_restartgame 1"); + Server.ExecuteCommand($"endround"); } [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] @@ -374,7 +377,7 @@ namespace src.command if (!string.IsNullOrEmpty(config.NormalCommands.BotPlace.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.BotPlace.Permissions)) return; var pawn = player.PlayerPawn.Value; - if (!player.PawnIsAlive || pawn.AbsOrigin == null || pawn.AbsRotation == null) return; + if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE || pawn.AbsOrigin == null || pawn.AbsRotation == null) return; if (!int.TryParse(command.GetArg(1), out int botSlot)) botSlot = -1; @@ -403,7 +406,7 @@ namespace src.command if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (!string.IsNullOrEmpty(config.NormalCommands.HudCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.HudCommand.Permissions)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo == null) return; playerInfo.DisplayHUD = !playerInfo.DisplayHUD; @@ -452,9 +455,9 @@ namespace src.command { Debug.WriteToDebug($"Player {player?.PlayerName} used the css_setstaticskill {command.ArgString} command."); if (!string.IsNullOrEmpty(config.NormalCommands.SetStaticSkillCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.SetStaticSkillCommand.Permissions)) return; - var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => !p.IsBot + var targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => p != null && p.IsValid && (p.SteamID.ToString().Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase) - || p.PlayerName.Equals(command.GetArg(1), StringComparison.CurrentCultureIgnoreCase))); + || p.PlayerName.Equals(command.GetArg(1), StringComparison.OrdinalIgnoreCase))); if (command.ArgCount < 2) { @@ -495,7 +498,7 @@ namespace src.command return; } - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == targetPlayer.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(targetPlayer.Index); if (skillPlayer != null) { Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]); @@ -504,9 +507,9 @@ namespace src.command skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); if (skill.Skill == src.player.Skills.None) - Event.staticSkills.TryRemove(targetPlayer.SteamID, out _); + Event.staticSkills.TryRemove(targetPlayer.Index, out _); else - Event.staticSkills.TryAdd(targetPlayer.SteamID, skill); + Event.staticSkills.TryAdd(targetPlayer.Index, skill); Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); if (player == null) @@ -593,32 +596,58 @@ namespace src.command var skillsList = SkillData.Skills.OrderBy(s => s.Skill.ToString()).ToList(); if (skillsList.Count == 0) return; - nextSkill.TryGetValue(player.Index, out int currentIndex); + string playerString = command.GetArg(1); + CCSPlayerController? targetPlayer = null; + + if (!string.IsNullOrEmpty(playerString)) + { + targetPlayer = Utilities.GetPlayers().FirstOrDefault(p => p != null && p.IsValid + && (p.SteamID.ToString().Equals(playerString, StringComparison.CurrentCultureIgnoreCase) + || p.PlayerName.Equals(playerString, StringComparison.OrdinalIgnoreCase))); + + if (targetPlayer == null) + { + if (player == null) + { + Server.PrintToConsole(Localization.GetTranslation("player_not_found_setskill")); + return; + } + SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill")); + return; + } + } + + if (targetPlayer == null) + return; + + nextSkill.TryGetValue(targetPlayer.Index, out int currentIndex); int nextIndex = (currentIndex + 1) % skillsList.Count; - string arg = command.GetArg(1); + string arg = command.GetArg(2); if (!string.IsNullOrEmpty(arg)) { if (arg == "-1") nextIndex--; + else if (int.TryParse(arg, out int newIndex)) + nextIndex = newIndex; else - nextIndex = int.Parse(arg); + return; } var skill = skillsList[nextIndex]; player.PrintToChat(nextIndex.ToString()); - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(targetPlayer!.Index); if (skillPlayer == null) return; - Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]); + Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]); skillPlayer.Skill = skill.Skill; skillPlayer.SpecialSkill = Skills.None; - nextSkill[player.Index] = nextIndex; + nextSkill[targetPlayer.Index] = nextIndex; - Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); + Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); if (skill.Display) diff --git a/jRandomSkills - SRC Files/src/command/VoteSystem.cs b/jRandomSkills - SRC Files/src/command/VoteSystem.cs index 801b7c0..b6908f8 100644 --- a/jRandomSkills - SRC Files/src/command/VoteSystem.cs +++ b/jRandomSkills - SRC Files/src/command/VoteSystem.cs @@ -22,7 +22,7 @@ namespace src.command vote.SetActive(false); vote.TimeToNextSameVoting = vote.TimeToNextVoting; Localization.PrintTranslationToChatAll($" {ChatColors.Red}{{0}}", ["vote_timeout"], [commandName]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } private static VoteData? CreateVote(VoteType voteType, string? args = null) @@ -49,7 +49,7 @@ namespace src.command { if (!votes.ContainsKey(vote)) return; votes.TryRemove(vote, out _); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); return vote; } diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index edde5c6..7db762b 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -28,7 +28,7 @@ namespace src public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleAuthor => "D3X, Juzlus"; public override string ModuleDescription => "Plugin adds random skills every round for CS2 by D3X. Modified by Juzlus."; - public override string ModuleVersion => "1.2.1.b9"; + public override string ModuleVersion => "1.2.2.b1"; public override void Load(bool hotReload) { @@ -43,6 +43,7 @@ namespace src Command.Load(); WASDMenuAPI.WASDMenuAPI.LoadPlugin(Instance, hotReload); LoadAllSkills(); + PlayerManager.SyncWithPlugin(Instance); Instance.RegisterListener(LoadManifest); @@ -217,7 +218,7 @@ namespace src Console.ForegroundColor = (ConsoleColor)CS2ConsoleColors.Cyan; Console.Write(", HtmlHudFix: "); Console.ForegroundColor = (ConsoleColor)CS2ConsoleColors.LightBlue; - Console.WriteLine(Config.LoadedConfig.FlashingHtmlHudFix); + Console.WriteLine(Config.LoadedConfig.EnableFlashingHtmlHudFix); // Dependences Console.ForegroundColor = (ConsoleColor)CS2ConsoleColors.Cyan; @@ -295,12 +296,21 @@ namespace src return null; } } + + /// + /// Gets a player info by index. O(n) lookup - consider caching if called frequently. + /// + internal jSkill_PlayerInfo? GetPlayerInfoByIndex(uint playerIndex) + { + return SkillPlayer.FirstOrDefault(p => p.PlayerIndex == playerIndex); + } } public class jSkill_PlayerInfo { - public required ulong SteamID { get; set; } + public required bool IsBot { get; set; } public required string PlayerName { get; set; } + public required uint PlayerIndex { get; set; } public Skills Skill { get; set; } public Skills SpecialSkill { get; set; } public float? SkillChance { get; set; } diff --git a/jRandomSkills - SRC Files/src/player/BotManager.cs b/jRandomSkills - SRC Files/src/player/BotManager.cs new file mode 100644 index 0000000..3a0d2cd --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/BotManager.cs @@ -0,0 +1,77 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Timers; +using CounterStrikeSharp.API.Modules.Utils; +using static src.jRandomSkills; +using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; + +namespace src.utils +{ + public static class BotManager + { + private static Timer? _skillTimer; + private static Timer? _rotationTimer; + private static readonly Random _random = new(); + + private const float SkillInterval = 2f; + private const float RotationInterval = 45f; + + public static void Initialize() + { + if (!Config.LoadedConfig.EnableBotSkills) return; + + Stop(); + _skillTimer = Instance.AddTimer(SkillInterval, OnBotUseSkillTimer, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); + + if (!Config.LoadedConfig.EnableBotKickDebug) return; + + _rotationTimer = Instance.AddTimer(RotationInterval, OnBotRotationTimer, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); + } + + public static void Stop() + { + if (!Config.LoadedConfig.EnableBotSkills) return; + + _skillTimer?.Kill(); + _skillTimer = null; + + if (!Config.LoadedConfig.EnableBotKickDebug) return; + + _rotationTimer?.Kill(); + _rotationTimer = null; + } + + private static void OnBotUseSkillTimer() + { + var activeBots = Utilities.GetPlayers() + .Where(p => p != null && p.IsValid && p.IsBot && !p.IsHLTV && p.LifeState == (byte)LifeState_t.LIFE_ALIVE && p.Team != CsTeam.Spectator) + .ToList(); + + if (activeBots.Count == 0) return; + + var randomBot = activeBots[_random.Next(activeBots.Count)]; + if (randomBot == null || !randomBot.IsValid) return; + if (randomBot.PlayerPawn?.Value == null || !randomBot.PlayerPawn.Value.IsValid || randomBot.PlayerPawn.Value.IsDefusing) return; + + var bot_info = PlayerManager.GetPlayerByIndex(randomBot.Index); + if (bot_info == null) return; + + Instance.SkillAction(bot_info.Skill.ToString(), "UseSkill", [randomBot]); + } + + private static void OnBotRotationTimer() + { + var allBots = Utilities.GetPlayers() + .Where(p => p != null && p.IsValid && p.IsBot && !p.IsHLTV) + .ToList(); + + if (allBots.Count > 0) + { + var botToKick = allBots[_random.Next(allBots.Count)]; + Server.ExecuteCommand($"kickid {botToKick.UserId}"); + } + + Server.NextFrame(() => Server.ExecuteCommand("bot_add")); + } + } +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/Debug.cs b/jRandomSkills - SRC Files/src/player/Debug.cs index a6427b8..c6b91fc 100644 --- a/jRandomSkills - SRC Files/src/player/Debug.cs +++ b/jRandomSkills - SRC Files/src/player/Debug.cs @@ -19,7 +19,7 @@ namespace src.player sessionId = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}"; Instance.RegisterEventHandler((@event, info) => { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return HookResult.Continue; WriteToDebug($"{(player.IsBot ? "Bot" : "Player")} {player.PlayerName} joined the game."); return HookResult.Continue; @@ -27,7 +27,7 @@ namespace src.player Instance.RegisterEventHandler((@event, info) => { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return HookResult.Continue; WriteToDebug($"{(player.IsBot ? "Bot" : "Player")} {player.PlayerName} disconnected."); return HookResult.Continue; @@ -59,8 +59,8 @@ namespace src.player Instance.RegisterEventHandler((@event, info) => { - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); if (victim != null) { if (attacker != null) @@ -90,7 +90,7 @@ namespace src.player Instance.RegisterEventHandler((@event, info) => { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return HookResult.Continue; WriteToDebug($"{(player.IsBot ? "Bot" : "Player")} {player.PlayerName} fired a shot."); return HookResult.Continue; @@ -116,10 +116,10 @@ namespace src.player if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) return HookResult.Continue; - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - CCSPlayerController victim = victimPawn.Controller.Value.As(); + CCSPlayerController attacker = PlayerManager.GetPlayerEvent(attackerPawn.Controller.Value.As())!; + CCSPlayerController victim = PlayerManager.GetPlayerEvent(victimPawn.Controller.Value.As())!; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo == null) return HookResult.Continue; WriteToDebug($"{(victim.IsBot ? "Bot" : "Player")} {victim.PlayerName} took damage from {(attacker.IsBot ? "bot" : "player")} {attacker.PlayerName}."); @@ -131,11 +131,33 @@ namespace src.player if (Config.LoadedConfig.DebugMode != true) return; + // GetAllEntityIndexes(); + string filename = $"debug_{sessionId}.txt"; string path = Path.Combine(debugFolder, filename); Directory.CreateDirectory(debugFolder); File.AppendAllText(path, $"[{DateTime.Now:dd.MM.yyyy HH:mm:ss}] {message}{Environment.NewLine}", System.Text.Encoding.UTF8); } + + private static void GetAllEntityIndexes() + { + if (Instance.GameRules == null) return; + + var entities = Utilities.GetAllEntities(); + + foreach (var entity in entities) + if (entity != null && entity.IsValid && !string.IsNullOrEmpty(entity.DesignerName)) + { + string text = $"Entity: {entity.DesignerName}, ID: {entity.Index}"; + Console.WriteLine(text); + + string filename = $"debug_{sessionId}.txt"; + string path = Path.Combine(debugFolder, filename); + + Directory.CreateDirectory(debugFolder); + File.AppendAllText(path, text, System.Text.Encoding.UTF8); + } + } } } \ 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 969fdf8..f1df3a4 100644 --- a/jRandomSkills - SRC Files/src/player/ISkill.cs +++ b/jRandomSkills - SRC Files/src/player/ISkill.cs @@ -85,7 +85,6 @@ public enum Skills Dracula, Duplicator, Dwarf, - Earthquake, EnemySpawn, ExplosiveShot, FalconEye, @@ -102,7 +101,6 @@ public enum Skills Glue, GodMode, Grenadier, - HealingChicken, HealingSmoke, Hermit, HolyHandGrenade, diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index b394b35..23a1cd6 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -2,12 +2,14 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Admin; +using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Events; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; +using Microsoft.Extensions.Logging; using RayTraceAPI; using src.player.skills; using src.utils; @@ -34,8 +36,8 @@ namespace src.player public static readonly SkillsInfo.DefaultSkillInfo[] counterterroristSkills = [.. SkillsInfo.LoadedConfig.Where(s => s.OnlyTeam == (int)CsTeam.CounterTerrorist)]; private static readonly SkillsInfo.DefaultSkillInfo[] allTeamsSkills = [.. SkillsInfo.LoadedConfig.Where(s => s.OnlyTeam == 0)]; - private static readonly ConcurrentDictionary> playersSkills = []; - public static readonly ConcurrentDictionary staticSkills = []; + private static readonly ConcurrentDictionary> playersSkills = []; + public static readonly ConcurrentDictionary staticSkills = []; private static readonly object setLock = new(); private static readonly MemoryFunctionVoid DropWeaponFunc = new(GameData.GetSignature("CCSPlayerController_HandleCommandDrop")); @@ -74,6 +76,7 @@ namespace src.player Instance.RegisterListener(CheckUseSkill); Instance.RegisterListener(EntitySpawned); Instance.RegisterListener(OnTick); + Instance.RegisterListener(OnPlayerConnectedBot); Instance.HookUserMessage(208, PlayerMakeSound); VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); @@ -96,7 +99,7 @@ namespace src.player const int attempts = 6; for (int attempt = 0; attempt < attempts; attempt++) { - var rolled = RarityManager.RollRarity(); + var (roll, rolled) = RarityManager.RollRarity(); var filtered = candidates.Where(s => { @@ -117,7 +120,7 @@ namespace src.player }).ToList(); if (filtered.Count > 0) - return filtered[Instance.Random.Next(filtered.Count)]; + return filtered[Random.Shared.Next(filtered.Count)]; } var fallback = candidates.Where(s => @@ -131,9 +134,9 @@ namespace src.player }).ToList(); if (fallback.Count > 0) - return fallback[Instance.Random.Next(fallback.Count)]; + return fallback[Random.Shared.Next(fallback.Count)]; - return candidates[Instance.Random.Next(candidates.Count)]; + return candidates[Random.Shared.Next(candidates.Count)]; } private static HookResult PlayerMakeSound(UserMessage um) @@ -402,6 +405,10 @@ namespace src.player foreach (string skillName in activeSkills) Instance.SkillAction(skillName, "OnTakeDamage", [h]); + + if (Fortnite.skillInThisRound == true && !activeSkills.Any(s => s == "Fortnite")) + Instance.SkillAction("Fortnite", "OnTakeDamage", [h]); + return HookResult.Continue; } } @@ -526,17 +533,21 @@ namespace src.player } } - private static HookResult PlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info) + private static void OnPlayerConnectedBot(int playerSlot) { lock (setLock) { - var player = @event.Userid; - if (player == null || !player.IsValid) return HookResult.Continue; + var player = Utilities.GetPlayerFromSlot(playerSlot); + if (player == null || !player.IsValid) return; - Instance.SkillPlayer.Add(new jSkill_PlayerInfo + if (player.IsBot && !Config.LoadedConfig.EnableBotSkills) + return; + + var playerInfo = new jSkill_PlayerInfo { - SteamID = player.SteamID, + IsBot = player.IsBot, PlayerName = player.PlayerName, + PlayerIndex = player.Index, Skill = Skills.None, SpecialSkill = Skills.None, IsDrawing = false, @@ -544,7 +555,18 @@ namespace src.player PrintHTML = null, DisplayHUD = true, SkillUsed = false, - }); + }; + Instance.SkillPlayer.Add(playerInfo); + PlayerManager.Register(playerInfo); + } + } + + private static HookResult PlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info) + { + lock (setLock) + { + var player = PlayerManager.GetPlayerEvent(@event.Userid); + if (player == null || !player.IsValid) return HookResult.Continue; string welcomeMsg = player.GetTranslation("welcome_message", "welcome"); foreach (string line in welcomeMsg.Split("\n")) @@ -562,16 +584,18 @@ namespace src.player { lock (setLock) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return HookResult.Continue; - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) return HookResult.Continue; Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]); var items = Instance.SkillPlayer.ToList(); - Instance.SkillPlayer = [.. items.Where(p => p.SteamID != skillPlayer.SteamID)]; + Instance.SkillPlayer = [.. items.Where(p => p.PlayerIndex != player.Index)]; + PlayerManager.UnregisterPlayer(player.Index); + EntityManager.DestroyPlayerEntities(player.Index); return HookResult.Continue; } @@ -586,16 +610,10 @@ namespace src.player string commandName = text.StartsWith('!') || text.StartsWith('/') ? text[1..] : text; - foreach (var cmd in Instance.CommandDefinitions) - Server.PrintToChatAll("1. " + cmd.Name); - - foreach (var cmd in Instance.CommandListeners.Keys) - Server.PrintToChatAll("2. " + cmd?.Target?.ToString()); - var player = Utilities.GetPlayerFromUserid(userID); if (player == null || !player.IsValid) return HookResult.Continue; - var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) return HookResult.Continue; var temp = skillPlayer.SkillHudExpired; @@ -605,7 +623,7 @@ namespace src.player { if (skillPlayer.SkillHudExpired == DateTime.MinValue) skillPlayer.SkillHudExpired = temp; - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); return HookResult.Continue; } @@ -614,10 +632,10 @@ namespace src.player { lock (setLock) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return HookResult.Continue; - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) return HookResult.Continue; if (setSkillTimer != null) @@ -642,11 +660,11 @@ namespace src.player { bool isWarmup = Instance.GameRules != null && Instance.GameRules.WarmupPeriod == true; isTransmitRegistered = false; - Instance.AddTimer(.1f, () => DisableAll()); + Instance.AddTimer(.1f, () => DisableAll(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) + foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) continue; skillPlayer.IsDrawing = !isWarmup; skillPlayer.PrintHTML = null; @@ -659,7 +677,7 @@ namespace src.player setSkillTimer?.Kill(); float timeToDraw = (Instance?.GameRules?.TeamIntroPeriod == true ? 7 : 0) + Math.Max(freezetime - Config.LoadedConfig.SkillTimeBeforeStart, 0) + .3f; - setSkillTimer = Instance?.AddTimer(timeToDraw, SetSkill); + setSkillTimer = Instance?.AddTimer(timeToDraw, SetSkill, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); return HookResult.Continue; } } @@ -668,9 +686,14 @@ namespace src.player { lock (setLock) { - foreach (var player in Utilities.GetPlayers().Where(p => p != null && !p.IsBot && p.IsValid)) + Fortnite.skillInThisRound = false; + EntityManager.DestroyAllTracked(); + + foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid)) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) continue; Instance.SkillAction(playerInfo.Skill.ToString(), "DisableSkill", [player]); @@ -681,10 +704,28 @@ namespace src.player playerInfo.PrintHTML = null; playerInfo.SkillChance = 1; playerInfo.SkillUsed = false; + + RestorePlayer(player); } } } + public static void RestorePlayer(CCSPlayerController? player) + { + if (player == null || !player.IsValid) return; + + var pawn = player.PlayerPawn?.Value; + if (pawn == null || !pawn.IsValid) return; + + pawn.HideHUD = (uint)(pawn.HideHUD & ~(1 << 8)); + Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_iHideHUD"); + + player.ReplicateConVar("sv_disable_radar", "0"); + + player.DesiredFOV = 0; + Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); + } + public static void OnMapChange() { lock (setLock) @@ -693,19 +734,21 @@ namespace src.player Instance.AddTimer(.1f, () => { DisableAll(); ConVar.Find("sv_legacy_jump")?.SetValue("1"); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); Instance.RemoveListener(CheckTransmit); playersSkills.Clear(); staticSkills.Clear(); ctSkill = noneSkill; tSkill = noneSkill; allSkill = noneSkill; + PlayerManager.Clear(); } } private static HookResult RoundEnd(EventRoundEnd @event, GameEventInfo info) { Illiterate.Disable(); + lock (setLock) { foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid)) @@ -717,7 +760,7 @@ namespace src.player string skillsText = ""; foreach (var _player in _players) { - var _playerSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == _player.SteamID); + var _playerSkill = PlayerManager.GetPlayerByIndex(_player.Index); if (_playerSkill != null) { var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == _playerSkill.Skill); @@ -735,13 +778,13 @@ namespace src.player SkillUtils.PrintToChat(player, text, title: player.GetTranslation("teammate_skills"), border: ""); SkillUtils.PrintToChat(player, string.Empty, border: "b"); } - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } if (Config.LoadedConfig.DisableSkillsOnRoundEnd) { isTransmitRegistered = false; - Instance.AddTimer(1f, () => DisableAll()); + Instance.AddTimer(1f, () => DisableAll(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); Instance.RemoveListener(CheckTransmit); } return HookResult.Continue; @@ -760,18 +803,18 @@ namespace src.player foreach (string skillName in activeSkills) Instance.SkillAction(skillName, "PlayerDeath", [@event]); - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); if (victim == null || attacker == null) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index); if (playerInfo == null || playerInfo.IsDrawing) return HookResult.Continue; Instance.SkillAction(playerInfo.Skill.ToString(), "DisableSkill", [victim]); if (victim == attacker) return HookResult.Continue; if (Config.LoadedConfig.KillerSkillChatInfo) { - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo != null) { var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == attackerInfo.Skill); @@ -790,7 +833,7 @@ namespace src.player private static void CheckUseSkill(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released) { - if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; lock (setLock) { @@ -802,7 +845,7 @@ namespace src.player if ((pressed & skillButton) == 0) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null || playerInfo.IsDrawing) return; if (SkillsInfo.GetValue(playerInfo.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) @@ -872,14 +915,16 @@ namespace src.player setSkillTimer = null; lock (setLock) { - if (Instance?.GameRules != null && Instance.GameRules.WarmupPeriod == true) + if (Instance == null) return; + + if (Instance.GameRules != null && Instance.GameRules.WarmupPeriod == true) { setSkillTimer?.Kill(); return; } var validPlayers = Utilities.GetPlayers() - .Where(p => p != null && p.IsValid && !p.IsBot && !p.IsHLTV) + .Where(p => p != null && p.IsValid && !p.IsHLTV) .Where(p => { try { return p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist; } catch { return false; } @@ -918,7 +963,7 @@ namespace src.player var teammates = validPlayers.Where(p => p != null && p.IsValid && p.Team == player.Team && p != player).ToList(); string teammateSkills = ""; - var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) continue; skillPlayer.IsDrawing = false; @@ -935,7 +980,8 @@ namespace src.player { List skillList = [.. SkillData.Skills]; skillList.RemoveAll(s => s?.Skill == Skills.None); - skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); + if (!player.IsBot) + skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); if (gameMode != Config.GameModes.FullRandom) skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill); @@ -951,7 +997,7 @@ namespace src.player else skillList.RemoveAll(s => terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.SteamID, out ConcurrentBag? skills)) + if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.Index, out ConcurrentBag? skills)) { skillList.RemoveAll(s => skills.Any(s2 => s2.Skill == s.Skill)); if (skillList.Count == 0) skills.Clear(); @@ -961,10 +1007,10 @@ namespace src.player if (gameMode == Config.GameModes.NoRepeat) { - if (playersSkills.TryGetValue(player.SteamID, out ConcurrentBag? value)) + if (playersSkills.TryGetValue(player.Index, out ConcurrentBag? value)) value.Add(randomSkill); else - playersSkills.TryAdd(player.SteamID, [randomSkill]); + playersSkills.TryAdd(player.Index, [randomSkill]); } } else if (gameMode == Config.GameModes.TeamSkills) @@ -984,7 +1030,7 @@ namespace src.player skillPlayer.Skill = randomSkill.Skill; skillPlayer.SpecialSkill = Skills.None; - if (randomSkill != null && randomSkill.Skill != Skills.None) + if (randomSkill.Skill != Skills.None) { if (assignmentCounts.TryGetValue(randomSkill.Skill, out var cnt)) assignmentCounts[randomSkill.Skill] = cnt + 1; else assignmentCounts[randomSkill.Skill] = 1; @@ -999,17 +1045,19 @@ namespace src.player if (randomSkill.Display) SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p != null && p.IsValid && p.Team == player.Team && p != player) ? "tb" : "t"); if (SkillsInfo.GetValue(randomSkill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Config.LoadedConfig.SkillTimeBeforeStart, () => { - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == randomSkill.Skill) == null) return; + if (PlayerManager.GetPlayerByIndex(player!.Index)?.Skill != randomSkill.Skill) return; Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); else + { Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", [player]); - }); + } + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\"."); @@ -1027,7 +1075,7 @@ namespace src.player foreach (var teammate in teammates) { - var teammateInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID); + var teammateInfo = PlayerManager.GetPlayerByIndex(teammate.Index); if (teammateInfo != null && teammateInfo?.Skill != null) { var skillInfo = SkillData.Skills.FirstOrDefault(p => p.Skill == teammateInfo.Skill); @@ -1043,7 +1091,7 @@ namespace src.player SkillUtils.PrintToChat(player, text, title: player.GetTranslation("teammate_skills"), border: ""); SkillUtils.PrintToChat(player, string.Empty, title: player.GetTranslation("teammate_skills"), border: "b"); } - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } } } @@ -1053,7 +1101,7 @@ namespace src.player { lock (setLock) { - var validPlayers = Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist).ToList(); + var validPlayers = Utilities.GetPlayers().Where(p => p != null && p.IsValid && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist).ToList(); if (Config.LoadedConfig.GameMode == (int)Config.GameModes.TeamSkills) { @@ -1067,7 +1115,7 @@ namespace src.player } if (player == null) return; - var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) return; skillPlayer.IsDrawing = false; @@ -1081,13 +1129,14 @@ namespace src.player if (Instance?.GameRules != null && Instance?.GameRules.WarmupPeriod == false) { Config.GameModes gameMode = (Config.GameModes)Config.LoadedConfig.GameMode; - if (staticSkills.TryGetValue(player.SteamID, out var staticSkill)) + if (staticSkills.TryGetValue(player.Index, out var staticSkill)) randomSkill = staticSkill; else if (gameMode == Config.GameModes.Normal || gameMode == Config.GameModes.FullRandom || gameMode == Config.GameModes.NoRepeat) { List skillList = [.. SkillData.Skills]; skillList.RemoveAll(s => s?.Skill == Skills.None); - skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); + if (!player.IsBot) + skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); if (gameMode != Config.GameModes.FullRandom) skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill); @@ -1103,7 +1152,7 @@ namespace src.player else skillList.RemoveAll(s => terroristSkills.Any(s2 => s2.Name == s.Skill.ToString())); - if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.SteamID, out ConcurrentBag? skills)) + if (gameMode == Config.GameModes.NoRepeat && playersSkills.TryGetValue(player.Index, out ConcurrentBag? skills)) { skillList.RemoveAll(s => skills.Any(s2 => s2.Skill == s.Skill)); if (skillList.Count == 0) skills.Clear(); @@ -1133,13 +1182,13 @@ namespace src.player } } - if (randomSkill.Display && Config.LoadedConfig.YourSkillChatInfo) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); - skillPlayer.Skill = randomSkill.Skill; skillPlayer.SpecialSkill = Skills.None; + if (randomSkill.Display && Config.LoadedConfig.YourSkillChatInfo) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", + border: !Utilities.GetPlayers().Any(p => p != null && p.IsValid && p.Team == player.Team && p != player) ? "tb" : "t"); + if (randomSkill.Skill == Skills.Illiterate) Illiterate.Enable(); @@ -1148,12 +1197,12 @@ namespace src.player if (SkillsInfo.GetValue(randomSkill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Config.LoadedConfig.SkillTimeBeforeStart, () => { - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == randomSkill.Skill) == null) return; + if (PlayerManager.GetPlayerByIndex(player!.Index)?.Skill != randomSkill.Skill) return; Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); else Instance?.SkillAction(randomSkill.Skill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\"."); skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); diff --git a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs index 7219e93..ba7ac98 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using System.Linq; using static CounterStrikeSharp.API.Core.Listeners; using static src.jRandomSkills; @@ -16,49 +15,62 @@ namespace src.player Instance.RegisterListener(() => { UpdateGameRules(); - var players = Utilities.GetPlayers().ToArray(); - foreach (var player in players) + + foreach (var player in Utilities.GetPlayers()) + { if (player != null && player.IsValid) UpdatePlayerHud(player); + } }); Instance.RegisterListener(OnMapStart); + Instance.RegisterListener(OnMapEnd); } private static void OnMapStart(string mapName) { Instance.GameRules = null; Event.OnMapChange(); + BotManager.Initialize(); + } + + private static void OnMapEnd() + { + BotManager.Stop(); } private static void InitializeGameRules() { if (Instance.GameRules != null) return; var gameRulesProxy = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").FirstOrDefault(); + if (gameRulesProxy != null) - Instance.GameRules = gameRulesProxy?.GameRules; + Instance.GameRules = gameRulesProxy.GameRules; } private static void UpdateGameRules() { - if (Instance?.GameRules == null || Instance?.GameRules?.Handle == IntPtr.Zero) + if (Instance?.GameRules == null || Instance.GameRules.Handle == IntPtr.Zero) InitializeGameRules(); - else if (Instance != null && Config.LoadedConfig.FlashingHtmlHudFix && !Instance.GameRules.WarmupPeriod) - Instance.GameRules.GameRestart = Instance.GameRules?.RestartRoundTime < Server.CurrentTime; + else if (Instance != null && Config.LoadedConfig.EnableFlashingHtmlHudFix && !Instance.GameRules.WarmupPeriod) + Instance.GameRules.GameRestart = Instance.GameRules.RestartRoundTime < Server.CurrentTime; } private static void UpdatePlayerHud(CCSPlayerController player) { - if (player == null || !player.IsValid) return; + if (player == null || !player.IsValid || player.IsBot) return; + + var skillPlayer = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); + if (skillPlayer == null || !skillPlayer.DisplayHUD) return; var now = DateTime.Now; - var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (skillPlayer == null || !skillPlayer.DisplayHUD) return; + if (player.PawnIsAlive && skillPlayer.SkillHudExpired < now) return; string infoLine = string.Empty; string skillLine = string.Empty; string remainingLine = string.Empty; + bool showDescriptionHUD = skillPlayer.SkillDescriptionHudExpired >= now; bool isDescription = true; @@ -72,10 +84,12 @@ namespace src.player else if (skillPlayer.IsDrawing && player.PawnIsAlive) { int skillCount = skills.Count; + if (skillCount > 0) { var skillsArray = skills.ToArray(); var randomSkill = skillsArray[Instance.Random.Next(skillCount)]; + infoLine = player.GetTranslation("drawing_skill"); skillLine = $"{player.GetSkillName(randomSkill.Skill)}"; } @@ -85,61 +99,70 @@ namespace src.player if (player.PawnIsAlive) { var skillInfo = skills.FirstOrDefault(s => s.Skill == skillPlayer.Skill); + if (skillInfo != null) { infoLine = player.GetTranslation("your_skill"); skillLine = $"{player.GetSkillName(skillInfo.Skill, skillPlayer.SkillChance)}"; + if (skillInfo.Skill != Skills.None) { remainingLine = string.IsNullOrEmpty(skillPlayer.PrintHTML) ? (showDescriptionHUD ? player.GetSkillDescription(skillInfo.Skill, skillPlayer.SkillChance) : "") : skillPlayer.PrintHTML; + isDescription = string.IsNullOrEmpty(skillPlayer.PrintHTML); } } } else { - if ((player.Team is CsTeam.Spectator or CsTeam.None && Config.LoadedConfig.DisableSpectateHUD) || AdminManager.PlayerHasPermissions(player, Config.LoadedConfig.DisableHUDOnDeathPermission)) + if ((player.Team is CsTeam.Spectator or CsTeam.None && Config.LoadedConfig.DisableSpectateHUD) + || AdminManager.PlayerHasPermissions(player, Config.LoadedConfig.DisableHUDOnDeathPermission)) return; var pawn = player.Pawn.Value; - if (pawn == null || pawn.ObserverServices == null) return; + if (pawn?.ObserverServices == null) return; var observerTarget = pawn.ObserverServices.ObserverTarget?.Value; if (observerTarget == null || !observerTarget.IsValid) return; - var players = Utilities.GetPlayers(); - var targetHandle = observerTarget.Handle; - var observedPlayer = players.FirstOrDefault(p => p?.IsValid == true && p?.Pawn?.Value?.Handle == targetHandle); + var observedPlayer = Utilities.GetPlayers().FirstOrDefault(p => + p != null && p.IsValid && p.Pawn?.Value?.Handle == observerTarget.Handle); + if (observedPlayer == null) return; - var observeredPlayerSkill = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == observedPlayer.SteamID); - if (observeredPlayerSkill == null) return; + var observedEvent = PlayerManager.GetPlayerEvent(observedPlayer); + if (observedEvent == null || !observedEvent.IsValid) return; - var observeredPlayerSkillInfo = skills.FirstOrDefault(s => s.Skill == observeredPlayerSkill.Skill); - var observeredPlayerSpecialSkillInfo = observeredPlayerSkill.SpecialSkill != Skills.None ? skills.FirstOrDefault(s => s.Skill == observeredPlayerSkill.SpecialSkill) : null; + var observedSkill = PlayerManager.GetPlayerByIndex(observedEvent.Index); + if (observedSkill == null) return; - string primaryName = player.GetSkillName(observeredPlayerSkill.Skill, observeredPlayerSkill.SkillChance); - string primaryColor = observeredPlayerSkillInfo?.Color ?? SkillsInfo.GetValue(Skills.None, "color"); + var observedSkillInfo = skills.FirstOrDefault(s => s.Skill == observedSkill.Skill); + var observedSpecialInfo = observedSkill.SpecialSkill != Skills.None + ? skills.FirstOrDefault(s => s.Skill == observedSkill.SpecialSkill) + : null; + + string primaryName = player.GetSkillName(observedSkill.Skill, observedSkill.SkillChance); + string primaryColor = observedSkillInfo?.Color ?? SkillsInfo.GetValue(Skills.None, "color"); + string pName = System.Net.WebUtility.HtmlEncode(observedSkill.PlayerName); - string pName = System.Net.WebUtility.HtmlEncode(observeredPlayerSkill.PlayerName); if (pName.Length > 18) pName = $"{pName[..17]}..."; var observerSkill = player.GetTranslation("observer_skill"); infoLine = string.IsNullOrEmpty(observerSkill) ? pName : $"{observerSkill} {pName}"; - if (observeredPlayerSkill.SpecialSkill == Skills.None || observeredPlayerSpecialSkillInfo == null) + if (observedSkill.SpecialSkill == Skills.None || observedSpecialInfo == null) skillLine = $"{primaryName}"; else { - string specialName = player.GetSkillName(observeredPlayerSpecialSkillInfo.Skill); - skillLine = $"{specialName}({primaryName})"; + string specialName = player.GetSkillName(observedSpecialInfo.Skill); + skillLine = $"{specialName}({primaryName})"; } if (showDescriptionHUD) - remainingLine = player.GetSkillDescription(observeredPlayerSkill.Skill, observeredPlayerSkill.SkillChance); + remainingLine = player.GetSkillDescription(observedSkill.Skill, observedSkill.SkillChance); } } @@ -149,4 +172,4 @@ namespace src.player Event.UpdateSkillHUD(player, infoLine, skillLine, remainingLine, isDescription); } } -} \ No newline at end of file +} diff --git a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs index 51ffcae..2244b3e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs @@ -1,7 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -10,7 +9,7 @@ namespace src.player.skills public class AimLock : ISkill { private const Skills skillName = Skills.AimLock; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -28,23 +27,28 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + { + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { UpdateHUD(player, skillInfo); if (skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "duration")) > DateTime.Now) - LookAtEnemey(player); + LookAtEnemy(player); } + } } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + if (player == null || !player.IsValid) return; + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + PlayerIndex = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -52,23 +56,22 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + if (player == null || !player.IsValid) return; + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) { - float cooldown = 0; - if (skillInfo != null) - { - float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); - cooldown = Math.Max(time, 0); + if (player == null || !player.IsValid || skillInfo == null) return; - if (cooldown == 0 && skillInfo?.CanUse == false) - skillInfo.CanUse = true; - } + float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); + float cooldown = Math.Max(time, 0); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + if (cooldown == 0 && !skillInfo.CanUse) + skillInfo.CanUse = true; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -79,61 +82,50 @@ namespace src.player.skills public static void UseSkill(CCSPlayerController player) { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; + if (player == null || !player.IsValid) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) return; + + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; - if (skillInfo.CanUse) - { - skillInfo.CanUse = false; - skillInfo.Cooldown = DateTime.Now; - LookAtEnemey(player); - } + if (!skillInfo.CanUse) return; + + skillInfo.Cooldown = DateTime.Now; + skillInfo.CanUse = false; } } - private static void LookAtEnemey(CCSPlayerController player) + private static void LookAtEnemy(CCSPlayerController player) { + if (player == null || !player.IsValid) return; + var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - CCSPlayerController? closetEnemy = null; - double minDist = double.MaxValue; + var myEyePos = new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team)) - { - var enemyPawn = enemy.PlayerPawn.Value; - if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) continue; + var enemy = Utilities.GetPlayers() + .Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team && p.PlayerPawn.Value != null && p.PlayerPawn.Value.AbsOrigin != null) + .OrderBy(p => (p.PlayerPawn.Value!.AbsOrigin! - pawn.AbsOrigin).LengthSqr()) + .FirstOrDefault(); - double dist = SkillUtils.GetDistance(enemyPawn.AbsOrigin, pawn.AbsOrigin); - if (dist < minDist) - { - minDist = dist; - closetEnemy = enemy; - } - } + if (enemy == null) return; - if (closetEnemy != null) - { - var enemyPawn = closetEnemy.PlayerPawn.Value; - if (enemyPawn == null || enemyPawn.AbsOrigin == null) return; + var enemyPawn = enemy.PlayerPawn.Value; + if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null || enemyPawn.ViewOffset == null) return; - Vector myEyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); + Vector diff = SkillUtils.GetForwardVector(enemyPawn.AbsRotation!) * 5; + Vector enemyHead = new( + enemyPawn.AbsOrigin.X + diff.X, + enemyPawn.AbsOrigin.Y + diff.Y, + enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + 2 + ); - Vector diff = SkillUtils.GetForwardVector(enemyPawn.AbsRotation!) * 5; - Vector enemyHead = new( - enemyPawn.AbsOrigin.X + diff.X, - enemyPawn.AbsOrigin.Y + diff.Y, - enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + 2 - ); + Vector direction = enemyHead - myEyePos; + QAngle angle = VectorToAngle(direction); - Vector direction = enemyHead - myEyePos; - QAngle angle = VectorToAngle(direction); - - pawn.Look(angle); - } + pawn.Look(angle); } private static QAngle VectorToAngle(Vector direction) @@ -146,7 +138,7 @@ namespace src.player.skills public class PlayerSkillInfo { - public ulong SteamID { get; set; } + public uint PlayerIndex { get; set; } public bool CanUse { get; set; } public DateTime Cooldown { get; set; } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs b/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs index 1c88526..b70316c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Aimbot.cs @@ -2,9 +2,9 @@ using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using System.Runtime.InteropServices; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; +using CounterStrikeSharp.API; namespace src.player.skills { @@ -23,61 +23,35 @@ namespace src.player.skills CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); - if (param == null || !param.IsValid || param.Entity == null) - return; + if (param == null || !param.IsValid || param2 == null || param2.Handle == nint.Zero) return; + if (param2.Attacker == null || !param2.Attacker.IsValid || param2.Attacker.Value == null) return; - if (param2 == null || param2.Handle == nint.Zero || param2.Attacker == null || !param2.Attacker.IsValid) - return; + var attackerEnt = param2.Attacker.Value; + if (attackerEnt == null || !attackerEnt.IsValid) return; - var attackerHandle = param2.Attacker; - if (attackerHandle.Value == null || !attackerHandle.IsValid) - return; + var attackerPawn = attackerEnt.As(); + if (attackerPawn == null || !attackerPawn.IsValid) return; - var attackerEnt = attackerHandle.Value; - var victimEnt = param; + var attackerController = attackerPawn.Controller.Value; + if (attackerController == null || !attackerController.IsValid) return; - if (attackerEnt == null || victimEnt == null || !victimEnt.IsValid || !attackerEnt.IsValid) - return; + var attacker = PlayerManager.GetPlayerEvent(attackerController.As())!; - CCSPlayerPawn attackerPawn = new(attackerEnt.Handle); - CCSPlayerPawn victimPawn = new(victimEnt.Handle); - - if (attackerPawn == null || !attackerPawn.IsValid || victimPawn == null || !victimPawn.IsValid) - return; - - if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return; - - var attackerController = attackerPawn.Controller?.Value; - var victimController = victimPawn.Controller?.Value; - - if (!attackerController.IsValid() || !victimController.IsValid()) - return; - - CCSPlayerController attacker = attackerController!.As(); - CCSPlayerController victim = victimController!.As(); - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker.Index); if (playerInfo == null) return; - if (!attacker.CheckPlayer()) - return; - int offset = GameData.GetOffset("CTakeDamageInfo_HitGroup"); - if (offset <= 0) - return; + if (offset <= 0) return; nint hitGroupPointer = Marshal.ReadIntPtr(param2.Handle, offset); - if (hitGroupPointer == nint.Zero) - return; + if (hitGroupPointer == nint.Zero) return; nint hitGroupOffset = Marshal.ReadIntPtr(hitGroupPointer, 16); - if (hitGroupOffset == nint.Zero) - return; + if (hitGroupOffset == nint.Zero) return; if (playerInfo.Skill == skillName) { - hitGroups[hitGroupOffset] = Marshal.ReadInt32(hitGroupOffset, 56); + hitGroups.TryAdd(hitGroupOffset, Marshal.ReadInt32(hitGroupOffset, 56)); Marshal.WriteInt32(hitGroupOffset, 56, (int)HitGroup_t.HITGROUP_HEAD); } else if (hitGroups.TryGetValue(hitGroupOffset, out var hitGroup)) @@ -87,10 +61,13 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController _) { foreach (var hit in hitGroups) - Marshal.WriteInt32(hit.Key, 56, hit.Value); + { + if (hit.Key != nint.Zero) + Marshal.WriteInt32(hit.Key, 56, hit.Value); + } } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Epic) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) { } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs b/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs index c9b4833..3f3005f 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 src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -11,7 +10,8 @@ namespace src.player.skills { private const Skills skillName = Skills.Anomaly; private static readonly float tickRate = 64; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -29,18 +29,24 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + { + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { UpdateHUD(player, skillInfo); - if (Server.TickCount % tickRate != 0) return; + if (Server.TickCount % tickRate != 0) continue; + var pawn = player.PlayerPawn.Value; if (pawn != null && pawn.IsValid && pawn.AbsOrigin != null) { if (skillInfo.LastRotations == null || skillInfo.LastPositions == null) continue; + skillInfo.LastPositions.Enqueue(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z)); skillInfo.LastRotations.Enqueue(new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0)); + if (skillInfo.LastRotations.Count > SkillsInfo.GetValue(skillName, "secondsInBack")) { skillInfo.LastPositions.TryDequeue(out _); @@ -48,40 +54,42 @@ namespace src.player.skills } } } + } } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + if (player == null || !player.IsValid) return; + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + PlayerIndex = player.Index, CanUse = true, Cooldown = DateTime.MinValue, - LastPositions = [], - LastRotations = [], + LastPositions = new ConcurrentQueue(), + LastRotations = new ConcurrentQueue() }); } public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + if (player == null || !player.IsValid) return; + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) { + if (player == null || !player.IsValid || skillInfo == null) return; + float cooldown = 0; - if (skillInfo != null) - { - float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); - cooldown = Math.Max(time, 0); + float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); + cooldown = Math.Max(time, 0); - if (cooldown == 0 && skillInfo?.CanUse == false) - skillInfo.CanUse = true; - } + if (cooldown == 0 && !skillInfo.CanUse) + skillInfo.CanUse = true; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -92,19 +100,27 @@ namespace src.player.skills public static void UseSkill(CCSPlayerController player) { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; + if (player == null || !player.IsValid) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) return; + + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; - if (skillInfo.CanUse) + if (!skillInfo.CanUse) return; + + skillInfo.Cooldown = DateTime.Now; + skillInfo.CanUse = false; + + var playerPawn = player.PlayerPawn.Value; + if (playerPawn != null && playerPawn.IsValid) { - skillInfo.CanUse = false; - skillInfo.Cooldown = DateTime.Now; - if (skillInfo.LastRotations == null || skillInfo.LastRotations.IsEmpty || skillInfo.LastPositions == null || skillInfo.LastPositions.IsEmpty) return; + if (skillInfo.LastPositions == null || skillInfo.LastPositions.IsEmpty) return; + if (skillInfo.LastRotations == null || skillInfo.LastRotations.IsEmpty) return; + Vector? lastPosition = skillInfo.LastPositions.FirstOrDefault(); QAngle? lastRotation = skillInfo.LastRotations.FirstOrDefault(); + if (lastPosition != null && lastRotation != null) { playerPawn.Teleport(lastPosition, null, null); @@ -116,7 +132,7 @@ namespace src.player.skills public class PlayerSkillInfo { - public ulong SteamID { get; set; } + public uint PlayerIndex { get; set; } public bool CanUse { get; set; } public DateTime Cooldown { get; set; } public ConcurrentQueue? LastPositions { get; set; } diff --git a/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs b/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs index ec8c2f6..8025f0c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AntyFlash.cs @@ -2,7 +2,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -17,25 +16,31 @@ namespace src.player.skills public static void PlayerBlind(EventPlayerBlind @event) { - var player = @event.Userid; - var attacker = @event.Attacker; + var player = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - if (attacker == null || !attacker.IsValid) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) + { playerPawn.FlashDuration = 0.0f; - else if (attackerInfo?.Skill == skillName) - playerPawn.FlashDuration = SkillsInfo.GetValue(skillName, "flashDuration"); + } + else if (attacker != null && attacker.IsValid) + { + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); + if (attackerInfo?.Skill == skillName) + playerPawn.FlashDuration = SkillsInfo.GetValue(skillName, "flashDuration"); + } } public static void EnableSkill(CCSPlayerController player) { + if (player == null || !player.IsValid) return; SkillUtils.TryGiveWeapon(player, CsItem.FlashbangGrenade); } diff --git a/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs b/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs index 32aaa63..76e0fdb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AntyHead.cs @@ -1,7 +1,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -16,12 +15,13 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); int hitgroup = @event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + if (victim == null || !victim.IsValid || attacker == null || !attacker.IsValid || attacker == victim) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index); if (playerInfo?.Skill == skillName && hitgroup == (int)HitGroup_t.HITGROUP_HEAD) SkillUtils.RestoreHealth(victim); } diff --git a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs index 15acfc6..25881ec 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs @@ -2,7 +2,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; +using System.Collections.Concurrent; namespace src.player.skills { @@ -11,6 +11,7 @@ namespace src.player.skills private const Skills skillName = Skills.AreaReaper; private static readonly string[] bombsiteA = ["A", "a"]; private static readonly string[] bombsiteB = ["B", "b"]; + private static readonly ConcurrentDictionary playersToTarget = []; public static void LoadSkill() { @@ -20,12 +21,19 @@ namespace src.player.skills public static void NewRound() { foreach (var player in Utilities.GetPlayers()) - SkillUtils.CloseMenu(player); + { + if (player != null && player.IsValid) + SkillUtils.CloseMenu(player); + } + + playersToTarget.Clear(); } public static void TypeSkill(CCSPlayerController player, string[] commands) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid || commands == null || commands.Length == 0) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -35,66 +43,74 @@ namespace src.player.skills } int site = bombsiteA.Contains(commands[0]) ? 0 : bombsiteB.Contains(commands[0]) ? 1 : -1; - if (site == -1) { + if (site == -1) + { player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_incorrect_site")}"); return; } - + var bombTargets = Utilities.FindAllEntitiesByDesignerName("func_bomb_target").ToArray(); if (bombTargets.Length == 2) { - bombTargets[site].BombPlantedHere = true; - Utilities.SetStateChanged(bombTargets[site], "CBombTarget", "m_bBombPlantedHere"); + var targetSite = bombTargets[site]; + if (targetSite != null && targetSite.IsValid) + { + targetSite.BombPlantedHere = true; + Utilities.SetStateChanged(targetSite, "CBombTarget", "m_bBombPlantedHere"); + playerInfo.SkillUsed = true; - playerInfo.SkillUsed = true; - player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}"); + playersToTarget[player.Index] = targetSite.Index; + } } - else - player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_no_site")}"); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player.Index); if (playerInfo == null) return; + playerInfo.SkillUsed = false; SkillUtils.CreateMenu(player, [(player.GetTranslation("bombsite_a"), "a")], (player.GetTranslation("bombsite_b"), "b", true)); } public static void DisableSkill(CCSPlayerController player) { - SkillUtils.CloseMenu(player); Server.NextWorldUpdate(() => { - if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return; + if (PlayerManager.GetPlayerCountBySkill(skillName) != 0) return; EnableBombsite(); }); + + SkillUtils.CloseMenu(player); } - private static void EnableBombsite() + private static void EnableBombsite(uint? bombsiteIndex = null) { var bombTargets = Utilities.FindAllEntitiesByDesignerName("func_bomb_target"); foreach (var bombTarget in bombTargets) - { - bombTarget.BombPlantedHere = false; - Utilities.SetStateChanged(bombTarget, "CBombTarget", "m_bBombPlantedHere"); - } + if (bombTarget != null && bombTarget.IsValid) + { + bombTarget.BombPlantedHere = false; + Utilities.SetStateChanged(bombTarget, "CBombTarget", "m_bBombPlantedHere"); + } } public static void OnTick() { - var bombTargets = Utilities.FindAllEntitiesByDesignerName("func_bomb_target"); - foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist)) - { - if (!Instance.IsPlayerValid(player)) continue; + if (Server.TickCount % 16 != 0) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + foreach (var player in Utilities.GetPlayers()) + { + if (player == null || !player.IsValid || player.Team != CsTeam.Terrorist) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == null) continue; var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) continue; + if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) continue; - if (pawn.WeaponServices == null) continue; var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue; diff --git a/jRandomSkills - SRC Files/src/player/skills/Armored.cs b/jRandomSkills - SRC Files/src/player/skills/Armored.cs index d799c92..4530d17 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Armored.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Armored.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -18,14 +18,17 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newScale = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newScale; newScale = (float)Math.Round(newScale, 2); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.IsValid && p.Team == player.Team && p != player) ? "tb" : "t"); } public static void OnTakeDamage(DynamicHook h) @@ -33,22 +36,18 @@ namespace src.player.skills 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; + if (param == null || !param.IsValid || param2 == null) return; - CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); - CCSPlayerPawn victimPawn = new(param.Handle); + var victimPawn = param.As(); + if (victimPawn == null || !victimPawn.IsValid || victimPawn.DesignerName != "player") return; - if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") - return; + var victimController = victimPawn.Controller.Value; + if (victimController == null || !victimController.IsValid) return; - if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) - return; + var victim = victimController.As(); + if (victim == null || !victim.IsValid) return; - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - CCSPlayerController victim = victimPawn.Controller.Value.As(); - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(victim)!.Index); if (playerInfo == null) return; if (playerInfo.Skill == skillName && victim.PawnIsAlive) diff --git a/jRandomSkills - SRC Files/src/player/skills/Assassin.cs b/jRandomSkills - SRC Files/src/player/skills/Assassin.cs index 7f20c72..7075c35 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Assassin.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Assassin.cs @@ -1,7 +1,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -18,29 +17,34 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { var damage = @event.DmgHealth; - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var weapon = @event.Weapon; - HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - if (nades.Contains(weapon)) return; + if (victim == null || !victim.IsValid || attacker == null || !attacker.IsValid || attacker == victim) return; + if (string.IsNullOrEmpty(weapon) || nades.Contains(weapon)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill != skillName) return; - if (IsBehind(attacker!, victim!)) - SkillUtils.TakeHealth(victim!.PlayerPawn.Value, (int)(damage * (SkillsInfo.GetValue(skillName, "damageMultiplier") - 1f))); + if (IsBehind(attacker, victim)) + { + var victimPawn = victim.PlayerPawn.Value; + if (victimPawn != null && victimPawn.IsValid) + SkillUtils.TakeHealth(victimPawn, (int)(damage * (SkillsInfo.GetValue(skillName, "damageMultiplier") - 1))); + } } private static bool IsBehind(CCSPlayerController attacker, CCSPlayerController victim) { var attackerPawn = attacker.PlayerPawn.Value; var victimPawn = victim.PlayerPawn.Value; + if (attackerPawn == null || !attackerPawn.IsValid || victimPawn == null || !victimPawn.IsValid) return false; if (victimPawn.AbsRotation == null || attackerPawn.AbsRotation == null) return false; + var angles = GetAngleRange(victimPawn.AbsRotation.Y); - return IsBeetween(angles.Item1, angles.Item2, attackerPawn.AbsRotation.Y); + return IsBetween(angles.Item1, angles.Item2, attackerPawn.AbsRotation.Y); } private static (float, float) GetAngleRange(float angle) @@ -55,7 +59,7 @@ namespace src.player.skills return (min, max); } - private static bool IsBeetween(float a, float b, float target) + private static bool IsBetween(float a, float b, float target) { if (a <= b) return (target >= a && target <= b); diff --git a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs index c2678f6..9e1d116 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs @@ -23,29 +23,40 @@ namespace src.player.skills public static void NewRound() { foreach (var player in Utilities.GetPlayers()) - DisableSkill(player); + { + if (player != null && player.IsValid) + DisableSkill(player); + } } public static void DisableSkill(CCSPlayerController player) { - 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 (player == null || !player.IsValid) return; + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; - player.PlayerPawn.Value.ActualGravityScale = 1; + pawn.ActualGravityScale = 1.0f; } private static void ApplyGravityModifier(CCSPlayerController player) { - 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 (player == null || !player.IsValid) return; + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float gravityModifier = (float)Math.Round(Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "chanceFrom")) + SkillsInfo.GetValue(skillName, "chanceFrom"), 1); playerInfo.SkillChance = gravityModifier; + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, gravityModifier)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); - player.PlayerPawn.Value.ActualGravityScale = gravityModifier; + border: !Utilities.GetPlayers().Any(p => p.IsValid && p.Team == player.Team && p != player) ? "tb" : "t"); + + pawn.ActualGravityScale = gravityModifier; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#7E10AD", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float chanceFrom = .1f, float chanceTo = .7f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Bankrupt.cs b/jRandomSkills - SRC Files/src/player/skills/Bankrupt.cs index b12e951..a450d07 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Bankrupt.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Bankrupt.cs @@ -1,9 +1,8 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; namespace src.player.skills { @@ -19,66 +18,88 @@ namespace src.player.skills public static void NewRound() { foreach (var player in Utilities.GetPlayers()) - SkillUtils.CloseMenu(player); + { + if (player != null && player.IsValid) + SkillUtils.CloseMenu(player); + } } public static void OnTick() { 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 (player == null || !player.IsValid || !SkillUtils.HasMenu(player)) continue; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); - ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account)}$", e.Index.ToString()))); - SkillUtils.UpdateMenu(player, menuItems); + var enemies = Utilities.GetPlayers().Where(p => p != null && p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p => p != null && p.IsValid && p.Team != player.Team && p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0 && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + ConcurrentBag<(string, string)> menuItems = []; + + foreach (var e in enemies) + { + int money = e.InGameMoneyServices?.Account ?? 0; + menuItems.Add(($"{e.PlayerName} : {money}$", e.Index.ToString())); + } + + if (!menuItems.IsEmpty) + SkillUtils.UpdateMenu(player, menuItems); + } + } + + public static void EnableSkill(CCSPlayerController player) + { + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) return; + + playerInfo.SkillUsed = false; + + var enemies = Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); + if (enemies.Length > 0) + { + ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices?.Account ?? 0)}$", e.Index.ToString()))]; + SkillUtils.CreateMenu(player, menuItems); + } + else + { + player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } } 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 (player == null || !player.IsValid || commands.Length < 1) return; + + string option = commands[0]; + if (string.IsNullOrEmpty(option)) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) { - player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}"); + player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_used_info")}"); return; } - string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); - - if (enemy == null) + if (uint.TryParse(option, out uint enemyIndex)) { - player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); - return; + var enemy = Utilities.GetEntityFromIndex((int)enemyIndex); + if (enemy != null && enemy.IsValid && enemy.PawnIsAlive && enemy.Team != player.Team) + { + ResetMoney(enemy); + playerInfo.SkillUsed = true; + SkillUtils.CloseMenu(player); + player.PrintToChat($" {ChatColors.Lime}{player.GetTranslation("bankrupt_player_info", enemy.PlayerName)}"); + enemy.PrintToChat($" {ChatColors.Red}{enemy.GetTranslation("bankrupt_enemy_info")}"); + return; + } } - - ResetMoney(enemy); - playerInfo.SkillUsed = true; - player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("bankrupt_player_info", enemy.PlayerName)); - enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("bankrupt_enemy_info")); - } - - public static void EnableSkill(CCSPlayerController player) - { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo == null) return; - playerInfo.SkillUsed = false; - - 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) - { - ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account)}$", e.Index.ToString()))); - SkillUtils.CreateMenu(player, menuItems); - } - else - player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); + player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } private static void ResetMoney(CCSPlayerController enemy) @@ -93,7 +114,8 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillUtils.CloseMenu(player); + if (player != null && player.IsValid) + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#abab33", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs index 478f85e..e79fa38 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs @@ -1,10 +1,10 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; +using static src.jRandomSkills; namespace src.player.skills { @@ -20,14 +20,14 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@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); + var attackerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(attacker)!.Index); if (attackerInfo?.Skill != skillName) return; SkillUtils.TakeHealth(victim!.PlayerPawn.Value, SkillsInfo.GetValue(skillName, "damageDeal")); @@ -41,27 +41,27 @@ namespace src.player.skills 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); + + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; decoys.TryAdd(decoy.Index, 0); - + decoy.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith; decoy.Collision.CollisionGroup = pawn.Collision.CollisionGroup; } public static void DecoyStarted(EventDecoyStarted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; uint key = (uint)@event.Entityid; @@ -69,7 +69,7 @@ namespace src.player.skills { var decoy = Utilities.GetEntityFromIndex(@event.Entityid); if (decoy != null && decoy.IsValid) - decoy.AcceptInput("Kill"); + decoy.AddEntityIOEvent("Kill", decoy, delay: 0.1f); decoys.TryRemove(key, out _); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Behind.cs b/jRandomSkills - SRC Files/src/player/skills/Behind.cs index 8e9845e..3677c39 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Behind.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Behind.cs @@ -17,11 +17,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event!.Attacker; - var victim = @event!.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event!.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event!.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) if (Instance.Random.NextDouble() <= playerInfo.SkillChance) @@ -30,12 +30,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } private static void RotateEnemy(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs b/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs index 7fe4f7c..5681759 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BladeMaster.cs @@ -18,58 +18,71 @@ namespace src.player.skills public static void OnTick() { + var modifier = SkillsInfo.GetValue(skillName, "velocityModifier"); + foreach (var player in Utilities.GetPlayers()) { - if (!Instance.IsPlayerValid(player)) continue; + if (player == null || !player.IsValid) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) continue; var playerPawn = player.PlayerPawn?.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.VelocityModifier == 0) continue; var weaponServices = playerPawn.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" && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet")) - return; + if (weaponServices == null) continue; - playerPawn.VelocityModifier = SkillsInfo.GetValue(skillName, "velocityModifier"); + if (weaponServices.ActiveWeapon == null + || !weaponServices.ActiveWeapon.IsValid + || weaponServices.ActiveWeapon.Value == null + || !weaponServices.ActiveWeapon.Value.IsValid + || (weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife" + && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet")) + continue; + + playerPawn.VelocityModifier = modifier; } } 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; + var damage = @event.DmgHealth; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var weapon = @event.Weapon; + int hitgroup = @event.Hitgroup; - 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; + if (victim == null || !victim.IsValid || attacker == null || !attacker.IsValid || attacker == victim) return; - int chance = Instance.Random.Next(0, 101); - if (hitGroup == HitGroup_t.HITGROUP_LEFTLEG || hitGroup == HitGroup_t.HITGROUP_RIGHTLEG) - { - if (chance > SkillsInfo.GetValue(skillName, "legReflectionChance") * 100) - return; - } - else - if (chance > SkillsInfo.GetValue(skillName, "torseReflectionChance") * 100) - return; + var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index); + if (playerInfo?.Skill != skillName) return; - var pawn = victim!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return; + if (string.IsNullOrEmpty(weapon) || noReflectionWeapon.Contains(weapon)) return; - var weaponServices = pawn.WeaponServices; + float chance = (hitgroup == (int)HitGroup_t.HITGROUP_LEFTLEG || hitgroup == (int)HitGroup_t.HITGROUP_RIGHTLEG) + ? SkillsInfo.GetValue(skillName, "legReflectionChance") + : SkillsInfo.GetValue(skillName, "torseReflectionChance"); + + var victimPawn = victim.PlayerPawn?.Value; + if (victimPawn == null || !victimPawn.IsValid || Instance.Random.NextDouble() > chance) + return; + + var weaponServices = victimPawn.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" && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet")) + + if (weaponServices.ActiveWeapon == null + || !weaponServices.ActiveWeapon.IsValid + || weaponServices.ActiveWeapon.Value == null + || !weaponServices.ActiveWeapon.Value.IsValid + || (weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife" + && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet")) return; SkillUtils.RestoreHealth(victim); } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#cc7504", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float torseReflectionChance = .95f, float legReflectionChance = .80f, float velocityModifier = .85f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#cc7504", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float torseReflectionChance = .95f, float legReflectionChance = .70f, float velocityModifier = .85f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) { public float TorseReflectionChance { get; set; } = torseReflectionChance; public float LegReflectionChance { get; set; } = legReflectionChance; diff --git a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs index a8a1b84..71067d5 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs @@ -3,14 +3,13 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { public class BunnyHop : ISkill { private const Skills skillName = Skills.BunnyHop; - private static readonly ConcurrentDictionary playersLastJump = []; + private static readonly ConcurrentDictionary playersLastJump = []; public static void LoadSkill() { @@ -21,7 +20,9 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill == skillName) GiveBunnyHop(player); } @@ -29,26 +30,31 @@ namespace src.player.skills private static void GiveBunnyHop(CCSPlayerController player) { + var eventPlayer = PlayerManager.GetPlayerEvent(player); + var eventPlayerPawn = eventPlayer?.PlayerPawn?.Value; + if (eventPlayerPawn == null || !eventPlayerPawn.IsValid) return; + var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; + if (JumpBan.bannedPlayers.ContainsKey(player.Index)) return; - var flags = (PlayerFlags)playerPawn.Flags; + var flags = (PlayerFlags)eventPlayerPawn.Flags; var buttons = player.Buttons; if ((playerPawn.MovementServices?.QueuedButtonChangeMask & (ulong)PlayerButtons.Jump) != 0) - playersLastJump.AddOrUpdate(player.SteamID, Server.TickCount, (_, _) => Server.TickCount); + playersLastJump.AddOrUpdate(eventPlayer!.Index, Server.TickCount, (_, _) => Server.TickCount); bool jumpPressed = buttons.HasFlag(PlayerButtons.Jump) - || (playersLastJump.TryGetValue(player.SteamID, out int tick) && tick + 20 >= Server.TickCount); + || (playersLastJump.TryGetValue(eventPlayer!.Index, out int tick) && tick + 20 >= Server.TickCount); - if (jumpPressed && flags.HasFlag(PlayerFlags.FL_ONGROUND) && !playerPawn.MoveType.HasFlag(MoveType_t.MOVETYPE_LADDER)) + if (jumpPressed && flags.HasFlag(PlayerFlags.FL_ONGROUND) && !eventPlayerPawn.MoveType.HasFlag(MoveType_t.MOVETYPE_LADDER)) { - playerPawn.AbsVelocity.Z = SkillsInfo.GetValue(skillName, "jumpVelocity"); + eventPlayerPawn.AbsVelocity.Z = SkillsInfo.GetValue(skillName, "jumpVelocity"); var maxSpeed = SkillsInfo.GetValue(skillName, "maxSpeed"); - var vX = playerPawn.AbsVelocity.X; - var vY = playerPawn.AbsVelocity.Y; + var vX = eventPlayerPawn.AbsVelocity.X; + var vY = eventPlayerPawn.AbsVelocity.Y; var speed2D = Math.Sqrt(vX * vX + vY * vY); var scale = 1d; @@ -60,8 +66,8 @@ namespace src.player.skills else if (speed2D > maxSpeed) scale = maxSpeed / speed2D; - playerPawn.AbsVelocity.X = (float)(vX * scale); - playerPawn.AbsVelocity.Y = (float)(vY * scale); + eventPlayerPawn.AbsVelocity.X = (float)(vX * scale); + eventPlayerPawn.AbsVelocity.Y = (float)(vY * scale); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs index a923065..add268f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs +++ b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs @@ -4,6 +4,7 @@ using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; +using System.Drawing; using static src.jRandomSkills; namespace src.player.skills @@ -13,11 +14,13 @@ namespace src.player.skills private const Skills skillName = Skills.C4Camouflage; private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; + private const string cameraViewModel = "models/sprays/spray_plane.vmdl"; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); Instance.AddToManifest(bloodParticle); + Instance.AddToManifest(cameraViewModel); } public static void NewRound() @@ -27,40 +30,74 @@ namespace src.player.skills 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); + var player = PlayerManager.GetPlayerEvent(@event.Userid); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; - EnableSkill(player!); + + Event.EnableTransmit(); + if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0) + CreatePlayerPosProp(player); } public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid!; + var player = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Item; - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (weapon == "c4") + { invisiblePlayers.TryAdd(player.Index, 0); + SkillUtils.SetPlayerInvisibility(player, .5f); + } else + { invisiblePlayers.TryRemove(player.Index, out _); + SkillUtils.SetPlayerInvisibility(player, 0); + } } public static void OnTick() { + if (Server.TickCount % 2 != 0) return; + foreach (var player in Utilities.GetPlayers()) - if (!player.PawnIsAlive) + { + if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE && invisiblePlayers.ContainsKey(player.Index)) + { invisiblePlayers.TryRemove(player.Index, out _); + SkillUtils.SetPlayerInvisibility(player, 0); + } + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) continue; + + var props = EntityManager.GetPlayerEntities(player.Index, "empty_prop"); + if (props.Count == 0) continue; + + var prop = Utilities.GetEntityFromIndex((int)props[0]); + if (prop == null || !prop.IsValid) continue; + + var pawn = player.PlayerPawn?.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; + + Vector newPos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + 30); + QAngle newAngle = new(0, pawn.V_angle.Y, 0); + prop.Teleport(newPos, newAngle, null); + } } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) { foreach (var (info, player) in infoList) { - if (player == null || !player.IsValid) continue; + if (player == null || !player.IsValid || player.Team == CsTeam.Spectator) continue; var targetHandle = player.Pawn.Value?.ObserverServices?.ObserverTarget.Value?.Handle ?? nint.Zero; bool isObservingC4Camouflage = false; @@ -68,14 +105,17 @@ namespace src.player.skills if (targetHandle != nint.Zero) { var target = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == targetHandle); - var targetInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == target?.SteamID); + var targetInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(target)?.Index); if (targetInfo?.Skill == skillName) isObservingC4Camouflage = true; } foreach (var playerIndex in invisiblePlayers.Keys) { - var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); - if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + var playerController = PlayerManager.GetPlayerEvent(Utilities.GetPlayerFromIndex((int)playerIndex)); + if (playerController == null || !playerController.IsValid || playerController.Index == player.Index) + continue; + + if (player.Team == playerController.Team) continue; if (!isObservingC4Camouflage) @@ -105,6 +145,10 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; + + if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0) + CreatePlayerPosProp(player); + if (playerPawn.WeaponServices == null || playerPawn.WeaponServices.ActiveWeapon == null || !playerPawn.WeaponServices.ActiveWeapon.IsValid) return; if (playerPawn.WeaponServices.ActiveWeapon.Value == null || !playerPawn.WeaponServices.ActiveWeapon.Value.IsValid) return; @@ -112,32 +156,55 @@ namespace src.player.skills if (activeWeapon.DesignerName != "weapon_c4") return; invisiblePlayers.TryAdd(player.Index, 0); + SkillUtils.SetPlayerInvisibility(player, .5f); } public static void DisableSkill(CCSPlayerController player) { invisiblePlayers.TryRemove(player.Index, out _); + SkillUtils.SetPlayerInvisibility(player, 0); + EntityManager.DestroyPlayerEntities(player.Index); + } + + private static void CreatePlayerPosProp(CCSPlayerController player) + { + if (player == null || !player.IsValid) return; + + var emptyProp = EntityManager.CreateTrackedDynamicProp(player.Index); + if (emptyProp == null || !emptyProp.IsValid) return; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; + + emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); + emptyProp.SetModel(cameraViewModel); + emptyProp.Render = Color.FromArgb(1, 255, 255, 255); + + Vector newPos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 30); + QAngle newAngle = new(playerPawn.AbsRotation.X, playerPawn.AbsRotation.Y, playerPawn.AbsRotation.Z); + + emptyProp.Teleport(newPos, newAngle); + emptyProp.DispatchSpawn(); + + Utilities.SetStateChanged(emptyProp, "CBaseEntity", "m_CBodyComponent"); + + EntityManager.RegisterExisting(emptyProp, player.Index, "empty_prop"); } public static void PlayerHurt(EventPlayerHurt @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; - CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + var particle = EntityManager.CreateTrackedParticleSystem(player.Index, bloodParticle, autoDestroySeconds: 3f); if (particle == null) return; - particle.EffectName = bloodParticle; - particle.StartActive = true; - Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); particle.Teleport(pos); - particle.DispatchSpawn(); - particle.AcceptInput("Start"); } diff --git a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs index 899b63f..eacdae7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs +++ b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -11,9 +11,10 @@ namespace src.player.skills public class CarefulBullets : ISkill { private const Skills skillName = Skills.CarefulBullets; - private static readonly ConcurrentDictionary targetPlayers = []; - private static readonly ConcurrentDictionary lastShot = []; - private static readonly ConcurrentDictionary hitPlayer = []; + private static readonly ConcurrentDictionary targetPlayers = []; + private static readonly ConcurrentDictionary lastShot = []; + private static readonly ConcurrentDictionary hitPlayer = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -25,22 +26,17 @@ namespace src.player.skills { lock (setLock) { + foreach (var player in Utilities.GetPlayers()) + { + DisableSkill(player); + SkillUtils.CloseMenu(player); + } + targetPlayers.Clear(); lastShot.Clear(); hitPlayer.Clear(); + playersToTarget.Clear(); } - foreach (var player in Utilities.GetPlayers()) - { - DisableSkill(player); - SkillUtils.CloseMenu(player); - } - } - - public static void PlayerDeath(EventPlayerDeath @event) - { - var player = @event.Userid; - if (player == null) return; - DisableSkill(player); } public static void OnTick() @@ -49,10 +45,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); @@ -61,8 +57,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -72,7 +68,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -80,19 +77,21 @@ namespace src.player.skills return; } - targetPlayers.TryAdd(enemy.SteamID, 0); + targetPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("carefulbullets_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("carefulbullets_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; @@ -104,37 +103,37 @@ namespace src.player.skills public static void BulletImpact(EventBulletImpact @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - if (!targetPlayers.ContainsKey(player.SteamID) || !player.PawnIsAlive) + if (!targetPlayers.ContainsKey(player.Index) || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - ulong steamID = player.SteamID; + uint playerIndex = player.Index; Server.NextFrame(() => { if (player == null || !player.IsValid) return; if (playerPawn == null || !playerPawn.IsValid) return; - bool ishitPlayer = hitPlayer.TryGetValue(steamID, out int tick) && tick + 10 >= Server.TickCount; + bool ishitPlayer = hitPlayer.TryGetValue(playerIndex, out int tick) && tick + 10 >= Server.TickCount; - if (!lastShot.ContainsKey(steamID)) + if (!lastShot.ContainsKey(playerIndex)) { - lastShot.TryAdd(steamID, ishitPlayer); + lastShot.TryAdd(playerIndex, ishitPlayer); Instance.AddTickTimer(1, () => { - if (lastShot.TryRemove(steamID, out bool didHit) && !didHit) + if (lastShot.TryRemove(playerIndex, out bool didHit) && !didHit) SkillUtils.TakeHealth(playerPawn, SkillsInfo.GetValue(skillName, "damageAfterMiss")); - lastShot.TryRemove(steamID, out _); + lastShot.TryRemove(playerIndex, out _); }); } else if (ishitPlayer) - lastShot.TryUpdate(steamID, true, false); + lastShot.TryUpdate(playerIndex, true, false); }); } @@ -155,17 +154,37 @@ namespace src.player.skills if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) return; - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - if (!targetPlayers.ContainsKey(attacker.SteamID)) return; + CCSPlayerController attacker = PlayerManager.GetPlayerEvent(attackerPawn.Controller.Value.As())!; + if (!targetPlayers.ContainsKey(attacker.Index)) return; - hitPlayer.AddOrUpdate(attacker.SteamID, Server.TickCount, (_, _) => Server.TickCount); + hitPlayer.AddOrUpdate(attacker.Index, Server.TickCount, (_, _) => Server.TickCount); } public static void DisableSkill(CCSPlayerController player) { - targetPlayers.TryRemove(player.SteamID, out _); - lastShot.TryRemove(player.SteamID, out _); - hitPlayer.TryRemove(player.SteamID, out _); + targetPlayers.TryRemove(player.Index, out _); + lastShot.TryRemove(player.Index, out _); + hitPlayer.TryRemove(player.Index, out _); + + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + { + targetPlayers.TryRemove(targetIndex, out _); + lastShot.TryRemove(targetIndex, out _); + hitPlayer.TryRemove(targetIndex, out _); + } + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + targetPlayers.TryRemove(player.Index, out _); + lastShot.TryRemove(player.Index, out _); + hitPlayer.TryRemove(player.Index, out _); + SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Catapult.cs b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs index afb0644..f731f08 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Catapult.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs @@ -17,11 +17,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo?.Skill == skillName && victim!.PawnIsAlive) if (Instance.Random.NextDouble() <= attackerInfo.SkillChance) @@ -34,12 +34,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "chanceTo") - SkillsInfo.GetValue(skillName, "chanceFrom")) + SkillsInfo.GetValue(skillName, "chanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float chanceFrom = .2f, float chanceTo = .4f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs index dda31eb..379af4c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs @@ -42,10 +42,10 @@ namespace src.player.skills public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; SetWeaponAttack(player, true); @@ -120,7 +120,7 @@ namespace src.player.skills { var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - var chickenModel = Utilities.CreateEntityByName("prop_dynamic"); + var chickenModel = EntityManager.CreateTrackedDynamicProp(player.Index); if (chickenModel == null) return; @@ -172,7 +172,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn.WeaponServices == null || pawn.WeaponServices.ActiveWeapon == null || !pawn.WeaponServices.ActiveWeapon.IsValid || pawn.WeaponServices.ActiveWeapon.Value == null || !pawn.WeaponServices.ActiveWeapon.Value.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var weapon = pawn.WeaponServices.ActiveWeapon.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs index e3a3704..30b4a0b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs @@ -1,6 +1,7 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; +using Microsoft.Extensions.Logging; using src.utils; using System.Collections.Concurrent; using static src.jRandomSkills; @@ -10,7 +11,7 @@ namespace src.player.skills public class ChillOut : ISkill { private const Skills skillName = Skills.ChillOut; - private static readonly ConcurrentDictionary plantingPlayers = []; + private static readonly ConcurrentDictionary plantingPlayers = []; public static void LoadSkill() { @@ -25,25 +26,27 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid) return; - plantingPlayers.TryRemove(player.SteamID, out _); + plantingPlayers.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } public static void BombAbortplant(EventBombAbortplant @event) { - var user = @event.Userid; - if (user == null || !user.IsValid || !user.PawnIsAlive) return; - plantingPlayers.TryRemove(user.SteamID, out _); + var user = PlayerManager.GetPlayerEvent(@event.Userid); + if (!Instance.IsPlayerValid(user)) return; + + plantingPlayers.TryRemove(user.Index, out _); SkillUtils.ResetPrintHTML(user); } public static void BombBeginplant(EventBombBeginplant @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - plantingPlayers.TryAdd(player!.SteamID, Server.CurrentTime); - var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName); + plantingPlayers.TryAdd(player!.Index, Server.CurrentTime); + + var anyChillOut = PlayerManager.GetAllPlayers().FirstOrDefault(p => p.Skill == skillName); if (anyChillOut != null) { var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); @@ -58,9 +61,10 @@ namespace src.player.skills public static void BombPlanted(EventBombPlanted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - plantingPlayers.TryRemove(player!.SteamID, out _); + + plantingPlayers.TryRemove(player!.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -71,9 +75,9 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist)) { - if (!Instance.IsPlayerValid(player)) continue; + if (player == null || !player.IsValid) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo == null) continue; var pawn = player.PlayerPawn.Value; @@ -83,7 +87,7 @@ namespace src.player.skills var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue; - if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime)) + if (plantingPlayers.TryGetValue(player.Index, out float plantTime)) { float remaining = plantTime + extraTime - currentTime; playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"{Math.Max(0, remaining):0.0}s")}"; diff --git a/jRandomSkills - SRC Files/src/player/skills/Cutter.cs b/jRandomSkills - SRC Files/src/player/skills/Cutter.cs index b917712..43515ef 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Cutter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Cutter.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -17,12 +17,12 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { var damage = @event.DmgHealth; - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Weapon; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill != skillName) return; if (weapon == "knife" || weapon == "bayonet") diff --git a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs index 2fc2f1c..ea73bf2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs @@ -1,5 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; @@ -178,15 +179,18 @@ namespace src.player.skills if (cameraView == null || !cameraView.IsValid) return; pawn!.CameraServices!.ViewEntity.Raw = cameraView.EntityHandle.Raw; - SkillUtils.ApplyScreenColor(player, 0, 0, 255, 20, 100, 1020); - ulong playerSteamID = player.SteamID; + var eventTarget = PlayerManager.GetPlayerFromEvent(player); + if (eventTarget != null && eventTarget.IsValid) + SkillUtils.ApplyScreenColor(eventTarget, 0, 0, 255, 20, 100, 1020); + + uint playerIndex = player.Index; Timer? cameraTimer = null; cameraTimer = jRandomSkills.Instance.AddTimer(2f, () => { - var target = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.SteamID == playerSteamID); - if (target == null || !target.IsValid || !target.PawnIsAlive) + var target = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.Index == playerIndex); + if (target == null || !target.IsValid || target.LifeState != (byte)LifeState_t.LIFE_ALIVE) { cameraTimer?.Kill(); return; @@ -198,7 +202,14 @@ namespace src.player.skills return; } - SkillUtils.ApplyScreenColor(target, 0, 0, 255, 20, 100, 1020); + var eventTarget = PlayerManager.GetPlayerFromEvent(player); + if (eventTarget == null || !eventTarget.IsValid) + { + cameraTimer?.Kill(); + return; + } + + SkillUtils.ApplyScreenColor(eventTarget, 0, 0, 255, 20, 100, 1020); }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); } else @@ -222,12 +233,12 @@ namespace src.player.skills if (!CheckCameraPosition(finalPos, player)) return null; - var camera = Utilities.CreateEntityByName("prop_dynamic_override"); + var camera = EntityManager.CreateTrackedPropOverride(player.Index); if (camera == null || !camera.IsValid) return null; camera.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); - camera.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.SteamID}"; + camera.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.Index}"; camera.SetModel(cameraPropModel); camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0)); @@ -244,17 +255,27 @@ namespace src.player.skills Vector diffVector = SkillUtils.GetForwardVector(cameraProp.AbsRotation) * 25; Vector finalPos = cameraProp.AbsOrigin + diffVector; - var camera = Utilities.CreateEntityByName("prop_dynamic"); + uint ownerIndex = EntityManager.SystemOwnerIndex; + if (!string.IsNullOrEmpty(cameraProp.Globalname)) + { + var parts = cameraProp.Globalname.Split('_'); + if (parts.Length >= 3 && uint.TryParse(parts[^1], out var idx)) + ownerIndex = idx; + } + + var camera = EntityManager.CreateTrackedDynamicProp(ownerIndex); if (camera == null || !camera.IsValid) return null; Server.NextFrame(() => { if (camera == null || !camera.IsValid) return; + camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); camera.SetModel(cameraViewModel); camera.Render = Color.FromArgb(1, 255, 255, 255); camera.Teleport(finalPos, cameraProp.AbsRotation); camera.DispatchSpawn(); + EntityManager.RegisterExisting(camera, ownerIndex, "prop_dynamic"); }); return camera; @@ -272,10 +293,10 @@ namespace src.player.skills if (!param.Entity.Name.StartsWith("CypherCamera_")) return; var nameParams = param.Entity.Name.Split('_')[2]; - _ = ulong.TryParse(nameParams, out ulong steamID); - if (steamID == 0) return; + _ = uint.TryParse(nameParams, out uint userIndex); + if (userIndex == 0) return; - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)userIndex); if (player == null) return; if (playersInfo.TryGetValue(player.Index, out var playerSkill)) @@ -355,7 +376,7 @@ namespace src.player.skills var player = Utilities.GetPlayerFromIndex((int)playerSkill.Player); if (player == null || !player.IsValid) return; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float ticksLeft = playerSkill.NextCamera - Server.TickCount; diff --git a/jRandomSkills - SRC Files/src/player/skills/Darkness.cs b/jRandomSkills - SRC Files/src/player/skills/Darkness.cs index f9fddd2..c7c044a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Darkness.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Darkness.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; @@ -12,7 +12,8 @@ namespace src.player.skills public class Darkness : ISkill { private const Skills skillName = Skills.Darkness; - private static readonly ConcurrentDictionary playersInDark = []; + private static readonly ConcurrentDictionary playersInDark = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -26,31 +27,25 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - if (playersInDark.ContainsKey(player.SteamID)) + if (playersInDark.ContainsKey(player.Index)) DisableSkill(player); SkillUtils.CloseMenu(player); } playersInDark.Clear(); + playersToTarget.Clear(); } } - public static void PlayerDeath(EventPlayerDeath @event) - { - var player = @event.Userid; - if (player == null) return; - DisableSkill(player); - } - public static void OnTick() { 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); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); @@ -59,8 +54,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -70,7 +65,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -79,18 +75,20 @@ namespace src.player.skills } SetUpPostProcessing(enemy); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("darkness_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("darkness_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; @@ -104,34 +102,50 @@ namespace src.player.skills { lock (setLock) { - SetUpPostProcessing(player, true); + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + { + var target = Utilities.GetPlayerFromIndex((int)targetIndex); + if (target != null && target.IsValid) + SetUpPostProcessing(target, true); + playersInDark.TryRemove(targetIndex, out _); + } + SkillUtils.CloseMenu(player); } } + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + SetUpPostProcessing(player, true); + playersInDark.TryRemove(player.Index, out _); + SkillUtils.CloseMenu(player); + } + private static void SetUpPostProcessing(CCSPlayerController player, bool turnOff = false) { if (player == null || !player.IsValid) return; - ulong? playerSteamID = player?.SteamID; - if (playerSteamID == null) return; + uint playerIndex = player.Index; lock (setLock) { if (!turnOff) { - playersInDark.TryAdd((ulong)playerSteamID, 0); + playersInDark.TryAdd(playerIndex, 0); ApplyColor(player); Timer? darkTimer = null; darkTimer = Instance.AddTimer(5f, () => { - if (!playersInDark.ContainsKey((ulong)playerSteamID)) + if (!playersInDark.ContainsKey(playerIndex)) { darkTimer?.Kill(); return; } - var target = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.SteamID == playerSteamID); + var target = Utilities.GetPlayerFromIndex((int)playerIndex); if (target == null || !target.IsValid) { darkTimer?.Kill(); @@ -145,7 +159,7 @@ namespace src.player.skills else { SkillUtils.ApplyScreenColor(player, r: 0, g: 0, b: 0, a: 0, duration: 200, holdTime: 0); - playersInDark.TryRemove((ulong)playerSteamID, out _); + playersInDark.TryRemove(playerIndex, out _); } } } @@ -161,7 +175,7 @@ namespace src.player.skills holdTime: 3000); } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#383838", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Uncommon, int r = 0, int g = 0, int b = 0, int a = 230) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#383838", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Rare, int r = 0, int g = 0, int b = 0, int a = 230) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) { public int R { get; set; } = r; public int G { get; set; } = g; diff --git a/jRandomSkills - SRC Files/src/player/skills/Dash.cs b/jRandomSkills - SRC Files/src/player/skills/Dash.cs index 9bd4284..b84424f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dash.cs @@ -1,16 +1,15 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { public class Dash : ISkill { private const Skills skillName = Skills.Dash; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -26,37 +25,22 @@ namespace src.player.skills } } - public static void OnTick() - { - 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) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - { - UpdateHUD(player, skillInfo); - HandleDash(player, skillInfo); - } - } - } - public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + Username = player.PlayerName, CanUse = true, Cooldown = DateTime.MinValue, - LastFlags = 0, Jumps = 0, - LastButtons = 0 + WasOnGround = true, + JumpReleasedTicks = 10 }); } public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -72,7 +56,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -81,31 +65,49 @@ namespace src.player.skills playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"{cooldown}")}"; } + public static void OnTick() + { + foreach (var player in Utilities.GetPlayers()) + { + if (player == null || !player.IsValid) return; + + var eventPlayer = PlayerManager.GetPlayerEvent(player); + var playerInfo = PlayerManager.GetPlayerByIndex(eventPlayer!.Index); + + if (playerInfo?.Skill == skillName) + if (SkillPlayerInfo.TryGetValue(eventPlayer!.Index, out var skillInfo)) + { + UpdateHUD(player, skillInfo); + HandleDash(player, skillInfo); + } + } + } + private static void HandleDash(CCSPlayerController player, PlayerSkillInfo skillInfo) { - var playerPawn = player.PlayerPawn.Value; + var eventPlayer = PlayerManager.GetPlayerEvent(player); + var eventPlayerPawn = eventPlayer?.PlayerPawn?.Value; + if (eventPlayerPawn == null || !eventPlayerPawn.IsValid) return; + + var playerPawn = player.PlayerPawn?.Value; if (playerPawn == null || !playerPawn.IsValid) return; - var flags = (PlayerFlags)playerPawn.Flags; var buttons = player.Buttons; bool jumpPressed = (buttons & PlayerButtons.Jump) != 0 || (playerPawn.MovementServices?.QueuedButtonChangeMask & (ulong)PlayerButtons.Jump) != 0; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerPawn == null || playerInfo == null) return; + bool isOnGround = + eventPlayerPawn.GroundEntity != null + && eventPlayerPawn.GroundEntity.IsValid; - bool wasOnGround = (skillInfo.LastFlags & PlayerFlags.FL_ONGROUND) != 0; - bool isOnGround = (flags & PlayerFlags.FL_ONGROUND) != 0; - - if (wasOnGround && !isOnGround && jumpPressed) + if (skillInfo.WasOnGround && !isOnGround && jumpPressed) skillInfo.Jumps = 0; else if (isOnGround) skillInfo.Jumps = 0; else if (!isOnGround && jumpPressed && skillInfo.Jumps < 1) { - bool lastJumpPressed = (skillInfo.LastButtons & PlayerButtons.Jump) != 0; - if (!lastJumpPressed && skillInfo.CanUse) + if (skillInfo.JumpReleasedTicks >= 3 && skillInfo.CanUse) { skillInfo.Jumps++; skillInfo.CanUse = false; @@ -133,29 +135,33 @@ namespace src.player.skills moveY = 1; float moveAngle = MathF.Atan2(moveX, moveY) * (180f / MathF.PI); - QAngle dashAngles = new(0, playerPawn.EyeAngles.Y + moveAngle, 0); + QAngle dashAngles = new(0, eventPlayerPawn.EyeAngles.Y + moveAngle, 0); Vector newVelocity = SkillUtils.GetForwardVector(dashAngles) * SkillsInfo.GetValue(skillName, "pushVelocity"); - newVelocity.Z = playerPawn.AbsVelocity.Z + SkillsInfo.GetValue(skillName, "jumpVelocity"); + newVelocity.Z = eventPlayerPawn.AbsVelocity.Z + SkillsInfo.GetValue(skillName, "jumpVelocity"); - playerPawn.AbsVelocity.X = newVelocity.X; - playerPawn.AbsVelocity.Y = newVelocity.Y; - playerPawn.AbsVelocity.Z = newVelocity.Z; + eventPlayerPawn.AbsVelocity.X = newVelocity.X; + eventPlayerPawn.AbsVelocity.Y = newVelocity.Y; + eventPlayerPawn.AbsVelocity.Z = newVelocity.Z; } } - skillInfo.LastFlags = flags; - skillInfo.LastButtons = buttons; + skillInfo.WasOnGround = isOnGround; + + if (!jumpPressed) + skillInfo.JumpReleasedTicks++; + else + skillInfo.JumpReleasedTicks = 0; } public class PlayerSkillInfo { - public ulong SteamID { get; set; } + public string? Username { get; set; } public bool CanUse { get; set; } public DateTime Cooldown { get; set; } - public PlayerFlags LastFlags { get; set; } public int Jumps { get; set; } - public PlayerButtons LastButtons { get; set; } + public bool WasOnGround { get; set; } + public int JumpReleasedTicks { get; set; } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#42bbfc", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float jumpVelocity = 150f, float pushVelocity = 600f, bool anyDirection = true, float cooldown = 2f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs b/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs index 12d44f7..a36fe35 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Deactivator.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -28,15 +28,15 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; @@ -50,15 +50,16 @@ namespace src.player.skills { if (player == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -71,13 +72,13 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; @@ -91,7 +92,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SpecialSkill = Skills.None; SkillUtils.CloseMenu(player); @@ -99,8 +100,8 @@ namespace src.player.skills private static void DeacitvateSkill(CCSPlayerController player, CCSPlayerController enemy) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (playerInfo != null) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs index 19bb414..e791b66 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs @@ -1,8 +1,7 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -12,6 +11,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Deaf; private static readonly ConcurrentDictionary deafPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; public static void LoadSkill() { @@ -28,6 +28,8 @@ namespace src.player.skills } deafPlayers.Clear(); + playersToTarget.Clear(); + foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); } @@ -48,10 +50,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); @@ -60,8 +62,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -71,7 +73,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -80,18 +83,20 @@ namespace src.player.skills } deafPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("deaf_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -103,8 +108,19 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + deafPlayers.TryRemove(targetIndex, out _); + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + deafPlayers.TryRemove(player.Index, out _); + SkillUtils.CloseMenu(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dae01f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs index ed78c84..83e942b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs @@ -17,11 +17,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) { @@ -39,12 +39,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "chanceTo") - SkillsInfo.GetValue(skillName, "chanceFrom")) + SkillsInfo.GetValue(skillName, "chanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float chanceFrom = .2f, float chanceTo = .35f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Distancer.cs b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs index e604abf..9793565 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Distancer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -31,7 +31,7 @@ namespace src.player.skills var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) continue; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) continue; var playerPawn = player.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs index 8135a09..310152c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dracula.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dracula.cs @@ -17,11 +17,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) HealAttacker(attacker!, @event.DmgHealth); diff --git a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs index 333948b..3b9f2b9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; @@ -29,18 +28,20 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); 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(); + var enemies = Utilities.GetPlayers().Where(p => p != null && p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p => p != null && p.IsValid && p.Team != player.Team && p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0 && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; + menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString())); } SkillUtils.UpdateMenu(player, menuItems); @@ -51,12 +52,12 @@ namespace src.player.skills { if (player == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; string enemyId = commands[0]; var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Index.ToString() == enemyId); @@ -72,14 +73,14 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - 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(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p != player && p.IsValid && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag skills = []; ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; @@ -89,6 +90,7 @@ namespace src.player.skills int ctSkills = Event.counterterroristSkills.Count(s => skills.Contains(s.Name)); int ttSkills = Event.terroristSkills.Count(s => skills.Contains(s.Name)); + if ((player.Team == CsTeam.Terrorist && ctSkills == skills.Count) || (player.Team == CsTeam.CounterTerrorist && ttSkills == skills.Count)) { Event.SetRandomSkill(player); @@ -97,7 +99,7 @@ namespace src.player.skills SkillUtils.CreateMenu(player, menuItems); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } else player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); @@ -105,7 +107,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SpecialSkill = Skills.None; SkillUtils.CloseMenu(player); @@ -113,27 +115,27 @@ namespace src.player.skills private static void DuplicateSkill(CCSPlayerController player, CCSPlayerController enemy) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (playerInfo == null || enemyInfo == null) return; var enemySkill = enemyInfo.Skill; bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString()); - ulong steamID = player.SteamID; + uint playerIndex = player.Index; string enemyName = enemy.PlayerName; if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill)) { Instance.AddTimer(.1f, () => { - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemyName)); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); return; } @@ -146,15 +148,16 @@ namespace src.player.skills if (SkillsInfo.GetValue(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return; + var dupInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (dupInfo == null || dupInfo.Skill != enemySkill) return; Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); else Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); player.PrintToChat($" {ChatColors.Green}" + player.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 997bab7..8720009 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -26,7 +26,7 @@ namespace src.player.skills public static unsafe void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var playerPawn = player.PlayerPawn?.Value; @@ -38,13 +38,13 @@ namespace src.player.skills SkillUtils.ChangePlayerScale(player, newSize); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSize)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } } public static void DisableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var playerPawn = player.PlayerPawn?.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/Earthquake.cs b/jRandomSkills - SRC Files/src/player/skills/Earthquake.cs index 162a94b..ce7adb4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Earthquake.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Earthquake.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -9,136 +9,133 @@ namespace src.player.skills { public class Earthquake : ISkill { - private const Skills skillName = Skills.Earthquake; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; - private static readonly object setLock = new(); + //private const Skills skillName = Skills.Earthquake; + //private static readonly ConcurrentDictionary SkillPlayerInfo = []; + //private static readonly object setLock = new(); - public static void LoadSkill() - { - // SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - } + //public static void LoadSkill() + //{ + // SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + //} - public static void NewRound() - { - lock (setLock) - SkillPlayerInfo.Clear(); - } + //public static void NewRound() + //{ + // lock (setLock) + // SkillPlayerInfo.Clear(); + //} - public static void EnableSkill(CCSPlayerController player) - { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo - { - SteamID = player.SteamID, - CanUse = true, - Cooldown = DateTime.MinValue, - }); - } + //public static void EnableSkill(CCSPlayerController player) + //{ + // SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo + // { + // SteamID = player.Index, + // CanUse = true, + // Cooldown = DateTime.MinValue, + // }); + //} - public static void DisableSkill(CCSPlayerController player) - { - SkillPlayerInfo.TryRemove(player.SteamID, out _); - SkillUtils.ResetPrintHTML(player); - } + //public static void DisableSkill(CCSPlayerController player) + //{ + // SkillPlayerInfo.TryRemove(player.Index, out _); + // SkillUtils.ResetPrintHTML(player); + //} - 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.TryRemove(player.SteamID, out _); - } + //public static void PlayerDeath(EventPlayerDeath @event) + //{ + // var player = PlayerManager.GetPlayerEvent(@event.Userid); + // if (player == null || !player.IsValid) return; + // var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + // if (playerInfo?.Skill == skillName) + // SkillPlayerInfo.TryRemove(player.Index, out _); + //} - 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 OnTick() + //{ + // foreach (var player in Utilities.GetPlayers()) + // { + // var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + // if (playerInfo?.Skill == skillName) + // if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) + // UpdateHUD(player, skillInfo); + // } + //} - private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) - { - float cooldown = 0; - if (skillInfo != null) - { - float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); - cooldown = Math.Max(time, 0); + //private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) + //{ + // float cooldown = 0; + // if (skillInfo != null) + // { + // float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "cooldown")) - DateTime.Now).TotalSeconds); + // cooldown = Math.Max(time, 0); - if (cooldown == 0 && skillInfo?.CanUse == false) - skillInfo.CanUse = true; - } + // if (cooldown == 0 && skillInfo?.CanUse == false) + // skillInfo.CanUse = true; + // } - if (cooldown == 0) - return; + // if (cooldown == 0) + // return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); - if (playerInfo == null) return; + // var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + // if (playerInfo == null) return; - string remainingLine = $"{player.GetTranslation("hud_info", $"{cooldown}")}"; - } + // string remainingLine = $"{player.GetTranslation("hud_info", $"{cooldown}")}"; + //} - public static void UseSkill(CCSPlayerController player) - { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; + //public static void UseSkill(CCSPlayerController player) + //{ + // var playerPawn = player.PlayerPawn.Value; + // if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) - { - if (!player.IsValid || !player.PawnIsAlive) return; - if (skillInfo.CanUse) - { - skillInfo.CanUse = false; - skillInfo.Cooldown = DateTime.Now; - MakeShake(player); - } - } - } + // if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) + // { + // if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + // if (skillInfo.CanUse) + // { + // skillInfo.CanUse = false; + // skillInfo.Cooldown = DateTime.Now; + // MakeShake(player); + // } + // } + //} - private static void MakeShake(CCSPlayerController player) - { - foreach (var enemy in Utilities.GetPlayers().Where(p => p != null && p.IsValid && p.PawnIsAlive)) - CreateShake(player); - } + //private static void MakeShake(CCSPlayerController player) + //{ + // foreach (var enemy in Utilities.GetPlayers().Where(p => p != null && p.IsValid && p.PawnIsAlive)) + // CreateShake(player); + //} - private static void CreateShake(CCSPlayerController player) - { - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; + //private static void CreateShake(CCSPlayerController player) + //{ + // var pawn = player.PlayerPawn.Value; + // if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - var shake = Utilities.CreateEntityByName("env_shake"); - if (shake == null) return; + // var shake = EntityManager.CreateTrackedEnvShake(player.Index); + // if (shake == null || !shake.IsValid) return; - shake.DispatchSpawn(); - if (!shake.IsValid) return; + // shake.Amplitude = SkillsInfo.GetValue(skillName, "amplitude"); + // shake.Frequency = SkillsInfo.GetValue(skillName, "frequency"); + // shake.Duration = SkillsInfo.GetValue(skillName, "duration"); + // shake.Radius = SkillsInfo.GetValue(skillName, "radius"); - shake.Amplitude = SkillsInfo.GetValue(skillName, "amplitude"); - shake.Frequency = SkillsInfo.GetValue(skillName, "frequency"); - shake.Duration = SkillsInfo.GetValue(skillName, "duration"); - shake.Radius = SkillsInfo.GetValue(skillName, "radius"); + // shake.Teleport(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z)); + // shake.AcceptInput("SetParent", pawn, pawn, "!activator"); + // shake.AcceptInput("StartShake"); + //} - shake.Teleport(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z)); - shake.AcceptInput("SetParent", pawn, pawn, "!activator"); - shake.AcceptInput("StartShake"); - } + //public class PlayerSkillInfo + //{ + // public ulong SteamID { get; set; } + // public bool CanUse { get; set; } + // public DateTime Cooldown { get; set; } + //} - public class PlayerSkillInfo - { - public ulong SteamID { get; set; } - public bool CanUse { get; set; } - public DateTime Cooldown { get; set; } - } - - public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#42f59b", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float cooldown = 16f, float amplitude = 15f, float frequency = 500f, float duration = 8f, float radius = 50f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) - { - public float Cooldown { get; set; } = cooldown; - public float Amplitude { get; set; } = amplitude; - public float Frequency { get; set; } = frequency; - public float Duration { get; set; } = duration; - public float Radius { get; set; } = radius; - } + //public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#42f59b", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float cooldown = 16f, float amplitude = 15f, float frequency = 500f, float duration = 8f, float radius = 50f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) + //{ + // public float Cooldown { get; set; } = cooldown; + // public float Amplitude { get; set; } = amplitude; + // public float Frequency { get; set; } = frequency; + // public float Duration { get; set; } = duration; + // public float Radius { get; set; } = radius; + //} } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs b/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs index 06b79a7..f126a1b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs +++ b/jRandomSkills - SRC Files/src/player/skills/EnemySpawn.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -10,7 +9,7 @@ namespace src.player.skills public class EnemySpawn : ISkill { private const Skills skillName = Skills.EnemySpawn; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -29,9 +28,9 @@ namespace src.player.skills if (SkillUtils.IsFreezeTime()) return; foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } @@ -39,9 +38,9 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { var cooldownBeforeUse = SkillsInfo.GetValue(skillName, "cooldownBeforeUse"); - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = false, Cooldown = cooldownBeforeUse <= 0 ? DateTime.MinValue : Event.GetFreezeTimeEnd().AddSeconds(cooldownBeforeUse - SkillsInfo.GetValue(skillName, "cooldown")), }); @@ -49,7 +48,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -65,7 +64,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -79,9 +78,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (skillInfo.CanUse) { skillInfo.CanUse = false; diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs index 88f877f..1824f20 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -21,14 +21,14 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } private static void SpawnExplosion(Vector vector) @@ -64,12 +64,12 @@ namespace src.player.skills { if (lastTick == Server.TickCount) return; - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; var pos = new Vector(@event.X, @event.Y, @event.Z); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null || playerInfo.Skill != skillName) return; if (Instance.Random.NextDouble() <= playerInfo.SkillChance) diff --git a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs index ba8bf02..f4528a2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using System.Drawing; @@ -11,7 +11,7 @@ namespace src.player.skills public class FalconEye : ISkill { private const Skills skillName = Skills.FalconEye; - private static readonly ConcurrentDictionary cameras = []; + private static readonly ConcurrentDictionary cameras = []; public static void LoadSkill() { @@ -21,28 +21,23 @@ namespace src.player.skills public static void NewRound() { foreach (var cameraIndex in cameras.Values) - { - var camera = Utilities.GetEntityFromIndex((int)cameraIndex.Item2); - if (camera == null || !camera.IsValid) continue; - - camera.AcceptInput("Kill"); - } + EntityManager.DestroyEntity(cameraIndex.Item2); cameras.Clear(); } public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return ; 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) + if (cameras.TryGetValue(player!.Index, out var cameraInfo) && cameraInfo.Item1 == pawn.CameraServices.ViewEntity.Raw) BlockWeapon(player, true); } @@ -55,13 +50,15 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (player == null) return; ChangeCamera(player, true); + EntityManager.DestroyPlayerEntities(player.Index); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; @@ -88,7 +85,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; @@ -114,7 +111,7 @@ namespace src.player.skills private static uint CreateCamera(CCSPlayerController player) { - var camera = Utilities.CreateEntityByName("prop_dynamic"); + var camera = EntityManager.CreateTrackedDynamicProp(player.Index); if (camera == null || !camera.IsValid) return 0; var pawn = player.PlayerPawn.Value; @@ -124,13 +121,14 @@ namespace src.player.skills Server.NextFrame(() => { if (camera == null || !camera.IsValid) return; + camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); camera.SetModel("models/sprays/spray_plane.vmdl"); camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Teleport(pos, new QAngle(90, 0, 0)); camera.DispatchSpawn(); }); - cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (k, v) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index)); + cameras.AddOrUpdate(player.Index, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (k, v) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index)); return camera.EntityHandle.Raw; } diff --git a/jRandomSkills - SRC Files/src/player/skills/FastReload.cs b/jRandomSkills - SRC Files/src/player/skills/FastReload.cs index b4c7603..176e5e7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FastReload.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FastReload.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -20,9 +20,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; InstaReload(playerPawn); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Flash.cs b/jRandomSkills - SRC Files/src/player/skills/Flash.cs index 71a807a..1957898 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Flash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Flash.cs @@ -11,7 +11,7 @@ namespace src.player.skills public class Flash : ISkill { private const Skills skillName = Skills.Flash; - public static readonly ConcurrentDictionary jumpedPlayers = []; + public static readonly ConcurrentDictionary jumpedPlayers = []; public static void LoadSkill() { @@ -34,7 +34,7 @@ namespace src.player.skills 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 playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (player!.Buttons.HasFlag(PlayerButtons.Speed) || player.Buttons.HasFlag(PlayerButtons.Duck)) @@ -43,26 +43,26 @@ namespace src.player.skills public static void PlayerJump(EventPlayerJump @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - if (!jumpedPlayers.TryGetValue(player.SteamID, out _)) return; - jumpedPlayers.AddOrUpdate(player.SteamID, Server.TickCount + 20, (k, v) => Server.TickCount + 20); + if (!jumpedPlayers.TryGetValue(player.Index, out _)) return; + jumpedPlayers.AddOrUpdate(player.Index, Server.TickCount + 20, (k, v) => Server.TickCount + 20); } public static void EnableSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerPawn == null || playerInfo == null) return; float newSpeed = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); newSpeed = (float)Math.Round(newSpeed, 2); playerInfo.SkillChance = newSpeed; - jumpedPlayers.TryAdd(player.SteamID, 0); + jumpedPlayers.TryAdd(player.Index, 0); playerPawn.VelocityModifier = newSpeed; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSpeed)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public static void DisableSkill(CCSPlayerController player) @@ -70,7 +70,7 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn == null) return; playerPawn.VelocityModifier = 1; - jumpedPlayers.TryRemove(player.SteamID, out _); + jumpedPlayers.TryRemove(player.Index, out _); } public static void OnTick() @@ -79,7 +79,7 @@ namespace src.player.skills { if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) continue; var playerPawn = player.PlayerPawn?.Value; @@ -90,7 +90,7 @@ namespace src.player.skills if (buttons.HasFlag(PlayerButtons.Moveleft) || buttons.HasFlag(PlayerButtons.Moveright) || buttons.HasFlag(PlayerButtons.Forward) || buttons.HasFlag(PlayerButtons.Back)) playerPawn.VelocityModifier = newVelocity; - if (jumpedPlayers.TryGetValue(player.SteamID, out var time) && time > Server.TickCount) + if (jumpedPlayers.TryGetValue(player.Index, out var time) && time > Server.TickCount) continue; if (!((PlayerFlags)player.Flags).HasFlag(PlayerFlags.FL_ONGROUND)) diff --git a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs index b96a6b1..f405ae0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -11,8 +11,9 @@ namespace src.player.skills public class Fortnite : ISkill { private const Skills skillName = Skills.Fortnite; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; - private static readonly ConcurrentDictionary barricades = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary barricades = []; + public static bool skillInThisRound = false; private static readonly object setLock = new(); public static void LoadSkill() @@ -23,6 +24,7 @@ namespace src.player.skills public static void NewRound() { + skillInThisRound = false; lock (setLock) { SkillPlayerInfo.Clear(); @@ -34,18 +36,19 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + skillInThisRound = true; + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -53,7 +56,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -69,7 +72,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -83,9 +86,10 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + if (skillInfo.CanUse) { skillInfo.CanUse = false; @@ -98,7 +102,7 @@ namespace src.player.skills private static void CreateBox(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - var box = Utilities.CreateEntityByName("prop_dynamic_override"); + var box = EntityManager.CreateTrackedPropOverride(player.Index); if (box == null || playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; float distance = 50; @@ -140,12 +144,12 @@ namespace src.player.skills if (newHealth <= 0) { barricades.TryRemove(box.Index, out _); - box.AcceptInput("Kill"); + EntityManager.DestroyEntity(box.Index); } else barricades.AddOrUpdate(box.Index, newHealth, (k, v) => newHealth); } - else box.AcceptInput("Kill"); + else EntityManager.DestroyEntity(box.Index); } public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs index 434797f..8a8a4e6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -40,7 +40,7 @@ namespace src.player.skills plantedC4 = null; var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null && plantedBomb.IsValid) - plantedBomb.AcceptInput("Kill"); + plantedBomb.AddEntityIOEvent("Kill", plantedBomb, delay: 0.1f); SkillUtils.TerminateRound(CsTeam.CounterTerrorist); } @@ -48,12 +48,12 @@ namespace src.player.skills { if (lastTick == Server.TickCount) return; - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid || plantedC4 == null) return; var pos = new Vector(@event.X, @event.Y, @event.Z); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null || playerInfo.Skill != skillName) return; if (SkillUtils.Distance(plantedC4, pos) >= 8) diff --git a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs index 4acd791..2e2481e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs @@ -1,6 +1,5 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -20,15 +19,14 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { var damage = @event.DmgHealth; - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var weapon = @event.Weapon; - HitGroup_t hitgroup = (HitGroup_t)@event.Hitgroup; 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); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill != skillName || attacker!.Team != victim!.Team) return; Server.ExecuteCommand("mp_autokick 0"); diff --git a/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs b/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs index a9bc602..1a07aa9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FrozenDecoy.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -25,10 +24,10 @@ namespace src.player.skills public static void DecoyStarted(EventDecoyStarted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; decoys.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0); @@ -36,10 +35,10 @@ namespace src.player.skills public static void DecoyDetonate(EventDecoyDetonate @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; foreach (var decoy in decoys.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z)) @@ -49,11 +48,16 @@ namespace src.player.skills public static void OnTick() { foreach (Vector decoyPos in decoys.Keys) - foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { + var eventPlayer = PlayerManager.GetPlayerEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) continue; + var decoyRadius = SkillsInfo.GetValue(skillName, "triggerRadius"); - var pawn = player.PlayerPawn.Value; + + var pawn = eventPlayer.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; + double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin); if (distance <= decoyRadius) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Gambler.cs b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs index 1c067e7..ac48132 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Gambler.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -24,11 +24,11 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; - ulong steamID = player.SteamID; + uint playerIndex = player.Index; if (playerInfo.SkillUsed) { @@ -58,15 +58,16 @@ namespace src.player.skills if (SkillsInfo.GetValue(skill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == steamID && p.Skill == skill.Skill) == null) return; + var pi = PlayerManager.GetPlayerByIndex(playerIndex); + if (pi == null || pi.Skill != skill.Skill) return; Instance?.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); else Instance?.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } private static bool TakeMoney(CCSPlayerController player) @@ -86,7 +87,7 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; @@ -107,13 +108,13 @@ namespace src.player.skills private static List GetSkills(CCSPlayerController player) { - var skillPlayer = Instance?.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) return [Event.noneSkill]; List skillList = [.. 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) + if (Utilities.GetPlayers().FindAll(p => p.Team == player.Team && p.IsValid && !p.IsHLTV && p.Team != CsTeam.Spectator).Count == 1) { SkillsInfo.DefaultSkillInfo[] skillsNeedsTeammates = SkillsInfo.LoadedConfig.Where(s => s.NeedsTeammates).ToArray(); skillList.RemoveAll(s => skillsNeedsTeammates.Any(s2 => s2.Name == s.Skill.ToString())); diff --git a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs index c4ac52c..6bbbc05 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs @@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; using System.Collections.Immutable; +using System.Drawing; using static src.jRandomSkills; namespace src.player.skills @@ -26,11 +27,13 @@ namespace src.player.skills ]; private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; + private const string cameraViewModel = "models/sprays/spray_plane.vmdl"; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); Instance.AddToManifest(bloodParticle); + Instance.AddToManifest(cameraViewModel); } public static void NewRound() @@ -42,9 +45,9 @@ namespace src.player.skills public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; SetWeaponAttack(player!, true); @@ -52,9 +55,9 @@ namespace src.player.skills public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; SetWeaponAttack(player!, true); @@ -64,7 +67,7 @@ namespace src.player.skills { foreach (var (info, player) in infoList) { - if (player == null || !player.IsValid) continue; + if (player == null || !player.IsValid || player.Team == CsTeam.Spectator) continue; var targetHandle = player.Pawn.Value?.ObserverServices?.ObserverTarget.Value?.Handle ?? nint.Zero; bool isObservingGhost = false; @@ -72,14 +75,17 @@ namespace src.player.skills if (targetHandle != nint.Zero) { var target = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == targetHandle); - var targetInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == target?.SteamID); + var targetInfo = PlayerManager.GetPlayerByIndex(target?.Index); if (targetInfo?.Skill == skillName) isObservingGhost = true; } foreach (var playerIndex in invisiblePlayers.Keys) { var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); - if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + if (playerController == null || !playerController.IsValid || playerController.Index == player.Index) + continue; + + if (player.Team == playerController.Team) continue; if (!isObservingGhost) @@ -108,48 +114,92 @@ namespace src.player.skills { Event.EnableTransmit(); SetWeaponAttack(player, true); + SkillUtils.SetPlayerInvisibility(player, .5f); invisiblePlayers.TryAdd(player.Index, 0); + + if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0) + CreatePlayerPosProp(player); + } + + private static void CreatePlayerPosProp(CCSPlayerController player) + { + if (player == null || !player.IsValid) return; + + var emptyProp = EntityManager.CreateTrackedDynamicProp(player.Index); + if (emptyProp == null || !emptyProp.IsValid) return; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; + + emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); + emptyProp.SetModel(cameraViewModel); + emptyProp.Render = Color.FromArgb(1, 255, 255, 255); + + Vector newPos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 30); + QAngle newAngle = new(playerPawn.AbsRotation.X, playerPawn.AbsRotation.Y, playerPawn.AbsRotation.Z); + + emptyProp.Teleport(newPos, newAngle); + emptyProp.DispatchSpawn(); + + Utilities.SetStateChanged(emptyProp, "CBaseEntity", "m_CBodyComponent"); + + EntityManager.RegisterExisting(emptyProp, player.Index, "empty_prop"); } public static void DisableSkill(CCSPlayerController player) { SkillUtils.ResetPrintHTML(player); SetWeaponAttack(player, false); + SkillUtils.SetPlayerInvisibility(player, 0); + invisiblePlayers.TryRemove(player.Index, out _); + EntityManager.DestroyPlayerEntities(player.Index); } public static void OnTick() { + if (Server.TickCount % 2 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) UpdateHUD(player); - if (!player.PawnIsAlive) + if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) invisiblePlayers.TryRemove(player.Index, out _); + + if (!invisiblePlayers.ContainsKey(player.Index)) continue; + + var props = EntityManager.GetPlayerEntities(player.Index, "empty_prop"); + if (props.Count == 0) continue; + + var prop = Utilities.GetEntityFromIndex((int)props[0]); + if (prop == null || !prop.IsValid) continue; + + var pawn = player.PlayerPawn?.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; + + Vector newPos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + 30); + QAngle newAngle = new(0, pawn.V_angle.Y, 0); + prop.Teleport(newPos, newAngle, null); } } public static void PlayerHurt(EventPlayerHurt @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; - CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + var particle = EntityManager.CreateTrackedParticleSystem(player.Index, bloodParticle, autoDestroySeconds: 3f); if (particle == null) return; - particle.EffectName = bloodParticle; - particle.StartActive = true; - Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); particle.Teleport(pos); - particle.DispatchSpawn(); - particle.AcceptInput("Start"); } @@ -177,7 +227,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var weapon = pawn.WeaponServices.ActiveWeapon.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/Glaz.cs b/jRandomSkills - SRC Files/src/player/skills/Glaz.cs index fadc0c5..f6bb458 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glaz.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glaz.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Entities.Constants; @@ -41,10 +41,10 @@ namespace src.player.skills foreach (var (info, player) in infoList) { if (player == null) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); var observedPlayer = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == player?.Pawn?.Value?.ObserverServices?.ObserverTarget?.Value?.Handle); - var observerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == observedPlayer?.SteamID); + var observerInfo = observedPlayer != null ? PlayerManager.GetPlayerByIndex(observedPlayer.Index) : null; if (playerInfo?.Skill != skillName && observerInfo?.Skill != skillName) continue; foreach (var entityIndex in smokes.Keys) diff --git a/jRandomSkills - SRC Files/src/player/skills/Glitch.cs b/jRandomSkills - SRC Files/src/player/skills/Glitch.cs index e95be07..912e13e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glitch.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glitch.cs @@ -1,16 +1,17 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; namespace src.player.skills { public class Glitch : ISkill { private const Skills skillName = Skills.Glitch; - private static readonly ConcurrentDictionary glitchedPlayers = []; + private static readonly ConcurrentDictionary glitchedPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -21,30 +22,28 @@ namespace src.player.skills public static void NewRound() { lock (setLock) - glitchedPlayers.Clear(); - foreach (var player in Utilities.GetPlayers()) { - DisableSkill(player); - SkillUtils.CloseMenu(player); + foreach (var player in Utilities.GetPlayers()) + { + DisableSkill(player); + SkillUtils.CloseMenu(player); + } + + glitchedPlayers.Clear(); + playersToTarget.Clear(); } } - public static void PlayerDeath(EventPlayerDeath @event) - { - var player = @event.Userid; - if (player == null) return; - DisableSkill(player); - } public static void OnTick() { 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); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -53,8 +52,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -64,7 +63,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -72,20 +72,23 @@ namespace src.player.skills return; } - glitchedPlayers.TryAdd(enemy, 0); + glitchedPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; + enemy.ReplicateConVar("sv_disable_radar", "1"); playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("glitch_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("glitch_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -97,8 +100,24 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + { + var target = Utilities.GetPlayerFromIndex((int)targetIndex); + if (target != null && target.IsValid) + target.ReplicateConVar("sv_disable_radar", "0"); + glitchedPlayers.TryRemove(targetIndex, out _); + } + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + player.ReplicateConVar("sv_disable_radar", "0"); - glitchedPlayers.TryRemove(player, out _); + glitchedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Glue.cs b/jRandomSkills - SRC Files/src/player/skills/Glue.cs index e2589df..52c8268 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Glue.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Glue.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -29,7 +28,7 @@ namespace src.player.skills var player = pawn.Controller.Value.As(); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; grenade.Bounces = 555; } diff --git a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs index 775fa4c..05cc683 100644 --- a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs +++ b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs @@ -1,6 +1,5 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; @@ -11,7 +10,7 @@ namespace src.player.skills public class GodMode : ISkill { private const Skills skillName = Skills.GodMode; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -27,9 +26,9 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -39,16 +38,16 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); var playerPawn = player.PlayerPawn.Value; @@ -68,7 +67,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -82,29 +81,29 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - ulong steamID = player.SteamID; + uint playerIndex = player.Index; - if (SkillPlayerInfo.TryGetValue(steamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(playerIndex, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (skillInfo.CanUse) { skillInfo.CanUse = false; skillInfo.Cooldown = DateTime.Now; - player.PrintToChat($" {ChatColors.Green} {player.GetTranslation("godmode_on")}"); + PlayerManager.GetPlayerFromEvent(player)?.PrintToChat($" {ChatColors.Green} {player.GetTranslation("godmode_on")}"); player.PlayerPawn.Value.TakesDamage = false; Instance.AddTimer(SkillsInfo.GetValue(skillName, "duration"), () => { - - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player != null && player.IsValid && player.PawnIsAlive) + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player != null && player.IsValid) { if (player.PlayerPawn == null || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + player.PlayerPawn.Value.TakesDamage = true; - player.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}"); + PlayerManager.GetPlayerFromEvent(player)?.PrintToChat($" {ChatColors.Red} {player.GetTranslation("godmode_off")}"); } - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Grenadier.cs b/jRandomSkills - SRC Files/src/player/skills/Grenadier.cs index c866a6d..85d649c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Grenadier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Grenadier.cs @@ -24,11 +24,11 @@ namespace src.player.skills public static void GrenadeThrown(EventGrenadeThrown @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Weapon; if (weapon != "hegrenade" || !Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) player!.GiveNamedItem($"weapon_{weapon}"); } diff --git a/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs b/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs index 84ef9dd..72337ec 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HealingChicken.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Timers; @@ -13,72 +13,70 @@ namespace src.player.skills { public class HealingChicken : ISkill { - private const Skills skillName = Skills.HealingChicken; - private readonly static ConcurrentDictionary> playerSmokes = []; - private static readonly object setLock = new(); + //private const Skills skillName = Skills.HealingChicken; + //private readonly static ConcurrentDictionary> playerSmokes = []; + //private static readonly object setLock = new(); - public static void LoadSkill() - { - // SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - } + //public static void LoadSkill() + //{ + // SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + //} - public static void NewRound() - { + //public static void NewRound() + //{ - } + //} - public static void EnableSkill(CCSPlayerController player) - { - SpawnChicken(player); - } + //public static void EnableSkill(CCSPlayerController player) + //{ + // SpawnChicken(player); + //} - public static void DisableSkill(CCSPlayerController player) - { + //public static void DisableSkill(CCSPlayerController player) + //{ - } + //} - private static void SpawnChicken(CCSPlayerController player) - { - if (player == null || !player.IsValid) return; + //private static void SpawnChicken(CCSPlayerController player) + //{ + // if (player == null || !player.IsValid) return; - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; + // var pawn = player.PlayerPawn.Value; + // if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - int amount = SkillsInfo.GetValue(skillName, "amount"); - for (int i = 0; i < 1; i++) - { - CChicken? chicken = Utilities.CreateEntityByName("chicken"); - if (chicken == null || !chicken.IsValid) continue; + // int amount = SkillsInfo.GetValue(skillName, "amount"); + // for (int i = 0; i < 1; i++) + // { + // CChicken? chicken = EntityManager.CreateTrackedChicken(player.Index); + // if (chicken == null || !chicken.IsValid) continue; - chicken.Render = Color.Green; - Vector offset = new ( - (float)(100 * Math.Cos(2 * Math.PI * i / amount)), - (float)(100 * Math.Sin(2 * Math.PI * i / amount)), - 0 - ); + // chicken.Render = Color.Green; + // Vector offset = new ( + // (float)(100 * Math.Cos(2 * Math.PI * i / amount)), + // (float)(100 * Math.Sin(2 * Math.PI * i / amount)), + // 0 + // ); - chicken.DispatchSpawn(); - chicken.Teleport(pawn.AbsOrigin + offset); + // chicken.Teleport(pawn.AbsOrigin + offset); - // Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_leader", player.PlayerPawn.Raw); - Vector spawn = SkillUtils.GetSpawnPointVector(player); - Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_vecPathGoal", spawn); + // // Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_leader", player.PlayerPawn.Raw); + // Vector? spawn = SkillUtils.GetSpawnPointVector(player); + // Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_vecPathGoal", spawn); - float speed = 50; - Instance.AddTickTimer(1, () => - { - if (chicken == null || !chicken.IsValid) return; + // Instance.AddTickTimer(1, () => + // { + // if (chicken == null || !chicken.IsValid) return; - Server.PrintToChatAll($"{chicken.PathGoal}, {chicken.UpdateTimer.Duration}, {chicken.UpdateTimer.Timescale}"); - }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); - } - } + // Server.PrintToChatAll($"{chicken.PathGoal}, {chicken.UpdateTimer.Duration}, {chicken.UpdateTimer.Timescale}"); + // }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); + // } + //} - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int amount = 3, int heal = 2, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) - { - public int Amount { get; set; } = amount; - public int Heal { get; set; } = heal; - public int TickCooldown { get; set; } = tickCooldown; - } + //public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int amount = 3, int heal = 2, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) + //{ + // public int Amount { get; set; } = amount; + // public int Heal { get; set; } = heal; + // public int TickCooldown { get; set; } = tickCooldown; + //} } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs index 5642387..9f19cb7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -25,10 +24,10 @@ namespace src.player.skills public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; smokes.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0); @@ -36,10 +35,10 @@ namespace src.player.skills public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; foreach (var smoke in smokes.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z)) @@ -60,7 +59,7 @@ namespace src.player.skills var player = pawn.Controller.Value.As(); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; Server.NextFrame(() => @@ -82,13 +81,17 @@ namespace src.player.skills int smokeHeal = SkillsInfo.GetValue(skillName, "smokeHeal"); foreach (Vector smokePos in smokes.Keys) - foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive)) + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid)) { - var pawn = player.PlayerPawn.Value; + var eventPlayer = PlayerManager.GetPlayerEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) continue; + + var pawn = eventPlayer.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; if (SkillUtils.GetDistance(smokePos, pawn.AbsOrigin) <= smokeRadius) - AddHealth(pawn, smokeHeal); + if (SkillUtils.AddHealth(pawn, smokeHeal)) + player.EmitSound("Healthshot.Success"); } } @@ -97,18 +100,6 @@ namespace src.player.skills SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade); } - private static void AddHealth(CCSPlayerPawn player, int health) - { - if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) - return; - - if (player.Health != player.MaxHealth) - player.EmitSound("Healthshot.Success"); - - player.Health = Math.Min(player.Health + health, player.MaxHealth); - Utilities.SetStateChanged(player, "CBaseEntity", "m_iHealth"); - } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1fe070", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeHeal = 1, float smokeRadius = 180, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) { public int SmokeHeal { get; set; } = smokeHeal; diff --git a/jRandomSkills - SRC Files/src/player/skills/Hermit.cs b/jRandomSkills - SRC Files/src/player/skills/Hermit.cs index 1033c5b..c225c22 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Hermit.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Hermit.cs @@ -31,10 +31,10 @@ namespace src.player.skills public static void PlayerDeath(EventPlayerDeath @event) { - var attacker = @event.Attacker; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); if (!Instance.IsPlayerValid(attacker)) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo?.Skill != skillName) return; var pawn = attacker!.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs index d82d848..6d8f2e6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; @@ -32,7 +32,7 @@ namespace src.player.skills 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); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; hegrenade.Damage *= SkillsInfo.GetValue(skillName, "damageMultiplier"); diff --git a/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs b/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs index 9d5275f..f8d1093 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -41,13 +40,13 @@ namespace src.player.skills Vector currentPos = new(nade.AbsOrigin.X, nade.AbsOrigin.Y, nade.AbsOrigin.Z); double distanceMoved = SkillUtils.GetDistance(currentPos, oldPos); - Vector calculatedVelocity = CalculateVelocity(nade, nade.TeamNum); + Vector? calculatedVelocity = CalculateVelocity(nade, nade.TeamNum); - bool isZero = calculatedVelocity.IsZero(); + bool isZero = calculatedVelocity?.IsZero() == true; - if (distanceMoved < 4 || isZero) + if (distanceMoved < 4 || calculatedVelocity == null || isZero) { - nade.DetonateTime = isZero ? 0 : nade.CreateTime + 3; + nade.DetonateTime = isZero ? 0f : nade.CreateTime + 1.5f; Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime"); nades.TryRemove(index, out _); @@ -67,9 +66,9 @@ namespace src.player.skills } } - private static Vector CalculateVelocity(CBaseCSGrenadeProjectile nade, int team) + private static Vector? CalculateVelocity(CBaseCSGrenadeProjectile nade, int team) { - if (nade.AbsOrigin == null) return Vector.Zero; + if (nade.AbsOrigin == null) return null; Vector? closetEnemyPos = null; double minDistance = int.MaxValue; @@ -95,7 +94,7 @@ namespace src.player.skills } if (closetEnemyPos == null) - return Vector.Zero; + return null; Vector direction = closetEnemyPos - nadePos; float length = direction.Length(); @@ -127,7 +126,7 @@ namespace src.player.skills if (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); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; Vector pos = new(grenade.AbsOrigin?.X, grenade.AbsOrigin?.Y, grenade.AbsOrigin?.Z); @@ -136,7 +135,7 @@ namespace src.player.skills Server.NextWorldUpdate(() => { if (grenade == null || !grenade.IsValid) return; - grenade.DetonateTime += 100f; + grenade.DetonateTime += 30f; Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime"); }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/HotBomb.cs b/jRandomSkills - SRC Files/src/player/skills/HotBomb.cs index 07c1359..41ee1ff 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HotBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HotBomb.cs @@ -27,7 +27,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.Team == CsTeam.Terrorist && p.PawnIsAlive)) { - var pawn = player.PlayerPawn.Value; + var playerEvent = PlayerManager.GetPlayerEvent(player); + if (playerEvent == null || !playerEvent.IsValid) continue; + + var pawn = playerEvent.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) continue; bool hasC4 = pawn.WeaponServices.MyWeapons.Any(w => w.Value?.DesignerName == "weapon_c4"); @@ -40,7 +43,7 @@ namespace src.player.skills public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; var weapon = @event.Item; @@ -66,7 +69,7 @@ namespace src.player.skills public static void PlayerDeath(EventPlayerDeath @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; players.TryRemove(player.Index, out _); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Iana.cs b/jRandomSkills - SRC Files/src/player/skills/Iana.cs index b4b9be7..aa1805a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Iana.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Iana.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Timers; @@ -25,14 +25,16 @@ namespace src.player.skills { foreach (var playerSkill in playersInfo.Values) KillClone(playerSkill); + lock (setLock) playersInfo.Clear(); } public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null) return; + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) if (playerSkill.CloneProp != null) BlockWeapon(player, true); @@ -40,8 +42,9 @@ namespace src.player.skills public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null) return; + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) if (playerSkill.CloneProp != null) BlockWeapon(player, true); @@ -77,9 +80,11 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (player == null) return; if (playersInfo.TryGetValue(player.Index, out var playerSkill)) KillClone(playerSkill); playersInfo.TryRemove(player.Index, out _); + EntityManager.DestroyPlayerEntities(player.Index); } private static void UpdateWeapons(CCSPlayerController player, PlayerSkill playerSkill) @@ -119,12 +124,16 @@ namespace src.player.skills playerPawn.Teleport(pos); }); } - cloneProp.AcceptInput("Kill"); + EntityManager.DestroyEntity(cloneProp.Index); playerSkill.CloneProp = null; } - SkillUtils.ApplyScreenColor(player, 0, 0, 0, 0, 10, 0, 2); + var eventTarget = PlayerManager.GetPlayerFromEvent(player); + if (eventTarget != null && eventTarget.IsValid) + SkillUtils.ApplyScreenColor(eventTarget, 0, 0, 0, 0, 10, 0, 2); + SkillUtils.SetPlayerCollisions(player, true); + BlockWeapon(player, false); playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue(skillName, "Cooldown") * 64; playerSkill.UseTime = 0; @@ -164,12 +173,12 @@ namespace src.player.skills } } - var clone = Utilities.CreateEntityByName("prop_dynamic"); + var clone = EntityManager.CreateTrackedDynamicProp(player.Index); if (clone == null || !clone.IsValid) return null; clone.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; clone.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(clone.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); - clone.Entity!.Name = clone.Globalname = $"IanaClone_{Server.TickCount}_{player.SteamID}"; + clone.Entity!.Name = clone.Globalname = $"IanaClone_{Server.TickCount}_{player.Index}"; clone.DispatchSpawn(); Server.NextFrame(() => @@ -183,7 +192,11 @@ namespace src.player.skills clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0)); playerPawn.Teleport(pos); - SkillUtils.ApplyScreenColor(player, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020); + + var eventTarget = PlayerManager.GetPlayerFromEvent(player); + if (eventTarget != null && eventTarget.IsValid) + SkillUtils.ApplyScreenColor(eventTarget, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020); + BlockWeapon(player, true); playerSkill.UseTime = Server.TickCount; @@ -194,16 +207,15 @@ namespace src.player.skills { if (playerSkill.CloneProp != null) KillClone(playerSkill); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - ulong? playerSteamID = player?.SteamID; - if (playerSteamID == null) return; + uint playerIndex = player.Index; Timer? cloneTimer = null; cloneTimer = jRandomSkills.Instance.AddTimer(2f, () => { - var target = Utilities.GetPlayers().FirstOrDefault(p => p.IsValid && p.SteamID == playerSteamID); - if (target == null || !target.IsValid || !target.PawnIsAlive) + var target = Utilities.GetPlayerFromIndex((int)playerIndex); + if (target == null || !target.IsValid || target.LifeState != (byte)LifeState_t.LIFE_ALIVE) { cloneTimer?.Kill(); return; @@ -215,7 +227,14 @@ namespace src.player.skills return; } - SkillUtils.ApplyScreenColor(target, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020); + var eventTarget = PlayerManager.GetPlayerFromEvent(player); + if (eventTarget == null || !eventTarget.IsValid) + { + cloneTimer?.Kill(); + return; + } + + SkillUtils.ApplyScreenColor(eventTarget, r: 255, g: 255, b: 0, a: 20, duration: 100, holdTime: 1020); }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); }); @@ -247,14 +266,18 @@ namespace src.player.skills float penetration = vdata.ArmorRatio * .5f; + var eventPlayer = PlayerManager.GetPlayerFromEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) + return calculatedDamage; + if (isHeadshot) { calculatedDamage *= vdata.HeadshotMultiplier; - if (player.PawnHasHelmet) + if (eventPlayer.PawnHasHelmet) calculatedDamage *= penetration; } else - if (player.PawnArmor > 0) + if (eventPlayer.PawnArmor > 0) calculatedDamage *= penetration; return calculatedDamage; @@ -272,11 +295,11 @@ namespace src.player.skills if (!param.Entity.Name.StartsWith("IanaClone_")) return; var nameParams = param.Entity.Name.Split('_')[2]; - _ = ulong.TryParse(nameParams, out ulong steamID); - if (steamID == 0) return; + _ = uint.TryParse(nameParams, out uint userIndex); + if (userIndex == 0) return; - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player == null) return; + var player = Utilities.GetPlayerFromIndex((int)userIndex); + if (player == null || !player.IsValid) return; float dealDamage = param2.Damage; @@ -314,8 +337,8 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid!; - if (!jRandomSkills.Instance.IsPlayerValid(victim)) return; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + if (victim == null || !victim.IsValid) return; if (playersInfo.TryGetValue(victim.Index, out var playerSkill) && playerSkill.CloneProp != null) { @@ -356,7 +379,7 @@ namespace src.player.skills float time2 = SkillsInfo.GetValue(skillName, "Duration") - (Server.TickCount - playerSkill.UseTime) / 64; duration = (int)Math.Ceiling(Math.Max(time2, 0)); - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (playerSkill.InfoTime + (64 * 2) > Server.TickCount) @@ -374,7 +397,7 @@ namespace src.player.skills string weaponName = vdata.Name; if (string.IsNullOrEmpty(weaponName)) return false; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return false; if (playersInfo.TryGetValue(player.Index, out var playerSkill)) diff --git a/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs b/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs index 32ec688..dcde9b7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs @@ -10,6 +10,7 @@ namespace src.player.skills private const Skills skillName = Skills.Illiterate; private static bool isActive = false; private static int offset = 5; + private static int lastChange = 0; private static readonly object offsetLock = new(); public static void LoadSkill() @@ -28,7 +29,7 @@ namespace src.player.skills } } - public static void EnableSkill(CCSPlayerController player) + public static void EnableSkill(CCSPlayerController _) { isActive = true; } @@ -48,24 +49,28 @@ namespace src.player.skills if (!isActive || player == null || !player.IsValid) return false; if (player.Team == CsTeam.Spectator) return false; - var playersWithSkill = jRandomSkills.Instance.SkillPlayer.Where(p => p.Skill == skillName).Select(p => p.SteamID).ToHashSet(); + var playersWithSkill = jRandomSkills.Instance.SkillPlayer.Where(p => p.Skill == skillName).Select(p => p.PlayerIndex).ToHashSet(); if (playersWithSkill.Count == 0) return false; return Utilities.GetPlayers().Any( p => p != null && p.IsValid && p.Pawn?.Value != null && - p.PawnIsAlive && + p.PlayerPawn?.Value != null && + p.PlayerPawn.Value.Health > 0 && p.Team != player.Team && - playersWithSkill.Contains(p.SteamID)); + playersWithSkill.Contains(p.Index)); } public static string? GetRandomText(string? input) { if (string.IsNullOrEmpty(input)) return null; - if (Server.TickCount % 64 == 0 || offset == 0) + if (Server.TickCount - lastChange > 64 || offset == 0) + { EnsureOffset(); + lastChange = Server.TickCount; + } var chars = input.Select(c => { @@ -84,7 +89,6 @@ namespace src.player.skills { lock (offsetLock) { - if (offset != 0) return; try { offset = jRandomSkills.Instance?.Random?.Next(1, 26) ?? new Random().Next(1, 26); diff --git a/jRandomSkills - SRC Files/src/player/skills/Illusionist.cs b/jRandomSkills - SRC Files/src/player/skills/Illusionist.cs index 6d0f496..c0cae21 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Illusionist.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Illusionist.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -13,7 +13,7 @@ namespace src.player.skills public class Illusionist : ISkill { private const Skills skillName = Skills.Illusionist; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly ConcurrentDictionary ActiveTimers = []; private static readonly object setLock = new(); @@ -37,27 +37,27 @@ namespace src.player.skills var entities = Utilities.FindAllEntitiesByDesignerName("prop_dynamic_override"); foreach (var entity in entities) if (entity != null && entity.IsValid && entity.Entity != null && !string.IsNullOrEmpty(entity.Entity.Name) && (entity.Entity.Name?.StartsWith("Illusionist_") ?? false)) - entity.AcceptInput("Kill"); + EntityManager.DestroyEntity(entity.Index); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { - if (player == null || !player.IsValid || player.IsBot) continue; + if (player == null || !player.IsValid ) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -65,7 +65,9 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + if (player == null) return; + SkillPlayerInfo.TryRemove(player.Index, out _); + EntityManager.DestroyPlayerEntities(player.Index); SkillUtils.ResetPrintHTML(player); } @@ -81,7 +83,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -92,9 +94,9 @@ namespace src.player.skills public static void UseSkill(CCSPlayerController player) { - if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo) && skillInfo.CanUse) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo) && skillInfo.CanUse) { skillInfo.CanUse = false; skillInfo.Cooldown = DateTime.Now; @@ -108,7 +110,7 @@ namespace src.player.skills if (playerPawn == null || !playerPawn.IsValid) return; if (playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; - var replica = Utilities.CreateEntityByName("prop_dynamic_override"); + var replica = EntityManager.CreateTrackedPropOverride(player.Index); if (replica == null || !replica.IsValid) return; replica.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; @@ -166,10 +168,10 @@ namespace src.player.skills { if (replica != null && replica.IsValid) { - replica.AcceptInput("Kill"); + EntityManager.DestroyEntity(replica.Index); if (ActiveTimers.TryRemove(replicaIndex, out var timer)) timer?.Kill(); } - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } public static void OnTakeDamage(DynamicHook h) @@ -188,7 +190,7 @@ namespace src.player.skills replica.EmitSound("GlassBottle.BulletImpact", volume: 1f); if (ActiveTimers.TryRemove((int)replica.Index, out var timer)) timer?.Kill(); - replica.AcceptInput("Kill"); + EntityManager.DestroyEntity(replica.Index); CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); if (attackerPawn.DesignerName != "player") return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs index f91dd6e..82abd97 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs @@ -13,7 +13,7 @@ namespace src.player.skills private const Skills skillName = Skills.Impostor; private static readonly string defaultCTModel = "agents/models/ctm_sas/ctm_sas.vmdl"; private static readonly string defaultTModel = "agents/models/tm_phoenix/tm_phoenix.vmdl"; - private static readonly ConcurrentDictionary originalModels = []; + private static readonly ConcurrentDictionary originalModels = []; public static void LoadSkill() { @@ -29,16 +29,16 @@ namespace src.player.skills { string model = GetEnemyModel(player); if (player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid && player.PlayerPawn.Value.CBodyComponent != null && player.PlayerPawn.Value.CBodyComponent.SceneNode != null) - originalModels.TryAdd(player.SteamID, player.PlayerPawn.Value.CBodyComponent.SceneNode.GetSkeletonInstance().ModelState.ModelName); + originalModels.TryAdd(player.Index, player.PlayerPawn.Value.CBodyComponent.SceneNode.GetSkeletonInstance().ModelState.ModelName); SetPlayerModel(player, model); } public static void DisableSkill(CCSPlayerController player) { - var model = originalModels.TryGetValue(player.SteamID, out var originalModel) && !string.IsNullOrEmpty(originalModel) ? originalModel : + var model = originalModels.TryGetValue(player.Index, out var originalModel) && !string.IsNullOrEmpty(originalModel) ? originalModel : player.Team == CsTeam.Terrorist ? defaultTModel : defaultCTModel; SetPlayerModel(player, model); - originalModels.TryRemove(player.SteamID, out _); + originalModels.TryRemove(player.Index, out _); } private static string GetEnemyModel(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs b/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs index ee106d7..fdd149f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs +++ b/jRandomSkills - SRC Files/src/player/skills/InfiniteAmmo.cs @@ -16,10 +16,10 @@ namespace src.player.skills public static void WeaponFire(EventWeaponFire @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) ApplyInfiniteAmmo(player!); @@ -27,10 +27,10 @@ namespace src.player.skills public static void GrenadeThrown(EventGrenadeThrown @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) player!.GiveNamedItem($"weapon_{@event.Weapon}"); @@ -38,10 +38,10 @@ namespace src.player.skills public static void WeaponReload(EventWeaponReload @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) ApplyInfiniteAmmo(player!); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs index 44dc28e..d8bddc7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs @@ -1,9 +1,9 @@ -using System.Collections.Concurrent; -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using src.utils; +using System.Collections.Concurrent; using static src.jRandomSkills; using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; @@ -12,9 +12,9 @@ namespace src.player.skills public class Jackal : ISkill { private const Skills skillName = Skills.Jackal; - private static readonly ConcurrentDictionary playersInAction = new(); - private static readonly ConcurrentDictionary playersStep = new(); - private static readonly ConcurrentDictionary activeTimers = new(); + private static Timer? mainSkillTimer = null; + private static readonly ConcurrentDictionary activeTrails = []; + private static readonly ConcurrentDictionary playersInAction = []; public static void LoadSkill() { @@ -24,134 +24,141 @@ namespace src.player.skills public static void NewRound() { - var particleIds = playersStep.Values.Where(v => v.HasValue).Select(v => v!.Value).ToArray(); - foreach (var pid in particleIds) - SkillUtils.SafeKillEntity(pid); + if (mainSkillTimer != null) + { + mainSkillTimer.Kill(); + mainSkillTimer = null; + } - var timers = activeTimers.Values.ToArray(); - foreach (var t in timers) - t?.Kill(); + foreach (var index in activeTrails.Keys) + EntityManager.DestroyPlayerEntities(index); - playersStep.Clear(); + activeTrails.Clear(); playersInAction.Clear(); - activeTimers.Clear(); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) { + var snapshot = activeTrails.ToArray(); + foreach (var (info, player) in infoList) { if (player == null || !player.IsValid) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var targetHandle = player.Pawn.Value?.ObserverServices?.ObserverTarget.Value?.Handle ?? nint.Zero; - bool isObservingJackal = false; + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); + bool isJackalOwner = playerInfo?.Skill == skillName; - if (targetHandle != nint.Zero) + if (!isJackalOwner) { - var target = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == targetHandle); - var targetInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == target?.SteamID); - if (targetInfo?.Skill == skillName) isObservingJackal = true; + var targetHandle = player.Pawn.Value?.ObserverServices?.ObserverTarget.Value?.Handle ?? nint.Zero; + if (targetHandle != nint.Zero) + { + var observed = Utilities.GetPlayers() + .FirstOrDefault(p => p?.Pawn?.Value?.Handle == targetHandle); + if (observed != null && observed.IsValid) + { + var observedInfo = PlayerManager.GetPlayerByIndex(observed.Index); + if (observedInfo?.Skill == skillName) + isJackalOwner = true; + } + } } - bool hasSkill = playerInfo?.Skill == skillName || isObservingJackal; - - foreach (var kv in playersStep.ToArray()) + foreach (var (trackedPlayerIndex, relayIndex) in snapshot) { - var enemyIndex = kv.Key; - var particleIndex = kv.Value; - if (particleIndex == null) continue; + if (relayIndex == null) continue; - var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); - if (enemy == null || !enemy.IsValid) continue; + var trailOwner = Utilities.GetPlayerFromIndex((int)trackedPlayerIndex); + if (trailOwner == null || !trailOwner.IsValid) continue; - var entity = Utilities.GetEntityFromIndex((int)particleIndex); - if (entity == null || !entity.IsValid) continue; + var relayEntity = Utilities.GetEntityFromIndex((int)relayIndex); + if (relayEntity == null || !relayEntity.IsValid) continue; - if (!hasSkill || enemy.Team == player.Team) - info.TransmitEntities.Remove(entity.Index); + if (player.Team == trailOwner.Team || !isJackalOwner) + info.TransmitEntities.Remove(relayEntity.Index); } } } public static void CreatePlayerTrail(CCSPlayerController? player) { - if (player == null) return; + if (player == null || !player.IsValid) return; + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null + || playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || playerPawn.Health <= 0) return; ; - ulong steamID = player.SteamID; - if (activeTimers.TryRemove(steamID, out var oldTimer)) - oldTimer?.Kill(); + var relay = EntityManager.CreateTrackedPhysicsProp(player.Index); + if (relay == null || !relay.IsValid) return; - if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - if (!playersStep.ContainsKey(player.Index)) return; + CBaseEntity target = playerPawn; + var entities = EntityManager.GetPlayerEntities(player.Index, "empty_prop"); - CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; - if (particle == null) return; - - particle.EffectName = SkillsInfo.GetValue(skillName, "particleName"); - particle.StartActive = true; - - particle.Teleport(playerPawn.AbsOrigin); - particle.DispatchSpawn(); - - particle.AcceptInput("SetParent", playerPawn, particle, "!activator"); - particle.AcceptInput("Start"); - - uint particleId = particle.Index; - playersStep.AddOrUpdate(player.Index, particle.Index, (k, v) => particle.Index); - - var timer = Instance.AddTimer(2.5f, () => + if (entities.Count > 0) { - SkillUtils.SafeKillEntity(particleId); + var entity = Utilities.GetEntityFromIndex((int)entities[0]); + if (entity != null && entity.IsValid) + target = entity; + } - var pl = Utilities.GetPlayerFromSteamId(steamID); - if (pl != null && pl.IsValid && playersStep.ContainsKey(pl.Index)) - CreatePlayerTrail(pl); - }); + relay.AcceptInput("SetParent", target, relay, "!activator"); - activeTimers.AddOrUpdate(player.SteamID, timer, (_, prev) => + var particle = EntityManager.CreateTrackedParticleSystem( + player.Index, + SkillsInfo.GetValue(skillName, "particleName")); + + if (particle != null && particle.IsValid && target.AbsOrigin != null) { - prev?.Kill(); - return timer; - }); + Vector pos = new(target.AbsOrigin.X, target.AbsOrigin.Y, target.AbsOrigin.Z); + if (entities.Count > 0) pos.Z -= 30; + + particle.Teleport(pos); + particle.AcceptInput("SetParent", relay, particle, "!activator"); + particle.AcceptInput("Start"); + } + + activeTrails[player.Index] = relay.Index; } public static void EnableSkill(CCSPlayerController player) { + if (player == null || !player.IsValid) return; + Event.EnableTransmit(); - playersInAction.TryAdd(player.SteamID, 0); + playersInAction.TryAdd(player.Index, 0); var opponents = Utilities.GetPlayers() - .Where(p => p.Team != player.Team - && p.IsValid - && !p.IsBot - && !p.IsHLTV - && p.PawnIsAlive - && (p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) + .Where(p => p != null + && p.IsValid + && p.Team != player.Team + && p.PawnIsAlive + && (p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) .ToArray(); - foreach (var _player in opponents) - { - playersStep.TryAdd(_player.Index, null); - CreatePlayerTrail(_player); - } + mainSkillTimer ??= Instance.AddTimer(2.5f, () => UpdateAllTrails(), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + + private static void UpdateAllTrails() + { + foreach (var player in Utilities.GetPlayers()) + CreatePlayerTrail(player); } public static void DisableSkill(CCSPlayerController player) { - playersInAction.TryRemove(player.SteamID, out _); + if (player == null || !player.IsValid) return; + uint playerIndex = player.Index; - if (playersStep.TryRemove(player.Index, out var particleIndex) && particleIndex != null) + playersInAction.TryRemove(playerIndex, out _); + EntityManager.DestroyPlayerEntities(playerIndex); + activeTrails.TryRemove(playerIndex, out _); + + if (playersInAction.IsEmpty && mainSkillTimer != null) { - SkillUtils.SafeKillEntity(particleIndex); + mainSkillTimer.Kill(); + mainSkillTimer = null; } - - if (activeTimers.TryRemove(player.SteamID, out var t)) - t?.Kill(); - - if (playersInAction.IsEmpty) - NewRound(); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f542ef", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Common, string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs index 28fe0a2..bc6a582 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs @@ -1,9 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; namespace src.player.skills { @@ -11,6 +11,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Jammer; private static readonly ConcurrentDictionary jammedPlayers = []; + private static readonly ConcurrentDictionary jammerToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -29,7 +30,9 @@ namespace src.player.skills SetCrosshair(player, true); } jammedPlayers.Clear(); + jammerToTarget.Clear(); } + foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); } @@ -40,10 +43,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -52,8 +55,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -63,7 +66,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -72,8 +76,11 @@ namespace src.player.skills } jammedPlayers.TryAdd(enemy.Index, 0); + jammerToTarget[player.Index] = enemy.Index; + SetCrosshair(enemy, false); playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jammer_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jammer_enemy_info")); } @@ -90,11 +97,11 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -106,6 +113,22 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (jammerToTarget.TryRemove(player.Index, out uint targetIndex)) + { + var target = Utilities.GetPlayerFromIndex((int)targetIndex); + if (target != null && target.IsValid) + SetCrosshair(target, true); + jammedPlayers.TryRemove(targetIndex, out _); + } + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + SetCrosshair(player, true); jammedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); diff --git a/jRandomSkills - SRC Files/src/player/skills/Jester.cs b/jRandomSkills - SRC Files/src/player/skills/Jester.cs index 1301e9b..7601b25 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jester.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jester.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; @@ -13,7 +12,7 @@ namespace src.player.skills public class Jester : ISkill { private const Skills skillName = Skills.Jester; - private static readonly ConcurrentDictionary jesters = []; + private static readonly ConcurrentDictionary jesters = []; public static void LoadSkill() { @@ -32,13 +31,13 @@ namespace src.player.skills jester.Timer = null; } - var player = Utilities.GetPlayerFromSteamId(jester.SteamId); + var player = Utilities.GetPlayerFromIndex((int)jester.PlayerIndex); if (player != null && player.IsValid) { SkillUtils.ResetPrintHTML(player); var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || !player.PawnIsAlive) return; + if (pawn == null || !pawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; var color = Color.FromArgb(255, 255, 255, 255); pawn.Render = color; @@ -51,7 +50,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - var jester = GetJesterInfo(player.SteamID); + var jester = GetJesterInfo(player.Index); if (jester == null) return; Server.NextWorldUpdate(() => @@ -69,11 +68,11 @@ namespace src.player.skills public static void BombBegindefuse(EventBombBegindefuse @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - ulong steamId = player.SteamID; - var jester = GetJesterInfo(steamId); + uint playerIndex = player.Index; + var jester = GetJesterInfo(playerIndex); if (jester == null) return; if (jester.Timer != null) @@ -83,17 +82,17 @@ namespace src.player.skills } jester.Timer = Instance.AddTimer(1, () => { - ChangeMode(steamId, false); - }); + ChangeMode(playerIndex, false); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } public static void BombBeginplant(EventBombBeginplant @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - ulong steamId = player.SteamID; - var jester = GetJesterInfo(steamId); + uint playerIndex = player.Index; + var jester = GetJesterInfo(playerIndex); if (jester == null) return; if (jester.Timer != null) @@ -104,18 +103,17 @@ namespace src.player.skills jester.Timer = Instance.AddTimer(1, () => { if (player != null && player.IsValid) - ChangeMode(steamId, false); - }); + ChangeMode(playerIndex, false); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; - int hitgroup = @event.Hitgroup; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(victim)) return; - var jesterVictim = GetJesterInfo(victim!.SteamID); + var jesterVictim = GetJesterInfo(victim!.Index); if (!Instance.IsPlayerValid(attacker)) { @@ -124,7 +122,7 @@ namespace src.player.skills return; } - var jesterAttacker = GetJesterInfo(attacker!.SteamID); + var jesterAttacker = GetJesterInfo(attacker!.Index); if ((jesterVictim != null && jesterVictim.Active) || (jesterAttacker != null && jesterAttacker.Active)) SkillUtils.RestoreHealth(victim); } @@ -135,18 +133,18 @@ namespace src.player.skills var maxTime = SkillsInfo.GetValue(skillName, "maxTime"); float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; - ulong steamId = player.SteamID; + uint playerIndex = player.Index; - jesters.TryAdd(steamId, new JesterInfo { - SteamId = steamId, + jesters.TryAdd(playerIndex, new JesterInfo { + PlayerIndex = playerIndex, Active = false, - Timer = Instance.AddTimer(wait, () => ChangeMode(steamId)) + Timer = Instance.AddTimer(wait, () => ChangeMode(playerIndex), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE) }); } - private static void ChangeMode(ulong steamId, bool? forceActive = null) + private static void ChangeMode(uint playerIndex, bool? forceActive = null) { - if (!jesters.TryGetValue(steamId, out var jester)) return; + if (!jesters.TryGetValue(playerIndex, out var jester)) return; if (jester.Timer != null) { @@ -154,10 +152,10 @@ namespace src.player.skills jester.Timer = null; } - var player = Utilities.GetPlayerFromSteamId(steamId); - if (player == null || !player.IsValid || !player.PawnIsAlive) + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) { - jesters.TryRemove(steamId, out _); + jesters.TryRemove(playerIndex, out _); return; } @@ -167,14 +165,17 @@ namespace src.player.skills if (jester.Active != previousState) { SetPlayerColor(player); - player.ExecuteClientCommand("play sounds/weapons/taser/taser_charge_ready"); + + var playerEvent = PlayerManager.GetPlayerFromEvent(player); + if (playerEvent != null && playerEvent.IsValid) + playerEvent.ExecuteClientCommand("play sounds/weapons/taser/taser_charge_ready"); } var minTime = SkillsInfo.GetValue(skillName, "minTime"); var maxTime = SkillsInfo.GetValue(skillName, "maxTime"); float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; - jester.Timer = Instance.AddTimer(wait, () => ChangeMode(steamId)); + jester.Timer = Instance.AddTimer(wait, () => ChangeMode(playerIndex), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } private static void SetPlayerColor(CCSPlayerController? player, bool forceDisable = false) @@ -184,7 +185,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return; - var jester = GetJesterInfo(player.SteamID); + var jester = GetJesterInfo(player.Index); if (jester == null) return; var color = jester.Active && !forceDisable ? Color.FromArgb(255, 128, 0, 128) : Color.FromArgb(255, 255, 255, 255); @@ -195,36 +196,39 @@ namespace src.player.skills public static void OnTick() { if (SkillUtils.IsFreezeTime()) return; - foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot && p.PawnIsAlive)) + foreach (var player in Utilities.GetPlayers()) { - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playeEvent = PlayerManager.GetPlayerEvent(player); + if (playeEvent == null || !playeEvent.IsValid || playeEvent.PlayerPawn.Value == null || !playeEvent.PlayerPawn.Value.IsValid) continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(playeEvent.Index); + if (playerInfo?.Skill == skillName) - UpdateHUD(player); + UpdateHUD(playeEvent); } } private static void UpdateHUD(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; - var jester = GetJesterInfo(player.SteamID); + var jester = GetJesterInfo(player.Index); if (jester == null) return; playerInfo.PrintHTML = $"{player.GetTranslation("jester_mode")}: {player.GetTranslation(jester.Active ? "jester_on" : "jester_off")}"; } - public static JesterInfo? GetJesterInfo(ulong steamID) + public static JesterInfo? GetJesterInfo(uint playerIndex) { - if (jesters.TryGetValue(steamID, value: out var info)) + if (jesters.TryGetValue(playerIndex, value: out var info)) return info; return null; } public class JesterInfo() { - public required ulong SteamId { get; set; } + public required uint PlayerIndex { get; set; } public bool Active { get; set; } = false; public Timer? Timer { get; set; } = null; } diff --git a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs index aaf85f0..7410f32 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -11,6 +10,7 @@ namespace src.player.skills { private const Skills skillName = Skills.JumpBan; public static readonly ConcurrentDictionary bannedPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; public static void LoadSkill() { @@ -20,13 +20,15 @@ namespace src.player.skills public static void NewRound() { bannedPlayers.Clear(); + playersToTarget.Clear(); + foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); } public static void PlayerJump(EventPlayerJump @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (!bannedPlayers.TryGetValue(player.Index, out _)) return; bannedPlayers.AddOrUpdate(player.Index, Server.TickCount + 10, (k, v) => Server.TickCount + 10); @@ -53,10 +55,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); @@ -65,8 +67,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -76,7 +78,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null || !enemy.IsValid || enemy.PlayerPawn.Value == null || !enemy.PlayerPawn.Value.IsValid) { @@ -85,18 +88,20 @@ namespace src.player.skills } bannedPlayers.AddOrUpdate(enemy.Index, 0, (k, v) => 0); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jumpban_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -108,7 +113,20 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) + return; + + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + bannedPlayers.TryRemove(targetIndex, out _); + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + bannedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs b/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs index f360aee..d0a4acd 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JumpingJack.cs @@ -1,8 +1,6 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -19,9 +17,14 @@ namespace src.player.skills { var player = @event.Userid; if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + + var playerEvent = PlayerManager.GetPlayerEvent(player); + if (playerEvent == null || !playerEvent.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(playerEvent.Index); if (playerInfo?.Skill != skillName) return; - SkillUtils.AddHealth(player.PlayerPawn.Value, SkillsInfo.GetValue(skillName, "healthToAdd")); + + SkillUtils.AddHealth(playerEvent.PlayerPawn.Value, SkillsInfo.GetValue(skillName, "healthToAdd")); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a86eff", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int healthToAdd = 3) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs b/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs index da38057..c525751 100644 --- a/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/KillerFlash.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; @@ -18,12 +18,12 @@ namespace src.player.skills public static void PlayerBlind(EventPlayerBlind @event) { - var player = @event.Userid; - var attacker = @event.Attacker; + var player = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); if (!Instance.IsPlayerValid(player) || !Instance.IsPlayerValid(attacker)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (!SkillsInfo.GetValue(skillName, "friendlyFire") && player!.Team == attacker!.Team) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs b/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs index eb07b98..e588f5f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LifeSwap.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -28,20 +28,20 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); - ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {e.PawnHealth} HP", e.Index.ToString()))); + ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {e?.PlayerPawn?.Value?.Health ?? 0} HP", e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); } } 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -51,7 +51,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -67,11 +68,11 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => ($"{e.PlayerName} : {e.PawnHealth} HP", e.Index.ToString()))); diff --git a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs index 9e99497..9847792 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -14,7 +14,7 @@ namespace src.player.skills private static bool hooked = false; private const int actionCode = 503; - private static readonly ConcurrentDictionary playersInAction = []; + private static readonly ConcurrentDictionary playersInAction = []; private static readonly MemoryFunctionVoid Shoot_Secondary = new(GameData.GetSignature("Shoot_Secondary")); public static void LoadSkill() @@ -34,12 +34,12 @@ namespace src.player.skills if (hooked) return; hooked = true; Shoot_Secondary.Hook(ShootSecondary, HookMode.Pre); - playersInAction.TryAdd(player.SteamID, 0); + playersInAction.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { - playersInAction.TryRemove(player.SteamID, out _); + playersInAction.TryRemove(player.Index, out _); if (playersInAction.IsEmpty) { Shoot_Secondary.Unhook(ShootSecondary, HookMode.Pre); @@ -61,19 +61,22 @@ namespace src.player.skills var player = pawn.Controller.Value.As(); if (player == null || !player.IsValid) return HookResult.Continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var eventPlayer = PlayerManager.GetPlayerEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) return HookResult.Continue; + + var playerInfo = PlayerManager.GetPlayerByIndex(eventPlayer.Index); if (playerInfo == null || playerInfo.Skill != skillName) return HookResult.Continue; - KnifeHit(player, true); + KnifeHit(eventPlayer, true); return HookResult.Continue; } public static void WeaponFire(EventWeaponFire @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var pawn = player!.PlayerPawn.Value; @@ -97,10 +100,10 @@ namespace src.player.skills if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null) return; - + if (target.Handle == player.Handle || result.Value.Distance() <= 70) return; - + if (target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs index 5c8396b..e72e403 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -17,10 +17,10 @@ namespace src.player.skills public unsafe static void WeaponFire(EventWeaponFire @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var pawn = player!.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs b/jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs index 450c81b..8a3815c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs +++ b/jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -25,10 +24,10 @@ namespace src.player.skills public static void DecoyStarted(EventDecoyStarted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; decoys.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0); @@ -36,10 +35,10 @@ namespace src.player.skills public static void DecoyDetonate(EventDecoyDetonate @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; foreach (var decoy in decoys.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z)) @@ -49,11 +48,14 @@ namespace src.player.skills public static void OnTick() { foreach (Vector decoyPos in decoys.Keys) - foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { + var eventPlayer = PlayerManager.GetPlayerEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) continue; + var decoyRadius = SkillsInfo.GetValue(skillName, "triggerRadius"); - var pawn = player.PlayerPawn.Value; + var pawn = eventPlayer.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin); diff --git a/jRandomSkills - SRC Files/src/player/skills/Magneto.cs b/jRandomSkills - SRC Files/src/player/skills/Magneto.cs index 3de5505..4bb1c52 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Magneto.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Magneto.cs @@ -40,7 +40,7 @@ namespace src.player.skills foreach (var playerIndex in players.Keys) { var player = Utilities.GetPlayerFromIndex((int)playerIndex); - if (player == null || !player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) { players.TryRemove(playerIndex, out _); continue; diff --git a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs index cde207e..7b1b264 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs @@ -1,9 +1,8 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; namespace src.player.skills { @@ -11,6 +10,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Magnifier; private static readonly ConcurrentDictionary playersFOV = []; + private static readonly ConcurrentDictionary playersToTarget = []; public static void LoadSkill() { @@ -27,27 +27,22 @@ namespace src.player.skills } playersFOV.Clear(); + playersToTarget.Clear(); + foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); } - public static void PlayerDeath(EventPlayerDeath @event) - { - var player = @event.Userid; - if (player == null) return; - DisableSkill(player); - } - public static void OnTick() { 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); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -56,18 +51,19 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) { - player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}"); + player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}" ); return; } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -75,23 +71,24 @@ namespace src.player.skills return; } - if (!playersFOV.ContainsKey(enemy.Index)) - playersFOV.TryAdd(enemy.Index, enemy.DesiredFOV); + playersFOV.AddOrUpdate(enemy.Index, enemy.DesiredFOV, (k, v) => enemy.DesiredFOV); + playersToTarget[player.Index] = enemy.Index; + enemy.DesiredFOV = SkillsInfo.GetValue(skillName, "customFOV"); Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV"); - playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("magnifier_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("magnifier_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p => p != null && p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p => p != null && p.IsValid && p.Team != player.Team && p.PlayerPawn?.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0 && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -103,13 +100,31 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (playersFOV.TryGetValue(player.Index, out uint fov)) + if (player == null || !player.IsValid) return; + + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) { - player.DesiredFOV = fov; - Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); + var target = Utilities.GetPlayerFromIndex((int)targetIndex); + if (target != null && target.IsValid) + if (playersFOV.TryGetValue(targetIndex, out uint fov)) + { + target.DesiredFOV = fov; + Utilities.SetStateChanged(target, "CBasePlayerController", "m_iDesiredFOV"); + } + playersFOV.TryRemove(targetIndex, out _); } - playersFOV.TryRemove(player.Index, out _); - SkillUtils.CloseMenu(player); + + SkillUtils.ResetPrintHTML(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + player.DesiredFOV = 0; + Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); + SkillUtils.ResetPrintHTML(player); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9ba882", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, uint customFOV = 50) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Medic.cs b/jRandomSkills - SRC Files/src/player/skills/Medic.cs index 20b1cc0..ecba7d3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Medic.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Medic.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Medic : ISkill { private const Skills skillName = Skills.Medic; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -29,18 +29,18 @@ namespace src.player.skills if (SkillUtils.IsFreezeTime()) return; foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, Count = SkillsInfo.GetValue(skillName, "healthShotLimit"), @@ -49,7 +49,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -68,7 +68,7 @@ namespace src.player.skills var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == skillName); if (skillData == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; string remainingLine = cooldown != 0 @@ -83,9 +83,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (skillInfo.CanUse && skillInfo.Count != 0) { skillInfo.CanUse = false; diff --git a/jRandomSkills - SRC Files/src/player/skills/Miner.cs b/jRandomSkills - SRC Files/src/player/skills/Miner.cs index d3862dd..5f02cdf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Miner.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Miner.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -87,7 +86,7 @@ namespace src.player.skills if (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); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; nades.TryAdd(grenade.Index, 0); diff --git a/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs b/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs index 0c90f2f..8c138e2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/MoneySwap.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -28,10 +28,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); @@ -40,8 +40,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -51,7 +51,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -67,11 +68,11 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => ($"{e.PlayerName} : {(e.InGameMoneyServices == null ? 0 : e.InGameMoneyServices.Account + e.InGameMoneyServices.CashSpentThisRound)}$", e.Index.ToString()))]; diff --git a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs index 9fd0d66..07f2f92 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs @@ -27,7 +27,7 @@ namespace src.player.skills public static void PlayerDeath(EventPlayerDeath @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!IsDeadPlayerValid(player)) return; CsTeam lastTeam = player!.Team; @@ -40,7 +40,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.Health == pawn.MaxHealth) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) SpawnExplosion(player!); }); @@ -56,9 +56,9 @@ namespace src.player.skills SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum); - foreach (var _p in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist && !p.IsBot)) + foreach (var _p in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) SkillUtils.PrintToChat(_p, $"{ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}{_p.GetTranslation("muhammed_explosion")}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" }; var randomFile = fileNames[new Random().Next(fileNames.Length)]; diff --git a/jRandomSkills - SRC Files/src/player/skills/Mute.cs b/jRandomSkills - SRC Files/src/player/skills/Mute.cs index 99d4351..a783e48 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Mute.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Mute.cs @@ -1,4 +1,4 @@ -/*using CounterStrikeSharp.API; +/*using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using static jRandomSkills.jRandomSkills; @@ -26,7 +26,7 @@ namespace src.player.skills var pawn = grenade.OwnerEntity.Value.As(); var player = pawn.Controller.Value.As(); - var playerInfo = Instance.skillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; Server.NextFrame(() => { @@ -55,8 +55,8 @@ namespace src.player.skills Instance.AddTimer(5f, () => { if (@event != null && @event.IsValid) - @event.AcceptInput("Kill"); - }); + @event.AddEntityIOEvent("Kill", ent, delay: 0.1f); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); }); }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs index a7a7d32..036080c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs @@ -15,12 +15,14 @@ namespace src.player.skills private static readonly ConcurrentDictionary invisibilityChanged = []; private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; + private const string cameraViewModel = "models/sprays/spray_plane.vmdl"; private static readonly object setLock = new(); public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); Instance.AddToManifest(bloodParticle); + Instance.AddToManifest(cameraViewModel); } public static void NewRound() @@ -35,8 +37,9 @@ namespace src.player.skills 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); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; UpdateNinja(player); @@ -45,8 +48,9 @@ namespace src.player.skills 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 (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; UpdateNinja(player); @@ -56,7 +60,7 @@ namespace src.player.skills { foreach (var (info, player) in infoList) { - if (player == null || !player.IsValid) continue; + if (player == null || !player.IsValid || player.Team == CsTeam.Spectator) continue; var targetHandle = player.Pawn.Value?.ObserverServices?.ObserverTarget.Value?.Handle ?? nint.Zero; bool isObservingNinja = false; @@ -64,14 +68,17 @@ namespace src.player.skills if (targetHandle != nint.Zero) { var target = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == targetHandle); - var targetInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == target?.SteamID); + var targetInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(target)?.Index); if (targetInfo?.Skill == skillName) isObservingNinja = true; } foreach (var playerIndex in invisiblePlayers.Keys) { - var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); - if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + var playerController = PlayerManager.GetPlayerEvent(Utilities.GetPlayerFromIndex((int)playerIndex)); + if (playerController == null || !playerController.IsValid || playerController.Index == player.Index) + continue; + + if (player.Team == playerController.Team) continue; if (!isObservingNinja) @@ -95,31 +102,81 @@ namespace src.player.skills public static void OnTick() { + if (Server.TickCount % 2 != 0) return; + foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - UpdateNinja(player); - if (!player.PawnIsAlive) + if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) invisiblePlayers.TryRemove(player.Index, out _); + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) continue; + + UpdateNinja(PlayerManager.GetPlayerFromEvent(player)); + + var props = EntityManager.GetPlayerEntities(PlayerManager.GetPlayerEvent(player)!.Index, "empty_prop"); + if (props.Count == 0) continue; + + var prop = Utilities.GetEntityFromIndex((int)props[0]); + if (prop == null || !prop.IsValid) continue; + + var pawn = player.PlayerPawn?.Value; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; + + Vector newPos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + 30); + QAngle newAngle = new(0, pawn.V_angle.Y, 0); + prop.Teleport(newPos, newAngle, null); } } - public static void EnableSkill(CCSPlayerController _) + public static void EnableSkill(CCSPlayerController player) { Event.EnableTransmit(); + + if (EntityManager.GetPlayerEntities(player.Index, "empty_prop").Count == 0) + CreatePlayerPosProp(player); } public static void DisableSkill(CCSPlayerController player) { - SetPlayerVisibility(player, 0); + SkillUtils.SetPlayerInvisibility(player, 0); invisiblePlayers.TryRemove(player.Index, out _); + EntityManager.DestroyPlayerEntities(player.Index); + } + + private static void CreatePlayerPosProp(CCSPlayerController player) + { + if (player == null || !player.IsValid) return; + + var emptyProp = EntityManager.CreateTrackedDynamicProp(player.Index); + if (emptyProp == null || !emptyProp.IsValid) return; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; + + emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(emptyProp.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); + emptyProp.SetModel(cameraViewModel); + emptyProp.Render = Color.FromArgb(1, 255, 255, 255); + + Vector newPos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 30); + QAngle newAngle = new(playerPawn.AbsRotation.X, playerPawn.AbsRotation.Y, playerPawn.AbsRotation.Z); + + emptyProp.Teleport(newPos, newAngle); + emptyProp.DispatchSpawn(); + + Utilities.SetStateChanged(emptyProp, "CBaseEntity", "m_CBodyComponent"); + + EntityManager.RegisterExisting(emptyProp, player.Index, "empty_prop"); } private static void UpdateNinja(CCSPlayerController? player) { if (player == null || !player.IsValid) return; - var pawn = player.PlayerPawn?.Value; + + var playerEvent = PlayerManager.GetPlayerEvent(player); + if (playerEvent == null || !playerEvent.IsValid) return; + + var pawn = playerEvent.PlayerPawn?.Value; if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; var flags = (PlayerFlags)pawn.Flags; @@ -138,51 +195,35 @@ namespace src.player.skills if (!buttons.HasFlag(PlayerButtons.Moveleft) && !buttons.HasFlag(PlayerButtons.Moveright) && !buttons.HasFlag(PlayerButtons.Forward) && !buttons.HasFlag(PlayerButtons.Back) && flags.HasFlag(PlayerFlags.FL_ONGROUND)) percentInvisibility += SkillsInfo.GetValue(skillName, "idlePercentInvisibility"); - if (invisibilityChanged.TryGetValue(player.Handle, out float oldInvisibility)) + if (invisibilityChanged.TryGetValue(playerEvent.Handle, out float oldInvisibility)) if (percentInvisibility == oldInvisibility) return; - invisibilityChanged.AddOrUpdate(player.Handle, percentInvisibility, (_, _) => percentInvisibility); + invisibilityChanged.AddOrUpdate(playerEvent.Handle, percentInvisibility, (_, _) => percentInvisibility); if (percentInvisibility > .9) - invisiblePlayers.TryAdd(player.Index, 0); + invisiblePlayers.TryAdd(playerEvent.Index, 0); else { - SetPlayerVisibility(player, percentInvisibility); - invisiblePlayers.TryRemove(player.Index, out _); - } - } - - private static void SetPlayerVisibility(CCSPlayerController player, float percentInvisibility) - { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn != null) - { - var color = Color.FromArgb(Math.Max(255 - (int)(255 * percentInvisibility), 0), 255, 255, 255); - playerPawn.Render = color; - Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender"); + SkillUtils.SetPlayerInvisibility(playerEvent, percentInvisibility); + invisiblePlayers.TryRemove(playerEvent.Index, out _); } } public static void PlayerHurt(EventPlayerHurt @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; - CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + var particle = EntityManager.CreateTrackedParticleSystem(player.Index, bloodParticle, autoDestroySeconds: 3f); if (particle == null) return; - particle.EffectName = bloodParticle; - particle.StartActive = true; - Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); particle.Teleport(pos); - particle.DispatchSpawn(); - particle.AcceptInput("Start"); } diff --git a/jRandomSkills - SRC Files/src/player/skills/NoNades.cs b/jRandomSkills - SRC Files/src/player/skills/NoNades.cs index 3c1a90c..5ef9aa3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoNades.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoNades.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -18,11 +18,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { var damage = @event.DmgHealth; - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Weapon; if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (weapon == "hegrenade" || weapon == "inferno" || weapon == "decoy" || weapon == "flashbang" || weapon == "smokegrenade" || weapon == "molotov") diff --git a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs index b4f65c0..fa52b5b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -25,13 +25,13 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { if (player == null || !player.IsValid) return; - player.ReplicateConVar("weapon_accuracy_nospread", "1"); + Server.ExecuteCommand("weapon_accuracy_nospread 1"); } public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid) return; - player.ReplicateConVar("weapon_accuracy_nospread", "0"); + Server.ExecuteCommand("weapon_accuracy_nospread 0"); } public static void OnTick() @@ -39,7 +39,7 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs index 9dbe466..540d564 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; @@ -13,7 +13,7 @@ namespace src.player.skills public class Noclip : ISkill { private const Skills skillName = Skills.Noclip; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -31,18 +31,18 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, IsFlying = false, Cooldown = DateTime.MinValue, @@ -52,7 +52,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -72,7 +72,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -92,9 +92,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - ulong steamId = player.SteamID; + uint playerIndex = player.Index; - if (SkillPlayerInfo.TryGetValue(steamId, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(playerIndex, out var skillInfo)) { if (skillInfo.IsFlying) { @@ -116,14 +116,14 @@ namespace src.player.skills skillInfo.Timer = Instance.AddTimer(duration, () => { - var player = Utilities.GetPlayerFromSteamId(steamId); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == steamId); + var playerInfo = PlayerManager.GetPlayerByIndex(playerIndex); if (playerInfo == null) return; StopFlying(player, skillInfo); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } } } @@ -133,7 +133,7 @@ namespace src.player.skills if (player == null || !player.IsValid) return; var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid || !player.PawnIsAlive) return; + if (playerPawn == null || !playerPawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; playerPawn.MoveType = noclip ? MoveType_t.MOVETYPE_NOCLIP : MoveType_t.MOVETYPE_WALK; Schema.SetSchemaValue(playerPawn.Handle, "CBaseEntity", "m_nActualMoveType", (int)playerPawn.MoveType); @@ -148,7 +148,7 @@ namespace src.player.skills if (!skillInfo.IsFlying) return; skillInfo.IsFlying = false; - if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; SetNoclip(player, false); var playerPawn = player.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/OneShot.cs b/jRandomSkills - SRC Files/src/player/skills/OneShot.cs index c76815b..e3e0c23 100644 --- a/jRandomSkills - SRC Files/src/player/skills/OneShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/OneShot.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -32,13 +32,12 @@ namespace src.player.skills if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) return; - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - CCSPlayerController victim = victimPawn.Controller.Value.As(); + CCSPlayerController attacker = PlayerManager.GetPlayerEvent(attackerPawn.Controller.Value.As())!; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(attacker)!.Index); if (playerInfo == null) return; - if (playerInfo.Skill == skillName && attacker.PawnIsAlive) + if (playerInfo.Skill == skillName) param2.Damage = 1000f; } diff --git a/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs b/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs index 0a774aa..dfe00b4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs +++ b/jRandomSkills - SRC Files/src/player/skills/OnlyHead.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -17,13 +17,13 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); int damage = @event.DmgHealth; var hitgroup = (HitGroup_t)@event.Hitgroup; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); 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]; diff --git a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs index 5dd232d..463d689 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs @@ -21,17 +21,19 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) return; + var playerEvent = PlayerManager.GetPlayerEvent(player); + var playerInfo = PlayerManager.GetPlayerByIndex(playerEvent!.Index); + if (playerInfo?.Skill == skillName) - GiveAdditionalJump(player); + GiveAdditionalJump(player, playerEvent); } } public static void EnableSkill(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerPawn == null || playerInfo == null) return; var skillConfig = SkillsInfo.LoadedConfig.FirstOrDefault(s => s.Name == skillName.ToString()); @@ -40,15 +42,18 @@ namespace src.player.skills float extraJumps = (float)Instance.Random.Next(SkillsInfo.GetValue(skillName, "extraJumpsMin"), SkillsInfo.GetValue(skillName, "extraJumpsMax") + 1); playerInfo.SkillChance = extraJumps; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, extraJumps)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } - private static void GiveAdditionalJump(CCSPlayerController player) + private static void GiveAdditionalJump(CCSPlayerController player, CCSPlayerController playerEvent) { var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - var flags = (PlayerFlags)playerPawn.Flags; + var playerEventPawn = playerEvent.PlayerPawn.Value; + if (playerEventPawn == null || !playerEventPawn.IsValid) return; + + var flags = (PlayerFlags)playerEventPawn.Flags; var buttons = player.Buttons; bool isJumpDown = (playerPawn.MovementServices?.Buttons?.ButtonStates[0] & (ulong)PlayerButtons.Jump) != 0 || (buttons & PlayerButtons.Jump) != 0; @@ -57,8 +62,8 @@ namespace src.player.skills bool jumpPressed = (isJumpDown && !wasJumpDown) || (playerPawn.MovementServices?.QueuedButtonChangeMask & (ulong)PlayerButtons.Jump) != 0; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerPawn == null || playerInfo == null) return; + var playerInfo = PlayerManager.GetPlayerByIndex(playerEvent!.Index); + if (playerInfo == null) return; bool isOnGround = (flags & PlayerFlags.FL_ONGROUND) != 0; @@ -67,7 +72,7 @@ namespace src.player.skills else if (jumpPressed && J[player.Slot] < playerInfo.SkillChance + 1) { J[player.Slot]++; - playerPawn.AbsVelocity.Z = 300; + playerEventPawn.AbsVelocity.Z = 300; } LB[player.Slot] = buttons; diff --git a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs index 53c12d4..61a41bc 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs @@ -1,122 +1,60 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using System.Collections.Concurrent; using static src.jRandomSkills; -using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; namespace src.player.skills { public class Phoenix : ISkill { private const Skills skillName = Skills.Phoenix; - private static readonly object setLock = new(); - private static readonly ConcurrentDictionary timers = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"), false); } - public static void PlayerDeath(EventPlayerDeath @event) + public static void PlayerHurt(EventPlayerHurt @event) { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; + var user = @event.Userid; + if (user == null || !user.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + if (victim == null || !victim.IsValid) return; + + var pawn = victim.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index); + if (playerInfo?.Skill != skillName || pawn.Health > 0) return; + + if (Instance.Random.NextDouble() > playerInfo.SkillChance) return; + if (victim.TeamChanged) return; + + SkillUtils.AddHealth(pawn, 100 - pawn.Health); + SkillUtils.PrintToChat(user, user.GetTranslation("phoenix_respawn")); + + Server.NextFrame(() => { - if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - { - lock (setLock) - { - ulong steamID = player.SteamID; - int team = player.TeamNum; + if (victim == null || !victim.IsValid) return; + if (pawn == null || !pawn.IsValid) return; - if (team != 2 && team != 3) return; + var spawnpoint = SkillUtils.GetSpawnPointVector(victim); + if (spawnpoint == null) return; - player.Respawn(); - - Server.NextFrame(() => { - lock (setLock) - { - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return; - - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return; - - bool isBlock = team != player.TeamNum || player.TeamChanged; - - player.Respawn(); - - if (isBlock) - { - pawn.Flags |= (uint)Flags_t.FL_FROZEN; - pawn.Teleport(new Vector(0, 0, -1000), new QAngle(90, 0, 0)); - - bool isFreezeTime = Instance.GameRules != null && Instance.GameRules.FreezePeriod == true; - - if (!isFreezeTime) - { - Server.NextFrame(() => - { - if (pawn == null || !pawn.IsValid) return; - pawn.CommitSuicide(false, true); - }); - return; - } - - ulong steamId = player.SteamID; - - if (!timers.ContainsKey(player.SteamID)) - { - var timer = Instance.AddTimer(1f, () => - { - if (player == null || !player.IsValid || pawn == null || !pawn.IsValid) - { - if (timers.TryRemove(steamId, out var t)) - t.Kill(); - return; - } - - bool isFreezeTime = Instance.GameRules != null && Instance.GameRules.FreezePeriod == true; - - if (!isFreezeTime) - { - if (timers.TryRemove(steamId, out var t)) - t.Kill(); - - pawn.CommitSuicide(false, true); - return; - } - - }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); - - timers.TryAdd(player.SteamID, timer); - } - - return; - } - } - }); - - SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn")); - } - } - } + pawn.Teleport(spawnpoint); + }); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff5C0A", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, float chanceFrom = .2f, float chanceTo = .4f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Pilot.cs b/jRandomSkills - SRC Files/src/player/skills/Pilot.cs index 9078bf9..a67c2d0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Pilot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Pilot.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Pilot : ISkill { private const Skills skillName = Skills.Pilot; - private static readonly ConcurrentDictionary PlayerPilotInfo = []; + private static readonly ConcurrentDictionary PlayerPilotInfo = []; public static void LoadSkill() { @@ -26,7 +26,7 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) HandlePilot(player); } @@ -34,12 +34,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - PlayerPilotInfo.TryAdd(player.SteamID, new Pilot_PlayerInfo { SteamID = player.SteamID }); + PlayerPilotInfo.TryAdd(player.Index, new Pilot_PlayerInfo { SteamID = player.Index }); } public static void DisableSkill(CCSPlayerController player) { - PlayerPilotInfo.TryRemove(player.SteamID, out _); + PlayerPilotInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -48,7 +48,7 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - if (!PlayerPilotInfo.TryGetValue(player.SteamID, out var pilotInfo)) return; + if (!PlayerPilotInfo.TryGetValue(player.Index, out var pilotInfo)) return; var flags = (PlayerFlags)playerPawn.Flags; var buttons = player.Buttons; @@ -107,7 +107,7 @@ namespace src.player.skills private static void UpdateHUD(CCSPlayerController player, Pilot_PlayerInfo pilotInfo) { if (pilotInfo == null) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var maximumFuel = SkillsInfo.GetValue(skillName, "maximumFuel"); diff --git a/jRandomSkills - SRC Files/src/player/skills/Planter.cs b/jRandomSkills - SRC Files/src/player/skills/Planter.cs index 4059c9b..e7f5a78 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Planter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Planter.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; @@ -11,7 +11,7 @@ namespace src.player.skills public class Planter : ISkill { private const Skills skillName = Skills.Planter; - private static readonly ConcurrentDictionary plantingPlayers = []; + private static readonly ConcurrentDictionary plantingPlayers = []; public static void LoadSkill() { @@ -20,26 +20,26 @@ namespace src.player.skills public static void BombBeginplant(EventBombBeginplant @event) { - var user = @event.Userid; + var user = PlayerManager.GetPlayerEvent(@event.Userid); if (user == null || !user.IsValid || !user.PawnIsAlive) return; - plantingPlayers.TryAdd(user.SteamID, Server.CurrentTime); + plantingPlayers.TryAdd(user.Index, Server.CurrentTime); } public static void BombAbortplant(EventBombAbortplant @event) { - var user = @event.Userid; + var user = PlayerManager.GetPlayerEvent(@event.Userid); if (user == null || !user.IsValid || !user.PawnIsAlive) return; - plantingPlayers.TryRemove(user.SteamID, out _); + plantingPlayers.TryRemove(user.Index, out _); SkillUtils.ResetPrintHTML(user); } public static void BombPlanted(EventBombPlanted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - plantingPlayers.TryRemove(player!.SteamID, out _); + plantingPlayers.TryRemove(player!.Index, out _); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; playerInfo.PrintHTML = null; @@ -64,7 +64,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid) return; - plantingPlayers.TryRemove(player.SteamID, out _); + plantingPlayers.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); var pawn = player.PlayerPawn.Value; @@ -80,7 +80,7 @@ namespace src.player.skills { if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) continue; var pawn = player.PlayerPawn.Value; @@ -93,7 +93,7 @@ namespace src.player.skills pawn.InBombZone = true; Schema.SetSchemaValue(pawn.Handle, "CCSPlayerPawn", "m_bInBombZone", true); - if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime)) + if (plantingPlayers.TryGetValue(player.Index, out float plantTime)) { float remaining = plantTime + 3f - currentTime; playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"{Math.Max(0, remaining):0.0}s")}"; diff --git a/jRandomSkills - SRC Files/src/player/skills/Poison.cs b/jRandomSkills - SRC Files/src/player/skills/Poison.cs index fd385be..6b9f619 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Poison.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Poison.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -11,6 +10,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Poison; private static readonly ConcurrentDictionary poisonedPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -21,7 +21,10 @@ namespace src.player.skills public static void NewRound() { lock (setLock) + { poisonedPlayers.Clear(); + playersToTarget.Clear(); + } } public static void OnTick() @@ -45,10 +48,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -57,8 +60,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -68,7 +71,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -77,18 +81,20 @@ namespace src.player.skills } poisonedPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("poison_enemy_info")); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -100,6 +106,17 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + poisonedPlayers.TryRemove(targetIndex, out _); + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + poisonedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs index 1f7af04..1cf624d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PrimaryBan.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -10,7 +9,8 @@ namespace src.player.skills public class PrimaryBan : ISkill { private const Skills skillName = Skills.PrimaryBan; - private static readonly ConcurrentDictionary bannedPlayers = []; + private static readonly ConcurrentDictionary bannedPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); private static readonly string[] disabledWeapons = [ @@ -28,6 +28,8 @@ namespace src.player.skills lock (setLock) { bannedPlayers.Clear(); + playersToTarget.Clear(); + foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); } @@ -35,10 +37,10 @@ namespace src.player.skills public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Item; if (player == null || !player.IsValid) return; - if (!bannedPlayers.ContainsKey(player.SteamID) || !disabledWeapons.Contains(weapon)) return; + if (!bannedPlayers.ContainsKey(player.Index) || !disabledWeapons.Contains(weapon)) return; player.ExecuteClientCommand("slot3"); } @@ -48,10 +50,10 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -60,8 +62,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -71,7 +73,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -79,9 +82,11 @@ namespace src.player.skills return; } - bannedPlayers.TryAdd(enemy.SteamID, 0); + bannedPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; CheckWeapon(enemy); playerInfo.SkillUsed = true; + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("primaryban_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("primaryban_enemy_info")); } @@ -92,17 +97,17 @@ namespace src.player.skills if (activeWeapon == null || !activeWeapon.IsValid) return; if (activeWeapon.DesignerName == null || string.IsNullOrEmpty(activeWeapon.DesignerName)) return; - if (!bannedPlayers.ContainsKey(player.SteamID) || !disabledWeapons.Contains(activeWeapon.DesignerName?.Replace("weapon_", ""))) return; + if (!bannedPlayers.ContainsKey(player.Index) || !disabledWeapons.Contains(activeWeapon.DesignerName?.Replace("weapon_", ""))) return; player.ExecuteClientCommand("slot3"); } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -114,7 +119,18 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - bannedPlayers.TryRemove(player.SteamID, out _); + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + bannedPlayers.TryRemove(targetIndex, out _); + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + bannedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs b/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs index f953c21..732ca08 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Prosthesis.cs @@ -1,4 +1,3 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -17,13 +16,12 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; - int damage = @event.DmgHealth; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); var hitgroup = (HitGroup_t)@event.Hitgroup; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); 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]; diff --git a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs index 9694651..d9d58aa 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -31,10 +31,10 @@ namespace src.player.skills public static void PlayerDeath(EventPlayerDeath @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) SkillPlayerInfo.TryRemove(player.Index, out _); } @@ -78,7 +78,7 @@ namespace src.player.skills var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) { - plantedBomb.AcceptInput("Kill"); + plantedBomb.AddEntityIOEvent("Kill", plantedBomb, delay: 0.1f); SkillUtils.TerminateRound(CsTeam.CounterTerrorist); } SkillUtils.ResetPrintHTML(player); @@ -96,7 +96,7 @@ namespace src.player.skills SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, Defusing = false, DefusingTime = SkillsInfo.GetValue(skillName, "defusingTime"), }); @@ -113,7 +113,7 @@ namespace src.player.skills if (!skillInfo.Defusing) return; int cooldown = (int)Math.Ceiling(skillInfo.DefusingTime); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) diff --git a/jRandomSkills - SRC Files/src/player/skills/Push.cs b/jRandomSkills - SRC Files/src/player/skills/Push.cs index cba1b44..faee6b9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Push.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Push.cs @@ -17,13 +17,13 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo?.Skill == skillName && victim!.PawnIsAlive) { @@ -34,12 +34,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle) diff --git a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs index c23d9bf..021dd8c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Pyro.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Pyro.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; @@ -18,13 +18,14 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); int damage = @event.DmgHealth; string weapon = @event.Weapon; if (weapon != "inferno" || !Instance.IsPlayerValid(victim)) return; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - if (victimInfo == null || victimInfo.Skill != skillName) return ; + var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); + + if (victimInfo == null || victimInfo.Skill != skillName) return; var pawn = victim!.PlayerPawn.Value; SkillUtils.AddHealth(pawn, (int)(damage * SkillsInfo.GetValue(skillName, "regenerationMultiplier"))); diff --git a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs index 036c1b9..b1b7e7f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -20,7 +20,7 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { diff --git a/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs b/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs index 9ba19d7..ae6ecc9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RadarHack.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -19,13 +19,12 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - if (!Instance.IsPlayerValid(player)) continue; + var playerEvent = PlayerManager.GetPlayerEvent(player); + if (!Instance.IsPlayerValid(playerEvent)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(playerEvent!.Index); if (playerInfo?.Skill == skillName) - { SetEnemiesVisibleOnRadar(player); - } } } @@ -34,19 +33,22 @@ namespace src.player.skills if (player == null || !player.IsValid || player.PlayerPawn?.Value == null) return; int playerIndex = (int)player.Index - 1; - foreach (var enemy in Utilities.GetPlayers().FindAll(p => p.Team != player.Team && p.PawnIsAlive)) + foreach (var enemy in Utilities.GetPlayers().FindAll(p => p.Team != player.Team)) { - var enemyPawn = enemy.PlayerPawn.Value; + var enemyEvent = PlayerManager.GetPlayerEvent(enemy); + if (enemyEvent == null || !enemyEvent.IsValid) continue; + + var enemyPawn = enemyEvent.PlayerPawn.Value; if (enemyPawn == null) continue; + enemyPawn.EntitySpottedState.SpottedByMask[0] |= (1u << (int)(playerIndex % 32)); - } - + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); - if (bombEntities.Any()) + if (bombEntities.Count != 0) { var bomb = bombEntities.FirstOrDefault(); - if (bomb != null) + if (bomb != null && bomb.IsValid) bomb.EntitySpottedState.SpottedByMask[0] |= (1u << (int)(playerIndex % 32)); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs index aa055c4..7691e18 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; @@ -10,7 +10,7 @@ namespace src.player.skills public class RandomWeapon : ISkill { private const Skills skillName = Skills.RandomWeapon; - private static readonly ConcurrentDictionary SkillPlayerInfo = new(); + private static readonly ConcurrentDictionary SkillPlayerInfo = new(); private static readonly object setLock = new(); private static readonly HashSet pistols = new(StringComparer.Ordinal) @@ -43,17 +43,17 @@ namespace src.player.skills var players = Utilities.GetPlayers().ToArray(); foreach (var player in players) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName && SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill == skillName && SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -61,7 +61,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -77,7 +77,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.PrintHTML = cooldown == 0 @@ -90,8 +90,8 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn?.CBodyComponent == null) return; - if (!SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (!SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (!skillInfo.CanUse) { @@ -146,13 +146,13 @@ namespace src.player.skills } } - ulong steamId = player.SteamID; + uint playerIndex = player.Index; Instance.AddTimer(.1f, () => { - var pl = Utilities.GetPlayerFromSteamId(steamId); + var pl = Utilities.GetPlayerFromIndex((int)playerIndex); if (pl == null || !pl.IsValid) return; pl.GiveNamedItem(newWeapon); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs index 5d3a50d..c93b08c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs @@ -1,13 +1,10 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; -using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; using System.Drawing; -using static src.jRandomSkills; -using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; namespace src.player.skills { @@ -15,7 +12,6 @@ namespace src.player.skills { private const Skills skillName = Skills.ReZombie; private static readonly ConcurrentDictionary zombies = []; - private static readonly ConcurrentDictionary timers = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -50,10 +46,13 @@ namespace src.player.skills public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); var weapon = @event.Item; if (player == null || !player.IsValid) return; - if (!zombies.ContainsKey(player.Index) || weapon == "c4") return; + + if (!zombies.ContainsKey(player.Index) || weapon == "c4" || weapon.Contains("knife") || weapon.Contains("bayonet")) + return; + player.ExecuteClientCommand("slot3"); } @@ -69,106 +68,33 @@ namespace src.player.skills zombies.Clear(); } - public static void PlayerDeath(EventPlayerDeath @event) + public static void PlayerHurt(EventPlayerHurt @event) { - var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.ContainsKey(player.Index)) return; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + if (victim == null || !victim.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill != skillName) return; + var pawn = victim.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; - var pawn = player.PlayerPawn.Value; - if (pawn.AbsOrigin == null) return; + if (zombies.ContainsKey(victim.Index)) return; - Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); - QAngle angle = new(pawn.V_angle.X, pawn.V_angle.Y, 0); + var playerInfo = PlayerManager.GetPlayerByIndex(victim.Index); + if (playerInfo?.Skill != skillName || pawn.Health > 0) return; - ulong steamID = player.SteamID; - int team = player.TeamNum; - if (team != 2 && team != 3) return; + lock (setLock) + { + var zombieHealth = SkillsInfo.GetValue(skillName, "zombieHealth"); + bool isBlock = victim.TeamChanged; - player.Respawn(); + zombies.TryAdd(victim.Index, 0); - Server.NextFrame(() => { - lock (setLock) - { - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return; + if (isBlock) return; - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return; + SetPlayerColor(pawn, false); + SkillUtils.AddHealth(pawn, zombieHealth - pawn.Health, zombieHealth); - var zombieHealth = SkillsInfo.GetValue(skillName, "zombieHealth"); - - bool isBlock = team != player.TeamNum || player.TeamChanged; - - player.Respawn(); - zombies.TryAdd(player.Index, 0); - - if (isBlock) - { - pawn.Flags |= (uint)Flags_t.FL_FROZEN; - pawn.Teleport(new Vector(0, 0, -1000), new QAngle(90, 0, 0)); - - bool isFreezeTime = Instance.GameRules != null && Instance.GameRules.FreezePeriod == true; - - if (!isFreezeTime) - { - Server.NextFrame(() => - { - if (pawn == null || !pawn.IsValid) return; - pawn.CommitSuicide(false, true); - }); - return; - } - - ulong steamId = player.SteamID; - - if (!timers.ContainsKey(player.SteamID)) - { - var timer = Instance.AddTimer(1f, () => - { - if (player == null || !player.IsValid || pawn == null || !pawn.IsValid) - { - if (timers.TryRemove(steamId, out var t)) - t.Kill(); - return; - } - - bool isFreezeTime = Instance.GameRules != null && Instance.GameRules.FreezePeriod == true; - - if (!isFreezeTime) - { - if (timers.TryRemove(steamId, out var t)) - t.Kill(); - - pawn.CommitSuicide(false, true); - return; - } - - }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); - - timers.TryAdd(player.SteamID, timer); - } - - return; - } - - SetPlayerColor(pawn, false); - SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth); - - pawn.Teleport(deadPosition); - pawn.Look(angle); - player.ExecuteClientCommand("slot3"); - - Instance.AddTimer(1, () => { - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return; - - player.ExecuteClientCommand("slot3"); - }); - } - }); + victim.ExecuteClientCommand("slot3"); + } } public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata) @@ -182,7 +108,7 @@ namespace src.player.skills if (weaponName.Contains("knife") || weaponName.Contains("bayonet")) return false; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return false; hook.SetReturn(AcquireResult.InvalidItem); diff --git a/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs b/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs index c0eb6bb..9ceab70 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReactiveArmor.cs @@ -1,7 +1,6 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; @@ -10,7 +9,7 @@ namespace src.player.skills public class ReactiveArmor : ISkill { private const Skills skillName = Skills.ReactiveArmor; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -28,34 +27,38 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; var victim = @event.Userid; - int damage = @event.DmgHealth; + if (victim == null || !victim.IsValid) return; - if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; - if (SkillPlayerInfo.TryGetValue(victim!.SteamID, out var skillInfo)) + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victimEvent = PlayerManager.GetPlayerEvent(victim); + + if (attacker == null || !attacker.IsValid) return; + if (victimEvent == null || !victimEvent.IsValid || !victim.PawnIsAlive) return; + + if (SkillPlayerInfo.TryGetValue(victimEvent!.Index, out var skillInfo)) { - if (!victim.IsValid || !victim.PawnIsAlive || !skillInfo.CanUse) return; + if (!skillInfo.CanUse) return; skillInfo.CanUse = false; skillInfo.Cooldown = DateTime.Now; - SkillUtils.RestoreHealth(victim); + SkillUtils.RestoreHealth(victimEvent); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -63,7 +66,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -79,7 +82,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) diff --git a/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs b/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs index 36326c8..f644a26 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Regeneration.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -19,7 +19,7 @@ namespace src.player.skills if (Server.TickCount % (int)(64 * SkillsInfo.GetValue(skillName, "cooldown")) != 0) return; foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) continue; var pawn = player.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs index 1521609..a9c4be5 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -12,7 +12,7 @@ namespace src.player.skills public class Replicator : ISkill { private const Skills skillName = Skills.Replicator; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -32,25 +32,25 @@ namespace src.player.skills var entities = Utilities.FindAllEntitiesByDesignerName("prop_dynamic_override"); foreach (var entity in entities) if (entity != null && entity.IsValid && entity.Entity != null && !string.IsNullOrEmpty(entity.Entity.Name) && (entity.Entity.Name?.StartsWith("Replica_") ?? false)) - entity.AcceptInput("Kill"); + EntityManager.DestroyEntity(entity.Index); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -58,7 +58,9 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + if (player == null) return; + SkillPlayerInfo.TryRemove(player.Index, out _); + EntityManager.DestroyPlayerEntities(player.Index); SkillUtils.ResetPrintHTML(player); } @@ -74,7 +76,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -88,9 +90,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (skillInfo.CanUse) { skillInfo.CanUse = false; @@ -106,7 +108,7 @@ namespace src.player.skills if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; - var replica = Utilities.CreateEntityByName("prop_dynamic_override"); + var replica = EntityManager.CreateTrackedPropOverride(player.Index); if (replica == null || !replica.IsValid) return; @@ -142,7 +144,7 @@ namespace src.player.skills var replica = param.As(); if (replica == null || !replica.IsValid) return; replica.EmitSound("GlassBottle.BulletImpact", volume: 1f); - replica.AcceptInput("Kill"); + EntityManager.DestroyEntity(replica.Index); CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); if (attackerPawn.DesignerName != "player") diff --git a/jRandomSkills - SRC Files/src/player/skills/Retreat.cs b/jRandomSkills - SRC Files/src/player/skills/Retreat.cs index ca787a1..28191a3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Retreat.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Retreat.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -10,7 +10,7 @@ namespace src.player.skills public class Retreat : ISkill { private const Skills skillName = Skills.Retreat; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -28,18 +28,18 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) UpdateHUD(player, skillInfo); } } public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, }); @@ -47,7 +47,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -63,7 +63,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -77,9 +77,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (skillInfo.CanUse) { skillInfo.CanUse = false; diff --git a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs index f504875..253ec3c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReturnToSender.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -24,12 +24,12 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); int damage = @event.DmgHealth; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo == null || attackerInfo.Skill != skillName) return; if (playersToSender.ContainsKey(victim!.Handle)) diff --git a/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs b/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs index 39d6f03..3a046b8 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RichBoy.cs @@ -17,7 +17,7 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; int moneyBonus = Instance.Random.Next(SkillsInfo.GetValue(skillName, "minMoney"), SkillsInfo.GetValue(skillName, "maxMoney")); @@ -32,7 +32,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; var moneyServices = player.InGameMoneyServices; diff --git a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs index 4446e05..91a6565 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RobinHood.cs @@ -17,12 +17,12 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); var damage = @event.DmgHealth; if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo?.Skill != skillName) return; int moneyToSteal = damage * SkillsInfo.GetValue(skillName, "moneyMultiplier"); diff --git a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs index 03c4b35..d0c775c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs @@ -24,11 +24,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim) || attacker == victim) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); var victimPawn = victim!.PlayerPawn.Value; if (victimPawn == null || !victimPawn.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Saper.cs b/jRandomSkills - SRC Files/src/player/skills/Saper.cs index f21eb58..ee91aee 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Saper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Saper.cs @@ -17,10 +17,10 @@ namespace src.player.skills public static void BombBegindefuse(EventBombBegindefuse @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (Instance.IsPlayerValid(player)) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); @@ -35,10 +35,10 @@ namespace src.player.skills public static void BombBeginplant(EventBombBeginplant @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); diff --git a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs index 82721b9..b18ccaf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs @@ -25,11 +25,11 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); int damage = @event.DmgHealth; if (!Instance.IsPlayerValid(victim)) return; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); + var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); if (victimInfo == null || victimInfo.Skill != skillName) return; var victimPawn = victim!.PlayerPawn.Value; @@ -66,9 +66,6 @@ namespace src.player.skills pawn.Health = health; Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); - - pawn.ArmorValue = 0; - Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_ArmorValue"); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#d41c1c", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int startHealth = 50) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Shade.cs b/jRandomSkills - SRC Files/src/player/skills/Shade.cs index b0b78a8..e4c8b9a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Shade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Shade.cs @@ -26,13 +26,13 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; - var victim = @event.Userid; + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); + var victim = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(attacker) || !Instance.IsPlayerValid(victim)) return; - var victimInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == victim?.SteamID); - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var victimInfo = PlayerManager.GetPlayerByIndex(victim!.Index); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo?.Skill == skillName) if (Instance.Random.NextDouble() <= attackerInfo.SkillChance) @@ -41,14 +41,14 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public static void DisableSkill(CCSPlayerController player) @@ -73,7 +73,7 @@ namespace src.player.skills private static void UpdateHUD(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.PrintHTML = $"{player.GetTranslation("shade_nospace")}"; } diff --git a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs index d920c2c..9191387 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -17,10 +17,10 @@ namespace src.player.skills public static void BombPlanted(EventBombPlanted @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); diff --git a/jRandomSkills - SRC Files/src/player/skills/Silent.cs b/jRandomSkills - SRC Files/src/player/skills/Silent.cs index 3ee884c..a255218 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Silent.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Silent.cs @@ -1,9 +1,8 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; -using static src.utils.RarityManager; namespace src.player.skills { @@ -26,9 +25,9 @@ namespace src.player.skills 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; + if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; um.Recipients.Clear(); diff --git a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs index da3fb6b..dc787f6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs @@ -1,6 +1,5 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; @@ -14,7 +13,7 @@ namespace src.player.skills public class Smoker : ISkill { private const Skills skillName = Skills.Smoker; - private readonly static ConcurrentDictionary> playerSmokes = []; + private readonly static ConcurrentDictionary> playerSmokes = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -39,19 +38,19 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (playerSmokes.TryRemove(player.SteamID, out var timers)) + if (playerSmokes.TryRemove(player.Index, out var timers)) timers.ForEach(t => t?.Kill()); } public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; - ulong steamID = player.SteamID; + uint playerIndex = player.Index; Vector pos = new(@event.X, @event.Y, @event.Z); float refillInterval = 15.5f; @@ -59,7 +58,7 @@ namespace src.player.skills Timer? smokeTimer = null; smokeTimer = Instance.AddTimer(refillInterval, () => { - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) { @@ -70,7 +69,7 @@ namespace src.player.skills SkillUtils.CreateSmokeGrenadeProjectile(pos, QAngle.Zero, Vector.Zero, player.TeamNum); }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); - playerSmokes.AddOrUpdate(player.SteamID, [smokeTimer], (_, list) => { list.Add(smokeTimer); return list; }); + playerSmokes.AddOrUpdate(player.Index, [smokeTimer], (_, list) => { list.Add(smokeTimer); return list; }); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = 1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs index 97fbcec..124b841 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -10,9 +10,9 @@ namespace src.player.skills public class SniperElite : ISkill { private const Skills skillName = Skills.SniperElite; - private static readonly ConcurrentDictionary> playerAWPIndexes = []; - private static readonly ConcurrentDictionary savedWeapons = []; - private static readonly ConcurrentDictionary isProcessing = []; + private static readonly ConcurrentDictionary> playerAWPIndexes = []; + private static readonly ConcurrentDictionary savedWeapons = []; + private static readonly ConcurrentDictionary isProcessing = []; private static readonly object setLock = new(); private const string weapon_awp = "weapon_awp"; @@ -46,45 +46,45 @@ namespace src.player.skills public static void PlayerDeath(EventPlayerDeath @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) DisableSkill(player); } public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { if (rifles.Contains(@event.Item) && @event.Item != weapon_awp) - savedWeapons.AddOrUpdate(player.SteamID, string.Empty, (_, _) => string.Empty); + savedWeapons.AddOrUpdate(player.Index, string.Empty, (_, _) => string.Empty); DeleteDroppedAWP(player); } } public static void EnableSkill(CCSPlayerController player) { - savedWeapons.TryAdd(player.SteamID, string.Empty); + savedWeapons.TryAdd(player.Index, string.Empty); } public static void DisableSkill(CCSPlayerController player) { player.ExecuteClientCommand("slot3"); - if (playerAWPIndexes.TryGetValue(player.SteamID, out var AWPs)) + if (playerAWPIndexes.TryGetValue(player.Index, out var AWPs)) foreach (var index in AWPs.ToList()) SkillUtils.SafeKillEntity(index); - if (savedWeapons.TryGetValue(player.SteamID, out string? savedWeapon) && !string.IsNullOrWhiteSpace(savedWeapon)) + if (savedWeapons.TryGetValue(player.Index, out string? savedWeapon) && !string.IsNullOrWhiteSpace(savedWeapon)) Server.NextFrame(() => { - if (player == null || !player.IsValid || !player.PawnIsAlive) return; + if (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return; @@ -100,24 +100,24 @@ namespace src.player.skills player.ExecuteClientCommand("lastinv"); }); - savedWeapons.TryRemove(player.SteamID, out _); - playerAWPIndexes.TryRemove(player.SteamID, out _); - isProcessing.TryRemove(player.SteamID, out _); + savedWeapons.TryRemove(player.Index, out _); + playerAWPIndexes.TryRemove(player.Index, out _); + isProcessing.TryRemove(player.Index, out _); } public static void UseSkill(CCSPlayerController player) { - if (player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || isProcessing.ContainsKey(player.SteamID)) return; - if (savedWeapons.ContainsKey(player.SteamID)) + if (player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || isProcessing.ContainsKey(player.Index)) return; + if (savedWeapons.ContainsKey(player.Index)) RemoveAndGiveWeapon(player); } private static void RemoveAndGiveWeapon(CCSPlayerController player) { - ulong steamID = player.SteamID; + uint playerIndex = player.Index; try { - if (!isProcessing.TryAdd(steamID, 0)) return; + if (!isProcessing.TryAdd(playerIndex, 0)) return; CBasePlayerWeapon? activeRifle = GetActiveRifle(player); string weaponToGive = weapon_awp; @@ -128,24 +128,24 @@ namespace src.player.skills bool isScriptAWP = false; lock (setLock) - isScriptAWP = playerAWPIndexes.TryGetValue(steamID, out var indexes) && indexes.Contains(activeRifle.Index); + isScriptAWP = playerAWPIndexes.TryGetValue(playerIndex, out var indexes) && indexes.Contains(activeRifle.Index); if (isScriptAWP) { - if (savedWeapons.TryGetValue(steamID, out var savedWeapon) && !string.IsNullOrEmpty(savedWeapon)) + if (savedWeapons.TryGetValue(playerIndex, out var savedWeapon) && !string.IsNullOrEmpty(savedWeapon)) { weaponToGive = savedWeapon; - savedWeapons.AddOrUpdate(steamID, string.Empty, (_, _) => string.Empty); + savedWeapons.AddOrUpdate(playerIndex, string.Empty, (_, _) => string.Empty); } else { - isProcessing.TryRemove(steamID, out _); + isProcessing.TryRemove(playerIndex, out _); return; } } else { - savedWeapons.AddOrUpdate(steamID, currentWeaponName, (_, _) => currentWeaponName); + savedWeapons.AddOrUpdate(playerIndex, currentWeaponName, (_, _) => currentWeaponName); weaponToGive = weapon_awp + "_script"; } @@ -153,17 +153,17 @@ namespace src.player.skills } else { - if (savedWeapons.TryGetValue(steamID, out string? savedWeapon) && !string.IsNullOrEmpty(savedWeapon)) + if (savedWeapons.TryGetValue(playerIndex, out string? savedWeapon) && !string.IsNullOrEmpty(savedWeapon)) { weaponToGive = savedWeapon; - savedWeapons.AddOrUpdate(steamID, string.Empty, (_, _) => string.Empty); + savedWeapons.AddOrUpdate(playerIndex, string.Empty, (_, _) => string.Empty); } else weaponToGive = weapon_awp + "_script"; } Instance.AddTimer(.15f, () => { - var player = Utilities.GetPlayerFromSteamId(steamID); + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; if (player != null && player.IsValid && player.PlayerPawn != null && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) @@ -178,21 +178,21 @@ namespace src.player.skills lock (setLock) { - if (!playerAWPIndexes.ContainsKey(steamID)) - playerAWPIndexes.TryAdd(steamID, []); + if (!playerAWPIndexes.ContainsKey(playerIndex)) + playerAWPIndexes.TryAdd(playerIndex, []); - if (playerAWPIndexes.TryGetValue(steamID, out var list)) + if (playerAWPIndexes.TryGetValue(playerIndex, out var list)) list.Add(createdWeapon.Index); } } } DeleteDroppedAWP(player); - isProcessing.TryRemove(steamID, out _); + isProcessing.TryRemove(playerIndex, out _); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } catch { - isProcessing.TryRemove(steamID, out _); + isProcessing.TryRemove(playerIndex, out _); } } @@ -210,7 +210,7 @@ namespace src.player.skills lock (setLock) { - if (playerAWPIndexes.TryGetValue(player.SteamID, out var AWPs)) + if (playerAWPIndexes.TryGetValue(player.Index, out var AWPs)) foreach (var index in AWPs.ToList()) if (!myWeaponsIndexes.Contains(index)) { diff --git a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs index e60d283..9184e55 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; @@ -18,13 +18,15 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; + float newScale = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newScale; + newScale = (float)Math.Round(newScale, 2); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public static void OnTakeDamage(DynamicHook h) @@ -44,13 +46,12 @@ namespace src.player.skills if (attackerPawn == null || attackerPawn.Controller?.Value == null || victimPawn == null || victimPawn.Controller?.Value == null) return; - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - CCSPlayerController victim = victimPawn.Controller.Value.As(); + CCSPlayerController attacker = PlayerManager.GetPlayerEvent(attackerPawn.Controller.Value.As())!; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (playerInfo == null) return; - if (playerInfo.Skill == skillName && attacker.PawnIsAlive) + if (playerInfo.Skill == skillName) { float? skillChance = playerInfo.SkillChance; param2.Damage *= skillChance ?? 1f; diff --git a/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs b/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs index a2d9399..54f07da 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SoundMaker.cs @@ -1,17 +1,16 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { public class SoundMaker : ISkill { private const Skills skillName = Skills.SoundMaker; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); private const string soundEventName = "Hostage.Pain"; @@ -30,22 +29,23 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, 0); + SkillPlayerInfo.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } public static void PlayerDeath(EventPlayerDeath @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); } public static void PlayerMakeSound(UserMessage um) @@ -53,21 +53,45 @@ namespace src.player.skills var soundevent = um.ReadUInt("soundevent_hash"); if (soundevent != soundEventHash) return; - var userIndex = um.ReadUInt("source_entity_index"); - if (userIndex == 0) return; + var entityIndex = um.ReadUInt("source_entity_index"); + if (entityIndex == 0) return; - var sourcePlayer = Utilities.GetPlayers().FirstOrDefault(p => p.Pawn?.Value != null && p.Pawn.Value.IsValid && p.Pawn.Value.Index == userIndex); - if (sourcePlayer == null || !sourcePlayer.IsValid) return; - - var toRemove = um.Recipients.Where(r => + CCSPlayerController? emitter = null; + foreach (var p in Utilities.GetPlayers().Where(p => p != null && p.IsValid)) { - if (r.Team == sourcePlayer.Team) return true; - if (SkillPlayerInfo.ContainsKey(r.SteamID)) return false; - return true; - }).ToList(); + if (p.PlayerPawn.Value?.Index == entityIndex) + { + emitter = p; + break; + } - foreach (var player in toRemove) - um.Recipients.Remove(player); + var entities = EntityManager.GetPlayerEntities(p.Index, "empty_prop"); + if (entities.Count > 0 && entities[0] == entityIndex) + { + emitter = p; + break; + } + } + + if (emitter == null) + { + foreach (var p in Utilities.GetPlayers().Where(p => p != null && p.IsValid)) + um.Recipients.Remove(p); + return; + } + + foreach (var recipient in Utilities.GetPlayers().Where(p => p != null && p.IsValid)) + { + bool hasSkill = SkillPlayerInfo.ContainsKey(recipient.Index); + + var bot = PlayerManager.GetPlayerEvent(recipient); + bool botSkill = bot != null && SkillPlayerInfo.ContainsKey(bot.Index); + + bool isTeammate = recipient.Team == emitter.Team; + + if ((!hasSkill && !botSkill) || isTeammate) + um.Recipients.Remove(recipient); + } } public static void OnTick() @@ -75,8 +99,20 @@ namespace src.player.skills if (Server.TickCount % (60 * SkillsInfo.GetValue(skillName, "cooldown")) != 0) return; foreach (var player in Utilities.GetPlayers() - .Where(p => p != null && p.IsValid && p.PawnIsAlive && p.PlayerPawn.Value != null && p.PlayerPawn.Value.IsValid)) + .Where(p => p != null && p.IsValid && p.PlayerPawn.Value != null && p.PlayerPawn.Value.IsValid && p.PlayerPawn.Value.Health > 0)) + { + var entities = EntityManager.GetPlayerEntities(player.Index, "empty_prop"); + + if (entities.Count == 0) + { player.PlayerPawn.Value!.EmitSound(soundEventName, volume: 1f); + continue; + } + + var entity = Utilities.GetEntityFromIndex((int)entities[0]); + if (entity != null && entity.IsValid) + entity.EmitSound(soundEventName, volume: 1f); + } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#e3ed8c", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int cooldown = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs index c72e22d..7ed2915 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using System.Drawing; @@ -11,7 +11,7 @@ namespace src.player.skills public class Spectator : ISkill { private const Skills skillName = Skills.Spectator; - private static readonly ConcurrentDictionary cameras = []; + private static readonly ConcurrentDictionary cameras = []; public static void LoadSkill() { @@ -21,25 +21,21 @@ namespace src.player.skills public static void NewRound() { foreach (var info in cameras) - { - var cam = Utilities.GetEntityFromIndex((int)info.Value.Item2); - if (cam != null && cam.IsValid) - cam.AcceptInput("Kill"); - } - + EntityManager.DestroyEntity(info.Value.Item2); + cameras.Clear(); } public static void WeaponPickup(EventItemPickup @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; 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) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item1 != pawn.CameraServices.ViewEntity.Raw) BlockWeapon(player, true); } @@ -52,13 +48,15 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (player == null) return; ChangeCamera(player, true); + EntityManager.DestroyPlayerEntities(player.Index); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { var enemy = Utilities.GetPlayerFromIndex((int)cameraInfo.Item3); @@ -68,7 +66,7 @@ namespace src.player.skills return; } - var enemyPawn = player.PlayerPawn.Value; + var enemyPawn = enemy.PlayerPawn.Value; if (enemyPawn == null || !enemyPawn.IsValid) { ChangeCamera(player, true); @@ -88,13 +86,13 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; var cam = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); if (cam != null && cam.IsValid) - cam.AcceptInput("Kill"); + EntityManager.DestroyEntity(cam.Index); if (!forceToDefault) newCameraRaw = CreateCamera(player); @@ -120,12 +118,20 @@ namespace src.player.skills private static uint CreateCamera(CCSPlayerController player) { - var camera = Utilities.CreateEntityByName("prop_dynamic"); + var camera = EntityManager.CreateTrackedDynamicProp(player.Index); if (camera == null || !camera.IsValid) return 0; - var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team).ToList(); + var enemies = Utilities.GetPlayers().Where(p => + p != null && + p.IsValid && + p.Team != player.Team && + p.PlayerPawn?.Value != null && + p.PlayerPawn.Value.IsValid && + p.PlayerPawn.Value.Health > 0).ToList(); + if (enemies.Count == 0) return 0; + var enemy = enemies[Instance.Random.Next(enemies.Count)]; var pawn = enemy.PlayerPawn.Value; @@ -139,17 +145,29 @@ namespace src.player.skills Server.NextFrame(() => { if (camera == null || !camera.IsValid) return; + camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); camera.SetModel("models/sprays/spray_plane.vmdl"); - camera.Render = Color.FromArgb(0, 255, 255, 255); + camera.Render = Color.FromArgb(1, 255, 255, 255); camera.Teleport(pos, angle); camera.DispatchSpawn(); - camera.AcceptInput("SetParent", pawn, pawn, "!activator"); + + CBaseEntity target = pawn; + var entities = EntityManager.GetPlayerEntities(enemy.Index, "empty_prop"); + + if (entities.Count > 0) + { + var entity = Utilities.GetEntityFromIndex((int)entities[0]); + if (entity != null && entity.IsValid) + target = entity; + } + + camera.AcceptInput("SetParent", target, target, "!activator"); }); - if (cameras.TryGetValue(player.SteamID, out var cameraInfo)) - cameras.AddOrUpdate(player.SteamID, (cameraInfo.Item1, camera.Index, player.Index), (k, v) => (cameraInfo.Item1, camera.Index, player.Index)); + if (cameras.TryGetValue(player.Index, out var cameraInfo)) + cameras.AddOrUpdate(player.Index, (cameraInfo.Item1, camera.Index, player.Index), (k, v) => (cameraInfo.Item1, camera.Index, player.Index)); else - cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index)); + cameras.AddOrUpdate(player.Index, (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera.Index, player.Index)); return camera.EntityHandle.Raw; } diff --git a/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs b/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs index b0c9de6..b8e23b4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -10,7 +10,7 @@ namespace src.player.skills public class SwapPosition : ISkill { private const Skills skillName = Skills.SwapPosition; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -29,22 +29,29 @@ namespace src.player.skills if (SkillUtils.IsFreezeTime()) return; foreach (var player in Utilities.GetPlayers()) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + { + if (SkillPlayerInfo.TryGetValue(player.Index, 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) { + if (player == null || !player.IsValid) return; + var cooldownBeforeUse = SkillsInfo.GetValue(skillName, "cooldownBeforeUse"); - SkillPlayerInfo.TryAdd(player.SteamID, new ZamianaMiejsc_PlayerInfo + SkillPlayerInfo.TryAdd(player.Index, new ZamianaMiejsc_PlayerInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = false, Cooldown = cooldownBeforeUse <= 0 ? DateTime.MinValue : Event.GetFreezeTimeEnd().AddSeconds(cooldownBeforeUse - SkillsInfo.GetValue(skillName, "cooldown")), LastClick = DateTime.MinValue, @@ -54,12 +61,15 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + if (player == null) return; + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } private static void UpdateHUD(CCSPlayerController player, ZamianaMiejsc_PlayerInfo skillInfo, bool showInfo) { + if(player == null || !player.IsValid) return; + float cooldown = 0; if (skillInfo != null) { @@ -70,7 +80,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -91,7 +101,7 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { List enemy = Utilities.GetPlayers().FindAll(p => Instance.IsPlayerValid(p) && p.Team != player.Team && p.PawnIsAlive); if (enemy.Count == 0) @@ -102,7 +112,7 @@ namespace src.player.skills } CCSPlayerController randomEnemy = enemy[Instance.Random.Next(0, enemy.Count)]; - if (!player.IsValid || !player.PawnIsAlive || !randomEnemy.IsValid || !randomEnemy.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE || !randomEnemy.IsValid || !randomEnemy.PawnIsAlive) return; if (skillInfo.CanUse) { skillInfo.FindedEnemy = true; diff --git a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs index 5267bce..6da0cf8 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs @@ -18,23 +18,23 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; float newChance = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newChance; SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newChance)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && p != player) ? "tb" : "t"); } public static void PlayerHurt(EventPlayerHurt @event) { - var victim = @event.Userid; - var attacker = @event.Attacker; + var victim = PlayerManager.GetPlayerEvent(@event.Userid); + var attacker = PlayerManager.GetPlayerEvent(@event.Attacker); if (!Instance.IsPlayerValid(victim) || !Instance.IsPlayerValid(attacker)) return; - var attackerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID); + var attackerInfo = PlayerManager.GetPlayerByIndex(attacker!.Index); if (attackerInfo?.Skill == skillName) if (Instance.Random.NextDouble() <= attackerInfo.SkillChance) diff --git a/jRandomSkills - SRC Files/src/player/skills/Thief.cs b/jRandomSkills - SRC Files/src/player/skills/Thief.cs index cc26800..ded984e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thief.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thief.cs @@ -19,21 +19,37 @@ namespace src.player.skills public static void OnTick() { if (Server.TickCount % 32 != 0) return; - foreach (var player in Utilities.GetPlayers()) + + foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid && SkillUtils.HasMenu(p))) { - if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo?.Skill != skillName) 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(); + var enemies = Utilities.GetPlayers().Where(p => + p != null && + p.IsValid) + .Select(p => PlayerManager.GetPlayerEvent(p)) + .Where(p => + p != null && + p.IsValid && + p.Team != player.Team && + p.PlayerPawn?.Value != null && + p.PlayerPawn.Value.IsValid && + p.PlayerPawn.Value.Health > 0 && + !p.IsHLTV && + p.Team != CsTeam.Spectator + && p.Team != CsTeam.None + ).ToArray(); ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; + menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString())); } SkillUtils.UpdateMenu(player, menuItems); @@ -42,25 +58,36 @@ namespace src.player.skills public static void NewRound() { - foreach (var player in Utilities.GetPlayers()) + foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid)) SkillUtils.CloseMenu(player); } public static void TypeSkill(CCSPlayerController player, string[] commands) { - if (player == null) return; + if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + + if (commands == null || commands.Length == 0) + { + player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); + return; + } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) + { + player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); + return; + } - if (enemy == null) + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); + if (enemy == null || !enemy.IsValid) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; @@ -71,32 +98,34 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - 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 (player == null || !player.IsValid) return; + + var enemies = Utilities.GetPlayers() + .Where(p => p != null + && p.PawnIsAlive + && p.Team != player.Team + && p.IsValid + && p.Team != CsTeam.Spectator + && p.Team != CsTeam.None) + .ToArray(); + if (enemies.Length > 0) { - ConcurrentBag skills = []; ConcurrentBag<(string, string)> menuItems = []; foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo == null) continue; + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == enemyInfo.Skill); if (skillData == null) continue; - skills.Add(skillData.Skill.ToString()); + menuItems.Add(($"{enemy.PlayerName} : {player.GetSkillName(skillData.Skill)}", enemy.Index.ToString())); } - int ctSkills = Event.counterterroristSkills.Count(s => skills.Contains(s.Name)); - int ttSkills = Event.terroristSkills.Count(s => skills.Contains(s.Name)); - if ((player.Team == CsTeam.Terrorist && ctSkills == skills.Count) || (player.Team == CsTeam.CounterTerrorist && ttSkills == skills.Count)) - { - Event.SetRandomSkill(player); - return; - } - SkillUtils.CreateMenu(player, menuItems); SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", - border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); + border: !Utilities.GetPlayers().Any(p => p != null && p.Team == player.Team && p != player) ? "tb" : "t"); } else player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); @@ -104,84 +133,97 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; + playerInfo.SpecialSkill = Skills.None; SkillUtils.CloseMenu(player); } private static void StealSkill(CCSPlayerController player, CCSPlayerController enemy) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemy.SteamID); + if (player == null || enemy == null) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (playerInfo == null || enemyInfo == null) return; var enemySkill = enemyInfo.Skill; bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString()); - ulong enemySteamId = enemy.SteamID; - ulong playerSteamId = player.SteamID; + uint playerIndex = player.Index; + uint enemyIndex = enemy.Index; if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill)) { Instance.AddTimer(.1f, () => { - var enemy = Utilities.GetPlayerFromSteamId(enemySteamId); - if (enemy == null || !enemy.IsValid) return; + var e = Utilities.GetPlayerFromIndex((int)enemyIndex); + if (e == null || !e.IsValid) return; - var player = Utilities.GetPlayerFromSteamId(playerSteamId); - if (player == null || !player.IsValid) return; + var p = Utilities.GetPlayerFromIndex((int)playerIndex); + if (p == null || !p.IsValid) return; - Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); - player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName)); - }); + Instance.SkillAction(skillName.ToString(), "EnableSkill", [p]); + p.PrintToChat($" {ChatColors.Red}" + p.GetTranslation("thief_incorrect_skill", e.PlayerName)); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); return; } SkillUtils.CloseMenu(player); Instance.AddTimer(.1f, () => { - var enemy = Utilities.GetPlayerFromSteamId(enemySteamId); - if (enemy == null || !enemy.IsValid) return; + var e = Utilities.GetPlayerFromIndex((int)enemyIndex); + if (e == null || !e.IsValid) return; - var player = Utilities.GetPlayerFromSteamId(playerSteamId); - if (player == null || !player.IsValid) return; + var p = Utilities.GetPlayerFromIndex((int)playerIndex); + if (p == null || !p.IsValid) return; - playerInfo.Skill = enemySkill; - playerInfo.SpecialSkill = skillName; + var pInfo = PlayerManager.GetPlayerByIndex(p.Index); + if (pInfo == null) return; - SkillUtils.CloseMenu(player); - Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); + pInfo.Skill = enemySkill; + pInfo.SpecialSkill = skillName; - player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName)); + SkillUtils.CloseMenu(p); + Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [p]); + + p.PrintToChat($" {ChatColors.Green}" + p.GetTranslation("thief_player_info", e.PlayerName)); if (SkillsInfo.GetValue(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) - Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { - var player = Utilities.GetPlayerFromSteamId(playerSteamId); + { + float delay = Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0); + Instance?.AddTimer(delay, () => + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) return; - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == enemySkill) == null) return; - Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); - }); + var info = PlayerManager.GetPlayerByIndex(player!.Index); + if (info?.Skill == enemySkill) + Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } else - Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); - }); + Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [p]); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); Instance.AddTimer(.1f, () => { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemySteamId); - if (enemyInfo == null) return; + var eInfo = PlayerManager.GetPlayerByIndex(enemyIndex); + if (eInfo == null) return; - var enemy = Utilities.GetPlayerFromSteamId(enemySteamId); - if (enemy == null || !enemy.IsValid) return; + var e = Utilities.GetPlayerFromIndex((int)enemyIndex); + if (e == null || !e.IsValid) return; - Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]); + Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [e]); - enemyInfo.SpecialSkill = enemySkill; - enemyInfo.Skill = Skills.None; - enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("thief_enemy_info")); - }); + eInfo.SpecialSkill = enemySkill; + eInfo.Skill = Skills.None; + e.PrintToChat($" {ChatColors.Red}" + e.GetTranslation("thief_enemy_info")); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adaec7", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) diff --git a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs index 9a5090f..8fc906e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using System.Drawing; @@ -10,7 +10,7 @@ namespace src.player.skills public class ThirdEye : ISkill { private const Skills skillName = Skills.ThirdEye; - private static readonly ConcurrentDictionary cameras = []; + private static readonly ConcurrentDictionary cameras = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -21,11 +21,7 @@ namespace src.player.skills public static void NewRound() { foreach (var cameraIndex in cameras.Values) - { - var camera = Utilities.GetEntityFromIndex((int)cameraIndex.Item2); - if (camera != null && camera.IsValid) - camera.AcceptInput("Kill"); - } + EntityManager.DestroyEntity(cameraIndex.Item2); lock (setLock) cameras.Clear(); @@ -40,13 +36,15 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { + if (player == null) return; ChangeCamera(player, true); + EntityManager.DestroyPlayerEntities(player.Index); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; @@ -70,7 +68,7 @@ namespace src.player.skills uint orginalCameraRaw; uint newCameraRaw; var pawn = player.PlayerPawn.Value; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) + if (cameras.TryGetValue(player.Index, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; @@ -100,7 +98,7 @@ namespace src.player.skills private static uint CreateCamera(CCSPlayerController player) { - var camera = Utilities.CreateEntityByName("prop_dynamic"); + var camera = EntityManager.CreateTrackedDynamicProp(player.Index); if (camera == null || !camera.IsValid) return 0; var pawn = player.PlayerPawn.Value; @@ -109,13 +107,14 @@ namespace src.player.skills Server.NextFrame(() => { if (camera == null || !camera.IsValid) return; + camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); camera.SetModel("models/sprays/spray_plane.vmdl"); camera.Render = Color.FromArgb(0, 255, 255, 255); camera.Teleport(pawn!.AbsOrigin, pawn.EyeAngles); camera.DispatchSpawn(); }); - cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (v, k) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index)); + cameras.AddOrUpdate(player.Index, (pawn.CameraServices!.ViewEntity.Raw, camera.Index), (v, k) => (pawn.CameraServices!.ViewEntity.Raw, camera.Index)); return camera.EntityHandle.Raw; } diff --git a/jRandomSkills - SRC Files/src/player/skills/Thorns.cs b/jRandomSkills - SRC Files/src/player/skills/Thorns.cs index d5fe360..3ea7b3c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thorns.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thorns.cs @@ -1,7 +1,7 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; -using static src.jRandomSkills; namespace src.player.skills { @@ -16,15 +16,28 @@ namespace src.player.skills public static void PlayerHurt(EventPlayerHurt @event) { - var attacker = @event.Attacker; var victim = @event.Userid; + if (victim == null || !victim.IsValid) return; - 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) + var attacker = @event.Attacker; + if (attacker == null || !attacker.IsValid) return; + + var attackerEvent = PlayerManager.GetPlayerEvent(attacker); + var victimEvent = PlayerManager.GetPlayerEvent(victim); + + if (attackerEvent == null || !attackerEvent.IsValid) return; + if (victimEvent == null || !victimEvent.IsValid ) return; + + var attackerPawn = attackerEvent.PlayerPawn.Value; + if (attackerPawn == null || !attackerPawn.IsValid || attackerPawn.Health == 0) return; + + if (attackerEvent.Index == victimEvent.Index) return; + + var victimInfo = PlayerManager.GetPlayerByIndex(victimEvent!.Index); + if (victimInfo?.Skill == skillName) { - SkillUtils.TakeHealth(attacker.PlayerPawn.Value, (int)(@event.DmgHealth * SkillsInfo.GetValue(skillName, "healthTakenScale"))); - attacker.EmitSound("Player.DamageBody.Onlooker"); + SkillUtils.TakeHealth(attackerEvent.PlayerPawn.Value, (int)(@event.DmgHealth * SkillsInfo.GetValue(skillName, "healthTakenScale"))); + attackerEvent.EmitSound("Player.DamageBody.Onlooker"); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs b/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs index 31fb650..8b28f73 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs @@ -58,7 +58,7 @@ namespace src.player.skills if (knife == null || !knife.IsValid || knife.AbsRotation == null) return; - if (knifeInfo == null || knifeInfo.InitialLook == null) + if (knifeInfo == null || knifeInfo.InitialLook == null || knife.Collision == null) return; knifeInfo.IsDropped = false; @@ -71,19 +71,25 @@ namespace src.player.skills Vector.Zero ); + knife.Collision.CollisionAttribute.InteractsWith = knifeInfo.OriginalCollisionMask; + Utilities.SetStateChanged(knife, "CCollisionProperty", "m_collisionAttribute"); + var world = Utilities.GetEntityFromIndex(0); if (world != null && world.IsValid) knife.AcceptInput("SetParent", world, world, "!activator"); - + if (knifeInfo.Timer != null) knifeInfo.Timer?.Kill(); - - knifeInfo.Timer = - Instance.AddTimer(3f, () => - { - if (knife != null && knife.IsValid) - knife.AcceptInput("ClearParent"); - }, TimerFlags.STOP_ON_MAPCHANGE); + + knifeInfo.Timer = Instance.AddTimer(3f, () => + { + if (knife == null || !knife.IsValid) return; + + var player = Utilities.GetPlayerFromIndex((int)knifeInfo.PlayerIndex); + if (player != null && player.IsValid && CheckHasKnife(player)) return; + + knife.AcceptInput("ClearParent"); + }, TimerFlags.STOP_ON_MAPCHANGE); } public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata) @@ -94,7 +100,7 @@ namespace src.player.skills if (!weaponName.Contains("knife") && !weaponName.Contains("bayonet")) return false; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return false; if (knivesInfo.TryGetValue(player.Index, out KnifeInfo? knifeInfo) && knifeInfo != null && knifeInfo.KnifeId == econItem.ItemID) @@ -147,14 +153,21 @@ namespace src.player.skills public static void UseSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) return; + + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; + DropKnife(player); } private static void DropKnife(CCSPlayerController player) { - player.ExecuteClientCommand("slot3"); + var playerEvent = PlayerManager.GetPlayerFromEvent(player); + if (playerEvent == null || !player.IsValid) return; + + playerEvent.ExecuteClientCommand("slot3"); + Instance.AddTickTimer(8, () => { if (player == null || !player.IsValid) return; @@ -188,10 +201,14 @@ namespace src.player.skills QAngle angle = new(0, 0, 0); Vector vel = SkillUtils.GetForwardVector(pawn.EyeAngles) * force; - knife.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith; - knife.Teleport(pos, angle, vel); + if (knife.Collision == null) + return; + + ulong originalMask = knife.Collision.CollisionAttribute.InteractsWith; + knife.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith; + if (!knivesInfo.ContainsKey(player.Index)) { uint? triggerIndex = CreateTrigger(player, knife); @@ -204,7 +221,8 @@ namespace src.player.skills KnifeId = knife.AttributeManager.Item.ItemID, TriggerIndex = triggerIndex, GlowIndex = glowIndex, - RelayIndex = relayIndex + RelayIndex = relayIndex, + OriginalCollisionMask = originalMask }); } @@ -232,7 +250,7 @@ namespace src.player.skills if (player == null || !player.IsValid) return (null, null); if (knife == null || !knife.IsValid || knife.AbsOrigin == null) return (null, null); - var modelRelay = Utilities.CreateEntityByName("prop_physics_multiplayer"); + var modelRelay = EntityManager.CreateTrackedPhysicsProp(player.Index); if (modelRelay == null) return (null, null); modelRelay.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(modelRelay.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); @@ -244,7 +262,7 @@ namespace src.player.skills modelRelay.Teleport(knife.AbsOrigin, knife.AbsRotation, knife.AbsVelocity); modelRelay.AcceptInput("SetParent", knife, modelRelay, "!activator"); - var modelGlow = Utilities.CreateEntityByName("prop_physics_multiplayer"); + var modelGlow = EntityManager.CreateTrackedPhysicsProp(player.Index); if (modelGlow == null) return (null, null); modelGlow.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(modelGlow.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); @@ -301,6 +319,7 @@ namespace src.player.skills { var pawn = player.PlayerPawn?.Value; if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return false; + return pawn.WeaponServices.MyWeapons.Any(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid && (w.Value.DesignerName.Contains("knife") || w.Value.DesignerName.Contains("bayonet"))); @@ -339,37 +358,23 @@ namespace src.player.skills { if (player == null || !player.IsValid) continue; + uint? observedPlayerIndex = null; var playerPawn = player.Pawn?.Value; - if (playerPawn == null) - continue; - - var observerServices = playerPawn.ObserverServices; - if (observerServices == null) - continue; - - var observerTarget = observerServices.ObserverTarget; - if (observerTarget == null || !observerTarget.IsValid) - continue; - - var target = observerTarget.Value; - if (target == null || !target.IsValid) - continue; - - var observedPlayer = Utilities.GetPlayers() - .FirstOrDefault(p => - p.CheckPlayer() && - - p.Pawn != null && p.Pawn.IsValid && - p.Pawn.Value != null && p.Pawn.Value.IsValid && - - p.Pawn.Value.Handle == target.Handle); - - foreach ((uint playerIndex, KnifeInfo knifeInfo) in snapshot) + if (playerPawn != null && playerPawn.IsValid) { - if (playerIndex == player.Index || - (observedPlayer != null && observedPlayer.IsValid && - playerIndex == observedPlayer.Index)) continue; + var obs = playerPawn.ObserverServices?.ObserverTarget?.Value; + if (obs != null && obs.IsValid) + { + var observed = Utilities.GetPlayers().FirstOrDefault(p => + p != null && p.IsValid && + p.Pawn?.Value?.Handle == obs.Handle); + if (observed != null) + observedPlayerIndex = observed.Index; + } + } + foreach ((uint knifeOwnerIndex, KnifeInfo knifeInfo) in snapshot) + { if (knifeInfo.GlowIndex == null) continue; var glowEntity = Utilities.GetEntityFromIndex((int)knifeInfo.GlowIndex); @@ -379,7 +384,11 @@ namespace src.player.skills continue; } - info.TransmitEntities.Remove(glowEntity.Index); + bool isOwner = knifeOwnerIndex == PlayerManager.GetPlayerEvent(player)!.Index; + bool isObservingOwner = observedPlayerIndex.HasValue && observedPlayerIndex.Value == knifeOwnerIndex; + + if (!isOwner && !isObservingOwner) + info.TransmitEntities.Remove(glowEntity.Index); } } } @@ -392,6 +401,7 @@ namespace src.player.skills public required uint? TriggerIndex { get; set; } public required uint? GlowIndex { get; set; } public required uint? RelayIndex { get; set; } + public ulong OriginalCollisionMask { get; set; } public bool IsDropped { get; set; } = false; public QAngle? InitialLook { get; set; } = null; public Timer? Timer { get; set; } = null; diff --git a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs index 13230f2..1ce09b7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -25,10 +24,10 @@ namespace src.player.skills public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; smokes.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0); @@ -36,10 +35,10 @@ namespace src.player.skills public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; foreach (var smoke in smokes.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z)) @@ -60,7 +59,7 @@ namespace src.player.skills var player = pawn.Controller.Value.As(); if (player == null || !player.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; Server.NextFrame(() => @@ -82,13 +81,17 @@ namespace src.player.skills int smokeDamage = SkillsInfo.GetValue(skillName, "smokeDamage"); foreach (Vector smokePos in smokes.Keys) - foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive)) + foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid)) { - var pawn = player.PlayerPawn.Value; + var eventPlayer = PlayerManager.GetPlayerEvent(player); + if (eventPlayer == null || !eventPlayer.IsValid) continue; + + var pawn = eventPlayer.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; if (SkillUtils.GetDistance(smokePos, pawn.AbsOrigin) <= smokeRadius) - AddHealth(pawn, -smokeDamage); + if (SkillUtils.TakeHealth(pawn, smokeDamage)) + player.EmitSound("Player.DamageBody.Onlooker"); } } @@ -97,19 +100,6 @@ namespace src.player.skills SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade); } - private static void AddHealth(CCSPlayerPawn player, int health) - { - if (player.LifeState != (byte)LifeState_t.LIFE_ALIVE) - return; - - player.Health += health; - Utilities.SetStateChanged(player, "CBaseEntity", "m_iHealth"); - - player.EmitSound("Player.DamageBody.Onlooker"); - if (player.Health <= 0) - player.CommitSuicide(false, true); - } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int maxPerServer = -1, Rarity rarity = Rarity.Common, int smokeDamage = 2, float smokeRadius = 180, int tickCooldown = 17) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, maxPerServer, rarity) { 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 9424452..9d9a270 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Wallhack.cs @@ -1,18 +1,17 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; using System.Drawing; -using static src.jRandomSkills; namespace src.player.skills { public class Wallhack : ISkill { private const Skills skillName = Skills.Wallhack; - private static readonly ConcurrentDictionary playersInAction = new(); + private static readonly ConcurrentDictionary playersInAction = new(); private static ConcurrentDictionary glows = new(); public static void LoadSkill() @@ -24,29 +23,39 @@ namespace src.player.skills { foreach (var (info, player) in infoList) { - if (player == null) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (player == null || !player.IsValid) continue; + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); var observedPlayer = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == player?.Pawn?.Value?.ObserverServices?.ObserverTarget?.Value?.Handle); - var observerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == observedPlayer?.SteamID); + var observerInfo = observedPlayer != null ? PlayerManager.GetPlayerByIndex(observedPlayer.Index) : null; foreach (var kvp in glows) { var enemyIndex = kvp.Key; var glowInfo = kvp.Value; + var enemy = Utilities.GetPlayers().FirstOrDefault(e => e != null && e.IsValid && e.Index == enemyIndex); - var enemy = Utilities.GetPlayers().FirstOrDefault(e => e.IsValid && e.Index == enemyIndex); + bool hasSkill = playerInfo?.Skill == skillName; + bool observerHasSkill = observerInfo != null && observerInfo?.Skill == skillName; + bool differentTeam = glowInfo.Team != player.Team; - if (enemy != null && enemy.PawnIsAlive) - if (glowInfo.Team != player.Team && (playerInfo?.Skill == skillName || (observerInfo != null && observerInfo?.Skill == skillName))) + if (enemy != null && enemy.IsValid) + { + var enemyPawn = enemy.PlayerPawn?.Value; + bool pawnValid = enemyPawn != null && enemyPawn.IsValid; + bool alive = pawnValid && enemyPawn!.Health > 0; + bool notInvisible = pawnValid && enemyPawn!.Render.A != 102 && enemyPawn!.Render.A != 128; + + bool shouldShow = alive && notInvisible && differentTeam && (hasSkill || observerHasSkill); + + if (shouldShow) continue; + } var glowEntity1 = Utilities.GetEntityFromIndex((int)glowInfo.RelayIndex); if (glowEntity1 == null || !glowEntity1.IsValid) continue; - var glowEntity2 = Utilities.GetEntityFromIndex((int)glowInfo.GlowIndex); if (glowEntity2 == null || !glowEntity2.IsValid) continue; - info.TransmitEntities.Remove(glowEntity1.Index); info.TransmitEntities.Remove(glowEntity2.Index); } @@ -71,24 +80,31 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { Event.EnableTransmit(); - playersInAction.TryAdd(player.SteamID, 0); + playersInAction.TryAdd(player.Index, 0); if (glows.IsEmpty) SetGlowEffectForAll(); } public static void DisableSkill(CCSPlayerController player) { - playersInAction.TryRemove(player.SteamID, out _); + playersInAction.TryRemove(player.Index, out _); if (playersInAction.IsEmpty) NewRound(); } private static void SetGlowEffectForAll() { - var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && (p.Team == CsTeam.Terrorist || p.Team == CsTeam.CounterTerrorist)).ToList(); + var enemies = Utilities.GetPlayers().Where(p => + p != null && + p.IsValid && + p.PlayerPawn?.Value != null && + p.PlayerPawn.Value.IsValid && + p.PlayerPawn.Value.Health > 0 && + (p.Team == CsTeam.Terrorist || p.Team == CsTeam.CounterTerrorist)).ToList(); + foreach (var enemy in enemies) { - var enemyInfo = Instance.SkillPlayer.FirstOrDefault(e => e.SteamID == enemy.SteamID); + var enemyInfo = PlayerManager.GetPlayerByIndex(enemy.Index); if (enemyInfo?.Skill == Skills.Ghost) continue; @@ -99,8 +115,8 @@ namespace src.player.skills var modelName = skeleton?.ModelState?.ModelName; if (string.IsNullOrEmpty(modelName)) continue; - var modelGlow = Utilities.CreateEntityByName("prop_dynamic"); - var modelRelay = Utilities.CreateEntityByName("prop_dynamic"); + var modelGlow = EntityManager.CreateTrackedDynamicProp(enemy.Index); + var modelRelay = EntityManager.CreateTrackedDynamicProp(enemy.Index); if (modelGlow == null || !modelGlow.IsValid || modelRelay == null || !modelRelay.IsValid) continue; diff --git a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs index af65c97..66401d4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -39,7 +39,7 @@ namespace src.player.skills 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); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName || Instance.GameRules == null) return; var roundTime = SkillsInfo.GetValue(skillName, "changeRoundTime"); @@ -49,6 +49,7 @@ namespace src.player.skills Localization.PrintTranslationToChatAll($" {ChatColors.Orange}{{0}}", ["watchmaker_tt"], [roundTime]); else Localization.PrintTranslationToChatAll($" {ChatColors.LightBlue}{{0}}", ["watchmaker_ct"], [roundTime]); + player.EmitSound(SkillsInfo.GetValue(skillName, "SoundEvent")); var proxy = Utilities.FindAllEntitiesByDesignerName("cs_gamerules").FirstOrDefault(); diff --git a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs index 44b263f..78f490b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; @@ -10,7 +10,7 @@ namespace src.player.skills public class WeaponsSwap : ISkill { private const Skills skillName = Skills.WeaponsSwap; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static readonly object setLock = new(); private static readonly HashSet weapons = [ "weapon_deagle", "weapon_revolver", "weapon_glock", "weapon_usp_silencer", @@ -33,9 +33,9 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { - SteamID = player.SteamID, + SteamID = player.Index, CanUse = true, Cooldown = DateTime.MinValue, LastClick = DateTime.MinValue, @@ -46,7 +46,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - SkillPlayerInfo.TryRemove(player.SteamID, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } @@ -55,10 +55,10 @@ namespace src.player.skills var players = Utilities.GetPlayers().ToArray(); foreach (var player in players) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) continue; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { bool recentClick = skillInfo.LastClick.AddSeconds(4) >= DateTime.Now; UpdateHUD(player, skillInfo, recentClick); @@ -78,7 +78,7 @@ namespace src.player.skills skillInfo.CanUse = true; } - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; if (cooldown == 0) @@ -101,9 +101,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + if (SkillPlayerInfo.TryGetValue(player.Index, out var skillInfo)) { - if (!player.IsValid || !player.PawnIsAlive) return; + if (!player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; if (skillInfo.CanUse) { CCSPlayerController? enemy = GetRandomEnemy(player); diff --git a/jRandomSkills - SRC Files/src/player/skills/Weightless.cs b/jRandomSkills - SRC Files/src/player/skills/Weightless.cs index c05ed64..0df985b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Weightless.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Weightless.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using static src.jRandomSkills; namespace src.player.skills { @@ -62,7 +61,7 @@ namespace src.player.skills if (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); + var playerInfo = PlayerManager.GetPlayerByIndex(PlayerManager.GetPlayerEvent(player)!.Index); if (playerInfo?.Skill != skillName) return; Server.NextFrame(() => { diff --git a/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs b/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs index 6515026..ebb7ca2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WildThrow.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -10,7 +10,8 @@ namespace src.player.skills public class WildThrow : ISkill { private const Skills skillName = Skills.WildThrow; - private readonly static ConcurrentDictionary infectedPlayers = []; + private readonly static ConcurrentDictionary infectedPlayers = []; + private static readonly ConcurrentDictionary playersToTarget = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -21,25 +22,22 @@ namespace src.player.skills public static void NewRound() { lock (setLock) - infectedPlayers.Clear(); - foreach (var player in Utilities.GetPlayers()) - DisableSkill(player); - } + { + foreach (var player in Utilities.GetPlayers()) + DisableSkill(player); - public static void PlayerDeath(EventPlayerDeath @event) - { - var player = @event.Userid; - if (player == null) return; - DisableSkill(player); + infectedPlayers.Clear(); + playersToTarget.Clear(); + } } public static void EnableSkill(CCSPlayerController player) { - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.SkillUsed = false; - 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(); + var enemies = Utilities.GetPlayers().Where(p =>p != null &&p.IsValid).Select(p => PlayerManager.GetPlayerEvent(p)).Where(p =>p != null &&p.IsValid &&p.Team != player.Team &&p.PlayerPawn?.Value != null &&p.PlayerPawn.Value.IsValid &&p.PlayerPawn.Value.Health > 0 &&!p.IsHLTV &&p.Team != CsTeam.Spectator&& p.Team != CsTeam.None).ToArray(); if (enemies.Length > 0) { ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); @@ -51,7 +49,18 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - infectedPlayers.TryRemove(player.SteamID, out _); + if (playersToTarget.TryRemove(player.Index, out uint targetIndex)) + infectedPlayers.TryRemove(targetIndex, out _); + + SkillUtils.CloseMenu(player); + } + + public static void PlayerDeath(EventPlayerDeath @event) + { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + + infectedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } @@ -61,10 +70,24 @@ namespace src.player.skills foreach (var player in Utilities.GetPlayers()) { if (!SkillUtils.HasMenu(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.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(); + var enemies = Utilities.GetPlayers().Where(p => + p != null && + p.IsValid) + .Select(p => PlayerManager.GetPlayerEvent(p)) + .Where(p => + p != null && + p.IsValid && + p.Team != player.Team && + p.PlayerPawn?.Value != null && + p.PlayerPawn.Value.IsValid && + p.PlayerPawn.Value.Health > 0 && + !p.IsHLTV && + p.Team != CsTeam.Spectator + && p.Team != CsTeam.None + ).ToArray(); ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString()))); SkillUtils.UpdateMenu(player, menuItems); @@ -73,8 +96,8 @@ namespace src.player.skills 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 (player == null || !player.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill != skillName) return; if (playerInfo.SkillUsed) @@ -84,7 +107,8 @@ namespace src.player.skills } string enemyId = commands[0]; - var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId); + if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); if (enemy == null) { @@ -92,7 +116,8 @@ namespace src.player.skills return; } - infectedPlayers.TryAdd(enemy.SteamID, 0); + infectedPlayers.TryAdd(enemy.Index, 0); + playersToTarget[player.Index] = enemy.Index; playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("wildthrow_player_info", enemy.PlayerName)); @@ -112,7 +137,7 @@ namespace src.player.skills if (pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return; var player = pawn.Controller.Value.As(); - if (!infectedPlayers.ContainsKey(player.SteamID)) return; + if (!infectedPlayers.ContainsKey(player.Index)) return; Server.NextFrame(() => { if (grenade == null || !grenade.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Zeus.cs b/jRandomSkills - SRC Files/src/player/skills/Zeus.cs index c4eb520..dbc0bf7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Zeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Zeus.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -22,10 +22,10 @@ namespace src.player.skills public static void WeaponFire(EventWeaponFire @event) { - var player = @event.Userid; + var player = PlayerManager.GetPlayerEvent(@event.Userid); if (!Instance.IsPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo?.Skill == skillName) { @@ -43,7 +43,7 @@ namespace src.player.skills taser.LastAttackTick = 0; taser.FireTime = 0; } - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } } diff --git a/jRandomSkills - SRC Files/src/utils/Config.cs b/jRandomSkills - SRC Files/src/utils/Config.cs index 043ce3c..9b1027b 100644 --- a/jRandomSkills - SRC Files/src/utils/Config.cs +++ b/jRandomSkills - SRC Files/src/utils/Config.cs @@ -80,6 +80,8 @@ namespace src.utils public bool KillerSkillChatInfo { get; set; } public bool TeamMateSkillChatInfo { get; set; } public bool SummaryAfterTheRound { get; set; } + public bool EnableBotSkills { get; set; } + public bool EnableBotKickDebug { get; set; } public bool DebugMode { get; set; } public string? AlternativeSkillButton { get; set; } public float SkillTimeBeforeStart { get; set; } @@ -87,7 +89,7 @@ namespace src.utils public float SkillDescriptionDuration { get; set; } public bool DisplayAlwaysDescription { get; set; } public bool DisableSpectateHUD { get; set; } - public bool FlashingHtmlHudFix { get; set; } + public bool EnableFlashingHtmlHudFix { get; set; } public bool TraceRayBeam { get; set; } public string DisableHUDOnDeathPermission { get; set; } public bool DisableSkillsOnRoundEnd { get; set; } @@ -105,13 +107,15 @@ namespace src.utils KillerSkillChatInfo = true; TeamMateSkillChatInfo = true; SummaryAfterTheRound = true; + EnableBotSkills = true; + EnableBotKickDebug = false; DebugMode = false; AlternativeSkillButton = null; SkillTimeBeforeStart = 7; SkillHudDuration = -1; SkillDescriptionDuration = 7; DisplayAlwaysDescription = false; - FlashingHtmlHudFix = true; + EnableFlashingHtmlHudFix = false; TraceRayBeam = false; DisableSpectateHUD = false; DisableHUDOnDeathPermission = "@jRandomSkills/death"; diff --git a/jRandomSkills - SRC Files/src/utils/EntityManager.cs b/jRandomSkills - SRC Files/src/utils/EntityManager.cs new file mode 100644 index 0000000..26f9df3 --- /dev/null +++ b/jRandomSkills - SRC Files/src/utils/EntityManager.cs @@ -0,0 +1,273 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities.Constants; +using CounterStrikeSharp.API.Modules.Utils; +using System.Collections.Concurrent; +using System.Drawing; +using static src.jRandomSkills; + +namespace src.utils +{ + public static class EntityManager + { + public const uint SystemOwnerIndex = uint.MaxValue; + private static readonly ConcurrentDictionary trackedEntities = []; + + private struct EntityData + { + public uint EntityIndex; + public uint PlayerIndex; + public string EntityType; + public DateTime CreatedAt; + } + + public static void RegisterEntity(uint entityIndex, uint playerIndex, string entityType) + { + if (entityIndex == 0) return; + + trackedEntities[entityIndex] = new EntityData + { + EntityIndex = entityIndex, + PlayerIndex = playerIndex, + EntityType = entityType, + CreatedAt = DateTime.UtcNow + }; + } + + public static void RegisterExisting(CBaseEntity? entity, uint playerIndex, string entityType) + { + if (entity == null || !entity.IsValid) return; + RegisterEntity(entity.Index, playerIndex, entityType); + } + + public static List GetPlayerEntities(uint playerIndex, string? entityType = null) + { + return [.. trackedEntities + .Where(kvp => kvp.Value.PlayerIndex == playerIndex && (string.IsNullOrEmpty(entityType) || kvp.Value.EntityType == entityType)) + .Select(kvp => kvp.Key)]; + } + + public static int GetTrackedCount(uint playerIndex) => GetPlayerEntities(playerIndex).Count; + + public static (int totalTracked, int ownerCount) GetStatistics() + { + return (trackedEntities.Count, trackedEntities.Values.Select(e => e.PlayerIndex).Distinct().Count()); + } + + + public static CParticleSystem? CreateTrackedParticleSystem(uint playerIndex, string particleName, float? autoDestroySeconds = null) + { + try + { + var particle = Utilities.CreateEntityByName("info_particle_system"); + if (particle == null || !particle.IsValid) return null; + + particle.EffectName = particleName; + particle.StartActive = true; + particle.DispatchSpawn(); + + RegisterEntity(particle.Index, playerIndex, "particle_system"); + ScheduleAutoDestroy(particle.Index, autoDestroySeconds); + return particle; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedParticleSystem: {ex.Message}"); + return null; + } + } + + public static CDynamicProp? CreateTrackedDynamicProp(uint playerIndex, string designerName = "prop_dynamic") + { + try + { + var prop = Utilities.CreateEntityByName(designerName); + if (prop == null || !prop.IsValid) return null; + + RegisterEntity(prop.Index, playerIndex, designerName); + return prop; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedDynamicProp: {ex.Message}"); + return null; + } + } + + public static CDynamicProp? CreateTrackedPropOverride(uint playerIndex) + { + return CreateTrackedDynamicProp(playerIndex, "prop_dynamic_override"); + } + + public static CEnvShake? CreateTrackedEnvShake(uint playerIndex) + { + try + { + var shake = Utilities.CreateEntityByName("env_shake"); + if (shake == null || !shake.IsValid) return null; + + shake.DispatchSpawn(); + RegisterEntity(shake.Index, playerIndex, "env_shake"); + return shake; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedEnvShake: {ex.Message}"); + return null; + } + } + + public static CChicken? CreateTrackedChicken(uint playerIndex) + { + try + { + var chicken = Utilities.CreateEntityByName("chicken"); + if (chicken == null || !chicken.IsValid) return null; + + chicken.DispatchSpawn(); + RegisterEntity(chicken.Index, playerIndex, "chicken"); + return chicken; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedChicken: {ex.Message}"); + return null; + } + } + + public static CPhysicsPropMultiplayer? CreateTrackedPhysicsProp(uint playerIndex) + { + try + { + var prop = Utilities.CreateEntityByName("prop_physics_multiplayer"); + if (prop == null || !prop.IsValid) return null; + + RegisterEntity(prop.Index, playerIndex, "prop_physics_multiplayer"); + return prop; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedPhysicsProp: {ex.Message}"); + return null; + } + } + + public static CTriggerMultiple? CreateTrackedTrigger(uint playerIndex, string name, float radius, Vector pos) + { + if (pos == null) return null; + + try + { + var trigger = Utilities.CreateEntityByName("trigger_multiple"); + if (trigger == null || trigger.AbsOrigin == null) return null; + + trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE; + trigger.Collision.SolidFlags = 0; + trigger.Spawnflags = 1; + trigger.Globalname = $"{name}_{trigger.Index}"; + trigger.Collision.SolidFlags = 1; + + trigger.AbsOrigin.X = pos.X; + trigger.AbsOrigin.Y = pos.Y; + trigger.AbsOrigin.Z = pos.Z; + + trigger.Collision.CapsuleRadius = radius; + trigger.Collision.BoundingRadius = radius; + trigger.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_TRIGGER; + trigger.Collision.EnablePhysics = 1; + trigger.Collision.TriggerBloat = 0; + trigger.Collision.SurroundType = SurroundingBoundsType_t.USE_OBB_COLLISION_BOUNDS; + trigger.Collision.CollisionAttribute.CollisionFunctionMask = 39; + trigger.Collision.CollisionAttribute.CollisionGroup = 2; + + trigger.DispatchSpawn(); + RegisterEntity(trigger.Index, playerIndex, "trigger_multiple"); + return trigger; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedTrigger: {ex.Message}"); + return null; + } + } + + public static CBeam? CreateTrackedBeam(uint playerIndex, Vector start, Vector end, Color color) + { + try + { + var beam = Utilities.CreateEntityByName("beam"); + if (beam == null || !beam.IsValid) return null; + + beam.Render = color; + beam.Width = 2.0f; + beam.EndWidth = 2.0f; + beam.Teleport(start); + + beam.EndPos.X = end.X; + beam.EndPos.Y = end.Y; + beam.EndPos.Z = end.Z; + + beam.DispatchSpawn(); + RegisterEntity(beam.Index, playerIndex, "beam"); + return beam; + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] CreateTrackedBeam: {ex.Message}"); + return null; + } + } + + public static bool DestroyEntity(uint entityIndex) + { + trackedEntities.TryRemove(entityIndex, out _); + + try + { + var entity = Utilities.GetEntityFromIndex((int)entityIndex); + if (entity != null && entity.IsValid) + { + entity.AddEntityIOEvent("Kill", entity, delay: 0.1f); + return true; + } + } + catch (Exception ex) + { + Server.PrintToConsole($"[EntityManager] DestroyEntity {entityIndex}: {ex.Message}"); + } + + return false; + } + + public static bool DestroyEntity(uint? entityIndex) where T : CBaseEntity + { + if (entityIndex == null) return false; + return DestroyEntity(entityIndex.Value); + } + + public static void DestroyPlayerEntities(uint playerIndex) + { + foreach (var entityIndex in GetPlayerEntities(playerIndex).ToList()) + DestroyEntity(entityIndex); + } + + public static void DestroyAllTracked() + { + foreach (var entityIndex in trackedEntities.Keys.ToList()) + DestroyEntity(entityIndex); + + trackedEntities.Clear(); + } + + public static void Clear() + { + DestroyAllTracked(); + } + + private static void ScheduleAutoDestroy(uint entityIndex, float? seconds) + { + if (seconds is not > 0) return; + Instance?.AddTimer(seconds.Value, () => DestroyEntity(entityIndex), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } + } +} diff --git a/jRandomSkills - SRC Files/src/utils/Localization.cs b/jRandomSkills - SRC Files/src/utils/Localization.cs index c29a751..f61b72a 100644 --- a/jRandomSkills - SRC Files/src/utils/Localization.cs +++ b/jRandomSkills - SRC Files/src/utils/Localization.cs @@ -166,7 +166,7 @@ namespace src.utils private static string GetLangCode(CCSPlayerController? player) { - if (player == null || !player.IsValid) return defaultLangCode; + if (player == null || !player.IsValid || player.IsBot) return defaultLangCode; string? fileLangCode = GetLangCodeFromFile(player.SteamID); if (!string.IsNullOrEmpty(fileLangCode)) diff --git a/jRandomSkills - SRC Files/src/utils/PlayerManager.cs b/jRandomSkills - SRC Files/src/utils/PlayerManager.cs new file mode 100644 index 0000000..6b67a5c --- /dev/null +++ b/jRandomSkills - SRC Files/src/utils/PlayerManager.cs @@ -0,0 +1,135 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Modules.Utils; +using System.Collections.Concurrent; +using src.player; +using CounterStrikeSharp.API.Core; + +namespace src.utils +{ + public static class PlayerManager + { + private static readonly ConcurrentDictionary playersByIndex = []; + + public static void Register(jSkill_PlayerInfo playerInfo) + { + if (playerInfo == null) return; + playersByIndex[playerInfo.PlayerIndex] = playerInfo; + } + + public static void UnregisterPlayer(uint playerIndex) + { + playersByIndex.TryRemove(playerIndex, out _); + } + + public static jSkill_PlayerInfo? GetPlayerByIndex(uint? playerIndex) + { + if (playerIndex == null) return null; + + playersByIndex.TryGetValue((uint)playerIndex, out var playerInfo); + return playerInfo; + } + + public static CCSPlayerController? GetPlayerEvent(CCSPlayerController? player) + { + if (player == null || !player.IsValid) + return null; + + if (!player.ControllingBot) + return player; + + return Utilities.GetPlayers().FirstOrDefault(p => + p != null && + p.IsValid && + p.IsBot && + p.OriginalControllerOfCurrentPawn.Value != null && p.OriginalControllerOfCurrentPawn.Value == player) + ?? player; + } + + public static CCSPlayerController? GetPlayerFromEvent(CCSPlayerController? player) + { + if (player == null || !player.IsValid) + return null; + + if (!player.IsBot) + return player; + + return Utilities.GetPlayers().FirstOrDefault(p => + p != null && + p.IsValid && + !p.IsBot && + player.OriginalControllerOfCurrentPawn.Value != null && player.OriginalControllerOfCurrentPawn.Value == p) + ?? player; + } + + public static IEnumerable GetAllPlayers() + { + return playersByIndex.Values; + } + + public static IEnumerable GetAlivePlayers() + { + return playersByIndex.Values.Where(p => + { + try + { + var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex); + return controller != null && controller.IsValid && controller.PawnIsAlive; + } + catch + { + return false; + } + }); + } + + public static IEnumerable GetPlayersByTeam(CsTeam team) + { + return playersByIndex.Values.Where(p => + { + try + { + var controller = Utilities.GetPlayerFromIndex((int)p.PlayerIndex); + return controller != null && controller.IsValid && controller.Team == team; + } + catch + { + return false; + } + }); + } + + public static int GetTeamPlayerCount(CsTeam team) + { + return GetPlayersByTeam(team).Count(); + } + + public static int GetPlayerCountBySkill(Skills skills) + { + return playersByIndex.Values.Count(p => p.Skill == skills); + } + + public static bool UpdatePlayerSkill(uint playerIndex, Skills skill, Skills specialSkill = Skills.None) + { + if (playersByIndex.TryGetValue(playerIndex, out var playerInfo)) + { + playerInfo.Skill = skill; + playerInfo.SpecialSkill = specialSkill; + return true; + } + return false; + } + + public static void Clear() + { + playersByIndex.Clear(); + } + + public static void SyncWithPlugin(jRandomSkills instance) + { + if (instance?.SkillPlayer == null) return; + + foreach (var player in instance.SkillPlayer) + Register(player); + } + } +} diff --git a/jRandomSkills - SRC Files/src/utils/RarityManager.cs b/jRandomSkills - SRC Files/src/utils/RarityManager.cs index cde8b92..002a8f2 100644 --- a/jRandomSkills - SRC Files/src/utils/RarityManager.cs +++ b/jRandomSkills - SRC Files/src/utils/RarityManager.cs @@ -1,4 +1,6 @@ -namespace src.utils +using System.Drawing; + +namespace src.utils { public enum Rarity { @@ -14,11 +16,11 @@ private static readonly object rarityLock = new(); private static Dictionary rarityPercentages = new() { - { Rarity.Common, 40f }, - { Rarity.Uncommon, 25f }, - { Rarity.Rare, 20f }, - { Rarity.Epic, 10f }, - { Rarity.Legendary, 5f } + { Rarity.Common, 70f }, + { Rarity.Uncommon, 14f }, + { Rarity.Rare, 10f }, + { Rarity.Epic, 5f }, + { Rarity.Legendary, 1f } }; public static IReadOnlyDictionary RarityPercentages @@ -60,23 +62,23 @@ return rarityPercentages.TryGetValue(rarity, out var v) ? v : 0f; } - public static Rarity RollRarity() + public static (double, Rarity) RollRarity() { - var random = jRandomSkills.Instance?.Random ?? new Random(); - double roll = (random.NextDouble()) * 100.0; + double roll = Random.Shared.NextDouble() * 100.0; double accum = 0.0; lock (rarityLock) { foreach (var r in Enum.GetValues(typeof(Rarity)).Cast()) { - accum += GetRarityPercentage(r); + float chance = rarityPercentages.TryGetValue(r, out var val) ? val : 0f; + accum += chance; if (roll <= accum) - return r; + return (roll, r); } } - return Rarity.Common; + return (roll, Rarity.Common); } } } diff --git a/jRandomSkills - SRC Files/src/utils/RayTrace.cs b/jRandomSkills - SRC Files/src/utils/RayTrace.cs index 74c934f..5b67078 100644 --- a/jRandomSkills - SRC Files/src/utils/RayTrace.cs +++ b/jRandomSkills - SRC Files/src/utils/RayTrace.cs @@ -17,8 +17,15 @@ namespace src.utils public static CustomTraceResult? TraceShape(CCSPlayerController player, Vector startPos, Vector endPos, ulong? mask = null, ulong? contents = null) { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null) + if (player == null || !player.IsValid) return null; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || + !playerPawn.IsValid || + playerPawn.Handle == IntPtr.Zero || + playerPawn.Collision == null || + playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || + playerPawn.CBodyComponent?.SceneNode == null) return null; var rayTrace = RayTraceInterface.Get(); @@ -27,10 +34,22 @@ namespace src.utils if (mask == null) { - mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes; - mask &= ~(ulong)InteractionLayers.PlayerClip; + try + { + if (playerPawn.Collision?.CollisionAttribute != null) + { + mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes; + mask &= ~(ulong)InteractionLayers.PlayerClip; + } + else + mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes); + } + catch + { + mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes); + } } - contents ??= 0; // playerPawn.Collision.CollisionGroup; + contents ??= 0; bool drawBeam = Config.LoadedConfig.TraceRayBeam; @@ -41,28 +60,39 @@ namespace src.utils DrawBeam = drawBeam == true ? 1 : 0, }; - rayTrace.TraceEndShape(startPos, endPos, playerPawn, options, out TraceResult result); - var customResult = new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); + Vector mins = new(-0.5f, -0.5f, -0.5f); + Vector maxs = new(0.5f, 0.5f, 0.5f); - if (drawBeam) - Server.PrintToChatAll($"start: {startPos}, end: {result.EndPos}, didHit: {result.DidHit}, hit: {(customResult.HitEntity(out var entity) && !string.IsNullOrEmpty(entity?.DesignerName) ? entity.DesignerName : "None")}, mask: {(InteractionLayers)mask}, contents: {(InteractionLayers)contents}"); + TraceResult result = default; - return customResult; + try + { + rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out result); + } + catch (Exception ex) + { + Console.WriteLine($"[jRandomSkills] A memory error was caught during RayTrace: {ex.Message}"); + return null; + } + + return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); } public static CustomTraceResult? EyeTrace(CCSPlayerController player) { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null) + if (player == null || !player.IsValid) return null; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return null; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player.Index); if (playerInfo == null) return null; float maxDistance = SkillsInfo.GetValue(playerInfo.Skill, "maxDistance"); if (maxDistance == 0) maxDistance = 4096f; - Vector startPos = new(playerPawn.AbsOrigin!.X, playerPawn.AbsOrigin!.Y, playerPawn.AbsOrigin!.Z + playerPawn.ViewOffset.Z); + Vector startPos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z); Vector endPos = startPos + SkillUtils.GetForwardVector(playerPawn.EyeAngles) * maxDistance; return TraceShape(player, startPos, endPos); @@ -70,38 +100,57 @@ namespace src.utils public static CustomTraceResult? TraceHullShape(Vector startPos, Vector endPos, CCSPlayerController player, Vector? mins = null, Vector? maxs = null, ulong? mask = null, ulong? contents = null, QAngle? angle = null) { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null) + if (player == null || !player.IsValid) return null; + + var playerPawn = player.PlayerPawn?.Value; + if (playerPawn == null || + !playerPawn.IsValid || + playerPawn.Handle == IntPtr.Zero || + playerPawn.Collision == null || + playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || + playerPawn.CBodyComponent?.SceneNode == null) return null; var rayTrace = RayTraceInterface.Get(); if (rayTrace == null) return null; - mask ??= playerPawn.Collision.CollisionAttribute.InteractsWith; - contents ??= 0; // playerPawn.Collision.CollisionGroup; + Vector safeMins = mins ?? playerPawn.Collision.Mins; + Vector safeMaxs = maxs ?? playerPawn.Collision.Maxs; + + ulong safeMask = mask ?? playerPawn.Collision.CollisionAttribute.InteractsWith; + ulong safeContents = contents ?? 0; bool drawBeam = Config.LoadedConfig.TraceRayBeam; + TraceResult result = default; TraceOptions options = new() { - InteractsWith = (ulong)mask, - InteractsExclude = (ulong)contents, + InteractsWith = safeMask, + InteractsExclude = safeContents, DrawBeam = drawBeam == true ? 1 : 0, }; - mins ??= playerPawn.Collision.Mins; - maxs ??= playerPawn.Collision.Maxs; + CEntityInstance? entityToIgnore = (playerPawn.LifeState == (byte)LifeState_t.LIFE_ALIVE) + ? playerPawn + : null; - rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out TraceResult result); + try + { + rayTrace.TraceHullShape(startPos, endPos, safeMins, safeMaxs, entityToIgnore, options, out result); + } + catch (Exception) + { + return null; + } if (drawBeam) { angle ??= new(0, playerPawn.EyeAngles.Y, 0); - DrawBoxEdges(startPos, endPos, angle, mins, maxs, Color.Green); + DrawBoxEdges(startPos, endPos, angle, safeMins, safeMaxs, Color.Green); } - return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); + return new CustomTraceResult(result, startPos, safeMask, safeContents, drawBeam); } private static void DrawBoxEdges(Vector start, Vector end, QAngle angles, Vector mins, Vector maxs, Color color) @@ -112,7 +161,7 @@ namespace src.utils Vector visualStart = start - (forward * halfLength); Vector visualEnd = end + (forward * halfLength); - + Vector GetVertex(Vector center, float rx, float ux) { return center + (right * rx) + (up * ux); @@ -300,4 +349,4 @@ namespace src.utils EndsWith } } -} +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index 78c27d9..b24c1a6 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -105,11 +105,7 @@ namespace src.utils public static void SafeKillEntity(uint? index) where T : CBaseEntity { if (index == null) return; - - var ent = Utilities.GetEntityFromIndex((int)index); - if (ent == null || !ent.IsValid) return; - - ent.AddEntityIOEvent("Kill", ent, delay: 0.1f); + EntityManager.DestroyEntity(index.Value); } public static bool IsValid(this CHandle? handle) where T : NativeEntity @@ -150,23 +146,9 @@ namespace src.utils SnapViewAngles.Invoke(pawn, angle); } - public static CBeam? CreateLine(Vector start, Vector end, Color color) + public static CBeam? CreateLine(Vector start, Vector end, Color color, uint ownerPlayerIndex = EntityManager.SystemOwnerIndex) { - CBeam beam = Utilities.CreateEntityByName("beam")!; - if (beam == null) return null; - - beam.Render = color; - beam.Width = 2.0f; - beam.EndWidth = 2.0f; - beam.Teleport(start); - - beam.EndPos.X = end.X; - beam.EndPos.Y = end.Y; - beam.EndPos.Z = end.Z; - - beam.DispatchSpawn(); - - return beam; + return EntityManager.CreateTrackedBeam(ownerPlayerIndex, start, end, color); } public static void SetPlayerCollisions(CCSPlayerController? player, bool enable) @@ -176,7 +158,7 @@ namespace src.utils if (player == null || !player.IsValid) return; var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || !player.PawnIsAlive || pawn.CBodyComponent == null) return; + if (pawn == null || !pawn.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE || pawn.CBodyComponent == null) return; var collision = pawn.Collision; if (collision == null) return; @@ -264,21 +246,19 @@ namespace src.utils SmokeGrenadeProjectile_CreateFunc.Invoke(pos.Handle, angle.Handle, vel.Handle, vel.Handle, IntPtr.Zero, 45, teamNum); } - public static void TakeHealth(CCSPlayerPawn? pawn, int damage) + public static bool TakeHealth(CCSPlayerPawn? pawn, int damage) { if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) - return; + return false; var player = pawn.Controller.Value; if (player != null && player.IsValid && player.SteamID != 0) { - ulong steamId = player.SteamID; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); + if (playerInfo == null) return false; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == steamId); - if (playerInfo == null) return; - - var jester = Jester.GetJesterInfo(steamId); - if (jester?.Active == true) return; + var jester = Jester.GetJesterInfo(player.Index); + if (jester?.Active == true) return false; } int newHealth = (int)(pawn.Health - damage); @@ -286,65 +266,49 @@ namespace src.utils Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); if (pawn.Health <= 0) + { Server.NextFrame(() => { if (pawn == null || !pawn.IsValid) return; pawn?.CommitSuicide(false, true); }); + return false; + } + + return true; } public static void ResetPrintHTML(CCSPlayerController? player) { - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); + if (player == null || !player.IsValid) return; + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; playerInfo.PrintHTML = null; } - public static CTriggerMultiple? CreateTrigger(string name, float radius, Vector pos) + public static CTriggerMultiple? CreateTrigger(string name, float radius, Vector pos, uint ownerPlayerIndex = EntityManager.SystemOwnerIndex) { - if (pos == null) return null; - - var trigger = Utilities.CreateEntityByName("trigger_multiple"); - if (trigger == null || trigger.AbsOrigin == null) return null; - - trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE; - trigger.Collision.SolidFlags = 0; - trigger.Spawnflags = 1; - trigger.Globalname = $"{name}_{trigger.Index}"; - trigger.Collision.SolidFlags = 1; - - trigger.AbsOrigin.X = pos.X; - trigger.AbsOrigin.Y = pos.Y; - trigger.AbsOrigin.Z = pos.Z; - - trigger.Collision.CapsuleRadius = radius; - trigger.Collision.BoundingRadius = radius; - - trigger.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_TRIGGER; - trigger.Collision.EnablePhysics = 1; - trigger.Collision.TriggerBloat = 0; - - trigger.Collision.SurroundType = SurroundingBoundsType_t.USE_OBB_COLLISION_BOUNDS; - trigger.Collision.CollisionAttribute.CollisionFunctionMask = 39; - trigger.Collision.CollisionAttribute.CollisionGroup = 2; - - trigger.DispatchSpawn(); - return trigger; + return EntityManager.CreateTrackedTrigger(ownerPlayerIndex, name, radius, pos); } - public static void AddHealth(CCSPlayerPawn? pawn, int extraHealth, int? maxHealth = null) + public static bool AddHealth(CCSPlayerPawn? pawn, int extraHealth, int? maxHealth = null) { if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) - return; + return false; maxHealth ??= pawn.MaxHealth; + if (pawn.Health == maxHealth) + return false; + int newHealth = (int)(pawn.Health + extraHealth); pawn.Health = Math.Min(newHealth, (int)maxHealth); Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); pawn.MaxHealth = (int)maxHealth; Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth"); + + return true; } public static void RestoreHealth(CCSPlayerController? player) @@ -356,10 +320,28 @@ namespace src.utils if (pawn == null || !pawn.IsValid || pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - pawn.Health = (int)player.PawnHealth; + var p = PlayerManager.GetPlayerFromEvent(player); + if (p == null || !p.IsValid) + return; + + pawn.Health = (int)p.PawnHealth; Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); } + public static void SetPlayerInvisibility(CCSPlayerController player, float percentInvisibility) + { + if (player == null || !player.IsValid || player.PlayerPawn == null) + return; + + var playerPawn = player.PlayerPawn.Value; + if (playerPawn != null) + { + var color = Color.FromArgb(Math.Max(255 - (int)(255 * percentInvisibility), 0), 255, 255, 255); + playerPawn.Render = color; + Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender"); + } + } + public static string GetDesignerName(CBasePlayerWeapon? weapon) { if (weapon == null || !weapon.IsValid) return string.Empty; @@ -406,7 +388,7 @@ namespace src.utils var manager = GetMenuManager(); if (manager == null) return; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null) return; bool isIlliterate = Illiterate.CheckIlliterateSkill(player); @@ -428,9 +410,29 @@ namespace src.utils { if (player == null || !player.IsValid) return; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null || !playerInfo.DisplayHUD) return; + if (player.IsBot) + { + var pool = new List(); + + foreach (var enemy in enemies) + if (!string.IsNullOrEmpty(enemy.Item2)) + pool.Add(enemy.Item2); + + if (lastElement != null && !string.IsNullOrEmpty(lastElement.Value.Item2)) + pool.Add(lastElement.Value.Item2); + + if (pool.Count > 0) + { + string randomTarget = pool[Random.Shared.Next(pool.Count)]; + jRandomSkills.Instance.SkillAction(playerInfo.Skill.ToString(), "TypeSkill", [player, new[] { randomTarget }]); + } + + return; + } + var skillData = SkillData.Skills.FirstOrDefault(s => s.Skill == playerInfo.Skill); if (skillData == null) return; @@ -454,8 +456,6 @@ namespace src.utils ? "" : $"{skill_select_info}
"; - - var hudContent = infoLine + skillLine + remainingLine; string controllsLine = diff --git a/jRandomSkills - SRC Files/tools/RefactorSkills/Program.cs b/jRandomSkills - SRC Files/tools/RefactorSkills/Program.cs new file mode 100644 index 0000000..5149960 --- /dev/null +++ b/jRandomSkills - SRC Files/tools/RefactorSkills/Program.cs @@ -0,0 +1,148 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; + +var skillsDir = args.Length > 0 + ? args[0] + : Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "src", "player", "skills")); + +if (!Directory.Exists(skillsDir)) +{ + Console.Error.WriteLine($"Skills directory not found: {skillsDir}"); + return 1; +} + +Console.WriteLine($"Refactoring skills in: {skillsDir}"); + +var skipFiles = new HashSet(StringComparer.OrdinalIgnoreCase) +{ + "OPTIMIZED_SKILL_TEMPLATE.cs", + "OPTIMIZATION_SUMMARY.cs" +}; + +var files = Directory.GetFiles(skillsDir, "*.cs"); +int updated = 0; + +foreach (var file in files) +{ + if (skipFiles.Contains(Path.GetFileName(file))) continue; + + var text = File.ReadAllText(file); + var original = text; + + text = ApplyRefactoring(text, file); + + if (text != original) + { + File.WriteAllText(file, text); + updated++; + Console.WriteLine($"Updated: {Path.GetFileName(file)}"); + } +} + +Console.WriteLine($"Refactor complete. Files updated: {updated}"); +return 0; + +static string ApplyRefactoring(string text, string filePath) +{ + // --- PlayerManager lookups (all FirstOrDefault variants) --- + text = Regex.Replace(text, + @"Instance\.SkillPlayer\.FirstOrDefault\(p => p\.SteamID == (\w+)\?\.SteamID\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"Instance\.SkillPlayer\.FirstOrDefault\(p => p\.SteamID == (\w+)\.SteamID\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"Instance\.SkillPlayer\.FirstOrDefault\([a-z]\s*=>\s*[a-z]\.SteamID\s*==\s*(\w+)\?\.SteamID\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"jRandomSkills\.Instance\.SkillPlayer\.FirstOrDefault\([a-z]\s*=>\s*[a-z]\.SteamID\s*==\s*(\w+)\?\.SteamID\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"jRandomSkills\.Instance\.SkillPlayer\.FirstOrDefault\([a-z]\s*=>\s*[a-z]\.SteamID\s*==\s*(\w+)\.Index\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"Instance\.SkillPlayer\.FirstOrDefault\([a-z]\s*=>\s*[a-z]\.Index\s*==\s*(\w+)\.Index\)", + "PlayerManager.GetPlayerByIndex($1.Index)"); + + text = Regex.Replace(text, + @"Instance\.SkillPlayer\.FirstOrDefault\([a-z]\s*=>\s*[a-z]\.Index\s*==\s*playerIndex\s*&&\s*[a-z]\.Skill\s*==\s*(\w+)\)", + "PlayerManager.GetPlayerByIndex(playerIndex) is { Skill: $1 } playerInfo ? playerInfo : null"); + + // --- ConcurrentDictionary ulong -> uint --- + text = Regex.Replace(text, @"ConcurrentDictionary<\s*ulong\s*,", "ConcurrentDictionary .Index for common player variables --- + foreach (var varName in new[] { "player", "enemy", "attacker", "victim", "target", "pl", "p", "e" }) + { + text = text.Replace($"{varName}.SteamID", $"{varName}.Index"); + } + + // --- ulong steamID local vars used as keys --- + text = Regex.Replace(text, @"ulong\s+steamID\s*=\s*(\w+)\.Index", "uint playerIndex = $1.Index"); + text = Regex.Replace(text, @"ulong\s+steamID\s*=\s*player\.Index", "uint playerIndex = player.Index"); + + // Replace steamID variable references with playerIndex when it was renamed + if (text.Contains("uint playerIndex = ")) + { + text = Regex.Replace(text, @"\bsteamID\b", "playerIndex"); + } + + // --- Remove bot restrictions from player filters --- + text = Regex.Replace(text, @"\s*&&\s*!p\.IsBot", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"\s*&&\s*!(\w+)\.IsBot", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"!p\.IsBot\s*&&\s*", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"!(\w+)\.IsBot\s*&&\s*", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"\|\|\s*(\w+)\.IsBot", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"(\w+)\.IsBot\s*\|\|", "", RegexOptions.Multiline); + text = Regex.Replace(text, @"if\s*\([^)]*\.IsBot\)\s*continue;", "", RegexOptions.Multiline); + + // --- Menu enemy lookup: SteamID string -> index TryParse --- + text = Regex.Replace(text, + @"var\s+enemy\s*=\s*Utilities\.GetPlayers\(\)\.FirstOrDefault\(p\s*=>\s*p\.SteamID\.ToString\(\)\s*==\s*enemyId\)", + @"if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($"" {ChatColors.Red}"" + player.GetTranslation(""selectplayerskill_incorrect_enemy_index"")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex)"); + + text = Regex.Replace(text, + @"var\s+enemy\s*=\s*Utilities\.GetPlayers\(\)\.FirstOrDefault\(p\s*=>\s*p\.Team\s*!=\s*player\.Team\s*&&\s*p\.Index\.ToString\(\)\s*==\s*enemyId\)", + @"if (!uint.TryParse(enemyId, out uint enemyIndex)) { player.PrintToChat($"" {ChatColors.Red}"" + player.GetTranslation(""selectplayerskill_incorrect_enemy_index"")); return; } + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex)"); + + // --- Add using src.utils if PlayerManager/EntityManager used but missing --- + if ((text.Contains("PlayerManager.") || text.Contains("EntityManager.")) + && !text.Contains("using src.utils;")) + { + var lastUsing = text.LastIndexOf("using ", StringComparison.Ordinal); + if (lastUsing >= 0) + { + var lineEnd = text.IndexOf('\n', lastUsing); + if (lineEnd >= 0) + text = text.Insert(lineEnd + 1, "using src.utils;\n"); + } + } + + // --- Null safety: common EnableSkill/DisableSkill entry points --- + if (text.Contains("public static void EnableSkill(CCSPlayerController player)") + && !text.Contains("if (player == null || !player.IsValid) return;") + && !text.Contains("if (player == null) return;")) + { + text = text.Replace( + "public static void EnableSkill(CCSPlayerController player)\n {", + "public static void EnableSkill(CCSPlayerController player)\n {\n if (player == null || !player.IsValid) return;"); + } + + if (text.Contains("public static void DisableSkill(CCSPlayerController player)") + && !Regex.IsMatch(text, @"DisableSkill\(CCSPlayerController player\)\s*\{[^}]*if \(player == null")) + { + text = text.Replace( + "public static void DisableSkill(CCSPlayerController player)\n {", + "public static void DisableSkill(CCSPlayerController player)\n {\n if (player == null) return;"); + } + + return text; +} diff --git a/jRandomSkills - SRC Files/tools/RefactorSkills/RefactorSkills.csproj b/jRandomSkills - SRC Files/tools/RefactorSkills/RefactorSkills.csproj new file mode 100644 index 0000000..c76b054 --- /dev/null +++ b/jRandomSkills - SRC Files/tools/RefactorSkills/RefactorSkills.csproj @@ -0,0 +1,8 @@ + + + Exe + net8.0 + enable + enable + + \ No newline at end of file diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll index 01695fdecb5732e3b5ba243359fb9a88cc5d4b10..522a3f26c13e100af2da282a1aef63c070750fa0 100644 GIT binary patch delta 22236 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 T`A^Fp8{DS9_@&s;%klpJ!d`I_ delta 23334 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 fGvKK^b#Lyp|6SoeX8((HgxJGISog| diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll index 5768ad47701ec5e3558032c9c0aaeb91c091b731..bc20c506ce736db3eb6dc8941b03a4b2140e472d 100644 GIT binary patch delta 237 zcmZo@U~Fh$oY2AI(|&&b#-0j8fn}RNzYh2%>OJG;y~W+{8t-ftF}la1VUU(&oML92 zoMK^+mS&M`Xkd|)oNQ`nlxk^~Y+{gNVP<4#Vwr53JXy;87|Y|*Q+p;qF%J-^-6DO+ zs`I4po)dhoI)*>$C%ae_DL@6++CT+?s%=)b-#YHu)&7v*L$Gf1H48Zwe*=azh9m}K zh7<-fAejuLEf_#zX+S!e!4Sx{0Lmu=p(&7O#E{Bh2~?TPU;>l@sWk(N83K8hU=_)m Joo)9r0RX$BP4fT% delta 237 zcmZo@U~Fh$oY29dm*w|kV^4*lfWtSFjt|*vPOJ5|_%CqUmc3cT=pKuPp+QPgnwgoA zWva1}S*n3WnuUdtfw@VFg-NoZWvW4{agvdlMOv!KWGVAwEXVnn+a^CT4-nYy=BKQ| z-QzO*){~#DqV6jvyI2${Kn0h;1c9pA4rZ6SB#Q2A+5P>F&E{(saxDIa3%3QklwNvf0^o GFB1U2jYh%% diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll index 50be93d303bd08ce431bb6a5c055a84178406a81..26993a2ca0c03f18982ddc642ca7c575e0a64194 100644 GIT binary patch literal 536064 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

N- zvBI1I$EutRw<207Y|5_qxHU8t_|VwaL+I?89Gf?xXHX(+KLxfg3!aIS(L-mPzgoA$ zfqT9g8ma8TUW+o|6eLNsM~WBc#5&2%-zYcVjND?{IYB60XWz!`+)l2!I>tC`C-$8s zK}`gmcpfX6a&F+TKt;=W4uux_8k{dUOZe9;zVD-sXoR&z*pb#3)Ie#uk!`pMKdRj{ z7AQq0N0N+^eOcSS1%U884a1%7-tl9FtkTZc*_b4612{`mYS6vFT(C`XfO0hm6y96H z28=BUZnYUu*Vjx3VTs&Vx2v1l9TwEuH7Q7jxg|t!z!dH3J|gaQnljFw2(%hP^7TZo zGR`tZ8E2_CCFE@1*~GC_ptutb35%&pGzuMM`)Q2Ks8pq+5`IRaBDRJ_M;1{cP-?0~ zCsr8Tq>OSL+)XD%z$h+?j*NT4g5AhEN5);gh&%I2L)?B=DcTdPpy;U8O3_96QLA-S zQdQ~b8bgilA+@hgeX5y5Cnl**DGMsKDRnA_T~)_ZsmW3Eb1QC}<`>_8Pk`poAKE6v zO|RIY0}lX>_WarD{`>u$rP9+#K4Ss~`|oc1{`<<;AcK@1Z87~@w&3@{BqEy#$XGT% zVQ^HwBC=gjfVv~rb1s^&IJn^ubw*X~*Td}LHg6%nf-E@|1PNKfM_cD2Swd@mTTeEJ zc&F$ByQ~HgksjsW`}It%xX)m}US)i`{rX!uEmOb{KW#e8A)t^xL2HFd zp^etUZE@KHn*f@y@QLk#<*Plx7I>!Q6}hU=`?+I3!)hXa%B=NcP_>^2^#_hPojkFD zuR{UL4=x)#kpb6Th}-OSoA!J{<&#AQrf|6bwQy;$|7CM+W??*PN9*Nd58l_gAa_cUQ9(k6Wx??~Q3R+TR$iwui2@qijZ$>8 zZLgPu63D!70~!cM`_-*Vvv;E-v+~s}TesTcsR`9;^}D9B=laUIUKiRhV<(tFccQHi zvv!0vOz(&$D@&*#lpquY5cnNwgJ?h;gV-ZJ4J_|M>Elc`Cs9cb0EjJHr1rEe(oh}@ z>ElTK%ASV%gp}#68&#`a0`Nz5#{#egJyfP5q7q}cu>mDiQ$uj;ddW#a zTJP*>jr&L~k4My^^Qicq-jEj2gEgpn-xa(?ET65VgJmXAt>@u{^~mw_#MDaL(Val- zX5hZLo%~nN5>fa9Lr8p!Trl`z$|yCmjnDu%flmlSz2vVNMvQiXb7hafErHu1@RigaE-uKxdvW@6_Z#C`w*bH(70Jhs!=zHl#u!@q$(zh z>!?b?{M2R0aC{^kqrWMO7Nv_!9E0y&CWeh4qo zh$lzkjfUz1x$0Ow;188jqvS8_&y{2h!Os!5l)t(x)vGXy^Qc$BYdtAZW-YljqqJY z_)A9kCr0=mM!3HmwPCptKF$bV5QZl?C`$XMc0`@OSSik;hrv_gzX9Yg1ZH_ZxVlsE zVv~+z`zvxU)PUp(1?M7;ig7z3{x-l#n^aNq)eV0!o8?^(rKfc!xVx+_&p=?xc{h37I0$cK zk|`c!4Xx@^2~5CK+U@bw8MQ@TPCeD?kda~T#>ZX_?fIHh&2)}_f56Rp=zv~-%4w^QUhvm?(Ydsy5ZZW3&4s|{89LO0nqnJ{D~rj_i$actT}?_PjcFFZueGtXPMi| zpZ-4Ng`DGDybHK(JKl2xqGWmozO1rpRY!ShYIUDchkQ)mRa&R)>iNcYlk$DQREZrr z!9Ze+MZ?5RuUT=K6n~_#&aC)L%1dBN!Zj+PpdRYp6^k5o;3w?)AFN7WrElimO1m4G zesIc}eZsh}brx`eDqPUR&&l;hfk=N>{N$>*l>)aO;C5DTDFwW~R`{1OcYzkXz>_%X zk%6xAO;Up@WjEx*RuyzvIG8f}G0|mZEDP2^O%0)qTO3L!t1$WOYP1E0h+y5P52AAg z;W!?5k%2rgH}0vkts%EvirT=ZGU<|6V@p{V^$%)QFkQyVn@QcMB0q`-(&dJm>ygc< zpm{&~9$fSHK7_3iEV;$mCGEez?frxDUh+RIPnj70M~(2uBy1=%J}dWY{2AlVhXkOt zjNy+n?C*}Cx+jo)@&)XV(K?vx*nRLv7hB}2|Bf247?|y2u%(=o)r~m>RTFqYucgZt zVr>5dsILS2HBSQ7wPN&6R}`G}!NLjEEYg4;G}$UPb8Ll*j4xg1lxiy_c#lfKSe<78 zil@uDD2;L@JglT_)OxX2gXebRv!LW&pmdT~yF;4p!49eVrZq;!#ln5*G7z?`-8Kgk z;{9 zw<5R@G9WPCi%~C+?A~siB-OQ1+oKVfb>*N`{{bv4P~^)v7q$Cb+FK#&zji44zOZnd zzI60nDJEmU!wYCVCa85F{sJD(dH)dJUxbb|9{@sVPuv1A>?9^G!h@R{e2tJbaWPZJ z`Ku>0wnX@5EE_Sn_{_ z<3?-1W*jCX<4@JQ&;`{B4_;96xhH~x`R7A_g(@!A@wQ<|Wl^D6#|%{m;$e}lPHGyO zMD^=8`@%o!w}x#&iOW#m$XLf{RFC0+r)H(DMMzTun!pzJGa%;0!fPU`4UIoBhhD*Crnl(Sv0Dh! z*&ZlYExOoFNq7sfEYufVzdW?sgP6m$h06ISqaMofB(2;>GwKnY>rPmNeT=n z0Kr@b_bB8mUHW>!d?P(SRJ!s)7W&GDd}E1`qFX*7I+!}dKT^#3d!bppBw}xQCY53! zMj1D0_|KZ|v*3@jocRi_1WhWxC)`Kjz@F@={V2|FtR>v$XF(F2&zFImK+SyUDZ5m? zDOQII#hIjT9Ks}(7up{b?}Nxs_jan=up+>K0=}RqAP*uA^QFn+aub)5iu)#Bz=ulQ z2Yr_d2sqrBowWmXvwWsh&M5hR0oF;0*KL}=r|YIhaEZZ&o8cvUKMJHU5?X||Ev0hi zuyn(q)|ATl8!;!o8O%xOEZN&x9mK5pTsUiF*VGv&aA(!Zf^U*H{uxvK3YkCu>i#KB z5b8cXwd3kPCqRaDDph|ixr%bnW0FvtUq>jI8#b0jQF?%_{+r=2ln?}sW(lf{QHN%g zXcL*vxuXxI)kJv#eRF!@lMK{eWNA}`XwnJ{WR$3!U?Q|N?*e+lz6kXdsd&LJm{Z=4Egiy^MmECky0<(c2j;%3L=;LyPkN2PWearkRYDf5AD{hx-G2amqRi z$Y}}wX5hgFhN3AK@nX8!XlMMzm;#D(PV>&!5yD#?xi)|LmHp5Ns5b=jcJeUc+%i); zhUP8Dc0#9}#w|)1`CI|s?pX1`+ugfG7;qu!RS{q7K>#X5u8{RUf&|V;a_yF-FgK>1_%}#$ z;WtQf<~K-kSuM(Q<~K-`@6e1klWHa~CP(+1tZTwsFgMAyv2t+W;+zJNQlU|soJWSHHzby?`!+JZkDzIeeQP!~^-e$!bGhb*Rhynb=I$1Ag|qiFP_dOF|M z{Wi|-+j=G2E#p^-?gzVI9>*CnAvi@YzOCQK7)8FVS3%Cgg_VyPeOs9z9gJuU>(<}~ zFbuJb@^s(UE09kNtK$evIS*65E8`+lywxD4)Mp1 z>jG5ppY(0LU-*`X4SL6t38dHbA^EXvL2Dpv+w7vw;#)SP=FzZGpnW84_WE|$(gi#ZgDS=Px z<3ZMF!p`c``qFrb-(glYdzoU)-e=;|N(9W})5@ed`m_@C8TqvGTqM@~*2`y>DF(&C z-%tCP?57ESCpJKMFqJjUQhsED)3|}>;qVEP4{_ebk&XFqwCgIi%YHh)#9^3I z)eK>6Y8x%^PYgT{=?jywxK9Ib61Vv%MiKrPv#wGe0HF54n79(y6?tn~&%su-Ms!Z| zyC{sj%$ayOKrIouZfcw_~ZrtGX-fqxd&OYhg)ifv)jp z&ffJ9cR|Ek+9P;xc?^PgoU4d)hwg=iP&X>la9Ya2lLMl*bE!QjU5Ba*b)CV=tlz<) zt}}*KE)=@_12V*Po!0LW;~xMOYWgu7?T3@K`WFX%PRTvS(rL-5cxdxiKsa^_Zl`MW z1j76%(2wM)J__^`377nz>a?HBvy$_F$$)<#svp&Be{7dnIHU!=j4e~;!`^=oL4wU? zey@-A{8thVqmF9vk-h|$xD6~nevC5tjh_G~bNYY=7KF3Xs^}vxaDw8U+Me5f9r>Q=!2;9Rm6><59UO1-}$v7 zVjZ#{zg%4`(lOI1dwknPU)VQ@UeOL*lYvsOm_Dm8P_mxr#kam3?=a3&2C)8d(5&EV zRZTA9r++;%@crtv-ncFB!Nj+V5|;I9_UD=1L82B&f48Yh(cEkL|AtO1@vBH=6<7a) zWce<*M`sq7ii|Co{jw2mUg9Rb)#yFHP{gNy9x}>aPQw2gs0ZH};$jOiZt@Hvh|Ywb z5_N2Yft!gHDT;)z6e5uY@HKpG>c3Hl+%Bqa+WaeK0Lc9ph@HP@CgGDpSsivQRz4+(U&zwF&Q~oU1Y~hf$1Gp{MxR&v!b%7wo3y_aJ;b ze-3JecgFNJ?ZYHvb4`0YBAWjIp+{@l8>lE`#`$Pl)4mYEDxpm=HrBMbgF@zHu%-H+yxcKW=`?d5Tqi6;s7$pk)v@1 zh`I~A!8@=OX50>c1@acU_0@je>T16`P=v0$*i-1)`32aAftTyj+Aq95ZpM?L!QSX% z^!cMeIG3&P){uYnVW2PWwWJ5FRqE9(3@y{7ZG17TMpGP3QuPi25BK-zh!3ZVbl_B> zHvp)|Y7b5Lz6ATmWakvwsru)Tj&*Nn?gzC9n?4F|0J-3x;!cjqi3iY5&U98Un6_uY zZRdYm@mU+&rN>eDa-Yhvu-@XiZntTr)%x*9kdh|(HzH_|{NDn)9hqc`BKbGPVg61S zMeW>>x`-QCQuX&E#)TSxbJ1zq$XZOp zAq#u%+dzhq;bY<^)ZnJa`5;-VJ(sPD_|sEPf|W+ZkMSdva{pbEMRC+mh4!6s_8Km| zLi@PIWfkr2d4u*<-9_9VKb`hdI6(r<$4$cT_i)g@DlJ>+)W<11jpLN8r_dD~r|dG1 zQ+AohDZ5l5jTvv2?h+yj%>Wojo8L{hUMq8?4NI^hYq!d72Omnt{T!nf29 zh0c-j55w;$_SV*548|Ua^$hDjwZ<-3hptm?;aa9O&$8aY`sZfv?gS5rbc1b}eNX}T zXwwbUT@FlWqk2O(z=!-|xz#aj(_*LrIlCPNs-D47!I z23)dY1HS(6uza658xxjuHB`*s2tLs4#vGvCdpoEXc5gn~rf_8U zc9AJ&_kKH|jftBJX5YvpQ`E%0B@UA(jGDMi2{fFZAZs*nBfEF)NGsF2HC|2!GpM=C z6q&ot!@&=EAp?5><2AOK&!8sa7#akV=JbsVRm#j7gn3Pg@>d!IUw;$%s)&)$&PK~L zoJ+cda(L?f3*a^|yamVH#Xsjj#wI3a=X`Da%I&Boc5L1C;4L1Sux_K6m#YSQt7%*{i1jfY$hh!> zDzS-o5ccALxk^xWFW0++0t6T4_EuBgTTz&JB8|EE2Cv)p;aZs+tKf~dC#yFXZ@isK z-b5spWaSCP>j=;bTBy!2(+Up{KDSu{t#gjv0ouhJ)y{rKo~f1j&)|%_%J_6=~}Lx{-6n`y_@&9N}MsC`*+RYOMMC zX^2gW(%R9SkIvvQklLP|cn2_-9p`W0?x)^NcRzLZ2S++Bowf~x7R@c$@zRU4R2`ae z02VISDdBbTZ6D20M}j_qJg|XXhGO|ibfNfE{auJ{G;rTZ(OH6(8UFqDC0I;~MJGG{ zPBeLBtba6%Ydr^o@fj(0O)vpxc~)bj+?(0u5or^GFXMpYZ%ZgF9&=$4gJ z5u09}>fF#7=v>1c>U-y^<@kixHE<7`he|$;oVdO7 zNU{bLw93e#7P8C07fD=P1?+pH+{T&473HDxd~g>h?jN+?h5mdV&razX*D97Zgg+mF z*WxemsXswcuo7fi*};-RerjMOkE5_uq*iTF@?tYF*e{y$j>E+1n&W9-fzkgs^T_Z3*X7;9Lf&W>+`p zn-(@Ff`9$@6Hv&`6;*kGLGDUb#>%DQ9VZtcYlPSTPahD*gWQwgBqpu{I_T&*{n8lv_ zK9mc4G9T0%cww$-Pab7ekx6am_GDt_-)B#j(*8a6#!;okhFaa$r-QxQl~I zk3IOrd*PshxrSf+5+gKi!P&sxmNo5dS<{4=eOgm<#?E?|C{wW5f*<{V?7erKTxGpK zelk0ArtEH#nb~Yfn-q3AWOgZ`O+rbb1VV2y2_hCyO5nhZ3bO7nDC!kOuX;tr0-=a{ z#e!nJDu`miih5D6f(lsR+Cc2C-}n3Td7g8gGdmLk!teg`OI|y3=4t0CpXbw`&jbAV zPR`42oEPwGA4G=~T+yQyQIFQ4M@b#-v8dS?M*(mJ4Y*ksrapwKdIw}0THP#MlxyF^ zBrxds)#ZF+50sVrIuT%LJIcp%J@sLNO<|H>mUYe4pz`rlv0Iq-_he6EC?+dW&#-beXlkE@YVzzohca+vZNxUrkBe0W~Z`yvr}1fD~sBvL5Y3Yz1gYk-t5$= z;-w&?hD#_5BwEO>atbn>ny#F%S4HGOj;K_&s`9c6=Vcep&C5Fry83FPD*spXK5b+0AaVSi~!|) z08pR650dvzB=@`TpZW-@`>Ii&`Y4~ZZ!nV;pe4(lK2dT~My6-wPbUD;XCqLFOK!iz zOZMSQ=r1)K`%8`0;9Uc-;&4^^r*!ArD*JY-qNPi|#Z|t$hQ4bX@C8D&e7%1`tVrr& zAV{zki!0_1^$uzQ(Ze5yp2H&AW~Uytc4}*17{quW%?d|^o9bUIT6b%`zPp3IaYl@JPSYaG|8!p*2r-A!T0TL0q zGSE80SPCb#mv(s~oP1v$^Mv_>twhik&-sKEjQ^dg`97D%U*Pt5y7FlEM zN6EJ+#CK5$0FooEEavHzwN!3o-OJ&87lrsP3W+M3H@g>mD|A@=aS%c6aqtKA4{634 z@vh~%x6^a6iOD*jIMW3P%c9}cib)GG&whimTOvnOY{;?fj2KIf=-|rpl}e>^gaQa9 zNqHVFib;7MJ24#|4T{k2+&NR8@1d`px1D3Q@_ed#iDM4xt)6JZ=po<)3ObaRH^s&N zTotf?L{Uqde82JM%7n+DA7W6?;|h@g))+``HW1&9*dxh6d@GC%XV^RaBD+U&Ja_M1 z$3EIQIo(2LL0)E->rgDTi8*k7xCTGG(ZO(?e5)VbUdw|k0iV64S-x#4a_-x*EqEDs zN=7{n4`H)?p=U2EMO^RQkS=i{+`eyN{A`*c@x0DGW zEEM#-&AB`DD_o0KjY^HIW3FdNhdcv@|Bw9&xxdKO-k|#{Vu0y@F(X#R#qK1}5*Wfx zdTtk%m{6Ch9-0j~7eb%*ht^)F0TJl1s-Y}rYAEC@M%(7P1?Nhy zD+TlYcl{R6#}=1&P?nlIX=!C?+fIs3*r|T!2+RcZcl3t<{Z5CcVD#Z8d=zj;bNCEA z^kyeF<14rT;DDgmR0vKym~acwnp;rFTVeeJDtoEgk9hrdyyLxmM=E@PC|B+-7gjZj zF=hmPXvAjNc#?wtQkiqXK&k5aPQ1X#UBkJ-Dh{9{o9 zookDDqt2;BV2lF$MkA7gPN|;%EFDi*94i|lml_QIU2C!)mAyb+m6@Ep-L6n>wqjqq7=^K79;JD6pYWjGq!38p(4PH#?@OXK47=U35-!dRyya1m$P z?8kBkeuS1+%@Z>22*+&8F_$x!}e$ za`qGI_vj^kZLHs8KZZvi$7kYi4xags^cCav{U{8$$rw(BRPY7>BmA4d%oxwSQ+g(b z+spY8S_6w2HNkjc+3GAmd=}dGa`jveQDi@db+nO-#mhO`DD-1|2IdO>R>j6vp&90c zkrR~SOF}33Y1R*@z#N^mVR=*)Zd|_SVw^1!JQB%em1SLtB=Poz zsJni~9CzTUkJY^$D^8QNYnf~;Kw_%8OJ~iqve{WbcuP!g($tH4ACUJOSWmBh z>zJFy(6Pl{z%2$4D9}_|?UPCxK#}EDa(PiFc^sFxn)6l5l^G!pPF0W0$#uta?q&%I zy>nn@V#LXu?_^NhN5TpV1idfA7vRJ2+!@B#@n9n&-*gtzm2a|BH&STvee)HuvYP zjtrN%3C>mxnGQMb(_nZuCUGn)F{1N`tIgh)GFD}laaCq;_hN2kIo-Y15)yq^WtMSO zW*Jvy7FE=qxEixeLgRjR1btmK?h=D`HDKTtg@K6pS^O@mUU6ge%a{#=k}-Ne?FcE(p1KNCdlS~g+`P>G zvBKdgIH(uOT&ed1Kp(CPhmTglOnV{n(JGV*s0AJ0%_wxPK7uQt2esY=4kcjX^x4Fr zQARqMQ8gLv>9`4;_>--hI1fj7r7uff`(4azk{LD}x4B`w7r=2DdNQ3N1yr}LL(CoM z?H7!5Vrjr#=Gkk+rIf^X5gou%dB0hlba*cMAygrs#rc|> zNKx&aPTbVNbYS|`@11sz)r)34Y<~SWq+{j?4VAwDTR75%o{JwmQhlC$tAaD+bGVII zNA@!Hn-H6z-;7&fibDbn>+)Ps_KFnuqJOv{WR7a2SLk%`9ZUhF@S9M7M(kn1y~aA!6Os=UAC-$5 zmk_w~xIQ$GAirGrv$stB01IBsPx5PUIz{@#(|F4jftyBpm6gz6stEL|qt0tg14VdQ zfbUi|QW;2&La>Ndi{*r?8s}r_TEv8U6B-GI5*9TEkh)Mh8?B7CQ7o&%yc?OCb&p-> z7Gh4MXQqO^NDs6iD?^K{{)RvT-Y2={^+#D3KdZb92zUBgnJA9X7;6!P<2vYx#T`_w z6~pq`4wT_6bF6*8cB?}#00GJCq{c`5`VZ%N7x;Qbv6%S>LpWX*ypiCiMp;jIz8>)R zDUPj)!xae~`D>BWNk@*L5SW3&c%jKTN-*kMq{_dlDj$t>N-C!HpjCNSHn;;l2VU~l zsY9)9g8Pvm$fd<0G`Xs=w17hgE5Z=avqhF$at-W~HuZVIhlr$W@D1@wxkU?u6ELQ2H7`JYbMtAgo?jH`*?cD)QI3%U>K?*%FqVc1gaWvwaO9Ybl1;Y1&nga5}oZ^h!45S-7 zW)CRZB`y^hlU1L9MxG8YS^10rL8azP>xXgfFC-e*tN&C>4KOhqvCXxd@?%D1>)&;w zL-iDn;9oa7TpyJ0k@}wUJ->b+zgwI^F3ql$UArs|v>k&e6gD_GARg*Fa3;rlfv(dR z>;gqNCn3{|;Qq{Z^HWlzw5!afD0WuLyHeo`@iIXgjs4r2vh%EzpXwwNvD!YTZwesUxF zgj>w}p{|4*gw+D74sg3SdZ)UlbG*+5n16pPsG57X70MkqO zI}~Z;ac%laFI72vD7Za|A$M=I(2W*%6t`Va3A$`M!1UAOw@y5}7@hts_sV~mz48k{ z0qz6<_U4x1FSA^W^_MOgZY*Y2WK9Di1uv1Q-Hl+cf3SBErd*+Hfsy{ zVsZV&o_#ZS#MjYxiDxqPko19{lod(s5y)Q}Mjwn2v4cLyYfMMJNC-R(5GYY@og@D> zdb#+Me2KUeSAxA^Ib!F7J3#pzS@xtS`|dw=dv|r25FG1dc@;-bj|JB+)8P6RdigoQ z^#&wxcZslBpvbpkrz)RC49c5OH)&${G30D4Sm+*EY<6LzF zSgb)IWR0SQMQ@ zY53KcliP^{-fD2bZvc7RiTrMx-l<9QjI!ro7LPWwN9s@tdT_IA+3&l9&mwtNULDAcY-iXT3V z=h4ak#b@v2ukqQ}xB)BOAKhy2cEh;>aj4aXrZ3Mg&PR>Ik@6=L z(dH3oFlv6#ZGJ&<0Sb>e%?~=w%LEFq`VsP^w7BFjrRo^~$ds&8KbKf#VTTd*Rc9hgkZ}*Ix(}6r717;e!}B<{M`GY%2H$5z7kHC*KM4g|~(6cZ}j|jH<6dA$>vYWYbx= zG`ox=?Cfn1k*+YYL)Em=8$dsUj(1h&cFl?OxQcQAPN?vQ+HPQWZai1bx8tv45@J^! zldv2u(T?`Jb&hixE@Fbkxe#8?Oc9Sw0;VjP(54XY_j7sUIp*t~Lgv!;&tuW-QClekj(%foPpnHrRsXt&*(yb~fZkR`A~(@4Y) z(Abn1YHUhJuqkJ`f7MeO1z(Pit1qH}P@JbhN1=A$S<1-KaF#k6o}>2L_EQ+K{dNgn z0gl)E4E|zYL&W68@2vtq;Z>Y6@td{UfP}8d?0=dLWR;Xrh*n8SD%6A6shmwwv32tP zakL7mhvm@~ZA=&?jCk!@8GCRR;M^K0j7jjcC%i|GFvcj+O2K`@o)XB_AHen+P(`=7 z#$5f~j>nvwBXeTtLc$kHWNNU*UWyh$Tno|;I}tW?t{1uXoS5904DQEpa2;eFy1hiu9Ay42L^<-@nR=VKOrzmZIGIo4HgodG1oSU(tP({hcs@lS=xJdOGB-+7cEhDY z%IM`GS#R;>YH7QTgrX)2)Ux4cIfPe36jPk8{3LssC^*M)ZZINyB*0K-d?Wyx|0>I^ zhWZ!?x71LdE#JfSSIhTE{d)PHU%yMf7t|k=?}hbjh2(}wHsLs3B@vykgi`Vf`sq@x#JS?g6%5^*}t@FNhJS?m8vi0j)+F^3HYP(~L%64%qAH+Lh*;M!%6dnv;i%-$HlV6;N^%UN~ z6uA`&>cKQH1{Up6lS*3=&$xp?4- z@uld|SZh+Kr^!M@gzbzsUs)p@AUx}PlERIU=L^XR0-NI2!S;H7o4sd+0QmS&5eLqO z5ERE(fk%_+UZOUii*#PX*JH5ZzvH8vuWrQo|2OavvVr0K8ACw*Q~MAKfD(_{=IUZK zoKw-FztoTH?Zl`eTEM)mwt$<#_v7|u{7mxwpYEWhj`;rju`bWRA7{Fq?>`!8r{K@> z{TnT_UpZrjwt7?JjTlXf>#yc)f)N3)TB&veJi^_@c=t28=FR1(;Kq=0S-rmMaCGNY zK7i6-=IvJZK@*WmoNZ_>MT_QkEAT%yE@?6#mBt#ac%z3ZE5dt9p0`bhOqirxbSL|# zZlv+uR;0QKW|T13xCHueP`?6ht+n4aPua?A=yXfv(sDx!u07`A0M; z`mD$BFzvtJLh)#eIl(&M@#deBWo~Afk75grwwPn%wtU1^l}aXVOEKO2bF%gaSnQKh zn>lWvKph42RQFO4u;*}BKhlK>v_5=GF_?LnvHkED^ME-IXM3N(T~y0ZT1id3yOZI! zbrOyE2gL$3c~tibA95Umm}IS;AnV!*vaX!~7h`lZ5x4;iYi~u-{75qnnR8HeTngwrafj+TwNoE!ob8SwXiUbKGsHqv#T^lLOo- zNY_?6hcR)%UFH4L05V?|+#N#+XnG!m0D=jw^o`<5lctX6l$!-z1d=P}6oj4)I8qQ2 z;PXpq6}}x41oS~Y-f?)>EBLO*y)UZjcWzl$xNE>qbE6SSh6eoPkd%^P+rx&sIC>*ixBg2e)v|D zA370;a>w^reHzmu{@7-@o*IAbPoh;}b>n-iWG!ZpcEQR<`SO3_kDc+JjqUq2%y;7s zbUNw(oD9`6OY{Z%pt$jip6W@%%)(XjC;13eBoF{4i5^-u#`3+4r}jkPC>kt&aFX0T zsi+0C4eCSACfS=+aMQ-`L51sFa2XImC~%z$UJtT2I?*#$J*AW#HrLwkfM6$Bqg4HS zNkR*A8+@acJOq#Mhucd+*5HX^-LsqgeSIL*s8xj-_Y3Il41a=T(2TdCg%;;c(J^rV z(edt;-Mion(u*Y+JLVpIyRN_>)&VdkN6-tY%JZ!N!?F;yysxutDunsN=p9ob!qS3{ ziT9hte3+PeulOH10U#Mfwj6 zY>&zwT?PgRyA>F{b+BvmuX|_I_l`PKF{wU|f88E}u4Pm!=(7HG z%;@f4#}=N1e;w)mMF6pHa=dq&@%HL?`6a4PK+)g0XBas|B#%t(aDwHeln7liewZQS z2jzs&kMFDBa&a4JdPMy#MsSi`jG$htKLKRB1;{Z(Wc@HD>*ELIm1Edfzr*XWLgRt? z;j#}-lKU!U2rhPW$v$v#B7H`}8Bn=_4LGDk4S%>Dvl4F}Qbg6JWK^4CmRj%3VbGNC zSdruH&cQlpT13S;){+C$YNhH)6-T?a{?;7e7HhIK}h#X~Y{ zoFl1B+OwF?At*8OUE zZab51?aTCF`zrp<#1y)ECg^^=U69st(&-O5Q^REZA-PY9{`aix*#%32he>-I(cZTS z52+9ylpTFc%uWP*KLZGpjwX956RTV559qLCRf_m;$GPKryig4+#_#nu)XAxZ7x%3HA1#-y9Gvw5q9fBJY_E*#@7YeAjbf49s+(et}y7Kw)6O<63u zf43I2|1=-Cg(?M6+b2r(ib_9Gs!vq;iBkRb2hq($(rnS{Cz9rf>OYY*SBwCO=8Ix7 zNFT6y()Wk!yYQjuLEq~4gAsgk)i2xfXzX%`DJN3qk&oJUbrh#rysXbCnB?m+jQBy zm6erUx&Ss0+U0ckUhdu%w9lly3ijJ~h|g3HU5K0_pltz;kn-aBen zm<{d`aNj9_nz2X@VR&xFPpTu-<=|$Nfpsqzyae?~dn4MCv9v`m3@`|do(2Q9vAN*~ z(AZe*EHnaZ36%ed*hnS?niS)5V#@&K+C!M&>xCr(vf^a}5bn^2@PlY}L(rc>0>~q| zY4{lgA3`deI820pZ|>Ta^ga+juwwq%;_!6@`|)9vgPYo1Jl=vwI>+3$W^*-zZ#do; zGxd2(p}gD!9|rrGxv|56LWa$J1a(8;xw!L^0#B&6l#fLz8rZ2|SM~(FLf8u&Hz;5L zyK%4}z~R^U052`vkD21#sN=J7|0}MEJylM(mix3rAh91u)9A~<04n`ED#?O=0*R}a zM+){g1467>J31p@#TXvIvdjT^Sp7QT=nF{uF5&tY0@poL1BC08Wgmnl<_5~y8vK&I zfnJ=NxD6!#zI8ZA#pUf+uE(F8hiaC~{$<4Tl=D-}fKTAMi0{d1bR9h@BId4GAHiS) zWcCWU=#ZQY;Btb-FTTnEoQ8itBX3d_N-&3Zj?cDpybZ46gy|&;okkThM?tjtNz7R} z`(v1LykcJtMd>)$k7xTj7`eb^2`6Ks>p(Gr6lHR78K8O;%G|WjN;V%{!d0Y?gDfZD zRshVb=qAth@YS}5xUM*@zB$Frsm1bE5v!0S8zh+|JH$y+z{*zhW+3qT&6?PA=XxJs zrtyBr_uPwRgK??Y_!ZX|3rkHTQIybSaI-+&bq)q;^a&&W)G z=hphIXOq@|zGZ4Bp+a*dNz;GfMH3?d7chj{63V3X*kIKUK7;fPsu;=C$k*GZ-_A`y zam=1Gn-72z8|DZeru|1E9MWQrgFn)>+tFWa6Oo&6n?y$CCcv!$wLTz9gFOh)3KI0X zK{_3xRBi&qMzl>&^dSylR=9G5YE;DBWD><0s<|N9%}3eI&tj0HE#?H5kZJ;&Nl;bn z8Y&`!<#$2Ka7M5GUW_{Y9E!^T1i6SSQa|)TiO^jp7RNQ-cN_6uejbJZvm9j@pzSoH7dEBLMX-uemTe(mz;` z8*MSi%G%VI9f*E8wisEC$P+5zrzhvf%K|bg=Ue;B3h+1rNcYR@mB)EK+WkJq8^aj% zb?14(JTL-A@!njN?B-)J+%PAGo8Ic;tbj~kF4u9)de_gy55*tAUi71{R@xEW*rR?f zhkGk7P`?1qLF~`MVHjd#99m=3#_sBb!y?>~`&9Pnwj*ihcn-$@1CHNoLT{W7an7I+ zejXo%>TEx}L)Uf}&V>m}`cN_~De!5!Z?GRsUI11RVIriJFQ6W*BjWms+0{^Sp87qM zy!qogrj)nF8$2Z*AI~rTunX)7wCyden^m0^ei3hhdSy{I{4-WW!cG4XODh^Wp3Z>H zN1VGkcTU?sZ-?uDwQcGd{zv;AZT&9spgB8{!Nm0cxo!PtsJOpkK*DvOE5}Re*F$~o z0xy*fmUCFyU<_Yl2!8qv?0f92g>9_}jRjhewWIA+W1YRIt)CV>x$1Mwo8g2+b$yh~ zy7sz}%0*VJ@K5NZH;T~baxfzs{zZNZLlXYYdHx5V!#mNc#^?ciLNRd!X|c z7<4%|SQmuplL5GyJ>i$wly)eN<(l&7S2X3cJ2BI5^$rwqh8kgz?yjnDK#iWz!?43I zF|ukzzAd>kEqjqfv#R_{oB`$a<<$3p^%|uz#x9LE? zo<}p85gMFYA@%ub>aXx8`Ah1LBcQDOAmfW@n)-u>NDOyGoX55gMsH2-_mO*4r;u-u zg~mrviUW{o4*yBKgW5b)By%dOZ`y%LZwKcLdNC7G&$1E)3N0M5USwsFsi($eWc-x4 z%cB(ey|tSW^ib!FIl-=274m5mc#cHplEs&->r$MOPUo?JfM6=jG;arKjZYy>Ri#J# zjMs|4oVAi|#2NixHZv)?w{a%+2Ci9nqDkp`(nu?G%Z`p4X|cDUciLd7Q0X-m-$K1- z8G!yoG6f}N`LU7dqE)CbABl6E5eD-$UtG9Gp}O9OcoBAnefe#=j5WsdGZX{;eSp5bdIo?gjlHR(b(EC`smH}qy`4)t9~TVLq2*K2(}YH zz;m>UCb{&4VH`fsRELlVg`l2}tY#E2GLWh>(zg_2u6aLY-_nJiU=o84UTP5RRhTYu z+sMJpUL((%4MFMXiGw$YT#StBOLE~iFb@KWYqs{Q&7B=E@W2@4j?f|!G3%|%hyb&M zfoZK6sFpgZ9 zCVVLMmhjV#QzN2DJ)EH+^KfR8YXZTr-{_!(VB#q0s@GtlvC?<*O(m0EE)SLmmQ4;! ztuN0Lj8h&gmJ~X1XjBCJ;=Ikp!7UoRM z-i$KkRalB0$Zo=kua=2UaQWkqk7aIg35c9!1xElLW-i!Zl}&>0liZ43HZ8Wj$KeCh z0D&jQ2j0!Kn8Ewiu1D&VW&i%aKa+G~morJv^KKosXOi-=haZsjB6d+--5+GaBEFzA zTWL;0d>Lg4njW~wSdiI*q}KXV`*M;M%myTEGdBbEN>aaNi$+KxXdzc_DHZ-5+sahm zLUcB>g?q)DH>R}`|J^nM!6ENP)%o26kOF=7wsO#FJ4uZ$EFqZ9sE{q8*UD7$0L zz1p8pCo3=AyO5V}jpRvm0(c)V#o!CznQX<6r?Tm9!1Ktu9GChki;S;wU;Q>5n=yp2 zFCUzO@p`2`_nP27p?DfXqpeHT7ifPl1}dw!?C?cDq3@GY+`jA+d=bz(=w^?19ljqV zOk~3E0)G^I!O+-)IY_28Xl5WJZ3i-mS0HK6-bYoQWYRPei)?bO0|kvBQ$pHaIo;^I z(1l2Jd>|*nSK7!#-^0tPa1*M*04@Egp|HuhvyoV|zt2REe$M{(7~0p{7 zs>+o3^X!4^F3(@mU;jX@(@><1>)YjSMkh}gtmF@wrq$(7+95;vgFh3ddUk11Z#EAurY3H`&>FeBFG_MKqQ3sVMg14 zpZ%K)W&sw>!BOoK+k^hfdx-6M&4XC;C#V_z6d%1+sPBHpmB~${syO=J4_E;cw-KY5 zz@1Lc4ewg>e!jE5fdmL6twM?kA3#!n^_+b8ARd%|7j46#;Jk!aJOB^EMXxjuG1ELz zag)?WQm8lBJb(?j6QT%^FsuQBuT{@sluWNnDw(Xl*4{If!b$lTf6LB6kB1(3u!3O@ zWOL}w$+e5*hHB0h(|z)Rte&po~` z#tXR_dtA|%Xh+AKHsJ*SOBQ!klQ!r$>h9RjeIZ^ae(na0Bg5Fgbg$xkv?>TE_H&mp zg8OYJ*H)BFRsT=?+$&DGFtxvI1l~+A5V~A%R=>dkssz zR;UU;W2(nr4%IVk>YG?~Qt}c?8A<7;buksXWyeYxwgNE<=tx6?!@^Yvf5i_d0}J8b ziKk3s#4Y*=)lGk-x)Cg*jN}efHz^_6BfDqoR|4x)GxawS`GB7njn8I$cTnQU5FbWA z2BCzKAEMD&=6Orj;|vdHTj#nxB6~lInCKzdaK}o$GKf2y&Kn6rv^jD0$~(**fAkMh z&lf~`|2}@GzHwNzj={Z1m|Bl!poQbtM7I7m9p@+UHFXGcoQO)&Q`z2y&y}j+aKny-VP|E;^ric$JeS^s7zh^9YvR4?!2>^JvK! z?yBs$3&nEvXJD`cnA+AFS?_Q!PK?lB6Mv^C#I|OL*52{HJPCJR3Abh|m2`#@UX8&u zVE9vKoOj@%zA1$XeJ7LX@0_Zh3=;c6G`gXj$%XsjK{kRo?@ja!S7(g?pCA}v(ciml zS(jIHO|V0%)uK(h$tI~%B^ElGjo+Zn7Aacew|pWWqAU@a8?r?ESN8A162TO{9)-f+ zp<<+`!6+C%mOSiHz>)~45vh5Mvg%+bNjZ^mH-)%me13b1U>hivfR}-~_mvkb_32nL zY{N^xM;FIZesDAqx7_go4CMWu{dAfF>3swR#}P#PR4l>xkYb_X-LuWL7%1*TUdOLl z*@A7#t(*!Un(hjb@zCrhO=p-5`*EKt*BdUZ>YV_T^T6 z7X5=}N3=PZ+!o`1eL{Zb6gx>~iro~Q;`S70ibaq+7&@tF?Yg3T zGJ-N&6m-Z}`S9<~R+o?namW^ryEBMpQr=F=JIZyED;;U7|m|-CH z!qgGS@F)4HBv42=Jy%y+d}Dk)B9XdT{}KSd#kH&V?}8^TU*j=Mc8h>Z=&n_2U7#EN z;u)D^@%;jU=kSlHsCq|PmSoJw@pk1ARTnr+mDR%_H5ESn;3R=Sg^_2)ZO7-gI<$S@ z&a^$G$F%hLmwQ%g#yI};)Q%(NK`in9pmP)fj8zWP&TW_R20TYT4YXD(Bx50=&=>3V z8R%N&4Cjn3ZbDjBS=D)oWTtH9=~!R)CM3#N=b>MZv0u%@u-w2NV7ANpBNT~hpv4S` zUpUp24*!goOKiv9>g=q9b?nQjYk-lw;I`sQUQ+2VsN^*_u>SoRk>Ej<_4e}S9~H|v zFG_jdAEhr+?XRdtZt)@1>8*jE1UL9Fo;3_-pG1l2_w0e0{4z}aF?t8f>~*-#-5Qtv-!5row(2ozLX1!1vhkOoY)?^GtO~Ccjim^w$Pn< z4c&PRc5g8^$uB2xCkf`6iW?cj_5kkZ3?_s6#wrP+!FYK%6W4(XD1TC8xhLFU+awU0 z61eYRLx=}Y8w%_fK%>A)<++39V(p7~EY2+!uYWfNTOKG4l;)KNgTHYxi}PS787!B* zQdv}YoHtrPGPNsMsia09gxNHlcwceI<-#>O=5tY5EH!6x2sDV;2sy)UVU3Q718j`_ ziFWw4I|NgawuZ_JiwnnxO!%BdrA5VI6}KNlDfFZ`w3)u+#ksFLd(ECu${Pj2>RTjU zrUR)f(C>B7j{su40sNhUhqLk5i)a3$9P<}Ynm-XfJIAdQoonqL6msZoq`(hM!22a? z^W@!@&}9`iOw94aKFleNeP&1sygc=0q{rYqp!+Vek_to5ArXWh_jWWH$1UuKW&`s; zGa~i#6JFj8SO}$j1T;z~2{h#9dW!izFI)f6fOkPITmJ&S4EL-rn1N5o39l7SSVHMJ znv?o?@78VE z1dgxYM&K)^Whl5g%^eGV%?!+^XikUe=uX1F6Y2>g)Vosu_h-OC<3ORusi|YJS3%49 z6^owy<-oC+++Ly)RRtGnd08>zjc8S$2SuBE9d?EU?&%fuJh4jf`7#J=Ynw--ebLAs zg@6)XJ{Q$5;Z&Pc<JIh-bU0K~mDD8EwGCwJv!}0#gaWs!Y6<2c!5_lv@*jG5OzsE;kbyZGC zAc)Z8Sh#8ORsE^+mQwl5^Ixsk7WE8YT^BvMpA_&zE?9U7|u z;SW$myl2?laQXo!PJaX#^pF4!t}yX)tel?+nFT#vK>W6gci7pA)~Nrz{7U%?U3Ls(3M z@-W8@%A>=3%3@<33R(kRH{L&;b#k%;GPMzu*4-4(U@|tAPNJxwGqs1Xm`_t|tk

  • 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

    QqkZr0+Rtc9`DNO>os?!}ays^n4w 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%0DE!C$}& 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�rTnd%^ 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 z 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 Pxm9N|{{QFyISTwQ^~bi?

    +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%0Afc6LAPA%*sQ{kbx)<5&Mj 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 Q>2RG)~q=r5@m(OcVZy6#GC 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 z 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