cs2-SimpleAdmin/CS2-SimpleAdmin/Commands/playercommands.cs
2025-10-03 17:18:24 +05:30

1140 lines
No EOL
50 KiB
C#

using System.Globalization;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Admin;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Entities.Constants;
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils;
using FixVectorLeak;
namespace CS2_SimpleAdmin;
public partial class CS2_SimpleAdmin
{
internal static readonly Dictionary<int, float> SpeedPlayers = [];
internal static readonly Dictionary<int, float> GravityPlayers = [];
/// <summary>
/// Executes the 'slay' command, forcing the targeted players to commit suicide.
/// Checks player validity and permissions.
/// </summary>
/// <param name="caller">Player or console issuing the command.</param>
/// <param name="command">Command details, including targets.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnSlayCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
Slay(caller, player, callerName, command);
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Performs the actual slay action on a player, with notification and logging.
/// </summary>
/// <param name="caller">Admin or console issuing the slay.</param>
/// <param name="player">Target player to slay.</param>
/// <param name="callerName">Optional name to display as the slayer.</param>
/// <param name="command">Optional command info for logging.</param>
internal static void Slay(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
{
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected) return;
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Make the player commit suicide
player.CommitSuicide(false, true);
// Determine message keys and arguments for the slay notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_slay_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
// Log the command and send Discord notification
if (command == null)
Helper.LogCommand(caller, $"css_slay {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
}
/// <summary>
/// Executes the 'give' command to provide a specified weapon to targeted players.
/// Enforces server rules for prohibited weapons.
/// </summary>
/// <param name="caller">Player or console issuing the command.</param>
/// <param name="command">Command details, including targets and weapon name.</param>
[RequiresPermissions("@css/cheats")]
[CommandHelper(minArgs: 2, usage: "<#userid or name> <weapon>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnGiveCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
var weaponName = command.GetArg(2);
// check if weapon is knife
if (weaponName.Contains("_knife") || weaponName.Contains("bayonet"))
{
if (CoreConfig.FollowCS2ServerGuidelines)
{
command.ReplyToCommand($"Cannot Give {weaponName} because it's illegal to be given.");
return;
}
}
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
GiveWeapon(caller, player, weaponName, callerName, command);
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Gives a weapon identified by name to a player, handling ambiguous matches and logging.
/// </summary>
/// <param name="caller">Admin issuing the command.</param>
/// <param name="player">Target player to receive the weapon.</param>
/// <param name="weaponName">Weapon name or partial name.</param>
/// <param name="callerName">Optional name to display in notifications.</param>
/// <param name="command">Optional command info for logging.</param>
private static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
var weapons = WeaponHelper.GetWeaponsByPartialName(weaponName);
switch (weapons.Count)
{
case 0:
return;
case > 1:
{
var weaponList = string.Join(", ", weapons.Select(w => w.EnumMemberValue));
command?.ReplyToCommand($"Found weapons with a similar name: {weaponList}");
return;
}
}
// Give weapon to the player
player.GiveNamedItem(weapons.First().EnumValue);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weaponName}");
// Determine message keys and arguments for the weapon give notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_give_message",
new object[] { "CALLER", player.PlayerName, weaponName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Gives a specific weapon to a player, with notifications and logging.
/// </summary>
/// <param name="caller">Admin issuing the command.</param>
/// <param name="player">Target player.</param>
/// <param name="weapon">Weapon item object.</param>
/// <param name="callerName">Optional caller name for notifications.</param>
/// <param name="command">Optional command info.</param>
internal static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, CsItem weapon, string? callerName = null, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Give weapon to the player
player.GiveNamedItem(weapon);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weapon.ToString()}");
// Determine message keys and arguments for the weapon give notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_give_message",
new object[] { "CALLER", player.PlayerName, weapon.ToString() });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Executes the 'strip' command, removing all weapons from targeted players.
/// Checks player validity and permissions.
/// </summary>
/// <param name="caller">Player or console issuing the command.</param>
/// <param name="command">Command details including targets.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnStripCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
if (caller!.CanTarget(player))
{
StripWeapons(caller, player, callerName, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Removes all weapons from a player, with notifications and logging.
/// </summary>
/// <param name="caller">Admin or console issuing the strip command.</param>
/// <param name="player">Target player.</param>
/// <param name="callerName">Optional caller name.</param>
/// <param name="command">Optional command info for logging.</param>
internal static void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Check if player is valid, alive, and connected
if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE || player.Connected != PlayerConnectedState.PlayerConnected)
return;
// Strip weapons from the player
player.RemoveWeapons();
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_strip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
// Determine message keys and arguments for the weapon strip notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_strip_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Sets health value on targeted players.
/// </summary>
/// <param name="caller">Admin or console issuing the command.</param>
/// <param name="command">Command details including targets and health value.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> <health>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnHpCommand(CCSPlayerController? caller, CommandInfo command)
{
int.TryParse(command.GetArg(2), out var health);
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
if (caller!.CanTarget(player))
{
SetHp(caller, player, health, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Changes health of a player and logs the action.
/// </summary>
/// <param name="caller">Admin or console calling the method.</param>
/// <param name="player">Target player.</param>
/// <param name="health">Health value to set.</param>
/// <param name="command">Optional command info.</param>
internal static void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, CommandInfo? command = null)
{
if (!player.IsValid || player.IsHLTV) return;
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Set player's health
player.SetHp(health);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_hp {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {health}");
// Determine message keys and arguments for the HP set notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_hp_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Sets movement speed on targeted players.
/// </summary>
/// <param name="caller">Admin or console issuing the command.</param>
/// <param name="command">Command details including targets and speed.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> <speed>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnSpeedCommand(CCSPlayerController? caller, CommandInfo command)
{
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var speed);
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
if (caller!.CanTarget(player))
{
SetSpeed(caller, player, speed, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Changes speed of a player and logs the action.
/// </summary>
/// <param name="caller">Admin or console calling the method.</param>
/// <param name="player">Target player.</param>
/// <param name="speed">Speed value to set.</param>
/// <param name="command">Optional command info.</param>
internal static void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, float speed, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Set player's speed
player.SetSpeed(speed);
if (speed == 1f)
SpeedPlayers.Remove(player.Slot);
else
SpeedPlayers[player.Slot] = speed;
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_speed {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {speed}");
// Determine message keys and arguments for the speed set notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_speed_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Sets gravity on targeted players.
/// </summary>
/// <param name="caller">Admin or console issuing the command.</param>
/// <param name="command">Command details including targets and gravity value.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command)
{
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var gravity);
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
if (caller!.CanTarget(player))
{
SetGravity(caller, player, gravity, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Changes gravity of a player and logs the action.
/// </summary>
/// <param name="caller">Admin or console calling the method.</param>
/// <param name="player">Target player.</param>
/// <param name="gravity">Gravity value to set.</param>
/// <param name="command">Optional command info.</param>
internal static void SetGravity(CCSPlayerController? caller, CCSPlayerController player, float gravity, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Set player's gravity
player.SetGravity(gravity);
if (gravity == 1f)
GravityPlayers.Remove(player.Slot);
else
GravityPlayers[player.Slot] = gravity;
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_gravity {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {gravity}");
// Determine message keys and arguments for the gravity set notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_gravity_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Sets the money amount for the targeted players.
/// </summary>
/// <param name="caller">The player/admin executing the command.</param>
/// <param name="command">The command containing target player and money value.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> <money>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnMoneyCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
int.TryParse(command.GetArg(2), out var money);
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
if (caller!.CanTarget(player))
{
SetMoney(caller, player, money, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Applies money value to a single targeted player and logs the operation.
/// </summary>
/// <param name="caller">The player/admin setting the money.</param>
/// <param name="player">The player whose money will be set.</param>
/// <param name="money">The value of money to set.</param>
/// <param name="command">Optional command info for logging.</param>
internal static void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Set player's money
player.SetMoney(money);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_money {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {money}");
// Determine message keys and arguments for the money set notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_money_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller == null || !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Applies damage as a slap effect to the targeted players.
/// </summary>
/// <param name="caller">The player/admin executing the slap command.</param>
/// <param name="command">The command including targets and optional damage value.</param>
[RequiresPermissions("@css/slay")]
[CommandHelper(minArgs: 1, usage: "<#userid or name> [damage]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnSlapCommand(CCSPlayerController? caller, CommandInfo command)
{
var damage = 0;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
if (command.ArgCount >= 2)
{
int.TryParse(command.GetArg(2), out damage);
}
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
if (caller!.CanTarget(player))
{
Slap(caller, player, damage, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Applies slap damage to a specific player with notifications and logging.
/// </summary>
/// <param name="caller">The player/admin applying the slap effect.</param>
/// <param name="player">The target player to slap.</param>
/// <param name="damage">The damage amount to apply.</param>
/// <param name="command">Optional command info for logging.</param>
internal static void Slap(CCSPlayerController? caller, CCSPlayerController player, int damage, CommandInfo? command = null)
{
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Apply slap damage to the player
player.Pawn.Value?.Slap(damage);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_slap {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {damage}");
// Determine message key and arguments for the slap notification
var (activityMessageKey, adminActivityArgs) =
("sa_admin_slap_message",
new object[] { "CALLER", player.PlayerName });
// Display admin activity message to other players
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
if (_localizer != null)
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
}
/// <summary>
/// Changes the team of targeted players with optional kill on switch.
/// </summary>
/// <param name="caller">The player/admin issuing the command.</param>
/// <param name="command">The command containing targets, team info, and optional kill flag.</param>
[RequiresPermissions("@css/kick")]
[CommandHelper(minArgs: 2, usage: "<#userid or name> [<ct/tt/spec>] [-k]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
public void OnTeamCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var teamName = command.GetArg(2).ToLower();
string _teamName;
var teamNum = CsTeam.Spectator;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
switch (teamName)
{
case "ct":
case "counterterrorist":
teamNum = CsTeam.CounterTerrorist;
_teamName = "CT";
break;
case "t":
case "tt":
case "terrorist":
teamNum = CsTeam.Terrorist;
_teamName = "TT";
break;
case "swap":
_teamName = "SWAP";
break;
default:
teamNum = CsTeam.Spectator;
_teamName = "SPEC";
break;
}
var kill = command.GetArg(3).ToLower().Equals("-k");
playersToTarget.ForEach(player =>
{
ChangeTeam(caller, player, _teamName, teamNum, kill, command);
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Changes the team of a player with various conditions and logs the operation.
/// </summary>
/// <param name="caller">The player/admin issuing the change.</param>
/// <param name="player">The target player.</param>
/// <param name="teamName">Team name string.</param>
/// <param name="teamNum">Team enumeration value.</param>
/// <param name="kill">If true, kills player on team change.</param>
/// <param name="command">Optional command info for logging.</param>
internal static void ChangeTeam(CCSPlayerController? caller, CCSPlayerController player, string teamName, CsTeam teamNum, bool kill, CommandInfo? command = null)
{
// Check if the player is valid and connected
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected)
return;
// Ensure the caller can target the player
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
// Change team based on the provided teamName and conditions
if (!teamName.Equals("swap", StringComparison.OrdinalIgnoreCase))
{
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE && teamNum != CsTeam.Spectator && !kill && Instance.Config.OtherSettings.TeamSwitchType == 1)
player.SwitchTeam(teamNum);
else
player.ChangeTeam(teamNum);
}
else
{
if (player.TeamNum != (byte)CsTeam.Spectator)
{
var _teamNum = (CsTeam)player.TeamNum == CsTeam.Terrorist ? CsTeam.CounterTerrorist : CsTeam.Terrorist;
teamName = _teamNum == CsTeam.Terrorist ? "TT" : "CT";
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE && !kill && Instance.Config.OtherSettings.TeamSwitchType == 1)
player.SwitchTeam(_teamNum);
else
player.ChangeTeam(_teamNum);
}
}
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_team {player.PlayerName} {teamName}");
// Determine message key and arguments for the team change notification
var activityMessageKey = "sa_admin_team_message";
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, teamName };
// Display admin activity message to other players
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
/// <summary>
/// Renames targeted players to a new name.
/// </summary>
/// <param name="caller">The admin issuing the rename command.</param>
/// <param name="command">The command including targets and new name.</param>
[CommandHelper(1, "<#userid or name> <new name>")]
[RequiresPermissions("@css/kick")]
public void OnRenameCommand(CCSPlayerController? caller, CommandInfo command)
{
// Set default caller name if not provided
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
// Get the new name from the command arguments
var newName = command.GetArg(2);
// Check if the new name is valid
if (string.IsNullOrEmpty(newName))
return;
// Retrieve the targets based on the command
var targets = GetTarget(command);
if (targets == null) return;
// Filter out valid players from the targets
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
// Log the command
Helper.LogCommand(caller, command);
// Process each player to rename
playersToTarget.ForEach(player =>
{
// Check if the player is connected and can be targeted
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
return;
// Determine message key and arguments for the rename notification
var activityMessageKey = "sa_admin_rename_message";
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
// Display admin activity message to other players
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
// Rename the player
player.Rename(newName);
});
}
/// <summary>
/// Renames permamently targeted players to a new name.
/// </summary>
/// <param name="caller">The admin issuing the pre-rename command.</param>
/// <param name="command">The command containing targets and new alias.</param>
[CommandHelper(1, "<#userid or name> <new name>")]
[RequiresPermissions("@css/ban")]
public void OnPrenameCommand(CCSPlayerController? caller, CommandInfo command)
{
// Set default caller name if not provided
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
// Get the new name from the command arguments
var newName = command.GetArg(2);
// Retrieve the targets based on the command
var targets = GetTarget(command);
if (targets == null) return;
// Filter out valid players from the targets
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
// Log the command
Helper.LogCommand(caller, command);
// Process each player to rename
playersToTarget.ForEach(player =>
{
// Check if the player is connected and can be targeted
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
return;
// Determine message key and arguments for the rename notification
var activityMessageKey = "sa_admin_rename_message";
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
// Display admin activity message to other players
if (caller != null && !SilentPlayers.Contains(caller.Slot))
{
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
// Determine if the new name is valid and update the renamed players list
if (!string.IsNullOrEmpty(newName))
{
RenamedPlayers[player.SteamID] = newName;
player.Rename(newName);
}
else
{
RenamedPlayers.Remove(player.SteamID);
}
});
}
/// <summary>
/// Respawns targeted players, restoring their state.
/// </summary>
/// <param name="caller">The admin or player issuing respawn.</param>
/// <param name="command">The command including target players.</param>
[CommandHelper(1, "<#userid or name>")]
[RequiresPermissions("@css/cheats")]
public void OnRespawnCommand(CCSPlayerController? caller, CommandInfo command)
{
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
var targets = GetTarget(command);
if (targets == null) return;
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
playersToTarget.ForEach(player =>
{
if (player.Connected != PlayerConnectedState.PlayerConnected)
return;
if (caller!.CanTarget(player))
{
Respawn(caller, player, callerName, command);
}
});
Helper.LogCommand(caller, command);
}
/// <summary>
/// Respawns a specified player and updates admin notifications.
/// </summary>
/// <param name="caller">Admin or player executing respawn.</param>
/// <param name="player">Player to respawn.</param>
/// <param name="callerName">Optional admin name.</param>
/// <param name="command">Optional command info.</param>
internal static void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
{
// Check if the caller can target the player
if (!caller.CanTarget(player)) return;
// Set default caller name if not provided
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
// Ensure the player's pawn is valid before attempting to respawn
if (player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) return;
// Perform the respawn operation
var playerPawn = player.PlayerPawn.Value;
player.Respawn();
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.SteamID, out var value) && value.DiePosition != null)
playerPawn.Teleport(value.DiePosition?.Position, value.DiePosition?.Angle);
// Log the command
if (command == null)
Helper.LogCommand(caller, $"css_respawn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
// Determine message key and arguments for the respawn notification
var activityMessageKey = "sa_admin_respawn_message";
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
// Display admin activity message to other players
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
}
/// <summary>
/// Teleports targeted player(s) to another player's location.
/// </summary>
/// <param name="caller">Admin issuing teleport command.</param>
/// <param name="command">Command containing teleport targets and destination.</param>
[CommandHelper(1, "<#userid or name> [#userid or name]")]
[RequiresPermissions("@css/kick")]
public void OnGotoCommand(CCSPlayerController? caller, CommandInfo command)
{
IEnumerable<CCSPlayerController> playersToTeleport;
CCSPlayerController? destinationPlayer;
var targets = GetTarget(command);
if (command.ArgCount < 3)
{
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
return;
if (targets == null || targets.Count() != 1)
return;
destinationPlayer = targets.Players.FirstOrDefault(p =>
p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
if (destinationPlayer == null || !caller.CanTarget(destinationPlayer) || caller.PlayerPawn.Value == null)
return;
playersToTeleport = [caller];
}
else
{
var destination = GetTarget(command, 2);
if (targets == null || destination == null || destination.Count() != 1)
return;
destinationPlayer = destination.Players.FirstOrDefault(p =>
p is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
if (destinationPlayer == null)
return;
playersToTeleport = targets.Players
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller.CanTarget(p))
.ToList();
if (!playersToTeleport.Any())
return;
}
// Log command
Helper.LogCommand(caller, command);
foreach (var player in playersToTeleport)
{
if (player.PlayerPawn?.Value == null || destinationPlayer?.PlayerPawn?.Value == null)
continue;
player.TeleportPlayer(destinationPlayer);
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
AddTimer(4, () =>
{
if (player is { IsValid: true, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
{
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
}
if (destinationPlayer.IsValid && destinationPlayer.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
{
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
}
});
if (caller != null && !SilentPlayers.Contains(caller.Slot) && _localizer != null)
{
Helper.ShowAdminActivity("sa_admin_tp_message", player.PlayerName, false, "CALLER", destinationPlayer.PlayerName);
}
}
}
/// <summary>
/// Brings targeted player(s) to the caller or specified destination player's location.
/// </summary>
/// <param name="caller">Player issuing the bring command.</param>
/// <param name="command">Command containing the destination and targets.</param>
[CommandHelper(1, "<#destination or name> [#userid or name...]")]
[RequiresPermissions("@css/kick")]
public void OnBringCommand(CCSPlayerController? caller, CommandInfo command)
{
IEnumerable<CCSPlayerController> playersToTeleport;
CCSPlayerController? destinationPlayer;
if (command.ArgCount < 3)
{
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
return;
var targets = GetTarget(command);
if (targets == null || !targets.Any())
return;
destinationPlayer = caller;
playersToTeleport = targets.Players
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller.CanTarget(p))
.ToList();
}
else
{
var destination = GetTarget(command);
if (destination == null || destination.Count() != 1)
return;
destinationPlayer = destination.Players.FirstOrDefault(p =>
p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE });
if (destinationPlayer == null)
return;
// Rest args = targets to teleport
var targets = GetTarget(command, 2);
if (targets == null || !targets.Any())
return;
playersToTeleport = targets.Players
.Where(p => p is { IsValid: true, IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE } && caller!.CanTarget(p))
.ToList();
}
if (destinationPlayer == null || !playersToTeleport.Any())
return;
// Log command
Helper.LogCommand(caller, command);
foreach (var player in playersToTeleport)
{
if (player.PlayerPawn?.Value == null || destinationPlayer.PlayerPawn?.Value == null)
continue;
// Teleport
player.TeleportPlayer(destinationPlayer);
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
AddTimer(4, () =>
{
if (player is { IsValid: true, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE })
{
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
}
if (destinationPlayer.IsValid && destinationPlayer.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
{
destinationPlayer.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
destinationPlayer.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
Utilities.SetStateChanged(destinationPlayer, "CCollisionProperty", "m_CollisionGroup");
Utilities.SetStateChanged(destinationPlayer, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
}
});
if (caller != null && !SilentPlayers.Contains(caller.Slot) && _localizer != null)
{
Helper.ShowAdminActivity("sa_admin_bring_message", player.PlayerName, false, "CALLER", destinationPlayer.PlayerName);
}
}
}
// [CommandHelper(1, "<#userid or name> [#userid or name]")]
// [RequiresPermissions("@css/kick")]
// public void OnBringCommand(CCSPlayerController? caller, CommandInfo command)
// {
// // Check if the caller is valid and has a live pawn
// if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
// return;
//
// // Get the target players
// var targets = GetTarget(command);
// if (targets == null || targets.Count() > 1) return;
//
// var playersToTarget = targets.Players
// .Where(player => player is { IsValid: true, IsHLTV: false })
// .ToList();
//
// // Log the command
// Helper.LogCommand(caller, command);
//
// // Process each player to teleport
// foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
// {
// if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
// continue;
//
// // Teleport the player to the caller and toggle noclip
// player.TeleportPlayer(caller);
// // caller.PlayerPawn.Value.ToggleNoclip();
//
// caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
// caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
//
// Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
// Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
//
// player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
// player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
//
// Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
// Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
//
// // Set a timer to toggle collision back after 4 seconds
// AddTimer(4, () =>
// {
// if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
// return;
//
// caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
// caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
//
// Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
// Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
//
// player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
// player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
//
// Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
// Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
// });
//
// // Prepare message key and arguments for the bring notification
// var activityMessageKey = "sa_admin_bring_message";
// var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
//
// // Show admin activity
// if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
// {
// Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
// }
// }
// }
}