Bump update rules to release-20231010

This commit is contained in:
Gustas
2023-11-10 11:14:48 +02:00
committed by Pavel Penev
parent 73be3641ea
commit 39755a2fce
30 changed files with 2 additions and 1576 deletions

View File

@@ -1,266 +0,0 @@
#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 AddPipDecorationTraits : UpdateRule
{
public override string Name => "Add decoration traits for selection pips.";
public override string Description =>
"The AmmoPool, Cargo, Harvester, and StoresResources traits no longer\n" +
"automatically add pips to the selection box. New traits WithAmmoPipsDecoration,\n" +
"WithCargoPipsDecoration, WithHarvesterPipsDecoration,\n" +
"WithResourceStoragePipsDecoration are added to provide the same functionality.\n\n" +
"Passenger.PipType has been replaced with CustomPipType, which now references a\n" +
"sequence defined in WithCargoDecoration.CustomPipTypeSequences.\n\n" +
"ResourceType.PipColor has been removed and resource pip colours are now defined\n" +
"in WithHarvesterPipsDecoration.ResourceSequences.";
static readonly Dictionary<string, string> PipReplacements = new()
{
{ "transparent", "pip-empty" },
{ "green", "pip-green" },
{ "yellow", "pip-yellow" },
{ "red", "pip-red" },
{ "gray", "pip-gray" },
{ "blue", "pip-blue" },
{ "ammo", "pip-ammo" },
{ "ammoempty", "pip-ammoempty" },
};
bool customPips;
readonly List<string> locations = new();
readonly List<string> cargoPipLocations = new();
readonly HashSet<string> cargoCustomPips = new();
readonly List<string> harvesterPipLocations = new();
readonly Dictionary<string, string> harvesterCustomPips = new();
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (customPips && locations.Count > 0)
yield return "Custom pip Images and Palettes are now defined on the individual With*PipsDecoration traits.\n" +
"You should review the following definitions and manually define the Image and Palette properties as required:\n" +
UpdateUtils.FormatMessageList(locations);
if (cargoCustomPips.Count > 0 && cargoPipLocations.Count > 0)
yield return "Some passenger types define custom cargo pips. Review the following definitions:\n" +
UpdateUtils.FormatMessageList(cargoPipLocations) +
"\nand, if required, add the following to the WithCargoPipsDecoration traits:\n" +
"CustomPipSequences:\n" + cargoCustomPips.Select(p => $"\t{p}: {PipReplacements[p]}").JoinWith("\n");
if (harvesterCustomPips.Count > 0 && harvesterPipLocations.Count > 0)
yield return "Review the following definitions:\n" +
UpdateUtils.FormatMessageList(harvesterPipLocations) +
"\nand, if required, add the following to the WithHarvesterPipsDecoration traits:\n" +
"ResourceSequences:\n" + harvesterCustomPips.Select(kv => $"\t{kv.Key}: {PipReplacements[kv.Value]}").JoinWith("\n");
customPips = false;
locations.Clear();
cargoPipLocations.Clear();
harvesterPipLocations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var addNodes = new List<MiniYamlNodeBuilder>();
foreach (var selectionDecorations in actorNode.ChildrenMatching("SelectionDecorations"))
{
customPips |= selectionDecorations.RemoveNodes("Palette") > 0;
customPips |= selectionDecorations.RemoveNodes("Image") > 0;
}
foreach (var ammoPool in actorNode.ChildrenMatching("AmmoPool"))
{
var ammoPips = new MiniYamlNodeBuilder("WithAmmoPipsDecoration", "");
ammoPips.AddNode("Position", "BottomLeft");
ammoPips.AddNode("RequiresSelection", "true");
var pipCountNode = ammoPool.LastChildMatching("PipCount");
if (pipCountNode != null)
{
ammoPool.RemoveNode(pipCountNode);
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNodeBuilder("-" + ammoPips.Key, ""));
continue;
}
var ammoNode = ammoPool.LastChildMatching("Ammo");
var maxAmmo = ammoNode != null ? ammoNode.NodeValue<int>() : 0;
if (pipCount != maxAmmo)
ammoPips.AddNode("PipCount", pipCount);
}
var pipTypeNode = ammoPool.LastChildMatching("PipType");
if (pipTypeNode != null)
{
ammoPool.RemoveNode(pipTypeNode);
if (PipReplacements.TryGetValue(pipTypeNode.Value.Value.ToLowerInvariant(), out var sequence))
ammoPips.AddNode("FullSequence", sequence);
}
var pipTypeEmptyNode = ammoPool.LastChildMatching("PipTypeEmpty");
if (pipTypeEmptyNode != null)
{
ammoPool.RemoveNode(pipTypeEmptyNode);
if (PipReplacements.TryGetValue(pipTypeEmptyNode.Value.Value.ToLowerInvariant(), out var sequence))
ammoPips.AddNode("EmptySequence", sequence);
}
addNodes.Add(ammoPips);
locations.Add($"{actorNode.Key}: {ammoPips.Key} ({actorNode.Location.Filename})");
}
foreach (var cargo in actorNode.ChildrenMatching("Cargo"))
{
var cargoPips = new MiniYamlNodeBuilder("WithCargoPipsDecoration", "");
cargoPips.AddNode("Position", "BottomLeft");
cargoPips.AddNode("RequiresSelection", "true");
var pipCountNode = cargo.LastChildMatching("PipCount");
if (pipCountNode != null)
{
cargo.RemoveNode(pipCountNode);
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNodeBuilder("-" + cargoPips.Key, ""));
continue;
}
var maxWeightNode = cargo.LastChildMatching("MaxWeight");
var maxWeight = maxWeightNode != null ? maxWeightNode.NodeValue<int>() : 0;
if (pipCount != maxWeight)
cargoPips.AddNode("PipCount", pipCount);
}
else
continue;
addNodes.Add(cargoPips);
locations.Add($"{actorNode.Key}: {cargoPips.Key} ({actorNode.Location.Filename})");
cargoPipLocations.Add($"{actorNode.Key} ({actorNode.Location.Filename})");
}
foreach (var passenger in actorNode.ChildrenMatching("Passenger"))
{
var pipTypeNode = passenger.LastChildMatching("PipType");
if (pipTypeNode != null)
{
pipTypeNode.RenameKey("CustomPipType");
pipTypeNode.Value.Value = pipTypeNode.Value.Value.ToLowerInvariant();
cargoCustomPips.Add(pipTypeNode.Value.Value);
}
}
foreach (var harvester in actorNode.ChildrenMatching("Harvester"))
{
var harvesterPips = new MiniYamlNodeBuilder("WithHarvesterPipsDecoration", "");
harvesterPips.AddNode("Position", "BottomLeft");
harvesterPips.AddNode("RequiresSelection", "true");
// Harvester hardcoded a default PipCount > 0 so we can't use that to determine whether
// this is a definition or an override. Resources isn't ideal either, but is better than nothing
var resourcesNode = harvester.LastChildMatching("Resources");
if (resourcesNode == null)
continue;
var pipCountNode = harvester.LastChildMatching("PipCount");
if (pipCountNode != null)
{
harvester.RemoveNode(pipCountNode);
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNodeBuilder("-" + harvesterPips.Key, ""));
continue;
}
harvesterPips.AddNode("PipCount", pipCount);
}
else
harvesterPips.AddNode("PipCount", 7);
addNodes.Add(harvesterPips);
locations.Add($"{actorNode.Key}: {harvesterPips.Key} ({actorNode.Location.Filename})");
harvesterPipLocations.Add($"{actorNode.Key} ({actorNode.Location.Filename})");
}
foreach (var resourceType in actorNode.ChildrenMatching("ResourceType"))
{
var pipColor = "yellow";
var pipCountNode = resourceType.LastChildMatching("PipColor");
if (pipCountNode != null)
{
pipColor = pipCountNode.Value.Value.ToLowerInvariant();
resourceType.RemoveNode(pipCountNode);
}
var typeNode = resourceType.LastChildMatching("Type");
if (typeNode != null)
harvesterCustomPips.Add(typeNode.Value.Value, pipColor);
}
foreach (var storesResources in actorNode.ChildrenMatching("StoresResources"))
{
var storagePips = new MiniYamlNodeBuilder("WithResourceStoragePipsDecoration", "");
storagePips.AddNode("Position", "BottomLeft");
storagePips.AddNode("RequiresSelection", "true");
var pipCountNode = storesResources.LastChildMatching("PipCount");
if (pipCountNode != null)
{
storesResources.RemoveNode(pipCountNode);
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNodeBuilder("-" + storagePips.Key, ""));
continue;
}
storagePips.AddNode("PipCount", pipCount);
}
else
continue;
// Default pip color changed from yellow to green for consistency with other pip traits
var pipColorNode = storesResources.LastChildMatching("PipColor");
if (pipColorNode != null)
{
storesResources.RemoveNode(pipColorNode);
var type = pipColorNode.Value.Value.ToLowerInvariant();
if (type != "green" && PipReplacements.TryGetValue(type, out var sequence))
storagePips.AddNode("FullSequence", sequence);
}
else
storagePips.AddNode("FullSequence", PipReplacements["yellow"]);
addNodes.Add(storagePips);
locations.Add($"{actorNode.Key}: {storagePips.Key} ({actorNode.Location.Filename})");
}
foreach (var addNode in addNodes)
actorNode.AddNode(addNode);
yield break;
}
}
}

