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.
This commit is contained in:
Joonas Rikkonen
2018-01-11 16:03:16 +02:00
parent e2c7b684de
commit a3f49e0bc5
@@ -275,6 +275,7 @@ namespace Barotrauma
foreach (PathNode node in nodes) foreach (PathNode node in nodes)
{ {
node.Parent = null;
node.state = 0; node.state = 0;
node.F = 0.0f; node.F = 0.0f;
node.G = 0.0f; node.G = 0.0f;
@@ -306,30 +307,39 @@ namespace Barotrauma
PathNode nextNode = currNode.connections[i]; PathNode nextNode = currNode.connections[i];
//a node that hasn't been searched yet //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) if (GetNodePenalty != null)
{ {
float? nodePenalty =GetNodePenalty(currNode, nextNode); float? nodePenalty = GetNodePenalty(currNode, nextNode);
if (nodePenalty == null) if (nodePenalty == null)
{ {
nextNode.state = -1; nextNode.state = -1;
continue; 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.F = nextNode.G + nextNode.H;
nextNode.Parent = currNode; nextNode.Parent = currNode;
nextNode.state = 1; nextNode.state = 1;
} }
//node that has been searched //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]; 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 //only use if this new route is better than the
//route the node was a part of //route the node was a part of
if (tempG < nextNode.G) if (tempG < nextNode.G)
@@ -337,6 +347,7 @@ namespace Barotrauma
nextNode.G = tempG; nextNode.G = tempG;
nextNode.F = nextNode.G + nextNode.H; nextNode.F = nextNode.G + nextNode.H;
nextNode.Parent = currNode; nextNode.Parent = currNode;
nextNode.state = 1;
} }
} }
} }
@@ -356,8 +367,10 @@ namespace Barotrauma
{ {
finalPath.Add(pathNode.Waypoint); finalPath.Add(pathNode.Waypoint);
//there was one bug report that seems to have been caused by this loop never terminating: //(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 //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) if (finalPath.Count > nodes.Count)
{ {
DebugConsole.ThrowError("Pathfinding error: constructing final path failed"); DebugConsole.ThrowError("Pathfinding error: constructing final path failed");