diff --git a/OpenRa.Game/BuildingInfluenceMap.cs b/OpenRa.Game/BuildingInfluenceMap.cs index 460fd9bdbd..07fa35061a 100644 --- a/OpenRa.Game/BuildingInfluenceMap.cs +++ b/OpenRa.Game/BuildingInfluenceMap.cs @@ -12,17 +12,14 @@ namespace OpenRa.Game class BuildingInfluenceMap { bool[,] blocked = new bool[128, 128]; - Pair[,] influence = new Pair[128, 128]; - readonly int maxDistance; /* clip limit for voronoi cells */ + Actor[,] influence = new Actor[128, 128]; static readonly Pair NoClaim = Pair.New((Actor)null, float.MaxValue); public BuildingInfluenceMap(int maxDistance) { - this.maxDistance = maxDistance; - for (int j = 0; j < 128; j++) for (int i = 0; i < 128; i++) - influence[i, j] = NoClaim; + influence[i, j] = null; Game.world.ActorAdded += a => { if (a.traits.Contains()) AddInfluence(a, a.traits.Get()); }; @@ -32,110 +29,24 @@ namespace OpenRa.Game void AddInfluence(Actor a, Traits.Building building) { - var tiles = Footprint.Tiles(a, building).ToArray(); - var min = int2.Max(new int2(0, 0), - tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); - var max = int2.Min(new int2(128, 128), - tiles.Aggregate(int2.Max) + new int2(maxDistance, maxDistance)); - - var pq = new PriorityQueue(); - - var initialTileCount = 0; - foreach (var u in Footprint.UnpathableTiles(building.unitInfo, a.Location)) if (IsValid(u)) blocked[u.X, u.Y] = true; - foreach (var t in tiles) - if (IsValid(t)) - { - pq.Add(new Cell { location = t, distance = 0, actor=a }); - ++initialTileCount; - } - - if (!building.unitInfo.BaseNormal) - { - while (!pq.Empty) - { - var c = pq.Pop(); - influence[c.location.X, c.location.Y].First = c.actor; - influence[c.location.X, c.location.Y].Second = 0; - } - return; - } - - Log.Write("Recalculating voronoi region for {{ {0} ({1},{2}) }}: {3} initial tiles", - a.unitInfo.Name, a.Location.X, a.Location.Y, initialTileCount); - - var updatedCells = 0; - - while (!pq.Empty) - { - var c = pq.Pop(); - - if (influence[c.location.X, c.location.Y].Second < c.distance) - continue; - - influence[c.location.X, c.location.Y].First = c.actor; - influence[c.location.X, c.location.Y].Second = c.distance; - - ++updatedCells; - - if (c.distance + 1 > maxDistance) continue; - - foreach (var d in Util.directions) - { - var e = c.location + d; - if (e.X < min.X || e.Y < min.Y || e.X > max.X || e.Y > max.Y) - continue; - - pq.Add(new Cell - { - location = e, - distance = c.distance + ((d.X * d.Y != 0) ? 1.414f : 1f), - actor = c.actor - }); - } - } - - Log.Write("Finished recalculating region. {0} cells updated.", updatedCells); + foreach (var u in Footprint.Tiles(building.unitInfo, a.Location, false)) + if (IsValid(u)) + influence[u.X, u.Y] = a; } void RemoveInfluence(Actor a, Traits.Building building) { - var tiles = Footprint.Tiles(a, building).ToArray(); - var min = int2.Max(new int2(0, 0), - tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); - var max = int2.Min(new int2(128, 128), - tiles.Aggregate(int2.Max) + new int2(maxDistance, maxDistance)); - foreach (var u in Footprint.UnpathableTiles(building.unitInfo, a.Location)) if (IsValid(u)) blocked[u.X, u.Y] = false; - - for (var j = min.Y; j <= max.Y; j++) - for (var i = min.X; i <= max.X; i++) - if (influence[i, j].First == a) - influence[i, j] = NoClaim; - // slightly expanded bounds for collecting candidates for recalculation. - var min2 = int2.Max(new int2(0, 0), min - new int2(1, 1)); - var max2 = int2.Min(new int2(128, 128), max + new int2(1, 1)); - - var actors = new List(); - for (var j = min2.Y; j <= max2.Y; j++) - for (var i = min2.X; i <= max2.X; i++) - if (influence[i, j].First != null && !actors.Contains(influence[i, j].First)) - actors.Add(influence[i, j].First); - - Log.Write("Finished collecting candidates for evacuated region = {0}", actors.Count); - - foreach( var b in actors ) - { - var bb = a.traits.GetOrDefault(); - if( bb != null ) - AddInfluence( b, bb ); - } + foreach (var u in Footprint.Tiles(building.unitInfo, a.Location, false)) + if (IsValid(u)) + influence[u.X, u.Y] = null; } bool IsValid(int2 t) @@ -145,38 +56,25 @@ namespace OpenRa.Game public Actor GetBuildingAt(int2 cell) { - if (!IsValid(cell) || influence[cell.X, cell.Y].Second != 0) - return null; - return influence[cell.X, cell.Y].First; + if (!IsValid(cell)) return null; + return influence[cell.X, cell.Y]; } public Actor GetNearestBuilding(int2 cell) { if (!IsValid(cell)) return null; - return influence[cell.X, cell.Y].First; + return influence[cell.X, cell.Y]; } public int GetDistanceToBuilding(int2 cell) { if (!IsValid(cell)) return int.MaxValue; - return (int)influence[cell.X, cell.Y].Second; + return influence[cell.X, cell.Y] == null ? int.MaxValue : 0; } public bool CanMoveHere(int2 cell) { return IsValid(cell) && !blocked[cell.X, cell.Y]; } - - struct Cell : IComparable - { - public int2 location; - public float distance; - public Actor actor; - - public int CompareTo(Cell other) - { - return distance.CompareTo(other.distance); - } - } } } diff --git a/OpenRa.Game/UiOverlay.cs b/OpenRa.Game/UiOverlay.cs index 76cc57127c..8c93e44060 100644 --- a/OpenRa.Game/UiOverlay.cs +++ b/OpenRa.Game/UiOverlay.cs @@ -49,13 +49,13 @@ namespace OpenRa.Game var maxDistance = bi.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */ - if( ShowBuildDebug ) - for( var j = 0 ; j < 128 ; j++ ) - for( var i = 0 ; i < 128 ; i++ ) - if( Game.GetDistanceToBase( new int2( i, j ), Game.LocalPlayer ) < maxDistance ) - if( Game.IsCellBuildable( new int2( i, j ), bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) ) - if( !Game.map.ContainsResource( new int2( i, j ) ) ) - spriteRenderer.DrawSprite( unitDebug, Game.CellSize * new float2( i, j ), 0 ); + //if( ShowBuildDebug ) + // for( var j = 0 ; j < 128 ; j++ ) + // for( var i = 0 ; i < 128 ; i++ ) + // if( Game.GetDistanceToBase( new int2( i, j ), Game.LocalPlayer ) < maxDistance ) + // if( Game.IsCellBuildable( new int2( i, j ), bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) ) + // if( !Game.map.ContainsResource( new int2( i, j ) ) ) + // spriteRenderer.DrawSprite( unitDebug, Game.CellSize * new float2( i, j ), 0 ); var tooFarFromBase = !Footprint.Tiles( bi, position ).Any( t => Game.GetDistanceToBase( t, Game.LocalPlayer ) < maxDistance );