View File

@@ -1,36 +0,0 @@
#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 ChangeTargetLineDelayToMilliseconds : UpdateRule
{
public override string Name => "Changed DrawLineToTarget.Delay interpretation from ticks to milliseconds.";
public override string Description =>
"Going forward, the value of the `Delay` attribute of the `DrawLineToTarget` trait will be\n" +
"interpreted as milliseconds instead of ticks.\n";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var dltt in actorNode.ChildrenMatching("DrawLineToTarget", includeRemovals: false))
{
var delayNode = dltt.LastChildMatching("Delay", false);
if (delayNode != null && Exts.TryParseInt32Invariant(delayNode.Value.Value, out var delay))
delayNode.ReplaceValue((delay * 1000 / 25).ToStringInvariant());
}
yield break;
}
}
}

View File

@@ -1,96 +0,0 @@
#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 ConvertSupportPowerRangesToFootprint : UpdateRule
{
public override string Name => "Convert support power ranges to footprint";
public override string Description =>
"ChronoshiftPower and GrantExternalConditionPower use footprint areas\n" +
"instead of a circular range and they no longer have a fallback default area value.\n" +
"The old Range values will be converted to footprints as part of this update.";
static readonly string[] AffectedTraits = new string[] { "GrantExternalConditionPower", "ChronoshiftPower" };
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var at in AffectedTraits)
foreach (var trait in actorNode.ChildrenMatching(at))
UpdatePower(trait);
yield break;
}
void UpdatePower(MiniYamlNodeBuilder power)
{
var range = 1;
var rangeNode = power.LastChildMatching("Range");
if (rangeNode != null)
{
range = rangeNode.NodeValue<int>();
if (range > 3)
locations.Add($"{rangeNode.Key} ({rangeNode.Location.Filename})");
power.RemoveNode(rangeNode);
}
var size = 2 * range + 1;
power.AddNode(new MiniYamlNodeBuilder("Dimensions", size.ToStringInvariant() + ", " + size.ToStringInvariant()));
var footprint = string.Empty;
var emptycell = range;
var affectedcell = 1;
for (var i = 0; i < size; i++)
{
for (var e = 0; e < emptycell; e++)
footprint += '_';
for (var a = 0; a < affectedcell; a++)
footprint += 'x';
for (var e = 0; e < emptycell; e++)
footprint += '_';
if (i < range)
{
emptycell--;
affectedcell += 2;
}
else
{
emptycell++;
affectedcell -= 2;
}
footprint += ' ';
}
power.AddNode(new MiniYamlNodeBuilder("Footprint", footprint));
}
readonly List<string> locations = new();
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (locations.Count > 0)
yield return "Please check and adjust the new auto-generated dimensions.\n" +
UpdateUtils.FormatMessageList(locations);
locations.Clear();
}
}
}

