Revise AttackMoveActivity.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user