feat: add BasePower abstraction
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Cs2SuperPowers.Players;
|
||||
|
||||
namespace Cs2SuperPowers.Powers;
|
||||
|
||||
public class Jetpack(IPlayerHud playerHud) : BasePower(playerHud)
|
||||
{
|
||||
private const float MaxFuel = 180.0f;
|
||||
private const float FuelBurnPerTick = 0.8f;
|
||||
private const float FuelRechargePerTick = 0.9f;
|
||||
private const float LiftPerTick = 14.0f;
|
||||
private const float MaxVerticalSpeed = 260.0f;
|
||||
private static readonly TimeSpan HudRefreshInterval = TimeSpan.FromMilliseconds(125);
|
||||
|
||||
public override int Id => 33;
|
||||
public override string Name => "Jetpack";
|
||||
public override string Description => "Hold Jump (Space) to fly with a fuel-based jetpack.";
|
||||
public override char ChatColor => ChatColors.Orange;
|
||||
public override string HtmlColor => "#FF8C00";
|
||||
|
||||
private readonly Dictionary<CCSPlayerController, float> _fuelByPlayer = new();
|
||||
private readonly Dictionary<CCSPlayerController, DateTime> _lastHudUpdate = new();
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
RegisterListener<Listeners.OnTick>(OnTick);
|
||||
RegisterEventHandler<EventRoundStart>(OnRoundStart);
|
||||
}
|
||||
|
||||
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
|
||||
{
|
||||
_fuelByPlayer.Clear();
|
||||
_lastHudUpdate.Clear();
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
public override void AssignToPlayer(CCSPlayerController player, bool showMessages)
|
||||
{
|
||||
base.AssignToPlayer(player, showMessages);
|
||||
_fuelByPlayer[player] = MaxFuel;
|
||||
_lastHudUpdate.Remove(player);
|
||||
}
|
||||
|
||||
public override void UnassignFromPlayer(CCSPlayerController player)
|
||||
{
|
||||
base.UnassignFromPlayer(player);
|
||||
_fuelByPlayer.Remove(player);
|
||||
_lastHudUpdate.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;
|
||||
|
||||
float fuel = _fuelByPlayer.GetValueOrDefault(player, MaxFuel);
|
||||
bool isJumpPressed = player.Buttons.HasFlag(PlayerButtons.Jump);
|
||||
|
||||
if (isJumpPressed && fuel > 0.0f)
|
||||
{
|
||||
var currentVelocity = pawn.AbsVelocity;
|
||||
currentVelocity.Z = Math.Min(currentVelocity.Z + LiftPerTick, MaxVerticalSpeed);
|
||||
pawn.Teleport(pawn.AbsOrigin, null, currentVelocity);
|
||||
fuel = Math.Max(0.0f, fuel - FuelBurnPerTick);
|
||||
}
|
||||
else
|
||||
{
|
||||
fuel = Math.Min(MaxFuel, fuel + FuelRechargePerTick);
|
||||
}
|
||||
|
||||
_fuelByPlayer[player] = fuel;
|
||||
|
||||
if (isJumpPressed)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (!_lastHudUpdate.TryGetValue(player, out var lastHudUpdate) ||
|
||||
now - lastHudUpdate >= HudRefreshInterval)
|
||||
{
|
||||
_lastHudUpdate[player] = now;
|
||||
player.PrintToCenterHtml(BuildFuelMessage(fuel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildFuelMessage(float fuel)
|
||||
{
|
||||
int percent = (int)MathF.Round((fuel / MaxFuel) * 100.0f);
|
||||
int filledBars = (int)MathF.Round((fuel / MaxFuel) * 10.0f);
|
||||
filledBars = Math.Clamp(filledBars, 0, 10);
|
||||
string bar = new string('|', filledBars).PadRight(10, '.');
|
||||
string color = percent > 60 ? "#4CAF50" : percent > 30 ? "#FFC107" : "#F44336";
|
||||
return $"<font color='#FFFFFF'>Jetpack Fuel:</font> <font color='{color}'>{percent}%</font><br><font color='{color}'>{bar}</font>";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user