Implement a secondary target-of-opportunity for AttackFollow.

This commit is contained in:
Paul Chote
2019-02-02 11:18:50 +00:00
committed by Oliver Brakmann
parent 1830b3ee80
commit 012b17b974
2 changed files with 21 additions and 28 deletions

View File

@@ -28,6 +28,8 @@ namespace OpenRA.Mods.Common.Traits
protected Target requestedTarget; protected Target requestedTarget;
protected bool requestedForceAttack; protected bool requestedForceAttack;
protected int requestedTargetLastTick; protected int requestedTargetLastTick;
protected Target opportunityTarget;
protected bool opportunityForceAttack;
Mobile mobile; Mobile mobile;
public AttackFollow(Actor self, AttackFollowInfo info) public AttackFollow(Actor self, AttackFollowInfo info)
@@ -59,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits
protected override void Tick(Actor self) protected override void Tick(Actor self)
{ {
if (IsTraitDisabled) if (IsTraitDisabled)
requestedTarget = Target.Invalid; requestedTarget = opportunityTarget = Target.Invalid;
if (requestedTargetLastTick != self.World.WorldTick) if (requestedTargetLastTick != self.World.WorldTick)
{ {
@@ -79,6 +81,12 @@ namespace OpenRA.Mods.Common.Traits
if (IsAiming) if (IsAiming)
DoAttack(self, requestedTarget); DoAttack(self, requestedTarget);
} }
else if (opportunityTarget.Type != TargetType.Invalid)
{
IsAiming = CanAimAtTarget(self, opportunityTarget, opportunityForceAttack);
if (IsAiming)
DoAttack(self, opportunityTarget);
}
else else
IsAiming = false; IsAiming = false;
@@ -105,18 +113,13 @@ namespace OpenRA.Mods.Common.Traits
public override void OnStopOrder(Actor self) public override void OnStopOrder(Actor self)
{ {
requestedTarget = Target.Invalid; requestedTarget = opportunityTarget = Target.Invalid;
base.OnStopOrder(self); base.OnStopOrder(self);
} }
public bool HasReachableTarget(bool allowMove)
{
return IsReachableTarget(requestedTarget, allowMove);
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{ {
requestedTarget = Target.Invalid; requestedTarget = opportunityTarget = Target.Invalid;
} }
class AttackActivity : Activity class AttackActivity : Activity
@@ -157,7 +160,13 @@ namespace OpenRA.Mods.Common.Traits
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
if (IsCanceled) 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; return NextActivity;
}
// Check that AttackFollow hasn't cancelled the target by modifying attack.Target // Check that AttackFollow hasn't cancelled the target by modifying attack.Target
// Having both this and AttackFollow modify that field is a horrible hack. // Having both this and AttackFollow modify that field is a horrible hack.

View File

@@ -112,7 +112,6 @@ 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; readonly IEnumerable<AttackBase> activeAttackBases;
readonly AttackFollow[] attackFollows;
[Sync] int nextScanTime = 0; [Sync] int nextScanTime = 0;
public UnitStance Stance { get { return stance; } } 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; stance = self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance;
PredictedStance = stance; PredictedStance = stance;
attackFollows = self.TraitsImplementing<AttackFollow>().ToArray();
} }
void INotifyCreated.Created(Actor self) void INotifyCreated.Created(Actor self)
@@ -221,8 +219,7 @@ namespace OpenRA.Mods.Common.Traits
Aggressor = attacker; Aggressor = attacker;
bool allowMove; var allowMove = Info.AllowMovement && Stance > UnitStance.Defend;
if (ShouldAttack(out allowMove))
Attack(self, Target.FromActor(Aggressor), allowMove); Attack(self, Target.FromActor(Aggressor), allowMove);
} }
@@ -231,23 +228,10 @@ namespace OpenRA.Mods.Common.Traits
if (IsTraitDisabled || Stance < UnitStance.Defend) if (IsTraitDisabled || Stance < UnitStance.Defend)
return; return;
bool allowMove; var allowMove = Info.AllowMovement && Stance > UnitStance.Defend;
if (ShouldAttack(out allowMove))
ScanAndAttack(self, 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;
}
void ITick.Tick(Actor self) void ITick.Tick(Actor self)
{ {
if (IsTraitDisabled) if (IsTraitDisabled)