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:
@@ -37,7 +37,7 @@ namespace Barotrauma
|
||||
|
||||
if (currentHull != null)
|
||||
{
|
||||
if (currentHull.Volume / currentHull.FullVolume > 0.5f || character.Oxygen < 80.0f)
|
||||
if (NeedsDivingGear())
|
||||
{
|
||||
if (!FindDivingGear(deltaTime)) return;
|
||||
}
|
||||
@@ -131,6 +131,19 @@ namespace Barotrauma
|
||||
return (otherObjective is AIObjectiveFindSafety);
|
||||
}
|
||||
|
||||
private bool NeedsDivingGear()
|
||||
{
|
||||
var currentHull = character.AnimController.CurrentHull;
|
||||
if (currentHull == null) return true;
|
||||
|
||||
//there's lots of water in the room -> get a suit
|
||||
if (currentHull.Volume / currentHull.FullVolume > 0.5f) return true;
|
||||
|
||||
if (currentHull.OxygenPercentage < 30.0f) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override float GetPriority(Character character)
|
||||
{
|
||||
if (character.Oxygen < 80.0f)
|
||||
@@ -142,8 +155,12 @@ namespace Barotrauma
|
||||
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull, character);
|
||||
priority = 100.0f - currenthullSafety;
|
||||
|
||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
||||
|
||||
if (NeedsDivingGear())
|
||||
{
|
||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Barotrauma
|
||||
|
||||
public bool IgnoreContainedItems;
|
||||
|
||||
private AIObjectiveGoTo goToObjective;
|
||||
|
||||
private bool equip;
|
||||
|
||||
public override bool CanBeCompleted
|
||||
@@ -52,13 +54,8 @@ namespace Barotrauma
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
if (targetItem == null)
|
||||
{
|
||||
FindTargetItem();
|
||||
if (targetItem == null) return;
|
||||
}
|
||||
|
||||
if (moveToTarget == null) return;
|
||||
FindTargetItem();
|
||||
if (targetItem == null || moveToTarget == null) return;
|
||||
|
||||
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance*2.0f)
|
||||
{
|
||||
@@ -97,9 +94,15 @@ namespace Barotrauma
|
||||
character.Inventory.TryPutItem(targetItem, targetSlot, true, false);
|
||||
}
|
||||
}
|
||||
else if (!subObjectives.Any())
|
||||
else
|
||||
{
|
||||
AddGoToObjective(targetItem);
|
||||
if (goToObjective == null)
|
||||
{
|
||||
bool gettingDivingGear = itemName == "diving" || itemName == "Diving Gear";
|
||||
goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear);
|
||||
}
|
||||
|
||||
goToObjective.TryComplete(deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -111,7 +114,7 @@ namespace Barotrauma
|
||||
{
|
||||
float currDist = moveToTarget == null ? 0.0f : Vector2.DistanceSquared(moveToTarget.Position, character.Position);
|
||||
|
||||
for (int i = 0; i < 5 && currSearchIndex < Item.ItemList.Count - 2; i++)
|
||||
for (int i = 0; i < 10 && currSearchIndex < Item.ItemList.Count - 2; i++)
|
||||
{
|
||||
currSearchIndex++;
|
||||
|
||||
@@ -136,22 +139,12 @@ namespace Barotrauma
|
||||
|
||||
targetItem = item;
|
||||
moveToTarget = rootContainer ?? item;
|
||||
|
||||
AddGoToObjective(moveToTarget);
|
||||
|
||||
}
|
||||
|
||||
//if searched through all the items and a target wasn't found, can't be completed
|
||||
if (currSearchIndex >= Item.ItemList.Count && targetItem == null) canBeCompleted = false;
|
||||
}
|
||||
|
||||
private void AddGoToObjective(Item gotoToTarget)
|
||||
{
|
||||
subObjectives.Clear();
|
||||
AddSubObjective(new AIObjectiveGoTo(gotoToTarget, character));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Barotrauma
|
||||
//how long until the path to the target is declared unreachable
|
||||
private float waitUntilPathUnreachable;
|
||||
|
||||
private bool getDivingGearIfNeeded;
|
||||
|
||||
public override bool CanBeCompleted
|
||||
{
|
||||
get
|
||||
@@ -35,23 +37,25 @@ namespace Barotrauma
|
||||
get { return target; }
|
||||
}
|
||||
|
||||
public AIObjectiveGoTo(Entity target, Character character, bool repeat = false)
|
||||
public AIObjectiveGoTo(Entity target, Character character, bool repeat = false, bool getDivingGearIfNeeded = true)
|
||||
: base (character, "")
|
||||
{
|
||||
this.target = target;
|
||||
this.repeat = repeat;
|
||||
|
||||
waitUntilPathUnreachable = 5.0f;
|
||||
this.getDivingGearIfNeeded = getDivingGearIfNeeded;
|
||||
}
|
||||
|
||||
|
||||
public AIObjectiveGoTo(Vector2 simPos, Character character, bool repeat = false)
|
||||
public AIObjectiveGoTo(Vector2 simPos, Character character, bool repeat = false, bool getDivingGearIfNeeded = true)
|
||||
: base(character, "")
|
||||
{
|
||||
this.targetPos = simPos;
|
||||
this.repeat = repeat;
|
||||
|
||||
waitUntilPathUnreachable = 5.0f;
|
||||
this.getDivingGearIfNeeded = getDivingGearIfNeeded;
|
||||
}
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
@@ -108,7 +112,7 @@ namespace Barotrauma
|
||||
{
|
||||
indoorsSteering.SteeringWander();
|
||||
}
|
||||
else if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||
else if (getDivingGearIfNeeded && indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||
{
|
||||
AddSubObjective(new AIObjectiveFindDivingGear(character, true));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -11,8 +12,6 @@ namespace Barotrauma
|
||||
AITarget currentTarget;
|
||||
private float newTargetTimer;
|
||||
|
||||
|
||||
|
||||
public AIObjectiveIdle(Character character) : base(character, "")
|
||||
{
|
||||
|
||||
@@ -23,7 +22,6 @@ namespace Barotrauma
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
||||
protected override void Act(float deltaTime)
|
||||
{
|
||||
|
||||
@@ -53,7 +51,8 @@ namespace Barotrauma
|
||||
newTargetTimer = currentTarget == null ? 5.0f : 15.0f;
|
||||
}
|
||||
|
||||
newTargetTimer -= deltaTime;
|
||||
newTargetTimer -= deltaTime;
|
||||
|
||||
|
||||
//wander randomly if reached the end of the path or the target is unreachable
|
||||
if (pathSteering==null || (pathSteering.CurrentPath != null &&
|
||||
@@ -62,13 +61,28 @@ namespace Barotrauma
|
||||
//steer away from edges of the hull
|
||||
if (character.AnimController.CurrentHull!=null)
|
||||
{
|
||||
if (character.Position.X < character.AnimController.CurrentHull.Rect.X + WallAvoidDistance)
|
||||
float leftDist = character.Position.X - character.AnimController.CurrentHull.Rect.X;
|
||||
float rightDist = character.AnimController.CurrentHull.Rect.Right - character.Position.X;
|
||||
|
||||
if (leftDist < WallAvoidDistance && rightDist < WallAvoidDistance)
|
||||
{
|
||||
pathSteering.SteeringManual(deltaTime, Vector2.UnitX*5.0f);
|
||||
if (Math.Abs(rightDist - leftDist) > WallAvoidDistance / 2)
|
||||
{
|
||||
pathSteering.SteeringManual(deltaTime, Vector2.UnitX * Math.Sign(rightDist - leftDist));
|
||||
}
|
||||
else
|
||||
{
|
||||
pathSteering.Reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (character.Position.X > character.AnimController.CurrentHull.Rect.Right - WallAvoidDistance)
|
||||
else if (leftDist < WallAvoidDistance)
|
||||
{
|
||||
pathSteering.SteeringManual(deltaTime, -Vector2.UnitX);
|
||||
pathSteering.SteeringManual(deltaTime, Vector2.UnitX * (WallAvoidDistance-leftDist)/WallAvoidDistance);
|
||||
}
|
||||
else if (rightDist < WallAvoidDistance)
|
||||
{
|
||||
pathSteering.SteeringManual(deltaTime, -Vector2.UnitX * (WallAvoidDistance-rightDist)/WallAvoidDistance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +99,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (currentTarget == null) return;
|
||||
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
|
||||
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition, 2.0f);
|
||||
}
|
||||
|
||||
private AITarget FindRandomTarget()
|
||||
|
||||
Reference in New Issue
Block a user