Add AutoTarget support for FrozenActors.

This commit is contained in:
Paul Chote
2018-11-28 21:11:05 +00:00
committed by Oliver Brakmann
parent c34dd4b824
commit 5f79c31a57

View File

@@ -12,6 +12,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
@@ -117,7 +118,6 @@ namespace OpenRA.Mods.Common.Traits
public UnitStance Stance { get { return stance; } }
[Sync] public Actor Aggressor;
[Sync] public Actor TargetedActor;
// NOT SYNCED: do not refer to this anywhere other than UI code
public UnitStance PredictedStance;
@@ -217,7 +217,7 @@ namespace OpenRA.Mods.Common.Traits
bool allowMove;
if (ShouldAttack(out allowMove))
Attack(self, Aggressor, allowMove);
Attack(self, Target.FromActor(Aggressor), allowMove);
}
void INotifyIdle.TickIdle(Actor self)
@@ -251,7 +251,7 @@ namespace OpenRA.Mods.Common.Traits
--nextScanTime;
}
public Actor ScanForTarget(Actor self, bool allowMove)
public Target ScanForTarget(Actor self, bool allowMove)
{
if (nextScanTime <= 0 && activeAttackBases.Any())
{
@@ -269,48 +269,67 @@ namespace OpenRA.Mods.Common.Traits
}
}
return null;
return Target.Invalid;
}
public void ScanAndAttack(Actor self, bool allowMove)
{
var targetActor = ScanForTarget(self, allowMove);
if (targetActor != null)
Attack(self, targetActor, allowMove);
var target = ScanForTarget(self, allowMove);
if (target.Type != TargetType.Invalid)
Attack(self, target, allowMove);
}
void Attack(Actor self, Actor targetActor, bool allowMove)
void Attack(Actor self, Target target, bool allowMove)
{
TargetedActor = targetActor;
var target = Target.FromActor(targetActor);
self.SetTargetLine(target, Color.Red, false);
foreach (var ab in activeAttackBases)
ab.AttackTarget(target, false, allowMove);
}
Actor ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove)
Target ChooseTarget(Actor self, AttackBase ab, Stance attackStances, WDist scanRange, bool allowMove)
{
Actor chosenTarget = null;
var chosenTarget = Target.Invalid;
var chosenTargetPriority = int.MinValue;
int chosenTargetRange = 0;
var activePriorities = activeTargetPriorities.ToList();
if (activePriorities.Count == 0)
return null;
return chosenTarget;
var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange);
foreach (var actor in actorsInRange)
var targetsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange)
.Select(Target.FromActor)
.Concat(self.Owner.FrozenActorLayer.FrozenActorsInCircle(self.World, self.CenterPosition, scanRange)
.Select(Target.FromFrozenActor));
foreach (var target in targetsInRange)
{
// PERF: Most units can only attack enemy units. If this is the case but the target is not an enemy, we
// can bail early and avoid the more expensive targeting checks and armament selection. For groups of
// allied units, this helps significantly reduce the cost of auto target scans. This is important as
// these groups will continuously rescan their allies until an enemy finally comes into range.
if (attackStances == OpenRA.Traits.Stance.Enemy && !actor.AppearsHostileTo(self))
BitSet<TargetableType> targetTypes;
if (target.Type == TargetType.Actor)
{
// PERF: Most units can only attack enemy units. If this is the case but the target is not an enemy, we
// can bail early and avoid the more expensive targeting checks and armament selection. For groups of
// allied units, this helps significantly reduce the cost of auto target scans. This is important as
// these groups will continuously rescan their allies until an enemy finally comes into range.
if (attackStances == OpenRA.Traits.Stance.Enemy && !target.Actor.AppearsHostileTo(self))
continue;
// Check whether we can auto-target this actor
targetTypes = target.Actor.GetEnabledTargetTypes();
if (PreventsAutoTarget(self, target.Actor) || !target.Actor.CanBeViewedByPlayer(self.Owner))
continue;
}
else if (target.Type == TargetType.FrozenActor)
{
if (attackStances == OpenRA.Traits.Stance.Enemy && self.Owner.Stances[target.FrozenActor.Owner] == OpenRA.Traits.Stance.Ally)
continue;
targetTypes = target.FrozenActor.TargetTypes;
}
else
continue;
// Check whether we can auto-target this actor
var targetTypes = actor.GetEnabledTargetTypes();
var validPriorities = activePriorities.Where(ati =>
{
// Already have a higher priority target
@@ -324,11 +343,10 @@ namespace OpenRA.Mods.Common.Traits
return true;
}).ToList();
if (validPriorities.Count == 0 || PreventsAutoTarget(self, actor) || !actor.CanBeViewedByPlayer(self.Owner))
if (validPriorities.Count == 0)
continue;
// Make sure that we can actually fire on the actor
var target = Target.FromActor(actor);
var armaments = ab.ChooseArmamentsForTarget(target, false);
if (!allowMove)
armaments = armaments.Where(arm =>
@@ -342,10 +360,10 @@ namespace OpenRA.Mods.Common.Traits
var targetRange = (target.CenterPosition - self.CenterPosition).Length;
foreach (var ati in validPriorities)
{
if (chosenTarget == null || chosenTargetPriority < ati.Priority
if (chosenTarget.Type == TargetType.Invalid || chosenTargetPriority < ati.Priority
|| (chosenTargetPriority == ati.Priority && targetRange < chosenTargetRange))
{
chosenTarget = actor;
chosenTarget = target;
chosenTargetPriority = ati.Priority;
chosenTargetRange = targetRange;
}