jRandomSkills/jRandomSkills - SRC Files/src/player/skills/ThrowingKnife.cs
Juzlus 97887118bf (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.
2026-03-17 05:53:41 +01:00

204 lines
No EOL
8.8 KiB
C#

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)
{
}
}
}