Allow move orders to cancel DeployForGrantedCondition.

This commit is contained in:
tovl
2019-06-07 22:14:47 +00:00
committed by reaperrr
parent 8589e26dc2
commit ea036d4cc0
9 changed files with 99 additions and 88 deletions

View File

@@ -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<IFacingInfo>();
}
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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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<GrantConditionOnDeployInfo>, 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<IFacingInfo>();
move = self.TraitOrDefault<IMove>();
if (init.Contains<DeployStateInit>())
deployState = init.Get<DeployStateInit, DeployState>();
}
@@ -118,20 +124,32 @@ namespace OpenRA.Mods.Common.Traits
}
}
public IEnumerable<IOrderTargeter> 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<IOrderTargeter> 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)

View File

@@ -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<INotifyVisualPositionChanged>().ToArray();
notifyMoving = self.TraitsImplementing<INotifyMoving>().ToArray();
notifyFinishedMoving = self.TraitsImplementing<INotifyFinishedMoving>().ToArray();
moveWrappers = self.TraitsImplementing<IWrapMove>().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")

View File

@@ -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<Pair<CPos, Color>> destinationBuffer);

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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