swb_base/Weapon.Extra.cs

Partial Weapon class extensions. Adds burst-fire reset logic, barrel heat cooldown, and player tuck distance checks using traces and owner state.

File Access
namespace SWB.Base;

public partial class Weapon
{
	// Burst Fire
	public void ResetBurstFireCount( ShootInfo shootInfo, string inputButton )
	{
		if ( shootInfo is null || shootInfo.FiringType != FiringType.burst ) return;

		// ⛔ THE UPSTREAM RESET RUNS ONCE PER FRAME AND WOULD BEAT THE LATCH. Weapon.cs
		// calls this immediately before CanPrimaryShoot, so an uninterruptible burst would
		// be cleared here and CanShoot's own latch would never see a non-zero `burstCount`
		// — the node would work everywhere except on the one prefab that reaches this line.
		//
		// ⛔ "ONLY THE G11 CAN REACH IT" WAS TRUE AT 31 WEAPONS AND IS FALSE AT 496. Twenty-six
		// prefabs author `FiringType: burst` today — B23R, M9, Trespasser, Chicom, M1216, five
		// separate M16A4s and the rest (enumerated 2026-09-14, not estimated). A count in a
		// comment is a claim with an expiry date; this one outlived the roster that made it true.
		//
		// ⚠️ AND THIS RESET IS NO LONGER THE ONLY ONE THAT MATTERS. It is edge-triggered on
		// `Input.Released`, and that edge is spent mid-burst now that every burst latches — see
		// the level-triggered clear in `CanShoot`'s burst branch, which is what actually ends a
		// finished burst. This one still handles the cancel-before-the-latch case.
		if ( Input.Released( inputButton ) && !BurstLatched( shootInfo ) )
		{
			burstCount = 0;
		}
	}

	// Barrel heat
	public void BarrelHeatCheck()
	{
		if ( TimeSincePrimaryShoot > 3 && TimeSinceSecondaryShoot > 0 )
		{
			barrelHeat = 0;
		}
	}

	// Tucking
	public virtual float GetTuckDist()
	{
		if ( TuckRange == -1 )
			return -1;

		if ( !Owner.IsValid ) return -1;

		// Increase tuck range around ladders
		var tuckRange = Owner.IsClimbingLadder ? TuckRange * 1.25f : TuckRange;
		var pos = Owner.EyePos;
		var forward = Owner.EyeAngles.ToRotation().Forward;
		var trace = TraceBullet( Owner.EyePos, pos + forward * tuckRange, 2, TuckingTraceIgnoreTags );

		if ( !trace.Hit )
			return -1;

		return trace.Distance;
	}

	public bool ShouldTuck( out float dist )
	{
		dist = GetTuckDist();
		return dist != -1;
	}
}