diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 2caa41779b..88c872f078 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -593,6 +593,7 @@
+
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RemoveNegativeDamageFullHealthCheck.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RemoveNegativeDamageFullHealthCheck.cs
new file mode 100644
index 0000000000..8f0c7885ce
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RemoveNegativeDamageFullHealthCheck.cs
@@ -0,0 +1,70 @@
+#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 RemoveNegativeDamageFullHealthCheck : UpdateRule
+ {
+ public override string Name { get { return "Negative damage weapons are now valid against full-health targets."; } }
+ public override string Description
+ {
+ get
+ {
+ return "Negative-damage weapons are no longer automatically invalid against targets that have full health.\n" +
+ "Previous behaviour can be restored by enabling a Targetable trait using GrantConditionOnDamageState.\n" +
+ "Affected weapons are listed so that conditions may be manually defined.";
+ }
+ }
+
+ static readonly string[] DamageWarheads =
+ {
+ "TargetDamage",
+ "SpreadDamage",
+ "HealthPercentageDamage"
+ };
+
+ readonly Dictionary> locations = new Dictionary>();
+
+ public override IEnumerable AfterUpdate(ModData modData)
+ {
+ if (locations.Any())
+ yield return "The following weapons may now target actors that have full health. Review their\n" +
+ "target types and, if necessary, use GrantConditionOnDamageState to enable\n" +
+ "a conditional Targetable trait with the appropriate target type when damaged:\n" +
+ UpdateUtils.FormatMessageList(locations.Select(
+ kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
+
+ locations.Clear();
+ }
+
+ public override IEnumerable UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
+ {
+ var used = new List();
+ foreach (var node in weaponNode.ChildrenMatching("Warhead"))
+ {
+ foreach (var warhead in DamageWarheads)
+ if (node.NodeValue() == warhead && node.ChildrenMatching("Damage").Any(d => d.NodeValue() < 0))
+ used.Add(node.Key);
+
+ if (used.Any())
+ {
+ var location = "{0} ({1})".F(weaponNode.Key, node.Location.Filename);
+ locations[location] = used;
+ }
+ }
+
+ yield break;
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
index 6e95ac3d53..ca627cbd56 100644
--- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
+++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
@@ -107,6 +107,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new CloakRequiresConditionToPause(),
new AddBotOrderManager(),
new AddHarvesterBotModule(),
+ new RemoveNegativeDamageFullHealthCheck(),
})
};
diff --git a/OpenRA.Mods.Common/Warheads/DamageWarhead.cs b/OpenRA.Mods.Common/Warheads/DamageWarhead.cs
index f4f6bbd4ee..b5923f750f 100644
--- a/OpenRA.Mods.Common/Warheads/DamageWarhead.cs
+++ b/OpenRA.Mods.Common/Warheads/DamageWarhead.cs
@@ -34,9 +34,6 @@ namespace OpenRA.Mods.Common.Warheads
if (!victim.Info.HasTraitInfo())
return false;
- if (Damage < 0 && victim.GetDamageState() == DamageState.Undamaged)
- return false;
-
return base.IsValidAgainst(victim, firedBy);
}