Bunch of crew AI bugfixes/improvements:
- replacing empty oxygen tanks - fixed characters only fixing leaks in the outer hull - prioritizing large leaks over small ones - fixed characters doing nothing after fixing all the leaks (and sinking to the bottom if they happen to be outside) - more accurate welder aiming - AIObjectiveGetItem makes the characters go to the cabinet/container an item is inside, not to the actual item (which may not be actually positioned at the container)
This commit is contained in:
@@ -45,16 +45,22 @@ namespace Barotrauma
|
|||||||
if (containedItems == null) return;
|
if (containedItems == null) return;
|
||||||
|
|
||||||
//check if there's an oxygen tank in the mask
|
//check if there's an oxygen tank in the mask
|
||||||
var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f);
|
var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank");
|
||||||
|
|
||||||
if (oxygenTank != null)
|
if (oxygenTank != null)
|
||||||
{
|
{
|
||||||
//isCompleted = true;
|
if (oxygenTank.Condition > 0.0f)
|
||||||
return;
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oxygenTank.Drop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!(subObjective is AIObjectiveContainItem))
|
if (!(subObjective is AIObjectiveContainItem) || subObjective.IsCompleted())
|
||||||
{
|
{
|
||||||
subObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent<ItemContainer>());
|
subObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent<ItemContainer>());
|
||||||
}
|
}
|
||||||
@@ -68,6 +74,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override float GetPriority(Character character)
|
||||||
|
{
|
||||||
|
if (character.AnimController.CurrentHull == null) return 100.0f;
|
||||||
|
|
||||||
|
return 100.0f - character.Oxygen;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsDuplicate(AIObjective otherObjective)
|
public override bool IsDuplicate(AIObjective otherObjective)
|
||||||
{
|
{
|
||||||
return otherObjective is AIObjectiveFindDivingGear;
|
return otherObjective is AIObjectiveFindDivingGear;
|
||||||
|
|||||||
@@ -29,68 +29,41 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
if (character.AnimController.CurrentHull == null) return;
|
|
||||||
|
|
||||||
currenthullSafety = OverrideCurrentHullSafety == null ?
|
|
||||||
GetHullSafety(character.AnimController.CurrentHull) : (float)OverrideCurrentHullSafety;
|
|
||||||
|
|
||||||
if (character.AnimController.CurrentHull == null || currenthullSafety > MinSafety)
|
|
||||||
{
|
|
||||||
character.AIController.SteeringManager.SteeringSeek(character.AnimController.CurrentHull.SimPosition);
|
|
||||||
character.AIController.SelectTarget(null);
|
|
||||||
|
|
||||||
goToObjective = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentHull = character.AnimController.CurrentHull;
|
var currentHull = character.AnimController.CurrentHull;
|
||||||
if (currentHull.Volume / currentHull.FullVolume > 0.5f)
|
|
||||||
|
currenthullSafety = OverrideCurrentHullSafety == null ?
|
||||||
|
GetHullSafety(currentHull) : (float)OverrideCurrentHullSafety;
|
||||||
|
|
||||||
|
if (currentHull != null)
|
||||||
{
|
{
|
||||||
if (!FindDivingGear(deltaTime)) return;
|
if (currentHull.Volume / currentHull.FullVolume > 0.5f || character.Oxygen < 80.0f)
|
||||||
|
{
|
||||||
|
if (!FindDivingGear(deltaTime)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currenthullSafety > MinSafety)
|
||||||
|
{
|
||||||
|
character.AIController.SteeringManager.SteeringSeek(currentHull.SimPosition, 0.5f);
|
||||||
|
character.AIController.SelectTarget(null);
|
||||||
|
|
||||||
|
goToObjective = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchHullTimer>0.0f)
|
if (searchHullTimer > 0.0f)
|
||||||
{
|
{
|
||||||
searchHullTimer -= deltaTime;
|
searchHullTimer -= deltaTime;
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Hull bestHull = null;
|
var bestHull = FindBestHull();
|
||||||
float bestValue = currenthullSafety;
|
|
||||||
|
|
||||||
foreach (Hull hull in Hull.hullList)
|
|
||||||
{
|
|
||||||
if (hull == character.AnimController.CurrentHull) continue;
|
|
||||||
if (unreachable.Contains(hull)) continue;
|
|
||||||
|
|
||||||
float hullValue = GetHullSafety(hull);
|
|
||||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X- hull.Position.X));
|
|
||||||
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.Y - hull.Position.Y)*2.0f);
|
|
||||||
|
|
||||||
if (bestHull == null || hullValue > bestValue)
|
|
||||||
{
|
|
||||||
bestHull = hull;
|
|
||||||
bestValue = hullValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestHull != null)
|
if (bestHull != null)
|
||||||
{
|
{
|
||||||
//var path = pathSteering.PathFinder.FindPath(character.SimPosition, bestHull.SimPosition);
|
goToObjective = new AIObjectiveGoTo(bestHull, character);
|
||||||
//if (pathSteering.CurrentPath == null || (pathSteering.CurrentPath.NextNode==null && pathSteering.CurrentPath.Cost > path.Cost) ||
|
|
||||||
// pathSteering.CurrentPath.Unreachable || goToObjective==null)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//pathSteering.SetPath(path);
|
|
||||||
goToObjective = new AIObjectiveGoTo(bestHull, character);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//haracter.AIController.SelectTarget(bestHull.AiTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
searchHullTimer = SearchHullInterval;
|
searchHullTimer = SearchHullInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,43 +90,29 @@ namespace Barotrauma
|
|||||||
|
|
||||||
divingGearObjective.TryComplete(deltaTime);
|
divingGearObjective.TryComplete(deltaTime);
|
||||||
return divingGearObjective.IsCompleted();
|
return divingGearObjective.IsCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
//var item = character.Inventory.FindItem("diving");
|
private Hull FindBestHull()
|
||||||
//if (item == null)
|
{
|
||||||
//{
|
Hull bestHull = null;
|
||||||
// //get a diving mask/suit first
|
float bestValue = currenthullSafety;
|
||||||
// if (!(divingGearObjective is AIObjectiveGetItem))
|
|
||||||
// {
|
|
||||||
// divingGearObjective = new AIObjectiveGetItem(character, "diving", true);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// var containedItems = item.ContainedItems;
|
|
||||||
// if (containedItems == null) return true;
|
|
||||||
|
|
||||||
// //check if there's an oxygen tank in the mask
|
foreach (Hull hull in Hull.hullList)
|
||||||
// var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f);
|
{
|
||||||
|
if (hull == character.AnimController.CurrentHull || unreachable.Contains(hull)) continue;
|
||||||
|
|
||||||
// if (oxygenTank != null) return true;
|
float hullValue = GetHullSafety(hull);
|
||||||
|
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X - hull.Position.X));
|
||||||
|
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.Y - hull.Position.Y) * 2.0f);
|
||||||
|
|
||||||
|
if (bestHull == null || hullValue > bestValue)
|
||||||
|
{
|
||||||
|
bestHull = hull;
|
||||||
|
bestValue = hullValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if (!(divingGearObjective is AIObjectiveContainItem))
|
return bestHull;
|
||||||
// {
|
|
||||||
// divingGearObjective = new AIObjectiveContainItem(character, "Oxygen Tank", item.GetComponent<ItemContainer>());
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if (divingGearObjective != null)
|
|
||||||
//{
|
|
||||||
// divingGearObjective.TryComplete(deltaTime);
|
|
||||||
|
|
||||||
// bool isCompleted = divingGearObjective.IsCompleted();
|
|
||||||
// if (isCompleted) divingGearObjective = null;
|
|
||||||
// return isCompleted;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsDuplicate(AIObjective otherObjective)
|
public override bool IsDuplicate(AIObjective otherObjective)
|
||||||
@@ -163,11 +122,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public override float GetPriority(Character character)
|
public override float GetPriority(Character character)
|
||||||
{
|
{
|
||||||
if (character.AnimController.CurrentHull == null) return 0.0f;
|
if (character.Oxygen < 80.0f)
|
||||||
|
{
|
||||||
|
return 150.0f - character.Oxygen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character.AnimController.CurrentHull == null) return 5.0f;
|
||||||
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull);
|
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull);
|
||||||
priority = 100.0f - currenthullSafety;
|
priority = 100.0f - currenthullSafety;
|
||||||
|
|
||||||
|
|
||||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
||||||
|
|
||||||
return priority;
|
return priority;
|
||||||
@@ -175,6 +138,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float GetHullSafety(Hull hull)
|
private float GetHullSafety(Hull hull)
|
||||||
{
|
{
|
||||||
|
if (hull == null) return 0.0f;
|
||||||
|
|
||||||
float waterPercentage = (hull.Volume / hull.FullVolume)*100.0f;
|
float waterPercentage = (hull.Volume / hull.FullVolume)*100.0f;
|
||||||
float fireAmount = 0.0f;
|
float fireAmount = 0.0f;
|
||||||
|
|
||||||
@@ -185,7 +150,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
float safety = 100.0f - fireAmount;
|
float safety = 100.0f - fireAmount;
|
||||||
|
|
||||||
if (waterPercentage > 30.0f && character.Oxygen<80.0f) safety -= waterPercentage;
|
if (waterPercentage > 30.0f && character.OxygenAvailable<=0.0f) safety -= waterPercentage;
|
||||||
if (hull.OxygenPercentage < 30.0f) safety -= (30.0f-hull.OxygenPercentage)*5.0f;
|
if (hull.OxygenPercentage < 30.0f) safety -= (30.0f-hull.OxygenPercentage)*5.0f;
|
||||||
|
|
||||||
return safety;
|
return safety;
|
||||||
|
|||||||
@@ -63,14 +63,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vector2.Distance(character.Position, leak.Position) > 300.0f)
|
var repairTool = weldingTool.GetComponent<RepairTool>();
|
||||||
|
if (repairTool == null) return;
|
||||||
|
|
||||||
|
if (Vector2.Distance(character.WorldPosition, leak.WorldPosition) > 300.0f)
|
||||||
{
|
{
|
||||||
AddSubObjective(new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character));
|
AddSubObjective(new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var repairTool = weldingTool.GetComponent<RepairTool>();
|
|
||||||
if (repairTool == null) return;
|
|
||||||
AddSubObjective(new AIObjectiveOperateItem(repairTool, character, "", leak));
|
AddSubObjective(new AIObjectiveOperateItem(repairTool, character, "", leak));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -10,6 +11,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float updateGapListTimer;
|
private float updateGapListTimer;
|
||||||
|
|
||||||
|
private AIObjectiveIdle idleObjective;
|
||||||
|
|
||||||
private List<AIObjectiveFixLeak> objectiveList;
|
private List<AIObjectiveFixLeak> objectiveList;
|
||||||
|
|
||||||
public AIObjectiveFixLeaks(Character character)
|
public AIObjectiveFixLeaks(Character character)
|
||||||
@@ -36,13 +39,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (objectiveList.Any())
|
if (objectiveList.Any())
|
||||||
{
|
{
|
||||||
objectiveList[objectiveList.Count-1].TryComplete(deltaTime);
|
objectiveList[objectiveList.Count - 1].TryComplete(deltaTime);
|
||||||
|
|
||||||
if (!objectiveList[objectiveList.Count-1].CanBeCompleted || objectiveList[objectiveList.Count-1].IsCompleted())
|
if (!objectiveList[objectiveList.Count - 1].CanBeCompleted ||
|
||||||
|
objectiveList[objectiveList.Count - 1].IsCompleted())
|
||||||
{
|
{
|
||||||
objectiveList.RemoveAt(objectiveList.Count - 1);
|
objectiveList.RemoveAt(objectiveList.Count - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (idleObjective == null) idleObjective = new AIObjectiveIdle(character);
|
||||||
|
idleObjective.TryComplete(deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateGapList()
|
private void UpdateGapList()
|
||||||
@@ -51,13 +60,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
foreach (Gap gap in Gap.GapList)
|
foreach (Gap gap in Gap.GapList)
|
||||||
{
|
{
|
||||||
if (gap.IsRoomToRoom || gap.ConnectedDoor != null || gap.Open < 0.1f) continue;
|
if (gap.ConnectedWall == null) continue;
|
||||||
|
if (gap.ConnectedDoor != null || gap.Open <= 0.0f) continue;
|
||||||
|
|
||||||
float dist = Vector2.DistanceSquared(character.WorldPosition, gap.WorldPosition);
|
float gapPriority = GetGapFixPriority(gap);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index<objectiveList.Count &&
|
while (index < objectiveList.Count &&
|
||||||
Vector2.DistanceSquared(objectiveList[index].Leak.WorldPosition, character.WorldPosition)>dist)
|
GetGapFixPriority(objectiveList[index].Leak) < gapPriority)
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -66,6 +76,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float GetGapFixPriority(Gap gap)
|
||||||
|
{
|
||||||
|
if (gap == null) return 0.0f;
|
||||||
|
|
||||||
|
//larger gap -> higher priority
|
||||||
|
float gapPriority = (gap.isHorizontal ? gap.Rect.Width : gap.Rect.Height) * gap.Open;
|
||||||
|
|
||||||
|
//prioritize gaps that are close
|
||||||
|
gapPriority /= Math.Max(Vector2.Distance(character.WorldPosition, gap.WorldPosition), 1.0f);
|
||||||
|
|
||||||
|
//gaps to outside are much higher priority
|
||||||
|
if (!gap.IsRoomToRoom) gapPriority *= 10.0f;
|
||||||
|
|
||||||
|
return gapPriority;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsDuplicate(AIObjective otherObjective)
|
public override bool IsDuplicate(AIObjective otherObjective)
|
||||||
{
|
{
|
||||||
return otherObjective is AIObjectiveFixLeaks;
|
return otherObjective is AIObjectiveFixLeaks;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
private string itemName;
|
private string itemName;
|
||||||
|
|
||||||
private Item targetItem;
|
private Item targetItem, moveToTarget;
|
||||||
|
|
||||||
private int currSearchIndex;
|
private int currSearchIndex;
|
||||||
|
|
||||||
@@ -52,83 +52,96 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
if (targetItem != null)
|
if (targetItem == null)
|
||||||
{
|
{
|
||||||
if (Vector2.Distance(character.Position, targetItem.Position) < targetItem.PickDistance)
|
FindTargetItem();
|
||||||
|
if (targetItem == null) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance*2.0f)
|
||||||
|
{
|
||||||
|
int targetSlot = -1;
|
||||||
|
if (equip)
|
||||||
{
|
{
|
||||||
int targetSlot = -1;
|
var pickable = targetItem.GetComponent<Pickable>();
|
||||||
if (equip)
|
//check if all the slots required by the item are free
|
||||||
|
foreach (LimbSlot slots in pickable.AllowedSlots)
|
||||||
{
|
{
|
||||||
var pickable = targetItem.GetComponent<Pickable>();
|
if (slots.HasFlag(LimbSlot.Any)) continue;
|
||||||
//check if all the slots required by the item are free
|
|
||||||
foreach (LimbSlot slots in pickable.AllowedSlots)
|
|
||||||
{
|
|
||||||
if (slots.HasFlag(LimbSlot.Any)) continue;
|
|
||||||
|
|
||||||
for (int i = 0; i<character.Inventory.Items.Length; i++)
|
for (int i = 0; i<character.Inventory.Items.Length; i++)
|
||||||
{
|
{
|
||||||
//slot not needed by the item, continue
|
//slot not needed by the item, continue
|
||||||
if (!slots.HasFlag(CharacterInventory.limbSlots[i])) continue;
|
if (!slots.HasFlag(CharacterInventory.limbSlots[i])) continue;
|
||||||
|
|
||||||
targetSlot = i;
|
targetSlot = i;
|
||||||
|
|
||||||
//slot free, continue
|
//slot free, continue
|
||||||
if (character.Inventory.Items[i] == null) continue;
|
if (character.Inventory.Items[i] == null) continue;
|
||||||
|
|
||||||
//try to move the existing item to LimbSlot.Any and continue if successful
|
//try to move the existing item to LimbSlot.Any and continue if successful
|
||||||
if (character.Inventory.TryPutItem(character.Inventory.Items[i], new List<LimbSlot>() { LimbSlot.Any }, false)) continue;
|
if (character.Inventory.TryPutItem(character.Inventory.Items[i], new List<LimbSlot>() { LimbSlot.Any }, false)) continue;
|
||||||
|
|
||||||
//if everything else fails, simply drop the existing item
|
//if everything else fails, simply drop the existing item
|
||||||
character.Inventory.Items[i].Drop();
|
character.Inventory.Items[i].Drop();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
targetItem.Pick(character, false, true);
|
|
||||||
|
|
||||||
if (targetSlot>-1 && character.Inventory.IsInLimbSlot(targetItem, LimbSlot.Any))
|
|
||||||
{
|
|
||||||
character.Inventory.TryPutItem(targetItem, targetSlot, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
targetItem.Pick(character, false, true);
|
||||||
|
|
||||||
|
if (targetSlot > -1 && character.Inventory.IsInLimbSlot(targetItem, LimbSlot.Any))
|
||||||
|
{
|
||||||
|
character.Inventory.TryPutItem(targetItem, targetSlot, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!subObjectives.Any())
|
||||||
|
{
|
||||||
|
AddGoToObjective(targetItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i<10 && currSearchIndex<Item.ItemList.Count-2; i++)
|
/// <summary>
|
||||||
|
/// searches for an item that matches the desired item and adds a goto subobjective if one is found
|
||||||
|
/// </summary>
|
||||||
|
private void FindTargetItem()
|
||||||
|
{
|
||||||
|
float currDist = moveToTarget == null ? 0.0f : Vector2.DistanceSquared(moveToTarget.Position, character.Position);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5 && currSearchIndex < Item.ItemList.Count - 2; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
currSearchIndex++;
|
currSearchIndex++;
|
||||||
|
|
||||||
//don't try to get items from outside the sub
|
var item = Item.ItemList[currSearchIndex];
|
||||||
if (Item.ItemList[currSearchIndex].CurrentHull == null) continue;
|
|
||||||
|
|
||||||
if (!Item.ItemList[currSearchIndex].HasTag(itemName) && Item.ItemList[currSearchIndex].Name != itemName) continue;
|
if (item.CurrentHull == null || item.Condition <= 0.0f) continue;
|
||||||
if (IgnoreContainedItems && Item.ItemList[currSearchIndex].Container != null) continue;
|
if (IgnoreContainedItems && item.Container != null) continue;
|
||||||
if (Item.ItemList[currSearchIndex].ParentInventory is CharacterInventory) continue;
|
if (item.Name != itemName && !item.HasTag(itemName)) continue;
|
||||||
|
if (item.ParentInventory is CharacterInventory) continue;
|
||||||
|
|
||||||
|
//ignore if item is further away than the currently targeted item
|
||||||
|
Item rootContainer = item.GetRootContainer();
|
||||||
|
if (moveToTarget != null && Vector2.DistanceSquared((rootContainer ?? item).Position, character.Position) > currDist) continue;
|
||||||
|
|
||||||
targetItem = Item.ItemList[currSearchIndex];
|
targetItem = item;
|
||||||
|
moveToTarget = rootContainer ?? item;
|
||||||
|
|
||||||
AddGoToObjective(targetItem);
|
AddGoToObjective(moveToTarget);
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currSearchIndex >= Item.ItemList.Count) canBeCompleted = false;
|
//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 item)
|
private void AddGoToObjective(Item gotoToTarget)
|
||||||
{
|
{
|
||||||
Item moveToTarget = item;
|
subObjectives.Clear();
|
||||||
while (moveToTarget.Container != null)
|
AddSubObjective(new AIObjectiveGoTo(gotoToTarget, character));
|
||||||
{
|
|
||||||
moveToTarget = moveToTarget.Container;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddSubObjective(new AIObjectiveGoTo(moveToTarget, character));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override bool IsDuplicate(AIObjective otherObjective)
|
public override bool IsDuplicate(AIObjective otherObjective)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -104,10 +104,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var indoorsSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
var indoorsSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||||
|
|
||||||
if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
if (indoorsSteering.CurrentPath.Unreachable)
|
||||||
{
|
{
|
||||||
|
indoorsSteering.SteeringWander();
|
||||||
AddSubObjective(new AIObjectiveGetItem(character, "Diving Suit", true));
|
}
|
||||||
|
else if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||||
|
{
|
||||||
|
AddSubObjective(new AIObjectiveFindDivingGear(character, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (currentTarget != null)
|
if (currentTarget != null)
|
||||||
{
|
{
|
||||||
var path = pathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition);
|
Vector2 pos = character.SimPosition;
|
||||||
if (path.Cost > 200.0f) return;
|
if (character != null && character.Submarine == null) pos -= Submarine.Loaded.SimPosition;
|
||||||
|
|
||||||
|
var path = pathSteering.PathFinder.FindPath(pos, currentTarget.SimPosition);
|
||||||
|
if (path.Cost > 200.0f && character.AnimController.CurrentHull!=null) return;
|
||||||
|
|
||||||
pathSteering.SetPath(path);
|
pathSteering.SetPath(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ namespace Barotrauma
|
|||||||
if (dist<closestDist || startNode==null)
|
if (dist<closestDist || startNode==null)
|
||||||
{
|
{
|
||||||
//if searching for a path inside the sub, make sure the waypoint is visible
|
//if searching for a path inside the sub, make sure the waypoint is visible
|
||||||
if (insideSubmarine && node.Waypoint.CurrentHull != null && Submarine.CheckVisibility(start, node.Waypoint.SimPosition) != null) continue;
|
if (insideSubmarine && Submarine.CheckVisibility(start, node.Waypoint.SimPosition) != null) continue;
|
||||||
|
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
startNode = node;
|
startNode = node;
|
||||||
@@ -160,7 +160,7 @@ namespace Barotrauma
|
|||||||
var path = FindPath(startNode,endNode);
|
var path = FindPath(startNode,endNode);
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
System.Diagnostics.Debug.WriteLine("findpath: " + sw.ElapsedTicks);
|
System.Diagnostics.Debug.WriteLine("findpath: " + sw.ElapsedMilliseconds+" ms");
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ namespace Barotrauma
|
|||||||
keyboardDispatcher = new KeyboardDispatcher(window);
|
keyboardDispatcher = new KeyboardDispatcher(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetChild<T>()
|
public T GetChild<T>() where T : GUIComponent
|
||||||
{
|
{
|
||||||
foreach (GUIComponent child in children)
|
foreach (GUIComponent child in children)
|
||||||
{
|
{
|
||||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return default(T);
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIComponent GetChild(object obj)
|
public GUIComponent GetChild(object obj)
|
||||||
{
|
{
|
||||||
foreach (GUIComponent child in children)
|
foreach (GUIComponent child in children)
|
||||||
|
|||||||
@@ -220,7 +220,29 @@ namespace Barotrauma.Items.Components
|
|||||||
Gap leak = objective.OperateTarget as Gap;
|
Gap leak = objective.OperateTarget as Gap;
|
||||||
if (leak == null) return true;
|
if (leak == null) return true;
|
||||||
|
|
||||||
if (Vector2.Distance(leak.WorldPosition, item.WorldPosition) > range) return true;
|
float dist = Vector2.Distance(leak.WorldPosition, item.WorldPosition);
|
||||||
|
|
||||||
|
//too far away -> consider this done and hope the AI is smart enough to move closer
|
||||||
|
if (dist > range*5.0f) return true;
|
||||||
|
|
||||||
|
//steer closer if almost in range
|
||||||
|
if (dist > range)
|
||||||
|
{
|
||||||
|
Vector2 standPos = leak.isHorizontal ?
|
||||||
|
new Vector2(Math.Sign(item.WorldPosition.X - leak.WorldPosition.X), 0.0f)
|
||||||
|
: new Vector2(0.0f, Math.Sign(item.WorldPosition.Y - leak.WorldPosition.Y));
|
||||||
|
|
||||||
|
standPos = leak.WorldPosition + standPos * range;
|
||||||
|
|
||||||
|
character.AIController.SteeringManager.SteeringManual(deltaTime, (standPos - character.WorldPosition) / 1000.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//close enough -> stop moving
|
||||||
|
character.AIController.SteeringManager.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
character.CursorPosition = leak.Position;
|
character.CursorPosition = leak.Position;
|
||||||
character.SetInput(InputType.Aim, false, true);
|
character.SetInput(InputType.Aim, false, true);
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, null);
|
ApplyStatusEffects(ActionType.OnUse, 1.0f);
|
||||||
|
|
||||||
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
|
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
|
||||||
|
|
||||||
|
|||||||
@@ -466,6 +466,20 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
return CurrentHull;
|
return CurrentHull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Item GetRootContainer()
|
||||||
|
{
|
||||||
|
if (Container == null) return null;
|
||||||
|
|
||||||
|
Item rootContainer = Container;
|
||||||
|
|
||||||
|
while (rootContainer.Container != null)
|
||||||
|
{
|
||||||
|
rootContainer = rootContainer.Container;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootContainer;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddTag(string tag)
|
public void AddTag(string tag)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Door ConnectedDoor;
|
public Door ConnectedDoor;
|
||||||
|
|
||||||
|
public Structure ConnectedWall;
|
||||||
|
|
||||||
public Vector2 LerpedFlowForce
|
public Vector2 LerpedFlowForce
|
||||||
{
|
{
|
||||||
get { return lerpedFlowForce; }
|
get { return lerpedFlowForce; }
|
||||||
|
|||||||
@@ -577,8 +577,9 @@ namespace Barotrauma
|
|||||||
gapRect.Width += 20;
|
gapRect.Width += 20;
|
||||||
gapRect.Height += 20;
|
gapRect.Height += 20;
|
||||||
sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal, Submarine);
|
sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal, Submarine);
|
||||||
if(CastShadow)
|
sections[sectionIndex].gap.ConnectedWall = this;
|
||||||
GenerateConvexHull();
|
|
||||||
|
if(CastShadow) GenerateConvexHull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,6 +759,7 @@ namespace Barotrauma
|
|||||||
if (s.GapIndex == -1) continue;
|
if (s.GapIndex == -1) continue;
|
||||||
|
|
||||||
s.gap = FindEntityByID((ushort)s.GapIndex) as Gap;
|
s.gap = FindEntityByID((ushort)s.GapIndex) as Gap;
|
||||||
|
if (s.gap != null) s.gap.ConnectedWall = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ namespace Barotrauma
|
|||||||
wayPoint.Remove();
|
wayPoint.Remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
float minDist = 200.0f;
|
float minDist = 150.0f;
|
||||||
float heightFromFloor = 100.0f;
|
float heightFromFloor = 100.0f;
|
||||||
|
|
||||||
foreach (Hull hull in Hull.hullList)
|
foreach (Hull hull in Hull.hullList)
|
||||||
@@ -324,7 +324,7 @@ namespace Barotrauma
|
|||||||
prevWaypoint = wayPoint;
|
prevWaypoint = wayPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float outSideWaypointInterval = 200.0f;
|
float outSideWaypointInterval = 200.0f;
|
||||||
int outsideWaypointDist = 100;
|
int outsideWaypointDist = 100;
|
||||||
|
|
||||||
@@ -521,7 +521,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
for (int dir = -1; dir <= 1; dir += 2)
|
for (int dir = -1; dir <= 1; dir += 2)
|
||||||
{
|
{
|
||||||
float tolerance = gap.IsRoomToRoom ? 30.0f : outSideWaypointInterval / 2.0f;
|
float tolerance = gap.IsRoomToRoom ? 50.0f : outSideWaypointInterval / 2.0f;
|
||||||
WayPoint closest = wayPoint.FindClosest(dir, true, new Vector2(-tolerance, tolerance));
|
WayPoint closest = wayPoint.FindClosest(dir, true, new Vector2(-tolerance, tolerance));
|
||||||
if (closest == null) continue;
|
if (closest == null) continue;
|
||||||
wayPoint.ConnectTo(closest);
|
wayPoint.ConnectTo(closest);
|
||||||
|
|||||||
Reference in New Issue
Block a user