Drop targets when switching to a more restrictive stance.
This commit is contained in:
@@ -20,25 +20,29 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Cnc.Activities
|
namespace OpenRA.Mods.Cnc.Activities
|
||||||
{
|
{
|
||||||
public class LeapAttack : Activity
|
public class LeapAttack : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly AttackLeapInfo info;
|
readonly AttackLeapInfo info;
|
||||||
readonly AttackLeap attack;
|
readonly AttackLeap attack;
|
||||||
readonly Mobile mobile;
|
readonly Mobile mobile;
|
||||||
readonly bool allowMovement;
|
readonly bool allowMovement;
|
||||||
|
readonly bool forceAttack;
|
||||||
|
|
||||||
Target target;
|
Target target;
|
||||||
Target lastVisibleTarget;
|
Target lastVisibleTarget;
|
||||||
bool useLastVisibleTarget;
|
bool useLastVisibleTarget;
|
||||||
WDist lastVisibleMinRange;
|
WDist lastVisibleMinRange;
|
||||||
WDist lastVisibleMaxRange;
|
WDist lastVisibleMaxRange;
|
||||||
|
BitSet<TargetableType> lastVisibleTargetTypes;
|
||||||
|
Player lastVisibleOwner;
|
||||||
|
|
||||||
public LeapAttack(Actor self, Target target, bool allowMovement, AttackLeap attack, AttackLeapInfo info)
|
public LeapAttack(Actor self, Target target, bool allowMovement, bool forceAttack, AttackLeap attack, AttackLeapInfo info)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.attack = attack;
|
this.attack = attack;
|
||||||
this.allowMovement = allowMovement;
|
this.allowMovement = allowMovement;
|
||||||
|
this.forceAttack = forceAttack;
|
||||||
mobile = self.Trait<Mobile>();
|
mobile = self.Trait<Mobile>();
|
||||||
|
|
||||||
// The target may become hidden between the initial order request and the first tick (e.g. if queued)
|
// The target may become hidden between the initial order request and the first tick (e.g. if queued)
|
||||||
@@ -49,6 +53,17 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
||||||
lastVisibleMinRange = attack.GetMinimumRangeVersusTarget(target);
|
lastVisibleMinRange = attack.GetMinimumRangeVersusTarget(target);
|
||||||
lastVisibleMaxRange = attack.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaxRange = attack.GetMaximumRangeVersusTarget(target);
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.FrozenActor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.FrozenActor.TargetTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +91,8 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
lastVisibleTarget = Target.FromTargetPositions(target);
|
lastVisibleTarget = Target.FromTargetPositions(target);
|
||||||
lastVisibleMinRange = attack.GetMinimumRangeVersusTarget(target);
|
lastVisibleMinRange = attack.GetMinimumRangeVersusTarget(target);
|
||||||
lastVisibleMaxRange = attack.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaxRange = attack.GetMaximumRangeVersusTarget(target);
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
||||||
@@ -141,5 +158,15 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
{
|
{
|
||||||
attack.IsAiming = false;
|
attack.IsAiming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
|
||||||
|
target = Target.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
|
|
||||||
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
||||||
{
|
{
|
||||||
return new LeapAttack(self, newTarget, allowMove, this, info);
|
return new LeapAttack(self, newTarget, allowMove, forceAttack, this, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,18 +75,20 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
|
|
||||||
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
||||||
{
|
{
|
||||||
return new ChargeAttack(this, newTarget);
|
return new ChargeAttack(this, newTarget, forceAttack);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChargeAttack : Activity
|
class ChargeAttack : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly AttackTesla attack;
|
readonly AttackTesla attack;
|
||||||
readonly Target target;
|
readonly Target target;
|
||||||
|
readonly bool forceAttack;
|
||||||
|
|
||||||
public ChargeAttack(AttackTesla attack, Target target)
|
public ChargeAttack(AttackTesla attack, Target target, bool forceAttack)
|
||||||
{
|
{
|
||||||
this.attack = attack;
|
this.attack = attack;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.forceAttack = forceAttack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Activity Tick(Actor self)
|
public override Activity Tick(Actor self)
|
||||||
@@ -114,6 +116,26 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
QueueChild(self, new ChargeFire(attack, target));
|
QueueChild(self, new ChargeFire(attack, target));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
var a = target.Actor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, a.Owner, a.GetEnabledTargetTypes()))
|
||||||
|
Cancel(self, true);
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
var fa = target.FrozenActor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, fa.Owner, fa.TargetTypes))
|
||||||
|
Cancel(self, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChargeFire : Activity
|
class ChargeFire : Activity
|
||||||
|
|||||||
@@ -17,22 +17,26 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Activities
|
namespace OpenRA.Mods.Common.Activities
|
||||||
{
|
{
|
||||||
public class FlyAttack : Activity
|
public class FlyAttack : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly Aircraft aircraft;
|
readonly Aircraft aircraft;
|
||||||
readonly AttackAircraft attackAircraft;
|
readonly AttackAircraft attackAircraft;
|
||||||
readonly Rearmable rearmable;
|
readonly Rearmable rearmable;
|
||||||
|
readonly bool forceAttack;
|
||||||
readonly int ticksUntilTurn;
|
readonly int ticksUntilTurn;
|
||||||
|
|
||||||
Target target;
|
Target target;
|
||||||
Target lastVisibleTarget;
|
Target lastVisibleTarget;
|
||||||
WDist lastVisibleMaximumRange;
|
WDist lastVisibleMaximumRange;
|
||||||
|
BitSet<TargetableType> lastVisibleTargetTypes;
|
||||||
|
Player lastVisibleOwner;
|
||||||
bool useLastVisibleTarget;
|
bool useLastVisibleTarget;
|
||||||
bool hasTicked;
|
bool hasTicked;
|
||||||
|
|
||||||
public FlyAttack(Actor self, Target target)
|
public FlyAttack(Actor self, Target target, bool forceAttack)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.forceAttack = forceAttack;
|
||||||
aircraft = self.Trait<Aircraft>();
|
aircraft = self.Trait<Aircraft>();
|
||||||
attackAircraft = self.Trait<AttackAircraft>();
|
attackAircraft = self.Trait<AttackAircraft>();
|
||||||
rearmable = self.TraitOrDefault<Rearmable>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
@@ -45,6 +49,17 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
{
|
{
|
||||||
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
||||||
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.FrozenActor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.FrozenActor.TargetTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +107,8 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
{
|
{
|
||||||
lastVisibleTarget = Target.FromTargetPositions(target);
|
lastVisibleTarget = Target.FromTargetPositions(target);
|
||||||
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
||||||
@@ -144,5 +161,15 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
|
||||||
|
attackAircraft.RequestedTarget = Target.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,21 +17,25 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Activities
|
namespace OpenRA.Mods.Common.Activities
|
||||||
{
|
{
|
||||||
public class HeliAttack : Activity
|
public class HeliAttack : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly Aircraft aircraft;
|
readonly Aircraft aircraft;
|
||||||
readonly AttackAircraft attackAircraft;
|
readonly AttackAircraft attackAircraft;
|
||||||
readonly Rearmable rearmable;
|
readonly Rearmable rearmable;
|
||||||
|
readonly bool forceAttack;
|
||||||
|
|
||||||
Target target;
|
Target target;
|
||||||
Target lastVisibleTarget;
|
Target lastVisibleTarget;
|
||||||
WDist lastVisibleMaximumRange;
|
WDist lastVisibleMaximumRange;
|
||||||
|
BitSet<TargetableType> lastVisibleTargetTypes;
|
||||||
|
Player lastVisibleOwner;
|
||||||
bool useLastVisibleTarget;
|
bool useLastVisibleTarget;
|
||||||
bool hasTicked;
|
bool hasTicked;
|
||||||
|
|
||||||
public HeliAttack(Actor self, Target target)
|
public HeliAttack(Actor self, Target target, bool forceAttack)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
this.forceAttack = forceAttack;
|
||||||
aircraft = self.Trait<Aircraft>();
|
aircraft = self.Trait<Aircraft>();
|
||||||
attackAircraft = self.Trait<AttackAircraft>();
|
attackAircraft = self.Trait<AttackAircraft>();
|
||||||
rearmable = self.TraitOrDefault<Rearmable>();
|
rearmable = self.TraitOrDefault<Rearmable>();
|
||||||
@@ -43,6 +47,17 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
{
|
{
|
||||||
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
||||||
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.FrozenActor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.FrozenActor.TargetTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +105,8 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
{
|
{
|
||||||
lastVisibleTarget = Target.FromTargetPositions(target);
|
lastVisibleTarget = Target.FromTargetPositions(target);
|
||||||
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attackAircraft.GetMaximumRangeVersusTarget(target);
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
||||||
@@ -156,5 +173,15 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
|
||||||
|
attackAircraft.RequestedTarget = Target.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Common.Activities
|
namespace OpenRA.Mods.Common.Activities
|
||||||
{
|
{
|
||||||
/* non-turreted attack */
|
/* non-turreted attack */
|
||||||
public class Attack : Activity
|
public class Attack : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
protected enum AttackStatus { UnableToAttack, NeedsToTurn, NeedsToMove, Attacking }
|
protected enum AttackStatus { UnableToAttack, NeedsToTurn, NeedsToMove, Attacking }
|
||||||
@@ -35,6 +35,8 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
protected Target target;
|
protected Target target;
|
||||||
Target lastVisibleTarget;
|
Target lastVisibleTarget;
|
||||||
WDist lastVisibleMaximumRange;
|
WDist lastVisibleMaximumRange;
|
||||||
|
BitSet<TargetableType> lastVisibleTargetTypes;
|
||||||
|
Player lastVisibleOwner;
|
||||||
bool useLastVisibleTarget;
|
bool useLastVisibleTarget;
|
||||||
bool wasMovingWithinRange;
|
bool wasMovingWithinRange;
|
||||||
|
|
||||||
@@ -62,6 +64,17 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
||||||
lastVisibleMaximumRange = attackTraits.Where(x => !x.IsTraitDisabled)
|
lastVisibleMaximumRange = attackTraits.Where(x => !x.IsTraitDisabled)
|
||||||
.Min(x => x.GetMaximumRangeVersusTarget(target));
|
.Min(x => x.GetMaximumRangeVersusTarget(target));
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.FrozenActor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.FrozenActor.TargetTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +101,9 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
lastVisibleTarget = Target.FromTargetPositions(target);
|
lastVisibleTarget = Target.FromTargetPositions(target);
|
||||||
lastVisibleMaximumRange = attackTraits.Where(x => !x.IsTraitDisabled)
|
lastVisibleMaximumRange = attackTraits.Where(x => !x.IsTraitDisabled)
|
||||||
.Min(x => x.GetMaximumRangeVersusTarget(target));
|
.Min(x => x.GetMaximumRangeVersusTarget(target));
|
||||||
|
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
var oldUseLastVisibleTarget = useLastVisibleTarget;
|
||||||
@@ -211,5 +227,15 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
foreach (var a in armaments)
|
foreach (var a in armaments)
|
||||||
a.CheckFire(self, facing, target);
|
a.CheckFire(self, facing, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
|
||||||
|
target = Target.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
||||||
{
|
{
|
||||||
if (aircraftInfo.CanHover)
|
if (aircraftInfo.CanHover)
|
||||||
return new HeliAttack(self, newTarget);
|
return new HeliAttack(self, newTarget, forceAttack);
|
||||||
|
|
||||||
return new FlyAttack(self, newTarget);
|
return new FlyAttack(self, newTarget, forceAttack);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CanAttack(Actor self, Target target)
|
protected override bool CanAttack(Actor self, Target target)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public override object Create(ActorInitializer init) { return new AttackFollow(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new AttackFollow(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AttackFollow : AttackBase, INotifyOwnerChanged, IDisableAutoTarget
|
public class AttackFollow : AttackBase, INotifyOwnerChanged, IDisableAutoTarget, INotifyStanceChanged
|
||||||
{
|
{
|
||||||
public new readonly AttackFollowInfo Info;
|
public new readonly AttackFollowInfo Info;
|
||||||
public Target RequestedTarget;
|
public Target RequestedTarget;
|
||||||
@@ -161,7 +161,27 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
(OpportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid);
|
(OpportunityTargetIsPersistentTarget && OpportunityTarget.Type != TargetType.Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttackActivity : Activity
|
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)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (OpportunityTarget.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
var a = OpportunityTarget.Actor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, a.Owner, a.GetEnabledTargetTypes()))
|
||||||
|
OpportunityTarget = Target.Invalid;
|
||||||
|
}
|
||||||
|
else if (OpportunityTarget.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
var fa = OpportunityTarget.FrozenActor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, fa.Owner, fa.TargetTypes))
|
||||||
|
OpportunityTarget = Target.Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AttackActivity : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly AttackFollow attack;
|
readonly AttackFollow attack;
|
||||||
readonly RevealsShroud[] revealsShroud;
|
readonly RevealsShroud[] revealsShroud;
|
||||||
@@ -173,6 +193,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
bool useLastVisibleTarget;
|
bool useLastVisibleTarget;
|
||||||
WDist lastVisibleMaximumRange;
|
WDist lastVisibleMaximumRange;
|
||||||
WDist lastVisibleMinimumRange;
|
WDist lastVisibleMinimumRange;
|
||||||
|
BitSet<TargetableType> lastVisibleTargetTypes;
|
||||||
|
Player lastVisibleOwner;
|
||||||
bool wasMovingWithinRange;
|
bool wasMovingWithinRange;
|
||||||
bool hasTicked;
|
bool hasTicked;
|
||||||
|
|
||||||
@@ -193,6 +215,17 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
lastVisibleTarget = Target.FromPos(target.CenterPosition);
|
||||||
lastVisibleMaximumRange = attack.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attack.GetMaximumRangeVersusTarget(target);
|
||||||
lastVisibleMinimumRange = attack.GetMinimumRangeVersusTarget(target);
|
lastVisibleMinimumRange = attack.GetMinimumRangeVersusTarget(target);
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
lastVisibleOwner = target.FrozenActor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.FrozenActor.TargetTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +271,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
lastVisibleTarget = Target.FromTargetPositions(target);
|
lastVisibleTarget = Target.FromTargetPositions(target);
|
||||||
lastVisibleMaximumRange = attack.GetMaximumRangeVersusTarget(target);
|
lastVisibleMaximumRange = attack.GetMaximumRangeVersusTarget(target);
|
||||||
lastVisibleMinimumRange = attack.GetMinimumRange();
|
lastVisibleMinimumRange = attack.GetMinimumRange();
|
||||||
|
lastVisibleOwner = target.Actor.Owner;
|
||||||
|
lastVisibleTargetTypes = target.Actor.GetEnabledTargetTypes();
|
||||||
|
|
||||||
// Try and sit at least one cell away from the min or max ranges to give some leeway if the target starts moving.
|
// Try and sit at least one cell away from the min or max ranges to give some leeway if the target starts moving.
|
||||||
if (move != null && target.Actor.Info.HasTraitInfo<IMoveInfo>())
|
if (move != null && target.Actor.Info.HasTraitInfo<IMoveInfo>())
|
||||||
@@ -312,6 +347,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
QueueChild(self, move.MoveWithinRange(target, minRange, maxRange, checkTarget.CenterPosition, Color.Red), true);
|
QueueChild(self, move.MoveWithinRange(target, minRange, maxRange, checkTarget.CenterPosition, Color.Red), true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, lastVisibleOwner, lastVisibleTargetTypes))
|
||||||
|
attack.RequestedTarget = Target.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,21 +27,23 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
public override Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove, bool forceAttack)
|
||||||
{
|
{
|
||||||
return new SetTarget(this, newTarget, allowMove);
|
return new SetTarget(this, newTarget, allowMove, forceAttack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some 3rd-party mods rely on this being public
|
// Some 3rd-party mods rely on this being public
|
||||||
public class SetTarget : Activity
|
public class SetTarget : Activity, IActivityNotifyStanceChanged
|
||||||
{
|
{
|
||||||
readonly AttackOmni attack;
|
readonly AttackOmni attack;
|
||||||
readonly bool allowMove;
|
readonly bool allowMove;
|
||||||
|
readonly bool forceAttack;
|
||||||
Target target;
|
Target target;
|
||||||
|
|
||||||
public SetTarget(AttackOmni attack, Target target, bool allowMove)
|
public SetTarget(AttackOmni attack, Target target, bool allowMove, bool forceAttack)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.attack = attack;
|
this.attack = attack;
|
||||||
this.allowMove = allowMove;
|
this.allowMove = allowMove;
|
||||||
|
this.forceAttack = forceAttack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Activity Tick(Actor self)
|
public override Activity Tick(Actor self)
|
||||||
@@ -55,6 +57,26 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
attack.DoAttack(self, target);
|
attack.DoAttack(self, target);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IActivityNotifyStanceChanged.StanceChanged(Actor self, AutoTarget autoTarget, UnitStance oldStance, UnitStance newStance)
|
||||||
|
{
|
||||||
|
// Cancel non-forced targets when switching to a more restrictive stance if they are no longer valid for auto-targeting
|
||||||
|
if (newStance > oldStance || forceAttack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (target.Type == TargetType.Actor)
|
||||||
|
{
|
||||||
|
var a = target.Actor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, a.Owner, a.GetEnabledTargetTypes()))
|
||||||
|
target = Target.Invalid;
|
||||||
|
}
|
||||||
|
else if (target.Type == TargetType.FrozenActor)
|
||||||
|
{
|
||||||
|
var fa = target.FrozenActor;
|
||||||
|
if (!autoTarget.HasValidTargetPriority(self, fa.Owner, fa.TargetTypes))
|
||||||
|
target = Target.Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,6 +313,25 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
ab.AttackTarget(target, false, allowMove);
|
ab.AttackTarget(target, false, allowMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasValidTargetPriority(Actor self, Player owner, BitSet<TargetableType> targetTypes)
|
||||||
|
{
|
||||||
|
if (Stance <= UnitStance.ReturnFire)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return activeTargetPriorities.Any(ati =>
|
||||||
|
{
|
||||||
|
// Incompatible stances
|
||||||
|
if (!ati.ValidStances.HasStance(self.Owner.Stances[owner]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Incompatible target types
|
||||||
|
if (!ati.ValidTargets.Overlaps(targetTypes) || ati.InvalidTargets.Overlaps(targetTypes))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Target ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove, bool allowTurn)
|
Target ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove, bool allowTurn)
|
||||||
{
|
{
|
||||||
var chosenTarget = Target.Invalid;
|
var chosenTarget = Target.Invalid;
|
||||||
|
|||||||
Reference in New Issue
Block a user