Chaos.cs

Static game state component that tracks a global "chaos" meter influencing mood. It stores value, version, exposes read-only properties, allows resetting, setting, adding with clamps, decays over time in TickCalm, and reads/writes to SaveData while notifying GameAudio on mood changes.

File Access
namespace NoChillquarium;

/// <summary>
/// Chaos meter — one input into No-Chill mood.
/// High chaos (≥40) forces metal beds; calm chaos alone keeps chill
/// unless other absurd systems (sharks, meth, M80, death…) take over via <see cref="GameAudio"/>.
/// </summary>
public static class Chaos
{
	public const float NoChillThreshold = 40f;
	public const float Max = 100f;

	static float _value;
	static int _version;

	public static float Value => _value;
	public static int Version => _version;
	public static bool IsNoChill => _value >= NoChillThreshold;
	public static string MoodLabel => IsNoChill ? "NO-CHILL" : "CHILL";
	public static string ValueText => $"{_value:0}";

	public static void Reset()
	{
		_value = 0f;
		_version++;
	}

	public static void Set( float value )
	{
		_value = Math.Clamp( value, 0f, Max );
		_version++;
		GameAudio.OnMoodMaybeChanged();
	}

	public static void Add( float amount )
	{
		if ( amount == 0f )
			return;

		var before = IsNoChill;
		_value = Math.Clamp( _value + amount, 0f, Max );
		_version++;

		if ( before != IsNoChill )
			GameAudio.OnMoodMaybeChanged( force: true );
	}

	/// <summary>Good-boy decay while not exploding (slow).</summary>
	public static void TickCalm( float dt )
	{
		if ( _value <= 0f || dt <= 0f )
			return;

		// Decay without spamming version/music every frame.
		var before = IsNoChill;
		var next = Math.Clamp( _value - 1.5f * dt, 0f, Max );
		if ( MathF.Abs( next - _value ) < 0.0001f )
			return;

		_value = next;
		// HUD refresh ~4 Hz
		if ( (int)(_value * 4f) != (int)((_value + 1.5f * dt) * 4f) )
			_version++;

		if ( before != IsNoChill )
		{
			_version++;
			GameAudio.OnMoodMaybeChanged( force: true );
		}
	}

	public static void WriteToSave( SaveData data )
	{
		if ( data is not null )
			data.Chaos = _value;
	}

	public static void LoadFromSave( SaveData data )
	{
		if ( data is null )
		{
			Reset();
			return;
		}

		Set( data.Chaos );
	}
}