Release 1.10.5.0 - Autumn Update 2025

This commit is contained in:
Regalis11
2025-09-17 13:44:21 +03:00
parent d13836ce87
commit caa0326cf8
120 changed files with 2584 additions and 635 deletions
@@ -1,5 +1,6 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
namespace Barotrauma.Items.Components
@@ -197,7 +198,16 @@ namespace Barotrauma.Items.Components
item.Drop(CurrentThrower, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer);
item.WaterDragCoefficient = WaterDragCoefficient;
item.body.ApplyLinearImpulse(throwVector * ThrowForce * item.body.Mass * 3.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
float throwForce = ThrowForce;
//Reduce force when aiming down
float downwardsDotProduct = Vector2.Dot(-Vector2.UnitY, throwVector); //1 when pointing directly down, 0 when sideways, -1 when up
if (downwardsDotProduct > 0)
{
throwForce *= (1.0f - downwardsDotProduct * 0.7f);
}
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
//disable platform collisions until the item comes back to rest again
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
@@ -483,6 +483,9 @@ namespace Barotrauma.Items.Components
public virtual bool UpdateWhenInactive => false;
[Serialize(false, IsPropertySaveable.No, "If true, the component will retain its normal functionality when the item reaches 0 condition.")]
public bool UpdateWhenBroken { get; set; }
//called when isActive is true and condition > 0.0f
public virtual void Update(float deltaTime, Camera cam)
{
@@ -132,6 +132,12 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(true, IsPropertySaveable.No, description: "Should a button that allows sorting the items alphabetically be shown in the container's UI panel?")]
public bool ShowSortButton { get; set; }
[Serialize(true, IsPropertySaveable.No, description: "Should a button that merges items into stacks be shown in the container's UI panel?")]
public bool ShowMergeButton { get; set; }
[Serialize(true, IsPropertySaveable.Yes, description: "When this item is equipped, and you 'quick use' (double click / equip button) another equippable item, should the game attempt to move that item inside this one?")]
public bool QuickUseMovesItemsInside { get; set; }
@@ -406,6 +406,7 @@ namespace Barotrauma.Items.Components
if (IsOutOfPower()) { return false; }
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
if (IsToggle && (activator == null || lastUsed < Timing.TotalTime - 0.1))
{
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
@@ -421,8 +422,7 @@ namespace Barotrauma.Items.Components
item.SendSignal(new Signal(output, sender: user), "trigger_out");
}
lastUsed = Timing.TotalTime;
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
lastUsed = Timing.TotalTime;
return true;
}
@@ -541,6 +541,7 @@ namespace Barotrauma.Items.Components
#if CLIENT
PlaySound(ActionType.OnUse, picker);
#endif
ApplyStatusEffects(ActionType.OnUse, 1f, picker);
return true;
}
@@ -84,7 +84,10 @@ namespace Barotrauma.Items.Components
CurrFlow = 0.0f;
}
private void GetVents()
/// <summary>
/// Finds all the linked vents and calculates how much oxygen should be distributed to each of them based on the hull volumes.
/// </summary>
public void GetVents()
{
totalHullVolume = 0.0f;
ventList ??= new List<(Vent vent, float hullVolume)>();
@@ -2,6 +2,7 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -35,7 +36,7 @@ namespace Barotrauma.Items.Components
{
get
{
if (item.ConditionPercentage > 10.0f || !IsActive) { return 0.0f; }
if (item.ConditionPercentage > 10.0f || !IsActive || Disabled) { return 0.0f; }
return (1.0f - item.ConditionPercentage / 10.0f) * 100.0f;
}
}
@@ -61,6 +62,23 @@ namespace Barotrauma.Items.Components
set => maxFlow = value;
}
private bool disabled;
[Serialize(false, IsPropertySaveable.Yes, description: "If true, the pump is unable to pump water.", alwaysUseInstanceValues: true)]
public bool Disabled
{
get => disabled;
set
{
if (disabled == value) { return; }
disabled = value;
#if SERVER
//send a network update soon
//don't force to 0 though so this doesn't lead to spam if the property is toggled rapidly
networkUpdateTimer = Math.Min(networkUpdateTimer, 0.5f);
#endif
}
}
[Editable, Serialize(true, IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
public bool IsOn
{
@@ -68,15 +86,13 @@ namespace Barotrauma.Items.Components
set { IsActive = value; }
}
[Serialize(false, IsPropertySaveable.No)]
public bool CanCauseLethalPressure { get; set; }
private float currFlow;
public float CurrFlow
{
get
{
if (!IsActive) { return 0.0f; }
return Math.Abs(currFlow);
}
}
public float CurrFlow => IsActive ? Math.Abs(currFlow) : 0.0f;
public bool IsHullFull => item.CurrentHull != null && item.CurrentHull.WaterVolume >= item.CurrentHull.Volume * Hull.MaxCompress;
public override bool HasPower => IsActive && Voltage >= MinVoltage;
public bool IsAutoControlled => pumpSpeedLockTimer > 0.0f || isActiveLockTimer > 0.0f;
@@ -85,7 +101,7 @@ namespace Barotrauma.Items.Components
public override bool UpdateWhenInactive => true;
public float CurrentStress => Math.Abs(flowPercentage / 100.0f);
public float CurrentStress => IsActive ? Math.Abs(flowPercentage / 100.0f) : 0.0f;
public Pump(Item item, ContentXElement element)
: base(item, element)
@@ -95,48 +111,42 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific(ContentXElement element);
private readonly List<Hull> linkedHulls = [];
public override void Update(float deltaTime, Camera cam)
{
pumpSpeedLockTimer -= deltaTime;
isActiveLockTimer -= deltaTime;
if (!IsActive)
currFlow = 0f;
if (item.CurrentHull == null)
{
if (TargetLevel != null) { FlowPercentage = 0f; }
return;
}
currFlow = 0.0f;
if (TargetLevel != null)
{
float hullPercentage = 0.0f;
if (item.CurrentHull != null)
float hullWaterVolume = item.CurrentHull.WaterVolume;
float totalHullVolume = item.CurrentHull.Volume;
linkedHulls.Clear();
//hidden hulls still affect buoyancy, include them here
item.CurrentHull.GetLinkedHulls(linkedHulls, includeHiddenHulls: true);
foreach (var linkedHull in linkedHulls)
{
float hullWaterVolume = item.CurrentHull.WaterVolume;
float totalHullVolume = item.CurrentHull.Volume;
foreach (var linked in item.CurrentHull.linkedTo)
{
if ((linked is Hull linkedHull))
{
hullWaterVolume += linkedHull.WaterVolume;
totalHullVolume += linkedHull.Volume;
}
}
hullPercentage = hullWaterVolume / totalHullVolume * 100.0f;
hullWaterVolume += linkedHull.WaterVolume;
totalHullVolume += linkedHull.Volume;
}
float hullPercentage = hullWaterVolume / totalHullVolume * 100.0f;
FlowPercentage = ((float)TargetLevel - hullPercentage) * 10.0f;
}
if (!HasPower)
{
return;
}
UpdateNetworking(deltaTime);
UpdateProjSpecific(deltaTime);
ApplyStatusEffects(ActionType.OnActive, deltaTime);
if (item.CurrentHull == null) { return; }
if (!IsActive || Disabled) { return; }
if (flowPercentage <= 0f && item.CurrentHull.WaterVolume <= 0f) { return; }
float powerFactor = Math.Min(currPowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
@@ -150,8 +160,22 @@ namespace Barotrauma.Items.Components
//less effective when in a bad condition
currFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / item.MaxCondition);
item.CurrentHull.WaterVolume += currFlow * deltaTime * Timing.FixedUpdateRate;
if (item.CurrentHull.WaterVolume > item.CurrentHull.Volume) { item.CurrentHull.Pressure += 30.0f * deltaTime; }
if (MathUtils.NearlyEqual(currFlow, 0f, epsilon: 0.01f))
{
currFlow = 0f; // Set to 0 for conditionals.
return;
}
item.CurrentHull.WaterVolume += currFlow * deltaTime * Timing.FixedUpdateRate;
if (flowPercentage > 0f && item.CurrentHull.WaterVolume > item.CurrentHull.Volume)
{
item.CurrentHull.Pressure += 30f * deltaTime;
if (CanCauseLethalPressure) { item.CurrentHull.LethalPressure += Hull.PressureBuildUpSpeed * deltaTime; }
}
ApplyStatusEffects(ActionType.OnActive, deltaTime);
UpdateProjSpecific(deltaTime);
}
public void InfectBallast(Identifier identifier, bool allowMultiplePerShip = false)
@@ -188,7 +212,7 @@ namespace Barotrauma.Items.Components
public override float GetCurrentPowerConsumption(Connection connection = null)
{
//There shouldn't be other power connections to this
if (connection != this.powerIn || !IsActive)
if (connection != this.powerIn || !IsActive || Disabled)
{
return 0;
}
@@ -202,6 +226,8 @@ namespace Barotrauma.Items.Components
partial void UpdateProjSpecific(float deltaTime);
partial void UpdateNetworking(float deltaTime);
public override void ReceiveSignal(Signal signal, Connection connection)
{
if (Hijacked) { return; }
@@ -276,5 +302,11 @@ namespace Barotrauma.Items.Components
}
return true;
}
protected override void RemoveComponentSpecific()
{
base.RemoveComponentSpecific();
linkedHulls.Clear();
}
}
}
@@ -82,6 +82,11 @@ namespace Barotrauma.Items.Components
#if CLIENT
CreateGUI();
if (Screen.Selected is not { IsEditor: true })
{
//set text via the property to refresh the UI
Name = name;
}
#endif
}
@@ -13,10 +13,24 @@ namespace Barotrauma.Items.Components
{
partial class TriggerComponent : ItemComponent
{
[Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The maximum amount of force applied to the triggering entitites.", alwaysUseInstanceValues: true)]
[Editable, Serialize(0f, IsPropertySaveable.Yes, description: "The maximum amount of force applied to the triggering entitites.", alwaysUseInstanceValues: true)]
public float Force { get; set; }
[Editable, Serialize("0,0", IsPropertySaveable.Yes, description: "The maximum amount of directional force applied to the triggering entitites.", alwaysUseInstanceValues: true)]
public Vector2 DirectionalForce { get; set; }
[Editable, Serialize(false, IsPropertySaveable.Yes, $"If true, {nameof(DirectionalForce)} is relative to the angle between the target and the item, Similar to {nameof(Force)}.\nIf false, it always pushes in the same direction, with respect to the item's rotation.", alwaysUseInstanceValues: true)]
public bool RelativeDirectionalForce { get; set; }
[Editable, Serialize(true, IsPropertySaveable.Yes, "If false, no vertical force will be applied.", alwaysUseInstanceValues: true)]
public bool VerticalForce { get; set; }
[Editable, Serialize(true, IsPropertySaveable.Yes, "If false, no horizontal force will be applied.", alwaysUseInstanceValues: true)]
public bool HorizontalForce { get; set; }
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "Determines if the force gets higher the closer the triggerer is to the center of the trigger.", alwaysUseInstanceValues: true)]
public bool DistanceBasedForce { get; set; }
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "Determines if the force fluctuates over time or if it stays constant.", alwaysUseInstanceValues: true)]
public bool ForceFluctuation { get; set; }
@@ -141,12 +155,29 @@ namespace Barotrauma.Items.Components
get => base.IsActive;
set
{
bool wasActive = base.IsActive;
base.IsActive = value;
if (!IsActive)
{
TriggerActive = false;
triggerers.Clear();
}
else if (!wasActive && PhysicsBody?.FarseerBody != null)
{
//when the trigger becomes active, we need to check which entities are inside it
ContactEdge ce = PhysicsBody.FarseerBody.ContactList;
while (ce != null && ce.Contact != null)
{
if (ce.Contact.Enabled)
{
var thisFixture = ce.Contact.FixtureA.Body == PhysicsBody.FarseerBody ? ce.Contact.FixtureA : ce.Contact.FixtureB;
var otherFixture = ce.Contact.FixtureA.Body == PhysicsBody.FarseerBody ? ce.Contact.FixtureB : ce.Contact.FixtureA;
OnCollision(thisFixture, otherFixture, ce.Contact);
}
ce = ce.Next;
}
}
}
}
@@ -374,7 +405,9 @@ namespace Barotrauma.Items.Components
float amount = MathUtils.InverseLerp(-1.0f, 1.0f, v);
CurrentForceFluctuation = MathHelper.Lerp(1.0f - ForceFluctuationStrength, 1.0f, amount);
ForceFluctuationTimer = 0.0f;
GameMain.NetworkMember?.CreateEntityEvent(this);
#if SERVER
item.CreateServerEvent(this);
#endif
}
}
@@ -398,7 +431,7 @@ namespace Barotrauma.Items.Components
}
}
if (Math.Abs(Force) < 0.01f)
if (Force < 0.01f && DirectionalForce.LengthSquared() < 0.0001f)
{
// Just ignore very minimal forces
continue;
@@ -436,7 +469,25 @@ namespace Barotrauma.Items.Components
if (diff.LengthSquared() < 0.0001f) { return; }
float distanceFactor = DistanceBasedForce ? LevelTrigger.GetDistanceFactor(body, PhysicsBody, RadiusInDisplayUnits) : 1.0f;
if (distanceFactor <= 0.0f) { return; }
Vector2 force = distanceFactor * (CurrentForceFluctuation * Force) * Vector2.Normalize(diff) * multiplier;
Vector2 radialForce = Force * Vector2.Normalize(diff);
Vector2 directionalForce;
if (RelativeDirectionalForce)
{
directionalForce = DirectionalForce * new Vector2(Math.Sign(diff.X), Math.Sign(diff.Y));
}
else
{
Vector2 flippedForce = DirectionalForce;
if (item.FlippedX) { flippedForce.X = -flippedForce.X; }
if (item.FlippedY) { flippedForce.Y = -flippedForce.Y; }
directionalForce = MathUtils.RotatePoint(flippedForce, -item.RotationRad);
}
Vector2 force = (radialForce + directionalForce) * CurrentForceFluctuation * distanceFactor * multiplier;
if (!HorizontalForce) { force.Y = 0.0f; }
if (!VerticalForce) { force.Y = 0.0f; }
if (force.LengthSquared() < 0.01f) { return; }
if (body.Mass < 1)
{