AI/ActionSystem/BehaviorTree/Nodes/TimedSequenceNode.cs
using System;

namespace HC3;

/// <summary>
/// A node that performs an animated action with a specific sequence.
/// </summary>
public class TimedSequenceNode : Node
{
	private readonly Agent _agent;
	private readonly string _animationSequence;
	private readonly float _animationDuration;
	private readonly string _reason;
	private readonly Action _onStart;
	private readonly Action _onComplete;
	private readonly Func<bool> _conditionCheck;
	private RealTimeSince _timeSinceStarted;
	private bool _animationComplete;
	private readonly string _icon;

	/// <summary>
	/// Creates a node that performs an animated action
	/// </summary>
	/// <param name="agent">The agent performing the animation</param>
	/// <param name="animationSequence">The animation sequence to play</param>
	/// <param name="animationDuration">How long the animation lasts</param>
	/// <param name="onStart">Action to perform when animation starts</param>
	/// <param name="onComplete">Action to perform when animation completes</param>
	/// <param name="conditionCheck">Optional condition that must be true for the action to continue</param>
	/// <param name="reason">Display reason for this action</param>
	/// <param name="icon">Material icon to display</param>
	public TimedSequenceNode(
		Agent agent,
		string animationSequence,
		float animationDuration,
		Action onStart = null,
		Action onComplete = null,
		Func<bool> conditionCheck = null,
		string reason = "Performing action...",
		string icon = "movie" )
	{
		_agent = agent;
		_animationSequence = animationSequence;
		_animationDuration = animationDuration;
		_onStart = onStart;
		_onComplete = onComplete;
		_conditionCheck = conditionCheck ?? (() => true);
		_reason = reason;
		_icon = icon;
	}

	protected override void OnStart()
	{
		_timeSinceStarted = 0;
		_animationComplete = false;

		// Play animation
		_agent.SetSequenceOverride( _animationSequence, 1.0f );

		// Execute start action
		_onStart?.Invoke();
	}

	public override Status Tick()
	{
		// If condition check fails, return failure
		if ( !_conditionCheck() )
		{
			_agent.SetSequenceOverride( null );
			return Status.Failure;
		}

		// Wait for animation to complete
		if ( _timeSinceStarted < _animationDuration )
			return Status.Running;

		// Animation is complete
		if ( !_animationComplete )
		{
			_agent.SetSequenceOverride( null );
			_onComplete?.Invoke();
			_animationComplete = true;
		}

		return Status.Success;
	}

	protected override void OnStop()
	{
		// Ensure animation is cleared when node stops
		if ( !_animationComplete )
		{
			_agent.SetSequenceOverride( null );
		}
	}

	public override ActionDisplayInfo? GetDisplay()
	{
		float progress = (_timeSinceStarted / _animationDuration).Clamp( 0f, 1f );
		return new ActionDisplayInfo( _icon, _reason, progress );
	}
}