Refine civilian building placement and multibrushes

This commit is contained in:
Ashley Newson
2025-02-09 02:35:30 +00:00
committed by Gustas Kažukauskas
parent cc632660eb
commit 98fe3c98ab
12 changed files with 47 additions and 133 deletions

View File

@@ -338,7 +338,8 @@ namespace OpenRA.Mods.Common.MapGenerator
List<ActorPlan> actorPlans,
CellLayer<Replaceability> replace,
IReadOnlyList<MultiBrush> availableBrushes,
MersenneTwister random)
MersenneTwister random,
bool alwaysPreferLargerBrushes = false)
{
var brushesByAreaDict = new Dictionary<int, List<MultiBrush>>();
foreach (var brush in availableBrushes)
@@ -438,7 +439,7 @@ namespace OpenRA.Mods.Common.MapGenerator
var brushWeights = brushes.Select(o => o.Weight).ToArray();
var brushWeightForArea = brushWeights.Sum();
var remainingQuota =
brushArea == 1
(brushArea == 1 || alwaysPreferLargerBrushes)
? int.MaxValue
: (int)(((long)replaceMposes.Count * brushWeightForArea + brushTotalWeight - 1) / brushTotalWeight);
RefreshIndices();

View File

@@ -175,6 +175,8 @@ namespace OpenRA.Mods.Common.Traits
[FieldLoader.Require]
public readonly int CivilianBuildings = default;
[FieldLoader.Require]
public readonly int CivilianBuildingDensity = default;
[FieldLoader.Require]
public readonly int MinimumCivilianBuildingDensity = default;
[FieldLoader.Require]
public readonly int CivilianBuildingDensityRadius = default;
@@ -440,6 +442,8 @@ namespace OpenRA.Mods.Common.Traits
throw new MapGenerationException("MinimumBuildings must be <= maximumBuildings");
if (CivilianBuildings < 0 || CivilianBuildings > FractionMax)
throw new MapGenerationException($"CivilianBuildings must be between 0 and {FractionMax} inclusive");
if (CivilianBuildingDensity < 0 || CivilianBuildingDensity > FractionMax)
throw new MapGenerationException($"CivilianBuildingDensity must be between 0 and {FractionMax} inclusive");
if (MinimumCivilianBuildingDensity < 0 || MinimumCivilianBuildingDensity > FractionMax)
throw new MapGenerationException($"MinimumCivilianBuildingDensity must be between 0 and {FractionMax} inclusive");
if (CivilianBuildingDensityRadius < 0)
@@ -1679,13 +1683,26 @@ namespace OpenRA.Mods.Common.Traits
param.CivilianBuildingsFeatureSize,
wavelength => 1);
var densityNoise = new CellLayer<int>(map);
NoiseUtils.SymmetricFractalNoiseIntoCellLayer(
decorationRandom,
densityNoise,
param.Rotations,
param.Mirror,
1024,
NoiseUtils.PinkAmplitude);
CellLayerUtils.CalibrateQuantileInPlace(
densityNoise,
0,
FractionMax - param.CivilianBuildingDensity, FractionMax);
var decorable = new CellLayer<bool>(map);
var totalDecorable = 0;
foreach (var mpos in map.AllCells.MapCoords)
{
var isDecorable =
map.Tiles[mpos].Type == param.LandTile
&& zoneable[mpos] && space[mpos] && !reserved[mpos];
&& zoneable[mpos] && space[mpos] && !reserved[mpos] && densityNoise[mpos] >= 0;
decorable[mpos] = isDecorable;
if (isDecorable)
totalDecorable++;
@@ -1736,7 +1753,13 @@ namespace OpenRA.Mods.Common.Traits
foreach (var mpos in map.AllCells.MapCoords)
replace[mpos] = decorable[mpos] ? MultiBrush.Replaceability.Actor : MultiBrush.Replaceability.None;
MultiBrush.PaintArea(map, actorPlans, replace, param.CivilianBuildingsObstacles, decorationTilingRandom);
MultiBrush.PaintArea(
map,
actorPlans,
replace,
param.CivilianBuildingsObstacles,
decorationTilingRandom,
alwaysPreferLargerBrushes: true);
}
}