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:
@@ -29,12 +29,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public Vector2 SimPosition
|
public Vector2 SimPosition
|
||||||
{
|
{
|
||||||
get { return Character.AnimController.Limbs[0].SimPosition; }
|
get { return Character.SimPosition; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 WorldPosition
|
||||||
|
{
|
||||||
|
get { return Character.WorldPosition; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 Velocity
|
public Vector2 Velocity
|
||||||
{
|
{
|
||||||
get { return Character.AnimController.Limbs[0].LinearVelocity; }
|
get { return Character.AnimController.RefLimb.LinearVelocity; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public AiState State
|
public AiState State
|
||||||
|
|||||||
@@ -71,7 +71,33 @@ namespace Barotrauma
|
|||||||
|
|
||||||
steeringManager.Update(moveSpeed);
|
steeringManager.Update(moveSpeed);
|
||||||
|
|
||||||
Character.AnimController.IgnorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X*0.5f));
|
Character.AnimController.IgnorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f &&
|
||||||
|
(-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X));
|
||||||
|
|
||||||
|
var currPath = (steeringManager as IndoorsSteeringManager).CurrentPath;
|
||||||
|
if (currPath != null && currPath.CurrentNode != null)
|
||||||
|
{
|
||||||
|
if (currPath.CurrentNode.WorldPosition.Y < Character.WorldPosition.Y - 200)
|
||||||
|
{
|
||||||
|
Character.AnimController.IgnorePlatforms = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Character.AnimController.Stairs != null)
|
||||||
|
{
|
||||||
|
float yDiff = currPath.CurrentNode.WorldPosition.Y - Character.WorldPosition.Y;
|
||||||
|
|
||||||
|
if (Math.Abs(yDiff)>10.0f)
|
||||||
|
{
|
||||||
|
int dir = Math.Sign(yDiff);
|
||||||
|
|
||||||
|
float movement = Character.AnimController.Stairs.StairDirection == Direction.Right ?
|
||||||
|
dir * Character.AnimController.TargetMovement.Length() : -dir * Character.AnimController.TargetMovement.Length();
|
||||||
|
|
||||||
|
Character.AnimController.TargetMovement = new Vector2(movement, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(Character.AnimController as HumanoidAnimController).Crouching = false;
|
(Character.AnimController as HumanoidAnimController).Crouching = false;
|
||||||
|
|
||||||
|
|
||||||
@@ -86,17 +112,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Character.SelectedConstruction != null && Character.SelectedConstruction.GetComponent<Items.Components.Ladder>()!=null)
|
if (Character.SelectedConstruction != null && Character.SelectedConstruction.GetComponent<Items.Components.Ladder>()!=null)
|
||||||
{
|
{
|
||||||
var currPath = (steeringManager as IndoorsSteeringManager).CurrentPath;
|
|
||||||
if (currPath != null && currPath.CurrentNode != null && currPath.CurrentNode.Ladders != null)
|
if (currPath != null && currPath.CurrentNode != null && currPath.CurrentNode.Ladders != null)
|
||||||
{
|
{
|
||||||
Character.AnimController.TargetMovement = new Vector2( 0.0f, Math.Sign(Character.AnimController.TargetMovement.Y));
|
Character.AnimController.TargetMovement = new Vector2( 0.0f, Math.Sign(Character.AnimController.TargetMovement.Y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//unequip diving suit if running out of oxygen
|
//suit can be taken off if there character is inside a hull and there's air in the room
|
||||||
if (Character.Oxygen < 50.0f && Character.AnimController.CurrentHull!=null &&
|
bool canTakeOffSuit = Character.AnimController.CurrentHull != null &&
|
||||||
Character.AnimController.CurrentHull.OxygenPercentage > 20.0f &&
|
Character.AnimController.CurrentHull.OxygenPercentage > 30.0f &&
|
||||||
Character.AnimController.CurrentHull.Volume < Character.AnimController.CurrentHull.FullVolume*0.3f)
|
Character.AnimController.CurrentHull.Volume < Character.AnimController.CurrentHull.FullVolume * 0.3f;
|
||||||
|
|
||||||
|
//the suit can be taken off and the character is running out of oxygen (couldn't find a tank for the suit?) or idling
|
||||||
|
//-> take the suit off
|
||||||
|
if (canTakeOffSuit && (Character.Oxygen < 50.0f || objectiveManager.CurrentObjective is AIObjectiveIdle))
|
||||||
{
|
{
|
||||||
var divingSuit = Character.Inventory.FindItem("Diving Suit");
|
var divingSuit = Character.Inventory.FindItem("Diving Suit");
|
||||||
if (divingSuit != null) divingSuit.Drop(Character);
|
if (divingSuit != null) divingSuit.Drop(Character);
|
||||||
@@ -121,9 +150,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
|
Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnAttacked(IDamageable attacker, float amount)
|
public override void OnAttacked(IDamageable attacker, float amount)
|
||||||
@@ -172,7 +198,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
new Vector2(pathSteering.CurrentPath.Nodes[i].WorldPosition.X, -pathSteering.CurrentPath.Nodes[i].WorldPosition.Y),
|
new Vector2(pathSteering.CurrentPath.Nodes[i].WorldPosition.X, -pathSteering.CurrentPath.Nodes[i].WorldPosition.Y),
|
||||||
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].WorldPosition.Y, -pathSteering.CurrentPath.Nodes[i-1].WorldPosition.Y),
|
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].WorldPosition.X, -pathSteering.CurrentPath.Nodes[i-1].WorldPosition.Y),
|
||||||
Color.LightGreen);
|
Color.LightGreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 WorldPosition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -122,12 +122,22 @@ namespace Barotrauma
|
|||||||
if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f;
|
if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f;
|
||||||
|
|
||||||
Vector2 pos = host.SimPosition;
|
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
|
if (CurrentPath.CurrentNode.Submarine != null)
|
||||||
pos -= CurrentPath.CurrentNode.Submarine.SimPosition;
|
{
|
||||||
}
|
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)
|
if (currentPath.CurrentNode!= null && currentPath.CurrentNode.Ladders!=null)
|
||||||
{
|
{
|
||||||
@@ -135,17 +145,32 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
currentPath.CurrentNode.Ladders.Item.Pick(character, false, true);
|
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);
|
currentPath.CheckProgress(pos, allowedDistance);
|
||||||
|
|
||||||
if (currentPath.CurrentNode == null) return Vector2.Zero;
|
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;
|
return currentPath.CurrentNode.SimPosition - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,41 +178,67 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++)
|
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;
|
WayPoint node = null;
|
||||||
|
WayPoint nextNode = null;
|
||||||
bool open = currentPath.CurrentNode != null &&
|
|
||||||
Math.Sign(door.Item.SimPosition.X - host.SimPosition.X) == Math.Sign(currentPath.CurrentNode.SimPosition.X - host.SimPosition.X);
|
if (i==0)
|
||||||
|
|
||||||
if (currentPath.CurrentNode==null)
|
|
||||||
{
|
{
|
||||||
open = false;
|
node = currentPath.CurrentNode;
|
||||||
|
nextNode = currentPath.NextNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (door.LinkedGap.isHorizontal)
|
node = currentPath.PrevNode;
|
||||||
{
|
nextNode = currentPath.CurrentNode;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//toggle the door if it's the previous node and open, or if it's current node and closed
|
if (node == null || node.ConnectedGap == null || node.ConnectedGap.ConnectedDoor == null) continue;
|
||||||
if (door.IsOpen != open)
|
|
||||||
|
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)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (currentHull != null)
|
if (currentHull != null)
|
||||||
{
|
{
|
||||||
if (currentHull.Volume / currentHull.FullVolume > 0.5f || character.Oxygen < 80.0f)
|
if (NeedsDivingGear())
|
||||||
{
|
{
|
||||||
if (!FindDivingGear(deltaTime)) return;
|
if (!FindDivingGear(deltaTime)) return;
|
||||||
}
|
}
|
||||||
@@ -131,6 +131,19 @@ namespace Barotrauma
|
|||||||
return (otherObjective is AIObjectiveFindSafety);
|
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)
|
public override float GetPriority(Character character)
|
||||||
{
|
{
|
||||||
if (character.Oxygen < 80.0f)
|
if (character.Oxygen < 80.0f)
|
||||||
@@ -142,8 +155,12 @@ namespace Barotrauma
|
|||||||
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull, character);
|
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull, character);
|
||||||
priority = 100.0f - currenthullSafety;
|
priority = 100.0f - currenthullSafety;
|
||||||
|
|
||||||
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
|
||||||
|
|
||||||
|
if (NeedsDivingGear())
|
||||||
|
{
|
||||||
|
if (divingGearObjective != null && !divingGearObjective.IsCompleted()) priority += 20.0f;
|
||||||
|
}
|
||||||
|
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool IgnoreContainedItems;
|
public bool IgnoreContainedItems;
|
||||||
|
|
||||||
|
private AIObjectiveGoTo goToObjective;
|
||||||
|
|
||||||
private bool equip;
|
private bool equip;
|
||||||
|
|
||||||
public override bool CanBeCompleted
|
public override bool CanBeCompleted
|
||||||
@@ -52,13 +54,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
if (targetItem == null)
|
FindTargetItem();
|
||||||
{
|
if (targetItem == null || moveToTarget == null) return;
|
||||||
FindTargetItem();
|
|
||||||
if (targetItem == null) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moveToTarget == null) return;
|
|
||||||
|
|
||||||
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance*2.0f)
|
if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance*2.0f)
|
||||||
{
|
{
|
||||||
@@ -97,9 +94,15 @@ namespace Barotrauma
|
|||||||
character.Inventory.TryPutItem(targetItem, targetSlot, true, false);
|
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);
|
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++;
|
currSearchIndex++;
|
||||||
|
|
||||||
@@ -136,22 +139,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
targetItem = item;
|
targetItem = item;
|
||||||
moveToTarget = rootContainer ?? item;
|
moveToTarget = rootContainer ?? item;
|
||||||
|
|
||||||
AddGoToObjective(moveToTarget);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if searched through all the items and a target wasn't found, can't be completed
|
//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;
|
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)
|
public override bool IsDuplicate(AIObjective otherObjective)
|
||||||
{
|
{
|
||||||
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
|
AIObjectiveGetItem getItem = otherObjective as AIObjectiveGetItem;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace Barotrauma
|
|||||||
//how long until the path to the target is declared unreachable
|
//how long until the path to the target is declared unreachable
|
||||||
private float waitUntilPathUnreachable;
|
private float waitUntilPathUnreachable;
|
||||||
|
|
||||||
|
private bool getDivingGearIfNeeded;
|
||||||
|
|
||||||
public override bool CanBeCompleted
|
public override bool CanBeCompleted
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -35,23 +37,25 @@ namespace Barotrauma
|
|||||||
get { return target; }
|
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, "")
|
: base (character, "")
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.repeat = repeat;
|
this.repeat = repeat;
|
||||||
|
|
||||||
waitUntilPathUnreachable = 5.0f;
|
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, "")
|
: base(character, "")
|
||||||
{
|
{
|
||||||
this.targetPos = simPos;
|
this.targetPos = simPos;
|
||||||
this.repeat = repeat;
|
this.repeat = repeat;
|
||||||
|
|
||||||
waitUntilPathUnreachable = 5.0f;
|
waitUntilPathUnreachable = 5.0f;
|
||||||
|
this.getDivingGearIfNeeded = getDivingGearIfNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
@@ -108,7 +112,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
indoorsSteering.SteeringWander();
|
indoorsSteering.SteeringWander();
|
||||||
}
|
}
|
||||||
else if (indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
else if (getDivingGearIfNeeded && indoorsSteering.CurrentPath != null && indoorsSteering.HasOutdoorsNodes)
|
||||||
{
|
{
|
||||||
AddSubObjective(new AIObjectiveFindDivingGear(character, true));
|
AddSubObjective(new AIObjectiveFindDivingGear(character, true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -11,8 +12,6 @@ namespace Barotrauma
|
|||||||
AITarget currentTarget;
|
AITarget currentTarget;
|
||||||
private float newTargetTimer;
|
private float newTargetTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public AIObjectiveIdle(Character character) : base(character, "")
|
public AIObjectiveIdle(Character character) : base(character, "")
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -23,7 +22,6 @@ namespace Barotrauma
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void Act(float deltaTime)
|
protected override void Act(float deltaTime)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -53,7 +51,8 @@ namespace Barotrauma
|
|||||||
newTargetTimer = currentTarget == null ? 5.0f : 15.0f;
|
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
|
//wander randomly if reached the end of the path or the target is unreachable
|
||||||
if (pathSteering==null || (pathSteering.CurrentPath != null &&
|
if (pathSteering==null || (pathSteering.CurrentPath != null &&
|
||||||
@@ -62,13 +61,28 @@ namespace Barotrauma
|
|||||||
//steer away from edges of the hull
|
//steer away from edges of the hull
|
||||||
if (character.AnimController.CurrentHull!=null)
|
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;
|
if (currentTarget == null) return;
|
||||||
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition);
|
character.AIController.SteeringManager.SteeringSeek(currentTarget.SimPosition, 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AITarget FindRandomTarget()
|
private AITarget FindRandomTarget()
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Barotrauma
|
|||||||
public float F,G,H;
|
public float F,G,H;
|
||||||
|
|
||||||
public List<PathNode> connections;
|
public List<PathNode> connections;
|
||||||
public float[] distances;
|
public List<float> distances;
|
||||||
|
|
||||||
public WayPoint Waypoint
|
public WayPoint Waypoint
|
||||||
{
|
{
|
||||||
@@ -63,15 +63,14 @@ namespace Barotrauma
|
|||||||
var nodeList = nodes.Values.ToList();
|
var nodeList = nodes.Values.ToList();
|
||||||
foreach (PathNode node in nodeList)
|
foreach (PathNode node in nodeList)
|
||||||
{
|
{
|
||||||
node.distances = new float[node.connections.Count];
|
node.distances = new List<float>();
|
||||||
for (int i = 0; i< node.distances.Length; i++)
|
for (int i = 0; i< node.connections.Count; i++)
|
||||||
{
|
{
|
||||||
node.distances[i] = Vector2.Distance(node.position, node.connections[i].position);
|
node.distances.Add(Vector2.Distance(node.position, node.connections[i].position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodeList;
|
return nodeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PathFinder
|
class PathFinder
|
||||||
@@ -87,9 +86,66 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => w.MoveWithLevel != insideSubmarine));
|
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => w.MoveWithLevel != insideSubmarine));
|
||||||
|
|
||||||
|
foreach (WayPoint wp in wayPoints)
|
||||||
|
{
|
||||||
|
wp.linkedTo.CollectionChanged += WaypointLinksChanged;
|
||||||
|
}
|
||||||
|
|
||||||
this.insideSubmarine = insideSubmarine;
|
this.insideSubmarine = insideSubmarine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaypointLinksChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Submarine.Unloading) return;
|
||||||
|
|
||||||
|
var waypoints = sender as IEnumerable<MapEntity>;
|
||||||
|
|
||||||
|
foreach (MapEntity me in waypoints)
|
||||||
|
{
|
||||||
|
WayPoint wp = me as WayPoint;
|
||||||
|
if (me == null) continue;
|
||||||
|
|
||||||
|
var node = nodes.Find(n => n.Waypoint == wp);
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
|
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||||
|
{
|
||||||
|
for (int i = node.connections.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
//remove connection if the waypoint isn't connected anymore
|
||||||
|
if (wp.linkedTo.FirstOrDefault(l => l == node.connections[i].Waypoint) == null)
|
||||||
|
{
|
||||||
|
node.connections.RemoveAt(i);
|
||||||
|
node.distances.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < wp.linkedTo.Count; i++)
|
||||||
|
{
|
||||||
|
WayPoint connected = wp.linkedTo[i] as WayPoint;
|
||||||
|
if (connected == null) continue;
|
||||||
|
|
||||||
|
//already connected, continue
|
||||||
|
if (node.connections.Any(n => n.Waypoint == connected)) continue;
|
||||||
|
|
||||||
|
var matchingNode = nodes.Find(n => n.Waypoint == connected);
|
||||||
|
if (matchingNode == null)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("Waypoint connections were changed, no matching path node found in PathFinder");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.connections.Add(matchingNode);
|
||||||
|
node.distances.Add(Vector2.Distance(node.Position, matchingNode.Position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SteeringPath FindPath(Vector2 start, Vector2 end)
|
public SteeringPath FindPath(Vector2 start, Vector2 end)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
|
||||||
@@ -100,21 +156,21 @@ namespace Barotrauma
|
|||||||
foreach (PathNode node in nodes)
|
foreach (PathNode node in nodes)
|
||||||
{
|
{
|
||||||
Vector2 nodePos = node.Position;
|
Vector2 nodePos = node.Position;
|
||||||
|
|
||||||
|
float dist = System.Math.Abs(start.X - nodePos.X) +
|
||||||
|
System.Math.Abs(start.Y - nodePos.Y) * 10.0f; //higher cost for vertical movement
|
||||||
|
|
||||||
//if node waypoint is one of submarine waypoints outside the sub, transform position
|
//prefer nodes that are closer to the end position
|
||||||
//if (node.Waypoint != null && node.Waypoint.Submarine != null && node.Waypoint.CurrentHull == null)
|
dist += Vector2.Distance(end, nodePos) / 10.0f;
|
||||||
//{
|
|
||||||
// nodePos -= node.Waypoint.Submarine.Position;
|
|
||||||
//}
|
|
||||||
|
|
||||||
float dist = System.Math.Abs(start.X-nodePos.X)+
|
|
||||||
System.Math.Abs(start.Y - nodePos.Y)*10.0f +
|
|
||||||
Vector2.Distance(end,nodePos)/2.0f;
|
|
||||||
|
|
||||||
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 && Submarine.CheckVisibility(start, node.Waypoint.SimPosition) != null) continue;
|
if (insideSubmarine)
|
||||||
|
{
|
||||||
|
var body = Submarine.CheckVisibility(start, node.Waypoint.SimPosition);
|
||||||
|
if (body != null && body.UserData is Structure) continue;
|
||||||
|
}
|
||||||
|
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
startNode = node;
|
startNode = node;
|
||||||
@@ -144,7 +200,11 @@ namespace Barotrauma
|
|||||||
if (dist < closestDist || endNode == null)
|
if (dist < closestDist || endNode == 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(end, node.Waypoint.SimPosition) != null) continue;
|
if (insideSubmarine)
|
||||||
|
{
|
||||||
|
var body = Submarine.CheckVisibility(end, node.Waypoint.SimPosition);
|
||||||
|
if (body != null && body.UserData is Structure) continue;
|
||||||
|
}
|
||||||
|
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
endNode = node;
|
endNode = node;
|
||||||
@@ -234,7 +294,7 @@ namespace Barotrauma
|
|||||||
for (int i = 0; i < currNode.connections.Count; i++)
|
for (int i = 0; i < currNode.connections.Count; i++)
|
||||||
{
|
{
|
||||||
PathNode nextNode = currNode.connections[i];
|
PathNode nextNode = currNode.connections[i];
|
||||||
|
|
||||||
//a node that hasn't been searched yet
|
//a node that hasn't been searched yet
|
||||||
if (nextNode.state==0)
|
if (nextNode.state==0)
|
||||||
{
|
{
|
||||||
@@ -272,7 +332,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end.state==0)
|
if (end.state == 0 || end.Parent == null)
|
||||||
{
|
{
|
||||||
//path not found
|
//path not found
|
||||||
return new SteeringPath(true);
|
return new SteeringPath(true);
|
||||||
@@ -290,6 +350,8 @@ namespace Barotrauma
|
|||||||
pathNode = pathNode.Parent;
|
pathNode = pathNode.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finalPath.Add(start.Waypoint);
|
||||||
|
|
||||||
finalPath.Reverse();
|
finalPath.Reverse();
|
||||||
|
|
||||||
foreach (WayPoint wayPoint in finalPath)
|
foreach (WayPoint wayPoint in finalPath)
|
||||||
|
|||||||
@@ -814,7 +814,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
notClimbing = targetMovement.X != 0.0f;
|
notClimbing = Math.Abs(targetMovement.X) > 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
//stop climbing if:
|
//stop climbing if:
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float FloorY
|
||||||
|
{
|
||||||
|
get { return floorY; }
|
||||||
|
}
|
||||||
|
|
||||||
public float Mass
|
public float Mass
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -330,14 +335,8 @@ namespace Barotrauma
|
|||||||
lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X);
|
lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X);
|
||||||
|
|
||||||
|
|
||||||
if (character.IsDead)
|
if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false;
|
||||||
{
|
|
||||||
if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (targetMovement.Y < 0.5f)
|
if (targetMovement.Y < 0.5f)
|
||||||
@@ -477,7 +476,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ignorePlatforms)
|
||||||
|
{
|
||||||
|
GUI.DrawLine(spriteBatch, new Vector2(refLimb.WorldPosition.X, -refLimb.WorldPosition.Y), new Vector2(refLimb.WorldPosition.X, -refLimb.WorldPosition.Y+50), Color.Orange, 0, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Flip()
|
public virtual void Flip()
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ namespace Barotrauma
|
|||||||
get { return FarseerPhysics.ConvertUnits.ToSimUnits(position); }
|
get { return FarseerPhysics.ConvertUnits.ToSimUnits(position); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 WorldPosition
|
||||||
|
{
|
||||||
|
get { return position; }
|
||||||
|
}
|
||||||
|
|
||||||
public Vector2 Velocity
|
public Vector2 Velocity
|
||||||
{
|
{
|
||||||
get { return new Vector2(velocity.X, velocity.Y); }
|
get { return new Vector2(velocity.X, velocity.Y); }
|
||||||
|
|||||||
@@ -1143,7 +1143,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Vector2 pos = DrawPosition;
|
Vector2 pos = DrawPosition;
|
||||||
pos.Y = -pos.Y;
|
pos.Y = -pos.Y;
|
||||||
|
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
AnimController.DebugDraw(spriteBatch);
|
||||||
|
|
||||||
|
if (aiTarget != null) aiTarget.Draw(spriteBatch);
|
||||||
|
}
|
||||||
|
|
||||||
if (this == controlled) return;
|
if (this == controlled) return;
|
||||||
|
|
||||||
if (IsNetworkPlayer && info!=null)
|
if (IsNetworkPlayer && info!=null)
|
||||||
@@ -1158,13 +1165,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.DebugDraw)
|
|
||||||
{
|
|
||||||
AnimController.DebugDraw(spriteBatch);
|
|
||||||
|
|
||||||
if (aiTarget != null) aiTarget.Draw(spriteBatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDead) return;
|
if (isDead) return;
|
||||||
|
|
||||||
Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f);
|
Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f);
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
public void Dock(DockingPort target)
|
public void Dock(DockingPort target)
|
||||||
{
|
{
|
||||||
|
if (item.Submarine.DockedTo.Contains(target.item.Submarine)) return;
|
||||||
|
|
||||||
if (dockingTarget != null)
|
if (dockingTarget != null)
|
||||||
{
|
{
|
||||||
Undock();
|
Undock();
|
||||||
@@ -154,6 +156,23 @@ namespace Barotrauma.Items.Components
|
|||||||
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
|
||||||
Math.Sign(item.WorldPosition.Y - dockingTarget.item.WorldPosition.Y);
|
Math.Sign(item.WorldPosition.Y - dockingTarget.item.WorldPosition.Y);
|
||||||
dockingTarget.dockingDir = -dockingDir;
|
dockingTarget.dockingDir = -dockingDir;
|
||||||
|
|
||||||
|
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||||
|
{
|
||||||
|
if (wp.Submarine != item.Submarine || wp.SpawnType != SpawnType.Path) continue;
|
||||||
|
|
||||||
|
if (!Submarine.RectContains(item.Rect, wp.Position)) continue;
|
||||||
|
|
||||||
|
foreach (WayPoint wp2 in WayPoint.WayPointList)
|
||||||
|
{
|
||||||
|
if (wp2.Submarine != dockingTarget.item.Submarine || wp2.SpawnType != SpawnType.Path) continue;
|
||||||
|
|
||||||
|
if (!Submarine.RectContains(dockingTarget.item.Rect, wp2.Position)) continue;
|
||||||
|
|
||||||
|
wp.linkedTo.Add(wp2);
|
||||||
|
wp2.linkedTo.Add(wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CreateJoint(false);
|
CreateJoint(false);
|
||||||
}
|
}
|
||||||
@@ -304,6 +323,24 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
||||||
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
||||||
|
|
||||||
|
//remove all waypoint links between this sub and the dockingtarget
|
||||||
|
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||||
|
{
|
||||||
|
if (wp.Submarine != item.Submarine || wp.SpawnType != SpawnType.Path) continue;
|
||||||
|
|
||||||
|
for (int i = wp.linkedTo.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var wp2 = wp.linkedTo[i] as WayPoint;
|
||||||
|
if (wp2 == null) continue;
|
||||||
|
|
||||||
|
if (wp.Submarine == dockingTarget.item.Submarine)
|
||||||
|
{
|
||||||
|
wp.linkedTo.RemoveAt(i);
|
||||||
|
wp2.linkedTo.Remove(wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item.linkedTo.Clear();
|
item.linkedTo.Clear();
|
||||||
|
|
||||||
@@ -330,7 +367,7 @@ namespace Barotrauma.Items.Components
|
|||||||
gap.Remove();
|
gap.Remove();
|
||||||
gap = null;
|
gap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bodies!=null)
|
if (bodies!=null)
|
||||||
{
|
{
|
||||||
foreach (Body body in bodies)
|
foreach (Body body in bodies)
|
||||||
|
|||||||
@@ -1060,13 +1060,22 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> GetConnectedComponents<T>()
|
public List<T> GetConnectedComponents<T>(bool recursive = false)
|
||||||
{
|
{
|
||||||
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
|
|
||||||
if (connectionPanel == null) return new List<T>();
|
|
||||||
|
|
||||||
List<T> connectedComponents = new List<T>();
|
List<T> connectedComponents = new List<T>();
|
||||||
|
|
||||||
|
if (recursive)
|
||||||
|
{
|
||||||
|
List<Item> alreadySearched = new List<Item>() {this};
|
||||||
|
GetConnectedComponentsRecursive<T>(alreadySearched, connectedComponents);
|
||||||
|
|
||||||
|
return connectedComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
|
||||||
|
if (connectionPanel == null) return connectedComponents;
|
||||||
|
|
||||||
|
|
||||||
foreach (Connection c in connectionPanel.Connections)
|
foreach (Connection c in connectionPanel.Connections)
|
||||||
{
|
{
|
||||||
var recipients = c.Recipients;
|
var recipients = c.Recipients;
|
||||||
@@ -1080,6 +1089,34 @@ namespace Barotrauma
|
|||||||
return connectedComponents;
|
return connectedComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GetConnectedComponentsRecursive<T>(List<Item> alreadySearched, List<T> connectedComponents)
|
||||||
|
{
|
||||||
|
alreadySearched.Add(this);
|
||||||
|
|
||||||
|
ConnectionPanel connectionPanel = GetComponent<ConnectionPanel>();
|
||||||
|
if (connectionPanel == null) return;
|
||||||
|
|
||||||
|
foreach (Connection c in connectionPanel.Connections)
|
||||||
|
{
|
||||||
|
var recipients = c.Recipients;
|
||||||
|
foreach (Connection recipient in recipients)
|
||||||
|
{
|
||||||
|
if (alreadySearched.Contains(recipient.Item)) continue;
|
||||||
|
|
||||||
|
var component = recipient.Item.GetComponent<T>();
|
||||||
|
|
||||||
|
if (component != null)
|
||||||
|
{
|
||||||
|
connectedComponents.Add(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
recipient.Item.GetConnectedComponentsRecursive<T>(alreadySearched, connectedComponents);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SendSignal(int stepsTaken, string signal, string connectionName, float power = 0.0f)
|
public void SendSignal(int stepsTaken, string signal, string connectionName, float power = 0.0f)
|
||||||
{
|
{
|
||||||
stepsTaken++;
|
stepsTaken++;
|
||||||
|
|||||||
@@ -895,14 +895,20 @@ namespace Barotrauma
|
|||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool Unloading
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Unload()
|
public static void Unload()
|
||||||
{
|
{
|
||||||
|
Unloading = true;
|
||||||
|
|
||||||
Sound.OnGameEnd();
|
Sound.OnGameEnd();
|
||||||
|
|
||||||
if (GameMain.LightManager != null) GameMain.LightManager.ClearLights();
|
if (GameMain.LightManager != null) GameMain.LightManager.ClearLights();
|
||||||
|
|
||||||
|
|
||||||
foreach (Submarine sub in loaded)
|
foreach (Submarine sub in loaded)
|
||||||
{
|
{
|
||||||
sub.Remove();
|
sub.Remove();
|
||||||
@@ -919,6 +925,8 @@ namespace Barotrauma
|
|||||||
Ragdoll.list.Clear();
|
Ragdoll.list.Clear();
|
||||||
|
|
||||||
GameMain.World.Clear();
|
GameMain.World.Clear();
|
||||||
|
|
||||||
|
Unloading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Remove()
|
public override void Remove()
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ namespace Barotrauma
|
|||||||
int iconY = (int)(Math.Floor(iconIndices[(int)spawnType]*IconSize / (float)iconTexture.Width))*IconSize;
|
int iconY = (int)(Math.Floor(iconIndices[(int)spawnType]*IconSize / (float)iconTexture.Width))*IconSize;
|
||||||
|
|
||||||
int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f);
|
int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f);
|
||||||
|
|
||||||
spriteBatch.Draw(iconTexture,
|
spriteBatch.Draw(iconTexture,
|
||||||
new Rectangle((int)(drawPos.X - iconSize/2), (int)(drawPos.Y - iconSize/2), iconSize, iconSize),
|
new Rectangle((int)(drawPos.X - iconSize/2), (int)(drawPos.Y - iconSize/2), iconSize, iconSize),
|
||||||
new Rectangle(iconX, iconY, IconSize,IconSize), clr);
|
new Rectangle(iconX, iconY, IconSize,IconSize), clr);
|
||||||
@@ -176,7 +176,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
editingHUD = CreateEditingHUD();
|
editingHUD = CreateEditingHUD();
|
||||||
}
|
}
|
||||||
|
|
||||||
editingHUD.Update((float)Physics.step);
|
editingHUD.Update((float)Physics.step);
|
||||||
editingHUD.Draw(spriteBatch);
|
editingHUD.Draw(spriteBatch);
|
||||||
|
|
||||||
@@ -321,7 +321,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
float minDist = 150.0f;
|
float minDist = 150.0f;
|
||||||
float heightFromFloor = 100.0f;
|
float heightFromFloor = 110.0f;
|
||||||
|
|
||||||
foreach (Hull hull in Hull.hullList)
|
foreach (Hull hull in Hull.hullList)
|
||||||
{
|
{
|
||||||
@@ -607,7 +607,11 @@ namespace Barotrauma
|
|||||||
float dist = Vector2.Distance(wp.Position, Position);
|
float dist = Vector2.Distance(wp.Position, Position);
|
||||||
if (closest == null || dist < closestDist)
|
if (closest == null || dist < closestDist)
|
||||||
{
|
{
|
||||||
if (Submarine.CheckVisibility(SimPosition, wp.SimPosition) != null) continue;
|
var body = Submarine.CheckVisibility(SimPosition, wp.SimPosition, true);
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
if (body.UserData is Structure) continue;
|
||||||
|
}
|
||||||
|
|
||||||
closestDist = dist;
|
closestDist = dist;
|
||||||
closest = wp;
|
closest = wp;
|
||||||
@@ -620,6 +624,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ConnectTo(WayPoint wayPoint2)
|
private void ConnectTo(WayPoint wayPoint2)
|
||||||
{
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(this != wayPoint2);
|
||||||
|
|
||||||
if (!linkedTo.Contains(wayPoint2)) linkedTo.Add(wayPoint2);
|
if (!linkedTo.Contains(wayPoint2)) linkedTo.Add(wayPoint2);
|
||||||
if (!wayPoint2.linkedTo.Contains(this)) wayPoint2.linkedTo.Add(this);
|
if (!wayPoint2.linkedTo.Contains(this)) wayPoint2.linkedTo.Add(this);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user