Tons of AI + pathfinding bugfixes:

- waypoints are created between docked subs and removed when they undock
- fixed start waypoint being left out of steering paths
- NPCs won't close doors/hatches on themselves
- NPCs won't let go of ladders until their feet are above the lower edge of the hull
- fixed FindDivingGear "loops": need to find a suit -> need to get to a suit -> need a suit to get to the suit -> need to find a suit...
- fixed characters constantly turning from side to side in small rooms
- recursive function for finding the button which opens a door (so a button doesn't have to be connected straight to a door for an NPC to be able to open it)
- AIObjectiveGetItem keeps searching for more suitable items even if a path to a matching item has been found
This commit is contained in:
Regalis
2016-07-08 20:53:11 +03:00
parent c8dae18135
commit a5111d33df
17 changed files with 397 additions and 125 deletions
@@ -122,12 +122,22 @@ namespace Barotrauma
if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f;
Vector2 pos = host.SimPosition;
if (character != null && character.Submarine == null &&
CurrentPath.CurrentNode != null && CurrentPath.CurrentNode.Submarine != null)
if (character != null && currentPath.CurrentNode != null)
{
//todo: take multiple subs into account
pos -= CurrentPath.CurrentNode.Submarine.SimPosition;
}
if (CurrentPath.CurrentNode.Submarine != null)
{
if (character.Submarine == null)
{
pos -= CurrentPath.CurrentNode.Submarine.SimPosition;
}
else if (character.Submarine != currentPath.CurrentNode.Submarine)
{
pos -= FarseerPhysics.ConvertUnits.ToSimUnits(currentPath.CurrentNode.Submarine.Position-character.Submarine.Position);
}
}
}
if (currentPath.CurrentNode!= null && currentPath.CurrentNode.Ladders!=null)
{
@@ -135,17 +145,32 @@ namespace Barotrauma
{
currentPath.CurrentNode.Ladders.Item.Pick(character, false, true);
}
if (Math.Sign(host.Steering.Y) == currentPath.CurrentNode.SimPosition.Y - pos.Y)
{
allowedDistance = 0.0f;
}
}
currentPath.CheckProgress(pos, allowedDistance);
if (currentPath.CurrentNode == null) return Vector2.Zero;
var hull = character.AnimController.CurrentHull;
if (character.AnimController.Anim == AnimController.Animation.Climbing)
{
float x = currentPath.CurrentNode.SimPosition.X - pos.X;
float y = (currentPath.CurrentNode.SimPosition.Y) - pos.Y;
if (Math.Abs(x) < Math.Abs(y) * 10.0f)
{
x = 0.0f;
}
else if (character.AnimController.LowestLimb != null && hull != null)
{
if (character.AnimController.LowestLimb.Position.Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f;
}
character.AnimController.IgnorePlatforms = false;
return new Vector2(x,y);
}
return currentPath.CurrentNode.SimPosition - pos;
}
@@ -153,41 +178,67 @@ namespace Barotrauma
{
for (int i = 0; i < 2; i++)
{
WayPoint node = i == 0 ? currentPath.CurrentNode : currentPath.PrevNode;
if (node == null || node.ConnectedGap == null || node.ConnectedGap.ConnectedDoor == null) continue;
var door = node.ConnectedGap.ConnectedDoor;
bool open = currentPath.CurrentNode != null &&
Math.Sign(door.Item.SimPosition.X - host.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - host.SimPosition.X);
if (currentPath.CurrentNode==null)
WayPoint node = null;
WayPoint nextNode = null;
if (i==0)
{
open = false;
node = currentPath.CurrentNode;
nextNode = currentPath.NextNode;
}
else
{
if (door.LinkedGap.isHorizontal)
{
open = Math.Sign(door.Item.SimPosition.X - character.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - character.SimPosition.X);
}
else
{
open = Math.Sign(door.Item.SimPosition.Y - character.SimPosition.Y) == Math.Sign(currentPath.CurrentNode.SimPosition.Y - character.SimPosition.Y);
}
node = currentPath.PrevNode;
nextNode = currentPath.CurrentNode;
}
//toggle the door if it's the previous node and open, or if it's current node and closed
if (door.IsOpen != open)
if (node == null || node.ConnectedGap == null || node.ConnectedGap.ConnectedDoor == null) continue;
if (nextNode == null) continue;
var door = node.ConnectedGap.ConnectedDoor;
bool shouldBeOpen = false;
if (door.LinkedGap.isHorizontal)
{
var buttons = door.Item.GetConnectedComponents<Controller>();
int currentDir = Math.Sign(nextNode.WorldPosition.X - door.Item.WorldPosition.X);
shouldBeOpen = (door.Item.WorldPosition.X - character.WorldPosition.X) * currentDir > -50.0f;
}
else
{
int currentDir = Math.Sign(nextNode.WorldPosition.Y - door.Item.WorldPosition.Y);
shouldBeOpen = (door.Item.WorldPosition.Y - character.WorldPosition.Y) * currentDir > -80.0f;
}
//toggle the door if it's the previous node and open, or if it's current node and closed
if (door.IsOpen != shouldBeOpen)
{
var buttons = door.Item.GetConnectedComponents<Controller>(true);
Controller closestButton = null;
float closestDist = 0.0f;
foreach (Controller controller in buttons)
{
if (Vector2.Distance(controller.Item.Position, character.Position) > controller.Item.PickDistance * 2.0f) continue;
float dist = Vector2.Distance(controller.Item.WorldPosition, character.WorldPosition);
if (dist > controller.Item.PickDistance * 2.0f) continue;
controller.Item.Pick(character, false, true);
if (dist < closestDist || closestButton == null)
{
closestButton = controller;
closestDist = dist;
}
}
if (closestButton != null)
{
closestButton.Item.Pick(character, false, true);
break;
}
}