v0.14.6.0
This commit is contained in:
@@ -34,6 +34,11 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
public bool TemporarilyLocked
|
||||
{
|
||||
get { return Level.IsLoadedOutpost && item.GetComponent<DockingPort>() != null; }
|
||||
}
|
||||
|
||||
//connection panels can't be deactivated externally (by signals or status effects)
|
||||
public override bool IsActive
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private string[] labels;
|
||||
[Serialize("", true, description: "The texts displayed on the buttons/tickboxes, separated by commas.")]
|
||||
[Serialize("", true, description: "The texts displayed on the buttons/tickboxes, separated by commas.", alwaysUseInstanceValues: true)]
|
||||
public string Labels
|
||||
{
|
||||
get { return string.Join(",", labels); }
|
||||
@@ -111,7 +111,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private string[] signals;
|
||||
[Serialize("", true, description: "The signals sent when the buttons are pressed or the tickboxes checked, separated by commas.")]
|
||||
[Serialize("", true, description: "The signals sent when the buttons are pressed or the tickboxes checked, separated by commas.", alwaysUseInstanceValues: true)]
|
||||
public string Signals
|
||||
{
|
||||
//use semicolon as a separator because comma may be needed in the signals (for color or vector values for example)
|
||||
|
||||
+31
-26
@@ -20,9 +20,10 @@ namespace Barotrauma.Items.Components
|
||||
private bool castShadows;
|
||||
private bool drawBehindSubs;
|
||||
|
||||
|
||||
private double lastToggleSignalTime;
|
||||
|
||||
private string prevColorSignal;
|
||||
|
||||
public PhysicsBody ParentBody;
|
||||
|
||||
private Turret turret;
|
||||
@@ -37,7 +38,7 @@ namespace Barotrauma.Items.Components
|
||||
range = MathHelper.Clamp(value, 0.0f, 4096.0f);
|
||||
#if CLIENT
|
||||
item.ResetCachedVisibleSize();
|
||||
if (light != null) { light.Range = range; }
|
||||
if (Light != null) { Light.Range = range; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -53,7 +54,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
castShadows = value;
|
||||
#if CLIENT
|
||||
if (light != null) light.CastShadows = value;
|
||||
if (Light != null) Light.CastShadows = value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -67,7 +68,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
drawBehindSubs = value;
|
||||
#if CLIENT
|
||||
if (light != null) light.IsBackground = drawBehindSubs;
|
||||
if (Light != null) Light.IsBackground = drawBehindSubs;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -93,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
flicker = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
#if CLIENT
|
||||
if (light != null) { light.LightSourceParams.Flicker = flicker; }
|
||||
if (Light != null) { Light.LightSourceParams.Flicker = flicker; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -106,7 +107,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
flickerSpeed = value;
|
||||
#if CLIENT
|
||||
if (light != null) { light.LightSourceParams.FlickerSpeed = flickerSpeed; }
|
||||
if (Light != null) { Light.LightSourceParams.FlickerSpeed = flickerSpeed; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -119,7 +120,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
pulseFrequency = MathHelper.Clamp(value, 0.0f, 60.0f);
|
||||
#if CLIENT
|
||||
if (light != null) { light.LightSourceParams.PulseFrequency = pulseFrequency; }
|
||||
if (Light != null) { Light.LightSourceParams.PulseFrequency = pulseFrequency; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
pulseAmount = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
#if CLIENT
|
||||
if (light != null) { light.LightSourceParams.PulseAmount = pulseAmount; }
|
||||
if (Light != null) { Light.LightSourceParams.PulseAmount = pulseAmount; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -145,7 +146,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
blinkFrequency = MathHelper.Clamp(value, 0.0f, 60.0f);
|
||||
#if CLIENT
|
||||
if (light != null) { light.LightSourceParams.BlinkFrequency = blinkFrequency; }
|
||||
if (Light != null) { Light.LightSourceParams.BlinkFrequency = blinkFrequency; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -158,7 +159,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
lightColor = value;
|
||||
#if CLIENT
|
||||
if (light != null) light.Color = IsActive ? lightColor : Color.Transparent;
|
||||
if (Light != null) Light.Color = IsActive ? lightColor : Color.Transparent;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -173,7 +174,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
#if CLIENT
|
||||
light.Position += amount;
|
||||
Light.Position += amount;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -197,7 +198,7 @@ namespace Barotrauma.Items.Components
|
||||
: base(item, element)
|
||||
{
|
||||
#if CLIENT
|
||||
light = new LightSource(element)
|
||||
Light = new LightSource(element)
|
||||
{
|
||||
ParentSub = item.CurrentHull?.Submarine,
|
||||
Position = item.Position,
|
||||
@@ -206,11 +207,11 @@ namespace Barotrauma.Items.Components
|
||||
SpriteScale = Vector2.One * item.Scale,
|
||||
Range = range
|
||||
};
|
||||
light.LightSourceParams.Flicker = flicker;
|
||||
light.LightSourceParams.FlickerSpeed = FlickerSpeed;
|
||||
light.LightSourceParams.PulseAmount = pulseAmount;
|
||||
light.LightSourceParams.PulseFrequency = pulseFrequency;
|
||||
light.LightSourceParams.BlinkFrequency = blinkFrequency;
|
||||
Light.LightSourceParams.Flicker = flicker;
|
||||
Light.LightSourceParams.FlickerSpeed = FlickerSpeed;
|
||||
Light.LightSourceParams.PulseAmount = pulseAmount;
|
||||
Light.LightSourceParams.PulseFrequency = pulseFrequency;
|
||||
Light.LightSourceParams.BlinkFrequency = blinkFrequency;
|
||||
#endif
|
||||
|
||||
IsActive = IsOn;
|
||||
@@ -233,7 +234,7 @@ namespace Barotrauma.Items.Components
|
||||
UpdateOnActiveEffects(deltaTime);
|
||||
|
||||
#if CLIENT
|
||||
light.ParentSub = item.Submarine;
|
||||
Light.ParentSub = item.Submarine;
|
||||
#endif
|
||||
if (item.Container != null)
|
||||
{
|
||||
@@ -243,23 +244,23 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
if (ParentBody != null)
|
||||
{
|
||||
light.Position = ParentBody.Position;
|
||||
Light.Position = ParentBody.Position;
|
||||
}
|
||||
else if (turret != null)
|
||||
{
|
||||
light.Position = new Vector2(item.Rect.X + turret.TransformedBarrelPos.X, item.Rect.Y - turret.TransformedBarrelPos.Y);
|
||||
Light.Position = new Vector2(item.Rect.X + turret.TransformedBarrelPos.X, item.Rect.Y - turret.TransformedBarrelPos.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
light.Position = item.Position;
|
||||
Light.Position = item.Position;
|
||||
}
|
||||
#endif
|
||||
PhysicsBody body = ParentBody ?? item.body;
|
||||
if (body != null)
|
||||
{
|
||||
#if CLIENT
|
||||
light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
|
||||
light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||
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)
|
||||
{
|
||||
@@ -270,8 +271,8 @@ namespace Barotrauma.Items.Components
|
||||
else
|
||||
{
|
||||
#if CLIENT
|
||||
light.Rotation = -Rotation - MathHelper.ToRadians(item.Rotation);
|
||||
light.LightSpriteEffect = item.SpriteEffects;
|
||||
Light.Rotation = -Rotation - MathHelper.ToRadians(item.Rotation);
|
||||
Light.LightSpriteEffect = item.SpriteEffects;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -326,7 +327,11 @@ namespace Barotrauma.Items.Components
|
||||
IsOn = signal.value != "0";
|
||||
break;
|
||||
case "set_color":
|
||||
LightColor = XMLExtensions.ParseColor(signal.value, false);
|
||||
if (signal.value != prevColorSignal)
|
||||
{
|
||||
LightColor = XMLExtensions.ParseColor(signal.value, false);
|
||||
prevColorSignal = signal.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class MotionSensor : ItemComponent
|
||||
{
|
||||
private const float UpdateInterval = 0.1f;
|
||||
private float rangeX, rangeY;
|
||||
|
||||
private Vector2 detectOffset;
|
||||
@@ -19,7 +18,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Any,
|
||||
Human,
|
||||
Monster
|
||||
Monster,
|
||||
Wall
|
||||
}
|
||||
|
||||
[Serialize(false, false, description: "Has the item currently detected movement. Intended to be used by StatusEffect conditionals (setting this value in XML has no effect).")]
|
||||
@@ -74,6 +74,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(MinValueFloat = 0.1f, MaxValueFloat = 100.0f, DecimalCount = 2), Serialize(0.1f, true, description: "How often the sensor checks if there's something moving near it. Higher values are better for performance.", alwaysUseInstanceValues: true)]
|
||||
public float UpdateInterval
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private int maxOutputLength;
|
||||
[Editable, Serialize(200, false, description: "The maximum length of the output strings. Warning: Large values can lead to large memory usage or networking issues.")]
|
||||
public int MaxOutputLength
|
||||
@@ -134,6 +141,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
rangeX = rangeY = element.GetAttributeFloat("range", 0.0f);
|
||||
}
|
||||
|
||||
//randomize update timer so all sensors aren't updated during the same frame
|
||||
updateTimer = Rand.Range(0.0f, UpdateInterval);
|
||||
}
|
||||
|
||||
public override void Load(XElement componentElement, bool usePrefabValues, IdRemap idRemap)
|
||||
@@ -153,7 +163,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(new Signal(signalOut, 1), "state_out"); }
|
||||
|
||||
updateTimer -= deltaTime;
|
||||
if (updateTimer > 0.0f) return;
|
||||
if (updateTimer > 0.0f) { return; }
|
||||
|
||||
MotionDetected = false;
|
||||
updateTimer = UpdateInterval;
|
||||
@@ -163,6 +173,7 @@ namespace Barotrauma.Items.Components
|
||||
if (Math.Abs(item.body.LinearVelocity.X) > MinimumVelocity || Math.Abs(item.body.LinearVelocity.Y) > MinimumVelocity)
|
||||
{
|
||||
MotionDetected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,42 +182,94 @@ namespace Barotrauma.Items.Components
|
||||
float broadRangeX = Math.Max(rangeX * 2, 500);
|
||||
float broadRangeY = Math.Max(rangeY * 2, 500);
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
if (item.CurrentHull == null && item.Submarine != null && Level.Loaded != null &&
|
||||
(Target == TargetType.Wall || Target == TargetType.Any))
|
||||
{
|
||||
if (IgnoreDead && c.IsDead) { continue; }
|
||||
|
||||
//ignore characters that have spawned a second or less ago
|
||||
//makes it possible to detect when a spawned character moves without triggering the detector immediately as the ragdoll spawns and drops to the ground
|
||||
if (c.SpawnTime > Timing.TotalTime - 1.0) { continue; }
|
||||
|
||||
switch (Target)
|
||||
if (Math.Abs(item.Submarine.Velocity.X) > MinimumVelocity || Math.Abs(item.Submarine.Velocity.Y) > MinimumVelocity)
|
||||
{
|
||||
case TargetType.Human:
|
||||
if (!c.IsHuman) { continue; }
|
||||
break;
|
||||
case TargetType.Monster:
|
||||
if (c.IsHuman || c.IsPet) { continue; }
|
||||
break;
|
||||
var cells = Level.Loaded.GetCells(item.WorldPosition, 1);
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
if (cell.IsPointInside(item.WorldPosition))
|
||||
{
|
||||
MotionDetected = true;
|
||||
return;
|
||||
}
|
||||
foreach (var edge in cell.Edges)
|
||||
{
|
||||
Vector2 e1 = edge.Point1 + cell.Translation;
|
||||
Vector2 e2 = edge.Point2 + cell.Translation;
|
||||
if (MathUtils.LinesIntersect(e1, e2, new Vector2(detectRect.X, detectRect.Y), new Vector2(detectRect.Right, detectRect.Y)) ||
|
||||
MathUtils.LinesIntersect(e1, e2, new Vector2(detectRect.X, detectRect.Bottom), new Vector2(detectRect.Right, detectRect.Bottom)) ||
|
||||
MathUtils.LinesIntersect(e1, e2, new Vector2(detectRect.X, detectRect.Y), new Vector2(detectRect.X, detectRect.Bottom)) ||
|
||||
MathUtils.LinesIntersect(e1, e2, new Vector2(detectRect.Right, detectRect.Y), new Vector2(detectRect.Right, detectRect.Bottom)))
|
||||
{
|
||||
MotionDetected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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)
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sub == item.Submarine) { continue; }
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (limb.LinearVelocity.LengthSquared() <= MinimumVelocity * MinimumVelocity) { continue; }
|
||||
if (MathUtils.CircleIntersectsRectangle(limb.WorldPosition, ConvertUnits.ToDisplayUnits(limb.body.GetMaxExtent()), detectRect))
|
||||
Vector2 relativeVelocity = item.Submarine.Velocity - sub.Velocity;
|
||||
if (Math.Abs(relativeVelocity.X) < MinimumVelocity && Math.Abs(relativeVelocity.Y) < MinimumVelocity) { continue; }
|
||||
|
||||
Rectangle worldBorders = new Rectangle(
|
||||
sub.Borders.X + (int)sub.WorldPosition.X,
|
||||
sub.Borders.Y + (int)sub.WorldPosition.Y - sub.Borders.Height,
|
||||
sub.Borders.Width,
|
||||
sub.Borders.Height);
|
||||
|
||||
if (worldBorders.Intersects(detectRect))
|
||||
{
|
||||
MotionDetected = true;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Target != TargetType.Wall)
|
||||
{
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (IgnoreDead && c.IsDead) { continue; }
|
||||
|
||||
//ignore characters that have spawned a second or less ago
|
||||
//makes it possible to detect when a spawned character moves without triggering the detector immediately as the ragdoll spawns and drops to the ground
|
||||
if (c.SpawnTime > Timing.TotalTime - 1.0) { continue; }
|
||||
|
||||
switch (Target)
|
||||
{
|
||||
case TargetType.Human:
|
||||
if (!c.IsHuman) { continue; }
|
||||
break;
|
||||
case TargetType.Monster:
|
||||
if (c.IsHuman || c.IsPet) { continue; }
|
||||
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.IsSevered) { continue; }
|
||||
if (limb.LinearVelocity.LengthSquared() <= MinimumVelocity * MinimumVelocity) { continue; }
|
||||
if (MathUtils.CircleIntersectsRectangle(limb.WorldPosition, ConvertUnits.ToDisplayUnits(limb.body.GetMaxExtent()), detectRect))
|
||||
{
|
||||
MotionDetected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
|
||||
@@ -19,5 +19,22 @@ namespace Barotrauma.Items.Components
|
||||
this.power = power;
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
internal Signal WithStepsTaken(int stepsTaken)
|
||||
{
|
||||
Signal retVal = this;
|
||||
retVal.stepsTaken = stepsTaken;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static bool operator==(Signal a, Signal b) =>
|
||||
a.value == b.value &&
|
||||
a.stepsTaken == b.stepsTaken &&
|
||||
a.sender == b.sender &&
|
||||
a.source == b.source &&
|
||||
MathUtils.NearlyEqual(a.power, b.power) &&
|
||||
MathUtils.NearlyEqual(a.strength, b.strength);
|
||||
|
||||
public static bool operator!=(Signal a, Signal b) => !(a == b);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -64,6 +64,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value);
|
||||
bool sendOutputImmediately = true;
|
||||
switch (Function)
|
||||
{
|
||||
case FunctionType.Sin:
|
||||
@@ -105,11 +106,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
timeSinceReceived[0] = 0.0f;
|
||||
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]);
|
||||
sendOutputImmediately = false;
|
||||
}
|
||||
else if (connection.Name == "signal_in_y")
|
||||
{
|
||||
timeSinceReceived[1] = 0.0f;
|
||||
float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]);
|
||||
sendOutputImmediately = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -121,9 +124,11 @@ namespace Barotrauma.Items.Components
|
||||
default:
|
||||
throw new NotImplementedException($"Function {Function} has not been implemented.");
|
||||
}
|
||||
|
||||
signal.value = value.ToString("G", CultureInfo.InvariantCulture);
|
||||
item.SendSignal(signal, "signal_out");
|
||||
if (sendOutputImmediately)
|
||||
{
|
||||
signal.value = value.ToString("G", CultureInfo.InvariantCulture);
|
||||
item.SendSignal(signal, "signal_out");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, false, description: "If enabled, any signals received from another chat-linked wifi component are displayed " +
|
||||
[ConditionallyEditable(ConditionallyEditable.ConditionType.AllowLinkingWifiToChat)]
|
||||
[Serialize(false, false, description: "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.", alwaysUseInstanceValues: true)]
|
||||
public bool LinkToChat
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Items.Components
|
||||
get
|
||||
{
|
||||
if (GameMain.NetworkMember?.ServerSettings != null && !GameMain.NetworkMember.ServerSettings.AllowRewiring) { return false; }
|
||||
return locked || connections.Any(c => c != null && c.ConnectionPanel.Locked);
|
||||
return locked || connections.Any(c => c != null && (c.ConnectionPanel.Locked || c.ConnectionPanel.TemporarilyLocked));
|
||||
}
|
||||
set { locked = value; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user