Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -320,8 +320,7 @@ namespace Barotrauma
Vector2 pos = host.WorldPosition;
Vector2 diff = currentPath.CurrentNode.WorldPosition - pos;
bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater;
// Only humanoids can climb ladders
bool canClimb = character.AnimController is HumanoidAnimController && !character.LockHands;
bool canClimb = character.CanClimb;
Ladder currentLadder = GetCurrentLadder();
Ladder nextLadder = GetNextLadder();
var ladders = currentLadder ?? nextLadder;
@@ -559,26 +558,42 @@ namespace Barotrauma
}
else
{
// We'll want this to run each time, because the delegate is used to find a valid button component.
bool canAccessButtons = false;
foreach (var button in door.Item.GetConnectedComponents<Controller>(true, connectionFilter: c => c.Name == "toggle" || c.Name == "set_state"))
bool buttonsFound = false;
// Check wired controllers (e.g. buttons)
// Always run the buttonFilter delegate (inside CanAccessButton method), if defined, because it's used for find a valid controller component that can be used for closing the door, when needed.
// TODO: connectionFilter is ignored in the recursive searches, so it does nothing here.
foreach (Controller button in door.Item.GetConnectedComponents<Controller>(recursive: true, connectionFilter: c => c.Name is "toggle" or "set_state"))
{
if (button.HasAccess(character) && (buttonFilter == null || buttonFilter(button)))
buttonsFound = true;
if (CanAccessButton(button))
{
canAccessButtons = true;
}
}
foreach (var linked in door.Item.linkedTo)
if (!canAccessButtons)
{
if (linked is not Item linkedItem) { continue; }
var button = linkedItem.GetComponent<Controller>();
if (button == null) { continue; }
if (button.HasAccess(character) && (buttonFilter == null || buttonFilter(button)))
// Check linked controllers (more complex circuits)
foreach (MapEntity linked in door.Item.linkedTo)
{
canAccessButtons = true;
}
}
return canAccessButtons || door.IsOpen || ShouldBreakDoor(door);
if (linked is not Item linkedItem) { continue; }
var button = linkedItem.GetComponent<Controller>();
if (button == null) { continue; }
buttonsFound = true;
if (CanAccessButton(button))
{
canAccessButtons = true;
}
}
}
if (door.IsOpen || ShouldBreakDoor(door))
{
return true;
}
// If no buttons were found, just trust it if we should have the access to the door. Could be there's some other mechanism controlling the door.
return buttonsFound ? canAccessButtons : door.HasAccess(character);
bool CanAccessButton(Controller button) => button.HasAccess(character) && (buttonFilter == null || buttonFilter(button));
}
}
@@ -713,12 +728,15 @@ namespace Barotrauma
float distance = Vector2.DistanceSquared(button.Item.WorldPosition, character.WorldPosition);
//heavily prefer buttons linked to the door, so sub builders can help the bots figure out which button to use by linking them
if (door.Item.linkedTo.Contains(button.Item)) { distance *= 0.1f; }
if (closestButton == null || distance < closestDist && character.CanSeeTarget(button.Item))
if (closestButton == null || distance < closestDist)
{
closestButton = button;
closestDist = distance;
if (distance < MathUtils.Pow2(button.Item.InteractDistance + GetColliderLength()) && character.CanSeeTarget(button.Item))
{
closestButton = button;
closestDist = distance;
}
}
return true;
return closestButton != null;
});
if (canAccess)
{
@@ -741,41 +759,19 @@ namespace Barotrauma
}
else if (closestButton != null)
{
if (closestDist < MathUtils.Pow2(closestButton.Item.InteractDistance + GetColliderLength()))
if (pressButton)
{
if (pressButton)
if (closestButton.Item.TryInteract(character, forceSelectKey: true))
{
if (closestButton.Item.TryInteract(character, forceSelectKey: true))
{
lastDoor = (door, shouldBeOpen);
buttonPressTimer = shouldBeOpen ? ButtonPressCooldown : 0;
}
else
{
buttonPressTimer = 0;
}
lastDoor = (door, shouldBeOpen);
buttonPressTimer = shouldBeOpen ? ButtonPressCooldown : 0;
}
break;
}
else
{
// Can't reach the button closest to the character.
// It's possible that we could reach another buttons.
// If this becomes an issue, we could go through them here and check if any of them are reachable
// (would have to cache a collection of buttons instead of a single reference in the CanAccess filter method above)
var body = Submarine.PickBody(character.SimPosition, character.GetRelativeSimPosition(closestButton.Item), collisionCategory: Physics.CollisionWall | Physics.CollisionLevel);
if (body != null)
else
{
if (body.UserData is Item item)
{
var d = item.GetComponent<Door>();
if (d == null || d.IsOpen) { return; }
}
// The button is on the wrong side of the door or a wall
currentPath.Unreachable = true;
buttonPressTimer = 0;
}
return;
}
break;
}
}
else if (shouldBeOpen)
@@ -796,10 +792,9 @@ namespace Barotrauma
float? penalty = GetSingleNodePenalty(nextNode);
if (penalty == null) { return null; }
bool nextNodeAboveWaterLevel = nextNode.Waypoint.CurrentHull != null && nextNode.Waypoint.CurrentHull.Surface < nextNode.Waypoint.Position.Y;
//non-humanoids can't climb up ladders
if (!(character.AnimController is HumanoidAnimController))
if (!character.CanClimb)
{
if (node.Waypoint.Ladders != null && nextNode.Waypoint.Ladders != null && (!nextNode.Waypoint.Ladders.Item.IsInteractable(character) || character.LockHands)||
if (node.Waypoint.Ladders != null && nextNode.Waypoint.Ladders != null && (!nextNode.Waypoint.Ladders.Item.IsInteractable(character) || character.LockHands) ||
(nextNode.Position.Y - node.Position.Y > 1.0f && //more than one sim unit to climb up
nextNodeAboveWaterLevel)) //upper node not underwater
{
@@ -847,7 +842,7 @@ namespace Barotrauma
if (!node.Waypoint.IsTraversable) { return null; }
if (node.IsBlocked()) { return null; }
float penalty = 0.0f;
if (node.Waypoint.ConnectedGap != null && node.Waypoint.ConnectedGap.Open < 0.9f)
if (node.Waypoint.ConnectedGap is { Open: < 0.9f })
{
var door = node.Waypoint.ConnectedDoor;
if (door == null)
@@ -858,19 +853,29 @@ namespace Barotrauma
{
if (!CanAccessDoor(door, button =>
{
// Ignore buttons that are on the wrong side of the door
if (Vector2.DistanceSquared(door.Item.WorldPosition, button.Item.WorldPosition) > MathUtils.Pow2(button.Item.InteractDistance + GetColliderLength()))
{
// Too far from the door.
return false;
}
if (!ISpatialEntity.IsTargetVisible(button.Item, door.Item))
{
// Obstructed.
return false;
}
// Ignore buttons that are on the wrong side of the door, unless there's a motion sensor connected to the door, which can be triggered by the character.
if (door.IsHorizontal)
{
if (Math.Sign(button.Item.WorldPosition.Y - door.Item.WorldPosition.Y) != Math.Sign(character.WorldPosition.Y - door.Item.WorldPosition.Y))
{
return false;
return door.Item.GetDirectlyConnectedComponent<MotionSensor>() is MotionSensor ms && ms.TriggersOn(character);
}
}
else
{
if (Math.Sign(button.Item.WorldPosition.X - door.Item.WorldPosition.X) != Math.Sign(character.WorldPosition.X - door.Item.WorldPosition.X))
{
return false;
return door.Item.GetDirectlyConnectedComponent<MotionSensor>() is MotionSensor ms && ms.TriggersOn(character);
}
}
return true;