From ea036d4cc0921631ef540850dc51acc8873a5339 Mon Sep 17 00:00:00 2001 From: tovl Date: Fri, 7 Jun 2019 22:14:47 +0000 Subject: [PATCH] Allow move orders to cancel DeployForGrantedCondition. --- .../Activities/DeployForGrantedCondition.cs | 58 +++++++++++++------ .../Activities/UndeployForGrantedCondition.cs | 39 ------------- .../Conditions/GrantConditionOnDeploy.cs | 44 +++++++++----- OpenRA.Mods.Common/Traits/Mobile.cs | 31 ++++++---- OpenRA.Mods.Common/TraitsInterfaces.cs | 5 ++ mods/ts/chrome/ingame-player.yaml | 2 +- mods/ts/rules/gdi-vehicles.yaml | 2 +- mods/ts/rules/nod-vehicles.yaml | 4 +- mods/ts/rules/shared-vehicles.yaml | 2 +- 9 files changed, 99 insertions(+), 88 deletions(-) delete mode 100644 OpenRA.Mods.Common/Activities/UndeployForGrantedCondition.cs diff --git a/OpenRA.Mods.Common/Activities/DeployForGrantedCondition.cs b/OpenRA.Mods.Common/Activities/DeployForGrantedCondition.cs index ef1428cdf6..8ad4c1da42 100644 --- a/OpenRA.Mods.Common/Activities/DeployForGrantedCondition.cs +++ b/OpenRA.Mods.Common/Activities/DeployForGrantedCondition.cs @@ -19,49 +19,71 @@ namespace OpenRA.Mods.Common.Activities { readonly GrantConditionOnDeploy deploy; readonly bool canTurn; + readonly bool moving; + bool initiated; - public DeployForGrantedCondition(Actor self, GrantConditionOnDeploy deploy) + public DeployForGrantedCondition(Actor self, GrantConditionOnDeploy deploy, bool moving = false) { this.deploy = deploy; + this.moving = moving; canTurn = self.Info.HasTraitInfo(); } protected override void OnFirstRun(Actor self) { // Turn to the required facing. - if (deploy.Info.Facing != -1 && canTurn) + if (deploy.DeployState == DeployState.Undeployed && deploy.Info.Facing != -1 && canTurn && !moving) QueueChild(self, new Turn(self, deploy.Info.Facing)); } public override Activity Tick(Actor self) { - // Do turn first, if needed. if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); - return this; + if (ChildActivity != null) + return this; } - // Without this, turn for facing deploy angle will be canceled and immediately deploy! - if (IsCanceling) + if (IsCanceling || initiated || (deploy.DeployState != DeployState.Deployed && moving)) return NextActivity; - if (IsInterruptible) - { - IsInterruptible = false; // must DEPLOY from now. - deploy.Deploy(); - return this; - } + QueueChild(self, new DeployInner(self, deploy), true); + initiated = true; + return this; + } + } + + public class DeployInner : Activity + { + readonly GrantConditionOnDeploy deployment; + bool initiated; + + public DeployInner(Actor self, GrantConditionOnDeploy deployment) + { + this.deployment = deployment; + + // Once deployment animation starts, the animation must finish. + IsInterruptible = false; + } + + public override Activity Tick(Actor self) + { // Wait for deployment - if (deploy.DeployState == DeployState.Deploying) + if (deployment.DeployState == DeployState.Deploying || deployment.DeployState == DeployState.Undeploying) return this; - // Failed or success, we are going to NextActivity. - // Deploy() at the first run would have put DeployState == Deploying so - // if we are back to DeployState.Undeployed, it means deploy failure. - // Parent activity will see the status and will take appropriate action. - return NextActivity; + if (initiated) + return NextActivity; + + if (deployment.DeployState == DeployState.Undeployed) + deployment.Deploy(); + else + deployment.Undeploy(); + + initiated = true; + return this; } } } diff --git a/OpenRA.Mods.Common/Activities/UndeployForGrantedCondition.cs b/OpenRA.Mods.Common/Activities/UndeployForGrantedCondition.cs deleted file mode 100644 index c3428fc0cb..0000000000 --- a/OpenRA.Mods.Common/Activities/UndeployForGrantedCondition.cs +++ /dev/null @@ -1,39 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2019 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 OpenRA.Activities; -using OpenRA.Mods.Common.Traits; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Activities -{ - public class UndeployForGrantedCondition : Activity - { - readonly GrantConditionOnDeploy deploy; - - public UndeployForGrantedCondition(Actor self, GrantConditionOnDeploy deploy) - { - this.deploy = deploy; - } - - public override Activity Tick(Actor self) - { - IsInterruptible = false; // must DEPLOY from now. - deploy.Undeploy(); - - // Wait for deployment - if (deploy.DeployState == DeployState.Undeploying) - return this; - - return NextActivity; - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeploy.cs b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeploy.cs index da5c1b1857..b827c23184 100644 --- a/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeploy.cs +++ b/OpenRA.Mods.Common/Traits/Conditions/GrantConditionOnDeploy.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.Activities; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Orders; using OpenRA.Traits; @@ -54,6 +55,9 @@ namespace OpenRA.Mods.Common.Traits [Desc("Skip make/deploy animation?")] public readonly bool SkipMakeAnimation = false; + [Desc("Undeploy before the actor tries to move?")] + public readonly bool UndeployOnMove = false; + [VoiceReference] public readonly string Voice = "Action"; @@ -63,11 +67,12 @@ namespace OpenRA.Mods.Common.Traits public enum DeployState { Undeployed, Deploying, Deployed, Undeploying } public class GrantConditionOnDeploy : PausableConditionalTrait, IResolveOrder, IIssueOrder, INotifyCreated, - INotifyDeployComplete, IIssueDeployOrder, IOrderVoice + INotifyDeployComplete, IIssueDeployOrder, IOrderVoice, IWrapMove { readonly Actor self; readonly bool checkTerrainType; readonly bool canTurn; + readonly IMove move; DeployState deployState; ConditionManager conditionManager; @@ -83,6 +88,7 @@ namespace OpenRA.Mods.Common.Traits self = init.Self; checkTerrainType = info.AllowedTerrainTypes.Count > 0; canTurn = self.Info.HasTraitInfo(); + move = self.TraitOrDefault(); if (init.Contains()) deployState = init.Get(); } @@ -118,20 +124,32 @@ namespace OpenRA.Mods.Common.Traits } } - public IEnumerable Orders + Activity IWrapMove.WrapMove(Activity moveInner) + { + // Note: We can't assume anything about the current deploy state + // because WrapMove may be called for a queued order + if (!Info.UndeployOnMove) + return moveInner; + + var activity = new DeployForGrantedCondition(self, this, true); + activity.Queue(self, moveInner); + return activity; + } + + IEnumerable IIssueOrder.Orders { get { if (!IsTraitDisabled) yield return new DeployOrderTargeter("GrantConditionOnDeploy", 5, - () => IsCursorBlocked() ? Info.DeployBlockedCursor : Info.DeployCursor); + () => CanDeploy() ? Info.DeployCursor : Info.DeployBlockedCursor); } } public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) { if (order.OrderID == "GrantConditionOnDeploy") - return new Order(order.OrderID, self, queued); + return new Order(order.OrderID, self, target, queued); return null; } @@ -148,16 +166,10 @@ namespace OpenRA.Mods.Common.Traits if (IsTraitDisabled || IsTraitPaused) return; - if (order.OrderString != "GrantConditionOnDeploy" || deployState == DeployState.Deploying || deployState == DeployState.Undeploying) + if (order.OrderString != "GrantConditionOnDeploy") return; - if (!order.Queued) - self.CancelActivity(); - - if (deployState == DeployState.Deployed) - self.QueueActivity(new UndeployForGrantedCondition(self, this)); - else if (deployState == DeployState.Undeployed) - self.QueueActivity(new DeployForGrantedCondition(self, this)); + self.QueueActivity(order.Queued, new DeployForGrantedCondition(self, this)); } public string VoicePhraseForOrder(Actor self, Order order) @@ -165,12 +177,12 @@ namespace OpenRA.Mods.Common.Traits return order.OrderString == "GrantConditionOnDeploy" ? Info.Voice : null; } - bool IsCursorBlocked() + bool CanDeploy() { - if (IsTraitPaused) - return true; + if (IsTraitPaused || IsTraitDisabled) + return false; - return !IsValidTerrain(self.Location) && (deployState != DeployState.Deployed); + return IsValidTerrain(self.Location) || (deployState == DeployState.Deployed); } public bool IsValidTerrain(CPos location) diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 708b7a125e..aab482ad1a 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -157,6 +157,7 @@ namespace OpenRA.Mods.Common.Traits INotifyVisualPositionChanged[] notifyVisualPositionChanged; INotifyMoving[] notifyMoving; INotifyFinishedMoving[] notifyFinishedMoving; + IWrapMove[] moveWrappers; #region IFacing [Sync] @@ -227,6 +228,7 @@ namespace OpenRA.Mods.Common.Traits notifyVisualPositionChanged = self.TraitsImplementing().ToArray(); notifyMoving = self.TraitsImplementing().ToArray(); notifyFinishedMoving = self.TraitsImplementing().ToArray(); + moveWrappers = self.TraitsImplementing().ToArray(); base.Created(self); } @@ -499,32 +501,41 @@ namespace OpenRA.Mods.Common.Traits #region IMove + Activity WrapMove(Activity inner) + { + var moveWrapper = moveWrappers.FirstOrDefault(Exts.IsTraitEnabled); + if (moveWrapper != null) + return moveWrapper.WrapMove(inner); + + return inner; + } + public Activity MoveTo(CPos cell, int nearEnough) { - return new Move(self, cell, WDist.FromCells(nearEnough)); + return WrapMove(new Move(self, cell, WDist.FromCells(nearEnough), null)); } public Activity MoveTo(CPos cell, Actor ignoreActor) { - return new Move(self, cell, WDist.Zero, ignoreActor); + return WrapMove(new Move(self, cell, WDist.Zero, ignoreActor)); } public Activity MoveWithinRange(Target target, WDist range, WPos? initialTargetPosition = null, Color? targetLineColor = null) { - return new MoveWithinRange(self, target, WDist.Zero, range, initialTargetPosition, targetLineColor); + return WrapMove(new MoveWithinRange(self, target, WDist.Zero, range, initialTargetPosition, targetLineColor)); } public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange, WPos? initialTargetPosition = null, Color? targetLineColor = null) { - return new MoveWithinRange(self, target, minRange, maxRange, initialTargetPosition, targetLineColor); + return WrapMove(new MoveWithinRange(self, target, minRange, maxRange, initialTargetPosition, targetLineColor)); } public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange, WPos? initialTargetPosition = null, Color? targetLineColor = null) { - return new Follow(self, target, minRange, maxRange, initialTargetPosition, targetLineColor); + return WrapMove(new Follow(self, target, minRange, maxRange, initialTargetPosition, targetLineColor)); } public Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any) @@ -542,7 +553,7 @@ namespace OpenRA.Mods.Common.Traits SetPosition(self, cell, subCell); SetVisualPosition(self, pos); - return VisualMove(self, pos, self.World.Map.CenterOfSubCell(cell, subCell), cell); + return WrapMove(VisualMove(self, pos, self.World.Map.CenterOfSubCell(cell, subCell), cell)); } public Activity MoveToTarget(Actor self, Target target, @@ -551,7 +562,7 @@ namespace OpenRA.Mods.Common.Traits if (target.Type == TargetType.Invalid) return null; - return new MoveAdjacentTo(self, target, initialTargetPosition, targetLineColor); + return WrapMove(new MoveAdjacentTo(self, target, initialTargetPosition, targetLineColor)); } public Activity MoveIntoTarget(Actor self, Target target) @@ -561,12 +572,12 @@ namespace OpenRA.Mods.Common.Traits // Activity cancels if the target moves by more than half a cell // to avoid problems with the cell grid - return new VisualMoveIntoTarget(self, target, new WDist(512)); + return WrapMove(new VisualMoveIntoTarget(self, target, new WDist(512))); } public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { - return VisualMove(self, fromPos, toPos, self.Location); + return WrapMove(VisualMove(self, fromPos, toPos, self.Location)); } public int EstimatedMoveDuration(Actor self, WPos fromPos, WPos toPos) @@ -768,7 +779,7 @@ namespace OpenRA.Mods.Common.Traits self.CancelActivity(); self.SetTargetLine(Target.FromCell(self.World, cell), Color.Green); - self.QueueActivity(order.Queued, new Move(self, cell, WDist.FromCells(8), null, true)); + self.QueueActivity(order.Queued, WrapMove(new Move(self, cell, WDist.FromCells(8), null, true))); } if (order.OrderString == "Stop") diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index cd37d14dc7..c46fba9ea8 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -437,6 +437,11 @@ namespace OpenRA.Mods.Common.Traits bool CanEnterTargetNow(Actor self, Target target); } + public interface IWrapMove + { + Activity WrapMove(Activity moveInner); + } + public interface IRadarSignature { void PopulateRadarSignatureCells(Actor self, List> destinationBuffer); diff --git a/mods/ts/chrome/ingame-player.yaml b/mods/ts/chrome/ingame-player.yaml index a5c6b8429e..275d3eb52f 100644 --- a/mods/ts/chrome/ingame-player.yaml +++ b/mods/ts/chrome/ingame-player.yaml @@ -61,7 +61,7 @@ Container@PLAYER_WIDGETS: Background: DisableKeySound: true TooltipText: Force Move - TooltipDesc: Selected units will move to the desired location\n - Default activity for the target is suppressed\n - Vehicles will attempt to crush enemies at the target location\n - Units entering transports will consider nearby alternatives\n - Carryalls will not release their cargo at the target location\n\nLeft-click icon then right-click on target.\nHold {(Alt)} to activate temporarily while commanding units. + TooltipDesc: Selected units will move to the desired location\n - Default activity for the target is suppressed\n - Vehicles will attempt to crush enemies at the target location\n - Deployed units will undeploy and move to the target location\n - Units entering transports will consider nearby alternatives\n - Carryalls will not release their cargo at the target location\n\nLeft-click icon then right-click on target.\nHold {(Alt)} to activate temporarily while commanding units. TooltipContainer: TOOLTIP_CONTAINER TooltipTemplate: BUTTON_WITH_DESC_HIGHLIGHT_TOOLTIP Children: diff --git a/mods/ts/rules/gdi-vehicles.yaml b/mods/ts/rules/gdi-vehicles.yaml index 7ae2c705ab..3e88775924 100644 --- a/mods/ts/rules/gdi-vehicles.yaml +++ b/mods/ts/rules/gdi-vehicles.yaml @@ -330,7 +330,6 @@ JUGG: Mobile: Speed: 71 TurnSpeed: 5 - RequiresCondition: undeployed PauseOnCondition: empdisable || being-captured RevealsShroud: RequiresCondition: !inside-tunnel @@ -352,6 +351,7 @@ JUGG: PauseOnCondition: empdisable || being-captured DeployedCondition: deployed UndeployedCondition: undeployed + UndeployOnMove: true Facing: 96 AllowedTerrainTypes: Clear, Road, DirtRoad, Rough DeploySounds: place2.aud diff --git a/mods/ts/rules/nod-vehicles.yaml b/mods/ts/rules/nod-vehicles.yaml index 8b406318b3..12fe1e5e4a 100644 --- a/mods/ts/rules/nod-vehicles.yaml +++ b/mods/ts/rules/nod-vehicles.yaml @@ -104,7 +104,6 @@ TTNK: Mobile: TurnSpeed: 5 Speed: 85 - RequiresCondition: undeployed PauseOnCondition: empdisable || being-captured Health: HP: 35000 @@ -135,6 +134,7 @@ TTNK: PauseOnCondition: empdisable || being-captured DeployedCondition: deployed UndeployedCondition: undeployed + UndeployOnMove: true Facing: 160 AllowedTerrainTypes: Clear, Road, DirtRoad, Rough DeploySounds: place2.aud @@ -226,7 +226,6 @@ ART2: Mobile: Speed: 71 TurnSpeed: 2 - RequiresCondition: undeployed PauseOnCondition: empdisable || being-captured RevealsShroud: RequiresCondition: !inside-tunnel @@ -241,6 +240,7 @@ ART2: PauseOnCondition: empdisable || being-captured DeployedCondition: deployed UndeployedCondition: undeployed + UndeployOnMove: true Facing: 96 AllowedTerrainTypes: Clear, Road, DirtRoad, Rough DeploySounds: place2.aud diff --git a/mods/ts/rules/shared-vehicles.yaml b/mods/ts/rules/shared-vehicles.yaml index e3a0540b1f..1dca7fb96e 100644 --- a/mods/ts/rules/shared-vehicles.yaml +++ b/mods/ts/rules/shared-vehicles.yaml @@ -126,7 +126,6 @@ LPST: Mobile: Speed: 85 TurnSpeed: 5 - RequiresCondition: undeployed PauseOnCondition: empdisable || being-captured RevealsShroud: RequiresCondition: !inside-tunnel && undeployed @@ -148,6 +147,7 @@ LPST: PauseOnCondition: empdisable || being-captured DeployedCondition: deployed UndeployedCondition: undeployed + UndeployOnMove: true Facing: 160 AllowedTerrainTypes: Clear, Road, DirtRoad, Rough DeploySounds: place2.aud