Make MoveAdjacentTo aware of moving targets.

Units moving toward another actor (passengers, hijackers, etc) will now repath if their target moves.
Fixes excessive repathing if the target cannot be reached.
This commit is contained in:
Paul Chote
2014-01-09 18:49:15 +13:00
parent c333b59eb9
commit 3cdeea009b

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* 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,
@@ -8,6 +8,8 @@
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
@@ -19,11 +21,19 @@ namespace OpenRA.Mods.RA.Activities
readonly Mobile mobile;
readonly PathFinder pathFinder;
Activity inner;
CPos cachedTargetPosition;
CPos[] adjacentCells;
bool repath;
public MoveAdjacentTo(Actor self, Target target)
{
this.target = target;
mobile = self.Trait<Mobile>();
pathFinder = self.World.WorldActor.Trait<PathFinder>();
repath = true;
}
public override Activity Tick(Actor self)
@@ -31,26 +41,61 @@ namespace OpenRA.Mods.RA.Activities
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
var ps1 = new PathSearch(self.World, mobile.Info, self)
{
checkForBlocked = true,
heuristic = location => 0,
inReverse = true
};
var targetPosition = target.CenterPosition.ToCPos();
foreach (var cell in Util.AdjacentCells(target))
// Calculate path to target
if (inner == null && repath)
{
if (cell == self.Location)
return NextActivity;
else
ps1.AddInitialCell(cell);
cachedTargetPosition = targetPosition;
adjacentCells = Util.AdjacentCells(target).ToArray();
repath = false;
var ps1 = new PathSearch(self.World, mobile.Info, self)
{
checkForBlocked = true,
heuristic = location => 0,
inReverse = true
};
foreach (var cell in adjacentCells)
{
if (cell == self.Location)
return NextActivity;
else
ps1.AddInitialCell(cell);
}
ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell);
var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true);
var ret = pathFinder.FindBidiPath(ps1, ps2);
inner = mobile.MoveTo(() => ret);
}
ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell);
var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true);
var ret = pathFinder.FindBidiPath(ps1, ps2);
// Force a repath once the actor reaches the next cell
if (!repath && cachedTargetPosition != targetPosition)
{
if (inner != null)
inner.Cancel(self);
return Util.SequenceActivities(mobile.MoveTo(() => ret), this);
repath = true;
}
inner = Util.RunActivity(self, inner);
// Move completed
if (inner == null && adjacentCells.Contains(self.Location))
return NextActivity;
return this;
}
public override IEnumerable<Target> GetTargets(Actor self)
{
if (inner != null)
return inner.GetTargets(self);
return Target.None;
}
}
}