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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user