View File

@@ -1,55 +0,0 @@
#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 CreateFlashPaletteEffectWarhead : UpdateRule
{
public override string Name => "Create FlashPaletteEffectWarhead to replace hardcoded nuke flashing.";
public override string Description => "The trait NukePower (via the NukeLaunch projectile that it uses) no longer has built-in palette flashing.";
readonly List<Tuple<string, string, string>> weaponsToUpdate = new();
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var nukePowerTraits = actorNode.ChildrenMatching("NukePower");
foreach (var nukePowerTrait in nukePowerTraits)
{
var traitName = nukePowerTrait.Key;
var weaponNode = nukePowerTrait.ChildrenMatching("MissileWeapon").FirstOrDefault();
if (weaponNode == null)
continue;
var weaponName = weaponNode.Value.Value;
weaponsToUpdate.Add(new Tuple<string, string, string>(weaponName, traitName, $"{actorNode.Key} ({actorNode.Location.Filename})"));
nukePowerTrait.RemoveNodes("FlashType");
}
yield break;
}
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (weaponsToUpdate.Count > 0)
yield return "Add a FlashPaletteEffectWarhead to the following weapons:\n" +
UpdateUtils.FormatMessageList(weaponsToUpdate.Select(x => $"Weapon `{x.Item1}`, used by trait `{x.Item2}` on actor {x.Item3}"));
weaponsToUpdate.Clear();
}
}
}

View File

@@ -1,117 +0,0 @@
#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 ModernizeDecorationTraits : UpdateRule
{
public override string Name => "Modernize SelectionDecorations and With*Decoration traits.";
public override string Description =>
"The configuration properties exposed on the SelectionDecorations and With*Decoration\n" +
"traits have been reworked. RenderSelectionBars and RenderSelectionBox have been removed from\n" +
"SelectionDecorations. The obsolete ZOffset and ScreenOffset has been removed from With*Decoration, and ReferencePoint has\n" +
"been replaced by Position which takes a single value (TopLeft, TopRight, BottomLeft, BottomRight, Center, or Top).\n" +
"A new Margin property is available to control the decoration offset relative to the edges of the selection box.\n" +
"RenderNameTag has been renamed to WithNameTagDecoration and now behaves like a normal decoration trait.\n";
static readonly string[] LegacyDecorationTraits = { "WithDecoration", "WithSpriteControlGroupDecoration", "WithTextControlGroupDecoration", "WithTextDecoration", "WithBuildingRepairDecoration", "InfiltrateForDecoration" };
static readonly string[] ModernDecorationTraits = { "WithAmmoPipsDecoration", "WithCargoPipsDecoration", "WithHarvesterPipsDecoration", "WithResourceStoragePipsDecoration", "WithNameTagDecoration" };
[Flags]
public enum LegacyReferencePoints
{
Center = 0,
Top = 1,
Bottom = 2,
Left = 4,
Right = 8,
}
static readonly Dictionary<LegacyReferencePoints, string> PositionMap = new()
{
{ LegacyReferencePoints.Center, "Center" },
{ LegacyReferencePoints.Top, "Top" },
{ LegacyReferencePoints.Top | LegacyReferencePoints.Left, "TopLeft" },
{ LegacyReferencePoints.Top | LegacyReferencePoints.Right, "TopRight" },
{ LegacyReferencePoints.Bottom | LegacyReferencePoints.Left, "BottomLeft" },
{ LegacyReferencePoints.Bottom | LegacyReferencePoints.Right, "BottomRight" }
};
readonly Dictionary<string, List<string>> locations = new();
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (locations.Count > 0)
yield return "The way that decorations are positioned relative to the selection box has changed.\n" +
"Review the following definitions and define Margin properties as required:\n" +
UpdateUtils.FormatMessageList(locations.Select(
kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var locationKey = $"{actorNode.Key} ({actorNode.Location.Filename})";
foreach (var trait in LegacyDecorationTraits)
{
foreach (var node in actorNode.ChildrenMatching(trait))
{
node.RemoveNodes("ZOffset");
node.RemoveNodes("ScreenOffset");
var positionNode = node.LastChildMatching("ReferencePoint");
if (positionNode != null)
{
if (!PositionMap.TryGetValue(positionNode.NodeValue<LegacyReferencePoints>(), out var value))
value = "TopLeft";
if (value != "TopLeft")
{
positionNode.RenameKey("Position");
positionNode.ReplaceValue(FieldSaver.FormatValue(value));
}
else
node.RemoveNode(positionNode);
}
locations.GetOrAdd(locationKey).Add(node.Key);
}
}
foreach (var trait in ModernDecorationTraits)
foreach (var node in actorNode.ChildrenMatching(trait))
locations.GetOrAdd(locationKey).Add(node.Key);
foreach (var selection in actorNode.ChildrenMatching("SelectionDecorations"))
{
selection.RemoveNodes("RenderSelectionBars");
selection.RemoveNodes("RenderSelectionBox");
}
foreach (var nameTag in actorNode.ChildrenMatching("RenderNameTag"))
{
nameTag.RenameKey("WithNameTagDecoration");
nameTag.AddNode("Position", "Top");
nameTag.AddNode("UsePlayerColor", "true");
locations.GetOrAdd(locationKey).Add(nameTag.Key);
}
yield break;
}
}
}

