Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear RequestedTargets that are cancelled before the first activity tick #16566

Merged
merged 2 commits into from Jun 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion OpenRA.Mods.Cnc/Traits/Attack/AttackTDGunboatTurreted.cs
Expand Up @@ -62,7 +62,7 @@ public override Activity Tick(Actor self)
if (hasTicked && attack.RequestedTarget.Type == TargetType.Invalid)
return NextActivity;

attack.RequestedTarget = target;
attack.SetRequestedTarget(self, target);
hasTicked = true;
}

Expand Down
19 changes: 6 additions & 13 deletions OpenRA.Mods.Common/Activities/Air/FlyAttack.cs
Expand Up @@ -79,14 +79,7 @@ public override Activity Tick(Actor self)
if (IsCanceling)
{
// Cancel the requested target, but keep firing on it while in range
if (attackAircraft.Info.PersistentTargeting)
{
attackAircraft.OpportunityTarget = attackAircraft.RequestedTarget;
attackAircraft.OpportunityForceAttack = attackAircraft.RequestedForceAttack;
attackAircraft.OpportunityTargetIsPersistentTarget = true;
}

attackAircraft.RequestedTarget = Target.Invalid;
attackAircraft.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -99,8 +92,8 @@ public override Activity Tick(Actor self)
return this;

bool targetIsHiddenActor;
attackAircraft.RequestedTarget = target = target.Recalculate(self.Owner, out targetIsHiddenActor);
attackAircraft.RequestedTargetLastTick = self.World.WorldTick;
target = target.Recalculate(self.Owner, out targetIsHiddenActor);
attackAircraft.SetRequestedTarget(self, target, forceAttack);
hasTicked = true;

if (!targetIsHiddenActor && target.Type == TargetType.Actor)
Expand All @@ -121,7 +114,7 @@ public override Activity Tick(Actor self)
// Target is hidden or dead, and we don't have a fallback position to move towards
if (useLastVisibleTarget && !lastVisibleTarget.IsValidFor(self))
{
attackAircraft.RequestedTarget = Target.Invalid;
attackAircraft.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -141,7 +134,7 @@ public override Activity Tick(Actor self)
// We've reached the assumed position but it is not there - give up
if (checkTarget.IsInRange(pos, lastVisibleMaximumRange))
{
attackAircraft.RequestedTarget = Target.Invalid;
attackAircraft.ClearRequestedTarget();
return NextActivity;
}

Expand Down Expand Up @@ -184,7 +177,7 @@ void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarge
return;

if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
attackAircraft.RequestedTarget = Target.Invalid;
attackAircraft.ClearRequestedTarget();
}
}
}
5 changes: 3 additions & 2 deletions OpenRA.Mods.Common/Activities/Move/AttackMoveActivity.cs
Expand Up @@ -63,8 +63,9 @@ public override Activity Tick(Actor self)
var attackBases = autoTarget.ActiveAttackBases;
foreach (var ab in attackBases)
{
QueueChild(self, ab.GetAttackActivity(self, target, true, false));
ab.OnQueueAttackActivity(self, target, false, true, false);
var activity = ab.GetAttackActivity(self, target, true, false);
QueueChild(self, activity);
ab.OnQueueAttackActivity(self, activity, target, true, false);
}

// Make sure to continue moving when the attack activities have finished.
Expand Down
7 changes: 4 additions & 3 deletions OpenRA.Mods.Common/Traits/Attack/AttackBase.cs
Expand Up @@ -392,11 +392,12 @@ public void AttackTarget(Target target, bool queued, bool allowMove, bool forceA
if (!queued)
self.CancelActivity();

self.QueueActivity(GetAttackActivity(self, target, allowMove, forceAttack));
OnQueueAttackActivity(self, target, queued, allowMove, forceAttack);
var activity = GetAttackActivity(self, target, allowMove, forceAttack);
self.QueueActivity(activity);
OnQueueAttackActivity(self, activity, target, allowMove, forceAttack);
}

public virtual void OnQueueAttackActivity(Actor self, Target target, bool queued, bool allowMove, bool forceAttack) { }
public virtual void OnQueueAttackActivity(Actor self, Activity activity, Target target, bool allowMove, bool forceAttack) { }

