diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index ecef9032e1..e92d3de7ad 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -585,10 +585,14 @@
+
+
+
+
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/ChangeBuildableArea.cs b/OpenRA.Mods.Common/UpdateRules/Rules/ChangeBuildableArea.cs
new file mode 100644
index 0000000000..2249ef6019
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/ChangeBuildableArea.cs
@@ -0,0 +1,51 @@
+#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 ChangeBuildableArea : UpdateRule
+ {
+ public override string Name { get { return "Require 'AreaTypes' on 'GivesBuildableArea'"; } }
+ public override string Description
+ {
+ get
+ {
+ return "'AreaTypes' are now mandatory on 'GivesBuildableArea'.\n" +
+ "A 'RequiresBuildableArea' trait was added and 'Building.Adjacent' was moved there.";
+ }
+ }
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ var givesBuildableArea = actorNode.LastChildMatching("GivesBuildableArea");
+ if (givesBuildableArea != null)
+ givesBuildableArea.AddNode("AreaTypes", "building");
+
+ var building = actorNode.LastChildMatching("Building");
+ if (building != null)
+ {
+ var requiresBuildableArea = new MiniYamlNode("RequiresBuildableArea", "");
+ requiresBuildableArea.AddNode("AreaTypes", "building");
+
+ var adjacent = building.LastChildMatching("Adjacent");
+ if (adjacent != null)
+ requiresBuildableArea.AddNode(adjacent);
+
+ actorNode.AddNode(requiresBuildableArea);
+ building.RemoveNodes("Adjacent");
+ }
+
+ yield break;
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/ChangeCanPowerDown.cs b/OpenRA.Mods.Common/UpdateRules/Rules/ChangeCanPowerDown.cs
new file mode 100644
index 0000000000..e56635d339
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/ChangeCanPowerDown.cs
@@ -0,0 +1,67 @@
+#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 ChangeCanPowerDown : UpdateRule
+ {
+ public override string Name { get { return "Provide a condition in 'CanPowerDown' instead of using 'Actor.Disabled'"; } }
+ public override string Description
+ {
+ get
+ {
+ return "'CanPowerDown' now provides a condition instead of using the legacy 'Actor.Disabled' boolean.\n" +
+ "Review your condition setup to make sure all relevant traits are disabled by that condition.";
+ }
+ }
+
+ bool displayed;
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ var canPowerDown = actorNode.LastChildMatching("CanPowerDown");
+ if (canPowerDown == null)
+ yield break;
+
+ canPowerDown.AddNode("PowerdownCondition", "powerdown");
+
+ var image = canPowerDown.LastChildMatching("IndicatorImage");
+ var seq = canPowerDown.LastChildMatching("IndicatorSequence");
+ var pal = canPowerDown.LastChildMatching("IndicatorPalette");
+ var imageValue = image != null ? image.NodeValue() : "poweroff";
+ var seqValue = seq != null ? seq.NodeValue() : "offline";
+ var palValue = pal != null ? pal.NodeValue() : "chrome";
+
+ var indicator = new MiniYamlNode("WithDecoration@POWERDOWN", "");
+ indicator.AddNode("Image", imageValue);
+ indicator.AddNode("Sequence", seqValue);
+ indicator.AddNode("Palette", palValue);
+ indicator.AddNode("RequiresCondition", "powerdown");
+ indicator.AddNode("ReferencePoint", "Center");
+
+ actorNode.AddNode(indicator);
+ if (image != null)
+ canPowerDown.RemoveNodes("IndicatorImage");
+ if (seq != null)
+ canPowerDown.RemoveNodes("IndicatorSequence");
+ if (pal != null)
+ canPowerDown.RemoveNodes("IndicatorPalette");
+
+ if (!displayed)
+ {
+ displayed = true;
+ yield return "'CanPowerDown' now provides a condition. You might need to review your condition setup.";
+ }
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/DropPauseAnimationWhenDisabled.cs b/OpenRA.Mods.Common/UpdateRules/Rules/DropPauseAnimationWhenDisabled.cs
new file mode 100644
index 0000000000..b76dda0ef5
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/DropPauseAnimationWhenDisabled.cs
@@ -0,0 +1,41 @@
+#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 DropPauseAnimationWhenDisabled : UpdateRule
+ {
+ public override string Name { get { return "Drop 'PauseAnimationWhenDisabled' from 'WithSpriteBody', replacing it with conditions."; } }
+ public override string Description
+ {
+ get
+ {
+ return "'WithSpriteBody' is a 'PausableConditionalTrait' now, allowing to drop the 'PauseAnimationWhenDisabled' property\n" +
+ "and to use 'PauseCondition' instead. (With a default value of 'disabled' in this case.)";
+ }
+ }
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ var pauseAnimation = actorNode.LastChildMatching("PauseAnimationWhenDisabled");
+ if (pauseAnimation == null)
+ yield break;
+
+ pauseAnimation.RenameKey("PauseCondition");
+ pauseAnimation.ReplaceValue("disabled");
+
+ yield return "'PauseAnimationWhenDisabled' was removed from 'WithSpriteBody' and replaced by conditions.\n" +
+ "You might need to review your condition setup.";
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/RemoveOutOfAmmo.cs b/OpenRA.Mods.Common/UpdateRules/Rules/RemoveOutOfAmmo.cs
new file mode 100644
index 0000000000..920906f529
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/RemoveOutOfAmmo.cs
@@ -0,0 +1,75 @@
+#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 RemoveOutOfAmmo : UpdateRule
+ {
+ public override string Name { get { return "Replace 'Armament.OutOfAmmo' by pausing on condition"; } }
+ public override string Description
+ {
+ get
+ {
+ return "'Armament.OutOfAmmo' has been replaced by pausing on condition\n" +
+ "(which is usually provided by AmmoPool).";
+ }
+ }
+
+ bool messageDisplayed;
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ var reloadAmmoPool = actorNode.LastChildMatching("ReloadAmmoPool");
+ var armaments = actorNode.ChildrenMatching("Armament");
+ var ammoPools = actorNode.ChildrenMatching("AmmoPool");
+
+ if (reloadAmmoPool != null || !armaments.Any() || !ammoPools.Any())
+ yield break;
+
+ foreach (var pool in ammoPools)
+ {
+ var nameNode = pool.LastChildMatching("Armaments");
+ var name = nameNode != null ? nameNode.NodeValue() : "primary, secondary";
+ var anyMatchingArmament = false;
+ var ammoNoAmmo = new MiniYamlNode("AmmoCondition", "ammo");
+ var armNoAmmo = new MiniYamlNode("PauseOnCondition", "!ammo");
+
+ foreach (var arma in armaments)
+ {
+ var armaNameNode = arma.LastChildMatching("Name");
+ var armaName = armaNameNode != null ? armaNameNode.NodeValue() : "primary";
+ if (name.Contains(armaName))
+ {
+ anyMatchingArmament = true;
+ arma.AddNode(armNoAmmo);
+ }
+ }
+
+ if (anyMatchingArmament)
+ {
+ pool.AddNode(ammoNoAmmo);
+ if (!messageDisplayed)
+ {
+ yield return "Aircraft returning to base is now triggered when all armaments are paused via condition.\n" +
+ "Check if any of your actors with AmmoPools may need further changes.";
+
+ messageDisplayed = true;
+ }
+ }
+ }
+
+ yield break;
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
index 5c38530f1a..31c3cb0ffa 100644
--- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
+++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
@@ -44,7 +44,11 @@ namespace OpenRA.Mods.Common.UpdateRules
new RemovePlayerPaletteTileset(),
new RenameWithTurreted(),
new ScaleDefaultModHealth(),
- new ScaleSupportPowerSecondsToTicks()
+ new ScaleSupportPowerSecondsToTicks(),
+ new ChangeBuildableArea(),
+ new ChangeCanPowerDown(),
+ new DropPauseAnimationWhenDisabled(),
+ new RemoveOutOfAmmo()
}),
new UpdatePath("release-20180218", "release-20180307", new UpdateRule[0]),