From 37e5b0d74c2e09e7947b9758c6926850ba59b53a Mon Sep 17 00:00:00 2001 From: Ashley Newson Date: Sun, 16 Mar 2025 03:14:12 +0000 Subject: [PATCH] Fix CnC generated map oceans becoming debris-filled Water is not playable in CnC, so, the map generator may fill it in if it's not attributed to the largest playable region. This would often happen for circular-in-water maps when DenyWalledAreas is enabled. This change adds a step to adopt any neighboring partially playable space (such as beaches and water) into the largest region, which is exempt from debris filling. The change is almost purely cosmetic, though the previous debris filling could slightly reduce playable space (due to filling playable beach tiles), possibly causing generation to fail. As such, map generation is now a very tiny bit more reliable. --- .../Traits/World/ExperimentalMapGenerator.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs index 0b7a810d9a..18c0757d0d 100644 --- a/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs +++ b/OpenRA.Mods.Common/Traits/World/ExperimentalMapGenerator.cs @@ -1013,6 +1013,26 @@ namespace OpenRA.Mods.Common.Traits if (largest.PlayableArea < minimumPlayableSpace) throw new MapGenerationException("playable space is too small"); + bool? AdoptPartiallyPlayableIntoLargest(CPos cpos, bool first) + { + if (first) + return false; + else if (regionMask[cpos] == largest.Id || playability[cpos] != PlayableSpace.Playability.Partial) + return null; + + regionMask[cpos] = largest.Id; + largest.Area++; + return false; + } + + // Adopt any partially playable tiles connected to the largest region into the largest region. + // This avoids potentially debris-filling connected oceans for mods where water is unplayable. + CellLayerUtils.FloodFill( + regionMask, + map.AllCells.Where(cpos => regionMask[cpos] == largest.Id).Select(cpos => (cpos, true)), + AdoptPartiallyPlayableIntoLargest, + Direction.Spread4CVec); + if (param.DenyWalledAreas) { // Beach tiles are particularly problematic. If they're for unplayable bodies