View File

@@ -1,72 +0,0 @@
#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 MoveClassicFacingFudge : UpdateRule
{
public override string Name => "UseClassicFacingFudge functionality was moved to Cnc-specific sequence/coordinate code.";
public override string Description =>
"UseClassicFacingFudge has been replaced with ClassicFacingBodyOrientation trait\n" +
"and Classic* variants of *Sequence loaders respectively, both located in Mods.Cnc.";
readonly List<string> locations = new();
public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (locations.Count > 0)
yield return "UseClassicFacingFudge property on BodyOrientation was replaced with ClassicFacingBodyOrientation trait.\n" +
"UseClassicFacingFudge for sequences was renamed to UseClassicFacings and moved to\n" +
"Classic(TileSetSpecific)SpriteSequence loaders in Mods.Cnc.\n" +
"Update SpriteSequenceFormat: in mod.yaml accordingly.\n" +
"Make sure that actors implementing the following places don't use or inherit the standard BodyOrientation:\n" +
UpdateUtils.FormatMessageList(locations);
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var bo in actorNode.ChildrenMatching("BodyOrientation"))
{
var usesClassicFacings = false;
var facingFudgeNode = bo.LastChildMatching("UseClassicFacingFudge");
if (facingFudgeNode != null)
{
usesClassicFacings = facingFudgeNode.NodeValue<bool>();
bo.RemoveNode(facingFudgeNode);
}
if (usesClassicFacings)
{
bo.RenameKey("ClassicFacingBodyOrientation");
locations.Add($"{actorNode.Key} ({actorNode.Location.Filename})");
}
}
yield break;
}
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode)
{
foreach (var sequence in sequenceNode.Value.Nodes)
{
var facingFudgeNode = sequence.LastChildMatching("UseClassicFacingFudge");
facingFudgeNode?.RenameKey("UseClassicFacings");
}
yield break;
}
}
}

View File

@@ -1,28 +0,0 @@
#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 RemoveConditionManager : UpdateRule
{
public override string Name => "ConditionManager trait has been removed.";
public override string Description => "ConditionManager trait has been removed. Its functionality has been integrated into the actor itself.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RemoveNodes("ConditionManager");
yield break;
}
}
}

View File

@@ -1,28 +0,0 @@
#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 RemoveLaysTerrain : UpdateRule
{
public override string Name => "'LaysTerrain' has been removed in favor of the new 'D2kBuilding' trait.";
public override string Description => "'LaysTerrain' was removed.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("LaysTerrain") > 0)
yield return $"'LaysTerrain' was removed from {actorNode.Key} ({actorNode.Location.Filename}) without replacement.\n";
}
}
}

View File

@@ -1,48 +0,0 @@
#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 RemoveMuzzleSplitFacings : UpdateRule
{
public override string Name => "Remove Armament.MuzzleSplitFacings.";
public override string Description =>
"The legacy MuzzleSplitFacings option was removed from Armament.\n" +
"The same result can be created by using `Combine` in the sequence definitions to\n" +
"assemble the different facings sprites into a single sequence.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var a in actorNode.ChildrenMatching("Armament"))
{
var muzzleSplitFacings = a.LastChildMatching("MuzzleSplitFacings");
var sequenceNode = a.LastChildMatching("MuzzleSequence");
if (muzzleSplitFacings != null && sequenceNode != null)
{
var sequence = sequenceNode.Value.Value;
var facings = muzzleSplitFacings.NodeValue<int>() - 1;
var actor = actorNode.Key.ToLowerInvariant();
yield return
$"The Armament muzzle effect has been removed from {actor} ({actorNode.Location.Filename}).\n" +
$"If you would like to restore the muzzle effect you must redefine `MuzzleSequence: {sequence}`\n" +
$"and replace the {sequence}0-{facings} sequence definitions with a single `{sequence}` sequence that uses\n" +
"the Combine syntax to assemble the different facing sprites.";
a.RemoveNode(muzzleSplitFacings);
a.RemoveNode(sequenceNode);
}
}
}
}
}

View File

@@ -1,55 +0,0 @@
#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 RemoveTurnToDock : UpdateRule
{
public override string Name => "TurnToDock is removed from the Aircraft trait.";
public override string Description =>
"TurnToDock is removed from the Aircraft trait in favor of letting the Exit trait on the host" +
"building determine whether or not turning is required and to what facing the aircraft must turn.";
readonly List<Tuple<string, string>> turningAircraft = new();
public override IEnumerable<string> AfterUpdate(ModData modData)
{
var message = "TurnToDock is now deprecated. The following actors had TurnToDock enabled:\n"
+ UpdateUtils.FormatMessageList(turningAircraft.Select(n => n.Item1 + " (" + n.Item2 + ")"))
+ "\n If you wish these units to keep their turning behaviour when docking with a host building" +
" you will need to define a 'Facing' parameter on the 'Exit' trait of the host building. This change" +
" does not affect the behaviour for landing on terrain which is governed by TurnToLand.";
if (turningAircraft.Count > 0)
yield return message;
turningAircraft.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var aircraft = actorNode.LastChildMatching("Aircraft");
if (aircraft != null)
{
var turnToDock = aircraft.LastChildMatching("TurnToDock");
if (turnToDock == null || !turnToDock.NodeValue<bool>())
yield break;
turningAircraft.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename));
}
}
}
}

