diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj index 3bcdaa1..0953faa 100644 --- a/jRandomSkills - SRC Files/jRandomSkills.csproj +++ b/jRandomSkills - SRC Files/jRandomSkills.csproj @@ -15,14 +15,19 @@ - - + - + + + libs/RayTraceApi.dll + + + + diff --git a/jRandomSkills - SRC Files/libs/RayTraceApi.dll b/jRandomSkills - SRC Files/libs/RayTraceApi.dll new file mode 100644 index 0000000..584aea0 Binary files /dev/null and b/jRandomSkills - SRC Files/libs/RayTraceApi.dll differ diff --git a/jRandomSkills - SRC Files/src/command/Command.cs b/jRandomSkills - SRC Files/src/command/Command.cs index b88aec7..6c6da80 100644 --- a/jRandomSkills - SRC Files/src/command/Command.cs +++ b/jRandomSkills - SRC Files/src/command/Command.cs @@ -17,6 +17,7 @@ namespace src.command private static bool gamePaused = false; private static Config.SettingsModel config = Config.LoadedConfig; private static readonly ConcurrentDictionary oldCommands = []; + private static readonly ConcurrentDictionary nextSkill = []; private static readonly object setLock = new(); public static void Load() @@ -47,6 +48,7 @@ namespace src.command { SplitCommands(config.NormalCommands.SetStaticSkillCommand.Alias), ("Set static skill", Command_SetStaticSkill) }, { SplitCommands(config.NormalCommands.ChangeLanguageCommand.Alias), ("Change language", Command_ChangeLanguage) }, { SplitCommands(config.NormalCommands.ReloadCommand.Alias), ("Reaload configs", Command_Reload) }, + { SplitCommands(config.NormalCommands.NextCommand.Alias), ("Next skill", Command_Next) }, { SplitCommands(config.VotingCommands.ChangeMapCommand.Alias), ("Change map", Command_ChangeMap) }, { SplitCommands(config.VotingCommands.StartGameCommand.Alias), ("Start game", Command_StartGame) }, @@ -142,7 +144,7 @@ namespace src.command { Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [targetPlayer]); skillPlayer.Skill = skill.Skill; - skillPlayer.SpecialSkill = src.player.Skills.None; + skillPlayer.SpecialSkill = Skills.None; Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [targetPlayer]); skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); @@ -337,7 +339,7 @@ namespace src.command var pawn = player.PlayerPawn.Value; if (int.TryParse(command.GetArg(1), out int health)) SkillUtils.AddHealth(pawn, health - pawn.Health, health); - + player.PrintToChat($" {ChatColors.Green}{player.GetTranslation("set_health")}"); } @@ -578,5 +580,48 @@ namespace src.command } } } + + [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] + private static void Command_Next(CCSPlayerController? player, CommandInfo command) + { + if (player == null || !player.IsValid) return; + + Debug.WriteToDebug($"Player {player.PlayerName} used the css_next {command.ArgString} command."); + if (!string.IsNullOrEmpty(config.NormalCommands.NextCommand.Permissions) && !AdminManager.PlayerHasPermissions(player, config.NormalCommands.NextCommand.Permissions)) return; + + var skillsList = SkillData.Skills.OrderBy(s => s.Skill.ToString()).ToList(); + if (skillsList.Count == 0) return; + + nextSkill.TryGetValue(player.Index, out int currentIndex); + + int nextIndex = (currentIndex + 1) % skillsList.Count; + + string arg = command.GetArg(1); + if (!string.IsNullOrEmpty(arg)) + { + if (arg == "-1") + nextIndex--; + else + nextIndex = int.Parse(arg); + } + + var skill = skillsList[nextIndex]; + player.PrintToChat(nextIndex.ToString()); + + var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (skillPlayer == null) return; + + Instance.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]); + skillPlayer.Skill = skill.Skill; + skillPlayer.SpecialSkill = Skills.None; + + nextSkill[player.Index] = nextIndex; + + Instance.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); + skillPlayer.SkillDescriptionHudExpired = DateTime.Now.AddSeconds(Config.LoadedConfig.SkillDescriptionDuration); + + if (skill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", border: "b"); + } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json b/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json index 713f6f8..7c8be60 100644 --- a/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json +++ b/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json @@ -16,15 +16,22 @@ "Shoot_Secondary": { "signatures": { "library": "server", - "windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2", - "linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65" + "windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA", + "linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 54 41 89 F4 53 48 8B 07 48 89 FB 48 8B 80 ? ? ? ? 48 39 D0 0F 85" } }, "SnapViewAngles": { "signatures": { "library": "server", "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55", - "linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 89 F7 48 81 EC ? ? ? ? E8 ? ? ? ? 48 8B 93" + "linux": "55 48 89 E5 41 57 49 89 FF 48 89 F7 41 56 41 55 41 54 53 48 81 EC" + } + }, + "CCSPlayerController_HandleCommandDrop": { + "signatures": { + "library": "server", + "windows": "48 89 5C 24 ? 57 48 83 EC ? 48 8B FA E8 ? ? ? ? 48 8B D8", + "linux": "55 48 89 E5 41 54 49 89 F4 53 E8 ? ? ? ? 48 85 C0 74 ? 48 89 C3" } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index 0fd62d4..6c3679e 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.b7"; + public override string ModuleVersion => "1.2.1.b8"; public override void Load(bool hotReload) { @@ -213,8 +213,9 @@ namespace src { "WASDMenuAPI", "./WASDMenuAPI.dll" }, { "MaxMind", "./MaxMind.Db.dll" }, { "GeoLite2", "./packages/GeoLite2-Country.mmdb" }, - { "CS2TraceRay", "./../../shared/CS2TraceRay/CS2TraceRay.dll" }, - { "CS2TraceRay gamedata", "./../../gamedata/CS2TraceRay.gamedata.json" }, + { "RayTraceApi", "./../../shared/RayTraceApi/RayTraceApi.dll" }, + { "RayTraceImpl", "./../../plugins/RayTraceImpl/RayTraceImpl.dll" }, + { "RayTrace MetaMod", "./../../../metamod/RayTrace.vdf" }, { "jRandomSkills gamedata", "./../../gamedata/jRandomSkills.gamedata.json" } }; @@ -263,7 +264,7 @@ namespace src private static async Task GetLatestVersion() { - using HttpClient client = new HttpClient(); + using HttpClient client = new(); client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("jRandomSkills", "1.0")); const string URL = "https://api.github.com/repos/Juzlus/jRandomSkills/releases/latest"; diff --git a/jRandomSkills - SRC Files/src/player/ISkill.cs b/jRandomSkills - SRC Files/src/player/ISkill.cs index 0dd186c..5e09f91 100644 --- a/jRandomSkills - SRC Files/src/player/ISkill.cs +++ b/jRandomSkills - SRC Files/src/player/ISkill.cs @@ -29,7 +29,9 @@ public interface ISkill public static void WeaponEquip(EventItemEquip _) { } public static void WeaponPickup(EventItemPickup _) { } public static void WeaponReload(EventWeaponReload _) { } + public static bool WeaponDrop(DynamicHook _, CCSPlayerController __) { return false; } public static void GrenadeThrown(EventGrenadeThrown _) { } + public static void BulletImpact(EventBulletImpact _) { } public static void BombBeginplant(EventBombBeginplant _) { } public static void BombAbortplant(EventBombAbortplant _) { } @@ -146,7 +148,6 @@ public enum Skills RadarHack, Rambo, RandomWeapon, - RCMelon, ReZombie, ReactiveArmor, Regeneration, diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index 6c727e9..9367d3a 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -2,15 +2,14 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Admin; +using CounterStrikeSharp.API.Modules.Commands; 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 CS2TraceRay.Class; -using CS2TraceRay.Enum; -using CS2TraceRay.Struct; +using RayTraceAPI; using src.player.skills; using src.utils; using System.Collections.Concurrent; @@ -40,6 +39,8 @@ namespace src.player public static readonly ConcurrentDictionary staticSkills = []; private static readonly object setLock = new(); + private static readonly MemoryFunctionVoid DropWeaponFunc = new(GameData.GetSignature("CCSPlayerController_HandleCommandDrop")); + public static void Load() { Instance.RegisterEventHandler(PlayerConnectFull); @@ -78,9 +79,13 @@ namespace src.player Instance.HookUserMessage(208, PlayerMakeSound); VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook(OnTakeDamage, HookMode.Pre); + Instance.RegisterEventHandler(BulletImpact); + VirtualFunctions.CBaseTrigger_StartTouchFunc.Hook(OnTriggerEnter, HookMode.Post); VirtualFunctions.CBaseTrigger_EndTouchFunc.Hook(OnTriggerExit, HookMode.Pre); VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Hook(OnWeaponCanAcquire, HookMode.Pre); + + DropWeaponFunc.Hook(WeaponDrop, HookMode.Pre); } private static HookResult PlayerMakeSound(UserMessage um) @@ -426,7 +431,34 @@ namespace src.player return block ? HookResult.Stop : HookResult.Continue; } } - + + private static HookResult WeaponDrop(DynamicHook hook) + { + lock (setLock) + { + CCSPlayerController player = hook.GetParam(0); + if (player == null || !player.IsValid) + return HookResult.Continue; + + var activeSkills = Instance.SkillPlayer + .Where(p => !p.IsDrawing) + .Select(p => p.Skill.ToString()) + .Distinct(); + + bool block = false; + foreach (string skillName in activeSkills) + { + bool? result = (bool?)Instance.SkillAction(skillName, "WeaponDrop", [hook, player]); + if (result == true) + { + block = true; + break; + } + } + return block ? HookResult.Stop : HookResult.Continue; + } + } + private static void OnTick() { lock (setLock) @@ -488,6 +520,8 @@ namespace src.player var skillPlayer = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); 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)]; @@ -735,13 +769,13 @@ namespace src.player 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 mask = (ulong)(InteractionLayers.MASK_WORLD_ONLY | InteractionLayers.Player | InteractionLayers.NPC); ulong contents = 0; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); + var result = RayTrace.TraceShape(player, eyePos, endPos, mask, contents); - if (trace.DidHit()) + if (result.HasValue && result.Value.DidHit) { - var entity = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity; + var entity = Activator.CreateInstance(typeof(CBaseEntity), result.Value.HitEntity) as CBaseEntity; if (entity == null || !entity.IsValid) return; string designer = entity.DesignerName; @@ -768,12 +802,32 @@ namespace src.player } } + private static HookResult BulletImpact(EventBulletImpact @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, "BulletImpact", [@event]); + return HookResult.Continue; + } + } + private static void SetSkill() { setSkillTimer = null; 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.IsBot && !p.IsHLTV) + .Where(p => { + try { return p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist; } + catch { return false; } + }).ToList(); if (Config.LoadedConfig.GameMode == (int)Config.GameModes.TeamSkills) { @@ -797,7 +851,7 @@ namespace src.player foreach (var player in validPlayers) { if (player == null) continue; - var teammates = validPlayers.Where(p => p.Team == player.Team && p != 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); @@ -875,6 +929,8 @@ namespace src.player Instance?.AddTimer(.2f, () => { + if(player == null || !player.IsValid) return; + 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"); @@ -901,6 +957,8 @@ namespace src.player { Instance?.AddTimer(.6f, () => { + if (player == null || !player.IsValid) return; + foreach (var teammate in teammates) { var teammateInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == teammate.SteamID); diff --git a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs index d38d39f..aae909c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/AimLock.cs +++ b/jRandomSkills - SRC Files/src/player/skills/AimLock.cs @@ -121,9 +121,15 @@ namespace src.player.skills 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 = enemyEyePos - myEyePos; + 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); pawn.Look(angle); @@ -145,11 +151,10 @@ 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 = 20f, float duration = .3f, float offsetZ = 0) : 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) : 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/Anomaly.cs b/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs index 84175ce..5cdf5ed 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Anomaly.cs @@ -40,7 +40,7 @@ namespace src.player.skills { 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.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.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 _); @@ -106,7 +106,10 @@ namespace src.player.skills Vector? lastPosition = skillInfo.LastPositions.FirstOrDefault(); QAngle? lastRotation = skillInfo.LastRotations.FirstOrDefault(); if (lastPosition != null && lastRotation != null) - playerPawn.Teleport(lastPosition, lastRotation, null); + { + playerPawn.Teleport(lastPosition, null, null); + playerPawn.Look(lastRotation); + } } } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs index 595f1aa..8bd9b20 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Baseball.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Baseball.cs @@ -11,7 +11,7 @@ namespace src.player.skills public class Baseball : ISkill { private const Skills skillName = Skills.Baseball; - private static readonly ConcurrentDictionary decoys = []; + private static readonly ConcurrentDictionary decoys = []; public static void LoadSkill() { @@ -50,7 +50,7 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; - decoys.TryAdd(decoy, 0); + decoys.TryAdd(decoy.Index, 0); decoy.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith; decoy.Collision.CollisionGroup = pawn.Collision.CollisionGroup; @@ -60,25 +60,33 @@ namespace src.player.skills { var player = @event.Userid; if (player == null || !player.IsValid) return; + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; - var decoy = decoys.FirstOrDefault(d => d.Key.Index == @event.Entityid).Key; - if (decoy != null && decoy.IsValid) - decoy.AcceptInput("Kill"); + if (decoys.ContainsKey((uint)@event.Entityid)) + { + var decoy = Utilities.GetEntityFromIndex(@event.Entityid); + if (decoy != null && decoy.IsValid) + decoy.AcceptInput("Kill"); + } } public static void OnTick() { - foreach (var decoy in decoys.Keys) + foreach (var decoyIndex in decoys.Keys) { - if (!decoy.IsValid) + var decoy = Utilities.GetEntityFromIndex((int)decoyIndex); + + if (decoy == null || !decoy.IsValid) { - decoys.TryRemove(decoy, out _); + decoys.TryRemove(decoyIndex, out _); continue; } + decoy.Bounces = 0; if (Server.TickCount % 8 != 0) continue; + var vel = decoy.AbsVelocity; float speed = vel.Length(); float targetSpeed = Math.Min(speed * SkillsInfo.GetValue(skillName, "speedMultipier"), SkillsInfo.GetValue(skillName, "maxSpeed")); diff --git a/jRandomSkills - SRC Files/src/player/skills/Behind.cs b/jRandomSkills - SRC Files/src/player/skills/Behind.cs index 63e64d3..0852d2c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Behind.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Behind.cs @@ -45,16 +45,8 @@ namespace src.player.skills if (pawn == null || !pawn.IsValid || pawn.LifeState != (int)LifeState_t.LIFE_ALIVE) return; - var currentPosition = pawn.AbsOrigin; - var currentAngles = pawn.EyeAngles; - - QAngle newAngles = new( - currentAngles.X, - currentAngles.Y + 180, - currentAngles.Z - ); - - pawn.Teleport(currentPosition, newAngles, new Vector(0, 0, 0)); + QAngle look = new(pawn.V_angle.X, pawn.V_angle.Y + 180, 0); + pawn.Look(look); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00FF00", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .2f, float chanceTo = .4f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs index 410ee7c..5c4cbd7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs +++ b/jRandomSkills - SRC Files/src/player/skills/BunnyHop.cs @@ -31,7 +31,7 @@ namespace src.player.skills { var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) return; - if (JumpBan.bannedPlayers.ContainsKey(playerPawn)) return; + if (JumpBan.bannedPlayers.ContainsKey(player.Index)) return; var flags = (PlayerFlags)playerPawn.Flags; var buttons = player.Buttons; diff --git a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs index 077dfe3..f97d44a 100644 --- a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs +++ b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs @@ -11,7 +11,7 @@ namespace src.player.skills public class C4Camouflage : ISkill { private const Skills skillName = Skills.C4Camouflage; - private static readonly ConcurrentDictionary invisiblePlayers = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; public static void LoadSkill() @@ -44,16 +44,16 @@ namespace src.player.skills if (playerInfo?.Skill != skillName) return; if (weapon == "c4") - invisiblePlayers.TryAdd(player, 0); + invisiblePlayers.TryAdd(player.Index, 0); else - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) if (!player.PawnIsAlive) - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -72,10 +72,15 @@ namespace src.player.skills if (targetInfo?.Skill == skillName) isObservingC4Camouflage = true; } - foreach (var _player in invisiblePlayers.Keys) - if (player.SteamID != _player.SteamID && !isObservingC4Camouflage) + foreach (var playerIndex in invisiblePlayers.Keys) + { + var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); + if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + continue; + + if (!isObservingC4Camouflage) { - var playerPawn = _player.PlayerPawn.Value; + var playerPawn = playerController.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) continue; var entity = Utilities.GetEntityFromIndex((int)playerPawn.Index); @@ -89,6 +94,7 @@ namespace src.player.skills if (bombEntity == null || !bombEntity.IsValid) continue; info.TransmitEntities.Remove(bombEntity.Index); } + } } } @@ -105,19 +111,19 @@ namespace src.player.skills var activeWeapon = playerPawn.WeaponServices.ActiveWeapon.Value; if (activeWeapon.DesignerName != "weapon_c4") return; - invisiblePlayers.TryAdd(player, 0); + invisiblePlayers.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } public static void PlayerHurt(EventPlayerHurt @event) { var player = @event.Userid; if (player == null || !player.IsValid) return; - if (!invisiblePlayers.ContainsKey(player)) return; + if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs index c67492f..c32a737 100644 --- a/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs +++ b/jRandomSkills - SRC Files/src/player/skills/CarefulBullets.cs @@ -1,10 +1,10 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; -using CounterStrikeSharp.API; +using System.Collections.Concurrent; +using static src.jRandomSkills; namespace src.player.skills { @@ -13,6 +13,7 @@ namespace src.player.skills private const Skills skillName = Skills.CarefulBullets; private static readonly ConcurrentDictionary targetPlayers = []; private static readonly ConcurrentDictionary lastShot = []; + private static readonly ConcurrentDictionary hitPlayer = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -26,6 +27,7 @@ namespace src.player.skills { targetPlayers.Clear(); lastShot.Clear(); + hitPlayer.Clear(); } foreach (var player in Utilities.GetPlayers()) { @@ -100,48 +102,70 @@ namespace src.player.skills player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); } + public static void BulletImpact(EventBulletImpact @event) + { + var player = @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) + return; + + ulong steamID = player.SteamID; + + 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; + + if (!lastShot.ContainsKey(steamID)) + { + lastShot.TryAdd(steamID, ishitPlayer); + + Instance.AddTickTimer(1, () => + { + if (lastShot.TryRemove(steamID, out bool didHit) && !didHit) + SkillUtils.TakeHealth(playerPawn, SkillsInfo.GetValue(skillName, "damageAfterMiss")); + lastShot.TryRemove(steamID, out _); + }); + } + else if (ishitPlayer) + lastShot.TryUpdate(steamID, true, false); + }); + } + public static void OnTakeDamage(DynamicHook h) { CEntityInstance param = h.GetParam(0); CTakeDamageInfo param2 = h.GetParam(1); - if (param?.Entity == null || param2?.Attacker?.Value == null) + if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) return; CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); + CCSPlayerPawn victimPawn = new(param.Handle); - if (attackerPawn.DesignerName != "player") + if (attackerPawn.DesignerName != "player" || victimPawn.DesignerName != "player") return; - if (attackerPawn == null || attackerPawn.Controller?.Value == null) + 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; - if (!targetPlayers.ContainsKey(attacker.SteamID) || !attacker.PawnIsAlive) - return; - - bool hitPlayer = param.DesignerName == "player"; - - if (!lastShot.ContainsKey(attacker.SteamID)) - { - lastShot.TryAdd(attacker.SteamID, hitPlayer); - - Instance.AddTickTimer(1, () => - { - if (lastShot.TryRemove(attacker.SteamID, out bool didHit) && !didHit) - SkillUtils.TakeHealth(attackerPawn, SkillsInfo.GetValue(skillName, "damageAfterMiss")); - lastShot.TryRemove(attacker.SteamID, out _); - }); - } - else if (hitPlayer) - lastShot.TryUpdate(attacker.SteamID, true, false); + hitPlayer.AddOrUpdate(attacker.SteamID, 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 _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs index 831fa01..f886784 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Chicken.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Chicken.cs @@ -21,9 +21,9 @@ namespace src.player.skills "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ]; - private static readonly ConcurrentDictionary chickens = []; - private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl"; - private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl"; + private static readonly ConcurrentDictionary chickens = []; + 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 = []; public static void LoadSkill() @@ -35,9 +35,14 @@ namespace src.player.skills { foreach (var player in Utilities.GetPlayers()) SetWeaponAttack(player, false); + foreach (var valuePair in chickens) - if (valuePair.Value != null && valuePair.Value.IsValid) - valuePair.Value.AcceptInput("Kill"); + { + var chicken = Utilities.GetEntityFromIndex((int)valuePair.Value); + if (chicken != null && chicken.IsValid) + chicken.AcceptInput("Kill"); + } + chickens.Clear(); originalModels.Clear(); } @@ -96,11 +101,12 @@ namespace src.player.skills SetWeaponAttack(player, false); } - if (chickens.TryGetValue(player, out var chicken)) + if (chickens.TryRemove(player.Index, out var chickenIndex)) { + var chicken = Utilities.GetEntityFromIndex((int)chickenIndex); + if (chicken != null && chicken.IsValid) chicken.AcceptInput("Kill"); - chickens.TryRemove(player, out _); } if (originalModels.TryGetValue(player.SteamID, out var model)) @@ -110,6 +116,9 @@ namespace src.player.skills Server.NextFrame(() => { + if (player == null || !player.IsValid) return; + if (pawn == null || !pawn.IsValid) return; + if (string.IsNullOrEmpty(model)) model = player.Team == CsTeam.Terrorist ? defaultTModel : defaultCTModel; @@ -157,19 +166,27 @@ namespace src.player.skills chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1; Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent"); - Server.NextFrame(() => chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1")); + + Server.NextFrame(() => { + if (chickenModel == null || !chickenModel.IsValid) return; + chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1"); + }); chickenModel.AcceptInput("SetParent", playerPawn, playerPawn, "!activator"); - chickens.TryAdd(player, chickenModel); + chickens.TryAdd(player.Index, chickenModel.Index); } public static void OnTick() { foreach (var valuePair in chickens) { - var player = valuePair.Key; - var chicken = valuePair.Value; + var playerIndex = valuePair.Key; + var chickenIndex = valuePair.Value; + + var player = Utilities.GetPlayerFromIndex((int)playerIndex); if (player == null || !player.IsValid) continue; + + var chicken = Utilities.GetEntityFromIndex((int)chickenIndex); if (chicken == null || !chicken.IsValid) continue; var pawn = player.PlayerPawn.Value; diff --git a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs index 59c7e6d..59ddf19 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs @@ -3,8 +3,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Struct; +using RayTraceAPI; using src.utils; using System.Collections.Concurrent; using System.Drawing; @@ -17,7 +16,7 @@ namespace src.player.skills public class Cypher : ISkill { private const Skills skillName = Skills.Cypher; - private static readonly ConcurrentDictionary playersInfo = []; + private static readonly ConcurrentDictionary playersInfo = []; private static readonly object setLock = new(); private const string cameraPropModel = "models/props/de_train/hr_train_s2/train_electronics/train_electronics_security_camera_01.vmdl"; @@ -42,16 +41,16 @@ namespace src.player.skills { var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) ChangeCamera(playerSkill); } public static void EnableSkill(CCSPlayerController player) { if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return; - playersInfo.TryAdd(player, new PlayerSkill + playersInfo.TryAdd(player.Index, new PlayerSkill { - Player = player, + Player = player.Index, CameraProp = null, CameraView = null, CameraActive = false, @@ -64,29 +63,36 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) { ChangeCamera(playerSkill, true); KillCamera(playerSkill); } - playersInfo.TryRemove(player, out _); + playersInfo.TryRemove(player.Index, out _); } private static void KillCamera(PlayerSkill playerSkill) { - if (playerSkill.CameraView != null && playerSkill.CameraView.IsValid) + if (playerSkill.CameraView != null && playerSkill.CameraView != 0) { - playerSkill.CameraView.AcceptInput("Kill"); + var cameraView = Utilities.GetEntityFromIndex((int)playerSkill.CameraView); + if (cameraView != null && cameraView.IsValid) + cameraView.AcceptInput("Kill"); playerSkill.CameraView = null; - playerSkill.CameraActive = false; } - if (playerSkill.CameraProp != null && playerSkill.CameraProp.IsValid) + if (playerSkill.CameraProp != null && playerSkill.CameraProp != 0) { - playerSkill.CameraProp.EmitSound("SolidMetal.BulletImpact"); - playerSkill.CameraProp.AcceptInput("Kill"); + var cameraProp = Utilities.GetEntityFromIndex((int)playerSkill.CameraProp); + if (cameraProp != null && cameraProp.IsValid) + { + cameraProp.EmitSound("SolidMetal.BulletImpact"); + cameraProp.AcceptInput("Kill"); + } playerSkill.CameraProp = null; } + + playerSkill.CameraActive = false; playerSkill.NextCamera = Server.TickCount + SkillsInfo.GetValue(skillName, "Cooldown") * 64; } @@ -94,65 +100,88 @@ namespace src.player.skills { foreach (var playerSkill in playersInfo.Values) { - if (playerSkill.CameraActive && playerSkill.CameraView != null && playerSkill.CameraView.IsValid) + if (playerSkill.CameraActive && playerSkill.CameraView != null && playerSkill.CameraView != 0) { - var pawn = playerSkill.Player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) continue; + var enemy = Utilities.GetPlayerFromIndex((int)playerSkill.Player); + if (enemy == null || !enemy.IsValid || enemy.PlayerPawn == null) continue; - if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) + var enemyPawn = enemy.PlayerPawn.Value; + if (enemyPawn == null || !enemyPawn.IsValid) continue; + + if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) { - DisableSkill(playerSkill.Player); + DisableSkill(enemy); continue; } - playerSkill.CameraView.Teleport(null, pawn.V_angle); + + var cameraView = Utilities.GetEntityFromIndex((int)playerSkill.CameraView); + if (cameraView == null || !cameraView.IsValid) continue; + + cameraView.Teleport(null, enemyPawn.V_angle); } UpdateHUD(playerSkill); } } - private static void ChangeCamera(PlayerSkill player, bool forceToDefault = false) + private static void ChangeCamera(PlayerSkill playerInfo, bool forceToDefault = false) { - player.CameraActive = forceToDefault ? false : !player.CameraActive; - if (player.CameraProp == null && !forceToDefault) + var player = Utilities.GetPlayerFromIndex((int)playerInfo.Player); + if (player == null || !player.IsValid) return; + + playerInfo.CameraActive = forceToDefault ? false : !playerInfo.CameraActive; + if (playerInfo.CameraProp == null && !forceToDefault) { - if (player.NextCamera > Server.TickCount) return; - player.CameraProp = CreateCameraProp(player.Player); - if (player.CameraProp == null) + if (playerInfo.NextCamera > Server.TickCount) return; + + var newProp = CreateCameraProp(player); + playerInfo.CameraProp = newProp?.Index ?? null; + + if (playerInfo.CameraProp == null) { - player.NoSpace = Server.TickCount + (64 * 2); + playerInfo.NoSpace = Server.TickCount + (64 * 2); return; } - player.CameraView = CreateCameraView(player.Player); - if (player.CameraView == null) return; + else + playerInfo.CameraView = CreateCameraView(newProp)?.Index ?? null; + + if (playerInfo.CameraView == null) return; } - var pawn = player.Player.PlayerPawn.Value; - if (player.PlayerCameraRaw == 0) + var pawn = player.PlayerPawn.Value; + if (playerInfo.PlayerCameraRaw == 0) return; - BlockWeapon(player.Player, player.CameraActive); + BlockWeapon(player, playerInfo.CameraActive); Server.NextWorldUpdate(() => { if (pawn != null && pawn.LifeState == (byte)LifeState_t.LIFE_ALIVE) { - if (player.CameraActive && player.CameraProp != null) + if (playerInfo.CameraActive && playerInfo.CameraProp != null) { - if ( pawn.AbsRotation != null) - player.LastAngle = new QAngle(pawn.AbsRotation.X, pawn.AbsRotation.Y, pawn.AbsRotation.Z); - pawn.Teleport(null, player.CameraProp.AbsRotation); + if (pawn.AbsRotation != null) + playerInfo.LastAngle = new QAngle(pawn.V_angle.X, pawn.V_angle.Y, 0); + + var cameraProp = Utilities.GetEntityFromIndex((int)playerInfo.CameraProp); + if (cameraProp == null || !cameraProp.IsValid) return; + + pawn.Teleport(null, cameraProp.AbsRotation); } else if (!forceToDefault) - pawn.Teleport(null, player.LastAngle); + { + pawn.Look(playerInfo.LastAngle); + } } - if (player.CameraActive && player.CameraView != null) + if (playerInfo.CameraActive && playerInfo.CameraView != null) { - pawn!.CameraServices!.ViewEntity.Raw = player.CameraView.EntityHandle.Raw; - SkillUtils.ApplyScreenColor(player.Player, 0, 0, 255, 20, 100, 1020); + var cameraView = Utilities.GetEntityFromIndex((int)playerInfo.CameraView); + if (cameraView == null || !cameraView.IsValid) return; - ulong? playerSteamID = player.Player?.SteamID; - if (playerSteamID == null) return; + pawn!.CameraServices!.ViewEntity.Raw = cameraView.EntityHandle.Raw; + SkillUtils.ApplyScreenColor(player, 0, 0, 255, 20, 100, 1020); + + ulong playerSteamID = player.SteamID; Timer? cameraTimer = null; cameraTimer = jRandomSkills.Instance.AddTimer(2f, () => @@ -164,7 +193,7 @@ namespace src.player.skills return; } - if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CameraActive == false) + if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CameraActive == false) { cameraTimer?.Kill(); return; @@ -174,7 +203,7 @@ namespace src.player.skills }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); } else - pawn!.CameraServices!.ViewEntity.Raw = player.PlayerCameraRaw; + pawn!.CameraServices!.ViewEntity.Raw = playerInfo.PlayerCameraRaw; Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices"); }); @@ -182,6 +211,18 @@ namespace src.player.skills private static CDynamicProp? CreateCameraProp(CCSPlayerController player) { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid) return null; + + Vector? cameraVector = GetNewCameraPosition(player); + if (cameraVector == null) return null; + + Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 10; + Vector finalPos = new(cameraVector.X + diffVector.X, cameraVector.Y + diffVector.Y, cameraVector.Z); + + if (!CheckCameraPosition(finalPos, player)) + return null; + var camera = Utilities.CreateEntityByName("prop_dynamic_override"); if (camera == null || !camera.IsValid) return null; @@ -189,47 +230,32 @@ namespace src.player.skills 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}"; - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid) return null; - - Vector? cameraVector = GetNewCameraPosition(player); - Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 10; - if (cameraVector == null) return null; - cameraVector = new Vector(cameraVector.X + diffVector.X, cameraVector.Y + diffVector.Y, cameraVector.Z); - - if (!CheckCameraPosition(cameraVector, player)) - return null; - - Server.NextFrame(() => - { - camera.SetModel(cameraPropModel); - camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0)); - camera.DispatchSpawn(); - }); + if (camera == null || !camera.IsValid) return null; + camera.SetModel(cameraPropModel); + camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0)); + camera.DispatchSpawn(); return camera; } - private static CDynamicProp? CreateCameraView(CCSPlayerController player) + private static CDynamicProp? CreateCameraView(CDynamicProp? cameraProp) { + if (cameraProp == null || !cameraProp.IsValid || cameraProp.AbsRotation == null || cameraProp.AbsOrigin == null) + return null; + + Vector diffVector = SkillUtils.GetForwardVector(cameraProp.AbsRotation) * 25; + Vector finalPos = cameraProp.AbsOrigin + diffVector; + var camera = Utilities.CreateEntityByName("prop_dynamic"); if (camera == null || !camera.IsValid) return null; - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid) return null; - - Vector? cameraVector = GetNewCameraPosition(player); - Vector diffVector = SkillUtils.GetForwardVector(playerPawn.V_angle) * 25; - if (cameraVector == null) return null; - - cameraVector = new Vector(cameraVector.X - diffVector.X, cameraVector.Y - diffVector.Y, cameraVector.Z); - if (cameraVector == null) return null; - Server.NextFrame(() => { + if (camera == null || !camera.IsValid) return; camera.SetModel(cameraViewModel); camera.Render = Color.FromArgb(0, 255, 255, 255); - camera.Teleport(cameraVector, playerPawn.EyeAngles); + + camera.Teleport(finalPos, cameraProp.AbsRotation); camera.DispatchSpawn(); }); @@ -254,7 +280,7 @@ namespace src.player.skills var player = Utilities.GetPlayerFromSteamId(steamID); if (player == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) { ChangeCamera(playerSkill, true); KillCamera(playerSkill); @@ -286,18 +312,13 @@ namespace src.player.skills Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z); Vector endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f; - ulong solid = 0x1; - ulong window = 0x1000; - ulong passBullets = 0x2000; + ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets); + var result = RayTrace.TraceShape(player, eyePos, endPos, mask); - ulong mask = solid | window | passBullets; - ulong contents = playerPawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); - - if (trace.HitWorld(out _)) + if (result.HasValue && result.Value.HitWorld(out _)) { - Vector3 hitPost = trace.EndPos; - Vector3 normal = trace.Normal; + Vector3 hitPost = result.Value.EndPos; + Vector3 normal = result.Value.Normal; float offset = 8; Vector finalPos = new( @@ -320,15 +341,10 @@ namespace src.player.skills Vector endPos = cameraVector + SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * -5; cameraVector += SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * 5; - ulong solid = 0x1; - ulong window = 0x1000; - ulong passBullets = 0x2000; + ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets); + var result = RayTrace.TraceShape(player, cameraVector, endPos, mask); - ulong mask = solid | window | passBullets; - ulong contents = playerPawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(cameraVector, endPos, mask, contents, player); - - if (trace.HitWorld(out _)) + if (result.HasValue && result.Value.HitWorld(out _)) return true; return false; @@ -336,28 +352,30 @@ namespace src.player.skills private static void UpdateHUD(PlayerSkill playerSkill) { - if (playerSkill == null || playerSkill.Player == null) return; + if (playerSkill == null) return; - float cooldown = 0; - float time = (playerSkill.NextCamera - Server.TickCount) / 64; - cooldown = (int)Math.Ceiling(Math.Max(time, 0)); + var player = Utilities.GetPlayerFromIndex((int)playerSkill.Player); + if (player == null || !player.IsValid) return; - var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID); + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID); if (playerInfo == null) return; + float ticksLeft = playerSkill.NextCamera - Server.TickCount; + int secondsLeft = (int)Math.Ceiling(Math.Max(ticksLeft / 64.0f, 0)); + if (playerSkill.NoSpace >= Server.TickCount) - playerInfo.PrintHTML = $"{playerSkill.Player.GetTranslation("cypher_nospace")}"; - else if (cooldown == 0) + playerInfo.PrintHTML = $"{player.GetTranslation("cypher_nospace")}"; + else if (secondsLeft > 0 && playerSkill.CameraProp == null) + playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"{secondsLeft}")}"; + else playerInfo.PrintHTML = null; - else if (playerSkill?.CameraProp == null) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"{cooldown}")}"; } public class PlayerSkill { - public required CCSPlayerController Player { get; set; } - public CDynamicProp? CameraProp { get; set; } - public CDynamicProp? CameraView { get; set; } + public required uint Player { get; set; } + public uint? CameraProp { get; set; } + public uint? CameraView { get; set; } public uint PlayerCameraRaw { get; set; } public bool CameraActive { get; set; } public float NextCamera { get; set; } diff --git a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs index 1444fba..2345ee2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Deaf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Deaf.cs @@ -11,7 +11,7 @@ namespace src.player.skills public class Deaf : ISkill { private const Skills skillName = Skills.Deaf; - private static readonly ConcurrentDictionary deafPlayers = []; + private static readonly ConcurrentDictionary deafPlayers = []; public static void LoadSkill() { @@ -20,8 +20,13 @@ namespace src.player.skills public static void NewRound() { - foreach (var player in deafPlayers.Keys) + foreach (var playerIndex in deafPlayers.Keys) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; DisableSkill(player); + } + deafPlayers.Clear(); foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); @@ -29,8 +34,12 @@ namespace src.player.skills public static void PlayerMakeSound(UserMessage um) { - foreach (var player in deafPlayers.Keys) + foreach (var playerIndex in deafPlayers.Keys) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; um.Recipients.Remove(player); + } } public static void OnTick() @@ -44,7 +53,7 @@ namespace src.player.skills 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.Index.ToString()))); + ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); } } @@ -70,7 +79,7 @@ namespace src.player.skills return; } - deafPlayers.TryAdd(enemy, 0); + deafPlayers.TryAdd(enemy.Index, 0); playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("deaf_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("deaf_enemy_info")); @@ -95,7 +104,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SkillUtils.CloseMenu(player); - deafPlayers.TryRemove(player, out _); + deafPlayers.TryRemove(player.Index, out _); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dae01f", CsTeam onlyTeam = CsTeam.None, 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/Distancer.cs b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs index 77a4f8e..6a7c804 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Distancer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Distancer.cs @@ -9,7 +9,7 @@ namespace src.player.skills public class Distancer : ISkill { private const Skills skillName = Skills.Distancer; - private static readonly ConcurrentDictionary distancerPlayers = []; + private static readonly ConcurrentDictionary distancerPlayers = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -26,8 +26,11 @@ namespace src.player.skills public static void OnTick() { if (SkillUtils.IsFreezeTime()) return; - foreach (var player in distancerPlayers.Keys) + foreach (var playerIndex in distancerPlayers.Keys) { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID); if (playerInfo == null) continue; @@ -56,12 +59,12 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - distancerPlayers.TryAdd(player, 0); + distancerPlayers.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { - distancerPlayers.TryRemove(player, out _); + distancerPlayers.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs index 463eca2..ee41b22 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs @@ -1,9 +1,10 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; 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 { @@ -120,12 +121,18 @@ namespace src.player.skills bool ctSkill = Event.counterterroristSkills.Any(s => s.Name == enemySkill.ToString()); bool ttSkill = Event.terroristSkills.Any(s => s.Name == enemySkill.ToString()); + ulong steamID = player.SteamID; + string enemyName = enemy.PlayerName; + if ((player.Team == CsTeam.Terrorist && ctSkill) || (player.Team == CsTeam.CounterTerrorist && ttSkill)) { Instance.AddTimer(.1f, () => { + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player == null || !player.IsValid) return; + Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); - player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName)); + player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemyName)); }); return; } @@ -139,6 +146,9 @@ 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); + 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]); }); diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs index 39eee08..4d551dd 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -24,8 +23,10 @@ namespace src.player.skills { var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); 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"); } @@ -59,29 +60,20 @@ namespace src.player.skills private static bool NearlyEquals(float a, float b, float epsilon = 0.001f) => Math.Abs(a -b) < epsilon; - public static void OnTakeDamage(DynamicHook h) + public static void BulletImpact(EventBulletImpact @event) { if (lastTick == Server.TickCount) return; - CEntityInstance param = h.GetParam(0); - CTakeDamageInfo param2 = h.GetParam(1); + var player = @event.Userid; + if (player == null || !player.IsValid) return; - if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return; + var pos = new Vector(@event.X, @event.Y, @event.Z); - CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); - if (attackerPawn.DesignerName != "player") - return; - - if (attackerPawn == null || attackerPawn.Controller?.Value == null) - return; - - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null || playerInfo.Skill != skillName) return; if (Instance.Random.NextDouble() <= playerInfo.SkillChance) - SpawnExplosion(param2.DamagePosition); + SpawnExplosion(pos); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#9c0000", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float damage = 25f, float damageRadius = 210f, float chanceFrom = .15f, float chanceTo = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs index 81839a1..f97698e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FalconEye.cs @@ -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() { @@ -20,9 +20,14 @@ namespace src.player.skills public static void NewRound() { - foreach (var camera in cameras) - if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) - camera.Value.Item2.AcceptInput("Kill"); + foreach (var cameraIndex in cameras.Values) + { + var camera = Utilities.GetEntityFromIndex((int)cameraIndex.Item2); + if (camera == null || !camera.IsValid) continue; + + camera.AcceptInput("Kill"); + } + cameras.Clear(); } @@ -56,18 +61,23 @@ namespace src.player.skills public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; + if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) { ChangeCamera(player, true); continue; } + Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + SkillsInfo.GetValue(skillName, "distance")); QAngle angle = new(90, 0, -pawn.V_angle.Y); - cameraInfo.Item2.Teleport(pos, angle); + + var camera = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); + if (camera == null || !camera.IsValid) continue; + camera.Teleport(pos, angle); } } @@ -77,10 +87,15 @@ namespace src.player.skills uint newCameraRaw; var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) return; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) + + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; - newCameraRaw = cameraInfo.Item2.EntityHandle.Raw; + + var camera = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); + if (camera == null || !camera.IsValid) return; + + newCameraRaw = camera.EntityHandle.Raw; } else { @@ -108,13 +123,14 @@ namespace src.player.skills Server.NextFrame(() => { + if (camera == null || !camera.IsValid) return; camera.SetModel("models/actors/ghost_speaker.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), (k, v) => (pawn.CameraServices!.ViewEntity.Raw, camera)); + cameras.AddOrUpdate(player.SteamID, (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/Fortnite.cs b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs index 4163af1..1113b86 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs @@ -112,6 +112,7 @@ namespace src.player.skills barricades.TryAdd(box.Index, SkillsInfo.GetValue(skillName, "barricadeHealth")); Server.NextFrame(() => { + if (box == null || !box.IsValid) return; box.SetModel(SkillsInfo.GetValue(skillName, "propModel")); box.Teleport(pos, angle, null); }); diff --git a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs index 79ba292..93ce550 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs @@ -1,10 +1,9 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; +using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; namespace src.player.skills { @@ -14,8 +13,8 @@ namespace src.player.skills private static int bombHealth = 1000; private static int maxBombHealth = 1000; - private static CPlantedC4? plantedC4; - private static CTriggerMultiple? triggerC4; + private static int lastTick = 0; + private static Vector? plantedC4; public static void LoadSkill() { @@ -27,80 +26,42 @@ namespace src.player.skills bombHealth = SkillsInfo.GetValue(skillName, "maxBombHealth"); maxBombHealth = SkillsInfo.GetValue(skillName, "maxBombHealth"); plantedC4 = null; - triggerC4 = null; } public static void BombPlanted(EventBombPlanted _) { var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb == null) return; - plantedC4 = plantedBomb; - CreateTrigger(); - } - - private static void CreateTrigger() - { - var trigger = Utilities.CreateEntityByName("trigger_multiple"); - if (trigger == null || plantedC4 == null || trigger.AbsOrigin == null || plantedC4.AbsOrigin == null) return; - - trigger.Collision.SolidType = SolidType_t.SOLID_CAPSULE; - trigger.Collision.SolidFlags = 0; - trigger.Spawnflags = 1; - trigger.Globalname = $"planted_bomb_prop_{trigger.Index}"; - trigger.Collision.SolidFlags = 1; - - trigger.AbsOrigin.X = plantedC4.AbsOrigin.X; - trigger.AbsOrigin.Y = plantedC4.AbsOrigin.Y; - trigger.AbsOrigin.Z = plantedC4.AbsOrigin.Z; - - trigger.Collision.CapsuleRadius = 10; - trigger.Collision.BoundingRadius = 10; - - 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(); - triggerC4 = trigger; + if (plantedBomb == null || !plantedBomb.IsValid || plantedBomb.AbsOrigin == null) return; + plantedC4 = new(plantedBomb.AbsOrigin.X, plantedBomb.AbsOrigin.Y, plantedBomb.AbsOrigin.Z); } private static void RemoveBomb() { - if (plantedC4 != null && plantedC4.IsValid) - plantedC4.AcceptInput("Kill"); - if (triggerC4 != null && triggerC4.IsValid) - triggerC4.AcceptInput("Kill"); + plantedC4 = null; + var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); + if (plantedBomb != null && plantedBomb.IsValid) + plantedBomb.AcceptInput("Kill"); SkillUtils.TerminateRound(CsTeam.CounterTerrorist); } - public static void OnTakeDamage(DynamicHook h) + public static void BulletImpact(EventBulletImpact @event) { - CEntityInstance param = h.GetParam(0); - CTakeDamageInfo param2 = h.GetParam(1); + if (lastTick == Server.TickCount) return; - if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) - return; + var player = @event.Userid; + if (player == null || !player.IsValid || plantedC4 == null) return; - CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle); + var pos = new Vector(@event.X, @event.Y, @event.Z); - if (attackerPawn.DesignerName != "player" || param.DesignerName != "trigger_multiple") - return; - - CTriggerMultiple trigger = new(param.Handle); - - if (attackerPawn == null || attackerPawn.Controller?.Value == null || trigger == null || !trigger.Globalname.StartsWith("planted_bomb_prop_")) - return; - - CCSPlayerController attacker = attackerPawn.Controller.Value.As(); - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker.SteamID); + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo == null || playerInfo.Skill != skillName) return; - bombHealth -= (int)param2.TotalledDamage; + if (SkillUtils.Distance(plantedC4, pos) >= 8) + return; + + lastTick = Server.TickCount; + bombHealth -= Instance.Random.Next(25, 42); + if (bombHealth <= 0) { RemoveBomb(); diff --git a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs index 8fb4811..3210119 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FriendlyFire.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -34,6 +35,10 @@ namespace src.player.skills var pawn = victim.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return; + + if (damage == 0) + damage = Instance.Random.Next(4, 6); + SkillUtils.AddHealth(pawn, damage + (int)(damage * SkillsInfo.GetValue(skillName, "healthMultiplier")), pawn.MaxHealth); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Gambler.cs b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs index 43e7c30..abf5806 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Gambler.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Gambler.cs @@ -28,6 +28,8 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; + ulong steamID = player.SteamID; + if (playerInfo.SkillUsed) { player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}"); @@ -56,7 +58,10 @@ namespace src.player.skills if (SkillsInfo.GetValue(skill.Skill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { - if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID && p.Skill == skill.Skill) == null) return; + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player == null || !player.IsValid) return; + + if (Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == steamID && p.Skill == skill.Skill) == null) return; Instance?.SkillAction(skill.Skill.ToString(), "EnableSkill", [player]); }); else diff --git a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs index 5d07c97..35d45e1 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs @@ -24,7 +24,7 @@ namespace src.player.skills "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ]; - private static readonly ConcurrentDictionary invisiblePlayers = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; public static void LoadSkill() @@ -76,22 +76,31 @@ namespace src.player.skills if (targetInfo?.Skill == skillName) isObservingGhost = true; } - foreach (var _player in invisiblePlayers.Keys) - if (player.SteamID != _player.SteamID && !isObservingGhost) + foreach (var playerIndex in invisiblePlayers.Keys) + { + var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); + if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + continue; + + if (!isObservingGhost) { - var playerPawn = _player.PlayerPawn.Value; + var playerPawn = playerController.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) continue; var entity = Utilities.GetEntityFromIndex((int)playerPawn.Index); if (entity == null || !entity.IsValid) continue; + info.TransmitEntities.Remove(entity.Index); - var bombIndex = GetBombIndex(_player); + var bombIndex = GetBombIndex(playerController); if (bombIndex == null) continue; + var bombEntity = Utilities.GetEntityFromIndex((int)bombIndex); if (bombEntity == null || !bombEntity.IsValid) continue; + info.TransmitEntities.Remove(bombEntity.Index); } + } } } @@ -99,14 +108,14 @@ namespace src.player.skills { Event.EnableTransmit(); SetWeaponAttack(player, true); - invisiblePlayers.TryAdd(player, 0); + invisiblePlayers.TryAdd(player.Index, 0); } public static void DisableSkill(CCSPlayerController player) { SkillUtils.ResetPrintHTML(player); SetWeaponAttack(player, false); - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } public static void OnTick() @@ -116,8 +125,9 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) UpdateHUD(player); + if (!player.PawnIsAlive) - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } } @@ -125,7 +135,7 @@ namespace src.player.skills { var player = @event.Userid; if (player == null || !player.IsValid) return; - if (!invisiblePlayers.ContainsKey(player)) return; + if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs index c8ab2e1..b68769f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/GodMode.cs +++ b/jRandomSkills - SRC Files/src/player/skills/GodMode.cs @@ -1,9 +1,10 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; 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 { @@ -49,6 +50,10 @@ namespace src.player.skills { SkillPlayerInfo.TryRemove(player.SteamID, out _); SkillUtils.ResetPrintHTML(player); + + var playerPawn = player.PlayerPawn.Value; + if (playerPawn != null && playerPawn.IsValid) + playerPawn.TakesDamage = true; } private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) @@ -77,7 +82,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + ulong steamID = player.SteamID; + + if (SkillPlayerInfo.TryGetValue(steamID, out var skillInfo)) { if (!player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; if (skillInfo.CanUse) @@ -89,8 +96,11 @@ namespace src.player.skills player.PlayerPawn.Value.TakesDamage = false; Instance.AddTimer(SkillsInfo.GetValue(skillName, "duration"), () => { - if (player.IsValid && player.PawnIsAlive) + + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player != null && player.IsValid && player.PawnIsAlive) { + 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")}"); } diff --git a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs index ca2c993..7fb7cf7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HealingSmoke.cs @@ -65,6 +65,7 @@ namespace src.player.skills Server.NextFrame(() => { + if (entity == null || !entity.IsValid) return; var smoke = entity.As(); smoke.SmokeColor.X = 0; smoke.SmokeColor.Y = 255; diff --git a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs index 296f499..11bdf49 100644 --- a/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/HolyHandGrenade.cs @@ -24,6 +24,7 @@ namespace src.player.skills Server.NextFrame(() => { + if (@event == null || !@event.IsValid) return; var hegrenade = @event.As(); if (hegrenade == null || !hegrenade.IsValid) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Iana.cs b/jRandomSkills - SRC Files/src/player/skills/Iana.cs index d20090d..18ec2d9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Iana.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Iana.cs @@ -3,8 +3,6 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Struct; using src.utils; using System.Collections.Concurrent; using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; @@ -15,7 +13,7 @@ namespace src.player.skills public class Iana : ISkill { private const Skills skillName = Skills.Iana; - private static readonly ConcurrentDictionary playersInfo = []; + private static readonly ConcurrentDictionary playersInfo = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -35,7 +33,7 @@ namespace src.player.skills { var player = @event.Userid; if (player == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) if (playerSkill.CloneProp != null) BlockWeapon(player, true); } @@ -44,7 +42,7 @@ namespace src.player.skills { var player = @event.Userid; if (player == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) if (playerSkill.CloneProp != null) BlockWeapon(player, true); } @@ -54,9 +52,12 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) if (playerSkill.CloneProp == null && playerSkill.NextUse <= Server.TickCount) + { + UpdateWeapons(player, playerSkill); CreateClone(playerSkill); + } else if (playerSkill.CloneProp != null) KillClone(playerSkill); } @@ -64,9 +65,9 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return; - playersInfo.TryAdd(player, new PlayerSkill + playersInfo.TryAdd(player.Index, new PlayerSkill { - Player = player, + PlayerIndex = player.Index, CloneProp = null, NextUse = 0, UseTime = 0, @@ -75,32 +76,54 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) KillClone(playerSkill); - playersInfo.TryRemove(player, out _); + playersInfo.TryRemove(player.Index, out _); + } + + private static void UpdateWeapons(CCSPlayerController player, PlayerSkill playerSkill) + { + if (player == null || !player.IsValid) return; + + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.WeaponServices == null) return; + + playerSkill.Weapons.Clear(); + + foreach (var weapon in playerPawn.WeaponServices.MyWeapons) + if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) + playerSkill.Weapons.Add(weapon.Value.AttributeManager.Item.ItemID); } private static void KillClone(PlayerSkill playerSkill) { - playerSkill.Player.EmitSound("SolidMetal.BulletImpact"); - if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null && playerSkill.CloneProp.AbsRotation != null) + var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex); + if (player == null || !player.IsValid) return; + + player.EmitSound("SolidMetal.BulletImpact"); + + CDynamicProp? cloneProp = null; + if (playerSkill.CloneProp != null) + cloneProp = Utilities.GetEntityFromIndex((int)playerSkill.CloneProp); + + if (cloneProp != null && cloneProp.IsValid && cloneProp.AbsOrigin != null && cloneProp.AbsRotation != null) { - var playerPawn = playerSkill.Player.PlayerPawn.Value; + var playerPawn = player.PlayerPawn.Value; if (playerPawn != null && playerPawn.IsValid) { - Vector pos = new(playerSkill.CloneProp.AbsOrigin.X, playerSkill.CloneProp.AbsOrigin.Y, playerSkill.CloneProp.AbsOrigin.Z); - QAngle angle = new(playerSkill.CloneProp.AbsRotation.X, playerSkill.CloneProp.AbsRotation.Y, playerSkill.CloneProp.AbsRotation.Z); + Vector pos = new(cloneProp.AbsOrigin.X, cloneProp.AbsOrigin.Y, cloneProp.AbsOrigin.Z); Server.NextFrame(() => { - playerPawn.Teleport(pos, angle); + if (playerPawn == null || !playerPawn.IsValid) return; + playerPawn.Teleport(pos); }); } - playerSkill.CloneProp.AcceptInput("Kill"); + cloneProp.AcceptInput("Kill"); playerSkill.CloneProp = null; } - SkillUtils.ApplyScreenColor(playerSkill.Player, 0, 0, 0, 0, 10, 0, 2); - BlockWeapon(playerSkill.Player, false); + SkillUtils.ApplyScreenColor(player, 0, 0, 0, 0, 10, 0, 2); + BlockWeapon(player, false); playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue(skillName, "Cooldown") * 64; playerSkill.UseTime = 0; } @@ -113,20 +136,32 @@ namespace src.player.skills private static CDynamicProp? CreateClone(PlayerSkill playerSkill) { - var player = playerSkill.Player; - if (player == null) return null; + var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex); + if (player == null || !player.IsValid) return null; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return null; - Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * 50; - Vector pos2 = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * (50 + 25); - if (!CheckPosition(player, pos2) || !((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND)) + if (!((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND)) { playerSkill.InfoTime = Server.TickCount; return null; } + QAngle angle = new(0, playerPawn.EyeAngles.Y, 0); + Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(angle) * 50; + pos.Z += 2; + + if (!CheckPosition(player, pos)) + { + pos.Z += 10; + if (!CheckPosition(player, pos)) + { + playerSkill.InfoTime = Server.TickCount; + return null; + } + } + var clone = Utilities.CreateEntityByName("prop_dynamic"); if (clone == null || !clone.IsValid) return null; @@ -137,16 +172,21 @@ namespace src.player.skills Server.NextFrame(() => { + if (player == null || !player.IsValid) return; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return; + + if (clone == null || !clone.IsValid) return; + clone.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName); 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); - BlockWeapon(playerSkill.Player, true); + BlockWeapon(player, true); playerSkill.UseTime = Server.TickCount; playerSkill.NextUse = Server.TickCount + 64000; - playerSkill.CloneProp = clone; + playerSkill.CloneProp = clone.Index; jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue(skillName, "Duration"), () => { @@ -167,7 +207,7 @@ namespace src.player.skills return; } - if (!playersInfo.TryGetValue(target, out var playerSkill) || playerSkill.CloneProp == null) + if (!playersInfo.TryGetValue(target.Index, out var playerSkill) || playerSkill.CloneProp == null) { cloneTimer?.Kill(); return; @@ -183,16 +223,14 @@ namespace src.player.skills private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos) { var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false; - Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 25); - endPos.Z += 25; + Vector start = new(playerPawn!.AbsOrigin!.X, playerPawn!.AbsOrigin!.Y, endPos.Z); + var result = RayTrace.TraceHullShape(start, endPos, player); - ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; - ulong contents = playerPawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); - - return !trace.DidHit(); + if (!result.HasValue) + return false; + + return !result.Value.DidHit; } private static float CalculateDamage(CCSPlayerController player, string weaponName, float damage, bool isHeadshot) @@ -240,12 +278,16 @@ namespace src.player.skills float dealDamage = param2.Damage; - if (playersInfo.TryGetValue(player, out var playerSkill)) + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) { - if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null) + CDynamicProp? cloneProp = null; + if (playerSkill.CloneProp != null) + cloneProp = Utilities.GetEntityFromIndex((int)playerSkill.CloneProp); + + if (cloneProp != null && cloneProp.IsValid && cloneProp.AbsOrigin != null) { Vector pos = param2.DamagePosition; - Vector posCl = playerSkill.CloneProp.AbsOrigin; + Vector posCl = cloneProp.AbsOrigin; bool isHead = false; float viewOffset = 63.27f; @@ -273,7 +315,7 @@ namespace src.player.skills var victim = @event.Userid!; if (!jRandomSkills.Instance.IsPlayerValid(victim)) return; - if (playersInfo.TryGetValue(victim, out var playerSkill) && playerSkill.CloneProp != null) + if (playersInfo.TryGetValue(victim.Index, out var playerSkill) && playerSkill.CloneProp != null) { KillClone(playerSkill); SkillUtils.RestoreHealth(victim); @@ -299,7 +341,10 @@ namespace src.player.skills private static void UpdateHUD(PlayerSkill playerSkill) { - if (playerSkill == null || playerSkill.Player == null) return; + if (playerSkill == null) return; + + var player = Utilities.GetPlayerFromIndex((int)playerSkill.PlayerIndex); + if (player == null || !player.IsValid) return; float cooldown = 0; float time1 = (playerSkill.NextUse - Server.TickCount) / 64; @@ -309,26 +354,57 @@ 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 == playerSkill?.Player?.SteamID); + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player.SteamID); if (playerInfo == null) return; if (playerSkill.InfoTime + (64 * 2) > Server.TickCount) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("shade_nospace")}"; + playerInfo.PrintHTML = $"{player.GetTranslation("shade_nospace")}"; else if (cooldown == 0 && duration == 0) playerInfo.PrintHTML = null; else if (duration > 0) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"{duration}")}"; + playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"{duration}")}"; else if (cooldown > 0) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"{cooldown}")}"; + playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"{cooldown}")}"; + } + + public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata) + { + string weaponName = vdata.Name; + if (string.IsNullOrEmpty(weaponName)) return false; + + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return false; + + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) + if (playerSkill.CloneProp == null || playerSkill.Weapons.Contains(econItem.ItemID)) + return false; + + hook.SetReturn(AcquireResult.InvalidItem); + return true; + } + + public static bool WeaponDrop(DynamicHook hook, CCSPlayerController player) + { + if (player == null || !player.IsValid) return false; + + if (playersInfo.TryGetValue(player.Index, out var playerSkill)) + if (playerSkill.CloneProp != null) + { + hook.SetReturn(1); + return true; + } + + return false; } public class PlayerSkill { - public required CCSPlayerController Player { get; set; } - public CDynamicProp? CloneProp { get; set; } + public required uint PlayerIndex { get; set; } + public uint? CloneProp { get; set; } public float NextUse { get; set; } public float UseTime { get; set; } public int InfoTime { get; set; } + public List Weapons { get; set; } = []; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#d0d930", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30, float duration = 10) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs b/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs index 54a7ca1..8449df7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Illiterate.cs @@ -9,7 +9,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Illiterate; private static bool isActive = false; - private static int offset = jRandomSkills.Instance.Random.Next(2, 26); + private static int offset = jRandomSkills.Instance.Random.Next(1, 26); public static void LoadSkill() { @@ -54,8 +54,12 @@ namespace src.player.skills public static string? GetRandomText(string? input) { if (string.IsNullOrEmpty(input)) return null; - if (Server.TickCount % 64 == 0) - offset = jRandomSkills.Instance.Random.Next(2, 26); + + if (Server.TickCount % 64 == 0 || offset == 0) + { + offset = jRandomSkills.Instance.Random.Next(1, 26); + if (offset == 13) offset = 14; + } return new string([.. input.Select(c => { @@ -63,15 +67,14 @@ namespace src.player.skills if (!char.IsLetter(c)) return c; char baseChar = char.IsUpper(c) ? 'A' : 'a'; - return (char)(baseChar + (c - baseChar + offset) % 26); + int shifted = (c - baseChar + offset) % 26; + + return (char)(baseChar + shifted); })]); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1466F5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float maximumFuel = 150f, float fuelConsumption = .64f, float refuelling = .1f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { - public float MaximumFuel { get; set; } = maximumFuel; - public float FuelConsumption { get; set; } = fuelConsumption; - public float Refuelling { get; set; } = refuelling; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs index e57c4d2..614bb31 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Impostor.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Impostor.cs @@ -11,8 +11,8 @@ namespace src.player.skills public class Impostor : ISkill { private const Skills skillName = Skills.Impostor; - private static readonly string defaultCTModel = "characters/models/ctm_sas/ctm_sas.vmdl"; - private static readonly string defaultTModel = "characters/models/tm_phoenix/tm_phoenix.vmdl"; + 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 = []; public static void LoadSkill() @@ -63,6 +63,7 @@ namespace src.player.skills Server.NextFrame(() => { + if (pawn == null || !pawn.IsValid) return; pawn.SetModel(model); var originalRender = pawn.Render; diff --git a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs index 35bac69..0c519a2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs @@ -5,6 +5,7 @@ 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 { @@ -12,8 +13,8 @@ namespace src.player.skills { private const Skills skillName = Skills.Jackal; private static readonly ConcurrentDictionary playersInAction = []; - private static readonly ConcurrentDictionary playersStep = []; - private static readonly string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf"; + private static readonly ConcurrentDictionary playersStep = []; + private static readonly ConcurrentDictionary activeTimers = []; public static void LoadSkill() { @@ -23,9 +24,15 @@ namespace src.player.skills public static void NewRound() { - foreach (var step in playersStep.Values) - if (step != null && step.IsValid) - step.AcceptInput("Kill"); + foreach (var particleIndex in playersStep.Values) + { + if (particleIndex == null) continue; + var particle = Utilities.GetEntityFromIndex((int)particleIndex); + + if (particle != null && particle.IsValid) + particle.AcceptInput("Kill"); + } + playersStep.Clear(); playersInAction.Clear(); } @@ -51,11 +58,15 @@ namespace src.player.skills foreach (var param in playersStep) { - var enemy = param.Key; - var step = param.Value; - if (step == null || !step.IsValid) continue; + var enemyIndex = param.Key; + var particleIndex = param.Value; - var entity = Utilities.GetEntityFromIndex((int)step.Index); + if (particleIndex == null) continue; + + var enemy = Utilities.GetPlayerFromIndex((int)enemyIndex); + if (enemy == null || !enemy.IsValid) continue; + + var entity = Utilities.GetEntityFromIndex((int)particleIndex); if (entity == null || !entity.IsValid) continue; if (!hasSkill || enemy.Team == player.Team) @@ -69,13 +80,17 @@ namespace src.player.skills if (player == null) return; var playerPawn = player.PlayerPawn.Value; + ulong steamID = player.SteamID; + if (activeTimers.TryRemove(steamID, out var oldTimer)) + oldTimer?.Kill(); + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return; - if (!playersStep.ContainsKey(player)) return; + if (!playersStep.ContainsKey(player.Index)) return; CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; if (particle == null) return; - particle.EffectName = particleName; + particle.EffectName = SkillsInfo.GetValue(skillName, "particleName"); particle.StartActive = true; particle.Teleport(playerPawn.AbsOrigin); @@ -84,12 +99,18 @@ namespace src.player.skills particle.AcceptInput("SetParent", playerPawn, particle, "!activator"); particle.AcceptInput("Start"); - playersStep.AddOrUpdate(player, particle, (k, v) => particle); + uint particleId = particle.Index; - Instance.AddTimer(2.5f, () => { + playersStep.AddOrUpdate(player.Index, particle.Index, (k, v) => particle.Index); + + activeTimers[player.SteamID] = Instance.AddTimer(2.5f, () => { + var particle = Utilities.GetEntityFromIndex((int)particleId); if (particle != null && particle.IsValid) particle.AcceptInput("Kill"); - CreatePlayerTrail(player); + + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player != null && player.IsValid && playersStep.ContainsKey(player.Index)) + CreatePlayerTrail(player); }); } @@ -99,23 +120,30 @@ namespace src.player.skills playersInAction.TryAdd(player.SteamID, 0); foreach (var _player in Utilities.GetPlayers().Where(p => p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { - if (!playersStep.ContainsKey(_player)) - playersStep.TryAdd(_player, null); + if (!playersStep.ContainsKey(_player.Index)) + playersStep.TryAdd(_player.Index, null); CreatePlayerTrail(_player); } } public static void DisableSkill(CCSPlayerController player) { - playersStep.TryRemove(player, out _); playersInAction.TryRemove(player.SteamID, out _); + + if (playersStep.TryRemove(player.Index, out var particleIndex) && particleIndex != null) + { + var particle = Utilities.GetEntityFromIndex((int)particleIndex); + if (particle != null && particle.IsValid) + particle.AcceptInput("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 = "", string particleName = "particles/ui/hud/ui_map_def_utility_trail.vpcf") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { - string ParticleName { get; set; } = particleName; + public string ParticleName { get; set; } = particleName; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs index c65faac..d9ac126 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jammer.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jammer.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Jammer : ISkill { private const Skills skillName = Skills.Jammer; - private static readonly ConcurrentDictionary jammedPlayers = []; + private static readonly ConcurrentDictionary jammedPlayers = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -22,8 +22,12 @@ namespace src.player.skills { lock (setLock) { - foreach (var player in jammedPlayers.Keys) + foreach (var playerIndex in jammedPlayers.Keys) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; SetCrosshair(player, true); + } jammedPlayers.Clear(); } foreach (var player in Utilities.GetPlayers()) @@ -67,7 +71,7 @@ namespace src.player.skills return; } - jammedPlayers.TryAdd(enemy, 0); + jammedPlayers.TryAdd(enemy.Index, 0); SetCrosshair(enemy, false); playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jammer_player_info", enemy.PlayerName)); @@ -103,7 +107,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SetCrosshair(player, true); - jammedPlayers.TryRemove(player, out _); + 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 0855998..3474cb6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jester.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jester.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; @@ -12,7 +13,7 @@ namespace src.player.skills public class Jester : ISkill { private const Skills skillName = Skills.Jester; - private static readonly ConcurrentBag jesters = []; + private static readonly ConcurrentDictionary jesters = []; public static void LoadSkill() { @@ -23,7 +24,7 @@ namespace src.player.skills { Server.NextWorldUpdate(() => { - foreach (var jester in jesters.ToList()) + foreach (var jester in jesters.Values) { if (jester.Timer != null) { @@ -71,7 +72,8 @@ namespace src.player.skills var player = @event.Userid; if (player == null || !player.IsValid) return; - var jester = GetJesterInfo(player.SteamID); + ulong steamId = player.SteamID; + var jester = GetJesterInfo(steamId); if (jester == null) return; if (jester.Timer != null) @@ -81,8 +83,7 @@ namespace src.player.skills } jester.Timer = Instance.AddTimer(1, () => { - if (player != null && player.IsValid) - ChangeMode(player.SteamID, false); + ChangeMode(steamId, false); }); } @@ -91,7 +92,8 @@ namespace src.player.skills var player = @event.Userid; if (player == null || !player.IsValid) return; - var jester = GetJesterInfo(player.SteamID); + ulong steamId = player.SteamID; + var jester = GetJesterInfo(steamId); if (jester == null) return; if (jester.Timer != null) @@ -102,7 +104,7 @@ namespace src.player.skills jester.Timer = Instance.AddTimer(1, () => { if (player != null && player.IsValid) - ChangeMode(player.SteamID, false); + ChangeMode(steamId, false); }); } @@ -133,20 +135,18 @@ namespace src.player.skills var maxTime = SkillsInfo.GetValue(skillName, "maxTime"); float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; - jesters.Add(new JesterInfo { - SteamId = player.SteamID, + ulong steamId = player.SteamID; + + jesters.TryAdd(steamId, new JesterInfo { + SteamId = steamId, Active = false, - Timer = Instance.AddTimer(wait, () => ChangeMode(player.SteamID)) + Timer = Instance.AddTimer(wait, () => ChangeMode(steamId)) }); } private static void ChangeMode(ulong steamId, bool? forceActive = null) { - var player = Utilities.GetPlayerFromSteamId(steamId); - if (player == null || !player.IsValid || !player.PawnIsAlive) return; - - var jester = GetJesterInfo(player.SteamID); - if (jester == null) return; + if (!jesters.TryGetValue(steamId, out var jester)) return; if (jester.Timer != null) { @@ -154,6 +154,13 @@ namespace src.player.skills jester.Timer = null; } + var player = Utilities.GetPlayerFromSteamId(steamId); + if (player == null || !player.IsValid || !player.PawnIsAlive) + { + jesters.TryRemove(steamId, out _); + return; + } + bool previousState = jester.Active; jester.Active = forceActive ?? !jester.Active; @@ -167,7 +174,7 @@ namespace src.player.skills var maxTime = SkillsInfo.GetValue(skillName, "maxTime"); float wait = (float)Instance.Random.NextDouble() * (maxTime - minTime) + minTime; - jester.Timer = Instance.AddTimer(wait, () => ChangeMode(player.SteamID)); + jester.Timer = Instance.AddTimer(wait, () => ChangeMode(steamId)); } private static void SetPlayerColor(CCSPlayerController? player, bool forceDisable = false) @@ -208,7 +215,12 @@ namespace src.player.skills playerInfo.PrintHTML = $"{player.GetTranslation("jester_mode")}: {player.GetTranslation(jester.Active ? "jester_on" : "jester_off")}"; } - public static JesterInfo? GetJesterInfo(ulong steamID) => jesters.FirstOrDefault(j => j.SteamId == steamID); + public static JesterInfo? GetJesterInfo(ulong steamID) + { + if (jesters.TryGetValue(steamID, value: out var info)) + return info; + return null; + } public class JesterInfo() { diff --git a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs index ebab4a2..8a63461 100644 --- a/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs +++ b/jRandomSkills - SRC Files/src/player/skills/JumpBan.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class JumpBan : ISkill { private const Skills skillName = Skills.JumpBan; - public static readonly ConcurrentDictionary bannedPlayers = []; + public static readonly ConcurrentDictionary bannedPlayers = []; public static void LoadSkill() { @@ -28,19 +28,25 @@ namespace src.player.skills { var player = @event.Userid; if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; - if (!bannedPlayers.TryGetValue(player.PlayerPawn.Value, out _)) return; - bannedPlayers.AddOrUpdate(player.PlayerPawn.Value, Server.TickCount + 10, (k, v) => Server.TickCount + 10); + if (!bannedPlayers.TryGetValue(player.Index, out _)) return; + bannedPlayers.AddOrUpdate(player.Index, Server.TickCount + 10, (k, v) => Server.TickCount + 10); } public static void OnTick() { foreach (var item in bannedPlayers) { - var pawn = item.Key; + var playerIndex = item.Key; var time = item.Value; + + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid || player.PlayerPawn == null) continue; + + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + if (time > Server.TickCount) - if (pawn != null && pawn.IsValid) - pawn.AbsVelocity.Z = -100; + pawn.AbsVelocity.Z = -100; } if (Server.TickCount % 32 != 0) return; @@ -52,7 +58,7 @@ namespace src.player.skills 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.Index.ToString()))); + ConcurrentBag<(string, string)> menuItems = [.. enemies.Select(e => (e.PlayerName, e.Index.ToString()))]; SkillUtils.UpdateMenu(player, menuItems); } } @@ -78,7 +84,7 @@ namespace src.player.skills return; } - bannedPlayers.AddOrUpdate(enemy.PlayerPawn.Value, 0, (k, v) => 0); + bannedPlayers.AddOrUpdate(enemy.Index, 0, (k, v) => 0); playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("jumpban_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("jumpban_enemy_info")); @@ -103,7 +109,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; - bannedPlayers.TryRemove(player.PlayerPawn.Value, out _); + bannedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs index 575e4cf..001d1c2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs @@ -2,14 +2,9 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Enum; -using CS2TraceRay.Struct; using src.utils; using System.Collections.Concurrent; -using System.Drawing; using static src.jRandomSkills; -using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; namespace src.player.skills { @@ -22,8 +17,6 @@ namespace src.player.skills private static readonly ConcurrentDictionary playersInAction = []; private static readonly MemoryFunctionVoid Shoot_Secondary = new(GameData.GetSignature("Shoot_Secondary")); - private static int i = 0; - public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); @@ -95,40 +88,22 @@ namespace src.player.skills private unsafe static void KnifeHit(CCSPlayerController player, bool heavyHit) { var pawn = player!.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; + if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) + return; - Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue(skillName, "maxDistance"); + var result = RayTrace.EyeTrace(player); + if (result == null || !result.HasValue) + return; - ulong hitboxes = 0x2; - ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | hitboxes; - ulong contents = pawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); + if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null) + return; - if (Config.LoadedConfig.CS2TraceRayDebug) - { - SkillUtils.CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0)); - SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0)); - SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255)); - - if (trace.DidHit()) - { - var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity; - player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}"); - } - else - player.PrintToChat($"Hit: {trace.DidHit()}, Object: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}"); - } - - CEntityInstance entityInstance = new(trace.HitEntity); - if (string.IsNullOrEmpty(entityInstance.DesignerName)) + if (target.Handle == player.Handle || result.Value.Distance() <= 70) + return; + + if (target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid) return; - CBaseEntity entity = entityInstance.As(); - if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) - return; - - if (target.Handle == player.Handle || target.PlayerPawn.Value == null || !target.PlayerPawn.Value.IsValid || trace.Distance() <= 70) return; if (!SkillsInfo.GetValue(skillName, "friendlyFire") && player.Team == target.Team) return; target.PlayerPawn.Value.EmitSound("Player.DamageBody.Onlooker"); diff --git a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs index ab13800..c6edcb6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs @@ -1,13 +1,8 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Enum; -using CS2TraceRay.Struct; using src.utils; -using System.Drawing; using static src.jRandomSkills; -using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; namespace src.player.skills { @@ -34,30 +29,11 @@ namespace src.player.skills var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value; if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_taser") return; - Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue(skillName, "maxDistance"); + var result = RayTrace.EyeTrace(player); + if (result == null || !result.HasValue) + return; - ulong hitboxes = 0x2; - ulong mask = pawn.Collision.CollisionAttribute.InteractsWith | hitboxes; - ulong contents = pawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); - - if (Config.LoadedConfig.CS2TraceRayDebug) - { - SkillUtils.CreateLine(eyePos, endPos, Color.FromArgb(255, 255, 255, 0)); - SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z), Color.FromArgb(255, 255, 0, 0)); - SkillUtils.CreateLine(new Vector(trace.StartPos.X, trace.StartPos.Y, trace.StartPos.Z), new Vector(trace.Position.X, trace.Position.Y, trace.Position.Z), Color.FromArgb(255, 0, 0, 255)); - - if (trace.DidHit()) - { - var val = Activator.CreateInstance(typeof(CBaseEntity), trace.HitEntity) as CBaseEntity; - player.PrintToChat($"Hit: {trace.DidHit()}, Entity: {(val == null ? "null" : val.DesignerName)}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}"); - } - else - player.PrintToChat($"Hit: {trace.DidHit()}, Object: {trace.HitEntity}, Solid: {trace.AllSolid}, Contents: {(Contents)trace.Contents}, Hitbox: {trace.HitboxData[0].HitGroup}"); - } - - if (!trace.HitPlayer(out CCSPlayerController? target) || target == null) + if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null) return; if (target.Handle == player.Handle) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs index c313ae8..41074a7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Magnifier.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Magnifier : ISkill { private const Skills skillName = Skills.Magnifier; - private static readonly ConcurrentDictionary playersFOV = []; + private static readonly ConcurrentDictionary playersFOV = []; public static void LoadSkill() { @@ -19,8 +19,13 @@ namespace src.player.skills public static void NewRound() { - foreach (var player in playersFOV.Keys) + foreach (var playerIndex in playersFOV.Keys) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || player.IsValid) continue; DisableSkill(player); + } + playersFOV.Clear(); foreach (var player in Utilities.GetPlayers()) SkillUtils.CloseMenu(player); @@ -70,8 +75,8 @@ namespace src.player.skills return; } - if (!playersFOV.ContainsKey(enemy)) - playersFOV.TryAdd(enemy, enemy.DesiredFOV); + if (!playersFOV.ContainsKey(enemy.Index)) + playersFOV.TryAdd(enemy.Index, enemy.DesiredFOV); enemy.DesiredFOV = SkillsInfo.GetValue(skillName, "customFOV"); Utilities.SetStateChanged(enemy, "CBasePlayerController", "m_iDesiredFOV"); @@ -98,12 +103,12 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - if (playersFOV.TryGetValue(player, out uint fov)) + if (playersFOV.TryGetValue(player.Index, out uint fov)) { player.DesiredFOV = fov; Utilities.SetStateChanged(player, "CBasePlayerController", "m_iDesiredFOV"); } - playersFOV.TryRemove(player, out _); + playersFOV.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs index 984024f..16f6c52 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs @@ -13,7 +13,7 @@ namespace src.player.skills { private const Skills skillName = Skills.Ninja; private static readonly ConcurrentDictionary invisibilityChanged = []; - private static readonly ConcurrentDictionary invisiblePlayers = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; private static readonly object setLock = new(); @@ -68,22 +68,28 @@ namespace src.player.skills if (targetInfo?.Skill == skillName) isObservingNinja = true; } - foreach (var _player in invisiblePlayers.Keys) - if (player.SteamID != _player.SteamID && !isObservingNinja) + foreach (var playerIndex in invisiblePlayers.Keys) + { + var playerController = Utilities.GetPlayerFromIndex((int)playerIndex); + if (playerController == null || !playerController.IsValid || playerController.SteamID == player.SteamID) + continue; + + if (!isObservingNinja) { - var playerPawn = _player.PlayerPawn.Value; + var playerPawn = playerController.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid) continue; var entity = Utilities.GetEntityFromIndex((int)playerPawn.Index); if (entity == null || !entity.IsValid) continue; info.TransmitEntities.Remove(entity.Index); - var bombIndex = GetBombIndex(_player); + var bombIndex = GetBombIndex(playerController); if (bombIndex == null) continue; var bombEntity = Utilities.GetEntityFromIndex((int)bombIndex); if (bombEntity == null || !bombEntity.IsValid) continue; info.TransmitEntities.Remove(bombEntity.Index); } + } } } @@ -95,7 +101,7 @@ namespace src.player.skills if (playerInfo?.Skill == skillName) UpdateNinja(player); if (!player.PawnIsAlive) - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } } @@ -107,7 +113,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SetPlayerVisibility(player, 0); - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } private static void UpdateNinja(CCSPlayerController? player) @@ -136,14 +142,14 @@ namespace src.player.skills if (percentInvisibility == oldInvisibility) return; - invisibilityChanged.TryAdd(player.Handle, percentInvisibility); + invisibilityChanged.AddOrUpdate(player.Handle, percentInvisibility, (_, _) => percentInvisibility); if (percentInvisibility > .9) - invisiblePlayers.TryAdd(player, 0); + invisiblePlayers.TryAdd(player.Index, 0); else { SetPlayerVisibility(player, percentInvisibility); - invisiblePlayers.TryRemove(player, out _); + invisiblePlayers.TryRemove(player.Index, out _); } } @@ -162,7 +168,7 @@ namespace src.player.skills { var player = @event.Userid; if (player == null || !player.IsValid) return; - if (!invisiblePlayers.ContainsKey(player)) return; + if (!invisiblePlayers.ContainsKey(player.Index)) return; var playerPawn = player.PlayerPawn.Value; if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs index 399833e..1978bdc 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs @@ -41,8 +41,14 @@ namespace src.player.skills { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null) continue; - pawn.AimPunchTickBase = 0; - pawn.AimPunchTickFraction = 0f; + + if (pawn.AimPunchServices != null) + { + pawn.AimPunchServices.PredictableBaseTick = 0; + pawn.AimPunchServices.PredictableBaseTickInterpAmount = 0; + pawn.AimPunchServices.UnpredictableBaseTick = 0; + } + pawn.CameraServices.CsViewPunchAngleTick = 0; pawn.CameraServices.CsViewPunchAngleTickRatio = 0f; } diff --git a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs index 7c05562..1ca494c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Noclip.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Noclip.cs @@ -1,9 +1,8 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Struct; using src.utils; using System.Collections.Concurrent; using static src.jRandomSkills; @@ -93,7 +92,9 @@ namespace src.player.skills var playerPawn = player.PlayerPawn.Value; if (playerPawn?.CBodyComponent == null) return; - if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo)) + ulong steamId = player.SteamID; + + if (SkillPlayerInfo.TryGetValue(steamId, out var skillInfo)) { if (skillInfo.IsFlying) { @@ -109,11 +110,18 @@ namespace src.player.skills skillInfo.IsFlying = true; skillInfo.Cooldown = DateTime.Now; skillInfo.LastPosition = playerPawn.AbsOrigin == null ? null : new Vector(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z); + SetNoclip(player, true); skillInfo.Timer?.Kill(); skillInfo.Timer = Instance.AddTimer(duration, () => { + var player = Utilities.GetPlayerFromSteamId(steamId); + if (player == null || !player.IsValid) return; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == steamId); + if (playerInfo == null) return; + StopFlying(player, skillInfo); }); } @@ -174,54 +182,39 @@ namespace src.player.skills ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; ulong contents = playerPawn.Collision.CollisionGroup; + bool hasGround = false; + Vector stuckVector = new(currentPos.X, currentPos.Y, currentPos.Z); foreach (Vector targetPos in checkOffsets) { Vector start = new(targetPos.X, targetPos.Y, targetPos.Z + 70); Vector end = new(targetPos.X, targetPos.Y, targetPos.Z - 1000); - CGameTrace groundTrace = TraceRay.TraceShape(start, end, mask, contents, player); - if (!groundTrace.DidHit()) continue; + var groundResult = RayTrace.TraceShape(player, start, end, mask, contents); + if (!groundResult.HasValue || !groundResult.Value.DidHit) continue; - hasGround = true; Vector newPos = - groundTrace.EndPos.Z > targetPos.Z - ? new(groundTrace.EndPos.X, groundTrace.EndPos.Y, groundTrace.EndPos.Z) + groundResult.Value.EndPos.Z > targetPos.Z + ? new(groundResult.Value.EndPos.X, groundResult.Value.EndPos.Y, groundResult.Value.EndPos.Z) : targetPos; - if (IsPositionSafe(newPos, player)) + hasGround = true; + stuckVector = newPos; + + var result = RayTrace.TraceHullShape( + targetPos, + targetPos, + player + ); + + if (result.HasValue && !result.Value.DidHit) return newPos; } if (hasGround) skillInfo.Cooldown = DateTime.Now.AddSeconds(-SkillsInfo.GetValue(skillName, "cooldown") + SkillsInfo.GetValue(skillName, "cooldownWhenStuck")); - return hasGround ? currentPos : null; - } - - private static bool IsPositionSafe(Vector pos, CCSPlayerController player) - { - 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; + return hasGround ? stuckVector : null; } public class PlayerSkillInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs index 159bfe9..c0d4e77 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using static src.jRandomSkills; @@ -29,7 +30,15 @@ namespace src.player.skills lock (setLock) { player.Respawn(); - Instance.AddTimer(.2f, () => player.Respawn()); + ulong steamId = player.SteamID; + + Instance.AddTimer(.2f, () => { + var player = Utilities.GetPlayerFromSteamId(steamId); + if (player == null || !player.IsValid) return; + + player.Respawn(); + }); + SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn")); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Planter.cs b/jRandomSkills - SRC Files/src/player/skills/Planter.cs index d4cca24..4eb5496 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Planter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Planter.cs @@ -45,7 +45,10 @@ namespace src.player.skills var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "extraC4BlowTime")); + Server.NextFrame(() => { + if (plantedBomb != null && plantedBomb.IsValid) + plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "extraC4BlowTime"); + }); foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid)) p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "extraC4BlowTime"))); diff --git a/jRandomSkills - SRC Files/src/player/skills/Poison.cs b/jRandomSkills - SRC Files/src/player/skills/Poison.cs index 6319998..03c81b5 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Poison.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Poison.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Poison : ISkill { private const Skills skillName = Skills.Poison; - private static readonly ConcurrentDictionary poisonedPlayers = []; + private static readonly ConcurrentDictionary poisonedPlayers = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -28,10 +28,14 @@ namespace src.player.skills { if (Server.TickCount % (int)(64 * SkillsInfo.GetValue(skillName, "Cooldown")) == 0) { - foreach (var player in poisonedPlayers.Keys) + foreach (var playerIndex in poisonedPlayers.Keys) { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid || player.PlayerPawn == null) continue; + var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) continue; + if (pawn.Health <= SkillsInfo.GetValue(skillName, "MinHealth")) continue; SkillUtils.TakeHealth(pawn, SkillsInfo.GetValue(skillName, "Damage")); } @@ -72,7 +76,7 @@ namespace src.player.skills return; } - poisonedPlayers.TryAdd(enemy, 0); + poisonedPlayers.TryAdd(enemy.Index, 0); playerInfo.SkillUsed = true; player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("poison_player_info", enemy.PlayerName)); enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("poison_enemy_info")); @@ -96,7 +100,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { - poisonedPlayers.TryRemove(player, out _); + poisonedPlayers.TryRemove(player.Index, out _); SkillUtils.CloseMenu(player); } diff --git a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs index 9c1451a..41ed828 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PsychicDefusing.cs @@ -4,14 +4,13 @@ using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; -using CounterStrikeSharp.API.Modules.Entities.Constants; namespace src.player.skills { public class PsychicDefusing : ISkill { private const Skills skillName = Skills.PsychicDefusing; - private static readonly ConcurrentDictionary SkillPlayerInfo = []; + private static readonly ConcurrentDictionary SkillPlayerInfo = []; private static Vector? bombLocation = null; private static readonly float tickRate = 64f; private static readonly object setLock = new(); @@ -35,12 +34,9 @@ namespace src.player.skills var player = @event.Userid; if (player == null || !player.IsValid) return; - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return; - var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill == skillName) - SkillPlayerInfo.TryRemove(pawn, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); } public static void BombPlanted(EventBombPlanted _) @@ -55,15 +51,15 @@ namespace src.player.skills if (bombLocation == null) return; foreach (var skillInfo in SkillPlayerInfo) { - var pawn = skillInfo.Key; + var playerIndex = skillInfo.Key; var info = skillInfo.Value; - var playerController = pawn.Controller.Value; - if (playerController == null || !pawn.Controller.IsValid) return; - - var player = playerController.As(); - if (player == null || !player.IsValid) return; + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid || player.PlayerPawn == null) continue; + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + if (pawn.AbsOrigin == null || SkillUtils.GetDistance(pawn.AbsOrigin, bombLocation) > SkillsInfo.GetValue(skillName, "maxDefusingRange")) { info.Defusing = false; @@ -97,7 +93,8 @@ namespace src.player.skills { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return; - SkillPlayerInfo.TryAdd(pawn, new PlayerSkillInfo + + SkillPlayerInfo.TryAdd(player.Index, new PlayerSkillInfo { SteamID = player.SteamID, Defusing = false, @@ -108,9 +105,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SkillUtils.ResetPrintHTML(player); - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return; - SkillPlayerInfo.TryRemove(pawn, out _); + SkillPlayerInfo.TryRemove(player.Index, out _); } private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo) diff --git a/jRandomSkills - SRC Files/src/player/skills/Push.cs b/jRandomSkills - SRC Files/src/player/skills/Push.cs index 33f7386..fd61bca 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Push.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Push.cs @@ -44,16 +44,16 @@ namespace src.player.skills private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle) { - if (player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || player.PlayerPawn.Value.LifeState != (int)LifeState_t.LIFE_ALIVE) + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.LifeState != (int)LifeState_t.LIFE_ALIVE) return; - var currentPosition = player.PlayerPawn.Value.AbsOrigin; - var currentAngles = player.PlayerPawn.Value.EyeAngles; + var currentPosition = playerPawn.AbsOrigin; Vector newVelocity = SkillUtils.GetForwardVector(attackerAngle) * SkillsInfo.GetValue(skillName, "pushVelocity"); - newVelocity.Z = player.PlayerPawn.Value.AbsVelocity.Z + SkillsInfo.GetValue(skillName, "jumpVelocity"); + newVelocity.Z = playerPawn.AbsVelocity.Z + SkillsInfo.GetValue(skillName, "jumpVelocity"); - player.PlayerPawn.Value.Teleport(currentPosition, currentAngles, newVelocity); + playerPawn.Teleport(currentPosition, null, newVelocity); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1e9ab0", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .3f, float chanceTo = .4f, float jumpVelocity = 300f, float pushVelocity = 400f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs index 2db900b..4f7358f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/QuickShot.cs @@ -30,9 +30,14 @@ namespace src.player.skills var weapon = weaponServices.ActiveWeapon.Value; if (weapon == null || !weapon.IsValid || pawn.CameraServices == null) continue; - - pawn.AimPunchTickBase = 0; - pawn.AimPunchTickFraction = 0f; + + if (pawn.AimPunchServices != null) + { + pawn.AimPunchServices.PredictableBaseTick = 0; + pawn.AimPunchServices.PredictableBaseTickInterpAmount = 0; + pawn.AimPunchServices.UnpredictableBaseTick = 0; + } + pawn.CameraServices.CsViewPunchAngleTick = 0; pawn.CameraServices.CsViewPunchAngleTickRatio = 0f; diff --git a/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs b/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs deleted file mode 100644 index e11a942..0000000 --- a/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs +++ /dev/null @@ -1,274 +0,0 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; -using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Struct; -using src.utils; -using System.Collections.Concurrent; -using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; -using static src.jRandomSkills; - -namespace src.player.skills -{ - public class RCMelon : ISkill - { - private const Skills skillName = Skills.RCMelon; - private static readonly ConcurrentDictionary playersInfo = []; - private const string melonProp = "models/cs_italy/italy_food_melon/italy_food_melon.vmdl"; - private static readonly object setLock = new(); - - public static void LoadSkill() - { - // SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - Instance.AddToManifest(melonProp); - } - - public static void NewRound() - { - foreach (var playerSkill in playersInfo.Values) - KillClone(playerSkill); - lock (setLock) - playersInfo.Clear(); - } - - public static void WeaponPickup(EventItemPickup @event) - { - var player = @event.Userid; - if (player == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) - if (playerSkill.CloneProp != null) - BlockWeapon(player, true); - } - - public static void WeaponEquip(EventItemEquip @event) - { - var player = @event.Userid; - if (player == null) return; - if (playersInfo.TryGetValue(player, out var playerSkill)) - if (playerSkill.CloneProp != null) - BlockWeapon(player, true); - } - - public static void UseSkill(CCSPlayerController player) - { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn?.CBodyComponent == null) return; - - if (playersInfo.TryGetValue(player, out var playerSkill)) - if (playerSkill.CloneProp == null && playerSkill.NextUse <= Server.TickCount) - CreateMelon(playerSkill); - else if (playerSkill.CloneProp != null) - KillClone(playerSkill); - } - - public static void EnableSkill(CCSPlayerController player) - { - if (player.PlayerPawn.Value == null || player.PlayerPawn.Value.CameraServices == null) return; - playersInfo.TryAdd(player, new PlayerSkill - { - Player = player, - CloneProp = null, - NextUse = 0, - UseTime = 0, - PlayerModel = player.PlayerPawn.Value!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName, - }); - } - - public static void DisableSkill(CCSPlayerController player) - { - if (playersInfo.TryGetValue(player, out var playerSkill)) - KillClone(playerSkill); - playersInfo.TryRemove(player, out _); - } - - private static void KillClone(PlayerSkill playerSkill) - { - playerSkill.Player.EmitSound("SolidMetal.BulletImpact"); - if (playerSkill.CloneProp != null && playerSkill.CloneProp.IsValid && playerSkill.CloneProp.AbsOrigin != null && playerSkill.CloneProp.AbsRotation != null) - { - var playerPawn = playerSkill.Player.PlayerPawn.Value; - if (playerPawn != null && playerPawn.IsValid) - { - Vector pos = new(playerSkill.CloneProp.AbsOrigin.X, playerSkill.CloneProp.AbsOrigin.Y, playerSkill.CloneProp.AbsOrigin.Z); - QAngle angle = new(playerSkill.CloneProp.AbsRotation.X, playerSkill.CloneProp.AbsRotation.Y, playerSkill.CloneProp.AbsRotation.Z); - Server.NextFrame(() => - { - playerPawn.Teleport(pos, angle); - }); - } - playerSkill.CloneProp.AcceptInput("Kill"); - playerSkill.CloneProp = null; - } - - BlockWeapon(playerSkill.Player, false); - playerSkill.NextUse = Server.TickCount + SkillsInfo.GetValue(skillName, "Cooldown") * 64; - playerSkill.UseTime = 0; - } - - public static void OnTick() - { - foreach (var playerSkill in playersInfo.Values) - UpdateHUD(playerSkill); - } - - private static CDynamicProp? CreateMelon(PlayerSkill playerSkill) - { - var player = playerSkill.Player; - if (player == null) return null; - - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return null; - - Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * 50; - Vector pos2 = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * (50 + 25); - if (!CheckPosition(player, pos2) || !((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_ONGROUND)) - { - playerSkill.InfoTime = Server.TickCount; - return null; - } - - var clone = Utilities.CreateEntityByName("prop_dynamic"); - 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.DispatchSpawn(); - - Server.NextFrame(() => - { - clone.SetModel(playerSkill.PlayerModel); - clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0)); - - playerPawn.Teleport(pos); - BlockWeapon(playerSkill.Player, true); - playerSkill.UseTime = Server.TickCount; - playerSkill.NextUse = Server.TickCount + 64000; - playerSkill.CloneProp = clone; - - Instance.AddTimer(SkillsInfo.GetValue(skillName, "Duration"), () => - { - if (playerSkill.CloneProp != null) - KillClone(playerSkill); - }); - - playerPawn.SetModel(melonProp); - }); - - return clone; - } - - private unsafe static bool CheckPosition(CCSPlayerController player, Vector endPos) - { - var playerPawn = player.PlayerPawn.Value; - if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return false; - - Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 25); - endPos.Z += 25; - - ulong mask = playerPawn.Collision.CollisionAttribute.InteractsWith; - ulong contents = playerPawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(eyePos, endPos, mask, contents, player); - - return !trace.DidHit(); - } - - 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; - - if (string.IsNullOrEmpty(param.Entity.Name)) return; - if (!param.Entity.Name.StartsWith("IanaClone_")) return; - - var nameParams = param.Entity.Name.Split('_')[2]; - _ = ulong.TryParse(nameParams, out ulong steamID); - if (steamID == 0) return; - - var player = Utilities.GetPlayerFromSteamId(steamID); - if (player == null) return; - - if (playersInfo.TryGetValue(player, out var playerSkill)) - { - KillClone(playerSkill); - var playerPawn = player.PlayerPawn.Value; - if (playerPawn != null) - SkillUtils.TakeHealth(playerPawn, (int)param2.Damage); - } - } - - public static void PlayerHurt(EventPlayerHurt @event) - { - var victim = @event.Userid!; - if (!Instance.IsPlayerValid(victim)) return; - - if (playersInfo.TryGetValue(victim, out var playerSkill) && playerSkill.CloneProp != null) - { - KillClone(playerSkill); - SkillUtils.RestoreHealth(victim); - } - } - - private static void BlockWeapon(CCSPlayerController player, bool block) - { - if (player == null || !player.IsValid) return; - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return; - - foreach (var weapon in pawn.WeaponServices.MyWeapons) - if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) - { - weapon.Value.NextPrimaryAttackTick = block ? int.MaxValue : Server.TickCount; - weapon.Value.NextSecondaryAttackTick = block ? int.MaxValue : Server.TickCount; - - Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextPrimaryAttackTick"); - Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick"); - } - } - - private static void UpdateHUD(PlayerSkill playerSkill) - { - if (playerSkill == null || playerSkill.Player == null) return; - - float cooldown = 0; - float time1 = (playerSkill.NextUse - Server.TickCount) / 64; - cooldown = (int)Math.Ceiling(Math.Max(time1, 0)); - - float duration = 0; - float time2 = SkillsInfo.GetValue(skillName, "Duration") - (Server.TickCount - playerSkill.UseTime) / 64; - duration = (int)Math.Ceiling(Math.Max(time2, 0)); - - var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID); - if (playerInfo == null) return; - - if (playerSkill.InfoTime + (64 * 2) > Server.TickCount) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("shade_nospace")}"; - else if (cooldown == 0 && duration == 0) - playerInfo.PrintHTML = null; - else if (duration > 0) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"{duration}")}"; - else if (cooldown > 0) - playerInfo.PrintHTML = $"{playerSkill?.Player.GetTranslation("hud_info", $"{cooldown}")}"; - } - - public class PlayerSkill - { - public required CCSPlayerController Player { get; set; } - public CDynamicProp? CloneProp { get; set; } - public float NextUse { get; set; } - public float UseTime { get; set; } - public int InfoTime { get; set; } - public string PlayerModel { get; set; } - } - - public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#d0d930", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30, float duration = 10) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) - { - public float Cooldown { get; set; } = cooldown; - public float Duration { get; set; } = duration; - } - } -} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs index 5259dae..4f0ddd7 100644 --- a/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs +++ b/jRandomSkills - SRC Files/src/player/skills/RandomWeapon.cs @@ -1,10 +1,10 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; +using src.utils; +using System.Collections.Concurrent; using System.Collections.Immutable; using static src.jRandomSkills; -using System.Collections.Concurrent; -using src.utils; namespace src.player.skills { @@ -113,7 +113,7 @@ namespace src.player.skills ConcurrentBag weaponList = [.. pistols.Concat(rifles).Where(w => !playerWeapons.Contains(w))]; - if (weaponList.Count == 0) + if (weaponList.IsEmpty) return; string weapon = weaponList.ToArray()[Instance.Random.Next(weaponList.Count)]; @@ -131,8 +131,12 @@ namespace src.player.skills } } + ulong steamId = player.SteamID; Instance.AddTimer(.1f, () => { + var player = Utilities.GetPlayerFromSteamId(steamId); + if (player == null || !player.IsValid) return; + player.GiveNamedItem(weapon); }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs index 409740c..5f46fcf 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs @@ -1,17 +1,18 @@ 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 System.Drawing; using static src.jRandomSkills; -using System.Collections.Concurrent; -using src.utils; namespace src.player.skills { public class ReZombie : ISkill { private const Skills skillName = Skills.ReZombie; - private static readonly ConcurrentDictionary zombies = []; + private static readonly ConcurrentDictionary zombies = []; private static readonly object setLock = new(); public static void LoadSkill() @@ -21,14 +22,27 @@ namespace src.player.skills public static void EnableSkill(CCSPlayerController player) { - zombies.TryRemove(player, out _); + zombies.TryRemove(player.Index, out _); } public static void DisableSkill(CCSPlayerController player) { if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return; - zombies.TryRemove(player, out _); + zombies.TryRemove(player.Index, out _); SetPlayerColor(player.PlayerPawn.Value, true); + ResetHealth(player); + } + + public static void ResetHealth(CCSPlayerController player) + { + var pawn = player.PlayerPawn?.Value; + if (pawn == null) return; + + pawn.MaxHealth = 100; + Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iMaxHealth"); + + pawn.Health = Math.Min(pawn.Health, 100); + Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth"); } public static void WeaponEquip(EventItemEquip @event) @@ -36,46 +50,88 @@ namespace src.player.skills var player = @event.Userid; var weapon = @event.Item; if (player == null || !player.IsValid) return; - if (!zombies.ContainsKey(player) || weapon == "c4") return; + if (!zombies.ContainsKey(player.Index) || weapon == "c4") return; player.ExecuteClientCommand("slot3"); } public static void NewRound() { - foreach (var player in zombies.Keys) + foreach (var playerIndex in zombies.Keys) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; + DisableSkill(player); + } zombies.Clear(); } public static void PlayerDeath(EventPlayerDeath @event) { var player = @event.Userid; - if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.ContainsKey(player)) return; + if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid || zombies.ContainsKey(player.Index)) return; var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; var pawn = player.PlayerPawn.Value; if (pawn.AbsOrigin == null) return; - Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); - QAngle deadRotation = new(pawn.EyeAngles.X, pawn.EyeAngles.Y, pawn.EyeAngles.Z); + Vector deadPosition = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z); + QAngle angle = new(pawn.V_angle.X, pawn.V_angle.Y, 0); + + ulong steamID = player.SteamID; player.Respawn(); + Instance.AddTimer(.2f, () => { 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; + var zombieHealth = SkillsInfo.GetValue(skillName, "zombieHealth"); + player.Respawn(); - zombies.TryAdd(player, 0); + zombies.TryAdd(player.Index, 0); + SetPlayerColor(pawn, false); SkillUtils.AddHealth(pawn, zombieHealth - 100, zombieHealth); - pawn.Teleport(deadPosition, deadRotation); + + pawn.Teleport(deadPosition); + pawn.Look(angle); player.ExecuteClientCommand("slot3"); - Instance.AddTimer(1, () => player.ExecuteClientCommand("slot3")); + + Instance.AddTimer(1, () => { + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player == null || !player.IsValid || !player.PlayerPawn.IsValid) return; + + player.ExecuteClientCommand("slot3"); + }); } }); } + public static bool OnWeaponCanAcquire(DynamicHook hook, CCSPlayerController player, CEconItemView econItem, CCSWeaponBaseVData vdata) + { + string weaponName = vdata.Name; + if (string.IsNullOrEmpty(weaponName)) return false; + + if (!zombies.ContainsKey(player.Index)) + return false; + + if (weaponName.Contains("knife") || weaponName.Contains("bayonet")) + return false; + + var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); + if (playerInfo?.Skill != skillName) return false; + + hook.SetReturn(AcquireResult.InvalidItem); + return true; + } + private static void SetPlayerColor(CCSPlayerPawn pawn, bool normal) { var color = normal ? Color.FromArgb(255, 255, 255, 255) : Color.FromArgb(255, 255, 0, 0); @@ -83,7 +139,7 @@ namespace src.player.skills Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender"); } - 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 zombieHealth = 250) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + 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 zombieHealth = 500) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public int ZombieHealth { get; set; } = zombieHealth; } diff --git a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs index f96ffa7..45d65e0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs @@ -5,6 +5,7 @@ using CounterStrikeSharp.API.Modules.Utils; using static src.jRandomSkills; using System.Collections.Concurrent; using src.utils; +using CounterStrikeSharp.API.Modules.Memory; namespace src.player.skills { @@ -102,13 +103,13 @@ namespace src.player.skills private static void CreateReplica(CCSPlayerController player) { var playerPawn = player.PlayerPawn.Value; - var replica = Utilities.CreateEntityByName("prop_dynamic_override"); - if (replica == null || playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) + return; + + var replica = Utilities.CreateEntityByName("prop_dynamic_override"); + if (replica == null || !replica.IsValid) return; - float distance = 40; - Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance; - replica.Flags = playerPawn.Flags; replica.Flags |= (uint)Flags_t.FL_DUCKING; replica.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; @@ -116,12 +117,13 @@ namespace src.player.skills replica.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName); replica.Entity!.Name = replica.Globalname = $"Replica_{Server.TickCount}_{(player.Team == CsTeam.CounterTerrorist ? "CT" : "TT")}"; - replica.UseAnimGraph = false; - string animName = "idle_for_turns_stand_pistol"; - if (((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING)) - animName = "idle_for_turns_crouch_pistol"; + replica.UseAnimGraph = true; + replica.AnimGraphUpdateEnabled = true; + bool isDucking = ((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING); + + float distance = 40; + Vector pos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance; - replica.AcceptInput("SetAnimation", value: animName); replica.Teleport(pos, playerPawn.AbsRotation, null); replica.DispatchSpawn(); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs index 0964254..50c2605 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Rubber.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Rubber.cs @@ -10,7 +10,7 @@ namespace src.player.skills public class Rubber: ISkill { private const Skills skillName = Skills.Rubber; - private static readonly ConcurrentDictionary playersToSlow = []; + private static readonly ConcurrentDictionary playersToSlow = []; public static void LoadSkill() { @@ -35,25 +35,33 @@ namespace src.player.skills var rubberTime = SkillsInfo.GetValue(skillName, "slownessTime"); if (attackerInfo?.Skill == skillName) - playersToSlow.AddOrUpdate(victimPawn, Server.TickCount + (64 * rubberTime), (k, v) => Server.TickCount + (64 * rubberTime)); + playersToSlow.AddOrUpdate(victim.Index, Server.TickCount + (64 * rubberTime), (k, v) => Server.TickCount + (64 * rubberTime)); } public static void OnTick() { foreach(var item in playersToSlow) { - var pawn = item.Key; + var playerIndex = item.Key; var time = item.Value; + + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; + if (time >= Server.TickCount) - ChangeVelocity(pawn); + ChangeVelocity(player); else playersToSlow.TryRemove(item.Key, out _); } } - private static void ChangeVelocity(CCSPlayerPawn pawn) + private static void ChangeVelocity(CCSPlayerController player) { + if (player.PlayerPawn == null) return; + + var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid) return; + pawn.VelocityModifier = SkillsInfo.GetValue(skillName, "slownessModifier"); } diff --git a/jRandomSkills - SRC Files/src/player/skills/Saper.cs b/jRandomSkills - SRC Files/src/player/skills/Saper.cs index 1b8da9f..c4744a6 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Saper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Saper.cs @@ -25,7 +25,10 @@ namespace src.player.skills { var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.DefuseCountDown = 0); + Server.NextFrame(() => { + if (plantedBomb != null && plantedBomb.IsValid) + plantedBomb.DefuseCountDown = 0; + }); } } } diff --git a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs index aa23ce6..a67a4a0 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SecondLife.cs @@ -43,7 +43,7 @@ namespace src.player.skills var spawnpoint = SkillUtils.GetSpawnPointVector(victim); if (spawnpoint == null) return; - victimPawn.Teleport(spawnpoint, victimPawn.AbsRotation, null); + victimPawn.Teleport(spawnpoint, null, null); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/Shade.cs b/jRandomSkills - SRC Files/src/player/skills/Shade.cs index bd85b22..3478a7e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Shade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Shade.cs @@ -1,8 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using CS2TraceRay.Class; -using CS2TraceRay.Struct; using static src.jRandomSkills; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; using System.Collections.Concurrent; @@ -13,7 +11,7 @@ namespace src.player.skills public class Shade : ISkill { private const Skills skillName = Skills.Shade; - private static readonly ConcurrentDictionary noSpace = []; + private static readonly ConcurrentDictionary noSpace = []; public static void LoadSkill() { @@ -44,25 +42,32 @@ namespace src.player.skills { var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); 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"); } public static void DisableSkill(CCSPlayerController player) { - noSpace.TryRemove(player, out _); + noSpace.TryRemove(player.Index, out _); SkillUtils.ResetPrintHTML(player); } public static void OnTick() { - foreach (var item in noSpace) - if (item.Value >= Server.TickCount) - UpdateHUD(item.Key); + foreach (var (playerIndex, time) in noSpace) + { + var player = Utilities.GetPlayerFromIndex((int)playerIndex); + if (player == null || !player.IsValid) continue; + + if (time >= Server.TickCount) + UpdateHUD(player); else - SkillUtils.ResetPrintHTML(item.Key); + SkillUtils.ResetPrintHTML(player); + } } private static void UpdateHUD(CCSPlayerController player) @@ -72,45 +77,29 @@ namespace src.player.skills playerInfo.PrintHTML = $"{player.GetTranslation("shade_nospace")}"; } - private unsafe static bool CheckTeleport(CCSPlayerController player, Vector startPos, Vector endPos) + private unsafe static bool CheckTeleport(CCSPlayerController attacker, CCSPlayerController victim, Vector startPos, Vector endPos, QAngle angle) { - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid) return false; + var attackerPawn = attacker.PlayerPawn.Value; + if (attackerPawn == null || !attackerPawn.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); + var victimPawn = attacker.PlayerPawn.Value; + if (victimPawn == null || !victimPawn.IsValid) return false; - ulong mask = pawn.Collision.CollisionAttribute.InteractsWith; - ulong contents = pawn.Collision.CollisionGroup; - CGameTrace trace = TraceRay.TraceShape(startPos, endPos, mask, contents, player); + var result = RayTrace.TraceHullShape( + startPos, + endPos, + victim, + attackerPawn.Collision.Mins, + attackerPawn.Collision.Maxs, + null, + null, + angle + ); - if (trace.DidHit()) return false; - return IsPositionSafe(player, endPos); - } + if (!result.HasValue) + return false; - 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; + return !result.Value.DidHit; } private static void TeleportAttackerBehindVictim(CCSPlayerController attacker, CCSPlayerController victim) @@ -133,7 +122,7 @@ namespace src.player.skills Vector direction = SkillUtils.GetForwardVector(targetAngle); Vector targetPos = victimPos - (direction * distance); - if (CheckTeleport(victim, victimPos, targetPos)) + if (CheckTeleport(attacker, victim, victimPos, targetPos, targetAngle)) { attackerPawn.Teleport(targetPos, targetAngle, Vector.Zero); teleported = true; @@ -142,7 +131,7 @@ namespace src.player.skills } if (!teleported) - noSpace.AddOrUpdate(attacker, Server.TickCount + (64 * 2), (_, _) => Server.TickCount + (64 * 2)); + noSpace.AddOrUpdate(attacker.Index, 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 a38f4e4..5cbf13d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ShortBomb.cs @@ -25,7 +25,10 @@ namespace src.player.skills var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); if (plantedBomb != null) - Server.NextFrame(() => plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "detonationTime")); + Server.NextFrame(() => { + if (plantedBomb != null && plantedBomb.IsValid) + plantedBomb.C4Blow = Server.CurrentTime + SkillsInfo.GetValue(skillName, "detonationTime"); + }); foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid)) p.PrintToCenterAlert(p.GetTranslation("bombplanted", SkillsInfo.GetValue(skillName, "detonationTime"))); diff --git a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs index 2a2a959..5bb1082 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Smoker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Smoker.cs @@ -1,5 +1,6 @@ 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; @@ -50,12 +51,16 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID); if (playerInfo?.Skill != skillName) return; + ulong steamID = player.SteamID; + Vector pos = new(@event.X, @event.Y, @event.Z); float refillInterval = 15.5f; Timer? smokeTimer = null; smokeTimer = Instance.AddTimer(refillInterval, () => { + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player == null || !player.IsValid) { smokeTimer?.Kill(); diff --git a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs index 68483ec..ed1b35c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SniperElite.cs @@ -166,7 +166,10 @@ namespace src.player.skills } Instance.AddTimer(.15f, () => { - if (player != null && player.IsValid && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) + var player = Utilities.GetPlayerFromSteamId(steamID); + if (player == null || !player.IsValid) return; + + if (player != null && player.IsValid && player.PlayerPawn != null && player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid) { var createdWeapon = player.PlayerPawn.Value?.ItemServices?.As().GiveNamedItem(weaponToGive.Replace("_script", "")); diff --git a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs index 281c040..dda8f7b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Spectator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Spectator.cs @@ -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() { @@ -20,9 +20,13 @@ namespace src.player.skills public static void NewRound() { - foreach (var camera in cameras) - if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) - camera.Value.Item2.AcceptInput("Kill"); + foreach (var info in cameras) + { + var cam = Utilities.GetEntityFromIndex((int)info.Value.Item2); + if (cam != null && cam.IsValid) + cam.AcceptInput("Kill"); + } + cameras.Clear(); } @@ -54,10 +58,24 @@ namespace src.player.skills public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { - var pawn = cameraInfo.Item3; - if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE + + var enemy = Utilities.GetPlayerFromIndex((int)cameraInfo.Item3); + if (enemy == null || !enemy.IsValid || enemy.PlayerPawn == null) + { + ChangeCamera(player, true); + return; + } + + var enemyPawn = player.PlayerPawn.Value; + if (enemyPawn == null || !enemyPawn.IsValid) + { + ChangeCamera(player, true); + return; + } + + if (enemyPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE || (player.PlayerPawn.Value != null && player.PlayerPawn.Value.LifeState != (byte)LifeState_t.LIFE_ALIVE)) ChangeCamera(player, true); } @@ -70,10 +88,14 @@ 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 != null && cameraInfo.Item2.IsValid) + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; - cameraInfo.Item2.AcceptInput("Kill"); + + var cam = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); + if (cam != null && cam.IsValid) + cam.AcceptInput("Kill"); + if (!forceToDefault) newCameraRaw = CreateCamera(player); } else @@ -109,22 +131,25 @@ namespace src.player.skills var pawn = enemy.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.CameraServices == null || pawn.AbsOrigin == null) return 0; - var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue(skillName, "distance"); + QAngle angle = new(0, pawn.EyeAngles.Y, 0); + + var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(angle) * SkillsInfo.GetValue(skillName, "distance"); pos.Z += pawn.ViewOffset.Z; Server.NextFrame(() => { + if (camera == null || !camera.IsValid) return; camera.SetModel("models/actors/ghost_speaker.vmdl"); camera.Render = Color.FromArgb(0, 255, 255, 255); - camera.Teleport(pos, new QAngle(0, pawn.EyeAngles.Y, 0)); + camera.Teleport(pos, angle); camera.DispatchSpawn(); camera.AcceptInput("SetParent", pawn, pawn, "!activator"); }); if (cameras.TryGetValue(player.SteamID, out var cameraInfo)) - cameras.AddOrUpdate(player.SteamID, (cameraInfo.Item1, camera, pawn), (k, v) => (cameraInfo.Item1, camera, pawn)); + cameras.AddOrUpdate(player.SteamID, (cameraInfo.Item1, camera.Index, player.Index), (k, v) => (cameraInfo.Item1, camera.Index, player.Index)); else - cameras.AddOrUpdate(player.SteamID, (pawn.CameraServices.ViewEntity.Raw, camera, pawn), (k, v) => (pawn.CameraServices.ViewEntity.Raw, camera, pawn)); + cameras.AddOrUpdate(player.SteamID, (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 cee4aea..d2fc530 100644 --- a/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs +++ b/jRandomSkills - SRC Files/src/player/skills/SwapPosition.cs @@ -123,15 +123,18 @@ namespace src.player.skills if (attackerPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsOrigin == null || victimPawn.AbsRotation == null) return; Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z); - QAngle attackerAngles = new(attackerPawn.AbsRotation.X, attackerPawn.AbsRotation.Y, attackerPawn.AbsRotation.Z); + QAngle attackerAngles = new(attackerPawn.V_angle.X, attackerPawn.V_angle.Y, 0); Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z); Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z); - QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z); + QAngle victimAngles = new(victimPawn.V_angle.X, victimPawn.V_angle.Y, 0); Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z); - victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity); - attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity); + victimPawn.Teleport(attackerPosition, null, attackerVelocity); + attackerPawn.Teleport(victimPosition, null, victimVelocity); + + victimPawn.Look(attackerAngles); + attackerPawn.Look(victimAngles); } public class ZamianaMiejsc_PlayerInfo diff --git a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs index 85d628d..0673350 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Teleporter.cs @@ -49,15 +49,18 @@ namespace src.player.skills if (attackerPawn.AbsOrigin == null || victimPawn.AbsOrigin == null || attackerPawn.AbsRotation == null || victimPawn.AbsRotation == null) return; Vector attackerPosition = new(attackerPawn.AbsOrigin.X, attackerPawn.AbsOrigin.Y, attackerPawn.AbsOrigin.Z); - QAngle attackerAngles = new(attackerPawn.AbsRotation.X, attackerPawn.AbsRotation.Y, attackerPawn.AbsRotation.Z); + QAngle attackerAngles = new(attackerPawn.V_angle.X, attackerPawn.V_angle.Y, 0); Vector attackerVelocity = new(attackerPawn.AbsVelocity.X, attackerPawn.AbsVelocity.Y, attackerPawn.AbsVelocity.Z); Vector victimPosition = new(victimPawn.AbsOrigin.X, victimPawn.AbsOrigin.Y, victimPawn.AbsOrigin.Z); - QAngle victimAngles = new(victimPawn.AbsRotation.X, victimPawn.AbsRotation.Y, victimPawn.AbsRotation.Z); + QAngle victimAngles = new(victimPawn.V_angle.X, victimPawn.V_angle.Y, 0); Vector victimVelocity = new(victimPawn.AbsVelocity.X, victimPawn.AbsVelocity.Y, victimPawn.AbsVelocity.Z); - victimPawn.Teleport(attackerPosition, attackerAngles, attackerVelocity); - attackerPawn.Teleport(victimPosition, victimAngles, victimVelocity); + victimPawn.Teleport(attackerPosition, null, attackerVelocity); + attackerPawn.Teleport(victimPosition, null, victimVelocity); + + victimPawn.Look(attackerAngles); + attackerPawn.Look(victimAngles); } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8A2BE2", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .5f, float chanceTo = .6f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/Thief.cs b/jRandomSkills - SRC Files/src/player/skills/Thief.cs index 99b585e..a917a52 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thief.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thief.cs @@ -120,10 +120,19 @@ namespace src.player.skills 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; + 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 player = Utilities.GetPlayerFromSteamId(playerSteamId); + if (player == null || !player.IsValid) return; + Instance.SkillAction(skillName.ToString(), "EnableSkill", [player]); player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("thief_incorrect_skill", enemy.PlayerName)); }); @@ -133,24 +142,42 @@ namespace src.player.skills SkillUtils.CloseMenu(player); Instance.AddTimer(.1f, () => { + var enemy = Utilities.GetPlayerFromSteamId(enemySteamId); + if (enemy == null || !enemy.IsValid) return; + + var player = Utilities.GetPlayerFromSteamId(playerSteamId); + if (player == null || !player.IsValid) return; + playerInfo.Skill = enemySkill; playerInfo.SpecialSkill = skillName; + SkillUtils.CloseMenu(player); Instance.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); + player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("thief_player_info", enemy.PlayerName)); if (SkillsInfo.GetValue(enemySkill, "disableOnFreezeTime") && SkillUtils.IsFreezeTime()) Instance?.AddTimer(Math.Max((float)(Event.GetFreezeTimeEnd() - DateTime.Now).TotalSeconds, 0), () => { + var player = Utilities.GetPlayerFromSteamId(playerSteamId); + 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", new[] { player }); + Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); }); else - Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", new[] { player }); + Instance?.SkillAction(enemySkill.ToString(), "EnableSkill", [player]); }); Instance.AddTimer(.1f, () => { + var enemyInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == enemySteamId); + if (enemyInfo == null) return; + + var enemy = Utilities.GetPlayerFromSteamId(enemySteamId); + if (enemy == null || !enemy.IsValid) return; + Instance.SkillAction(enemySkill.ToString(), "DisableSkill", [enemy]); + enemyInfo.SpecialSkill = enemySkill; enemyInfo.Skill = Skills.None; enemy.PrintToChat($" {ChatColors.Red}" + enemy.GetTranslation("thief_enemy_info")); diff --git a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs index 2eac8c1..e9f1954 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs @@ -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() @@ -20,9 +20,13 @@ namespace src.player.skills public static void NewRound() { - foreach (var camera in cameras) - if (camera.Value.Item2 != null && camera.Value.Item2.IsValid) - camera.Value.Item2.AcceptInput("Kill"); + foreach (var cameraIndex in cameras.Values) + { + var camera = Utilities.GetEntityFromIndex((int)cameraIndex.Item2); + if (camera != null && camera.IsValid) + camera.AcceptInput("Kill"); + } + lock (setLock) cameras.Clear(); } @@ -42,7 +46,7 @@ namespace src.player.skills public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { var pawn = player.PlayerPawn.Value; if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue; @@ -55,7 +59,7 @@ namespace src.player.skills var pos = pawn.AbsOrigin - SkillUtils.GetForwardVector(pawn.EyeAngles) * SkillsInfo.GetValue(skillName, "distance"); pos.Z += pawn.ViewOffset.Z; - var cam = cameraInfo.Item2; + var cam = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); if (cam == null || cam.AbsOrigin == null || cam.AbsRotation == null) continue; cam.Teleport(pos, pawn.V_angle); } @@ -66,10 +70,14 @@ namespace src.player.skills uint orginalCameraRaw; uint newCameraRaw; var pawn = player.PlayerPawn.Value; - if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2.IsValid) + if (cameras.TryGetValue(player.SteamID, out var cameraInfo) && cameraInfo.Item2 != 0) { orginalCameraRaw = cameraInfo.Item1; - newCameraRaw = cameraInfo.Item2.EntityHandle.Raw; + + var cam = Utilities.GetEntityFromIndex((int)cameraInfo.Item2); + if (cam == null || !cam.IsValid) return; + + newCameraRaw = cam.EntityHandle.Raw; } else { @@ -100,13 +108,14 @@ namespace src.player.skills Server.NextFrame(() => { + if (camera == null || !camera.IsValid) return; camera.SetModel("models/actors/ghost_speaker.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), (v, k) => (pawn.CameraServices!.ViewEntity.Raw, camera)); + cameras.AddOrUpdate(player.SteamID, (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/ThrowingKnife.cs b/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs index 207e089..714de46 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs @@ -129,7 +129,7 @@ namespace src.player.skills if (trigger != null && trigger.IsValid) Server.NextFrame(() => { - if (trigger.IsValid) + if (trigger != null && trigger.IsValid) trigger.AcceptInput("Kill"); }); } @@ -140,7 +140,7 @@ namespace src.player.skills if (glow != null && glow.IsValid) Server.NextFrame(() => { - if (glow.IsValid) + if (glow != null && glow.IsValid) glow.AcceptInput("Kill"); }); } @@ -151,7 +151,7 @@ namespace src.player.skills if (relay != null && relay.IsValid) Server.NextFrame(() => { - if (relay.IsValid) + if (relay != null && relay.IsValid) relay.AcceptInput("Kill"); }); } @@ -178,7 +178,11 @@ namespace src.player.skills if (weapon == null || !weapon.IsValid || (!weapon.DesignerName.Contains("knife") && !weapon.DesignerName.Contains("bayonet"))) return; player.DropActiveWeapon(); - Server.NextFrame(() => ThrowKnife(player, weapon) ); + Server.NextFrame(() => { + if (player == null || !player.IsValid) return; + if (weapon == null || !weapon.IsValid) return; + ThrowKnife(player, weapon); + }); }); } diff --git a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs index 2ddad5c..303a4c3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs @@ -65,6 +65,7 @@ namespace src.player.skills Server.NextFrame(() => { + if (entity == null || !entity.IsValid) return; var smoke = entity.As(); smoke.SmokeColor.X = 255; smoke.SmokeColor.Y = 0; diff --git a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs index e3a7b70..a7a5289 100644 --- a/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs +++ b/jRandomSkills - SRC Files/src/player/skills/WeaponsSwap.cs @@ -133,6 +133,8 @@ namespace src.player.skills Server.NextFrame(() => { + if (player == null || !player.IsValid) return; + if (enemy == null || !enemy.IsValid) return; player.RemoveWeapons(); enemy.RemoveWeapons(); GiveWeapons(player, enemyWeapon, playerWeapon.Contains("weapon_c4")); diff --git a/jRandomSkills - SRC Files/src/utils/Config.cs b/jRandomSkills - SRC Files/src/utils/Config.cs index c3af6d1..043ce3c 100644 --- a/jRandomSkills - SRC Files/src/utils/Config.cs +++ b/jRandomSkills - SRC Files/src/utils/Config.cs @@ -88,7 +88,7 @@ namespace src.utils public bool DisplayAlwaysDescription { get; set; } public bool DisableSpectateHUD { get; set; } public bool FlashingHtmlHudFix { get; set; } - public bool CS2TraceRayDebug { get; set; } + public bool TraceRayBeam { get; set; } public string DisableHUDOnDeathPermission { get; set; } public bool DisableSkillsOnRoundEnd { get; set; } public LanguageSystem LanguageSystem { get; set; } @@ -112,7 +112,7 @@ namespace src.utils SkillDescriptionDuration = 7; DisplayAlwaysDescription = false; FlashingHtmlHudFix = true; - CS2TraceRayDebug = false; + TraceRayBeam = false; DisableSpectateHUD = false; DisableHUDOnDeathPermission = "@jRandomSkills/death"; DisableSkillsOnRoundEnd = false; @@ -180,6 +180,7 @@ namespace src.utils SetStaticSkillCommand = new NormalCommand("ustawstatycznyskill, ustaw_statyczny_skill, setstaticskill, set_static_skill", "@jRandomSkills/admin"), ChangeLanguageCommand = new NormalCommand("lang, language, changelang, change_lang, jezyk, język", ""), ReloadCommand = new NormalCommand("reload, refresh", "@jRandomSkills/admin"), + NextCommand = new NormalCommand("next_skill", "@jRandomSkills/admin"), }; VotingCommands = new VotingCommands @@ -259,6 +260,7 @@ namespace src.utils public required NormalCommand SetStaticSkillCommand { get; set; } public required NormalCommand ChangeLanguageCommand { get; set; } public required NormalCommand ReloadCommand { get; set; } + public required NormalCommand NextCommand { get; set; } } public class VotingCommand(bool enableVoting, string alias, string permissions, float timeToVote, float percentagesToSuccess, float timeToNextVoting, float timeToNextSameVoting, int minimumPlayersToStartVoting) : NormalCommand(alias, permissions) diff --git a/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs b/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs new file mode 100644 index 0000000..8a41399 --- /dev/null +++ b/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs @@ -0,0 +1,36 @@ +using RayTraceAPI; +using System.Numerics; +using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; + +namespace jRandomSkills.src.utils +{ + public struct CustomTraceResult (TraceResult result, Vector startPos, ulong mask, ulong contents, bool drawBeam) + { + public float StartPosX = startPos.X; + public float StartPosY = startPos.Y; + public float StartPosZ = startPos.Z; + + public float EndPosX = result.EndPosX; + public float EndPosY = result.EndPosY; + public float EndPosZ = result.EndPosZ; + + public nint HitEntity = result.HitEntity; + public float Fraction = result.Fraction; + public int AllSolid = result.AllSolid; + + public float NormalX = result.NormalX; + public float NormalY = result.NormalY; + public float NormalZ = result.NormalZ; + + public ulong InteractsWith = mask; + public ulong InteractsExclude = contents; + public bool DrawBeam = drawBeam; + + public readonly Vector3 StartPos => new(StartPosX, StartPosY, StartPosZ); + public readonly Vector3 EndPos => new(EndPosX, EndPosY, EndPosZ); + public readonly Vector3 Normal => new(NormalX, NormalY, NormalZ); + public readonly float Distance => Vector3.Distance(StartPos, EndPos); + public readonly bool DidHit => Fraction < 1f; + public readonly bool IsAllSolid => AllSolid != 0; + } +} diff --git a/jRandomSkills - SRC Files/src/utils/RayTrace.cs b/jRandomSkills - SRC Files/src/utils/RayTrace.cs new file mode 100644 index 0000000..c28af98 --- /dev/null +++ b/jRandomSkills - SRC Files/src/utils/RayTrace.cs @@ -0,0 +1,299 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; +using CounterStrikeSharp.API.Modules.Utils; +using jRandomSkills.src.utils; +using RayTraceAPI; +using System.Drawing; +using System.Numerics; +using TraceOptions = RayTraceAPI.TraceOptions; +using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; + +namespace src.utils +{ + public static class RayTrace + { + private static PluginCapability RayTraceInterface { get; } = new("raytrace:craytraceinterface"); + + public static CustomTraceResult? TraceShape(CCSPlayerController player, Vector startPos, Vector endPos, ulong? mask = null, ulong? contents = null) + { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null) + return null; + + var rayTrace = RayTraceInterface.Get(); + if (rayTrace == null) + return null; + + if (mask == null) + { + mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes; + mask &= ~(ulong)InteractionLayers.PlayerClip; + } + contents ??= playerPawn.Collision.CollisionGroup; + + bool drawBeam = Config.LoadedConfig.TraceRayBeam; + + TraceOptions options = new() + { + InteractsWith = (ulong)mask, + InteractsExclude = (ulong)contents, + DrawBeam = drawBeam == true ? 1 : 0, + }; + + rayTrace.TraceEndShape(startPos, endPos, playerPawn, options, out TraceResult result); + + return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); + } + + public static CustomTraceResult? EyeTrace(CCSPlayerController player) + { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null) + return null; + + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); + 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 endPos = startPos + SkillUtils.GetForwardVector(playerPawn.EyeAngles) * maxDistance; + + return TraceShape(player, startPos, endPos); + } + + 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) + return null; + + var rayTrace = RayTraceInterface.Get(); + if (rayTrace == null) + return null; + + mask ??= playerPawn.Collision.CollisionAttribute.InteractsWith; + contents ??= playerPawn.Collision.CollisionGroup; + + bool drawBeam = Config.LoadedConfig.TraceRayBeam; + + TraceOptions options = new() + { + InteractsWith = (ulong)mask, + InteractsExclude = (ulong)contents, + DrawBeam = drawBeam == true ? 1 : 0, + }; + + mins ??= playerPawn.Collision.Mins; + maxs ??= playerPawn.Collision.Maxs; + + rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out TraceResult result); + + if (drawBeam) + { + angle ??= new(0, playerPawn.EyeAngles.Y, 0); + DrawBoxEdges(startPos, endPos, angle, mins, maxs, Color.Green); + } + + return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); + } + + private static void DrawBoxEdges(Vector start, Vector end, QAngle angles, Vector mins, Vector maxs, Color color) + { + AngleVectors(angles, out Vector forward, out Vector right, out Vector up); + + float halfLength = (maxs.X - mins.X) / 2.0f; + + Vector visualStart = start - (forward * halfLength); + Vector visualEnd = end + (forward * halfLength); + + Vector GetVertex(Vector center, float rx, float ux) + { + return center + (right * rx) + (up * ux); + } + + Vector[] s = [ + GetVertex(visualStart, mins.Y, mins.Z), + GetVertex(visualStart, maxs.Y, mins.Z), + GetVertex(visualStart, maxs.Y, maxs.Z), + GetVertex(visualStart, mins.Y, maxs.Z) + ]; + + Vector[] e = [ + GetVertex(visualEnd, mins.Y, mins.Z), + GetVertex(visualEnd, maxs.Y, mins.Z), + GetVertex(visualEnd, maxs.Y, maxs.Z), + GetVertex(visualEnd, mins.Y, maxs.Z) + ]; + + for (int i = 0; i < 4; i++) + { + int next = (i + 1) % 4; + CreateBeamLine(s[i], s[next], color); + CreateBeamLine(e[i], e[next], color); + CreateBeamLine(s[i], e[i], color); + } + } + + private static void AngleVectors(QAngle angles, out Vector forward, out Vector right, out Vector up) + { + float sp, sy, cp, cy, sr, cr; + + float pitch = angles.X * (MathF.PI / 180.0f); + float yaw = angles.Y * (MathF.PI / 180.0f); + float roll = angles.Z * (MathF.PI / 180.0f); + + sp = MathF.Sin(pitch); cp = MathF.Cos(pitch); + sy = MathF.Sin(yaw); cy = MathF.Cos(yaw); + sr = MathF.Sin(roll); cr = MathF.Cos(roll); + + forward = new Vector(cp * cy, cp * sy, -sp); + right = new Vector(-1 * sr * sp * cy + cr * sy, -1 * sr * sp * sy - cr * cy, -1 * sr * cp); + up = new Vector(cr * sp * cy + sr * sy, cr * sp * sy - sr * cy, cr * cp); + } + + private static void CreateBeamLine(Vector start, Vector end, Color color) + { + var beam = Utilities.CreateEntityByName("env_beam"); + if (beam == null || !beam.IsValid) return; + + beam.Render = color; + beam.Width = 1.3f; + + beam.Teleport(start, new QAngle(0, 0, 0), new Vector(0, 0, 0)); + beam.EndPos.X = end.X; + beam.EndPos.Y = end.Y; + beam.EndPos.Z = end.Z; + + beam.DispatchSpawn(); + } + + public static float Distance(this CustomTraceResult result) + { + return Vector3.Distance(result.StartPos, result.EndPos); + } + + public static Vector3 Direction(this CustomTraceResult result) + { + return Vector3.Normalize(result.EndPos - result.Normal); + } + + public static bool HitEntityByDesignerName(this CustomTraceResult result, out T? entity, string designerName, DesignerNameMatchType matchType = DesignerNameMatchType.Equals) where T : CEntityInstance + { + T? val = (T?)Activator.CreateInstance(typeof(T), result.HitEntity); + if ((object?)val != null && matchType switch + { + DesignerNameMatchType.Equals => val.DesignerName == designerName, + DesignerNameMatchType.StartsWith => val.DesignerName.StartsWith(designerName, StringComparison.OrdinalIgnoreCase), + DesignerNameMatchType.EndsWith => val.DesignerName.EndsWith(designerName, StringComparison.OrdinalIgnoreCase), + _ => false, + }) + { + entity = val; + return true; + } + + entity = null; + return false; + } + + public static bool HitEntity(this CustomTraceResult result, out CBaseEntity? entity) + { + CEntityInstance entityInstance = new(result.HitEntity); + if (string.IsNullOrEmpty(entityInstance.DesignerName)) + { + entity = null; + return false; + } + + entity = entityInstance.As(); + return entity != null; + } + + public static bool HitPlayer(this CustomTraceResult result, out CCSPlayerController? player) + { + if (result.HitEntityByDesignerName(out CCSPlayerPawn? entity, "player")) + { + player = entity?.OriginalController.Value; + return player != null; + } + + player = null; + return false; + } + + public static bool HitWeapon(this CustomTraceResult result, out CBasePlayerWeapon? weapon) + { + return result.HitEntityByDesignerName(out weapon, "weapon_", DesignerNameMatchType.StartsWith); + } + + public static bool HitChicken(this CustomTraceResult result, out CChicken? chicken) + { + return result.HitEntityByDesignerName(out chicken, "chicken"); + } + + public static bool HitButton(this CustomTraceResult result, out CBaseButton? button) + { + return result.HitEntityByDesignerName(out button, "func_door"); + } + + public static bool HitBuyzone(this CustomTraceResult result, out CBuyZone? buyzone) + { + return result.HitEntityByDesignerName(out buyzone, "func_buyzone"); + } + + public static bool HitSky(this CustomTraceResult result, out CEnvSky? sky) + { + return result.HitEntityByDesignerName(out sky, "env_sky"); + } + + public static bool HitDoor(this CustomTraceResult result, out CBaseDoor? door) + { + return result.HitEntityByDesignerName(out door, "func_door"); + } + + public static bool HitDoor(this CustomTraceResult result, out CRotDoor? door) + { + return result.HitEntityByDesignerName(out door, "func_door_rotating"); + } + + public static bool HitLadder(this CustomTraceResult result, out CFuncLadder? ladder) + { + return result.HitEntityByDesignerName(out ladder, "func_ladder"); + } + + public static bool HitGrenade(this CustomTraceResult result, out CBaseCSGrenade? grenade) + { + return result.HitEntityByDesignerName(out grenade, "grenade"); + } + + public static bool HitPlantedC4(this CustomTraceResult result, out CPlantedC4? c4) + { + return result.HitEntityByDesignerName(out c4, "planted_c4"); + } + + public static bool HitPointWorldText(this CustomTraceResult result, out CPointWorldText? pointWorldText) + { + return result.HitEntityByDesignerName(out pointWorldText, "point_worldtext"); + } + + public static bool HitC4(this CustomTraceResult result, out CC4? c4) + { + return result.HitEntityByDesignerName(out c4, "weapon_c4"); + } + + public static bool HitWorld(this CustomTraceResult result, out CWorld? world) + { + return result.HitEntityByDesignerName(out world, "worldent"); + } + + public enum DesignerNameMatchType + { + Equals, + StartsWith, + EndsWith + } + } +} diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index 45dd42e..282bfae 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -165,7 +165,11 @@ namespace src.utils skeleton.Scale = scale; playerPawn.AcceptInput("SetScale", null, null, scale.ToString(CultureInfo.InvariantCulture)); - Server.NextWorldUpdate(() => Utilities.SetStateChanged(player.PlayerPawn.Value!, "CBaseEntity", "m_CBodyComponent")); + + Server.NextWorldUpdate(() => { + if (playerPawn == null || !playerPawn.IsValid) return; + Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_CBodyComponent"); + }); } public static Vector? GetSpawnPointVector(CCSPlayerController player, bool enemySpawn = false) @@ -224,6 +228,7 @@ namespace src.utils if (pawn.Health <= 0) Server.NextFrame(() => { + if (pawn == null || !pawn.IsValid) return; pawn?.CommitSuicide(false, true); }); } diff --git a/jRandomSkills - Server Files/gamedata.zip b/jRandomSkills - Server Files/gamedata.zip new file mode 100644 index 0000000..6f19514 Binary files /dev/null and b/jRandomSkills - Server Files/gamedata.zip differ diff --git a/jRandomSkills - Server Files/gamedata/jRandomSkills.gamedata.json b/jRandomSkills - Server Files/gamedata/jRandomSkills.gamedata.json index 713f6f8..7c8be60 100644 --- a/jRandomSkills - Server Files/gamedata/jRandomSkills.gamedata.json +++ b/jRandomSkills - Server Files/gamedata/jRandomSkills.gamedata.json @@ -16,15 +16,22 @@ "Shoot_Secondary": { "signatures": { "library": "server", - "windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2", - "linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65" + "windows": "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B F9 0F BF DA", + "linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 54 41 89 F4 53 48 8B 07 48 89 FB 48 8B 80 ? ? ? ? 48 39 D0 0F 85" } }, "SnapViewAngles": { "signatures": { "library": "server", "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55", - "linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 89 F7 48 81 EC ? ? ? ? E8 ? ? ? ? 48 8B 93" + "linux": "55 48 89 E5 41 57 49 89 FF 48 89 F7 41 56 41 55 41 54 53 48 81 EC" + } + }, + "CCSPlayerController_HandleCommandDrop": { + "signatures": { + "library": "server", + "windows": "48 89 5C 24 ? 57 48 83 EC ? 48 8B FA E8 ? ? ? ? 48 8B D8", + "linux": "55 48 89 E5 41 54 49 89 F4 53 E8 ? ? ? ? 48 85 C0 74 ? 48 89 C3" } } } \ No newline at end of file diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll index d9e5906..4ab424a 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/configs/config.json b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/config.json index 8499a7d..a7888c8 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/configs/config.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/config.json @@ -13,7 +13,7 @@ "DisplayAlwaysDescription": false, "DisableSpectateHUD": false, "FlashingHtmlHudFix": true, - "CS2TraceRayDebug": false, + "TraceRayBeam": false, "DisableHUDOnDeathPermission": "@jRandomSkills/death", "DisableSkillsOnRoundEnd": false, "LanguageSystem": { @@ -130,6 +130,10 @@ "ReloadCommand": { "Alias": "reload, refresh", "Permissions": "@jRandomSkills/admin" + }, + "NextCommand": { + "Alias": "next_skill", + "Permissions": "@jRandomSkills/admin" } }, "VotingCommands": { diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json index d999a49..0430a4a 100644 --- a/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json +++ b/jRandomSkills - Server Files/plugins/jRandomSkills/configs/skillsInfo.json @@ -262,7 +262,7 @@ "RequiredPermission": "" }, { - "ZombieHealth": 250, + "ZombieHealth": 500, "NeedsTeammates": false, "DisableOnFreezeTime": false, "OnlyTeam": 0, @@ -323,17 +323,6 @@ "Name": "ReactiveArmor", "RequiredPermission": "" }, - { - "Cooldown": 30.0, - "Duration": 10.0, - "NeedsTeammates": false, - "DisableOnFreezeTime": true, - "OnlyTeam": 0, - "Color": "#d0d930", - "Active": false, - "Name": "RCMelon", - "RequiredPermission": "" - }, { "Cooldown": 15.0, "NeedsTeammates": false, @@ -706,6 +695,7 @@ "RequiredPermission": "" }, { + "ParticleName": "particles/ui/hud/ui_map_def_utility_trail.vpcf", "NeedsTeammates": false, "DisableOnFreezeTime": false, "OnlyTeam": 0, @@ -747,9 +737,6 @@ "RequiredPermission": "" }, { - "MaximumFuel": 150.0, - "FuelConsumption": 0.64, - "Refuelling": 0.1, "NeedsTeammates": false, "DisableOnFreezeTime": true, "OnlyTeam": 0, @@ -1307,7 +1294,6 @@ { "Cooldown": 20.0, "Duration": 0.3, - "Offset": 0.0, "NeedsTeammates": false, "DisableOnFreezeTime": true, "OnlyTeam": 0, diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll index dd03173..beff695 100644 Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll differ