diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 03d2ed1e13..ceaa777a7a 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -592,13 +592,20 @@ + + + + + + + diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/MoveVisualBounds.cs b/OpenRA.Mods.Common/UpdateRules/Rules/MoveVisualBounds.cs new file mode 100644 index 0000000000..432876dd19 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/MoveVisualBounds.cs @@ -0,0 +1,72 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 MoveVisualBounds : UpdateRule + { + public override string Name { get { return "Move 'SelectionDecorations.VisualBounds' to 'Selectable.Bounds'"; } } + public override string Description + { + get + { + return "'SelectionDecorations.VisualBounds' was moved to 'Selectable.Bounds'.\n" + + "'AutoRenderSize' and 'CustomRenderSize' were renamed to 'Interactable'."; + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var autoSelectionSize = actorNode.LastChildMatching("AutoSelectionSize"); + if (autoSelectionSize != null) + actorNode.AddNode("Interactable", ""); + + var customSelectionSize = actorNode.LastChildMatching("CustomSelectionSize"); + if (customSelectionSize != null) + { + var bounds = customSelectionSize.LastChildMatching("CustomBounds"); + var customRenderSize = new MiniYamlNode("Interactable", ""); + if (bounds != null) + customRenderSize.AddNode("Bounds", bounds.NodeValue()); + + actorNode.AddNode(customRenderSize); + } + + var sd = actorNode.LastChildMatching("SelectionDecorations"); + if (sd != null) + { + var boundsNode = sd.LastChildMatching("VisualBounds"); + if (boundsNode != null) + { + boundsNode.RenameKey("DecorationBounds"); + sd.RemoveNode(boundsNode); + var selectable = actorNode.LastChildMatching("Selectable"); + if (selectable == null) + { + selectable = new MiniYamlNode("Selectable", new MiniYaml("")); + actorNode.AddNode(selectable); + } + + selectable.AddNode(boundsNode); + } + } + + if (actorNode.LastChildMatching("-Selectable") != null && actorNode.LastChildMatching("Interactable") == null) + actorNode.AddNode("Interactable", ""); + + actorNode.RemoveNodes("CustomSelectionSize"); + actorNode.RemoveNodes("AutoSelectionSize"); + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/RemoveIDisable.cs b/OpenRA.Mods.Common/UpdateRules/Rules/RemoveIDisable.cs new file mode 100644 index 0000000000..9d116d6a1b --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/RemoveIDisable.cs @@ -0,0 +1,47 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 RemoveIDisable : UpdateRule + { + public override string Name { get { return "Remove 'IDisabled'"; } } + public override string Description + { + get + { + return "'Actor.IsDisabled' has been removed in favor of pausing/disabling traits via conditions."; + } + } + + bool displayed; + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var doc = actorNode.LastChildMatching("DisableOnCondition"); + var grant = actorNode.LastChildMatching("GrantConditionOnDisabled"); + + if (!displayed && (doc != null || grant != null)) + { + displayed = true; + yield return "Actor.IsDisabled has been removed in favor of pausing/disabling traits via conditions.\n" + + "DisableOnCondition and GrantConditionOnDisabled were stop-gap solutions that have been removed along with it.\n" + + "You'll have to use RequiresCondition or PauseOnCondition on individual traits to 'disable' actors."; + } + + actorNode.RemoveNodes("DisableOnCondition"); + actorNode.RemoveNodes("GrantConditionOnDisabled"); + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/RenameBurstDelay.cs b/OpenRA.Mods.Common/UpdateRules/Rules/RenameBurstDelay.cs new file mode 100644 index 0000000000..949127a435 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/RenameBurstDelay.cs @@ -0,0 +1,37 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 RenameBurstDelay : UpdateRule + { + public override string Name { get { return "BurstDelay was renamed to BurstDelays due to support of multiple values."; } } + public override string Description + { + get + { + return "It's now possible to set multiple delay values (one for each consecutive burst),\n" + + "so the property was renamed to BurstDelays to account for this."; + } + } + + public override IEnumerable UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode) + { + var bd = weaponNode.LastChildMatching("BurstDelay"); + if (bd != null) + bd.RenameKey("BurstDelays"); + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/ReplaceCanPowerDown.cs b/OpenRA.Mods.Common/UpdateRules/Rules/ReplaceCanPowerDown.cs new file mode 100644 index 0000000000..11b0cdf83e --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/ReplaceCanPowerDown.cs @@ -0,0 +1,74 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 ReplaceCanPowerDown : UpdateRule + { + public override string Name { get { return "Replace 'CanPowerDown' by 'ToggleConditionOnOrder'"; } } + public override string Description + { + get + { + return "'CanPowerDown' was replaced with a more general 'ToggleConditionOnOrder' trait."; + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var cpd = actorNode.LastChildMatching("CanPowerDown"); + if (cpd == null) + yield break; + + cpd.RenameKey("ToggleConditionOnOrder"); + var upSound = cpd.LastChildMatching("PowerupSound"); + if (upSound != null) + upSound.RenameKey("DisabledSound"); + + var upSpeech = cpd.LastChildMatching("PowerupSpeech"); + if (upSpeech != null) + upSpeech.RenameKey("DisabledSpeech"); + + var downSound = cpd.LastChildMatching("PowerdownSound"); + if (downSound != null) + downSound.RenameKey("EnabledSound"); + + var downSpeech = cpd.LastChildMatching("PowerdownSpeech"); + if (downSpeech != null) + downSpeech.RenameKey("EnabledSpeech"); + + cpd.AddNode("OrderName", "PowerDown"); + + var condition = cpd.LastChildMatching("PowerdownCondition"); + if (condition != null) + condition.RenameKey("Condition"); + else + cpd.AddNode("Condition", "powerdown"); + + if (cpd.ChildrenMatching("CancelWhenDisabled").Any()) + { + cpd.RemoveNodes("CancelWhenDisabled"); + yield return "CancelWhenDisabled was removed when CanPowerDown was replaced by ToggleConditionOnOrder.\n" + + "Use PauseOnCondition instead of RequiresCondition to replicate the behavior of 'false'."; + } + + actorNode.AddNode(new MiniYamlNode("PowerMultiplier@POWERDOWN", new MiniYaml("", new List() + { + new MiniYamlNode("RequiresCondition", condition.Value.Value), + new MiniYamlNode("Modifier", "0") + }))); + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/ReworkCheckboxes.cs b/OpenRA.Mods.Common/UpdateRules/Rules/ReworkCheckboxes.cs new file mode 100644 index 0000000000..4ee1a679d1 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/ReworkCheckboxes.cs @@ -0,0 +1,145 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 ReworkCheckboxes : UpdateRule + { + public override string Name { get { return "Rename 'Locked' and 'Enabled' on checkboxes and dropdowns"; } } + public override string Description + { + get + { + return "'Locked' and 'Enabled' were renamed to contain the respective checkboxes' name,\n" + + "like 'FogCheckboxLocked'. For dropdowns 'Locked' was renamed to 'DropdownLocked'."; + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var mpUnits = actorNode.LastChildMatching("SpawnMPUnits"); + if (mpUnits != null) + { + var locked = mpUnits.LastChildMatching("Locked"); + if (locked != null) + locked.RenameKey("DropdownLocked"); + } + + var shroud = actorNode.LastChildMatching("Shroud"); + if (shroud != null) + { + var fogLocked = shroud.LastChildMatching("FogLocked"); + if (fogLocked != null) + fogLocked.RenameKey("FogCheckboxLocked"); + + var fogEnabled = shroud.LastChildMatching("FogEnabled"); + if (fogEnabled != null) + fogEnabled.RenameKey("FogCheckboxEnabled"); + + var exploredMapLocked = shroud.LastChildMatching("ExploredMapLocked"); + if (exploredMapLocked != null) + exploredMapLocked.RenameKey("ExploredMapCheckboxLocked"); + + var exploredMapEnabled = shroud.LastChildMatching("ExploredMapEnabled"); + if (exploredMapEnabled != null) + exploredMapEnabled.RenameKey("ExploredMapCheckboxEnabled"); + } + + var options = actorNode.LastChildMatching("MapOptions"); + if (options != null) + { + var shortGameLocked = options.LastChildMatching("ShortGameLocked"); + if (shortGameLocked != null) + shortGameLocked.RenameKey("ShortGameCheckboxLocked"); + + var shortGameEnabled = options.LastChildMatching("ShortGameEnabled"); + if (shortGameEnabled != null) + shortGameEnabled.RenameKey("ShortGameCheckboxEnabled"); + + var techLevelLocked = options.LastChildMatching("TechLevelLocked"); + if (techLevelLocked != null) + techLevelLocked.RenameKey("TechLevelDropdownLocked"); + + var gameSpeedLocked = options.LastChildMatching("GameSpeedLocked"); + if (gameSpeedLocked != null) + gameSpeedLocked.RenameKey("GameSpeedDropdownLocked"); + } + + var creeps = actorNode.LastChildMatching("MapCreeps"); + if (creeps != null) + { + var locked = creeps.LastChildMatching("Locked"); + if (locked != null) + locked.RenameKey("CheckboxLocked"); + + var enabled = creeps.LastChildMatching("Enabled"); + if (enabled != null) + enabled.RenameKey("CheckboxEnabled"); + } + + var buildRadius = actorNode.LastChildMatching("MapBuildRadius"); + if (buildRadius != null) + { + var alllyLocked = buildRadius.LastChildMatching("AllyBuildRadiusLocked"); + if (alllyLocked != null) + alllyLocked.RenameKey("AllyBuildRadiusCheckboxLocked"); + + var allyEnabled = buildRadius.LastChildMatching("AllyBuildRadiusEnabled"); + if (allyEnabled != null) + allyEnabled.RenameKey("AllyBuildRadiusCheckboxEnabled"); + + var buildRadiusLocked = buildRadius.LastChildMatching("BuildRadiusLocked"); + if (buildRadiusLocked != null) + buildRadiusLocked.RenameKey("BuildRadiusCheckboxLocked"); + + var buildRadiusEnabled = buildRadius.LastChildMatching("BuildRadiusEnabled"); + if (buildRadiusEnabled != null) + buildRadiusEnabled.RenameKey("BuildRadiusCheckboxEnabled"); + } + + var devMode = actorNode.LastChildMatching("DeveloperMode"); + if (devMode != null) + { + var locked = devMode.LastChildMatching("Locked"); + if (locked != null) + locked.RenameKey("CheckboxLocked"); + + var enabled = devMode.LastChildMatching("Enabled"); + if (enabled != null) + enabled.RenameKey("CheckboxEnabled"); + } + + var spawner = actorNode.LastChildMatching("CrateSpawner"); + if (spawner != null) + { + var locked = spawner.LastChildMatching("Locked"); + if (locked != null) + locked.RenameKey("CheckboxLocked"); + + var enabled = spawner.LastChildMatching("Enabled"); + if (enabled != null) + enabled.RenameKey("CheckboxEnabled"); + } + + var resources = actorNode.LastChildMatching("PlayerResources"); + if (resources != null) + { + var locked = resources.LastChildMatching("Locked"); + if (locked != null) + locked.RenameKey("DefaultCashDropdownLocked"); + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/SplitGateFromBuilding.cs b/OpenRA.Mods.Common/UpdateRules/Rules/SplitGateFromBuilding.cs new file mode 100644 index 0000000000..6b02bce035 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/SplitGateFromBuilding.cs @@ -0,0 +1,77 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 SplitGateFromBuilding : UpdateRule + { + public override string Name { get { return "Make gates use the 'Building' trait"; } } + public override string Description + { + get + { + return "The 'Gate' trait does no longer inherit 'Building'.\n" + + "Thus gates must define their own 'Building' trait."; + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var gate = actorNode.LastChildMatching("Gate"); + if (gate == null) + yield break; + + var openSound = gate.LastChildMatching("OpeningSound"); + var closeSound = gate.LastChildMatching("ClosingSound"); + var closeDelay = gate.LastChildMatching("CloseDelay"); + var transitDelay = gate.LastChildMatching("TransitionDelay"); + var blockHeight = gate.LastChildMatching("BlocksProjectilesHeight"); + + var newGate = new MiniYamlNode("Gate", ""); + gate.RenameKey("Building"); + + if (openSound != null) + { + newGate.AddNode(openSound); + gate.RemoveNode(openSound); + } + + if (closeSound != null) + { + newGate.AddNode(closeSound); + gate.RemoveNode(closeSound); + } + + if (closeDelay != null) + { + newGate.AddNode(closeDelay); + gate.RemoveNode(closeDelay); + } + + if (transitDelay != null) + { + newGate.AddNode(transitDelay); + gate.RemoveNode(transitDelay); + } + + if (blockHeight != null) + { + newGate.AddNode(blockHeight); + gate.RemoveNode(blockHeight); + } + + actorNode.AddNode(newGate); + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/WarnAboutInfiltrateForTypes.cs b/OpenRA.Mods.Common/UpdateRules/Rules/WarnAboutInfiltrateForTypes.cs new file mode 100644 index 0000000000..a200f462de --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/WarnAboutInfiltrateForTypes.cs @@ -0,0 +1,64 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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 WarnAboutInfiltrateForTypes : UpdateRule + { + public override string Name { get { return "Introduced Types field to InfiltrateFor* traits"; } } + public override string Description + { + get + { + return "InfiltrateFor* traits now have a Types field and infiltration will only have the desired\n" + + "effect if the Types include the type of the infiltrator."; + } + } + + readonly string[] infiltrateForTraits = + { + "InfiltrateForCash", "InfiltrateForDecoration", + "InfiltrateForExploration", "InfiltrateForPowerOutage", + "InfiltrateForSupportPower", + }; + + readonly List> infiltrateForLocations = new List>(); + + public override IEnumerable AfterUpdate(ModData modData) + { + var message1 = "You need to define Types on the InfiltrateFor* trait(s) on the following actors:\n" + + UpdateUtils.FormatMessageList(infiltrateForLocations.Select(n => n.Item1 + " (" + n.Item2 + ")")); + + if (infiltrateForLocations.Any()) + yield return message1; + + infiltrateForLocations.Clear(); + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + foreach (var t in infiltrateForTraits) + { + if (actorNode.LastChildMatching(t) != null) + { + infiltrateForLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); + yield break; + } + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index 08f4df9e1c..938d1ef40b 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -34,22 +34,29 @@ namespace OpenRA.Mods.Common.UpdateRules Justification = "Extracting update lists to temporary variables obfuscates the definitions.")] static readonly UpdatePath[] Paths = { - new UpdatePath("incomplete-release-20171014", "release-20180218", new UpdateRule[] + new UpdatePath("release-20171014", "release-20180218", new UpdateRule[] { new RemoveMobileOnRails(), new AircraftCanHoverGeneralization(), new AddNukeLaunchAnimation(), + new RenameWithTurreted(), + new RemovePlayerPaletteTileset(), new CapturableChanges(), new DecoupleSelfReloading(), - new RemovePlayerPaletteTileset(), - new RenameWithTurreted(), - new ScaleDefaultModHealth(), - new ScaleSupportPowerSecondsToTicks(), - new ChangeBuildableArea(), - new ChangeCanPowerDown(), - new DropPauseAnimationWhenDisabled(), new RemoveOutOfAmmo(), - new ReplaceRequiresPower() + new ChangeCanPowerDown(), + new ReplaceRequiresPower(), + new DropPauseAnimationWhenDisabled(), + new ChangeBuildableArea(), + new MoveVisualBounds(), + new ScaleDefaultModHealth(), + new ReworkCheckboxes(), + new SplitGateFromBuilding(), + new RemoveIDisable(), + new ReplaceCanPowerDown(), + new ScaleSupportPowerSecondsToTicks(), + new WarnAboutInfiltrateForTypes(), + new RenameBurstDelay(), }), new UpdatePath("release-20180218", "release-20180307", new UpdateRule[0]),