193 lines
6.1 KiB
C#
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");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|