Initial commit: OpenRA game engine
Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AddColorPickerValueRange : UpdateRule
|
||||
{
|
||||
public override string Name => "ColorPickerManager's PresetHues, PresetSaturations and V were replaced with PresetColors.";
|
||||
|
||||
public override string Description =>
|
||||
"Each preset color can now have their brightness specified. SimilarityThreshold range was changed.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
var manager = actorNode.LastChildMatching("ColorPickerManager");
|
||||
if (manager == null)
|
||||
yield break;
|
||||
|
||||
manager.RemoveNodes("SimilarityThreshold");
|
||||
|
||||
var v = manager.LastChildMatching("V")?.NodeValue<float>() ?? 0.95f;
|
||||
var hues = manager.LastChildMatching("PresetHues")?.NodeValue<float[]>();
|
||||
var saturations = manager.LastChildMatching("PresetSaturations")?.NodeValue<float[]>();
|
||||
|
||||
manager.RemoveNodes("V");
|
||||
manager.RemoveNodes("PresetHues");
|
||||
manager.RemoveNodes("PresetSaturations");
|
||||
|
||||
if (hues == null || saturations == null)
|
||||
yield break;
|
||||
|
||||
var colors = new Color[hues.Length];
|
||||
for (var i = 0; i < colors.Length; i++)
|
||||
colors[i] = Color.FromAhsv(hues[i], saturations[i], v);
|
||||
|
||||
manager.AddNode("PresetColors", colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ExplicitSequenceFilenames : UpdateRule, IBeforeUpdateSequences
|
||||
{
|
||||
public override string Name => "Sequence filenames must be specified explicitly.";
|
||||
|
||||
public override string Description =>
|
||||
"Sequence sprite filenames are no longer automatically inferred, and the AddExtension,\n" +
|
||||
"UseTilesetExtension, UseTilesetNodes and TilesetOverrides fields have been removed.\n\n" +
|
||||
"The sprite filename for each sequence must now be defined using the Filename field.\n" +
|
||||
"Tileset specific overrides can be defined as children of the TilesetFilenames field.";
|
||||
|
||||
string defaultSpriteExtension = ".shp";
|
||||
List<MiniYamlNodeBuilder> resolvedImagesNodes;
|
||||
readonly Dictionary<string, string> tilesetExtensions = [];
|
||||
readonly Dictionary<string, string> tilesetCodes = [];
|
||||
bool parseModYaml = true;
|
||||
bool reportModYamlChanges;
|
||||
bool disabled;
|
||||
|
||||
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNodeBuilder> resolvedImagesNodes)
|
||||
{
|
||||
// Keep a resolved copy of the sequences so we can account for values imported through inheritance or Defaults.
|
||||
// This will be modified during processing, so take a deep copy to avoid side-effects on other update rules.
|
||||
this.resolvedImagesNodes = MiniYaml.FromString(resolvedImagesNodes.WriteToString(), nameof(BeforeUpdateSequences))
|
||||
.Select(n => new MiniYamlNodeBuilder(n))
|
||||
.ToList();
|
||||
|
||||
var requiredMetadata = new HashSet<string>();
|
||||
foreach (var imageNode in resolvedImagesNodes)
|
||||
{
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes)
|
||||
{
|
||||
var useTilesetExtensionNode = sequenceNode.LastChildMatching("UseTilesetExtension");
|
||||
if (useTilesetExtensionNode != null && tilesetExtensions.Count == 0)
|
||||
requiredMetadata.Add("TilesetExtensions");
|
||||
|
||||
var useTilesetCodeNode = sequenceNode.LastChildMatching("UseTilesetCode");
|
||||
if (useTilesetCodeNode != null && tilesetCodes.Count == 0)
|
||||
requiredMetadata.Add("TilesetCodes");
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredMetadata.Count != 0)
|
||||
{
|
||||
yield return
|
||||
$"The ExplicitSequenceFilenames rule requires {requiredMetadata.JoinWith(", ")}\n" +
|
||||
"to be defined under the SpriteSequenceFormat definition in mod.yaml.\n" +
|
||||
"Add these definitions back and run the update rule again.";
|
||||
disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> BeforeUpdate(ModData modData)
|
||||
{
|
||||
// Don't reload data when processing maps
|
||||
if (!parseModYaml)
|
||||
yield break;
|
||||
|
||||
parseModYaml = false;
|
||||
|
||||
// HACK: We need to read the obsolete yaml definitions to be able to update the sequences
|
||||
// TilesetSpecificSpriteSequence no longer defines fields for these, so we must take them directly from mod.yaml
|
||||
var yamlField = modData.Manifest.GetType().GetField("yaml", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
var yaml = (Dictionary<string, MiniYaml>)yamlField?.GetValue(modData.Manifest);
|
||||
|
||||
if (yaml != null && yaml.TryGetValue("SpriteSequenceFormat", out var spriteSequenceFormatYaml))
|
||||
{
|
||||
if (spriteSequenceFormatYaml.Value == "DefaultSpriteSequence")
|
||||
{
|
||||
defaultSpriteExtension = "";
|
||||
yield break;
|
||||
}
|
||||
|
||||
var spriteSequenceFormatNode = new MiniYamlNodeBuilder("", new MiniYamlBuilder(spriteSequenceFormatYaml));
|
||||
var defaultSpriteExtensionNode = spriteSequenceFormatNode.LastChildMatching("DefaultSpriteExtension");
|
||||
if (defaultSpriteExtensionNode != null)
|
||||
{
|
||||
reportModYamlChanges = true;
|
||||
defaultSpriteExtension = defaultSpriteExtensionNode.Value.Value;
|
||||
}
|
||||
|
||||
var fromBackup = false;
|
||||
|
||||
var tilesetExtensionsNode = spriteSequenceFormatNode.LastChildMatching("TilesetExtensions")?.Value?.Nodes;
|
||||
if (tilesetExtensionsNode == null)
|
||||
{
|
||||
switch (modData.Manifest.Id)
|
||||
{
|
||||
case "cnc":
|
||||
fromBackup = true;
|
||||
tilesetExtensionsNode =
|
||||
[
|
||||
new("TEMPERAT", ".tem"),
|
||||
new("SNOW", ".sno"),
|
||||
new("INTERIOR", ".int"),
|
||||
new("DESERT", ".des"),
|
||||
new("JUNGLE", ".jun"),
|
||||
];
|
||||
break;
|
||||
case "ra":
|
||||
fromBackup = true;
|
||||
tilesetExtensionsNode =
|
||||
[
|
||||
new("TEMPERAT", ".tem"),
|
||||
new("SNOW", ".sno"),
|
||||
new("INTERIOR", ".int"),
|
||||
new("DESERT", ".des"),
|
||||
];
|
||||
break;
|
||||
case "ts":
|
||||
fromBackup = true;
|
||||
tilesetExtensionsNode =
|
||||
[
|
||||
new("TEMPERATE", ".tem"),
|
||||
new("SNOW", ".sno"),
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tilesetExtensionsNode != null)
|
||||
{
|
||||
if (!fromBackup)
|
||||
reportModYamlChanges = true;
|
||||
|
||||
foreach (var n in tilesetExtensionsNode)
|
||||
tilesetExtensions[n.Key] = n.Value.Value;
|
||||
}
|
||||
|
||||
fromBackup = false;
|
||||
|
||||
var tilesetCodesNode = spriteSequenceFormatNode.LastChildMatching("TilesetCodes")?.Value?.Nodes;
|
||||
if (tilesetCodesNode == null && modData.Manifest.Id == "ts")
|
||||
{
|
||||
fromBackup = true;
|
||||
tilesetCodesNode =
|
||||
[
|
||||
new("TEMPERATE", "t"),
|
||||
new("SNOW", "a"),
|
||||
];
|
||||
}
|
||||
|
||||
if (tilesetCodesNode != null)
|
||||
{
|
||||
if (!fromBackup)
|
||||
reportModYamlChanges = true;
|
||||
|
||||
foreach (var n in tilesetCodesNode)
|
||||
tilesetCodes[n.Key] = n.Value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (!reportModYamlChanges)
|
||||
yield break;
|
||||
|
||||
yield return "The DefaultSpriteExtension, TilesetExtensions, and TilesetCodes fields defined\n" +
|
||||
"under SpriteSequenceFormat in your mod.yaml are no longer used, and can be removed.";
|
||||
|
||||
reportModYamlChanges = false;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder imageNode)
|
||||
{
|
||||
if (disabled)
|
||||
yield break;
|
||||
|
||||
var resolvedImageNode = resolvedImagesNodes.Single(n => n.Key == imageNode.Key);
|
||||
|
||||
// Add a placeholder for inherited sequences that were previously implicitly named
|
||||
var implicitInheritedSequences = new List<string>();
|
||||
foreach (var resolvedSequenceNode in resolvedImageNode.Value.Nodes)
|
||||
{
|
||||
if (resolvedSequenceNode.Key == "Defaults")
|
||||
continue;
|
||||
|
||||
// Ignore nodes that are not implicitly named or already processed
|
||||
if (!string.IsNullOrEmpty(resolvedSequenceNode.Value.Value) || resolvedSequenceNode.LastChildMatching("Filename") != null)
|
||||
continue;
|
||||
|
||||
if (imageNode.LastChildMatching(resolvedSequenceNode.Key) == null)
|
||||
{
|
||||
imageNode.AddNode(resolvedSequenceNode.Key, "");
|
||||
implicitInheritedSequences.Add(resolvedSequenceNode.Key);
|
||||
}
|
||||
}
|
||||
|
||||
var resolvedDefaultsNode = resolvedImageNode.LastChildMatching("Defaults");
|
||||
if (resolvedDefaultsNode != null)
|
||||
{
|
||||
foreach (var resolvedSequenceNode in resolvedImageNode.Value.Nodes)
|
||||
{
|
||||
if (resolvedSequenceNode == resolvedDefaultsNode)
|
||||
continue;
|
||||
|
||||
resolvedSequenceNode.Value.Nodes = MiniYaml.Merge(
|
||||
[
|
||||
resolvedDefaultsNode.Value.Nodes.Select(n => n.Build()).ToArray(),
|
||||
resolvedSequenceNode.Value.Nodes.Select(n => n.Build()).ToArray()
|
||||
]).ConvertAll(n => new MiniYamlNodeBuilder(n));
|
||||
resolvedSequenceNode.Value.Value ??= resolvedDefaultsNode.Value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Sequences that explicitly defined a filename may be inherited by others that depend on the explicit name
|
||||
// Keep track of these sequences so we don't remove the filenames later!
|
||||
var explicitlyNamedSequences = new List<string>();
|
||||
|
||||
// Add Filename/TilesetFilenames nodes to every sequence
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sequenceNode.Key) || sequenceNode.KeyMatches("Inherits"))
|
||||
continue;
|
||||
|
||||
if (!string.IsNullOrEmpty(sequenceNode.Value.Value))
|
||||
explicitlyNamedSequences.Add(sequenceNode.Key);
|
||||
|
||||
var resolvedSequenceNode = resolvedImageNode.Value.NodeWithKeyOrDefault(sequenceNode.Key);
|
||||
if (resolvedSequenceNode == null)
|
||||
continue;
|
||||
|
||||
ProcessNode(modData, sequenceNode, resolvedSequenceNode, imageNode.Key);
|
||||
}
|
||||
|
||||
// Identify a suitable default for deduplication
|
||||
MiniYamlNodeBuilder defaultFilenameNode = null;
|
||||
MiniYamlNodeBuilder defaultTilesetFilenamesNode = null;
|
||||
foreach (var defaultsNode in imageNode.ChildrenMatching("Defaults"))
|
||||
{
|
||||
defaultFilenameNode = defaultsNode.LastChildMatching("Filename") ?? defaultFilenameNode;
|
||||
defaultTilesetFilenamesNode = defaultsNode.LastChildMatching("TilesetFilenames") ?? defaultTilesetFilenamesNode;
|
||||
}
|
||||
|
||||
if ((defaultFilenameNode == null || defaultTilesetFilenamesNode == null) && !imageNode.Key.StartsWith('^'))
|
||||
{
|
||||
var duplicateCount = new Dictionary<string, int>();
|
||||
var duplicateTilesetCount = new Dictionary<string, int>();
|
||||
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sequenceNode.Key) || explicitlyNamedSequences.Contains(sequenceNode.Key))
|
||||
continue;
|
||||
|
||||
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
|
||||
if (defaultTilesetFilenamesNode == null && tilesetFilenamesNode != null)
|
||||
{
|
||||
var key = tilesetFilenamesNode.Value.Nodes.WriteToString();
|
||||
duplicateTilesetCount[key] = duplicateTilesetCount.GetValueOrDefault(key, 0) + 1;
|
||||
}
|
||||
|
||||
var filenameNode = sequenceNode.LastChildMatching("Filename");
|
||||
if (defaultFilenameNode == null && filenameNode != null)
|
||||
{
|
||||
var key = filenameNode.Value.Value;
|
||||
duplicateCount[key] = duplicateCount.GetValueOrDefault(key, 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
var inheritsNode = imageNode.LastChildMatching("Inherits");
|
||||
var inheritsNodeIndex = inheritsNode == null ? 0 : imageNode.Value.Nodes.IndexOf(inheritsNode) + 1;
|
||||
|
||||
var maxDuplicateTilesetCount = duplicateTilesetCount.MaxByOrDefault(kv => kv.Value).Value;
|
||||
if (maxDuplicateTilesetCount > 1)
|
||||
{
|
||||
var defaultsNode = imageNode.LastChildMatching("Defaults");
|
||||
if (defaultsNode == null)
|
||||
{
|
||||
defaultsNode = new MiniYamlNodeBuilder("Defaults", "");
|
||||
imageNode.Value.Nodes.Insert(inheritsNodeIndex, defaultsNode);
|
||||
}
|
||||
|
||||
var nodes = MiniYaml.FromString(duplicateTilesetCount.First(kv => kv.Value == maxDuplicateTilesetCount).Key, nameof(UpdateSequenceNode)).ToList();
|
||||
defaultTilesetFilenamesNode = new MiniYamlNodeBuilder("TilesetFilenames", "", nodes);
|
||||
defaultsNode.Value.Nodes.Insert(0, defaultTilesetFilenamesNode);
|
||||
}
|
||||
|
||||
var maxDuplicateCount = duplicateCount.MaxByOrDefault(kv => kv.Value).Value;
|
||||
if (maxDuplicateCount > 1)
|
||||
{
|
||||
var defaultsNode = imageNode.LastChildMatching("Defaults");
|
||||
if (defaultsNode == null)
|
||||
{
|
||||
defaultsNode = new MiniYamlNodeBuilder("Defaults", "");
|
||||
imageNode.Value.Nodes.Insert(inheritsNodeIndex, defaultsNode);
|
||||
}
|
||||
|
||||
defaultFilenameNode = new MiniYamlNodeBuilder("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
|
||||
defaultsNode.Value.Nodes.Insert(0, defaultFilenameNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove redundant definitions
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
||||
{
|
||||
if (sequenceNode.Key == "Defaults" || sequenceNode.Key == "Inherits" || string.IsNullOrEmpty(sequenceNode.Key))
|
||||
continue;
|
||||
|
||||
var combineNode = sequenceNode.LastChildMatching("Combine");
|
||||
var filenameNode = sequenceNode.LastChildMatching("Filename");
|
||||
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
|
||||
|
||||
if (defaultTilesetFilenamesNode != null && combineNode != null)
|
||||
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("TilesetFilenames", ""));
|
||||
|
||||
if (defaultFilenameNode != null && combineNode != null)
|
||||
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("Filename", ""));
|
||||
|
||||
if (defaultTilesetFilenamesNode != null && tilesetFilenamesNode == null && filenameNode != null)
|
||||
{
|
||||
var index = sequenceNode.Value.Nodes.IndexOf(filenameNode) + 1;
|
||||
sequenceNode.Value.Nodes.Insert(index, new MiniYamlNodeBuilder("TilesetFilenames", ""));
|
||||
}
|
||||
|
||||
// Remove redundant overrides
|
||||
if (!explicitlyNamedSequences.Contains(sequenceNode.Key))
|
||||
{
|
||||
if (defaultTilesetFilenamesNode != null && tilesetFilenamesNode != null)
|
||||
{
|
||||
var allTilesetsMatch = true;
|
||||
foreach (var overrideNode in tilesetFilenamesNode.Value.Nodes)
|
||||
if (!defaultTilesetFilenamesNode.Value.Nodes.Any(n => n.Key == overrideNode.Key && n.Value.Value == overrideNode.Value.Value))
|
||||
allTilesetsMatch = false;
|
||||
|
||||
if (allTilesetsMatch)
|
||||
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
||||
}
|
||||
|
||||
if (filenameNode?.Value.Value != null && filenameNode?.Value.Value == defaultFilenameNode?.Value.Value)
|
||||
sequenceNode.RemoveNode(filenameNode);
|
||||
}
|
||||
}
|
||||
|
||||
var allSequencesHaveFilename = true;
|
||||
var allSequencesHaveTilesetFilenames = true;
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
||||
{
|
||||
if (sequenceNode.Key == "Defaults" || sequenceNode.Key == "Inherits" || string.IsNullOrEmpty(sequenceNode.Key))
|
||||
continue;
|
||||
|
||||
if (sequenceNode.LastChildMatching("Filename") == null)
|
||||
allSequencesHaveFilename = false;
|
||||
|
||||
if (sequenceNode.LastChildMatching("TilesetFilenames") == null)
|
||||
allSequencesHaveTilesetFilenames = false;
|
||||
}
|
||||
|
||||
if (allSequencesHaveFilename || allSequencesHaveTilesetFilenames)
|
||||
{
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
||||
{
|
||||
if (sequenceNode.Key == "Defaults")
|
||||
{
|
||||
if (allSequencesHaveFilename)
|
||||
sequenceNode.RemoveNodes("Filename");
|
||||
|
||||
if (allSequencesHaveTilesetFilenames)
|
||||
sequenceNode.RemoveNodes("TilesetFilenames");
|
||||
|
||||
if (sequenceNode.Value.Nodes.Count == 0)
|
||||
imageNode.RemoveNode(sequenceNode);
|
||||
}
|
||||
|
||||
if (allSequencesHaveFilename && sequenceNode.LastChildMatching("Combine") != null)
|
||||
sequenceNode.RemoveNodes("Filename");
|
||||
|
||||
if (allSequencesHaveTilesetFilenames && sequenceNode.LastChildMatching("Combine") != null)
|
||||
sequenceNode.RemoveNodes("TilesetFilenames");
|
||||
|
||||
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
|
||||
if (allSequencesHaveTilesetFilenames && tilesetFilenamesNode != null && tilesetFilenamesNode.Value.Nodes.Count == 0)
|
||||
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
||||
if (implicitInheritedSequences.Contains(sequenceNode.Key) && sequenceNode.Value.Nodes.Count == 0)
|
||||
imageNode.RemoveNode(sequenceNode);
|
||||
}
|
||||
|
||||
void ProcessNode(ModData modData, MiniYamlNodeBuilder sequenceNode, MiniYamlNodeBuilder resolvedSequenceNode, string imageName)
|
||||
{
|
||||
// "Filename" was introduced with this update rule, so that means this node was already processed and can be skipped
|
||||
if (sequenceNode.LastChildMatching("Filename") != null)
|
||||
return;
|
||||
|
||||
var addExtension = true;
|
||||
var addExtensionNode = resolvedSequenceNode.LastChildMatching("AddExtension");
|
||||
if (addExtensionNode != null)
|
||||
addExtension = FieldLoader.GetValue<bool>("AddExtension", addExtensionNode.Value.Value);
|
||||
|
||||
var useTilesetExtension = false;
|
||||
var useTilesetExtensionNode = resolvedSequenceNode.LastChildMatching("UseTilesetExtension");
|
||||
if (useTilesetExtensionNode != null)
|
||||
useTilesetExtension = FieldLoader.GetValue<bool>("UseTilesetExtension", useTilesetExtensionNode.Value.Value);
|
||||
|
||||
var useTilesetCode = false;
|
||||
var useTilesetCodeNode = resolvedSequenceNode.LastChildMatching("UseTilesetCode");
|
||||
if (useTilesetCodeNode != null)
|
||||
useTilesetCode = FieldLoader.GetValue<bool>("UseTilesetCode", useTilesetCodeNode.Value.Value);
|
||||
|
||||
var tilesetOverrides = new Dictionary<string, string>();
|
||||
var tilesetOverridesNode = resolvedSequenceNode.LastChildMatching("TilesetOverrides");
|
||||
if (tilesetOverridesNode != null)
|
||||
foreach (var tilesetNode in tilesetOverridesNode.Value.Nodes)
|
||||
tilesetOverrides[tilesetNode.Key] = tilesetNode.Value.Value;
|
||||
|
||||
sequenceNode.RemoveNodes("AddExtension");
|
||||
sequenceNode.RemoveNodes("UseTilesetExtension");
|
||||
sequenceNode.RemoveNodes("UseTilesetCode");
|
||||
sequenceNode.RemoveNodes("TilesetOverrides");
|
||||
|
||||
// Replace removals with masking
|
||||
foreach (var node in sequenceNode.Value.Nodes)
|
||||
if (node.Key?.StartsWith('-') ?? false)
|
||||
node.Key = node.Key[1..];
|
||||
|
||||
var combineNode = sequenceNode.LastChildMatching("Combine");
|
||||
if (combineNode != null)
|
||||
{
|
||||
var i = 0;
|
||||
foreach (var node in combineNode.Value.Nodes)
|
||||
{
|
||||
ProcessNode(modData, node, node, node.Key);
|
||||
node.Key = i++.ToStringInvariant();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = string.IsNullOrEmpty(resolvedSequenceNode.Value.Value) ? imageName : resolvedSequenceNode.Value.Value;
|
||||
if (filename.StartsWith('^'))
|
||||
return;
|
||||
|
||||
if (useTilesetExtension || useTilesetCode)
|
||||
{
|
||||
var tilesetFilenamesNode = new MiniYamlNodeBuilder("TilesetFilenames", "");
|
||||
var duplicateCount = new Dictionary<string, int>();
|
||||
foreach (var tileset in modData.DefaultTerrainInfo.Keys)
|
||||
{
|
||||
if (!tilesetOverrides.TryGetValue(tileset, out var sequenceTileset))
|
||||
sequenceTileset = tileset;
|
||||
|
||||
var overrideFilename = filename;
|
||||
if (useTilesetCode)
|
||||
overrideFilename = filename[..1] + tilesetCodes[sequenceTileset] + filename[2..];
|
||||
|
||||
if (addExtension)
|
||||
overrideFilename += useTilesetExtension ? tilesetExtensions[sequenceTileset] : defaultSpriteExtension;
|
||||
|
||||
tilesetFilenamesNode.AddNode(tileset, overrideFilename);
|
||||
duplicateCount[overrideFilename] = duplicateCount.GetValueOrDefault(overrideFilename, 0) + 1;
|
||||
}
|
||||
|
||||
sequenceNode.Value.Nodes.Insert(0, tilesetFilenamesNode);
|
||||
|
||||
// Deduplicate tileset overrides
|
||||
var maxDuplicateCount = duplicateCount.MaxByOrDefault(kv => kv.Value).Value;
|
||||
if (maxDuplicateCount > 1)
|
||||
{
|
||||
var filenameNode = new MiniYamlNodeBuilder("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
|
||||
foreach (var overrideNode in tilesetFilenamesNode.Value.Nodes.ToList())
|
||||
if (overrideNode.Value.Value == filenameNode.Value.Value)
|
||||
tilesetFilenamesNode.Value.Nodes.Remove(overrideNode);
|
||||
|
||||
if (tilesetFilenamesNode.Value.Nodes.Count == 0)
|
||||
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
||||
|
||||
sequenceNode.Value.Nodes.Insert(0, filenameNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addExtension)
|
||||
filename += defaultSpriteExtension;
|
||||
|
||||
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("Filename", filename));
|
||||
}
|
||||
|
||||
sequenceNode.ReplaceValue("");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ProductionTabsWidgetAddTabButtonCollection : UpdateRule
|
||||
{
|
||||
public override string Name => "Change name of Button field of ProductionTabsWidget and add ArrowButton if necessary.";
|
||||
|
||||
public override string Description =>
|
||||
"Change the field name from Button to TabButton and add ArrowButton, if Button field was set.";
|
||||
|
||||
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
|
||||
{
|
||||
if (!chromeNode.KeyMatches("ProductionTabs"))
|
||||
yield break;
|
||||
|
||||
string buttonCollection = null;
|
||||
foreach (var field in chromeNode.ChildrenMatching("Button"))
|
||||
{
|
||||
field.RenameKey("TabButton");
|
||||
buttonCollection = field.Value.Value;
|
||||
}
|
||||
|
||||
if (buttonCollection != null)
|
||||
chromeNode.AddNode(new MiniYamlNodeBuilder("ArrowButton", buttonCollection));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveExperienceFromInfiltrates : UpdateRule
|
||||
{
|
||||
public override string Name => "Removes PlayerExperience property from Infiltrates.";
|
||||
|
||||
public override string Description =>
|
||||
"Infiltrates property PlayerExperience was removed, " +
|
||||
"it was replaced by adding PlayerExperience to all InfiltrateFor* Traits.";
|
||||
|
||||
readonly List<string> locations = [];
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Count > 0)
|
||||
yield return "The 'PlayerExperience' fields have been removed from the 'Infiltrates' trait\n" +
|
||||
"and added to InfiltrateFor* traits. If you want to keep 'PlayerExperience' you will\n" +
|
||||
"need to add it to each of the InfiltrateFor* traits. Properties removed from:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
var removed = false;
|
||||
foreach (var node in actorNode.ChildrenMatching("Infiltrates"))
|
||||
if (node.RemoveNodes("PlayerExperience") > 0)
|
||||
removed = true;
|
||||
|
||||
if (removed)
|
||||
locations.Add($"{actorNode.Key} ({actorNode.Location.Name})");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveNegativeSequenceLength : UpdateRule, IBeforeUpdateSequences
|
||||
{
|
||||
public override string Name => "Negative sequence length is no longer allowed.";
|
||||
|
||||
public override string Description => "Negative sequence length is no longer allowed, define individual frames in reverse instead.";
|
||||
|
||||
List<MiniYamlNodeBuilder> resolvedImagesNodes;
|
||||
|
||||
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNodeBuilder> resolvedImagesNodes)
|
||||
{
|
||||
this.resolvedImagesNodes = resolvedImagesNodes;
|
||||
yield break;
|
||||
}
|
||||
|
||||
readonly Queue<Action> actionQueue = [];
|
||||
|
||||
static MiniYamlNodeBuilder GetNode(string key, MiniYamlNodeBuilder node, MiniYamlNodeBuilder defaultNode)
|
||||
{
|
||||
return node.LastChildMatching(key, includeRemovals: false) ?? defaultNode?.LastChildMatching(key, includeRemovals: false);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode)
|
||||
{
|
||||
var defaultNode = sequenceNode.LastChildMatching("Defaults");
|
||||
var defaultLengthNode = defaultNode == null ? null : GetNode("Length", defaultNode, null);
|
||||
foreach (var node in sequenceNode.Value.Nodes)
|
||||
{
|
||||
var lengthNode = node.LastChildMatching("Length");
|
||||
if (lengthNode != null && lengthNode.IsRemoval())
|
||||
continue;
|
||||
|
||||
lengthNode ??= defaultLengthNode;
|
||||
if (lengthNode == null || lengthNode.Value.Value == "*")
|
||||
continue;
|
||||
|
||||
var length = FieldLoader.GetValue<int>(lengthNode.Key, lengthNode.Value.Value);
|
||||
if (length >= 0)
|
||||
continue;
|
||||
|
||||
var resolvedImage = resolvedImagesNodes.First(n => n.Key == sequenceNode.Key);
|
||||
var resolvedNode = resolvedImage.LastChildMatching(node.Key);
|
||||
var resolvedDefaultNode = resolvedNode.Value.Value == "Defaults" ? null : resolvedImage.LastChildMatching("Defaults");
|
||||
|
||||
var startNode = GetNode("Start", node, defaultNode) ?? GetNode("Start", resolvedNode, resolvedDefaultNode);
|
||||
if (startNode == null)
|
||||
{
|
||||
actionQueue.Enqueue(() => node.RemoveNodes("Length"));
|
||||
continue;
|
||||
}
|
||||
|
||||
var facingsNode = GetNode("Facings", node, defaultNode) ?? GetNode("Facings", resolvedNode, resolvedDefaultNode);
|
||||
var facings = facingsNode == null ? 1 : FieldLoader.GetValue<int>(facingsNode.Key, facingsNode.Value.Value);
|
||||
|
||||
length = -length * facings;
|
||||
var start = FieldLoader.GetValue<int>(startNode.Key, startNode.Value.Value) - 1;
|
||||
|
||||
var frames = new int[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
frames[i] = start - i;
|
||||
|
||||
actionQueue.Enqueue(() =>
|
||||
{
|
||||
node.RemoveNodes("Start");
|
||||
node.RemoveNodes("Length");
|
||||
node.AddNode("Frames", frames);
|
||||
});
|
||||
}
|
||||
|
||||
while (actionQueue.Count != 0)
|
||||
actionQueue.Dequeue().Invoke();
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveSequenceHasEmbeddedPalette : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove sequence HasEmbeddedPalette property.";
|
||||
|
||||
public override string Description =>
|
||||
"The PaletteFromEmbeddedSpritePalette trait no longer references a sequence.\n" +
|
||||
"Image and Sequence are replaced by Filename and Frame.";
|
||||
|
||||
readonly HashSet<string> locations = [];
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Count > 0)
|
||||
yield return
|
||||
"The PaletteFromEmbeddedSpritePalette trait no longer references a sequence.\n" +
|
||||
"You must manually define Filename (and Frame if needed) on the following actors:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder imageNode)
|
||||
{
|
||||
foreach (var sequenceNode in imageNode.Value.Nodes)
|
||||
sequenceNode.RemoveNodes("HasEmbeddedPalette");
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var traitNode in actorNode.ChildrenMatching("PaletteFromEmbeddedSpritePalette"))
|
||||
{
|
||||
traitNode.RemoveNodes("Image");
|
||||
traitNode.RemoveNodes("Sequence");
|
||||
locations.Add($"{actorNode.Key} ({actorNode.Location.Name})");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveTSRefinery : UpdateRule
|
||||
{
|
||||
public override string Name => "TiberianSunRefinery removed.";
|
||||
|
||||
public override string Description => "TiberianSunRefinery was removed, use Refinery instead.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RenameChildrenMatching("TiberianSunRefinery", "Refinery");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameContrailWidth : UpdateRule
|
||||
{
|
||||
public override string Name => "Rename contrail width";
|
||||
|
||||
public override string Description => "Rename contrail `TrailWidth` to `StartWidth` in traits and weapons to account for added `EndWidth` functionality";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var traitNode in actorNode.ChildrenMatching("Contrail"))
|
||||
traitNode.RenameChildrenMatching("TrailWidth", "StartWidth");
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
|
||||
{
|
||||
foreach (var traitNode in weaponNode.ChildrenMatching("Projectile").Where(n => n.Value.Value == "Missile"))
|
||||
traitNode.RenameChildrenMatching("ContrailWidth", "ContrailStartWidth");
|
||||
|
||||
foreach (var traitNode in weaponNode.ChildrenMatching("Projectile").Where(n => n.Value.Value == "Bullet"))
|
||||
traitNode.RenameChildrenMatching("ContrailWidth", "ContrailStartWidth");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameEngineerRepair : UpdateRule
|
||||
{
|
||||
public override string Name => "Traits revolving around instant (building) repairs were renamed.";
|
||||
|
||||
public override string Description =>
|
||||
"'EngineerRepair' was renamed to 'InstantlyRepairs' " +
|
||||
"and 'EngineerRepairable' to 'InstantlyRepairable'.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RenameChildrenMatching("EngineerRepair", "InstantlyRepairs");
|
||||
actorNode.RenameChildrenMatching("EngineerRepairable", "InstantlyRepairable");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameMcvCrateAction : UpdateRule
|
||||
{
|
||||
public override string Name => "Rename 'GiveMcvCrateAction' to 'GiveBaseBuilderCrateAction'.";
|
||||
|
||||
public override string Description => "The 'GiveMcvCrateAction' has been renamed to 'GiveBaseBuilderCrateAction'.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var node in actorNode.ChildrenMatching("GiveMcvCrateAction"))
|
||||
node.RenameKey("GiveBaseBuilderCrateAction");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class TextNotificationsDisplayWidgetRemoveTime : UpdateRule
|
||||
{
|
||||
public override string Name => "Change name and unit of RemoveTime field of TextNotificationsDisplayWidget.";
|
||||
|
||||
public override string Description =>
|
||||
"Change the field name from RemoveTime to DisplayDurationMs and convert the value from ticks to milliseconds";
|
||||
|
||||
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
|
||||
{
|
||||
if (!chromeNode.KeyMatches("TextNotificationsDisplay"))
|
||||
yield break;
|
||||
|
||||
foreach (var field in chromeNode.ChildrenMatching("RemoveTime"))
|
||||
{
|
||||
field.RenameKey("DisplayDurationMs");
|
||||
|
||||
var durationMilliseconds = field.NodeValue<int>() * 40;
|
||||
field.ReplaceValue(FieldSaver.FormatValue(durationMilliseconds));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
166
OpenRA.Mods.Common/UpdateRules/Rules/20231010/AbstractDocking.cs
Normal file
166
OpenRA.Mods.Common/UpdateRules/Rules/20231010/AbstractDocking.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AbstractDocking : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
readonly string[] moveRefineyValues = ["DockAngle", "IsDragRequired", "DragOffset", "DragLength"];
|
||||
readonly string[] moveHarvesterValues = ["EnterCursor", "EnterBlockedCursor"];
|
||||
readonly string[] buildings = ["Building", "D2kBuilding"];
|
||||
readonly string[,] moveAndRenameHarvesterValues = new string[4, 2]
|
||||
{
|
||||
{ "DeliverVoice", "Voice" },
|
||||
{ "DeliverLineColor", "DockLineColor" },
|
||||
{ "UnloadQueueCostModifier", "OccupancyCostModifier" },
|
||||
{ "SearchForDeliveryBuildingDelay", "SearchForDockDelay" }
|
||||
};
|
||||
|
||||
readonly Dictionary<string, List<MiniYamlNodeBuilder>> refineryNodes = [];
|
||||
public override string Name => "Docking was abstracted from Refinery & Harvester.";
|
||||
|
||||
public override string Description =>
|
||||
"Fields moved from Refinery to new trait DockHost, fields moved from Harvester to new trait DockClientManager and to DockHost";
|
||||
|
||||
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
|
||||
{
|
||||
grid = modData.GetOrCreate<MapGrid>();
|
||||
var harvesters = new Dictionary<string, HashSet<string>>();
|
||||
var refineries = new List<string>();
|
||||
foreach (var actorNode in resolvedActors)
|
||||
{
|
||||
var harvesterNode = actorNode.ChildrenMatching("Harvester", includeRemovals: false).FirstOrDefault();
|
||||
if (harvesterNode != null)
|
||||
harvesters[actorNode.Key] = harvesterNode.ChildrenMatching("DeliveryBuildings", includeRemovals: false)
|
||||
.FirstOrDefault()?.NodeValue<HashSet<string>>() ?? [];
|
||||
|
||||
if (actorNode.HasChild("Refinery"))
|
||||
refineries.Add(actorNode.Key.ToLowerInvariant());
|
||||
}
|
||||
|
||||
foreach (var harvester in harvesters)
|
||||
{
|
||||
foreach (var deliveryBuildingHigh in harvester.Value)
|
||||
{
|
||||
var deliveryBuilding = deliveryBuildingHigh.ToLowerInvariant();
|
||||
foreach (var refinery in refineries)
|
||||
{
|
||||
if (refinery == deliveryBuilding)
|
||||
{
|
||||
if (!refineryNodes.ContainsKey(refinery))
|
||||
refineryNodes[refinery] = [];
|
||||
|
||||
var node = new MiniYamlNodeBuilder("Type", deliveryBuilding.ToString());
|
||||
if (!refineryNodes[refinery].Any(n => n.Key == node.Key))
|
||||
refineryNodes[refinery].Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
var refineryNode = actorNode.ChildrenMatching("Refinery", includeRemovals: false).FirstOrDefault();
|
||||
if (refineryNode != null)
|
||||
{
|
||||
var dockNode = new MiniYamlNodeBuilder("DockHost", "");
|
||||
|
||||
var lowActorName = actorNode.Key.ToLowerInvariant();
|
||||
if (!refineryNodes.TryGetValue(lowActorName, out var nodes) || !nodes.Any(n => n.Key == "Type"))
|
||||
dockNode.AddNode("Type", "Unload");
|
||||
else
|
||||
dockNode.AddNode(nodes.First(n => n.Key == "Type"));
|
||||
|
||||
foreach (var value in moveRefineyValues)
|
||||
{
|
||||
foreach (var node in refineryNode.ChildrenMatching(value).ToList())
|
||||
{
|
||||
dockNode.AddNode(node);
|
||||
refineryNode.RemoveNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
var oldOffset = CVec.Zero;
|
||||
var dockOffsetNode = refineryNode.ChildrenMatching("DockOffset", includeRemovals: false).FirstOrDefault();
|
||||
if (dockOffsetNode != null)
|
||||
{
|
||||
oldOffset = dockOffsetNode.NodeValue<CVec>();
|
||||
refineryNode.RemoveNode(dockOffsetNode);
|
||||
}
|
||||
|
||||
var buildingNode = actorNode.Value.Nodes.FirstOrDefault(n => buildings.Any(b => n.KeyMatches(b, includeRemovals: false)));
|
||||
if (buildingNode != null)
|
||||
{
|
||||
var dimensions = buildingNode.ChildrenMatching("Dimensions", includeRemovals: false).FirstOrDefault()?.NodeValue<CVec>() ?? new CVec(1, 1);
|
||||
var localCenterOffset = buildingNode.ChildrenMatching("LocalCenterOffset", includeRemovals: false).FirstOrDefault()?.NodeValue<WVec>() ?? WVec.Zero;
|
||||
|
||||
var offset = CenterOfCell(oldOffset) - CenterOfCell(CVec.Zero) - BuildingCenter(dimensions, localCenterOffset);
|
||||
if (offset != WVec.Zero)
|
||||
dockNode.AddNode("DockOffset", offset);
|
||||
}
|
||||
|
||||
actorNode.AddNode(dockNode);
|
||||
}
|
||||
|
||||
var harvesterNode = actorNode.ChildrenMatching("Harvester", includeRemovals: false).FirstOrDefault();
|
||||
if (harvesterNode != null)
|
||||
{
|
||||
var dockClientNode = new MiniYamlNodeBuilder("DockClientManager", "");
|
||||
|
||||
foreach (var value in moveHarvesterValues)
|
||||
{
|
||||
foreach (var node in harvesterNode.ChildrenMatching(value).ToList())
|
||||
{
|
||||
dockClientNode.AddNode(node);
|
||||
harvesterNode.RemoveNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < moveAndRenameHarvesterValues.GetLength(0); i++)
|
||||
{
|
||||
foreach (var node in harvesterNode.ChildrenMatching(moveAndRenameHarvesterValues[i, 0]).ToList())
|
||||
{
|
||||
harvesterNode.RemoveNode(node);
|
||||
node.RenameKey(moveAndRenameHarvesterValues[i, 1]);
|
||||
dockClientNode.AddNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
harvesterNode.RenameChildrenMatching("DeliveryBuildings", "DockType");
|
||||
harvesterNode.RemoveNodes("MaxUnloadQueue");
|
||||
|
||||
actorNode.AddNode(dockClientNode);
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
MapGrid grid;
|
||||
public WVec CenterOfCell(CVec cell)
|
||||
{
|
||||
if (grid.Type == MapGridType.Rectangular)
|
||||
return new WVec(1024 * cell.X + 512, 1024 * cell.Y + 512, 0);
|
||||
|
||||
return new WVec(724 * (cell.X - cell.Y + 1), 724 * (cell.X + cell.Y + 1), 0);
|
||||
}
|
||||
|
||||
public WVec BuildingCenter(CVec dimensions, WVec localCenterOffset)
|
||||
{
|
||||
return (CenterOfCell(dimensions) - CenterOfCell(new CVec(1, 1))) / 2 + localCenterOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AddMarkerLayerOverlay : UpdateRule
|
||||
{
|
||||
public override string Name => "Add MarkerLayerOverlay.";
|
||||
|
||||
public override string Description =>
|
||||
"Add MarkerLayerOverlay to editor.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
if (!actorNode.KeyMatches("EditorWorld") || actorNode.LastChildMatching("MarkerLayerOverlay") != null)
|
||||
yield break;
|
||||
|
||||
var markerLayerOverlayNode = new MiniYamlNodeBuilder("MarkerLayerOverlay", new MiniYamlBuilder(""));
|
||||
actorNode.AddNode(markerLayerOverlayNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AddSupportPowerBlockedCursor : UpdateRule
|
||||
{
|
||||
public override string Name => "Add SpawnActorPower/GrantExternalConditionPower BlockedCursor.";
|
||||
|
||||
public override string Description =>
|
||||
"SpawnActorPower and GrantExternalConditionPower field BlockedCursor changed its default value.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var power in new List<string> { "SpawnActorPower", "GrantExternalConditionPower" })
|
||||
{
|
||||
foreach (var spawnActorPower in actorNode.ChildrenMatching(power))
|
||||
{
|
||||
var cursor = spawnActorPower.LastChildMatching("BlockedCursor");
|
||||
if (cursor != null && !cursor.IsRemoval())
|
||||
yield break;
|
||||
var blockedCursorNode = new MiniYamlNodeBuilder("BlockedCursor", new MiniYamlBuilder("move-blocked"));
|
||||
spawnActorPower.AddNode(blockedCursorNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ExtractResourceStorageFromHarvester : UpdateRule
|
||||
{
|
||||
public override string Name => "Renames StoresResources to StoresPlayerResources and extracts StoresResources from Harvester.";
|
||||
|
||||
public override string Description =>
|
||||
"Resource storage was extracted from Harvester. WithHarvesterPipsDecoration was also renamed to WithStoresResourcesPipsDecoration.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RenameChildrenMatching("StoresResources", "StoresPlayerResources");
|
||||
actorNode.RenameChildrenMatching("WithHarvesterPipsDecoration", "WithStoresResourcesPipsDecoration");
|
||||
|
||||
var harvester = actorNode.LastChildMatching("Harvester", false);
|
||||
if (harvester == null)
|
||||
yield break;
|
||||
|
||||
var storesResources = new MiniYamlNodeBuilder("StoresResources", "");
|
||||
var capacity = harvester.LastChildMatching("Capacity", false);
|
||||
if (capacity != null)
|
||||
{
|
||||
storesResources.AddNode(capacity);
|
||||
harvester.RemoveNode(capacity);
|
||||
}
|
||||
|
||||
var resources = harvester.LastChildMatching("Resources", false);
|
||||
if (resources != null)
|
||||
storesResources.AddNode(resources);
|
||||
|
||||
actorNode.AddNode(storesResources);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class MovePreviewFacing : UpdateRule
|
||||
{
|
||||
public override string Name => "Move map editor preview facing to EditorActorLayer";
|
||||
|
||||
public override string Description =>
|
||||
"PreviewFacing property was moved from the EditorCursorLayer to the EditorActorLayer.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
var cursorLayer = actorNode.LastChildMatching("EditorCursorLayer");
|
||||
if (cursorLayer == null || cursorLayer.IsRemoval())
|
||||
yield break;
|
||||
|
||||
var node = cursorLayer.LastChildMatching("PreviewFacing");
|
||||
cursorLayer.RemoveNodes("PreviewFacing");
|
||||
if (node == null || node.IsRemoval())
|
||||
yield break;
|
||||
|
||||
var actorLayer = actorNode.LastChildMatching("EditorActorLayer");
|
||||
if (actorLayer != null && !actorLayer.IsRemoval())
|
||||
{
|
||||
node.RenameKey("DefaultActorFacing");
|
||||
actorLayer.AddNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveConyardChronoReturnAnimation : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove Sequence and Body properties from ConyardChronoReturn.";
|
||||
|
||||
public override string Description => "These properties have been replaced with a dynamic vortex renderable.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var trait in actorNode.ChildrenMatching("ConyardChronoReturn"))
|
||||
{
|
||||
trait.RemoveNodes("Sequence");
|
||||
trait.RemoveNodes("Body");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveEditorSelectionLayerProperties : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove defunct properties from EditorSelectionLayer.";
|
||||
|
||||
public override string Description =>
|
||||
"Map editor was refactored and many of EditorSelectionLayer properties were removed.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var editorSelectionLayer in actorNode.ChildrenMatching("EditorSelectionLayer"))
|
||||
{
|
||||
editorSelectionLayer.RemoveNodes("Palette");
|
||||
editorSelectionLayer.RemoveNodes("FootprintAlpha");
|
||||
editorSelectionLayer.RemoveNodes("Image");
|
||||
editorSelectionLayer.RemoveNodes("CopySequence");
|
||||
editorSelectionLayer.RemoveNodes("PasteSequence");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveParentTopParentLeftSubstitutions : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove PARENT_TOP and PARENT_LEFT from integer expressions for widgets.";
|
||||
|
||||
public override string Description =>
|
||||
"PARENT_TOP is replaced with 0 and PARENT_LEFT is replaced with 0 in integer expressions for width, height and position.";
|
||||
|
||||
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
|
||||
{
|
||||
var dimensionFields =
|
||||
chromeNode.ChildrenMatching("Width")
|
||||
.Concat(chromeNode.ChildrenMatching("Height"))
|
||||
.Concat(chromeNode.ChildrenMatching("X"))
|
||||
.Concat(chromeNode.ChildrenMatching("Y")).ToArray();
|
||||
|
||||
foreach (var field in dimensionFields)
|
||||
{
|
||||
if (field.Value.Value == "PARENT_TOP" || field.Value.Value == "PARENT_LEFT")
|
||||
{
|
||||
chromeNode.RemoveNode(field);
|
||||
}
|
||||
else if (field.Value.Value.Contains("PARENT_TOP"))
|
||||
{
|
||||
field.ReplaceValue(field.Value.Value.Replace("PARENT_TOP", "0"));
|
||||
}
|
||||
else if (field.Value.Value.Contains("PARENT_LEFT"))
|
||||
{
|
||||
field.ReplaceValue(field.Value.Value.Replace("PARENT_LEFT", "0"));
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveValidRelationsFromCapturable : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove ValidRelations property from Capturable.";
|
||||
|
||||
public override string Description => "ValidRelations has been moved from Capturable to Captures to match weapon definitions.";
|
||||
|
||||
readonly List<string> locations = [];
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Count > 0)
|
||||
yield return Description + "\n" +
|
||||
"ValidRelations have been removed from:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var capturable in actorNode.ChildrenMatching("Capturable"))
|
||||
{
|
||||
if (capturable.RemoveNodes("ValidRelations") > 0)
|
||||
locations.Add($"{actorNode.Key}: {capturable.Key} ({actorNode.Location.Name})");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameOnDeath : UpdateRule
|
||||
{
|
||||
public override string Name => "Rename Explodes to FireWarheadOnDeath and ThrowsShrapnel to FireProjectilesOnDeath.";
|
||||
|
||||
public override string Description =>
|
||||
" The Explodes trait was renamed to FireWarheadsOnDeath." +
|
||||
" The ThrowsShrapnel trait was renamed to FireProjectilesOnDeath.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RenameChildrenMatching("Explodes", "FireWarheadsOnDeath");
|
||||
actorNode.RenameChildrenMatching("ThrowsShrapnel", "FireProjectilesOnDeath");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameWidgetSubstitutions : UpdateRule
|
||||
{
|
||||
public override string Name => "Rename *_RIGHT to *_WIDTH and *_BOTTOM to *_HEIGHT in integer expressions for widgets.";
|
||||
|
||||
public override string Description =>
|
||||
"PARENT_RIGHT -> PARENT_WIDTH, PARENT_BOTTOM -> PARENT_HEIGHT, " +
|
||||
"WINDOW_RIGHT -> WINDOW_WIDTH, WINDOW_BOTTOM -> WINDOW_HEIGHT " +
|
||||
"in integer expressions for width, height and position.";
|
||||
|
||||
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
|
||||
{
|
||||
var dimensionFields =
|
||||
chromeNode.ChildrenMatching("Width")
|
||||
.Concat(chromeNode.ChildrenMatching("Height"))
|
||||
.Concat(chromeNode.ChildrenMatching("X"))
|
||||
.Concat(chromeNode.ChildrenMatching("Y")).ToArray();
|
||||
|
||||
foreach (var field in dimensionFields)
|
||||
{
|
||||
field.ReplaceValue(field.Value.Value.Replace("PARENT_RIGHT", "PARENT_WIDTH"));
|
||||
field.ReplaceValue(field.Value.Value.Replace("PARENT_BOTTOM", "PARENT_HEIGHT"));
|
||||
field.ReplaceValue(field.Value.Value.Replace("WINDOW_RIGHT", "WINDOW_WIDTH"));
|
||||
field.ReplaceValue(field.Value.Value.Replace("WINDOW_BOTTOM", "WINDOW_HEIGHT"));
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ReplaceCloakPalette : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
public override string Name => "Change default Cloak style from Palette to Alpha.";
|
||||
|
||||
public override string Description =>
|
||||
"Cloak has gained several new rendering modes\n" +
|
||||
"and its default behaviour has changed from using a palette to native alpha.";
|
||||
|
||||
readonly List<(string, string)> actorsWithDefault = [];
|
||||
IEnumerable<string> IBeforeUpdateActors.BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
|
||||
{
|
||||
foreach (var actor in resolvedActors)
|
||||
foreach (var cloak in actor.ChildrenMatching("Cloak"))
|
||||
if (cloak.HasChild("Palette"))
|
||||
actorsWithDefault.Add((actor.Key, cloak.Key));
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var cloak in actorNode.ChildrenMatching("Cloak"))
|
||||
{
|
||||
if (actorsWithDefault.Any(pair => pair.Item1 == actorNode.Key && pair.Item2 == cloak.Key))
|
||||
{
|
||||
cloak.AddNode("CloakedPalette", "cloak");
|
||||
cloak.AddNode("CloakStyle", "Palette");
|
||||
yield break;
|
||||
}
|
||||
|
||||
var palette = cloak.LastChildMatching("Palette", false);
|
||||
if (palette != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(palette.Value.Value))
|
||||
{
|
||||
cloak.RemoveNode(palette);
|
||||
cloak.AddNode("CloakStyle", "None");
|
||||
}
|
||||
else
|
||||
{
|
||||
palette.RenameKey("CloakedPalette");
|
||||
cloak.AddNode("CloakStyle", "Palette");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ReplacePaletteModifiers : UpdateRule
|
||||
{
|
||||
public override string Name => "Replace palette modifiers with post-processing shaders.";
|
||||
|
||||
public override string Description =>
|
||||
"MenuPaletteEffect is renamed to MenuPostProcessEffect\n" +
|
||||
"ChronoshiftPaletteEffect is renamed to ChronoshiftPostProcessEffect\n" +
|
||||
"FlashPaletteEffect is renamed to FlashPostProcessEffect\n" +
|
||||
"GlobalLightingPaletteEffect is renamed to TintPostProcessEffect\n" +
|
||||
"D2kFogPalette is removed\n" +
|
||||
"PaletteFromScaledPalette is removed";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RenameChildrenMatching("MenuPaletteEffect", "MenuPostProcessEffect");
|
||||
actorNode.RenameChildrenMatching("ChronoshiftPaletteEffect", "ChronoshiftPostProcessEffect");
|
||||
actorNode.RenameChildrenMatching("FlashPaletteEffect", "FlashPostProcessEffect");
|
||||
actorNode.RenameChildrenMatching("GlobalLightingPaletteEffect", "TintPostProcessEffect");
|
||||
actorNode.RemoveNodes("D2kFogPalette");
|
||||
actorNode.RemoveNodes("PaletteFromScaledPalette");
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
|
||||
{
|
||||
foreach (var warheadNode in weaponNode.ChildrenMatching("Warhead"))
|
||||
if (warheadNode.Value.Value == "FlashPaletteEffect")
|
||||
warheadNode.Value.Value = "FlashEffect";
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds color names to the editor history list.
|
||||
/// </summary>
|
||||
public class EditorMarkerTileLabels : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
public override string Name => "Add labels to MarkerLayerOverlay colors.";
|
||||
public override string Description => "Adds color names to the editor history list.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var layerNode in actorNode.ChildrenMatching("MarkerLayerOverlay"))
|
||||
{
|
||||
foreach (var colorsNode in layerNode.ChildrenMatching("Colors"))
|
||||
{
|
||||
var colors = FieldLoader.GetValue<Color[]>("Colors", colorsNode.Value.Value);
|
||||
colorsNode.Value.Value = null;
|
||||
foreach (var color in colors)
|
||||
{
|
||||
var c = FieldSaver.FormatValue(color);
|
||||
colorsNode.AddNode("notification-added-marker-tiles-markers." + c, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveAlwaysVisible : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove AlwaysVisible";
|
||||
public override string Description => "AlwaysVisible trait was removed and now is the default behavior.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
actorNode.RemoveNodes("AlwaysVisible");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
sealed class RemoveBarracksTypesAndVehiclesTypesInBaseBuilderBotModule : UpdateRule
|
||||
{
|
||||
public override string Name => "Remove BarracksTypes and VehiclesTypes in BaseBuilderBotModule";
|
||||
public override string Description => "BarracksTypes and VehiclesTypes were removed and now BaseBuilderBotModule check by using ProductionTypes.";
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var baseBuilder in actorNode.ChildrenMatching("BaseBuilderBotModule"))
|
||||
{
|
||||
baseBuilder.RemoveNodes("BarracksTypes");
|
||||
baseBuilder.RemoveNodes("VehiclesFactoryTypes");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces the BaseAttackNotifier with a new AttackNotifier that uses the
|
||||
/// new attack system.
|
||||
/// </summary>
|
||||
public class RemoveBuildingInfoAllowPlacementOnResources : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
public override string Name => "Remove AllowPlacementOnResources from BuildingInfo";
|
||||
public override string Description => "Removes AllowPlacementOnResources from BuildingInfo and adds terrains with resources" +
|
||||
"to TerrainTypes (if a Building trait uses AllowPlacementOnResources: true).";
|
||||
|
||||
readonly HashSet<string> terrainTypesWithResources = [];
|
||||
|
||||
IEnumerable<string> IBeforeUpdateActors.BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
|
||||
{
|
||||
var resourceLayerInfo = modData.DefaultRules.Actors[SystemActors.World].TraitInfoOrDefault<ResourceLayerInfo>();
|
||||
if (resourceLayerInfo == null)
|
||||
yield break;
|
||||
|
||||
foreach (var resourceType in resourceLayerInfo.ResourceTypes.Values)
|
||||
{
|
||||
terrainTypesWithResources.Add(resourceType.TerrainType);
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var buildingInfo in actorNode.ChildrenMatching("Building"))
|
||||
{
|
||||
if (buildingInfo.RemoveNodes("AllowPlacementOnResources") == 0)
|
||||
continue;
|
||||
|
||||
var terrainTypesNode = buildingInfo.Value.NodeWithKeyOrDefault("TerrainTypes");
|
||||
if (terrainTypesNode == null)
|
||||
{
|
||||
terrainTypesNode = new MiniYamlNodeBuilder("TerrainTypes", "");
|
||||
buildingInfo.AddNode(terrainTypesNode);
|
||||
}
|
||||
|
||||
var allowedTerrainTypes = terrainTypesNode?.NodeValue<List<string>>() ?? [];
|
||||
foreach (var terrainType in terrainTypesWithResources)
|
||||
{
|
||||
if (!allowedTerrainTypes.Contains(terrainType))
|
||||
allowedTerrainTypes.Add(terrainType);
|
||||
}
|
||||
|
||||
terrainTypesNode.ReplaceValue(string.Join(", ", allowedTerrainTypes));
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces the BaseAttackNotifier with a new AttackNotifier that uses the
|
||||
/// new attack system.
|
||||
/// </summary>
|
||||
public class ReplaceBaseAttackNotifier : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
public override string Name => "Replace BaseAttackNotifier with DamageNotifier";
|
||||
public override string Description => "Replaces the BaseAttackNotifier with a new DamageNotifier that uses BaseBuilding target type.";
|
||||
|
||||
bool any = false;
|
||||
readonly HashSet<string> definedNotifications = [];
|
||||
|
||||
IEnumerable<string> IBeforeUpdateActors.BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
|
||||
{
|
||||
any = false;
|
||||
foreach (var actor in resolvedActors)
|
||||
foreach (var notifier in actor.ChildrenMatching("BaseAttackNotifier"))
|
||||
if (notifier.LastChildMatching("Notification", false) != null)
|
||||
definedNotifications.Add(actor.Key + ":" + notifier.Key);
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var notifier in actorNode.ChildrenMatching("BaseAttackNotifier"))
|
||||
{
|
||||
any = true;
|
||||
notifier.AddNode("ValidTargets", "BaseBuilding");
|
||||
if (!definedNotifications.Contains(actorNode.Key + ":" + notifier.Key))
|
||||
notifier.AddNode("Notification", "BaseAttack");
|
||||
|
||||
notifier.RenameKey("DamageNotifier");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (!any)
|
||||
yield break;
|
||||
|
||||
yield return "BaseAttackNotifier has been replaced by DamageNotifier with ValidTargets: BaseBuilding" +
|
||||
"\nPlease replace the target type or add it to actor types as needed.";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class WithDamageOverlayPropertyRename : UpdateRule, IBeforeUpdateActors
|
||||
{
|
||||
public override string Name => "Renamed `WithDamageOverlay`'s `IdleSequence` to `StartSequence`.";
|
||||
|
||||
public override string Description => "WithDamageOverlay's property `IdleSequence` was renamed to `StartSequence`"
|
||||
+ " and functionality of WithDamageOverlay changed.";
|
||||
|
||||
readonly List<(string, string)> hasIdleDefault = [];
|
||||
readonly List<(string, string)> hasEndDefault = [];
|
||||
|
||||
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
|
||||
{
|
||||
foreach (var actorNode in resolvedActors)
|
||||
foreach (var damage in actorNode.ChildrenMatching("WithDamageOverlay"))
|
||||
if (damage.HasChild("IdleSequence") || damage.HasChild("StartSequence"))
|
||||
hasIdleDefault.Add((actorNode.Key, damage.Key));
|
||||
|
||||
foreach (var actorNode in resolvedActors)
|
||||
foreach (var damage in actorNode.ChildrenMatching("WithDamageOverlay"))
|
||||
if (damage.HasChild("EndSequence"))
|
||||
hasEndDefault.Add((actorNode.Key, damage.Key));
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
|
||||
{
|
||||
foreach (var damage in actorNode.ChildrenMatching("WithDamageOverlay"))
|
||||
{
|
||||
var renamed = false;
|
||||
foreach (var start in damage.ChildrenMatching("IdleSequence"))
|
||||
{
|
||||
start.RenameKey("StartSequence");
|
||||
renamed = true;
|
||||
}
|
||||
|
||||
if (!renamed && !hasIdleDefault.Contains((actorNode.Key, damage.Key)))
|
||||
damage.AddNode("StartSequence", "idle");
|
||||
|
||||
damage.AddNode("LoopCount", 1);
|
||||
|
||||
if (!hasEndDefault.Contains((actorNode.Key, damage.Key)))
|
||||
damage.AddNode("EndSequence", "end");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user