diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 14976530ef..320b636121 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -259,6 +259,7 @@ namespace OpenRA.Traits IEnumerable ActorsInBox(WPos a, WPos b); WDist LargestActorRadius { get; } + WDist LargestBlockingActorRadius { get; } } public interface IRenderModifier diff --git a/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs b/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs index 70d4af1b96..bb1a44c23e 100644 --- a/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs +++ b/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits public static bool AnyBlockingActorsBetween(World world, WPos start, WPos end, WDist width, out WPos hit) { - var actors = world.FindActorsOnLine(start, end, width); + var actors = world.FindBlockingActorsOnLine(start, end, width); var length = (end - start).Length; foreach (var a in actors) diff --git a/OpenRA.Mods.Common/Traits/World/ActorMap.cs b/OpenRA.Mods.Common/Traits/World/ActorMap.cs index 8fa241cf47..7547d41b10 100644 --- a/OpenRA.Mods.Common/Traits/World/ActorMap.cs +++ b/OpenRA.Mods.Common/Traits/World/ActorMap.cs @@ -184,6 +184,7 @@ namespace OpenRA.Mods.Common.Traits readonly Predicate actorShouldBeRemoved; public WDist LargestActorRadius { get; private set; } + public WDist LargestBlockingActorRadius { get; private set; } public ActorMap(World world, ActorMapInfo info) { @@ -202,6 +203,8 @@ namespace OpenRA.Mods.Common.Traits actorShouldBeRemoved = removeActorPosition.Contains; LargestActorRadius = map.Rules.Actors.SelectMany(a => a.Value.TraitInfos()).Max(h => h.Type.OuterRadius); + var blockers = map.Rules.Actors.Where(a => a.Value.HasTraitInfo()); + LargestBlockingActorRadius = blockers.Any() ? blockers.SelectMany(a => a.Value.TraitInfos()).Max(h => h.Type.OuterRadius) : WDist.Zero; } void INotifyCreated.Created(Actor self) diff --git a/OpenRA.Mods.Common/WorldExtensions.cs b/OpenRA.Mods.Common/WorldExtensions.cs index 77c957e353..cdb1a91a72 100644 --- a/OpenRA.Mods.Common/WorldExtensions.cs +++ b/OpenRA.Mods.Common/WorldExtensions.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common /// The position the line should end at /// How close an actor's health radius needs to be to the line to be considered 'intersected' by the line /// A list of all the actors intersected by the line - public static IEnumerable FindActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth) + public static IEnumerable FindActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth, bool onlyBlockers = false) { // This line intersection check is done by first just finding all actors within a square that starts at the source, and ends at the target. // Then we iterate over this list, and find all actors for which their health radius is at least within lineWidth of the line. @@ -39,7 +39,8 @@ namespace OpenRA.Mods.Common var yDir = yDiff < 0 ? -1 : 1; var dir = new WVec(xDir, yDir, 0); - var overselect = dir * (1024 + lineWidth.Length + world.ActorMap.LargestActorRadius.Length); + var largestValidActorRadius = onlyBlockers ? world.ActorMap.LargestBlockingActorRadius.Length : world.ActorMap.LargestActorRadius.Length; + var overselect = dir * (1024 + lineWidth.Length + largestValidActorRadius); var finalTarget = lineEnd + overselect; var finalSource = lineStart - overselect; @@ -64,6 +65,11 @@ namespace OpenRA.Mods.Common return intersectedActors; } + public static IEnumerable FindBlockingActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth) + { + return world.FindActorsOnLine(lineStart, lineEnd, lineWidth, true); + } + /// /// Finds all the actors of which their health radius is intersected by a specified circle. ///