mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-02-17 18:39:07 +00:00
Reworked the database layer to support both MySQL and SQLite via new provider classes and migration scripts for each backend. Updated the build workflow to support building and packaging additional modules, including StealthModule and BanSoundModule, and improved artifact handling. Refactored command registration to allow dynamic registration/unregistration and improved API event handling. Updated dependencies, project structure, and configuration checks for better reliability and extensibility. Added new language files, updated versioning, and removed obsolete files.
**⚠️ Warning: SQLite support is currently experimental.
Using this version requires reconfiguration of your database settings!
Plugin now uses UTC time. Please adjust your configurations accordingly!
**
1140 lines
50 KiB
C#
1140 lines
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;
|
|
|
|
namespace CS2_SimpleAdmin;
|
|
|
|
public partial class CS2_SimpleAdmin
|
|
{
|
|
internal static readonly Dictionary<CCSPlayerController, float> SpeedPlayers = [];
|
|
internal static readonly Dictionary<CCSPlayerController, 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);
|
|
else
|
|
SpeedPlayers[player] = 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);
|
|
else
|
|
GravityPlayers[player] = 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 (_cBasePlayerControllerSetPawnFunc == null || player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) return;
|
|
|
|
// Perform the respawn operation
|
|
var playerPawn = player.PlayerPawn.Value;
|
|
_cBasePlayerControllerSetPawnFunc.Invoke(player, playerPawn, true, false);
|
|
VirtualFunction.CreateVoid<CCSPlayerController>(player.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(player);
|
|
|
|
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);
|
|
// }
|
|
// }
|
|
// }
|
|
} |