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);
|
(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user