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

View File

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

View File

@@ -9,6 +9,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Activities;
using OpenRA.Mods.Common.Traits;
@@ -18,31 +19,75 @@ namespace OpenRA.Mods.Common.Activities
{
public class AttackMoveActivity : Activity
{
const int ScanInterval = 7;
readonly Func<Activity> getInner;
public readonly bool IsAssaultMove;
Activity inner;
int scanTicks;
Activity attack;
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>();
moving = false;
IsAssaultMove = assaultMoving;
}
public override Activity Tick(Actor self)
{
if (autoTarget != null && --scanTicks <= 0)
if (IsCanceling)
{
autoTarget.ScanAndAttack(self, true);
scanTicks = ScanInterval;
if (attack != null)
{
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)
return NextActivity;
attack = ActivityUtils.RunActivity(self, attack);
inner = ActivityUtils.RunActivity(self, inner);
return this;
}
@@ -51,6 +96,9 @@ namespace OpenRA.Mods.Common.Activities
if (!IsCanceling && inner != null)
inner.Cancel(self);
if (!IsCanceling && attack != null)
attack.Cancel(self);
base.Cancel(self, keepQueue);
}

View File

@@ -9,6 +9,7 @@
*/
#endregion
using System;
using System.Linq;
using Eluant;
using OpenRA.Activities;
@@ -43,7 +44,7 @@ namespace OpenRA.Mods.Common.Scripting
"close enough to complete the activity.")]
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]
@@ -53,7 +54,7 @@ namespace OpenRA.Mods.Common.Scripting
{
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));
}

View File

@@ -163,7 +163,7 @@ namespace OpenRA.Mods.Common.Traits
}
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle,
INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing,
IActorPreviewInitModifier, IIssueDeployOrder, IObservesVariables
{
static readonly Pair<CPos, SubCell>[] NoCells = { };
@@ -173,7 +173,6 @@ namespace OpenRA.Mods.Common.Traits
RepairableInfo repairableInfo;
RearmableInfo rearmableInfo;
AttackMove attackMove;
ConditionManager conditionManager;
IDisposable reservation;
IEnumerable<int> speedModifiers;
@@ -231,7 +230,6 @@ namespace OpenRA.Mods.Common.Traits
{
repairableInfo = self.Info.TraitInfoOrDefault<RepairableInfo>();
rearmableInfo = self.Info.TraitInfoOrDefault<RearmableInfo>();
attackMove = self.TraitOrDefault<AttackMove>();
conditionManager = self.TraitOrDefault<ConditionManager>();
speedModifiers = self.TraitsImplementing<ISpeedModifier>().ToArray().Select(sm => sm.GetSpeedModifier());
cachedPosition = self.CenterPosition;
@@ -521,16 +519,6 @@ namespace OpenRA.Mods.Common.Traits
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)
{
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); }
}
class AttackMove : INotifyCreated, ITick, IResolveOrder, IOrderVoice, INotifyIdle, ISync
class AttackMove : INotifyCreated, ITick, IResolveOrder, IOrderVoice, ISync
{
public readonly AttackMoveInfo Info;
[Sync] public CPos _targetLocation { get { return TargetLocation.HasValue ? TargetLocation.Value : CPos.Zero; } }
public CPos? TargetLocation = null;
readonly IMove move;
ConditionManager conditionManager;
int attackMoveToken = ConditionManager.InvalidConditionToken;
int assaultMoveToken = ConditionManager.InvalidConditionToken;
bool assaultMoving = false;
public AttackMove(Actor self, AttackMoveInfo info)
{
@@ -69,8 +64,8 @@ namespace OpenRA.Mods.Common.Traits
return;
var activity = self.CurrentActivity as AttackMoveActivity;
var attackActive = activity != null && !assaultMoving;
var assaultActive = activity != null && assaultMoving;
var attackActive = activity != null && !activity.IsAssaultMove;
var assaultActive = activity != null && activity.IsAssaultMove;
if (attackActive && attackMoveToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.AttackMoveScanCondition))
attackMoveToken = conditionManager.GrantCondition(self, Info.AttackMoveScanCondition);
@@ -98,23 +93,8 @@ namespace OpenRA.Mods.Common.Traits
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)
{
TargetLocation = null;
if (order.OrderString == "AttackMove" || order.OrderString == "AssaultMove")
{
if (!order.Queued)
@@ -124,9 +104,10 @@ namespace OpenRA.Mods.Common.Traits
if (!Info.MoveIntoShroud && !self.Owner.Shroud.IsExplored(cell))
return;
TargetLocation = move.NearestMoveableCell(cell);
self.SetTargetLine(Target.FromCell(self.World, TargetLocation.Value), Color.Red);
Activate(self, order.OrderString == "AssaultMove");
var targetLocation = move.NearestMoveableCell(cell);
self.SetTargetLine(Target.FromCell(self.World, targetLocation), Color.Red);
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
{
readonly IEnumerable<AttackBase> activeAttackBases;
public readonly IEnumerable<AttackBase> ActiveAttackBases;
[Sync] int nextScanTime = 0;
public UnitStance Stance { get { return stance; } }
@@ -151,7 +151,7 @@ namespace OpenRA.Mods.Common.Traits
: base(info)
{
var self = init.Self;
activeAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(Exts.IsTraitEnabled);
ActiveAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(Exts.IsTraitEnabled);
if (init.Contains<StanceInit>())
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?
var attackerAsTarget = Target.FromActor(attacker);
if (!activeAttackBases.Any(a => a.HasAnyValidWeapons(attackerAsTarget)))
if (!ActiveAttackBases.Any(a => a.HasAnyValidWeapons(attackerAsTarget)))
return;
// 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)
{
if (nextScanTime <= 0 && activeAttackBases.Any())
if (nextScanTime <= 0 && ActiveAttackBases.Any())
{
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.
var attackStances = ab.UnforcedAttackTargetStances();
@@ -272,7 +272,7 @@ namespace OpenRA.Mods.Common.Traits
{
self.SetTargetLine(target, Color.Red, false);
foreach (var ab in activeAttackBases)
foreach (var ab in ActiveAttackBases)
ab.AttackTarget(target, false, allowMove);
}

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
self.SetTargetLine(target, Color.Yellow);
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)

View File

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