Player/NZPlayer.ClassTech.cs

Partial NZPlayer class holding per-class weapon-tech state for a player body. Stores adrenaline stacks, lifeline-applied health, follow-through shot id and leftover damage, and provides TechOrNull(prefab) to return the owned tech node list or null.

NetworkingFile Access
namespace NZombies;

/// <summary>
/// The per-class weapon tech's state that belongs to the BODY rather than to a gun (2026-10-04,
/// `Sbox nzombies/Docs/WEAPON_TECH_BY_CLASS.md`).
///
/// ⚠️ NOT `[Sync]`. Each is set and read on the owner's own machine; what they change (move speed, max health)
/// replicates the way every other source of it does.
/// </summary>
public sealed partial class NZPlayer
{
	/// <summary>
	/// ADRENALINE ROUNDS (`t5_adrenaline`): hits stacked since the last one-second gap. Each is +1% damage and +1% aiming
	/// walk speed, up to the node's cap. Read together with `AdrenalineUntil`, which ends them.
	/// </summary>
	public int AdrenalineStacks { get; set; }

	/// <summary>
	/// LIFELINE (`t5_hg_lifeline`): the max health the gun in hand added at the last `JuggAugments.RefreshHealth`, so a
	/// switch can tell its own share of a change from Juggernog's. Lifeline's share raises the ceiling and heals nothing.
	/// </summary>
	public float LifelineApplied { get; set; }

	/// <summary>
	/// FOLLOW-THROUGH (`t3_br_followthrough`, 2026-10-04): the bullet (`ShotId`) whose kill left
	/// <see cref="FollowThroughLeft"/> over, and that leftover, waiting for the same bullet's next zombie
	/// (`ClassTech.FollowThroughCarry`).
	///
	/// ⚠️ THE HOST'S, NOT THE OWNER'S — the exception in this file: only the host knows a kill, so it keeps these on its
	/// copy of the shooter. One slot: a newer kill replaces it, and a bullet that stops leaves it unmatched.
	/// </summary>
	public System.Guid FollowThroughShot { get; set; }

	/// <summary>FOLLOW-THROUGH: the leftover damage waiting for <see cref="FollowThroughShot"/>'s next zombie. 0 when none.</summary>
	public float FollowThroughLeft { get; set; }

	/// <summary>
	/// The nodes this prefab owns, or null when it owns none — `TechFor` without its fresh empty list.
	///
	/// ⚠️ FOR THE PER-FRAME STAT READS (`TechStats`): `EffectiveFiringType` alone asks three switches several times a frame,
	/// and `TechFor` allocates a new list for every gun that has no tech. Same rules as `TechFor`: the wonder weapon owns
	/// nothing, and the host reads a client's tree off the wire (`TechStore`).
	/// </summary>
	public System.Collections.Generic.List<string> TechOrNull( string prefab )
		=> !string.IsNullOrEmpty( prefab ) && !BuildParts.IsWonderWeapon( prefab )
			&& TechStore.TryGetValue( prefab, out var l ) && l.Count > 0
				? l
				: null;
}