diff --git a/OpenRA.Mods.Common/MapGenerator/Terraformer.cs b/OpenRA.Mods.Common/MapGenerator/Terraformer.cs
index 67068c009a..75ca8e2ffe 100644
--- a/OpenRA.Mods.Common/MapGenerator/Terraformer.cs
+++ b/OpenRA.Mods.Common/MapGenerator/Terraformer.cs
@@ -176,7 +176,7 @@ namespace OpenRA.Mods.Common.MapGenerator
{
var maxTerrainHeight = Map.Grid.MaximumTerrainHeight;
var tl = new PPos(1, 1 + maxTerrainHeight);
- var br = new PPos(Map.MapSize.Width - 2, Map.MapSize.Height + maxTerrainHeight - 2);
+ var br = new PPos(Map.MapSize.Width - 2, Map.MapSize.Height - maxTerrainHeight - 2);
Map.SetBounds(tl, br);
Map.Title = MapGenerationArgs.Title;
Map.Author = MapGenerationArgs.Author;
@@ -185,12 +185,26 @@ namespace OpenRA.Mods.Common.MapGenerator
///
/// Commits draft data to the map, such as player and actor definitions.
+ /// This may trigger some initialization of map data structures that could become invalid
+ /// if further edits to the map are made.
///
public void BakeMap()
{
var playerCount = ActorsOfType("mpspawn").Count();
Map.PlayerDefinitions = new MapPlayers(Map.Rules, playerCount).ToMiniYaml();
+
+ // Return true iff any of the actors projected footprint satisfies Map.Contains(PPos).
+ // Note that this is not the same as Map.Tiles.Contains or Map.Bounds.Contains.
+ // Note that calling this initializes cell projections.
+ bool HasProjectedFootprintInMap(ActorPlan plan)
+ {
+ return plan.Footprint()
+ .SelectMany(f => Map.ProjectedCellsCovering(f.Key.ToMPos(Map)))
+ .Any(Map.Contains);
+ }
+
Map.ActorDefinitions = ActorPlans
+ .Where(HasProjectedFootprintInMap)
.Select((plan, i) => new MiniYamlNode($"Actor{i}", plan.Reference.Save()))
.ToImmutableArray();
}
@@ -261,10 +275,13 @@ namespace OpenRA.Mods.Common.MapGenerator
zoneable[mpos] = value;
}
+ ///
+ /// Zone based on Map.Bounds.Contains. This is stricter than Map.Contains, ignoring height.
+ ///
public void ZoneFromOutOfBounds(CellLayer zoneable, T value)
{
foreach (var mpos in Map.AllCells.MapCoords)
- if (!Map.Contains(mpos))
+ if (!Map.Bounds.Contains(mpos.U, mpos.V))
zoneable[mpos] = value;
}
@@ -1687,10 +1704,10 @@ namespace OpenRA.Mods.Common.MapGenerator
throw new ArgumentException("fillSide was not In or Out");
var notFillSide = fillSide == Side.In ? Side.Out : Side.In;
- var fillSeeds = CellLayerUtils.Create(Map, (MPos mpos) =>
+ var fillSeeds = CellLayerUtils.Create(Map, mpos =>
sides[mpos] == fillSide &&
!mask[mpos] &&
- Map.Contains(mpos));
+ Map.Bounds.Contains(mpos.U, mpos.V));
fillSeeds = ImproveSymmetry(fillSeeds, false, (a, b) => a || b);
var fillable = CellLayerUtils.Map(sides, side => side != notFillSide);
CellLayerUtils.SimpleFloodFill(
diff --git a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
index 740766a9e1..437a1d5a58 100644
--- a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
+++ b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs
@@ -747,7 +747,7 @@ namespace OpenRA.Mods.Common.Traits
var replace = PlayableToReplaceable();
foreach (var mpos in map.AllCells.MapCoords)
- if (playable[mpos] || !map.Contains(mpos))
+ if (playable[mpos] || !map.Bounds.Contains(mpos.U, mpos.V))
replace[mpos] = MultiBrush.Replaceability.None;
terraformer.PaintArea(debrisTilingRandom, replace, param.UnplayableObstacles);
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/MapGeneratorToolLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/MapGeneratorToolLogic.cs
index 1497c84817..211b745208 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Editor/MapGeneratorToolLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/MapGeneratorToolLogic.cs
@@ -261,8 +261,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var map = world.Map;
var terrainInfo = modData.DefaultTerrainInfo[map.Tileset];
- var size = new Size(map.Bounds.Width + 2, map.Bounds.Height + 2);
- var args = settings.Compile(terrainInfo, size);
+ var args = settings.Compile(terrainInfo, map.MapSize);
// Run main generator logic. May throw.
var generateStopwatch = Stopwatch.StartNew();
@@ -301,12 +300,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
previews.Add(kv.Key, preview);
}
- var offset = map.CellContaining(map.ProjectedTopLeft) - generatedMap.CellContaining(generatedMap.ProjectedTopLeft);
- var blitSource = new EditorBlitSource(generatedMap.AllCells, previews, tiles);
+ var cellBounds = CellLayerUtils.CellBounds(map);
+ var topLeft = new CPos(cellBounds.TopLeft.X, cellBounds.TopLeft.Y);
+ var bottomRight = new CPos(cellBounds.BottomRight.X, cellBounds.BottomRight.Y);
+ var cellRegion = new CellRegion(map.Grid.Type, topLeft, bottomRight);
+ var blitSource = new EditorBlitSource(cellRegion, previews, tiles);
var editorBlit = new EditorBlit(
MapBlitFilters.All,
resourceLayer,
- new CPos(offset.X, offset.Y),
+ topLeft,
map,
blitSource,
editorActorLayer,
diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs
index 3622081bf9..9fb859bd4f 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs
@@ -234,9 +234,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
void RandomizeSize()
{
+ var mapGrid = modData.Manifest.Get();
var sizeRange = MapSizes[selectedSize];
var width = Game.CosmeticRandom.Next(sizeRange.X, sizeRange.Y);
- size = new Size(width + 2, width + 2);
+ var height =
+ mapGrid.Type == MapGridType.RectangularIsometric
+ ? width * 2
+ : width;
+
+ size = new Size(width + 2, height + mapGrid.MaximumTerrainHeight * 2 + 2);
}
void RefreshSettings()