jRandomSkills/jRandomSkills - SRC Files/src/player/skills/Chicken.cs
ByDexter db7108517a v1.2.3.b4
- Curses are now tracked at all times and cleared when a player leaves, so a curse can no longer stick to whoever joins into that player slot afterwards
- Wallhack and Nightmare no longer shows up for the whole server during the round start skill reveal
- One skill throwing during round cleanup no longer cancels the rest of the cleanup or leaves entity kills suppressed for the rest of the map
- Fixed the TakeAmmo crash on map change while restoring weapon reserve ammo
- Friendly fire reduction now applies to BlastShot, DeathBomb, ExplodingBarrel, ExplosiveShot and ToxicSmoke
- FireRain molotovs now land around the decoy instead of on nearby rooftops, and the fire keeps its owner and team so friendly fire rules apply to it
- Teammates can no longer shoot the chickens spawned by HealingChicken
- Fortnite wall now spawns with its model and health set up front, so it takes the configured amount of damage instead of breaking on the first bullet
- JetKick, CarefulBullets and WildThrow now clean up after their target disconnects
2026-08-03 01:25:04 +03:00

197 lines
No EOL
8.6 KiB
C#

using System.Drawing;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using System.Collections.Concurrent;
using src.utils;
namespace src.player.skills
{
public class Chicken : ISkill
{
private const Skills skillName = Skills.Chicken;
private static readonly HashSet<string> disabledWeapons =
[
"weapon_ak47", "weapon_m4a4", "weapon_m4a1", "weapon_m4a1_silencer",
"weapon_famas", "weapon_galilar", "weapon_aug", "weapon_sg556",
"weapon_mp9", "weapon_mac10", "weapon_bizon", "weapon_mp7",
"weapon_ump45", "weapon_p90", "weapon_mp5sd", "weapon_ssg08",
"weapon_awp", "weapon_scar20", "weapon_g3sg1", "weapon_nova",
"weapon_xm1014", "weapon_mag7", "weapon_sawedoff", "weapon_m249",
"weapon_negev"
];
private const string chickenModelPath = "models/chicken/chicken.vmdl";
private static readonly ConcurrentDictionary<uint, uint> chickens = [];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
jRandomSkills.Instance.AddToManifest(chickenModelPath);
}
public static void NewRound()
{
foreach (var player in PlayerManager.GetTickPlayers())
SetWeaponAttack(player, false);
var chickenIndices = chickens.Values.ToArray();
foreach (var idx in chickenIndices)
SkillUtils.SafeKillEntity<CBaseModelEntity>(idx);
chickens.Clear();
}
public static void WeaponPickup(EventItemPickup @event)
{
var player = PlayerManager.GetPlayerEvent(@event.Userid);
if (player == null || !player.IsValid) return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo?.Skill != skillName) return;
SetWeaponAttack(player, true);
}
public static void EnableSkill(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn?.Value;
if (playerPawn != null && playerPawn.IsValid)
{
Event.EnableTransmit();
playerPawn.VelocityModifier = 1.1f;
playerPawn.Health = 50;
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_iHealth");
SkillUtils.ChangePlayerScale(player, .2f);
playerPawn.Render = Color.FromArgb(0, 255, 255, 255);
playerPawn.ShadowStrength = 0f;
Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender");
SetWeaponAttack(player, true);
CreateChicken(player);
}
}
public static void DisableSkill(CCSPlayerController player)
{
SkillUtils.ResetPrintHTML(player);
var playerPawn = player.PlayerPawn?.Value;
if (playerPawn != null)
{
playerPawn.VelocityModifier = 1f;
if (playerPawn.Health > 0)
{
playerPawn.Health = Math.Min(playerPawn.Health + 50, 100);
Utilities.SetStateChanged(playerPawn, "CBaseEntity", "m_iHealth");
}
SkillUtils.ChangePlayerScale(player, 1);
playerPawn.Render = Color.FromArgb(255, 255, 255, 255);
playerPawn.ShadowStrength = 1.0f;
Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender");
SetWeaponAttack(player, false);
}
if (chickens.TryRemove(player.Index, out var chickenIndex))
SkillUtils.SafeKillEntity<CBaseModelEntity>(chickenIndex);
}
private static void SetWeaponAttack(CCSPlayerController player, bool disableWeapon)
{
if (player == null || !player.IsValid) return;
var pawn = player?.PlayerPawn?.Value;
if (pawn == null || !pawn.IsValid || pawn.WeaponServices == null || pawn.WeaponServices.MyWeapons == null) return;
foreach (var weapon in pawn.WeaponServices.MyWeapons)
if (weapon != null && weapon.IsValid && weapon.Value != null && weapon.Value.IsValid)
if (disabledWeapons.Contains(weapon.Value.DesignerName))
{
weapon.Value.NextPrimaryAttackTick = disableWeapon ? int.MaxValue : Server.TickCount;
weapon.Value.NextSecondaryAttackTick = disableWeapon ? int.MaxValue : Server.TickCount;
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextPrimaryAttackTick");
Utilities.SetStateChanged(weapon.Value, "CBasePlayerWeapon", "m_nNextSecondaryAttackTick");
}
}
private static void CreateChicken(CCSPlayerController player)
{
var playerPawn = player.PlayerPawn.Value;
if (playerPawn == null || !playerPawn.IsValid) return;
var chickenModel = EntityManager.CreateTrackedDynamicProp(player.Index);
if (chickenModel == null)
return;
chickenModel.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags = (uint)(chickenModel.CBodyComponent!.SceneNode!.Owner!.Entity!.Flags & ~(1 << 2));
chickenModel.SetModel(chickenModelPath);
chickenModel.Render = Color.FromArgb(255, 255, 255, 255);
chickenModel.Teleport(playerPawn.AbsOrigin, playerPawn.AbsRotation, null);
chickenModel.DispatchSpawn();
chickenModel.AcceptInput("InitializeSpawnFromWorld", playerPawn, playerPawn, "");
Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent");
chickenModel.CBodyComponent.SceneNode.GetSkeletonInstance().Scale = 1;
Utilities.SetStateChanged(chickenModel, "CBaseEntity", "m_CBodyComponent");
Server.NextFrame(() =>
{
if (chickenModel == null || !chickenModel.IsValid) return;
chickenModel.AcceptInput("SetScale", chickenModel, chickenModel, "1");
});
chickenModel.AcceptInput("SetParent", playerPawn, playerPawn, "!activator");
chickens.TryAdd(player.Index, chickenModel.Index);
}
public static void OnTick()
{
var pairs = chickens.ToArray();
foreach (var valuePair in pairs)
{
var playerIndex = valuePair.Key;
var chickenIndex = valuePair.Value;
var player = Utilities.GetPlayerFromIndex((int)playerIndex);
if (player == null || !player.IsValid) continue;
var chicken = Utilities.GetEntityFromIndex<CBaseModelEntity>((int)chickenIndex);
if (chicken == null || !chicken.IsValid) continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null || chicken.AbsOrigin == null) continue;
pawn.VelocityModifier = 1.1f;
UpdateHUD(player);
}
}
private static void UpdateHUD(CCSPlayerController player)
{
if (player == null || !player.IsValid || player.PlayerPawn.Value == null || !player.PlayerPawn.Value.IsValid) return;
var pawn = player.PlayerPawn.Value;
if (pawn.WeaponServices == null || pawn.WeaponServices.ActiveWeapon == null || !pawn.WeaponServices.ActiveWeapon.IsValid || pawn.WeaponServices.ActiveWeapon.Value == null || !pawn.WeaponServices.ActiveWeapon.Value.IsValid) return;
var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
if (playerInfo == null) return;
var weapon = pawn.WeaponServices.ActiveWeapon.Value;
if (weapon == null || !disabledWeapons.Contains(weapon.DesignerName))
{
playerInfo.PrintHTML = null;
return;
}
playerInfo.PrintHTML = $"<font color='#FF0000'>{player.GetTranslation("disabled_weapon")}</font>";
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#FF8B42", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
{
}
}
}