View File

@@ -1,33 +0,0 @@
#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 RenameCircleContrast : UpdateRule
{
public override string Name => "Rename 'ContrastColor' to 'BorderColor'.";
public override string Description => "RenderDetectionCircle and RenderShroudCircle ContrastColor have been renamed to BorderColor for consistency.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var rdc in actorNode.ChildrenMatching("RenderDetectionCircle"))
rdc.RenameChildrenMatching("ContrastColor", "BorderColor");
foreach (var rsc in actorNode.ChildrenMatching("RenderShroudCircle"))
rsc.RenameChildrenMatching("ContrastColor", "BorderColor");
yield break;
}
}
}

View File

@@ -1,30 +0,0 @@
#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 RenameHealCrateAction : UpdateRule
{
public override string Name => "Rename 'HealUnitsCrateAction' to 'HealActorsCrateAction'.";
public override string Description => "The 'HealUnitsCrateAction' has been renamed to 'HealActorsCrateAction'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var huca in actorNode.ChildrenMatching("HealUnitsCrateAction"))
huca.RenameKey("HealActorsCrateAction");
yield break;
}
}
}

View File

@@ -1,30 +0,0 @@
#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 RenameInfiltrationNotifications : UpdateRule
{
public override string Name => "Renamed InfiltrateForCash Notification to InfiltratedNotification.";
public override string Description => "The InfiltrateForCash Notification has been renamed to be in line with new notification properties added.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var rp in actorNode.ChildrenMatching("InfiltrateForCash"))
rp.RenameChildrenMatching("Notification", "InfiltratedNotification");
yield break;
}
}
}

View File

@@ -1,35 +0,0 @@
#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 RenameSelfHealing : UpdateRule
{
public override string Name => "SelfHealing was renamed as negative SelfHealing is a common usecase.";
public override string Description =>
"SelfHealing was renamed to ChangesHealth\n" +
"HealIfBelow was renamed to StartIfBelow.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var sh in actorNode.ChildrenMatching("SelfHealing"))
{
sh.RenameChildrenMatching("HealIfBelow", "StartIfBelow");
sh.RenameKey("ChangesHealth");
}
yield break;
}
}
}

View File

@@ -1,50 +0,0 @@
#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 RenameSmudgeSmokeFields : UpdateRule
{
public override string Name => "Renamed smoke-related properties on SmudgeLayer.";
public override string Description =>
"Renamed smoke-related properties on SmudgeLayer to be in line with comparable properties.\n" +
"Additionally, set the *Chance, *Image and *Sequences defaults to null.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var layer in actorNode.ChildrenMatching("SmudgeLayer"))
{
var chance = layer.LastChildMatching("SmokePercentage");
if (chance != null)
chance.RenameKey("SmokeChance");
else
layer.AddNode("SmokeChance", FieldSaver.FormatValue("25"));
var image = layer.LastChildMatching("SmokeType");
if (image != null)
image.RenameKey("SmokeImage");
else
layer.AddNode("SmokeImage", FieldSaver.FormatValue("smoke_m"));
var sequences = layer.LastChildMatching("SmokeSequence");
if (sequences != null)
sequences.RenameKey("SmokeSequences");
else
layer.AddNode("SmokeSequences", FieldSaver.FormatValue("idle"));
}
yield break;
}
}
}

View File

