Player/Mechanics/StaminaMechanic.cs
namespace Opium;

public partial class StaminaMechanic : PlayerMechanic
{
	public float Stamina { get; set; } = 100f;

	[Property] public float SprintStaminaDrain { get; set; } = 10f;
	[Property] public float StaminaReplenishTime { get; set; } = 5f;

	[Property, Category( "Stamina" )] public float StaminaDrainSpeed { get; set; } = 10f;
	[Property, Category( "Stamina" )] public float StaminaRegenerateSpeed { get; set; } = 5f;

	public bool CanUseStamina { get; set; }
	public TimeSince TimeSinceStaminaWasEmpty { get; private set; }
	public TimeSince TimeSinceLastUsedStamina { get; private set; }
	public TimeUntil TimeUntilRegenerate { get; private set; }

	/// <summary>
	/// Stamina is ALWAYS active.
	/// </summary>
	/// <returns></returns>
	public override bool ShouldBecomeActive()
	{
		return true;
	}

	public void RemoveStamina( float staminaUsed, float timeUntilNextRegenerate = 0.0f )
	{
		Stamina = Stamina.Clamp( 0, 100 ) - staminaUsed;
		TimeSinceLastUsedStamina = 0;

		if ( timeUntilNextRegenerate != 0f )
		{
			TimeUntilRegenerate = timeUntilNextRegenerate;
		}
	}

	public void AddStamina( float staminaAdded )
	{
		Stamina = Stamina.Clamp( 0, 100 ) + staminaAdded;
		if ( Stamina <= 100 )
		{
			TimeSinceLastUsedStamina = 0;
		}
	}

	public override void OnActiveUpdate()
	{
		Stamina = Stamina.Clamp( 0, 100 );

		if ( Stamina <= 1 )
		{
			CanUseStamina = false;
			TimeSinceStaminaWasEmpty = 0;
		}

		if ( TimeSinceStaminaWasEmpty > StaminaReplenishTime )
		{
			CanUseStamina = true;
		}

		if ( Player.MechanicTags.Has( "sprint" ) )
		{
			RemoveStamina( Time.Delta * SprintStaminaDrain, 1f );
		}
		if ( TimeUntilRegenerate )
		{
			AddStamina( Time.Delta * StaminaRegenerateSpeed );
		}
	}

	public override IEnumerable<string> GetTags()
	{
		if ( Stamina <= 0 ) yield return "exhausted";
	}
}