From 355d00a0f2529a5beac6426837fad129d45a41a6 Mon Sep 17 00:00:00 2001
From: deltanedas <39013340+deltanedas@users.noreply.github.com>
Date: Fri, 29 Mar 2024 23:46:05 +0000
Subject: [PATCH 01/26] combine same-tile explosions in the same tick (#25664)
* combine same-tile explosions in the same tick
* !
---------
Co-authored-by: deltanedas <@deltanedas:kde.org>
---
.../ExplosionSystem.Processing.cs | 26 +++++-
.../EntitySystems/ExplosionSystem.cs | 80 ++++++++++++-------
.../Explosion/ExplosionPrototype.cs | 7 ++
3 files changed, 82 insertions(+), 31 deletions(-)
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs
index 60db6bdf5b..6e100fe656 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs
@@ -38,8 +38,15 @@ public sealed partial class ExplosionSystem
/// Queue for delayed processing of explosions. If there is an explosion that covers more than tiles, other explosions will actually be delayed slightly. Unless it's a station
/// nuke, this delay should never really be noticeable.
+ /// This is also used to combine explosion intensities of the same kind.
///
- private Queue> _explosionQueue = new();
+ private Queue _explosionQueue = new();
+
+ ///
+ /// All queued explosions that will be processed in .
+ /// These always have the same contents.
+ ///
+ private HashSet _queuedExplosions = new();
///
/// The explosion currently being processed.
@@ -93,10 +100,11 @@ public sealed partial class ExplosionSystem
if (MathF.Max(MaxProcessingTime - 1, 0.1f) < Stopwatch.Elapsed.TotalMilliseconds)
break;
- if (!_explosionQueue.TryDequeue(out var spawnNextExplosion))
+ if (!_explosionQueue.TryDequeue(out var queued))
break;
- _activeExplosion = spawnNextExplosion();
+ _queuedExplosions.Remove(queued);
+ _activeExplosion = SpawnExplosion(queued);
// explosion spawning can be null if something somewhere went wrong. (e.g., negative explosion
// intensity).
@@ -867,3 +875,15 @@ sealed class Explosion
_tileUpdateDict.Clear();
}
}
+
+///
+/// Data needed to spawn an explosion with .
+///
+public sealed class QueuedExplosion
+{
+ public MapCoordinates Epicenter;
+ public ExplosionPrototype Proto = new();
+ public float TotalIntensity, Slope, MaxTileIntensity, TileBreakScale;
+ public int MaxTileBreak;
+ public bool CanCreateVacuum;
+}
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
index 46238fd7c5..23543895e6 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionSystem.cs
@@ -112,6 +112,7 @@ public sealed partial class ExplosionSystem : EntitySystem
private void OnReset(RoundRestartCleanupEvent ev)
{
_explosionQueue.Clear();
+ _queuedExplosions.Clear();
if (_activeExplosion != null)
QueueDel(_activeExplosion.VisualEnt);
_activeExplosion = null;
@@ -297,8 +298,36 @@ public sealed partial class ExplosionSystem : EntitySystem
if (addLog) // dont log if already created a separate, more detailed, log.
_adminLogger.Add(LogType.Explosion, LogImpact.High, $"Explosion ({typeId}) spawned at {epicenter:coordinates} with intensity {totalIntensity} slope {slope}");
- _explosionQueue.Enqueue(() => SpawnExplosion(epicenter, type, totalIntensity,
- slope, maxTileIntensity, tileBreakScale, maxTileBreak, canCreateVacuum));
+ // try to combine explosions on the same tile if they are the same type
+ foreach (var queued in _queuedExplosions)
+ {
+ // ignore different types or those on different maps
+ if (queued.Proto.ID != type.ID || queued.Epicenter.MapId != epicenter.MapId)
+ continue;
+
+ var dst2 = queued.Proto.MaxCombineDistance * queued.Proto.MaxCombineDistance;
+ var direction = queued.Epicenter.Position - epicenter.Position;
+ if (direction.LengthSquared() > dst2)
+ continue;
+
+ // they are close enough to combine so just add total intensity and prevent queuing another one
+ queued.TotalIntensity += totalIntensity;
+ return;
+ }
+
+ var boom = new QueuedExplosion()
+ {
+ Epicenter = epicenter,
+ Proto = type,
+ TotalIntensity = totalIntensity,
+ Slope = slope,
+ MaxTileIntensity = maxTileIntensity,
+ TileBreakScale = tileBreakScale,
+ MaxTileBreak = maxTileBreak,
+ CanCreateVacuum = canCreateVacuum
+ };
+ _explosionQueue.Enqueue(boom);
+ _queuedExplosions.Add(boom);
}
///
@@ -306,32 +335,26 @@ public sealed partial class ExplosionSystem : EntitySystem
/// information about the affected tiles for the explosion system to process. It will also trigger the
/// camera shake and sound effect.
///
- private Explosion? SpawnExplosion(MapCoordinates epicenter,
- ExplosionPrototype type,
- float totalIntensity,
- float slope,
- float maxTileIntensity,
- float tileBreakScale,
- int maxTileBreak,
- bool canCreateVacuum)
+ private Explosion? SpawnExplosion(QueuedExplosion queued)
{
- if (!_mapManager.MapExists(epicenter.MapId))
+ var pos = queued.Epicenter;
+ if (!_mapManager.MapExists(pos.MapId))
return null;
- var results = GetExplosionTiles(epicenter, type.ID, totalIntensity, slope, maxTileIntensity);
+ var results = GetExplosionTiles(pos, queued.Proto.ID, queued.TotalIntensity, queued.Slope, queued.MaxTileIntensity);
if (results == null)
return null;
var (area, iterationIntensity, spaceData, gridData, spaceMatrix) = results.Value;
- var visualEnt = CreateExplosionVisualEntity(epicenter, type.ID, spaceMatrix, spaceData, gridData.Values, iterationIntensity);
+ var visualEnt = CreateExplosionVisualEntity(pos, queued.Proto.ID, spaceMatrix, spaceData, gridData.Values, iterationIntensity);
// camera shake
- CameraShake(iterationIntensity.Count * 4f, epicenter, totalIntensity);
+ CameraShake(iterationIntensity.Count * 4f, pos, queued.TotalIntensity);
//For whatever bloody reason, sound system requires ENTITY coordinates.
- var mapEntityCoords = EntityCoordinates.FromMap(_mapManager.GetMapEntityId(epicenter.MapId), epicenter, _transformSystem, EntityManager);
+ var mapEntityCoords = EntityCoordinates.FromMap(_mapManager.GetMapEntityId(pos.MapId), pos, _transformSystem, EntityManager);
// play sound.
// for the normal audio, we want everyone in pvs range
@@ -339,34 +362,35 @@ public sealed partial class ExplosionSystem : EntitySystem
// this is capped to 30 because otherwise really huge bombs
// will attempt to play regular audio for people who can't hear it anyway because the epicenter is so far away
var audioRange = Math.Min(iterationIntensity.Count * 2, MaxExplosionAudioRange);
- var filter = Filter.Pvs(epicenter).AddInRange(epicenter, audioRange);
- var sound = iterationIntensity.Count < type.SmallSoundIterationThreshold
- ? type.SmallSound
- : type.Sound;
+ var filter = Filter.Pvs(pos).AddInRange(pos, audioRange);
+ var sound = iterationIntensity.Count < queued.Proto.SmallSoundIterationThreshold
+ ? queued.Proto.SmallSound
+ : queued.Proto.Sound;
_audio.PlayStatic(sound, filter, mapEntityCoords, true, sound.Params);
// play far sound
// far sound should play for anyone who wasn't in range of any of the effects of the bomb
var farAudioRange = iterationIntensity.Count * 5;
- var farFilter = Filter.Empty().AddInRange(epicenter, farAudioRange).RemoveInRange(epicenter, audioRange);
- var farSound = iterationIntensity.Count < type.SmallSoundIterationThreshold
- ? type.SmallSoundFar
- : type.SoundFar;
+ var farFilter = Filter.Empty().AddInRange(pos, farAudioRange).RemoveInRange(pos, audioRange);
+ var farSound = iterationIntensity.Count < queued.Proto.SmallSoundIterationThreshold
+ ? queued.Proto.SmallSoundFar
+ : queued.Proto.SoundFar;
_audio.PlayGlobal(farSound, farFilter, true, farSound.Params);
return new Explosion(this,
- type,
+ queued.Proto,
spaceData,
gridData.Values.ToList(),
iterationIntensity,
- epicenter,
+ pos,
spaceMatrix,
area,
- tileBreakScale,
- maxTileBreak,
- canCreateVacuum,
+ // TODO: instead of le copy paste fields refactor so it has QueuedExplosion as a field?
+ queued.TileBreakScale,
+ queued.MaxTileBreak,
+ queued.CanCreateVacuum,
EntityManager,
_mapManager,
visualEnt);
diff --git a/Content.Shared/Explosion/ExplosionPrototype.cs b/Content.Shared/Explosion/ExplosionPrototype.cs
index ec9f2efa1e..df2fb18360 100644
--- a/Content.Shared/Explosion/ExplosionPrototype.cs
+++ b/Content.Shared/Explosion/ExplosionPrototype.cs
@@ -77,6 +77,13 @@ public sealed partial class ExplosionPrototype : IPrototype
[DataField("smallSoundIterationThreshold")]
public int SmallSoundIterationThreshold = 6;
+ ///
+ /// How far away another explosion in the same tick can be and be combined.
+ /// Total intensity is added to the original queued explosion.
+ ///
+ [DataField]
+ public float MaxCombineDistance = 1f;
+
[DataField("sound")]
public SoundSpecifier Sound = new SoundCollectionSpecifier("Explosion");
From 3a3652a767106b3111f93a0a0d2964d5259c2491 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Fri, 29 Mar 2024 23:47:13 +0000
Subject: [PATCH 02/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 5e5c44dd72..f3495edc01 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Agoichi
- changes:
- - message: Rebalanced Lobbying Bundle
- type: Tweak
- id: 5751
- time: '2024-01-20T02:35:44.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24303
- author: Dygon
changes:
- message: Storage objects can't be opened anymore while stored in a container.
@@ -3793,3 +3786,11 @@
id: 6250
time: '2024-03-29T06:30:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26290
+- author: deltanedas
+ changes:
+ - message: Multiple bombs exploding at once on a tile now combine to have a larger
+ explosion rather than stacking the same small explosion.
+ type: Tweak
+ id: 6251
+ time: '2024-03-29T23:46:06.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/25664
From 985c4b40163a71737d229aa1c4513a93da8a6d23 Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Sat, 30 Mar 2024 12:58:12 +1300
Subject: [PATCH 03/26] Fix empty atmos deserialization (#26540)
Fix atmos deserialization
---
.../Serialization/TileAtmosCollectionSerializer.cs | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/Content.Server/Atmos/Serialization/TileAtmosCollectionSerializer.cs b/Content.Server/Atmos/Serialization/TileAtmosCollectionSerializer.cs
index 71e4c2d0de..00be83e86d 100644
--- a/Content.Server/Atmos/Serialization/TileAtmosCollectionSerializer.cs
+++ b/Content.Server/Atmos/Serialization/TileAtmosCollectionSerializer.cs
@@ -26,7 +26,7 @@ public sealed partial class TileAtmosCollectionSerializer : ITypeSerializer tiles;
+ Dictionary tiles = new();
// Backwards compatability
if (version == 1)
@@ -36,8 +36,6 @@ public sealed partial class TileAtmosCollectionSerializer : ITypeSerializer?>(tile2, hookCtx, context);
var unique = serializationManager.Read?>(node["uniqueMixes"], hookCtx, context);
- tiles = new Dictionary();
-
if (unique != null && mixies != null)
{
foreach (var (indices, mix) in mixies)
@@ -58,15 +56,14 @@ public sealed partial class TileAtmosCollectionSerializer : ITypeSerializer(dataNode["chunkSize"], hookCtx, context);
- var unique = serializationManager.Read?>(dataNode["uniqueMixes"], hookCtx, context);
-
- tiles = new Dictionary();
+ dataNode.TryGetValue(new ValueDataNode("uniqueMixes"), out var mixNode);
+ var unique = mixNode == null ? null : serializationManager.Read?>(mixNode, hookCtx, context);
if (unique != null)
{
+ var tileNode = (MappingDataNode) dataNode["tiles"];
foreach (var (chunkNode, valueNode) in tileNode)
{
var chunkOrigin = serializationManager.Read(chunkNode, hookCtx, context);
From 649af483e486e99785e9a1517fa3263c0723034e Mon Sep 17 00:00:00 2001
From: Mephisto72 <66994453+Mephisto72@users.noreply.github.com>
Date: Sat, 30 Mar 2024 01:01:39 +0100
Subject: [PATCH 04/26] Increase Ion Storm Weights (#26539)
This increases the probability for the following effects caused by Ion Storms:
Chance to affect a Station Borg: 50% -> 80%
Chance to replace a Law: 10% -> 20%
Chance to remove a Law: 10% -> 20%
Chance to shuffle Laws: 10% -> 20%
---
.../Silicons/Laws/Components/IonStormTargetComponent.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Content.Shared/Silicons/Laws/Components/IonStormTargetComponent.cs b/Content.Shared/Silicons/Laws/Components/IonStormTargetComponent.cs
index 49ac611ddc..341767e9ce 100644
--- a/Content.Shared/Silicons/Laws/Components/IonStormTargetComponent.cs
+++ b/Content.Shared/Silicons/Laws/Components/IonStormTargetComponent.cs
@@ -20,7 +20,7 @@ public sealed partial class IonStormTargetComponent : Component
/// Chance for this borg to be affected at all.
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
- public float Chance = 0.5f;
+ public float Chance = 0.8f;
///
/// Chance to replace the lawset with a random one
@@ -32,19 +32,19 @@ public sealed partial class IonStormTargetComponent : Component
/// Chance to remove a random law.
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
- public float RemoveChance = 0.1f;
+ public float RemoveChance = 0.2f;
///
/// Chance to replace a random law with the new one, rather than have it be a glitched-order law.
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
- public float ReplaceChance = 0.1f;
+ public float ReplaceChance = 0.2f;
///
/// Chance to shuffle laws after everything is done.
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
- public float ShuffleChance = 0.1f;
+ public float ShuffleChance = 0.2f;
}
///
From 86a24db72a2d8208b3e1152a6e03021e3a2fde5d Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 00:02:45 +0000
Subject: [PATCH 05/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index f3495edc01..216ca87304 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Dygon
- changes:
- - message: Storage objects can't be opened anymore while stored in a container.
- type: Fix
- id: 5752
- time: '2024-01-20T02:50:14.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24253
- author: FairlySadPanda
changes:
- message: Lobby restart sound effects no longer cut-off.
@@ -3794,3 +3787,10 @@
id: 6251
time: '2024-03-29T23:46:06.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25664
+- author: Mephisto72
+ changes:
+ - message: Ion Storms are now more likely to alter a Borg's laws.
+ type: Tweak
+ id: 6252
+ time: '2024-03-30T00:01:39.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26539
From 2e9c8f691c6a1e5f8e45899866a9fe443f9f4b50 Mon Sep 17 00:00:00 2001
From: "Alice \"Arimah\" Heurlin" <30327355+arimah@users.noreply.github.com>
Date: Sat, 30 Mar 2024 02:25:42 +0100
Subject: [PATCH 06/26] Fix guardian damage transfer (#26541)
---
Content.Server/Guardian/GuardianSystem.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs
index e58f997b21..97d4eb0680 100644
--- a/Content.Server/Guardian/GuardianSystem.cs
+++ b/Content.Server/Guardian/GuardianSystem.cs
@@ -256,7 +256,7 @@ namespace Content.Server.Guardian
///
private void OnGuardianDamaged(EntityUid uid, GuardianComponent component, DamageChangedEvent args)
{
- if (args.DamageDelta == null || component.Host == null || component.DamageShare > 0)
+ if (args.DamageDelta == null || component.Host == null || component.DamageShare == 0)
return;
_damageSystem.TryChangeDamage(
From 72c6a14d593ea6eafc7477292657166968c75401 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 01:26:48 +0000
Subject: [PATCH 07/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 216ca87304..c52c19a50c 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: FairlySadPanda
- changes:
- - message: Lobby restart sound effects no longer cut-off.
- type: Fix
- id: 5753
- time: '2024-01-20T03:40:01.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24044
- author: casperr04
changes:
- message: Fixed players being able to re-anchor items after fultoning them.
@@ -3794,3 +3787,11 @@
id: 6252
time: '2024-03-30T00:01:39.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26539
+- author: arimah
+ changes:
+ - message: Holoparasites, holoclowns and other guardians correctly transfer damage
+ to their hosts again.
+ type: Fix
+ id: 6253
+ time: '2024-03-30T01:25:43.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26541
From 3b791459c74c6b56c8ae6204a936f6de06674b93 Mon Sep 17 00:00:00 2001
From: Pieter-Jan Briers
Date: Sat, 30 Mar 2024 02:40:55 +0100
Subject: [PATCH 08/26] Refactor FTL time tracking code to fix a UI bug
(#26538)
The FTL UI on the shuttle console would reset the FTL progress bar every time you open it. This is because the server only sends "time until completion", not a start/end time. The FTL code now uses a separate start/end time so the exact same progress bar can be preserved.
For convenience, I made a StartEndTime record struct that stores the actual tuple. This is now used by the code and has some helpers.
---
Content.Client/Shuttles/UI/MapScreen.xaml.cs | 27 ++------
.../Shuttles/Components/FTLComponent.cs | 7 +-
.../Shuttles/Systems/ShuttleConsoleSystem.cs | 14 ++--
.../Systems/ShuttleSystem.FasterThanLight.cs | 28 ++++----
.../Shuttles/Systems/ShuttleSystem.cs | 4 +-
.../BUIStates/ShuttleMapInterfaceState.cs | 9 +--
Content.Shared/Timing/StartEndTime.cs | 68 +++++++++++++++++++
7 files changed, 111 insertions(+), 46 deletions(-)
create mode 100644 Content.Shared/Timing/StartEndTime.cs
diff --git a/Content.Client/Shuttles/UI/MapScreen.xaml.cs b/Content.Client/Shuttles/UI/MapScreen.xaml.cs
index 8430699bae..225d1be14e 100644
--- a/Content.Client/Shuttles/UI/MapScreen.xaml.cs
+++ b/Content.Client/Shuttles/UI/MapScreen.xaml.cs
@@ -5,6 +5,7 @@ using Content.Shared.Shuttles.BUIStates;
using Content.Shared.Shuttles.Components;
using Content.Shared.Shuttles.Systems;
using Content.Shared.Shuttles.UI.MapObjects;
+using Content.Shared.Timing;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
@@ -38,16 +39,11 @@ public sealed partial class MapScreen : BoxContainer
private EntityUid? _shuttleEntity;
private FTLState _state;
- private float _ftlDuration;
+ private StartEndTime _ftlTime;
private List _beacons = new();
private List _exclusions = new();
- ///
- /// When the next FTL state change happens.
- ///
- private TimeSpan _nextFtlTime;
-
private TimeSpan _nextPing;
private TimeSpan _pingCooldown = TimeSpan.FromSeconds(3);
private TimeSpan _nextMapDequeue;
@@ -114,8 +110,7 @@ public sealed partial class MapScreen : BoxContainer
_beacons = state.Destinations;
_exclusions = state.Exclusions;
_state = state.FTLState;
- _ftlDuration = state.FTLDuration;
- _nextFtlTime = _timing.CurTime + TimeSpan.FromSeconds(_ftlDuration);
+ _ftlTime = state.FTLTime;
MapRadar.InFtl = true;
MapFTLState.Text = Loc.GetString($"shuttle-console-ftl-state-{_state.ToString()}");
@@ -511,20 +506,8 @@ public sealed partial class MapScreen : BoxContainer
MapRebuildButton.Disabled = false;
}
- var ftlDiff = (float) (_nextFtlTime - _timing.CurTime).TotalSeconds;
-
- float ftlRatio;
-
- if (_ftlDuration.Equals(0f))
- {
- ftlRatio = 1f;
- }
- else
- {
- ftlRatio = Math.Clamp(1f - (ftlDiff / _ftlDuration), 0f, 1f);
- }
-
- FTLBar.Value = ftlRatio;
+ var progress = _ftlTime.ProgressAt(curTime);
+ FTLBar.Value = float.IsFinite(progress) ? progress : 1;
}
protected override void Draw(DrawingHandleScreen handle)
diff --git a/Content.Server/Shuttles/Components/FTLComponent.cs b/Content.Server/Shuttles/Components/FTLComponent.cs
index d15f65a355..a3da4855f7 100644
--- a/Content.Server/Shuttles/Components/FTLComponent.cs
+++ b/Content.Server/Shuttles/Components/FTLComponent.cs
@@ -1,5 +1,6 @@
using Content.Shared.Shuttles.Systems;
using Content.Shared.Tag;
+using Content.Shared.Timing;
using Robust.Shared.Audio;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
@@ -16,15 +17,15 @@ public sealed partial class FTLComponent : Component
[ViewVariables]
public FTLState State = FTLState.Available;
+ [ViewVariables(VVAccess.ReadWrite)]
+ public StartEndTime StateTime;
+
[ViewVariables(VVAccess.ReadWrite)]
public float StartupTime = 0f;
[ViewVariables(VVAccess.ReadWrite)]
public float TravelTime = 0f;
- [ViewVariables(VVAccess.ReadWrite)]
- public float Accumulator = 0f;
-
///
/// Coordinates to arrive it: May be relative to another grid (for docking) or map coordinates.
///
diff --git a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
index f0368ed3a9..a4f2c7b4db 100644
--- a/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
+++ b/Content.Server/Shuttles/Systems/ShuttleConsoleSystem.cs
@@ -13,6 +13,7 @@ using Content.Shared.Shuttles.Systems;
using Content.Shared.Tag;
using Content.Shared.Movement.Systems;
using Content.Shared.Shuttles.UI.MapObjects;
+using Content.Shared.Timing;
using Robust.Server.GameObjects;
using Robust.Shared.Collections;
using Robust.Shared.GameStates;
@@ -257,7 +258,11 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
else
{
navState = new NavInterfaceState(0f, null, null, new Dictionary>());
- mapState = new ShuttleMapInterfaceState(FTLState.Invalid, 0f, new List(), new List());
+ mapState = new ShuttleMapInterfaceState(
+ FTLState.Invalid,
+ default,
+ new List(),
+ new List());
}
if (_ui.TryGetUi(consoleUid, ShuttleConsoleUiKey.Key, out var bui))
@@ -408,12 +413,12 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
public ShuttleMapInterfaceState GetMapState(Entity shuttle)
{
FTLState ftlState = FTLState.Available;
- float stateDuration = 0f;
+ StartEndTime stateDuration = default;
if (Resolve(shuttle, ref shuttle.Comp, false) && shuttle.Comp.LifeStage < ComponentLifeStage.Stopped)
{
ftlState = shuttle.Comp.State;
- stateDuration = _shuttle.GetStateDuration(shuttle.Comp);
+ stateDuration = _shuttle.GetStateTime(shuttle.Comp);
}
List? beacons = null;
@@ -422,7 +427,8 @@ public sealed partial class ShuttleConsoleSystem : SharedShuttleConsoleSystem
GetExclusions(ref exclusions);
return new ShuttleMapInterfaceState(
- ftlState, stateDuration,
+ ftlState,
+ stateDuration,
beacons ?? new List(),
exclusions ?? new List());
}
diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
index cb322ac396..5128869103 100644
--- a/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
+++ b/Content.Server/Shuttles/Systems/ShuttleSystem.FasterThanLight.cs
@@ -12,6 +12,7 @@ using Content.Shared.Parallax;
using Content.Shared.Shuttles.Components;
using Content.Shared.Shuttles.Systems;
using Content.Shared.StatusEffect;
+using Content.Shared.Timing;
using Content.Shared.Whitelist;
using JetBrains.Annotations;
using Robust.Shared.Audio;
@@ -131,7 +132,7 @@ public sealed partial class ShuttleSystem
return mapUid;
}
- public float GetStateDuration(FTLComponent component)
+ public StartEndTime GetStateTime(FTLComponent component)
{
var state = component.State;
@@ -141,9 +142,9 @@ public sealed partial class ShuttleSystem
case FTLState.Travelling:
case FTLState.Arriving:
case FTLState.Cooldown:
- return component.Accumulator;
+ return component.StateTime;
case FTLState.Available:
- return 0f;
+ return default;
default:
throw new NotImplementedException();
}
@@ -251,7 +252,9 @@ public sealed partial class ShuttleSystem
hyperspace.StartupTime = startupTime;
hyperspace.TravelTime = hyperspaceTime;
- hyperspace.Accumulator = hyperspace.StartupTime;
+ hyperspace.StateTime = StartEndTime.FromStartDuration(
+ _gameTiming.CurTime,
+ TimeSpan.FromSeconds(hyperspace.StartupTime));
hyperspace.TargetCoordinates = coordinates;
hyperspace.TargetAngle = angle;
hyperspace.PriorityTag = priorityTag;
@@ -282,7 +285,9 @@ public sealed partial class ShuttleSystem
var config = _dockSystem.GetDockingConfig(shuttleUid, target, priorityTag);
hyperspace.StartupTime = startupTime;
hyperspace.TravelTime = hyperspaceTime;
- hyperspace.Accumulator = hyperspace.StartupTime;
+ hyperspace.StateTime = StartEndTime.FromStartDuration(
+ _gameTiming.CurTime,
+ TimeSpan.FromSeconds(hyperspace.StartupTime));
hyperspace.PriorityTag = priorityTag;
_console.RefreshShuttleConsoles(shuttleUid);
@@ -366,7 +371,7 @@ public sealed partial class ShuttleSystem
// Reset rotation so they always face the same direction.
xform.LocalRotation = Angle.Zero;
_index += width + Buffer;
- comp.Accumulator += comp.TravelTime - DefaultArrivalTime;
+ comp.StateTime = StartEndTime.FromCurTime(_gameTiming, comp.TravelTime - DefaultArrivalTime);
Enable(uid, component: body);
_physics.SetLinearVelocity(uid, new Vector2(0f, 20f), body: body);
@@ -401,7 +406,7 @@ public sealed partial class ShuttleSystem
{
var shuttle = entity.Comp2;
var comp = entity.Comp1;
- comp.Accumulator += DefaultArrivalTime;
+ comp.StateTime = StartEndTime.FromCurTime(_gameTiming, DefaultArrivalTime);
comp.State = FTLState.Arriving;
// TODO: Arrival effects
// For now we'll just use the ss13 bubbles but we can do fancier.
@@ -504,7 +509,7 @@ public sealed partial class ShuttleSystem
}
comp.State = FTLState.Cooldown;
- comp.Accumulator += FTLCooldown;
+ comp.StateTime = StartEndTime.FromCurTime(_gameTiming, FTLCooldown);
_console.RefreshShuttleConsoles(uid);
_mapManager.SetMapPaused(mapId, false);
Smimsh(uid, xform: xform);
@@ -519,15 +524,14 @@ public sealed partial class ShuttleSystem
_console.RefreshShuttleConsoles(entity);
}
- private void UpdateHyperspace(float frameTime)
+ private void UpdateHyperspace()
{
+ var curTime = _gameTiming.CurTime;
var query = EntityQueryEnumerator();
while (query.MoveNext(out var uid, out var comp, out var shuttle))
{
- comp.Accumulator -= frameTime;
-
- if (comp.Accumulator > 0f)
+ if (curTime < comp.StateTime.End)
continue;
var entity = (uid, comp, shuttle);
diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs
index 7c42753a7d..6dc25e8d76 100644
--- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs
+++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs
@@ -19,6 +19,7 @@ using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;
+using Robust.Shared.Timing;
namespace Content.Server.Shuttles.Systems;
@@ -30,6 +31,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly BiomeSystem _biomes = default!;
[Dependency] private readonly BodySystem _bobby = default!;
[Dependency] private readonly DockingSystem _dockSystem = default!;
@@ -68,7 +70,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem
public override void Update(float frameTime)
{
base.Update(frameTime);
- UpdateHyperspace(frameTime);
+ UpdateHyperspace();
}
private void OnGridFixtureChange(EntityUid uid, FixturesComponent manager, GridFixtureChangeEvent args)
diff --git a/Content.Shared/Shuttles/BUIStates/ShuttleMapInterfaceState.cs b/Content.Shared/Shuttles/BUIStates/ShuttleMapInterfaceState.cs
index cee0daab4b..3cb7cb6412 100644
--- a/Content.Shared/Shuttles/BUIStates/ShuttleMapInterfaceState.cs
+++ b/Content.Shared/Shuttles/BUIStates/ShuttleMapInterfaceState.cs
@@ -1,5 +1,6 @@
using Content.Shared.Shuttles.Systems;
using Content.Shared.Shuttles.UI.MapObjects;
+using Content.Shared.Timing;
using Robust.Shared.Serialization;
namespace Content.Shared.Shuttles.BUIStates;
@@ -16,9 +17,9 @@ public sealed class ShuttleMapInterfaceState
public readonly FTLState FTLState;
///
- /// How long the FTL state takes.
+ /// When the current FTL state starts and ends.
///
- public float FTLDuration;
+ public StartEndTime FTLTime;
public List Destinations;
@@ -26,12 +27,12 @@ public sealed class ShuttleMapInterfaceState
public ShuttleMapInterfaceState(
FTLState ftlState,
- float ftlDuration,
+ StartEndTime ftlTime,
List destinations,
List exclusions)
{
FTLState = ftlState;
- FTLDuration = ftlDuration;
+ FTLTime = ftlTime;
Destinations = destinations;
Exclusions = exclusions;
}
diff --git a/Content.Shared/Timing/StartEndTime.cs b/Content.Shared/Timing/StartEndTime.cs
new file mode 100644
index 0000000000..fde9f7341c
--- /dev/null
+++ b/Content.Shared/Timing/StartEndTime.cs
@@ -0,0 +1,68 @@
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Timing;
+
+///
+/// Represents a range of an "action" in time, as start/end times.
+///
+///
+/// Positions in time are represented as s, usually from
+/// or .
+///
+/// The time the action starts.
+/// The time action ends.
+[Serializable]
+public record struct StartEndTime(TimeSpan Start, TimeSpan End)
+{
+ ///
+ /// How long the action takes.
+ ///
+ public TimeSpan Length => End - Start;
+
+ ///
+ /// Get how far the action has progressed relative to a time value.
+ ///
+ /// The time to get the current progress value for.
+ /// If true, clamp values outside the time range to 0 through 1.
+ ///
+ ///
+ /// A progress value. Zero means is at ,
+ /// one means is at .
+ ///
+ ///
+ /// This function returns if and are identical.
+ ///
+ ///
+ public float ProgressAt(TimeSpan time, bool clamp = true)
+ {
+ var length = Length;
+ if (length == default)
+ return float.NaN;
+
+ var progress = (float) ((time - Start) / length);
+ if (clamp)
+ progress = MathHelper.Clamp01(progress);
+
+ return progress;
+ }
+
+ public static StartEndTime FromStartDuration(TimeSpan start, TimeSpan duration)
+ {
+ return new StartEndTime(start, start + duration);
+ }
+
+ public static StartEndTime FromStartDuration(TimeSpan start, float durationSeconds)
+ {
+ return new StartEndTime(start, start + TimeSpan.FromSeconds(durationSeconds));
+ }
+
+ public static StartEndTime FromCurTime(IGameTiming gameTiming, TimeSpan duration)
+ {
+ return FromStartDuration(gameTiming.CurTime, duration);
+ }
+
+ public static StartEndTime FromCurTime(IGameTiming gameTiming, float durationSeconds)
+ {
+ return FromStartDuration(gameTiming.CurTime, durationSeconds);
+ }
+}
From d215419f9ac6108185b724e40185d2cf27f7a749 Mon Sep 17 00:00:00 2001
From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Date: Sat, 30 Mar 2024 13:28:42 +1100
Subject: [PATCH 09/26] Revert "Fix scram implant's teleportation out of
containers" (#25030)
* Revert "Fix scram implant's teleportation out of containers (#24827)"
This reverts commit d4434dbb5e586544a5dbd067a3fee4a6bd4e9e89.
* Remove EntityQuery pass-ins
---
Content.Server/Implants/SubdermalImplantSystem.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Content.Server/Implants/SubdermalImplantSystem.cs b/Content.Server/Implants/SubdermalImplantSystem.cs
index 6b58f6eb09..fd95720732 100644
--- a/Content.Server/Implants/SubdermalImplantSystem.cs
+++ b/Content.Server/Implants/SubdermalImplantSystem.cs
@@ -139,7 +139,6 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem
break;
}
_xform.SetWorldPosition(ent, targetCoords.Position);
- _xform.AttachToGridOrMap(ent, xform);
_audio.PlayPvs(implant.TeleportSound, ent);
args.Handled = true;
From bb5ca720fccd035e310c12b266f71081f85edf47 Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Sat, 30 Mar 2024 15:34:55 +1300
Subject: [PATCH 10/26] Split GasTileOverlaySystem update over two ticks
(#26542)
Split GasTileOverlaySystem update over ticks
---
.../EntitySystems/GasTileOverlaySystem.cs | 49 +++++++++++++------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
index 6d49feb018..003eed59e0 100644
--- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
+++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
@@ -52,6 +52,8 @@ namespace Content.Server.Atmos.EntitySystems
new DefaultObjectPool>>(
new DefaultPooledObjectPolicy>>(), 64);
+ private bool _doSessionUpdate;
+
///
/// Overlay update interval, in seconds.
///
@@ -192,7 +194,7 @@ namespace Content.Server.Atmos.EntitySystems
///
/// Updates the visuals for a tile on some grid chunk. Returns true if the visuals have changed.
///
- private bool UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index, GameTick curTick)
+ private bool UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index)
{
ref var oldData = ref chunk.TileData[chunk.GetDataIndex(index)];
if (!gridAtmosphere.Tiles.TryGetValue(index, out var tile))
@@ -200,7 +202,7 @@ namespace Content.Server.Atmos.EntitySystems
if (oldData.Equals(default))
return false;
- chunk.LastUpdate = curTick;
+ chunk.LastUpdate = _gameTiming.CurTick;
oldData = default;
return true;
}
@@ -258,11 +260,11 @@ namespace Content.Server.Atmos.EntitySystems
if (!changed)
return false;
- chunk.LastUpdate = curTick;
+ chunk.LastUpdate = _gameTiming.CurTick;
return true;
}
- private void UpdateOverlayData(GameTick curTick)
+ private void UpdateOverlayData()
{
// TODO parallelize?
var query = EntityQueryEnumerator();
@@ -276,7 +278,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!overlay.Chunks.TryGetValue(chunkIndex, out var chunk))
overlay.Chunks[chunkIndex] = chunk = new GasOverlayChunk(chunkIndex);
- changed |= UpdateChunkTile(gam, chunk, index, curTick);
+ changed |= UpdateChunkTile(gam, chunk, index);
}
if (changed)
@@ -291,13 +293,28 @@ namespace Content.Server.Atmos.EntitySystems
base.Update(frameTime);
AccumulatedFrameTime += frameTime;
- if (AccumulatedFrameTime < _updateInterval) return;
+ if (_doSessionUpdate)
+ {
+ UpdateSessions();
+ return;
+ }
+
+ if (AccumulatedFrameTime < _updateInterval)
+ return;
+
AccumulatedFrameTime -= _updateInterval;
- var curTick = _gameTiming.CurTick;
-
// First, update per-chunk visual data for any invalidated tiles.
- UpdateOverlayData(curTick);
+ UpdateOverlayData();
+
+ // Then, next tick we send the data to players.
+ // This is to avoid doing all the work in the same tick.
+ _doSessionUpdate = true;
+ }
+
+ public void UpdateSessions()
+ {
+ _doSessionUpdate = false;
if (!PvsEnabled)
return;
@@ -315,11 +332,11 @@ namespace Content.Server.Atmos.EntitySystems
_sessions.Add(player);
}
- if (_sessions.Count > 0)
- {
- _updateJob.CurrentTick = curTick;
- _parMan.ProcessNow(_updateJob, _sessions.Count);
- }
+ if (_sessions.Count == 0)
+ return;
+
+ _parMan.ProcessNow(_updateJob, _sessions.Count);
+ _updateJob.LastSessionUpdate = _gameTiming.CurTick;
}
public void Reset(RoundRestartCleanupEvent ev)
@@ -352,7 +369,7 @@ namespace Content.Server.Atmos.EntitySystems
public ObjectPool> ChunkIndexPool;
public ObjectPool>> ChunkViewerPool;
- public GameTick CurrentTick;
+ public GameTick LastSessionUpdate;
public Dictionary>> LastSentChunks;
public List Sessions;
@@ -415,7 +432,7 @@ namespace Content.Server.Atmos.EntitySystems
if (previousChunks != null &&
previousChunks.Contains(gIndex) &&
- value.LastUpdate != CurrentTick)
+ value.LastUpdate > LastSessionUpdate)
{
continue;
}
From 6ef592ddba336a41330eaf3760a600c805907e1d Mon Sep 17 00:00:00 2001
From: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Date: Sat, 30 Mar 2024 03:46:20 +0100
Subject: [PATCH 11/26] Industrial Reagent Grinder (#25020)
* all work done
* adress whitespace
* millions must factorio
* conflict fix
* i forgot
---
.../Circuitboards/Machine/production.yml | 13 ++++++
.../Entities/Structures/Machines/lathe.yml | 1 +
.../Structures/Machines/reagent_grinder.yml | 42 +++++++++++++++++++
.../Entities/Structures/Machines/recycler.yml | 2 +-
.../Prototypes/Recipes/Lathes/electronics.yml | 9 ++++
.../Prototypes/Research/civilianservices.yml | 1 +
6 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
index 093c0524b4..7a9e60ac56 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
@@ -1357,3 +1357,16 @@
materialRequirements:
Steel: 5
CableHV: 2
+
+- type: entity
+ parent: BaseMachineCircuitboard
+ id: ReagentGrinderIndustrialMachineCircuitboard
+ name: industrial reagent grinder machine board
+ components:
+ - type: MachineBoard
+ prototype: ReagentGrinderIndustrial
+ requirements:
+ MatterBin: 1
+ Manipulator: 3
+ materialRequirements:
+ Glass: 1
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index 28bc62894e..5fbe84a3fe 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -451,6 +451,7 @@
- ArtifactCrusherMachineCircuitboard
- TelecomServerCircuitboard
- MassMediaCircuitboard
+ - ReagentGrinderIndustrialMachineCircuitboard
- type: MaterialStorage
whitelist:
tags:
diff --git a/Resources/Prototypes/Entities/Structures/Machines/reagent_grinder.yml b/Resources/Prototypes/Entities/Structures/Machines/reagent_grinder.yml
index d19e237997..3bb1458b8c 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/reagent_grinder.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/reagent_grinder.yml
@@ -56,3 +56,45 @@
inputContainer: !type:Container
machine_board: !type:Container
machine_parts: !type:Container
+
+- type: entity
+ parent: Recycler #too different so different parent
+ id: ReagentGrinderIndustrial
+ name: industrial reagent grinder
+ description: An industrial reagent grinder.
+ components:
+ - type: SolutionContainerManager
+ solutions:
+ output:
+ maxVol: 400 #*slaps roof of machine* This baby can fit so much omnizine in it
+ - type: MaterialReclaimer
+ whitelist:
+ components:
+ - Extractable #same as reagent grinder
+ blacklist:
+ tags:
+ - HighRiskItem #ian meat
+ efficiency: 0.9
+ - type: Sprite
+ sprite: Structures/Machines/recycling.rsi
+ layers:
+ - state: grinder-b0
+ - type: Machine
+ board: ReagentGrinderIndustrialMachineCircuitboard
+ - type: GenericVisualizer
+ visuals:
+ enum.ConveyorVisuals.State:
+ enum.RecyclerVisualLayers.Main:
+ Forward: { state: grinder-b1 }
+ Reverse: { state: grinder-b1 }
+ Off: { state: grinder-b0 }
+ - type: ContainerContainer
+ containers:
+ machine_board: !type:Container
+ machine_parts: !type:Container
+ - type: Construction
+ graph: Machine
+ node: machine
+ containers:
+ - machine_parts
+ - machine_board
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Structures/Machines/recycler.yml b/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
index 814852125a..138795cbf1 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
@@ -116,4 +116,4 @@
interactSuccessString: petting-success-recycler
interactFailureString: petting-failure-generic
interactSuccessSound:
- path: /Audio/Items/drill_hit.ogg
+ path: /Audio/Items/drill_hit.ogg
\ No newline at end of file
diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml
index f0c59a0bdf..c4417f868b 100644
--- a/Resources/Prototypes/Recipes/Lathes/electronics.yml
+++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml
@@ -956,3 +956,12 @@
Steel: 100
Glass: 900
Gold: 100
+
+- type: latheRecipe
+ id: ReagentGrinderIndustrialMachineCircuitboard
+ result: ReagentGrinderIndustrialMachineCircuitboard
+ completetime: 5
+ materials:
+ Steel: 100
+ Glass: 900
+ Gold: 100
diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml
index 61f95894ee..79dac27510 100644
--- a/Resources/Prototypes/Research/civilianservices.yml
+++ b/Resources/Prototypes/Research/civilianservices.yml
@@ -14,6 +14,7 @@
- BorgModuleHarvesting
- SeedExtractorMachineCircuitboard
- HydroponicsTrayMachineCircuitboard
+ - ReagentGrinderIndustrialMachineCircuitboard
- type: technology
id: CritterMechs
From ac129820492ff0189dd581033848dc9aa3a15b5c Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 02:47:27 +0000
Subject: [PATCH 12/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index c52c19a50c..420db73301 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,13 +1,4 @@
Entries:
-- author: casperr04
- changes:
- - message: Fixed players being able to re-anchor items after fultoning them.
- type: Fix
- - message: Changed which objects can be fultoned.
- type: Tweak
- id: 5754
- time: '2024-01-20T04:57:05.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/20628
- author: Blackern5000
changes:
- message: Crushers can no longer be researched.
@@ -3795,3 +3786,11 @@
id: 6253
time: '2024-03-30T01:25:43.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26541
+- author: Boaz1111
+ changes:
+ - message: Added an industrial reagent grinder to the basic hydroponics research.
+ It grinds things into reagents like a recycler.
+ type: Add
+ id: 6254
+ time: '2024-03-30T02:46:20.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/25020
From 52db14a19dcafa5592be0e2d23a4a628c9ab981e Mon Sep 17 00:00:00 2001
From: SonicHDC <100022571+SonicHDC@users.noreply.github.com>
Date: Sat, 30 Mar 2024 15:31:32 +1200
Subject: [PATCH 13/26] Zippable coats (#26494)
* Update base_clothingouter.yml
* Update coats.yml
* Change Flipped to Opened
* labcoat
* coat
* Update meta.json
* Update meta.json
* Update meta.json
* Update meta.json
* Update meta.json
* Update meta.json
* Update meta.json
* cmo
* gene
* rd
* robo
* sci
* viro
* Locale zip-unzip
* Missing meta
* Fix wrong sprites
---
.../components/foldable-component.ftl | 5 +-
.../OuterClothing/base_clothingouter.yml | 42 ++++++++++++++
.../Entities/Clothing/OuterClothing/coats.yml | 54 +++++++++++++++---
.../OuterClothing/Coats/labcoat.rsi/meta.json | 8 +++
.../Coats/labcoat.rsi/open-inhand-left.png | Bin 0 -> 390 bytes
.../Coats/labcoat.rsi/open-inhand-right.png | Bin 0 -> 394 bytes
.../Coats/labcoat_chem.rsi/meta.json | 8 +++
.../labcoat_chem.rsi/open-inhand-left.png | Bin 0 -> 408 bytes
.../labcoat_chem.rsi/open-inhand-right.png | Bin 0 -> 410 bytes
.../Coats/labcoat_cmo.rsi/meta.json | 8 +++
.../labcoat_cmo.rsi/open-inhand-left.png | Bin 0 -> 382 bytes
.../labcoat_cmo.rsi/open-inhand-right.png | Bin 0 -> 383 bytes
.../Coats/labcoat_gene.rsi/meta.json | 8 +++
.../labcoat_gene.rsi/open-inhand-left.png | Bin 0 -> 408 bytes
.../labcoat_gene.rsi/open-inhand-right.png | Bin 0 -> 410 bytes
.../Coats/labcoat_rd.rsi/meta.json | 8 +++
.../Coats/labcoat_rd.rsi/open-inhand-left.png | Bin 0 -> 1352 bytes
.../labcoat_rd.rsi/open-inhand-right.png | Bin 0 -> 1349 bytes
.../Coats/labcoat_robo.rsi/meta.json | 8 +++
.../labcoat_robo.rsi/open-inhand-left.png | Bin 0 -> 395 bytes
.../labcoat_robo.rsi/open-inhand-right.png | Bin 0 -> 399 bytes
.../Coats/labcoat_sci.rsi/meta.json | 8 +++
.../labcoat_sci.rsi/open-inhand-left.png | Bin 0 -> 408 bytes
.../labcoat_sci.rsi/open-inhand-right.png | Bin 0 -> 410 bytes
.../Coats/labcoat_viro.rsi/meta.json | 8 +++
.../labcoat_viro.rsi/open-inhand-left.png | Bin 0 -> 408 bytes
.../labcoat_viro.rsi/open-inhand-right.png | Bin 0 -> 410 bytes
27 files changed, 156 insertions(+), 9 deletions(-)
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-right.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-left.png
create mode 100644 Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-right.png
diff --git a/Resources/Locale/en-US/foldable/components/foldable-component.ftl b/Resources/Locale/en-US/foldable/components/foldable-component.ftl
index 539b4fd9e7..525820920b 100644
--- a/Resources/Locale/en-US/foldable/components/foldable-component.ftl
+++ b/Resources/Locale/en-US/foldable/components/foldable-component.ftl
@@ -4,4 +4,7 @@ foldable-deploy-fail = You can't deploy the {$object} here.
fold-verb = Fold
unfold-verb = Unfold
-fold-flip-verb = Flip
\ No newline at end of file
+fold-flip-verb = Flip
+
+fold-zip-verb = Zip up
+fold-unzip-verb = Unzip
diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
index 82df2c21e8..310661f6ca 100644
--- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
+++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml
@@ -43,6 +43,48 @@
- type: StaticPrice
price: 80
+- type: entity
+ abstract: true
+ parent: [ClothingOuterStorageBase, BaseFoldable]
+ id: ClothingOuterStorageFoldableBase
+ components:
+ - type: Appearance
+ - type: Foldable
+ canFoldInsideContainer: true
+ unfoldVerbText: fold-zip-verb
+ foldVerbText: fold-unzip-verb
+ - type: FoldableClothing
+ foldedEquippedPrefix: open
+ foldedHeldPrefix: open
+ - type: Sprite
+ layers:
+ - state: icon
+ map: [ "unfoldedLayer" ]
+ - state: icon-open
+ map: ["foldedLayer"]
+ visible: false
+
+- type: entity
+ abstract: true
+ parent: ClothingOuterStorageFoldableBase
+ id: ClothingOuterStorageFoldableBaseOpened
+ suffix: opened
+ components:
+ - type: Foldable
+ folded: true
+ - type: Clothing
+ equippedPrefix: open
+ - type: Item
+ heldPrefix: open
+ - type: Sprite
+ layers:
+ - state: icon
+ map: [ "unfoldedLayer" ]
+ visible: false
+ - state: icon-open
+ map: ["foldedLayer"]
+ visible: true
+
- type: entity
abstract: true
parent: ClothingOuterStorageBase
diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml
index bb2f598cd0..ca0e2d4b4d 100644
--- a/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml
+++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/coats.yml
@@ -114,7 +114,7 @@
Quantity: 20
- type: entity
- parent: ClothingOuterStorageBase
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatLab
name: lab coat
description: A suit that protects against minor chemical spills.
@@ -129,7 +129,12 @@
Caustic: 0.75
- type: entity
- parent: ClothingOuterStorageBase
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatLab]
+ id: ClothingOuterCoatLabOpened
+ name: lab coat
+
+- type: entity
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatLabChem
name: chemist lab coat
description: A suit that protects against minor chemical spills. Has an orange stripe on the shoulder.
@@ -144,7 +149,12 @@
Caustic: 0.75
- type: entity
- parent: ClothingOuterStorageBase
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatLabChem]
+ id: ClothingOuterCoatLabChemOpened
+ name: chemist lab coat
+
+- type: entity
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatLabViro
name: virologist lab coat
description: A suit that protects against bacteria and viruses. Has an green stripe on the shoulder.
@@ -158,9 +168,13 @@
coefficients:
Caustic: 0.75
+- type: entity
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatLabViro]
+ id: ClothingOuterCoatLabViroOpened
+ name: virologist lab coat
- type: entity
- parent: ClothingOuterStorageBase
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatLabGene
name: geneticist lab coat
description: A suit that protects against minor chemical spills. Has an blue stripe on the shoulder.
@@ -174,9 +188,13 @@
coefficients:
Caustic: 0.75
+- type: entity
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatLabGene]
+ id: ClothingOuterCoatLabGeneOpened
+ name: geneticist lab coat
- type: entity
- parent: ClothingOuterStorageBase
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatLabCmo
name: chief medical officer's lab coat
description: Bluer than the standard model.
@@ -191,7 +209,12 @@
Caustic: 0.75
- type: entity
- parent: ClothingOuterStorageBase
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatLabCmo]
+ id: ClothingOuterCoatLabCmoOpened
+ name: chief medical officer's lab coat
+
+- type: entity
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatRnd
name: scientist lab coat
description: A suit that protects against minor chemical spills. Has a purple stripe on the shoulder.
@@ -206,7 +229,12 @@
Caustic: 0.75
- type: entity
- parent: ClothingOuterStorageBase
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatRnd]
+ id: ClothingOuterCoatRndOpened
+ name: scientist lab coat
+
+- type: entity
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatRobo
name: roboticist lab coat
description: More like an eccentric coat than a labcoat. Helps pass off bloodstains as part of the aesthetic. Comes with red shoulder pads.
@@ -221,7 +249,12 @@
Caustic: 0.75
- type: entity
- parent: ClothingOuterStorageBase
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatRobo]
+ id: ClothingOuterCoatRoboOpened
+ name: roboticist lab coat
+
+- type: entity
+ parent: ClothingOuterStorageFoldableBase
id: ClothingOuterCoatRD
name: research director lab coat
description: Woven with top of the line technology, this labcoat helps protect against radiation in similar way to the experimental hardsuit.
@@ -236,6 +269,11 @@
Caustic: 0.75
Radiation: 0.9
+- type: entity
+ parent: [ClothingOuterStorageFoldableBaseOpened, ClothingOuterCoatRD]
+ id: ClothingOuterCoatRDOpened
+ name: research director lab coat
+
- type: entity
parent: ClothingOuterStorageBase
id: ClothingOuterCoatPirate
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..489f958b9e9e6ae91a0428ecde2b4fc97585c26d
GIT binary patch
literal 390
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1k1^9%xPMkRL|Ns9_pFX{K@nTn3myeH+lao_+cJ`4YM}SIp%?x@4q_|3g
z{DOhXAb?@h8J+V$QO*L7$YKTtzC$3)D5~Mr02I9K>Eaj?;r@2oTdrmU9@oqKrM3UX
z<1Sx~nk;=&BALUoXVvzbnm>+vKlP4zz;ujNFQHD|BLBwo1#_phR<=7u-`>m6B2r=F
z!!}n&!EsGuPWJM9$LDEJXwY~Xa{XV=B<3ksH;Wa{@+(_lazy5+_mqfUDsxXmk3lFrI%5O6Bgvg6U4Xnq~
zc|=(acG~ppH(sUDaC1(NUf@Mn#-4T8nIdI>l_u>LJMrqmdgE)_DItM7X4LlI=Ju*&
Zy2#R{xb*nZhd^&Kc)I$ztaD0e0stYfo5}zH
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..54bd14c8aac98862f49d070485b2adb226a9a434
GIT binary patch
literal 394
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1k1^9%xPMkRL|Ns9_pFX{K@nTn3myeH+lao_+cJ`4YM}SIp%?x@4q_|3g
z{DOhXAb?@h8J+V$QO*L7$YKTtzC$3)D5~Mr02I9M>Eaj?;r@2oO}=IW9+tT+i~s!R
zH#cLuCS!T!+rmli9T6w1CRB80{uB`3(NNgPJtLpX%T|pMFtR`{Kn%2t1eP~LtWHU^>RSU*L)2K
zR(d^1))kz*&WH1h)K(^g{C9t~MJ_K;EfAWrtVL(W78bvzOH(GWZl2cA8NRIL_GYJj
fz5B&=PD?M}(WQ7~>H2>_uQGVL`njxgN@xNA7*wRN
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_chem.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..57d36185047e17e51ac20411891363e034207aa1
GIT binary patch
literal 408
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkRLOd8*RAebQe^y$-!7cX{ob@}-CI5|0GXJ@bQVLNi<2uN)V
zmkyBPEeY}q1}TOC2HO`(Z9oam0*}aI1_r)EAj~ML;ne^XeCX-o7!u+BcG_FMLkc{u
zjR)k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkRLOd8*RAebQe^y$-!7cX{ob@}-CI5|0GXJ@bQVLNi<2uN)V
zmkyBPEeY}q1}TOC2HO`(Z9oam0*}aI1_r)EAj~ML;ne^XeC+As7!u+BcA6(&vjLB*
zFWa)B|DVmw*mBxIXb@5-KQZjtlJJ*#R$O4a_+E
zzUa-E#o}Hyn_+%b%C3J`nAHpzlbD1R)PA%sxT^8_)xG^jpVtU7eXy`Az1cWLJyIj2$8?
oDi(V0xO@7^>mStzH|=43vvS9*=ieN!1HH@O>FVdQ&MBb@0AV+%Pyhe`
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..31025b7ddad3b10f1804e7ded6722bacd63ff539
GIT binary patch
literal 382
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`031o(uwsw7nv?6@4V`m|xo0!fz;F>6nUg-3ysZ(hlN0a6?#L4LviA%Njt
z^WI3H7-xY;WHAE+-$4*&+%YlxEl}{br;B4qg!|iR7x|hMcwD&`{rNAyUUfxmwf8oi
z)0>vKD?bb3Zxi?W>l`$JNs(1kV4r%$ypHRR#>(1NZKo>w%9%MZ29Qw^Hdf*=w({5
zRQVRuyw7V7%ZUDtN{DW^)Vc+xvKHxz#4O&hqPBOx_?LeS?DMmmyJ}t(0KLiJ>FVdQ
I&MBb@09{g&H~;_u
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_cmo.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..01e8e0fbc1123246578f528efe824e1890af8bff
GIT binary patch
literal 383
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`031o(uwsw7nv?6@4V`m|xo0!fz;F>6nUg-3ysZ(hlN0a6?#L4LviA%Njt
z^WI3H7-xY;WHAE+-$4*&+%YlxEl}`|r;B4qg!|iRH-(xNcwF^&eE46VBjnJmbb3qe
z3!gr}&H~GAwTc|_Nld~9Y6gs-br0@Qf8U{eC-nQoIo_F)4bir2RL$f75`@}d$aONhU0GU1+9Gza<^ic
zrkRFv&DB5mSN%hE>RYvpQcjf{K`VD~M#VC5TG=nO_^ustUFxUdzc_(IjL)>Pn_2!b
Ry8->l;OXk;vd$@?2>_OdlcxXx
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..d95cfab8a7f44f1632971643716f6ae8f98143a0
GIT binary patch
literal 408
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkPVcgCLo|NkrRdi(V0(~B1`c6D|6`1m+EIb~;Ot7kVIIdTN3
zwyTu63`p^o1o;I66~h68?F*$gpaf@uM`SSr1K&XqX529``z=uLp{I*uNQC>_X>a)s
zDe$;99<-bCy*^H}jOXRsMUg#*FFPA6U-EU<@6n4t!lI_&lfd+-y6HOeU%8S;nVhAm
zH7l}fyQ)1$t*!uK6RY%C4bZu6sDw=w{<3f#(vx
zglC$F9MocQz7)VRTY$%txxLTM*68NJm+UhRu(WXcILvs!&SconYJQJ(lSV>gIM4Y-
z6MiphU^%J!#?_UPd&+*p5Rn5=?47YFTfaTH@U*fo#)*sBB8$IJ92Rx`i1
nz2)!Gv8cf4w_LsciJy#0u{&l}`;`;`JgTe~DWM4fx-*~S
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fbbaa54df7255e742a138c820a5e7957ddcd584
GIT binary patch
literal 410
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkPVcgCLo|NkrRdi(V0(~B1`c6D|6`1m+EIb~;Ot7kVIIdTN3
zwyTu63`p^o1o;I66~h68?F*$gpaf@uM`SSr1K&XqX529``z=uLv8Rh;NQC>_X`Xz|
z20X65Y|D!Ne>O8?%W31u+P&h5`ji<@o*&d}d+O|yz;uK~&0(Kv#`hfcYdecgf@0f>
z`Yx+5^yklA|C@hq94jMJ@0O6JqL(cq3`gviO`PWS!eoAbJ6_x2loUL(l#!NRVL^Yh+F
zt}A=%8I@f0RD&kG7b=+T-RUL1i=~1$hBGDZ?(cAgBlEludQNyPG%4XpP=U~sT`ejz
rc8IK~Sm?du?&&A5e^ejbw1@G{${n+we{;MJ^e%&^tDnm{r-UW|atNy=
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/meta.json
index f10d1d8014..5a13fa99f3 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a3f3f85b0d6115bb8e3125ef30ff36c984f41b2
GIT binary patch
literal 1352
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkO~f+6Go|Nk=?W)?EEJbn7~;>C+yU0pstK2AtCq9nrC$0|8L
zS1&OoKPgqOBDVmjnt{Q_zM>#8IXksPAt^OIGtXA({qFrr3YjUkO5vuy2EGN(sTr9b
zRYj@6RemAKRoTgwDN6Qsyj(UFRzMSSQ%e#RDspr3imfVamB0pD0ofp7eI*63l9Fs&
zr3l{u1?T*tR0T6V13d#JpmqfXo1&C7s~{IQsCFRFRw<*Tq`*pFzr4I$uiRKKzbIYb
z(9+UU-@r)U$VeBcLbtdwuOzWTH?LS3VhGe2m(=3qqRfJl%=|nBkgZI5j|wgoG(l0)!-PaNq+|H;`we56>zf9z46H<^l6q5im1FHN8j&
zX2iFiE{-7)?r*2P=4)2qaa$R)r{{b9y{$Q1)A)rq>ztl6Phye$*9CtT>eY8}`Y6me
zz;ft2%k$2URvB$6Gfw?zTV^z^npI!|zYSab>)%V5SoDe(E{|Al@o`P&BrYKfuVSU^
z9J`h@8O3E!T%Yk`vaE`N{PT)m5A7@^IIj6EnAF^u@R~)-@<6pi(bg{~`9$sA5$;_&p7L|)^X
zbyBPfGlF;AaJj3&aIi`@pqEJ?=Q`6>4F<=u!{2W%kY-icar8cSQ5_TWpPlk{ug)z5
O6+xb^elF{r5}E+CH_lD~
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_rd.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..7be0d597256ad965a8844c4be42e510b94b1c30a
GIT binary patch
literal 1349
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkO~f+6Go|Nk=?W)?EEJbn7~;>C+yU0pstK2AtCq9nrC$0|8L
zS1&OoKPgqOBDVmjnt{Q_zM>#8IXksPAt^OIGtXA({qFrr3YjUkO5vuy2EGN(sTr9b
zRYj@6RemAKRoTgwDN6Qsyj(UFRzMSSQ%e#RDspr3imfVamB0pD0ofp7eI*63l9Fs&
zr3l{u1?T*tR0T6V13d#JpmqfXo1&C7s~{IQsCFRFRw<*Tq`*pFzr4I$uiRKKzbIYb
z(9+UU-@r)U$VeBcLbtdwuOzWTH?LS3VhGe2m(=3qqRfJl%=|nBkgZI5j|wgoG(l0)!-PaNq+|H;`we56>zf9z46H<^l6q5im1FHN8j&
zX2e&XE{-7)?r*2vER)}TjsoGYdW>?y;Y^wu@BSJ;ICNs^
z1BDf(oEkHBipa2R)njDkp5F9{2dGvg@!6|r@p}D^kDOOrcgoLf&({K#Kc23BF6*2U
FngG4m&Uyd<
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..83d3f527c8c2448a3946b945f51d52cec933bb21
GIT binary patch
literal 395
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E1o(uwS}-sdvoKAZIPw4g|4*MjO=e*5WMJPO7pE$%Fw4>L;>C+Vg)1XX
z6Mz&?NswPKP#Fv`2;Dz-4k*r9;1OBOz`%D9gc)~C%zg_Lyy5BM7!u+BcG_FMW(6MC
zrG6Jb{(HY$Y=6T&Jwt9o@2aGZY0o(RJmh=n9`k_dAgi9hFV0t-zwI;Bt~*&8x7a-U
z&K9sF@YZ3E+vcsmC&_
zd0(IERE(IiVC9^WNXMw~O0SZq3|#LXFo|>M6*N9*VrN+;&+W68k86i$+>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E1o(uwS}-sdvoKAZIPw4g|4*MjO=e*5WMJPO7pE$%Fw4>L;>C+Vg)1XX
z6Mz&?NswPKP#Fv`2;Dz-4k*r9;1OBOz`%C^gc-B0b#ej)?|8a6hD5l(opzD0S%JrO
z>53OW{{NR1UnN$$+Nw6WPz;k3rEElijwVmEH^+ELX2`v8m8?ULpc^BHG
e{b#SjG4rgVRV_tr87qPQWbkzLb6Mw<&;$TYIii~Y
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..5dc3a92fdcdbb9441a1813f956b59cb2ef668d2a
GIT binary patch
literal 408
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkQgkfG)O|Nk=?WPNgLYHC*T-p=@w|MyD6+@!WoKjMOTNzfJ$ms+Skx4J5||!UH(h7`D_8O;le09n
zW<_?b90Qa2#U=CmlxNB)IO-&>(GH%c{G3UpK=16zHGgDP*)_Dwbr0tn-E6!h@Lb}T
z@JthtgIX-kmjYO33-EX{xA)oE8r?kjl6}SjmKIJQhZzspnGE|`&F`^p(nx3w=Q+P<
z!tX^5EGJdpxVkcOPuXu6B68qKQFxrXOCZDM;-FnFj$*6^yXJ8pdv&1tc$uEWYUcO0
nxBNXi78Mx%maEr4@sm+0cE_x0zmfu=XBj+Q{an^LB{Ts5GV`69
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_sci.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..c28ef522612bf5ae467a6afd3f5f32f1fc41a27f
GIT binary patch
literal 410
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkQgkfG)O|Nk=?WyyH`9>pEBdg^MiVAPn~@dn2xZhIqXx-_@1MFZD+AbP;6UK
z-(?ks{`|S?fAi0cV`XIO-4fDN^s+^S;fUR`iPOAZn9Of92&t2wn0al-1@`dlfS0ib
zW}JOr^k&Rraj%-qFh43~*S{;wY6gr+Ou`CkKUx=D)%g7C-hQLcYXq4-SlE?ue%>3&
zb!BfoqmqlBYS4uDLItzEJH5nru~hKJaHhoF{T;4wWS;jy&k3)ECM7%xDiC_It3_qT
r4v`fV3%z&TJ^keMkLrV)_AtI#xntJzZ;sc2-evG~^>bP0l+XkK<|nAz
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/meta.json b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/meta.json
index 775a3c2151..02abb07806 100644
--- a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/meta.json
+++ b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/meta.json
@@ -28,6 +28,14 @@
{
"name": "inhand-right",
"directions": 4
+ },
+ {
+ "name": "open-inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "open-inhand-right",
+ "directions": 4
}
]
}
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-left.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..2dde993a3df6075fcb5df9e01f536fbe0336ddc8
GIT binary patch
literal 408
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkPVyq)j=|Nn|Bq@F%~dhz1LuC6X0A0Hc0P<4y1TXg8YJkis694_JvX#P=d3-BeIx*f$ty)Gwzs}{T3+r(9^{+B*Ojew6}bR
z6nI=4586%nULU7f#`E&+qR1Y@mz|B3FZnv__vpnRVNp}?NnmwrYjpGAOZFKDSXwxJ9A-RVXEN+(HNVHYNh6^#oag+a
z3BMOLu$)wV1
n-tzb8SX5y2TdrRJ#7{=0*d4Q~{Ynaeo@MZK^>bP0l+XkK`uU!i
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-right.png b/Resources/Textures/Clothing/OuterClothing/Coats/labcoat_viro.rsi/open-inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..285c57c33f339c5e14303a550e55cf94a630c244
GIT binary patch
literal 410
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9
z?C1WI$O`1E2l#}zPMkPVyq)j=|Nn|Bq@F%~dhz1LuC6X0A0Hc0P<4y1TXg8YJkis694_JvX#P=d3-BeIx*f$ty)Gwzs}{T3+r*we)^B*OjeG*7-}
z10Gjjwq-^CKbx7c<+Sl+?OyRjeaeg{&kyRgJ$3d;U^>F0=CDsS<9m+!wVlN#L9uN`
zeV0`j`t#?m|II%)j+K$AcS}f9(aRPQh9h>%CQkEuVKTqbAf!%yV&=6S7udtI175}&
zm~r-f(VH=g#l31a!~Cd}UH`5ys~IpRF$pWE{b*fqRpaxkd;5((uMuSWU}0Cr`FU?7
z*Ok5Xj7lzgszDRp3l+@v?(`Dh#Zti=!tnw0P)s6gn+t`?OU
rJ49AgEcD)S_w
Date: Sat, 30 Mar 2024 14:31:47 +1100
Subject: [PATCH 14/26] Fix itemslots swapping (#25634)
Fix itemslots prediction
---
Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
index 3463be2e71..83e09b1a6d 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
@@ -279,7 +279,7 @@ namespace Content.Shared.Containers.ItemSlots
if (ev.Cancelled)
return false;
- return _containers.CanInsert(usedUid, slot.ContainerSlot, assumeEmpty: true);
+ return _containers.CanInsert(usedUid, slot.ContainerSlot, assumeEmpty: swap);
}
///
From 3af54a286ee3630a00502db20a65f958863e3321 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 03:32:37 +0000
Subject: [PATCH 15/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 420db73301..2a3ec713b3 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Blackern5000
- changes:
- - message: Crushers can no longer be researched.
- type: Remove
- id: 5755
- time: '2024-01-20T05:11:02.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24319
- author: metalgearsloth
changes:
- message: Fix buckle sound playing twice in some instances.
@@ -3794,3 +3787,10 @@
id: 6254
time: '2024-03-30T02:46:20.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25020
+- author: SonicHDC
+ changes:
+ - message: Added unzipping for lab coats!
+ type: Add
+ id: 6255
+ time: '2024-03-30T03:31:32.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26494
From 39753892c2b7a86fb7a10480a32a9dd8252ce80f Mon Sep 17 00:00:00 2001
From: Zealith-Gamer <61980908+Zealith-Gamer@users.noreply.github.com>
Date: Fri, 29 Mar 2024 20:35:42 -0700
Subject: [PATCH 16/26] Stop items that are being pulled from spinning (#26504)
* Fixed pulled items spinning when moved
* edited out others issues
* more reverts
* requested fix
* Removed "Optional:"
---
.../Movement/Pulling/Systems/PullingSystem.cs | 2 +-
Content.Shared/Throwing/ThrowingSystem.cs | 38 +++++++++++--------
2 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
index b347c6da16..acca7aafd0 100644
--- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
+++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs
@@ -269,7 +269,7 @@ public sealed class PullingSystem : EntitySystem
}
Dirty(player, pullerComp);
- _throwing.TryThrow(pulled.Value, fromUserCoords, user: player, strength: 4f, animated: false, recoil: false, playSound: false);
+ _throwing.TryThrow(pulled.Value, fromUserCoords, user: player, strength: 4f, animated: false, recoil: false, playSound: false, doSpin: false);
return false;
}
diff --git a/Content.Shared/Throwing/ThrowingSystem.cs b/Content.Shared/Throwing/ThrowingSystem.cs
index 38772eaf34..7d94ada924 100644
--- a/Content.Shared/Throwing/ThrowingSystem.cs
+++ b/Content.Shared/Throwing/ThrowingSystem.cs
@@ -49,7 +49,8 @@ public sealed class ThrowingSystem : EntitySystem
float pushbackRatio = PushbackDefault,
bool recoil = true,
bool animated = true,
- bool playSound = true)
+ bool playSound = true,
+ bool doSpin = true)
{
var thrownPos = _transform.GetMapCoordinates(uid);
var mapPos = _transform.ToMapCoordinates(coordinates);
@@ -57,7 +58,7 @@ public sealed class ThrowingSystem : EntitySystem
if (mapPos.MapId != thrownPos.MapId)
return;
- TryThrow(uid, mapPos.Position - thrownPos.Position, strength, user, pushbackRatio, recoil: recoil, animated: animated, playSound: playSound);
+ TryThrow(uid, mapPos.Position - thrownPos.Position, strength, user, pushbackRatio, recoil: recoil, animated: animated, playSound: playSound, doSpin: doSpin);
}
///
@@ -67,6 +68,7 @@ public sealed class ThrowingSystem : EntitySystem
/// A vector pointing from the entity to its destination.
/// How much the direction vector should be multiplied for velocity.
/// The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced
+ /// Whether spin will be applied to the thrown entity.
public void TryThrow(EntityUid uid,
Vector2 direction,
float strength = 1.0f,
@@ -74,7 +76,8 @@ public sealed class ThrowingSystem : EntitySystem
float pushbackRatio = PushbackDefault,
bool recoil = true,
bool animated = true,
- bool playSound = true)
+ bool playSound = true,
+ bool doSpin = true)
{
var physicsQuery = GetEntityQuery();
if (!physicsQuery.TryGetComponent(uid, out var physics))
@@ -90,7 +93,7 @@ public sealed class ThrowingSystem : EntitySystem
projectileQuery,
strength,
user,
- pushbackRatio, recoil: recoil, animated: animated, playSound: playSound);
+ pushbackRatio, recoil: recoil, animated: animated, playSound: playSound, doSpin: doSpin);
}
///
@@ -100,6 +103,7 @@ public sealed class ThrowingSystem : EntitySystem
/// A vector pointing from the entity to its destination.
/// How much the direction vector should be multiplied for velocity.
/// The ratio of impulse applied to the thrower - defaults to 10 because otherwise it's not enough to properly recover from getting spaced
+ /// Whether spin will be applied to the thrown entity.
public void TryThrow(EntityUid uid,
Vector2 direction,
PhysicsComponent physics,
@@ -110,7 +114,8 @@ public sealed class ThrowingSystem : EntitySystem
float pushbackRatio = PushbackDefault,
bool recoil = true,
bool animated = true,
- bool playSound = true)
+ bool playSound = true,
+ bool doSpin = true)
{
if (strength <= 0 || direction == Vector2Helpers.Infinity || direction == Vector2Helpers.NaN || direction == Vector2.Zero)
return;
@@ -147,17 +152,20 @@ public sealed class ThrowingSystem : EntitySystem
ThrowingAngleComponent? throwingAngle = null;
// Give it a l'il spin.
- if (physics.InvI > 0f && (!TryComp(uid, out throwingAngle) || throwingAngle.AngularVelocity))
+ if (doSpin)
{
- _physics.ApplyAngularImpulse(uid, ThrowAngularImpulse / physics.InvI, body: physics);
- }
- else
- {
- Resolve(uid, ref throwingAngle, false);
- var gridRot = _transform.GetWorldRotation(transform.ParentUid);
- var angle = direction.ToWorldAngle() - gridRot;
- var offset = throwingAngle?.Angle ?? Angle.Zero;
- _transform.SetLocalRotation(uid, angle + offset);
+ if (physics.InvI > 0f && (!TryComp(uid, out throwingAngle) || throwingAngle.AngularVelocity))
+ {
+ _physics.ApplyAngularImpulse(uid, ThrowAngularImpulse / physics.InvI, body: physics);
+ }
+ else
+ {
+ Resolve(uid, ref throwingAngle, false);
+ var gridRot = _transform.GetWorldRotation(transform.ParentUid);
+ var angle = direction.ToWorldAngle() - gridRot;
+ var offset = throwingAngle?.Angle ?? Angle.Zero;
+ _transform.SetLocalRotation(uid, angle + offset);
+ }
}
var throwEvent = new ThrownEvent(user, uid);
From 3fc02edd4ea10d914f280e367c49238ec6126f02 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 03:36:48 +0000
Subject: [PATCH 17/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 2a3ec713b3..b4ec1e0b33 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: metalgearsloth
- changes:
- - message: Fix buckle sound playing twice in some instances.
- type: Fix
- id: 5756
- time: '2024-01-20T06:22:19.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24321
- author: tday
changes:
- message: Added admin log messages for adding and ending game rules, and for the
@@ -3794,3 +3787,10 @@
id: 6255
time: '2024-03-30T03:31:32.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26494
+- author: Zealith-Gamer
+ changes:
+ - message: Items being pulled no longer spin when being thrown.
+ type: Fix
+ id: 6256
+ time: '2024-03-30T03:35:43.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26504
From f192d7901fedd134c38a6cab38731f8e93994492 Mon Sep 17 00:00:00 2001
From: Plykiya <58439124+Plykiya@users.noreply.github.com>
Date: Fri, 29 Mar 2024 20:59:16 -0700
Subject: [PATCH 18/26] Hyposprays Draw from Jugs (#25544)
* Hyposprays Draw from Jugs
* Fix last onlyMobs usage in yml
* Some Suggested Changes
* Remove unnecessary datafield name declarations
* Remove unnecessary dirtying of component
* Same line parentheses
* Added client-side HypospraySystem
* Cache UI values and only updates if values change
* empty line
* Update label
* Label change
* Reimplement ReactionMixerSystem
* Remove DataField from Hypospray Toggle Mode
* Change ToggleMode from enum to Bool OnlyAffectsMobs
* Add DataField required back since it's required for replays...?
* update EligibleEntity and uses of it
* Add user argument back
* Adds newline
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
* Guard for dirty entity
* Adds summary tag
---------
Co-authored-by: Plykiya
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
---
.../Components/HyposprayComponent.cs | 16 --
.../EntitySystems/HypospraySystem.cs | 15 ++
.../Chemistry/EntitySystems/InjectorSystem.cs | 13 --
.../Chemistry/UI/HyposprayStatusControl.cs | 48 +++--
.../Body/Components/BloodstreamComponent.cs | 2 +-
.../Components/HyposprayComponent.cs | 28 ---
.../EntitySystems/ChemistrySystem.cs | 26 ---
.../EntitySystems/ChemistrySystemHypospray.cs | 164 ---------------
.../EntitySystems/HypospraySystem.cs | 197 ++++++++++++++++++
...ySystemMixer.cs => ReactionMixerSystem.cs} | 11 +-
.../Components/HyposprayComponent.cs | 33 +++
.../Components/SharedHyposprayComponent.cs | 25 ---
.../EntitySystems/SharedHypospraySystem.cs | 61 ++++++
.../EntitySystems/SharedInjectorSystem.cs | 3 -
.../components/hypospray-component.ftl | 12 +-
.../Objects/Specific/Medical/hypospray.yml | 14 +-
16 files changed, 369 insertions(+), 299 deletions(-)
delete mode 100644 Content.Client/Chemistry/Components/HyposprayComponent.cs
create mode 100644 Content.Client/Chemistry/EntitySystems/HypospraySystem.cs
delete mode 100644 Content.Server/Chemistry/Components/HyposprayComponent.cs
delete mode 100644 Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
delete mode 100644 Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
create mode 100644 Content.Server/Chemistry/EntitySystems/HypospraySystem.cs
rename Content.Server/Chemistry/EntitySystems/{ChemistrySystemMixer.cs => ReactionMixerSystem.cs} (76%)
create mode 100644 Content.Shared/Chemistry/Components/HyposprayComponent.cs
delete mode 100644 Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
create mode 100644 Content.Shared/Chemistry/EntitySystems/SharedHypospraySystem.cs
diff --git a/Content.Client/Chemistry/Components/HyposprayComponent.cs b/Content.Client/Chemistry/Components/HyposprayComponent.cs
deleted file mode 100644
index 705b79ad84..0000000000
--- a/Content.Client/Chemistry/Components/HyposprayComponent.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Content.Shared.Chemistry.Components;
-using Content.Shared.FixedPoint;
-
-namespace Content.Client.Chemistry.Components
-{
- [RegisterComponent]
- public sealed partial class HyposprayComponent : SharedHyposprayComponent
- {
- [ViewVariables]
- public FixedPoint2 CurrentVolume;
- [ViewVariables]
- public FixedPoint2 TotalVolume;
- [ViewVariables(VVAccess.ReadWrite)]
- public bool UiUpdateNeeded;
- }
-}
diff --git a/Content.Client/Chemistry/EntitySystems/HypospraySystem.cs b/Content.Client/Chemistry/EntitySystems/HypospraySystem.cs
new file mode 100644
index 0000000000..ee7aa3aafe
--- /dev/null
+++ b/Content.Client/Chemistry/EntitySystems/HypospraySystem.cs
@@ -0,0 +1,15 @@
+using Content.Client.Chemistry.UI;
+using Content.Client.Items;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.EntitySystems;
+
+namespace Content.Client.Chemistry.EntitySystems;
+
+public sealed class HypospraySystem : SharedHypospraySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+ Subs.ItemStatus(ent => new HyposprayStatusControl(ent, _solutionContainers));
+ }
+}
diff --git a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs b/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs
index 12eb7f3d14..0131a283c8 100644
--- a/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs
+++ b/Content.Client/Chemistry/EntitySystems/InjectorSystem.cs
@@ -1,4 +1,3 @@
-using Content.Client.Chemistry.Components;
using Content.Client.Chemistry.UI;
using Content.Client.Items;
using Content.Shared.Chemistry.Components;
@@ -13,17 +12,5 @@ public sealed class InjectorSystem : SharedInjectorSystem
{
base.Initialize();
Subs.ItemStatus(ent => new InjectorStatusControl(ent, SolutionContainers));
- SubscribeLocalEvent(OnHandleHyposprayState);
- Subs.ItemStatus(ent => new HyposprayStatusControl(ent));
- }
-
- private void OnHandleHyposprayState(EntityUid uid, HyposprayComponent component, ref ComponentHandleState args)
- {
- if (args.Current is not HyposprayComponentState cState)
- return;
-
- component.CurrentVolume = cState.CurVolume;
- component.TotalVolume = cState.MaxVolume;
- component.UiUpdateNeeded = true;
}
}
diff --git a/Content.Client/Chemistry/UI/HyposprayStatusControl.cs b/Content.Client/Chemistry/UI/HyposprayStatusControl.cs
index bd85cd546c..4a4d90dc4d 100644
--- a/Content.Client/Chemistry/UI/HyposprayStatusControl.cs
+++ b/Content.Client/Chemistry/UI/HyposprayStatusControl.cs
@@ -1,6 +1,8 @@
-using Content.Client.Chemistry.Components;
using Content.Client.Message;
using Content.Client.Stylesheets;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.FixedPoint;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Timing;
@@ -9,34 +11,48 @@ namespace Content.Client.Chemistry.UI;
public sealed class HyposprayStatusControl : Control
{
- private readonly HyposprayComponent _parent;
+ private readonly Entity _parent;
private readonly RichTextLabel _label;
+ private readonly SharedSolutionContainerSystem _solutionContainers;
- public HyposprayStatusControl(HyposprayComponent parent)
+ private FixedPoint2 PrevVolume;
+ private FixedPoint2 PrevMaxVolume;
+ private bool PrevOnlyAffectsMobs;
+
+ public HyposprayStatusControl(Entity parent, SharedSolutionContainerSystem solutionContainers)
{
_parent = parent;
- _label = new RichTextLabel {StyleClasses = {StyleNano.StyleClassItemStatus}};
+ _solutionContainers = solutionContainers;
+ _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
AddChild(_label);
-
- Update();
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
- if (!_parent.UiUpdateNeeded)
+
+ if (!_solutionContainers.TryGetSolution(_parent.Owner, _parent.Comp.SolutionName, out _, out var solution))
return;
- Update();
- }
- public void Update()
- {
+ // only updates the UI if any of the details are different than they previously were
+ if (PrevVolume == solution.Volume
+ && PrevMaxVolume == solution.MaxVolume
+ && PrevOnlyAffectsMobs == _parent.Comp.OnlyAffectsMobs)
+ return;
- _parent.UiUpdateNeeded = false;
+ PrevVolume = solution.Volume;
+ PrevMaxVolume = solution.MaxVolume;
+ PrevOnlyAffectsMobs = _parent.Comp.OnlyAffectsMobs;
- _label.SetMarkup(Loc.GetString(
- "hypospray-volume-text",
- ("currentVolume", _parent.CurrentVolume),
- ("totalVolume", _parent.TotalVolume)));
+ var modeStringLocalized = Loc.GetString(_parent.Comp.OnlyAffectsMobs switch
+ {
+ false => "hypospray-all-mode-text",
+ true => "hypospray-mobs-only-mode-text",
+ });
+
+ _label.SetMarkup(Loc.GetString("hypospray-volume-label",
+ ("currentVolume", solution.Volume),
+ ("totalVolume", solution.MaxVolume),
+ ("modeString", modeStringLocalized)));
}
}
diff --git a/Content.Server/Body/Components/BloodstreamComponent.cs b/Content.Server/Body/Components/BloodstreamComponent.cs
index d448c4aab2..1d8aa9ffd3 100644
--- a/Content.Server/Body/Components/BloodstreamComponent.cs
+++ b/Content.Server/Body/Components/BloodstreamComponent.cs
@@ -11,7 +11,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.Body.Components
{
- [RegisterComponent, Access(typeof(BloodstreamSystem), (typeof(ChemistrySystem)))]
+ [RegisterComponent, Access(typeof(BloodstreamSystem), typeof(ReactionMixerSystem))]
public sealed partial class BloodstreamComponent : Component
{
public static string DefaultChemicalsSolutionName = "chemicals";
diff --git a/Content.Server/Chemistry/Components/HyposprayComponent.cs b/Content.Server/Chemistry/Components/HyposprayComponent.cs
deleted file mode 100644
index 2a80cec801..0000000000
--- a/Content.Server/Chemistry/Components/HyposprayComponent.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Content.Shared.Chemistry.Components;
-using Content.Shared.FixedPoint;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Chemistry.Components
-{
- [RegisterComponent]
- public sealed partial class HyposprayComponent : SharedHyposprayComponent
- {
- // TODO: This should be on clumsycomponent.
- [DataField("clumsyFailChance")]
- [ViewVariables(VVAccess.ReadWrite)]
- public float ClumsyFailChance = 0.5f;
-
- [DataField("transferAmount")]
- [ViewVariables(VVAccess.ReadWrite)]
- public FixedPoint2 TransferAmount = FixedPoint2.New(5);
-
- [DataField("injectSound")]
- public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg");
-
- ///
- /// Whether or not the hypo is able to inject only into mobs. On false you can inject into beakers/jugs
- ///
- [DataField("onlyMobs")]
- public bool OnlyMobs = true;
- }
-}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
deleted file mode 100644
index c4f22dc63a..0000000000
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Content.Server.Administration.Logs;
-using Content.Server.Chemistry.Containers.EntitySystems;
-using Content.Server.Interaction;
-using Content.Server.Popups;
-using Content.Shared.Chemistry;
-using Robust.Shared.Audio.Systems;
-
-namespace Content.Server.Chemistry.EntitySystems;
-
-public sealed partial class ChemistrySystem : EntitySystem
-{
- [Dependency] private readonly IAdminLogManager _adminLogger = default!;
- [Dependency] private readonly IEntityManager _entMan = default!;
- [Dependency] private readonly InteractionSystem _interaction = default!;
- [Dependency] private readonly PopupSystem _popup = default!;
- [Dependency] private readonly ReactiveSystem _reactiveSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audio = default!;
- [Dependency] private readonly SolutionContainerSystem _solutionContainers = default!;
-
- public override void Initialize()
- {
- // Why ChemMaster duplicates reagentdispenser nobody knows.
- InitializeHypospray();
- InitializeMixing();
- }
-}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
deleted file mode 100644
index be8faec984..0000000000
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using Content.Server.Chemistry.Components;
-using Content.Server.Chemistry.Containers.EntitySystems;
-using Content.Shared.Chemistry.Components;
-using Content.Shared.Chemistry.Components.SolutionManager;
-using Content.Shared.Chemistry.EntitySystems;
-using Content.Shared.Chemistry.Reagent;
-using Content.Shared.Database;
-using Content.Shared.FixedPoint;
-using Content.Shared.Forensics;
-using Content.Shared.IdentityManagement;
-using Content.Shared.Interaction;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Mobs.Components;
-using Content.Shared.Timing;
-using Content.Shared.Weapons.Melee.Events;
-using Robust.Shared.GameStates;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-
-namespace Content.Server.Chemistry.EntitySystems
-{
- public sealed partial class ChemistrySystem
- {
- [Dependency] private readonly UseDelaySystem _useDelay = default!;
-
- private void InitializeHypospray()
- {
- SubscribeLocalEvent(OnAfterInteract);
- SubscribeLocalEvent(OnAttack);
- SubscribeLocalEvent(OnSolutionChange);
- SubscribeLocalEvent(OnUseInHand);
- SubscribeLocalEvent(OnHypoGetState);
- }
-
- private void OnHypoGetState(Entity entity, ref ComponentGetState args)
- {
- args.State = _solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out _, out var solution)
- ? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
- : new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
- }
-
- private void OnUseInHand(Entity entity, ref UseInHandEvent args)
- {
- if (args.Handled)
- return;
-
- TryDoInject(entity, args.User, args.User);
- args.Handled = true;
- }
-
- private void OnSolutionChange(Entity entity, ref SolutionContainerChangedEvent args)
- {
- Dirty(entity);
- }
-
- public void OnAfterInteract(Entity entity, ref AfterInteractEvent args)
- {
- if (!args.CanReach)
- return;
-
- var target = args.Target;
- var user = args.User;
-
- TryDoInject(entity, target, user);
- }
-
- public void OnAttack(Entity entity, ref MeleeHitEvent args)
- {
- if (!args.HitEntities.Any())
- return;
-
- TryDoInject(entity, args.HitEntities.First(), args.User);
- }
-
- public bool TryDoInject(Entity hypo, EntityUid? target, EntityUid user)
- {
- var (uid, component) = hypo;
-
- if (!EligibleEntity(target, _entMan, component))
- return false;
-
- if (TryComp(uid, out UseDelayComponent? delayComp))
- {
- if (_useDelay.IsDelayed((uid, delayComp)))
- return false;
- }
-
-
- string? msgFormat = null;
-
- if (target == user)
- msgFormat = "hypospray-component-inject-self-message";
- else if (EligibleEntity(user, _entMan, component) && _interaction.TryRollClumsy(user, component.ClumsyFailChance))
- {
- msgFormat = "hypospray-component-inject-self-clumsy-message";
- target = user;
- }
-
- if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0)
- {
- _popup.PopupCursor(Loc.GetString("hypospray-component-empty-message"), user);
- return true;
- }
-
- if (!_solutionContainers.TryGetInjectableSolution(target.Value, out var targetSoln, out var targetSolution))
- {
- _popup.PopupCursor(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan))), user);
- return false;
- }
-
- _popup.PopupCursor(Loc.GetString(msgFormat ?? "hypospray-component-inject-other-message", ("other", target)), user);
-
- if (target != user)
- {
- _popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target.Value, target.Value);
- // TODO: This should just be using melee attacks...
- // meleeSys.SendLunge(angle, user);
- }
-
- _audio.PlayPvs(component.InjectSound, user);
-
- // Medipens and such use this system and don't have a delay, requiring extra checks
- // BeginDelay function returns if item is already on delay
- if (delayComp != null)
- _useDelay.TryResetDelay((uid, delayComp));
-
- // Get transfer amount. May be smaller than component.TransferAmount if not enough room
- var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume);
-
- if (realTransferAmount <= 0)
- {
- _popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message", ("owner", target)), user);
- return true;
- }
-
- // Move units from attackSolution to targetSolution
- var removedSolution = _solutionContainers.SplitSolution(hypoSpraySoln.Value, realTransferAmount);
-
- if (!targetSolution.CanAddSolution(removedSolution))
- return true;
- _reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection);
- _solutionContainers.TryAddSolution(targetSoln.Value, removedSolution);
-
- var ev = new TransferDnaEvent { Donor = target.Value, Recipient = uid };
- RaiseLocalEvent(target.Value, ref ev);
-
- // same LogType as syringes...
- _adminLogger.Add(LogType.ForceFeed, $"{_entMan.ToPrettyString(user):user} injected {_entMan.ToPrettyString(target.Value):target} with a solution {SolutionContainerSystem.ToPrettyString(removedSolution):removedSolution} using a {_entMan.ToPrettyString(uid):using}");
-
- return true;
- }
-
- static bool EligibleEntity([NotNullWhen(true)] EntityUid? entity, IEntityManager entMan, HyposprayComponent component)
- {
- // TODO: Does checking for BodyComponent make sense as a "can be hypospray'd" tag?
- // In SS13 the hypospray ONLY works on mobs, NOT beakers or anything else.
- // But this is 14, we dont do what SS13 does just because SS13 does it.
- return component.OnlyMobs
- ? entMan.HasComponent(entity) &&
- entMan.HasComponent(entity)
- : entMan.HasComponent(entity);
- }
- }
-}
diff --git a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs
new file mode 100644
index 0000000000..dfbe45c035
--- /dev/null
+++ b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs
@@ -0,0 +1,197 @@
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Chemistry.Components.SolutionManager;
+using Content.Shared.Chemistry.Reagent;
+using Content.Shared.Database;
+using Content.Shared.FixedPoint;
+using Content.Shared.Forensics;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Timing;
+using Content.Shared.Weapons.Melee.Events;
+using Content.Server.Interaction;
+using Content.Server.Body.Components;
+using Content.Server.Chemistry.Containers.EntitySystems;
+using Robust.Shared.GameStates;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Robust.Server.Audio;
+
+namespace Content.Server.Chemistry.EntitySystems;
+
+public sealed class HypospraySystem : SharedHypospraySystem
+{
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly InteractionSystem _interaction = default!;
+ [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnAfterInteract);
+ SubscribeLocalEvent(OnAttack);
+ SubscribeLocalEvent(OnUseInHand);
+ }
+
+ private void UseHypospray(Entity entity, EntityUid target, EntityUid user)
+ {
+ // if target is ineligible but is a container, try to draw from the container
+ if (!EligibleEntity(target, EntityManager, entity)
+ && _solutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _))
+ {
+ TryDraw(entity, target, drawableSolution.Value, user);
+ }
+
+ TryDoInject(entity, target, user);
+ }
+
+ private void OnUseInHand(Entity entity, ref UseInHandEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ TryDoInject(entity, args.User, args.User);
+ args.Handled = true;
+ }
+
+ public void OnAfterInteract(Entity entity, ref AfterInteractEvent args)
+ {
+ if (args.Handled || !args.CanReach || args.Target == null)
+ return;
+
+ UseHypospray(entity, args.Target.Value, args.User);
+ args.Handled = true;
+ }
+
+ public void OnAttack(Entity entity, ref MeleeHitEvent args)
+ {
+ if (!args.HitEntities.Any())
+ return;
+
+ TryDoInject(entity, args.HitEntities.First(), args.User);
+ }
+
+ public bool TryDoInject(Entity entity, EntityUid target, EntityUid user)
+ {
+ var (uid, component) = entity;
+
+ if (!EligibleEntity(target, EntityManager, component))
+ return false;
+
+ if (TryComp(uid, out UseDelayComponent? delayComp))
+ {
+ if (_useDelay.IsDelayed((uid, delayComp)))
+ return false;
+ }
+
+ string? msgFormat = null;
+
+ if (target == user)
+ msgFormat = "hypospray-component-inject-self-message";
+ else if (EligibleEntity(user, EntityManager, component) && _interaction.TryRollClumsy(user, component.ClumsyFailChance))
+ {
+ msgFormat = "hypospray-component-inject-self-clumsy-message";
+ target = user;
+ }
+
+ if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0)
+ {
+ _popup.PopupEntity(Loc.GetString("hypospray-component-empty-message"), target, user);
+ return true;
+ }
+
+ if (!_solutionContainers.TryGetInjectableSolution(target, out var targetSoln, out var targetSolution))
+ {
+ _popup.PopupEntity(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target, EntityManager))), target, user);
+ return false;
+ }
+
+ _popup.PopupEntity(Loc.GetString(msgFormat ?? "hypospray-component-inject-other-message", ("other", target)), target, user);
+
+ if (target != user)
+ {
+ _popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target);
+ // TODO: This should just be using melee attacks...
+ // meleeSys.SendLunge(angle, user);
+ }
+
+ _audio.PlayPvs(component.InjectSound, user);
+
+ // Medipens and such use this system and don't have a delay, requiring extra checks
+ // BeginDelay function returns if item is already on delay
+ if (delayComp != null)
+ _useDelay.TryResetDelay((uid, delayComp));
+
+ // Get transfer amount. May be smaller than component.TransferAmount if not enough room
+ var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume);
+
+ if (realTransferAmount <= 0)
+ {
+ _popup.PopupEntity(Loc.GetString("hypospray-component-transfer-already-full-message", ("owner", target)), target, user);
+ return true;
+ }
+
+ // Move units from attackSolution to targetSolution
+ var removedSolution = _solutionContainers.SplitSolution(hypoSpraySoln.Value, realTransferAmount);
+
+ if (!targetSolution.CanAddSolution(removedSolution))
+ return true;
+ _reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection);
+ _solutionContainers.TryAddSolution(targetSoln.Value, removedSolution);
+
+ var ev = new TransferDnaEvent { Donor = target, Recipient = uid };
+ RaiseLocalEvent(target, ref ev);
+
+ // same LogType as syringes...
+ _adminLogger.Add(LogType.ForceFeed, $"{EntityManager.ToPrettyString(user):user} injected {EntityManager.ToPrettyString(target):target} with a solution {SolutionContainerSystem.ToPrettyString(removedSolution):removedSolution} using a {EntityManager.ToPrettyString(uid):using}");
+
+ return true;
+ }
+
+ private void TryDraw(Entity entity, Entity target, Entity targetSolution, EntityUid user)
+ {
+ if (!_solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln,
+ out var solution) || solution.AvailableVolume == 0)
+ {
+ return;
+ }
+
+ // Get transfer amount. May be smaller than _transferAmount if not enough room, also make sure there's room in the injector
+ var realTransferAmount = FixedPoint2.Min(entity.Comp.TransferAmount, targetSolution.Comp.Solution.Volume,
+ solution.AvailableVolume);
+
+ if (realTransferAmount <= 0)
+ {
+ _popup.PopupEntity(
+ Loc.GetString("injector-component-target-is-empty-message",
+ ("target", Identity.Entity(target, EntityManager))),
+ entity.Owner, user);
+ return;
+ }
+
+ var removedSolution = _solutionContainers.Draw(target.Owner, targetSolution, realTransferAmount);
+
+ if (!_solutionContainers.TryAddSolution(soln.Value, removedSolution))
+ {
+ return;
+ }
+
+ _popup.PopupEntity(Loc.GetString("injector-component-draw-success-message",
+ ("amount", removedSolution.Volume),
+ ("target", Identity.Entity(target, EntityManager))), entity.Owner, user);
+ }
+
+ private bool EligibleEntity(EntityUid entity, IEntityManager entMan, HyposprayComponent component)
+ {
+ // TODO: Does checking for BodyComponent make sense as a "can be hypospray'd" tag?
+ // In SS13 the hypospray ONLY works on mobs, NOT beakers or anything else.
+ // But this is 14, we dont do what SS13 does just because SS13 does it.
+ return component.OnlyAffectsMobs
+ ? entMan.HasComponent(entity) &&
+ entMan.HasComponent(entity)
+ : entMan.HasComponent(entity);
+ }
+}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs b/Content.Server/Chemistry/EntitySystems/ReactionMixerSystem.cs
similarity index 76%
rename from Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs
rename to Content.Server/Chemistry/EntitySystems/ReactionMixerSystem.cs
index 0230671ec9..032374d4a5 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemMixer.cs
+++ b/Content.Server/Chemistry/EntitySystems/ReactionMixerSystem.cs
@@ -1,13 +1,20 @@
using Content.Shared.Chemistry.Reaction;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
+using Content.Server.Chemistry.Containers.EntitySystems;
+using Content.Server.Popups;
namespace Content.Server.Chemistry.EntitySystems;
-public sealed partial class ChemistrySystem
+public sealed partial class ReactionMixerSystem : EntitySystem
{
- public void InitializeMixing()
+ [Dependency] private readonly PopupSystem _popup = default!;
+ [Dependency] private readonly SolutionContainerSystem _solutionContainers = default!;
+
+ public override void Initialize()
{
+ base.Initialize();
+
SubscribeLocalEvent(OnAfterInteract);
}
diff --git a/Content.Shared/Chemistry/Components/HyposprayComponent.cs b/Content.Shared/Chemistry/Components/HyposprayComponent.cs
new file mode 100644
index 0000000000..05d202aaaa
--- /dev/null
+++ b/Content.Shared/Chemistry/Components/HyposprayComponent.cs
@@ -0,0 +1,33 @@
+using Content.Shared.FixedPoint;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+using Robust.Shared.Audio;
+
+namespace Content.Shared.Chemistry.Components;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class HyposprayComponent : Component
+{
+ [DataField]
+ public string SolutionName = "hypospray";
+
+ // TODO: This should be on clumsycomponent.
+ [DataField]
+ [ViewVariables(VVAccess.ReadWrite)]
+ public float ClumsyFailChance = 0.5f;
+
+ [DataField]
+ [ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 TransferAmount = FixedPoint2.New(5);
+
+ [DataField]
+ public SoundSpecifier InjectSound = new SoundPathSpecifier("/Audio/Items/hypospray.ogg");
+
+ ///
+ /// Decides whether you can inject everything or just mobs.
+ /// When you can only affect mobs, you're capable of drawing from beakers.
+ ///
+ [AutoNetworkedField]
+ [DataField(required: true)]
+ public bool OnlyAffectsMobs = false;
+}
diff --git a/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs b/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
deleted file mode 100644
index a8df6be109..0000000000
--- a/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Content.Shared.FixedPoint;
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Chemistry.Components;
-
-[NetworkedComponent()]
-public abstract partial class SharedHyposprayComponent : Component
-{
- [DataField("solutionName")]
- public string SolutionName = "hypospray";
-}
-
-[Serializable, NetSerializable]
-public sealed class HyposprayComponentState : ComponentState
-{
- public FixedPoint2 CurVolume { get; }
- public FixedPoint2 MaxVolume { get; }
-
- public HyposprayComponentState(FixedPoint2 curVolume, FixedPoint2 maxVolume)
- {
- CurVolume = curVolume;
- MaxVolume = maxVolume;
- }
-}
diff --git a/Content.Shared/Chemistry/EntitySystems/SharedHypospraySystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedHypospraySystem.cs
new file mode 100644
index 0000000000..f91e5621f0
--- /dev/null
+++ b/Content.Shared/Chemistry/EntitySystems/SharedHypospraySystem.cs
@@ -0,0 +1,61 @@
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Timing;
+using Content.Shared.Verbs;
+using Content.Shared.Popups;
+using Robust.Shared.Player;
+using Content.Shared.Administration.Logs;
+
+namespace Content.Shared.Chemistry.EntitySystems;
+
+public abstract class SharedHypospraySystem : EntitySystem
+{
+ [Dependency] protected readonly UseDelaySystem _useDelay = default!;
+ [Dependency] protected readonly SharedPopupSystem _popup = default!;
+ [Dependency] protected readonly SharedSolutionContainerSystem _solutionContainers = default!;
+ [Dependency] protected readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] protected readonly ReactiveSystem _reactiveSystem = default!;
+
+ public override void Initialize()
+ {
+ SubscribeLocalEvent>(AddToggleModeVerb);
+ }
+
+ //
+ // Uses the OnlyMobs field as a check to implement the ability
+ // to draw from jugs and containers with the hypospray
+ // Toggleable to allow people to inject containers if they prefer it over drawing
+ //
+ private void AddToggleModeVerb(Entity entity, ref GetVerbsEvent args)
+ {
+ if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+ return;
+
+ var (_, component) = entity;
+ var user = args.User;
+ var verb = new AlternativeVerb
+ {
+ Text = Loc.GetString("hypospray-verb-mode-label"),
+ Act = () =>
+ {
+ ToggleMode(entity, user);
+ }
+ };
+ args.Verbs.Add(verb);
+ }
+
+ private void ToggleMode(Entity entity, EntityUid user)
+ {
+ SetMode(entity, !entity.Comp.OnlyAffectsMobs);
+ string msg = entity.Comp.OnlyAffectsMobs ? "hypospray-verb-mode-inject-mobs-only" : "hypospray-verb-mode-inject-all";
+ _popup.PopupClient(Loc.GetString(msg), entity, user);
+ }
+
+ public void SetMode(Entity entity, bool onlyAffectsMobs)
+ {
+ if (entity.Comp.OnlyAffectsMobs == onlyAffectsMobs)
+ return;
+
+ entity.Comp.OnlyAffectsMobs = onlyAffectsMobs;
+ Dirty(entity);
+ }
+}
diff --git a/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs
index 7e41cb39bd..6c43c1d5f0 100644
--- a/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs
+++ b/Content.Shared/Chemistry/EntitySystems/SharedInjectorSystem.cs
@@ -37,10 +37,7 @@ public abstract class SharedInjectorSystem : EntitySystem
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
return;
- if (!HasComp(args.User))
- return;
var user = args.User;
-
var (_, component) = entity;
var min = component.MinimumTransferAmount;
diff --git a/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl b/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
index 7acbe8664c..52dbf9010e 100644
--- a/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
@@ -1,13 +1,21 @@
## UI
-hypospray-volume-text = Volume: [color=white]{$currentVolume}/{$totalVolume}[/color]
+hypospray-all-mode-text = Only Injects
+hypospray-mobs-only-mode-text = Draws and Injects
+hypospray-invalid-text = Invalid
+hypospray-volume-label = Volume: [color=white]{$currentVolume}/{$totalVolume}u[/color]
+ Mode: [color=white]{$modeString}[/color]
## Entity
hypospray-component-inject-other-message = You inject {$other}.
hypospray-component-inject-self-message = You inject yourself.
hypospray-component-inject-self-clumsy-message = Oops! You injected yourself.
-hypospray-component-empty-message = It's empty!
+hypospray-component-empty-message = Nothing to inject.
hypospray-component-feel-prick-message = You feel a tiny prick!
hypospray-component-transfer-already-full-message = {$owner} is already full!
hypospray-cant-inject = Can't inject into {$target}!
+
+hypospray-verb-mode-label = Toggle Container Draw
+hypospray-verb-mode-inject-all = You cannot draw from containers anymore.
+hypospray-verb-mode-inject-mobs-only = You can now draw from containers.
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
index 3d28487d68..abcabd7481 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
@@ -18,7 +18,7 @@
- type: ExaminableSolution
solution: hypospray
- type: Hypospray
- onlyMobs: false
+ onlyAffectsMobs: false
- type: UseDelay
delay: 0.5
- type: StaticPrice
@@ -49,7 +49,7 @@
- type: ExaminableSolution
solution: hypospray
- type: Hypospray
- onlyMobs: false
+ onlyAffectsMobs: false
- type: UseDelay
delay: 0.5
@@ -73,6 +73,7 @@
- type: ExaminableSolution
solution: hypospray
- type: Hypospray
+ onlyAffectsMobs: false
- type: UseDelay
delay: 0.5
@@ -113,6 +114,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 15
+ onlyAffectsMobs: false
- type: Appearance
- type: SolutionContainerVisuals
maxFillLevels: 1
@@ -202,6 +204,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 20
+ onlyAffectsMobs: false
- type: SolutionContainerManager
solutions:
pen:
@@ -232,6 +235,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 20
+ onlyAffectsMobs: false
- type: SolutionContainerManager
solutions:
pen:
@@ -262,6 +266,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 20
+ onlyAffectsMobs: false
- type: SolutionContainerManager
solutions:
pen:
@@ -293,6 +298,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 30
+ onlyAffectsMobs: false
- type: SolutionContainerManager
solutions:
pen:
@@ -330,6 +336,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 30
+ onlyAffectsMobs: false
- type: StaticPrice
price: 500
- type: Tag
@@ -389,6 +396,7 @@
- type: Hypospray
solutionName: pen
transferAmount: 30
+ onlyAffectsMobs: false
- type: StaticPrice
price: 500
- type: Tag
@@ -410,7 +418,7 @@
- type: ExaminableSolution
solution: hypospray
- type: Hypospray
- onlyMobs: false
+ onlyAffectsMobs: false
- type: UseDelay
delay: 0.5
- type: StaticPrice # A new shitcurity meta
From 431c3ad3b893b01b80e18ce0c00daffd2f77b046 Mon Sep 17 00:00:00 2001
From: EdenTheLiznerd <138748328+EdenTheLiznerd@users.noreply.github.com>
Date: Fri, 29 Mar 2024 22:00:21 -0600
Subject: [PATCH 19/26] Rebalance amatoxin so it is a slower killer (#25830)
* Balancing? Balancing!!!
* Additional changes
---
Resources/Prototypes/Reagents/toxins.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml
index 02e0b99519..6e1ad75a35 100644
--- a/Resources/Prototypes/Reagents/toxins.yml
+++ b/Resources/Prototypes/Reagents/toxins.yml
@@ -425,11 +425,12 @@
color: "#D6CE7B"
metabolisms:
Poison:
+ metabolismRate: 0.2
effects:
- !type:HealthChange
damage:
types:
- Poison: 6
+ Poison: 3
- type: reagent
id: VentCrud
From 299625772d86f28d847cde3104b6bf809033a2e5 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 04:00:22 +0000
Subject: [PATCH 20/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index b4ec1e0b33..2ca08113a3 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,14 +1,4 @@
Entries:
-- author: tday
- changes:
- - message: Added admin log messages for adding and ending game rules, and for the
- commands to do so.
- type: Add
- - message: Added admin log messages for secret mode rule selection.
- type: Add
- id: 5757
- time: '2024-01-20T18:02:13.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24092
- author: Nimfar11
changes:
- message: Adds snake kebab and its recipe.
@@ -3794,3 +3784,11 @@
id: 6256
time: '2024-03-30T03:35:43.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26504
+- author: Plykiya
+ changes:
+ - message: Hyposprays can now be toggled to draw from solution containers like jugs
+ and beakers.
+ type: Tweak
+ id: 6257
+ time: '2024-03-30T03:59:17.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/25544
From aa96baeb5fd68f7877c60ed20fdfdd3edf0ade02 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 04:01:31 +0000
Subject: [PATCH 21/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 2ca08113a3..8c70fdc638 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Nimfar11
- changes:
- - message: Adds snake kebab and its recipe.
- type: Add
- id: 5758
- time: '2024-01-20T23:38:11.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24341
- author: Alekshhh
changes:
- message: Cerberus now has a wideswing that works similarly to spears.
@@ -3792,3 +3785,11 @@
id: 6257
time: '2024-03-30T03:59:17.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25544
+- author: EdenTheLiznerd
+ changes:
+ - message: Amanita toxin now kills you slightly slower, providing you time to seek
+ charcoal before it's too late
+ type: Tweak
+ id: 6258
+ time: '2024-03-30T04:00:21.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/25830
From 888a3bda515a214733bf748c5d6a7e7c923a301e Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Sat, 30 Mar 2024 17:17:53 +1300
Subject: [PATCH 22/26] Atmos device performance improvements (#26493)
* Atmos device performance improvements
* AtmosDirection perf improvements
* Fix errors
* Add GasTileOverlayComponent arguments
* Make excite no longer invalidate a tile
---
.../Atmos/EntitySystems/AirFilterSystem.cs | 10 +--
.../Atmos/EntitySystems/AtmosExposedSystem.cs | 12 +--
.../EntitySystems/AtmosphereSystem.API.cs | 86 +++++++++++--------
.../AtmosphereSystem.ExcitedGroup.cs | 12 ++-
.../AtmosphereSystem.GridAtmosphere.cs | 11 +--
.../EntitySystems/AtmosphereSystem.Hotspot.cs | 14 +--
.../EntitySystems/AtmosphereSystem.LINDA.cs | 18 ++--
.../AtmosphereSystem.Monstermos.cs | 40 +++++----
.../AtmosphereSystem.Processing.cs | 46 ++++++----
.../AtmosphereSystem.Superconductivity.cs | 2 +-
.../EntitySystems/AtmosphereSystem.Utils.cs | 12 ++-
.../Atmos/EntitySystems/AtmosphereSystem.cs | 2 +-
.../Atmos/EntitySystems/GasTankSystem.cs | 2 +-
.../EntitySystems/GasTileOverlaySystem.cs | 8 +-
.../EntitySystems/HeatExchangerSystem.cs | 20 ++---
.../Monitor/Systems/AtmosMonitoringSystem.cs | 6 +-
.../EntitySystems/GasPassiveGateSystem.cs | 6 +-
.../EntitySystems/GasPressurePumpSystem.cs | 4 +-
.../Binary/EntitySystems/GasRecyclerSystem.cs | 10 +--
.../Binary/EntitySystems/GasValveSystem.cs | 5 +-
.../EntitySystems/GasVolumePumpSystem.cs | 7 +-
.../Piping/Components/AtmosDeviceComponent.cs | 20 +++--
.../Piping/EntitySystems/AtmosDeviceSystem.cs | 3 +-
.../Other/EntitySystems/GasMinerSystem.cs | 4 +-
.../Trinary/EntitySystems/GasFilterSystem.cs | 15 ++--
.../Trinary/EntitySystems/GasMixerSystem.cs | 14 +--
.../PressureControlledValveSystem.cs | 6 +-
.../Unary/EntitySystems/GasCanisterSystem.cs | 4 +-
.../Unary/EntitySystems/GasCondenserSystem.cs | 5 +-
.../EntitySystems/GasOutletInjectorSystem.cs | 10 +--
.../EntitySystems/GasPassiveVentSystem.cs | 7 +-
.../Unary/EntitySystems/GasPortableSystem.cs | 5 +-
.../EntitySystems/GasThermoMachineSystem.cs | 5 +-
.../Unary/EntitySystems/GasVentPumpSystem.cs | 12 +--
.../EntitySystems/GasVentScrubberSystem.cs | 19 ++--
.../Atmos/Portable/PortableScrubberSystem.cs | 32 +++----
.../Atmos/Portable/SpaceHeaterSystem.cs | 2 +-
.../Electrocution/ElectrocutionNode.cs | 9 +-
.../EntitySystems/ExplosionGridTileFlood.cs | 4 +-
.../EntitySystems/ExplosionSpaceTileFlood.cs | 2 +-
Content.Server/Mech/Systems/MechSystem.cs | 11 ++-
Content.Server/Medical/CryoPodSystem.cs | 15 +---
.../EntitySystems/NodeContainerSystem.cs | 74 ++++++++++++++++
.../PneumaticCannon/PneumaticCannonSystem.cs | 2 +-
.../Power/Components/CableVisComponent.cs | 4 +-
.../Power/EntitySystems/CableVisSystem.cs | 7 +-
.../Power/Generator/GasPowerReceiverSystem.cs | 8 +-
Content.Server/Spreader/SpreaderSystem.cs | 7 +-
Content.Shared/Atmos/AtmosDirection.cs | 24 +++++-
.../Tools/Systems/WeldableSystem.cs | 32 +++----
.../Entities/Virtual/electrocution.yml | 2 +-
51 files changed, 373 insertions(+), 324 deletions(-)
diff --git a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs
index d947e60b6d..2ab15cfb17 100644
--- a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs
@@ -13,6 +13,7 @@ public sealed class AirFilterSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly IMapManager _map = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
public override void Initialize()
{
@@ -31,7 +32,7 @@ public sealed class AirFilterSystem : EntitySystem
if (air.Pressure >= intake.Pressure)
return;
- var environment = _atmosphere.GetContainingMixture(uid, true, true);
+ var environment = _atmosphere.GetContainingMixture(uid, args.Grid, args.Map, true, true);
// nothing to intake from
if (environment == null)
return;
@@ -63,12 +64,11 @@ public sealed class AirFilterSystem : EntitySystem
var oxygen = air.GetMoles(filter.Oxygen) / air.TotalMoles;
var gases = oxygen >= filter.TargetOxygen ? filter.Gases : filter.OverflowGases;
- var coordinates = Transform(uid).MapPosition;
GasMixture? destination = null;
- if (_map.TryFindGridAt(coordinates, out _, out var grid))
+ if (args.Grid is {} grid)
{
- var tile = grid.GetTileRef(coordinates);
- destination = _atmosphere.GetTileMixture(tile.GridUid, null, tile.GridIndices, true);
+ var position = _transform.GetGridTilePositionOrDefault(uid);
+ destination = _atmosphere.GetTileMixture(grid, args.Map, position, true);
}
if (destination != null)
diff --git a/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs
index 4be4d8271f..9590b9aa54 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs
@@ -24,6 +24,8 @@ namespace Content.Server.Atmos.EntitySystems
///
/// Event that tries to query the mixture a certain entity is exposed to.
+ /// This is mainly intended for use with entities inside of containers.
+ /// This event is not raised for entities that are directly parented to the grid.
///
[ByRefEvent]
public struct AtmosExposedGetAirEvent
@@ -31,7 +33,7 @@ namespace Content.Server.Atmos.EntitySystems
///
/// The entity we want to query this for.
///
- public readonly EntityUid Entity;
+ public readonly Entity Entity;
///
/// The mixture that the entity is exposed to. Output parameter.
@@ -39,9 +41,9 @@ namespace Content.Server.Atmos.EntitySystems
public GasMixture? Gas = null;
///
- /// Whether to invalidate the mixture, if possible.
+ /// Whether to excite the mixture, if possible.
///
- public bool Invalidate = false;
+ public readonly bool Excite = false;
///
/// Whether this event has been handled or not.
@@ -49,10 +51,10 @@ namespace Content.Server.Atmos.EntitySystems
///
public bool Handled = false;
- public AtmosExposedGetAirEvent(EntityUid entity, bool invalidate = false)
+ public AtmosExposedGetAirEvent(Entity entity, bool excite = false)
{
Entity = entity;
- Invalidate = invalidate;
+ Excite = excite;
}
}
}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
index fb94fe414b..614d550c2f 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
@@ -4,6 +4,7 @@ using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Reactions;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
@@ -11,41 +12,39 @@ namespace Content.Server.Atmos.EntitySystems;
public partial class AtmosphereSystem
{
- public GasMixture? GetContainingMixture(EntityUid uid, bool ignoreExposed = false, bool excite = false, TransformComponent? transform = null)
+ public GasMixture? GetContainingMixture(Entity ent, bool ignoreExposed = false, bool excite = false)
{
- if (!ignoreExposed)
+ if (!Resolve(ent, ref ent.Comp))
+ return null;
+
+ return GetContainingMixture(ent, ent.Comp.GridUid, ent.Comp.MapUid, ignoreExposed, excite);
+ }
+
+ public GasMixture? GetContainingMixture(
+ Entity ent,
+ Entity? grid,
+ Entity? map,
+ bool ignoreExposed = false,
+ bool excite = false)
+ {
+ if (!Resolve(ent, ref ent.Comp))
+ return null;
+
+ if (!ignoreExposed && !ent.Comp.Anchored)
{
// Used for things like disposals/cryo to change which air people are exposed to.
- var ev = new AtmosExposedGetAirEvent(uid, excite);
-
- // Give the entity itself a chance to handle this.
- RaiseLocalEvent(uid, ref ev, false);
-
+ var ev = new AtmosExposedGetAirEvent((ent, ent.Comp), excite);
+ RaiseLocalEvent(ent, ref ev);
if (ev.Handled)
return ev.Gas;
- // We need to get the parent now, so we need the transform... If the parent is invalid, we can't do much else.
- if(!Resolve(uid, ref transform) || !transform.ParentUid.IsValid() || transform.MapUid == null)
- return GetTileMixture(null, null, Vector2i.Zero, excite);
-
- // Give the parent entity a chance to handle the event...
- RaiseLocalEvent(transform.ParentUid, ref ev, false);
-
- if (ev.Handled)
- return ev.Gas;
- }
- // Oops, we did a little bit of code duplication...
- else if(!Resolve(uid, ref transform))
- {
- return GetTileMixture(null, null, Vector2i.Zero, excite);
+ // TODO ATMOS: recursively iterate up through parents
+ // This really needs recursive InContainer metadata flag for performance
+ // And ideally some fast way to get the innermost airtight container.
}
-
- var gridUid = transform.GridUid;
- var mapUid = transform.MapUid;
- var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
-
- return GetTileMixture(gridUid, mapUid, position, excite);
+ var position = _transformSystem.GetGridTilePositionOrDefault((ent, ent.Comp));
+ return GetTileMixture(grid, map, position, excite);
}
public bool HasAtmosphere(EntityUid gridUid) => _atmosQuery.HasComponent(gridUid);
@@ -84,21 +83,28 @@ public partial class AtmosphereSystem
entity.Comp.InvalidatedCoords.Add(tile);
}
- public GasMixture?[]? GetTileMixtures(Entity? grid, Entity? map, List tiles, bool excite = false)
+ public GasMixture?[]? GetTileMixtures(
+ Entity? grid,
+ Entity? map,
+ List tiles,
+ bool excite = false)
{
GasMixture?[]? mixtures = null;
var handled = false;
// If we've been passed a grid, try to let it handle it.
- if (grid is {} gridEnt && Resolve(gridEnt, ref gridEnt.Comp))
+ if (grid is {} gridEnt && Resolve(gridEnt, ref gridEnt.Comp1))
{
+ if (excite)
+ Resolve(gridEnt, ref gridEnt.Comp2);
+
handled = true;
mixtures = new GasMixture?[tiles.Count];
for (var i = 0; i < tiles.Count; i++)
{
var tile = tiles[i];
- if (!gridEnt.Comp.Tiles.TryGetValue(tile, out var atmosTile))
+ if (!gridEnt.Comp1.Tiles.TryGetValue(tile, out var atmosTile))
{
// need to get map atmosphere
handled = false;
@@ -108,7 +114,10 @@ public partial class AtmosphereSystem
mixtures[i] = atmosTile.Air;
if (excite)
- gridEnt.Comp.InvalidatedCoords.Add(tile);
+ {
+ AddActiveTile(gridEnt.Comp1, atmosTile);
+ InvalidateVisuals((gridEnt.Owner, gridEnt.Comp2), tile);
+ }
}
}
@@ -146,15 +155,22 @@ public partial class AtmosphereSystem
return GetTileMixture(entity.Comp.GridUid, entity.Comp.MapUid, indices, excite);
}
- public GasMixture? GetTileMixture(Entity? grid, Entity? map, Vector2i gridTile, bool excite = false)
+ public GasMixture? GetTileMixture(
+ Entity? grid,
+ Entity? map,
+ Vector2i gridTile,
+ bool excite = false)
{
// If we've been passed a grid, try to let it handle it.
if (grid is {} gridEnt
- && Resolve(gridEnt, ref gridEnt.Comp, false)
- && gridEnt.Comp.Tiles.TryGetValue(gridTile, out var tile))
+ && Resolve(gridEnt, ref gridEnt.Comp1, false)
+ && gridEnt.Comp1.Tiles.TryGetValue(gridTile, out var tile))
{
if (excite)
- gridEnt.Comp.InvalidatedCoords.Add(gridTile);
+ {
+ AddActiveTile(gridEnt.Comp1, tile);
+ InvalidateVisuals((grid.Value.Owner, grid.Value.Comp2), gridTile);
+ }
return tile.Air;
}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs
index de4c9199cf..c1b58f7a77 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs
@@ -1,5 +1,7 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
+using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
namespace Content.Server.Atmos.EntitySystems
@@ -64,10 +66,12 @@ namespace Content.Server.Atmos.EntitySystems
excitedGroup.DismantleCooldown = 0;
}
- private void ExcitedGroupSelfBreakdown(GridAtmosphereComponent gridAtmosphere, ExcitedGroup excitedGroup)
+ private void ExcitedGroupSelfBreakdown(
+ Entity ent,
+ ExcitedGroup excitedGroup)
{
DebugTools.Assert(!excitedGroup.Disposed, "Excited group is disposed!");
- DebugTools.Assert(gridAtmosphere.ExcitedGroups.Contains(excitedGroup), "Grid Atmosphere does not contain Excited Group!");
+ DebugTools.Assert(ent.Comp1.ExcitedGroups.Contains(excitedGroup), "Grid Atmosphere does not contain Excited Group!");
var combined = new GasMixture(Atmospherics.CellVolume);
var tileSize = excitedGroup.Tiles.Count;
@@ -77,7 +81,7 @@ namespace Content.Server.Atmos.EntitySystems
if (tileSize == 0)
{
- ExcitedGroupDispose(gridAtmosphere, excitedGroup);
+ ExcitedGroupDispose(ent.Comp1, excitedGroup);
return;
}
@@ -103,7 +107,7 @@ namespace Content.Server.Atmos.EntitySystems
continue;
tile.Air.CopyFromMutable(combined);
- InvalidateVisuals(tile.GridIndex, tile.GridIndices);
+ InvalidateVisuals(ent, tile);
}
excitedGroup.BreakdownCooldown = 0;
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs
index bd45030896..4b9ef49a40 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs
@@ -1,4 +1,3 @@
-using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Reactions;
using Content.Shared.Atmos;
@@ -160,7 +159,7 @@ public sealed partial class AtmosphereSystem
}
///
- /// Update array of adjacent tiles and the adjacency flags. Optionally activates all tiles with modified adjacencies.
+ /// Update array of adjacent tiles and the adjacency flags.
///
private void UpdateAdjacentTiles(
Entity ent,
@@ -195,14 +194,16 @@ public sealed partial class AtmosphereSystem
if (activate)
AddActiveTile(atmos, adjacent);
- var oppositeDirection = direction.GetOpposite();
+ var oppositeIndex = i.ToOppositeIndex();
+ var oppositeDirection = (AtmosDirection) (1 << oppositeIndex);
+
if (adjBlockDirs.IsFlagSet(oppositeDirection) || blockedDirs.IsFlagSet(direction))
{
// Adjacency is blocked by some airtight entity.
tile.AdjacentBits &= ~direction;
adjacent.AdjacentBits &= ~oppositeDirection;
tile.AdjacentTiles[i] = null;
- adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = null;
+ adjacent.AdjacentTiles[oppositeIndex] = null;
}
else
{
@@ -210,7 +211,7 @@ public sealed partial class AtmosphereSystem
tile.AdjacentBits |= direction;
adjacent.AdjacentBits |= oppositeDirection;
tile.AdjacentTiles[i] = adjacent;
- adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = tile;
+ adjacent.AdjacentTiles[oppositeIndex] = tile;
}
DebugTools.Assert(!(tile.AdjacentBits.IsFlagSet(direction) ^
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs
index 713d1c4682..7163b4cd44 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs
@@ -1,10 +1,12 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Reactions;
using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
using Content.Shared.Audio;
using Content.Shared.Database;
using Robust.Shared.Audio;
using Robust.Shared.Map;
+using Robust.Shared.Map.Components;
using Robust.Shared.Player;
namespace Content.Server.Atmos.EntitySystems
@@ -18,18 +20,18 @@ namespace Content.Server.Atmos.EntitySystems
[ViewVariables(VVAccess.ReadWrite)]
public string? HotspotSound { get; private set; } = "/Audio/Effects/fire.ogg";
- private void ProcessHotspot(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
+ private void ProcessHotspot(
+ Entity ent,
+ TileAtmosphere tile)
{
+ var gridAtmosphere = ent.Comp1;
if (!tile.Hotspot.Valid)
{
gridAtmosphere.HotspotTiles.Remove(tile);
return;
}
- if (!tile.Excited)
- {
- AddActiveTile(gridAtmosphere, tile);
- }
+ AddActiveTile(gridAtmosphere, tile);
if (!tile.Hotspot.SkippedFirstProcess)
{
@@ -44,7 +46,7 @@ namespace Content.Server.Atmos.EntitySystems
|| tile.Air == null || tile.Air.GetMoles(Gas.Oxygen) < 0.5f || (tile.Air.GetMoles(Gas.Plasma) < 0.5f && tile.Air.GetMoles(Gas.Tritium) < 0.5f))
{
tile.Hotspot = new Hotspot();
- InvalidateVisuals(tile.GridIndex, tile.GridIndices);
+ InvalidateVisuals(ent, tile);
return;
}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs
index c27e18b55b..fb2375899d 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs
@@ -1,14 +1,18 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
+using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
namespace Content.Server.Atmos.EntitySystems
{
public sealed partial class AtmosphereSystem
{
- private void ProcessCell(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, int fireCount, GasTileOverlayComponent visuals)
+ private void ProcessCell(
+ Entity ent,
+ TileAtmosphere tile, int fireCount)
{
+ var gridAtmosphere = ent.Comp1;
// Can't process a tile without air
if (tile.Air == null)
{
@@ -52,11 +56,7 @@ namespace Content.Server.Atmos.EntitySystems
shouldShareAir = true;
} else if (CompareExchange(tile.Air, enemyTile.Air) != GasCompareResult.NoExchange)
{
- if (!enemyTile.Excited)
- {
- AddActiveTile(gridAtmosphere, enemyTile);
- }
-
+ AddActiveTile(gridAtmosphere, enemyTile);
if (ExcitedGroups)
{
var excitedGroup = tile.ExcitedGroup;
@@ -91,7 +91,7 @@ namespace Content.Server.Atmos.EntitySystems
}
else
{
- ConsiderPressureDifference(gridAtmosphere, enemyTile, direction.GetOpposite(), -difference);
+ ConsiderPressureDifference(gridAtmosphere, enemyTile, i.ToOppositeDir(), -difference);
}
}
@@ -102,7 +102,7 @@ namespace Content.Server.Atmos.EntitySystems
if(tile.Air != null)
React(tile.Air, tile);
- InvalidateVisuals(tile.GridIndex, tile.GridIndices, visuals);
+ InvalidateVisuals(ent, tile);
var remove = true;
@@ -146,7 +146,7 @@ namespace Content.Server.Atmos.EntitySystems
/// Tile Atmosphere to be activated.
private void AddActiveTile(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
{
- if (tile.Air == null)
+ if (tile.Air == null || tile.Excited)
return;
tile.Excited = true;
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs
index dcbc1e86ee..08193027d6 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs
@@ -230,7 +230,7 @@ namespace Content.Server.Atmos.EntitySystems
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
_equalizeQueue[queueLength++] = otherTile2;
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
- otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
+ otherTile2.MonstermosInfo.CurrentTransferDirection = k.ToOppositeDir();
otherTile2.MonstermosInfo.CurrentTransferAmount = 0;
if (otherTile2.MonstermosInfo.MoleDelta < 0)
{
@@ -296,7 +296,7 @@ namespace Content.Server.Atmos.EntitySystems
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
_equalizeQueue[queueLength++] = otherTile2;
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
- otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
+ otherTile2.MonstermosInfo.CurrentTransferDirection = k.ToOppositeDir();
otherTile2.MonstermosInfo.CurrentTransferAmount = 0;
if (otherTile2.MonstermosInfo.MoleDelta > 0)
@@ -338,7 +338,7 @@ namespace Content.Server.Atmos.EntitySystems
for (var i = 0; i < tileCount; i++)
{
var otherTile = _equalizeTiles[i]!;
- FinalizeEq(gridAtmosphere, otherTile, ent);
+ FinalizeEq(ent, otherTile);
}
for (var i = 0; i < tileCount; i++)
@@ -473,7 +473,7 @@ namespace Content.Server.Atmos.EntitySystems
if(tile2.Space)
continue;
- tile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
+ tile2.MonstermosInfo.CurrentTransferDirection = j.ToOppositeDir();
tile2.MonstermosInfo.CurrentTransferAmount = 0.0f;
tile2.PressureSpecificTarget = otherTile.PressureSpecificTarget;
tile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
@@ -549,7 +549,7 @@ namespace Content.Server.Atmos.EntitySystems
otherTile.Air.Temperature = Atmospherics.TCMB;
}
- InvalidateVisuals(otherTile.GridIndex, otherTile.GridIndices, visuals);
+ InvalidateVisuals(ent, otherTile);
HandleDecompressionFloorRip(mapGrid, otherTile, otherTile.MonstermosInfo.CurrentTransferAmount);
}
@@ -598,11 +598,13 @@ namespace Content.Server.Atmos.EntitySystems
UpdateAdjacentTiles(ent, tile);
UpdateAdjacentTiles(ent, other);
- InvalidateVisuals(tile.GridIndex, tile.GridIndices, ent);
- InvalidateVisuals(other.GridIndex, other.GridIndices, ent);
+ InvalidateVisuals(ent, tile);
+ InvalidateVisuals(ent, other);
}
- private void FinalizeEq(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, GasTileOverlayComponent? visuals)
+ private void FinalizeEq(
+ Entity ent,
+ TileAtmosphere tile)
{
Span transferDirections = stackalloc float[Atmospherics.Directions];
var hasTransferDirs = false;
@@ -629,17 +631,19 @@ namespace Content.Server.Atmos.EntitySystems
// Everything that calls this method already ensures that Air will not be null.
if (tile.Air!.TotalMoles < amount)
- FinalizeEqNeighbors(gridAtmosphere, tile, transferDirections, visuals);
+ FinalizeEqNeighbors(ent, tile, transferDirections);
- otherTile.MonstermosInfo[direction.GetOpposite()] = 0;
+ otherTile.MonstermosInfo[i.ToOppositeDir()] = 0;
Merge(otherTile.Air, tile.Air.Remove(amount));
- InvalidateVisuals(tile.GridIndex, tile.GridIndices, visuals);
- InvalidateVisuals(otherTile.GridIndex, otherTile.GridIndices, visuals);
- ConsiderPressureDifference(gridAtmosphere, tile, direction, amount);
+ InvalidateVisuals(ent, tile);
+ InvalidateVisuals(ent, otherTile);
+ ConsiderPressureDifference(ent, tile, direction, amount);
}
}
- private void FinalizeEqNeighbors(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, ReadOnlySpan transferDirs, GasTileOverlayComponent? visuals)
+ private void FinalizeEqNeighbors(
+ Entity ent,
+ TileAtmosphere tile, ReadOnlySpan transferDirs)
{
for (var i = 0; i < Atmospherics.Directions; i++)
{
@@ -647,7 +651,7 @@ namespace Content.Server.Atmos.EntitySystems
var amount = transferDirs[i];
// Since AdjacentBits is set, AdjacentTiles[i] wouldn't be null, and neither would its air.
if(amount < 0 && tile.AdjacentBits.IsFlagSet(direction))
- FinalizeEq(gridAtmosphere, tile.AdjacentTiles[i]!, visuals); // A bit of recursion if needed.
+ FinalizeEq(ent, tile.AdjacentTiles[i]!); // A bit of recursion if needed.
}
}
@@ -664,7 +668,9 @@ namespace Content.Server.Atmos.EntitySystems
Log.Error($"Encountered null-tile in {nameof(AdjustEqMovement)}. Trace: {Environment.StackTrace}");
return;
}
- var adj = tile.AdjacentTiles[direction.ToIndex()];
+
+ var idx = direction.ToIndex();
+ var adj = tile.AdjacentTiles[idx];
if (adj == null)
{
var nonNull = tile.AdjacentTiles.Where(x => x != null).Count();
@@ -673,7 +679,7 @@ namespace Content.Server.Atmos.EntitySystems
}
tile.MonstermosInfo[direction] += amount;
- adj.MonstermosInfo[direction.GetOpposite()] -= amount;
+ adj.MonstermosInfo[idx.ToOppositeDir()] -= amount;
}
private void HandleDecompressionFloorRip(MapGridComponent mapGrid, TileAtmosphere tile, float sum)
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs
index eba398c182..bd023e8574 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs
@@ -86,7 +86,7 @@ namespace Content.Server.Atmos.EntitySystems
DebugTools.Assert(atmosphere.Tiles.GetValueOrDefault(tile.GridIndices) == tile);
UpdateAdjacentTiles(ent, tile, activate: true);
UpdateTileAir(ent, tile, volume);
- InvalidateVisuals(uid, tile.GridIndices, visuals);
+ InvalidateVisuals(ent, tile);
if (number++ < InvalidCoordinatesLagCheckIterations)
continue;
@@ -313,15 +313,17 @@ namespace Content.Server.Atmos.EntitySystems
return true;
}
- private bool ProcessActiveTiles(GridAtmosphereComponent atmosphere, GasTileOverlayComponent visuals)
+ private bool ProcessActiveTiles(
+ Entity ent)
{
+ var atmosphere = ent.Comp1;
if(!atmosphere.ProcessingPaused)
QueueRunTiles(atmosphere.CurrentRunTiles, atmosphere.ActiveTiles);
var number = 0;
while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
{
- ProcessCell(atmosphere, tile, atmosphere.UpdateCounter, visuals);
+ ProcessCell(ent, tile, atmosphere.UpdateCounter);
if (number++ < LagCheckIterations)
continue;
@@ -337,8 +339,10 @@ namespace Content.Server.Atmos.EntitySystems
return true;
}
- private bool ProcessExcitedGroups(GridAtmosphereComponent gridAtmosphere)
+ private bool ProcessExcitedGroups(
+ Entity ent)
{
+ var gridAtmosphere = ent.Comp1;
if (!gridAtmosphere.ProcessingPaused)
{
gridAtmosphere.CurrentRunExcitedGroups.Clear();
@@ -356,7 +360,7 @@ namespace Content.Server.Atmos.EntitySystems
excitedGroup.DismantleCooldown++;
if (excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles)
- ExcitedGroupSelfBreakdown(gridAtmosphere, excitedGroup);
+ ExcitedGroupSelfBreakdown(ent, excitedGroup);
else if (excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles)
DeactivateGroupTiles(gridAtmosphere, excitedGroup);
// TODO ATMOS. What is the point of this? why is this only de-exciting the group? Shouldn't it also dismantle it?
@@ -411,15 +415,17 @@ namespace Content.Server.Atmos.EntitySystems
return true;
}
- private bool ProcessHotspots(GridAtmosphereComponent atmosphere)
+ private bool ProcessHotspots(
+ Entity ent)
{
+ var atmosphere = ent.Comp1;
if(!atmosphere.ProcessingPaused)
QueueRunTiles(atmosphere.CurrentRunTiles, atmosphere.HotspotTiles);
var number = 0;
while (atmosphere.CurrentRunTiles.TryDequeue(out var hotspot))
{
- ProcessHotspot(atmosphere, hotspot);
+ ProcessHotspot(ent, hotspot);
if (number++ < LagCheckIterations)
continue;
@@ -507,8 +513,11 @@ namespace Content.Server.Atmos.EntitySystems
return num * AtmosTime;
}
- private bool ProcessAtmosDevices(GridAtmosphereComponent atmosphere)
+ private bool ProcessAtmosDevices(
+ Entity ent,
+ Entity map)
{
+ var atmosphere = ent.Comp1;
if (!atmosphere.ProcessingPaused)
{
atmosphere.CurrentRunAtmosDevices.Clear();
@@ -521,7 +530,7 @@ namespace Content.Server.Atmos.EntitySystems
var time = _gameTiming.CurTime;
var number = 0;
- var ev = new AtmosDeviceUpdateEvent(RealAtmosTime());
+ var ev = new AtmosDeviceUpdateEvent(RealAtmosTime(), (ent, ent.Comp1, ent.Comp2), map);
while (atmosphere.CurrentRunAtmosDevices.TryDequeue(out var device))
{
RaiseLocalEvent(device, ref ev);
@@ -565,12 +574,11 @@ namespace Content.Server.Atmos.EntitySystems
var ent = _currentRunAtmosphere[_currentRunAtmosphereIndex];
var (owner, atmosphere, visuals, grid, xform) = ent;
- if (!TryComp(owner, out TransformComponent? x)
- || x.MapUid == null
- || TerminatingOrDeleted(x.MapUid.Value)
- || x.MapID == MapId.Nullspace)
+ if (xform.MapUid == null
+ || TerminatingOrDeleted(xform.MapUid.Value)
+ || xform.MapID == MapId.Nullspace)
{
- Log.Error($"Attempted to process atmos without a map? Entity: {ToPrettyString(owner)}. Map: {ToPrettyString(x?.MapUid)}. MapId: {x?.MapID}");
+ Log.Error($"Attempted to process atmos without a map? Entity: {ToPrettyString(owner)}. Map: {ToPrettyString(xform?.MapUid)}. MapId: {xform?.MapID}");
continue;
}
@@ -585,6 +593,8 @@ namespace Content.Server.Atmos.EntitySystems
// We subtract it so it takes lost time into account.
atmosphere.Timer -= AtmosTime;
+ var map = new Entity(xform.MapUid.Value, _mapAtmosQuery.CompOrNull(xform.MapUid.Value));
+
switch (atmosphere.State)
{
case AtmosphereProcessingState.Revalidate:
@@ -614,7 +624,7 @@ namespace Content.Server.Atmos.EntitySystems
atmosphere.State = AtmosphereProcessingState.ActiveTiles;
continue;
case AtmosphereProcessingState.ActiveTiles:
- if (!ProcessActiveTiles(ent, ent))
+ if (!ProcessActiveTiles(ent))
{
atmosphere.ProcessingPaused = true;
return;
@@ -625,7 +635,7 @@ namespace Content.Server.Atmos.EntitySystems
atmosphere.State = ExcitedGroups ? AtmosphereProcessingState.ExcitedGroups : AtmosphereProcessingState.HighPressureDelta;
continue;
case AtmosphereProcessingState.ExcitedGroups:
- if (!ProcessExcitedGroups(atmosphere))
+ if (!ProcessExcitedGroups(ent))
{
atmosphere.ProcessingPaused = true;
return;
@@ -645,7 +655,7 @@ namespace Content.Server.Atmos.EntitySystems
atmosphere.State = AtmosphereProcessingState.Hotspots;
continue;
case AtmosphereProcessingState.Hotspots:
- if (!ProcessHotspots(atmosphere))
+ if (!ProcessHotspots(ent))
{
atmosphere.ProcessingPaused = true;
return;
@@ -680,7 +690,7 @@ namespace Content.Server.Atmos.EntitySystems
atmosphere.State = AtmosphereProcessingState.AtmosDevices;
continue;
case AtmosphereProcessingState.AtmosDevices:
- if (!ProcessAtmosDevices(atmosphere))
+ if (!ProcessAtmosDevices(ent, map))
{
atmosphere.ProcessingPaused = true;
return;
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs
index 5c73cf1124..8ed92a9d0e 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs
@@ -16,7 +16,7 @@ namespace Content.Server.Atmos.EntitySystems
if (!directions.IsFlagSet(direction))
continue;
- var adjacent = tile.AdjacentTiles[direction.ToIndex()];
+ var adjacent = tile.AdjacentTiles[i];
// TODO ATMOS handle adjacent being null.
if (adjacent == null || adjacent.ThermalConductivity == 0f)
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
index 67c6d5998d..cf4c73aa2f 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
@@ -36,9 +36,17 @@ public partial class AtmosphereSystem
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void InvalidateVisuals(EntityUid gridUid, Vector2i tile, GasTileOverlayComponent? comp = null)
+ public void InvalidateVisuals(Entity grid, Vector2i tile)
{
- _gasTileOverlaySystem.Invalidate(gridUid, tile, comp);
+ _gasTileOverlaySystem.Invalidate(grid, tile);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void InvalidateVisuals(
+ Entity ent,
+ TileAtmosphere tile)
+ {
+ _gasTileOverlaySystem.Invalidate((ent.Owner, ent.Comp2), tile.GridIndices);
}
///
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
index a553766582..44bfa4cc10 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
@@ -96,7 +96,7 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
var query = EntityQueryEnumerator();
while (query.MoveNext(out var uid, out _, out var transform))
{
- var air = GetContainingMixture(uid, transform:transform);
+ var air = GetContainingMixture((uid, transform));
if (air == null)
continue;
diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
index aed00432e1..80842416e8 100644
--- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
@@ -168,7 +168,7 @@ namespace Content.Server.Atmos.EntitySystems
private void ReleaseGas(Entity gasTank)
{
var removed = RemoveAirVolume(gasTank, gasTank.Comp.ValveOutputRate * TimerDelay);
- var environment = _atmosphereSystem.GetContainingMixture(gasTank, false, true);
+ var environment = _atmosphereSystem.GetContainingMixture(gasTank.Owner, false, true);
if (environment != null)
{
_atmosphereSystem.Merge(environment, removed);
diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
index 003eed59e0..c42cfd08da 100644
--- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
+++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs
@@ -60,6 +60,7 @@ namespace Content.Server.Atmos.EntitySystems
private float _updateInterval;
private int _thresholds;
+ private EntityQuery _query;
public override void Initialize()
{
@@ -84,6 +85,7 @@ namespace Content.Server.Atmos.EntitySystems
SubscribeLocalEvent(Reset);
SubscribeLocalEvent(OnStartup);
+ _query = GetEntityQuery();
}
private void OnStartup(EntityUid uid, GasTileOverlayComponent component, ComponentStartup args)
@@ -132,10 +134,10 @@ namespace Content.Server.Atmos.EntitySystems
private void UpdateThresholds(int value) => _thresholds = value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Invalidate(EntityUid grid, Vector2i index, GasTileOverlayComponent? comp = null)
+ public void Invalidate(Entity grid, Vector2i index)
{
- if (Resolve(grid, ref comp))
- comp.InvalidTiles.Add(index);
+ if (_query.Resolve(grid.Owner, ref grid.Comp))
+ grid.Comp.InvalidTiles.Add(index);
}
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
diff --git a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs
index 286b154e96..b3644e88b7 100644
--- a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs
@@ -40,24 +40,16 @@ public sealed class HeatExchangerSystem : EntitySystem
private void OnAtmosUpdate(EntityUid uid, HeatExchangerComponent comp, ref AtmosDeviceUpdateEvent args)
{
- if (!TryComp(uid, out NodeContainerComponent? nodeContainer)
- || !TryComp(uid, out AtmosDeviceComponent? device)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outlet))
+ // make sure that the tile the device is on isn't blocked by a wall or something similar.
+ if (args.Grid is {} grid
+ && _transform.TryGetGridTilePosition(uid, out var tile)
+ && _atmosphereSystem.IsTileAirBlocked(grid, tile))
{
return;
}
- // make sure that the tile the device is on isn't blocked by a wall or something similar.
- var xform = Transform(uid);
- if (_transform.TryGetGridTilePosition(uid, out var tile))
- {
- // TryGetGridTilePosition() already returns false if GridUid is null, but the null checker isn't smart enough yet
- if (xform.GridUid != null && _atmosphereSystem.IsTileAirBlocked(xform.GridUid.Value, tile))
- {
- return;
- }
- }
+ if (!_nodeContainer.TryGetNodes(uid, comp.InletName, comp.OutletName, out PipeNode? inlet, out PipeNode? outlet))
+ return;
var dt = args.dt;
diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
index 28a0a01c99..c1a5256fdd 100644
--- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
@@ -204,11 +204,7 @@ public sealed class AtmosMonitorSystem : EntitySystem
if (!this.IsPowered(uid, EntityManager))
return;
- // can't hurt
- // (in case something is making AtmosDeviceUpdateEvents
- // outside the typical device loop)
- if (!TryComp(uid, out var atmosDeviceComponent)
- || atmosDeviceComponent.JoinedGrid == null)
+ if (args.Grid == null)
return;
// if we're not monitoring atmos, don't bother
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs
index 77bab4775c..fced4d7988 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs
@@ -26,11 +26,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnPassiveGateUpdated(EntityUid uid, GasPassiveGateComponent gate, ref AtmosDeviceUpdateEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, gate.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, gate.OutletName, out PipeNode? outlet))
+ if (!_nodeContainer.TryGetNodes(uid, gate.InletName, gate.OutletName, out PipeNode? inlet, out PipeNode? outlet))
return;
var n1 = inlet.Air.TotalMoles;
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs
index 49b69fc673..af25d04df9 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs
@@ -66,9 +66,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, ref AtmosDeviceUpdateEvent args)
{
if (!pump.Enabled
- || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, pump.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, pump.OutletName, out PipeNode? outlet))
+ || !_nodeContainer.TryGetNodes(uid, pump.InletName, pump.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{
_ambientSoundSystem.SetAmbience(uid, false);
return;
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs
index e14069b8a7..3ebc509492 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs
@@ -41,12 +41,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
if (!EntityManager.GetComponent(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status.
return;
- if (!EntityManager.TryGetComponent(ent, out NodeContainerComponent? nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? _))
- {
+ if (!_nodeContainer.TryGetNode(ent.Owner, comp.InletName, out PipeNode? inlet))
return;
- }
using (args.PushGroup(nameof(GasRecyclerComponent)))
{
@@ -72,9 +68,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnUpdate(Entity ent, ref AtmosDeviceUpdateEvent args)
{
var comp = ent.Comp;
- if (!EntityManager.TryGetComponent(ent, out NodeContainerComponent? nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outlet))
+ if (!_nodeContainer.TryGetNodes(ent.Owner, comp.InletName, comp.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{
_ambientSoundSystem.SetAmbience(ent, false);
return;
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
index 934ce8a7a4..ed7567428e 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs
@@ -59,9 +59,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
public void Set(EntityUid uid, GasValveComponent component, bool value)
{
component.Open = value;
- if (TryComp(uid, out NodeContainerComponent? nodeContainer)
- && _nodeContainer.TryGetNode(nodeContainer, component.InletName, out PipeNode? inlet)
- && _nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet))
+
+ if (_nodeContainer.TryGetNodes(uid, component.InletName, component.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{
if (TryComp(uid, out var appearance))
{
diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs
index 8e478bd2b5..e4767c4061 100644
--- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs
+++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs
@@ -71,11 +71,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, ref AtmosDeviceUpdateEvent args)
{
- if (!pump.Enabled
- || !TryComp(uid, out NodeContainerComponent? nodeContainer)
- || !TryComp(uid, out AtmosDeviceComponent? device)
- || !_nodeContainer.TryGetNode(nodeContainer, pump.InletName, out PipeNode? inlet)
- || !_nodeContainer.TryGetNode(nodeContainer, pump.OutletName, out PipeNode? outlet))
+ if (!pump.Enabled ||
+ !_nodeContainer.TryGetNodes(uid, pump.InletName, pump.OutletName, out PipeNode? inlet, out PipeNode? outlet))
{
_ambientSoundSystem.SetAmbience(uid, false);
return;
diff --git a/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs b/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs
index 80461f1beb..b70262e857 100644
--- a/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs
+++ b/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs
@@ -1,4 +1,5 @@
using Content.Server.Atmos.Components;
+using Content.Shared.Atmos.Components;
namespace Content.Server.Atmos.Piping.Components;
@@ -46,18 +47,25 @@ public sealed partial class AtmosDeviceComponent : Component
/// Use this for atmos devices instead of .
///
[ByRefEvent]
-public readonly struct AtmosDeviceUpdateEvent
+public readonly struct AtmosDeviceUpdateEvent(float dt, Entity? grid, Entity? map)
{
///
/// Time elapsed since last update, in seconds. Multiply values used in the update handler
/// by this number to make them tickrate-invariant. Use this number instead of AtmosphereSystem.AtmosTime.
///
- public readonly float dt;
+ public readonly float dt = dt;
- public AtmosDeviceUpdateEvent(float dt)
- {
- this.dt = dt;
- }
+ ///
+ /// The grid that this device is currently on.
+ ///
+ public readonly Entity? Grid = grid == null
+ ? null
+ : (grid.Value, grid.Value, grid.Value);
+
+ ///
+ /// The map that the device & grid is on.
+ ///
+ public readonly Entity? Map = map;
}
///
diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs
index c15d31f7d6..3c73a8f64e 100644
--- a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs
+++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs
@@ -129,9 +129,10 @@ namespace Content.Server.Atmos.Piping.EntitySystems
_timer -= _atmosphereSystem.AtmosTime;
var time = _gameTiming.CurTime;
- var ev = new AtmosDeviceUpdateEvent(_atmosphereSystem.AtmosTime);
+ var ev = new AtmosDeviceUpdateEvent(_atmosphereSystem.AtmosTime, null, null);
foreach (var device in _joinedDevices)
{
+ DebugTools.Assert(!HasComp(Transform(device).GridUid));
RaiseLocalEvent(device, ref ev);
device.Comp.LastProcess = time;
}
diff --git a/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs b/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs
index 9853a17f82..aa206dbc68 100644
--- a/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs
+++ b/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs
@@ -38,9 +38,9 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
private bool CheckMinerOperation(Entity ent, [NotNullWhen(true)] out GasMixture? environment)
{
var (uid, miner) = ent;
- environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
-
var transform = Transform(uid);
+ environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true);
+
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
// Space.
diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
index faf06a6079..f856946a92 100644
--- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
+++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
@@ -53,11 +53,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, ref AtmosDeviceUpdateEvent args)
{
if (!filter.Enabled
- || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
- || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device)
- || !_nodeContainer.TryGetNode(nodeContainer, filter.InletName, out PipeNode? inletNode)
- || !_nodeContainer.TryGetNode(nodeContainer, filter.FilterName, out PipeNode? filterNode)
- || !_nodeContainer.TryGetNode(nodeContainer, filter.OutletName, out PipeNode? outletNode)
+ || !_nodeContainer.TryGetNodes(uid, filter.InletName, filter.OutletName, filter.FilterName, out PipeNode? inletNode, out PipeNode? filterNode, out PipeNode? outletNode)
|| outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) // No need to transfer if target is full.
{
_ambientSoundSystem.SetAmbience(uid, false);
@@ -187,16 +183,15 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
return;
- var gasMixDict = new Dictionary();
+ args.GasMixtures ??= new Dictionary();
if(_nodeContainer.TryGetNode(nodeContainer, component.InletName, out PipeNode? inlet))
- gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-inlet"), inlet.Air);
+ args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-inlet"), inlet.Air);
if(_nodeContainer.TryGetNode(nodeContainer, component.FilterName, out PipeNode? filterNode))
- gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-filter"), filterNode.Air);
+ args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-filter"), filterNode.Air);
if(_nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet))
- gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air);
+ args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air);
- args.GasMixtures = gasMixDict;
args.DeviceFlipped = inlet != null && filterNode != null && inlet.CurrentPipeDirection.ToDirection() == filterNode.CurrentPipeDirection.ToDirection().GetClockwise90Degrees();
}
}
diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
index fb65c17f61..ba8ebf3c9a 100644
--- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
+++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
@@ -54,18 +54,8 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
{
// TODO ATMOS: Cache total moles since it's expensive.
- if (!mixer.Enabled)
- {
- _ambientSoundSystem.SetAmbience(uid, false);
- return;
- }
-
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, mixer.InletOneName, out PipeNode? inletOne)
- || !_nodeContainer.TryGetNode(nodeContainer, mixer.InletTwoName, out PipeNode? inletTwo)
- || !_nodeContainer.TryGetNode(nodeContainer, mixer.OutletName, out PipeNode? outlet))
+ if (!mixer.Enabled
+ || !_nodeContainer.TryGetNodes(uid, mixer.InletOneName, mixer.InletTwoName, mixer.OutletName, out PipeNode? inletOne, out PipeNode? inletTwo, out PipeNode? outlet))
{
_ambientSoundSystem.SetAmbience(uid, false);
return;
diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs
index 2c2f1584a5..1bab2abd8e 100644
--- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs
+++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs
@@ -33,11 +33,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
private void OnUpdate(EntityUid uid, PressureControlledValveComponent comp, ref AtmosDeviceUpdateEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
- || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inletNode)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.ControlName, out PipeNode? controlNode)
- || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outletNode))
+ if (!_nodeContainer.TryGetNodes(uid, comp.InletName, comp.ControlName, comp.OutletName, out PipeNode? inletNode, out PipeNode? controlNode, out PipeNode? outletNode))
{
_ambientSoundSystem.SetAmbience(uid, false);
comp.Enabled = false;
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
index 170586339d..3e4340bf1d 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
@@ -60,7 +60,7 @@ public sealed class GasCanisterSystem : EntitySystem
if (!Resolve(uid, ref canister, ref transform))
return;
- var environment = _atmos.GetContainingMixture(uid, false, true);
+ var environment = _atmos.GetContainingMixture((uid, transform), false, true);
if (environment is not null)
_atmos.Merge(environment, canister.Air);
@@ -168,7 +168,7 @@ public sealed class GasCanisterSystem : EntitySystem
}
else
{
- var environment = _atmos.GetContainingMixture(uid, false, true);
+ var environment = _atmos.GetContainingMixture(uid, args.Grid, args.Map, false, true);
_atmos.ReleaseGasTo(canister.Air, environment, canister.ReleasePressure);
}
}
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs
index 852542ec6c..e903ceedaf 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs
@@ -30,9 +30,8 @@ public sealed class GasCondenserSystem : EntitySystem
private void OnCondenserUpdated(Entity entity, ref AtmosDeviceUpdateEvent args)
{
- if (!(_power.IsPowered(entity) && TryComp(entity, out var receiver))
- || !TryComp(entity, out var nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, entity.Comp.Inlet, out PipeNode? inlet)
+ if (!(TryComp(entity, out var receiver) && _power.IsPowered(entity, receiver))
+ || !_nodeContainer.TryGetNode(entity.Owner, entity.Comp.Inlet, out PipeNode? inlet)
|| !_solution.ResolveSolution(entity.Owner, entity.Comp.SolutionId, ref entity.Comp.Solution, out var solution))
{
return;
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs
index 8029a09556..834a1dfb0b 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs
@@ -50,16 +50,10 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
if (!injector.Enabled)
return;
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
+ if (!_nodeContainer.TryGetNode(uid, injector.InletName, out PipeNode? inlet))
return;
- if (!TryComp(uid, out AtmosDeviceComponent? device))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, injector.InletName, out PipeNode? inlet))
- return;
-
- var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
+ var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true);
if (environment == null)
return;
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs
index c8fd23d466..72812cb523 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs
@@ -24,15 +24,12 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, ref AtmosDeviceUpdateEvent args)
{
- var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
+ var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true);
if (environment == null)
return;
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, vent.InletName, out PipeNode? inlet))
+ if (!_nodeContainer.TryGetNode(uid, vent.InletName, out PipeNode? inlet))
return;
var inletAir = inlet.Air.RemoveRatio(1f);
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs
index 4ddd19dd45..7cb8102a38 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs
@@ -39,10 +39,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnAnchorChanged(EntityUid uid, GasPortableComponent portable, ref AnchorStateChangedEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, portable.PortName, out PipeNode? portableNode))
+ if (!_nodeContainer.TryGetNode(uid, portable.PortName, out PipeNode? portableNode))
return;
portableNode.ConnectionsEnabled = args.Anchored;
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs
index d4ddd65a8e..9b61044f03 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs
@@ -110,7 +110,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
_atmosphereSystem.AddHeat(heatExchangeGasMixture, dQPipe);
thermoMachine.LastEnergyDelta = dQPipe;
- if (dQLeak != 0f && _atmosphereSystem.GetContainingMixture(uid, excite: true) is { } containingMixture)
+ if (dQLeak != 0f && _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, excite: true) is { } containingMixture)
_atmosphereSystem.AddHeat(containingMixture, dQLeak);
}
@@ -130,8 +130,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
}
else
{
- if (!TryComp(uid, out var nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, thermoMachine.InletName, out PipeNode? inlet))
+ if (!_nodeContainer.TryGetNode(uid, thermoMachine.InletName, out PipeNode? inlet))
return;
heatExchangeGasMixture = inlet.Air;
}
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
index 3a3ccf7523..a986385f5e 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
@@ -67,15 +67,12 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
_ => throw new ArgumentOutOfRangeException()
};
- if (!vent.Enabled
- || !TryComp(uid, out AtmosDeviceComponent? device)
- || !TryComp(uid, out NodeContainerComponent? nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, nodeName, out PipeNode? pipe))
+ if (!vent.Enabled || !_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe))
{
return;
}
- var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
+ var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true);
// We're in an air-blocked tile... Do nothing.
if (environment == null)
@@ -295,9 +292,6 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
///
private void OnAnalyzed(EntityUid uid, GasVentPumpComponent component, GasAnalyzerScanEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
-
var gasMixDict = new Dictionary();
// these are both called pipe, above it switches using this so I duplicated that...?
@@ -307,7 +301,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
VentPumpDirection.Siphoning => component.Outlet,
_ => throw new ArgumentOutOfRangeException()
};
- if (_nodeContainer.TryGetNode(nodeContainer, nodeName, out PipeNode? pipe))
+ if (_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe))
gasMixDict.Add(nodeName, pipe.Air);
args.GasMixtures = gasMixDict;
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs
index 5afa007e5e..b27689ed58 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs
@@ -49,27 +49,18 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, ref AtmosDeviceUpdateEvent args)
{
if (_weldable.IsWelded(uid))
- {
- return;
- }
-
- if (!TryComp(uid, out AtmosDeviceComponent? device))
return;
var timeDelta = args.dt;
- if (!scrubber.Enabled
- || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, scrubber.OutletName, out PipeNode? outlet))
+ if (!scrubber.Enabled || !_nodeContainer.TryGetNode(uid, scrubber.OutletName, out PipeNode? outlet))
return;
- var xform = Transform(uid);
-
- if (xform.GridUid == null)
+ if (args.Grid is not {} grid)
return;
- var position = _transformSystem.GetGridTilePositionOrDefault((uid,xform));
- var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true);
+ var position = _transformSystem.GetGridTilePositionOrDefault(uid);
+ var environment = _atmosphereSystem.GetTileMixture(grid, args.Map, position, true);
Scrub(timeDelta, scrubber, environment, outlet);
@@ -77,7 +68,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
return;
// Scrub adjacent tiles too.
- var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true);
+ var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(grid, position, false, true);
while (enumerator.MoveNext(out var adjacent))
{
Scrub(timeDelta, scrubber, adjacent, outlet);
diff --git a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
index e986f8f991..f9043c091a 100644
--- a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
+++ b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
@@ -47,17 +47,13 @@ namespace Content.Server.Atmos.Portable
private void OnDeviceUpdated(EntityUid uid, PortableScrubberComponent component, ref AtmosDeviceUpdateEvent args)
{
- if (!TryComp(uid, out AtmosDeviceComponent? device))
- return;
-
var timeDelta = args.dt;
if (!component.Enabled)
return;
// If we are on top of a connector port, empty into it.
- if (TryComp(uid, out var nodeContainer)
- && _nodeContainer.TryGetNode(nodeContainer, component.PortName, out PortablePipeNode? portableNode)
+ if (_nodeContainer.TryGetNode(uid, component.PortName, out PortablePipeNode? portableNode)
&& portableNode.ConnectionsEnabled)
{
_atmosphereSystem.React(component.Air, portableNode);
@@ -71,13 +67,11 @@ namespace Content.Server.Atmos.Portable
return;
}
- var xform = Transform(uid);
-
- if (xform.GridUid == null)
+ if (args.Grid is not {} grid)
return;
- var position = _transformSystem.GetGridTilePositionOrDefault((uid,xform));
- var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true);
+ var position = _transformSystem.GetGridTilePositionOrDefault(uid);
+ var environment = _atmosphereSystem.GetTileMixture(grid, args.Map, position, true);
var running = Scrub(timeDelta, component, environment);
@@ -85,8 +79,9 @@ namespace Content.Server.Atmos.Portable
// We scrub once to see if we can and set the animation
if (!running)
return;
+
// widenet
- var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true);
+ var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(grid, position, false, true);
while (enumerator.MoveNext(out var adjacent))
{
Scrub(timeDelta, component, adjacent);
@@ -98,10 +93,7 @@ namespace Content.Server.Atmos.Portable
///
private void OnAnchorChanged(EntityUid uid, PortableScrubberComponent component, ref AnchorStateChangedEvent args)
{
- if (!TryComp(uid, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, component.PortName, out PipeNode? portableNode))
+ if (!_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? portableNode))
return;
portableNode.ConnectionsEnabled = (args.Anchored && _gasPortableSystem.FindGasPortIn(Transform(uid).GridUid, Transform(uid).Coordinates, out _));
@@ -159,14 +151,10 @@ namespace Content.Server.Atmos.Portable
///
private void OnScrubberAnalyzed(EntityUid uid, PortableScrubberComponent component, GasAnalyzerScanEvent args)
{
- var gasMixDict = new Dictionary { { Name(uid), component.Air } };
+ args.GasMixtures ??= new Dictionary { { Name(uid), component.Air } };
// If it's connected to a port, include the port side
- if (TryComp(uid, out NodeContainerComponent? nodeContainer))
- {
- if (_nodeContainer.TryGetNode(nodeContainer, component.PortName, out PipeNode? port))
- gasMixDict.Add(component.PortName, port.Air);
- }
- args.GasMixtures = gasMixDict;
+ if (_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? port))
+ args.GasMixtures.Add(component.PortName, port.Air);
}
}
}
diff --git a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs
index 1631132821..fff15f696c 100644
--- a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs
+++ b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs
@@ -71,7 +71,7 @@ public sealed class SpaceHeaterSystem : EntitySystem
// If in automatic temperature mode, check if we need to adjust the heat exchange direction
if (spaceHeater.Mode == SpaceHeaterMode.Auto)
{
- var environment = _atmosphereSystem.GetContainingMixture(uid);
+ var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map);
if (environment == null)
return;
diff --git a/Content.Server/Electrocution/ElectrocutionNode.cs b/Content.Server/Electrocution/ElectrocutionNode.cs
index 7abcba7666..c8e437d353 100644
--- a/Content.Server/Electrocution/ElectrocutionNode.cs
+++ b/Content.Server/Electrocution/ElectrocutionNode.cs
@@ -9,7 +9,7 @@ namespace Content.Server.Electrocution
public sealed partial class ElectrocutionNode : Node
{
[DataField("cable")]
- public EntityUid CableEntity;
+ public EntityUid? CableEntity;
[DataField("node")]
public string? NodeName;
@@ -19,12 +19,11 @@ namespace Content.Server.Electrocution
MapGridComponent? grid,
IEntityManager entMan)
{
- var _nodeContainer = entMan.System();
-
- if (!nodeQuery.TryGetComponent(CableEntity, out var nodeContainer))
+ if (CableEntity == null || NodeName == null)
yield break;
- if (_nodeContainer.TryGetNode(nodeContainer, NodeName, out Node? node))
+ var _nodeContainer = entMan.System();
+ if (_nodeContainer.TryGetNode(CableEntity.Value, NodeName, out Node? node))
yield return node;
}
}
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs b/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs
index 8d2a699de2..7db1f513f7 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs
@@ -271,7 +271,7 @@ public sealed class ExplosionGridTileFlood : ExplosionTileFlood
var direction = (AtmosDirection) (1 << i);
if (ignoreTileBlockers || !blockedDirections.IsFlagSet(direction))
{
- ProcessNewTile(iteration, tile.Offset(direction), direction.GetOpposite());
+ ProcessNewTile(iteration, tile.Offset(direction), i.ToOppositeDir());
}
}
@@ -300,7 +300,7 @@ public sealed class ExplosionGridTileFlood : ExplosionTileFlood
var direction = (AtmosDirection) (1 << i);
if (blockedDirections.IsFlagSet(direction))
{
- list.Add((tile.Offset(direction), direction.GetOpposite()));
+ list.Add((tile.Offset(direction), i.ToOppositeDir()));
}
}
}
diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs b/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs
index f8c917c1cd..313b03e03a 100644
--- a/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs
+++ b/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs
@@ -97,7 +97,7 @@ public sealed class ExplosionSpaceTileFlood : ExplosionTileFlood
if (!unblockedDirections.IsFlagSet(direction))
continue; // explosion cannot propagate in this direction. Ever.
- ProcessNewTile(iteration, tile.Offset(direction), direction.GetOpposite());
+ ProcessNewTile(iteration, tile.Offset(direction), i.ToOppositeDir());
}
}
}
diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs
index 78034e0fc3..9e546dc33f 100644
--- a/Content.Server/Mech/Systems/MechSystem.cs
+++ b/Content.Server/Mech/Systems/MechSystem.cs
@@ -404,14 +404,17 @@ public sealed partial class MechSystem : SharedMechSystem
if (args.Handled)
return;
- if (!TryComp(component.Mech, out var mech) ||
- !TryComp(component.Mech, out var mechAir))
+ if (!TryComp(component.Mech, out MechComponent? mech))
+ return;
+
+ if (mech.Airtight && TryComp(component.Mech, out MechAirComponent? air))
{
+ args.Handled = true;
+ args.Gas = air.Air;
return;
}
- args.Gas = mech.Airtight ? mechAir.Air : _atmosphere.GetContainingMixture(component.Mech);
-
+ args.Gas = _atmosphere.GetContainingMixture(component.Mech, excite: args.Excite);
args.Handled = true;
}
diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs
index a7d12d9f0f..a949d980be 100644
--- a/Content.Server/Medical/CryoPodSystem.cs
+++ b/Content.Server/Medical/CryoPodSystem.cs
@@ -257,10 +257,7 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem
private void OnCryoPodUpdateAtmosphere(Entity entity, ref AtmosDeviceUpdateEvent args)
{
- if (!TryComp(entity, out NodeContainerComponent? nodeContainer))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PortablePipeNode? portNode))
+ if (!_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PortablePipeNode? portNode))
return;
if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir))
@@ -279,14 +276,10 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem
if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir))
return;
- var gasMixDict = new Dictionary { { Name(entity.Owner), cryoPodAir.Air } };
+ args.GasMixtures ??= new Dictionary { { Name(entity.Owner), cryoPodAir.Air } };
// If it's connected to a port, include the port side
- if (TryComp(entity, out NodeContainerComponent? nodeContainer))
- {
- if (_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PipeNode? port))
- gasMixDict.Add(entity.Comp.PortName, port.Air);
- }
- args.GasMixtures = gasMixDict;
+ if (_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PipeNode? port))
+ args.GasMixtures.Add(entity.Comp.PortName, port.Air);
}
private void OnEjected(Entity cryoPod, ref EntRemovedFromContainerMessage args)
diff --git a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs
index 99d18aeb3f..19b811a287 100644
--- a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs
+++ b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs
@@ -14,6 +14,7 @@ namespace Content.Server.NodeContainer.EntitySystems
public sealed class NodeContainerSystem : EntitySystem
{
[Dependency] private readonly NodeGroupSystem _nodeGroupSystem = default!;
+ private EntityQuery _query;
public override void Initialize()
{
@@ -26,6 +27,8 @@ namespace Content.Server.NodeContainer.EntitySystems
SubscribeLocalEvent(OnReAnchor);
SubscribeLocalEvent(OnMoveEvent);
SubscribeLocalEvent(OnExamine);
+
+ _query = GetEntityQuery();
}
public bool TryGetNode(NodeContainerComponent component, string? identifier, [NotNullWhen(true)] out T? node) where T : Node
@@ -46,6 +49,77 @@ namespace Content.Server.NodeContainer.EntitySystems
return false;
}
+ public bool TryGetNode(Entity ent, string identifier, [NotNullWhen(true)] out T? node) where T : Node
+ {
+ if (_query.Resolve(ent, ref ent.Comp, false)
+ && ent.Comp.Nodes.TryGetValue(identifier, out var n)
+ && n is T t)
+ {
+ node = t;
+ return true;
+ }
+
+ node = null;
+ return false;
+ }
+
+ public bool TryGetNodes(
+ Entity ent,
+ string id1,
+ string id2,
+ [NotNullWhen(true)] out T1? node1,
+ [NotNullWhen(true)] out T2? node2)
+ where T1 : Node
+ where T2 : Node
+ {
+ if (_query.Resolve(ent, ref ent.Comp, false)
+ && ent.Comp.Nodes.TryGetValue(id1, out var n1)
+ && n1 is T1 t1
+ && ent.Comp.Nodes.TryGetValue(id2, out var n2)
+ && n2 is T2 t2)
+ {
+ node1 = t1;
+ node2 = t2;
+ return true;
+ }
+
+ node1 = null;
+ node2 = null;
+ return false;
+ }
+
+ public bool TryGetNodes(
+ Entity ent,
+ string id1,
+ string id2,
+ string id3,
+ [NotNullWhen(true)] out T1? node1,
+ [NotNullWhen(true)] out T2? node2,
+ [NotNullWhen(true)] out T3? node3)
+ where T1 : Node
+ where T2 : Node
+ where T3 : Node
+ {
+ if (_query.Resolve(ent, ref ent.Comp, false)
+ && ent.Comp.Nodes.TryGetValue(id1, out var n1)
+ && n1 is T1 t1
+ && ent.Comp.Nodes.TryGetValue(id2, out var n2)
+ && n2 is T2 t2
+ && ent.Comp.Nodes.TryGetValue(id3, out var n3)
+ && n2 is T3 t3)
+ {
+ node1 = t1;
+ node2 = t2;
+ node3 = t3;
+ return true;
+ }
+
+ node1 = null;
+ node2 = null;
+ node3 = null;
+ return false;
+ }
+
private void OnInitEvent(EntityUid uid, NodeContainerComponent component, ComponentInit args)
{
foreach (var (key, node) in component.Nodes)
diff --git a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs
index 60f0603074..6e0e0c503a 100644
--- a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs
+++ b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs
@@ -94,7 +94,7 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem
return;
// this should always be possible, as we'll eject the gas tank when it no longer is
- var environment = _atmos.GetContainingMixture(cannon, false, true);
+ var environment = _atmos.GetContainingMixture(cannon.Owner, false, true);
var removed = _gasTank.RemoveAir(gas.Value, component.GasUsage);
if (environment != null && removed != null)
{
diff --git a/Content.Server/Power/Components/CableVisComponent.cs b/Content.Server/Power/Components/CableVisComponent.cs
index bd9c62ba80..51d68b99fd 100644
--- a/Content.Server/Power/Components/CableVisComponent.cs
+++ b/Content.Server/Power/Components/CableVisComponent.cs
@@ -4,7 +4,7 @@
public sealed partial class CableVisComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
- [DataField("node")]
- public string? Node;
+ [DataField("node", required:true)]
+ public string Node;
}
}
diff --git a/Content.Server/Power/EntitySystems/CableVisSystem.cs b/Content.Server/Power/EntitySystems/CableVisSystem.cs
index ec08523d44..1a68e87ad6 100644
--- a/Content.Server/Power/EntitySystems/CableVisSystem.cs
+++ b/Content.Server/Power/EntitySystems/CableVisSystem.cs
@@ -23,10 +23,7 @@ namespace Content.Server.Power.EntitySystems
private void UpdateAppearance(EntityUid uid, CableVisComponent cableVis, ref NodeGroupsRebuilt args)
{
- if (!TryComp(uid, out NodeContainerComponent? nodeContainer) || !TryComp(uid, out AppearanceComponent? appearance))
- return;
-
- if (!_nodeContainer.TryGetNode(nodeContainer, cableVis.Node, out var node))
+ if (!_nodeContainer.TryGetNode(uid, cableVis.Node, out CableNode? node))
return;
var transform = Transform(uid);
@@ -55,7 +52,7 @@ namespace Content.Server.Power.EntitySystems
};
}
- _appearance.SetData(uid, WireVisVisuals.ConnectedMask, mask, appearance);
+ _appearance.SetData(uid, WireVisVisuals.ConnectedMask, mask);
}
}
}
diff --git a/Content.Server/Power/Generator/GasPowerReceiverSystem.cs b/Content.Server/Power/Generator/GasPowerReceiverSystem.cs
index 76cf90c369..5f79906c99 100644
--- a/Content.Server/Power/Generator/GasPowerReceiverSystem.cs
+++ b/Content.Server/Power/Generator/GasPowerReceiverSystem.cs
@@ -26,12 +26,8 @@ public sealed class GasPowerReceiverSystem : EntitySystem
{
var timeDelta = args.dt;
- if (!HasComp(uid)
- || !TryComp(uid, out var nodeContainer)
- || !_nodeContainer.TryGetNode(nodeContainer, "pipe", out var pipe))
- {
+ if (!_nodeContainer.TryGetNode(uid, "pipe", out PipeNode? pipe))
return;
- }
// if we're below the max temperature, then we are simply consuming our target gas
if (pipe.Air.Temperature <= component.MaxTemperature)
@@ -57,7 +53,7 @@ public sealed class GasPowerReceiverSystem : EntitySystem
if (component.OffVentGas)
{
// eject the gas into the atmosphere
- var mix = _atmosphereSystem.GetContainingMixture(uid, false, true);
+ var mix = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, false, true);
if (mix is not null)
_atmosphereSystem.Merge(res, mix);
}
diff --git a/Content.Server/Spreader/SpreaderSystem.cs b/Content.Server/Spreader/SpreaderSystem.cs
index 671c281d1f..fe14d86aa1 100644
--- a/Content.Server/Spreader/SpreaderSystem.cs
+++ b/Content.Server/Spreader/SpreaderSystem.cs
@@ -231,10 +231,9 @@ public sealed class SpreaderSystem : EntitySystem
// Add the normal neighbors.
for (var i = 0; i < 4; i++)
{
- var direction = (Direction) (i * 2);
- var atmosDir = direction.ToAtmosDirection();
- var neighborPos = SharedMapSystem.GetDirection(tile, direction);
- neighborTiles.Add((comp.GridUid.Value, grid, neighborPos, atmosDir, atmosDir.GetOpposite()));
+ var atmosDir = (AtmosDirection) (1 << i);
+ var neighborPos = tile.Offset(atmosDir);
+ neighborTiles.Add((comp.GridUid.Value, grid, neighborPos, atmosDir, i.ToOppositeDir()));
}
foreach (var (neighborEnt, neighborGrid, neighborPos, ourAtmosDir, otherAtmosDir) in neighborTiles)
diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs
index a25c9d553c..09ba521aa9 100644
--- a/Content.Shared/Atmos/AtmosDirection.cs
+++ b/Content.Shared/Atmos/AtmosDirection.cs
@@ -1,4 +1,5 @@
-using System.Runtime.CompilerServices;
+using System.Numerics;
+using System.Runtime.CompilerServices;
using Robust.Shared.Serialization;
namespace Content.Shared.Atmos
@@ -15,6 +16,8 @@ namespace Content.Shared.Atmos
South = 1 << 1, // 2
East = 1 << 2, // 4
West = 1 << 3, // 8
+ // If more directions are added, note that AtmosDirectionHelpers.ToOppositeIndex() expects opposite directions
+ // to come in pairs
NorthEast = North | East, // 5
SouthEast = South | East, // 6
@@ -42,6 +45,22 @@ namespace Content.Shared.Atmos
};
}
+ ///
+ /// This returns the index that corresponds to the opposite direction of some other direction index.
+ /// I.e., 1<<OppositeIndex(i) == (1<<i).GetOpposite()
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int ToOppositeIndex(this int index)
+ {
+ return index ^ 1;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static AtmosDirection ToOppositeDir(this int index)
+ {
+ return (AtmosDirection) (1 << (index ^ 1));
+ }
+
public static Direction ToDirection(this AtmosDirection direction)
{
return direction switch
@@ -119,10 +138,11 @@ namespace Content.Shared.Atmos
return angle.GetDir().ToAtmosDirection();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ToIndex(this AtmosDirection direction)
{
// This will throw if you pass an invalid direction. Not this method's fault, but yours!
- return (int) Math.Log2((int) direction);
+ return BitOperations.Log2((uint)direction);
}
public static AtmosDirection WithFlag(this AtmosDirection direction, AtmosDirection other)
diff --git a/Content.Shared/Tools/Systems/WeldableSystem.cs b/Content.Shared/Tools/Systems/WeldableSystem.cs
index f887ed3049..b0ea68f713 100644
--- a/Content.Shared/Tools/Systems/WeldableSystem.cs
+++ b/Content.Shared/Tools/Systems/WeldableSystem.cs
@@ -15,14 +15,7 @@ public sealed class WeldableSystem : EntitySystem
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
-
- public bool IsWelded(EntityUid uid, WeldableComponent? component = null)
- {
- if (!Resolve(uid, ref component, false))
- return false;
-
- return component.IsWelded;
- }
+ private EntityQuery _query;
public override void Initialize()
{
@@ -31,6 +24,13 @@ public sealed class WeldableSystem : EntitySystem
SubscribeLocalEvent(OnWeldFinished);
SubscribeLocalEvent(OnWeldChanged);
SubscribeLocalEvent(OnExamine);
+
+ _query = GetEntityQuery();
+ }
+
+ public bool IsWelded(EntityUid uid, WeldableComponent? component = null)
+ {
+ return _query.Resolve(uid, ref component, false) && component.IsWelded;
}
private void OnExamine(EntityUid uid, WeldableComponent component, ExaminedEvent args)
@@ -49,7 +49,7 @@ public sealed class WeldableSystem : EntitySystem
private bool CanWeld(EntityUid uid, EntityUid tool, EntityUid user, WeldableComponent? component = null)
{
- if (!Resolve(uid, ref component))
+ if (!_query.Resolve(uid, ref component))
return false;
// Other component systems
@@ -63,7 +63,7 @@ public sealed class WeldableSystem : EntitySystem
private bool TryWeld(EntityUid uid, EntityUid tool, EntityUid user, WeldableComponent? component = null)
{
- if (!Resolve(uid, ref component))
+ if (!_query.Resolve(uid, ref component))
return false;
if (!CanWeld(uid, tool, user, component))
@@ -115,17 +115,13 @@ public sealed class WeldableSystem : EntitySystem
private void UpdateAppearance(EntityUid uid, WeldableComponent? component = null)
{
- if (!Resolve(uid, ref component))
- return;
-
- if (!TryComp(uid, out AppearanceComponent? appearance))
- return;
- _appearance.SetData(uid, WeldableVisuals.IsWelded, component.IsWelded, appearance);
+ if (_query.Resolve(uid, ref component))
+ _appearance.SetData(uid, WeldableVisuals.IsWelded, component.IsWelded);
}
public void SetWeldedState(EntityUid uid, bool state, WeldableComponent? component = null)
{
- if (!Resolve(uid, ref component))
+ if (!_query.Resolve(uid, ref component))
return;
if (component.IsWelded == state)
@@ -141,7 +137,7 @@ public sealed class WeldableSystem : EntitySystem
public void SetWeldingTime(EntityUid uid, TimeSpan time, WeldableComponent? component = null)
{
- if (!Resolve(uid, ref component))
+ if (!_query.Resolve(uid, ref component))
return;
if (component.WeldingTime.Equals(time))
diff --git a/Resources/Prototypes/Entities/Virtual/electrocution.yml b/Resources/Prototypes/Entities/Virtual/electrocution.yml
index 497071ee93..ac65245191 100644
--- a/Resources/Prototypes/Entities/Virtual/electrocution.yml
+++ b/Resources/Prototypes/Entities/Virtual/electrocution.yml
@@ -1,7 +1,7 @@
# Special entity used to attach to power networks as load when somebody gets electrocuted.
- type: entity
id: VirtualElectrocutionLoadBase
- noSpawn: true
+ abstract: true
components:
- type: Electrocution
- type: Icon
From 9ddfe38668a263d0d9dc7230727cb55b9ab9e283 Mon Sep 17 00:00:00 2001
From: liltenhead <104418166+liltenhead@users.noreply.github.com>
Date: Fri, 29 Mar 2024 21:36:33 -0700
Subject: [PATCH 23/26] Adjust syndicate hardbomb damage (#26548)
hardbomb tweaks
---
Resources/Prototypes/explosion.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Resources/Prototypes/explosion.yml b/Resources/Prototypes/explosion.yml
index a768dead6d..4f72067376 100644
--- a/Resources/Prototypes/explosion.yml
+++ b/Resources/Prototypes/explosion.yml
@@ -110,9 +110,9 @@
Blunt: 15
Piercing: 6
Structural: 40
- tileBreakChance: [ 0.75, 0.95, 1 ]
- tileBreakIntensity: [ 1, 10, 15 ]
- tileBreakRerollReduction: 30
+ tileBreakChance: [ 0, 0.5, 1 ]
+ tileBreakIntensity: [ 0, 10, 30 ]
+ tileBreakRerollReduction: 10
intensityPerState: 20
lightColor: Orange
texturePath: /Textures/Effects/fire.rsi
From 0f6c7c9d51f81c01dba3a5047ce5e78acdc5bba5 Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 04:37:39 +0000
Subject: [PATCH 24/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 8c70fdc638..4429f2be05 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: Alekshhh
- changes:
- - message: Cerberus now has a wideswing that works similarly to spears.
- type: Tweak
- id: 5759
- time: '2024-01-20T23:38:27.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24328
- author: TheShuEd
changes:
- message: Added new Floral anomaly!
@@ -3793,3 +3786,11 @@
id: 6258
time: '2024-03-30T04:00:21.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25830
+- author: liltenhead
+ changes:
+ - message: Changed the syndicate hardbomb to have less of a chance to completely
+ destroy tiles.
+ type: Tweak
+ id: 6259
+ time: '2024-03-30T04:36:33.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/26548
From 97b390d35f503dd9bda35e0b3a6192b2a502d120 Mon Sep 17 00:00:00 2001
From: takemysoult <143123247+takemysoult@users.noreply.github.com>
Date: Sat, 30 Mar 2024 09:52:27 +0300
Subject: [PATCH 25/26] up stimulants (no sleep) (#25886)
* up stimulants (no sleep)
* Update SharedSleepingSystem.cs
---
Content.Shared/Bed/Sleep/SharedSleepingSystem.cs | 2 +-
Resources/Prototypes/Reagents/narcotics.yml | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs b/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs
index 4e4bc2c574..c6248c88f7 100644
--- a/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs
+++ b/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs
@@ -37,7 +37,7 @@ namespace Content.Server.Bed.Sleep
_actionsSystem.AddAction(uid, ref component.WakeAction, WakeActionId, uid);
// TODO remove hardcoded time.
- _actionsSystem.SetCooldown(component.WakeAction, _gameTiming.CurTime, _gameTiming.CurTime + TimeSpan.FromSeconds(15));
+ _actionsSystem.SetCooldown(component.WakeAction, _gameTiming.CurTime, _gameTiming.CurTime + TimeSpan.FromSeconds(2f));
}
private void OnShutdown(EntityUid uid, SleepingComponent component, ComponentShutdown args)
diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml
index d05cc29ab0..cefc8043b0 100644
--- a/Resources/Prototypes/Reagents/narcotics.yml
+++ b/Resources/Prototypes/Reagents/narcotics.yml
@@ -116,6 +116,13 @@
damage:
types:
Poison: 1
+ - !type:AdjustReagent
+ conditions:
+ - !type:ReagentThreshold
+ reagent: ChloralHydrate
+ min: 1
+ reagent: ChloralHydrate
+ amount: -10
- !type:GenericStatusEffect
key: Stun
time: 3
@@ -129,6 +136,10 @@
component: StaminaModifier
time: 3
type: Add
+ - !type:GenericStatusEffect
+ key: ForcedSleep
+ time: 3
+ type: Remove
Medicine:
metabolismRate: 1.0
effects:
From 1e51febc67fdd010a286f170bf47d6b7e7445a4e Mon Sep 17 00:00:00 2001
From: PJBot
Date: Sat, 30 Mar 2024 06:53:32 +0000
Subject: [PATCH 26/26] Automatic changelog update
---
Resources/Changelog/Changelog.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 4429f2be05..136f7054ef 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -1,11 +1,4 @@
Entries:
-- author: TheShuEd
- changes:
- - message: Added new Floral anomaly!
- type: Add
- id: 5760
- time: '2024-01-21T01:31:12.0000000+00:00'
- url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24351
- author: Menshin
changes:
- message: The PA control box should now properly detect the PA parts in all situations
@@ -3794,3 +3787,10 @@
id: 6259
time: '2024-03-30T04:36:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26548
+- author: takemysoult
+ changes:
+ - message: stimulants removes chloral hydrate from body
+ type: Tweak
+ id: 6260
+ time: '2024-03-30T06:52:27.0000000+00:00'
+ url: https://github.com/space-wizards/space-station-14/pull/25886