diff --git a/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs b/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs index e13081670e..15eb1232b7 100644 --- a/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs +++ b/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Lint if (!warhead.ValidTargets.Overlaps(targetable)) continue; - if (healthTraits.Where(x => x.Radius.Length > warhead.TargetExtraSearchRadius.Length).Any()) + if (healthTraits.Where(x => x.Shape.OuterRadius.Length > warhead.TargetExtraSearchRadius.Length).Any()) emitError("Actor type `{0}` has a health radius exceeding the victim scan radius of a warhead on `{1}`!" .F(actorInfo.Key, weaponInfo.Key)); } diff --git a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs index ed0d04ec8c..e016bf9620 100644 --- a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs +++ b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs @@ -12,7 +12,6 @@ using System; using System.Drawing; using OpenRA.Graphics; using OpenRA.Mods.Common.Effects; -using OpenRA.Mods.Common.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -48,13 +47,12 @@ namespace OpenRA.Mods.Common.Traits if (devMode == null || !devMode.ShowCombatGeometry) return; - if (healthInfo != null) - RangeCircleRenderable.DrawRangeCircle(wr, self.CenterPosition, healthInfo.Radius, - 1, Color.Red, 0, Color.Red); - var wcr = Game.Renderer.WorldRgbaColorRenderer; var iz = 1 / wr.Viewport.Zoom; + if (healthInfo != null) + healthInfo.Shape.DrawCombatOverlay(wr, wcr, self); + if (blockInfo != null) { var hc = Color.Orange; diff --git a/OpenRA.Mods.Common/Traits/Health.cs b/OpenRA.Mods.Common/Traits/Health.cs index 7da9ddcc96..0eaf6d65ba 100644 --- a/OpenRA.Mods.Common/Traits/Health.cs +++ b/OpenRA.Mods.Common/Traits/Health.cs @@ -8,7 +8,9 @@ */ #endregion +using System; using System.Linq; +using OpenRA.Mods.Common.HitShapes; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -17,13 +19,39 @@ namespace OpenRA.Mods.Common.Traits { [Desc("HitPoints")] public readonly int HP = 0; - - [Desc("Physical size of the unit used for damage calculations. Impacts within this radius apply full damage.")] - public readonly WDist Radius = new WDist(426); - [Desc("Trigger interfaces such as AnnounceOnKill?")] public readonly bool NotifyAppliedDamage = true; + [FieldLoader.LoadUsing("LoadShape")] + public readonly IHitShape Shape; + + static object LoadShape(MiniYaml yaml) + { + IHitShape ret; + + var shapeNode = yaml.Nodes.Find(n => n.Key == "Shape"); + var shape = shapeNode != null ? shapeNode.Value.Value : string.Empty; + + if (!string.IsNullOrEmpty(shape)) + { + ret = Game.CreateObject(shape + "Shape"); + + try + { + FieldLoader.Load(ret, shapeNode.Value); + } + catch (YamlException e) + { + throw new YamlException("HitShape {0}: {1}".F(shape, e.Message)); + } + } + else + ret = new CircleShape(); + + ret.Initialize(); + return ret; + } + public virtual object Create(ActorInitializer init) { return new Health(init, this); } } diff --git a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs index 63d2401d7f..63279db33c 100644 --- a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs @@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Warheads continue; // If the impact position is within any actor's health radius, we have a direct hit - if ((unit.CenterPosition - pos).LengthSquared <= healthInfo.Radius.LengthSquared) + if ((unit.CenterPosition - pos).LengthSquared <= healthInfo.Shape.OuterRadius.LengthSquared) return true; } diff --git a/OpenRA.Mods.Common/Warheads/SpreadDamageWarhead.cs b/OpenRA.Mods.Common/Warheads/SpreadDamageWarhead.cs index 9330404895..982640b225 100644 --- a/OpenRA.Mods.Common/Warheads/SpreadDamageWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/SpreadDamageWarhead.cs @@ -66,9 +66,8 @@ namespace OpenRA.Mods.Common.Warheads if (healthInfo == null) continue; - var localModifiers = damageModifiers; - var distance = Math.Max(0, (victim.CenterPosition - pos).Length - healthInfo.Radius.Length); - localModifiers = localModifiers.Append(GetDamageFalloff(distance)); + var distance = healthInfo.Shape.DistanceFromEdge(pos, victim); + var localModifiers = damageModifiers.Append(GetDamageFalloff(distance.Length)); DoImpact(victim, firedBy, localModifiers); } diff --git a/OpenRA.Mods.Common/WorldExtensions.cs b/OpenRA.Mods.Common/WorldExtensions.cs index 5015813b7c..979755341f 100644 --- a/OpenRA.Mods.Common/WorldExtensions.cs +++ b/OpenRA.Mods.Common/WorldExtensions.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common var actorWidth = 0; var healthInfo = currActor.Info.TraitInfoOrDefault(); if (healthInfo != null) - actorWidth = healthInfo.Radius.Length; + actorWidth = healthInfo.Shape.OuterRadius.Length; var projection = MinimumPointLineProjection(lineStart, lineEnd, currActor.CenterPosition); var distance = (currActor.CenterPosition - projection).HorizontalLength;