diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradableTrait.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradableTrait.cs
index 584586a56b..086c960daf 100644
--- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradableTrait.cs
+++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradableTrait.cs
@@ -19,6 +19,13 @@ namespace OpenRA.Mods.Common.Traits
/// Use as base class for *Info to subclass of UpgradableTrait. (See UpgradableTrait.)
public abstract class UpgradableTraitInfo : IUpgradableInfo, IRulesetLoaded
{
+ static readonly Dictionary NoConditions = new Dictionary();
+
+ [UpgradeUsedReference]
+ [Desc("Boolean expression defining the condition to enable this trait.",
+ "Overrides UpgradeTypes/UpgradeMinEnabledLevel/UpgradeMaxEnabledLevel/UpgradeMaxAcceptedLevel if set.")]
+ public readonly BooleanExpression RequiresCondition = null;
+
[UpgradeUsedReference]
[Desc("The upgrade types which can enable or disable this trait.")]
public readonly HashSet UpgradeTypes = new HashSet();
@@ -44,7 +51,8 @@ namespace OpenRA.Mods.Common.Traits
public virtual void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
- EnabledByDefault = UpgradeMinEnabledLevel < 1;
+ EnabledByDefault = RequiresCondition != null ?
+ RequiresCondition.Evaluate(NoConditions) : UpgradeMinEnabledLevel < 1;
}
}
@@ -56,33 +64,63 @@ namespace OpenRA.Mods.Common.Traits
public abstract class UpgradableTrait : IUpgradable, IDisabledTrait, ISync where InfoType : UpgradableTraitInfo
{
public readonly InfoType Info;
- public IEnumerable UpgradeTypes { get { return Info.UpgradeTypes; } }
+ readonly Dictionary conditions = new Dictionary();
+
+ IEnumerable IUpgradable.UpgradeTypes
+ {
+ get
+ {
+ if (Info.RequiresCondition != null)
+ return Info.RequiresCondition.Variables;
+
+ return Info.UpgradeTypes;
+ }
+ }
+
[Sync] public bool IsTraitDisabled { get; private set; }
public UpgradableTrait(InfoType info)
{
Info = info;
- IsTraitDisabled = info.UpgradeTypes != null && info.UpgradeTypes.Count > 0 && info.UpgradeMinEnabledLevel > 0;
+
+ // TODO: Set initial state from a ConditionsInit once that exists
+ if (info.RequiresCondition != null)
+ IsTraitDisabled = !info.RequiresCondition.Evaluate(conditions);
+ else
+ IsTraitDisabled = info.UpgradeTypes != null && info.UpgradeTypes.Count > 0 && info.UpgradeMinEnabledLevel > 0;
}
- public bool AcceptsUpgradeLevel(Actor self, string type, int level)
+ bool IUpgradable.AcceptsUpgradeLevel(Actor self, string type, int level)
{
+ if (Info.RequiresCondition != null)
+ return level == 1;
+
return level > 0 && level <= Info.UpgradeMaxAcceptedLevel;
}
- public void UpgradeLevelChanged(Actor self, string type, int oldLevel, int newLevel)
+ void IUpgradable.UpgradeLevelChanged(Actor self, string type, int oldLevel, int newLevel)
{
- if (!Info.UpgradeTypes.Contains(type))
- return;
-
- // Restrict the levels to the allowed range
- oldLevel = oldLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
- newLevel = newLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
- if (oldLevel == newLevel)
- return;
-
var wasDisabled = IsTraitDisabled;
- IsTraitDisabled = newLevel < Info.UpgradeMinEnabledLevel || newLevel > Info.UpgradeMaxEnabledLevel;
+
+ if (Info.RequiresCondition != null)
+ {
+ conditions[type] = newLevel > 0;
+ IsTraitDisabled = !Info.RequiresCondition.Evaluate(conditions);
+ }
+ else
+ {
+ if (!Info.UpgradeTypes.Contains(type))
+ return;
+
+ // Restrict the levels to the allowed range
+ oldLevel = oldLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
+ newLevel = newLevel.Clamp(0, Info.UpgradeMaxAcceptedLevel);
+ if (oldLevel == newLevel)
+ return;
+
+ IsTraitDisabled = newLevel < Info.UpgradeMinEnabledLevel || newLevel > Info.UpgradeMaxEnabledLevel;
+ }
+
UpgradeLevelChanged(self, oldLevel, newLevel);
if (IsTraitDisabled != wasDisabled)