using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Utils; using Cs2SuperPowers.Players; using Cs2SuperPowers.Powers; using Cs2SuperPowers.Powers.Assign; using Microsoft.Extensions.Logging; namespace Cs2SuperPowers; public class Cs2SuperPowersPlugin : BasePlugin { public override string ModuleName => "Cs2SuperPowersPlugin"; public override string ModuleVersion => "0.1.0"; public override string ModuleAuthor => "Latoch"; public override string ModuleDescription => "This CS2 server plugin unleashes the divine within! Experience a chaotic and exhilarating gameplay where players wield incredible superpowers."; private readonly ISuperPower[] _superPowers; private readonly IPowerAssignLogic _powerAssignLogic; private readonly IPlayerHud _playerHud; private readonly Random _random = new Random(); // Store listener delegate to prevent garbage collection! private readonly Listeners.CheckTransmit _checkTransmitHandler; public Cs2SuperPowersPlugin(IEnumerable superPowers, IPowerAssignLogic powerAssignLogic, IPlayerHud playerHud) : base() { _superPowers = superPowers.ToArray(); _powerAssignLogic = powerAssignLogic; _playerHud = playerHud; // Initialize CheckTransmit handler here to store a reference! _checkTransmitHandler = OnCheckTransmit; } public override void Load(bool hotReload) { Logger.LogInformation("Loading {ModuleName} with HotReload = {HotReload}", ModuleName, hotReload); base.Load(hotReload); // Register CheckTransmit listener using stored handler! RegisterListener(_checkTransmitHandler); foreach (var superPower in _superPowers) { Logger.LogInformation("Initializing SuperPower {Name} with Id = {Id}", superPower.Name, superPower.Id); superPower.Initialize(this); Logger.LogInformation("Finished Initializing SuperPower {Name}", superPower.Name); } _playerHud.Initialize(this); _powerAssignLogic.Initialize(this, _superPowers); Logger.LogInformation("Finished loading {ModuleName} with HotReload = {HotReload}", ModuleName, hotReload); } public void OnCheckTransmit(CCheckTransmitInfoList infoList) { foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList) { if (player == null || !player.IsValid) continue; Wallhack._onPlayerTransmitHandler(info, player); } } [ConsoleCommand("css_reroll", "Reroll your super power")] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_ONLY)] public void OnRerollCommand(CCSPlayerController? player, CommandInfo command) { if (player == null || !player.IsValid || !player.PawnIsAlive) { return; } var activePlayerCount = Utilities.GetPlayers().Count(currentPlayer => currentPlayer.IsValid && currentPlayer.Team != CsTeam.None && currentPlayer.Team != CsTeam.Spectator); var randomAssignablePowers = _superPowers .Where(power => power.CanBeRandomlyAssigned && power.MinimumPlayersRequired <= activePlayerCount) .ToArray(); if (randomAssignablePowers.Length == 0) { player.PrintToChat("No eligible powers are available right now."); return; } var randomPower = randomAssignablePowers[_random.Next(randomAssignablePowers.Length)]; PlayerPowers.Instance.AddPower(player, randomPower, showMessages: true); } [ConsoleCommand("css_forcepower", "Force a super power on a player: /forcepower ")] [CommandHelper(minArgs: 2, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnForcePowerCommand(CCSPlayerController? caller, CommandInfo command) { var playerNameArg = command.GetArg(1); var powerArg = command.GetArg(2); // Find target player CCSPlayerController? targetPlayer = null; foreach (var player in Utilities.GetPlayers()) { if (player.IsValid && player.PlayerName.Contains(playerNameArg, StringComparison.OrdinalIgnoreCase)) { targetPlayer = player; break; } } if (targetPlayer == null) { command.ReplyToCommand($"Could not find player containing '{playerNameArg}'"); return; } // Find power ISuperPower? targetPower = null; if (int.TryParse(powerArg, out var powerId)) { targetPower = _superPowers.FirstOrDefault(p => p.Id == powerId); } else { targetPower = _superPowers.FirstOrDefault(p => p.Name.Contains(powerArg, StringComparison.OrdinalIgnoreCase)); } if (targetPower == null) { command.ReplyToCommand($"Could not find power '{powerArg}'"); return; } // Assign power PlayerPowers.Instance.AddPower(targetPlayer, targetPower, showMessages: true); command.ReplyToCommand($"Gave {targetPlayer.PlayerName} the power '{targetPower.Name}'"); } [ConsoleCommand("css_nodelay", "Turn off cooldowns for Grenade Launcher, Not So Decoy, and Air Strike!")] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnNoDelayCommand(CCSPlayerController? caller, CommandInfo command) { GlobalConfig.NoDelayEnabled = true; if (caller != null && caller.IsValid) { caller.PrintToChat($"NoDelay mode turned ON! Cooldowns disabled for Grenade Launcher, Not So Decoy, Air Strike!"); } else { Server.PrintToChatAll($"NoDelay mode turned ON! Cooldowns disabled for Grenade Launcher, Not So Decoy, Air Strike!"); } } [ConsoleCommand("css_delay", "Turn on cooldowns for Grenade Launcher, Not So Decoy, and Air Strike!")] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnDelayCommand(CCSPlayerController? caller, CommandInfo command) { GlobalConfig.NoDelayEnabled = false; if (caller != null && caller.IsValid) { caller.PrintToChat($"NoDelay mode turned OFF! Cooldowns re-enabled!"); } else { Server.PrintToChatAll($"NoDelay mode turned OFF! Cooldowns re-enabled!"); } } [ConsoleCommand("css_boost", "Shows boost levels for all abilities.")] [CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBoostCommand(CCSPlayerController? caller, CommandInfo command) { string message = $"Boost Levels:\n GrenadeLauncher: {GlobalConfig.GrenadeLauncherBoostLevel} ({GlobalConfig.GetGrenadeLauncherCount(1)}x)\n NotSoDecoy: {GlobalConfig.NotSoDecoyBoostLevel} ({GlobalConfig.GetNotSoDecoyCount(20)} grenades)\n AirStrike: {GlobalConfig.AirStrikeBoostLevel} ({GlobalConfig.GetAirStrikeCount(20)} grenades)\n Dropped Nades: {GlobalConfig.DroppedNadesBoostLevel} ({GlobalConfig.GetDroppedNadesCount(5)} grenades)"; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } [ConsoleCommand("css_boost_grenade", "Sets boost level for GrenadeLauncher (0+).")] [CommandHelper(minArgs: 1, usage: "[level >= 0]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBoostGrenadeCommand(CCSPlayerController? caller, CommandInfo command) { if (int.TryParse(command.GetArg(1), out int level) && level >= 0) { GlobalConfig.GrenadeLauncherBoostLevel = level; string message = $"GrenadeLauncher Boost Level set to {level} ({GlobalConfig.GetGrenadeLauncherCount(1)}x)!"; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } else { string message = "Invalid level! Use 0 or higher."; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } } [ConsoleCommand("css_boost_decoy", "Sets boost level for NotSoDecoy (0+).")] [CommandHelper(minArgs: 1, usage: "[level >= 0]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBoostDecoyCommand(CCSPlayerController? caller, CommandInfo command) { if (int.TryParse(command.GetArg(1), out int level) && level >= 0) { GlobalConfig.NotSoDecoyBoostLevel = level; string message = $"NotSoDecoy Boost Level set to {level} ({GlobalConfig.GetNotSoDecoyCount(20)} grenades)!"; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } else { string message = "Invalid level! Use 0 or higher."; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } } [ConsoleCommand("css_boost_airstrike", "Sets boost level for AirStrike (0+).")] [CommandHelper(minArgs: 1, usage: "[level >= 0]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBoostAirstrikeCommand(CCSPlayerController? caller, CommandInfo command) { if (int.TryParse(command.GetArg(1), out int level) && level >= 0) { GlobalConfig.AirStrikeBoostLevel = level; string message = $"AirStrike Boost Level set to {level} ({GlobalConfig.GetAirStrikeCount(20)} grenades)!"; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } else { string message = "Invalid level! Use 0 or higher."; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } } [ConsoleCommand("css_boost_dropped_nades", "Sets boost level for Dropped Nades (0+).")] [CommandHelper(minArgs: 1, usage: "[level >= 0]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBoostDroppedNadesCommand(CCSPlayerController? caller, CommandInfo command) { if (int.TryParse(command.GetArg(1), out int level) && level >= 0) { GlobalConfig.DroppedNadesBoostLevel = level; string message = $"Dropped Nades Boost Level set to {level} ({GlobalConfig.GetDroppedNadesCount(5)} grenades)!"; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } else { string message = "Invalid level! Use 0 or higher."; if (caller != null && caller.IsValid) { caller.PrintToChat(message); } else { Server.PrintToChatAll(message); } } } }