Units/Lifesteal.cs
using System;

namespace PlanetMeat;

[Group( "Planet Meat - Units" ), Title( "Lifesteal" ), Icon( "vaccines" )]
public sealed class Lifesteal : Component
{
	public static List<Lifesteal> All => field ??= [];

	[Property] public string DamageStealImprovement { get; set; } = "";
	public ValueAggregator<float> AggregateDamageSteal => field ??= ValueAggregator<float>.FromImprovement( DamageStealImprovement, 0.0f );

	[Property] public string KillHealAmountImprovement { get; set; } = "";
	public ValueAggregator<int> AggregateKillHealAmount => field ??= ValueAggregator<int>.FromImprovement( KillHealAmountImprovement, 0 );

	[Property] public string KillHealRateImprovement { get; set; } = "";
	public ValueAggregator<float> AggregateKillHealRate => field ??= ValueAggregator<float>.FromImprovement( KillHealRateImprovement, 0.0f );
	private float KillHealProgress { get; set; } = 0.0f;

	private Targetable Targetable => field ??= this.FindNearestUpwards<Targetable>();
	float damageDebt = 0.0f;

	protected override void OnStart()
	{
		base.OnStart();
		All.Add( this );
	}

	protected override void OnDestroy()
	{
		All.Remove( this );
		base.OnDestroy();
	}

	public void StealDamage( Targetable victim, int dmg )
	{
		if ( IsValidTarget( victim ) )
		{
			var steal = dmg * AggregateDamageSteal.Total + damageDebt;
			var wholeSteal = (int)Math.Round( steal );
			Targetable.CurrentHp += wholeSteal;
			damageDebt += steal - wholeSteal;
		}
	}

	public void KillHeal( Targetable victim )
	{
		if ( IsValidTarget( victim ) )
		{
			KillHealProgress += AggregateKillHealRate.Total;
			if ( KillHealProgress > 0.99f )
			{
				Targetable.CurrentHp += AggregateKillHealAmount.Total;
				KillHealProgress -= 1.0f;
			}
		}
	}

	private bool IsValidTarget( Targetable t ) => !Targetable.IsFriendlyTo( t );
}