diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index fb791dc7cd..3a646f5ebc 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -201,7 +201,6 @@
-
@@ -245,7 +244,7 @@
-
+
diff --git a/OpenRA.Mods.Common/Scripting/Properties/ConditionProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/ConditionProperties.cs
new file mode 100644
index 0000000000..83bbd4495a
--- /dev/null
+++ b/OpenRA.Mods.Common/Scripting/Properties/ConditionProperties.cs
@@ -0,0 +1,89 @@
+#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;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using OpenRA.Mods.Common.Traits;
+using OpenRA.Scripting;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Scripting
+{
+ [ScriptPropertyGroup("General")]
+ public class ConditionProperties : ScriptActorProperties, Requires
+ {
+ readonly UpgradeManager um;
+ readonly Dictionary> legacyShim = new Dictionary>();
+
+ public ConditionProperties(ScriptContext context, Actor self)
+ : base(context, self)
+ {
+ um = self.Trait();
+ }
+
+ [Desc("Grant an external condition on this actor and return the revocation token.",
+ "Conditions must be defined on an ExternalConditions trait on the actor.",
+ "If duration > 0 the condition will be automatically revoked after the defined number of ticks")]
+ public int GrantCondition(string condition, int duration = 0)
+ {
+ if (!um.AcceptsExternalCondition(Self, condition))
+ throw new InvalidDataException("Condition `{0}` has not been listed on an ExternalConditions trait".F(condition));
+
+ return um.GrantCondition(Self, condition, true, duration);
+ }
+
+ [Desc("Revoke a condition using the token returned by GrantCondition.")]
+ public void RevokeCondition(int token)
+ {
+ um.RevokeCondition(Self, token);
+ }
+
+ [Desc("Check whether this actor accepts a specific external condition.")]
+ public bool AcceptsCondition(string condition)
+ {
+ return um.AcceptsExternalCondition(Self, condition);
+ }
+
+ [Desc("Grant an upgrade to this actor. DEPRECATED! Will be removed.")]
+ public void GrantUpgrade(string upgrade)
+ {
+ Game.Debug("GrantUpgrade is deprecated. Use GrantCondition instead.");
+ legacyShim.GetOrAdd(upgrade).Push(GrantCondition(upgrade));
+ }
+
+ [Desc("Revoke an upgrade that was previously granted using GrantUpgrade. DEPRECATED! Will be removed.")]
+ public void RevokeUpgrade(string upgrade)
+ {
+ Game.Debug("RevokeUpgrade is deprecated. Use RevokeCondition instead.");
+ Stack tokens;
+ if (!legacyShim.TryGetValue(upgrade, out tokens) || !tokens.Any())
+ throw new InvalidDataException("Attempting to revoke upgrade `{0}` that has not been granted.".F(upgrade));
+
+ RevokeCondition(tokens.Pop());
+ }
+
+ [Desc("Grant a limited-time upgrade to this actor. DEPRECATED! Will be removed.")]
+ public void GrantTimedUpgrade(string upgrade, int duration)
+ {
+ Game.Debug("GrantTimedUpgrade is deprecated. Use GrantCondition instead.");
+ GrantCondition(upgrade, duration);
+ }
+
+ [Desc("Check whether this actor accepts a specific upgrade. DEPRECATED! Will be removed.")]
+ public bool AcceptsUpgrade(string upgrade)
+ {
+ Game.Debug("AcceptsUpgrade is deprecated. Use AcceptsCondition instead.");
+ return AcceptsCondition(upgrade);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenRA.Mods.Common/Scripting/Properties/UpgradeProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/UpgradeProperties.cs
deleted file mode 100644
index 88424982b4..0000000000
--- a/OpenRA.Mods.Common/Scripting/Properties/UpgradeProperties.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-#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;
-using System.IO;
-using OpenRA.Mods.Common.Traits;
-using OpenRA.Scripting;
-using OpenRA.Traits;
-
-namespace OpenRA.Mods.Common.Scripting
-{
- [ScriptPropertyGroup("General")]
- public class UpgradeProperties : ScriptActorProperties, Requires
- {
- readonly UpgradeManager um;
- readonly ScriptUpgradesCache validUpgrades;
-
- public UpgradeProperties(ScriptContext context, Actor self)
- : base(context, self)
- {
- um = self.Trait();
- validUpgrades = self.World.WorldActor.TraitOrDefault();
- }
-
- [Desc("Grant an upgrade to this actor.")]
- public void GrantUpgrade(string upgrade)
- {
- if (validUpgrades == null)
- throw new InvalidOperationException("Can not grant upgrades because there is no ScriptUpgradesCache defined!");
-
- if (validUpgrades.Info.Upgrades.Contains(upgrade))
- um.GrantUpgrade(Self, upgrade, this);
- else
- throw new InvalidDataException("The ScriptUpgradesCache does not contain a definition for upgrade `{0}`".F(upgrade));
- }
-
- [Desc("Revoke an upgrade that was previously granted using GrantUpgrade.")]
- public void RevokeUpgrade(string upgrade)
- {
- if (validUpgrades == null)
- throw new InvalidOperationException("Can not grant upgrades because there is no ScriptUpgradesCache defined!");
-
- if (validUpgrades.Info.Upgrades.Contains(upgrade))
- um.RevokeUpgrade(Self, upgrade, this);
- else
- throw new InvalidDataException("The ScriptUpgradesCache does not contain a definition for upgrade `{0}`".F(upgrade));
- }
-
- [Desc("Grant a limited-time upgrade to this actor.")]
- public void GrantTimedUpgrade(string upgrade, int duration)
- {
- if (validUpgrades == null)
- throw new InvalidOperationException("Can not grant upgrades because there is no ScriptUpgradesCache defined!");
-
- if (validUpgrades.Info.Upgrades.Contains(upgrade))
- um.GrantTimedUpgrade(Self, upgrade, duration);
- else
- throw new InvalidDataException("The ScriptUpgradesCache does not contain a definition for upgrade `{0}`".F(upgrade));
- }
-
- [Desc("Check whether this actor accepts a specific upgrade.")]
- public bool AcceptsUpgrade(string upgrade)
- {
- return validUpgrades != null && validUpgrades.Info.Upgrades.Contains(upgrade) && um.AcceptsUpgrade(Self, upgrade);
- }
- }
-}
\ No newline at end of file
diff --git a/OpenRA.Mods.Common/Scripting/ScriptUpgradesCache.cs b/OpenRA.Mods.Common/Scripting/ScriptUpgradesCache.cs
deleted file mode 100644
index d0790b18a8..0000000000
--- a/OpenRA.Mods.Common/Scripting/ScriptUpgradesCache.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-#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 OpenRA.Traits;
-
-namespace OpenRA.Mods.Common.Scripting
-{
- [Desc("Allows granting upgrades to actors from Lua scripts.")]
- public class ScriptUpgradesCacheInfo : ITraitInfo
- {
- [UpgradeGrantedReference]
- [Desc("Upgrades that can be granted from the scripts.")]
- public readonly HashSet Upgrades = new HashSet();
-
- public object Create(ActorInitializer init) { return new ScriptUpgradesCache(this); }
- }
-
- public sealed class ScriptUpgradesCache
- {
- public readonly ScriptUpgradesCacheInfo Info;
-
- public ScriptUpgradesCache(ScriptUpgradesCacheInfo info)
- {
- Info = info;
- }
- }
-}
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index 80c360ea8f..ec4e4e25fc 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -555,6 +555,18 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
+ if (engineVersion < 20161210)
+ {
+ // Migrated lua upgrades to conditions
+ if (node.Key.StartsWith("ScriptUpgradesCache", StringComparison.Ordinal))
+ {
+ RenameNodeKey(node, "ExternalConditions");
+ var conditions = node.Value.Nodes.FirstOrDefault(n => n.Key == "Upgrades");
+ if (conditions != null)
+ conditions.Key = "Conditions";
+ }
+ }
+
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
}
diff --git a/mods/ra/maps/desert-shellmap/rules.yaml b/mods/ra/maps/desert-shellmap/rules.yaml
index 2163dffcae..f49bfa81fd 100644
--- a/mods/ra/maps/desert-shellmap/rules.yaml
+++ b/mods/ra/maps/desert-shellmap/rules.yaml
@@ -11,8 +11,8 @@ World:
ValuePerUnit: 0
LuaScript:
Scripts: desert-shellmap.lua
- ScriptUpgradesCache:
- Upgrades: unkillable
+ ExternalConditions:
+ Conditions: unkillable
-StartGameNotification:
^Vehicle:
diff --git a/mods/ra/maps/fort-lonestar/rules.yaml b/mods/ra/maps/fort-lonestar/rules.yaml
index 3ac6f9f0f0..b7fe962f65 100644
--- a/mods/ra/maps/fort-lonestar/rules.yaml
+++ b/mods/ra/maps/fort-lonestar/rules.yaml
@@ -28,8 +28,8 @@ World:
Type: LightningStrike
LuaScript:
Scripts: fort-lonestar.lua, fort-lonestar-AI.lua
- ScriptUpgradesCache:
- Upgrades: invulnerability
+ ExternalConditions:
+ Conditions: invulnerability
MapBuildRadius:
AllyBuildRadiusLocked: True
AllyBuildRadiusEnabled: True
diff --git a/mods/ts/maps/fields-of-green/map.yaml b/mods/ts/maps/fields-of-green/map.yaml
index 581710380b..be11da9d7d 100644
--- a/mods/ts/maps/fields-of-green/map.yaml
+++ b/mods/ts/maps/fields-of-green/map.yaml
@@ -1436,8 +1436,8 @@ Rules:
GlobalLightingPaletteEffect:
Blue: 0.7
Ambient: 0.7
- ScriptUpgradesCache:
- Upgrades: unkillable
+ ExternalConditions:
+ Conditions: unkillable
HARV:
-Targetable:
GALITE: