Release 1.11.4.1 (Winter Update)
This commit is contained in:
@@ -226,6 +226,14 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsSlotEmpty(InvSlotType limbSlot)
|
||||
{
|
||||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
if (SlotTypes[i] == limbSlot && slots[i].Empty()) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can the item be put in the inventory in a slot of the specified type (i.e. is there a suitable free slot or a stack the item can be put in).
|
||||
@@ -438,7 +446,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
int placedInSlot = -1;
|
||||
foreach (InvSlotType allowedSlot in allowedSlots)
|
||||
//order by whether the slot is empty, i.e. try putting in free slots first before trying to unequip items from occupied slots
|
||||
foreach (InvSlotType allowedSlot in allowedSlots.OrderBy(slotType => IsSlotEmpty(slotType) ? 0 : 1))
|
||||
{
|
||||
if (allowedSlot.HasFlag(InvSlotType.RightHand) && character.AnimController.GetLimb(LimbType.RightHand) == null) { continue; }
|
||||
if (allowedSlot.HasFlag(InvSlotType.LeftHand) && character.AnimController.GetLimb(LimbType.LeftHand) == null) { continue; }
|
||||
|
||||
@@ -87,6 +87,13 @@ namespace Barotrauma.Items.Components
|
||||
"Normally there's no need to touch this setting, but if you notice the docking position is incorrect (for example due to some unusual docking port configuration without hulls or doors), you can use this to enforce the direction.")]
|
||||
public DirectionType ForceDockingDirection { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Was the docking port docked at the end of the previous round.")]
|
||||
public bool WasDocked
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public DockingPort DockingTarget { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -280,6 +287,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
OnDocked?.Invoke();
|
||||
OnDocked = null;
|
||||
|
||||
WasDocked = true;
|
||||
DockingTarget.Docked = true;
|
||||
}
|
||||
|
||||
public void Lock(bool isNetworkMessage, bool applyEffects = true, bool moveSubs = true)
|
||||
@@ -988,6 +998,8 @@ namespace Barotrauma.Items.Components
|
||||
Item.Submarine.EnableObstructedWaypoints(DockingTarget.Item.Submarine);
|
||||
obstructedWayPointsDisabled = false;
|
||||
|
||||
WasDocked = false;
|
||||
DockingTarget.WasDocked = false;
|
||||
DockingTarget.Undock();
|
||||
DockingTarget = null;
|
||||
|
||||
@@ -1052,6 +1064,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
//PRETTY HACKY:
|
||||
//the docking port was docked on the previous round, but not any more -
|
||||
//must mean that whatever it was docked to (e.g. some enemy sub or respawn shuttle) no longer exists
|
||||
//let's send an "on_undock" signal so circuits can react to the undocking that never "actually" happened
|
||||
if (!docked && WasDocked)
|
||||
{
|
||||
item.SendSignal("1", "on_undock");
|
||||
WasDocked = false;
|
||||
}
|
||||
|
||||
dockingCooldown -= deltaTime;
|
||||
if (DockingTarget == null)
|
||||
{
|
||||
@@ -1208,19 +1230,21 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.linkedTo.Any()) { return; }
|
||||
|
||||
List<MapEntity> linked = new List<MapEntity>(item.linkedTo);
|
||||
foreach (MapEntity entity in linked)
|
||||
{
|
||||
if (!(entity is Item linkedItem)) { continue; }
|
||||
|
||||
var dockingPort = linkedItem.GetComponent<DockingPort>();
|
||||
if (dockingPort != null)
|
||||
if (item.linkedTo.Any())
|
||||
{
|
||||
List<MapEntity> linked = new List<MapEntity>(item.linkedTo);
|
||||
foreach (MapEntity entity in linked)
|
||||
{
|
||||
Dock(dockingPort);
|
||||
}
|
||||
if (entity is not Item linkedItem) { continue; }
|
||||
|
||||
var dockingPort = linkedItem.GetComponent<DockingPort>();
|
||||
if (dockingPort != null)
|
||||
{
|
||||
Dock(dockingPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
|
||||
@@ -154,6 +154,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize("0,0", IsPropertySaveable.Yes)]
|
||||
public Point DisallowAttachingOverSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Should the item be attached to a wall by default when it's placed in the submarine editor.")]
|
||||
public bool AttachedByDefault
|
||||
{
|
||||
@@ -496,13 +503,19 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 diff = new Vector2(
|
||||
(heldHand.SimPosition.X - arm.SimPosition.X) / 2f,
|
||||
(heldHand.SimPosition.Y - arm.SimPosition.Y) / 2.5f);
|
||||
item.SetTransform(heldHand.SimPosition + diff, 0.0f);
|
||||
|
||||
//we have forced the item to be in the same sub as the dropper above,
|
||||
//and are placing it to the position of the hands in "local" coordinates
|
||||
//which may be outside the sub if the character is e.g. standing half-way through the airlock
|
||||
// -> let's use the forceSubmarine argument ensure the item is still considered to be in the sub's coordinate space,
|
||||
// or it will end up in a weird state and seemingly disappear
|
||||
item.SetTransform(heldHand.SimPosition + diff, 0.0f, forceSubmarine: picker.Submarine);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SetTransform(picker.SimPosition, 0.0f);
|
||||
}
|
||||
}
|
||||
item.SetTransform(picker.SimPosition, 0.0f, forceSubmarine: picker.Submarine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
picker.Inventory.RemoveItem(item);
|
||||
@@ -621,17 +634,34 @@ namespace Barotrauma.Items.Components
|
||||
if (disallowAttachingOverTags.Any() || !AllowAttachInsideDoors)
|
||||
{
|
||||
var connectedHulls = item.CurrentHull?.GetConnectedHulls(includingThis: true, searchDepth: 5, ignoreClosedGaps: true);
|
||||
Vector2 size = item.Rect.Size.ToVector2() / 2;
|
||||
|
||||
Vector2 size = DisallowAttachingOverSize == Point.Zero ?
|
||||
item.Rect.Size.ToVector2() :
|
||||
DisallowAttachingOverSize.ToVector2() * item.Scale;
|
||||
size /= 2f;
|
||||
|
||||
foreach (Item otherItem in Item.ItemList)
|
||||
{
|
||||
if (otherItem == item || otherItem.body is { BodyType: BodyType.Dynamic, Enabled: true }) { continue; }
|
||||
if (connectedHulls != null && !connectedHulls.Contains(otherItem.CurrentHull)) { continue; }
|
||||
if (disallowAttachingOverTags.None(tag => otherItem.HasTag(tag)) &&
|
||||
if (disallowAttachingOverTags.None(otherItem.HasTag) &&
|
||||
(otherItem.GetComponent<Door>() == null || AllowAttachInsideDoors))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Rectangle worldRect = otherItem.WorldRect;
|
||||
|
||||
if (otherItem.GetComponent<Holdable>() is Holdable otherHoldable)
|
||||
{
|
||||
if (!otherHoldable.attached) { continue; }
|
||||
if (otherHoldable.DisallowAttachingOverSize != Point.Zero)
|
||||
{
|
||||
Vector2 scaledSize = otherHoldable.DisallowAttachingOverSize.ToVector2() * item.Scale;
|
||||
worldRect = new Rectangle(
|
||||
otherItem.WorldPosition.ToPoint() - new Point((int)(scaledSize.X / 2), (int)(-scaledSize.Y / 2)),
|
||||
scaledSize.ToPoint());
|
||||
}
|
||||
}
|
||||
if (attachPos.X + size.X < worldRect.X || attachPos.X - size.X > worldRect.Right) { continue; }
|
||||
if (attachPos.Y - size.Y > worldRect.Y || attachPos.Y + size.Y < worldRect.Y - worldRect.Height) { continue; }
|
||||
tempOverlappingItems.Add(otherItem);
|
||||
|
||||
@@ -538,8 +538,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (targetEntity != null)
|
||||
{
|
||||
ApplyStatusEffects(conditionalActionType, 1.0f, targetCharacter, targetLimb, useTarget: targetEntity, user: user, afflictionMultiplier: damageMultiplier);
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter, targetLimb, useTarget: targetEntity, user: user, afflictionMultiplier: damageMultiplier);
|
||||
ApplyStatusEffects(conditionalActionType, 1.0f, targetCharacter, targetLimb, useTarget: targetEntity, user: user, attackMultiplier: damageMultiplier);
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter, targetLimb, useTarget: targetEntity, user: user, attackMultiplier: damageMultiplier);
|
||||
}
|
||||
|
||||
if (DeleteOnUse)
|
||||
|
||||
@@ -920,7 +920,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null, float afflictionMultiplier = 1.0f)
|
||||
/// <param name="attackMultiplier">Multiplier used on afflictions caused by the status effects, except ones that <see cref="AfflictionPrefab.AffectedByAttackMultipliers">have been configured to not be affected by attack multipliers.</see></param>
|
||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null, float attackMultiplier = 1.0f)
|
||||
{
|
||||
if (statusEffectLists == null) { return; }
|
||||
|
||||
@@ -932,7 +933,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (broken && !effect.AllowWhenBroken && effect.type != ActionType.OnBroken) { continue; }
|
||||
if (user != null) { effect.SetUser(user); }
|
||||
effect.AfflictionMultiplier = afflictionMultiplier;
|
||||
effect.AttackMultiplier = attackMultiplier;
|
||||
var c = character;
|
||||
if (user != null && effect.HasTargetType(StatusEffect.TargetType.Character) && !effect.HasTargetType(StatusEffect.TargetType.UseTarget))
|
||||
{
|
||||
@@ -940,7 +941,7 @@ namespace Barotrauma.Items.Components
|
||||
c = user;
|
||||
}
|
||||
item.ApplyStatusEffect(effect, type, deltaTime, c, targetLimb, useTarget, isNetworkEvent: false, checkCondition: false, worldPosition);
|
||||
effect.AfflictionMultiplier = 1.0f;
|
||||
effect.AttackMultiplier = 1.0f;
|
||||
reducesCondition |= effect.ReducesItemCondition();
|
||||
}
|
||||
//if any of the effects reduce the item's condition, set the user for OnBroken effects as well
|
||||
|
||||
@@ -832,7 +832,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public float FabricationDegreeOfSuccess(Character character, ImmutableArray<Skill> skills)
|
||||
{
|
||||
if (skills.Length == 0) { return 1.0f; }
|
||||
if (skills.Length == 0) { return 0.5f; }
|
||||
if (character == null) { return 0.0f; }
|
||||
|
||||
float minDegreeOfSuccess = 1.0f;
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes the item inherit the condition from a linked wall or multiple - or in other words, makes it essentially treat the health of the wall as its own health.
|
||||
/// The wall section with the most damage determines the condition (i.e. the item will be fully broken if there's at least one fully broken wall section).
|
||||
/// </summary>
|
||||
class InheritConditionFromLinkedWall(Item item, ContentXElement element) : ItemComponent(item, element)
|
||||
{
|
||||
private readonly List<Structure> linkedWalls = [];
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
foreach (var linkedTo in item.linkedTo)
|
||||
{
|
||||
if (linkedTo is Structure structure &&
|
||||
structure.HasBody)
|
||||
{
|
||||
linkedWalls.Add(structure);
|
||||
structure.OnHealthChanged += (_, _) => UpdateCondition();
|
||||
}
|
||||
}
|
||||
if (linkedWalls.None())
|
||||
{
|
||||
DebugConsole.AddWarning($"The item {item.Name} ({item.Prefab.Identifier}) is not linked to any walls with a physics body. The {nameof(InheritConditionFromLinkedWall)} component will do nothing.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void UpdateCondition()
|
||||
{
|
||||
float lowestHealthPercent = 1.0f;
|
||||
foreach (var wall in linkedWalls)
|
||||
{
|
||||
foreach (var section in wall.Sections)
|
||||
{
|
||||
lowestHealthPercent = Math.Min(lowestHealthPercent, 1.0f - section.damage / wall.MaxHealth);
|
||||
}
|
||||
}
|
||||
item.Condition = item.MaxCondition * lowestHealthPercent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,7 @@ namespace Barotrauma.Items.Components
|
||||
item.CurrentHull.GetLinkedHulls(linkedHulls, includeHiddenHulls: true);
|
||||
foreach (var linkedHull in linkedHulls)
|
||||
{
|
||||
if (linkedHull == item.CurrentHull) { continue; }
|
||||
hullWaterVolume += linkedHull.WaterVolume;
|
||||
totalHullVolume += linkedHull.Volume;
|
||||
}
|
||||
@@ -148,7 +149,7 @@ namespace Barotrauma.Items.Components
|
||||
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);
|
||||
float powerFactor = Math.Min(PowerConsumption <= 0.0f || MinVoltage <= 0.0f ? 1.0f : Voltage, MaxOverVoltageFactor);
|
||||
|
||||
currFlow = flowPercentage / 100.0f * MaxFlow * powerFactor;
|
||||
if (item.GetComponent<Repairable>() is { IsTinkering: true } repairable)
|
||||
|
||||
@@ -247,9 +247,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
bool fissionRateControlledBySignals = signalControlledTargetFissionRate.HasValue && lastReceivedFissionRateSignalTime > Timing.TotalTime - 1;
|
||||
bool turbineOutputRateControlledBySignals = signalControlledTargetTurbineOutput.HasValue && lastReceivedTurbineOutputSignalTime > Timing.TotalTime - 1;
|
||||
|
||||
//rapidly adjust the reactor in the first few seconds of the round to prevent overvoltages if the load changed between rounds
|
||||
//(unless the reactor is being operated by a player)
|
||||
if (GameMain.GameSession is { RoundDuration: <5 } && lastUser is not { IsPlayer: true })
|
||||
if (GameMain.GameSession is { RoundDuration: < 5 } && lastUser is not { IsPlayer: true } && PowerOn && AutoTemp &&
|
||||
!fissionRateControlledBySignals && !turbineOutputRateControlledBySignals)
|
||||
{
|
||||
UpdateAutoTemp(100.0f, (float)(Timing.Step * 10.0f));
|
||||
}
|
||||
@@ -263,7 +267,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float maxPowerOut = GetMaxOutput();
|
||||
|
||||
if (signalControlledTargetFissionRate.HasValue && lastReceivedFissionRateSignalTime > Timing.TotalTime - 1)
|
||||
if (fissionRateControlledBySignals)
|
||||
{
|
||||
TargetFissionRate = adjustValueWithoutOverShooting(TargetFissionRate, signalControlledTargetFissionRate.Value, deltaTime * 5.0f);
|
||||
#if CLIENT
|
||||
@@ -274,7 +278,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
signalControlledTargetFissionRate = null;
|
||||
}
|
||||
if (signalControlledTargetTurbineOutput.HasValue && lastReceivedTurbineOutputSignalTime > Timing.TotalTime - 1)
|
||||
if (turbineOutputRateControlledBySignals)
|
||||
{
|
||||
TargetTurbineOutput = adjustValueWithoutOverShooting(TargetTurbineOutput, signalControlledTargetTurbineOutput.Value, deltaTime * 5.0f);
|
||||
#if CLIENT
|
||||
|
||||
@@ -641,8 +641,7 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < hits.Count; i++)
|
||||
{
|
||||
var h = hits[i];
|
||||
item.SetTransform(h.Point, rotation);
|
||||
item.Submarine = h.Submarine;
|
||||
item.SetTransform(h.Point, rotation, forceSubmarine: h.Submarine);
|
||||
item.UpdateTransform();
|
||||
if (HandleProjectileCollision(h.Fixture, h.Normal, Vector2.Zero))
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Barotrauma.Items.Components
|
||||
var inputBuilder = ImmutableArray.CreateBuilder<CircuitBoxInputConnection>();
|
||||
var outputBuilder = ImmutableArray.CreateBuilder<CircuitBoxOutputConnection>();
|
||||
|
||||
foreach (Connection conn in Item.Connections)
|
||||
foreach (Connection conn in Item.Connections.OrderBy(static c => c.DisplayOrder))
|
||||
{
|
||||
if (conn.IsOutput)
|
||||
{
|
||||
@@ -236,9 +236,7 @@ namespace Barotrauma.Items.Components
|
||||
cloneNode.ReplaceAllConnectionLabelOverrides(origNode.ConnectionLabelOverrides);
|
||||
}
|
||||
|
||||
if (!clonedContainedItems.Any()) { return; }
|
||||
|
||||
foreach (var origComp in original.Components)
|
||||
foreach (CircuitBoxComponent origComp in original.Components)
|
||||
{
|
||||
if (!clonedContainedItems.TryGetValue(origComp.Item.ID, out var clonedItem)) { continue; }
|
||||
var newComponent = new CircuitBoxComponent(origComp.ID, clonedItem, origComp.Position, this, origComp.UsedResource);
|
||||
@@ -661,6 +659,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
wire.From.Connection.CircuitBoxConnections.Remove(wire.To);
|
||||
wire.To.Connection.CircuitBoxConnections.Remove(wire.From);
|
||||
|
||||
if (wire.From is CircuitBoxInputConnection input)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Barotrauma.Items.Components
|
||||
//how many wires can be linked to this connection in total
|
||||
public readonly int MaxWires = 5;
|
||||
|
||||
public readonly int DisplayOrder;
|
||||
|
||||
public readonly string Name;
|
||||
private readonly LocalizedString _displayName;
|
||||
public LocalizedString DisplayName
|
||||
@@ -92,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
return "Connection (" + item.Name + ", " + Name + ")";
|
||||
}
|
||||
|
||||
public Connection(ContentXElement element, ConnectionPanel connectionPanel, IdRemap idRemap)
|
||||
public Connection(ContentXElement element, int connectionIndex, ConnectionPanel connectionPanel, IdRemap idRemap, bool isItemSwap)
|
||||
{
|
||||
|
||||
#if CLIENT
|
||||
@@ -117,25 +119,44 @@ namespace Barotrauma.Items.Components
|
||||
IsOutput = element.Name.ToString() == "output";
|
||||
Name = element.GetAttributeString("name", IsOutput ? "output" : "input");
|
||||
|
||||
int displayOrder;
|
||||
if (element.GetAttribute("displayorderoverride") is not { } displayOrderAttr)
|
||||
{
|
||||
var sameElements = connectionPanel.Connections.Where(c => c.IsOutput == IsOutput);
|
||||
displayOrder = !sameElements.Any() ? 0 : sameElements.Max(static c => c.DisplayOrder) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayOrder = displayOrderAttr.GetAttributeInt(0);
|
||||
}
|
||||
|
||||
DisplayOrder = displayOrder;
|
||||
|
||||
string displayNameTag = "", fallbackTag = "";
|
||||
//if displayname is not present, attempt to find it from the prefab
|
||||
if (element.GetAttribute("displayname") == null)
|
||||
{
|
||||
foreach (var subElement in item.Prefab.ConfigElement.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("connectionpanel", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
|
||||
if (!subElement.Name.ToString().Equals("connectionpanel", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
int prefabConnectionIndex = 0;
|
||||
foreach (XElement connectionElement in subElement.Elements())
|
||||
{
|
||||
string prefabConnectionName = connectionElement.GetAttributeString("name", null);
|
||||
if (prefabConnectionName.IsNullOrEmpty()) { continue; }
|
||||
|
||||
string[] aliases = connectionElement.GetAttributeStringArray("aliases", Array.Empty<string>());
|
||||
if (prefabConnectionName == Name || aliases.Contains(Name))
|
||||
if (prefabConnectionName == Name || aliases.Contains(Name) ||
|
||||
//when swapping items, we move wires based on the order of the connections, not the names
|
||||
//= we should find a connection based on the index if the name doesn't match
|
||||
(isItemSwap && connectionIndex == prefabConnectionIndex))
|
||||
{
|
||||
displayNameTag = connectionElement.GetAttributeString("displayname", "");
|
||||
fallbackTag = connectionElement.GetAttributeString("fallbackdisplayname", "");
|
||||
}
|
||||
prefabConnectionIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString())
|
||||
{
|
||||
case "input":
|
||||
Connections.Add(new Connection(subElement, this, IdRemap.DiscardId));
|
||||
Connections.Add(new Connection(subElement, connectionIndex: Connections.Count, this, IdRemap.DiscardId, isItemSwap: false));
|
||||
break;
|
||||
case "output":
|
||||
Connections.Add(new Connection(subElement, this, IdRemap.DiscardId));
|
||||
Connections.Add(new Connection(subElement, connectionIndex: Connections.Count, this, IdRemap.DiscardId, isItemSwap: false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -293,10 +293,10 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString())
|
||||
{
|
||||
case "input":
|
||||
loadedConnections.Add(new Connection(subElement, this, idRemap));
|
||||
loadedConnections.Add(new Connection(subElement, connectionIndex: loadedConnections.Count, this, idRemap, isItemSwap));
|
||||
break;
|
||||
case "output":
|
||||
loadedConnections.Add(new Connection(subElement, this, idRemap));
|
||||
loadedConnections.Add(new Connection(subElement, connectionIndex: loadedConnections.Count, this, idRemap, isItemSwap));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-2
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -7,7 +8,7 @@ namespace Barotrauma.Items.Components;
|
||||
/// <summary>
|
||||
/// Base class for signal components that can select between input/output connections (e.g. multiplexer and demultiplexer components)
|
||||
/// </summary>
|
||||
abstract class ConnectionSelectorComponent : ItemComponent
|
||||
abstract partial class ConnectionSelectorComponent : ItemComponent, IServerSerializable
|
||||
{
|
||||
protected int selectedConnectionIndex;
|
||||
protected string selectedConnectionIndexStr;
|
||||
@@ -22,6 +23,8 @@ abstract class ConnectionSelectorComponent : ItemComponent
|
||||
get { return selectedConnectionIndex; }
|
||||
set
|
||||
{
|
||||
int prevIndex = selectedConnectionIndex; // store original, so we know if the state has changed and can sync it in MP
|
||||
|
||||
selectedConnectionIndex = Math.Max(0, value);
|
||||
//don't clamp until we've determined how many connections the item has
|
||||
//(can't be done until the connection panel component has been loaded too)
|
||||
@@ -31,6 +34,11 @@ abstract class ConnectionSelectorComponent : ItemComponent
|
||||
}
|
||||
selectedConnectionName = GetConnectionName(selectedConnectionIndex);
|
||||
selectedConnectionIndexStr = selectedConnectionIndex.ToString();
|
||||
|
||||
if (prevIndex != selectedConnectionIndex)
|
||||
{
|
||||
OnStateChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +63,8 @@ abstract class ConnectionSelectorComponent : ItemComponent
|
||||
{
|
||||
}
|
||||
|
||||
partial void OnStateChanged();
|
||||
|
||||
protected abstract string GetConnectionName(int connectionIndex);
|
||||
|
||||
/// <summary>
|
||||
|
||||
+14
-10
@@ -63,10 +63,7 @@ namespace Barotrauma.Items.Components
|
||||
/// This can be used to make them additionally work the other way around, periodically getting the current value of the property from the item and refreshing the UI.
|
||||
/// </summary>
|
||||
public float GetValueInterval { get; set; } = -1.0f;
|
||||
|
||||
#if CLIENT
|
||||
public float GetValueTimer;
|
||||
#endif
|
||||
|
||||
public string Name => "CustomInterfaceElement";
|
||||
|
||||
@@ -248,7 +245,7 @@ namespace Barotrauma.Items.Components
|
||||
ciElement.Label = "Signal out " + customInterfaceElementList.Count(e => e.ContinuousSignal == ciElement.ContinuousSignal);
|
||||
}
|
||||
customInterfaceElementList.Add(ciElement);
|
||||
IsActive |= ciElement.ContinuousSignal;
|
||||
IsActive |= ciElement.ContinuousSignal || ciElement.GetValueInterval > 0.0f;
|
||||
}
|
||||
|
||||
InitProjSpecific();
|
||||
@@ -348,13 +345,10 @@ namespace Barotrauma.Items.Components
|
||||
//make sure the clients know about the states of the checkboxes and text fields
|
||||
if (customInterfaceElementList.Any())
|
||||
{
|
||||
if (item.FullyInitialized)
|
||||
CoroutineManager.Invoke(() =>
|
||||
{
|
||||
CoroutineManager.Invoke(() =>
|
||||
{
|
||||
if (!item.Removed) { item.CreateServerEvent(this); }
|
||||
}, delay: 0.1f);
|
||||
}
|
||||
if (item.FullyInitialized && !item.Removed) { item.CreateServerEvent(this); }
|
||||
}, delay: 0.1f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -418,6 +412,16 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
|
||||
{
|
||||
if (ciElement.GetValueInterval > 0.0f)
|
||||
{
|
||||
ciElement.GetValueTimer -= deltaTime;
|
||||
if (ciElement.GetValueTimer <= 0.0f)
|
||||
{
|
||||
SetSignalToPropertyValue(ciElement);
|
||||
ciElement.GetValueTimer = ciElement.GetValueInterval;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ciElement.ContinuousSignal && ciElement.PropertyName != "Voltage") { continue; }
|
||||
//TODO: allow changing output when a tickbox is not selected
|
||||
if (!string.IsNullOrEmpty(ciElement.Signal) && ciElement.Connection != null)
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f, DecimalCount = 2), Serialize(0.0f, IsPropertySaveable.Yes, description: "How much light pulsates (in Hz). 0 = not at all, 1 = alternates between full brightness and off.")]
|
||||
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 1.0f, DecimalCount = 2), Serialize(0.0f, IsPropertySaveable.Yes, description: "How much light pulsates. 0 = not at all, 1 = alternates between full brightness and off.")]
|
||||
public float PulseAmount
|
||||
{
|
||||
get { return pulseAmount; }
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace Barotrauma.Items.Components
|
||||
public float RotationSpeedHighSkill { get; private set; }
|
||||
|
||||
[Serialize("0,0,0,0", IsPropertySaveable.Yes, description: "Optional screen tint color when the item is being operated (R,G,B,A)."),
|
||||
Editable]
|
||||
Editable(TransferToSwappedItem = true)]
|
||||
public Color HudTint { get; set; }
|
||||
|
||||
[Header(localizedTextTag: "sp.turret.AutoOperate.propertyheader")]
|
||||
|
||||
@@ -461,10 +461,25 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public float ImpactTolerance => Prefab.ImpactTolerance;
|
||||
private float impactTolerance;
|
||||
[Serialize(0.0f, IsPropertySaveable.No), ConditionallyEditable(ConditionallyEditable.ConditionType.ReceivesSubmarineImpacts, MinValueFloat = 0, MaxValueFloat = 100)]
|
||||
public float ImpactTolerance
|
||||
{
|
||||
get { return impactTolerance; }
|
||||
set { impactTolerance = Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
public float ImpactDamage => Prefab.ImpactDamage;
|
||||
public float ImpactDamageProbability => Prefab.ImpactDamageProbability;
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "The amount of damage the item takes from impacts. Acts as a multiplier on the strength of the impact. Note that ImpactTolerance must be set for impacts to register."),
|
||||
ConditionallyEditable(ConditionallyEditable.ConditionType.ReceivesSubmarineImpacts, MinValueFloat = 0, MaxValueFloat = 100)]
|
||||
public float ImpactDamage { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Probability for impacts to register. Defaults to 1. Note that ImpactTolerance must also be set for impacts to register."),
|
||||
ConditionallyEditable(ConditionallyEditable.ConditionType.ReceivesSubmarineImpacts, MinValueFloat = 0, MaxValueFloat = 1)]
|
||||
public float ImpactDamageProbability { get; set; }
|
||||
|
||||
public const float SubmarineImpactCooldown = 0.1f;
|
||||
|
||||
public double LastSubmarineImpactTime;
|
||||
|
||||
public float InteractDistance => Prefab.InteractDistance;
|
||||
|
||||
@@ -1556,7 +1571,7 @@ namespace Barotrauma
|
||||
if (!updateableComponents.Contains(component))
|
||||
{
|
||||
updateableComponents.Add(component);
|
||||
this.isActive = true;
|
||||
this.IsActive = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1647,7 +1662,19 @@ namespace Barotrauma
|
||||
contained.Container = null;
|
||||
}
|
||||
|
||||
public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true, bool setPrevTransform = true)
|
||||
/// <summary>
|
||||
/// Sets the position and rotation of the item, and its physics body if it has one.
|
||||
/// </summary>
|
||||
/// <param name="simPosition">Position in simulation units.</param>
|
||||
/// <param name="rotation">Rotation in radians</param>
|
||||
/// <param name="findNewHull">Should the hull the item is inside be immediately updated? Generally only useful to set to false
|
||||
/// for performance reasons when finding the hull is unnecessary (e.g. if it's being forced to something after setting the transform).</param>
|
||||
/// <param name="setPrevTransform">Should the previous transform of the item be immediately set to the new one?
|
||||
/// The previous transform is used to interpolate draw positions/rotations, and you should generally only set this to false if
|
||||
/// you're trying to simulate movement instead of simply teleporting the item somewhere.</param>
|
||||
/// <param name="forceSubmarine">If you know the position is in a specific sub's coordinate space and want to ensure the item
|
||||
/// is still considered to be in that sub even if the transform ended up outside hulls.</param>
|
||||
public void SetTransform(Vector2 simPosition, float rotation, bool findNewHull = true, bool setPrevTransform = true, Submarine forceSubmarine = null)
|
||||
{
|
||||
if (!MathUtils.IsValid(simPosition))
|
||||
{
|
||||
@@ -1685,6 +1712,7 @@ namespace Barotrauma
|
||||
rect.Y = (int)MathF.Round(displayPos.Y + rect.Height / 2.0f);
|
||||
|
||||
if (findNewHull) { FindHull(); }
|
||||
if (forceSubmarine != null) { Submarine = forceSubmarine; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1856,7 +1884,7 @@ namespace Barotrauma
|
||||
if (newRootContainer != RootContainer)
|
||||
{
|
||||
RootContainer = newRootContainer;
|
||||
isActive = true;
|
||||
IsActive = true;
|
||||
foreach (Item containedItem in ContainedItems)
|
||||
{
|
||||
containedItem.RefreshRootContainer();
|
||||
@@ -2371,12 +2399,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private bool isActive = true;
|
||||
/// <summary>
|
||||
/// Inactive items are not updated. Note that actions such as dropping can reactivate the item, and that the item can go inactive by itself if it no longer needs updating;
|
||||
/// </summary>
|
||||
public bool IsActive = true;
|
||||
|
||||
public bool IsInRemoveQueue;
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!isActive || IsLayerHidden || IsInRemoveQueue) { return; }
|
||||
if (!IsActive || IsLayerHidden || IsInRemoveQueue) { return; }
|
||||
|
||||
if (impactQueue != null)
|
||||
{
|
||||
@@ -2542,7 +2574,7 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
positionBuffer.Clear();
|
||||
#endif
|
||||
isActive = false;
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2703,7 +2735,7 @@ namespace Barotrauma
|
||||
impactQueue.Enqueue(impact);
|
||||
}
|
||||
|
||||
isActive = true;
|
||||
IsActive = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3484,7 +3516,7 @@ namespace Barotrauma
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
isActive = true;
|
||||
IsActive = true;
|
||||
body.Enabled = true;
|
||||
body.PhysEnabled = true;
|
||||
body.ResetDynamics();
|
||||
@@ -3624,7 +3656,7 @@ namespace Barotrauma
|
||||
item.body.Enabled = item.body.PhysEnabled = isFirst;
|
||||
if (isFirst)
|
||||
{
|
||||
item.isActive = true;
|
||||
item.IsActive = true;
|
||||
item.body.ResetDynamics();
|
||||
}
|
||||
}
|
||||
@@ -4385,13 +4417,18 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var connection in thisConnectionPanel.Connections)
|
||||
{
|
||||
var newConnection = newConnectionPanel.Connections.FirstOrDefault(c => c.Name == connection.Name);
|
||||
if (newConnection == null) { continue; }
|
||||
foreach (var wire in connection.Wires)
|
||||
{
|
||||
int connectionIndex = wire.Connections.IndexOf(connection);
|
||||
int wireConnectionIndex = wire.Connections.IndexOf(connection);
|
||||
wire.RemoveConnection(this);
|
||||
wire.Connect(newConnection, connectionIndex, addNode: false);
|
||||
int thisConnectionIndex = connection.ConnectionPanel.Connections.IndexOf(connection);
|
||||
if (thisConnectionIndex < 0 || thisConnectionIndex >= newConnectionPanel.Connections.Count)
|
||||
{
|
||||
DebugConsole.AddWarning($"Failed to move a wire from the connection {connection.Name} when swapping the item {Name} with {newItem.Name}. The new item probably does not have the same number of connections as the previous one.");
|
||||
continue;
|
||||
}
|
||||
Connection newConnection = newConnectionPanel.Connections[thisConnectionIndex];
|
||||
wire.Connect(newConnection, wireConnectionIndex, addNode: false);
|
||||
newConnection.ConnectWire(wire);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,20 +813,6 @@ namespace Barotrauma
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool DamagedByMonsters { get; private set; }
|
||||
|
||||
private float impactTolerance;
|
||||
[Serialize(0.0f, IsPropertySaveable.No)]
|
||||
public float ImpactTolerance
|
||||
{
|
||||
get { return impactTolerance; }
|
||||
set { impactTolerance = Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.No, description: "The amount of damage the item takes from impacts. Acts as a multiplier on the strength of the impact. Note that ImpactTolerance must be set for impacts to register.")]
|
||||
public float ImpactDamage { get; set; }
|
||||
|
||||
[Serialize(1.0f, IsPropertySaveable.No, description: "Probability for impacts to register. Defaults to 1. Note that ImpactTolerance must also be set for impacts to register.")]
|
||||
public float ImpactDamageProbability { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, "If true, submarine impacts will trigger OnImpact effects. Only applies to items with a null or non-dynamic physics body - items with dynamic bodies always react to impacts.")]
|
||||
public bool ReceiveSubmarineImpacts { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user