HitShape, query trait via actor cached targetable positions.
This commit is contained in:
committed by
Matthias Mailänder
parent
f88b6d78ff
commit
e3aa2dc6c0
@@ -68,6 +68,7 @@ namespace OpenRA
|
||||
public IEffectiveOwner EffectiveOwner { get; }
|
||||
public IOccupySpace OccupiesSpace { get; }
|
||||
public ITargetable[] Targetables { get; }
|
||||
public IEnumerable<ITargetablePositions> EnabledTargetablePositions { get; private set; }
|
||||
|
||||
public bool IsIdle => CurrentActivity == null;
|
||||
public bool IsDead => Disposed || (health != null && health.IsDead);
|
||||
@@ -114,7 +115,6 @@ namespace OpenRA
|
||||
readonly IDefaultVisibility defaultVisibility;
|
||||
readonly INotifyBecomingIdle[] becomingIdles;
|
||||
readonly INotifyIdle[] tickIdles;
|
||||
readonly IEnumerable<ITargetablePositions> enabledTargetablePositions;
|
||||
readonly IEnumerable<WPos> enabledTargetableWorldPositions;
|
||||
bool created;
|
||||
|
||||
@@ -192,8 +192,8 @@ namespace OpenRA
|
||||
tickIdles = tickIdlesList.ToArray();
|
||||
Targetables = targetablesList.ToArray();
|
||||
var targetablePositions = targetablePositionsList.ToArray();
|
||||
enabledTargetablePositions = targetablePositions.Where(Exts.IsTraitEnabled);
|
||||
enabledTargetableWorldPositions = enabledTargetablePositions.SelectMany(tp => tp.TargetablePositions(this));
|
||||
EnabledTargetablePositions = targetablePositions.Where(Exts.IsTraitEnabled);
|
||||
enabledTargetableWorldPositions = EnabledTargetablePositions.SelectMany(tp => tp.TargetablePositions(this));
|
||||
SyncHashes = syncHashesList.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -530,7 +530,7 @@ namespace OpenRA
|
||||
|
||||
public IEnumerable<WPos> GetTargetablePositions()
|
||||
{
|
||||
if (enabledTargetablePositions.Any())
|
||||
if (EnabledTargetablePositions.Any())
|
||||
return enabledTargetableWorldPositions;
|
||||
|
||||
return new[] { CenterPosition };
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Effects;
|
||||
@@ -336,9 +335,11 @@ namespace OpenRA.Mods.Common.Projectiles
|
||||
continue;
|
||||
|
||||
// If the impact position is within any actor's HitShape, we have a direct hit
|
||||
var activeShapes = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
|
||||
if (activeShapes.Any(i => i.DistanceFromEdge(victim, pos).Length <= 0))
|
||||
return true;
|
||||
// PERF: Avoid using TraitsImplementing<HitShape> that needs to find the actor in the trait dictionary.
|
||||
foreach (var targetPos in victim.EnabledTargetablePositions)
|
||||
if (targetPos is HitShape h)
|
||||
if (h.DistanceFromEdge(victim, pos).Length <= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -50,8 +50,14 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
if (!IsValidAgainst(victim, firedBy))
|
||||
return;
|
||||
|
||||
var closestActiveShape = victim.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled)
|
||||
.MinByOrDefault(t => t.DistanceFromEdge(victim, victim.CenterPosition));
|
||||
// PERF: Avoid using TraitsImplementing<HitShape> that needs to find the actor in the trait dictionary.
|
||||
var closestActiveShape = (HitShape)victim.EnabledTargetablePositions.MinByOrDefault(t =>
|
||||
{
|
||||
if (t is HitShape h)
|
||||
return h.DistanceFromEdge(victim, victim.CenterPosition);
|
||||
else
|
||||
return WDist.MaxValue;
|
||||
});
|
||||
|
||||
// Cannot be damaged without an active HitShape
|
||||
if (closestActiveShape == null)
|
||||
|
||||
@@ -63,20 +63,32 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
if (!IsValidAgainst(victim, firedBy))
|
||||
continue;
|
||||
|
||||
var closestActiveShape = victim.TraitsImplementing<HitShape>()
|
||||
.Where(Exts.IsTraitEnabled)
|
||||
.Select(s => (HitShape: s, Distance: s.DistanceFromEdge(victim, pos)))
|
||||
.MinByOrDefault(s => s.Distance);
|
||||
HitShape closestActiveShape = null;
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
// PERF: Avoid using TraitsImplementing<HitShape> that needs to find the actor in the trait dictionary.
|
||||
foreach (var targetPos in victim.EnabledTargetablePositions)
|
||||
{
|
||||
if (targetPos is HitShape h)
|
||||
{
|
||||
var distance = h.DistanceFromEdge(victim, pos).Length;
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestActiveShape = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot be damaged without an active HitShape.
|
||||
if (closestActiveShape.HitShape == null)
|
||||
if (closestActiveShape == null)
|
||||
continue;
|
||||
|
||||
var falloffDistance = 0;
|
||||
switch (DamageCalculationType)
|
||||
{
|
||||
case DamageCalculationType.HitShape:
|
||||
falloffDistance = closestActiveShape.Distance.Length;
|
||||
falloffDistance = closestDistance;
|
||||
break;
|
||||
case DamageCalculationType.ClosestTargetablePosition:
|
||||
falloffDistance = victim.GetTargetablePositions().Select(x => (x - pos).Length).Min();
|
||||
@@ -108,7 +120,7 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
ImpactOrientation = impactOrientation,
|
||||
};
|
||||
|
||||
InflictDamage(victim, firedBy, closestActiveShape.HitShape, updatedWarheadArgs);
|
||||
InflictDamage(victim, firedBy, closestActiveShape, updatedWarheadArgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
@@ -36,20 +35,32 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
if (!IsValidAgainst(victim, firedBy))
|
||||
continue;
|
||||
|
||||
var closestActiveShape = victim.TraitsImplementing<HitShape>()
|
||||
.Where(Exts.IsTraitEnabled)
|
||||
.Select(s => (HitShape: s, Distance: s.DistanceFromEdge(victim, pos)))
|
||||
.MinByOrDefault(s => s.Distance);
|
||||
HitShape closestActiveShape = null;
|
||||
var closestDistance = int.MaxValue;
|
||||
|
||||
// PERF: Avoid using TraitsImplementing<HitShape> that needs to find the actor in the trait dictionary.
|
||||
foreach (var targetPos in victim.EnabledTargetablePositions)
|
||||
{
|
||||
if (targetPos is HitShape hitshape)
|
||||
{
|
||||
var distance = hitshape.DistanceFromEdge(victim, pos).Length;
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestActiveShape = hitshape;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot be damaged without an active HitShape.
|
||||
if (closestActiveShape.HitShape == null)
|
||||
if (closestActiveShape == null)
|
||||
continue;
|
||||
|
||||
// Cannot be damaged if HitShape is outside Spread.
|
||||
if (closestActiveShape.Distance > Spread)
|
||||
if (closestDistance > Spread.Length)
|
||||
continue;
|
||||
|
||||
InflictDamage(victim, firedBy, closestActiveShape.HitShape, args);
|
||||
InflictDamage(victim, firedBy, closestActiveShape, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
@@ -49,9 +49,11 @@ namespace OpenRA.Mods.Common
|
||||
foreach (var currActor in actorsInSquare)
|
||||
{
|
||||
var actorWidth = 0;
|
||||
var shapes = currActor.TraitsImplementing<HitShape>().Where(Exts.IsTraitEnabled);
|
||||
if (shapes.Any())
|
||||
actorWidth = shapes.Max(h => h.Info.Type.OuterRadius.Length);
|
||||
|
||||
// PERF: Avoid using TraitsImplementing<HitShape> that needs to find the actor in the trait dictionary.
|
||||
foreach (var targetPos in currActor.EnabledTargetablePositions)
|
||||
if (targetPos is HitShape hitshape)
|
||||
actorWidth = Math.Max(actorWidth, hitshape.Info.Type.OuterRadius.Length);
|
||||
|
||||
var projection = lineStart.MinimumPointLineProjection(lineEnd, currActor.CenterPosition);
|
||||
var distance = (currActor.CenterPosition - projection).HorizontalLength;
|
||||
|
||||
Reference in New Issue
Block a user