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;
|
||||
|
||||
//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)
|
||||
{
|
||||
//isCompleted = true;
|
||||
return;
|
||||
if (oxygenTank.Condition > 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
oxygenTank.Drop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(subObjective is AIObjectiveContainItem))
|
||||
if (!(subObjective is AIObjectiveContainItem) || subObjective.IsCompleted())
|
||||
{
|
||||
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)
|
||||
{
|
||||
return otherObjective is AIObjectiveFindDivingGear;
|
||||
|
||||
@@ -29,68 +29,41 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
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;
|
||||
//return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Hull bestHull = null;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
var bestHull = FindBestHull();
|
||||
if (bestHull != null)
|
||||
{
|
||||
//var path = pathSteering.PathFinder.FindPath(character.SimPosition, bestHull.SimPosition);
|
||||
//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);
|
||||
goToObjective = new AIObjectiveGoTo(bestHull, character);
|
||||
}
|
||||
|
||||
|
||||
searchHullTimer = SearchHullInterval;
|
||||
}
|
||||
|
||||
@@ -117,43 +90,29 @@ namespace Barotrauma
|
||||
|
||||
divingGearObjective.TryComplete(deltaTime);
|
||||
return divingGearObjective.IsCompleted();
|
||||
}
|
||||
|
||||
//var item = character.Inventory.FindItem("diving");
|
||||
//if (item == null)
|
||||
//{
|
||||
// //get a diving mask/suit first
|
||||
// if (!(divingGearObjective is AIObjectiveGetItem))
|
||||
// {
|
||||
// divingGearObjective = new AIObjectiveGetItem(character, "diving", true);
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// var containedItems = item.ContainedItems;
|
||||
// if (containedItems == null) return true;
|
||||
private Hull FindBestHull()
|
||||
{
|
||||
Hull bestHull = null;
|
||||
float bestValue = currenthullSafety;
|
||||
|
||||
// //check if there's an oxygen tank in the mask
|
||||
// var oxygenTank = Array.Find(containedItems, i => i.Name == "Oxygen Tank" && i.Condition > 0.0f);
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
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))
|
||||
// {
|
||||
// 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;
|
||||
return bestHull;
|
||||
}
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
@@ -163,11 +122,15 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
priority = 100.0f - currenthullSafety;
|
||||
|
||||
|
||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
||||
|
||||
return priority;
|
||||
@@ -175,6 +138,8 @@ namespace Barotrauma
|
||||
|
||||
private float GetHullSafety(Hull hull)
|
||||
{
|
||||
if (hull == null) return 0.0f;
|
||||
|
||||
float waterPercentage = (hull.Volume / hull.FullVolume)*100.0f;
|
||||
float fireAmount = 0.0f;
|
||||
|
||||
@@ -185,7 +150,7 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
var repairTool = weldingTool.GetComponent<RepairTool>();
|
||||
if (repairTool == null) return;
|
||||
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.Linq;
|
||||
|
||||
@@ -10,6 +11,8 @@ namespace Barotrauma
|
||||
|
||||
private float updateGapListTimer;
|
||||
|
||||
private AIObjectiveIdle idleObjective;
|
||||
|
||||
private List<AIObjectiveFixLeak> objectiveList;
|
||||
|
||||
public AIObjectiveFixLeaks(Character character)
|
||||
@@ -36,13 +39,19 @@ namespace Barotrauma
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idleObjective == null) idleObjective = new AIObjectiveIdle(character);
|
||||
idleObjective.TryComplete(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGapList()
|
||||
@@ -51,13 +60,14 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
while (index<objectiveList.Count &&
|
||||
Vector2.DistanceSquared(objectiveList[index].Leak.WorldPosition, character.WorldPosition)>dist)
|
||||
while (index < objectiveList.Count &&
|
||||
GetGapFixPriority(objectiveList[index].Leak) < gapPriority)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return otherObjective is AIObjectiveFixLeaks;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
||||
{
|
||||
private string itemName;
|
||||
|
||||
private Item targetItem;
|
||||
private Item targetItem, moveToTarget;
|
||||
|
||||
private int currSearchIndex;
|
||||
|
||||
@@ -52,83 +52,96 @@ namespace Barotrauma
|
||||
|
||||
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;
|
||||
if (equip)
|
||||
var pickable = targetItem.GetComponent<Pickable>();
|
||||
//check if all the slots required by the item are free
|
||||
foreach (LimbSlot slots in pickable.AllowedSlots)
|
||||
{
|
||||
var pickable = targetItem.GetComponent<Pickable>();
|
||||
//check if all the slots required by the item are free
|
||||
foreach (LimbSlot slots in pickable.AllowedSlots)
|
||||
{
|
||||
if (slots.HasFlag(LimbSlot.Any)) continue;
|
||||
if (slots.HasFlag(LimbSlot.Any)) continue;
|
||||
|
||||
for (int i = 0; i<character.Inventory.Items.Length; i++)
|
||||
{
|
||||
//slot not needed by the item, continue
|
||||
if (!slots.HasFlag(CharacterInventory.limbSlots[i])) continue;
|
||||
for (int i = 0; i<character.Inventory.Items.Length; i++)
|
||||
{
|
||||
//slot not needed by the item, continue
|
||||
if (!slots.HasFlag(CharacterInventory.limbSlots[i])) continue;
|
||||
|
||||
targetSlot = i;
|
||||
targetSlot = i;
|
||||
|
||||
//slot free, continue
|
||||
if (character.Inventory.Items[i] == null) continue;
|
||||
//slot free, continue
|
||||
if (character.Inventory.Items[i] == null) continue;
|
||||
|
||||
//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;
|
||||
//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 everything else fails, simply drop the existing item
|
||||
character.Inventory.Items[i].Drop();
|
||||
}
|
||||
//if everything else fails, simply drop the existing item
|
||||
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++;
|
||||
|
||||
//don't try to get items from outside the sub
|
||||
if (Item.ItemList[currSearchIndex].CurrentHull == null) continue;
|
||||
var item = Item.ItemList[currSearchIndex];
|
||||
|
||||
if (!Item.ItemList[currSearchIndex].HasTag(itemName) && Item.ItemList[currSearchIndex].Name != itemName) continue;
|
||||
if (IgnoreContainedItems && Item.ItemList[currSearchIndex].Container != null) continue;
|
||||
if (Item.ItemList[currSearchIndex].ParentInventory is CharacterInventory) continue;
|
||||
if (item.CurrentHull == null || item.Condition <= 0.0f) continue;
|
||||
if (IgnoreContainedItems && item.Container != null) 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;
|
||||
while (moveToTarget.Container != null)
|
||||
{
|
||||
moveToTarget = moveToTarget.Container;
|
||||
}
|
||||
|
||||
AddSubObjective(new AIObjectiveGoTo(moveToTarget, character));
|
||||
subObjectives.Clear();
|
||||
AddSubObjective(new AIObjectiveGoTo(gotoToTarget, character));
|
||||
}
|
||||
|
||||
|
||||
public override bool IsDuplicate(AIObjective otherObjective)
|
||||
{
|
||||
|
||||
@@ -104,10 +104,13 @@ namespace Barotrauma
|
||||
|
||||
var indoorsSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
|
||||
|
||||
if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||
if (indoorsSteering.CurrentPath.Unreachable)
|
||||
{
|
||||
|
||||
AddSubObjective(new AIObjectiveGetItem(character, "Diving Suit", true));
|
||||
indoorsSteering.SteeringWander();
|
||||
}
|
||||
else if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||
{
|
||||
AddSubObjective(new AIObjectiveFindDivingGear(character, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,11 @@ namespace Barotrauma
|
||||
|
||||
if (currentTarget != null)
|
||||
{
|
||||
var path = pathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition);
|
||||
if (path.Cost > 200.0f) return;
|
||||
Vector2 pos = character.SimPosition;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Barotrauma
|
||||
if (dist<closestDist || startNode==null)
|
||||
{
|
||||
//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;
|
||||
startNode = node;
|
||||
@@ -160,7 +160,7 @@ namespace Barotrauma
|
||||
var path = FindPath(startNode,endNode);
|
||||
|
||||
sw.Stop();
|
||||
System.Diagnostics.Debug.WriteLine("findpath: " + sw.ElapsedTicks);
|
||||
System.Diagnostics.Debug.WriteLine("findpath: " + sw.ElapsedMilliseconds+" ms");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Barotrauma
|
||||
keyboardDispatcher = new KeyboardDispatcher(window);
|
||||
}
|
||||
|
||||
public T GetChild<T>()
|
||||
public T GetChild<T>() where T : GUIComponent
|
||||
{
|
||||
foreach (GUIComponent child in children)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
|
||||
public GUIComponent GetChild(object obj)
|
||||
{
|
||||
foreach (GUIComponent child in children)
|
||||
|
||||
@@ -220,7 +220,29 @@ namespace Barotrauma.Items.Components
|
||||
Gap leak = objective.OperateTarget as Gap;
|
||||
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.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;
|
||||
|
||||
|
||||
@@ -466,6 +466,20 @@ namespace Barotrauma
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace Barotrauma
|
||||
|
||||
public Door ConnectedDoor;
|
||||
|
||||
public Structure ConnectedWall;
|
||||
|
||||
public Vector2 LerpedFlowForce
|
||||
{
|
||||
get { return lerpedFlowForce; }
|
||||
|
||||
@@ -577,8 +577,9 @@ namespace Barotrauma
|
||||
gapRect.Width += 20;
|
||||
gapRect.Height += 20;
|
||||
sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal, Submarine);
|
||||
if(CastShadow)
|
||||
GenerateConvexHull();
|
||||
sections[sectionIndex].gap.ConnectedWall = this;
|
||||
|
||||
if(CastShadow) GenerateConvexHull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -758,6 +759,7 @@ namespace Barotrauma
|
||||
if (s.GapIndex == -1) continue;
|
||||
|
||||
s.gap = FindEntityByID((ushort)s.GapIndex) as Gap;
|
||||
if (s.gap != null) s.gap.ConnectedWall = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace Barotrauma
|
||||
wayPoint.Remove();
|
||||
}
|
||||
|
||||
float minDist = 200.0f;
|
||||
float minDist = 150.0f;
|
||||
float heightFromFloor = 100.0f;
|
||||
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
@@ -324,7 +324,7 @@ namespace Barotrauma
|
||||
prevWaypoint = wayPoint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float outSideWaypointInterval = 200.0f;
|
||||
int outsideWaypointDist = 100;
|
||||
|
||||
@@ -521,7 +521,7 @@ namespace Barotrauma
|
||||
|
||||
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));
|
||||
if (closest == null) continue;
|
||||
wayPoint.ConnectTo(closest);
|
||||
|
||||
Reference in New Issue
Block a user