diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 75b7aa858e..b94ecc9812 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -332,6 +332,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs b/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs
new file mode 100644
index 0000000000..3e4c2fe113
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs
@@ -0,0 +1,70 @@
+#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 System.Collections.Generic;
+using System.Linq;
+using OpenRA.GameRules;
+using OpenRA.Mods.Common.Warheads;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ [Desc("This actor triggers an explosion on itself when transitioning to a specific damage state.")]
+ public class ExplosionOnDamageTransitionInfo : ITraitInfo, IRulesetLoaded, Requires
+ {
+ [WeaponReference, FieldLoader.Require, Desc("Weapon to use for explosion.")]
+ public readonly string Weapon = null;
+
+ [Desc("At which damage state explosion will trigger.")]
+ public readonly DamageState DamageState = DamageState.Heavy;
+
+ [Desc("Should the explosion only be triggered once?")]
+ public readonly bool TriggerOnlyOnce = false;
+
+ public WeaponInfo WeaponInfo { get; private set; }
+
+ public object Create(ActorInitializer init) { return new ExplosionOnDamageTransition(this, init.Self); }
+
+ public void RulesetLoaded(Ruleset rules, ActorInfo ai)
+ {
+ WeaponInfo = string.IsNullOrEmpty(Weapon) ? null : rules.Weapons[Weapon.ToLowerInvariant()];
+ }
+ }
+
+ public class ExplosionOnDamageTransition : INotifyDamageStateChanged
+ {
+ readonly ExplosionOnDamageTransitionInfo info;
+ bool triggered;
+
+ public ExplosionOnDamageTransition(ExplosionOnDamageTransitionInfo info, Actor self)
+ {
+ this.info = info;
+ }
+
+ public void DamageStateChanged(Actor self, AttackInfo e)
+ {
+ if (!self.IsInWorld)
+ return;
+
+ if (triggered)
+ return;
+
+ if (e.DamageState >= info.DamageState && e.PreviousDamageState < info.DamageState)
+ {
+ if (info.TriggerOnlyOnce)
+ triggered = true;
+
+ // Use .FromPos since the actor might have been killed, don't use Target.FromActor
+ info.WeaponInfo.Impact(Target.FromPos(self.CenterPosition), e.Attacker, Enumerable.Empty());
+ }
+ }
+ }
+}
diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml
index 1676cfe7dd..b2b1b20591 100644
--- a/mods/ts/rules/defaults.yaml
+++ b/mods/ts/rules/defaults.yaml
@@ -365,6 +365,10 @@
^Cyborg:
Inherits@1: ^Infantry
Inherits@2: ^EmpDisableMobile
+ ExplosionOnDamageTransition:
+ Weapon: CyborgExplode
+ DamageState: Critical
+ TriggerOnlyOnce: true
Explodes:
Weapon: CyborgExplode
EmptyWeapon: CyborgExplode