Merge pull request #10943 from pchote/map-grid-tile-range
Move Map.TilesByDistance to MapGrid and un-static it.
This commit is contained in:
@@ -70,7 +70,6 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public const int SupportedMapFormat = 10;
|
public const int SupportedMapFormat = 10;
|
||||||
|
|
||||||
public const int MaxTilesInCircleRange = 50;
|
|
||||||
public readonly MapGrid Grid;
|
public readonly MapGrid Grid;
|
||||||
readonly ModData modData;
|
readonly ModData modData;
|
||||||
|
|
||||||
@@ -1102,47 +1101,6 @@ namespace OpenRA
|
|||||||
return new WDist(Math.Min(x, y) * dir.Length);
|
return new WDist(Math.Min(x, y) * dir.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly CVec[][] TilesByDistance = InitTilesByDistance(MaxTilesInCircleRange);
|
|
||||||
|
|
||||||
static CVec[][] InitTilesByDistance(int max)
|
|
||||||
{
|
|
||||||
var ts = new List<CVec>[max + 1];
|
|
||||||
for (var i = 0; i < max + 1; i++)
|
|
||||||
ts[i] = new List<CVec>();
|
|
||||||
|
|
||||||
for (var j = -max; j <= max; j++)
|
|
||||||
for (var i = -max; i <= max; i++)
|
|
||||||
if (max * max >= i * i + j * j)
|
|
||||||
ts[Exts.ISqrt(i * i + j * j, Exts.ISqrtRoundMode.Ceiling)].Add(new CVec(i, j));
|
|
||||||
|
|
||||||
// Sort each integer-distance group by the actual distance
|
|
||||||
foreach (var list in ts)
|
|
||||||
{
|
|
||||||
list.Sort((a, b) =>
|
|
||||||
{
|
|
||||||
var result = a.LengthSquared.CompareTo(b.LengthSquared);
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// If the lengths are equal, use other means to sort them.
|
|
||||||
// Try the hash code first because it gives more
|
|
||||||
// random-appearing results than X or Y that would always
|
|
||||||
// prefer the leftmost/topmost position.
|
|
||||||
result = a.GetHashCode().CompareTo(b.GetHashCode());
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
result = a.X.CompareTo(b.X);
|
|
||||||
if (result != 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return a.Y.CompareTo(b.Y);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.Select(list => list.ToArray()).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both ranges are inclusive because everything that calls it is designed for maxRange being inclusive:
|
// Both ranges are inclusive because everything that calls it is designed for maxRange being inclusive:
|
||||||
// it rounds the actual distance up to the next integer so that this call
|
// it rounds the actual distance up to the next integer so that this call
|
||||||
// will return any cells that intersect with the requested range circle.
|
// will return any cells that intersect with the requested range circle.
|
||||||
@@ -1152,8 +1110,9 @@ namespace OpenRA
|
|||||||
if (maxRange < minRange)
|
if (maxRange < minRange)
|
||||||
throw new ArgumentOutOfRangeException("maxRange", "Maximum range is less than the minimum range.");
|
throw new ArgumentOutOfRangeException("maxRange", "Maximum range is less than the minimum range.");
|
||||||
|
|
||||||
if (maxRange >= TilesByDistance.Length)
|
if (maxRange >= Grid.TilesByDistance.Length)
|
||||||
throw new ArgumentOutOfRangeException("maxRange", "The requested range ({0}) exceeds the maximum allowed ({1})".F(maxRange, MaxTilesInCircleRange));
|
throw new ArgumentOutOfRangeException("maxRange",
|
||||||
|
"The requested range ({0}) cannot exceed the value of MaximumTileSearchRange ({1})".F(maxRange, Grid.MaximumTileSearchRange));
|
||||||
|
|
||||||
Func<CPos, bool> valid = Contains;
|
Func<CPos, bool> valid = Contains;
|
||||||
if (allowOutsideBounds)
|
if (allowOutsideBounds)
|
||||||
@@ -1161,7 +1120,7 @@ namespace OpenRA
|
|||||||
|
|
||||||
for (var i = minRange; i <= maxRange; i++)
|
for (var i = minRange; i <= maxRange; i++)
|
||||||
{
|
{
|
||||||
foreach (var offset in TilesByDistance[i])
|
foreach (var offset in Grid.TilesByDistance[i])
|
||||||
{
|
{
|
||||||
var t = offset + center;
|
var t = offset + center;
|
||||||
if (valid(t))
|
if (valid(t))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -25,6 +26,8 @@ namespace OpenRA
|
|||||||
public readonly byte MaximumTerrainHeight = 0;
|
public readonly byte MaximumTerrainHeight = 0;
|
||||||
public readonly SubCell DefaultSubCell = (SubCell)byte.MaxValue;
|
public readonly SubCell DefaultSubCell = (SubCell)byte.MaxValue;
|
||||||
|
|
||||||
|
public readonly int MaximumTileSearchRange = 50;
|
||||||
|
|
||||||
public readonly WVec[] SubCellOffsets =
|
public readonly WVec[] SubCellOffsets =
|
||||||
{
|
{
|
||||||
new WVec(0, 0, 0), // full cell - index 0
|
new WVec(0, 0, 0), // full cell - index 0
|
||||||
@@ -73,6 +76,8 @@ namespace OpenRA
|
|||||||
new[] { 0, 1, 0, 1 }
|
new[] { 0, 1, 0, 1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal readonly CVec[][] TilesByDistance;
|
||||||
|
|
||||||
public MapGrid(MiniYaml yaml)
|
public MapGrid(MiniYaml yaml)
|
||||||
{
|
{
|
||||||
FieldLoader.Load(this, yaml);
|
FieldLoader.Load(this, yaml);
|
||||||
@@ -95,6 +100,47 @@ namespace OpenRA
|
|||||||
rightDelta + new WVec(0, 0, 512 * ramp[2]),
|
rightDelta + new WVec(0, 0, 512 * ramp[2]),
|
||||||
bottomDelta + new WVec(0, 0, 512 * ramp[3])
|
bottomDelta + new WVec(0, 0, 512 * ramp[3])
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
|
TilesByDistance = CreateTilesByDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
CVec[][] CreateTilesByDistance()
|
||||||
|
{
|
||||||
|
var ts = new List<CVec>[MaximumTileSearchRange + 1];
|
||||||
|
for (var i = 0; i < MaximumTileSearchRange + 1; i++)
|
||||||
|
ts[i] = new List<CVec>();
|
||||||
|
|
||||||
|
for (var j = -MaximumTileSearchRange; j <= MaximumTileSearchRange; j++)
|
||||||
|
for (var i = -MaximumTileSearchRange; i <= MaximumTileSearchRange; i++)
|
||||||
|
if (MaximumTileSearchRange * MaximumTileSearchRange >= i * i + j * j)
|
||||||
|
ts[Exts.ISqrt(i * i + j * j, Exts.ISqrtRoundMode.Ceiling)].Add(new CVec(i, j));
|
||||||
|
|
||||||
|
// Sort each integer-distance group by the actual distance
|
||||||
|
foreach (var list in ts)
|
||||||
|
{
|
||||||
|
list.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
var result = a.LengthSquared.CompareTo(b.LengthSquared);
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// If the lengths are equal, use other means to sort them.
|
||||||
|
// Try the hash code first because it gives more
|
||||||
|
// random-appearing results than X or Y that would always
|
||||||
|
// prefer the leftmost/topmost position.
|
||||||
|
result = a.GetHashCode().CompareTo(b.GetHashCode());
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = a.X.CompareTo(b.X);
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return a.Y.CompareTo(b.Y);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts.Select(list => list.ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WVec OffsetOfSubCell(SubCell subCell)
|
public WVec OffsetOfSubCell(SubCell subCell)
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ namespace OpenRA.Mods.Common.AI
|
|||||||
return findPos(baseCenter, baseCenter, Info.MinBaseRadius, Info.MaxBaseRadius);
|
return findPos(baseCenter, baseCenter, Info.MinBaseRadius, Info.MaxBaseRadius);
|
||||||
|
|
||||||
case BuildingType.Building:
|
case BuildingType.Building:
|
||||||
return findPos(baseCenter, baseCenter, Info.MinBaseRadius, distanceToBaseIsImportant ? Info.MaxBaseRadius : Map.MaxTilesInCircleRange);
|
return findPos(baseCenter, baseCenter, Info.MinBaseRadius, distanceToBaseIsImportant ? Info.MaxBaseRadius : Map.Grid.MaximumTileSearchRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't find a build location
|
// Can't find a build location
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public class Teleport : Activity
|
public class Teleport : Activity
|
||||||
{
|
{
|
||||||
const int MaxCellSearchRange = Map.MaxTilesInCircleRange;
|
|
||||||
readonly Actor teleporter;
|
readonly Actor teleporter;
|
||||||
readonly int? maximumDistance;
|
readonly int? maximumDistance;
|
||||||
CPos destination;
|
CPos destination;
|
||||||
@@ -32,8 +31,9 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
public Teleport(Actor teleporter, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
|
public Teleport(Actor teleporter, CPos destination, int? maximumDistance, bool killCargo, bool screenFlash, string sound)
|
||||||
{
|
{
|
||||||
if (maximumDistance > MaxCellSearchRange)
|
var max = teleporter.World.Map.Grid.MaximumTileSearchRange;
|
||||||
throw new InvalidOperationException("Teleport cannot be used with a maximum teleport distance greater than {0}.".F(MaxCellSearchRange));
|
if (maximumDistance > max)
|
||||||
|
throw new InvalidOperationException("Teleport distance cannot exceed the value of MaximumTileSearchRange ({0}).".F(max));
|
||||||
|
|
||||||
this.teleporter = teleporter;
|
this.teleporter = teleporter;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
@@ -114,7 +114,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
if (pos.CanEnterCell(destination) && teleporter.Owner.Shroud.IsExplored(destination))
|
if (pos.CanEnterCell(destination) && teleporter.Owner.Shroud.IsExplored(destination))
|
||||||
return destination;
|
return destination;
|
||||||
|
|
||||||
var max = maximumDistance != null ? maximumDistance.Value : MaxCellSearchRange;
|
var max = maximumDistance != null ? maximumDistance.Value : teleporter.World.Map.Grid.MaximumTileSearchRange;
|
||||||
foreach (var tile in self.World.Map.FindTilesInCircle(destination, max))
|
foreach (var tile in self.World.Map.FindTilesInCircle(destination, max))
|
||||||
{
|
{
|
||||||
if (teleporter.Owner.Shroud.IsExplored(tile)
|
if (teleporter.Owner.Shroud.IsExplored(tile)
|
||||||
|
|||||||
Reference in New Issue
Block a user