From f5460f9f56317b3572213d4c57cbc1f6f887d2cc Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Fri, 25 Sep 2015 15:00:22 -0500 Subject: [PATCH 1/5] Upgrade(s) while loading cargo --- OpenRA.Mods.Common/Traits/Cargo.cs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 07bb3b5cef..3f9ff05acf 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -19,7 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor can transport Passenger actors.")] - public class CargoInfo : ITraitInfo, Requires + public class CargoInfo : ITraitInfo, Requires, Requires { [Desc("The maximum sum of Passenger.Weight that this actor can support.")] public readonly int MaxWeight = 0; @@ -51,6 +51,10 @@ namespace OpenRA.Mods.Common.Traits [Desc("Cursor to display when unable to unload the passengers.")] public readonly string UnloadBlockedCursor = "deploy-blocked"; + [UpgradeGrantedReference] + [Desc("The upgrades to grant to self while loading cargo.")] + public readonly string[] LoadingUpgrades = { }; + public object Create(ActorInitializer init) { return new Cargo(init, this); } } @@ -59,6 +63,7 @@ namespace OpenRA.Mods.Common.Traits { public readonly CargoInfo Info; readonly Actor self; + readonly UpgradeManager upgradeManager; readonly Stack cargo = new Stack(); readonly HashSet reserves = new HashSet(); readonly Lazy facing; @@ -80,6 +85,7 @@ namespace OpenRA.Mods.Common.Traits Info = info; Unloading = false; checkTerrainType = info.UnloadTerrainTypes.Count > 0; + upgradeManager = self.Trait(); if (init.Contains()) { @@ -183,6 +189,10 @@ namespace OpenRA.Mods.Common.Traits if (!HasSpace(w)) return false; + if (reserves.Count == 0) + foreach (var u in Info.LoadingUpgrades) + upgradeManager.GrantUpgrade(self, u, this); + reserves.Add(a); reservedWeight += w; @@ -196,6 +206,10 @@ namespace OpenRA.Mods.Common.Traits reservedWeight -= GetWeight(a); reserves.Remove(a); + + if (reserves.Count == 0) + foreach (var u in Info.LoadingUpgrades) + upgradeManager.RevokeUpgrade(self, u, this); } public string CursorForOrder(Actor self, Order order) @@ -235,7 +249,7 @@ namespace OpenRA.Mods.Common.Traits p.Transport = null; foreach (var u in p.Info.GrantUpgrades) - self.Trait().RevokeUpgrade(self, u, p); + upgradeManager.RevokeUpgrade(self, u, p); return a; } @@ -287,6 +301,10 @@ namespace OpenRA.Mods.Common.Traits { reservedWeight -= w; reserves.Remove(a); + + if (reserves.Count == 0) + foreach (var u in Info.LoadingUpgrades) + upgradeManager.RevokeUpgrade(self, u, this); } foreach (var npe in self.TraitsImplementing()) @@ -295,7 +313,7 @@ namespace OpenRA.Mods.Common.Traits var p = a.Trait(); p.Transport = self; foreach (var u in p.Info.GrantUpgrades) - self.Trait().GrantUpgrade(self, u, p); + upgradeManager.GrantUpgrade(self, u, p); } public void Killed(Actor self, AttackInfo e) From 019951795d457bf9530d9f98d64f4257d72c1adf Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Fri, 25 Sep 2015 15:21:06 -0500 Subject: [PATCH 2/5] Upgrades for Carryable while waiting or being carried --- OpenRA.Mods.D2k/Traits/Carryable.cs | 36 +++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/OpenRA.Mods.D2k/Traits/Carryable.cs b/OpenRA.Mods.D2k/Traits/Carryable.cs index 4dd906ef44..6cdc5e0e41 100644 --- a/OpenRA.Mods.D2k/Traits/Carryable.cs +++ b/OpenRA.Mods.D2k/Traits/Carryable.cs @@ -17,10 +17,14 @@ using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { [Desc("Can be carried by units with the trait `Carryall`.")] - public class CarryableInfo : ITraitInfo + public class CarryableInfo : ITraitInfo, Requires { [Desc("Required distance away from destination before requesting a pickup. Default is 6 cells.")] - public WDist MinDistance = WDist.FromCells(6); + public readonly WDist MinDistance = WDist.FromCells(6); + + [UpgradeGrantedReference] + [Desc("The upgrades to grant to self while waiting or being carried.")] + public readonly string[] CarryableUpgrades = { }; public object Create(ActorInitializer init) { return new Carryable(init.Self, this); } } @@ -29,12 +33,33 @@ namespace OpenRA.Mods.D2k.Traits { readonly CarryableInfo info; readonly Actor self; + readonly UpgradeManager upgradeManager; public bool Reserved { get; private set; } // If we're locked there isn't much we can do. We'll have to wait for the carrier to finish with us. We should not move or get new orders! bool locked; + void Unlock() + { + if (!locked) + return; + + locked = false; + foreach (var u in info.CarryableUpgrades) + upgradeManager.RevokeUpgrade(self, u, this); + } + + void Lock() + { + if (locked) + return; + + locked = true; + foreach (var u in info.CarryableUpgrades) + upgradeManager.GrantUpgrade(self, u, this); + } + public bool WantsTransport { get; set; } public CPos Destination; Activity afterLandActivity; @@ -43,6 +68,7 @@ namespace OpenRA.Mods.D2k.Traits { this.info = info; this.self = self; + upgradeManager = self.Trait(); locked = false; Reserved = false; @@ -110,7 +136,7 @@ namespace OpenRA.Mods.D2k.Traits public void Dropped() { WantsTransport = false; - locked = false; + Unlock(); if (afterLandActivity != null) { @@ -144,7 +170,7 @@ namespace OpenRA.Mods.D2k.Traits public void UnReserve(Actor carrier) { Reserved = false; - locked = false; + Unlock(); } // Prepare for transport pickup @@ -166,7 +192,7 @@ namespace OpenRA.Mods.D2k.Traits // Cancel our activities self.CancelActivity(); - locked = true; + Lock(); return true; } From 0fc04b7a4a360cafb43fac4ae12c3dcce15e246c Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Fri, 25 Sep 2015 13:37:50 -0500 Subject: [PATCH 3/5] Make Mobile upgradable --- OpenRA.Mods.Common/Activities/Move/Move.cs | 2 +- .../Scripting/Properties/MobileProperties.cs | 3 ++ OpenRA.Mods.Common/Traits/Mobile.cs | 31 ++++++++++--------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Move/Move.cs b/OpenRA.Mods.Common/Activities/Move/Move.cs index 5c8ea5b1a0..b3e31e93ff 100644 --- a/OpenRA.Mods.Common/Activities/Move/Move.cs +++ b/OpenRA.Mods.Common/Activities/Move/Move.cs @@ -155,7 +155,7 @@ namespace OpenRA.Mods.Common.Activities if (IsCanceled) return NextActivity; - if (moveDisablers.Any(d => d.MoveDisabled(self))) + if (mobile.IsTraitDisabled || moveDisablers.Any(d => d.MoveDisabled(self))) return this; if (destination == mobile.ToCell) diff --git a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs index 7fad4b2834..217edd41c6 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/MobileProperties.cs @@ -61,5 +61,8 @@ namespace OpenRA.Mods.Common.Scripting { Self.QueueActivity(new EnterTransport(Self, transport, 1, true)); } + + [Desc("Whether the actor can move (false if immobilized).")] + public bool IsMobile { get { return !mobile.IsTraitDisabled; } } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 835acd1ab0..804a3b7312 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits } [Desc("Unit is able to move.")] - public class MobileInfo : IMoveInfo, IPositionableInfo, IOccupySpaceInfo, IFacingInfo, + public class MobileInfo : UpgradableTraitInfo, IMoveInfo, IPositionableInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { [FieldLoader.LoadUsing("LoadSpeeds", true)] @@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits [VoiceReference] public readonly string Voice = "Action"; - public virtual object Create(ActorInitializer init) { return new Mobile(init, this); } + public override object Create(ActorInitializer init) { return new Mobile(init, this); } static object LoadSpeeds(MiniYaml y) { @@ -304,8 +304,8 @@ namespace OpenRA.Mods.Common.Traits bool IOccupySpaceInfo.SharesCell { get { return SharesCell; } } } - public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, IDeathActorInitModifier, - INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove + public class Mobile : UpgradableTrait, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, + IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove { const int AverageTicksBeforePathing = 5; const int SpreadTicksBeforePathing = 5; @@ -313,7 +313,6 @@ namespace OpenRA.Mods.Common.Traits readonly Actor self; readonly Lazy> speedModifiers; - public readonly MobileInfo Info; public bool IsMoving { get; set; } int facing; @@ -349,9 +348,9 @@ namespace OpenRA.Mods.Common.Traits } public Mobile(ActorInitializer init, MobileInfo info) + : base(info) { self = init.Self; - Info = info; speedModifiers = Exts.Lazy(() => self.TraitsImplementing().ToArray().Select(x => x.GetSpeedModifier())); @@ -438,7 +437,7 @@ namespace OpenRA.Mods.Common.Traits self.World.ScreenMap.Remove(self); } - public IEnumerable Orders { get { yield return new MoveOrderTargeter(self, Info); } } + public IEnumerable Orders { get { yield return new MoveOrderTargeter(self, this); } } // Note: Returns a valid order even if the unit can't move to the target public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) @@ -629,6 +628,9 @@ namespace OpenRA.Mods.Common.Traits public void Nudge(Actor self, Actor nudger, bool force) { + if (IsTraitDisabled) + return; + /* initial fairly braindead implementation. */ if (!force && self.Owner.Stances[nudger.Owner] != Stance.Ally) return; /* don't allow ourselves to be pushed around @@ -691,14 +693,14 @@ namespace OpenRA.Mods.Common.Traits class MoveOrderTargeter : IOrderTargeter { - readonly MobileInfo unitType; + readonly Mobile mobile; readonly bool rejectMove; readonly IDisableMove[] moveDisablers; public bool OverrideSelection { get { return false; } } - public MoveOrderTargeter(Actor self, MobileInfo unitType) + public MoveOrderTargeter(Actor self, Mobile unit) { - this.unitType = unitType; + this.mobile = unit; rejectMove = !self.AcceptsOrder("Move"); moveDisablers = self.TraitsImplementing().ToArray(); } @@ -717,12 +719,13 @@ namespace OpenRA.Mods.Common.Traits var explored = self.Owner.Shroud.IsExplored(location); cursor = self.World.Map.Contains(location) ? - (self.World.Map.GetTerrainInfo(location).CustomCursor ?? unitType.Cursor) : unitType.BlockedCursor; + (self.World.Map.GetTerrainInfo(location).CustomCursor ?? mobile.Info.Cursor) : mobile.Info.BlockedCursor; - if ((!explored && !unitType.MoveIntoShroud) - || (explored && unitType.MovementCostForCell(self.World, location) == int.MaxValue) + if (mobile.IsTraitDisabled + || (!explored && !mobile.Info.MoveIntoShroud) + || (explored && mobile.Info.MovementCostForCell(self.World, location) == int.MaxValue) || moveDisablers.Any(d => d.MoveDisabled(self))) - cursor = unitType.BlockedCursor; + cursor = mobile.Info.BlockedCursor; return true; } From c827dbe1833647fc96fc81d27b925a93be77b098 Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Fri, 25 Sep 2015 16:55:33 -0500 Subject: [PATCH 4/5] Replace IDisableMove with upgradability --- OpenRA.Game/Traits/TraitsInterfaces.cs | 1 - OpenRA.Mods.Common/Activities/Move/Drag.cs | 6 ++-- OpenRA.Mods.Common/Activities/Move/Move.cs | 9 +----- OpenRA.Mods.Common/Activities/Turn.cs | 7 +++-- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 - OpenRA.Mods.Common/Traits/Cargo.cs | 3 +- OpenRA.Mods.Common/Traits/Mobile.cs | 5 +--- .../Upgrades/DisableMovementOnUpgrade.cs | 28 ------------------- .../Traits/Upgrades/DisableOnUpgrade.cs | 3 +- .../UtilityCommands/UpgradeRules.cs | 26 +++++++++++++++++ OpenRA.Mods.D2k/Traits/Carryable.cs | 9 +----- mods/cnc/rules/ships.yaml | 3 ++ mods/cnc/rules/vehicles.yaml | 3 ++ mods/d2k/rules/defaults.yaml | 3 ++ mods/d2k/rules/infantry.yaml | 5 ++-- mods/ra/rules/ships.yaml | 3 ++ mods/ra/rules/vehicles.yaml | 9 ++++++ mods/ts/rules/civilian-vehicles.yaml | 10 +++---- mods/ts/rules/defaults.yaml | 16 +++++++++-- mods/ts/rules/gdi-vehicles.yaml | 1 + mods/ts/rules/nod-vehicles.yaml | 1 + mods/ts/rules/shared-vehicles.yaml | 5 +--- mods/ts/weapons/superweapons.yaml | 2 +- 23 files changed, 82 insertions(+), 77 deletions(-) delete mode 100644 OpenRA.Mods.Common/Traits/Upgrades/DisableMovementOnUpgrade.cs diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index a0fb5eeae0..c1fdbeda35 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -127,7 +127,6 @@ namespace OpenRA.Traits public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyInfiltrated { void Infiltrated(Actor self, Actor infiltrator); } public interface INotifyDiscovered { void OnDiscovered(Actor self, Player discoverer, bool playNotification); } - public interface IDisableMove { bool MoveDisabled(Actor self); } public interface ISeedableResource { void Seed(Actor self); } diff --git a/OpenRA.Mods.Common/Activities/Move/Drag.cs b/OpenRA.Mods.Common/Activities/Move/Drag.cs index 0095b9d6c7..96285bac56 100644 --- a/OpenRA.Mods.Common/Activities/Move/Drag.cs +++ b/OpenRA.Mods.Common/Activities/Move/Drag.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Activities { readonly IPositionable positionable; readonly IMove movement; - readonly IDisableMove[] moveDisablers; + readonly IDisabledTrait disableable; WPos start, end; int length; int ticks = 0; @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Activities { positionable = self.Trait(); movement = self.TraitOrDefault(); - moveDisablers = self.TraitsImplementing().ToArray(); + disableable = movement as IDisabledTrait; this.start = start; this.end = end; this.length = length; @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Activities public override Activity Tick(Actor self) { - if (moveDisablers.Any(d => d.MoveDisabled(self))) + if (disableable != null && disableable.IsTraitDisabled) return this; var pos = length > 1 diff --git a/OpenRA.Mods.Common/Activities/Move/Move.cs b/OpenRA.Mods.Common/Activities/Move/Move.cs index b3e31e93ff..37e99bedfd 100644 --- a/OpenRA.Mods.Common/Activities/Move/Move.cs +++ b/OpenRA.Mods.Common/Activities/Move/Move.cs @@ -25,7 +25,6 @@ namespace OpenRA.Mods.Common.Activities static readonly List NoPath = new List(); readonly Mobile mobile; - readonly IDisableMove[] moveDisablers; readonly WDist nearEnough; readonly Func> getPath; readonly Actor ignoredActor; @@ -43,7 +42,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, CPos destination) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); getPath = () => { @@ -65,7 +63,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, CPos destination, WDist nearEnough) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); getPath = () => self.World.WorldActor.Trait() .FindUnitPath(mobile.ToCell, destination, self); @@ -76,7 +73,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, CPos destination, SubCell subCell, WDist nearEnough) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); getPath = () => self.World.WorldActor.Trait() .FindUnitPathToRange(mobile.FromCell, subCell, self.World.Map.CenterOfSubCell(destination, subCell), nearEnough, self); @@ -87,7 +83,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, CPos destination, Actor ignoredActor) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); getPath = () => { @@ -107,7 +102,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, Target target, WDist range) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); getPath = () => { @@ -125,7 +119,6 @@ namespace OpenRA.Mods.Common.Activities public Move(Actor self, Func> getPath) { mobile = self.Trait(); - moveDisablers = self.TraitsImplementing().ToArray(); this.getPath = getPath; @@ -155,7 +148,7 @@ namespace OpenRA.Mods.Common.Activities if (IsCanceled) return NextActivity; - if (mobile.IsTraitDisabled || moveDisablers.Any(d => d.MoveDisabled(self))) + if (mobile.IsTraitDisabled) return this; if (destination == mobile.ToCell) diff --git a/OpenRA.Mods.Common/Activities/Turn.cs b/OpenRA.Mods.Common/Activities/Turn.cs index fe5d986edd..c7096c7567 100644 --- a/OpenRA.Mods.Common/Activities/Turn.cs +++ b/OpenRA.Mods.Common/Activities/Turn.cs @@ -11,18 +11,19 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Activities; +using OpenRA.Mods.Common.Traits; using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { public class Turn : Activity { - readonly IDisableMove[] moveDisablers; + readonly IDisabledTrait disablable; readonly int desiredFacing; public Turn(Actor self, int desiredFacing) { - moveDisablers = self.TraitsImplementing().ToArray(); + disablable = self.TraitOrDefault() as IDisabledTrait; this.desiredFacing = desiredFacing; } @@ -30,7 +31,7 @@ namespace OpenRA.Mods.Common.Activities { if (IsCanceled) return NextActivity; - if (moveDisablers.Any(d => d.MoveDisabled(self))) + if (disablable != null && disablable.IsTraitDisabled) return this; var facing = self.Trait(); diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index a753d8c425..b30729bc3b 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -483,7 +483,6 @@ - diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 3f9ff05acf..a0d23ca5d8 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits } public class Cargo : IPips, IIssueOrder, IResolveOrder, IOrderVoice, INotifyCreated, INotifyKilled, - INotifyOwnerChanged, INotifyAddedToWorld, ITick, INotifySold, IDisableMove, INotifyActorDisposing + INotifyOwnerChanged, INotifyAddedToWorld, ITick, INotifySold, INotifyActorDisposing { public readonly CargoInfo Info; readonly Actor self; @@ -228,7 +228,6 @@ namespace OpenRA.Mods.Common.Traits return Info.UnloadVoice; } - public bool MoveDisabled(Actor self) { return reserves.Any(); } public bool HasSpace(int weight) { return totalWeight + reservedWeight + weight <= Info.MaxWeight; } public bool IsEmpty(Actor self) { return cargo.Count == 0; } diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 804a3b7312..49a23db464 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -695,14 +695,12 @@ namespace OpenRA.Mods.Common.Traits { readonly Mobile mobile; readonly bool rejectMove; - readonly IDisableMove[] moveDisablers; public bool OverrideSelection { get { return false; } } public MoveOrderTargeter(Actor self, Mobile unit) { this.mobile = unit; rejectMove = !self.AcceptsOrder("Move"); - moveDisablers = self.TraitsImplementing().ToArray(); } public string OrderID { get { return "Move"; } } @@ -723,8 +721,7 @@ namespace OpenRA.Mods.Common.Traits if (mobile.IsTraitDisabled || (!explored && !mobile.Info.MoveIntoShroud) - || (explored && mobile.Info.MovementCostForCell(self.World, location) == int.MaxValue) - || moveDisablers.Any(d => d.MoveDisabled(self))) + || (explored && mobile.Info.MovementCostForCell(self.World, location) == int.MaxValue)) cursor = mobile.Info.BlockedCursor; return true; diff --git a/OpenRA.Mods.Common/Traits/Upgrades/DisableMovementOnUpgrade.cs b/OpenRA.Mods.Common/Traits/Upgrades/DisableMovementOnUpgrade.cs deleted file mode 100644 index 7d92a4f600..0000000000 --- a/OpenRA.Mods.Common/Traits/Upgrades/DisableMovementOnUpgrade.cs +++ /dev/null @@ -1,28 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 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. For more information, - * see COPYING. - */ -#endregion - -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - [Desc("Disable the ability to move and turn of the actor when this trait is enabled by an upgrade.")] - public class DisableMovementInfo : UpgradableTraitInfo - { - public override object Create(ActorInitializer init) { return new DisableMovementOnUpgrade(this); } - } - - public class DisableMovementOnUpgrade : UpgradableTrait, IDisableMove - { - public DisableMovementOnUpgrade(DisableMovementInfo info) - : base(info) { } - - public bool MoveDisabled(Actor self) { return !IsTraitDisabled; } - } -} diff --git a/OpenRA.Mods.Common/Traits/Upgrades/DisableOnUpgrade.cs b/OpenRA.Mods.Common/Traits/Upgrades/DisableOnUpgrade.cs index c2a917ec3e..3e8927d6ab 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/DisableOnUpgrade.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/DisableOnUpgrade.cs @@ -18,12 +18,11 @@ namespace OpenRA.Mods.Common.Traits public override object Create(ActorInitializer init) { return new DisableOnUpgrade(this); } } - public class DisableOnUpgrade : UpgradableTrait, IDisable, IDisableMove + public class DisableOnUpgrade : UpgradableTrait, IDisable { public DisableOnUpgrade(DisableOnUpgradeInfo info) : base(info) { } public bool Disabled { get { return !IsTraitDisabled; } } - public bool MoveDisabled(Actor self) { return !IsTraitDisabled; } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index d4a5a21b7b..818c4be6f8 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -2510,6 +2510,32 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + // Notify how to restore blocking movement of Mobile actors with Carryable and/or Cargo + if (engineVersion < 20151204 && depth == 2) + { + if (node.Key == "Carryable") + { + Console.WriteLine("Use CarryableUpgrades of Carryable to disable Mobile while " + parent.Key + " is waiting or being carried."); + } + else if (node.Key == "Cargo") + { + Console.WriteLine("Use LoadingUpgrades of Cargo to disable Mobile while " + parent.Key + " is loading cargo."); + } + else if (node.Key == "DeployToUpgrade") + { + Console.WriteLine("Use Upgrades of DeployToUpgrade to disable Mobile while " + parent.Key + " is deployed (instead of DisableUpgrade)."); + } + else if (node.Key == "DisableUpgrade") + { + Console.WriteLine("DisableUpgrade no longer disables Mobile. Use Mobile upgradablility instead for " + parent.Key + "."); + } + else if (node.Key == "DisableMovementOnUpgrade") + { + parent.Value.Nodes.Remove(node); + Console.WriteLine("DisableMovementOnUpgrade is removed. Use Mobile upgradablility instead for " + parent.Key + "."); + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/OpenRA.Mods.D2k/Traits/Carryable.cs b/OpenRA.Mods.D2k/Traits/Carryable.cs index 6cdc5e0e41..8974b344a7 100644 --- a/OpenRA.Mods.D2k/Traits/Carryable.cs +++ b/OpenRA.Mods.D2k/Traits/Carryable.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.D2k.Traits public object Create(ActorInitializer init) { return new Carryable(init.Self, this); } } - public class Carryable : IDisableMove, INotifyHarvesterAction, ICallForTransport + public class Carryable : INotifyHarvesterAction, ICallForTransport { readonly CarryableInfo info; readonly Actor self; @@ -196,12 +196,5 @@ namespace OpenRA.Mods.D2k.Traits return true; } - - // IMoveDisabled - public bool MoveDisabled(Actor self) - { - // We do not want to move while being locked. The carrier will try to pick us up. - return locked; - } } } diff --git a/mods/cnc/rules/ships.yaml b/mods/cnc/rules/ships.yaml index 8217d2cc23..937ac16c50 100644 --- a/mods/cnc/rules/ships.yaml +++ b/mods/cnc/rules/ships.yaml @@ -47,6 +47,8 @@ LST: BuildPaletteOrder: 1000 Prerequisites: ~disabled Mobile: + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 Crushes: crate TerrainSpeeds: Clear: 100 @@ -76,4 +78,5 @@ LST: MaxWeight: 5 PipCount: 5 PassengerFacing: 0 + LoadingUpgrades: notmobile diff --git a/mods/cnc/rules/vehicles.yaml b/mods/cnc/rules/vehicles.yaml index 17fab2ef02..e29b147a65 100644 --- a/mods/cnc/rules/vehicles.yaml +++ b/mods/cnc/rules/vehicles.yaml @@ -89,6 +89,8 @@ APC: Prerequisites: pyle Queue: Vehicle.GDI Mobile: + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 ROT: 8 Speed: 128 Health: @@ -120,6 +122,7 @@ APC: Types: Infantry MaxWeight: 5 PipCount: 5 + LoadingUpgrades: notmobile SpawnActorOnDeath: Actor: APC.Husk diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index d7ef14dc1a..b27824fa6a 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -58,6 +58,8 @@ Inherits@2: ^GainsExperience Inherits@3: ^SpriteActor Mobile: + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 Crushes: crate, spicebloom TerrainSpeeds: Sand: 100 @@ -92,6 +94,7 @@ Voiced: VoiceSet: VehicleVoice Carryable: + CarryableUpgrades: notmobile WithDecorationCarryable: Image: pips Sequence: pickup-indicator diff --git a/mods/d2k/rules/infantry.yaml b/mods/d2k/rules/infantry.yaml index 78ef1fdbb7..9e35b61a15 100644 --- a/mods/d2k/rules/infantry.yaml +++ b/mods/d2k/rules/infantry.yaml @@ -93,6 +93,8 @@ thumper: RevealsShroud: Range: 2c768 Mobile: + UpgradeTypes: deployed + UpgradeMaxEnabledLevel: 0 Speed: 43 DeployToUpgrade: DeployedUpgrades: deployed @@ -119,9 +121,6 @@ thumper: Falloff: 0, 0, 0, 100, 100, 100, 25, 11, 6, 4, 3, 2, 1, 0 UpgradeTypes: deployed UpgradeMinEnabledLevel: 1 - DisableOnUpgrade: - UpgradeTypes: deployed - UpgradeMinEnabledLevel: 1 Passenger: PipType: Blue Voiced: diff --git a/mods/ra/rules/ships.yaml b/mods/ra/rules/ships.yaml index a496b33edd..1b690addc2 100644 --- a/mods/ra/rules/ships.yaml +++ b/mods/ra/rules/ships.yaml @@ -226,6 +226,8 @@ LST: Armor: Type: Heavy Mobile: + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 ROT: 10 Speed: 113 RevealsShroud: @@ -239,6 +241,7 @@ LST: MaxWeight: 5 PipCount: 5 PassengerFacing: 0 + LoadingUpgrades: notmobile -Chronoshiftable: PT: diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index 7f15891566..0f6a93a45c 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -334,6 +334,8 @@ JEEP: Mobile: ROT: 10 Speed: 170 + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 RevealsShroud: Range: 8c0 Turreted: @@ -350,6 +352,7 @@ JEEP: Types: Infantry MaxWeight: 1 PipCount: 1 + LoadingUpgrades: notmobile ProducibleWithLevel: Prerequisites: vehicles.upgraded @@ -371,6 +374,8 @@ APC: Mobile: Speed: 142 Crushes: wall, mine, crate, infantry + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 RevealsShroud: Range: 5c0 Armament: @@ -384,6 +389,7 @@ APC: Types: Infantry MaxWeight: 5 PipCount: 5 + LoadingUpgrades: notmobile ProducibleWithLevel: Prerequisites: vehicles.upgraded @@ -727,6 +733,8 @@ STNK: Mobile: Speed: 142 Crushes: wall, mine, crate, infantry + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 RevealsShroud: Range: 7c0 AutoTarget: @@ -743,6 +751,7 @@ STNK: Types: Infantry MaxWeight: 4 PipCount: 4 + LoadingUpgrades: notmobile Cloak: InitialDelay: 125 CloakDelay: 250 diff --git a/mods/ts/rules/civilian-vehicles.yaml b/mods/ts/rules/civilian-vehicles.yaml index 19b4e3ec7c..b8dff29a9e 100644 --- a/mods/ts/rules/civilian-vehicles.yaml +++ b/mods/ts/rules/civilian-vehicles.yaml @@ -98,6 +98,7 @@ BUS: MaxWeight: 20 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile PICK: Inherits: ^CivilianVoxelVehicle @@ -119,6 +120,7 @@ PICK: MaxWeight: 2 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile CAR: Inherits: ^CivilianVoxelVehicle @@ -140,6 +142,7 @@ CAR: MaxWeight: 4 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile WINI: Inherits: ^CivilianVoxelVehicle @@ -161,6 +164,7 @@ WINI: MaxWeight: 5 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile LOCOMOTIVE: Inherits: ^Train @@ -169,10 +173,8 @@ LOCOMOTIVE: Tooltip: Name: Train Locomotive Cargo: - Types: Infantry MaxWeight: 2 PipCount: 2 - UnloadVoice: Unload TRAINCAR: Inherits: ^Train @@ -181,10 +183,8 @@ TRAINCAR: Tooltip: Name: Passenger Car Cargo: - Types: Infantry MaxWeight: 10 PipCount: 5 - UnloadVoice: Unload CARGOCAR: Inherits: ^Train @@ -193,8 +193,6 @@ CARGOCAR: Tooltip: Name: Cargo Car Cargo: - Types: Infantry MaxWeight: 10 PipCount: 5 - UnloadVoice: Unload diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 316e5157ff..55383bd3e7 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -73,6 +73,12 @@ UpgradeTypes: empdisable Modifier: 0 +^EmpDisableMobile: + Inherits: ^EmpDisable + Mobile: + UpgradeTypes: notmobile + UpgradeMaxEnabledLevel: 0 + ^BasicBuilding: Inherits@1: ^ExistsInWorld Inherits@2: ^SpriteActor @@ -334,7 +340,7 @@ ^Cyborg: Inherits@1: ^Infantry - Inherits@2: ^EmpDisable + Inherits@2: ^EmpDisableMobile RevealsShroud: Range: 4c0 MustBeDestroyed: @@ -361,7 +367,7 @@ ^Vehicle: Inherits@1: ^GainsExperience Inherits@2: ^ExistsInWorld - Inherits@3: ^EmpDisable + Inherits@3: ^EmpDisableMobile DrawLineToTarget: Mobile: Crushes: crate @@ -656,7 +662,7 @@ ActorLostNotification: ^Train: - Inherits@1: ^EmpDisable + Inherits@1: ^EmpDisableMobile Inherits@2: ^ExistsInWorld RenderVoxels: WithVoxelBody: @@ -667,6 +673,10 @@ ROT: 5 Voice: Move Speed: 113 + Cargo: + Types: Infantry + UnloadVoice: Unload + LoadingUpgrades: notmobile Health: HP: 100 Armor: diff --git a/mods/ts/rules/gdi-vehicles.yaml b/mods/ts/rules/gdi-vehicles.yaml index 04c0f0a2c2..0a140c7ff3 100644 --- a/mods/ts/rules/gdi-vehicles.yaml +++ b/mods/ts/rules/gdi-vehicles.yaml @@ -27,6 +27,7 @@ APC: MaxWeight: 5 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile -WithVoxelBody: WithVoxelWaterBody: LeavesTrails: diff --git a/mods/ts/rules/nod-vehicles.yaml b/mods/ts/rules/nod-vehicles.yaml index c3ea24fa90..51d1895d20 100644 --- a/mods/ts/rules/nod-vehicles.yaml +++ b/mods/ts/rules/nod-vehicles.yaml @@ -226,6 +226,7 @@ SAPC: MaxWeight: 5 PipCount: 5 UnloadVoice: Unload + LoadingUpgrades: notmobile SUBTANK: Inherits: ^VoxelTank diff --git a/mods/ts/rules/shared-vehicles.yaml b/mods/ts/rules/shared-vehicles.yaml index d1fe767309..caf38fc2cb 100644 --- a/mods/ts/rules/shared-vehicles.yaml +++ b/mods/ts/rules/shared-vehicles.yaml @@ -127,7 +127,7 @@ LPST: gdi: lpst.gdi nod: lpst.nod DeployToUpgrade: - DeployedUpgrades: deployed + DeployedUpgrades: deployed, notmobile UndeployedUpgrades: undeployed DeployAnimation: make Facing: 160 @@ -141,9 +141,6 @@ LPST: WithSpriteBody@deployed: UpgradeTypes: undeployed UpgradeMaxEnabledLevel: 0 - DisableOnUpgrade: - UpgradeTypes: undeployed - UpgradeMaxEnabledLevel: 0 DetectCloaked: UpgradeTypes: deployed UpgradeMinEnabledLevel: 1 diff --git a/mods/ts/weapons/superweapons.yaml b/mods/ts/weapons/superweapons.yaml index 2d3143a87f..0f066f6596 100644 --- a/mods/ts/weapons/superweapons.yaml +++ b/mods/ts/weapons/superweapons.yaml @@ -90,7 +90,7 @@ EMPulseCannon: Warhead@emp: GrantUpgrade Range: 3c0 Duration: 250 - Upgrades: empdisable + Upgrades: empdisable, notmobile ClusterMissile: ValidTargets: Ground, Water, Air From e9b0691f70ab6821676c456a68e07a737b9585cd Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Fri, 27 Nov 2015 00:51:51 -0600 Subject: [PATCH 5/5] Improve rule upgrade logic for immobilization --- .../UtilityCommands/UpgradeRules.cs | 185 ++++++++++++++++-- 1 file changed, 166 insertions(+), 19 deletions(-) diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 818c4be6f8..2fe4617c25 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -2510,29 +2510,176 @@ namespace OpenRA.Mods.Common.UtilityCommands } } - // Notify how to restore blocking movement of Mobile actors with Carryable and/or Cargo - if (engineVersion < 20151204 && depth == 2) + // Mobile actors immobilized by Carryable, Cargo, DeployToUpgrade, and/or others using upgrade(s) + if (engineVersion < 20151204 && depth == 0) { - if (node.Key == "Carryable") + var notMobile = "notmobile"; + + var mobileNode = node.Value.Nodes.Find(n => n.Key == "Mobile"); + var carryableNode = node.Value.Nodes.Find(n => n.Key == "Carryable"); + var cargoNode = node.Value.Nodes.Find(n => n.Key == "Cargo"); + var deployToUpgradeNode = node.Value.Nodes.Find(n => n.Key == "DeployToUpgrade"); + var disableUpgradeNode = node.Value.Nodes.Find(n => n.Key == "DisableUpgrade"); + var disableMovementOnUpgradeNode = node.Value.Nodes.Find(n => n.Key == "DisableMovementOnUpgrade"); + + Action addNotMobileToTraitUpgrades = (trait, upgradesKey) => { - Console.WriteLine("Use CarryableUpgrades of Carryable to disable Mobile while " + parent.Key + " is waiting or being carried."); + if (trait != null) + { + var upgrades = trait.Value.Nodes.Find(u => u.Key == upgradesKey); + if (upgrades == null) + trait.Value.Nodes.Add(new MiniYamlNode(upgradesKey, notMobile)); + else if (string.IsNullOrEmpty(upgrades.Value.Value)) + upgrades.Value.Value = notMobile; + else if (!upgrades.Value.Value.Contains(notMobile)) + upgrades.Value.Value += ", " + notMobile; + } + }; + + if (mobileNode != null) + { + var mobileUpgrades = mobileNode.Value.Nodes.Find(n => n.Key == "UpgradeTypes"); + var mobileUpgradeMaxEnabledLevel = mobileNode.Value.Nodes.Find(n => n.Key == "UpgradeMaxEnabledLevel"); + var comma = new char[] { ',' }; + + Func addUpgradeMaxEnabledLevelNode = () => + { + if (mobileUpgradeMaxEnabledLevel == null) + { + mobileUpgradeMaxEnabledLevel = new MiniYamlNode("UpgradeMaxEnabledLevel", "0"); + mobileNode.Value.Nodes.Add(mobileUpgradeMaxEnabledLevel); + return true; + } + else + return mobileUpgradeMaxEnabledLevel.Value.Value == "0"; + }; + + // If exactly one upgrade type is in UpgradeTypes and UpgradeMaxEnabledLevel is/can be 0 , then use it as notmobile + if (mobileUpgrades != null && !string.IsNullOrEmpty(mobileUpgrades.Value.Value) + && !mobileUpgrades.Value.Value.Contains(",") && addUpgradeMaxEnabledLevelNode()) + notMobile = mobileUpgrades.Value.Value; + + if (mobileUpgradeMaxEnabledLevel != null && mobileUpgradeMaxEnabledLevel.Value.Value != "0") + Console.WriteLine("\t\t" + node.Key + " actor rules may require manual upgrading for immobilization upgrade logic."); + else + { + Action addImmobilizeUpgradeType = upgradeType => + { + if (mobileUpgrades == null) + { + mobileUpgrades = new MiniYamlNode("UpgradeTypes", upgradeType); + mobileNode.Value.Nodes.Add(mobileUpgrades); + } + else if (string.IsNullOrEmpty(mobileUpgrades.Value.Value)) + mobileUpgrades.Value.Value = upgradeType; + else if (!mobileUpgrades.Value.Value.Split(comma).Contains(upgradeType)) + mobileUpgrades.Value.Value += ", " + upgradeType; + }; + + Predicate addImmobilizeUpgradeTypes = upgradeTypes => + { + if (string.IsNullOrEmpty(upgradeTypes)) + return false; + + foreach (var upgradeType in upgradeTypes.Split(comma)) + addImmobilizeUpgradeType(upgradeType); + return true; + }; + + Predicate addUpgradeTypeFromTrait = trait => + { + var upgradeTypesNode = trait.Value.Nodes.Find(n => n.Key == "UpgradeTypes"); + if (upgradeTypesNode == null) + return false; + + addUpgradeMaxEnabledLevelNode(); + return addImmobilizeUpgradeTypes(upgradeTypesNode.Value.Value); + }; + + var noticeWritten = false; + + Action writeNotice = () => + { + if (noticeWritten) + return; + Console.WriteLine("\t\t" + node.Key + " actor rules may require manual upgrading for immobilization upgrade logic."); + noticeWritten = true; + }; + + if (disableUpgradeNode != null && !addUpgradeTypeFromTrait(disableUpgradeNode)) + { + writeNotice(); + Console.WriteLine("\t\t\tOne or more upgrades may need to be copied from the DisableUpgrade trait to the Mobile trait."); + } + + if (disableMovementOnUpgradeNode != null) + { + if (addUpgradeTypeFromTrait(disableMovementOnUpgradeNode)) + parent.Value.Nodes.Remove(disableMovementOnUpgradeNode); + else + { + writeNotice(); + Console.WriteLine("\t\t\tOne or more upgrades may need to be moved from the DisableMovementOnUpgrade trait to the Mobile trait."); + Console.WriteLine("\t\t\t\tRemember to remove the DisableMovementOnUpgrade trait."); + } + } + + if (carryableNode != null || cargoNode != null || deployToUpgradeNode != null) + { + addUpgradeMaxEnabledLevelNode(); + addImmobilizeUpgradeTypes(notMobile); + + addNotMobileToTraitUpgrades(carryableNode, "CarryableUpgrades"); + addNotMobileToTraitUpgrades(cargoNode, "LoadingUpgrades"); + addNotMobileToTraitUpgrades(deployToUpgradeNode, "DeployedUpgrades"); + } + } } - else if (node.Key == "Cargo") + else if (!node.Value.Nodes.Exists(n => n.Key == "Husk" || n.Key == "Building" || n.Key == "Aircraft" || n.Key == "Immobile")) { - Console.WriteLine("Use LoadingUpgrades of Cargo to disable Mobile while " + parent.Key + " is loading cargo."); - } - else if (node.Key == "DeployToUpgrade") - { - Console.WriteLine("Use Upgrades of DeployToUpgrade to disable Mobile while " + parent.Key + " is deployed (instead of DisableUpgrade)."); - } - else if (node.Key == "DisableUpgrade") - { - Console.WriteLine("DisableUpgrade no longer disables Mobile. Use Mobile upgradablility instead for " + parent.Key + "."); - } - else if (node.Key == "DisableMovementOnUpgrade") - { - parent.Value.Nodes.Remove(node); - Console.WriteLine("DisableMovementOnUpgrade is removed. Use Mobile upgradablility instead for " + parent.Key + "."); + if (carryableNode != null || cargoNode != null || deployToUpgradeNode != null) + { + Console.WriteLine("\t\tIf " + node.Key + + " has a Mobile trait then adding the following with substituted by an immobilization upgrade for " + + node.Key + " may be neeeded:"); + + if (carryableNode != null) + { + Console.WriteLine("\t\t\tCarryable:"); + Console.WriteLine("\t\t\t\tCarryableUpgrades: "); + } + + if (cargoNode != null) + { + Console.WriteLine("\t\t\tCargo:"); + Console.WriteLine("\t\t\t\tLoadingUpgrades: "); + } + + if (deployToUpgradeNode != null) + { + Console.WriteLine("\t\t\tDeployToUpgrade:"); + Console.WriteLine("\t\t\t\tDeployedUpgrades: "); + } + } + + var disableUpgradeUpgradeTypesNode = disableUpgradeNode != null + ? disableUpgradeNode.Value.Nodes.Find(n => n.Key == "UpgradeTypes") + : null; + var disableMovementOnUpgradeUpgradeTypesNode = disableMovementOnUpgradeNode != null + ? disableMovementOnUpgradeNode.Value.Nodes.Find(n => n.Key == "UpgradeTypes") + : null; + + if (disableUpgradeUpgradeTypesNode != null || disableMovementOnUpgradeUpgradeTypesNode != null) + Console.WriteLine("\t\t" + node.Key + " actor rules may require manual upgrading for immobilization upgrade logic."); + + if (disableUpgradeUpgradeTypesNode != null) + Console.WriteLine("\t\t\tDisableUpgrade UpgradeTypes: " + disableUpgradeUpgradeTypesNode.Value.Value); + + if (disableMovementOnUpgradeUpgradeTypesNode != null) + Console.WriteLine("\t\t\tDisableMovementOnUpgrade UpgradeTypes: " + disableMovementOnUpgradeUpgradeTypesNode.Value.Value); + + if (disableMovementOnUpgradeNode != null) + node.Value.Nodes.Remove(disableMovementOnUpgradeNode); } }