diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 224a7ec441..d4563b79d1 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -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(); pathFinder = self.World.WorldActor.Trait(); + + 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 GetTargets(Actor self) + { + if (inner != null) + return inner.GetTargets(self); + + return Target.None; } } }