@@ -1,100 +0,0 @@
#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 RenameStances : UpdateRule
{
public override string Name => "Renamed player 'Stances' to 'Relationships'.";
public override string Description =>
"'Stances' in regards to a player have been renamed to 'Relationships'.\n" +
"The yaml values did not change.";
readonly (string TraitName, string OldName, string NewName)[] traits =
{
("Disguise", "ValidStances", "ValidRelationships"),
("Infiltrates", "ValidStances", "ValidRelationships"),
("AcceptsDeliveredCash", "ValidStances", "ValidRelationships"),
("AcceptsDeliveredExperience", "ValidStances", "ValidRelationships"),
("Armament", "TargetStances", "TargetRelationships"),
("Armament", "ForceTargetStances", "ForceTargetRelationships"),
("AutoTargetPriority", "ValidStances", "ValidRelationships"),
("CaptureManagerBotModule", "CapturableStances", "CapturableRelationships"),
("Capturable", "ValidStances", "ValidRelationships"),
("Captures", "PlayerExperienceStances", "PlayerExperienceRelationships"),
("ProximityExternalCondition", "ValidStances", "ValidRelationships"),
("CreatesShroud", "ValidStances", "ValidRelationships"),
("Demolition", "TargetStances", "TargetRelationships"),
("Demolition", "ForceTargetStances", "ForceTargetRelationships"),
("EngineerRepair", "ValidStances", "ValidRelationships"),
("GivesBounty", "ValidStances", "ValidRelationships"),
("GivesExperience", "ValidStances", "ValidRelationships"),
("JamsMissiles", "DeflectionStances", "DeflectionRelationships"),
("FrozenUnderFog", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
("HiddenUnderShroud", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
("HiddenUnderFog", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
("AppearsOnRadar", "ValidStances", "ValidRelationships"),
("CashTricklerBar", "DisplayStances", "DisplayRelationships"),
("SupportPowerChargeBar", "DisplayStances", "DisplayRelationships"),
("WithAmmoPipsDecoration", "ValidStances", "ValidRelationships"),
("WithCargoPipsDecoration", "ValidStances", "ValidRelationships"),
("WithDecoration", "ValidStances", "ValidRelationships"),
("WithHarvesterPipsDecoration", "ValidStances", "ValidRelationships"),
("WithNameTagDecoration", "ValidStances", "ValidRelationships"),
("WithResourceStoragePipsDecoration", "ValidStances", "ValidRelationships"),
("WithTextDecoration", "ValidStances", "ValidRelationships"),
("WithRangeCircle", "ValidStances", "ValidRelationships"),
("RevealOnDeath", "RevealForStances", "RevealForRelationships"),
("RevealOnFire", "RevealForStancesRelativeToTarget", "RevealForRelationships"),
("RevealsMap", "ValidStances", "ValidRelationships"),
("RevealsShroud", "ValidStances", "ValidRelationships"),
("VoiceAnnouncement", "ValidStances", "ValidRelationships"),
("GrantExternalConditionPower", "ValidStances", "ValidRelationships"),
("NukePower", "CameraStances", "CameraRelationships"),
("NukePower", "DisplayTimerStances", "DisplayTimerRelationships"),
("AttackOrderPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("ChronoshiftPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("DropPodsPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("GpsPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("GrantPrerequisiteChargeDrainPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("IonCannonPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("AirstrikePower", "DisplayTimerStances", "DisplayTimerRelationships"),
("GrantExternalConditionPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("ParatroopersPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("ProduceActorPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("SpawnActorPower", "DisplayTimerStances", "DisplayTimerRelationships"),
("TooltipDescription", "ValidStances", "ValidRelationships")
};
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var (traitName, oldName, newName) in traits)
foreach (var traitNode in actorNode.ChildrenMatching(traitName))
traitNode.RenameChildrenMatching(oldName, newName);
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
projectileNode.RenameChildrenMatching("ValidBounceBlockerStances", "ValidBounceBlockerRelationships");
foreach (var warheadNode in weaponNode.ChildrenMatching("Warhead"))
warheadNode.RenameChildrenMatching("ValidStances", "ValidRelationships");
yield break;
}
}
}

View File

@@ -1,30 +0,0 @@
#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 RenameWithNukeLaunch : UpdateRule
{
public override string Name => "Renamed WithNukeLaunchAnimation and Overlay";
public override string Description => "`WithNukeLaunchAnimation` has been renamed to `WithSupportPowerActivationAnimation` and `WithNukeLaunchOverlay` to `WithSupportPowerActivationOverlay`.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RenameChildrenMatching("WithNukeLaunchAnimation", "WithSupportPowerActivationAnimation", true);
actorNode.RenameChildrenMatching("WithNukeLaunchOverlay", "WithSupportPowerActivationOverlay", true);
yield break;
}
}
}

View File

@@ -1,58 +0,0 @@
#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 ReplaceBurns : UpdateRule
{
public override string Name => "Replaced Burns with separate render and health change traits.";
public override string Description => "Burns can be replaced using WithIdleOverlay and ChangesHealth.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var addNodes = new List<MiniYamlNodeBuilder>();
foreach (var burns in actorNode.ChildrenMatching("Burns"))
{
var anim = burns.LastChildMatching("Anim");
var animValue = anim != null ? anim.NodeValue<string>() : "1";
var damage = burns.LastChildMatching("Damage");
var damageValue = damage != null ? damage.NodeValue<int>() : 1;
var interval = burns.LastChildMatching("Interval");
var intervalValue = interval != null ? interval.NodeValue<int>() : 8;
var overlay = new MiniYamlNodeBuilder("WithIdleOverlay@Burns", "");
overlay.AddNode("Image", FieldSaver.FormatValue("fire"));
overlay.AddNode("Sequence", FieldSaver.FormatValue(animValue));
overlay.AddNode("IsDecoration", FieldSaver.FormatValue(true));
addNodes.Add(overlay);
var changesHealth = new MiniYamlNodeBuilder("ChangesHealth", "");
changesHealth.AddNode("Step", FieldSaver.FormatValue(-damageValue));
changesHealth.AddNode("StartIfBelow", FieldSaver.FormatValue(101));
changesHealth.AddNode("Delay", FieldSaver.FormatValue(intervalValue));
addNodes.Add(changesHealth);
}
actorNode.RemoveNodes("Burns");
foreach (var addNode in addNodes)
actorNode.AddNode(addNode);
yield break;
}
}
}

View File

@@ -1,116 +0,0 @@
#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
{
sealed class ReplaceFacingAngles : UpdateRule
{
static readonly Dictionary<string, string[]> TraitFields = new()
{
{ "Aircraft", new[] { "InitialFacing", "PreviewFacing", "TurnSpeed", "IdleTurnSpeed" } },
{ "Mobile", new[] { "InitialFacing", "PreviewFacing", "TurnSpeed" } },
{ "Husk", new[] { "PreviewFacing" } },
{ "Turreted", new[] { "InitialFacing", "TurnSpeed" } },
{ "GrantConditionOnDeploy", new[] { "Facing" } },
{ "FreeActor", new[] { "Facing" } },
{ "ProductionAirdrop", new[] { "Facing" } },
{ "EditorCursorLayer", new[] { "PreviewFacing" } },
{ "MPStartUnits", new[] { "BaseActorFacing", "SupportActorsFacing" } },
{ "Refinery", new[] { "DockAngle" } },
{ "Cargo", new[] { "PassengerFacing" } },
{ "Exit", new[] { "Facing" } },
{ "ThrowsParticle", new[] { "TurnSpeed" } },
{ "Transforms", new[] { "Facing" } },
{ "FallsToEarth", new[] { "MaximumSpinSpeed" } },
{ "ConyardChronoReturn", new[] { "Facing" } },
{ "TDGunboat", new[] { "InitialFacing", "PreviewFacing" } },
{ "DropPodsPower", new[] { "PodFacing" } },
{ "TiberianSunRefinery", new[] { "DockAngle" } },
{ "AttackAircraft", new[] { "FacingTolerance" } },
{ "AttackBomber", new[] { "FacingTolerance" } },
{ "AttackCharges", new[] { "FacingTolerance" } },
{ "AttackFollow", new[] { "FacingTolerance" } },
{ "AttackFrontal", new[] { "FacingTolerance" } },
{ "AttackGarrisoned", new[] { "FacingTolerance" } },
{ "AttackOmni", new[] { "FacingTolerance" } },
{ "AttackTurreted", new[] { "FacingTolerance" } },
{ "AttackLeap", new[] { "FacingTolerance" } },
{ "AttackPopupTurreted", new[] { "DefaultFacing", "FacingTolerance" } },
{ "AttackTDGunboatTurreted", new[] { "FacingTolerance" } },
{ "AttackTesla", new[] { "FacingTolerance" } },
};
static readonly Dictionary<string, string[]> ProjectileFields = new()
{
{ "Missile", new[] { "HorizontalRateOfTurn", "VerticalRateOfTurn" } }
};
public override string Name => "Increase facing angle resolution";
public override string Description
{
get
{
return "Trait fields that defined facings (0-255) have been replaced with higher resolution angles (0-1023).\n" +
"Values for the following trait fields should be multiplied by 4, or if undefined (-1) replaced by an empty definition:\n" +
UpdateUtils.FormatMessageList(TraitFields.Select(t => t.Key + "\n" + UpdateUtils.FormatMessageList(t.Value))) + "\n" +
"Values for the following projectile files should be multiplied by 4:\n" +
UpdateUtils.FormatMessageList(ProjectileFields.Select(t => t.Key + "\n" + UpdateUtils.FormatMessageList(t.Value)));
}
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var kv in TraitFields)
{
foreach (var traitNode in actorNode.ChildrenMatching(kv.Key))
{
foreach (var fieldName in kv.Value)
{
foreach (var fieldNode in traitNode.ChildrenMatching(fieldName))
{
var value = fieldNode.NodeValue<int>();
fieldNode.Value.Value = value != -1 ? FieldSaver.FormatValue(value != 255 ? 4 * value : 1023) : "";
}
}
}
}
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
{
if (projectileNode.Value.Value == null)
continue;
if (ProjectileFields.TryGetValue(projectileNode.Value.Value, out var fieldNames))
{
foreach (var fieldName in fieldNames)
{
foreach (var fieldNode in projectileNode.ChildrenMatching(fieldName))
{
var value = fieldNode.NodeValue<int>();
fieldNode.Value.Value = FieldSaver.FormatValue(value != 255 ? 4 * value : 1023);
}
}
}
}
yield break;
}
}
}

