From 399aac7e0f7f263d0191fef328d7c40decaf72b9 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Jul 2013 15:07:18 +1200 Subject: [PATCH] Extend Target with world-coordinate range checks. --- OpenRA.Game/Traits/Target.cs | 50 ++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index 33456afd5c..43a8efec68 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -8,11 +8,15 @@ */ #endregion +using System; +using System.Collections.Generic; +using System.Linq; + namespace OpenRA.Traits { - public struct Target // a target: either an actor, or a fixed location. + public struct Target { - public static Target[] NoTargets = {}; + public static readonly Target[] NoTargets = {}; Actor actor; PPos pos; @@ -43,6 +47,48 @@ namespace OpenRA.Traits public PPos PxPosition { get { return IsActor ? actor.Trait().PxPosition : pos; } } public PPos CenterLocation { get { return PxPosition; } } + // Representative position - see Positions for the full set of targetable positions. + public WPos CenterPosition + { + get + { + if (!IsValid) + throw new InvalidOperationException("Attempting to query the position of an invalid Target"); + + return actor != null ? actor.CenterPosition : pos.ToWPos(0); + } + } + + // Positions available to target for range checks + static readonly WPos[] NoPositions = {}; + public IEnumerable Positions + { + get + { + if (!IsValid) + return NoPositions; + + if (actor == null) + return new []{pos.ToWPos(0)}; + + var targetable = actor.TraitOrDefault(); + if (targetable == null) + return new []{actor.CenterPosition}; + + return targetable.TargetableCells(actor).Select(c => c.CenterPosition); + } + } + + public bool IsInRange(WPos origin, WRange range) + { + if (!IsValid) + return false; + + // Target ranges are calculated in 2D, so ignore height differences + return Positions.Any(t => (t.X - origin.X)*(t.X - origin.X) + + (t.Y - origin.Y)*(t.Y - origin.Y) <= range.Range*range.Range); + } + public Actor Actor { get { return IsActor ? actor : null; } } public bool IsActor { get { return actor != null && !actor.Destroyed; } } }