From 012b17b974966ba21a1d7be08965308cf38f113c Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 2 Feb 2019 11:18:50 +0000 Subject: [PATCH] Implement a secondary target-of-opportunity for AttackFollow. --- .../Traits/Attack/AttackFollow.cs | 25 +++++++++++++------ OpenRA.Mods.Common/Traits/AutoTarget.cs | 24 +++--------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index 517fdf48c4..49f0280a53 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -28,6 +28,8 @@ namespace OpenRA.Mods.Common.Traits protected Target requestedTarget; protected bool requestedForceAttack; protected int requestedTargetLastTick; + protected Target opportunityTarget; + protected bool opportunityForceAttack; Mobile mobile; public AttackFollow(Actor self, AttackFollowInfo info) @@ -59,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits protected override void Tick(Actor self) { if (IsTraitDisabled) - requestedTarget = Target.Invalid; + requestedTarget = opportunityTarget = Target.Invalid; if (requestedTargetLastTick != self.World.WorldTick) { @@ -79,6 +81,12 @@ namespace OpenRA.Mods.Common.Traits if (IsAiming) DoAttack(self, requestedTarget); } + else if (opportunityTarget.Type != TargetType.Invalid) + { + IsAiming = CanAimAtTarget(self, opportunityTarget, opportunityForceAttack); + if (IsAiming) + DoAttack(self, opportunityTarget); + } else IsAiming = false; @@ -105,18 +113,13 @@ namespace OpenRA.Mods.Common.Traits public override void OnStopOrder(Actor self) { - requestedTarget = Target.Invalid; + requestedTarget = opportunityTarget = Target.Invalid; base.OnStopOrder(self); } - public bool HasReachableTarget(bool allowMove) - { - return IsReachableTarget(requestedTarget, allowMove); - } - void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { - requestedTarget = Target.Invalid; + requestedTarget = opportunityTarget = Target.Invalid; } class AttackActivity : Activity @@ -157,7 +160,13 @@ namespace OpenRA.Mods.Common.Traits public override Activity Tick(Actor self) { if (IsCanceled) + { + // Cancel the requested target, but keep firing on it while in range + attack.opportunityTarget = attack.requestedTarget; + attack.opportunityForceAttack = attack.requestedForceAttack; + attack.requestedTarget = Target.Invalid; return NextActivity; + } // Check that AttackFollow hasn't cancelled the target by modifying attack.Target // Having both this and AttackFollow modify that field is a horrible hack. diff --git a/OpenRA.Mods.Common/Traits/AutoTarget.cs b/OpenRA.Mods.Common/Traits/AutoTarget.cs index 59ea75b303..16190d62ed 100644 --- a/OpenRA.Mods.Common/Traits/AutoTarget.cs +++ b/OpenRA.Mods.Common/Traits/AutoTarget.cs @@ -112,7 +112,6 @@ namespace OpenRA.Mods.Common.Traits public class AutoTarget : ConditionalTrait, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync, INotifyCreated, INotifyOwnerChanged { readonly IEnumerable activeAttackBases; - readonly AttackFollow[] attackFollows; [Sync] int nextScanTime = 0; public UnitStance Stance { get { return stance; } } @@ -161,7 +160,6 @@ namespace OpenRA.Mods.Common.Traits stance = self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance; PredictedStance = stance; - attackFollows = self.TraitsImplementing().ToArray(); } void INotifyCreated.Created(Actor self) @@ -221,9 +219,8 @@ namespace OpenRA.Mods.Common.Traits Aggressor = attacker; - bool allowMove; - if (ShouldAttack(out allowMove)) - Attack(self, Target.FromActor(Aggressor), allowMove); + var allowMove = Info.AllowMovement && Stance > UnitStance.Defend; + Attack(self, Target.FromActor(Aggressor), allowMove); } void INotifyIdle.TickIdle(Actor self) @@ -231,21 +228,8 @@ namespace OpenRA.Mods.Common.Traits if (IsTraitDisabled || Stance < UnitStance.Defend) return; - bool allowMove; - if (ShouldAttack(out allowMove)) - ScanAndAttack(self, allowMove); - } - - bool ShouldAttack(out bool allowMove) - { - allowMove = Info.AllowMovement && Stance > UnitStance.Defend; - - // PERF: Avoid LINQ. - foreach (var attackFollow in attackFollows) - if (!attackFollow.IsTraitDisabled && attackFollow.HasReachableTarget(allowMove)) - return false; - - return true; + var allowMove = Info.AllowMovement && Stance > UnitStance.Defend; + ScanAndAttack(self, allowMove); } void ITick.Tick(Actor self)