MoveWithinRange was only moving the unit far enough away so the center of the target was above the minimum distance. However, the min range checks in the attack code require all positions on the target to be above the minimum distance. For large targets (e.g. buildings) this means some of the target was still too close, and the unit would get stuck in a loop. Now MoveWithinRange uses the same range checks in order to ensure units are moved the correct distances.
59 lines
1.6 KiB
C#
59 lines
1.6 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2015 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.Activities;
|
|
using OpenRA.Mods.Common.Traits;
|
|
using OpenRA.Traits;
|
|
|
|
namespace OpenRA.Mods.Common.Activities
|
|
{
|
|
public class MoveWithinRange : MoveAdjacentTo
|
|
{
|
|
readonly WDist maxRange;
|
|
readonly WDist minRange;
|
|
|
|
public MoveWithinRange(Actor self, Target target, WDist minRange, WDist 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
|
|
return AtCorrectRange(self.CenterPosition);
|
|
}
|
|
|
|
protected override bool ShouldRepath(Actor self, CPos oldTargetPosition)
|
|
{
|
|
return targetPosition != oldTargetPosition && !AtCorrectRange(self.CenterPosition);
|
|
}
|
|
|
|
protected override IEnumerable<CPos> CandidateMovementCells(Actor self)
|
|
{
|
|
var map = self.World.Map;
|
|
var maxCells = (maxRange.Length + 1023) / 1024;
|
|
var minCells = minRange.Length / 1024;
|
|
|
|
return map.FindTilesInAnnulus(targetPosition, minCells, maxCells)
|
|
.Where(c => AtCorrectRange(map.CenterOfCell(c)));
|
|
}
|
|
|
|
bool AtCorrectRange(WPos origin)
|
|
{
|
|
return Target.IsInRange(origin, maxRange) && !Target.IsInRange(origin, minRange);
|
|
}
|
|
}
|
|
}
|