feat: add BasePower abstraction
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Cs2SuperPowers.Players;
|
||||
using Cs2SuperPowers.Players.PlayerValidations;
|
||||
using Cs2SuperPowers.Utils;
|
||||
|
||||
namespace Cs2SuperPowers.Powers;
|
||||
|
||||
public class GrenadeLauncher(IPlayerHud playerHud) : BasePower(playerHud)
|
||||
{
|
||||
public override int Id => 11;
|
||||
public override string Name => "Grenade Launcher";
|
||||
|
||||
public override string Description => "Every shot from your pistol launches a grenade (0.5s cooldown).";
|
||||
|
||||
public override char ChatColor => ChatColors.Red;
|
||||
|
||||
public override string HtmlColor => "#FF0000";
|
||||
|
||||
private readonly Dictionary<CCSPlayerController, DateTime> _lastUse = new();
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
RegisterEventHandler<EventRoundStart>(OnRoundStart);
|
||||
RegisterEventHandler<EventWeaponFire>(OnWeaponFire);
|
||||
}
|
||||
|
||||
private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo _)
|
||||
{
|
||||
_lastUse.Clear();
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
private HookResult OnWeaponFire(EventWeaponFire @event, GameEventInfo info)
|
||||
{
|
||||
var controller = @event.Userid;
|
||||
if (!Ensure.Player(controller).IsValid().Check() || !IsAssignedTo(controller!))
|
||||
return HookResult.Continue;
|
||||
|
||||
// Only pistols
|
||||
var weapon = controller!.PlayerPawn.Value?.WeaponServices?.ActiveWeapon.Value;
|
||||
if (weapon == null)
|
||||
return HookResult.Continue;
|
||||
|
||||
// List of pistol weapon names (classnames)
|
||||
var pistolClassNames = new[]
|
||||
{
|
||||
"weapon_glock", "weapon_usp_silencer", "weapon_hkp2000", "weapon_p250",
|
||||
"weapon_fiveseven", "weapon_tec9", "weapon_cz75a", "weapon_deagle",
|
||||
"weapon_revolver", "weapon_elite"
|
||||
};
|
||||
|
||||
if (!pistolClassNames.Contains(weapon.DesignerName))
|
||||
return HookResult.Continue;
|
||||
|
||||
// Check cooldown (skip if nodelay is enabled)
|
||||
var now = DateTime.UtcNow;
|
||||
if (!GlobalConfig.NoDelayEnabled && _lastUse.TryGetValue(controller!, out var lastUseTime) && (now - lastUseTime).TotalSeconds < 0.5)
|
||||
return HookResult.Continue;
|
||||
_lastUse[controller!] = now;
|
||||
|
||||
var pawn = controller!.PlayerPawn.Value;
|
||||
if (pawn == null || !pawn.IsValid)
|
||||
return HookResult.Continue;
|
||||
|
||||
var pos = pawn.AbsOrigin;
|
||||
if (pos == null) return HookResult.Continue;
|
||||
pos = new Vector(pos.X, pos.Y, pos.Z + 64f);
|
||||
|
||||
// Forward vector from the player's view angles
|
||||
var ang = pawn.V_angle;
|
||||
float yaw = ang.Y * MathF.PI / 180f;
|
||||
float pitch = ang.X * MathF.PI / 180f;
|
||||
var forward = new Vector(
|
||||
MathF.Cos(yaw) * MathF.Cos(pitch),
|
||||
MathF.Sin(yaw) * MathF.Cos(pitch),
|
||||
-MathF.Sin(pitch)
|
||||
);
|
||||
|
||||
// Spawn farther in front of the player so the grenade does not collide with the shooter.
|
||||
const float spawnAhead = 72f;
|
||||
pos = new Vector(
|
||||
pos.X + forward.X * spawnAhead,
|
||||
pos.Y + forward.Y * spawnAhead,
|
||||
pos.Z + forward.Z * 24f
|
||||
);
|
||||
|
||||
const float speed = 1100f;
|
||||
|
||||
int grenadeCount = GlobalConfig.GetGrenadeLauncherCount(1);
|
||||
for (int i = 0; i < grenadeCount; i++)
|
||||
{
|
||||
// Add slight random spread for multiple grenades
|
||||
var random = new Random();
|
||||
var spreadAng = new QAngle(
|
||||
ang.X + (float)(random.NextDouble() * 10.0 - 5.0), // ±5° pitch
|
||||
ang.Y + (float)(random.NextDouble() * 10.0 - 5.0), // ±5° yaw
|
||||
ang.Z
|
||||
);
|
||||
|
||||
float spreadYaw = spreadAng.Y * MathF.PI / 180f;
|
||||
float spreadPitch = spreadAng.X * MathF.PI / 180f;
|
||||
var spreadForward = new Vector(
|
||||
MathF.Cos(spreadYaw) * MathF.Cos(spreadPitch),
|
||||
MathF.Sin(spreadYaw) * MathF.Cos(spreadPitch),
|
||||
-MathF.Sin(spreadPitch)
|
||||
);
|
||||
|
||||
var velocity = new Vector(
|
||||
spreadForward.X * speed,
|
||||
spreadForward.Y * speed,
|
||||
spreadForward.Z * speed + 100f
|
||||
);
|
||||
|
||||
GrenadeSpawner.CreateGrenade(pos, spreadAng, velocity, pawn);
|
||||
}
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user