using UnityEngine; namespace ProjectI.Combat { public static class DamageRules { public static float Scale(DamageKind kind, float amount, float multiplier, bool critical, float headshotMultiplier) { if (!System.Enum.IsDefined(typeof(DamageKind), kind) || !Positive(amount) || !Positive(multiplier)) return 0; double scaled = (double)amount * multiplier; if (kind == DamageKind.Weapon && critical) { if (!Positive(headshotMultiplier)) return 0; scaled *= headshotMultiplier; } // An accepted high-rank hit saturates at the physical float boundary; it never becomes zero. return scaled > 0 ? (float)System.Math.Min(float.MaxValue, scaled) : 0; } public static DamageResult Apply(HealthState state, DamageContext context, ulong targetId, uint lifetime, bool hostile, Vector3 anchor) { if (state == null || !System.Enum.IsDefined(typeof(DamageKind), context.Kind) || !Positive(context.Amount) || !Finite(anchor.x) || !Finite(anchor.y) || !Finite(anchor.z)) return default; bool alive = !state.IsDowned; float applied = state.ApplyDamage(context.Amount); return new DamageResult { TargetId = targetId, Lifetime = lifetime, Anchor = anchor, Applied = applied, HitDamage = alive ? context.Amount : 0, ImpactPoint = Finite(context.HitPoint.x) && Finite(context.HitPoint.y) && Finite(context.HitPoint.z) ? context.HitPoint : anchor, Critical = context.Critical && applied > 0, Lethal = alive && state.IsDowned && applied > 0, Hostile = hostile }; } private static bool Finite(float value) => !float.IsNaN(value) && !float.IsInfinity(value); public static DamageResult AggregateFeedback(DamageResult normal,DamageResult critical,float hitDamage,bool precision) { if(!Positive(hitDamage)||(!normal.HasDamage&&!critical.HasDamage))return default; var result=normal.HasDamage?normal:critical; result.Applied=(float)System.Math.Min(float.MaxValue,(double)normal.Applied+critical.Applied); result.HitDamage=hitDamage;result.Critical=precision;result.Lethal=normal.Lethal||critical.Lethal; return result; } public static float SumHitDamage(float normal,float precision)=>Finite(normal)&&Finite(precision)&&normal>=0&&precision>=0 ?(float)System.Math.Min(float.MaxValue,(double)normal+precision):0; private static bool Positive(float value) => Finite(value) && value > 0; } }