Only use largest blocker instead of largest actor for projectile blocker overscan

Before this, we unconditionally used the largest OuterRadius of all actors inside a mod for overscanning of blockable projectiles.
However, in many mods the only blockable actors are 1-cell walls, and even if there are gates like in TS, they usually aren't the largest actors in terms of hit-shape.

So this measure should save a bit of performance by reducing the overscan radius of blockable projectiles, especially in mods where walls are the only blocking actors.
This commit is contained in:
reaperrr
2018-04-21 06:37:39 +02:00
committed by abcdefg30
parent 39aa1a9f9c
commit 18ed04eab5
4 changed files with 13 additions and 3 deletions

View File

@@ -259,6 +259,7 @@ namespace OpenRA.Traits
IEnumerable<Actor> ActorsInBox(WPos a, WPos b); IEnumerable<Actor> ActorsInBox(WPos a, WPos b);
WDist LargestActorRadius { get; } WDist LargestActorRadius { get; }
WDist LargestBlockingActorRadius { get; }
} }
public interface IRenderModifier public interface IRenderModifier

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits
public static bool AnyBlockingActorsBetween(World world, WPos start, WPos end, WDist width, out WPos hit) public static bool AnyBlockingActorsBetween(World world, WPos start, WPos end, WDist width, out WPos hit)
{ {
var actors = world.FindActorsOnLine(start, end, width); var actors = world.FindBlockingActorsOnLine(start, end, width);
var length = (end - start).Length; var length = (end - start).Length;
foreach (var a in actors) foreach (var a in actors)

View File

@@ -184,6 +184,7 @@ namespace OpenRA.Mods.Common.Traits
readonly Predicate<Actor> actorShouldBeRemoved; readonly Predicate<Actor> actorShouldBeRemoved;
public WDist LargestActorRadius { get; private set; } public WDist LargestActorRadius { get; private set; }
public WDist LargestBlockingActorRadius { get; private set; }
public ActorMap(World world, ActorMapInfo info) public ActorMap(World world, ActorMapInfo info)
{ {
@@ -202,6 +203,8 @@ namespace OpenRA.Mods.Common.Traits
actorShouldBeRemoved = removeActorPosition.Contains; actorShouldBeRemoved = removeActorPosition.Contains;
LargestActorRadius = map.Rules.Actors.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius); LargestActorRadius = map.Rules.Actors.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius);
var blockers = map.Rules.Actors.Where(a => a.Value.HasTraitInfo<IBlocksProjectilesInfo>());
LargestBlockingActorRadius = blockers.Any() ? blockers.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius) : WDist.Zero;
} }
void INotifyCreated.Created(Actor self) void INotifyCreated.Created(Actor self)

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common
/// <param name="lineEnd">The position the line should end at</param> /// <param name="lineEnd">The position the line should end at</param>
/// <param name="lineWidth">How close an actor's health radius needs to be to the line to be considered 'intersected' by the line</param> /// <param name="lineWidth">How close an actor's health radius needs to be to the line to be considered 'intersected' by the line</param>
/// <returns>A list of all the actors intersected by the line</returns> /// <returns>A list of all the actors intersected by the line</returns>
public static IEnumerable<Actor> FindActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth) public static IEnumerable<Actor> FindActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth, bool onlyBlockers = false)
{ {
// This line intersection check is done by first just finding all actors within a square that starts at the source, and ends at the target. // This line intersection check is done by first just finding all actors within a square that starts at the source, and ends at the target.
// Then we iterate over this list, and find all actors for which their health radius is at least within lineWidth of the line. // Then we iterate over this list, and find all actors for which their health radius is at least within lineWidth of the line.
@@ -39,7 +39,8 @@ namespace OpenRA.Mods.Common
var yDir = yDiff < 0 ? -1 : 1; var yDir = yDiff < 0 ? -1 : 1;
var dir = new WVec(xDir, yDir, 0); var dir = new WVec(xDir, yDir, 0);
var overselect = dir * (1024 + lineWidth.Length + world.ActorMap.LargestActorRadius.Length); var largestValidActorRadius = onlyBlockers ? world.ActorMap.LargestBlockingActorRadius.Length : world.ActorMap.LargestActorRadius.Length;
var overselect = dir * (1024 + lineWidth.Length + largestValidActorRadius);
var finalTarget = lineEnd + overselect; var finalTarget = lineEnd + overselect;
var finalSource = lineStart - overselect; var finalSource = lineStart - overselect;
@@ -64,6 +65,11 @@ namespace OpenRA.Mods.Common
return intersectedActors; return intersectedActors;
} }
public static IEnumerable<Actor> FindBlockingActorsOnLine(this World world, WPos lineStart, WPos lineEnd, WDist lineWidth)
{
return world.FindActorsOnLine(lineStart, lineEnd, lineWidth, true);
}
/// <summary> /// <summary>
/// Finds all the actors of which their health radius is intersected by a specified circle. /// Finds all the actors of which their health radius is intersected by a specified circle.
/// </summary> /// </summary>