Effects/Ring/TimedRing.cs
namespace PlanetMeat;

[Group( "Planet Meat - Effects" ), Title( "Timed Ring" ), Icon( "radar" )]
public class TimedRing : Component, IWorldRing
{
	private static GameObject Prefab => GameObject.GetPrefab( "tools/timed_ring.prefab" );
	public static TimedRing Create( Vector3 position, float radius )
	{
		var go = Prefab.Clone( position );
		if ( go.Components.Get<TimedRing>() is TimedRing ring )
		{
			ring.EffectRadius = radius;
			return ring;
		}
		return null;
	}

	[Property] public AoeRing EffectRing { get; set; }
	[Property] public AoeRing TimerRing { get; set; }

	public float EffectRadius
	{
		get => EffectRing.Radius;
		set => EffectRing.Radius = value;
	}

	protected float TimerStartRadius { get; set; }
	protected float TimerFinalRadius { get; set; }
	protected float ProgressMax { get; set; } = float.NaN;
	protected float Progress
	{
		get;
		set
		{
			var pMax = ProgressMax;
			if ( !float.IsNaN( pMax ) )
			{
				Lerp( value / pMax );

				if ( value >= pMax )
				{
					ProgressMax = float.NaN;
					field = 0.0f;
					return;
				}
			}
			field = value;
		}
	} = 0.0f;

	protected virtual void Lerp( float frac )
	{
		TimerRing.Radius = TimerStartRadius.LerpTo( TimerFinalRadius, frac );
	}

	protected virtual void ShowTimer( bool show )
	{
		TimerRing.Components.Get<WorldPanel>()?.Enabled = show;
	}

	private void ApplyTimerVisibility()
	{
		ShowTimer( !float.IsNaN( ProgressMax ) );
	}

	protected override void OnStart()
	{
		base.OnStart();
		ApplyTimerVisibility();
	}

	public virtual void MultiplyAlpha( float mult )
	{
		EffectRing.RingColor = EffectRing.RingColor.WithAlphaMultiplied( mult );
		TimerRing.RingColor = TimerRing.RingColor.WithAlphaMultiplied( mult );
	}

	protected void StartTimer( float duration )
	{
		ProgressMax = duration;
		Progress = 0.0f;
	}

	public void StartBasicTimer( float duration, bool inwards )
	{
		TimerStartRadius = inwards ? EffectRadius : 0.0f;
		TimerFinalRadius = inwards ? 0.0f : EffectRadius;
		StartTimer( duration );
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();
		if ( !float.IsNaN( ProgressMax ) )
			Progress += Time.Delta;
	}
}