Revise AttackMoveActivity.

This commit is contained in:
tovl
2019-03-09 16:06:03 +01:00
committed by Oliver Brakmann
parent 01f6f98097
commit 64cec4a0ad
10 changed files with 82 additions and 65 deletions

View File

@@ -53,8 +53,8 @@ namespace OpenRA.Mods.Common.Activities
(hasHost ? self.World.Map.CellContaining(host.CenterPosition) : self.Location); (hasHost ? self.World.Map.CellContaining(host.CenterPosition) : self.Location);
if (moveToRallyPoint(self, this, destination)) if (moveToRallyPoint(self, this, destination))
return new AttackMoveActivity(self, move.MoveTo(destination, 1)); return new AttackMoveActivity(self, () => move.MoveTo(destination, 1));
else
return NextActivity; return NextActivity;
} }
} }

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Activities
return this; return this;
return ActivityUtils.SequenceActivities(self, return ActivityUtils.SequenceActivities(self,
new AttackMoveActivity(self, move.MoveTo(target.Location, 2)), new AttackMoveActivity(self, () => move.MoveTo(target.Location, 2)),
new Wait(25), new Wait(25),
this); this);
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
@@ -18,31 +19,75 @@ namespace OpenRA.Mods.Common.Activities
{ {
public class AttackMoveActivity : Activity public class AttackMoveActivity : Activity
{ {
const int ScanInterval = 7; readonly Func<Activity> getInner;
public readonly bool IsAssaultMove;
Activity inner; Activity inner;
int scanTicks; Activity attack;
AutoTarget autoTarget; AutoTarget autoTarget;
bool moving;
public AttackMoveActivity(Actor self, Activity inner) public AttackMoveActivity(Actor self, Func<Activity> getInner, bool assaultMoving = false)
{ {
this.inner = inner; this.getInner = getInner;
autoTarget = self.TraitOrDefault<AutoTarget>(); autoTarget = self.TraitOrDefault<AutoTarget>();
moving = false;
IsAssaultMove = assaultMoving;
} }
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
if (autoTarget != null && --scanTicks <= 0) if (IsCanceling)
{ {
autoTarget.ScanAndAttack(self, true); if (attack != null)
scanTicks = ScanInterval; {
attack = ActivityUtils.RunActivity(self, attack);
return this;
}
if (inner != null)
{
inner = ActivityUtils.RunActivity(self, inner);
return this;
}
return NextActivity;
}
if (attack == null && autoTarget != null)
{
var target = autoTarget.ScanForTarget(self, true);
if (target.Type != TargetType.Invalid)
{
if (inner != null)
inner.Cancel(self);
var attackBases = autoTarget.ActiveAttackBases;
foreach (var ab in attackBases)
{
if (attack == null)
attack = ab.GetAttackActivity(self, target, true, false);
else
attack = ActivityUtils.SequenceActivities(self, attack, ab.GetAttackActivity(self, target, true, false));
ab.OnQueueAttackActivity(self, target, false, true, false);
}
moving = false;
}
}
if (attack == null && inner == null)
{
if (moving)
return NextActivity;
inner = getInner();
moving = true;
} }
if (inner == null) if (inner == null)
return NextActivity; attack = ActivityUtils.RunActivity(self, attack);
inner = ActivityUtils.RunActivity(self, inner); inner = ActivityUtils.RunActivity(self, inner);
return this; return this;
} }
@@ -51,6 +96,9 @@ namespace OpenRA.Mods.Common.Activities
if (!IsCanceling && inner != null) if (!IsCanceling && inner != null)
inner.Cancel(self); inner.Cancel(self);
if (!IsCanceling && attack != null)
attack.Cancel(self);
base.Cancel(self, keepQueue); base.Cancel(self, keepQueue);
} }

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System;
using System.Linq; using System.Linq;
using Eluant; using Eluant;
using OpenRA.Activities; using OpenRA.Activities;
@@ -43,7 +44,7 @@ namespace OpenRA.Mods.Common.Scripting
"close enough to complete the activity.")] "close enough to complete the activity.")]
public void AttackMove(CPos cell, int closeEnough = 0) public void AttackMove(CPos cell, int closeEnough = 0)
{ {
Self.QueueActivity(new AttackMoveActivity(Self, move.MoveTo(cell, closeEnough))); Self.QueueActivity(new AttackMoveActivity(Self, () => move.MoveTo(cell, closeEnough)));
} }
[ScriptActorPropertyActivity] [ScriptActorPropertyActivity]
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.Common.Scripting
{ {
foreach (var wpt in waypoints) foreach (var wpt in waypoints)
{ {
Self.QueueActivity(new AttackMoveActivity(Self, move.MoveTo(wpt, 2))); Self.QueueActivity(new AttackMoveActivity(Self, () => move.MoveTo(wpt, 2)));
Self.QueueActivity(new Wait(wait)); Self.QueueActivity(new Wait(wait));
} }

View File

@@ -163,7 +163,7 @@ namespace OpenRA.Mods.Common.Traits
} }
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier, public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing,
IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables
{ {
static readonly Pair<CPos, SubCell>[] NoCells = { }; static readonly Pair<CPos, SubCell>[] NoCells = { };
@@ -173,7 +173,6 @@ namespace OpenRA.Mods.Common.Traits
RepairableInfo repairableInfo; RepairableInfo repairableInfo;
RearmableInfo rearmableInfo; RearmableInfo rearmableInfo;
AttackMove attackMove;
ConditionManager conditionManager; ConditionManager conditionManager;
IDisposable reservation; IDisposable reservation;
IEnumerable<int> speedModifiers; IEnumerable<int> speedModifiers;
@@ -231,7 +230,6 @@ namespace OpenRA.Mods.Common.Traits
{ {
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>(); repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>(); rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
attackMove = self.TraitOrDefault<AttackMove>();
conditionManager = self.TraitOrDefault<ConditionManager>(); conditionManager = self.TraitOrDefault<ConditionManager>();
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier()); speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
cachedPosition = self.CenterPosition; cachedPosition = self.CenterPosition;
@@ -521,16 +519,6 @@ namespace OpenRA.Mods.Common.Traits
init.Add(new FacingInit(Facing)); init.Add(new FacingInit(Facing));
} }
void INotifyBecomingIdle.OnBecomingIdle(Actor self)
{
// HACK: Work around AttackMove relying on INotifyIdle.TickIdle to continue its path
// AttackMoveActivity needs to be rewritten to use child activities instead!
if (attackMove != null && attackMove.TargetLocation.HasValue)
((INotifyIdle)attackMove).TickIdle(self);
else
OnBecomingIdle(self);
}
protected virtual void OnBecomingIdle(Actor self) protected virtual void OnBecomingIdle(Actor self)
{ {
if (Info.VTOL && Info.LandWhenIdle) if (Info.VTOL && Info.LandWhenIdle)

View File

@@ -38,19 +38,14 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new AttackMove(init.Self, this); } public object Create(ActorInitializer init) { return new AttackMove(init.Self, this); }
} }
class AttackMove : INotifyCreated, ITick, IResolveOrder, IOrderVoice, INotifyIdle, ISync class AttackMove : INotifyCreated, ITick, IResolveOrder, IOrderVoice, ISync
{ {
public readonly AttackMoveInfo Info; public readonly AttackMoveInfo Info;
[Sync] public CPos _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : CPos.Zero; } }
public CPos? TargetLocation = null;
readonly IMove move; readonly IMove move;
ConditionManager conditionManager; ConditionManager conditionManager;
int attackMoveToken = ConditionManager.InvalidConditionToken; int attackMoveToken = ConditionManager.InvalidConditionToken;
int assaultMoveToken = ConditionManager.InvalidConditionToken; int assaultMoveToken = ConditionManager.InvalidConditionToken;
bool assaultMoving = false;
public AttackMove(Actor self, AttackMoveInfo info) public AttackMove(Actor self, AttackMoveInfo info)
{ {
@@ -69,8 +64,8 @@ namespace OpenRA.Mods.Common.Traits
return; return;
var activity = self.CurrentActivity as AttackMoveActivity; var activity = self.CurrentActivity as AttackMoveActivity;
var attackActive = activity != null && !assaultMoving; var attackActive = activity != null && !activity.IsAssaultMove;
var assaultActive = activity != null && assaultMoving; var assaultActive = activity != null && activity.IsAssaultMove;
if (attackActive && attackMoveToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.AttackMoveScanCondition)) if (attackActive && attackMoveToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.AttackMoveScanCondition))
attackMoveToken = conditionManager.GrantCondition(self, Info.AttackMoveScanCondition); attackMoveToken = conditionManager.GrantCondition(self, Info.AttackMoveScanCondition);
@@ -98,23 +93,8 @@ namespace OpenRA.Mods.Common.Traits
return null; return null;
} }
void Activate(Actor self, bool assaultMove)
{
assaultMoving = assaultMove;
self.QueueActivity(new AttackMoveActivity(self, move.MoveTo(TargetLocation.Value, 1)));
}
void INotifyIdle.TickIdle(Actor self)
{
// This might cause the actor to be stuck if the target location is unreachable
if (TargetLocation.HasValue && self.Location != TargetLocation.Value)
Activate(self, assaultMoving);
}
public void ResolveOrder(Actor self, Order order) public void ResolveOrder(Actor self, Order order)
{ {
TargetLocation = null;
if (order.OrderString == "AttackMove" || order.OrderString == "AssaultMove") if (order.OrderString == "AttackMove" || order.OrderString == "AssaultMove")
{ {
if (!order.Queued) if (!order.Queued)
@@ -124,9 +104,10 @@ namespace OpenRA.Mods.Common.Traits
if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell)) if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
return; return;
TargetLocation = move.NearestMoveableCell(cell); var targetLocation = move.NearestMoveableCell(cell);
self.SetTargetLine(Target.FromCell(self.World, TargetLocation.Value), Color.Red); self.SetTargetLine(Target.FromCell(self.World, targetLocation), Color.Red);
Activate(self, order.OrderString == "AssaultMove"); var assaultMoving = order.OrderString == "AssaultMove";
self.QueueActivity(new AttackMoveActivity(self, () => move.MoveTo(targetLocation, 1), assaultMoving));
} }
} }
} }

