这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions OpenRA.Mods.Common/Lint/CheckMultiBrushes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ public void Run(Action<string> emitError, Action<string> emitWarning, ModData mo
// Includes validation of actor types and template IDs.
var multiBrush = new MultiBrush(map, info);

// Validates there is at least something in the MultiBrush.
multiBrush.Contract();

foreach (var (_, tile) in multiBrush.Tiles)
if (!templatedTerrainInfo.TryGetTerrainInfo(tile, out var _))
emitError($"Tileset {terrainInfoName} has invalid MultiBrush collection `{collectionName}`: tileset does not have tile {tile.Type},{tile.Index}");
Expand Down
32 changes: 19 additions & 13 deletions OpenRA.Mods.Common/MapGenerator/MapGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,29 @@ public enum UiType
public sealed class Choice
{
/// <summary>Uniquely identifies a Choice within an Option.</summary>
[FieldLoader.Ignore]
public readonly string Id;

/// <summary>The label to use for UI selection. Post-fluent.</summary>
[FieldLoader.Ignore]
public readonly string Label = null;

/// <summary>Only offer the Choice for this tileset. (If null, show for all.)</summary>
public readonly string Tileset = null;
/// <summary>
/// Only offer the Choice for these tilesets. (If null, show for all.)
/// </summary>
public readonly IReadOnlySet<string> Tileset = null;

/// <summary>(Partial) settings to combine into the final overall settings.</summary>
[FieldLoader.LoadUsing(nameof(SettingsLoader))]
public readonly MiniYaml Settings;

public Choice(string id, MiniYaml my)
{
Id = id;
FieldLoader.Load(this, my);
var label = my.NodeWithKeyOrDefault("Label")?.Value.Value;
if (label != null)
Label = FluentProvider.GetMessage(label);
Tileset = my.NodeWithKeyOrDefault("Tileset")?.Value.Value
?.Split(',')
.ToImmutableHashSet();
Settings = my.NodeWithKey("Settings").Value;
}

/// <summary>Create a choice that represents a top-level setting with a given value.</summary>
Expand All @@ -72,12 +74,10 @@ public static void DumpFluent(MiniYaml my, List<string> references)
references.Add(label);
}

static MiniYaml SettingsLoader(MiniYaml my) => my.NodeWithKey("Settings").Value;

/// <summary>Check whether this choice is permitted for this map.</summary>
public bool Allowed(Map map)
{
if (Tileset != null && map.Tileset != Tileset)
if (Tileset != null && !Tileset.Contains(map.Tileset))
return false;

return true;
Expand Down Expand Up @@ -208,12 +208,18 @@ public Option(string id, MiniYaml my, Map map)

if (Choices.Count > 0)
{
var defaultNode = my.NodeWithKeyOrDefault("Default");
if (defaultNode != null)
var defaultOrder = my.NodeWithKeyOrDefault("Default")?.Value.Value;
if (defaultOrder != null)
{
Default = Choices.FirstOrDefault(choice => choice.Id == defaultNode.Value.Value);
foreach (var defaultChoice in defaultOrder.Split(','))
{
Default = Choices.FirstOrDefault(choice => choice.Id == defaultChoice);
if (Default != null)
break;
}

if (Default == null)
throw new YamlException($"Option `{id}` default choice `{defaultNode.Value.Value}` is not valid");
throw new YamlException($"None of option `{id}`'s default choices `{defaultOrder}` are not valid");
}
else
{
Expand Down
7 changes: 5 additions & 2 deletions OpenRA.Mods.Common/MapGenerator/MultiBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public Replaceability Contract()
else if (!hasTiles && hasActorPlans)
return Replaceability.Actor;
else
throw new ArgumentException("MultiBrush has no tiles or actors");
return Replaceability.None;
}

/// <summary>
Expand Down Expand Up @@ -190,7 +190,10 @@ void UpdateShape()
foreach (var cpos in actorPlan.Footprint().Keys)
xys.Add(new CVec(cpos.X, cpos.Y));

shape = xys.OrderBy(xy => (xy.Y, xy.X)).ToArray();
if (xys.Count != 0)
shape = xys.OrderBy(xy => (xy.Y, xy.X)).ToArray();
else
shape = new[] { new CVec(0, 0) };
}

/// <summary>
Expand Down
26 changes: 26 additions & 0 deletions OpenRA.Mods.Common/Traits/World/RaMapGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ sealed class Parameters
public readonly IReadOnlyList<MultiBrush> ForestObstacles;
[FieldLoader.Ignore]
public readonly IReadOnlyList<MultiBrush> UnplayableObstacles;
[FieldLoader.Ignore]
public readonly IReadOnlyDictionary<ushort, IReadOnlyList<MultiBrush>> RepaintTiles;

[FieldLoader.Ignore]
public readonly IReadOnlyDictionary<string, ResourceTypeInfo> ResourceTypes;
Expand Down Expand Up @@ -221,6 +223,16 @@ public Parameters(Map map, MiniYaml my)
TemplatedTerrainInfo = Map.Rules.TerrainInfo as ITemplatedTerrainInfo;
ForestObstacles = MultiBrush.LoadCollection(map, my.NodeWithKey("ForestObstacles").Value.Value);
UnplayableObstacles = MultiBrush.LoadCollection(map, my.NodeWithKey("UnplayableObstacles").Value.Value);
RepaintTiles = my.NodeWithKeyOrDefault("RepaintTiles")?.Value.ToDictionary(
k =>
{
if (Exts.TryParseUshortInvariant(k, out var tile))
return tile;
else
throw new YamlException($"RepaintTile {k} is not a ushort");
},
v => MultiBrush.LoadCollection(map, v.Value) as IReadOnlyList<MultiBrush>);
RepaintTiles ??= ImmutableDictionary<ushort, IReadOnlyList<MultiBrush>>.Empty;

ResourceTypes = map.Rules.Actors[SystemActors.World].TraitInfoOrDefault<ResourceLayerInfo>().ResourceTypes;
if (!ResourceTypes.TryGetValue(my.NodeWithKey("DefaultResource").Value.Value, out DefaultResource))
Expand Down Expand Up @@ -559,6 +571,7 @@ public void Generate(Map map, MiniYaml settings)
var expansionRandom = new MersenneTwister(random.Next());
var buildingRandom = new MersenneTwister(random.Next());
var topologyRandom = new MersenneTwister(random.Next());
var repaintRandom = new MersenneTwister(random.Next());

TerrainTile PickTile(ushort tileType)
{
Expand Down Expand Up @@ -1601,6 +1614,19 @@ int AddResource(CPos cpos)
}
}

// Cosmetically repaint tiles
foreach (var (tile, collection) in param.RepaintTiles.OrderBy(kv => kv.Key))
{
var replace = new CellLayer<MultiBrush.Replaceability>(map);
foreach (var mpos in replace.CellRegion.MapCoords)
replace[mpos] =
map.Tiles[mpos].Type == tile
? MultiBrush.Replaceability.Any
: MultiBrush.Replaceability.None;

MultiBrush.PaintArea(map, actorPlans, replace, collection, repaintRandom);
}

map.PlayerDefinitions = new MapPlayers(map.Rules, 0).ToMiniYaml();
map.ActorDefinitions = actorPlans
.Select((plan, i) => new MiniYamlNode($"Actor{i}", plan.Reference.Save()))
Expand Down
65 changes: 65 additions & 0 deletions mods/cnc/fluent/rules.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ faction-nod =
and the alien substance Tiberium. They use stealth technology
and guerilla tactics to defeat those who oppose them.

map-generator-ra = RA Experimental (CnC)
map-generator-clear = Clear

## defaults.yaml
notification-unit-lost = Unit lost.
notification-unit-promoted = Unit promoted.
Expand Down Expand Up @@ -776,3 +779,65 @@ bot-watson =

bot-hal9001 =
.name = HAL 9001

## map-generators.yaml
label-clear-map-generator-option-tile = Tile
label-clear-map-generator-choice-tile-clear = Clear
label-clear-map-generator-choice-tile-water = Water

label-cnc-map-generator-option-seed = Seed

label-cnc-map-generator-option-terrain-type = Terrain Type
label-cnc-map-generator-choice-terrain-type-lakes = Lakes
label-cnc-map-generator-choice-terrain-type-puddles = Puddles
label-cnc-map-generator-choice-terrain-type-gardens = Gardens
label-cnc-map-generator-choice-terrain-type-plains = Plains
label-cnc-map-generator-choice-terrain-type-parks = Parks
label-cnc-map-generator-choice-terrain-type-woodlands = Woodlands
label-cnc-map-generator-choice-terrain-type-overgrown = Overgrown
label-cnc-map-generator-choice-terrain-type-rocky = Rocky
label-cnc-map-generator-choice-terrain-type-mountains = Mountains
label-cnc-map-generator-choice-terrain-type-mountain-lakes = Mountain Lakes

label-cnc-map-generator-option-rotations = Rotations

label-cnc-map-generator-option-mirror = Mirror
label-cnc-map-generator-choice-mirror-none = None
label-cnc-map-generator-choice-mirror-left-matches-right = Left vs right
label-cnc-map-generator-choice-mirror-top-left-matches-bottom-right = Top left vs bottom right
label-cnc-map-generator-choice-mirror-top-matches-bottom = Top vs bottom
label-cnc-map-generator-choice-mirror-top-right-matches-bottom-left = Top right vs bottom left

label-cnc-map-generator-option-shape = Bounds Shape
label-cnc-map-generator-choice-shape-square = Square
label-cnc-map-generator-choice-shape-circle-mountain = Circle in mountains
label-cnc-map-generator-choice-shape-circle-water = Circle in water

label-cnc-map-generator-option-players = Players per side

label-cnc-map-generator-option-resources = Resources
label-cnc-map-generator-choice-resources-none = None
label-cnc-map-generator-choice-resources-low = Low
label-cnc-map-generator-choice-resources-medium = Medium
label-cnc-map-generator-choice-resources-high = High
label-cnc-map-generator-choice-resources-very-high = Very High
label-cnc-map-generator-choice-resources-full = Oreful

label-cnc-map-generator-option-buildings = Buildings
label-cnc-map-generator-choice-buildings-none = None
label-cnc-map-generator-choice-buildings-standard = Standard
label-cnc-map-generator-choice-buildings-extra = Extra
label-cnc-map-generator-choice-buildings-oil-only = Oil Only
label-cnc-map-generator-choice-buildings-oil-rush = Oil Rush

label-cnc-map-generator-option-density = Entity Density
label-cnc-map-generator-choice-density-players = Scale with players
label-cnc-map-generator-choice-density-area-and-players = Scale with area and players
label-cnc-map-generator-choice-density-area-very-low = Scale with area (very low density)
label-cnc-map-generator-choice-density-area-low = Scale with area (low density)
label-cnc-map-generator-choice-density-area-medium = Scale with area (medium density)
label-cnc-map-generator-choice-density-area-high = Scale with area (high density)
label-cnc-map-generator-choice-density-area-very-high = Scale with area (very high density)

label-cnc-map-generator-option-roads = Roads
label-cnc-map-generator-option-deny-walled-areas = Obstruct walled areas
1 change: 1 addition & 0 deletions mods/cnc/mod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Rules:
cnc|rules/ships.yaml
cnc|rules/aircraft.yaml
cnc|rules/husks.yaml
cnc|rules/map-generators.yaml

Sequences:
cnc|sequences/structures.yaml
Expand Down
Loading