public bool IsReachableTarget(Target target, bool allowMove)
{
Expand Down
104 changes: 61 additions & 43 deletions OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs
Expand Up @@ -32,15 +32,35 @@ public class AttackFollowInfo : AttackBaseInfo
public class AttackFollow : AttackBase, INotifyOwnerChanged, IDisableAutoTarget, INotifyStanceChanged
{
public new readonly AttackFollowInfo Info;
public Target RequestedTarget;
public bool RequestedForceAttack;
public int RequestedTargetLastTick;
public Target OpportunityTarget;
public bool OpportunityForceAttack;
public bool OpportunityTargetIsPersistentTarget;
public Target RequestedTarget { get; private set; }
public Target OpportunityTarget { get; private set; }

Mobile mobile;
AutoTarget autoTarget;
bool requestedForceAttack;
Activity requestedTargetPresetForActivity;
bool opportunityForceAttack;
bool opportunityTargetIsPersistentTarget;

public void SetRequestedTarget(Actor self, Target target, bool isForceAttack = false)
{
RequestedTarget = target;
requestedForceAttack = isForceAttack;
requestedTargetPresetForActivity = null;
}

public void ClearRequestedTarget()
{
if (Info.PersistentTargeting)
{
OpportunityTarget = RequestedTarget;
opportunityForceAttack = requestedForceAttack;
opportunityTargetIsPersistentTarget = true;
}

RequestedTarget = Target.Invalid;
requestedTargetPresetForActivity = null;
}

public AttackFollow(Actor self, AttackFollowInfo info)
: base(self, info)
Expand Down Expand Up @@ -78,15 +98,22 @@ protected override void Tick(Actor self)
if (IsTraitDisabled)
{
RequestedTarget = OpportunityTarget = Target.Invalid;
OpportunityTargetIsPersistentTarget = false;
opportunityTargetIsPersistentTarget = false;
}

if (RequestedTargetLastTick != self.World.WorldTick)
if (requestedTargetPresetForActivity != null)
{
// Activities tick before traits, so if we are here it means the activity didn't run
// (either queued next or already cancelled) and we need to recalculate the target ourself
bool targetIsHiddenActor;
RequestedTarget = RequestedTarget.Recalculate(self.Owner, out targetIsHiddenActor);
// RequestedTarget was set by OnQueueAttackActivity in preparation for a queued activity
// requestedTargetPresetForActivity will be cleared once the activity starts running and calls UpdateRequestedTarget
if (self.CurrentActivity != null && self.CurrentActivity.NextActivity == requestedTargetPresetForActivity)
{
bool targetIsHiddenActor;
RequestedTarget = RequestedTarget.Recalculate(self.Owner, out targetIsHiddenActor);
}

// Requested activity has been canceled
else
ClearRequestedTarget();
}

// Can't fire on anything
Expand All @@ -95,7 +122,7 @@ protected override void Tick(Actor self)

if (RequestedTarget.Type != TargetType.Invalid)
{
IsAiming = CanAimAtTarget(self, RequestedTarget, RequestedForceAttack);
IsAiming = CanAimAtTarget(self, RequestedTarget, requestedForceAttack);
if (IsAiming)
DoAttack(self, RequestedTarget);
}
Expand All @@ -104,17 +131,17 @@ protected override void Tick(Actor self)
IsAiming = false;

if (OpportunityTarget.Type != TargetType.Invalid)
IsAiming = CanAimAtTarget(self, OpportunityTarget, OpportunityForceAttack);
IsAiming = CanAimAtTarget(self, OpportunityTarget, opportunityForceAttack);

if (!IsAiming && Info.OpportunityFire && autoTarget != null &&
!autoTarget.IsTraitDisabled && autoTarget.Stance >= UnitStance.Defend)
{
OpportunityTarget = autoTarget.ScanForTarget(self, false, false);
OpportunityForceAttack = false;
OpportunityTargetIsPersistentTarget = false;
opportunityForceAttack = false;
opportunityTargetIsPersistentTarget = false;

if (OpportunityTarget.Type != TargetType.Invalid)
IsAiming = CanAimAtTarget(self, OpportunityTarget, OpportunityForceAttack);
IsAiming = CanAimAtTarget(self, OpportunityTarget, opportunityForceAttack);
}

if (IsAiming)
Expand All @@ -129,42 +156,41 @@ public override Activity GetAttackActivity(Actor self, Target newTarget, bool al
return new AttackActivity(self, newTarget, allowMove, forceAttack);
}

public override void OnQueueAttackActivity(Actor self, Target target, bool queued, bool allowMove, bool forceAttack)
public override void OnQueueAttackActivity(Actor self, Activity activity, Target target, bool allowMove, bool forceAttack)
{
// If not queued we know that the attack activity will run next
// We can improve responsiveness for turreted actors by preempting
// the last order (usually a move) and set the target immediately
if (!queued)
// the last order (usually a move) and setting the target immediately
if (self.CurrentActivity != null && self.CurrentActivity.NextActivity == activity)
{
RequestedTarget = target;
RequestedForceAttack = forceAttack;
RequestedTargetLastTick = self.World.WorldTick;
requestedForceAttack = forceAttack;
requestedTargetPresetForActivity = activity;
}
}

public override void OnStopOrder(Actor self)
{
RequestedTarget = OpportunityTarget = Target.Invalid;
OpportunityTargetIsPersistentTarget = false;
opportunityTargetIsPersistentTarget = false;
base.OnStopOrder(self);
}

void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
RequestedTarget = OpportunityTarget = Target.Invalid;
OpportunityTargetIsPersistentTarget = false;
opportunityTargetIsPersistentTarget = false;
}

bool IDisableAutoTarget.DisableAutoTarget(Actor self)
{
return RequestedTarget.Type != TargetType.Invalid ||
(OpportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid);
(opportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid);
}

void INotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
{
// Cancel opportunity targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
if (newStance > oldStance || OpportunityForceAttack)
if (newStance > oldStance || opportunityForceAttack)
return;

if (OpportunityTarget.Type == TargetType.Actor)
Expand Down Expand Up @@ -241,14 +267,7 @@ public override Activity Tick(Actor self)
if (IsCanceling)
{
// Cancel the requested target, but keep firing on it while in range
if (attack.Info.PersistentTargeting)
{
attack.OpportunityTarget = attack.RequestedTarget;
attack.OpportunityForceAttack = attack.RequestedForceAttack;
attack.OpportunityTargetIsPersistentTarget = true;
}

attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -261,9 +280,8 @@ public override Activity Tick(Actor self)
return this;

bool targetIsHiddenActor;
attack.RequestedForceAttack = forceAttack;
attack.RequestedTarget = target = target.Recalculate(self.Owner, out targetIsHiddenActor);
attack.RequestedTargetLastTick = self.World.WorldTick;
target = target.Recalculate(self.Owner, out targetIsHiddenActor);
attack.SetRequestedTarget(self, target, forceAttack);
hasTicked = true;

if (!targetIsHiddenActor && target.Type == TargetType.Actor)
Expand Down Expand Up @@ -305,7 +323,7 @@ public override Activity Tick(Actor self)
// Either we are in range and can see the target, or we've lost track of it and should give up
if (wasMovingWithinRange && targetIsHiddenActor)
{
attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -316,7 +334,7 @@ public override Activity Tick(Actor self)
// Target is hidden or dead, and we don't have a fallback position to move towards
if (useLastVisibleTarget && !lastVisibleTarget.IsValidFor(self))
{
attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -329,7 +347,7 @@ public override Activity Tick(Actor self)
{
if (useLastVisibleTarget)
{
attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -339,7 +357,7 @@ public override Activity Tick(Actor self)
// We can't move into range, so give up
if (move == null || maxRange == WDist.Zero || maxRange < minRange)
{
attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
return NextActivity;
}

Expand All @@ -355,7 +373,7 @@ void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarge
return;

if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
attack.RequestedTarget = Target.Invalid;
attack.ClearRequestedTarget();
}
}
}
Expand Down