AI/ActionSystem/AgentAction.cs
using System;

namespace HC3;

/// <summary>
/// Represents the display information for an action. We show this in the UI.
/// </summary>
/// <param name="Icon"></param>
/// <param name="Description"></param>
/// <param name="Progress"></param>
public readonly record struct ActionDisplayInfo
(
	string Icon,
	string Description,
	float Progress
);

[Group( "Agent Actions" ), Icon( "mediation" )]
public abstract class AgentAction : Component
{
	private Agent _cachedAgent;
	public Agent Agent => _cachedAgent ??= GetComponentInParent<Agent>();

	public AgentActionController ActionController => Agent.ActionController;
	public AgentController Controller => Agent.Controller;
	public Random Random => ActionController.Random;

	[Property, Group( "Times" )] public float CooldownTime { get; set; } = 0f;
	[Property, Group( "Times" )] public float DurationTime { get; set; } = 0f;

	protected float _lastEndTime = float.NegativeInfinity;
	protected float _startTime;

	public virtual ActionDisplayInfo? GetDisplay() => null;

	public bool IsOnCooldown()
	{
		return Time.Now < _lastEndTime + CooldownTime;
	}

	public float ScoreInternal()
	{
		return IsOnCooldown() ? 0f : Score();
	}

	public void StartInternal()
	{
		_startTime = Time.Now;
		StartAction();
	}

	public Status TickInternal()
	{
		if ( DurationTime > 0 )
		{
			if ( Time.Now - _startTime >= DurationTime )
				return Status.Success;
		}

		return TickAction();
	}

	public void StopInternal()
	{
		_lastEndTime = Time.Now;
		StopAction();
	}

	public abstract float Score();
	public virtual void StartAction() { }
	public abstract Status TickAction();
	public virtual void StopAction() { }

	public enum Status
	{
		Running,
		Success,
		Failure
	}
}