Entities/Abilities/ClimberDashEyeTintAbility.cs
namespace BlockParty;

/// <summary>Shows whether Climber's dash (recharged by moving on surfaces) is currently available.</summary>
public sealed class ClimberDashEyeTintAbility : PlayerAbility
{
	private static readonly Color EMPTY_DASH_EYE_TINT = new( 0.86f, 0.18f, 0.18f, 0.82f );
	// Bright blue-white blink the moment the charge refills, fading back to the plain eyes.
	private static readonly Color RECHARGE_FLASH_EYE_TINT = new( 0.88f, 0.96f, 1f, 1f );
	private const float RECHARGE_FLASH_TIME = 0.22f;

	private TwinAbilityEyeTint _eyeTint;
	private float _flashTimer;

	public override void OnSpawn( Player player )
	{
		var tintObject = new GameObject( true, "climber dash eye tint" );
		tintObject.SetParent( player.GameObject );
		tintObject.LocalPosition = Vector3.Zero;
		_eyeTint = tintObject.Components.Create<TwinAbilityEyeTint>();
		_eyeTint.Setup( player, adjustTwinOneWalk: false, eyeLeft: 3, eyeTop: 1,
			eyeWidth: 4, eyeHeight: 4, tintDarkPixels: true );
	}

	public override void OnRemoved( Player player )
	{
		_eyeTint?.GameObject?.Destroy();
		_eyeTint = null;
	}

	public override void OnDeath( Player player )
	{
		_flashTimer = 0f;
		if ( _eyeTint is not null ) _eyeTint.Tint = Color.Transparent;
	}

	public override void OnDashRecharged( Player player ) => _flashTimer = RECHARGE_FLASH_TIME;

	public override void PostTick( Player player, float dt )
	{
		if ( _eyeTint is null ) return;
		if ( !player.DashCharged )
		{
			_flashTimer = 0f;
			_eyeTint.Tint = EMPTY_DASH_EYE_TINT;
			return;
		}
		if ( _flashTimer <= 0f )
		{
			_eyeTint.Tint = Color.Transparent;
			return;
		}
		_flashTimer -= dt;
		_eyeTint.Tint = RECHARGE_FLASH_EYE_TINT.WithAlpha( Math.Clamp( _flashTimer / RECHARGE_FLASH_TIME, 0f, 1f ) );
	}
}