diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 6fb50cc2d4..00f0aa2197 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -17,14 +17,14 @@ namespace OpenRA.Mods.RA.Activities { public class MoveAdjacentTo : Activity { - readonly Target target; + protected readonly Target target; readonly Mobile mobile; readonly PathFinder pathFinder; readonly DomainIndex domainIndex; readonly uint movementClass; + protected CPos targetPosition; Activity inner; - CPos targetPosition; bool repath; public MoveAdjacentTo(Actor self, Target target) @@ -39,6 +39,16 @@ namespace OpenRA.Mods.RA.Activities repath = true; } + protected virtual bool ShouldStop(Actor self, CPos oldTargetPosition) + { + return false; + } + + protected virtual bool ShouldRepath(Actor self, CPos oldTargetPosition) + { + return targetPosition != oldTargetPosition; + } + public override Activity Tick(Actor self) { var targetIsValid = target.IsValidFor(self); @@ -59,15 +69,17 @@ namespace OpenRA.Mods.RA.Activities if (targetIsValid) { // Check if the target has moved - var oldPosition = targetPosition; + var oldTargetPosition = targetPosition; targetPosition = target.CenterPosition.ToCPos(); - if (!repath && targetPosition != oldPosition) + + var shroudStop = ShouldStop(self, oldTargetPosition); + if (shroudStop || (!repath && ShouldRepath(self, oldTargetPosition))) { // Finish moving into the next cell and then repath. if (inner != null) inner.Cancel(self); - repath = true; + repath = !shroudStop; } } else @@ -84,9 +96,14 @@ namespace OpenRA.Mods.RA.Activities return this; } + protected virtual IEnumerable CandidateMovementCells(Actor self) + { + return Util.AdjacentCells(target); + } + void UpdateInnerPath(Actor self) { - var targetCells = Util.AdjacentCells(target); + var targetCells = CandidateMovementCells(self); var searchCells = new List(); var loc = self.Location; diff --git a/OpenRA.Mods.RA/Activities/MoveWithinRange.cs b/OpenRA.Mods.RA/Activities/MoveWithinRange.cs new file mode 100755 index 0000000000..20eb9b4ce6 --- /dev/null +++ b/OpenRA.Mods.RA/Activities/MoveWithinRange.cs @@ -0,0 +1,63 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Mods.RA.Move; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Activities +{ + public class MoveWithinRange : MoveAdjacentTo + { + readonly WRange maxRange; + readonly WRange minRange; + + public MoveWithinRange(Actor self, Target target, WRange minRange, WRange maxRange) + : base(self, target) + { + this.minRange = minRange; + this.maxRange = maxRange; + } + + protected override bool ShouldStop(Actor self, CPos oldTargetPosition) + { + // We are now in range. Don't move any further! + // HACK: This works around the pathfinder not returning the shortest path + var cp = self.CenterPosition; + return target.IsInRange(cp, maxRange) && !target.IsInRange(cp, minRange); + } + + protected override bool ShouldRepath(Actor self, CPos oldTargetPosition) + { + var cp = self.CenterPosition; + return targetPosition != oldTargetPosition && (!target.IsInRange(cp, maxRange) || target.IsInRange(cp, minRange)); + } + + protected override IEnumerable CandidateMovementCells(Actor self) + { + var maxCells = (maxRange.Range + 1023) / 1024; + var outerCells = self.World.Map.FindTilesInCircle(targetPosition, maxCells); + + var minCells = minRange.Range / 1024; + var innerCells = self.World.Map.FindTilesInCircle(targetPosition, minCells); + + var outerSq = maxRange.Range * maxRange.Range; + var innerSq = minRange.Range * minRange.Range; + var center = target.CenterPosition; + + return outerCells.Except(innerCells).Where(c => + { + var dxSq = (c.CenterPosition - center).HorizontalLengthSquared; + return dxSq >= innerSq && dxSq <= outerSq; + }); + } + } +} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 7161cb0c93..bc0080da54 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -528,6 +528,7 @@ +