Implement a secondary target-of-opportunity for AttackFollow.
This commit is contained in:
committed by
Oliver Brakmann
parent
1830b3ee80
commit
012b17b974
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user