(c5e44ed94) Take access into account before accepting a path. Fixes bots trying to reach places where they have no access to (#1351).

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:26:09 +03:00
parent 812598774e
commit 268389a128
13 changed files with 190 additions and 848 deletions
@@ -51,10 +51,9 @@ namespace Barotrauma
return otherExtinguishFire != null && otherExtinguishFire.targetHull == targetHull;
}
public override bool CanBeCompleted
{
get { return getExtinguisherObjective == null || getExtinguisherObjective.IsCompleted() || getExtinguisherObjective.CanBeCompleted; }
}
public override bool CanBeCompleted =>
(getExtinguisherObjective == null || getExtinguisherObjective.IsCompleted() || getExtinguisherObjective.CanBeCompleted) &&
(gotoObjective == null || gotoObjective.IsCompleted() || gotoObjective.CanBeCompleted);
protected override void Act(float deltaTime)
{
@@ -204,6 +204,7 @@ namespace Barotrauma
unreachable.Add(hull);
continue;
}
if (!PathSteering.HasAccessToPath(path)) { continue; }
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
hullSafety /= 1 + unsafeNodes;
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
@@ -161,31 +161,34 @@ namespace Barotrauma
else
{
bool isInside = character.CurrentHull != null;
bool insideSteering = SteeringManager == PathSteering && PathSteering.CurrentPath != null;
bool insideSteering = SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.IsPathDirty;
bool targetIsOutside = (Target != null && Target.Submarine == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes);
if (isInside && targetIsOutside && !AllowGoingOutside)
{
cannotReach = true;
return;
}
else
if (insideSteering && !PathSteering.HasAccessToPath(PathSteering.CurrentPath))
{
character.AIController.SteeringManager.SteeringSeek(currTargetPos);
if (getDivingGearIfNeeded)
cannotReach = true;
return;
}
character.AIController.SteeringManager.SteeringSeek(currTargetPos);
if (getDivingGearIfNeeded)
{
if (targetIsOutside ||
Target is Hull h && HumanAIController.NeedsDivingGear(h) ||
Target is Item i && HumanAIController.NeedsDivingGear(i.CurrentHull) ||
Target is Character c && HumanAIController.NeedsDivingGear(c.CurrentHull))
{
if (targetIsOutside ||
Target is Hull h && HumanAIController.NeedsDivingGear(h) ||
Target is Item i && HumanAIController.NeedsDivingGear(i.CurrentHull) ||
Target is Character c && HumanAIController.NeedsDivingGear(c.CurrentHull))
if (findDivingGear == null)
{
if (findDivingGear == null)
{
findDivingGear = new AIObjectiveFindDivingGear(character, true, objectiveManager);
AddSubObjective(findDivingGear);
}
else if (!findDivingGear.CanBeCompleted)
{
abandon = true;
}
findDivingGear = new AIObjectiveFindDivingGear(character, true, objectiveManager);
AddSubObjective(findDivingGear);
}
else if (!findDivingGear.CanBeCompleted)
{
abandon = true;
}
}
}
@@ -111,8 +111,10 @@ namespace Barotrauma
// Check that there is no unsafe or forbidden hulls on the way to the target
// Only do this when the current hull is ok, because otherwise would block all paths from the current hull to the target hull.
var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
if (path.Unreachable ||
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
if (path.Unreachable ||
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) ||
IsForbidden(n.CurrentHull)) ||
!PathSteering.HasAccessToPath(path))
{
//can't go to this room, remove it from the list and try another room next frame
int index = targetHulls.IndexOf(randomHull);