View File

@@ -1,34 +0,0 @@
#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 SpawnActorPowerDefaultEffect : UpdateRule
{
public override string Name => "Set SpawnActorPower EffectSequence to it's previous default value.";
public override string Description => "The 'EffectSequence' of 'SpawnActorPower' is unset by default.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var spawnActorPower in actorNode.ChildrenMatching("SpawnActorPower"))
{
var effectNode = spawnActorPower.LastChildMatching("EffectSequence");
if (effectNode == null)
spawnActorPower.AddNode("EffectSequence", "idle");
}
yield break;
}
}
}

View File

@@ -1,33 +0,0 @@
#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 SplitDamagedByTerrain : UpdateRule
{
public override string Name => "Several properties of 'DamagedByTerrain' have been moved to the new 'D2kBuilding' trait.";
public override string Description => "'DamageThreshold' and 'StartOnThreshold' are no longer supported and removed from 'DamagedByTerrain'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var damaged in actorNode.ChildrenMatching("DamagedByTerrain", includeRemovals: false))
{
if (damaged.RemoveNodes("DamageThreshold") > 0)
yield return $"'DamageThreshold' was removed from {actorNode.Key} ({actorNode.Location.Filename}) without replacement.\n";
if (damaged.RemoveNodes("StartOnThreshold") > 0)
yield return $"'StartOnThreshold' was removed from {actorNode.Key} ({actorNode.Location.Filename}) without replacement.\n";
}
}
}
}

View File

@@ -1,73 +0,0 @@
#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 UpdateMapInits : UpdateRule
{
public override string Name => "Update map actor definitions";
public override string Description
{
get
{
return "Several changes have been made to initial actor state in maps:\n" +
UpdateUtils.FormatMessageList(new[]
{
"Facing is now defined as a world angle",
"TurretFacing is now defined as a world angle relative to Facing",
"Plugs has been removed (use Plug instead)",
"TurretFacings has been removed (use TurretFacing instead)"
}) +
"\nMaps are automatically updated to keep the previous actor facings.";
}
}
public override IEnumerable<string> UpdateMapActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("Plugs") > 0)
yield return $"Initial plugs for actor {actorNode.Key} will need to be reconfigured using the map editor.";
if (actorNode.RemoveNodes("TurretFacings") > 0)
yield return $"Initial turret facings for actor {actorNode.Key} will need to be reconfigured using the map editor.";
var bodyFacing = WAngle.Zero;
foreach (var facing in actorNode.ChildrenMatching("Facing"))
{
bodyFacing = WAngle.FromFacing(facing.NodeValue<int>());
facing.ReplaceValue(FieldSaver.FormatValue(bodyFacing));
}
var removeNodes = new List<MiniYamlNodeBuilder>();
foreach (var facing in actorNode.ChildrenMatching("TurretFacing"))
{
var turretFacing = WAngle.FromFacing(facing.NodeValue<int>()) - bodyFacing;
if (turretFacing == WAngle.Zero)
removeNodes.Add(facing);
else
facing.ReplaceValue(FieldSaver.FormatValue(turretFacing));
}
foreach (var node in removeNodes)
actorNode.Value.Nodes.Remove(node);
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var turret in actorNode.ChildrenMatching("Turreted"))
turret.RemoveNodes("PreviewFacing");
yield break;
}
}
}

