FpsUI/Widgets/FpsInput.cs

Utility static class for player input helpers. AutoFire implements full-auto firing cadence (returns true on frames a shot should fire, tracking cooldown by ref). ApplySprintGate enforces a sprint gate by clamping a PlayerController's RunSpeed to WalkSpeed while stamina is empty and restoring it when stamina recovers.

using Sandbox;

namespace Goo.FpsUI;

// Shared input helpers - full-auto fire cadence and a sprint gate.
// The gate clamps RunSpeed down to WalkSpeed while stamina is empty (no-op unless the player is valid).
static class FpsInput
{
    // Full-auto cadence. Pass held = Input.Down("attack1") each frame, returns true on the frames a shot fires.
    // First shot fires instantly, releasing resets so the next press fires immediately. Cooldown tracked via ref.
    public static bool AutoFire( bool held, float roundsPerMinute, float dt, ref float cooldown )
    {
        cooldown -= dt;
        if ( !held ) { cooldown = 0f; return false; }
        if ( cooldown > 0f ) return false;
        cooldown = 60f / System.MathF.Max( 1f, roundsPerMinute );
        return true;
    }

    public static void ApplySprintGate(
        PlayerController? player,
        float stamina,
        ref bool blocked,
        ref float cachedRunSpeed )
    {
        if ( player is null || !player.IsValid() ) return;

        if ( stamina <= 0f && !blocked )
        {
            // Gassed: cache run speed and clamp it to walk speed so sprinting gives no extra speed.
            cachedRunSpeed = player.RunSpeed;
            player.RunSpeed = player.WalkSpeed;
            blocked = true;
        }
        else if ( stamina > 0f && blocked )
        {
            player.RunSpeed = cachedRunSpeed;  // recovered: restore sprint speed
            blocked = false;
        }
    }
}