(CURRENTYLY BROKEN) Add new skills, signatures and fixes
Introduce multiple new skill implementations and related updates: add AimLock, HealingChicken, HomingNades, HotBomb, Illusionist, MagneticDecoy, ThrowingKnife, Weightless and WildThrow; register skills and HUD/cooldown handling. Update ISkill enum to include new skills. Add SnapViewAngles signature to gamedata. Improve existing skills to handle bayonet (BladeMaster, Cutter, Disarmament, LongKnife) and fix iteration/null-check issues in FrozenDecoy. Make HealingSmoke tick interval configurable and extend its config. Update English and Polish language files with new skill strings and tweaks. Also sync server-side gamedata and language files.
This commit is contained in:
parent
4e4458ad38
commit
97887118bf
31 changed files with 1625 additions and 73 deletions
|
|
@ -3,7 +3,7 @@
|
|||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 8B C4 48 89 58 ? 48 89 68 ? 48 89 70 ? 57 41 56 41 57 48 81 EC ? ? ? ? 48 8B B4 24 ? ? ? ? 4D 8B F8",
|
||||
"linux": "55 4C 89 C1 48 89 E5 41 57 49 89 FF 41 56 45 89 CE"
|
||||
"linux": "55 4C 89 C1 48 89 E5 41 57 45 89 CF 41 56 49 89 FE"
|
||||
}
|
||||
},
|
||||
"HEGrenadeProjectile_CreateFunc": {
|
||||
|
|
@ -19,5 +19,12 @@
|
|||
"windows": "48 89 5C 24 ? 57 48 83 EC 20 44 0F BF C2",
|
||||
"linux": "55 48 89 E5 41 54 53 48 89 FB 66 83 FE 65"
|
||||
}
|
||||
},
|
||||
"SnapViewAngles": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 48 89 FB 48 89 F7 48 81 EC ? ? ? ? E8 ? ? ? ? 48 8B 93"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +285,7 @@
|
|||
"psychicdefusing_hud_info": "{0} seconds remaining to defuse",
|
||||
|
||||
"pilot": "Pilot",
|
||||
"pilot_desc": "Fly for a limited time. Hold [USE - E] to fly",
|
||||
"pilot_desc": "Fly for a limited time. Double-click the jump to fly",
|
||||
"pilot_hud_info": "Fuel",
|
||||
|
||||
"planter": "Free Planter",
|
||||
|
|
@ -369,6 +369,9 @@
|
|||
"silent": "Silent",
|
||||
"silent_desc": "Your footsteps and jumps are silent to OTHER players",
|
||||
|
||||
"smoker": "Smoker",
|
||||
"smoker_desc": "Your smoke grenades never run out",
|
||||
|
||||
"sniperelite": "Sniper Elite",
|
||||
"sniperelite_customname": "Sniper Elite Skill",
|
||||
"sniperelite_desc": "Click [css_useSkill] to swap your current weapon for an AWP",
|
||||
|
|
@ -378,7 +381,7 @@
|
|||
"soldier_desc2": "Your damage multiplier is: {0}x",
|
||||
|
||||
"soundmaker": "Soundmaker",
|
||||
"soundmaker_desc": "Click [css_useSkill] to trigger a sound for every enemy",
|
||||
"soundmaker_desc": "Every now and then, you hear player screams",
|
||||
|
||||
"spectator": "Spectator",
|
||||
"spectator_desc": "Click [css_useSkill] to spectate a random enemy",
|
||||
|
|
@ -473,5 +476,52 @@
|
|||
|
||||
"menu_controlls_scroll": "W/S - Scroll",
|
||||
"menu_controlls_padding": " | ",
|
||||
"menu_controlls_select": "E - Select"
|
||||
"menu_controlls_select": "E - Select",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"aimlock": "Aim Lock",
|
||||
"aimlock_desc": "Click [css_useSkill] to lock your aim on the nearest enemy",
|
||||
|
||||
"homingnades": "Homing Grenades",
|
||||
"homingnades_desc": "Your grenades (except smokes) are attracted to enemies",
|
||||
|
||||
"hotbomb": "Hot Bomb",
|
||||
"hotbomb_desc": "As long as you are alive, the bomb deals damage to its carrier",
|
||||
"hotbomb_hint": "Careful, the bomb is hot!",
|
||||
|
||||
"illiterate": "Illiterate",
|
||||
"illiterate_desc": "As long as you are alive, your enemies cannot read",
|
||||
|
||||
"illusionist": "Illusionist",
|
||||
"illusionist_desc": "Click [css_useSkill] to deploy a replica that walks straight ahead",
|
||||
|
||||
"magneticdecoy": "Magnetic Decoy",
|
||||
"magneticdecoy_desc": "Your decoy attracts nearby players towards itself",
|
||||
|
||||
"magneto": "Magneto",
|
||||
"magneto_desc": "All enemy grenades are repelled away from you",
|
||||
|
||||
"weightless": "Weightlessness",
|
||||
"weightless_desc": "Your grenades are not affected by gravity and fly faster",
|
||||
|
||||
"wildthrow": "Wild Throws",
|
||||
"wildthrow_desc": "Choose a player who will have trouble throwing grenades",
|
||||
"wildthrow_player_info": "Player '{0}' has forgotten all their lineups",
|
||||
"wildthrow_select_info": "Select a player:",
|
||||
|
||||
"throwingknife": "Throwing Knife",
|
||||
"throwingknife_desc": "Click [css_useSkill] to throw a knife. But watch out for others"
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@
|
|||
"aimbot": "Aimbot",
|
||||
"aimbot_desc": "Każdy twój trafiony pocisk liczy się jako strzał w głowę",
|
||||
|
||||
"aimlock": "Aim Lock",
|
||||
"aimlock_desc": "Kliknij [css_useSkill], aby wycelować na najbliższego wroga",
|
||||
|
||||
"anomaly": "Anomalia",
|
||||
"anomaly_desc": "Cofasz się o kilka sekund do tyłu",
|
||||
|
||||
|
|
@ -77,7 +80,7 @@
|
|||
"cypher": "Kamera",
|
||||
"cypher_desc": "Kliknij [css_useSkill], aby utworzyć/przełączyć się na kamerę",
|
||||
"cypher_nospace": "Kamera musi być ustawiona pod kątem prostym do ściany",
|
||||
|
||||
|
||||
"darkness": "Mrok",
|
||||
"darkness_desc": "Nadaje efekt ciemności wybranemu przeciwnikowi",
|
||||
"darkness_enemy_info": "Niech zgasną światła.",
|
||||
|
|
@ -186,9 +189,18 @@
|
|||
"holyhandgrenade": "Święty Granat Ręczny",
|
||||
"holyhandgrenade_desc": "Twoje granaty uderzeniowe zadają podwójne obrażenia i mają podwójny zasięg",
|
||||
|
||||
"homingnades": "Namierzające Granaty",
|
||||
"homingnades_desc": "Twoje granaty (oprócz dymnych) są przyciągane do wrogów",
|
||||
|
||||
"hotbomb": "Gorąca Bomba",
|
||||
"hotbomb_desc": "Póki żyjesz, bomba zadaje obrażenia nosicielowi",
|
||||
|
||||
"iana": "Hologram",
|
||||
"iana_desc": "Kliknij [css_useSkill], aby sterować hologramem przez kilka sekund",
|
||||
|
||||
"illiterate": "Analfabeta",
|
||||
"illiterate_desc": "Dopóki żyjesz, twoi wrogowie nie potrafią czytać",
|
||||
|
||||
"impostor": "Szpieg",
|
||||
"impostor_desc": "Na początku rundy otrzymujesz model postaci przeciwnika",
|
||||
|
||||
|
|
@ -234,6 +246,12 @@
|
|||
"longzeus": "Długi Zeus",
|
||||
"longzeus_desc": "Zeus zadaje obrażenia niezależnie od odległości",
|
||||
|
||||
"magneticdecoy": "Magnetyczny Decoy",
|
||||
"magneticdecoy_desc": "Twój wabik przyciąga graczy wokół siebie",
|
||||
|
||||
"magneto": "Magneto",
|
||||
"magneto_desc": "Wszystkie granaty przeciwnika są odpychane od ciebie",
|
||||
|
||||
"magnifier": "Lupa",
|
||||
"magnifier_desc": "Przybiżasz ekran wybranemu przeciwnikowi",
|
||||
"magnifier_enemy_info": "Twoje pole widzenia zostało zniekształcone!",
|
||||
|
|
@ -285,7 +303,7 @@
|
|||
"psychicdefusing_hud_info": "Pozostało {0} sekund do rozbrojenia",
|
||||
|
||||
"pilot": "Pilot",
|
||||
"pilot_desc": "Latanie przez określony czas. Przytrzymaj [USE - E], aby latać",
|
||||
"pilot_desc": "Latanie przez określony czas. Kliknij dwukrotnie skok, aby latać",
|
||||
"pilot_hud_info": "Paliwo",
|
||||
|
||||
"planter": "Samowolka",
|
||||
|
|
@ -369,7 +387,10 @@
|
|||
"silent": "Cichociemny",
|
||||
"silent_desc": "Twoje kroki i skoki są niesłyszalne dla INNYCH graczy",
|
||||
|
||||
"sniperelite": "SzeliS",
|
||||
"smoker": "Zadymiarz",
|
||||
"smoker_desc": "Twoje granaty dymne nigdy się nie kończą",
|
||||
|
||||
"sniperelite": "Papito",
|
||||
"sniperelite_customname": "Mityczna AWP",
|
||||
"sniperelite_desc": "Kliknij [css_useSkill], aby zamienić aktualną broń na AWP",
|
||||
|
||||
|
|
@ -378,7 +399,7 @@
|
|||
"soldier_desc2": "Twój mnożnik obrażeń wynosi: {0}x",
|
||||
|
||||
"soundmaker": "Dźwiękowiec",
|
||||
"soundmaker_desc": "Kliknij [css_useSkill], aby wywołać dzwięk u każdego przeciwnika",
|
||||
"soundmaker_desc": "Co jakiś czas szłyszysz krzyki graczy",
|
||||
|
||||
"spectator": "Obserwator",
|
||||
"spectator_desc": "Kliknij [css_useSkill], aby obserwować losowego przeciwnika",
|
||||
|
|
@ -402,6 +423,9 @@
|
|||
"thorns": "Ciernie",
|
||||
"thorns_desc": "Twój przeciwnik otrzymuje część obrażeń, które zadał ci",
|
||||
|
||||
"throwingknife": "Nóż do Rzucania",
|
||||
"throwingknife_desc": "Kliknij [css_useSkill], aby rzucić nożem. Ale uważaj na innych",
|
||||
|
||||
"toxicsmoke": "Toksyczny Dym",
|
||||
"toxicsmoke_desc": "Twoje granaty dymny zadają obrażenia",
|
||||
|
||||
|
|
@ -417,6 +441,14 @@
|
|||
"weaponsswap_desc": "Kliknij [css_useSkill], aby zamienić się bronią z losowym przeciwnikiem",
|
||||
"weaponsswap_hud_info2": "Nie posiadasz broni na zamiane",
|
||||
|
||||
"weightless": "Stan Nieważkości",
|
||||
"weightless_desc": "Twoje granaty nie podlegają grawitacji i lecą szybciej",
|
||||
|
||||
"wildthrow": "Dzikie rzuty",
|
||||
"wildthrow_desc": "Wybierz gracza, który będzie miał trudności z rzucaniem granatami",
|
||||
"wildthrow_player_info": "Gracz '{0}' zapomniał wszystkie lineup'y",
|
||||
"wildthrow_select_info": "Wybierz gracza:",
|
||||
|
||||
"zeus": "Zeus",
|
||||
"zeus_desc": "Zeus x27 natychmiastowo się odnawia",
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public enum Skills
|
|||
{
|
||||
None,
|
||||
Aimbot,
|
||||
AimLock, // <-
|
||||
Anomaly,
|
||||
AntyFlash,
|
||||
AntyHead,
|
||||
|
|
@ -79,7 +80,7 @@ public enum Skills
|
|||
Dracula,
|
||||
Duplicator,
|
||||
Dwarf,
|
||||
Earthquake,
|
||||
Earthquake, // <-
|
||||
EnemySpawn,
|
||||
ExplosiveShot,
|
||||
FalconEye,
|
||||
|
|
@ -96,11 +97,15 @@ public enum Skills
|
|||
Glue,
|
||||
GodMode,
|
||||
Grenadier,
|
||||
HealingChicken, // <-
|
||||
HealingSmoke,
|
||||
Hermit,
|
||||
HolyHandGrenade,
|
||||
HomingNades, // <-
|
||||
HotBomb,
|
||||
Iana,
|
||||
Illiterate,
|
||||
Illusionist,
|
||||
Impostor,
|
||||
InfiniteAmmo,
|
||||
Jackal,
|
||||
|
|
@ -112,6 +117,8 @@ public enum Skills
|
|||
LifeSwap,
|
||||
LongKnife,
|
||||
LongZeus,
|
||||
MagneticDecoy,
|
||||
Magneto,
|
||||
Magnifier,
|
||||
Medic,
|
||||
MoneySwap,
|
||||
|
|
@ -125,7 +132,7 @@ public enum Skills
|
|||
PawelJumper,
|
||||
Phoenix,
|
||||
PsychicDefusing,
|
||||
Pilot,
|
||||
Pilot, // <-
|
||||
Planter,
|
||||
Poison,
|
||||
PrimaryBan,
|
||||
|
|
@ -136,7 +143,7 @@ public enum Skills
|
|||
RadarHack,
|
||||
Rambo,
|
||||
RandomWeapon,
|
||||
RCMelon,
|
||||
RCMelon, // <-
|
||||
ReZombie,
|
||||
ReactiveArmor,
|
||||
Regeneration,
|
||||
|
|
@ -149,10 +156,10 @@ public enum Skills
|
|||
Saper,
|
||||
SecondLife,
|
||||
Shade,
|
||||
ShortBomb,
|
||||
ShortBomb, // <- short
|
||||
Silent,
|
||||
Smoker,
|
||||
SniperElite,
|
||||
Smoker, // <- nie dziala
|
||||
SniperElite, // <- nie dziala
|
||||
Soldier,
|
||||
SoundMaker,
|
||||
Spectator,
|
||||
|
|
@ -161,9 +168,12 @@ public enum Skills
|
|||
Thief,
|
||||
ThirdEye,
|
||||
Thorns,
|
||||
ThrowingKnife,
|
||||
ToxicSmoke,
|
||||
Wallhack,
|
||||
Watchmaker,
|
||||
WeaponsSwap,
|
||||
Weightless,
|
||||
WildThrow,
|
||||
Zeus,
|
||||
}
|
||||
|
|
|
|||
146
jRandomSkills - SRC Files/src/player/skills/AimLock.cs
Normal file
146
jRandomSkills - SRC Files/src/player/skills/AimLock.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class AimLock : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.AimLock;
|
||||
private static readonly ConcurrentDictionary<ulong, PlayerSkillInfo> SkillPlayerInfo = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
lock (setLock)
|
||||
SkillPlayerInfo.Clear();
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
{
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
|
||||
UpdateHUD(player, skillInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo
|
||||
{
|
||||
SteamID = player.SteamID,
|
||||
CanUse = true,
|
||||
Cooldown = DateTime.MinValue,
|
||||
});
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillPlayerInfo.TryRemove(player.SteamID, out _);
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
}
|
||||
|
||||
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
|
||||
{
|
||||
float cooldown = 0;
|
||||
if (skillInfo != null)
|
||||
{
|
||||
float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue<float>(skillName, "cooldown")) - DateTime.Now).TotalSeconds);
|
||||
cooldown = Math.Max(time, 0);
|
||||
|
||||
if (cooldown == 0 && skillInfo?.CanUse == false)
|
||||
skillInfo.CanUse = true;
|
||||
}
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID);
|
||||
if (playerInfo == null) return;
|
||||
|
||||
if (cooldown == 0)
|
||||
playerInfo.PrintHTML = null;
|
||||
else
|
||||
playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
|
||||
}
|
||||
|
||||
public static void UseSkill(CCSPlayerController player)
|
||||
{
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn?.CBodyComponent == null) return;
|
||||
|
||||
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
|
||||
{
|
||||
if (!player.IsValid || !player.PawnIsAlive) return;
|
||||
if (skillInfo.CanUse)
|
||||
{
|
||||
skillInfo.CanUse = false;
|
||||
skillInfo.Cooldown = DateTime.Now;
|
||||
LookAtEnemey(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void LookAtEnemey(CCSPlayerController player)
|
||||
{
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
|
||||
CCSPlayerController? closetEnemy = null;
|
||||
double minDist = double.MaxValue;
|
||||
|
||||
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team != player.Team))
|
||||
{
|
||||
var enemyPawn = enemy.PlayerPawn.Value;
|
||||
if (enemyPawn == null || !enemyPawn.IsValid || enemyPawn.AbsOrigin == null) return;
|
||||
|
||||
double dist = SkillUtils.GetDistance(enemyPawn.AbsOrigin, pawn.AbsOrigin);
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
closetEnemy = enemy;
|
||||
}
|
||||
}
|
||||
|
||||
if (closetEnemy != null)
|
||||
{
|
||||
Vector enemyPos = closetEnemy.PlayerPawn.Value!.AbsOrigin!;
|
||||
Vector myPos = pawn.AbsOrigin;
|
||||
|
||||
|
||||
Vector direction = enemyPos - myPos;
|
||||
QAngle angle = VectorToAngle(direction);
|
||||
|
||||
pawn.Look(angle);
|
||||
}
|
||||
}
|
||||
|
||||
private static QAngle VectorToAngle(Vector direction)
|
||||
{
|
||||
float pitch = (float)(-Math.Atan2(direction.Z, Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y)) * 180 / Math.PI);
|
||||
float yaw = (float)(Math.Atan2(direction.Y, direction.X) * 180 / Math.PI);
|
||||
|
||||
return new QAngle(pitch, yaw, 0);
|
||||
}
|
||||
|
||||
public class PlayerSkillInfo
|
||||
{
|
||||
public ulong SteamID { get; set; }
|
||||
public bool CanUse { get; set; }
|
||||
public DateTime Cooldown { get; set; }
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#fa7b48", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 5f) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float Cooldown { get; set; } = cooldown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ namespace src.player.skills
|
|||
public class BladeMaster : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.BladeMaster;
|
||||
private static readonly string[] noReflectionWeapon = ["inferno", "flashbang", "smokegrenade", "decoy", "hegrenade", "knife", "taser"];
|
||||
private static readonly string[] noReflectionWeapon = ["inferno", "flashbang", "smokegrenade", "decoy", "hegrenade", "knife", "taser", "bayonet"];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -30,7 +30,7 @@ namespace src.player.skills
|
|||
|
||||
var weaponServices = playerPawn.WeaponServices;
|
||||
if (weaponServices == null) return;
|
||||
if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife")
|
||||
if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || (weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife" && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet"))
|
||||
return;
|
||||
|
||||
playerPawn.VelocityModifier = SkillsInfo.GetValue<float>(skillName, "velocityModifier");
|
||||
|
|
@ -63,7 +63,7 @@ namespace src.player.skills
|
|||
|
||||
var weaponServices = pawn.WeaponServices;
|
||||
if (weaponServices == null) return;
|
||||
if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife")
|
||||
if (weaponServices.ActiveWeapon == null || !weaponServices.ActiveWeapon.IsValid || weaponServices.ActiveWeapon.Value == null || !weaponServices.ActiveWeapon.Value.IsValid || (weaponServices.ActiveWeapon.Value.DesignerName != "weapon_knife" && weaponServices.ActiveWeapon.Value.DesignerName != "weapon_bayonet"))
|
||||
return;
|
||||
|
||||
SkillUtils.RestoreHealth(victim);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace src.player.skills
|
|||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == attacker?.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
if (weapon == "knife")
|
||||
if (weapon == "knife" || weapon == "bayonet")
|
||||
SkillUtils.TakeHealth(victim!.PlayerPawn.Value, 9999);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace src.player.skills
|
|||
if (weaponServices?.ActiveWeapon == null) return;
|
||||
|
||||
var weaponName = weaponServices?.ActiveWeapon?.Value?.DesignerName;
|
||||
if (weaponName != null && !weaponName.Contains("weapon_knife") && !weaponName.Contains("weapon_c4"))
|
||||
if (weaponName != null && !weaponName.Contains("weapon_knife") && !weaponName.Contains("weapon_bayonet") && !weaponName.Contains("weapon_c4"))
|
||||
victim.DropActiveWeapon();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
decoys.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0);
|
||||
}
|
||||
|
||||
|
|
@ -36,8 +38,10 @@ namespace src.player.skills
|
|||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
foreach (var decoy in decoys.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z))
|
||||
decoys.TryRemove(decoy, out _);
|
||||
}
|
||||
|
|
@ -45,11 +49,11 @@ namespace src.player.skills
|
|||
public static void OnTick()
|
||||
{
|
||||
foreach (Vector decoyPos in decoys.Keys)
|
||||
foreach (var player in Utilities.GetPlayers().Where(p => p.Team == CsTeam.Terrorist || p.Team == CsTeam.CounterTerrorist))
|
||||
foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
|
||||
{
|
||||
var decoyRadius = SkillsInfo.GetValue<float>(skillName, "triggerRadius");
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue;
|
||||
double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin);
|
||||
if (distance <= decoyRadius)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using static src.jRandomSkills;
|
||||
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class HealingChicken : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.HealingChicken;
|
||||
private readonly static ConcurrentDictionary<ulong, List<Timer>> playerSmokes = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SpawnChicken(player);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void SpawnChicken(CCSPlayerController player)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
|
||||
int amount = SkillsInfo.GetValue<int>(skillName, "amount");
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
CChicken? chicken = Utilities.CreateEntityByName<CChicken>("chicken");
|
||||
if (chicken == null || !chicken.IsValid) continue;
|
||||
|
||||
chicken.Render = Color.Green;
|
||||
Vector offset = new (
|
||||
(float)(100 * Math.Cos(2 * Math.PI * i / amount)),
|
||||
(float)(100 * Math.Sin(2 * Math.PI * i / amount)),
|
||||
0
|
||||
);
|
||||
|
||||
chicken.DispatchSpawn();
|
||||
chicken.Teleport(pawn.AbsOrigin + offset);
|
||||
|
||||
// Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_leader", player.PlayerPawn.Raw);
|
||||
Vector spawn = SkillUtils.GetSpawnPointVector(player);
|
||||
Schema.SetSchemaValue(chicken.Handle, "CChicken", "m_vecPathGoal", spawn);
|
||||
|
||||
float speed = 50;
|
||||
Instance.AddTickTimer(1, () =>
|
||||
{
|
||||
if (chicken == null || !chicken.IsValid) return;
|
||||
|
||||
Server.PrintToChatAll($"{chicken.PathGoal}, {chicken.UpdateTimer.Duration}, {chicken.UpdateTimer.Timescale}");
|
||||
}, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int amount = 3, int heal = 2, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public int Amount { get; set; } = amount;
|
||||
public int Heal { get; set; } = heal;
|
||||
public int TickCooldown { get; set; } = tickCooldown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,9 +70,10 @@ namespace src.player.skills
|
|||
|
||||
public static void OnTick()
|
||||
{
|
||||
int tick = SkillsInfo.GetValue<int>(skillName, "tickCooldown");
|
||||
foreach (Vector smokePos in smokes.Keys)
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
if (Server.TickCount % 16 == 0)
|
||||
if (Server.TickCount % tick == 0)
|
||||
if (player.PlayerPawn.Value != null && player.PlayerPawn.Value.IsValid && player.PlayerPawn.Value.AbsOrigin != null)
|
||||
if (SkillUtils.GetDistance(smokePos, player.PlayerPawn.Value.AbsOrigin) <= SkillsInfo.GetValue<float>(skillName, "smokeRadius"))
|
||||
AddHealth(player.PlayerPawn.Value, SkillsInfo.GetValue<int>(skillName, "smokeHeal"));
|
||||
|
|
@ -95,10 +96,11 @@ namespace src.player.skills
|
|||
Utilities.SetStateChanged(player, "CBaseEntity", "m_iHealth");
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1fe070", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int smokeHeal = 1, float smokeRadius = 180) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#1fe070", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", int smokeHeal = 1, float smokeRadius = 180, int tickCooldown = 16) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public int SmokeHeal { get; set; } = smokeHeal;
|
||||
public float SmokeRadius { get; set; } = smokeRadius;
|
||||
public int TickCooldown { get; set; } = tickCooldown;
|
||||
}
|
||||
}
|
||||
}
|
||||
155
jRandomSkills - SRC Files/src/player/skills/HomingNades.cs
Normal file
155
jRandomSkills - SRC Files/src/player/skills/HomingNades.cs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class HomingNades : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.HomingNades;
|
||||
private readonly static ConcurrentDictionary<uint, (Vector, double)> nades = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
nades.Clear();
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
if (Server.TickCount % 10 != 0) return;
|
||||
|
||||
foreach (var index in nades.Keys.ToList())
|
||||
{
|
||||
if (!nades.TryGetValue(index, out var data)) continue;
|
||||
(Vector oldPos, double createdTime) = data;
|
||||
|
||||
var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)index);
|
||||
if (nade == null || !nade.IsValid || nade.AbsOrigin == null)
|
||||
{
|
||||
nades.TryRemove(index, out _);
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector currentPos = new(nade.AbsOrigin.X, nade.AbsOrigin.Y, nade.AbsOrigin.Z);
|
||||
double distanceMoved = SkillUtils.GetDistance(currentPos, oldPos);
|
||||
Vector calculatedVelocity = CalculateVelocity(nade, nade.TeamNum);
|
||||
|
||||
Server.PrintToChatAll($"Dist: {distanceMoved}, vel: {calculatedVelocity}");
|
||||
|
||||
if (distanceMoved < 4 || calculatedVelocity.IsZero())
|
||||
{
|
||||
Server.PrintToChatAll($"Short, {Server.TickedTime} -> {createdTime + 3}, {createdTime + 3 - Server.TickedTime}s");
|
||||
|
||||
nade.DetonateTime = (float)createdTime + 3;
|
||||
Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime");
|
||||
nades.TryRemove(index, out _);
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector currentVel = new(nade.Velocity.X, nade.Velocity.Y, nade.Velocity.Z);
|
||||
float maxVelocity = SkillsInfo.GetValue<float>(skillName, "maxVelocity");
|
||||
Vector newVelocity = currentVel + calculatedVelocity;
|
||||
|
||||
float speed = newVelocity.Length();
|
||||
if (speed > maxVelocity)
|
||||
newVelocity *= (maxVelocity / speed);
|
||||
|
||||
nades[index] = (currentPos, createdTime);
|
||||
nade.Teleport(null, null, newVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector CalculateVelocity(CBaseCSGrenadeProjectile nade, int team)
|
||||
{
|
||||
if (nade.AbsOrigin == null) return Vector.Zero;
|
||||
|
||||
Vector? closetEnemyPos = null;
|
||||
double minDistance = int.MaxValue;
|
||||
Vector nadePos = nade.AbsOrigin;
|
||||
|
||||
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.TeamNum != team))
|
||||
{
|
||||
var pawn = enemy.PlayerPawn.Value;
|
||||
if (pawn?.IsValid != true || pawn.AbsOrigin == null) continue;
|
||||
|
||||
double dist = SkillUtils.GetDistance(nadePos, pawn.AbsOrigin);
|
||||
if (dist < SkillsInfo.GetValue<float>(skillName, "detonationRange"))
|
||||
{
|
||||
nade.DetonateTime = 0;
|
||||
Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime");
|
||||
|
||||
nades.TryRemove(nade.Index, out _);
|
||||
return Vector.Zero;
|
||||
}
|
||||
|
||||
if (dist < minDistance)
|
||||
{
|
||||
minDistance = dist;
|
||||
closetEnemyPos = pawn.AbsOrigin;
|
||||
}
|
||||
}
|
||||
|
||||
if (closetEnemyPos == null)
|
||||
return Vector.Zero;
|
||||
|
||||
Vector direction = closetEnemyPos - nadePos;
|
||||
float length = direction.Length();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
float strength = SkillsInfo.GetValue<float>(skillName, "strength");
|
||||
return new Vector(
|
||||
(direction.X / length) * strength,
|
||||
(direction.Y / length) * strength,
|
||||
(direction.Z / length) * strength
|
||||
);
|
||||
}
|
||||
|
||||
return Vector.Zero;
|
||||
}
|
||||
|
||||
public static void OnEntitySpawned(CEntityInstance @event)
|
||||
{
|
||||
var name = @event.DesignerName;
|
||||
if (!name.EndsWith("_projectile") || name == "smokegrenade_projectile") return;
|
||||
|
||||
var grenade = @event.As<CBaseCSGrenadeProjectile>();
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
|
||||
if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return;
|
||||
var pawn = grenade.OwnerEntity.Value.As<CCSPlayerPawn>();
|
||||
|
||||
if (pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return;
|
||||
var player = pawn.Controller.Value.As<CCSPlayerController>();
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
grenade.DetonateTime = (float)Server.TickedTime + 6;
|
||||
|
||||
Vector pos = new(grenade.AbsOrigin?.X, grenade.AbsOrigin?.Y, grenade.AbsOrigin?.Z);
|
||||
nades.TryAdd(grenade.Index, (pos, Server.TickedTime));
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#384728", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float strength = 150, float maxVelocity = 2000, float detonationRange = 130) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float Strength { get; set; } = strength;
|
||||
public float MaxVelocity { get; set; } = maxVelocity;
|
||||
public float DetonationRange { get; set; } = detonationRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
jRandomSkills - SRC Files/src/player/skills/HotBomb.cs
Normal file
102
jRandomSkills - SRC Files/src/player/skills/HotBomb.cs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class HotBomb : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.HotBomb;
|
||||
private readonly static ConcurrentDictionary<uint, byte> players = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
float cooldown = SkillsInfo.GetValue<float>(skillName, "cooldown");
|
||||
if (Server.TickCount % (int)(cooldown * 64) != 0) return;
|
||||
|
||||
if (players.IsEmpty || jRandomSkills.Instance.GameRules?.FreezePeriod == true) return;
|
||||
int damage = SkillsInfo.GetValue<int>(skillName, "damage");
|
||||
|
||||
foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.Team == CsTeam.Terrorist && p.PawnIsAlive))
|
||||
{
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) continue;
|
||||
|
||||
bool hasC4 = pawn.WeaponServices.MyWeapons.Any(w => w.Value?.DesignerName == "weapon_c4");
|
||||
|
||||
if (!hasC4) continue;
|
||||
SkillUtils.TakeHealth(pawn, damage);
|
||||
player.ExecuteClientCommand("play sounds/player/burn_damage1");
|
||||
}
|
||||
}
|
||||
|
||||
public static void WeaponPickup(EventItemPickup @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var weapon = @event.Item;
|
||||
if (string.IsNullOrEmpty(weapon) || weapon != "c4") return;
|
||||
|
||||
player.PrintToCenterAlert(player.GetTranslation("hotbomb_hint"));
|
||||
}
|
||||
|
||||
private static void ChangeC4Color()
|
||||
{
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
var bombEntities = Utilities.FindAllEntitiesByDesignerName<CC4>("weapon_c4").ToList();
|
||||
if (bombEntities.Count == 0) return;
|
||||
|
||||
var bomb = bombEntities.FirstOrDefault();
|
||||
if (bomb == null) return;
|
||||
|
||||
bomb.Render = Color.Red;
|
||||
Utilities.SetStateChanged(bomb, "CBaseModelEntity", "m_clrRender");
|
||||
});
|
||||
}
|
||||
|
||||
public static void PlayerDeath(EventPlayerDeath @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
players.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
players.Clear();
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
if (players.IsEmpty)
|
||||
{
|
||||
ChangeC4Color();
|
||||
foreach (var enemy in Utilities.GetPlayers().Where(p => p.IsValid && p.Team == CsTeam.Terrorist && p.PawnIsAlive))
|
||||
enemy.PrintToCenterAlert(enemy.GetTranslation("hotbomb_hint"));
|
||||
}
|
||||
|
||||
players.TryAdd(player.Index, 0);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
players.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#baf081", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float cooldown = 1, int damage = 2) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float Cooldown { get; set; } = cooldown;
|
||||
public int Damage { get; set; } = damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,8 +47,8 @@ namespace src.player.skills
|
|||
return Utilities.GetPlayers().Any(
|
||||
p => p.IsValid &&
|
||||
p.PawnIsAlive &&
|
||||
p.Team != player.Team
|
||||
&& playersWithSkill.Contains(p.SteamID));
|
||||
p.Team != player.Team &&
|
||||
playersWithSkill.Contains(p.SteamID));
|
||||
}
|
||||
|
||||
public static string? GetRandomText(string? input)
|
||||
|
|
|
|||
217
jRandomSkills - SRC Files/src/player/skills/Illusionist.cs
Normal file
217
jRandomSkills - SRC Files/src/player/skills/Illusionist.cs
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using static src.jRandomSkills;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class Illusionist : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Illusionist;
|
||||
private static readonly ConcurrentDictionary<ulong, PlayerSkillInfo> SkillPlayerInfo = [];
|
||||
private static readonly ConcurrentDictionary<int, Timer> ActiveTimers = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
ClearAllReplicas();
|
||||
lock (setLock)
|
||||
SkillPlayerInfo.Clear();
|
||||
}
|
||||
|
||||
private static void ClearAllReplicas()
|
||||
{
|
||||
foreach (var timer in ActiveTimers.Values) timer?.Kill();
|
||||
ActiveTimers.Clear();
|
||||
|
||||
var entities = Utilities.FindAllEntitiesByDesignerName<CDynamicProp>("prop_dynamic_override");
|
||||
foreach (var entity in entities)
|
||||
if (entity != null && entity.IsValid && entity.Entity != null && !string.IsNullOrEmpty(entity.Entity.Name) && (entity.Entity.Name?.StartsWith("Illusionist_") ?? false))
|
||||
entity.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
{
|
||||
if (player == null || !player.IsValid || player.IsBot) continue;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill == skillName)
|
||||
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo))
|
||||
UpdateHUD(player, skillInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillPlayerInfo.TryAdd(player.SteamID, new PlayerSkillInfo
|
||||
{
|
||||
SteamID = player.SteamID,
|
||||
CanUse = true,
|
||||
Cooldown = DateTime.MinValue,
|
||||
});
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillPlayerInfo.TryRemove(player.SteamID, out _);
|
||||
SkillUtils.ResetPrintHTML(player);
|
||||
}
|
||||
|
||||
private static void UpdateHUD(CCSPlayerController player, PlayerSkillInfo skillInfo)
|
||||
{
|
||||
float cooldown = 0;
|
||||
if (skillInfo != null)
|
||||
{
|
||||
float time = (int)Math.Ceiling((skillInfo.Cooldown.AddSeconds(SkillsInfo.GetValue<float>(skillName, "cooldown")) - DateTime.Now).TotalSeconds);
|
||||
cooldown = Math.Max(time, 0);
|
||||
|
||||
if (cooldown == 0 && skillInfo?.CanUse == false)
|
||||
skillInfo.CanUse = true;
|
||||
}
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(s => s.SteamID == player?.SteamID);
|
||||
if (playerInfo == null) return;
|
||||
|
||||
if (cooldown == 0)
|
||||
playerInfo.PrintHTML = null;
|
||||
else
|
||||
playerInfo.PrintHTML = $"{player.GetTranslation("hud_info", $"<font color='#FF0000'>{cooldown}</font>")}";
|
||||
}
|
||||
|
||||
public static void UseSkill(CCSPlayerController player)
|
||||
{
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
|
||||
|
||||
if (SkillPlayerInfo.TryGetValue(player.SteamID, out var skillInfo) && skillInfo.CanUse)
|
||||
{
|
||||
skillInfo.CanUse = false;
|
||||
skillInfo.Cooldown = DateTime.Now;
|
||||
CreateReplica(player);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateReplica(CCSPlayerController player)
|
||||
{
|
||||
var playerPawn = player.PlayerPawn.Value;
|
||||
if (playerPawn == null || !playerPawn.IsValid) return;
|
||||
if (playerPawn.AbsOrigin == null || playerPawn.AbsRotation == null) return;
|
||||
|
||||
var replica = Utilities.CreateEntityByName<CDynamicProp>("prop_dynamic_override");
|
||||
if (replica == null || !replica.IsValid) return;
|
||||
|
||||
replica.Collision.SolidType = SolidType_t.SOLID_VPHYSICS;
|
||||
replica.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(replica.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2));
|
||||
|
||||
replica.SetModel(playerPawn!.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName);
|
||||
replica.Entity!.Name = replica.Globalname = $"Illusionist_{Server.TickCount}_{(player.Team == CsTeam.CounterTerrorist ? "CT" : "TT")}";
|
||||
|
||||
replica.UseAnimGraph = false;
|
||||
replica.DispatchSpawn();
|
||||
|
||||
float distance = 40;
|
||||
Vector startPos = playerPawn.AbsOrigin + SkillUtils.GetForwardVector(playerPawn.AbsRotation) * distance;
|
||||
QAngle angle = new(0, playerPawn.EyeAngles.Y, 0);
|
||||
replica.Teleport(startPos, angle, new Vector(0, 0, -100));
|
||||
|
||||
bool ducking = ((PlayerFlags)playerPawn.Flags).HasFlag(PlayerFlags.FL_DUCKING);
|
||||
|
||||
string animName = ducking ? "crouch_new_knife_n" : "run_new_knife_n";
|
||||
replica.AcceptInput("SetAnimation", value: animName);
|
||||
replica.AcceptInput("SetPlaybackRate", value: "1.0");
|
||||
|
||||
float speed = ducking ? 1.25f : 3.5f;
|
||||
Vector forwardVec = SkillUtils.GetForwardVector(angle);
|
||||
int replicaIndex = (int)replica.Index;
|
||||
|
||||
Instance.AddTickTimer(10, () => {
|
||||
var moveTimer = Instance.AddTickTimer(1, () =>
|
||||
{
|
||||
if (replica == null || !replica.IsValid)
|
||||
{
|
||||
if (ActiveTimers.TryRemove(replicaIndex, out var timer)) timer?.Kill();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ducking && Server.TickCount % 50 == 0)
|
||||
{
|
||||
replica.AcceptInput("SetAnimation", value: animName);
|
||||
replica.AcceptInput("SetPlaybackRate", value: "1.0");
|
||||
}
|
||||
|
||||
Vector currentPos = replica.AbsOrigin!;
|
||||
Vector nexPos = new(
|
||||
currentPos.X + (forwardVec.X * speed),
|
||||
currentPos.Y + (forwardVec.Y * speed),
|
||||
currentPos.Z
|
||||
);
|
||||
replica.Teleport(nexPos, null, null);
|
||||
}, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE);
|
||||
ActiveTimers.TryAdd(replicaIndex, moveTimer);
|
||||
});
|
||||
|
||||
float duration = SkillsInfo.GetValue<float>(skillName, ducking ? "durationCrouch" : "durationRun");
|
||||
Instance.AddTimer(duration, () =>
|
||||
{
|
||||
if (replica != null && replica.IsValid)
|
||||
{
|
||||
replica.AcceptInput("Kill");
|
||||
if (ActiveTimers.TryRemove(replicaIndex, out var timer)) timer?.Kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void OnTakeDamage(DynamicHook h)
|
||||
{
|
||||
CEntityInstance param = h.GetParam<CEntityInstance>(0);
|
||||
CTakeDamageInfo param2 = h.GetParam<CTakeDamageInfo>(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("Illusionist_")) return;
|
||||
|
||||
var replica = param.As<CDynamicProp>();
|
||||
if (replica == null || !replica.IsValid) return;
|
||||
|
||||
replica.EmitSound("GlassBottle.BulletImpact", volume: 1f);
|
||||
if (ActiveTimers.TryRemove((int)replica.Index, out var timer)) timer?.Kill();
|
||||
replica.AcceptInput("Kill");
|
||||
|
||||
CCSPlayerPawn attackerPawn = new(param2.Attacker.Value.Handle);
|
||||
if (attackerPawn.DesignerName != "player") return;
|
||||
|
||||
var attackerTeam = attackerPawn.TeamNum;
|
||||
var replicaTeam = replica.Globalname.EndsWith("CT") ? 3 : 2;
|
||||
SkillUtils.TakeHealth(attackerPawn, attackerTeam != replicaTeam ? SkillsInfo.GetValue<int>(skillName, "EnemyTeamDamage") : SkillsInfo.GetValue<int>(skillName, "YourTeamDamage"));
|
||||
}
|
||||
|
||||
public class PlayerSkillInfo
|
||||
{
|
||||
public ulong SteamID { get; set; }
|
||||
public bool CanUse { get; set; }
|
||||
public DateTime Cooldown { get; set; }
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#42f5ef", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = true, bool needsTeammates = false, string requiredPermission = "", float cooldown = 30f, float durationRun = 5, float durationCrouch = 12, int yourTeamDamage = 10, int enemyTeamDamage = 20) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float Cooldown { get; set; } = cooldown;
|
||||
public float DurationRun { get; set; } = durationRun;
|
||||
public float DurationCrouch { get; set; } = durationCrouch;
|
||||
public int YourTeamDamage { get; set; } = yourTeamDamage;
|
||||
public int EnemyTeamDamage { get; set; } = enemyTeamDamage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ namespace src.player.skills
|
|||
var weapon = hook.GetParam<CBasePlayerWeapon>(0);
|
||||
var action = hook.GetParam<short>(1);
|
||||
|
||||
if (action != actionCode || weapon?.DesignerName != "weapon_knife") return HookResult.Continue;
|
||||
if (action != actionCode || (weapon?.DesignerName != "weapon_knife" && weapon?.DesignerName != "weapon_bayonet")) return HookResult.Continue;
|
||||
if (weapon.OwnerEntity.Value == null || !weapon.OwnerEntity.Value.IsValid) return HookResult.Continue;
|
||||
|
||||
var pawn = weapon.OwnerEntity.Value.As<CCSPlayerPawn>();
|
||||
|
|
@ -87,7 +87,7 @@ namespace src.player.skills
|
|||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || pawn.WeaponServices == null) return;
|
||||
|
||||
var activeWeapon = pawn.WeaponServices.ActiveWeapon.Value;
|
||||
if (activeWeapon == null || !activeWeapon.IsValid || activeWeapon.DesignerName != "weapon_knife") return;
|
||||
if (activeWeapon == null || !activeWeapon.IsValid || (activeWeapon.DesignerName != "weapon_knife" && activeWeapon.DesignerName != "weapon_bayonet")) return;
|
||||
|
||||
KnifeHit(player, false);
|
||||
}
|
||||
|
|
|
|||
86
jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs
Normal file
86
jRandomSkills - SRC Files/src/player/skills/MagneticDecoy.cs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class MagneticDecoy : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.MagneticDecoy;
|
||||
private static readonly ConcurrentDictionary<Vector, byte> decoys = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
decoys.Clear();
|
||||
}
|
||||
|
||||
public static void DecoyStarted(EventDecoyStarted @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
decoys.TryAdd(new Vector(@event.X, @event.Y, @event.Z), 0);
|
||||
}
|
||||
|
||||
public static void DecoyDetonate(EventDecoyDetonate @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
foreach (var decoy in decoys.Keys.Where(v => v.X == @event.X && v.Y == @event.Y && v.Z == @event.Z))
|
||||
decoys.TryRemove(decoy, out _);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (Vector decoyPos in decoys.Keys)
|
||||
foreach (var player in Utilities.GetPlayers().Where(p => p.IsValid && p.PawnIsAlive && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist))
|
||||
{
|
||||
var decoyRadius = SkillsInfo.GetValue<float>(skillName, "triggerRadius");
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) continue;
|
||||
|
||||
double distance = SkillUtils.GetDistance(decoyPos, pawn.AbsOrigin);
|
||||
if (distance <= decoyRadius && distance > 10)
|
||||
{
|
||||
Vector direction = new(decoyPos.X - pawn.AbsOrigin.X, decoyPos.Y - pawn.AbsOrigin.Y, 0);
|
||||
float length = direction.Length();
|
||||
|
||||
Vector normalized = direction / length;
|
||||
float ratio = 1 - (float)(distance / decoyRadius);
|
||||
float strenght = SkillsInfo.GetValue<float>(skillName, "strenght") * ratio;
|
||||
|
||||
pawn.AbsVelocity.X += normalized.X * strenght;
|
||||
pawn.AbsVelocity.Y += normalized.Y * strenght;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillUtils.TryGiveWeapon(player, CsItem.DecoyGrenade);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#81f0c4", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float triggerRadius = 180, float strenght = 30) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float TriggerRadius { get; set; } = triggerRadius;
|
||||
public float Strenght { get; set; } = strenght;
|
||||
}
|
||||
}
|
||||
}
|
||||
87
jRandomSkills - SRC Files/src/player/skills/Magneto.cs
Normal file
87
jRandomSkills - SRC Files/src/player/skills/Magneto.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class Magneto : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Magneto;
|
||||
private readonly static ConcurrentDictionary<uint, byte> nades = [];
|
||||
private readonly static ConcurrentDictionary<uint, byte> players = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
nades.Clear();
|
||||
players.Clear();
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
if (Server.TickCount % 5 != 0) return;
|
||||
float radius = SkillsInfo.GetValue<float>(skillName, "radius");
|
||||
|
||||
foreach (var nadeIndex in nades.Keys)
|
||||
{
|
||||
var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)nadeIndex);
|
||||
if (nade == null || !nade.IsValid)
|
||||
{
|
||||
nades.TryRemove(nadeIndex, out _);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var playerIndex in players.Keys)
|
||||
{
|
||||
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid)
|
||||
{
|
||||
players.TryRemove(playerIndex, out _);
|
||||
continue;
|
||||
}
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
double distanceMoved = SkillUtils.GetDistance(nade.AbsOrigin ?? Vector.Zero, pawn.AbsOrigin ?? Vector.Zero);
|
||||
|
||||
if (distanceMoved < radius && nade.TeamNum != player.TeamNum)
|
||||
{
|
||||
nade.Teleport(null, null, -nade.AbsVelocity);
|
||||
nades.TryRemove(nadeIndex, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnEntitySpawned(CEntityInstance @event)
|
||||
{
|
||||
var name = @event.DesignerName;
|
||||
if (!name.EndsWith("_projectile")) return;
|
||||
|
||||
var grenade = @event.As<CBaseCSGrenadeProjectile>();
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
|
||||
nades.TryAdd(grenade.Index, 0);
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
players.TryAdd(player.Index, 0);
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
players.TryRemove(player.Index, out _);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#f081ec", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float radius = 100) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
public float Radius { get; set; } = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ namespace src.player.skills
|
|||
|
||||
if (buttons.HasFlag(PlayerButtons.Duck))
|
||||
percentInvisibility += SkillsInfo.GetValue<float>(skillName, "duckPercentInvisibility");
|
||||
if (activeWeapon != null && activeWeapon.DesignerName == "weapon_knife")
|
||||
if (activeWeapon != null && (activeWeapon.DesignerName == "weapon_knife" || activeWeapon.DesignerName == "weapon_bayonet"))
|
||||
percentInvisibility += SkillsInfo.GetValue<float>(skillName, "knifePercentInvisibility");
|
||||
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<float>(skillName, "idlePercentInvisibility");
|
||||
|
|
|
|||
|
|
@ -21,10 +21,19 @@ namespace src.player.skills
|
|||
|
||||
public static void NewRound()
|
||||
{
|
||||
ClearAllReplicas();
|
||||
lock (setLock)
|
||||
SkillPlayerInfo.Clear();
|
||||
}
|
||||
|
||||
private static void ClearAllReplicas()
|
||||
{
|
||||
var entities = Utilities.FindAllEntitiesByDesignerName<CDynamicProp>("prop_dynamic_override");
|
||||
foreach (var entity in entities)
|
||||
if (entity != null && entity.IsValid && entity.Entity != null && !string.IsNullOrEmpty(entity.Entity.Name) && (entity.Entity.Name?.StartsWith("Replica_") ?? false))
|
||||
entity.AcceptInput("Kill");
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ namespace src.player.skills
|
|||
var moneyServices = player.InGameMoneyServices;
|
||||
if (moneyServices == null) return;
|
||||
|
||||
player.PrintToChat(moneyServices.CashSpentThisRound.ToString());
|
||||
int money = Math.Abs((int)playerInfo.SkillChance! - moneyServices.CashSpentThisRound);
|
||||
AddMoney(player, -money, 3000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class Smoker : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Smoker;
|
||||
private readonly static ConcurrentDictionary<uint, int> smokes = [];
|
||||
private readonly static ConcurrentDictionary<ulong, List<Timer>> playerSmokes = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
|
|
@ -25,9 +24,11 @@ namespace src.player.skills
|
|||
public static void NewRound()
|
||||
{
|
||||
lock (setLock)
|
||||
smokes.Clear();
|
||||
|
||||
|
||||
{
|
||||
foreach (var timers in playerSmokes.Values)
|
||||
timers.ForEach(t => t?.Kill());
|
||||
playerSmokes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
|
|
@ -35,28 +36,13 @@ namespace src.player.skills
|
|||
SkillUtils.TryGiveWeapon(player, CsItem.SmokeGrenade);
|
||||
}
|
||||
|
||||
public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event)
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
Server.PrintToChatAll("BOOM");
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
var smoke = Utilities.GetEntityFromIndex<CSmokeGrenadeProjectile>(@event.Entityid);
|
||||
if (smoke == null || !smoke.IsValid) return;
|
||||
|
||||
smokes.TryAdd(smoke.Index, Server.TickCount);
|
||||
|
||||
// smoke.SmokeEffectTickBegin = Server.TickCount - ((19 - 15) * 64);
|
||||
smoke.NextThinkTick = 0;
|
||||
|
||||
// Utilities.SetStateChanged(smoke, "CSmokeGrenadeProjectile", "m_nSmokeEffectTickBegin");
|
||||
Utilities.SetStateChanged(smoke, "CBaseEntity", "m_nNextThinkTick");
|
||||
if (playerSmokes.TryRemove(player.SteamID, out var timers))
|
||||
timers.ForEach(t => t?.Kill());
|
||||
}
|
||||
|
||||
public static void SmokegrenadeExpired(EventSmokegrenadeExpired @event)
|
||||
public static void SmokegrenadeDetonate(EventSmokegrenadeDetonate @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
|
@ -65,7 +51,22 @@ namespace src.player.skills
|
|||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
Vector pos = new(@event.X, @event.Y, @event.Z);
|
||||
SkillUtils.CreateSmokeGrenadeProjectile(pos, new QAngle(0, 0, 0), new Vector(0, 0, 0), player.TeamNum);
|
||||
float refillInterval = 15.5f;
|
||||
|
||||
Timer? smokeTimer = null;
|
||||
smokeTimer = Instance.AddTimer(refillInterval, () =>
|
||||
{
|
||||
if (player == null || !player.IsValid)
|
||||
{
|
||||
smokeTimer?.Kill();
|
||||
return;
|
||||
}
|
||||
|
||||
Server.PrintToChatAll("Create Smoke");
|
||||
SkillUtils.CreateSmokeGrenadeProjectile(pos, QAngle.Zero, Vector.Zero, player.TeamNum);
|
||||
}, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE);
|
||||
|
||||
playerSmokes.AddOrUpdate(player.SteamID, [smokeTimer], (_, list) => { list.Add(smokeTimer); return list; });
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#b5ab8f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
|
|
|
|||
|
|
@ -75,16 +75,33 @@ namespace src.player.skills
|
|||
if (playerAWPIndexes.TryGetValue(player.SteamID, out var AWPs))
|
||||
foreach (var index in AWPs.ToList())
|
||||
{
|
||||
var ent = Utilities.GetEntityFromIndex<CBaseEntity>((int)index);
|
||||
if (ent != null && ent.IsValid)
|
||||
ent.AcceptInput("Kill");
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) continue;
|
||||
|
||||
var weapon = pawn.WeaponServices.MyWeapons.FirstOrDefault(w => w != null && w.IsValid && w.Value != null && w.Value.IsValid && AWPs.Contains(w.Value.Index));
|
||||
if (weapon == null) continue;
|
||||
|
||||
weapon.Value?.AddEntityIOEvent("Kill", weapon.Value, delay: 0.1f);
|
||||
}
|
||||
|
||||
if (savedWeapons.TryGetValue(player.SteamID, out string? savedWeapon) && !string.IsNullOrWhiteSpace(savedWeapon))
|
||||
Server.NextFrame(() =>
|
||||
player.PlayerPawn.Value?.ItemServices?.As<CCSPlayer_ItemServices>().GiveNamedItem<CEntityInstance>(savedWeapon));
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
|
||||
|
||||
Server.NextFrame(() => player.ExecuteClientCommand("lastinv"));
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
|
||||
var itemServices = pawn.ItemServices;
|
||||
if (itemServices != null && itemServices.Handle != IntPtr.Zero)
|
||||
player.GiveNamedItem(savedWeapon);
|
||||
});
|
||||
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (player != null && player.IsValid && player.PawnIsAlive)
|
||||
player.ExecuteClientCommand("lastinv");
|
||||
});
|
||||
|
||||
savedWeapons.TryRemove(player.SteamID, out _);
|
||||
playerAWPIndexes.TryRemove(player.SteamID, out _);
|
||||
|
|
@ -135,7 +152,7 @@ namespace src.player.skills
|
|||
weaponToGive = weapon_awp + "_script";
|
||||
}
|
||||
|
||||
activeRifle.AcceptInput("Kill");
|
||||
activeRifle.AddEntityIOEvent("Kill", activeRifle, delay: 0.1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -200,7 +217,7 @@ namespace src.player.skills
|
|||
{
|
||||
var ent = Utilities.GetEntityFromIndex<CBaseEntity>((int)index);
|
||||
if (ent != null && ent.IsValid)
|
||||
ent.AcceptInput("Kill");
|
||||
ent.AddEntityIOEvent("Kill", ent, delay: 0.1f);
|
||||
|
||||
AWPs.Remove(index);
|
||||
}
|
||||
|
|
|
|||
204
jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs
Normal file
204
jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class ThrowingKnife : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.ThrowingKnife;
|
||||
private readonly static ConcurrentDictionary<uint, uint> triggers = [];
|
||||
private readonly static ConcurrentDictionary<uint, uint> glows = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
DisableSkill(player);
|
||||
triggers.Clear();
|
||||
glows.Clear();
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
Event.EnableTransmit();
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
var playersTriggers = triggers.Where(t => t.Value == player.Index).Select(t => t.Key).ToList();
|
||||
foreach (var triggerIndex in playersTriggers)
|
||||
if (triggers.TryRemove(triggerIndex, out _))
|
||||
{
|
||||
var entity = Utilities.GetEntityFromIndex<CTriggerMultiple>((int)triggerIndex);
|
||||
if (entity != null && entity.IsValid)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (entity.IsValid)
|
||||
entity.AcceptInput("Kill");
|
||||
});
|
||||
}
|
||||
|
||||
if (glows.TryRemove(player.Index, out uint glowIndex))
|
||||
{
|
||||
var entity = Utilities.GetEntityFromIndex<CTriggerMultiple>((int)glowIndex);
|
||||
if (entity != null && entity.IsValid)
|
||||
Server.NextFrame(() =>
|
||||
{
|
||||
if (entity.IsValid)
|
||||
entity.AcceptInput("Kill");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void UseSkill(CCSPlayerController player)
|
||||
{
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
DropKnife(player);
|
||||
}
|
||||
|
||||
private static void DropKnife(CCSPlayerController player)
|
||||
{
|
||||
player.ExecuteClientCommand("slot3");
|
||||
Instance.AddTickTimer(8, () =>
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return;
|
||||
|
||||
var weapon = pawn.WeaponServices.ActiveWeapon.Value;
|
||||
if (weapon == null || !weapon.IsValid || (!weapon.DesignerName.Contains("knife") && !weapon.DesignerName.Contains("bayonet"))) return;
|
||||
|
||||
player.DropActiveWeapon();
|
||||
Server.NextFrame(() => ThrowKnife(player, weapon) );
|
||||
});
|
||||
}
|
||||
|
||||
private static void ThrowKnife(CCSPlayerController player, CBasePlayerWeapon knife)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
if (knife == null || !knife.IsValid || knife.AbsOrigin == null) return;
|
||||
|
||||
float force = 2000;
|
||||
|
||||
Vector pos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z);
|
||||
QAngle angle = new(0, 0, 0);
|
||||
Vector vel = SkillUtils.GetForwardVector(pawn.EyeAngles) * force;
|
||||
|
||||
knife.Collision.CollisionAttribute.InteractsWith = pawn.Collision.CollisionAttribute.InteractsWith;
|
||||
|
||||
knife.Teleport(pos, angle, vel);
|
||||
CreateTrigger(player, knife);
|
||||
CreateGlow(player, knife);
|
||||
}
|
||||
|
||||
private static void CreateTrigger(CCSPlayerController player, CBaseEntity knife)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (triggers.Any(t => t.Value == player.Index)) return;
|
||||
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return;
|
||||
|
||||
if (knife == null || !knife.IsValid || knife.AbsOrigin == null) return;
|
||||
|
||||
var trigger = SkillUtils.CreateTrigger($"trowingknife", 10, knife.AbsOrigin);
|
||||
if (trigger == null || !trigger.IsValid) return;
|
||||
|
||||
trigger.AcceptInput("SetParent", knife, knife, "!activator");
|
||||
triggers.TryAdd(trigger.Index, player.Index);
|
||||
}
|
||||
|
||||
private static void CreateGlow(CCSPlayerController player, CBaseEntity knife)
|
||||
{
|
||||
if (player == null || !player.IsValid) return;
|
||||
if (glows.ContainsKey(player.Index)) return;
|
||||
if (knife == null || !knife.IsValid || knife.AbsOrigin == null) return;
|
||||
|
||||
var modelGlow = Utilities.CreateEntityByName<CPhysicsPropMultiplayer>("prop_physics_multiplayer");
|
||||
if (modelGlow == null) return;
|
||||
|
||||
modelGlow.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(modelGlow.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2));
|
||||
|
||||
modelGlow.SetModel(knife.CBodyComponent!.SceneNode!.GetSkeletonInstance().ModelState.ModelName);
|
||||
modelGlow.DispatchSpawn();
|
||||
|
||||
modelGlow.Glow.GlowColorOverride = Color.GreenYellow;
|
||||
modelGlow.Glow.GlowRange = 5000;
|
||||
modelGlow.Glow.GlowTeam = -1;
|
||||
modelGlow.Glow.GlowType = 3;
|
||||
modelGlow.Glow.GlowRangeMin = 10;
|
||||
|
||||
modelGlow.Teleport(knife.AbsOrigin, knife.AbsRotation, knife.AbsVelocity);
|
||||
modelGlow.AcceptInput("SetParent", knife, modelGlow, "!activator");
|
||||
|
||||
glows.TryAdd(player.Index, modelGlow.Index);
|
||||
}
|
||||
|
||||
public static void OnTriggerEnter(CBaseTrigger trigger, CBaseEntity entity)
|
||||
{
|
||||
if (entity == null || !entity.IsValid || trigger == null || !trigger.IsValid) return;
|
||||
|
||||
string triggerName = trigger.Globalname;
|
||||
if (entity.DesignerName != "player" || string.IsNullOrEmpty(triggerName) || !triggerName.StartsWith("trowingknife")) return;
|
||||
|
||||
if (triggers.TryGetValue(trigger.Index, out var throwerIndex))
|
||||
{
|
||||
var thrower = Utilities.GetPlayerFromIndex((int)throwerIndex);
|
||||
if (thrower == null || !thrower.IsValid) return;
|
||||
|
||||
CCSPlayerPawn victimPawn = entity.As<CCSPlayerPawn>();
|
||||
if (victimPawn == null || !victimPawn.IsValid || victimPawn.LifeState != (byte)LifeState_t.LIFE_ALIVE) return;
|
||||
|
||||
if (thrower != null && thrower.Pawn.Value != null && victimPawn.Index == thrower.Pawn.Index) return;
|
||||
if (CheckHasKnife(thrower!)) return;
|
||||
|
||||
SkillUtils.TakeHealth(victimPawn, 99999);
|
||||
Server.PrintToChatAll($"HIT");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CheckHasKnife(CCSPlayerController player)
|
||||
{
|
||||
var pawn = player.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null) return false;
|
||||
return pawn.WeaponServices.MyWeapons.Any(w => w.IsValid && w != null && w.Value != null && w.Value.IsValid && (w.Value.DesignerName.Contains("knife") || w.Value.DesignerName.Contains("bayonet")));
|
||||
}
|
||||
|
||||
public static void CheckTransmit([CastFrom(typeof(nint))] CCheckTransmitInfoList infoList)
|
||||
{
|
||||
foreach (var (info, player) in infoList)
|
||||
{
|
||||
if (player == null || !player.IsValid) continue;
|
||||
var observedPlayer = Utilities.GetPlayers().FirstOrDefault(p => p?.Pawn?.Value?.Handle == player?.Pawn?.Value?.ObserverServices?.ObserverTarget?.Value?.Handle);
|
||||
|
||||
foreach (var glow in glows)
|
||||
{
|
||||
if (glow.Key == player.Index || (observedPlayer != null && observedPlayer.IsValid && glow.Key == observedPlayer.Index)) continue;
|
||||
|
||||
var glowEntity = Utilities.GetEntityFromIndex<CBaseEntity>((int)glow.Value);
|
||||
if (glowEntity == null || !glowEntity.IsValid) continue;
|
||||
info.TransmitEntities.Remove(glowEntity.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8f108f", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ namespace src.player.skills
|
|||
|
||||
CCSPlayerPawn playerPawn = new(entity.Handle);
|
||||
if (playerPawn == null || playerPawn.Controller?.Value == null)return;
|
||||
|
||||
CCSPlayerController player = playerPawn.Controller.Value.As<CCSPlayerController>();
|
||||
if (player == null) return;
|
||||
|
||||
|
|
|
|||
92
jRandomSkills - SRC Files/src/player/skills/Weightless.cs
Normal file
92
jRandomSkills - SRC Files/src/player/skills/Weightless.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class Weightless : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Weightless;
|
||||
private readonly static ConcurrentDictionary<uint, byte> nades = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
nades.Clear();
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
if (Server.TickCount % 10 != 0) return;
|
||||
|
||||
foreach ((var index, _) in nades)
|
||||
{
|
||||
var nade = Utilities.GetEntityFromIndex<CBaseCSGrenadeProjectile>((int)index);
|
||||
if (nade == null || !nade.IsValid)
|
||||
{
|
||||
nades.TryRemove(index, out _);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nade.Bounces != 0)
|
||||
{
|
||||
nade.ActualGravityScale = 2;
|
||||
|
||||
nade.DetonateTime = 0;
|
||||
Utilities.SetStateChanged(nade, "CBaseGrenade", "m_flDetonateTime");
|
||||
|
||||
nades.TryRemove(index, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnEntitySpawned(CEntityInstance @event)
|
||||
{
|
||||
var name = @event.DesignerName;
|
||||
if (!name.EndsWith("_projectile")) return;
|
||||
|
||||
var grenade = @event.As<CBaseCSGrenadeProjectile>();
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
|
||||
if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return;
|
||||
var pawn = grenade.OwnerEntity.Value.As<CCSPlayerPawn>();
|
||||
|
||||
if (pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return;
|
||||
var player = pawn.Controller.Value.As<CCSPlayerController>();
|
||||
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
Server.NextFrame(() => {
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
grenade.ActualGravityScale = .0001f;
|
||||
|
||||
Vector currentVelocity = new(grenade.AbsVelocity.X, grenade.AbsVelocity.Y, grenade.AbsVelocity.Z);
|
||||
float speed = currentVelocity.Length() * 2;
|
||||
|
||||
Vector forward = SkillUtils.GetForwardVector(pawn.EyeAngles);
|
||||
Vector newVelocity = forward * speed;
|
||||
|
||||
grenade.Teleport(null, null, newVelocity);
|
||||
nades.TryAdd(grenade.Index, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
SkillUtils.TryGiveWeapon(player, CsItem.HEGrenade);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8f6dc9", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
149
jRandomSkills - SRC Files/src/player/skills/WildThrow.cs
Normal file
149
jRandomSkills - SRC Files/src/player/skills/WildThrow.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using src.utils;
|
||||
using System.Collections.Concurrent;
|
||||
using static src.jRandomSkills;
|
||||
|
||||
namespace src.player.skills
|
||||
{
|
||||
public class WildThrow : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.WildThrow;
|
||||
private readonly static ConcurrentDictionary<ulong, byte> infectedPlayers = [];
|
||||
private static readonly object setLock = new();
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
lock (setLock)
|
||||
infectedPlayers.Clear();
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
DisableSkill(player);
|
||||
}
|
||||
|
||||
public static void PlayerDeath(EventPlayerDeath @event)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player == null) return;
|
||||
DisableSkill(player);
|
||||
}
|
||||
|
||||
public static void EnableSkill(CCSPlayerController player)
|
||||
{
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo == null) return;
|
||||
playerInfo.SkillUsed = false;
|
||||
|
||||
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
|
||||
if (enemies.Length > 0)
|
||||
{
|
||||
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString())));
|
||||
SkillUtils.CreateMenu(player, menuItems);
|
||||
}
|
||||
else
|
||||
player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("selectplayerskill_incorrect_enemy_index")}");
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController player)
|
||||
{
|
||||
infectedPlayers.TryRemove(player.SteamID, out _);
|
||||
SkillUtils.CloseMenu(player);
|
||||
}
|
||||
|
||||
public static void OnTick()
|
||||
{
|
||||
if (Server.TickCount % 32 != 0) return;
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
{
|
||||
if (!SkillUtils.HasMenu(player)) continue;
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
|
||||
if (playerInfo == null || playerInfo.Skill != skillName) continue;
|
||||
var enemies = Utilities.GetPlayers().Where(p => p.PawnIsAlive && p.Team != player.Team && p.IsValid && !p.IsBot && !p.IsHLTV && p.Team != CsTeam.Spectator && p.Team != CsTeam.None).ToArray();
|
||||
|
||||
ConcurrentBag<(string, string)> menuItems = new(enemies.Select(e => (e.PlayerName, e.Index.ToString())));
|
||||
SkillUtils.UpdateMenu(player, menuItems);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TypeSkill(CCSPlayerController player, string[] commands)
|
||||
{
|
||||
if (player == null || !player.IsValid || !player.PawnIsAlive) return;
|
||||
var playerInfo = Instance.SkillPlayer.FirstOrDefault(p => p.SteamID == player.SteamID);
|
||||
if (playerInfo?.Skill != skillName) return;
|
||||
|
||||
if (playerInfo.SkillUsed)
|
||||
{
|
||||
player.PrintToChat($" {ChatColors.Red}{player.GetTranslation("areareaper_used_info")}");
|
||||
return;
|
||||
}
|
||||
|
||||
string enemyId = commands[0];
|
||||
var enemy = Utilities.GetPlayers().FirstOrDefault(p => p.Team != player.Team && p.Index.ToString() == enemyId);
|
||||
|
||||
if (enemy == null)
|
||||
{
|
||||
player.PrintToChat($" {ChatColors.Red}" + player.GetTranslation("selectplayerskill_incorrect_enemy_index"));
|
||||
return;
|
||||
}
|
||||
|
||||
infectedPlayers.TryAdd(enemy.SteamID, 0);
|
||||
|
||||
playerInfo.SkillUsed = true;
|
||||
player.PrintToChat($" {ChatColors.Green}" + player.GetTranslation("wildthrow_player_info", enemy.PlayerName));
|
||||
}
|
||||
|
||||
public static void OnEntitySpawned(CEntityInstance @event)
|
||||
{
|
||||
var name = @event.DesignerName;
|
||||
if (!name.EndsWith("_projectile")) return;
|
||||
|
||||
var grenade = @event.As<CBaseCSGrenadeProjectile>();
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
|
||||
if (grenade.OwnerEntity.Value == null || !grenade.OwnerEntity.Value.IsValid) return;
|
||||
var pawn = grenade.OwnerEntity.Value.As<CCSPlayerPawn>();
|
||||
|
||||
if (pawn.Controller.Value == null || !pawn.Controller.Value.IsValid) return;
|
||||
var player = pawn.Controller.Value.As<CCSPlayerController>();
|
||||
|
||||
if (!infectedPlayers.ContainsKey(player.SteamID)) return;
|
||||
|
||||
Server.NextFrame(() => {
|
||||
if (grenade == null || !grenade.IsValid) return;
|
||||
|
||||
float forceMultiplier = (float)(Instance.Random.NextDouble() * .6 + .7);
|
||||
float min = 150;
|
||||
float max = 450;
|
||||
|
||||
float devX = GetRandom(min, max);
|
||||
float devY = GetRandom(min, max);
|
||||
float devZ = GetRandom(min, max);
|
||||
|
||||
Vector randomDev = new(devX, devY, devZ);
|
||||
Vector newVelocity = new(
|
||||
(grenade.Velocity.X + randomDev.X) * forceMultiplier,
|
||||
(grenade.Velocity.Y + randomDev.Y) * forceMultiplier,
|
||||
(grenade.Velocity.Z + randomDev.Z) * forceMultiplier
|
||||
);
|
||||
|
||||
grenade.Teleport(null, null, newVelocity);
|
||||
});
|
||||
}
|
||||
|
||||
private static float GetRandom(float min, float max)
|
||||
{
|
||||
float val = (float)(Instance.Random.NextDouble() * (max - min) + min);
|
||||
return Instance.Random.Next(0, 2) == 0 ? val : -val;
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#384728", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "") : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,10 +20,11 @@ namespace src.utils
|
|||
public static class SkillUtils
|
||||
{
|
||||
private static readonly MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int> HEGrenadeProjectile_CreateFunc = new(GameData.GetSignature("HEGrenadeProjectile_CreateFunc"));
|
||||
private static readonly MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int> SmokeGrenadeProjectile_CreateFunc = new(GameData.GetSignature("SmokeGrenadeProjectile_CreateFunc"));
|
||||
private static readonly MemoryFunctionWithReturn<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, int, int, CSmokeGrenadeProjectile> SmokeGrenadeProjectile_CreateFunc = new(GameData.GetSignature("SmokeGrenadeProjectile_CreateFunc"));
|
||||
private static readonly MemoryFunctionVoid<nint, float, RoundEndReason, nint, nint> TerminateRoundFunc = new(GameData.GetSignature("CCSGameRules_TerminateRound"));
|
||||
private static readonly MemoryFunctionVoid<CBasePlayerPawn, QAngle> SnapViewAngles = new(GameData.GetSignature("SnapViewAngles"));
|
||||
|
||||
public static void PrintToChat(CCSPlayerController player, string msg, string border = "tb", string? title = null)
|
||||
public static void PrintToChat(CCSPlayerController player, string? msg, string border = "tb", string? title = null)
|
||||
{
|
||||
if (!player.IsValid) return;
|
||||
|
||||
|
|
@ -93,6 +94,13 @@ namespace src.utils
|
|||
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
public static void Look(this CBasePlayerPawn pawn, QAngle angle)
|
||||
{
|
||||
if (pawn == null || !pawn.IsValid) return;
|
||||
SnapViewAngles.Invoke(pawn, angle);
|
||||
}
|
||||
|
||||
public static CBeam? CreateLine(Vector start, Vector end, Color color)
|
||||
{
|
||||
CBeam beam = Utilities.CreateEntityByName<CBeam>("beam")!;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue