//--------------------------------------------------------------------------------------------- public void NormalizeReferences(PathNodeList originalList) { for (int i = 0; i < this.Count; i++) { PathNode originalFound = originalList.FindNode(this[i].X, this[i].Y); if (originalFound != null) { this[i] = originalFound; } } }
//--------------------------------------------------------------------------------------------- public void MergeIdent(PathNodeList possibleList) { int count = this.Count; for (int i = count - 1; i >= 0; i--) { PathNode findNode = possibleList.FindNode(this[i].X, this[i].Y); if (findNode != null) { this.RemoveAt(i); } } }
//--------------------------------------------------------------------------------------------- public void MergePossible(PathNodeList possibleList) { int count = this.Count; for (int i = count - 1; i >= 0; i--) { PathNode findNode = possibleList.FindNode(this[i].X, this[i].Y); if (findNode == null || findNode.Walkable.HasValue && !findNode.Walkable.Value) { this.RemoveAt(i); } } }
//--------------------------------------------------------------------------------------------- public PathNodeList FromPositionCollection(List <UOPositionBase> positions) { PathNodeList list = new PathNodeList(); foreach (UOPositionBase position in positions) { PathNode node = new PathNode(); node.X = position.X.GetValueOrDefault(); node.Y = position.Y.GetValueOrDefault(); node.Walkable = position.IsSepable; if (!list.ContainsNode(node)) { list.Add(node); } } return(list); }
//--------------------------------------------------------------------------------------------- public PathNodeList FindAdjacentNodes(PathNode node) { PathNodeList list = new PathNodeList(); PathNode adjNode = new PathNode() { X = (ushort)(node.X), Y = (ushort)(node.Y + 1) }; //0 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X + 1), Y = (ushort)(node.Y + 1), DiagonalToParent = true }; //45 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X + 1), Y = (ushort)(node.Y) }; //90 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X + 1), Y = (ushort)(node.Y - 1), DiagonalToParent = true }; //135 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X), Y = (ushort)(node.Y - 1) }; //180 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X - 1), Y = (ushort)(node.Y - 1), DiagonalToParent = true }; //225 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X - 1), Y = (ushort)(node.Y) }; //270 list.Add(adjNode); adjNode = new PathNode() { X = (ushort)(node.X - 1), Y = (ushort)(node.Y + 1), DiagonalToParent = true }; //315 list.Add(adjNode); return(list); }
//--------------------------------------------------------------------------------------------- protected virtual void Dispose(bool disposing) { if (disposing) { if (this.OpenNodes != null) { this.OpenNodes.Dispose(); this.OpenNodes = null; } if (this.CloseNodes != null) { this.CloseNodes.Dispose(); this.CloseNodes = null; } } }
//--------------------------------------------------------------------------------------------- public void RemoveDiagonalCorners(PathNode parent, PathBuilder builder) { int count = this.Count; for (int i = count - 1; i >= 0; i--) { PathNode current = this[i]; if (current.DiagonalToParent) { PathNodeList currentAdje = builder.FindAdjacentNodes(current); currentAdje.MergePossible(this); if (currentAdje.Count == 1 || currentAdje.Count == 0) { this.RemoveAt(i); } } } }
public PathBuilder(PathNodeList possibleNodes) { PossibleNodes = possibleNodes; }
//--------------------------------------------------------------------------------------------- public PathBuilder() { PossibleNodes = new PathNodeList(); }
public bool ComputePath(PathNode start, PathNode end, int fromDistance) { OpenNodes = new PathNodeList(); CloseNodes = new PathNodeList(); PathNode current = start; start.G = 0; start.H = ComputeH(start, end); if (!OpenNodes.ContainsNode(start)) { OpenNodes.Add(start); } bool finish = false; bool result = false; if (!this.PossibleNodes.ContainsNode(start)) { this.PossibleNodes.Add(start); } if (!this.PossibleNodes.ContainsNode(end)) { this.PossibleNodes.Add(end); } while (!finish && Searchs < 10000) { Searchs++; OpenNodes.Remove(current); if (!CloseNodes.ContainsNode(current)) { CloseNodes.Add(current); } PathNodeList searchNodes = FindAdjacentNodes(current); foreach (PathNode node in searchNodes) { if (!this.PossibleNodes.ContainsNode(node)) { this.PossibleNodes.Add(node); } } searchNodes.MergePossible(this.PossibleNodes); searchNodes.RemoveDiagonalCorners(current, this); if (searchNodes.Count > 0) { searchNodes.MergeIdent(CloseNodes); } else { PathNodeList adjNodes = FindAdjacentNodes(current); foreach (PathNode adj in adjNodes) { PathNode sNode = this.PossibleNodes.FindNode(adj.X, adj.Y); if (sNode == null) { sNode = adj; this.PossibleNodes.Add(sNode); } sNode.Walkable = null; searchNodes.Add(sNode); } searchNodes.RemoveDiagonalCorners(current, this); } searchNodes.NormalizeReferences(OpenNodes); PathNode bestNode = null; foreach (PathNode searchNode in searchNodes) { if (!OpenNodes.ContainsNode(searchNode)) { searchNode.Parent = current; searchNode.H = ComputeH(searchNode, end); searchNode.G = ComputeG(searchNode.Parent, searchNode); OpenNodes.Add(searchNode); } else if (searchNode.G > (current.G + (searchNode.DiagonalToParent ? 14 : 10))) { searchNode.Parent = current; searchNode.H = ComputeH(searchNode, end); searchNode.G = ComputeG(searchNode.Parent, searchNode); } } foreach (PathNode openNode in OpenNodes) { if (bestNode == null || (openNode.F < bestNode.F)) { bestNode = openNode; } } if (bestNode == null) { finish = true; } else if (bestNode.H == (fromDistance * 10)) { OpenNodes.Remove(bestNode); if (!CloseNodes.ContainsNode(bestNode)) { CloseNodes.Add(bestNode); } bestNode.Finish = true; result = true; finish = true; } current = bestNode; } return(result); }
//--------------------------------------------------------------------------------------------- private bool TryGoTo(ushort x, ushort y, int fromDistance, int tries, PathNodeList localList) { IUOPosition destination = this.CreatePositionInstance(x, y, 0); if (localList == null) { localList = new PathNodeList(); } if (EnableLog) { Game.PrintMessage("TryGoTo : " + x + ", " + y + " - " + tries); } if (this.ActualPosition.Equals(destination) || Robot.GetRelativeVectorLength(this.ActualPosition, destination) <= fromDistance) { if (EnableLog) { Game.PrintMessage("TryGoTo OK - 1: " + x + ", " + y); } return(true); } PathNode start = new PathNode() { X = World.Player.X, Y = World.Player.Y }; PathNode end = new PathNode() { X = x, Y = y }; if (tries > 0) { using (PathBuilder builder = new PathBuilder(UseCachedPathList ? this.PossibleNodes : localList)) { if (builder.ComputePath(start, end, fromDistance)) { PathNodeList computedPath = new PathNodeList(); computedPath.AddRange(builder.ComputedPathNodes); computedPath.Reverse(); if (EnableLog) { Game.PrintMessage("TryGoTo Found: " + x + ", " + y + " / " + builder.Searchs); } int step = 0; foreach (PathNode node in computedPath) { step++; IUOPosition pos = this.CreatePositionInstance(node.X, node.Y, x); GotoStepArgs args = new GotoStepArgs(pos, tries, fromDistance); if (this.BeforeMove != null) { this.BeforeMove(this, args); } bool moveFail = false; if (args.Abort) { Game.PrintMessage("TryGoTo Abort " + destination); return(false); } if (args.IvalidDestination) { if (EnableLog) { Game.PrintMessage("Path IvalidDestination: " + this.ActualPosition.ToString() + " to " + node.ToString()); } moveFail = true; } else { if (!this.Move(GetMovementDirection(this.GetAngle(pos)))) { if (!this.Move(GetMovementDirection(this.GetAngle(pos)))) { moveFail = true; } } } if (moveFail) { if (EnableLog) { Game.PrintMessage("PathFail: " + this.ActualPosition.ToString() + " to " + node.ToString()); } PathNode findNode = builder.PossibleNodes.FindNode(node.X, node.Y); if (findNode != null && !findNode.Walkable.HasValue) { findNode.Walkable = false; } return(TryGoTo(x, y, fromDistance, --tries, localList)); } if (this.AfterMoveSuccess != null) { this.AfterMoveSuccess(this, new GotoStepArgs(pos, tries, fromDistance)); } if (args.Abort) { return(false); } } // 09:44 Phoenix: TryGoTo: 1380, 2706 - 459 //09:44 Phoenix: Compute Path FAIL: 1380,2707 to 1380,2706 //09:44 Phoenix: TryGoTo END: 1380, 2706 if (this.ActualPosition.Equals(destination) || Robot.GetRelativeVectorLength(this.ActualPosition, destination) <= fromDistance) { if (EnableLog) { Game.PrintMessage("TryGoTo OK - 2: " + x + ", " + y); } this.OnGoToSuccess(this, EventArgs.Empty); return(true); } else { return(TryGoTo(x, y, fromDistance, --tries, localList)); } } else { if (EnableLog) { Game.PrintMessage("Compute Path FAIL - Restart: " + start.ToString() + " to " + end.ToString()); } return(TryGoTo(x, y, fromDistance, --tries, null)); } } } if (EnableLog) { Game.PrintMessage("TryGoTo END: " + x + ", " + y); } return(false); }