Add AutoTarget support for FrozenActors.
This commit is contained in:
committed by
Oliver Brakmann
parent
c34dd4b824
commit
5f79c31a57
@@ -12,6 +12,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
@@ -117,7 +118,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public UnitStance Stance { get { return stance; } }
|
public UnitStance Stance { get { return stance; } }
|
||||||
|
|
||||||
[Sync] public Actor Aggressor;
|
[Sync] public Actor Aggressor;
|
||||||
[Sync] public Actor TargetedActor;
|
|
||||||
|
|
||||||
// NOT SYNCED: do not refer to this anywhere other than UI code
|
// NOT SYNCED: do not refer to this anywhere other than UI code
|
||||||
public UnitStance PredictedStance;
|
public UnitStance PredictedStance;
|
||||||
@@ -217,7 +217,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
bool allowMove;
|
bool allowMove;
|
||||||
if (ShouldAttack(out allowMove))
|
if (ShouldAttack(out allowMove))
|
||||||
Attack(self, Aggressor, allowMove);
|
Attack(self, Target.FromActor(Aggressor), allowMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotifyIdle.TickIdle(Actor self)
|
void INotifyIdle.TickIdle(Actor self)
|
||||||
@@ -251,7 +251,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
--nextScanTime;
|
--nextScanTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Actor ScanForTarget(Actor self, bool allowMove)
|
public Target ScanForTarget(Actor self, bool allowMove)
|
||||||
{
|
{
|
||||||
if (nextScanTime <= 0 && activeAttackBases.Any())
|
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)
|
public void ScanAndAttack(Actor self, bool allowMove)
|
||||||
{
|
{
|
||||||
var targetActor = ScanForTarget(self, allowMove);
|
var target = ScanForTarget(self, allowMove);
|
||||||
if (targetActor != null)
|
if (target.Type != TargetType.Invalid)
|
||||||
Attack(self, targetActor, allowMove);
|
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);
|
self.SetTargetLine(target, Color.Red, false);
|
||||||
|
|
||||||
foreach (var ab in activeAttackBases)
|
foreach (var ab in activeAttackBases)
|
||||||
ab.AttackTarget(target, false, allowMove);
|
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;
|
var chosenTargetPriority = int.MinValue;
|
||||||
int chosenTargetRange = 0;
|
int chosenTargetRange = 0;
|
||||||
|
|
||||||
var activePriorities = activeTargetPriorities.ToList();
|
var activePriorities = activeTargetPriorities.ToList();
|
||||||
if (activePriorities.Count == 0)
|
if (activePriorities.Count == 0)
|
||||||
return null;
|
return chosenTarget;
|
||||||
|
|
||||||
var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange);
|
var targetsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange)
|
||||||
foreach (var actor in actorsInRange)
|
.Select(Target.FromActor)
|
||||||
|
.Concat(self.Owner.FrozenActorLayer.FrozenActorsInCircle(self.World, self.CenterPosition, scanRange)
|
||||||
|
.Select(Target.FromFrozenActor));
|
||||||
|
|
||||||
|
foreach (var target in targetsInRange)
|
||||||
|
{
|
||||||
|
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
|
// 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
|
// 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
|
// 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.
|
// these groups will continuously rescan their allies until an enemy finally comes into range.
|
||||||
if (attackStances == OpenRA.Traits.Stance.Enemy && !actor.AppearsHostileTo(self))
|
if (attackStances == OpenRA.Traits.Stance.Enemy && !target.Actor.AppearsHostileTo(self))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check whether we can auto-target this actor
|
// Check whether we can auto-target this actor
|
||||||
var targetTypes = actor.GetEnabledTargetTypes();
|
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;
|
||||||
|
|
||||||
var validPriorities = activePriorities.Where(ati =>
|
var validPriorities = activePriorities.Where(ati =>
|
||||||
{
|
{
|
||||||
// Already have a higher priority target
|
// Already have a higher priority target
|
||||||
@@ -324,11 +343,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return true;
|
return true;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
if (validPriorities.Count == 0 || PreventsAutoTarget(self, actor) || !actor.CanBeViewedByPlayer(self.Owner))
|
if (validPriorities.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Make sure that we can actually fire on the actor
|
// Make sure that we can actually fire on the actor
|
||||||
var target = Target.FromActor(actor);
|
|
||||||
var armaments = ab.ChooseArmamentsForTarget(target, false);
|
var armaments = ab.ChooseArmamentsForTarget(target, false);
|
||||||
if (!allowMove)
|
if (!allowMove)
|
||||||
armaments = armaments.Where(arm =>
|
armaments = armaments.Where(arm =>
|
||||||
@@ -342,10 +360,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var targetRange = (target.CenterPosition - self.CenterPosition).Length;
|
var targetRange = (target.CenterPosition - self.CenterPosition).Length;
|
||||||
foreach (var ati in validPriorities)
|
foreach (var ati in validPriorities)
|
||||||
{
|
{
|
||||||
if (chosenTarget == null || chosenTargetPriority < ati.Priority
|
if (chosenTarget.Type == TargetType.Invalid || chosenTargetPriority < ati.Priority
|
||||||
|| (chosenTargetPriority == ati.Priority && targetRange < chosenTargetRange))
|
|| (chosenTargetPriority == ati.Priority && targetRange < chosenTargetRange))
|
||||||
{
|
{
|
||||||
chosenTarget = actor;
|
chosenTarget = target;
|
||||||
chosenTargetPriority = ati.Priority;
|
chosenTargetPriority = ati.Priority;
|
||||||
chosenTargetRange = targetRange;
|
chosenTargetRange = targetRange;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user