Units/DamageUtil.cs
using static Sandbox.Component;

namespace PlanetMeat;

public static class DamageUtil
{
	const string TAG_FRIENDLY_FIRE = "unfriendly";
	const string TAG_EXPLOSIVE = "explosive";
	const string TAG_RETALIATION = "thorns";

	public static bool IsTargetValid( this DamageInfo dmg, ITargeterStatus target )
	{
		return dmg.IsHostileTo( target ) || IsFriendlyFire( dmg );
	}

	public static bool IsHostileTo( this DamageInfo dmg, ITargeterStatus target )
	{
		return dmg.Attacker?.Components.Get<ITargeterStatus>() is not ITargeterStatus attackerStatus
			|| !attackerStatus.IsFriendlyTo( target );
	}

	public static void SetFriendlyFire( this DamageInfo dmg, bool value ) => dmg.Tags.Set( TAG_FRIENDLY_FIRE, value );
	public static bool IsFriendlyFire( this DamageInfo dmg ) => dmg.Tags.Contains( TAG_FRIENDLY_FIRE );

	public static void SetExplosive( this DamageInfo dmg, bool value ) => dmg.Tags.Set( TAG_EXPLOSIVE, value );
	public static bool IsExplosive( this DamageInfo dmg ) => dmg.Tags.Contains( TAG_EXPLOSIVE );

	public static void SetRetaliation( this DamageInfo dmg, bool value ) => dmg.Tags.Set( TAG_RETALIATION, value );
	public static bool IsRetaliation( this DamageInfo dmg ) => dmg.Tags.Contains( TAG_RETALIATION );

	public static string FindBlameIdent( this DamageInfo dmg )
	{
		var blame = dmg.Weapon.Components.Get<IAttackBlame>() ?? dmg.Attacker.Components.Get<IAttackBlame>();
		return blame?.Ident ?? "";
	}

	public static Targetable FindAttackingTargetable( this DamageInfo dmg )
	{
		return dmg.Attacker.FindNearestUpwards<Targetable>() ?? dmg.Weapon.FindNearestUpwards<Targetable>();
	}

	public static void Explode( this DamageInfo dmg, Scene scene, Sphere sphere )
	{
		dmg.SetExplosive( true );
		foreach ( var go in scene.FindInPhysics( sphere ) )
		{
			if ( go.Components.Get<IDamageable>() is IDamageable hit )
				hit.OnDamage( in dmg );
		}
	}
	public static void Explode( this DamageInfo dmg, Component comp, float radius )
	{
		Explode( dmg, comp.Scene, new( comp.WorldPosition, radius ) );
	}
}