Merge pull request #9734 from RoosterDragon/auto-target-perf
Improve AutoTarget performance
This commit is contained in:
@@ -44,6 +44,7 @@ namespace OpenRA
|
||||
public Rectangle VisualBounds { get; private set; }
|
||||
public IEffectiveOwner EffectiveOwner { get; private set; }
|
||||
public IOccupySpace OccupiesSpace { get; private set; }
|
||||
public ITargetable[] Targetables { get; private set; }
|
||||
|
||||
public bool IsIdle { get { return currentActivity == null; } }
|
||||
public bool IsDead { get { return Disposed || (health != null && health.IsDead); } }
|
||||
@@ -110,6 +111,7 @@ namespace OpenRA
|
||||
disables = TraitsImplementing<IDisable>().ToArray();
|
||||
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
|
||||
defaultVisibility = Trait<IDefaultVisibility>();
|
||||
Targetables = TraitsImplementing<ITargetable>().ToArray();
|
||||
}
|
||||
|
||||
Rectangle DetermineBounds()
|
||||
@@ -334,6 +336,33 @@ namespace OpenRA
|
||||
return defaultVisibility.IsVisible(this, player);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetAllTargetTypes()
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var targetable in Targetables)
|
||||
foreach (var targetType in targetable.TargetTypes)
|
||||
yield return targetType;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetEnabledTargetTypes()
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var targetable in Targetables)
|
||||
if (targetable.IsTraitEnabled())
|
||||
foreach (var targetType in targetable.TargetTypes)
|
||||
yield return targetType;
|
||||
}
|
||||
|
||||
public bool IsTargetableBy(Actor byActor)
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var targetable in Targetables)
|
||||
if (targetable.IsTraitEnabled() && targetable.TargetableBy(this, byActor))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Scripting interface
|
||||
|
||||
Lazy<ScriptActorInterface> luaInterface;
|
||||
|
||||
@@ -127,14 +127,17 @@ namespace OpenRA.GameRules
|
||||
/// <summary>Checks if the weapon is valid against (can target) the actor.</summary>
|
||||
public bool IsValidAgainst(Actor victim, Actor firedBy)
|
||||
{
|
||||
var targetable = victim.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled);
|
||||
if (!IsValidTarget(targetable.SelectMany(t => t.TargetTypes)))
|
||||
var targetTypes = victim.GetEnabledTargetTypes();
|
||||
|
||||
if (!IsValidTarget(targetTypes))
|
||||
return false;
|
||||
|
||||
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
|
||||
return false;
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var warhead in Warheads)
|
||||
if (warhead.IsValidAgainst(victim, firedBy))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Checks if the weapon is valid against (can target) the frozen actor.</summary>
|
||||
|
||||
@@ -159,13 +159,27 @@ namespace OpenRA
|
||||
|
||||
public bool CanTargetActor(Actor a)
|
||||
{
|
||||
if (HasFogVisibility && fogVisibilities.Any(f => f.IsVisible(a)))
|
||||
return true;
|
||||
// PERF: Avoid LINQ.
|
||||
if (HasFogVisibility)
|
||||
foreach (var fogVisibility in fogVisibilities)
|
||||
if (fogVisibility.IsVisible(a))
|
||||
return true;
|
||||
|
||||
return CanViewActor(a);
|
||||
}
|
||||
|
||||
public bool HasFogVisibility { get { return fogVisibilities.Any(f => f.HasFogVisibility()); } }
|
||||
public bool HasFogVisibility
|
||||
{
|
||||
get
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
foreach (var fogVisibility in fogVisibilities)
|
||||
if (fogVisibility.HasFogVisibility())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#region Scripting interface
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace OpenRA.Traits
|
||||
|
||||
CenterPosition = self.CenterPosition;
|
||||
Bounds = self.Bounds;
|
||||
TargetTypes = self.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet();
|
||||
TargetTypes = self.GetEnabledTargetTypes().ToHashSet();
|
||||
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace OpenRA.Traits
|
||||
|
||||
TargetType type;
|
||||
Actor actor;
|
||||
IEnumerable<ITargetable> targetable;
|
||||
FrozenActor frozen;
|
||||
WPos pos;
|
||||
int generation;
|
||||
@@ -48,7 +47,6 @@ namespace OpenRA.Traits
|
||||
return new Target
|
||||
{
|
||||
actor = a,
|
||||
targetable = a.TraitsImplementing<ITargetable>(),
|
||||
type = TargetType.Actor,
|
||||
generation = a.Generation,
|
||||
};
|
||||
@@ -83,8 +81,7 @@ namespace OpenRA.Traits
|
||||
if (targeter == null || Type == TargetType.Invalid)
|
||||
return false;
|
||||
|
||||
var targeted = this.actor;
|
||||
if (targeted != null && !targetable.Any(t => t.IsTraitEnabled() && t.TargetableBy(targeted, targeter)))
|
||||
if (actor != null && !actor.IsTargetableBy(targeter))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -94,7 +91,25 @@ namespace OpenRA.Traits
|
||||
// TODO: either replace based on target type or put in singleton trait
|
||||
public bool RequiresForceFire
|
||||
{
|
||||
get { return targetable != null && targetable.Any(Exts.IsTraitEnabled) && targetable.Where(Exts.IsTraitEnabled).All(t => t.RequiresForceFire); }
|
||||
get
|
||||
{
|
||||
if (actor == null)
|
||||
return false;
|
||||
|
||||
// PERF: Avoid LINQ.
|
||||
var isTargetable = false;
|
||||
foreach (var targetable in actor.Targetables)
|
||||
{
|
||||
if (!targetable.IsTraitEnabled())
|
||||
continue;
|
||||
|
||||
isTargetable = true;
|
||||
if (!targetable.RequiresForceFire)
|
||||
return false;
|
||||
}
|
||||
|
||||
return isTargetable;
|
||||
}
|
||||
}
|
||||
|
||||
// Representative position - see Positions for the full set of targetable positions.
|
||||
@@ -126,8 +141,7 @@ namespace OpenRA.Traits
|
||||
switch (Type)
|
||||
{
|
||||
case TargetType.Actor:
|
||||
var targetable = actor.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled);
|
||||
if (!targetable.Any())
|
||||
if (!actor.Targetables.Any(Exts.IsTraitEnabled))
|
||||
return new[] { actor.CenterPosition };
|
||||
|
||||
var targetablePositions = actor.TraitOrDefault<ITargetablePositions>();
|
||||
|
||||
Reference in New Issue
Block a user