diff --git a/OpenRA.Game/Traits/Player/Shroud.cs b/OpenRA.Game/Traits/Player/Shroud.cs index 9a7b2e6bd3..b494e75927 100644 --- a/OpenRA.Game/Traits/Player/Shroud.cs +++ b/OpenRA.Game/Traits/Player/Shroud.cs @@ -186,20 +186,22 @@ namespace OpenRA.Traits Hash += 1; } - public static IEnumerable ProjectedCellsInRange(Map map, WPos pos, WDist range, int maxHeightDelta = -1) + public static IEnumerable ProjectedCellsInRange(Map map, WPos pos, WDist minRange, WDist maxRange, int maxHeightDelta = -1) { // Account for potential extra half-cell from odd-height terrain - var r = (range.Length + 1023 + 512) / 1024; - var limit = range.LengthSquared; + var r = (maxRange.Length + 1023 + 512) / 1024; + var minLimit = minRange.LengthSquared; + var maxLimit = maxRange.LengthSquared; // Project actor position into the shroud plane var projectedPos = pos - new WVec(0, pos.Z, pos.Z); var projectedCell = map.CellContaining(projectedPos); var projectedHeight = pos.Z / 512; - foreach (var c in map.FindTilesInCircle(projectedCell, r, true)) + foreach (var c in map.FindTilesInAnnulus(projectedCell, minRange.Length / 1024, r, true)) { - if ((map.CenterOfCell(c) - projectedPos).HorizontalLengthSquared <= limit) + var dist = (map.CenterOfCell(c) - projectedPos).HorizontalLengthSquared; + if (dist <= maxLimit && (dist == 0 || dist > minLimit)) { var puv = (PPos)c.ToMPos(map); if (maxHeightDelta < 0 || map.ProjectedHeight(puv) < projectedHeight + maxHeightDelta) @@ -210,7 +212,7 @@ namespace OpenRA.Traits public static IEnumerable ProjectedCellsInRange(Map map, CPos cell, WDist range, int maxHeightDelta = -1) { - return ProjectedCellsInRange(map, map.CenterOfCell(cell), range, maxHeightDelta); + return ProjectedCellsInRange(map, map.CenterOfCell(cell), WDist.Zero, range, maxHeightDelta); } public void AddSource(object key, SourceType type, PPos[] projectedCells) diff --git a/OpenRA.Mods.Common/Effects/RevealShroudEffect.cs b/OpenRA.Mods.Common/Effects/RevealShroudEffect.cs index dba6cdf389..8de19d75c2 100644 --- a/OpenRA.Mods.Common/Effects/RevealShroudEffect.cs +++ b/OpenRA.Mods.Common/Effects/RevealShroudEffect.cs @@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Effects if (range == WDist.Zero) return NoCells; - return Shroud.ProjectedCellsInRange(map, pos, range) + return Shroud.ProjectedCellsInRange(map, pos, WDist.Zero, range) .ToArray(); } diff --git a/OpenRA.Mods.Common/Traits/AffectsShroud.cs b/OpenRA.Mods.Common/Traits/AffectsShroud.cs index 6eb87e0c07..d7cc0c90e7 100644 --- a/OpenRA.Mods.Common/Traits/AffectsShroud.cs +++ b/OpenRA.Mods.Common/Traits/AffectsShroud.cs @@ -17,6 +17,8 @@ namespace OpenRA.Mods.Common.Traits { public abstract class AffectsShroudInfo : ConditionalTraitInfo { + public readonly WDist MinRange = WDist.Zero; + public readonly WDist Range = WDist.Zero; [Desc("If >= 0, prevent cells that are this much higher than the actor from being revealed.")] @@ -61,15 +63,16 @@ namespace OpenRA.Mods.Common.Traits PPos[] ProjectedCells(Actor self) { var map = self.World.Map; - var range = Range; - if (range == WDist.Zero) + var minRange = Info.MinRange; + var maxRange = Range; + if (maxRange <= minRange) return NoCells; if (Info.Type == VisibilityType.Footprint) { // PERF: Reuse collection to avoid allocations. footprint.UnionWith(self.OccupiesSpace.OccupiedCells() - .SelectMany(kv => Shroud.ProjectedCellsInRange(map, kv.First, range, Info.MaxHeightDelta))); + .SelectMany(kv => Shroud.ProjectedCellsInRange(map, map.CenterOfCell(kv.First), minRange, maxRange, Info.MaxHeightDelta))); var cells = footprint.ToArray(); footprint.Clear(); return cells; @@ -79,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits if (Info.Type == VisibilityType.GroundPosition) pos -= new WVec(WDist.Zero, WDist.Zero, self.World.Map.DistanceAboveTerrain(pos)); - return Shroud.ProjectedCellsInRange(map, pos, range, Info.MaxHeightDelta) + return Shroud.ProjectedCellsInRange(map, pos, minRange, maxRange, Info.MaxHeightDelta) .ToArray(); }