Merge pull request #5977 from pchote/oi-keep-moving

Don’t cancel MoveAdjacentTo / MoveWithinRange when target becomes invalid
This commit is contained in:
Matthias Mailänder
2014-07-19 09:39:32 +02:00

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
@@ -17,12 +18,14 @@ namespace OpenRA.Mods.RA.Activities
{ {
public class MoveAdjacentTo : Activity public class MoveAdjacentTo : Activity
{ {
protected readonly Target target; static readonly List<CPos> NoPath = new List<CPos>();
readonly Mobile mobile; readonly Mobile mobile;
readonly PathFinder pathFinder; readonly PathFinder pathFinder;
readonly DomainIndex domainIndex; readonly DomainIndex domainIndex;
readonly uint movementClass; readonly uint movementClass;
protected Target target { get; private set; }
protected CPos targetPosition; protected CPos targetPosition;
Activity inner; Activity inner;
bool repath; bool repath;
@@ -52,6 +55,11 @@ namespace OpenRA.Mods.RA.Activities
return targetPosition != oldTargetPosition; return targetPosition != oldTargetPosition;
} }
protected virtual IEnumerable<CPos> CandidateMovementCells(Actor self)
{
return Util.AdjacentCells(self.World, target);
}
public override Activity Tick(Actor self) public override Activity Tick(Actor self)
{ {
var targetIsValid = target.IsValidFor(self); var targetIsValid = target.IsValidFor(self);
@@ -65,7 +73,7 @@ namespace OpenRA.Mods.RA.Activities
return NextActivity; return NextActivity;
// Target has moved, and MoveAdjacentTo is still valid. // Target has moved, and MoveAdjacentTo is still valid.
UpdateInnerPath(self); inner = mobile.MoveTo(() => CalculatePathToTarget(self));
repath = false; repath = false;
} }
@@ -75,22 +83,20 @@ namespace OpenRA.Mods.RA.Activities
var oldTargetPosition = targetPosition; var oldTargetPosition = targetPosition;
targetPosition = self.World.Map.CellContaining(target.CenterPosition); targetPosition = self.World.Map.CellContaining(target.CenterPosition);
var shroudStop = ShouldStop(self, oldTargetPosition); var shouldStop = ShouldStop(self, oldTargetPosition);
if (shroudStop || (!repath && ShouldRepath(self, oldTargetPosition))) if (shouldStop || (!repath && ShouldRepath(self, oldTargetPosition)))
{ {
// Finish moving into the next cell and then repath. // Finish moving into the next cell and then repath.
if (inner != null) if (inner != null)
inner.Cancel(self); inner.Cancel(self);
repath = !shroudStop; repath = !shouldStop;
} }
} }
else else
{ {
// Target became invalid. Cancel the inner order, // Target became invalid. Move to its last known position.
// and then wait for it to move into the next cell target = Target.FromCell(self.World, targetPosition);
// before finishing this order (handled above).
inner.Cancel(self);
} }
// Ticks the inner move activity to actually move the actor. // Ticks the inner move activity to actually move the actor.
@@ -99,12 +105,7 @@ namespace OpenRA.Mods.RA.Activities
return this; return this;
} }
protected virtual IEnumerable<CPos> CandidateMovementCells(Actor self) List<CPos> CalculatePathToTarget(Actor self)
{
return Util.AdjacentCells(self.World, target);
}
void UpdateInnerPath(Actor self)
{ {
var targetCells = CandidateMovementCells(self); var targetCells = CandidateMovementCells(self);
var searchCells = new List<CPos>(); var searchCells = new List<CPos>();
@@ -115,14 +116,12 @@ namespace OpenRA.Mods.RA.Activities
searchCells.Add(cell); searchCells.Add(cell);
if (!searchCells.Any()) if (!searchCells.Any())
return; return NoPath;
var path = pathFinder.FindBidiPath( var fromSrc = PathSearch.FromPoints(self.World, mobile.Info, self, searchCells, loc, true);
PathSearch.FromPoints(self.World, mobile.Info, self, searchCells, loc, true), var fromDest = PathSearch.FromPoint(self.World, mobile.Info, self, loc, targetPosition, true).Reverse();
PathSearch.FromPoint(self.World, mobile.Info, self, loc, targetPosition, true).Reverse()
);
inner = mobile.MoveTo(() => path); return pathFinder.FindBidiPath(fromSrc, fromDest);
} }
public override IEnumerable<Target> GetTargets(Actor self) public override IEnumerable<Target> GetTargets(Actor self)