using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Utils; using Cs2SuperPowers.Players; using Cs2SuperPowers.Players.PlayerValidations; using Microsoft.Extensions.Logging; namespace Cs2SuperPowers.Powers; public class BlindingLight(IPlayerHud playerHud) : BasePower(playerHud) { public override int Id => 22; public override string Name => "Blinding Light"; public override string Description => $"Inflict a blinding flash of light that disorients enemies. Press E (Use) to activate the power."; public override char ChatColor => ChatColors.BlueGrey; public override string HtmlColor => "#cdcece"; private readonly List _registrations = new(); private const int SecondsBetweenActivations = 8; public override void AssignToPlayer(CCSPlayerController player, bool showMessages) { base.AssignToPlayer(player, showMessages); if (!_registrations.Any(r => r.Player == player)) { _registrations.Add(new BlindingLightInfo(player, DateTime.MinValue)); } Plugin!.Logger.LogInformation("BlindingLight assigned to {PlayerName} ({SteamID})", player.PlayerName, player.SteamID); } public override void UnassignFromPlayer(CCSPlayerController player) { base.UnassignFromPlayer(player); var registration = _registrations.FirstOrDefault(r => r.Player == player); if (registration != null) { _registrations.Remove(registration); } Plugin!.Logger.LogInformation("BlindingLight unassigned from {PlayerName} ({SteamID})", player.PlayerName, player.SteamID); } protected override void OnInitialize() { RegisterListener(OnTick); RegisterEventHandler(OnRoundStart); RegisterEventHandler(OnPlayerDeath); Plugin!.Logger.LogInformation("BlindingLight initialized!"); } private HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info) { var player = @event.Userid; var registration = _registrations .FirstOrDefault(r => r.Player == player); if (registration != null) { registration.WasUsePressedLastTick = false; } return HookResult.Continue; } private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { _registrations.Clear(); foreach (var player in PlayerPowers.Instance.GetPlayersWithPower(this)) { _registrations.Add(new BlindingLightInfo(player, DateTime.MinValue)); } Plugin!.Logger.LogInformation("BlindingLight: Round start, registered {Count} players", _registrations.Count); return HookResult.Continue; } private void OnTick() { foreach (var registration in _registrations.ToList()) { if (!Ensure.Player(registration.Player).IsValid().Check()) { _registrations.Remove(registration); continue; } var usePressed = registration.Player.Buttons.HasFlag(PlayerButtons.Use); var canUsePower = (DateTime.UtcNow - registration.LastUse).TotalSeconds > SecondsBetweenActivations; if (usePressed && !registration.WasUsePressedLastTick) { Plugin!.Logger.LogInformation("BlindingLight: {PlayerName} pressed use! CanUse: {CanUse}", registration.Player.PlayerName, canUsePower); if (canUsePower) { ActivatePower(registration); } else { var secondsBeforeNextUse = SecondsBetweenActivations - (int)(DateTime.UtcNow - registration.LastUse).TotalSeconds; registration.Player .PrintToCenterAlert($"You need to wait {ChatColors.DarkRed}{secondsBeforeNextUse} {ChatColors.Default}seconds before using the power."); } } registration.WasUsePressedLastTick = usePressed; } } private void ActivatePower(BlindingLightInfo registration) { // Check for at least 1 player in the opposing team var playerTeam = registration.Player.Team; var enemyCount = Utilities.GetPlayers().Count(p => p.IsValid && p.Team != CsTeam.None && p.Team != CsTeam.Spectator && p.Team != playerTeam); Plugin!.Logger.LogInformation("BlindingLight: Activating for {PlayerName}, enemy count: {EnemyCount}", registration.Player.PlayerName, enemyCount); if (enemyCount < 1) { return; } var flashProjectile = Utilities.CreateEntityByName("flashbang_projectile"); if (flashProjectile == null || !flashProjectile.IsValid) { Plugin!.Logger.LogError("BlindingLight: Failed to create flashbang projectile!"); return; } var player = registration.Player; var pos = player.PlayerPawn.Value!.AbsOrigin; pos!.Z += 10; flashProjectile.TicksAtZeroVelocity = 100; flashProjectile.TeamNum = player.TeamNum; flashProjectile.Teleport(pos, null, new Vector(0, 0, -10)); flashProjectile.DispatchSpawn(); flashProjectile.AcceptInput("InitializeSpawnFromWorld", player.PlayerPawn.Value, player.PlayerPawn.Value); flashProjectile.DetonateTime = 0; Plugin!.Logger.LogInformation("BlindingLight: Flashbang created and detonated!"); registration.UpdateUse(); } } public record BlindingLightInfo(CCSPlayerController Player, DateTime LastUse) { public DateTime LastUse { get; private set; } = LastUse; public bool WasUsePressedLastTick { get; set; } = false; public void UpdateUse() { LastUse = DateTime.UtcNow; } }