38f1ddb...178a853: v0.8.9.1, removed content folder

This commit is contained in:
Joonas Rikkonen
2019-03-18 19:46:58 +02:00
parent 38f1ddb6fe
commit 6c0679c297
1054 changed files with 151673 additions and 144931 deletions
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
@@ -14,7 +15,7 @@ namespace Barotrauma.Items.Components
//the output is sent if both inputs have received a signal within the timeframe
protected float timeFrame;
[InGameEditable, Serialize(0.0f, true)]
[InGameEditable(DecimalCount = 2), Serialize(0.0f, true)]
public float TimeFrame
{
get { return timeFrame; }
@@ -46,16 +47,16 @@ namespace Barotrauma.Items.Components
}
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
case "signal_in1":
float.TryParse(signal, out receivedSignal[0]);
float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]);
timeSinceReceived[0] = 0.0f;
break;
case "signal_in2":
float.TryParse(signal, out receivedSignal[1]);
float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]);
timeSinceReceived[1] = 0.0f;
break;
}
@@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components
//the output is sent if both inputs have received a signal within the timeframe
protected float timeFrame;
[InGameEditable, Serialize(0.0f, true)]
[InGameEditable(DecimalCount = 2), Serialize(0.0f, true)]
public float TimeFrame
{
get { return timeFrame; }
@@ -59,7 +59,7 @@ namespace Barotrauma.Items.Components
item.SendSignal(0, signalOut, "signal_out", null);
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
@@ -12,14 +13,16 @@ namespace Barotrauma.Items.Components
public readonly string Name;
public Wire[] Wires;
private Wire[] wires;
public IEnumerable<Wire> Wires
{
get { return wires; }
}
private Item item;
public readonly bool IsOutput;
private static Wire draggingConnected;
public readonly List<StatusEffect> effects;
public readonly ushort[] wireId;
@@ -30,45 +33,45 @@ namespace Barotrauma.Items.Components
private set;
}
private bool recipientsDirty = true;
private List<Connection> recipients = new List<Connection>();
public List<Connection> Recipients
{
get
{
List<Connection> recipients = new List<Connection>();
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
Connection recipient = Wires[i].OtherConnection(this);
if (recipient != null) recipients.Add(recipient);
}
if (recipientsDirty) RefreshRecipients();
return recipients;
}
}
public Item Item
{
get { return item; }
}
public Connection(XElement element, Item item)
public ConnectionPanel ConnectionPanel
{
get;
private set;
}
public Connection(XElement element, ConnectionPanel connectionPanel)
{
#if CLIENT
if (connector == null)
{
panelTexture = Sprite.LoadTexture("Content/Items/connectionpanel.png");
connector = new Sprite(panelTexture, new Rectangle(470, 102, 19, 43), Vector2.Zero, 0.0f);
connector.Origin = new Vector2(9.5f, 10.0f);
wireVertical = new Sprite(panelTexture, new Rectangle(408, 1, 11, 102), Vector2.Zero, 0.0f);
}
connector = GUI.Style.GetComponentStyle("ConnectionPanelConnector").Sprites[GUIComponent.ComponentState.None][0].Sprite;
wireVertical = GUI.Style.GetComponentStyle("ConnectionPanelWire").Sprites[GUIComponent.ComponentState.None][0].Sprite;
connectionSprite = GUI.Style.GetComponentStyle("ConnectionPanelConnection").Sprites[GUIComponent.ComponentState.None][0].Sprite;
connectionSpriteHighlight = GUI.Style.GetComponentStyle("ConnectionPanelConnection").Sprites[GUIComponent.ComponentState.Hover][0].Sprite;
screwSprites = GUI.Style.GetComponentStyle("ConnectionPanelScrew").Sprites[GUIComponent.ComponentState.None].Select(s => s.Sprite).ToList();
}
#endif
ConnectionPanel = connectionPanel;
item = connectionPanel.Item;
this.item = item;
//recipient = new Connection[MaxLinked];
Wires = new Wire[MaxLinked];
wires = new Wire[MaxLinked];
IsOutput = (element.Name.ToString() == "output");
Name = element.GetAttributeString("name", (IsOutput) ? "output" : "input");
@@ -98,37 +101,48 @@ namespace Barotrauma.Items.Components
break;
case "statuseffect":
effects.Add(StatusEffect.Load(subElement));
effects.Add(StatusEffect.Load(subElement, item.Name + ", connection " + Name));
break;
}
}
}
private void RefreshRecipients()
{
recipients.Clear();
for (int i = 0; i < MaxLinked; i++)
{
if (wires[i] == null) continue;
Connection recipient = wires[i].OtherConnection(this);
if (recipient != null) recipients.Add(recipient);
}
recipientsDirty = false;
}
public int FindEmptyIndex()
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) return i;
if (wires[i] == null) return i;
}
return -1;
}
//public int FindLinkIndex(Item item)
//{
// for (int i = 0; i < MaxLinked; i++)
// {
// if (item == null && recipient[i] == null) return i;
// if (recipient[i]!=null && recipient[i].item == item) return i;
// }
// return -1;
//}
public int FindWireIndex(Wire wire)
{
for (int i = 0; i < MaxLinked; i++)
{
if (wires[i] == wire) return i;
}
return -1;
}
public int FindWireIndex(Item wireItem)
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null && wireItem == null) return i;
if (Wires[i] != null && Wires[i].Item == wireItem) return i;
if (wires[i] == null && wireItem == null) return i;
if (wires[i] != null && wires[i].Item == wireItem) return i;
}
return -1;
}
@@ -137,26 +151,27 @@ namespace Barotrauma.Items.Components
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null)
if (wires[i] == null)
{
Wires[i] = wire;
SetWire(i, wire);
return;
}
}
}
public void AddLink(int index, Wire wire)
public void SetWire(int index, Wire wire)
{
Wires[index] = wire;
wires[index] = wire;
recipientsDirty = true;
}
public void SendSignal(int stepsTaken, string signal, Item source, Character sender, float power)
public void SendSignal(int stepsTaken, string signal, Item source, Character sender, float power, float signalStrength = 1.0f)
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
if (wires[i] == null) continue;
Connection recipient = Wires[i].OtherConnection(this);
Connection recipient = wires[i].OtherConnection(this);
if (recipient == null) continue;
if (recipient.item == this.item || recipient.item == source) continue;
@@ -167,12 +182,14 @@ namespace Barotrauma.Items.Components
foreach (ItemComponent ic in recipient.item.components)
{
ic.ReceiveSignal(stepsTaken, signal, recipient, item, sender, power);
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, power, signalStrength);
}
bool broken = recipient.Item.Condition <= 0.0f;
foreach (StatusEffect effect in recipient.effects)
{
recipient.item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
if (broken && effect.type != ActionType.OnBroken) continue;
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f, null, null, false, false);
}
}
}
@@ -181,10 +198,11 @@ namespace Barotrauma.Items.Components
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
if (wires[i] == null) continue;
Wires[i].RemoveConnection(this);
Wires[i] = null;
wires[i].RemoveConnection(this);
wires[i] = null;
recipientsDirty = true;
}
}
@@ -196,15 +214,16 @@ namespace Barotrauma.Items.Components
{
if (wireId[i] == 0) continue;
Item wireItem = MapEntity.FindEntityByID(wireId[i]) as Item;
Item wireItem = Entity.FindEntityByID(wireId[i]) as Item;
if (wireItem == null) continue;
Wires[i] = wireItem.GetComponent<Wire>();
wires[i] = wireItem.GetComponent<Wire>();
recipientsDirty = true;
if (Wires[i] != null)
if (wires[i] != null)
{
if (Wires[i].Item.body != null) Wires[i].Item.body.Enabled = false;
Wires[i].Connect(this, false, false);
if (wires[i].Item.body != null) wires[i].Item.body.Enabled = false;
wires[i].Connect(this, false, false);
}
}
}
@@ -214,7 +233,7 @@ namespace Barotrauma.Items.Components
{
XElement newElement = new XElement(IsOutput ? "output" : "input", new XAttribute("name", Name));
Array.Sort(Wires, delegate (Wire wire1, Wire wire2)
Array.Sort(wires, delegate (Wire wire1, Wire wire2)
{
if (wire1 == null) return 1;
if (wire2 == null) return -1;
@@ -223,10 +242,10 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
if (wires[i] == null) continue;
newElement.Add(new XElement("link",
new XAttribute("w", Wires[i].Item.ID.ToString())));
new XAttribute("w", wires[i].Item.ID.ToString())));
}
parentElement.Add(newElement);
@@ -1,6 +1,7 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -10,8 +11,6 @@ namespace Barotrauma.Items.Components
{
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
{
public static Wire HighlightedWire;
public List<Connection> Connections;
private Character user;
@@ -23,6 +22,13 @@ namespace Barotrauma.Items.Components
set;
}
//connection panels can't be deactivated
public override bool IsActive
{
get { return true; }
set { /*do nothing*/ }
}
public ConnectionPanel(Item item, XElement element)
: base(item, element)
{
@@ -33,17 +39,20 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString())
{
case "input":
Connections.Add(new Connection(subElement, item));
Connections.Add(new Connection(subElement, this));
break;
case "output":
Connections.Add(new Connection(subElement, item));
Connections.Add(new Connection(subElement, this));
break;
}
}
IsActive = true;
InitProjSpecific(element);
}
partial void InitProjSpecific(XElement element);
public override void OnMapLoaded()
{
foreach (Connection c in Connections)
@@ -52,9 +61,57 @@ namespace Barotrauma.Items.Components
}
}
public override void OnItemLoaded()
{
if (item.body != null)
{
var holdable = item.GetComponent<Holdable>();
if (holdable == null || !holdable.Attachable)
{
DebugConsole.ThrowError("Item \"" + item.Name + "\" has a ConnectionPanel component," +
" but cannot be wired because it has an active physics body that cannot be attached to a wall." +
" Remove the physics body or add a Holdable component with the Attachable attribute set to true.");
}
}
}
public void MoveConnectedWires(Vector2 amount)
{
Vector2 wireNodeOffset = item.Submarine == null ? Vector2.Zero : item.Submarine.HiddenSubPosition + amount;
foreach (Connection c in Connections)
{
foreach (Wire wire in c.Wires)
{
if (wire == null) continue;
#if CLIENT
if (wire.Item.IsSelected) continue;
#endif
var wireNodes = wire.GetNodes();
if (wireNodes.Count == 0) continue;
if (Submarine.RectContains(item.Rect, wireNodes[0] + wireNodeOffset))
{
wire.MoveNode(0, amount);
}
else if (Submarine.RectContains(item.Rect, wireNodes[wireNodes.Count - 1] + wireNodeOffset))
{
wire.MoveNode(wireNodes.Count - 1, amount);
}
}
}
}
public override void Update(float deltaTime, Camera cam)
{
if (user != null && user.SelectedConstruction != item) user = null;
if (user == null || user.SelectedConstruction != item)
{
user = null;
return;
}
if (!user.Enabled || !HasRequiredItems(user, addMessage: false)) { return; }
user.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * (((float)Timing.TotalTime / 10.0f) % 0.1f));
}
public override bool Select(Character picker)
@@ -70,10 +127,10 @@ namespace Barotrauma.Items.Components
IsActive = true;
return true;
}
public override bool Use(float deltaTime, Character character = null)
{
if (character == null || character!=user) return false;
if (character == null || character != user) return false;
var powered = item.GetComponent<Powered>();
if (powered != null)
@@ -82,7 +139,7 @@ namespace Barotrauma.Items.Components
}
float degreeOfSuccess = DegreeOfSuccess(character);
if (Rand.Range(0.0f, 50.0f) < degreeOfSuccess) return false;
if (Rand.Range(0.0f, 0.5f) < degreeOfSuccess) return false;
character.SetStun(5.0f);
@@ -94,7 +151,7 @@ namespace Barotrauma.Items.Components
public override void Load(XElement element)
{
base.Load(element);
List<Connection> loadedConnections = new List<Connection>();
foreach (XElement subElement in element.Elements())
@@ -102,15 +159,15 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString())
{
case "input":
loadedConnections.Add(new Connection(subElement, item));
loadedConnections.Add(new Connection(subElement, this));
break;
case "output":
loadedConnections.Add(new Connection(subElement, item));
loadedConnections.Add(new Connection(subElement, this));
break;
}
}
for (int i = 0; i<loadedConnections.Count && i<Connections.Count; i++)
for (int i = 0; i < loadedConnections.Count && i < Connections.Count; i++)
{
loadedConnections[i].wireId.CopyTo(Connections[i].wireId, 0);
}
@@ -157,9 +214,9 @@ namespace Barotrauma.Items.Components
{
foreach (Connection connection in Connections)
{
for (int i = 0; i < Connection.MaxLinked; i++)
foreach (Wire wire in connection.Wires)
{
msg.Write(connection.Wires[i]?.Item == null ? (ushort)0 : connection.Wires[i].Item.ID);
msg.Write(wire?.Item == null ? (ushort)0 : wire.Item.ID);
}
}
}
@@ -171,8 +228,7 @@ namespace Barotrauma.Items.Components
//read wire IDs for each connection
for (int i = 0; i < Connections.Count; i++)
{
wires[i] = new List<Wire>();
wires[i] = new List<Wire>();
for (int j = 0; j < Connection.MaxLinked; j++)
{
ushort wireId = msg.ReadUInt16();
@@ -212,9 +268,10 @@ namespace Barotrauma.Items.Components
//go through existing wire links
for (int i = 0; i < Connections.Count; i++)
{
for (int j = 0; j < Connection.MaxLinked; j++)
int j = -1;
foreach (Wire existingWire in Connections[i].Wires)
{
Wire existingWire = Connections[i].Wires[j];
j++;
if (existingWire == null) continue;
//existing wire not in the list of new wires -> disconnect it
@@ -263,9 +320,8 @@ namespace Barotrauma.Items.Components
}
}
Connections[i].Wires[j] = null;
}
Connections[i].SetWire(j, null);
}
}
}
@@ -302,6 +358,6 @@ namespace Barotrauma.Items.Components
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
{
ClientWrite(msg, extraData);
}
}
}
}
@@ -0,0 +1,193 @@
using Barotrauma.Networking;
using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class CustomInterface : ItemComponent, IClientSerializable, IServerSerializable
{
class CustomInterfaceElement
{
public bool ContinuousSignal;
public bool State;
public string Label, Connection, Signal;
public CustomInterfaceElement(XElement element)
{
Label = element.GetAttributeString("text", "");
Connection = element.GetAttributeString("connection", "");
Signal = element.GetAttributeString("signal", "1");
}
}
private string[] labels;
[Serialize("", true), Editable()]
public string Labels
{
get { return string.Join(",", labels); }
set
{
if (value == null) { return; }
string[] splitValues = value == "" ? new string[0] : value.Split(',');
if (customInterfaceElementList.Count > 0)
{
UpdateLabels(splitValues);
}
}
}
private string[] signals;
[Serialize("", true), Editable()]
public string Signals
{
//use semicolon as a separator because comma may be needed in the signals (for color or vector values for example)
//kind of hacky, we should probably add support for (string) arrays to SerializableEntityEditor so this wouldn't be needed
get { return signals == null ? "" : string.Join(";", signals); }
set
{
if (value == null) { return; }
string[] splitValues = value == "" ? new string[0] : value.Split(';');
if (customInterfaceElementList.Count > 0)
{
signals = new string[customInterfaceElementList.Count];
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
signals[i] = i < splitValues.Length ? splitValues[i] : customInterfaceElementList[i].Signal;
customInterfaceElementList[i].Signal = signals[i];
}
}
}
}
private List<CustomInterfaceElement> customInterfaceElementList = new List<CustomInterfaceElement>();
public CustomInterface(Item item, XElement element)
: base(item, element)
{
int i = 0;
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "button":
var button = new CustomInterfaceElement(subElement)
{
ContinuousSignal = false
};
if (string.IsNullOrEmpty(button.Label))
{
button.Label = "Signal out " + customInterfaceElementList.Count(e => !e.ContinuousSignal);
}
customInterfaceElementList.Add(button);
break;
case "tickbox":
var tickBox = new CustomInterfaceElement(subElement)
{
ContinuousSignal = true
};
if (string.IsNullOrEmpty(tickBox.Label))
{
tickBox.Label = "Signal out " + customInterfaceElementList.Count(e => !e.ContinuousSignal);
}
customInterfaceElementList.Add(tickBox);
break;
}
i++;
}
IsActive = true;
InitProjSpecific(element);
Labels = element.GetAttributeString("labels", "");
Signals = element.GetAttributeString("signals", "");
}
private void UpdateLabels(string[] newLabels)
{
labels = new string[customInterfaceElementList.Count];
for (int i = 0; i < labels.Length; i++)
{
labels[i] = i < newLabels.Length ? newLabels[i] : customInterfaceElementList[i].Label;
customInterfaceElementList[i].Label = labels[i];
}
UpdateLabelsProjSpecific();
}
partial void UpdateLabelsProjSpecific();
partial void InitProjSpecific(XElement element);
private void ButtonClicked(CustomInterfaceElement btnElement)
{
if (btnElement == null) return;
item.SendSignal(0, btnElement.Signal, btnElement.Connection, sender: null, source: item);
}
private void TickBoxToggled(CustomInterfaceElement tickBoxElement, bool state)
{
if (tickBoxElement == null) return;
tickBoxElement.State = state;
}
public override void Update(float deltaTime, Camera cam)
{
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
{
if (!ciElement.ContinuousSignal) { continue; }
//TODO: allow changing output when a tickbox is not selected
item.SendSignal(0, ciElement.State ? ciElement.Signal : "0", ciElement.Connection, sender: null, source: item);
}
}
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
{
bool[] elementStates = new bool[customInterfaceElementList.Count];
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
elementStates[i] = msg.ReadBoolean();
}
CustomInterfaceElement clickedButton = null;
if (item.CanClientAccess(c))
{
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (customInterfaceElementList[i].ContinuousSignal)
{
TickBoxToggled(customInterfaceElementList[i], elementStates[i]);
}
else if (elementStates[i])
{
clickedButton = customInterfaceElementList[i];
ButtonClicked(customInterfaceElementList[i]);
}
}
}
//notify all clients of the new state
GameMain.Server.CreateEntityEvent(item, new object[]
{
NetEntityEvent.Type.ComponentState,
item.components.IndexOf(this),
clickedButton
});
item.CreateServerEvent(this);
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
{
//extradata contains an array of buttons clicked by a client (or nothing if nothing was clicked)
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (customInterfaceElementList[i].ContinuousSignal)
{
msg.Write(customInterfaceElementList[i].State);
}
else
{
msg.Write(extraData != null && extraData.Any(d => d as CustomInterfaceElement == customInterfaceElementList[i]));
}
}
}
}
}
@@ -1,18 +1,29 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class DelayComponent : ItemComponent
{
class DelayedSignal
{
public readonly string Signal;
public readonly float SignalStrength;
public float SendTimer;
public DelayedSignal(string signal, float signalStrength, float sendTimer)
{
Signal = signal;
SignalStrength = signalStrength;
SendTimer = sendTimer;
}
}
const int SignalQueueSize = 500;
private Queue<Pair<string, float>> signalQueue;
private Queue<DelayedSignal> signalQueue;
[InGameEditable(MinValueFloat = 0.0f, MaxValueFloat = 60.0f), Serialize(1.0f, true)]
[InGameEditable(MinValueFloat = 0.0f, MaxValueFloat = 60.0f, DecimalCount = 2), Serialize(1.0f, true)]
public float Delay
{
get;
@@ -26,10 +37,17 @@ namespace Barotrauma.Items.Components
set;
}
[InGameEditable(ToolTip = "Should the component discard previously received signals when the incoming signal changes."), Serialize(false, true)]
public bool ResetWhenDifferentSignalReceived
{
get;
set;
}
public DelayComponent(Item item, XElement element)
: base (item, element)
{
signalQueue = new Queue<Pair<string, float>>();
signalQueue = new Queue<DelayedSignal>();
IsActive = true;
}
@@ -37,24 +55,28 @@ namespace Barotrauma.Items.Components
{
foreach (var val in signalQueue)
{
val.Second -= deltaTime;
val.SendTimer -= deltaTime;
}
while (signalQueue.Count > 0 && signalQueue.Peek().Second <= 0.0f)
while (signalQueue.Count > 0 && signalQueue.Peek().SendTimer <= 0.0f)
{
var signalOut = signalQueue.Dequeue();
item.SendSignal(0, signalOut.First, "signal_out", null);
item.SendSignal(0, signalOut.Signal, "signal_out", null, signalStrength: signalOut.SignalStrength);
}
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
case "signal_in":
if (signalQueue.Count >= SignalQueueSize) return;
if (ResetWhenSignalReceived) signalQueue.Clear();
signalQueue.Enqueue(Pair<string, float>.Create(signal, Delay));
if (ResetWhenDifferentSignalReceived && signalQueue.Count > 0 && signalQueue.Peek().Signal != signal)
{
signalQueue.Clear();
}
signalQueue.Enqueue(new DelayedSignal(signal, signalStrength, Delay));
break;
}
}
@@ -13,24 +13,24 @@ namespace Barotrauma.Items.Components
partial class LightComponent : Powered, IServerSerializable, IDrawableComponent
{
private Color lightColor;
private float range;
private float lightBrightness;
private float blinkFrequency;
private float range;
private float flicker;
private bool castShadows;
private bool drawBehindSubs;
private float blinkTimer;
public PhysicsBody ParentBody;
[Editable(0.0f, 2048.0f), Serialize(100.0f, true)]
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f), Serialize(100.0f, true)]
public float Range
{
get { return range; }
set
{
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
range = MathHelper.Clamp(value, 0.0f, 4096.0f);
#if CLIENT
if (light != null) light.Range = range;
#endif
@@ -53,6 +53,20 @@ namespace Barotrauma.Items.Components
}
}
[Editable(ToolTip = "Lights drawn behind submarines don't cast any shadows and are much faster to draw than shadow-casting lights. "+
"It's recommended to enable this on decorative lights outside the submarine's hull."), Serialize(false, true)]
public bool DrawBehindSubs
{
get { return drawBehindSubs; }
set
{
drawBehindSubs = value;
#if CLIENT
if (light != null) light.IsBackground = drawBehindSubs;
#endif
}
}
[Editable, Serialize(false, true)]
public bool IsOn
{
@@ -76,6 +90,16 @@ namespace Barotrauma.Items.Components
}
}
[Editable, Serialize(0.0f, true)]
public float BlinkFrequency
{
get { return blinkFrequency; }
set
{
blinkFrequency = MathHelper.Clamp(value, 0.0f, 60.0f);
}
}
[InGameEditable, Serialize("1.0,1.0,1.0,1.0", true)]
public Color LightColor
{
@@ -84,7 +108,7 @@ namespace Barotrauma.Items.Components
{
lightColor = value;
#if CLIENT
if (light != null) light.Color = lightColor;
if (light != null) light.Color = IsActive ? lightColor : Color.Transparent;
#endif
}
}
@@ -118,10 +142,13 @@ namespace Barotrauma.Items.Components
: base (item, element)
{
#if CLIENT
light = new LightSource(element);
light.ParentSub = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
light.Position = item.Position;
light.CastShadows = castShadows;
light = new LightSource(element)
{
ParentSub = item.CurrentHull?.Submarine,
Position = item.Position,
CastShadows = castShadows,
IsBackground = drawBehindSubs
};
#endif
IsActive = IsOn;
@@ -130,6 +157,7 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
UpdateOnActiveEffects(deltaTime);
if (AITarget != null) AITarget.Enabled = voltage > minVoltage || powerConsumption <= 0.0f;
#if CLIENT
light.ParentSub = item.Submarine;
@@ -176,7 +204,11 @@ namespace Barotrauma.Items.Components
if (Rand.Range(0.0f, 1.0f) < 0.05f && voltage < Rand.Range(0.0f, minVoltage))
{
#if CLIENT
if (voltage > 0.1f) sparkSounds[Rand.Int(sparkSounds.Length)].Play(1.0f, 400.0f, item.WorldPosition);
if (voltage > 0.1f && sparkSounds.Count > 0)
{
var sparkSound = sparkSounds[Rand.Int(sparkSounds.Count)];
SoundPlayer.PlaySound(sparkSound.Sound, sparkSound.Volume, sparkSound.Range, item.WorldPosition, item.CurrentHull);
}
#endif
lightBrightness = 0.0f;
}
@@ -185,11 +217,26 @@ namespace Barotrauma.Items.Components
lightBrightness = MathHelper.Lerp(lightBrightness, Math.Min(voltage, 1.0f), 0.1f);
}
#if CLIENT
light.Color = lightColor * lightBrightness * (1.0f-Rand.Range(0.0f,Flicker));
light.Range = range * (float)Math.Sqrt(lightBrightness);
#endif
if (blinkFrequency > 0.0f)
{
blinkTimer = (blinkTimer + deltaTime * blinkFrequency) % 1.0f;
}
if (blinkTimer > 0.5f)
{
#if CLIENT
light.Color = Color.Transparent;
#endif
}
else
{
#if CLIENT
light.Color = lightColor * lightBrightness * (1.0f - Rand.Range(0.0f, Flicker));
light.Range = range;
#endif
item.SightRange = Math.Max(range * (float)Math.Sqrt(lightBrightness), item.SightRange);
}
voltage = 0.0f;
}
@@ -210,9 +257,9 @@ namespace Barotrauma.Items.Components
return true;
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power);
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength);
switch (connection.Name)
{
@@ -1,11 +1,12 @@
using Microsoft.Xna.Framework;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class MotionSensor : ItemComponent
partial class MotionSensor : ItemComponent
{
private const float UpdateInterval = 0.1f;
@@ -13,17 +14,54 @@ namespace Barotrauma.Items.Components
private bool motionDetected;
private float range;
private float rangeX, rangeY;
private Vector2 detectOffset;
private float updateTimer;
[InGameEditable, Serialize(0.0f, true)]
public float Range
[Serialize(false, false)]
public bool MotionDetected
{
get { return range; }
get { return motionDetected; }
set { motionDetected = value; }
}
[Serialize(false, true), Editable]
public bool OnlyHumans
{
get;
set;
}
[InGameEditable, Serialize(0.0f, true)]
public float RangeX
{
get { return rangeX; }
set
{
range = MathHelper.Clamp(value, 0.0f, 500.0f);
rangeX = MathHelper.Clamp(value, 0.0f, 1000.0f);
}
}
[InGameEditable, Serialize(0.0f, true)]
public float RangeY
{
get { return rangeY; }
set
{
rangeY = MathHelper.Clamp(value, 0.0f, 1000.0f);
}
}
[Serialize("0,0", true), Editable(ToolTip = "The position to detect the movement at relative to the item. For example, 0,100 would detect movement 100 units above the item.")]
public Vector2 DetectOffset
{
get { return detectOffset; }
set
{
detectOffset = value;
detectOffset.X = MathHelper.Clamp(value.X, -rangeX, rangeX);
detectOffset.Y = MathHelper.Clamp(value.Y, -rangeY, rangeY);
}
}
@@ -41,10 +79,17 @@ namespace Barotrauma.Items.Components
set { falseOutput = value; }
}
public MotionSensor(Item item, XElement element)
: base (item, element)
{
IsActive = true;
//backwards compatibility
if (element.Attribute("range") != null)
{
rangeX = rangeY = element.GetAttributeFloat("range", 0.0f);
}
}
public override void Update(float deltaTime, Camera cam)
@@ -67,16 +112,31 @@ namespace Barotrauma.Items.Components
}
}
Vector2 detectPos = item.WorldPosition + detectOffset;
Rectangle detectRect = new Rectangle((int)(detectPos.X - rangeX), (int)(detectPos.Y - rangeY), (int)(rangeX * 2), (int)(rangeY * 2));
float broadRangeX = Math.Max(rangeX * 2, 500);
float broadRangeY = Math.Max(rangeY * 2, 500);
foreach (Character c in Character.CharacterList)
{
if (Math.Abs(c.WorldPosition.X - item.WorldPosition.X) < range &&
Math.Abs(c.WorldPosition.Y - item.WorldPosition.Y) < range)
{
if (!c.AnimController.Limbs.Any(l => l.body.FarseerBody.Awake)) continue;
if (OnlyHumans && c.ConfigPath != Character.HumanConfigFile) { continue; }
motionDetected = true;
break;
}
//do a rough check based on the position of the character's collider first
//before the more accurate limb-based check
if (Math.Abs(c.WorldPosition.X - detectPos.X) > broadRangeX || Math.Abs(c.WorldPosition.Y - detectPos.Y) > broadRangeY)
{
continue;
}
foreach (Limb limb in c.AnimController.Limbs)
{
if (limb.LinearVelocity.LengthSquared() <= 0.001f) continue;
if (MathUtils.CircleIntersectsRectangle(limb.WorldPosition, ConvertUnits.ToDisplayUnits(limb.body.GetMaxExtent()), detectRect))
{
motionDetected = true;
break;
}
}
}
}
}
@@ -8,12 +8,12 @@ namespace Barotrauma.Items.Components
: base (item, element)
{
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
if (connection.Name != "signal_in") return;
item.SendSignal(stepsTaken, signal=="0" ? "1" : "0", "signal_out", sender);
item.SendSignal(stepsTaken, signal == "0" ? "1" : "0", "signal_out", sender, 0.0f, source, signalStrength);
}
}
}
@@ -27,7 +27,7 @@ namespace Barotrauma.Items.Components
set;
}
[InGameEditable, Serialize(1.0f, true)]
[InGameEditable(DecimalCount = 2), Serialize(1.0f, true)]
public float Frequency
{
get { return frequency; }
@@ -71,14 +71,14 @@ namespace Barotrauma.Items.Components
}
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
case "set_frequency":
case "frequency_in":
float newFrequency;
if (float.TryParse(signal, out newFrequency))
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out newFrequency))
{
Frequency = newFrequency;
}
@@ -75,18 +75,19 @@ namespace Barotrauma.Items.Components
}
}
string signalOut = previousResult ? Output : FalseOutput;
if (ContinuousOutput)
{
item.SendSignal(0, previousResult ? Output : FalseOutput, "signal_out", null);
if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(0, signalOut, "signal_out", null); }
}
else if (!nonContinuousOutputSent)
{
item.SendSignal(0, previousResult ? Output : FalseOutput, "signal_out", null);
if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(0, signalOut, "signal_out", null); }
nonContinuousOutputSent = true;
}
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
@@ -53,13 +53,11 @@ namespace Barotrauma.Items.Components
if (Math.Min(-currPowerConsumption, PowerLoad) > maxPower) item.Condition = 0.0f;
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
{
if (connection.IsPower) return;
if (item.Condition <= 0.0f) return;
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
if (connection.IsPower || item.Condition <= 0.0f) return;
if (connection.Name.Contains("_in"))
{
if (!IsOn) return;
@@ -68,10 +66,8 @@ namespace Barotrauma.Items.Components
int connectionNumber = -1;
int.TryParse(connection.Name.Substring(connection.Name.Length - 1, 1), out connectionNumber);
if (connectionNumber > 0) outConnection += connectionNumber;
item.SendSignal(stepsTaken, signal, outConnection, sender, power);
item.SendSignal(stepsTaken, signal, outConnection, sender, power, source, signalStrength);
}
else if (connection.Name == "toggle")
{
@@ -33,7 +33,7 @@ namespace Barotrauma.Items.Components
{
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
switch (connection.Name)
{
@@ -41,7 +41,7 @@ namespace Barotrauma.Items.Components
string signalOut = (signal == targetSignal) ? output : falseOutput;
if (string.IsNullOrWhiteSpace(signalOut)) return;
item.SendSignal(stepsTaken, signalOut, "signal_out", sender);
item.SendSignal(stepsTaken, signalOut, "signal_out", sender, signalStrength);
break;
case "set_output":
@@ -0,0 +1,25 @@
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class SmokeDetector : ItemComponent
{
[Serialize(50.0f, false)]
public float FireSizeThreshold
{
get; set;
}
public SmokeDetector(Item item, XElement element)
: base (item, element)
{
IsActive = true;
}
public override void Update(float deltaTime, Camera cam)
{
item.SendSignal(0, item.CurrentHull != null && item.CurrentHull.FireSources.Any(fs => fs.Size.X > FireSizeThreshold) ? "1" : "0", "signal_out", null);
}
}
}
@@ -4,15 +4,50 @@ namespace Barotrauma.Items.Components
{
class WaterDetector : ItemComponent
{
private string output, falseOutput;
[InGameEditable, Serialize("1", true)]
public string Output
{
get { return output; }
set { output = value; }
}
[InGameEditable, Serialize("0", true)]
public string FalseOutput
{
get { return falseOutput; }
set { falseOutput = value; }
}
public WaterDetector(Item item, XElement element)
: base (item, element)
: base(item, element)
{
IsActive = true;
}
public override void Update(float deltaTime, Camera cam)
{
item.SendSignal(0, item.InWater ? "1" : "0", "signal_out", null);
string signalOut = falseOutput;
if (item.InWater)
{
//item in water -> we definitely want to send the True output
signalOut = Output;
}
else if (item.CurrentHull != null)
{
//item in not water -> check if there's water anywhere within the rect of the item
if (item.CurrentHull.Surface > item.CurrentHull.Rect.Y - item.CurrentHull.Rect.Height + 1 &&
item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
{
signalOut = output;
}
}
if (!string.IsNullOrEmpty(signalOut))
{
item.SendSignal(0, signalOut, "signal_out", null);
}
}
}
}
@@ -6,13 +6,17 @@ using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class WifiComponent : ItemComponent
partial class WifiComponent : ItemComponent
{
private static List<WifiComponent> list = new List<WifiComponent>();
private float range;
private int channel;
private float chatMsgCooldown;
private string prevSignal;
public byte TeamID;
@@ -33,18 +37,36 @@ namespace Barotrauma.Items.Components
}
}
[Editable(ToolTip = "If enabled, any signals received by the item are displayed as chat messages in the chatbox of the player holding the item."), Serialize(false, false)]
[Editable(ToolTip =
"If enabled, any signals received from another chat-linked wifi component are displayed "+
"as chat messages in the chatbox of the player holding the item."), Serialize(false, false)]
public bool LinkToChat
{
get;
set;
}
[Editable(ToolTip = "How many seconds have to pass between signals for a message to be displayed in the chatbox. "+
"Setting this to a very low value is not recommended, because it may cause an excessive amount of chat messages to be created "+
"if there are chat-linked wifi components that transmit a continuous signal."), Serialize(1.0f, true)]
public float MinChatMessageInterval
{
get;
set;
}
[Editable(ToolTip = "If set to true, the component will only create chat messages when the received signal changes."), Serialize(false, true)]
public bool DiscardDuplicateChatMessages
{
get;
set;
}
public WifiComponent(Item item, XElement element)
: base (item, element)
{
list.Add(this);
IsActive = true;
}
public bool CanTransmit()
@@ -59,57 +81,86 @@ namespace Barotrauma.Items.Components
public bool CanReceive(WifiComponent sender)
{
if (!HasRequiredContainedItems(false)) return false;
if (sender == null || sender.channel != channel || sender.TeamID != TeamID) return false;
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) return false;
return Vector2.Distance(item.WorldPosition, sender.item.WorldPosition) <= sender.Range;
return HasRequiredContainedItems(false);
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
public override void Update(float deltaTime, Camera cam)
{
var senderComponent = source.GetComponent<WifiComponent>();
chatMsgCooldown -= deltaTime;
}
public void TransmitSignal(int stepsTaken, string signal, Item source, Character sender, bool sendToChat, float signalStrength = 1.0f)
{
var senderComponent = source?.GetComponent<WifiComponent>();
if (senderComponent != null && !CanReceive(senderComponent)) return;
if (LinkToChat)
bool chatMsgSent = false;
var receivers = GetReceiversInRange();
foreach (WifiComponent wifiComp in receivers)
{
if (item.ParentInventory != null &&
item.ParentInventory.Owner != null &&
item.ParentInventory.Owner == Character.Controlled &&
GameMain.NetworkMember != null)
//signal strength diminishes by distance
float sentSignalStrength = signalStrength *
MathHelper.Clamp(1.0f - (Vector2.Distance(item.WorldPosition, wifiComp.item.WorldPosition) / wifiComp.range), 0.0f, 1.0f);
wifiComp.item.SendSignal(stepsTaken, signal, "signal_out", sender, 0, source, sentSignalStrength);
if (source != null)
{
if (senderComponent != null)
foreach (Item receiverItem in wifiComp.item.LastSentSignalRecipients)
{
signal = ChatMessage.ApplyDistanceEffect(item, sender, signal, senderComponent.range);
}
GameMain.NetworkMember.AddChatMessage(signal, ChatMessageType.Radio);
}
}
if (connection == null) return;
switch (connection.Name)
{
case "signal_in":
var receivers = GetReceiversInRange();
foreach (WifiComponent wifiComp in receivers)
{
wifiComp.item.SendSignal(stepsTaken, signal, "signal_out", sender);
if (source != null)
if (!source.LastSentSignalRecipients.Contains(receiverItem))
{
foreach (Item receiverItem in wifiComp.item.LastSentSignalRecipients)
{
if (!source.LastSentSignalRecipients.Contains(receiverItem))
{
source.LastSentSignalRecipients.Add(receiverItem);
}
}
source.LastSentSignalRecipients.Add(receiverItem);
}
}
break;
}
if (DiscardDuplicateChatMessages && signal == prevSignal) continue;
if (LinkToChat && wifiComp.LinkToChat && chatMsgCooldown <= 0.0f && sendToChat)
{
if (wifiComp.item.ParentInventory != null &&
wifiComp.item.ParentInventory.Owner != null &&
GameMain.NetworkMember != null)
{
string chatMsg = signal;
if (senderComponent != null)
{
chatMsg = ChatMessage.ApplyDistanceEffect(chatMsg, 1.0f - sentSignalStrength);
}
if (chatMsg.Length > ChatMessage.MaxLength) chatMsg = chatMsg.Substring(0, ChatMessage.MaxLength);
if (string.IsNullOrEmpty(chatMsg)) continue;
if (wifiComp.item.ParentInventory.Owner == Character.Controlled)
{
if (GameMain.Client == null)
GameMain.NetworkMember.AddChatMessage(signal, ChatMessageType.Radio, source == null ? "" : source.Name);
}
else if (GameMain.Server != null)
{
Client recipientClient = GameMain.Server.ConnectedClients.Find(c => c.Character == wifiComp.item.ParentInventory.Owner);
if (recipientClient != null)
{
GameMain.Server.SendDirectChatMessage(
ChatMessage.Create(source == null ? "" : source.Name, chatMsg, ChatMessageType.Radio, null), recipientClient);
}
}
chatMsgSent = true;
}
}
}
if (chatMsgSent) chatMsgCooldown = MinChatMessageInterval;
prevSignal = signal;
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
{
if (connection == null || connection.Name != "signal_in") return;
TransmitSignal(stepsTaken, signal, source, sender, true, signalStrength);
}
protected override void RemoveComponentSpecific()
@@ -40,8 +40,18 @@ namespace Barotrauma.Items.Components
private bool canPlaceNode;
private Vector2 newNodePos;
public bool Hidden, Locked;
public bool Hidden;
private bool locked;
public bool Locked
{
get
{
return locked || connections.Any(c => c != null && c.ConnectionPanel.Locked);
}
set { locked = value; }
}
public Connection[] Connections
{
@@ -95,13 +105,14 @@ namespace Barotrauma.Items.Components
{
if (connections[i] == null || connections[i].Item != item) continue;
for (int n = 0; n < connections[i].Wires.Length; n++)
foreach (Wire wire in connections[i].Wires)
{
if (connections[i].Wires[n] != this) continue;
if (wire != this) continue;
SetConnectedDirty();
connections[i].Wires[n] = null;
connections[i].SetWire(connections[i].FindWireIndex(wire), null);
}
connections[i] = null;
}
}
@@ -142,18 +153,29 @@ namespace Barotrauma.Items.Components
if (!addNode) break;
if (newConnection.Item.Submarine == null) continue;
Submarine refSub = newConnection.Item.Submarine;
if (refSub == null)
{
Structure attachTarget = Structure.GetAttachTarget(newConnection.Item.WorldPosition);
if (attachTarget == null) continue;
refSub = attachTarget.Submarine;
}
if (nodes.Count > 0 && nodes[0] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
if (nodes.Count > 1 && nodes[nodes.Count - 1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
Vector2 nodePos = refSub == null ?
newConnection.Item.Position :
newConnection.Item.Position - refSub.HiddenSubPosition;
if (nodes.Count > 0 && nodes[0] == nodePos) break;
if (nodes.Count > 1 && nodes[nodes.Count - 1] == nodePos) break;
if (i == 0)
{
nodes.Insert(0, newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
nodes.Insert(0, nodePos);
}
else
{
nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
nodes.Add(nodePos);
}
break;
@@ -226,7 +248,7 @@ namespace Barotrauma.Items.Components
if (Screen.Selected != GameMain.SubEditorScreen)
{
//cannot run wires from sub to another
if (sub == null || (item.Submarine != sub && sub != null && item.Submarine != null))
if (item.Submarine != sub && sub != null && item.Submarine != null)
{
ClearConnections();
return;
@@ -234,12 +256,18 @@ namespace Barotrauma.Items.Components
if (item.CurrentHull == null)
{
newNodePos = item.WorldPosition - sub.Position - sub.HiddenSubPosition;
canPlaceNode = false;
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
canPlaceNode = attachTarget != null;
sub = attachTarget?.Submarine;
newNodePos = sub == null ?
item.WorldPosition :
item.WorldPosition - sub.Position - sub.HiddenSubPosition;
}
else
{
newNodePos = RoundNode(item.Position, item.CurrentHull) - sub.HiddenSubPosition;
newNodePos = RoundNode(item.Position, item.CurrentHull);
if (sub != null) { newNodePos -= sub.HiddenSubPosition; }
canPlaceNode = true;
}
@@ -250,7 +278,7 @@ namespace Barotrauma.Items.Components
if (user == null) return;
Vector2 prevNodePos = nodes[nodes.Count - 1];
prevNodePos += sub.HiddenSubPosition;
if (sub != null) { prevNodePos += sub.HiddenSubPosition; }
float currLength = 0.0f;
for (int i = 0; i < nodes.Count - 1; i++)
@@ -263,8 +291,9 @@ namespace Barotrauma.Items.Components
{
Vector2 diff = nodes[nodes.Count - 1] - newNodePos;
Vector2 pullBackDir = diff == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(diff);
user.AnimController.Collider.ApplyForce(pullBackDir * user.Mass * 50.0f);
user.AnimController.UpdateUseItem(true, user.SimPosition + pullBackDir * 2.0f);
user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * 200.0f);
if (currLength > MaxLength * 1.5f && GameMain.Client == null)
{
ClearConnections();
@@ -344,6 +373,13 @@ namespace Barotrauma.Items.Components
UpdateSections();
}
public void MoveNode(int index, Vector2 amount)
{
if (index < 0 || index >= nodes.Count) return;
nodes[index] += amount;
UpdateSections();
}
public void MoveNodes(Vector2 amount)
{
for (int i = 0; i < nodes.Count; i++)
@@ -397,7 +433,7 @@ namespace Barotrauma.Items.Components
int wireIndex = connections[i].FindWireIndex(item);
if (wireIndex == -1) continue;
connections[i].AddLink(wireIndex, null);
connections[i].SetWire(wireIndex, null);
connections[i] = null;
}
@@ -512,7 +548,7 @@ namespace Barotrauma.Items.Components
return closestIndex;
}
public override void FlipX()
public override void FlipX(bool relativeToSub)
{
for (int i = 0; i < nodes.Count; i++)
{
@@ -521,6 +557,15 @@ namespace Barotrauma.Items.Components
UpdateSections();
}
public override void FlipY(bool relativeToSub)
{
for (int i = 0; i < nodes.Count; i++)
{
nodes[i] = new Vector2(nodes[i].X, -nodes[i].Y);
}
UpdateSections();
}
public override void Load(XElement componentElement)
{
base.Load(componentElement);
@@ -533,17 +578,9 @@ namespace Barotrauma.Items.Components
{
float x = 0.0f, y = 0.0f;
try
{
x = float.Parse(nodeCoords[i * 2], CultureInfo.InvariantCulture);
}
catch { x = 0.0f; }
float.TryParse(nodeCoords[i * 2], NumberStyles.Float, CultureInfo.InvariantCulture, out x);
try
{
y = float.Parse(nodeCoords[i * 2 + 1], CultureInfo.InvariantCulture);
}
catch { y = 0.0f; }
float.TryParse(nodeCoords[i * 2 + 1], NumberStyles.Float, CultureInfo.InvariantCulture, out y);
nodes.Add(new Vector2(x, y));
}
@@ -571,7 +608,7 @@ namespace Barotrauma.Items.Components
protected override void ShallowRemoveComponentSpecific()
{
for (int i = 0; i < 2; i++)
/*for (int i = 0; i < 2; i++)
{
if (connections[i] == null) continue;
int wireIndex = connections[i].FindWireIndex(item);
@@ -580,7 +617,7 @@ namespace Barotrauma.Items.Components
{
connections[i].AddLink(wireIndex, null);
}
}
}*/
}
protected override void RemoveComponentSpecific()