Files
2026-07-26 23:47:38 +02:00

111 lines
3.8 KiB
C#

using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using Cs2SuperPowers.Players;
using Cs2SuperPowers.Players.PlayerValidations;
using Cs2SuperPowers.Utils;
namespace Cs2SuperPowers.Powers;
public class NotSoDecoy(IPlayerHud playerHud) : BasePower(playerHud)
{
public override int Id => 24;
public override string Name => "Not So Decoy";
public override string Description => "Decoys thrown by you spawn 20 grenades when thrown (5 second cooldown).";
public override char ChatColor => ChatColors.Red;
public override string HtmlColor => "#FF0000";
private readonly Dictionary<CCSPlayerController, DateTime> _lastUse = new();
protected override void OnInitialize()
{
RegisterEventHandler<EventRoundStart>(OnRoundStart);
RegisterEventHandler<EventDecoyStarted>(OnDecoyStarted);
}
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo _)
{
_lastUse.Clear();
foreach (var player in Utilities.GetPlayers())
{
if (!Ensure.Player(player).IsValid().IsAlive().Check() || !IsAssignedTo(player!))
{
continue;
}
Server.NextFrame(() =>
{
player.GiveNamedItem("weapon_decoy");
});
}
return HookResult.Continue;
}
private HookResult OnDecoyStarted(EventDecoyStarted @event, GameEventInfo _)
{
var player = @event.Userid;
if (!Ensure.Player(player).IsValid().Check() || !IsAssignedTo(player!))
{
return HookResult.Continue;
}
// Check cooldown (skip if nodelay is enabled)
var now = DateTime.UtcNow;
DateTime lastUseTime = default;
bool isOnCooldown = !GlobalConfig.NoDelayEnabled && _lastUse.TryGetValue(player!, out lastUseTime) && (now - lastUseTime).TotalSeconds < 5;
// Always give a new decoy, regardless of cooldown!
player!.GiveNamedItem("weapon_decoy");
if (isOnCooldown)
{
double secondsRemaining = Math.Ceiling(5 - (now - lastUseTime).TotalSeconds);
player.PrintToCenterAlert($"Not So Decoy is on cooldown! {ChatColors.DarkRed}{secondsRemaining}{ChatColors.Default}s remaining");
return HookResult.Continue;
}
_lastUse[player!] = now;
var pos = new Vector(@event.X, @event.Y, @event.Z);
// Spawn grenades (with boost level) in a loop with random angles and velocities
var random = new Random();
int grenadeCount = GlobalConfig.GetNotSoDecoyCount(20);
for (int i = 0; i < grenadeCount; i++)
{
// Random pitch between -45 and 45 degrees, yaw between 0 and 360
float pitch = (float)(random.NextDouble() * 90.0 - 45.0);
float yaw = (float)(random.NextDouble() * 360.0);
var ang = new QAngle(pitch, yaw, 0);
// Random speed between 400 and 900 units
float speed = (float)(random.NextDouble() * 500.0 + 400.0);
// Convert angles to a forward vector
float pitchRad = pitch * MathF.PI / 180f;
float yawRad = yaw * MathF.PI / 180f;
var forward = new Vector(
MathF.Cos(yawRad) * MathF.Cos(pitchRad),
MathF.Sin(yawRad) * MathF.Cos(pitchRad),
-MathF.Sin(pitchRad));
// Add some random upward velocity for the "jump"
float upward = (float)(random.NextDouble() * 200.0 + 200.0);
var velocity = new Vector(
forward.X * speed,
forward.Y * speed,
forward.Z * speed + upward);
var createdGrenade = GrenadeSpawner.CreateGrenade(pos, ang, velocity, player.PlayerPawn.Value);
}
return HookResult.Continue;
}
}