diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index c06017d596..c30434bafd 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -494,7 +494,7 @@
-
+
diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamageState.cs b/OpenRA.Mods.Common/Traits/Upgrades/GrantConditionOnDamageState.cs
similarity index 57%
rename from OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamageState.cs
rename to OpenRA.Mods.Common/Traits/Upgrades/GrantConditionOnDamageState.cs
index 0fd2711631..630d5d372d 100644
--- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeOnDamageState.cs
+++ b/OpenRA.Mods.Common/Traits/Upgrades/GrantConditionOnDamageState.cs
@@ -14,11 +14,12 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Applies an upgrade to the actor at specified damage states.")]
- public class UpgradeOnDamageStateInfo : ITraitInfo, Requires, Requires
+ public class GrantConditionOnDamageStateInfo : ITraitInfo, Requires
{
- [UpgradeGrantedReference, FieldLoader.Require]
- [Desc("The upgrades to grant.")]
- public readonly string[] Upgrades = { };
+ [FieldLoader.Require]
+ [UpgradeGrantedReference]
+ [Desc("Condition to grant.")]
+ public readonly string Condition = null;
[Desc("Play a random sound from this list when enabled.")]
public readonly string[] EnabledSounds = { };
@@ -29,59 +30,57 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Levels of damage at which to grant upgrades.")]
public readonly DamageState ValidDamageStates = DamageState.Heavy | DamageState.Critical;
- [Desc("Are upgrades irrevocable once the conditions have been met?")]
+ [Desc("Is the condition irrevocable once it has been activated?")]
public readonly bool GrantPermanently = false;
- public object Create(ActorInitializer init) { return new UpgradeOnDamageState(init.Self, this); }
+ public object Create(ActorInitializer init) { return new GrantConditionOnDamageState(init.Self, this); }
}
- public class UpgradeOnDamageState : INotifyDamageStateChanged, INotifyCreated
+ public class GrantConditionOnDamageState : INotifyDamageStateChanged, INotifyCreated
{
- readonly UpgradeOnDamageStateInfo info;
- readonly UpgradeManager um;
+ readonly GrantConditionOnDamageStateInfo info;
readonly Health health;
- bool granted;
- public UpgradeOnDamageState(Actor self, UpgradeOnDamageStateInfo info)
+ UpgradeManager manager;
+ int conditionToken = UpgradeManager.InvalidConditionToken;
+
+ public GrantConditionOnDamageState(Actor self, GrantConditionOnDamageStateInfo info)
{
this.info = info;
- um = self.Trait();
health = self.Trait();
}
void INotifyCreated.Created(Actor self)
{
+ manager = self.TraitOrDefault();
GrantUpgradeOnValidDamageState(self, health.DamageState);
}
void GrantUpgradeOnValidDamageState(Actor self, DamageState state)
{
- if (!info.ValidDamageStates.HasFlag(state))
+ if (!info.ValidDamageStates.HasFlag(state) || conditionToken != UpgradeManager.InvalidConditionToken)
return;
- granted = true;
- var rand = Game.CosmeticRandom;
- var sound = info.EnabledSounds.RandomOrDefault(rand);
+ conditionToken = manager.GrantCondition(self, info.Condition);
+
+ var sound = info.EnabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(sound, self.CenterPosition);
- foreach (var u in info.Upgrades)
- um.GrantUpgrade(self, u, this);
}
void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
{
- if (granted && info.GrantPermanently)
+ var granted = conditionToken != UpgradeManager.InvalidConditionToken;
+ if ((granted && info.GrantPermanently) || manager == null)
return;
if (!granted && !info.ValidDamageStates.HasFlag(e.PreviousDamageState))
GrantUpgradeOnValidDamageState(self, health.DamageState);
else if (granted && !info.ValidDamageStates.HasFlag(e.DamageState) && info.ValidDamageStates.HasFlag(e.PreviousDamageState))
{
- granted = false;
- var rand = Game.CosmeticRandom;
- var sound = info.DisabledSounds.RandomOrDefault(rand);
+ conditionToken = manager.RevokeCondition(self, conditionToken);
+
+ var sound = info.DisabledSounds.RandomOrDefault(Game.CosmeticRandom);
Game.Sound.Play(sound, self.CenterPosition);
- foreach (var u in info.Upgrades)
- um.RevokeUpgrade(self, u, this);
}
}
}
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index acd9f40b88..d01f943186 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -617,6 +617,12 @@ namespace OpenRA.Mods.Common.UtilityCommands
if (!node.Value.Nodes.Any(n => n.Key == "PrimaryCondition"))
node.Value.Nodes.Add(new MiniYamlNode("PrimaryCondition", "primary"));
}
+
+ if (node.Key.StartsWith("UpgradeOnDamageState", StringComparison.Ordinal))
+ {
+ RenameNodeKey(node, "GrantConditionOnDamageState");
+ ConvertUpgradesToCondition(parent, node, "Upgrades", "Condition");
+ }
}
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml
index 311bc01e03..b041bb5437 100644
--- a/mods/ts/rules/defaults.yaml
+++ b/mods/ts/rules/defaults.yaml
@@ -418,8 +418,8 @@
WithInfantryBody:
DefaultAttackSequence: attack
IdleSequences: idle1,idle2
- UpgradeOnDamageState@CRITICAL:
- Upgrades: criticalspeed
+ GrantConditionOnDamageState@CRITICAL:
+ Condition: criticalspeed
ValidDamageStates: Critical
GrantPermanently: true
SpeedMultiplier@CRITICAL:
@@ -498,11 +498,11 @@
Weapons: SmallDebris
Pieces: 3, 7
Range: 2c0, 5c0
- UpgradeOnDamageState@DAMAGED:
- Upgrades: damagedspeed
+ GrantConditionOnDamageState@DAMAGED:
+ Condition: damagedspeed
ValidDamageStates: Heavy
- UpgradeOnDamageState@CRITICAL:
- Upgrades: criticalspeed
+ GrantConditionOnDamageState@CRITICAL:
+ Condition: criticalspeed
ValidDamageStates: Critical
SpeedMultiplier@DAMAGED:
RequiresCondition: damagedspeed