1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System.Collections.Generic; 13 using OpenRA.Support; 14 using OpenRA.Traits; 15 16 namespace OpenRA.Mods.Common.Traits 17 { 18 /// <summary>Use as base class for *Info to subclass of PausableConditionalTrait. (See PausableConditionalTrait.)</summary> 19 public abstract class PausableConditionalTraitInfo : ConditionalTraitInfo 20 { 21 [ConsumedConditionReference] 22 [Desc("Boolean expression defining the condition to pause this trait.")] 23 public readonly BooleanExpression PauseOnCondition = null; 24 25 public bool PausedByDefault { get; private set; } 26 RulesetLoaded(Ruleset rules, ActorInfo ai)27 public override void RulesetLoaded(Ruleset rules, ActorInfo ai) 28 { 29 base.RulesetLoaded(rules, ai); 30 PausedByDefault = PauseOnCondition != null && PauseOnCondition.Evaluate(VariableExpression.NoVariables); 31 } 32 } 33 34 /// <summary> 35 /// Abstract base for enabling and disabling trait using conditions. 36 /// Requires basing *Info on PausableConditionalTraitInfo and using base(info) constructor. 37 /// TraitResumed will be called at creation if the trait starts not paused or does not have a pause condition. 38 /// </summary> 39 public abstract class PausableConditionalTrait<InfoType> : ConditionalTrait<InfoType> where InfoType : PausableConditionalTraitInfo 40 { 41 [Sync] 42 public bool IsTraitPaused { get; private set; } 43 PausableConditionalTrait(InfoType info)44 protected PausableConditionalTrait(InfoType info) 45 : base(info) 46 { 47 IsTraitPaused = info.PausedByDefault; 48 } 49 Created(Actor self)50 protected override void Created(Actor self) 51 { 52 base.Created(self); 53 if (Info.PauseOnCondition == null) 54 TraitResumed(self); 55 } 56 57 // Overrides must call `base.GetVariableObservers()` to avoid breaking RequiresCondition or PauseOnCondition. GetVariableObservers()58 public override IEnumerable<VariableObserver> GetVariableObservers() 59 { 60 foreach (var observer in base.GetVariableObservers()) 61 yield return observer; 62 63 if (Info.PauseOnCondition != null) 64 yield return new VariableObserver(PauseConditionsChanged, Info.PauseOnCondition.Variables); 65 } 66 PauseConditionsChanged(Actor self, IReadOnlyDictionary<string, int> conditions)67 void PauseConditionsChanged(Actor self, IReadOnlyDictionary<string, int> conditions) 68 { 69 var wasPaused = IsTraitPaused; 70 IsTraitPaused = Info.PauseOnCondition.Evaluate(conditions); 71 72 if (IsTraitPaused != wasPaused) 73 { 74 if (wasPaused) 75 TraitResumed(self); 76 else 77 TraitPaused(self); 78 } 79 } 80 81 // Subclasses can add pause support by querying IsTraitPaused and/or overriding these methods. TraitResumed(Actor self)82 protected virtual void TraitResumed(Actor self) { } TraitPaused(Actor self)83 protected virtual void TraitPaused(Actor self) { } 84 } 85 } 86