From a3f49e0bc52d83a42c2de0ff8a33b197954df95c Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 11 Jan 2018 16:03:16 +0200 Subject: [PATCH] Pathfinding fixes: - The parent fields of the nodes are cleared before finding a path. Should fix the "constructing final path failed" errors. - Nodes that have been marked as unreachable because of GetNodePenalty can still be used if another path to the node is found. --- .../Source/Characters/AI/PathFinder.cs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs index f01d1b89c..cc4bcbd0a 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs @@ -275,6 +275,7 @@ namespace Barotrauma foreach (PathNode node in nodes) { + node.Parent = null; node.state = 0; node.F = 0.0f; node.G = 0.0f; @@ -306,30 +307,39 @@ namespace Barotrauma PathNode nextNode = currNode.connections[i]; //a node that hasn't been searched yet - if (nextNode.state==0) + if (nextNode.state == 0) { - nextNode.H = Vector2.Distance(nextNode.Position,end.Position); + nextNode.H = Vector2.Distance(nextNode.Position, end.Position); + float penalty = 0.0f; if (GetNodePenalty != null) { - float? nodePenalty =GetNodePenalty(currNode, nextNode); + float? nodePenalty = GetNodePenalty(currNode, nextNode); if (nodePenalty == null) { nextNode.state = -1; continue; } - nextNode.H += (float)nodePenalty; + penalty = nodePenalty.Value; } - nextNode.G = currNode.G + currNode.distances[i]; + nextNode.G = currNode.G + currNode.distances[i] + penalty; nextNode.F = nextNode.G + nextNode.H; nextNode.Parent = currNode; nextNode.state = 1; } //node that has been searched - else if (nextNode.state==1) + else if (nextNode.state == 1 || nextNode.state == -1) { float tempG = currNode.G + currNode.distances[i]; + + if (GetNodePenalty != null) + { + float? nodePenalty = GetNodePenalty(currNode, nextNode); + if (nodePenalty == null) continue; + tempG += nodePenalty.Value; + } + //only use if this new route is better than the //route the node was a part of if (tempG < nextNode.G) @@ -337,6 +347,7 @@ namespace Barotrauma nextNode.G = tempG; nextNode.F = nextNode.G + nextNode.H; nextNode.Parent = currNode; + nextNode.state = 1; } } } @@ -356,8 +367,10 @@ namespace Barotrauma { finalPath.Add(pathNode.Waypoint); - //there was one bug report that seems to have been caused by this loop never terminating: - //couldn't reproduce or figure out what caused it, but here's a workaround that prevents the game from crashing in case it happens again + //(there was one bug report that seems to have been caused by this loop never terminating: + //couldn't reproduce or figure out what caused it, but here's a workaround that prevents the game from crashing in case it happens again) + + //should be fixed now, was most likely caused by the parent fields of the nodes not being cleared before starting the pathfinding if (finalPath.Count > nodes.Count) { DebugConsole.ThrowError("Pathfinding error: constructing final path failed");