Fix various map generator bounds and size related issues

- If generating a RectangularIsometric map via lobby, make the height
  twice the width so that the map is approximately world-square.
- Use equal top and bottom cordons for RectangularIsometric maps.
- Change some map bounds checking.
- Check that actors are at least partially inside map.Contains before
  placing. (To avoid frozen actor crashes.)
- Fix editor generated map blitting for RectangularIsometric.
This commit is contained in:
Ashley Newson
2025-11-09 00:05:21 +00:00
committed by Gustas Kažukauskas
parent 915ad36ddc
commit 91ddfd6fc1
4 changed files with 36 additions and 11 deletions

View File

@@ -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
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// Zone based on Map.Bounds.Contains. This is stricter than Map.Contains, ignoring height.
/// </summary>
public void ZoneFromOutOfBounds<T>(CellLayer<T> 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(

View File

@@ -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);

View File

@@ -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,

View File

@@ -234,9 +234,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
void RandomizeSize()
{
var mapGrid = modData.Manifest.Get<MapGrid>();
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()