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

128 lines
4.1 KiB
C#

using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using Cs2SuperPowers.Players;
using Cs2SuperPowers.Players.PlayerValidations;
namespace Cs2SuperPowers.Powers;
public class DoubleJump(IPlayerHud playerHud) : BasePower(playerHud)
{
public override int Id => 28;
public override string Name => "Double Jump";
public override string Description => "Jump again in mid-air! A classic double jump ability.";
public override char ChatColor => ChatColors.Blue;
public override string HtmlColor => "#0000FF";
private readonly Dictionary<CCSPlayerController, bool> _canDoubleJump = new();
private readonly Dictionary<CCSPlayerController, bool> _wasOnGround = new();
private readonly Dictionary<CCSPlayerController, bool> _requireJumpRelease = new();
protected override void OnInitialize()
{
RegisterListener<Listeners.OnTick>(OnTick);
RegisterEventHandler<EventRoundStart>(OnRoundStart);
RegisterEventHandler<EventPlayerHurt>(OnPlayerHurt);
}
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo _)
{
_canDoubleJump.Clear();
_wasOnGround.Clear();
_requireJumpRelease.Clear();
return HookResult.Continue;
}
public override void AssignToPlayer(CCSPlayerController player, bool showMessages)
{
base.AssignToPlayer(player, showMessages);
_canDoubleJump[player] = true;
_wasOnGround[player] = true;
_requireJumpRelease[player] = false;
}
public override void UnassignFromPlayer(CCSPlayerController player)
{
base.UnassignFromPlayer(player);
_canDoubleJump.Remove(player);
_wasOnGround.Remove(player);
_requireJumpRelease.Remove(player);
}
private void OnTick()
{
foreach (var player in Utilities.GetPlayers())
{
if (!player.IsValid || !player.PawnIsAlive)
continue;
if (!IsAssignedTo(player))
continue;
var pawn = player.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid)
continue;
var isOnGround = pawn.GroundEntity.IsValid;
var jumpPressed = player.Buttons.HasFlag(PlayerButtons.Jump);
var wasOnGroundLastTick = _wasOnGround.GetValueOrDefault(player, true);
if (isOnGround)
{
_canDoubleJump[player] = true;
_requireJumpRelease[player] = false;
}
else if (wasOnGroundLastTick)
{
_canDoubleJump[player] = true;
_requireJumpRelease[player] = jumpPressed;
}
if (!isOnGround && !jumpPressed)
{
_requireJumpRelease[player] = false;
}
if (!isOnGround &&
jumpPressed &&
!_requireJumpRelease.GetValueOrDefault(player, false) &&
_canDoubleJump.GetValueOrDefault(player, false))
{
var velocity = pawn.AbsVelocity;
velocity.Z = Math.Max(velocity.Z, 300.0f);
pawn.Teleport(pawn.AbsOrigin, null, velocity);
_canDoubleJump[player] = false;
_requireJumpRelease[player] = true;
}
_wasOnGround[player] = isOnGround;
}
}
private HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info)
{
var victim = @event.Userid;
if (!Ensure.Player(victim).IsValid().Check() || !IsAssignedTo(victim!))
{
return HookResult.Continue;
}
bool isWorldDamage = !Ensure.Player(@event.Attacker).IsValid().Check();
bool hasNoWeapon = string.IsNullOrEmpty(@event.Weapon);
if (!isWorldDamage || !hasNoWeapon)
{
return HookResult.Continue;
}
var pawn = victim!.PlayerPawn.Value;
if (pawn == null || !pawn.IsValid)
{
return HookResult.Continue;
}
pawn.Health = Math.Min(pawn.MaxHealth, pawn.Health + @event.DmgHealth);
return HookResult.Stop;
}
}