View File

@@ -110,7 +110,7 @@ namespace OpenRA.Mods.Common.Traits
public class AutoTarget : ConditionalTrait<AutoTargetInfo>, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync, INotifyCreated, INotifyOwnerChanged public class AutoTarget : ConditionalTrait<AutoTargetInfo>, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync, INotifyCreated, INotifyOwnerChanged
{ {
readonly IEnumerable<AttackBase> activeAttackBases; public readonly IEnumerable<AttackBase> ActiveAttackBases;
[Sync] int nextScanTime = 0; [Sync] int nextScanTime = 0;
public UnitStance Stance { get { return stance; } } public UnitStance Stance { get { return stance; } }
@@ -151,7 +151,7 @@ namespace OpenRA.Mods.Common.Traits
: base(info) : base(info)
{ {
var self = init.Self; var self = init.Self;
activeAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(Exts.IsTraitEnabled); ActiveAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(Exts.IsTraitEnabled);
if (init.Contains<StanceInit>()) if (init.Contains<StanceInit>())
stance = init.Get<StanceInit, UnitStance>(); stance = init.Get<StanceInit, UnitStance>();
@@ -209,7 +209,7 @@ namespace OpenRA.Mods.Common.Traits
// Not a lot we can do about things we can't hurt... although maybe we should automatically run away? // Not a lot we can do about things we can't hurt... although maybe we should automatically run away?
var attackerAsTarget = Target.FromActor(attacker); var attackerAsTarget = Target.FromActor(attacker);
if (!activeAttackBases.Any(a => a.HasAnyValidWeapons(attackerAsTarget))) if (!ActiveAttackBases.Any(a => a.HasAnyValidWeapons(attackerAsTarget)))
return; return;
// Don't retaliate against own units force-firing on us. It's usually not what the player wanted. // Don't retaliate against own units force-firing on us. It's usually not what the player wanted.
@@ -242,11 +242,11 @@ namespace OpenRA.Mods.Common.Traits
public Target ScanForTarget(Actor self, bool allowMove) public Target ScanForTarget(Actor self, bool allowMove)
{ {
if (nextScanTime <= 0 && activeAttackBases.Any()) if (nextScanTime <= 0 && ActiveAttackBases.Any())
{ {
nextScanTime = self.World.SharedRandom.Next(Info.MinimumScanTimeInterval, Info.MaximumScanTimeInterval); nextScanTime = self.World.SharedRandom.Next(Info.MinimumScanTimeInterval, Info.MaximumScanTimeInterval);
foreach (var ab in activeAttackBases) foreach (var ab in ActiveAttackBases)
{ {
// If we can't attack right now, there's no need to try and find a target. // If we can't attack right now, there's no need to try and find a target.
var attackStances = ab.UnforcedAttackTargetStances(); var attackStances = ab.UnforcedAttackTargetStances();
@@ -272,7 +272,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
self.SetTargetLine(target, Color.Red, false); self.SetTargetLine(target, Color.Red, false);
foreach (var ab in activeAttackBases) foreach (var ab in ActiveAttackBases)
ab.AttackTarget(target, false, allowMove); ab.AttackTarget(target, false, allowMove);
} }

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
self.SetTargetLine(target, Color.Yellow); self.SetTargetLine(target, Color.Yellow);
var range = target.Actor.Info.TraitInfo<GuardableInfo>().Range; var range = target.Actor.Info.TraitInfo<GuardableInfo>().Range;
self.QueueActivity(new AttackMoveActivity(self, move.MoveFollow(self, target, WDist.Zero, range, targetLineColor: Color.Yellow))); self.QueueActivity(new AttackMoveActivity(self, () => move.MoveFollow(self, target, WDist.Zero, range, targetLineColor: Color.Yellow)));
} }
public string VoicePhraseForOrder(Actor self, Order order) public string VoicePhraseForOrder(Actor self, Order order)

View File

@@ -90,8 +90,7 @@ namespace OpenRA.Mods.Common.Traits
newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false)); newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false));
newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit)); newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
newUnit.QueueActivity(new AttackMoveActivity( newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(exitLocation, 1)));
newUnit, move.MoveTo(exitLocation, 1)));
} }
} }

View File

@@ -144,7 +144,7 @@ namespace OpenRA.Mods.Common.Traits
newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false)); newUnit.QueueActivity(new Wait(exitinfo.ExitDelay, false));
newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit)); newUnit.QueueActivity(move.MoveIntoWorld(newUnit, exit));
newUnit.QueueActivity(new AttackMoveActivity(newUnit, move.MoveTo(exitLocation, 1))); newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(exitLocation, 1)));
} }
} }