From 72e2910a68ac90bbf806eb7d3796dc87ad5f7682 Mon Sep 17 00:00:00 2001 From: Juzlus Date: Tue, 11 Nov 2025 01:43:10 +0100 Subject: [PATCH] main --- .../src/command/Command.cs | 50 +-- .../src/jRandomSkills.cs | 8 +- jRandomSkills - SRC Files/src/lang/en.json | 2 +- jRandomSkills - SRC Files/src/lang/fr.json | 2 +- jRandomSkills - SRC Files/src/lang/pl.json | 2 +- jRandomSkills - SRC Files/src/lang/pt-br.json | 2 +- jRandomSkills - SRC Files/src/lang/zh.json | 2 +- jRandomSkills - SRC Files/src/menu/Menu.cs | 2 +- .../src/player/ISkill.cs | 3 + .../src/player/PlayerEvents.cs | 34 +- .../src/player/skills/Armored.cs | 6 +- .../src/player/skills/Astronaut.cs | 3 +- .../src/player/skills/Behind.cs | 4 +- .../src/player/skills/C4Camouflage.cs | 126 ++++---- .../src/player/skills/Catapult.cs | 4 +- .../src/player/skills/Cypher.cs | 287 +++++++++++++++++ .../src/player/skills/Disarmament.cs | 4 +- .../src/player/skills/Duplicator.cs | 3 +- .../src/player/skills/Dwarf.cs | 3 +- .../src/player/skills/ExplosiveShot.cs | 3 +- .../src/player/skills/Flash.cs | 3 +- .../src/player/skills/Fortnite.cs | 2 +- .../src/player/skills/Ghost.cs | 120 +++---- .../src/player/skills/Iana.cs | 301 ++++++++++++++++++ .../src/player/skills/Jackal.cs | 2 +- .../src/player/skills/Muhammed.cs | 3 +- .../src/player/skills/Ninja.cs | 110 ++++--- .../src/player/skills/PawelJumper.cs | 3 +- .../src/player/skills/Phoenix.cs | 6 +- .../src/player/skills/Push.cs | 4 +- .../src/player/skills/RCMelon.cs | 292 +++++++++++++++++ .../src/player/skills/ReZombie.cs | 2 +- .../src/player/skills/Replicator.cs | 6 +- .../src/player/skills/Shade.cs | 3 +- .../src/player/skills/Soldier.cs | 6 +- .../src/player/skills/Thief.cs | 3 +- .../src/player/skills/ThirdEye.cs | 2 + .../src/player/skills/ToxicSmoke.cs | 3 +- .../src/player/skills/Watchmaker.cs | 2 +- .../src/utils/SkillUtils.cs | 12 +- 40 files changed, 1191 insertions(+), 244 deletions(-) create mode 100644 jRandomSkills - SRC Files/src/player/skills/Cypher.cs create mode 100644 jRandomSkills - SRC Files/src/player/skills/Iana.cs create mode 100644 jRandomSkills - SRC Files/src/player/skills/RCMelon.cs diff --git a/jRandomSkills - SRC Files/src/command/Command.cs b/jRandomSkills - SRC Files/src/command/Command.cs index 0e9324b..7e3bd95 100644 --- a/jRandomSkills - SRC Files/src/command/Command.cs +++ b/jRandomSkills - SRC Files/src/command/Command.cs @@ -102,9 +102,7 @@ namespace src.command Server.PrintToConsole(Localization.GetTranslation("correct_form_setskill")); return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill")); return; } @@ -115,9 +113,7 @@ namespace src.command Server.PrintToConsole(Localization.GetTranslation("player_not_found_setskill")); return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill")); return; } @@ -131,9 +127,7 @@ namespace src.command Server.PrintToConsole(Localization.GetTranslation("skill_not_found_setskill")); return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill")); return; } @@ -152,12 +146,10 @@ namespace src.command return; } - if (skill.Display) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", false); + SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}"); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + if (skill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", border: "b"); } else { @@ -167,9 +159,7 @@ namespace src.command return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill")); } } @@ -365,7 +355,7 @@ namespace src.command if (!int.TryParse(command.GetArg(1), out int ctScore) || !int.TryParse(command.GetArg(2), out int tScore)) { if (player != null && player.IsValid) - SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setscore"), true); + SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setscore")); return; } @@ -399,9 +389,7 @@ namespace src.command return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("correct_form_setskill")); return; } @@ -413,9 +401,7 @@ namespace src.command return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("player_not_found_setskill")); return; } @@ -430,9 +416,7 @@ namespace src.command return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("skill_not_found_setskill")); return; } @@ -456,12 +440,10 @@ namespace src.command return; } - if (skill.Display) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", false); + SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}"); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, $"{player.GetTranslation("done_setskill")}: {ChatColors.LightRed}{player.GetSkillName(skill.Skill)} {ChatColors.Lime}{player.GetTranslation("for_setskill")} {ChatColors.LightRed}{targetPlayer.PlayerName}", false); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + if (skill.Display) + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(skill.Skill)}", border: "b"); } else { @@ -471,9 +453,7 @@ namespace src.command return; } - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); - SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill"), true); - player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◥◣◆◢◤{ChatColors.Green}―――――――――――"); + SkillUtils.PrintToChat(player, player.GetTranslation("error_setskill")); } } diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index 3322284..6c51d01 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -21,7 +21,7 @@ namespace src public ConcurrentBag SkillPlayer { get; set; } = []; public Random Random { get; } = new Random(); public CCSGameRules? GameRules { get; set; } - public ConcurrentBag ManifestResources { get; set; } = [ "models/actors/ghost_speaker.vmdl" ]; + private ConcurrentBag ManifestResources { get; set; } = [ "models/actors/ghost_speaker.vmdl" ]; public IWasdMenuManager? MenuManager; public const string Tag = "jRandomSkills"; @@ -47,6 +47,12 @@ namespace src Instance.RegisterListener(LoadManifest); } + internal void AddToManifest(string prop) + { + if (!ManifestResources.Contains(prop)) + ManifestResources.Add(prop); + } + internal void LoadManifest(ResourceManifest manifest) { foreach (var prop in ManifestResources) diff --git a/jRandomSkills - SRC Files/src/lang/en.json b/jRandomSkills - SRC Files/src/lang/en.json index f991a4e..3cb440f 100644 --- a/jRandomSkills - SRC Files/src/lang/en.json +++ b/jRandomSkills - SRC Files/src/lang/en.json @@ -454,7 +454,7 @@ "bombsite_b": "Bombsite B", "teammate_skills": "Your teammates' skills", - "summary_start": "======SUMMARY=OF=THE=LAST=ROUND======", + "summary_start": "Summary of the last round", "summary_end": "=======================================", "menu_controlls_scroll": "W/S - Scroll", diff --git a/jRandomSkills - SRC Files/src/lang/fr.json b/jRandomSkills - SRC Files/src/lang/fr.json index 080ba0f..7dfa8f1 100644 --- a/jRandomSkills - SRC Files/src/lang/fr.json +++ b/jRandomSkills - SRC Files/src/lang/fr.json @@ -454,7 +454,7 @@ "bombsite_b": "Site de bombe B", "teammate_skills": "Compétences de vos coéquipiers", - "summary_start": "======RÉSUMÉ=DU=DERNIER=ROUND======", + "summary_start": "Résumé du dernier round", "summary_end": "===================================", "menu_controlls_scroll": "W/S - Défilement", diff --git a/jRandomSkills - SRC Files/src/lang/pl.json b/jRandomSkills - SRC Files/src/lang/pl.json index de9ed74..5fba217 100644 --- a/jRandomSkills - SRC Files/src/lang/pl.json +++ b/jRandomSkills - SRC Files/src/lang/pl.json @@ -454,7 +454,7 @@ "bombsite_b": "Strefa detonacji B", "teammate_skills": "Supermoce twoich sojuszników", - "summary_start": "======PODSUMOWANIE=Z=OSTATNIEJ=RUNDY======", + "summary_start": "Podsumowanie z ostatniej rundy", "summary_end": "============================================", "menu_controlls_scroll": "W/S – Przewijanie", diff --git a/jRandomSkills - SRC Files/src/lang/pt-br.json b/jRandomSkills - SRC Files/src/lang/pt-br.json index 2a7ef7a..dcc4b4b 100644 --- a/jRandomSkills - SRC Files/src/lang/pt-br.json +++ b/jRandomSkills - SRC Files/src/lang/pt-br.json @@ -454,7 +454,7 @@ "bombsite_b": "Zona de detonação B", "teammate_skills": "Habilidades dos seus companheiros de equipe", - "summary_start": "=======RESUMO=DA=ÚLTIMA=RODADA=======", + "summary_start": "Resumo da última rodada", "summary_end": "=======================================", "menu_controlls_scroll": "W/S - Rolar", diff --git a/jRandomSkills - SRC Files/src/lang/zh.json b/jRandomSkills - SRC Files/src/lang/zh.json index 5b3bdcd..2489a55 100644 --- a/jRandomSkills - SRC Files/src/lang/zh.json +++ b/jRandomSkills - SRC Files/src/lang/zh.json @@ -454,7 +454,7 @@ "bombsite_b": "爆轰区B", "teammate_skills": "你队友的技能", - "summary_start": "=============上一回合总结==============", + "summary_start": "上一回合总结", "summary_end": "=======================================", "menu_controlls_scroll": "W/S - 滚动", diff --git a/jRandomSkills - SRC Files/src/menu/Menu.cs b/jRandomSkills - SRC Files/src/menu/Menu.cs index 02e1ad0..14c3be4 100644 --- a/jRandomSkills - SRC Files/src/menu/Menu.cs +++ b/jRandomSkills - SRC Files/src/menu/Menu.cs @@ -23,7 +23,7 @@ namespace src.menu string cleanSkillName = Regex.Replace(selectedSkillName, pattern, ""); string skillName = cleanSkillName.Replace($" ★ ", ""); string skillDesc = player.GetSkillDescription(skillInfo.Skill); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skillName}{ChatColors.Lime}: {skillDesc}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{skillName}{ChatColors.Lime}: {skillDesc}", border: ""); MenuManager.CloseActiveMenu(player); }); } diff --git a/jRandomSkills - SRC Files/src/player/ISkill.cs b/jRandomSkills - SRC Files/src/player/ISkill.cs index f9e3b45..3d43247 100644 --- a/jRandomSkills - SRC Files/src/player/ISkill.cs +++ b/jRandomSkills - SRC Files/src/player/ISkill.cs @@ -68,6 +68,7 @@ public enum Skills Chicken, ChillOut, Cutter, + Cypher, Darkness, Deactivator, Deaf, @@ -97,6 +98,7 @@ public enum Skills HealingSmoke, Hermit, HolyHandGrenade, + Iana, Impostor, InfiniteAmmo, Jackal, @@ -132,6 +134,7 @@ 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 625617f..517ce04 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -1,6 +1,7 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; @@ -11,6 +12,7 @@ using src.utils; using System.Collections.Concurrent; using static CounterStrikeSharp.API.Core.Listeners; using static src.jRandomSkills; +using static System.Net.Mime.MediaTypeNames; namespace src.player { @@ -261,7 +263,6 @@ namespace src.player private static HookResult OnTriggerEnter(DynamicHook hook) { - Server.PrintToChatAll("Start"); lock (setLock) { CBaseTrigger trigger = hook.GetParam(0); @@ -276,10 +277,9 @@ namespace src.player private static HookResult OnTriggerExit(DynamicHook hook) { - Server.PrintToChatAll("End"); lock (setLock) { - CBaseTrigger trigger = hook.GetParam(0); + CBaseTrigger trigger = hook.GetParam(0); CBaseEntity entity = hook.GetParam(1); foreach (var playerSkill in Instance.SkillPlayer) @@ -434,13 +434,11 @@ namespace src.player if (Config.LoadedConfig.SummaryAfterTheRound && !string.IsNullOrEmpty(skillsText)) { - player.PrintToChat(" "); - player.PrintToChat($" {ChatColors.Lime}{player.GetTranslation("summary_start")}"); + SkillUtils.PrintToChat(player, string.Empty, title: player.GetTranslation("summary_start"), border: "t"); foreach (string text in skillsText.Split("\n")) if (!string.IsNullOrEmpty(text)) - player.PrintToChat(text); - player.PrintToChat($" {ChatColors.Lime}{player.GetTranslation("summary_end")}"); - player.PrintToChat(" \n"); + SkillUtils.PrintToChat(player, text, title: player.GetTranslation("teammate_skills"), border: ""); + SkillUtils.PrintToChat(player, string.Empty, title: player.GetTranslation("summary_start"), border: "b"); } }); } @@ -482,8 +480,9 @@ namespace src.player if (skillData == null || specialSkillData == null) return HookResult.Continue; string skillDesc = victim.GetSkillDescription(skillData.Skill); - SkillUtils.PrintToChat(victim, $"{victim.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}:", false); - SkillUtils.PrintToChat(victim, $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? victim.GetSkillName(skillData.Skill) : $"{victim.GetSkillName(specialSkillData.Skill)} -> {victim.GetSkillName(skillData.Skill)}")}{ChatColors.Lime} - {skillDesc}", false); + SkillUtils.PrintToChat(victim, + $"{ChatColors.DarkRed}{(attackerInfo.SpecialSkill == Skills.None ? victim.GetSkillName(skillData.Skill) : $"{victim.GetSkillName(specialSkillData.Skill)} -> {victim.GetSkillName(skillData.Skill)}")}{ChatColors.Lime} - {skillDesc}", + title: $"{victim.GetTranslation("enemy_skill")} {ChatColors.DarkRed}{attacker.PlayerName}{ChatColors.Lime}"); } } return HookResult.Continue; @@ -582,6 +581,8 @@ namespace src.player { List skillList = [.. SkillData.Skills]; skillList.RemoveAll(s => s?.Skill == Skills.None); + skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); + if (gameMode != Config.GameModes.FullRandom) skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill); @@ -626,7 +627,8 @@ namespace src.player } if (randomSkill.Display) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", false); + 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"); Instance?.SkillAction(skillPlayer.Skill.ToString(), "DisableSkill", [player]); skillPlayer.Skill = randomSkill.Skill; @@ -661,10 +663,11 @@ namespace src.player if (!string.IsNullOrEmpty(teammateSkills)) { - SkillUtils.PrintToChat(player, $" {ChatColors.Lime}{player.GetTranslation("teammate_skills")}:", false); + SkillUtils.PrintToChat(player, string.Empty, title: player.GetTranslation("teammate_skills"), border: "t"); foreach (string text in teammateSkills.Split("\n")) if (!string.IsNullOrEmpty(text)) - player.PrintToChat(text); + SkillUtils.PrintToChat(player, text, title: player.GetTranslation("teammate_skills"), border: ""); + SkillUtils.PrintToChat(player, string.Empty, title: player.GetTranslation("teammate_skills"), border: "b"); } }); } @@ -709,6 +712,8 @@ namespace src.player { List skillList = [.. SkillData.Skills]; skillList.RemoveAll(s => s?.Skill == Skills.None); + skillList.RemoveAll(s => !string.IsNullOrEmpty(SkillsInfo.GetValue(s.Skill, "requiredPermission")) && !AdminManager.PlayerHasPermissions(player, SkillsInfo.GetValue(s.Skill, "requiredPermission"))); + if (gameMode != Config.GameModes.FullRandom) skillList.RemoveAll(s => s?.Skill == skillPlayer?.Skill || s?.Skill == skillPlayer?.SpecialSkill); @@ -745,7 +750,8 @@ namespace src.player } if (randomSkill.Display && Config.LoadedConfig.YourSkillChatInfo) - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(randomSkill.Skill)}{ChatColors.Lime}: {player.GetSkillDescription(randomSkill.Skill)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); skillPlayer.Skill = randomSkill.Skill; skillPlayer.SpecialSkill = Skills.None; diff --git a/jRandomSkills - SRC Files/src/player/skills/Armored.cs b/jRandomSkills - SRC Files/src/player/skills/Armored.cs index a5565d0..b9d1b0d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Armored.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Armored.cs @@ -1,4 +1,5 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -23,7 +24,8 @@ namespace src.player.skills float newScale = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newScale; newScale = (float)Math.Round(newScale, 2); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } public static void OnTakeDamage(DynamicHook h) diff --git a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs index 758533f..af4f9b2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Astronaut.cs @@ -43,7 +43,8 @@ namespace src.player.skills float gravityModifier = (float)Math.Round(Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "chanceFrom")) + SkillsInfo.GetValue(skillName, "chanceFrom"), 1); playerInfo.SkillChance = gravityModifier; - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, gravityModifier)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, gravityModifier)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); player.PlayerPawn.Value.ActualGravityScale = gravityModifier; } diff --git a/jRandomSkills - SRC Files/src/player/skills/Behind.cs b/jRandomSkills - SRC Files/src/player/skills/Behind.cs index 940a91d..63e64d3 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Behind.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Behind.cs @@ -1,3 +1,4 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -33,7 +34,8 @@ namespace src.player.skills 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)}", false); + 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"); } private static void RotateEnemy(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs index 24c2124..a7cd937 100644 --- a/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs +++ b/jRandomSkills - SRC Files/src/player/skills/C4Camouflage.cs @@ -1,22 +1,29 @@ -using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Modules.Memory; 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 { public class C4Camouflage : ISkill { private const Skills skillName = Skills.C4Camouflage; - private static readonly ConcurrentDictionary> invisibleEntities = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; + private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + Instance.AddToManifest(bloodParticle); + } + + public static void NewRound() + { + invisiblePlayers.Clear(); } public static void WeaponPickup(EventItemPickup @event) @@ -30,7 +37,7 @@ namespace src.player.skills public static void WeaponEquip(EventItemEquip @event) { - var player = @event.Userid; + var player = @event.Userid!; var weapon = @event.Item; if (!Instance.IsPlayerValid(player)) return; @@ -38,25 +45,16 @@ namespace src.player.skills if (playerInfo?.Skill != skillName) return; if (weapon == "c4") - { - SetPlayerVisibility(player!, false); - SetWeaponVisibility(player!, false); - } + invisiblePlayers.TryAdd(player, 0); else - { - SetPlayerVisibility(player!, true); - SetWeaponVisibility(player!, true); - } + invisiblePlayers.TryRemove(player, out _); } public static void OnTick() { foreach (var player in Utilities.GetPlayers()) - { if (!player.PawnIsAlive) - if (invisibleEntities.ContainsKey(player.SteamID)) - invisibleEntities.TryRemove(player.SteamID, out _); - } + invisiblePlayers.TryRemove(player, out _); } public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList) @@ -64,14 +62,22 @@ namespace src.player.skills foreach (var (info, player) in infoList) { if (player == null) continue; - foreach ((var playerId, var itemList) in invisibleEntities) - if (player.SteamID != playerId) - foreach (var entityIndex in itemList) - { - var entity = Utilities.GetEntityFromIndex((int)entityIndex); - if (entity == null || !entity.IsValid) continue; - info.TransmitEntities.Remove(entity.Index); - } + foreach (var _player in invisiblePlayers.Keys) + if (player.SteamID != _player.SteamID) + { + var playerPawn = _player.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 = HideBomb(_player); + if (bombIndex == null) continue; + var bombEntity = Utilities.GetEntityFromIndex((int)bombIndex); + if (bombEntity == null || !bombEntity.IsValid) continue; + info.TransmitEntities.Remove(bombEntity.Index); + } } } @@ -88,54 +94,54 @@ namespace src.player.skills var activeWeapon = playerPawn.WeaponServices.ActiveWeapon.Value; if (activeWeapon.DesignerName != "weapon_c4") return; - SetPlayerVisibility(player, false); - SetWeaponVisibility(player, false); + invisiblePlayers.TryAdd(player, 0); } public static void DisableSkill(CCSPlayerController player) { - SetPlayerVisibility(player, true); - SetWeaponVisibility(player, true); - invisibleEntities.TryRemove(player.SteamID, out _); + invisiblePlayers.TryRemove(player, out _); } - private static void SetPlayerVisibility(CCSPlayerController player, bool enabled) + public static void PlayerHurt(EventPlayerHurt @event) { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + if (!invisiblePlayers.ContainsKey(player)) return; + var playerPawn = player.PlayerPawn.Value; - if (playerPawn != null && playerPawn.IsValid) - { - var color = Color.FromArgb(enabled ? 255 : 0, 255, 255, 255); - playerPawn.Render = color; - Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender"); - } + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; + + CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + if (particle == null) return; + + particle.EffectName = bloodParticle; + particle.StartActive = true; + + Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); + particle.Teleport(pos); + particle.DispatchSpawn(); + + particle.AcceptInput("Start"); } - private static void SetWeaponVisibility(CCSPlayerController player, bool visible) + private static uint? HideBomb(CCSPlayerController player) { - if (!Instance.IsPlayerValid(player)) return; - var playerPawn = player.PlayerPawn.Value!; - if (playerPawn.WeaponServices == null) return; + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); + if (bombEntities.Count == 0) return null; - invisibleEntities.TryRemove(player.SteamID, out _); - foreach (var weapon in playerPawn.WeaponServices.MyWeapons) - { - if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) - { - if (!visible) - { - if (invisibleEntities.TryGetValue(player.SteamID, out var items)) - { - if (!items.Contains(weapon.Index)) - items.Add(weapon.Index); - } - else - invisibleEntities.TryAdd(player.SteamID, [weapon.Index]); - } - } - } + var bomb = bombEntities.FirstOrDefault(); + if (bomb == null) return null; - if (visible) - invisibleEntities.TryRemove(player.SteamID, out _); + // if (bomb.OwnerEntity.Index != player.Index) return null; + + bomb.EntitySpottedState.Spotted = false; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpotted")); + + for (int i = 0; i < bomb.EntitySpottedState.SpottedByMask.Length; i++) + bomb.EntitySpottedState.SpottedByMask[i] = 0; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpottedByMask")); + + return bomb.Index; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#00911f", CsTeam onlyTeam = CsTeam.Terrorist, 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/Catapult.cs b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs index 365fd49..342c786 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Catapult.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Catapult.cs @@ -1,3 +1,4 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -37,7 +38,8 @@ namespace src.player.skills 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)}", false); + 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 class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", 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/Cypher.cs b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs new file mode 100644 index 0000000..07625bc --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs @@ -0,0 +1,287 @@ +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 CS2TraceRay.Class; +using CS2TraceRay.Struct; +using src.utils; +using System.Collections.Concurrent; +using System.Drawing; +using System.Numerics; +using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; + +namespace src.player.skills +{ + public class Cypher : ISkill + { + private const Skills skillName = Skills.Cypher; + 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"; + private const string cameraViewModel = "models/actors/ghost_speaker.vmdl"; + + public static void LoadSkill() + { + SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + jRandomSkills.Instance.AddToManifest(cameraPropModel); + jRandomSkills.Instance.AddToManifest(cameraViewModel); + } + + public static void NewRound() + { + foreach (var playerSkill in playersInfo.Values) + KillCamera(playerSkill); + lock (setLock) + playersInfo.Clear(); + } + + public static void UseSkill(CCSPlayerController player) + { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn?.CBodyComponent == null) return; + if (playersInfo.TryGetValue(player, 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 + { + Player = player, + CameraProp = null, + CameraView = null, + CameraActive = false, + NextCamera = 0, + PlayerCameraRaw = player.PlayerPawn.Value.CameraServices.ViewEntity.Raw, + }); + } + + public static void DisableSkill(CCSPlayerController player) + { + if (playersInfo.TryGetValue(player, out var playerSkill)) + { + ChangeCamera(playerSkill, true); + KillCamera(playerSkill); + } + playersInfo.TryRemove(player, out _); + } + + private static void KillCamera(PlayerSkill playerSkill) + { + if (playerSkill.CameraView != null && playerSkill.CameraView.IsValid) + { + playerSkill.CameraView.AcceptInput("Kill"); + playerSkill.CameraView = null; + playerSkill.CameraActive = false; + } + + if (playerSkill.CameraProp != null && playerSkill.CameraProp.IsValid) + { + playerSkill.CameraProp.EmitSound("SolidMetal.BulletImpact"); + playerSkill.CameraProp.AcceptInput("Kill"); + playerSkill.CameraProp = null; + } + } + + public static void OnTick() + { + foreach (var playerSkill in playersInfo.Values) + { + if (playerSkill.CameraActive && playerSkill.CameraView != null && playerSkill.CameraView.IsValid) + { + var pawn = playerSkill.Player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) continue; + + if (pawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) + { + DisableSkill(playerSkill.Player); + continue; + } + playerSkill.CameraView.Teleport(null, pawn.V_angle); + } + UpdateHUD(playerSkill); + } + } + + private static void ChangeCamera(PlayerSkill player, bool forceToDefault = false) + { + player.CameraActive = forceToDefault ? false : !player.CameraActive; + if (player.CameraProp == null && !forceToDefault) + { + if (player.NextCamera > Server.TickCount) return; + player.CameraProp = CreateCameraProp(player.Player); + player.CameraView = CreateCameraView(player.Player); + player.NextCamera = Server.TickCount + SkillsInfo.GetValue(skillName, "Cooldown") * 64; + } + + var pawn = player.Player.PlayerPawn.Value; + if (player.PlayerCameraRaw == 0) + return; + + BlockWeapon(player.Player, player.CameraActive); + pawn!.CameraServices!.ViewEntity.Raw = player.CameraActive && player.CameraView != null ? player.CameraView.EntityHandle.Raw : player.PlayerCameraRaw; + Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices"); + } + + private static CDynamicProp? CreateCameraProp(CCSPlayerController player) + { + var camera = Utilities.CreateEntityByName("prop_dynamic_override"); + if (camera == null || !camera.IsValid) return null; + + camera.Collision.SolidType = SolidType_t.SOLID_VPHYSICS; + camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(camera.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2)); + camera.Entity!.Name = camera.Globalname = $"CypherCamera_{Server.TickCount}_{player.SteamID}"; + camera.DispatchSpawn(); + + 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); + + Server.NextFrame(() => + { + camera.SetModel(cameraPropModel); + camera.Teleport(cameraVector, new QAngle(0, playerPawn.V_angle.Y + 180, 0)); + }); + + return camera; + } + + private static CDynamicProp? CreateCameraView(CCSPlayerController player) + { + var camera = Utilities.CreateEntityByName("prop_dynamic"); + if (camera == null || !camera.IsValid) return null; + camera.DispatchSpawn(); + + 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(() => + { + camera.SetModel(cameraViewModel); + camera.Render = Color.FromArgb(0, 255, 255, 255); + camera.Teleport(cameraVector, playerPawn.EyeAngles); + }); + + return camera; + } + + public static void OnTakeDamage(DynamicHook h) + { + CEntityInstance param = h.GetParam(0); + CTakeDamageInfo param2 = h.GetParam(1); + + if (param == null || param.Entity == null || param2 == null || param2.Attacker == null || param2.Attacker.Value == null) + return; + + if (string.IsNullOrEmpty(param.Entity.Name)) return; + if (!param.Entity.Name.StartsWith("CypherCamera_")) 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)) + { + ChangeCamera(playerSkill, true); + KillCamera(playerSkill); + } + } + + 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 unsafe static Vector? GetNewCameraPosition(CCSPlayerController player) + { + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return null; + + Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z); + Vector endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f; + + Ray ray = new(Vector3.Zero); + CTraceFilter filter = new(playerPawn.Index, playerPawn.Index) + { + m_nObjectSetMask = 0xf, + m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, + m_nInteractsWith = playerPawn.GetInteractsWith(), + m_nInteractsExclude = 0, + m_nBits = 11, + m_bIterateEntities = true, + m_bHitTriggers = false, + m_nInteractsAs = 0x40000 + }; + + filter.m_nHierarchyIds[0] = playerPawn.GetHierarchyId(); + filter.m_nHierarchyIds[1] = 0; + CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); + + if (trace.HitWorld(out _)) + return new Vector(trace.EndPos.X, trace.EndPos.Y, trace.EndPos.Z); + + return null; + } + + private static void UpdateHUD(PlayerSkill playerSkill) + { + if (playerSkill == null || playerSkill.Player == null) return; + + float cooldown = 0; + float time = (playerSkill.NextCamera - Server.TickCount) / 64; + cooldown = (int)Math.Ceiling(Math.Max(time, 0)); + + var playerInfo = jRandomSkills.Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == playerSkill?.Player?.SteamID); + if (playerInfo == null) return; + + if (cooldown == 0) + 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 uint PlayerCameraRaw { get; set; } + public bool CameraActive { get; set; } + public float NextCamera { get; set; } + } + + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#34ebd5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + { + public float Cooldown { get; set; } = cooldown; + } + } +} \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs index c3d270a..c6acdef 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Disarmament.cs @@ -1,3 +1,4 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -42,7 +43,8 @@ namespace src.player.skills 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)}", false); + 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 class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF4500", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float chanceFrom = .2f, float chanceTo = .35f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs index 238c8ff..463eca2 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Duplicator.cs @@ -95,7 +95,8 @@ namespace src.player.skills } SkillUtils.CreateMenu(player, menuItems); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } else player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); diff --git a/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs b/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs index 660b546..5340103 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Dwarf.cs @@ -37,7 +37,8 @@ namespace src.player.skills playerInfo.SkillChance = newSize; SkillUtils.ChangePlayerScale(player, newSize); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSize)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSize)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } } diff --git a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs index d694de1..39eee08 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ExplosiveShot.cs @@ -26,7 +26,8 @@ namespace src.player.skills 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)}", false); + 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"); } private static void SpawnExplosion(Vector vector) diff --git a/jRandomSkills - SRC Files/src/player/skills/Flash.cs b/jRandomSkills - SRC Files/src/player/skills/Flash.cs index ccbd961..0e3a109 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Flash.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Flash.cs @@ -61,7 +61,8 @@ namespace src.player.skills jumpedPlayers.TryAdd(player.SteamID, 0); playerPawn.VelocityModifier = newSpeed; - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSpeed)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newSpeed)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } public static void DisableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs index 8c22e1c..4163af1 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Fortnite.cs @@ -18,7 +18,7 @@ namespace src.player.skills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"), false); - Instance.ManifestResources.Add(SkillsInfo.GetValue(skillName, "propModel")); + Instance.AddToManifest(SkillsInfo.GetValue(skillName, "propModel")); } public static void NewRound() diff --git a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs index 2e8c314..a75d406 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ghost.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ghost.cs @@ -1,12 +1,12 @@ -using System.Collections.Immutable; -using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; +using System.Collections.Immutable; +using static src.jRandomSkills; namespace src.player.skills { @@ -25,20 +25,20 @@ namespace src.player.skills "weapon_g3sg1", "weapon_nova", "weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249", "weapon_negev" ]; - private static readonly ConcurrentDictionary> invisibleEntities = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; + private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; public static void LoadSkill() { - if (SkillsInfo.LoadedConfig.FirstOrDefault(s => s.Name == skillName.ToString())?.Active != true) - return; - SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + Instance.AddToManifest(bloodParticle); } public static void NewRound() { foreach (var player in Utilities.GetPlayers()) SetWeaponAttack(player, false); + invisiblePlayers.Clear(); } public static void WeaponPickup(EventItemPickup @event) @@ -48,7 +48,6 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); if (playerInfo?.Skill != skillName) return; - SetWeaponVisibility(player!, false); SetWeaponAttack(player!, true); } @@ -59,7 +58,6 @@ namespace src.player.skills var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player?.SteamID); if (playerInfo?.Skill != skillName) return; - SetWeaponVisibility(player!, false); SetWeaponAttack(player!, true); } @@ -68,32 +66,37 @@ namespace src.player.skills foreach (var (info, player) in infoList) { if (player == null) continue; - foreach ((var playerId, var itemList) in invisibleEntities) - if (player.SteamID != playerId) - foreach (var entityIndex in itemList) - { - var entity = Utilities.GetEntityFromIndex((int)entityIndex); - if (entity == null || !entity.IsValid) continue; - info.TransmitEntities.Remove(entity.Index); - } + foreach (var _player in invisiblePlayers.Keys) + if (player.SteamID != _player.SteamID) + { + var playerPawn = _player.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 = HideBomb(_player); + if (bombIndex == null) continue; + var bombEntity = Utilities.GetEntityFromIndex((int)bombIndex); + if (bombEntity == null || !bombEntity.IsValid) continue; + info.TransmitEntities.Remove(bombEntity.Index); + } } } public static void EnableSkill(CCSPlayerController player) { Event.EnableTransmit(); - SetPlayerVisibility(player, false); - SetWeaponVisibility(player, false); SetWeaponAttack(player, true); + invisiblePlayers.TryAdd(player, 0); } public static void DisableSkill(CCSPlayerController player) { SkillUtils.ResetPrintHTML(player); - SetPlayerVisibility(player, true); - SetWeaponVisibility(player, true); SetWeaponAttack(player, false); - invisibleEntities.TryRemove(player.SteamID, out _); + invisiblePlayers.TryRemove(player, out _); } public static void OnTick() @@ -104,51 +107,30 @@ namespace src.player.skills if (playerInfo?.Skill == skillName) UpdateHUD(player); if (!player.PawnIsAlive) - if (invisibleEntities.ContainsKey(player.SteamID)) - invisibleEntities.TryRemove(player.SteamID, out _); + invisiblePlayers.TryRemove(player, out _); } } - private static void SetPlayerVisibility(CCSPlayerController player, bool visible) + public static void PlayerHurt(EventPlayerHurt @event) { + var player = @event.Userid; + if (player == null || !player.IsValid) return; + if (!invisiblePlayers.ContainsKey(player)) return; + var playerPawn = player.PlayerPawn.Value; - if (playerPawn != null) - { - var color = visible ? Color.FromArgb(255, 255, 255, 255) : Color.FromArgb(0, 255, 255, 255); - var shadowStrength = visible ? 1.0f : 0.0f; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; - playerPawn.Render = color; - playerPawn.ShadowStrength = shadowStrength; - Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender"); - } - } + CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + if (particle == null) return; - private static void SetWeaponVisibility(CCSPlayerController player, bool visible) - { - if (!Instance.IsPlayerValid(player)) return; - var playerPawn = player.PlayerPawn.Value!; - if (playerPawn.WeaponServices == null) return; + particle.EffectName = bloodParticle; + particle.StartActive = true; - invisibleEntities.TryRemove(player.SteamID, out _); - foreach (var weapon in playerPawn.WeaponServices.MyWeapons) - { - if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) - { - if (!visible) - { - if (invisibleEntities.TryGetValue(player.SteamID, out var items)) - { - if (!items.Contains(weapon.Index)) - items.Add(weapon.Index); - } - else - invisibleEntities.TryAdd(player.SteamID, [weapon.Index]); - } - } - } + Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); + particle.Teleport(pos); + particle.DispatchSpawn(); - if (visible) - invisibleEntities.TryRemove(player.SteamID, out _); + particle.AcceptInput("Start"); } private static void SetWeaponAttack(CCSPlayerController player, bool disableWeapon) @@ -188,6 +170,26 @@ namespace src.player.skills playerInfo.PrintHTML = $"{player.GetTranslation("disabled_weapon")}"; } + private static uint? HideBomb(CCSPlayerController player) + { + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); + if (bombEntities.Count == 0) return null; + + var bomb = bombEntities.FirstOrDefault(); + if (bomb == null) return null; + + if (bomb.OwnerEntity.Index != player.Index) return null; + + bomb.EntitySpottedState.Spotted = false; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpotted")); + + for (int i = 0; i < bomb.EntitySpottedState.SpottedByMask.Length; i++) + bomb.EntitySpottedState.SpottedByMask[i] = 0; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpottedByMask")); + + return bomb.Index; + } + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FFFFFF", 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/Iana.cs b/jRandomSkills - SRC Files/src/player/skills/Iana.cs new file mode 100644 index 0000000..0108441 --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/Iana.cs @@ -0,0 +1,301 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities.Constants; +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 System.Numerics; +using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; + +namespace src.player.skills +{ + public class Iana : ISkill + { + private const Skills skillName = Skills.Iana; + private static readonly ConcurrentDictionary playersInfo = []; + private static readonly object setLock = new(); + + public static void LoadSkill() + { + SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + } + + 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) + CreateClone(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, + }); + } + + 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; + } + + SkillUtils.ApplyScreenColor(playerSkill.Player, 0, 0, 0, 0, 10, 0, 2); + 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? CreateClone(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(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName); + clone.Teleport(playerPawn.AbsOrigin, new QAngle(0, playerPawn.V_angle.Y, 0)); + + playerPawn.Teleport(pos); + SkillUtils.ApplyScreenColor(player, 255, 255, 0, 20, 100, 1020); + BlockWeapon(playerSkill.Player, true); + playerSkill.UseTime = Server.TickCount; + playerSkill.NextUse = Server.TickCount + 64000; + playerSkill.CloneProp = clone; + + jRandomSkills.Instance.AddTimer(SkillsInfo.GetValue(skillName, "Duration"), () => + { + if (playerSkill.CloneProp != null) + KillClone(playerSkill); + }); + + jRandomSkills.Instance.AddTimer(2f, () => { + if (playerSkill.CloneProp == null) + return; + + if (player.IsValid && player.PawnIsAlive) + SkillUtils.ApplyScreenColor(player, + r: 255, + g: 255, + b: 0, + a: 20, + duration: 100, + holdTime: 1020); + }, TimerFlags.STOP_ON_MAPCHANGE | TimerFlags.REPEAT); + }); + + 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; + + Ray ray = new(Vector3.Zero); + CTraceFilter filter = new(playerPawn.Index, playerPawn.Index) + { + m_nObjectSetMask = 0xf, + m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, + m_nInteractsWith = playerPawn.GetInteractsWith(), + m_nInteractsExclude = 0, + m_nBits = 11, + m_bIterateEntities = true, + m_bHitTriggers = false, + m_nInteractsAs = 0x40000 + }; + + filter.m_nHierarchyIds[0] = playerPawn.GetHierarchyId(); + filter.m_nHierarchyIds[1] = 0; + CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); + + 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 (!jRandomSkills.Instance.IsPlayerValid(victim)) return; + + if (playersInfo.TryGetValue(victim, out var playerSkill) && playerSkill.CloneProp != null) + { + KillClone(playerSkill); + var victimPawn = victim.PlayerPawn.Value; + if (victimPawn == null) return; + SkillUtils.AddHealth(victimPawn, @event.DmgHealth); + } + } + + 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 = jRandomSkills.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 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) + { + 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/Jackal.cs b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs index 1ab239b..8c88a2b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Jackal.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Jackal.cs @@ -18,7 +18,7 @@ namespace src.player.skills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - Instance.ManifestResources.Add(SkillsInfo.GetValue(skillName, "particleName")); + Instance.AddToManifest(SkillsInfo.GetValue(skillName, "particleName")); } public static void NewRound() diff --git a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs index b164865..c8b955b 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Muhammed.cs @@ -38,7 +38,8 @@ namespace src.player.skills SkillUtils.CreateHEGrenadeProjectile(pos, angle, new Vector(0, 0, -10), player.TeamNum); foreach (var _p in Utilities.GetPlayers().Where(p => p.IsValid && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist && !p.IsBot)) - SkillUtils.PrintToChat(_p, $"{ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}{_p.GetTranslation("muhammed_explosion")}", false); + SkillUtils.PrintToChat(_p, $"{ChatColors.DarkRed}{player.PlayerName}: {ChatColors.Lime}{_p.GetTranslation("muhammed_explosion")}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); var fileNames = new[] { "radiobotfallback01", "radiobotfallback02", "radiobotfallback04" }; var randomFile = fileNames[new Random().Next(fileNames.Length)]; diff --git a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs index 5fd5f1f..0bdc11c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ninja.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ninja.cs @@ -1,11 +1,12 @@ -using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; +using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; -using static src.jRandomSkills; -using System.Collections.Concurrent; using src.utils; +using System.Collections.Concurrent; +using System.Drawing; +using static src.jRandomSkills; namespace src.player.skills { @@ -13,18 +14,23 @@ namespace src.player.skills { private const Skills skillName = Skills.Ninja; private static readonly ConcurrentDictionary invisibilityChanged = []; - private static readonly ConcurrentDictionary> invisibleEntities = []; + private static readonly ConcurrentDictionary invisiblePlayers = []; + private const string bloodParticle = "particles/blood_impact/blood_impact_high.vpcf"; private static readonly object setLock = new(); public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); + Instance.AddToManifest(bloodParticle); } public static void NewRound() { lock (setLock) + { invisibilityChanged.Clear(); + invisiblePlayers.Clear(); + } } public static void WeaponEquip(EventItemEquip @event) @@ -52,14 +58,22 @@ namespace src.player.skills foreach (var (info, player) in infoList) { if (player == null) continue; - foreach ((var playerId, var itemList) in invisibleEntities) - if (player.SteamID != playerId) - foreach (var entityIndex in itemList) - { - var entity = Utilities.GetEntityFromIndex((int)entityIndex); - if (entity == null || !entity.IsValid) continue; - info.TransmitEntities.Remove(entity.Index); - } + foreach (var _player in invisiblePlayers.Keys) + if (player.SteamID != _player.SteamID) + { + var playerPawn = _player.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 = HideBomb(_player); + if (bombIndex == null) continue; + var bombEntity = Utilities.GetEntityFromIndex((int)bombIndex); + if (bombEntity == null || !bombEntity.IsValid) continue; + info.TransmitEntities.Remove(bombEntity.Index); + } } } @@ -71,8 +85,7 @@ namespace src.player.skills if (playerInfo?.Skill == skillName) UpdateNinja(player); if (!player.PawnIsAlive) - if (invisibleEntities.ContainsKey(player.SteamID)) - invisibleEntities.TryRemove(player.SteamID, out _); + invisiblePlayers.TryRemove(player, out _); } } @@ -84,8 +97,7 @@ namespace src.player.skills public static void DisableSkill(CCSPlayerController player) { SetPlayerVisibility(player, 0); - SetWeaponVisibility(player, 0); - invisibleEntities.TryRemove(player.SteamID, out _); + invisiblePlayers.TryRemove(player, out _); } private static void UpdateNinja(CCSPlayerController? player) @@ -110,13 +122,19 @@ namespace src.player.skills if (!buttons.HasFlag(PlayerButtons.Moveleft) && !buttons.HasFlag(PlayerButtons.Moveright) && !buttons.HasFlag(PlayerButtons.Forward) && !buttons.HasFlag(PlayerButtons.Back) && flags.HasFlag(PlayerFlags.FL_ONGROUND)) percentInvisibility += SkillsInfo.GetValue(skillName, "idlePercentInvisibility"); - SetWeaponVisibility(player, percentInvisibility); if (invisibilityChanged.TryGetValue(player.Handle, out float oldInvisibility)) if (percentInvisibility == oldInvisibility) return; invisibilityChanged.TryAdd(player.Handle, percentInvisibility); - SetPlayerVisibility(player, percentInvisibility); + + if (percentInvisibility > .9) + invisiblePlayers.TryAdd(player, 0); + else + { + SetPlayerVisibility(player, percentInvisibility); + invisiblePlayers.TryRemove(player, out _); + } } private static void SetPlayerVisibility(CCSPlayerController player, float percentInvisibility) @@ -130,30 +148,46 @@ namespace src.player.skills } } - private static void SetWeaponVisibility(CCSPlayerController player, float percentInvisibility) + public static void PlayerHurt(EventPlayerHurt @event) { - if (!Instance.IsPlayerValid(player)) return; - var playerPawn = player.PlayerPawn.Value!; - if (playerPawn.WeaponServices == null) return; + var player = @event.Userid; + if (player == null || !player.IsValid) return; + if (!invisiblePlayers.ContainsKey(player)) return; - var color = Color.FromArgb(Math.Max(255 - (int)(255 * percentInvisibility * 2), 0), 255, 255, 255); + var playerPawn = player.PlayerPawn.Value; + if (playerPawn == null || !playerPawn.IsValid || playerPawn.AbsOrigin == null) return; - invisibleEntities.TryRemove(player.SteamID, out _); - if (color.A != 0) return; + CParticleSystem particle = Utilities.CreateEntityByName("info_particle_system")!; + if (particle == null) return; - foreach (var weapon in playerPawn.WeaponServices.MyWeapons) - { - if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid) - { - if (invisibleEntities.TryGetValue(player.SteamID, out var items)) - { - if (!items.Contains(weapon.Index)) - items.Add(weapon.Index); - } - else - invisibleEntities.TryAdd(player.SteamID, [weapon.Index]); - } - } + particle.EffectName = bloodParticle; + particle.StartActive = true; + + Vector pos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + 50); + particle.Teleport(pos); + particle.DispatchSpawn(); + + particle.AcceptInput("Start"); + } + + private static uint? HideBomb(CCSPlayerController player) + { + var bombEntities = Utilities.FindAllEntitiesByDesignerName("weapon_c4").ToList(); + if (bombEntities.Count == 0) return null; + + var bomb = bombEntities.FirstOrDefault(); + if (bomb == null) return null; + + if (bomb.OwnerEntity.Index != player.Index) return null; + + bomb.EntitySpottedState.Spotted = false; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpotted")); + + for (int i = 0; i < bomb.EntitySpottedState.SpottedByMask.Length; i++) + bomb.EntitySpottedState.SpottedByMask[i] = 0; + Utilities.SetStateChanged(bomb, "CCSPlayerPawn", "m_entitySpottedState", Schema.GetSchemaOffset("EntitySpottedState_t", "m_bSpottedByMask")); + + return bomb.Index; } public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#dedede", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float idlePercentInvisibility = .3f, float duckPercentInvisibility = .3f, float knifePercentInvisibility = .3f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) diff --git a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs index 7b962d0..de8ef31 100644 --- a/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs +++ b/jRandomSkills - SRC Files/src/player/skills/PawelJumper.cs @@ -40,7 +40,8 @@ namespace src.player.skills float extraJumps = (float)Instance.Random.Next(SkillsInfo.GetValue(skillName, "extraJumpsMin"), SkillsInfo.GetValue(skillName, "extraJumpsMax") + 1); playerInfo.SkillChance = extraJumps; - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, extraJumps)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, extraJumps)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } private static void GiveAdditionalJump(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs index 9720c16..159bfe9 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Phoenix.cs @@ -1,3 +1,4 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -29,7 +30,7 @@ namespace src.player.skills { player.Respawn(); Instance.AddTimer(.2f, () => player.Respawn()); - SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn"), false); + SkillUtils.PrintToChat(player, player.GetTranslation("phoenix_respawn")); } } } @@ -41,7 +42,8 @@ namespace src.player.skills 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)}", false); + 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 class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff5C0A", 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/Push.cs b/jRandomSkills - SRC Files/src/player/skills/Push.cs index b57fbed..33f7386 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Push.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Push.cs @@ -1,3 +1,4 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -37,7 +38,8 @@ namespace src.player.skills 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)}", false); + 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"); } private static void PushEnemy(CCSPlayerController player, QAngle attackerAngle) diff --git a/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs b/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs new file mode 100644 index 0000000..7b1109b --- /dev/null +++ b/jRandomSkills - SRC Files/src/player/skills/RCMelon.cs @@ -0,0 +1,292 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities.Constants; +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 System.Numerics; +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; + + Ray ray = new(Vector3.Zero); + CTraceFilter filter = new(playerPawn.Index, playerPawn.Index) + { + m_nObjectSetMask = 0xf, + m_nCollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER_MOVEMENT, + m_nInteractsWith = playerPawn.GetInteractsWith(), + m_nInteractsExclude = 0, + m_nBits = 11, + m_bIterateEntities = true, + m_bHitTriggers = false, + m_nInteractsAs = 0x40000 + }; + + filter.m_nHierarchyIds[0] = playerPawn.GetHierarchyId(); + filter.m_nHierarchyIds[1] = 0; + CGameTrace trace = TraceRay.TraceHull(eyePos, endPos, filter, ray); + + 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); + var victimPawn = victim.PlayerPawn.Value; + if (victimPawn == null) return; + SkillUtils.AddHealth(victimPawn, @event.DmgHealth); + } + } + + 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 = 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) + { + 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/ReZombie.cs b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs index 1cfe0bd..409740c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ReZombie.cs @@ -83,7 +83,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 = 200) : 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 = 250) : 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 b8c92fa..edf539d 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Replicator.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Replicator.cs @@ -135,7 +135,7 @@ namespace src.player.skills var attackerTeam = attackerPawn.TeamNum; var replicaTeam = replica.Globalname.EndsWith("CT") ? 3 : 2; - SkillUtils.TakeHealth(attackerPawn, attackerTeam != replicaTeam ? 15 : 5); + SkillUtils.TakeHealth(attackerPawn, attackerTeam != replicaTeam ? SkillsInfo.GetValue(skillName, "EnemyTeamDamage") : SkillsInfo.GetValue(skillName, "YourTeamDamage")); } public class PlayerSkillInfo @@ -145,9 +145,11 @@ namespace src.player.skills public DateTime Cooldown { get; set; } } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a3000b", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 15f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#a3000b", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 15f, int yourTeamDamage = 10, int enemyTeamDamage = 20) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public float Cooldown { get; set; } = cooldown; + public int YourTeamDamage { get; set; } = yourTeamDamage; + public int EnemyTeamDamage { get; set; } = enemyTeamDamage; } } } \ No newline at end of file diff --git a/jRandomSkills - SRC Files/src/player/skills/Shade.cs b/jRandomSkills - SRC Files/src/player/skills/Shade.cs index 30ce63e..0536f3e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Shade.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Shade.cs @@ -48,7 +48,8 @@ namespace src.player.skills 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)}", false); + 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) diff --git a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs index 21f2b9e..382ba51 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Soldier.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Soldier.cs @@ -1,4 +1,5 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using src.utils; @@ -22,7 +23,8 @@ namespace src.player.skills float newScale = (float)Instance.Random.NextDouble() * (SkillsInfo.GetValue(skillName, "ChanceTo") - SkillsInfo.GetValue(skillName, "ChanceFrom")) + SkillsInfo.GetValue(skillName, "ChanceFrom"); playerInfo.SkillChance = newScale; newScale = (float)Math.Round(newScale, 2); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName, newScale)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } public static void OnTakeDamage(DynamicHook h) diff --git a/jRandomSkills - SRC Files/src/player/skills/Thief.cs b/jRandomSkills - SRC Files/src/player/skills/Thief.cs index b670c99..99b585e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Thief.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Thief.cs @@ -95,7 +95,8 @@ namespace src.player.skills } SkillUtils.CreateMenu(player, menuItems); - SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", false); + SkillUtils.PrintToChat(player, $"{ChatColors.DarkRed}{player.GetSkillName(skillName)}{ChatColors.Lime}: {player.GetSkillDescription(skillName)}", + border: !Utilities.GetPlayers().Any(p => p.Team == player.Team && !p.IsBot && p != player) ? "tb" : "t"); } else player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}"); diff --git a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs index ca4ef7c..2eac8c1 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ThirdEye.cs @@ -96,6 +96,8 @@ namespace src.player.skills if (camera == null || !camera.IsValid) return 0; var pawn = player.PlayerPawn.Value; + if (pawn == null) return 0; + Server.NextFrame(() => { camera.SetModel("models/actors/ghost_speaker.vmdl"); diff --git a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs index 2911745..5add6c4 100644 --- a/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs +++ b/jRandomSkills - SRC Files/src/player/skills/ToxicSmoke.cs @@ -5,7 +5,6 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using src.utils; using System.Collections.Concurrent; -using System.Reflection.Metadata; using static src.jRandomSkills; namespace src.player.skills @@ -135,7 +134,7 @@ namespace src.player.skills } } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int smokeDamage = 2, float smokeRadius = 180) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + public class SkillConfig(Skills skill = skillName, bool active = false, string color = "#507529", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int smokeDamage = 2, float smokeRadius = 180) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public int SmokeDamage { get; set; } = smokeDamage; public float SmokeRadius { get; set; } = smokeRadius; diff --git a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs index 4d17c9a..40771ac 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Watchmaker.cs @@ -82,7 +82,7 @@ namespace src.player.skills playerInfo.PrintHTML = SkillUtils.SecondsToTimer(seconds); } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff462e", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int changeRoundTime = 10, string soundEvent = "UIPanorama.sidemenu_select") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) + public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff462e", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int changeRoundTime = 7, string soundEvent = "UIPanorama.sidemenu_select") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission) { public int ChangeRoundTime { get; set; } = changeRoundTime; public string SoundEvent { get; set; } = soundEvent; diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index 715828f..0e980b9 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -20,10 +20,14 @@ namespace src.utils private static readonly MemoryFunctionWithReturn HEGrenadeProjectile_CreateFunc = new(GameData.GetSignature("HEGrenadeProjectile_CreateFunc")); private static readonly MemoryFunctionVoid TerminateRoundFunc = new(GameData.GetSignature("CCSGameRules_TerminateRound")); - public static void PrintToChat(CCSPlayerController player, string msg, bool isError) + public static void PrintToChat(CCSPlayerController player, string msg, string border = "tb", string title = jRandomSkills.Tag) { - string checkIcon = isError ? $"{ChatColors.DarkRed}✖{ChatColors.LightRed}" : $"{ChatColors.Green}✔{ChatColors.Lime}"; - player.PrintToChat($" {ChatColors.DarkRed}► {ChatColors.Green}[{ChatColors.DarkRed} {jRandomSkills.Tag} {ChatColors.Green}] {checkIcon} {msg}"); + if (border.Contains('t')) + player.PrintToChat($" {ChatColors.Green}―――――――――――{ChatColors.DarkRed}◢◆◤ {title} ◥◆◣{ChatColors.Green}―――――――――――"); + if (!string.IsNullOrEmpty(msg)) + player.PrintToChat($" {ChatColors.Green} {msg}"); + if (border.Contains('b')) + player.PrintToChat($" {ChatColors.Green}―――――――――――――――{new string('―', title.Length)}―――――――――――――――"); } public static bool IsFreezeTime() @@ -81,7 +85,7 @@ namespace src.utils { using var msg = UserMessage.FromPartialName("Fade"); if (msg == null) return; - int packageColor = (a << 24) | (r << 16) | (g << 8) | b; + int packageColor = (a << 24) | (b << 16) | (g << 8) | r; msg.SetInt("duration", duration); msg.SetInt("hold_time", holdTime);