From 3a8a8110bee6d18587ecfda6a704846166b18eae Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 26 Apr 2016 17:46:26 +0200 Subject: [PATCH 1/4] Extend CreateEffectWarhead's GetDirectHit to scan a WDist radius for hits Instead of only the impact cell. --- OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs index 6863f92587..98650a6b66 100644 --- a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs @@ -30,6 +30,9 @@ namespace OpenRA.Mods.Common.Warheads [Desc("Remap explosion effect to player color, if art supports it.")] public readonly bool UsePlayerPalette = false; + [Desc("Search radius around impact for 'direct hit' check.")] + public readonly WDist TargetSearchRadius = new WDist(2048); + [Desc("List of sounds that can be played on impact.")] public readonly string[] ImpactSounds = new string[0]; @@ -72,7 +75,7 @@ namespace OpenRA.Mods.Common.Warheads public bool GetDirectHit(World world, CPos cell, WPos pos, Actor firedBy, bool checkTargetType = false) { - foreach (var unit in world.ActorMap.GetActorsAt(cell)) + foreach (var unit in world.FindActorsInCircle(pos, TargetSearchRadius)) { if (checkTargetType && !IsValidAgainst(unit, firedBy)) continue; From fe7fe9b49bbd3a0594156787ce90121673790839 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 26 Apr 2016 18:01:19 +0200 Subject: [PATCH 2/4] Fix CreateEffectWarhead's HitShape distance check Originally, this was comparing distance beween pos and unit.CenterPosition with HitShape's OuterRadius. However, the OuterRadius can exceed the shape for Capsule and Rectangular shapes, so I tried to adress that a few months ago by using the DistanceFromEdge check instead. The approach was bogus, though. DistanceFromEdge just calculates the distance of a position to the edge, so by comparing it with the distance between pos and victim.CenterPosition in combination with using LengthSquared, it was entirely possible the explosion would be within the HitShape, but closer to the edge than the victim.CenterPosition and the check would return false. Now we just check if DistanceFromEdge is 0 or negative, which means the impact is inside the HitShape. --- OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs index 98650a6b66..ab60e4aa77 100644 --- a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs @@ -85,7 +85,7 @@ namespace OpenRA.Mods.Common.Warheads continue; // If the impact position is within any actor's HitShape, we have a direct hit - if ((unit.CenterPosition - pos).LengthSquared <= healthInfo.Shape.DistanceFromEdge(pos, unit).LengthSquared) + if (healthInfo.Shape.DistanceFromEdge(pos, unit).Length <= 0) return true; } From 3aa811bd2e9f72b35e1648ebdc085a0101bcf804 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 26 Apr 2016 18:02:08 +0200 Subject: [PATCH 3/4] Rename 'unit' to 'victim' in CEWH's GetDirectHit check --- OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs index ab60e4aa77..f7cb684c14 100644 --- a/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs @@ -75,17 +75,17 @@ namespace OpenRA.Mods.Common.Warheads public bool GetDirectHit(World world, CPos cell, WPos pos, Actor firedBy, bool checkTargetType = false) { - foreach (var unit in world.FindActorsInCircle(pos, TargetSearchRadius)) + foreach (var victim in world.FindActorsInCircle(pos, TargetSearchRadius)) { - if (checkTargetType && !IsValidAgainst(unit, firedBy)) + if (checkTargetType && !IsValidAgainst(victim, firedBy)) continue; - var healthInfo = unit.Info.TraitInfoOrDefault(); + var healthInfo = victim.Info.TraitInfoOrDefault(); if (healthInfo == null) continue; // If the impact position is within any actor's HitShape, we have a direct hit - if (healthInfo.Shape.DistanceFromEdge(pos, unit).Length <= 0) + if (healthInfo.Shape.DistanceFromEdge(pos, victim).Length <= 0) return true; } From 10dc6ca85c6952b22cf0e4b34e17e08abf7b0085 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 26 Apr 2016 18:48:41 +0200 Subject: [PATCH 4/4] CreateEffectWarhead.TargetSearchRadius lint check --- .../Lint/CheckTargetHealthRadius.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs b/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs index 7e88927503..cc6d46e3fe 100644 --- a/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs +++ b/OpenRA.Mods.Common/Lint/CheckTargetHealthRadius.cs @@ -47,7 +47,20 @@ namespace OpenRA.Mods.Common.Lint continue; 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}`!" + emitError("Actor type `{0}` has a health radius exceeding the victim scan radius of a SpreadDamageWarhead on `{1}`!" + .F(actorInfo.Key, weaponInfo.Key)); + } + + var effectWarheads = weaponInfo.Value.Warheads.OfType(); + + foreach (var warhead in effectWarheads) + { + // This warhead cannot affect this actor. + if (!warhead.ValidTargets.Overlaps(targetable)) + continue; + + if (healthTraits.Where(x => x.Shape.OuterRadius.Length > warhead.TargetSearchRadius.Length).Any()) + emitError("Actor type `{0}` has a health radius exceeding the victim scan radius of a CreateEffectWarhead on `{1}`!" .F(actorInfo.Key, weaponInfo.Key)); }