Renamed project folders from Subsurface to Barotrauma
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class AndComponent : ItemComponent
|
||||
{
|
||||
protected string output, falseOutput;
|
||||
|
||||
//an array to keep track of how long ago a non-zero signal was received on both inputs
|
||||
protected float[] timeSinceReceived;
|
||||
|
||||
//the output is sent if both inputs have received a signal within the timeframe
|
||||
protected float timeFrame;
|
||||
|
||||
[InGameEditable, HasDefaultValue(0.0f, true)]
|
||||
public float TimeFrame
|
||||
{
|
||||
get { return timeFrame; }
|
||||
set
|
||||
{
|
||||
timeFrame = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("1", true)]
|
||||
public string Output
|
||||
{
|
||||
get { return output; }
|
||||
set { output = value; }
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("", true)]
|
||||
public string FalseOutput
|
||||
{
|
||||
get { return falseOutput; }
|
||||
set { falseOutput = value; }
|
||||
}
|
||||
|
||||
public AndComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
timeSinceReceived = new float[] { Math.Max(timeFrame*2.0f,0.1f), Math.Max(timeFrame*2.0f, 0.1f) };
|
||||
|
||||
//output = "1";
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
bool sendOutput = true;
|
||||
for (int i = 0; i<timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] > timeFrame) sendOutput = false;
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = sendOutput ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
|
||||
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)
|
||||
{
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in1":
|
||||
if (signal == "0") return;
|
||||
timeSinceReceived[0] = 0.0f;
|
||||
IsActive = true;
|
||||
break;
|
||||
case "signal_in2":
|
||||
if (signal == "0") return;
|
||||
timeSinceReceived[1] = 0.0f;
|
||||
IsActive = true;
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
|
||||
class Connection
|
||||
{
|
||||
private static Texture2D panelTexture;
|
||||
private static Sprite connector;
|
||||
private static Sprite wireVertical;
|
||||
|
||||
//how many wires can be linked to a single connector
|
||||
public const int MaxLinked = 5;
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public Wire[] Wires;
|
||||
|
||||
private Item item;
|
||||
|
||||
public readonly bool IsOutput;
|
||||
|
||||
private static Wire draggingConnected;
|
||||
|
||||
private List<StatusEffect> effects;
|
||||
|
||||
public readonly ushort[] wireId;
|
||||
|
||||
public bool IsPower
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return recipients;
|
||||
}
|
||||
}
|
||||
|
||||
public Item Item
|
||||
{
|
||||
get { return item; }
|
||||
}
|
||||
|
||||
public Connection(XElement element, Item item)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
this.item = item;
|
||||
|
||||
//recipient = new Connection[MaxLinked];
|
||||
Wires = new Wire[MaxLinked];
|
||||
|
||||
IsOutput = (element.Name.ToString() == "output");
|
||||
Name = ToolBox.GetAttributeString(element, "name", (IsOutput) ? "output" : "input");
|
||||
|
||||
IsPower = Name == "power_in" || Name == "power" || Name == "power_out";
|
||||
|
||||
effects = new List<StatusEffect>();
|
||||
|
||||
wireId = new ushort[MaxLinked];
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "link":
|
||||
int index = -1;
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (wireId[i] < 1) index = i;
|
||||
}
|
||||
if (index == -1) break;
|
||||
|
||||
int id = ToolBox.GetAttributeInt(subElement, "w", 0);
|
||||
if (id < 0) id = 0;
|
||||
wireId[index] = (ushort)id;
|
||||
|
||||
break;
|
||||
|
||||
case "statuseffect":
|
||||
effects.Add(StatusEffect.Load(subElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int FindEmptyIndex()
|
||||
{
|
||||
for (int i = 0; i < MaxLinked; 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(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;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void TryAddLink(Wire wire)
|
||||
{
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null)
|
||||
{
|
||||
Wires[i] = wire;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddLink(int index, Wire wire)
|
||||
{
|
||||
Wires[index] = wire;
|
||||
}
|
||||
|
||||
public void SendSignal(int stepsTaken, string signal, Item source, Character sender, float power)
|
||||
{
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null) continue;
|
||||
|
||||
Connection recipient = Wires[i].OtherConnection(this);
|
||||
if (recipient == null) continue;
|
||||
if (recipient.item == this.item || recipient.item == source) continue;
|
||||
|
||||
foreach (ItemComponent ic in recipient.item.components)
|
||||
{
|
||||
ic.ReceiveSignal(stepsTaken, signal, recipient, item, sender, power);
|
||||
}
|
||||
|
||||
foreach (StatusEffect effect in recipient.effects)
|
||||
{
|
||||
|
||||
//effect.Apply(ActionType.OnUse, 1.0f, recipient.item, recipient.item);
|
||||
recipient.item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearConnections()
|
||||
{
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null) continue;
|
||||
|
||||
Wires[i].RemoveConnection(this);
|
||||
Wires[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
|
||||
{
|
||||
|
||||
int width = 400, height = 200;
|
||||
int x = GameMain.GraphicsWidth / 2 - width / 2, y = GameMain.GraphicsHeight - height;
|
||||
|
||||
Rectangle panelRect = new Rectangle(x, y, width, height);
|
||||
|
||||
spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 512 - height, width, height), Color.White);
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, panelRect, Color.Black, true);
|
||||
|
||||
bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition);
|
||||
|
||||
int totalWireCount = 0;
|
||||
foreach (Connection c in panel.Connections)
|
||||
{
|
||||
totalWireCount += c.Wires.Count(w => w != null);
|
||||
}
|
||||
|
||||
Wire equippedWire = null;
|
||||
|
||||
//if the Character using the panel has a wire item equipped
|
||||
//and the wire hasn't been connected yet, draw it on the panel
|
||||
for (int i = 0; i < character.SelectedItems.Length; i++)
|
||||
{
|
||||
Item selectedItem = character.SelectedItems[i];
|
||||
|
||||
if (selectedItem == null) continue;
|
||||
|
||||
Wire wireComponent = selectedItem.GetComponent<Wire>();
|
||||
if (wireComponent != null) equippedWire = wireComponent;
|
||||
}
|
||||
|
||||
Vector2 rightPos = new Vector2(x + width - 130, y + 50);
|
||||
Vector2 leftPos = new Vector2(x + 130, y + 50);
|
||||
|
||||
Vector2 rightWirePos = new Vector2(x + width - 5, y + 30);
|
||||
|
||||
Vector2 leftWirePos = new Vector2(x + 5, y + 30);
|
||||
|
||||
int wireInterval = (height - 20) / Math.Max(totalWireCount, 1);
|
||||
|
||||
foreach (Connection c in panel.Connections)
|
||||
{
|
||||
//if dragging a wire, let the Inventory know so that the wire can be
|
||||
//dropped or dragged from the panel to the players inventory
|
||||
if (draggingConnected != null)
|
||||
{
|
||||
int linkIndex = c.FindWireIndex(draggingConnected.Item);
|
||||
if (linkIndex > -1)
|
||||
{
|
||||
Inventory.draggingItem = c.Wires[linkIndex].Item;
|
||||
}
|
||||
}
|
||||
|
||||
//outputs are drawn at the right side of the panel, inputs at the left
|
||||
if (c.IsOutput)
|
||||
{
|
||||
c.Draw(spriteBatch, panel.Item, rightPos,
|
||||
new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3),
|
||||
rightWirePos,
|
||||
mouseInRect, equippedWire,
|
||||
wireInterval);
|
||||
|
||||
rightPos.Y += 30;
|
||||
rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.Draw(spriteBatch, panel.Item, leftPos,
|
||||
new Vector2(leftPos.X + 20, leftPos.Y - 12),
|
||||
leftWirePos,
|
||||
mouseInRect, equippedWire,
|
||||
wireInterval);
|
||||
|
||||
leftPos.Y += 30;
|
||||
leftWirePos.Y += c.Wires.Count(w => w != null) * wireInterval;
|
||||
//leftWireX -= wireInterval;
|
||||
}
|
||||
}
|
||||
|
||||
if (draggingConnected != null)
|
||||
{
|
||||
DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null);
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
panel.Item.CreateClientEvent<ConnectionPanel>(panel);
|
||||
}
|
||||
else if (GameMain.Server != null)
|
||||
{
|
||||
panel.Item.CreateServerEvent<ConnectionPanel>(panel);
|
||||
}
|
||||
|
||||
draggingConnected = null;
|
||||
}
|
||||
}
|
||||
|
||||
//if the Character using the panel has a wire item equipped
|
||||
//and the wire hasn't been connected yet, draw it on the panel
|
||||
if (equippedWire != null)
|
||||
{
|
||||
if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null)
|
||||
{
|
||||
DrawWire(spriteBatch, equippedWire, equippedWire.Item,
|
||||
new Vector2(x + width / 2, y + height - 100),
|
||||
new Vector2(x + width / 2, y + height), mouseInRect, null);
|
||||
|
||||
if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item;
|
||||
}
|
||||
}
|
||||
|
||||
//stop dragging a wire item if cursor is outside the panel
|
||||
if (mouseInRect) Inventory.draggingItem = null;
|
||||
|
||||
|
||||
spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 0, width, height), Color.White);
|
||||
|
||||
}
|
||||
|
||||
private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval)
|
||||
{
|
||||
//spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White);
|
||||
GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X - 10, (int)position.Y - 10, 20, 20), Color.White);
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(64, 256, 32, 32), Color.White);
|
||||
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null || Wires[i].Hidden || draggingConnected == Wires[i]) continue;
|
||||
|
||||
Connection recipient = Wires[i].OtherConnection(this);
|
||||
|
||||
DrawWire(spriteBatch, Wires[i], (recipient == null) ? Wires[i].Item : recipient.item, position, wirePosition, mouseIn, equippedWire);
|
||||
|
||||
wirePosition.Y += wireInterval;
|
||||
}
|
||||
|
||||
if (draggingConnected != null && Vector2.Distance(position, PlayerInput.MousePosition) < 13.0f)
|
||||
{
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(21.5f, 21.5f), new Rectangle(106, 250, 43, 43), Color.White);
|
||||
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
//find an empty cell for the new connection
|
||||
int index = FindWireIndex(null);
|
||||
|
||||
if (index > -1 && !Wires.Contains(draggingConnected))
|
||||
{
|
||||
bool alreadyConnected = draggingConnected.IsConnectedTo(item);
|
||||
|
||||
draggingConnected.RemoveConnection(item);
|
||||
|
||||
if (draggingConnected.Connect(this, !alreadyConnected, true)) Wires[index] = draggingConnected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int screwIndex = (position.Y % 60 < 30) ? 0 : 1;
|
||||
|
||||
if (Wires.Any(w => w != null && w != draggingConnected))
|
||||
{
|
||||
spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(screwIndex * 32, 256, 32, 32), Color.White);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire)
|
||||
{
|
||||
if (draggingConnected == wire)
|
||||
{
|
||||
if (!mouseIn) return;
|
||||
end = PlayerInput.MousePosition;
|
||||
start.X = (start.X + end.X) / 2.0f;
|
||||
}
|
||||
|
||||
int textX = (int)start.X;
|
||||
if (start.X < end.X)
|
||||
textX -= 10;
|
||||
else
|
||||
textX += 10;
|
||||
|
||||
bool canDrag = equippedWire == null || equippedWire == wire;
|
||||
|
||||
float alpha = canDrag ? 1.0f : 0.5f;
|
||||
|
||||
bool mouseOn =
|
||||
canDrag &&
|
||||
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
|
||||
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
|
||||
MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) ||
|
||||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
|
||||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
|
||||
|
||||
string label = wire.Locked ? item.Name + "\n(Locked)" : item.Name;
|
||||
|
||||
GUI.DrawString(spriteBatch,
|
||||
new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f),
|
||||
label,
|
||||
(mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f,
|
||||
3, GUI.SmallFont);
|
||||
|
||||
var wireEnd = end + Vector2.Normalize(start - end) * 30.0f;
|
||||
|
||||
float dist = Vector2.Distance(start, wireEnd);
|
||||
|
||||
if (mouseOn)
|
||||
{
|
||||
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(18, (int)dist)), wireVertical.SourceRect,
|
||||
Color.Gold,
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
|
||||
new Vector2(6, 0), // point in line about which to rotate
|
||||
SpriteEffects.None,
|
||||
0.0f);
|
||||
}
|
||||
spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(12, (int)dist)), wireVertical.SourceRect,
|
||||
wire.Item.Color * alpha,
|
||||
MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2, //angle of line (calulated above)
|
||||
new Vector2(6, 0), // point in line about which to rotate
|
||||
SpriteEffects.None,
|
||||
0.0f);
|
||||
|
||||
connector.Draw(spriteBatch, end, Color.White, new Vector2(10.0f, 10.0f), MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2);
|
||||
|
||||
if (draggingConnected == null && canDrag)
|
||||
{
|
||||
if (mouseOn)
|
||||
{
|
||||
ConnectionPanel.HighlightedWire = wire;
|
||||
|
||||
if (!wire.Locked)
|
||||
{
|
||||
//start dragging the wire
|
||||
if (PlayerInput.LeftButtonHeld()) draggingConnected = wire;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(XElement parentElement)
|
||||
{
|
||||
XElement newElement = new XElement(IsOutput ? "output" : "input", new XAttribute("name", Name));
|
||||
|
||||
Array.Sort(Wires, delegate(Wire wire1, Wire wire2)
|
||||
{
|
||||
if (wire1 == null) return 1;
|
||||
if (wire2 == null) return -1;
|
||||
return wire1.Item.ID.CompareTo(wire2.Item.ID);
|
||||
});
|
||||
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (Wires[i] == null) continue;
|
||||
|
||||
//Connection recipient = wires[i].OtherConnection(this);
|
||||
|
||||
//int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient);
|
||||
newElement.Add(new XElement("link",
|
||||
new XAttribute("w", Wires[i].Item.ID.ToString())));
|
||||
}
|
||||
|
||||
parentElement.Add(newElement);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ConnectLinked()
|
||||
{
|
||||
if (wireId == null) return;
|
||||
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (wireId[i] == 0) continue;
|
||||
|
||||
Item wireItem = MapEntity.FindEntityByID(wireId[i]) as Item;
|
||||
|
||||
if (wireItem == null) continue;
|
||||
Wires[i] = wireItem.GetComponent<Wire>();
|
||||
|
||||
if (Wires[i] != null)
|
||||
{
|
||||
if (Wires[i].Item.body != null) Wires[i].Item.body.Enabled = false;
|
||||
Wires[i].Connect(this, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public static Wire HighlightedWire;
|
||||
|
||||
public List<Connection> Connections;
|
||||
|
||||
Character user;
|
||||
|
||||
public ConnectionPanel(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
Connections = new List<Connection>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString())
|
||||
{
|
||||
case "input":
|
||||
Connections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
case "output":
|
||||
Connections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character)
|
||||
{
|
||||
if (character != Character.Controlled || character != user) return;
|
||||
|
||||
if (Screen.Selected != GameMain.EditMapScreen &&
|
||||
character.IsKeyHit(InputType.Select) &&
|
||||
character.SelectedConstruction == this.item) character.SelectedConstruction = null;
|
||||
|
||||
if (HighlightedWire != null)
|
||||
{
|
||||
HighlightedWire.Item.IsHighlighted = true;
|
||||
if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) HighlightedWire.Connections[0].Item.IsHighlighted = true;
|
||||
if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) HighlightedWire.Connections[1].Item.IsHighlighted = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (character != Character.Controlled || character != user) return;
|
||||
|
||||
HighlightedWire = null;
|
||||
Connection.DrawConnections(spriteBatch, this, character);
|
||||
|
||||
}
|
||||
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement componentElement = base.Save(parentElement);
|
||||
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
c.Save(componentElement);
|
||||
}
|
||||
|
||||
return componentElement;
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
c.ConnectLinked();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (user != null && user.SelectedConstruction != item) user = null;
|
||||
}
|
||||
|
||||
public override bool Select(Character picker)
|
||||
{
|
||||
user = picker;
|
||||
IsActive = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null || character!=user) return false;
|
||||
|
||||
var powered = item.GetComponent<Powered>();
|
||||
if (powered != null)
|
||||
{
|
||||
if (powered.Voltage < 0.1f) return false;
|
||||
}
|
||||
|
||||
float degreeOfSuccess = DegreeOfSuccess(character);
|
||||
if (Rand.Range(0.0f, 50.0f) < degreeOfSuccess) return false;
|
||||
|
||||
character.SetStun(5.0f);
|
||||
|
||||
item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Load(XElement element)
|
||||
{
|
||||
base.Load(element);
|
||||
|
||||
List<Connection> loadedConnections = new List<Connection>();
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString())
|
||||
{
|
||||
case "input":
|
||||
loadedConnections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
case "output":
|
||||
loadedConnections.Add(new Connection(subElement, item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i<loadedConnections.Count && i<Connections.Count; i++)
|
||||
{
|
||||
loadedConnections[i].wireId.CopyTo(Connections[i].wireId, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
foreach (Wire wire in c.Wires)
|
||||
{
|
||||
if (wire == null) continue;
|
||||
|
||||
if (wire.OtherConnection(c) == null) //wire not connected to anything else
|
||||
{
|
||||
wire.Item.Drop(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
wire.RemoveConnection(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
{
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
Wire[] wires = Array.FindAll(connection.Wires, w => w != null);
|
||||
msg.WriteRangedInteger(0, Connection.MaxLinked, wires.Length);
|
||||
for (int i = 0; i < wires.Length; i++)
|
||||
{
|
||||
msg.Write(wires[i].Item.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
int[] wireCounts = new int[Connections.Count];
|
||||
Wire[,] wires = new Wire[Connections.Count, Connection.MaxLinked];
|
||||
|
||||
//read wire IDs for each connection
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
wireCounts[i] = msg.ReadRangedInteger(0, Connection.MaxLinked);
|
||||
for (int j = 0; j < wireCounts[i]; j++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
|
||||
Item wireItem = MapEntity.FindEntityByID(wireId) as Item;
|
||||
if (wireItem == null) continue;
|
||||
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent != null)
|
||||
{
|
||||
wires[i, j] = wireComponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.CreateServerEvent<ConnectionPanel>(this);
|
||||
|
||||
//check if the character can access this connectionpanel
|
||||
//and all the wires they're trying to connect
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
foreach (Wire wire in wires)
|
||||
{
|
||||
if (wire != null)
|
||||
{
|
||||
//wire not found in any of the connections yet (client is trying to connect a new wire)
|
||||
// -> we need to check if the client has access to it
|
||||
if (!Connections.Any(connection => connection.Wires.Contains(wire)))
|
||||
{
|
||||
if (!wire.Item.CanClientAccess(c)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Networking.GameServer.Log(item.Name + " rewired by " + c.Character.Name, ServerLog.MessageType.ItemInteraction);
|
||||
|
||||
//update the connections
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
Connections[i].ClearConnections();
|
||||
|
||||
for (int j = 0; j < wireCounts[i]; j++)
|
||||
{
|
||||
if (wires[i, j] == null) continue;
|
||||
|
||||
Connections[i].Wires[j] = wires[i,j];
|
||||
wires[i, j].Connect(Connections[i], true);
|
||||
|
||||
var otherConnection = Connections[i].Wires[j].OtherConnection(Connections[i]);
|
||||
|
||||
Networking.GameServer.Log(
|
||||
item.Name + " (" + Connections[i].Name + ") -> " +
|
||||
(otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"), ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
ClientWrite(msg, extraData);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
foreach (Connection connection in Connections)
|
||||
{
|
||||
connection.ClearConnections();
|
||||
int wireCount = msg.ReadRangedInteger(0, Connection.MaxLinked);
|
||||
for (int i = 0; i < wireCount; i++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
|
||||
Item wireItem = MapEntity.FindEntityByID(wireId) as Item;
|
||||
if (wireItem == null) continue;
|
||||
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent == null) continue;
|
||||
|
||||
connection.Wires[i] = wireComponent;
|
||||
wireComponent.Connect(connection, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class DelayComponent : ItemComponent
|
||||
{
|
||||
const int SignalQueueSize = 500;
|
||||
|
||||
//the output is sent if both inputs have received a signal within the timeframe
|
||||
private TimeSpan delay;
|
||||
|
||||
private Queue<Tuple<string, DateTime>> signalQueue;
|
||||
|
||||
[InGameEditable, HasDefaultValue(1.0f, true)]
|
||||
public float Delay
|
||||
{
|
||||
get { return (float)delay.TotalSeconds; }
|
||||
set
|
||||
{
|
||||
float seconds = MathHelper.Clamp(value, 0.0f, 60.0f);
|
||||
|
||||
delay = new TimeSpan(0,0,0,0, (int)(seconds*1000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
public DelayComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
signalQueue = new Queue<Tuple<string, DateTime>>();
|
||||
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
while (signalQueue.Any() && signalQueue.Peek().Item2 + delay <= DateTime.Now)
|
||||
{
|
||||
var signalOut = signalQueue.Dequeue();
|
||||
|
||||
item.SendSignal(0, signalOut.Item1, "signal_out", null);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in":
|
||||
if (signalQueue.Count >= SignalQueueSize) return;
|
||||
|
||||
signalQueue.Enqueue(new Tuple<string, DateTime>(signal, DateTime.Now));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Lights;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class LightComponent : Powered, IServerSerializable, IDrawableComponent
|
||||
{
|
||||
|
||||
private Color lightColor;
|
||||
|
||||
private LightSource light;
|
||||
|
||||
private float range;
|
||||
|
||||
private float lightBrightness;
|
||||
|
||||
private float flicker;
|
||||
|
||||
private bool castShadows;
|
||||
|
||||
[Editable, HasDefaultValue(100.0f, true)]
|
||||
public float Range
|
||||
{
|
||||
get { return range; }
|
||||
set
|
||||
{
|
||||
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(true, true)]
|
||||
public bool CastShadows
|
||||
{
|
||||
get { return castShadows; }
|
||||
set
|
||||
{
|
||||
castShadows = value;
|
||||
if (light != null) light.CastShadows = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(false, true)]
|
||||
public bool IsOn
|
||||
{
|
||||
get { return IsActive; }
|
||||
set
|
||||
{
|
||||
if (IsActive == value) return;
|
||||
|
||||
IsActive = value;
|
||||
if (GameMain.Server != null) item.CreateServerEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
[HasDefaultValue(0.0f, false)]
|
||||
public float Flicker
|
||||
{
|
||||
get { return flicker; }
|
||||
set
|
||||
{
|
||||
flicker = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("1.0,1.0,1.0,1.0", true)]
|
||||
public string LightColor
|
||||
{
|
||||
get { return ToolBox.Vector4ToString(lightColor.ToVector4(), "0.00"); }
|
||||
set
|
||||
{
|
||||
Vector4 newColor = ToolBox.ParseToVector4(value, false);
|
||||
newColor.X = MathHelper.Clamp(newColor.X, 0.0f, 1.0f);
|
||||
newColor.Y = MathHelper.Clamp(newColor.Y, 0.0f, 1.0f);
|
||||
newColor.Z = MathHelper.Clamp(newColor.Z, 0.0f, 1.0f);
|
||||
newColor.W = MathHelper.Clamp(newColor.W, 0.0f, 1.0f);
|
||||
lightColor = new Color(newColor);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
light.Position += amount;
|
||||
}
|
||||
|
||||
public override bool IsActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return base.IsActive;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
base.IsActive = value;
|
||||
|
||||
if (light == null) return;
|
||||
light.Color = value ? lightColor : Color.Transparent;
|
||||
if (!value) lightBrightness = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public LightComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
light = new LightSource(element);
|
||||
light.ParentSub = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
|
||||
light.Position = item.Position;
|
||||
light.CastShadows = castShadows;
|
||||
|
||||
IsActive = IsOn;
|
||||
|
||||
//foreach (XElement subElement in element.Elements())
|
||||
//{
|
||||
// if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue;
|
||||
|
||||
// light.LightSprite = new Sprite(subElement);
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
light.ParentSub = item.Submarine;
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime);
|
||||
|
||||
if (item.Container != null)
|
||||
{
|
||||
light.Color = Color.Transparent;
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.body != null)
|
||||
{
|
||||
light.Position = item.Position;
|
||||
light.Rotation = item.body.Dir > 0.0f ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
|
||||
|
||||
if (!item.body.Enabled)
|
||||
{
|
||||
light.Color = Color.Transparent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (powerConsumption == 0.0f)
|
||||
{
|
||||
voltage = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
currPowerConsumption = powerConsumption;
|
||||
}
|
||||
|
||||
if (Rand.Range(0.0f, 1.0f) < 0.05f && voltage < Rand.Range(0.0f, minVoltage))
|
||||
{
|
||||
if (voltage > 0.1f) sparkSounds[Rand.Int(sparkSounds.Length)].Play(1.0f, 400.0f, item.WorldPosition);
|
||||
lightBrightness = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightBrightness = MathHelper.Lerp(lightBrightness, Math.Min(voltage, 1.0f), 0.1f);
|
||||
}
|
||||
|
||||
light.Color = lightColor * lightBrightness * (1.0f-Rand.Range(0.0f,Flicker));
|
||||
light.Range = range * (float)Math.Sqrt(lightBrightness);
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled))
|
||||
{
|
||||
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, 1.0f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, item.Sprite.Depth - 0.0001f);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
|
||||
light.Remove();
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power);
|
||||
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "toggle":
|
||||
IsActive = !IsActive;
|
||||
break;
|
||||
case "set_state":
|
||||
IsActive = (signal != "0");
|
||||
break;
|
||||
case "set_color":
|
||||
LightColor = signal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(IsOn);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
IsOn = msg.ReadBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class MotionSensor : ItemComponent
|
||||
{
|
||||
private const float UpdateInterval = 0.1f;
|
||||
|
||||
private string output, falseOutput;
|
||||
|
||||
private bool motionDetected;
|
||||
|
||||
private float range;
|
||||
|
||||
private float updateTimer;
|
||||
|
||||
[InGameEditable, HasDefaultValue(0.0f, true)]
|
||||
public float Range
|
||||
{
|
||||
get { return range; }
|
||||
set
|
||||
{
|
||||
range = MathHelper.Clamp(value, 0.0f, 500.0f);
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("1", true)]
|
||||
public string Output
|
||||
{
|
||||
get { return output; }
|
||||
set { output = value; }
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("", true)]
|
||||
public string FalseOutput
|
||||
{
|
||||
get { return falseOutput; }
|
||||
set { falseOutput = value; }
|
||||
}
|
||||
|
||||
public MotionSensor(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (motionDetected)
|
||||
{
|
||||
item.SendSignal(1, output, "state_out", null);
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(falseOutput))
|
||||
{
|
||||
item.SendSignal(1, falseOutput, "state_out", null);
|
||||
}
|
||||
|
||||
updateTimer -= deltaTime;
|
||||
if (updateTimer > 0.0f) return;
|
||||
|
||||
motionDetected = false;
|
||||
updateTimer = UpdateInterval;
|
||||
|
||||
if (item.body != null && item.body.Enabled)
|
||||
{
|
||||
if (Math.Abs(item.body.LinearVelocity.X) > 0.01f || Math.Abs(item.body.LinearVelocity.Y) > 0.1f)
|
||||
{
|
||||
motionDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
motionDetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class NotComponent : ItemComponent
|
||||
{
|
||||
public NotComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
if (connection.Name != "signal_in") return;
|
||||
|
||||
item.SendSignal(stepsTaken, signal=="0" ? "1" : "0", "signal_out", sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class OrComponent : AndComponent
|
||||
{
|
||||
public OrComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
bool sendOutput = false;
|
||||
for (int i = 0; i<timeSinceReceived.Length; i++)
|
||||
{
|
||||
if (timeSinceReceived[i] <= timeFrame) sendOutput = true;
|
||||
timeSinceReceived[i] += deltaTime;
|
||||
}
|
||||
|
||||
string signalOut = sendOutput ? output : falseOutput;
|
||||
if (string.IsNullOrEmpty(signalOut)) return;
|
||||
|
||||
item.SendSignal(0, signalOut, "signal_out", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class OxygenDetector : ItemComponent
|
||||
{
|
||||
public OxygenDetector(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (item.CurrentHull == null) return;
|
||||
|
||||
item.SendSignal(0, ((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out", null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Xml.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class RegExFindComponent : ItemComponent
|
||||
{
|
||||
private string output;
|
||||
|
||||
private string expression;
|
||||
|
||||
private string receivedSignal;
|
||||
private string previousReceivedSignal;
|
||||
|
||||
bool previousResult;
|
||||
|
||||
private Regex regex;
|
||||
|
||||
[InGameEditable, HasDefaultValue("1", true)]
|
||||
public string Output
|
||||
{
|
||||
get { return output; }
|
||||
set { output = value; }
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("", true)]
|
||||
public string Expression
|
||||
{
|
||||
get { return expression; }
|
||||
set
|
||||
{
|
||||
if (expression == value) return;
|
||||
expression = value;
|
||||
previousReceivedSignal = "";
|
||||
|
||||
try
|
||||
{
|
||||
regex = new Regex(@expression);
|
||||
}
|
||||
|
||||
catch
|
||||
{
|
||||
item.SendSignal(0, "ERROR", "signal_out", null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RegExFindComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(expression) || regex==null) return;
|
||||
|
||||
if (receivedSignal != previousReceivedSignal)
|
||||
{
|
||||
try
|
||||
{
|
||||
Match match = regex.Match(receivedSignal);
|
||||
previousResult = match.Success;
|
||||
previousReceivedSignal = receivedSignal;
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
item.SendSignal(0, "ERROR", "signal_out", null);
|
||||
previousResult = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.SendSignal(0, previousResult ? output : "0", "signal_out", null);
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f)
|
||||
{
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in":
|
||||
receivedSignal = signal;
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class RelayComponent : PowerTransfer, IServerSerializable
|
||||
{
|
||||
private float maxPower;
|
||||
|
||||
[Editable, HasDefaultValue(1000.0f, true)]
|
||||
public float MaxPower
|
||||
{
|
||||
get { return maxPower; }
|
||||
set
|
||||
{
|
||||
maxPower = Math.Max(0.0f, value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool isOn;
|
||||
|
||||
[Editable, HasDefaultValue(false, true)]
|
||||
public bool IsOn
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsActive;
|
||||
}
|
||||
set
|
||||
{
|
||||
isOn = value;
|
||||
IsActive = value;
|
||||
if (!IsActive)
|
||||
{
|
||||
currPowerConsumption = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RelayComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
IsActive = isOn;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
base.Update(deltaTime, cam);
|
||||
|
||||
item.SendSignal(0, IsOn ? "1" : "0", "state_out", null);
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
if (connection.IsPower && connection.Name.Contains("_out")) return;
|
||||
|
||||
if (item.Condition <= 0.0f) return;
|
||||
|
||||
if (power > maxPower) item.Condition = 0.0f;
|
||||
|
||||
if (connection.Name.Contains("_in"))
|
||||
{
|
||||
if (!IsOn) return;
|
||||
|
||||
string outConnection = connection.Name.Contains("power_in") ? "power_out" : "signal_out";
|
||||
|
||||
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);
|
||||
}
|
||||
else if (connection.Name == "toggle")
|
||||
{
|
||||
SetState(!IsOn, false);
|
||||
}
|
||||
else if (connection.Name == "set_state")
|
||||
{
|
||||
SetState(signal != "0", false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetState(bool on, bool isNetworkMessage)
|
||||
{
|
||||
if (GameMain.Client != null && !isNetworkMessage) return;
|
||||
|
||||
if (on != IsOn && GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
IsOn = on;
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(isOn);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
SetState(msg.ReadBoolean(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class SignalCheckComponent : ItemComponent
|
||||
{
|
||||
private string output, falseOutput;
|
||||
|
||||
private string targetSignal;
|
||||
|
||||
[InGameEditable, HasDefaultValue("1", true)]
|
||||
public string Output
|
||||
{
|
||||
get { return output; }
|
||||
set { output = value; }
|
||||
}
|
||||
[InGameEditable, HasDefaultValue("0", true)]
|
||||
public string FalseOutput
|
||||
{
|
||||
get { return falseOutput; }
|
||||
set { falseOutput = value; }
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue("", true)]
|
||||
public string TargetSignal
|
||||
{
|
||||
get { return targetSignal; }
|
||||
set { targetSignal = value; }
|
||||
}
|
||||
|
||||
public SignalCheckComponent(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
switch (connection.Name)
|
||||
{
|
||||
case "signal_in":
|
||||
string signalOut = (signal == targetSignal) ? output : falseOutput;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(signalOut)) return;
|
||||
item.SendSignal(stepsTaken, signalOut, "signal_out", sender);
|
||||
|
||||
break;
|
||||
case "set_output":
|
||||
output = signal;
|
||||
break;
|
||||
case "set_targetsignal":
|
||||
targetSignal = signal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class WaterDetector : ItemComponent
|
||||
{
|
||||
public WaterDetector(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
item.SendSignal(0, item.InWater ? "1" : "0", "signal_out", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class WifiComponent : ItemComponent
|
||||
{
|
||||
private static List<WifiComponent> list = new List<WifiComponent>();
|
||||
|
||||
private float range;
|
||||
|
||||
private int channel;
|
||||
|
||||
[HasDefaultValue(20000.0f, false)]
|
||||
public float Range
|
||||
{
|
||||
get { return range; }
|
||||
set { range = Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
[InGameEditable, HasDefaultValue(1, true)]
|
||||
public int Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set
|
||||
{
|
||||
channel = MathHelper.Clamp(value, 0, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(false, false)]
|
||||
public bool LinkToChat
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public WifiComponent(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
|
||||
list.Add(this);
|
||||
}
|
||||
|
||||
public bool CanTransmit()
|
||||
{
|
||||
return HasRequiredContainedItems(true);
|
||||
}
|
||||
|
||||
/*public void Transmit(string signal)
|
||||
{
|
||||
if (!CanTransmit()) return;
|
||||
|
||||
var receivers = GetReceiversInRange();
|
||||
foreach (WifiComponent w in receivers)
|
||||
{
|
||||
var connections = w.item.Connections;
|
||||
|
||||
w.ReceiveSignal(1, signal, connections == null ? null : connections.Find(c => c.Name == "signal_in"), item, null);
|
||||
}
|
||||
}*/
|
||||
|
||||
private List<WifiComponent> GetReceiversInRange()
|
||||
{
|
||||
return list.FindAll(w => w != this && w.CanReceive(this));
|
||||
}
|
||||
|
||||
public bool CanReceive(WifiComponent sender)
|
||||
{
|
||||
if (!HasRequiredContainedItems(false)) return false;
|
||||
|
||||
if (sender == null || sender.channel != channel) return false;
|
||||
|
||||
return Vector2.Distance(item.WorldPosition, sender.item.WorldPosition) <= sender.Range;
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power=0.0f)
|
||||
{
|
||||
var senderComponent = source.GetComponent<WifiComponent>();
|
||||
if (senderComponent != null && !CanReceive(senderComponent)) return;
|
||||
|
||||
if (LinkToChat)
|
||||
{
|
||||
if (item.ParentInventory != null &&
|
||||
item.ParentInventory.Owner != null &&
|
||||
item.ParentInventory.Owner == Character.Controlled &&
|
||||
GameMain.NetworkMember != null)
|
||||
{
|
||||
if (senderComponent != null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
|
||||
list.Remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,746 @@
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class Wire : ItemComponent, IDrawableComponent, IServerSerializable
|
||||
{
|
||||
class WireSection
|
||||
{
|
||||
private Vector2 start;
|
||||
|
||||
private float angle;
|
||||
private float length;
|
||||
|
||||
public WireSection(Vector2 start, Vector2 end)
|
||||
{
|
||||
this.start = start;
|
||||
|
||||
angle = MathUtils.VectorToAngle(end - start);
|
||||
length = Vector2.Distance(start, end);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Color color, Vector2 offset, float depth, float width = 0.3f)
|
||||
{
|
||||
spriteBatch.Draw(wireSprite.Texture,
|
||||
new Vector2(start.X+offset.X, -(start.Y+offset.Y)), null, color,
|
||||
-angle,
|
||||
new Vector2(0.0f, wireSprite.size.Y / 2.0f),
|
||||
new Vector2(length / wireSprite.Texture.Width, width),
|
||||
SpriteEffects.None,
|
||||
depth);
|
||||
}
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color, float depth, float width = 0.3f)
|
||||
{
|
||||
start.Y = -start.Y;
|
||||
end.Y = -end.Y;
|
||||
|
||||
spriteBatch.Draw(wireSprite.Texture,
|
||||
start, null, color,
|
||||
MathUtils.VectorToAngle(end - start),
|
||||
new Vector2(0.0f, wireSprite.size.Y / 2.0f),
|
||||
new Vector2((Vector2.Distance(start, end)) / wireSprite.Texture.Width, width),
|
||||
SpriteEffects.None,
|
||||
depth);
|
||||
}
|
||||
}
|
||||
|
||||
const float nodeDistance = 32.0f;
|
||||
const float heightFromFloor = 128.0f;
|
||||
|
||||
static Sprite wireSprite;
|
||||
|
||||
private List<Vector2> nodes;
|
||||
private List<WireSection> sections;
|
||||
|
||||
Connection[] connections;
|
||||
|
||||
private Vector2 newNodePos;
|
||||
|
||||
|
||||
|
||||
private static Wire draggingWire;
|
||||
private static int? selectedNodeIndex;
|
||||
private static int? highlightedNodeIndex;
|
||||
|
||||
public bool Hidden, Locked;
|
||||
|
||||
public Connection[] Connections
|
||||
{
|
||||
get { return connections; }
|
||||
}
|
||||
|
||||
public Wire(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
if (wireSprite == null)
|
||||
{
|
||||
wireSprite = new Sprite("Content/Items/wireHorizontal.png", new Vector2(0.5f, 0.5f));
|
||||
wireSprite.Depth = 0.85f;
|
||||
}
|
||||
|
||||
nodes = new List<Vector2>();
|
||||
sections = new List<WireSection>();
|
||||
|
||||
connections = new Connection[2];
|
||||
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
public Connection OtherConnection(Connection connection)
|
||||
{
|
||||
if (connection == null) return null;
|
||||
if (connection == connections[0]) return connections[1];
|
||||
if (connection == connections[1]) return connections[0];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsConnectedTo(Item item)
|
||||
{
|
||||
if (connections[0] != null && connections[0].Item == item) return true;
|
||||
return (connections[1] != null && connections[1].Item == item);
|
||||
}
|
||||
|
||||
public void RemoveConnection(Item item)
|
||||
{
|
||||
for (int i = 0; i<2; i++)
|
||||
{
|
||||
if (connections[i]==null || connections[i].Item!=item) continue;
|
||||
|
||||
for (int n = 0; n< connections[i].Wires.Length; n++)
|
||||
{
|
||||
if (connections[i].Wires[n] != this) continue;
|
||||
|
||||
connections[i].Wires[n] = null;
|
||||
}
|
||||
connections[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveConnection(Connection connection)
|
||||
{
|
||||
if (connection == connections[0]) connections[0] = null;
|
||||
if (connection == connections[1]) connections[1] = null;
|
||||
}
|
||||
|
||||
public bool Connect(Connection newConnection, bool addNode = true, bool sendNetworkEvent = false)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] == newConnection) return false;
|
||||
}
|
||||
|
||||
if (!connections.Any(c => c == null)) return false;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] != null && connections[i].Item == newConnection.Item)
|
||||
{
|
||||
addNode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.body != null) item.Submarine = newConnection.Item.Submarine;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] != null) continue;
|
||||
|
||||
connections[i] = newConnection;
|
||||
|
||||
if (!addNode) break;
|
||||
|
||||
if (newConnection.Item.Submarine == null) continue;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
nodes.Insert(0, newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (connections[0] != null && connections[1] != null)
|
||||
{
|
||||
foreach (ItemComponent ic in item.components)
|
||||
{
|
||||
if (ic == this) continue;
|
||||
ic.Drop(null);
|
||||
}
|
||||
if (item.Container != null) item.Container.RemoveContained(this.item);
|
||||
|
||||
if (item.body != null) item.body.Enabled = false;
|
||||
|
||||
IsActive = false;
|
||||
|
||||
CleanNodes();
|
||||
}
|
||||
|
||||
if (sendNetworkEvent)
|
||||
{
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
//the wire is active if only one end has been connected
|
||||
IsActive = connections[0] == null ^ connections[1] == null;
|
||||
}
|
||||
|
||||
Drawable = IsActive || nodes.Any();
|
||||
|
||||
UpdateSections();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Equip(Character character)
|
||||
{
|
||||
ClearConnections();
|
||||
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public override void Unequip(Character character)
|
||||
{
|
||||
ClearConnections();
|
||||
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
public override void Drop(Character dropper)
|
||||
{
|
||||
ClearConnections();
|
||||
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (nodes.Count == 0) return;
|
||||
|
||||
Submarine sub = null;
|
||||
if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine;
|
||||
if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine;
|
||||
|
||||
if ((item.Submarine != sub || sub == null) && Screen.Selected != GameMain.EditMapScreen)
|
||||
{
|
||||
ClearConnections();
|
||||
return;
|
||||
}
|
||||
|
||||
newNodePos = RoundNode(item.Position, item.CurrentHull) - sub.HiddenSubPosition;
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == Character.Controlled && character.SelectedConstruction != null) return false;
|
||||
|
||||
if (newNodePos!= Vector2.Zero && nodes.Count>0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
{
|
||||
nodes.Add(newNodePos);
|
||||
UpdateSections();
|
||||
|
||||
Drawable = true;
|
||||
|
||||
newNodePos = Vector2.Zero;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SecondaryUse(float deltaTime, Character character = null)
|
||||
{
|
||||
if (nodes.Count > 1)
|
||||
{
|
||||
nodes.RemoveAt(nodes.Count - 1);
|
||||
UpdateSections();
|
||||
}
|
||||
|
||||
Drawable = IsActive || sections.Count > 0;
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
ClearConnections();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
if (item.IsSelected) MoveNodes(amount);
|
||||
}
|
||||
|
||||
public List<Vector2> GetNodes()
|
||||
{
|
||||
return new List<Vector2>(nodes);
|
||||
}
|
||||
|
||||
public void SetNodes(List<Vector2> nodes)
|
||||
{
|
||||
this.nodes = new List<Vector2>(nodes);
|
||||
UpdateSections();
|
||||
}
|
||||
|
||||
public void MoveNodes(Vector2 amount)
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
nodes[i] += amount;
|
||||
}
|
||||
UpdateSections();
|
||||
}
|
||||
|
||||
public void UpdateSections()
|
||||
{
|
||||
sections.Clear();
|
||||
|
||||
for (int i = 0; i < nodes.Count-1; i++)
|
||||
{
|
||||
sections.Add(new WireSection(nodes[i], nodes[i + 1]));
|
||||
}
|
||||
Drawable = IsActive || sections.Count > 0;
|
||||
}
|
||||
|
||||
private void ClearConnections()
|
||||
{
|
||||
nodes.Clear();
|
||||
sections.Clear();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] == null) continue;
|
||||
int wireIndex = connections[i].FindWireIndex(item);
|
||||
|
||||
if (wireIndex == -1) continue;
|
||||
connections[i].AddLink(wireIndex, null);
|
||||
|
||||
connections[i] = null;
|
||||
}
|
||||
|
||||
Drawable = sections.Count > 0;
|
||||
}
|
||||
|
||||
private Vector2 RoundNode(Vector2 position, Hull hull)
|
||||
{
|
||||
if (Screen.Selected == GameMain.EditMapScreen)
|
||||
{
|
||||
position.X = MathUtils.Round(position.X, Submarine.GridSize.X / 2.0f);
|
||||
position.Y = MathUtils.Round(position.Y, Submarine.GridSize.Y / 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
position.X = MathUtils.Round(position.X, nodeDistance);
|
||||
if (hull == null)
|
||||
{
|
||||
position.Y = MathUtils.Round(position.Y, nodeDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
position.Y -= hull.Rect.Y - hull.Rect.Height;
|
||||
position.Y = Math.Max(MathUtils.Round(position.Y, nodeDistance), heightFromFloor);
|
||||
position.Y += hull.Rect.Y -hull.Rect.Height;
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
private void CleanNodes()
|
||||
{
|
||||
for (int i = nodes.Count - 2; i > 0; i--)
|
||||
{
|
||||
if ((nodes[i - 1].X == nodes[i].X || nodes[i - 1].Y == nodes[i].Y) &&
|
||||
(nodes[i + 1].X == nodes[i].X || nodes[i + 1].Y == nodes[i].Y))
|
||||
{
|
||||
if (Vector2.Distance(nodes[i - 1], nodes[i]) == Vector2.Distance(nodes[i + 1], nodes[i]))
|
||||
{
|
||||
nodes.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool removed;
|
||||
do
|
||||
{
|
||||
removed = false;
|
||||
for (int i = nodes.Count - 2; i > 0; i--)
|
||||
{
|
||||
if ((nodes[i - 1].X == nodes[i].X && nodes[i + 1].X == nodes[i].X)
|
||||
|| (nodes[i - 1].Y == nodes[i].Y && nodes[i + 1].Y == nodes[i].Y))
|
||||
{
|
||||
nodes.RemoveAt(i);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
} while (removed);
|
||||
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
{
|
||||
if (sections.Count == 0 && !IsActive)
|
||||
{
|
||||
Drawable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 drawOffset = Vector2.Zero;
|
||||
if (item.Submarine != null)
|
||||
{
|
||||
drawOffset = item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition;
|
||||
}
|
||||
|
||||
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
|
||||
|
||||
if (item.IsHighlighted)
|
||||
{
|
||||
foreach (WireSection section in sections)
|
||||
{
|
||||
section.Draw(spriteBatch, Color.Gold, drawOffset, depth + 0.00001f, 0.7f);
|
||||
}
|
||||
}
|
||||
else if (item.IsSelected)
|
||||
{
|
||||
foreach (WireSection section in sections)
|
||||
{
|
||||
section.Draw(spriteBatch, Color.Red, drawOffset, depth + 0.00001f, 0.7f);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (WireSection section in sections)
|
||||
{
|
||||
section.Draw(spriteBatch, item.Color, drawOffset, depth, 0.3f);
|
||||
}
|
||||
|
||||
if (IsActive && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
{
|
||||
WireSection.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
|
||||
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
|
||||
item.Color * 0.5f,
|
||||
depth,
|
||||
0.3f);
|
||||
}
|
||||
|
||||
if (!editing || !GameMain.EditMapScreen.WiringMode) return;
|
||||
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
Vector2 drawPos = nodes[i];
|
||||
if (item.Submarine != null) drawPos += item.Submarine.Position + item.Submarine.HiddenSubPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
if (item.IsSelected)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-5, -5), new Vector2(10, 10), item.Color, true, 0.0f);
|
||||
|
||||
if (highlightedNodeIndex == i)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), Color.Red, false, 0.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateEditing(List<Wire> wires)
|
||||
{
|
||||
//dragging a node of some wire
|
||||
if (draggingWire != null)
|
||||
{
|
||||
//cancel dragging
|
||||
if (!PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
draggingWire = null;
|
||||
selectedNodeIndex = null;
|
||||
}
|
||||
//update dragging
|
||||
else
|
||||
{
|
||||
MapEntity.DisableSelect = true;
|
||||
|
||||
Submarine sub = null;
|
||||
if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null) sub = draggingWire.connections[0].Item.Submarine;
|
||||
if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null) sub = draggingWire.connections[1].Item.Submarine;
|
||||
|
||||
Vector2 nodeWorldPos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex];
|
||||
|
||||
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
|
||||
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
|
||||
|
||||
draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos;
|
||||
draggingWire.UpdateSections();
|
||||
|
||||
MapEntity.SelectEntity(draggingWire.item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//a wire has been selected -> check if we should start dragging one of the nodes
|
||||
float nodeSelectDist = 10, sectionSelectDist = 5;
|
||||
highlightedNodeIndex = null;
|
||||
if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item)
|
||||
{
|
||||
Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent<Wire>();
|
||||
|
||||
if (selectedWire != null)
|
||||
{
|
||||
Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (selectedWire.item.Submarine != null) mousePos -= (selectedWire.item.Submarine.Position + selectedWire.item.Submarine.HiddenSubPosition);
|
||||
|
||||
//left click while holding ctrl -> check if the cursor is on a wire section,
|
||||
//and add a new node if it is
|
||||
if (PlayerInput.KeyDown(Keys.RightControl) || PlayerInput.KeyDown(Keys.LeftControl))
|
||||
{
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
float temp = 0.0f;
|
||||
int closestSectionIndex = selectedWire.GetClosestSectionIndex(mousePos, sectionSelectDist, out temp);
|
||||
|
||||
if (closestSectionIndex > -1)
|
||||
{
|
||||
selectedWire.nodes.Insert(closestSectionIndex + 1, mousePos);
|
||||
selectedWire.UpdateSections();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//check if close enough to a node
|
||||
float temp = 0.0f;
|
||||
int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out temp);
|
||||
if (closestIndex > -1)
|
||||
{
|
||||
highlightedNodeIndex = closestIndex;
|
||||
//start dragging the node
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
draggingWire = selectedWire;
|
||||
selectedNodeIndex = closestIndex;
|
||||
}
|
||||
//remove the node
|
||||
else if (PlayerInput.RightButtonClicked() && closestIndex > 0 && closestIndex < selectedWire.nodes.Count - 1)
|
||||
{
|
||||
selectedWire.nodes.RemoveAt(closestIndex);
|
||||
selectedWire.UpdateSections();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check which wire is highlighted with the cursor
|
||||
Wire highlighted = null;
|
||||
float closestDist = 0.0f;
|
||||
foreach (Wire w in wires)
|
||||
{
|
||||
Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition);
|
||||
|
||||
float dist = 0.0f;
|
||||
if (w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out dist) > -1)
|
||||
{
|
||||
highlighted = w;
|
||||
closestDist = dist;
|
||||
}
|
||||
|
||||
if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
|
||||
{
|
||||
highlighted = w;
|
||||
closestDist = dist;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (highlighted != null)
|
||||
{
|
||||
highlighted.item.IsHighlighted = true;
|
||||
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
MapEntity.DisableSelect = true;
|
||||
MapEntity.SelectEntity(highlighted.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetClosestNodeIndex(Vector2 pos, float maxDist, out float closestDist)
|
||||
{
|
||||
closestDist = 0.0f;
|
||||
int closestIndex = -1;
|
||||
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
float dist = Vector2.Distance(nodes[i], pos);
|
||||
if (dist > maxDist) continue;
|
||||
|
||||
if (closestIndex == -1 || dist < closestDist)
|
||||
{
|
||||
closestIndex = i;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return closestIndex;
|
||||
}
|
||||
|
||||
private int GetClosestSectionIndex(Vector2 mousePos, float maxDist, out float closestDist)
|
||||
{
|
||||
closestDist = 0.0f;
|
||||
int closestIndex = -1;
|
||||
|
||||
for (int i = 0; i < nodes.Count-1; i++)
|
||||
{
|
||||
if ((Math.Abs(nodes[i].X - nodes[i + 1].X)<5 || Math.Sign(mousePos.X - nodes[i].X) != Math.Sign(mousePos.X - nodes[i + 1].X)) &&
|
||||
(Math.Abs(nodes[i].Y - nodes[i + 1].Y)<5 || Math.Sign(mousePos.Y - nodes[i].Y) != Math.Sign(mousePos.Y - nodes[i + 1].Y)))
|
||||
{
|
||||
float dist = MathUtils.LineToPointDistance(nodes[i], nodes[i + 1], mousePos);
|
||||
if (dist > maxDist) continue;
|
||||
|
||||
if (closestIndex == -1 || dist < closestDist)
|
||||
{
|
||||
closestIndex = i;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closestIndex;
|
||||
}
|
||||
|
||||
public override void FlipX()
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
nodes[i] = new Vector2(-nodes[i].X, nodes[i].Y);
|
||||
}
|
||||
UpdateSections();
|
||||
}
|
||||
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement componentElement = base.Save(parentElement);
|
||||
|
||||
if (nodes == null || nodes.Count == 0) return componentElement;
|
||||
|
||||
string[] nodeCoords = new string[nodes.Count * 2];
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
nodeCoords[i * 2] = nodes[i].X.ToString(CultureInfo.InvariantCulture);
|
||||
nodeCoords[i * 2 + 1] = nodes[i].Y.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
componentElement.Add(new XAttribute("nodes", string.Join(";", nodeCoords)));
|
||||
|
||||
return componentElement;
|
||||
}
|
||||
|
||||
public override void Load(XElement componentElement)
|
||||
{
|
||||
base.Load(componentElement);
|
||||
|
||||
string nodeString = ToolBox.GetAttributeString(componentElement, "nodes", "");
|
||||
if (nodeString == "") return;
|
||||
|
||||
string[] nodeCoords = nodeString.Split(';');
|
||||
for (int i = 0; i < nodeCoords.Length / 2; i++)
|
||||
{
|
||||
float x = 0.0f, y = 0.0f;
|
||||
|
||||
try
|
||||
{
|
||||
x = float.Parse(nodeCoords[i * 2], CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch { x = 0.0f; }
|
||||
|
||||
try
|
||||
{
|
||||
y = float.Parse(nodeCoords[i * 2 + 1], CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch { y = 0.0f; }
|
||||
|
||||
nodes.Add(new Vector2(x, y));
|
||||
}
|
||||
|
||||
Drawable = nodes.Any();
|
||||
}
|
||||
|
||||
protected override void ShallowRemoveComponentSpecific()
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (connections[i] == null) continue;
|
||||
int wireIndex = connections[i].FindWireIndex(item);
|
||||
|
||||
if (wireIndex > -1)
|
||||
{
|
||||
connections[i].AddLink(wireIndex, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
ClearConnections();
|
||||
|
||||
base.RemoveComponentSpecific();
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write((byte)Math.Min(nodes.Count, 255));
|
||||
for (int i = 0; i < Math.Min(nodes.Count, 255); i++)
|
||||
{
|
||||
msg.Write(nodes[i].X);
|
||||
msg.Write(nodes[i].Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
nodes.Clear();
|
||||
|
||||
int nodeCount = msg.ReadByte();
|
||||
Vector2[] nodePositions = new Vector2[nodeCount];
|
||||
|
||||
for (int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
nodePositions[i] = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||
}
|
||||
|
||||
if (nodePositions.Any(n => !MathUtils.IsValid(n))) return;
|
||||
|
||||
nodes = nodePositions.ToList();
|
||||
|
||||
UpdateSections();
|
||||
Drawable = nodes.Any();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user