View File

@@ -1,44 +0,0 @@
#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 UpdateTilesetColors : UpdateRule
{
public override string Name => "Rename Tileset LeftColor and RightColor";
public override string Description => "The LeftColor and RightColor keys in tilesets have been renamed to MinColor and MaxColor to reflect their proper usage.";
public override IEnumerable<string> UpdateTilesetNode(ModData modData, MiniYamlNodeBuilder tilesetNode)
{
if (tilesetNode.Key == "Templates")
{
foreach (var templateNode in tilesetNode.Value.Nodes)
{
foreach (var tilesNode in templateNode.ChildrenMatching("Tiles"))
{
foreach (var node in tilesNode.Value.Nodes)
{
foreach (var leftNode in node.ChildrenMatching("LeftColor"))
leftNode.RenameKey("MinColor");
foreach (var leftNode in node.ChildrenMatching("RightColor"))
leftNode.RenameKey("MaxColor");
}
}
}
}
yield break;
}
}
}

View File

@@ -1,80 +0,0 @@
#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.Globalization;
using System.IO;
using OpenRA.Mods.Common.FileFormats;
namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class CopyIsometricSelectableHeight : UpdateRule
{
public override string Name => "Copy IsometricSelectable.Height from art*.ini definitions.";
public override string Description =>
"Reads building Height entries art.ini/artfs.ini/artmd.ini from the current working directory\n" +
"and adds IsometricSelectable definitions to matching actors.";
static readonly string[] SourceFiles = { "art.ini", "artfs.ini", "artmd.ini" };
readonly Dictionary<string, int> selectionHeight = new();
bool complete;
public override IEnumerable<string> BeforeUpdate(ModData modData)
{
if (complete)
yield break;
var grid = Game.ModData.Manifest.Get<MapGrid>();
foreach (var filename in SourceFiles)
{
if (!File.Exists(filename))
continue;
var file = new IniFile(File.Open(filename, FileMode.Open));
foreach (var section in file.Sections)
{
if (!section.Contains("Height"))
continue;
selectionHeight[section.Name] = (int)(float.Parse(section.GetValue("Height", "1"), NumberFormatInfo.InvariantInfo) * grid.TileSize.Height);
}
}
}
public override IEnumerable<string> AfterUpdate(ModData modData)
{
// Rule only applies to the default ruleset - skip maps
complete = true;
yield break;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (complete || actorNode.LastChildMatching("IsometricSelectable") != null)
yield break;
if (!selectionHeight.TryGetValue(actorNode.Key.ToLowerInvariant(), out var height))
yield break;
// Don't redefine the default value
if (height == 24)
yield break;
var selection = new MiniYamlNodeBuilder("IsometricSelectable", "");
selection.AddNode("Height", FieldSaver.FormatValue(height));
actorNode.AddNode(selection);
}
}
}

View File

@@ -31,33 +31,6 @@ namespace OpenRA.Mods.Common.UpdateRules
// release-to-bleed path.
static readonly UpdatePath[] Paths =
{
new UpdatePath("release-20200503", "release-20210321", new UpdateRule[]
{
new AddPipDecorationTraits(),
new ModernizeDecorationTraits(),
new RenameHealCrateAction(),
new RenameInfiltrationNotifications(),
new MoveClassicFacingFudge(),
new RenameWithNukeLaunch(),
new SpawnActorPowerDefaultEffect(),
new RemoveConditionManager(),
new ConvertSupportPowerRangesToFootprint(),
new UpdateTilesetColors(),
new UpdateMapInits(),
new CreateFlashPaletteEffectWarhead(),
new ChangeTargetLineDelayToMilliseconds(),
new ReplaceFacingAngles(),
new RenameSelfHealing(),
new ReplaceBurns(),
new RemoveMuzzleSplitFacings(),
new RenameStances(),
new RemoveTurnToDock(),
new RenameSmudgeSmokeFields(),
new RenameCircleContrast(),
new SplitDamagedByTerrain(),
new RemoveLaysTerrain(),
}),
new UpdatePath("release-20210321", "release-20230225", new UpdateRule[]
{
new RenameMPTraits(),
@@ -88,7 +61,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new UnhardcodeBaseBuilderBotModule(),
}),
new UpdatePath("release-20230225", "playtest-20230801", new UpdateRule[]
new UpdatePath("release-20230225", "release-20231010", new UpdateRule[]
{
new TextNotificationsDisplayWidgetRemoveTime(),
new RenameEngineerRepair(),
@@ -105,7 +78,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new RemoveNegativeSequenceLength(),
}),
new UpdatePath("playtest-20230801", new UpdateRule[]
new UpdatePath("release-20231010", new UpdateRule[]
{
// bleed only changes here.
new RemoveValidRelationsFromCapturable(),