diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj index c7dca49..3bcdaa1 100644 --- a/jRandomSkills - SRC Files/jRandomSkills.csproj +++ b/jRandomSkills - SRC Files/jRandomSkills.csproj @@ -15,9 +15,9 @@ - + - + diff --git a/jRandomSkills - SRC Files/src/command/Command.cs b/jRandomSkills - SRC Files/src/command/Command.cs index 32bac6f..b88aec7 100644 --- a/jRandomSkills - SRC Files/src/command/Command.cs +++ b/jRandomSkills - SRC Files/src/command/Command.cs @@ -42,6 +42,7 @@ namespace src.command { SplitCommands(config.NormalCommands.HealCommand.Alias), ("Heal", Command_Heal) }, { SplitCommands(config.NormalCommands.HealthCommand.Alias), ("Set heath", Command_Health) }, { SplitCommands(config.NormalCommands.PlantedBomb.Alias), ("Spawn planted bomb", Command_PlantedBomb) }, + { SplitCommands(config.NormalCommands.BotPlace.Alias), ("Place bot on your position", Command_BotPlace) }, { SplitCommands(config.NormalCommands.HudCommand.Alias), ("Enable/Disable HUD", Command_HUD) }, { SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) }, { SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) }, @@ -337,7 +338,7 @@ namespace src.command if (int.TryParse(command.GetArg(1), out int health)) SkillUtils.AddHealth(pawn, health - pawn.Health, health); - player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("healed")}"); + player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("set_health")}"); } [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] @@ -358,7 +359,38 @@ namespace src.command if (!int.TryParse(command.GetArg(1), out int time)) time = 40; - bomb.C4Blow = (float)Server.EngineTime + time; + bomb.C4Blow = Server.CurrentTime + time; + player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("planted_bomb_spawned", [time])}"); + } + + [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] + private static void Command_BotPlace(CCSPlayerController? player, CommandInfo command) + { + Debug.WriteToDebug($"Player {player?.PlayerName} used the css_bot_place {command.ArgString} command."); + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; + 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 (!int.TryParse(command.GetArg(1), out int botSlot)) + botSlot = -1; + + var bot = Utilities.GetPlayers().Where(p => p != null && p.IsValid && p.IsBot && p.PawnIsAlive && (botSlot == -1 || p.Slot == botSlot)).FirstOrDefault(); + if (bot == null || bot.PlayerPawn.Value == null || !bot.PlayerPawn.Value.IsValid) + { + player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("bot_placed_not_found")}"); + return; + } + + bot.PlayerPawn.Value.Teleport(new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z), new QAngle(pawn.AbsRotation.X, pawn.AbsRotation.Y, pawn.AbsRotation.Z), Vector.Zero); + + bot.PlayerPawn.Value.TakesDamage = true; + if ((bool.TryParse(command.GetArg(2), out bool godmode) && godmode == true) + || (int.TryParse(command.GetArg(2), out int godmodeInt) && godmodeInt == 1)) + bot.PlayerPawn.Value.TakesDamage = false; + + player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("bot_placed")}"); } [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index 3274761..26b74d7 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -118,8 +118,8 @@ namespace src public Skills SpecialSkill { get; set; } public float? SkillChance { get; set; } public bool IsDrawing { get; set; } - public DateTime SkillHudExpired { get; set; } - public DateTime SkillDescriptionHudExpired { get; set; } + public DateTime SkillHudExpired { get; set; } = Config.LoadedConfig.SkillHudDuration == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(Config.LoadedConfig.SkillHudDuration); + public DateTime SkillDescriptionHudExpired { get; set; } = Config.LoadedConfig.SkillDescriptionDuration == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); public string? PrintHTML { get; set; } public bool DisplayHUD { get; set; } public bool SkillUsed = false; diff --git a/jRandomSkills - SRC Files/src/player/ISkill.cs b/jRandomSkills - SRC Files/src/player/ISkill.cs index b6ff606..bcb9206 100644 --- a/jRandomSkills - SRC Files/src/player/ISkill.cs +++ b/jRandomSkills - SRC Files/src/player/ISkill.cs @@ -32,6 +32,7 @@ public interface ISkill public static void GrenadeThrown(EventGrenadeThrown _) { } public static void BombBeginplant(EventBombBeginplant _) { } + public static void BombAbortplant(EventBombAbortplant _) { } public static void BombPlanted(EventBombPlanted _) { } public static void BombBegindefuse(EventBombBegindefuse _) { } @@ -121,6 +122,7 @@ public enum Skills Magneto, Magnifier, Medic, + Miner, MoneySwap, Muhammed, Ninja, diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index 2718ecc..0085c12 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -8,6 +8,9 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; +using CS2TraceRay.Class; +using CS2TraceRay.Enum; +using CS2TraceRay.Struct; using src.player.skills; using src.utils; using System.Collections.Concurrent; @@ -58,6 +61,7 @@ namespace src.player Instance.RegisterEventHandler(GrenadeThrown); Instance.RegisterEventHandler(BombBeginplant); + Instance.RegisterEventHandler(BombAbortplant); Instance.RegisterEventHandler(BombPlanted); Instance.RegisterEventHandler(BombBegindefuse); @@ -82,9 +86,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerMakeSound", [um]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "PlayerMakeSound", [um]); return HookResult.Continue; } } @@ -93,9 +101,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponFire", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "WeaponFire", [@event]); return HookResult.Continue; } } @@ -104,9 +116,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponEquip", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "WeaponEquip", [@event]); return HookResult.Continue; } } @@ -115,9 +131,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponPickup", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "WeaponPickup", [@event]); return HookResult.Continue; } } @@ -126,9 +146,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "WeaponReload", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "WeaponReload", [@event]); return HookResult.Continue; } } @@ -137,9 +161,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "GrenadeThrown", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "GrenadeThrown", [@event]); return HookResult.Continue; } } @@ -148,9 +176,28 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "BombBeginplant", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "BombBeginplant", [@event]); + return HookResult.Continue; + } + } + + private static HookResult BombAbortplant(EventBombAbortplant @event, GameEventInfo info) + { + lock (setLock) + { + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "BombAbortplant", [@event]); return HookResult.Continue; } } @@ -159,9 +206,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "BombPlanted", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "BombPlanted", [@event]); return HookResult.Continue; } } @@ -170,9 +221,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "BombBegindefuse", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "BombBegindefuse", [@event]); return HookResult.Continue; } } @@ -181,9 +236,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyStarted", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "DecoyStarted", [@event]); return HookResult.Continue; } } @@ -192,9 +251,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "DecoyDetonate", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "DecoyDetonate", [@event]); return HookResult.Continue; } } @@ -203,9 +266,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeDetonate", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "SmokegrenadeDetonate", [@event]); return HookResult.Continue; } } @@ -214,9 +281,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "SmokegrenadeExpired", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "SmokegrenadeExpired", [@event]); return HookResult.Continue; } } @@ -225,9 +296,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerHurt", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "PlayerHurt", [@event]); return HookResult.Continue; } } @@ -236,9 +311,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerJump", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "PlayerJump", [@event]); return HookResult.Continue; } } @@ -247,9 +326,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerBlind", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "PlayerBlind", [@event]); return HookResult.Continue; } } @@ -258,9 +341,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "OnTakeDamage", [h]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "OnTakeDamage", [h]); return HookResult.Continue; } } @@ -272,9 +359,13 @@ namespace src.player CBaseTrigger trigger = hook.GetParam(0); CBaseEntity entity = hook.GetParam(1); - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "OnTriggerEnter", [trigger, entity]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "OnTriggerEnter", [trigger, entity]); return HookResult.Continue; } } @@ -286,9 +377,13 @@ namespace src.player CBaseTrigger trigger = hook.GetParam(0); CBaseEntity entity = hook.GetParam(1); - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "OnTriggerExit", [trigger, entity]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "OnTriggerExit", [trigger, entity]); return HookResult.Continue; } } @@ -297,12 +392,18 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - if (SkillsInfo.GetValue(playerSkill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) - return; + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill) + .Distinct() + .OrderBy(skill => skill.ToString() == "AreaReaper") + .ThenBy(skill => skill.ToString() == "ChillOut"); + + foreach (var skill in activeSkills) + if (SkillsInfo.GetValue(skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) + continue; else - Instance.SkillAction(playerSkill.Skill.ToString(), "OnTick"); + Instance.SkillAction(skill.ToString(), "OnTick"); } } @@ -528,9 +629,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "PlayerDeath", [@event]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "PlayerDeath", [@event]); var victim = @event.Userid; var attacker = @event.Attacker; @@ -562,28 +667,48 @@ namespace src.player private static void CheckUseSkill(CCSPlayerController player, PlayerButtons pressed, PlayerButtons released) { + if (player == null || !player.IsValid || !player.PawnIsAlive) return; + lock (setLock) { string? button = Config.LoadedConfig.AlternativeSkillButton; if (string.IsNullOrEmpty(button) || button.Length < 2) return; + string buttonName = $"{char.ToUpper(button[0])}{button[1..].ToLower()}"; + if (!Enum.TryParse(buttonName, out var skillButton)) return; - if (Enum.TryParse(buttonName, out var skillButton)) - { - if (pressed != skillButton) return; - } - else return; + if ((pressed & skillButton) == 0) return; - if (player == null) return; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null || playerInfo.IsDrawing) return; if (SkillsInfo.GetValue(playerInfo.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) return; - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; - if (!player.IsValid || !player.PawnIsAlive) return; + if (skillButton == PlayerButtons.Use) + { + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + if (pawn.AbsOrigin == null || pawn.AbsRotation == null) return; + + if (pawn.IsDefusing) return; + + Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); + Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * 80; + + ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | (ulong)(Contents.Solid | Contents.Hitbox | Contents.Pickup | Contents.TouchAll | Contents.CarriedObject | Contents.CarriedWeapon | Contents.Debris); + ulong contents = 0; + CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); + + if (trace.DidHit()) + { + var entity = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity; + if (entity == null || !entity.IsValid) return; + + string designer = entity.DesignerName; + if (designer.Contains("door") || designer.Contains("button") || designer.Contains("weapon") || designer.Contains("blocker")) return; + } + } Debug.WriteToDebug($"Player {player.PlayerName} used the skill: {playerInfo.Skill} by PlayerButtons: {pressed}"); Instance.SkillAction(playerInfo.Skill.ToString(), "UseSkill", [player]); @@ -594,9 +719,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "OnEntitySpawned", [entity]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "OnEntitySpawned", [entity]); } } @@ -722,8 +851,12 @@ namespace src.player }); Debug.WriteToDebug($"Player {skillPlayer.PlayerName} has got the skill \"{player.GetSkillName(randomSkill.Skill)}\"."); - skillPlayer.SkillHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillHudDuration); - skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); + + float hudExpired = Config.LoadedConfig.SkillHudDuration; + skillPlayer.SkillHudExpired = hudExpired == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(hudExpired); + + float descriptionHudExpired = Config.LoadedConfig.SkillHudDuration; + skillPlayer.SkillDescriptionHudExpired = descriptionHudExpired == -1 ? DateTime.MaxValue : DateTime.Now.AddSeconds(descriptionHudExpired); if (Config.LoadedConfig.TeamMateSkillChatInfo) { @@ -859,9 +992,13 @@ namespace src.player { lock (setLock) { - foreach (var playerSkill in Instance.SkillPlayer) - if (!playerSkill.IsDrawing) - Instance.SkillAction(playerSkill.Skill.ToString(), "CheckTransmit", [infoList]); + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + foreach (string skillName in activeSkills) + Instance.SkillAction(skillName, "CheckTransmit", [infoList]); } } diff --git a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs index 0412210..4bfd430 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs @@ -121,6 +121,7 @@ namespace src.player if (string.IsNullOrEmpty(skillLine)) return; if (player == null || !player.IsValid) return; if (SkillUtils.HasMenu(player)) return; + Event.UpdateSkillHUD(player, infoLine, skillLine, remainingLine, isDescription); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs index 932c7d5..d38d39f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs @@ -31,7 +31,12 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + { UpdateHUD(player, skillInfo); + + if (skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue(skillName, "duration")) > DateTime.Now) + LookAtEnemey(player); + } } } @@ -100,7 +105,7 @@ namespace src.player.skills 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) return; + if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) continue; double dist = SkillUtils.GetDistance(enemyPawn.AbsOrigin, pawn.AbsOrigin); if (dist < minDist) @@ -112,11 +117,13 @@ namespace src.player.skills if (closetEnemy != null) { - Vector enemyPos = closetEnemy.PlayerPawn.Value!.AbsOrigin!; - Vector myPos = pawn.AbsOrigin; + var enemyPawn = closetEnemy.PlayerPawn.Value; + if (enemyPawn == null || enemyPawn.AbsOrigin == null) return; + Vector myEyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); + Vector enemyEyePos = new(enemyPawn.AbsOrigin.X, enemyPawn.AbsOrigin.Y, enemyPawn.AbsOrigin.Z + enemyPawn.ViewOffset.Z + SkillsInfo.GetValue(skillName, "offsetZ")); - Vector direction = enemyPos - myPos; + Vector direction = enemyEyePos - myEyePos; QAngle angle = VectorToAngle(direction); pawn.Look(angle); @@ -138,9 +145,11 @@ namespace src.player.skills public DateTime Cooldown { get; set; } } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 20f, float duration = .3f, float offsetZ = 0) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public float Cooldown { get; set; } = cooldown; + public float Duration { get; set; } = duration; + public float Offset { get; set; } = offsetZ; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs index 588ed2d..12a50af 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AreaReaper.cs @@ -1,8 +1,8 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; using src.utils; +using static src.jRandomSkills; namespace src.player.skills { @@ -21,7 +21,6 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); - Instance.AddTimer(0.1f, EnableBombsite); } public static void TypeSkill(CCSPlayerController player, string[] commands) @@ -44,7 +43,9 @@ namespace src.player.skills var bombTargets = Utilities.FindAllEntitiesByDesignerName("func_bomb_target").ToArray(); if (bombTargets.Length == 2) { - bombTargets[site].AcceptInput("Disable"); + bombTargets[site].BombPlantedHere = true; + Utilities.SetStateChanged(bombTargets[site], "CBombTarget", "m_bBombPlantedHere"); + playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("areareaper_site_disabled", (site == 0 ? 'A' : 'B'))}"); } @@ -63,16 +64,43 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SkillUtils.CloseMenu(player); - if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return; - EnableBombsite(); - + Server.NextWorldUpdate(() => + { + if (Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName) != null) return; + EnableBombsite(); + }); } private static void EnableBombsite() { var bombTargets = Utilities.FindAllEntitiesByDesignerName("func_bomb_target"); foreach (var bombTarget in bombTargets) - bombTarget.AcceptInput("Enable"); + { + 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; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill == null) continue; + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + + if (pawn.WeaponServices == null) continue; + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue; + + if (!pawn.InBombZone && pawn.InBombZoneTrigger) + player.PrintToCenterAlert(player.GetTranslation("areareaper_bombsite_disabled")); + } } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#edf5b5", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs index c9deaac..6850385 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ChillOut.cs @@ -2,6 +2,7 @@ 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 @@ -9,16 +10,38 @@ namespace src.player.skills public class ChillOut : ISkill { private const Skills skillName = Skills.ChillOut; + private static readonly ConcurrentDictionary plantingPlayers = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); } + public static void NewRound() + { + plantingPlayers.Clear(); + } + + public static void DisableSkill(CCSPlayerController player) + { + if (player == null || !player.IsValid) return; + plantingPlayers.TryRemove(player.SteamID, 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 _); + SkillUtils.ResetPrintHTML(user); + } + public static void BombBeginplant(EventBombBeginplant @event) { var player = @event.Userid; if (!Instance.IsPlayerValid(player)) return; + plantingPlayers.TryAdd(player!.SteamID, Server.CurrentTime); var anyChillOut = Instance.SkillPlayer.FirstOrDefault(p => p.Skill == skillName); if (anyChillOut != null) @@ -33,6 +56,42 @@ namespace src.player.skills } } + public static void BombPlanted(EventBombPlanted @event) + { + var player = @event.Userid; + if (!Instance.IsPlayerValid(player)) return; + plantingPlayers.TryRemove(player!.SteamID, out _); + SkillUtils.ResetPrintHTML(player); + } + + public static void OnTick() + { + float currentTime = Server.CurrentTime; + float extraTime = SkillsInfo.GetValue(skillName, "bombArmedTime"); + + foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist)) + { + if (!Instance.IsPlayerValid(player)) continue; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo == null) continue; + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + + if (pawn.WeaponServices == null) continue; + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue; + + if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime)) + { + float remaining = plantTime + extraTime - currentTime; + playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"{Math.Max(0, remaining):0.0}s")}"; + player.PrintToCenter(""); + } + } + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#343deb", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float bombArmedTime = 10f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public float BombArmedTime { get; set; } = bombArmedTime; diff --git a/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs b/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs index e427aff..9fa7317 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HomingNades.cs @@ -11,7 +11,7 @@ namespace src.player.skills public class HomingNades : ISkill { private const Skills skillName = Skills.HomingNades; - private readonly static ConcurrentDictionary nades = []; + private readonly static ConcurrentDictionary nades = []; public static void LoadSkill() { @@ -30,7 +30,7 @@ namespace src.player.skills foreach (var index in nades.Keys.ToList()) { if (!nades.TryGetValue(index, out var data)) continue; - (Vector oldPos, double createdTime) = data; + Vector oldPos = data; var nade = Utilities.GetEntityFromIndex((int)index); if (nade == null || !nade.IsValid || nade.AbsOrigin == null) @@ -43,14 +43,13 @@ namespace src.player.skills double distanceMoved = SkillUtils.GetDistance(currentPos, oldPos); Vector calculatedVelocity = CalculateVelocity(nade, nade.TeamNum); - Server.PrintToChatAll($"Dist: {distanceMoved}, vel: {calculatedVelocity}"); + bool isZero = calculatedVelocity.IsZero(); - if (distanceMoved < 4 || calculatedVelocity.IsZero()) + if (distanceMoved < 4 || isZero) { - Server.PrintToChatAll($"Short, {Server.TickedTime} -> {createdTime + 3}, {createdTime + 3 - Server.TickedTime}s"); - - nade.DetonateTime = (float)createdTime + 3; + nade.DetonateTime = isZero ? 0 : nade.CreateTime + 3; Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime"); + nades.TryRemove(index, out _); continue; } @@ -63,7 +62,7 @@ namespace src.player.skills if (speed > maxVelocity) newVelocity *= (maxVelocity / speed); - nades[index] = (currentPos, createdTime); + nades[index] = currentPos; nade.Teleport(null, null, newVelocity); } } @@ -84,9 +83,6 @@ namespace src.player.skills double dist = SkillUtils.GetDistance(nadePos, pawn.AbsOrigin); if (dist < SkillsInfo.GetValue(skillName, "detonationRange")) { - nade.DetonateTime = 0; - Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime"); - nades.TryRemove(nade.Index, out _); return Vector.Zero; } @@ -134,10 +130,15 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; - grenade.DetonateTime = (float)Server.TickedTime + 6; - Vector pos = new(grenade.AbsOrigin?.X, grenade.AbsOrigin?.Y, grenade.AbsOrigin?.Z); - nades.TryAdd(grenade.Index, (pos, Server.TickedTime)); + nades.TryAdd(grenade.Index, pos); + + Server.NextWorldUpdate(() => + { + if (grenade == null || !grenade.IsValid) return; + grenade.DetonateTime += 100f; + Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime"); + }); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Miner.cs b/jRandomSkills - SRC Files/src/player/skills/Miner.cs new file mode 100644 index 0000000..e39871e --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/Miner.cs @@ -0,0 +1,113 @@ +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 +{ + public class Miner : ISkill + { + private const Skills skillName = Skills.Miner; + private readonly static ConcurrentDictionary nades = []; + + public static void LoadSkill() + { + SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + } + + public static void NewRound() + { + nades.Clear(); + } + + public static void OnTick() + { + if (Server.TickCount % 10 != 0) return; + float detonationRange = SkillsInfo.GetValue(skillName, "detonationRange"); + float currentTime = Server.CurrentTime; + + foreach (var index in nades.Keys.ToList()) + { + var nade = Utilities.GetEntityFromIndex((int)index); + if (nade == null || !nade.IsValid || nade.AbsOrigin == null) + { + nades.TryRemove(index, out _); + continue; + } + + if (nade.CreateTime + 3 > currentTime) return; + Vector currentPos = new(nade.AbsOrigin.X, nade.AbsOrigin.Y, nade.AbsOrigin.Z); + + foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.TeamNum != nade.TeamNum)) + { + var enemyPawn = enemy.PlayerPawn.Value; + if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) continue; + + Vector enemyPos = new(enemyPawn.AbsOrigin.X, enemyPawn.AbsOrigin.Y, enemyPawn.AbsOrigin.Z); + double distance = SkillUtils.GetDistance(currentPos, enemyPos); + + if (distance <= detonationRange) + { + Detonate(nade); + nades.TryRemove(index, out _); + break; + } + } + } + } + + private static void Detonate(CBaseCSGrenadeProjectile grenade) + { + if (grenade == null || !grenade.IsValid || grenade.AbsOrigin == null) return; + + Vector position = grenade.AbsOrigin; + position.Z += 60; + grenade.Teleport(position); + + grenade.EmitSound("IncGrenade.Bounce_M"); + + grenade.DetonateTime = Server.CurrentTime + .5f; + Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime"); + } + + public static void OnEntitySpawned(CEntityInstance @event) + { + var name = @event.DesignerName; + if (name != "hegrenade_projectile") return; + + var grenade = @event.As(); + if (grenade == null || !grenade.IsValid) return; + + if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; + var pawn = grenade.OwnerEntity.Value.As(); + + 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); + if (playerInfo?.Skill != skillName) return; + + nades.TryAdd(grenade.Index, 0); + + Server.NextWorldUpdate(() => + { + if (grenade == null || !grenade.IsValid) return; + grenade.DetonateTime = float.MaxValue; + Utilities.SetStateChanged(grenade, "CBaseGrenade", "m_flDetonateTime"); + }); + } + + public static void EnableSkill(CCSPlayerController player) + { + SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade); + } + + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#adf542", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float detonationRange = 130) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + { + public float DetonationRange { get; set; } = detonationRange; + } + } +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs index a407a1d..a73459b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs @@ -1,7 +1,9 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; +using System.Collections.Concurrent; using static src.jRandomSkills; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; @@ -11,20 +13,37 @@ namespace src.player.skills { private const Skills skillName = Skills.Muhammed; private static readonly QAngle angle = new(10, -5, 9); + private static readonly ConcurrentDictionary nades = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); } + public static void NewRound() + { + nades.Clear(); + } + public static void PlayerDeath(EventPlayerDeath @event) { var player = @event.Userid; if (!IsDeadPlayerValid(player)) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); - if (playerInfo?.Skill == skillName) - SpawnExplosion(player!); + CsTeam lastTeam = player!.Team; + + Server.NextWorldUpdate(() => + { + + if (player == null || !player.IsValid || player.Team != lastTeam) return; + + 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); + if (playerInfo?.Skill == skillName) + SpawnExplosion(player!); + }); } private static void SpawnExplosion(CCSPlayerController player) @@ -32,7 +51,7 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - Vector pos = pawn.AbsOrigin; + Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); pos.Z += 10; SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum); @@ -44,6 +63,8 @@ namespace src.player.skills var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" }; var randomFile = fileNames[new Random().Next(fileNames.Length)]; player.ExecuteClientCommand($"play vo/agents/balkan/{randomFile}.vsnd"); + + nades.AddOrUpdate(Server.TickCount, player.TeamNum, (_, _) => player.TeamNum); } public static void OnEntitySpawned(CEntityInstance entity) @@ -53,6 +74,8 @@ namespace src.player.skills var heProjectile = entity.As(); if (heProjectile == null || !heProjectile.IsValid || heProjectile.AbsRotation == null) return; + int lastTick = Server.TickCount; + Server.NextFrame(() => { if (heProjectile == null || !heProjectile.IsValid) return; @@ -63,9 +86,37 @@ namespace src.player.skills heProjectile.Damage = SkillsInfo.GetValue(skillName, "explosionDamage"); heProjectile.DmgRadius = SkillsInfo.GetValue(skillName, "explosionRadius"); heProjectile.DetonateTime = 0; + + if (nades.TryRemove(lastTick, out byte teamNum)) + heProjectile.Globalname = $"muhammed_team_{teamNum}_{heProjectile.Index}"; }); } + public static void OnTakeDamage(DynamicHook h) + { + CEntityInstance param = h.GetParam(0); + CTakeDamageInfo param2 = h.GetParam(1); + + if (param == null || param.Entity == null || param2 == null) return; + + var nade = param2.Attacker.Value; + if (nade == null || !nade.IsValid) return; + + if (nade.DesignerName != "hegrenade_projectile") return; + if (string.IsNullOrEmpty(nade.Globalname) || !nade.Globalname.StartsWith("muhammed_team_")) return; + + if (!int.TryParse(nade.Globalname.Split('_')[2], out int nadeTeam)) return; + + CCSPlayerPawn victimPawn = new(param.Handle); + + if (victimPawn.DesignerName != "player") return; + if (victimPawn == null || victimPawn.Controller?.Value == null) return; + if (victimPawn.TeamNum != nadeTeam) return; + + float reduction = SkillsInfo.GetValue(skillName, "dmgReductionForTeamates"); + param2.Damage *= 1f - Math.Clamp(reduction, 0f, 1f); + } + private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a - b) < epsilon; private static bool IsDeadPlayerValid(CCSPlayerController? player) @@ -73,12 +124,11 @@ namespace src.player.skills return player != null && player.IsValid && player.PlayerPawn?.Value != null; } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#F5CB42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float explosionRadius = 500.0f, int explosionDamage = 999, float dmgReductionForTeamates = .5f, bool explosionAfterWorldDeath = true) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#F5CB42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float explosionRadius = 500.0f, int explosionDamage = 999, float dmgReductionForTeamates = .5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public float ExplosionRadius { get; set; } = explosionRadius; public int ExplosionDamage { get; set; } = explosionDamage; public float DmgReductionForTeamates { get; set; } = dmgReductionForTeamates; - public bool ExplosionAfterWorldDeath { get; set; } = explosionAfterWorldDeath; } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Planter.cs b/jRandomSkills - SRC Files/src/player/skills/Planter.cs index 06c9d16..1697e03 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Planter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Planter.cs @@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using src.utils; +using System.Collections.Concurrent; using static src.jRandomSkills; namespace src.player.skills @@ -10,42 +11,91 @@ namespace src.player.skills public class Planter : ISkill { private const Skills skillName = Skills.Planter; + private static readonly ConcurrentDictionary plantingPlayers = []; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); } + public static void BombBeginplant(EventBombBeginplant @event) + { + var user = @event.Userid; + if (user == null || !user.IsValid || !user.PawnIsAlive) return; + plantingPlayers.TryAdd(user.SteamID, Server.CurrentTime); + } + + public static void BombAbortplant(EventBombAbortplant @event) + { + var user = @event.Userid; + if (user == null || !user.IsValid || !user.PawnIsAlive) return; + plantingPlayers.TryRemove(user.SteamID, out _); + SkillUtils.ResetPrintHTML(user); + } + public static void BombPlanted(EventBombPlanted @event) { var player = @event.Userid; if (!Instance.IsPlayerValid(player)) return; + plantingPlayers.TryRemove(player!.SteamID, out _); var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); if (playerInfo?.Skill != skillName) return; + playerInfo.PrintHTML = null; var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + SkillsInfo.GetValue(skillName, "extraC4BlowTime")); + Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "extraC4BlowTime")); - player!.PrintToCenterAlert(player.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "extraC4BlowTime"))); + foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive)) + p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "extraC4BlowTime"))); + } + + public static void NewRound() + { + foreach (var player in Utilities.GetPlayers()) + DisableSkill(player); + plantingPlayers.Clear(); } public static void DisableSkill(CCSPlayerController player) { - if (!Instance.IsPlayerValid(player)) return; - Schema.SetSchemaValue(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", false); + if (player == null || !player.IsValid) return; + plantingPlayers.TryRemove(player.SteamID, out _); + SkillUtils.ResetPrintHTML(player); + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + + Schema.SetSchemaValue(pawn!.Handle, "CCSPlayerPawn", "m_bInBombZone", false); } public static void OnTick() { - foreach (var player in Utilities.GetPlayers()) + float currentTime = Server.CurrentTime; + foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist)) { if (!Instance.IsPlayerValid(player)) continue; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); - if (playerInfo?.Skill == skillName) - Schema.SetSchemaValue(player!.PlayerPawn.Value!.Handle, "CCSPlayerPawn", "m_bInBombZone", true); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) continue; + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + + if (pawn.WeaponServices == null) continue; + var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_c4") continue; + + pawn.InBombZone = true; + Schema.SetSchemaValue(pawn.Handle, "CCSPlayerPawn", "m_bInBombZone", true); + + if (plantingPlayers.TryGetValue(player.SteamID, out float plantTime)) + { + float remaining = plantTime + 3f - currentTime; + playerInfo.PrintHTML = $"{player.GetTranslation("planter_planting", $"{Math.Max(0, remaining):0.0}s")}"; + player.PrintToCenter(""); + } } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Shade.cs b/jRandomSkills - SRC Files/src/player/skills/Shade.cs index e2c3651..bd85b22 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Shade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Shade.cs @@ -61,6 +61,8 @@ namespace src.player.skills foreach (var item in noSpace) if (item.Value >= Server.TickCount) UpdateHUD(item.Key); + else + SkillUtils.ResetPrintHTML(item.Key); } private static void UpdateHUD(CCSPlayerController player) @@ -75,11 +77,40 @@ namespace src.player.skills var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return false; + Vector s = startPos + new Vector(0, 0, pawn.ViewOffset.Z / 2); + Vector e = endPos + new Vector(0, 0, pawn.ViewOffset.Z / 2); + ulong mask = pawn.Collision.CollisionAttribute.InteractsWith; ulong contents = pawn.Collision.CollisionGroup; CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player); - return !trace.HitWorld(out _); + if (trace.DidHit()) return false; + return IsPositionSafe(player, endPos); + } + + private static bool IsPositionSafe(CCSPlayerController player, Vector pos) + { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false; + + float footHeight = 0; + float headHeight = 70; + float innerDist = 12; + + ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; + ulong contents = playerPawn.Collision.CollisionGroup; + + Vector s1 = new(pos.X - innerDist, pos.Y - innerDist, pos.Z + footHeight); + Vector e1 = new(pos.X + innerDist, pos.Y + innerDist, pos.Z + headHeight); + CGameTrace t1 = TraceRay.TraceShape(s1, e1, mask, contents, player); + if (t1.DidHit() || t1.AllSolid) return false; + + Vector s2 = new(pos.X + innerDist, pos.Y - innerDist, pos.Z + footHeight); + Vector e2 = new(pos.X - innerDist, pos.Y + innerDist, pos.Z + headHeight); + CGameTrace t2 = TraceRay.TraceShape(s2, e2, mask, contents, player); + if (t2.DidHit() || t2.AllSolid) return false; + + return true; } private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim) @@ -89,22 +120,29 @@ namespace src.player.skills if (victimPawn == null || attackerPawn == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return; - QAngle victimAngles = victimPawn.AbsRotation; - Vector victimEyePos = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z + victimPawn.ViewOffset.Z); - int[] angles = [0, 90, -90]; + Vector victimPos = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z); + QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z); + float distance = SkillsInfo.GetValue(skillName, "teleportDistance"); + int[] angles = [0, 90, -90]; bool teleported = false; + foreach (int extraAngle in angles) { - QAngle newAngle = new(victimAngles.X, victimAngles.Y + extraAngle, victimAngles.Z); - Vector behindPosition = victimEyePos - SkillUtils.GetForwardVector(newAngle) * SkillsInfo.GetValue(skillName, "teleportDistance"); - if (!CheckTeleport(victim, victimEyePos, behindPosition)) continue; - attackerPawn.Teleport(behindPosition, newAngle, new(0, 0, 0)); - teleported = true; - break; + QAngle targetAngle = new(0, victimAngles.Y + extraAngle, 0); + Vector direction = SkillUtils.GetForwardVector(targetAngle); + Vector targetPos = victimPos - (direction * distance); + + if (CheckTeleport(victim, victimPos, targetPos)) + { + attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero); + teleported = true; + break; + } } + if (!teleported) - noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (k, v) => Server.TickCount + (64 * 2)); + noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (_, _) => Server.TickCount + (64 * 2)); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#4d4d4d", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float teleportDistance = 100f, float chanceFrom = .3f, float chanceTo = .45f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs index 32850e0..f553380 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs @@ -25,9 +25,10 @@ namespace src.player.skills var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = (float)Server.EngineTime + SkillsInfo.GetValue(skillName, "detonationTime")); + Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "detonationTime")); - player!.PrintToCenterAlert(player.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "detonationTime"))); + foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive)) + p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "detonationTime"))); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f5b74c", CsTeam onlyTeam = CsTeam.Terrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int detonationTime = 20) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs index 5bc203e..2a2a959 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs @@ -62,7 +62,6 @@ namespace src.player.skills return; } - Server.PrintToChatAll("Create Smoke"); SkillUtils.CreateSmokeGrenadeProjectile(pos, QAngle.Zero, Vector.Zero, player.TeamNum); }, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); diff --git a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs index b46feaa..68483ec 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs @@ -165,8 +165,7 @@ namespace src.player.skills weaponToGive = weapon_awp + "_script"; } - Server.NextFrame(() => - { + Instance.AddTimer(.15f, () => { if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) { var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As().GiveNamedItem(weaponToGive.Replace("_script", "")); @@ -190,7 +189,7 @@ namespace src.player.skills DeleteDroppedAWP(player); isProcessing.TryRemove(steamID, out _); - }); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } catch { isProcessing.TryRemove(steamID, out _); diff --git a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs index 897a362..79e0c29 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs @@ -30,8 +30,7 @@ namespace src.player.skills { if (bombPlanted) return; var name = entity.DesignerName; - if (!name.EndsWith("_projectile")) - return; + if (!name.EndsWith("_projectile")) return; var grenade = entity.As(); if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/utils/Config.cs b/jRandomSkills - SRC Files/src/utils/Config.cs index a8f559a..fecc86f 100644 --- a/jRandomSkills - SRC Files/src/utils/Config.cs +++ b/jRandomSkills - SRC Files/src/utils/Config.cs @@ -170,8 +170,9 @@ namespace src.utils SkillsListCommand = new NormalCommand("supermoc, skille, listamocy, supermoce, skills, listaHabilidades, habilidades, 技能列表, 超能力列表", "@jRandomSkills/admin"), UseSkillCommand = new NormalCommand("t, useSkill, usarHabilidade, 技能使用, 使用技能", "@jRandomSkills/admin"), HealCommand = new NormalCommand("heal, ulecz, curar, tratar, 治疗, 治愈", "@jRandomSkills/admin"), - HealthCommand = new NormalCommand("sethealth, health", "@jRandomSkills/admin"), - PlantedBomb = new NormalCommand("plantedbomb, bomb", "@jRandomSkills/admin"), + HealthCommand = new NormalCommand("sethealth, set_health, health", "@jRandomSkills/admin"), + PlantedBomb = new NormalCommand("plantedbomb, planted_bomb, bomb", "@jRandomSkills/admin"), + BotPlace = new NormalCommand("botplace, bot_place", "@jRandomSkills/admin"), ConsoleCommand = new NormalCommand("console, sv, 控制台, 服务器", "@jRandomSkills/owner"), HudCommand = new NormalCommand("hud, hood", ""), SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"), @@ -250,6 +251,7 @@ namespace src.utils public required NormalCommand HealCommand { get; set; } public required NormalCommand HealthCommand { get; set; } public required NormalCommand PlantedBomb { get; set; } + public required NormalCommand BotPlace { get; set; } public required NormalCommand ConsoleCommand { get; set; } public required NormalCommand HudCommand { get; set; } public required NormalCommand SetStaticSkillCommand { get; set; } diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll index 346afb5..01695fd 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/MaxMind.Db.dll differ diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll index 3ee78b0..0a2ba24 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll differ diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll index 8cc9a7a..f647514 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll differ