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

193 lines
6.1 KiB
C#

using System.Drawing;
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using Cs2SuperPowers.Players;
using Cs2SuperPowers.Players.PlayerValidations;
namespace Cs2SuperPowers.Powers;
public class Ghost(IPlayerHud playerHud) : BasePower(playerHud)
{
public override int Id => 7;
public override string Name => "The Ghost";
public override string Description => $"You are invisible to other players - but will show up for few seconds after you will take/give damage.";
public override char ChatColor => ChatColors.White;
private readonly Random _random = new Random();
public override string HtmlColor => "#FFFFFF";
public override int MinimumPlayersRequired => 4;
private readonly Dictionary<ulong, int> _visibilityTokens = new();
protected override void OnInitialize()
{
RegisterEventHandler<EventRoundStart>(OnRoundStart);
RegisterEventHandler<EventPlayerHurt>(OnPlayerHurt);
RegisterEventHandler<EventRoundEnd>(OnRoundEnd);
}
private HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
{
foreach (var player in PlayerPowers.Instance.GetPlayersWithPower(this))
{
_visibilityTokens[player.SteamID] = _visibilityTokens.GetValueOrDefault(player.SteamID) + 1;
NextFrame(() =>
{
SetPlayerVisibility(player, true);
});
}
return HookResult.Continue;
}
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{
var validPlayersWithPower = PlayerPowers.Instance
.GetPlayersWithPower(this)
.Where(player => Ensure.Player(player).IsValid().Check());
foreach (var player in validPlayersWithPower)
{
NextFrame(() =>
{
SetPlayerVisibility(player, false);
});
}
return HookResult.Continue;
}
public override void UnassignFromPlayer(CCSPlayerController player)
{
base.UnassignFromPlayer(player);
NextFrame(() =>
{
SetPlayerVisibility(player, true);
});
}
private HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info)
{
var attacker = @event.Attacker;
var victim = @event.Userid;
if (!Ensure.Player(victim).IsValid().IsAlive().Check() ||
!Ensure.Player(attacker).IsValid().Check())
{
return HookResult.Continue;
}
// Check for at least 4 valid (non-spectator, non-none) players total
var validPlayerCount = Utilities.GetPlayers().Count(p =>
p.IsValid && p.Team != CsTeam.None && p.Team != CsTeam.Spectator);
if (validPlayerCount < 4)
{
return HookResult.Continue;
}
if (IsAssignedTo(victim!))
{
RevealGhostTemporarily(victim!);
}
else if (IsAssignedTo(attacker!))
{
RevealGhostTemporarily(attacker!);
}
return HookResult.Continue;
}
private void RevealGhostTemporarily(CCSPlayerController player)
{
if (!Ensure.Player(player).IsValid().IsAlive().Check())
{
return;
}
var token = _visibilityTokens.GetValueOrDefault(player.SteamID) + 1;
_visibilityTokens[player.SteamID] = token;
SetPlayerVisibility(player, true);
AddTimer(_random.Next(1, 5), () =>
{
if (!IsAssignedTo(player) || _visibilityTokens.GetValueOrDefault(player.SteamID) != token)
{
return;
}
SetPlayerVisibility(player, false);
});
}
private void SetPlayerVisibility(CCSPlayerController player, bool visible)
{
if (!IsAssignedTo(player) && !visible)
{
return;
}
var playerPawn = player.PlayerPawn.Value;
if (playerPawn != null)
{
var color = visible
? Color.FromArgb(255, 255, 255, 255)
: Color.FromArgb(0, 255, 255, 255);
var shadowStrength = visible ? 1.0f : 0.0f;
playerPawn.Render = color;
playerPawn.ShadowStrength = shadowStrength;
Utilities.SetStateChanged(playerPawn, "CBaseModelEntity", "m_clrRender");
var activeWeapon = playerPawn.WeaponServices?.ActiveWeapon.Value;
if (activeWeapon != null && activeWeapon.IsValid)
{
activeWeapon.Render = color;
activeWeapon.ShadowStrength = shadowStrength;
Utilities.SetStateChanged(activeWeapon, "CBaseModelEntity", "m_clrRender");
}
var skeleton = playerPawn.CBodyComponent?.SceneNode?.GetSkeletonInstance();
if (skeleton != null)
{
skeleton.MaterialGroup.Value = visible ? (uint)0 : 1;
}
var myWeapons = playerPawn.WeaponServices?.MyWeapons;
if (myWeapons != null)
{
foreach (var gun in myWeapons)
{
var weapon = gun.Value;
if (weapon != null)
{
weapon.Render = color;
weapon.ShadowStrength = shadowStrength;
Utilities.SetStateChanged(weapon, "CBaseModelEntity", "m_clrRender");
}
}
}
var myWearables = playerPawn.MyWearables;
if (myWearables != null)
{
foreach (var wearableHandle in myWearables)
{
var wearable = wearableHandle.Value;
if (wearable == null || !wearable.IsValid)
{
continue;
}
wearable.Render = color;
wearable.ShadowStrength = shadowStrength;
Utilities.SetStateChanged(wearable, "CBaseModelEntity", "m_clrRender");
}
}
}
}
}