From 0134f63f4d583a7f6c7a6e1db376bb615877d01a Mon Sep 17 00:00:00 2001 From: abcdefg30 Date: Sun, 27 Mar 2022 19:04:32 +0200 Subject: [PATCH] Fix actors with AttackFollow moving away from their targets on amove --- .../Traits/Attack/AttackFollow.cs | 20 +++++++++++++++---- OpenRA.Mods.Common/Traits/AutoTarget.cs | 17 ++++++++-------- OpenRA.Mods.Common/TraitsInterfaces.cs | 4 ++-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index 61d14b507f..73cd0525a5 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits public override object Create(ActorInitializer init) { return new AttackFollow(init.Self, this); } } - public class AttackFollow : AttackBase, INotifyOwnerChanged, IDisableAutoTarget, INotifyStanceChanged + public class AttackFollow : AttackBase, INotifyOwnerChanged, IOverrideAutoTarget, INotifyStanceChanged { public new readonly AttackFollowInfo Info; public Target RequestedTarget { get; private set; } @@ -184,10 +184,22 @@ namespace OpenRA.Mods.Common.Traits opportunityTargetIsPersistentTarget = false; } - bool IDisableAutoTarget.DisableAutoTarget(Actor self) + bool IOverrideAutoTarget.TryGetAutoTargetOverride(Actor self, out Target target) { - return RequestedTarget.Type != TargetType.Invalid || - (opportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid); + if (RequestedTarget.Type != TargetType.Invalid) + { + target = RequestedTarget; + return true; + } + + if (opportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid) + { + target = OpportunityTarget; + return true; + } + + target = Target.Invalid; + return false; } void INotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance) diff --git a/OpenRA.Mods.Common/Traits/AutoTarget.cs b/OpenRA.Mods.Common/Traits/AutoTarget.cs index dbadd1def6..484cf34665 100644 --- a/OpenRA.Mods.Common/Traits/AutoTarget.cs +++ b/OpenRA.Mods.Common/Traits/AutoTarget.cs @@ -144,7 +144,7 @@ namespace OpenRA.Mods.Common.Traits public UnitStance PredictedStance; UnitStance stance; - IDisableAutoTarget[] disableAutoTarget; + IOverrideAutoTarget[] overrideAutoTarget; INotifyStanceChanged[] notifyStanceChanged; IEnumerable activeTargetPriorities; int conditionToken = Actor.InvalidConditionToken; @@ -197,7 +197,7 @@ namespace OpenRA.Mods.Common.Traits .OrderByDescending(ati => ati.Info.Priority).ToArray() .Where(Exts.IsTraitEnabled).Select(atp => atp.Info); - disableAutoTarget = self.TraitsImplementing().ToArray(); + overrideAutoTarget = self.TraitsImplementing().ToArray(); notifyStanceChanged = self.TraitsImplementing().ToArray(); ApplyStanceCondition(self); @@ -229,8 +229,9 @@ namespace OpenRA.Mods.Common.Traits if (attacker.Disposed) return; - foreach (var dat in disableAutoTarget) - if (dat.DisableAutoTarget(self)) + // Don't change targets when there is a target overriding auto-targeting + foreach (var oat in overrideAutoTarget) + if (oat.TryGetAutoTargetOverride(self, out _)) return; if (!attacker.IsInWorld) @@ -283,9 +284,9 @@ namespace OpenRA.Mods.Common.Traits { if ((ignoreScanInterval || nextScanTime <= 0) && ActiveAttackBases.Any()) { - foreach (var dat in disableAutoTarget) - if (dat.DisableAutoTarget(self)) - return Target.Invalid; + foreach (var oat in overrideAutoTarget) + if (oat.TryGetAutoTargetOverride(self, out var existingTarget)) + return existingTarget; if (!ignoreScanInterval) nextScanTime = self.World.SharedRandom.Next(Info.MinimumScanTimeInterval, Info.MaximumScanTimeInterval); @@ -294,7 +295,7 @@ namespace OpenRA.Mods.Common.Traits { // If we can't attack right now, there's no need to try and find a target. var attackStances = ab.UnforcedAttackTargetStances(); - if (attackStances != OpenRA.Traits.PlayerRelationship.None) + if (attackStances != PlayerRelationship.None) { var range = Info.ScanRadius > 0 ? WDist.FromCells(Info.ScanRadius) : ab.GetMaximumRange(); return ChooseTarget(self, ab, attackStances, range, allowMove, allowTurn); diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 8be26d4280..51887beb59 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -309,9 +309,9 @@ namespace OpenRA.Mods.Common.Traits } [RequireExplicitImplementation] - public interface IDisableAutoTarget + public interface IOverrideAutoTarget { - bool DisableAutoTarget(Actor self); + bool TryGetAutoTargetOverride(Actor self, out Target target); } [RequireExplicitImplementation]