diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs
index 56346096a4..be07eb8eab 100644
--- a/OpenRA.Game/Traits/TraitsInterfaces.cs
+++ b/OpenRA.Game/Traits/TraitsInterfaces.cs
@@ -22,7 +22,16 @@ namespace OpenRA.Traits
{
public sealed class RequireExplicitImplementationAttribute : Attribute { }
- public enum DamageState { Undamaged, Light, Medium, Heavy, Critical, Dead }
+ [Flags]
+ public enum DamageState
+ {
+ Undamaged = 1,
+ Light = 2,
+ Medium = 4,
+ Heavy = 8,
+ Critical = 16,
+ Dead = 32
+ }
public interface IHealth
{
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 836500e69f..59de2a6e3f 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -493,6 +493,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamage.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamage.cs
new file mode 100644
index 0000000000..c058fcaa07
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamage.cs
@@ -0,0 +1,71 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2016 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 OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ [Desc("Applies an upgrade to actors within a specified range.")]
+ public class UpgradeOnDamageInfo : ITraitInfo, Requires
+ {
+ [UpgradeGrantedReference, FieldLoader.Require]
+ [Desc("The upgrades to grant.")]
+ public readonly string[] Upgrades = { };
+
+ [Desc("Play a random sound from this list when enabled.")]
+ public readonly string[] EnabledSounds = { };
+
+ [Desc("Play a random sound from this list when disabled.")]
+ public readonly string[] DisabledSounds = { };
+
+ [Desc("Levels of damage at which to grant upgrades.")]
+ public readonly DamageState ValidDamageStates = DamageState.Heavy | DamageState.Critical;
+
+ public object Create(ActorInitializer init) { return new UpgradeOnDamage(init.Self, this); }
+ }
+
+ public class UpgradeOnDamage : INotifyDamageStateChanged
+ {
+ readonly UpgradeOnDamageInfo info;
+ readonly UpgradeManager um;
+
+ public UpgradeOnDamage(Actor self, UpgradeOnDamageInfo info)
+ {
+ this.info = info;
+ um = self.TraitOrDefault();
+ }
+
+ bool granted;
+ void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
+ {
+ if (um == null)
+ return;
+
+ var rand = Game.CosmeticRandom;
+ if (!granted && info.ValidDamageStates.HasFlag(e.DamageState) && !info.ValidDamageStates.HasFlag(e.PreviousDamageState))
+ {
+ granted = true;
+ var sound = info.EnabledSounds.RandomOrDefault(rand);
+ Game.Sound.Play(sound, self.CenterPosition);
+ foreach (var u in info.Upgrades)
+ um.GrantUpgrade(self, u, this);
+ }
+ else if (granted && !info.ValidDamageStates.HasFlag(e.DamageState) && info.ValidDamageStates.HasFlag(e.PreviousDamageState))
+ {
+ granted = false;
+ var sound = info.DisabledSounds.RandomOrDefault(rand);
+ Game.Sound.Play(sound, self.CenterPosition);
+ foreach (var u in info.Upgrades)
+ um.RevokeUpgrade(self, u, this);
+ }
+ }
+ }
+}
diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml
index 14c8cd91ea..72e740d4fc 100644
--- a/mods/ts/rules/defaults.yaml
+++ b/mods/ts/rules/defaults.yaml
@@ -370,6 +370,12 @@
WithInfantryBody:
AttackSequence: shoot
IdleSequences: idle1,idle2
+ UpgradeOnDamage@CRITICAL:
+ Upgrades: criticalspeed
+ ValidDamageStates: Critical
+ SpeedMultiplier@CRITICAL:
+ UpgradeTypes: criticalspeed
+ Modifier: 50
^CivilianInfantry:
Inherits: ^Infantry
@@ -442,6 +448,18 @@
PoisonedByTiberium:
Weapon: Veins
Resources: Veins
+ UpgradeOnDamage@DAMAGED:
+ Upgrades: damagedspeed
+ ValidDamageStates: Heavy
+ UpgradeOnDamage@CRITICAL:
+ Upgrades: criticalspeed
+ ValidDamageStates: Critical
+ SpeedMultiplier@DAMAGED:
+ UpgradeTypes: damagedspeed
+ Modifier: 80
+ SpeedMultiplier@CRITICAL:
+ UpgradeTypes: criticalspeed
+ Modifier: 60
^Tank:
Inherits: ^Vehicle