Merge branch 'master' of https://github.com/Regalis11/Barotrauma.git into Regalis11-master

This commit is contained in:
Evil Factory
2021-12-15 14:45:31 -03:00
388 changed files with 12646 additions and 8136 deletions
@@ -19,6 +19,10 @@ namespace Barotrauma.Items.Components
get { return timeFrame; }
set
{
if (value > timeFrame)
{
timeSinceReceived[0] = timeSinceReceived[1] = Math.Max(value * 2.0f, 0.1f);
}
timeFrame = Math.Max(0.0f, value);
}
}
@@ -39,6 +39,10 @@ namespace Barotrauma.Items.Components
get { return timeFrame; }
set
{
if (value > timeFrame)
{
timeSinceReceived[0] = timeSinceReceived[1] = Math.Max(value * 2.0f, 0.1f);
}
timeFrame = Math.Max(0.0f, value);
}
}
@@ -36,9 +36,9 @@ namespace Barotrauma.Items.Components
if (UseHSV)
{
Color hsvColor = ToolBox.HSVToRGB(signalR, signalG, signalB);
signalR = hsvColor.R / (float) byte.MaxValue;
signalG = hsvColor.G / (float) byte.MaxValue;
signalB = hsvColor.B / (float) byte.MaxValue;
signalR = hsvColor.R;
signalG = hsvColor.G;
signalB = hsvColor.B;
}
output = signalR.ToString("G", CultureInfo.InvariantCulture);
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
namespace Barotrauma.Items.Components
{
class DelayComponent : ItemComponent
@@ -114,6 +114,18 @@ namespace Barotrauma.Items.Components
};
signalQueue.Enqueue(prevQueuedSignal);
break;
case "set_delay":
if (float.TryParse(signal.value, out float newDelay))
{
newDelay = MathHelper.Clamp(newDelay, 0, 60);
if (signalQueue.Count > 0 && newDelay != Delay)
{
prevQueuedSignal = null;
signalQueue.Clear();
}
Delay = newDelay;
}
break;
}
}
}
@@ -62,6 +62,10 @@ namespace Barotrauma.Items.Components
get { return timeFrame; }
set
{
if (value > timeFrame)
{
timeSinceReceived[0] = timeSinceReceived[1] = Math.Max(value * 2.0f, 0.1f);
}
timeFrame = Math.Max(0.0f, value);
}
}
@@ -36,9 +36,17 @@ namespace Barotrauma.Items.Components
{
case FunctionType.Round:
value = MathF.Round(value);
if (value == -0)
{
value = 0;
}
break;
case FunctionType.Ceil:
value = MathF.Ceiling(value);
if (value == -0)
{
value = 0;
}
break;
case FunctionType.Floor:
value = MathF.Floor(value);
@@ -43,7 +43,16 @@ namespace Barotrauma.Items.Components
}
}
public float Rotation;
private float rotation;
public float Rotation
{
get { return rotation; }
set
{
rotation = value;
SetLightSourceTransform();
}
}
[Editable, Serialize(true, true, description: "Should structures cast shadows when light from this light source hits them. " +
"Disabling shadows increases the performance of the game, and is recommended for lights with a short range.", alwaysUseInstanceValues: true)]
@@ -246,39 +255,14 @@ namespace Barotrauma.Items.Components
SetLightSourceState(false, 0.0f);
return;
}
#if CLIENT
if (ParentBody != null)
{
Light.Position = ParentBody.Position;
}
else if (turret != null)
{
Light.Position = new Vector2(item.Rect.X + turret.TransformedBarrelPos.X, item.Rect.Y - turret.TransformedBarrelPos.Y);
}
else
{
Light.Position = item.Position;
}
#endif
SetLightSourceTransform();
PhysicsBody body = ParentBody ?? item.body;
if (body != null)
if (body != null && !body.Enabled)
{
#if CLIENT
Light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
Light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
#endif
if (!body.Enabled)
{
SetLightSourceState(false, 0.0f);
return;
}
}
else
{
#if CLIENT
Light.Rotation = -Rotation - MathHelper.ToRadians(item.Rotation);
Light.LightSpriteEffect = item.SpriteEffects;
#endif
SetLightSourceState(false, 0.0f);
return;
}
currPowerConsumption = powerConsumption;
@@ -333,6 +317,9 @@ namespace Barotrauma.Items.Components
if (signal.value != prevColorSignal)
{
LightColor = XMLExtensions.ParseColor(signal.value, false);
#if CLIENT
SetLightSourceState(Light.Enabled, currentBrightness);
#endif
prevColorSignal = signal.value;
}
break;
@@ -350,5 +337,8 @@ namespace Barotrauma.Items.Components
}
partial void SetLightSourceState(bool enabled, float brightness);
partial void SetLightSourceTransform();
}
}
@@ -34,7 +34,12 @@ namespace Barotrauma.Items.Components
}
}
protected bool writeable = true;
[Editable, Serialize(true, true, description: "Can the value stored in the memory component be changed via signals.", alwaysUseInstanceValues: true)]
public bool Writeable
{
get;
set;
}
public MemoryComponent(Item item, XElement element)
: base(item, element)
@@ -54,7 +59,7 @@ namespace Barotrauma.Items.Components
switch (connection.Name)
{
case "signal_in":
if (writeable)
if (Writeable)
{
string prevValue = Value;
Value = signal.value;
@@ -66,7 +71,7 @@ namespace Barotrauma.Items.Components
break;
case "signal_store":
case "lock_state":
writeable = signal.value == "1";
Writeable = signal.value == "1";
break;
}
}
@@ -131,6 +131,13 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(true, true, description: "Should the sensor trigger when the item itself moves.")]
public bool DetectOwnMotion
{
get;
set;
}
public MotionSensor(Item item, XElement element)
: base(item, element)
{
@@ -168,7 +175,7 @@ namespace Barotrauma.Items.Components
MotionDetected = false;
updateTimer = UpdateInterval;
if (item.body != null && item.body.Enabled)
if (item.body != null && item.body.Enabled && DetectOwnMotion)
{
if (Math.Abs(item.body.LinearVelocity.X) > MinimumVelocity || Math.Abs(item.body.LinearVelocity.Y) > MinimumVelocity)
{
@@ -6,6 +6,8 @@ namespace Barotrauma.Items.Components
{
class RegExFindComponent : ItemComponent
{
private static readonly TimeSpan timeout = TimeSpan.FromSeconds(Timing.Step);
private string expression;
private string receivedSignal;
@@ -67,7 +69,10 @@ namespace Barotrauma.Items.Components
try
{
regex = new Regex(@expression);
regex = new Regex(
@expression,
options: RegexOptions.None,
matchTimeout: timeout);
}
catch
@@ -97,11 +102,14 @@ namespace Barotrauma.Items.Components
previousResult = match.Success;
previousGroups = UseCaptureGroup && previousResult ? match.Groups : null;
previousReceivedSignal = receivedSignal;
}
catch
catch (Exception e)
{
item.SendSignal("ERROR", "signal_out");
item.SendSignal(
e is RegexMatchTimeoutException
? "TIMEOUT"
: "ERROR",
"signal_out");
previousResult = false;
return;
}
@@ -24,6 +24,10 @@ namespace Barotrauma.Items.Components
get { return timeFrame; }
set
{
if (value > timeFrame)
{
timeSinceReceived[0] = timeSinceReceived[1] = Math.Max(value * 2.0f, 0.1f);
}
timeFrame = Math.Max(0.0f, value);
}
}
@@ -2,16 +2,35 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
namespace Barotrauma.Items.Components
{
readonly struct TerminalMessage
{
public readonly string Text;
public readonly Color Color;
public TerminalMessage(string text, Color color)
{
Text = text;
Color = color;
}
public void Deconstruct(out string text, out Color color)
{
text = Text;
color = Color;
}
}
partial class Terminal : ItemComponent
{
private const int MaxMessageLength = ChatMessage.MaxLength;
private const int MaxMessages = 60;
private List<string> messageHistory = new List<string>(MaxMessages);
private List<TerminalMessage> messageHistory = new List<TerminalMessage>(MaxMessages);
public string DisplayedWelcomeMessage
{
@@ -37,19 +56,39 @@ namespace Barotrauma.Items.Components
/// </summary>
public string ShowMessage
{
get { return messageHistory.Count == 0 ? string.Empty : messageHistory.Last(); }
get { return messageHistory.Count == 0 ? string.Empty : messageHistory.Last().Text; }
set
{
if (string.IsNullOrEmpty(value)) { return; }
ShowOnDisplay(value, addToHistory: true);
ShowOnDisplay(value, addToHistory: true, TextColor);
}
}
[Editable, Serialize(false, true, description: "The terminal will use a monospace font if this box is ticked.", alwaysUseInstanceValues: true)]
public bool UseMonospaceFont { get; set; }
private Color textColor = Color.LimeGreen;
[Editable, Serialize("50,205,50,255", true, description: "Color of the terminal text.", alwaysUseInstanceValues: true)]
public Color TextColor
{
get => textColor;
set
{
textColor = value;
#if CLIENT
if (inputBox is { } input)
{
input.TextColor = value;
}
#endif
}
}
private string OutputValue { get; set; }
private string prevColorSignal;
public Terminal(Item item, XElement element)
: base(item, element)
{
@@ -59,18 +98,41 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific(XElement element);
partial void ShowOnDisplay(string input, bool addToHistory);
partial void ShowOnDisplay(string input, bool addToHistory, Color color);
public override void ReceiveSignal(Signal signal, Connection connection)
{
if (connection.Name != "signal_in") { return; }
if (signal.value.Length > MaxMessageLength)
switch (connection.Name)
{
signal.value = signal.value.Substring(0, MaxMessageLength);
}
case "set_text":
case "signal_in":
if (signal.value.Length > MaxMessageLength)
{
signal.value = signal.value.Substring(0, MaxMessageLength);
}
string inputSignal = signal.value.Replace("\\n", "\n");
ShowOnDisplay(inputSignal, addToHistory: true);
string inputSignal = signal.value.Replace("\\n", "\n");
ShowOnDisplay(inputSignal, addToHistory: true, TextColor);
break;
case "set_text_color":
if (signal.value != prevColorSignal)
{
TextColor = XMLExtensions.ParseColor(signal.value, false);
prevColorSignal = signal.value;
}
break;
case "clear_text" when signal.value != "0":
messageHistory.Clear();
#if CLIENT
if (historyBox?.Content is { } history)
{
history.ClearChildren();
}
CreateFillerBlock();
#endif
break;
}
}
public override void OnItemLoaded()
@@ -83,7 +145,7 @@ namespace Barotrauma.Items.Components
base.OnItemLoaded();
if (!string.IsNullOrEmpty(DisplayedWelcomeMessage))
{
ShowOnDisplay(DisplayedWelcomeMessage, addToHistory: !isSubEditor);
ShowOnDisplay(DisplayedWelcomeMessage, addToHistory: !isSubEditor, TextColor);
DisplayedWelcomeMessage = "";
//remove welcome message if a game session is running so it doesn't reappear on successive rounds
if (GameMain.GameSession != null && !isSubEditor)
@@ -98,7 +160,8 @@ namespace Barotrauma.Items.Components
var componentElement = base.Save(parentElement);
for (int i = 0; i < messageHistory.Count; i++)
{
componentElement.Add(new XAttribute("msg" + i, messageHistory[i]));
componentElement.Add(new XAttribute("msg" + i, messageHistory[i].Text));
componentElement.Add(new XAttribute("color" + i, messageHistory[i].Color.ToStringHex()));
}
return componentElement;
}
@@ -109,8 +172,9 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < MaxMessages; i++)
{
string msg = componentElement.GetAttributeString("msg" + i, null);
if (msg == null) { break; }
ShowOnDisplay(msg, addToHistory: true);
if (msg is null) { break; }
Color color = componentElement.GetAttributeColor("color" + i, TextColor);
ShowOnDisplay(msg, addToHistory: true, color);
}
}
}
@@ -17,8 +17,8 @@ namespace Barotrauma.Items.Components
Atan,
}
private float[] receivedSignal = new float[2];
private float[] timeSinceReceived = new float[2];
private readonly float[] receivedSignal = new float[2];
private readonly float[] timeSinceReceived = new float[2];
[Serialize(FunctionType.Sin, false, description: "Which kind of function to run the input through.", alwaysUseInstanceValues: true)]
public FunctionType Function
@@ -77,7 +77,7 @@ namespace Barotrauma.Items.Components
//item in water -> we definitely want to send the True output
isInWater = true;
}
else if (item.CurrentHull != null && item.CurrentHull.WaterPercentage > 0.0f)
else if (item.CurrentHull != null && item.CurrentHull.WaterPercentage > 0.0f && item.CurrentHull.WaterVolume > 1.0f)
{
//(center of the) item in not water -> check if the water surface is below the bottom of the item's rect
if (item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
@@ -100,7 +100,12 @@ namespace Barotrauma.Items.Components
if (item.CurrentHull != null)
{
int waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
int waterPercentage = 0;
//ignore minuscule amounts of water
if (item.CurrentHull.WaterVolume > 1.0f)
{
waterPercentage = MathHelper.Clamp((int)Math.Ceiling(item.CurrentHull.WaterPercentage), 0, 100);
}
item.SendSignal(waterPercentage.ToString(), "water_%");
}
string highPressureOut = (item.CurrentHull == null || item.CurrentHull.LethalPressure > 5.0f) ? "1" : "0";
@@ -128,6 +128,9 @@ namespace Barotrauma.Items.Components
return HasRequiredContainedItems(user: null, addMessage: false);
}
/// <summary>
/// Returns the wifi components that can receive signals from this one
/// </summary>
public IEnumerable<WifiComponent> GetReceiversInRange()
{
return list.Where(w => w != this && w.CanReceive(this));
@@ -136,10 +139,16 @@ namespace Barotrauma.Items.Components
public bool CanReceive(WifiComponent sender)
{
if (sender == null || sender.channel != channel) { return false; }
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication) { return false; }
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication)
//if the component is not linked to chat and has nothing connected to the output, sending a signal to it does nothing
// = no point in receiving
if (!LinkToChat)
{
return false;
if (signalOutConnection == null || !signalOutConnection.Wires.Any(w => w != null))
{
return false;
}
}
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
@@ -147,6 +156,21 @@ namespace Barotrauma.Items.Components
return HasRequiredContainedItems(user: null, addMessage: false);
}
/// <summary>
/// Returns the wifi components that can transmit signals to this one
/// </summary>
public IEnumerable<WifiComponent> GetTransmittersInRange()
{
return list.Where(w => w != this && w.CanTransmit(this));
}
public bool CanTransmit(WifiComponent sender)
{
if (sender == null || sender.channel != channel) { return false; }
if (sender.TeamID != TeamID && !AllowCrossTeamCommunication) { return false; }
if (Vector2.DistanceSquared(item.WorldPosition, sender.item.WorldPosition) > sender.range * sender.range) { return false; }
return HasRequiredContainedItems(user: null, addMessage: false);
}
public override void Update(float deltaTime, Camera cam)
{
chatMsgCooldown -= deltaTime;
@@ -756,14 +756,17 @@ namespace Barotrauma.Items.Components
{
if (item.ParentInventory != null) { return; }
#if CLIENT
if (!relativeToSub && Screen.Selected != GameMain.SubEditorScreen) { return; }
if (!relativeToSub)
{
if (Screen.Selected != GameMain.SubEditorScreen || (item.Submarine?.Loading ?? false)) { return; }
}
#else
if (!relativeToSub) { return; }
#endif
Vector2 refPos = item.Submarine == null ?
Vector2.Zero :
item.Position - item.Submarine.HiddenSubPosition;
item.Position - item.Submarine.HiddenSubPosition;
for (int i = 0; i < nodes.Count; i++)
{