EasterEgg/Clue.cs

Component representing a single world clue for an Easter egg system. It tracks all live Clue instances in a static list, exposes its source ClueSpot config, and provides a diagnostic helper to find the nearest clue to a position.

using Sandbox;
using System.Collections.Generic;
using System.Linq;

namespace NZombies;

/// <summary>
/// One clue standing in the world.
///
/// ⛔ NO FLAGS, NO CONDITIONS, NO `EggStep`. Per `Docs/EASTER_EGG_TOOLSET.md`, a clue is
/// "purely informational — not part of the flag system at all". Everything else in the
/// EE toolset carries Required/Reward/Excluded/StepNumber; this deliberately does not,
/// and adding them "for consistency" would invent a mechanism the design withholds.
///
/// ⚠️ SO IT IS THE ONE EE TOOL THAT NEEDS NONE OF THE CONDITION SYSTEM, which is why it
/// was built first — it proves the placement, the surface mounting and the world-space
/// panel without waiting on flags.
/// </summary>
public sealed class Clue : Component
{
	/// <summary>Every live clue, for the diagnostics.</summary>
	public static readonly List<Clue> All = new();

	protected override void OnEnabled() { if ( !All.Contains( this ) ) All.Add( this ); }
	protected override void OnDisabled() => All.Remove( this );

	/// <summary>The config row this was built from. The panel reads it directly.</summary>
	[Property] public ClueSpot Spot { get; set; }

	/// <summary>The nearest clue to a point, for the diagnostics.</summary>
	public static Clue Near( Vector3 pos )
		=> All.Where( c => c.IsValid() )
			.OrderBy( c => c.WorldPosition.DistanceSquared( pos ) )
			.FirstOrDefault();
}