diff --git a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs index 6e8a67293a..78b43bb2df 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs @@ -169,7 +169,7 @@ namespace OpenRA.Mods.Common.Scripting if (!Enum.TryParse(value, true, out stance)) throw new LuaException("Unknown stance type '{0}'".F(value)); - autotarget.Stance = stance; + autotarget.SetStance(Self, stance); } } diff --git a/OpenRA.Mods.Common/Traits/AutoTarget.cs b/OpenRA.Mods.Common/Traits/AutoTarget.cs index 5c474f3acf..729489017d 100644 --- a/OpenRA.Mods.Common/Traits/AutoTarget.cs +++ b/OpenRA.Mods.Common/Traits/AutoTarget.cs @@ -32,6 +32,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Possible values are HoldFire, ReturnFire, Defend and AttackAnything. Used for human players.")] public readonly UnitStance InitialStance = UnitStance.Defend; + [Desc("Stance-condition key-value pairs for specifying condition granting by stance.")] + public readonly Dictionary ConditionByStance = new Dictionary(); + [Desc("Allow the player to change the unit stance.")] public readonly bool EnableStances = true; @@ -45,24 +48,54 @@ namespace OpenRA.Mods.Common.Traits public readonly bool TargetWhenDamaged = true; + [GrantedConditionReference] + public IEnumerable GrantedConditions { get { return ConditionByStance.Values; } } + public override object Create(ActorInitializer init) { return new AutoTarget(init, this); } } public enum UnitStance { HoldFire, ReturnFire, Defend, AttackAnything } - public class AutoTarget : ConditionalTrait, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync + public class AutoTarget : ConditionalTrait, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync, INotifyCreated { readonly IEnumerable activeAttackBases; readonly AttackFollow[] attackFollows; [Sync] int nextScanTime = 0; - public UnitStance Stance; + public UnitStance Stance { get { return stance; } } + [Sync] public Actor Aggressor; [Sync] public Actor TargetedActor; // NOT SYNCED: do not refer to this anywhere other than UI code public UnitStance PredictedStance; + UnitStance stance; + ConditionManager conditionManager; + int conditionToken = ConditionManager.InvalidConditionToken; + + public void SetStance(Actor self, UnitStance value) + { + if (stance == value) + return; + + stance = value; + ApplyStanceCondition(self); + } + + void ApplyStanceCondition(Actor self) + { + if (conditionManager == null) + return; + + if (conditionToken != ConditionManager.InvalidConditionToken) + conditionToken = conditionManager.RevokeCondition(self, conditionToken); + + string condition; + if (Info.ConditionByStance.TryGetValue(stance, out condition)) + conditionToken = conditionManager.GrantCondition(self, condition); + } + public AutoTarget(ActorInitializer init, AutoTargetInfo info) : base(info) { @@ -70,18 +103,24 @@ namespace OpenRA.Mods.Common.Traits activeAttackBases = self.TraitsImplementing().ToArray().Where(Exts.IsTraitEnabled); if (init.Contains()) - Stance = init.Get(); + stance = init.Get(); else - Stance = self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance; + stance = self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance; - PredictedStance = Stance; + PredictedStance = stance; attackFollows = self.TraitsImplementing().ToArray(); } + void INotifyCreated.Created(Actor self) + { + conditionManager = self.TraitOrDefault(); + ApplyStanceCondition(self); + } + public void ResolveOrder(Actor self, Order order) { if (order.OrderString == "SetUnitStance" && Info.EnableStances) - Stance = (UnitStance)order.ExtraData; + SetStance(self, (UnitStance)order.ExtraData); } public void Damaged(Actor self, AttackInfo e)