diff --git a/Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs b/Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs
index aaf3900beee..235e7b0fef9 100644
--- a/Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs
+++ b/Content.Client/CartridgeLoader/Cartridges/LogProbeUi.cs
@@ -1,4 +1,5 @@
using Content.Client.UserInterface.Fragments;
+using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges;
using Robust.Client.UserInterface;
@@ -13,16 +14,23 @@ public sealed partial class LogProbeUi : UIFragment
return _fragment!;
}
- public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
+ public override void Setup(BoundUserInterface ui, EntityUid? fragmentOwner)
{
_fragment = new LogProbeUiFragment();
+
+ _fragment.OnPrintPressed += () =>
+ {
+ var ev = new LogProbePrintMessage();
+ var message = new CartridgeUiMessage(ev);
+ ui.SendMessage(message);
+ };
}
public override void UpdateState(BoundUserInterfaceState state)
{
- if (state is not LogProbeUiState logProbeUiState)
+ if (state is not LogProbeUiState cast)
return;
- _fragment?.UpdateState(logProbeUiState); // DeltaV - just take the state
+ _fragment?.UpdateState(cast); // DeltaV - just take the state
}
}
diff --git a/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml b/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml
index a0769590e91..6c2fdb25262 100644
--- a/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml
+++ b/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml
@@ -38,4 +38,9 @@
+
+
+
+
+
diff --git a/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs
index ed3c9236e68..979f06d31ca 100644
--- a/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs
+++ b/Content.Client/CartridgeLoader/Cartridges/LogProbeUiFragment.xaml.cs
@@ -11,9 +11,16 @@ namespace Content.Client.CartridgeLoader.Cartridges;
[GenerateTypedNameReferences]
public sealed partial class LogProbeUiFragment : BoxContainer
{
+ ///
+ /// Action invoked when the print button gets pressed.
+ ///
+ public Action? OnPrintPressed;
+
public LogProbeUiFragment()
{
RobustXamlLoader.Load(this);
+
+ PrintButton.OnPressed += _ => OnPrintPressed?.Invoke();
}
// DeltaV begin - Update to handle both types of data
@@ -29,8 +36,7 @@ public sealed partial class LogProbeUiFragment : BoxContainer
else
{
SetupAccessLogView();
- if (state.PulledLogs.Count > 0)
- DisplayAccessLogs(state.PulledLogs);
+ DisplayAccessLogs(state.EntityName, state.PulledLogs);
}
}
@@ -120,12 +126,17 @@ public sealed partial class LogProbeUiFragment : BoxContainer
// DeltaV end
// DeltaV - Handle this in a separate method
- private void DisplayAccessLogs(List logs)
+ private void DisplayAccessLogs(string name, List logs)
{
//Reverse the list so the oldest entries appear at the bottom
logs.Reverse();
- var count = 1;
+ EntityName.Text = name;
+ PrintButton.Disabled = string.IsNullOrEmpty(name);
+
+ ProbedDeviceContainer.RemoveAllChildren();
+
+ var count = 1;
foreach (var log in logs)
{
AddAccessLog(log, count);
diff --git a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
index 3ef7f0ae73e..793c4694832 100644
--- a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
@@ -36,10 +36,6 @@ namespace Content.Client.Chemistry.UI
new ItemSlotButtonPressedEvent(SharedChemMaster.InputSlotName));
_window.OutputEjectButton.OnPressed += _ => SendMessage(
new ItemSlotButtonPressedEvent(SharedChemMaster.OutputSlotName));
- _window.BufferTransferButton.OnPressed += _ => SendMessage(
- new ChemMasterSetModeMessage(ChemMasterMode.Transfer));
- _window.BufferDiscardButton.OnPressed += _ => SendMessage(
- new ChemMasterSetModeMessage(ChemMasterMode.Discard));
_window.CreatePillButton.OnPressed += _ => SendMessage(
new ChemMasterCreatePillsMessage(
(uint) _window.PillDosage.Value, (uint) _window.PillNumber.Value, _window.LabelLine));
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
index b1f4f5917f4..04ee58f10c2 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
@@ -30,12 +30,7 @@
-
-
-
-
-
-
+
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
index 20c61f10cb8..e731f3a1145 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
@@ -205,9 +205,6 @@ namespace Content.Client.Chemistry.UI
/// State data for the dispenser.
private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
{
- BufferTransferButton.Pressed = state.Mode == ChemMasterMode.Transfer;
- BufferDiscardButton.Pressed = state.Mode == ChemMasterMode.Discard;
-
BuildContainerUI(InputContainerInfo, state.InputContainerInfo, true);
BuildContainerUI(OutputContainerInfo, state.OutputContainerInfo, false);
diff --git a/Content.Server/Access/Systems/IdCardSystem.cs b/Content.Server/Access/Systems/IdCardSystem.cs
index aeb4cc163fb..e379f7fb2af 100644
--- a/Content.Server/Access/Systems/IdCardSystem.cs
+++ b/Content.Server/Access/Systems/IdCardSystem.cs
@@ -1,6 +1,6 @@
using System.Linq;
using Content.Server.Administration.Logs;
-using Content.Server.Kitchen.Components;
+using Content.Shared.Kitchen.Components;
using Content.Server.Popups;
using Content.Shared.Access;
using Content.Shared.Access.Components;
@@ -31,7 +31,7 @@ public sealed class IdCardSystem : SharedIdCardSystem
private void OnMicrowaved(EntityUid uid, IdCardComponent component, BeingMicrowavedEvent args)
{
if (!component.CanMicrowave || !TryComp(args.Microwave, out var micro) || micro.Broken)
- return;
+ return;
if (TryComp(uid, out var access))
{
diff --git a/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs b/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs
index f5fbb811c39..c48cf11e5b5 100644
--- a/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs
+++ b/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeComponent.cs
@@ -1,13 +1,22 @@
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Shared._DV.CartridgeLoader.Cartridges; // DeltaV
+using Content.Shared.Paper;
using Robust.Shared.Audio;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.CartridgeLoader.Cartridges;
-[RegisterComponent]
-[Access(typeof(LogProbeCartridgeSystem))]
+[RegisterComponent, Access(typeof(LogProbeCartridgeSystem))]
+[AutoGenerateComponentPause]
public sealed partial class LogProbeCartridgeComponent : Component
{
+ ///
+ /// The name of the scanned entity, sent to clients when they open the UI.
+ ///
+ [DataField]
+ public string EntityName = string.Empty;
+
///
/// The list of pulled access logs
///
@@ -25,4 +34,25 @@ public sealed partial class LogProbeCartridgeComponent : Component
///
[DataField]
public NanoChatData? ScannedNanoChatData;
+
+ ///
+ /// Paper to spawn when printing logs.
+ ///
+ [DataField]
+ public EntProtoId PaperPrototype = "PaperAccessLogs";
+
+ [DataField]
+ public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/diagnoser_printing.ogg");
+
+ ///
+ /// How long you have to wait before printing logs again.
+ ///
+ [DataField]
+ public TimeSpan PrintCooldown = TimeSpan.FromSeconds(5);
+
+ ///
+ /// When anyone is allowed to spawn another printout.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
+ public TimeSpan NextPrintAllowed = TimeSpan.Zero;
}
diff --git a/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs b/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs
index 658c0649bbd..b8c1cb3f665 100644
--- a/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs
+++ b/Content.Server/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.cs
@@ -1,27 +1,42 @@
using Content.Shared.Access.Components;
+using Content.Shared.Administration.Logs;
using Content.Shared.Audio;
using Content.Shared.CartridgeLoader;
using Content.Shared.CartridgeLoader.Cartridges;
using Content.Shared._DV.NanoChat; // DeltaV
+using Content.Shared.Database;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Labels.EntitySystems;
+using Content.Shared.Paper;
using Content.Shared.Popups;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Random;
+using Robust.Shared.Timing;
+using System.Text;
namespace Content.Server.CartridgeLoader.Cartridges;
public sealed partial class LogProbeCartridgeSystem : EntitySystem // DeltaV - Made partial
{
+ [Dependency] private readonly CartridgeLoaderSystem _cartridge = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
- [Dependency] private readonly CartridgeLoaderSystem? _cartridgeLoaderSystem = default!;
- [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
- [Dependency] private readonly SharedAudioSystem _audioSystem = default!;
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly SharedLabelSystem _label = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+ [Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly PaperSystem _paper = default!;
public override void Initialize()
{
base.Initialize();
InitializeNanoChat(); // DeltaV
+
SubscribeLocalEvent(OnUiReady);
SubscribeLocalEvent(AfterInteract);
+ SubscribeLocalEvent(OnMessage);
}
///
@@ -48,9 +63,10 @@ public sealed partial class LogProbeCartridgeSystem : EntitySystem // DeltaV - M
return;
//Play scanning sound with slightly randomized pitch
- _audioSystem.PlayEntity(ent.Comp.SoundScan, args.InteractEvent.User, target, AudioHelpers.WithVariation(0.25f, _random));
- _popupSystem.PopupCursor(Loc.GetString("log-probe-scan", ("device", target)), args.InteractEvent.User);
+ _audio.PlayEntity(ent.Comp.SoundScan, args.InteractEvent.User, target, AudioHelpers.WithVariation(0.25f, _random));
+ _popup.PopupCursor(Loc.GetString("log-probe-scan", ("device", target)), args.InteractEvent.User);
+ ent.Comp.EntityName = Name(target);
ent.Comp.PulledAccessLogs.Clear();
ent.Comp.ScannedNanoChatData = null; // DeltaV - Clear any previous NanoChat data
@@ -64,6 +80,9 @@ public sealed partial class LogProbeCartridgeSystem : EntitySystem // DeltaV - M
ent.Comp.PulledAccessLogs.Add(log);
}
+ // Reverse the list so the oldest is at the bottom
+ ent.Comp.PulledAccessLogs.Reverse();
+
UpdateUiState(ent, args.Loader);
}
@@ -75,9 +94,49 @@ public sealed partial class LogProbeCartridgeSystem : EntitySystem // DeltaV - M
UpdateUiState(ent, args.Loader);
}
+ private void OnMessage(Entity ent, ref CartridgeMessageEvent args)
+ {
+ if (args is LogProbePrintMessage cast)
+ PrintLogs(ent, cast.Actor);
+ }
+
+ private void PrintLogs(Entity ent, EntityUid user)
+ {
+ if (string.IsNullOrEmpty(ent.Comp.EntityName))
+ return;
+
+ if (_timing.CurTime < ent.Comp.NextPrintAllowed)
+ return;
+
+ ent.Comp.NextPrintAllowed = _timing.CurTime + ent.Comp.PrintCooldown;
+
+ var paper = Spawn(ent.Comp.PaperPrototype, _transform.GetMapCoordinates(user));
+ _label.Label(paper, ent.Comp.EntityName); // label it for easy identification
+
+ _audio.PlayEntity(ent.Comp.PrintSound, user, paper);
+ _hands.PickupOrDrop(user, paper, checkActionBlocker: false);
+
+ // generate the actual printout text
+ var builder = new StringBuilder();
+ builder.AppendLine(Loc.GetString("log-probe-printout-device", ("name", ent.Comp.EntityName)));
+ builder.AppendLine(Loc.GetString("log-probe-printout-header"));
+ var number = 1;
+ foreach (var log in ent.Comp.PulledAccessLogs)
+ {
+ var time = TimeSpan.FromSeconds(Math.Truncate(log.Time.TotalSeconds)).ToString();
+ builder.AppendLine(Loc.GetString("log-probe-printout-entry", ("number", number), ("time", time), ("accessor", log.Accessor)));
+ number++;
+ }
+
+ var paperComp = Comp(paper);
+ _paper.SetContent((paper, paperComp), builder.ToString());
+
+ _adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):user} printed out LogProbe logs ({paper}) of {ent.Comp.EntityName}");
+ }
+
private void UpdateUiState(Entity ent, EntityUid loaderUid)
{
- var state = new LogProbeUiState(ent.Comp.PulledAccessLogs, ent.Comp.ScannedNanoChatData); // DeltaV - NanoChat support
- _cartridgeLoaderSystem?.UpdateCartridgeUiState(loaderUid, state);
+ var state = new LogProbeUiState(ent.Comp.EntityName, ent.Comp.PulledAccessLogs, ent.Comp.ScannedNanoChatData); // DeltaV - NanoChat support
+ _cartridge.UpdateCartridgeUiState(loaderUid, state);
}
}
diff --git a/Content.Server/Chemistry/Components/ChemMasterComponent.cs b/Content.Server/Chemistry/Components/ChemMasterComponent.cs
index 9578755ba76..08e26a5392e 100644
--- a/Content.Server/Chemistry/Components/ChemMasterComponent.cs
+++ b/Content.Server/Chemistry/Components/ChemMasterComponent.cs
@@ -15,9 +15,6 @@ namespace Content.Server.Chemistry.Components
[DataField("pillType"), ViewVariables(VVAccess.ReadWrite)]
public uint PillType = 0;
- [DataField("mode"), ViewVariables(VVAccess.ReadWrite)]
- public ChemMasterMode Mode = ChemMasterMode.Transfer;
-
[DataField("pillDosageLimit", required: true), ViewVariables(VVAccess.ReadWrite)]
public uint PillDosageLimit;
diff --git a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
index c733c7215ee..567fafb82ee 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
@@ -52,7 +52,6 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent(SubscribeUpdateUiState);
SubscribeLocalEvent(SubscribeUpdateUiState);
- SubscribeLocalEvent(OnSetModeMessage);
SubscribeLocalEvent(OnSetPillTypeMessage);
SubscribeLocalEvent(OnReagentButtonMessage);
SubscribeLocalEvent(OnCreatePillsMessage);
@@ -76,23 +75,12 @@ namespace Content.Server.Chemistry.EntitySystems
var bufferCurrentVolume = bufferSolution.Volume;
var state = new ChemMasterBoundUserInterfaceState(
- chemMaster.Mode, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
+ BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
bufferReagents, bufferCurrentVolume, chemMaster.PillType, chemMaster.PillDosageLimit, updateLabel);
_userInterfaceSystem.SetUiState(owner, ChemMasterUiKey.Key, state);
}
- private void OnSetModeMessage(Entity chemMaster, ref ChemMasterSetModeMessage message)
- {
- // Ensure the mode is valid, either Transfer or Discard.
- if (!Enum.IsDefined(typeof(ChemMasterMode), message.ChemMasterMode))
- return;
-
- chemMaster.Comp.Mode = message.ChemMasterMode;
- UpdateUiState(chemMaster);
- ClickSound(chemMaster);
- }
-
private void OnSetPillTypeMessage(Entity chemMaster, ref ChemMasterSetPillTypeMessage message)
{
// Ensure valid pill type. There are 20 pills selectable, 0-19.
@@ -110,19 +98,7 @@ namespace Content.Server.Chemistry.EntitySystems
if (!Enum.IsDefined(typeof(ChemMasterReagentAmount), message.Amount))
return;
- switch (chemMaster.Comp.Mode)
- {
- case ChemMasterMode.Transfer:
- TransferReagents(chemMaster, message.ReagentId, message.Amount.GetFixedPoint(), message.FromBuffer);
- break;
- case ChemMasterMode.Discard:
- DiscardReagents(chemMaster, message.ReagentId, message.Amount.GetFixedPoint(), message.FromBuffer);
- break;
- default:
- // Invalid mode.
- return;
- }
-
+ TransferReagents(chemMaster, message.ReagentId, message.Amount.GetFixedPoint(), message.FromBuffer);
ClickSound(chemMaster);
}
@@ -152,30 +128,6 @@ namespace Content.Server.Chemistry.EntitySystems
UpdateUiState(chemMaster, updateLabel: true);
}
- private void DiscardReagents(Entity chemMaster, ReagentId id, FixedPoint2 amount, bool fromBuffer)
- {
- if (fromBuffer)
- {
- if (_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
- bufferSolution.RemoveReagent(id, amount, preserveOrder: true);
- else
- return;
- }
- else
- {
- var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
- if (container is not null &&
- _solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, out _))
- {
- _solutionContainerSystem.RemoveReagent(containerSolution.Value, id, amount);
- }
- else
- return;
- }
-
- UpdateUiState(chemMaster, updateLabel: fromBuffer);
- }
-
private void OnCreatePillsMessage(Entity chemMaster, ref ChemMasterCreatePillsMessage message)
{
var user = message.Actor;
diff --git a/Content.Server/Forensics/Systems/FingerprintMaskSystem.cs b/Content.Server/Forensics/Systems/FingerprintMaskSystem.cs
new file mode 100644
index 00000000000..bdfbcee0aa2
--- /dev/null
+++ b/Content.Server/Forensics/Systems/FingerprintMaskSystem.cs
@@ -0,0 +1,20 @@
+using Content.Shared.Forensics;
+using Content.Shared.Inventory;
+
+namespace Content.Server.Forensics;
+
+public sealed class FingerprintMaskSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent>(OnTryAccessFingerprint);
+ }
+
+ private void OnTryAccessFingerprint(EntityUid uid, FingerprintMaskComponent comp, ref InventoryRelayedEvent args)
+ {
+ args.Args.Blocker = uid;
+ args.Args.Cancel();
+ }
+}
diff --git a/Content.Server/Forensics/Systems/ForensicPadSystem.cs b/Content.Server/Forensics/Systems/ForensicPadSystem.cs
index a3f5627cdba..40f9ef1d1cf 100644
--- a/Content.Server/Forensics/Systems/ForensicPadSystem.cs
+++ b/Content.Server/Forensics/Systems/ForensicPadSystem.cs
@@ -19,6 +19,7 @@ namespace Content.Server.Forensics
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly LabelSystem _label = default!;
+ [Dependency] private readonly ForensicsSystem _forensics = default!;
public override void Initialize()
{
@@ -58,9 +59,14 @@ namespace Content.Server.Forensics
return;
}
- if (_inventory.TryGetSlotEntity(args.Target.Value, "gloves", out var gloves))
+ if (!_forensics.CanAccessFingerprint(args.Target.Value, out var blocker))
{
- _popupSystem.PopupEntity(Loc.GetString("forensic-pad-gloves", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.Target.Value, args.User);
+
+ if (blocker is { } item)
+ _popupSystem.PopupEntity(Loc.GetString("forensic-pad-no-access-due", ("entity", Identity.Entity(item, EntityManager))), args.Target.Value, args.User);
+ else
+ _popupSystem.PopupEntity(Loc.GetString("forensic-pad-no-access"), args.Target.Value, args.User);
+
return;
}
diff --git a/Content.Server/Forensics/Systems/ForensicsSystem.cs b/Content.Server/Forensics/Systems/ForensicsSystem.cs
index 2f9709015ca..aa1e0c76bc8 100644
--- a/Content.Server/Forensics/Systems/ForensicsSystem.cs
+++ b/Content.Server/Forensics/Systems/ForensicsSystem.cs
@@ -304,11 +304,9 @@ namespace Content.Server.Forensics
component.Fibers.Add(fiberLocale + " ; " + fiber.Fiberprint);
}
// End of DeltaV code
-
- if (HasComp(gloves))
- return;
}
- if (TryComp(user, out var fingerprint))
+
+ if (TryComp(user, out var fingerprint) && CanAccessFingerprint(user, out var _))
component.Fingerprints.Add(fingerprint.Fingerprint ?? "");
}
@@ -337,6 +335,23 @@ namespace Content.Server.Forensics
}
}
+ ///
+ /// Checks if there's an access to the fingerprint of the target entity.
+ ///
+ /// The entity with the fingerprint
+ /// The entity that blocked accessing the fingerprint
+ public bool CanAccessFingerprint(EntityUid target, out EntityUid? blocker)
+ {
+ var ev = new TryAccessFingerprintEvent();
+
+ RaiseLocalEvent(target, ev);
+ if (!ev.Cancelled && TryComp(target, out var inv))
+ _inventory.RelayEvent((target, inv), ev);
+
+ blocker = ev.Blocker;
+ return !ev.Cancelled;
+ }
+
#endregion
}
}
diff --git a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs
index 1ac02ac8825..d0577af40eb 100644
--- a/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs
+++ b/Content.Server/Kitchen/EntitySystems/MicrowaveSystem.cs
@@ -519,7 +519,7 @@ namespace Content.Server.Kitchen.EntitySystems
foreach (var item in component.Storage.ContainedEntities.ToArray())
{
// special behavior when being microwaved ;)
- var ev = new BeingMicrowavedEvent(uid, user);
+ var ev = new BeingMicrowavedEvent(uid, user, component.CurrentCookTimerTime);
RaiseLocalEvent(item, ev);
if (ev.Handled)
diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs
index 0cdb0bc29a2..a2201d6f38f 100644
--- a/Content.Server/PAI/PAISystem.cs
+++ b/Content.Server/PAI/PAISystem.cs
@@ -1,7 +1,7 @@
using Content.Server.Ghost.Roles;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Instruments;
-using Content.Server.Kitchen.Components;
+using Content.Shared.Kitchen.Components;
using Content.Shared.Interaction.Events;
using Content.Shared.Mind.Components;
using Content.Shared.PAI;
diff --git a/Content.Server/Power/EntitySystems/RiggableSystem.cs b/Content.Server/Power/EntitySystems/RiggableSystem.cs
index 26eaca80fe7..758aef037ed 100644
--- a/Content.Server/Power/EntitySystems/RiggableSystem.cs
+++ b/Content.Server/Power/EntitySystems/RiggableSystem.cs
@@ -1,6 +1,6 @@
using Content.Server.Administration.Logs;
using Content.Server.Explosion.EntitySystems;
-using Content.Server.Kitchen.Components;
+using Content.Shared.Kitchen.Components;
using Content.Server.Power.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Database;
diff --git a/Content.Server/PowerCell/PowerCellSystem.cs b/Content.Server/PowerCell/PowerCellSystem.cs
index f7b4cf02491..e78f3a597f8 100644
--- a/Content.Server/PowerCell/PowerCellSystem.cs
+++ b/Content.Server/PowerCell/PowerCellSystem.cs
@@ -6,7 +6,7 @@ using Content.Shared.PowerCell.Components;
using Content.Shared.Rounding;
using Robust.Shared.Containers;
using System.Diagnostics.CodeAnalysis;
-using Content.Server.Kitchen.Components;
+using Content.Shared.Kitchen.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.UserInterface;
using Content.Shared.Containers.ItemSlots;
diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMicrowaveTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMicrowaveTriggerSystem.cs
index ca61c8f8ab3..2fbd6505d65 100644
--- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMicrowaveTriggerSystem.cs
+++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactMicrowaveTriggerSystem.cs
@@ -1,4 +1,4 @@
-using Content.Server.Kitchen.Components;
+using Content.Shared.Kitchen.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs
index 852e3182c3c..d2b12fde142 100644
--- a/Content.Server/Zombies/ZombieSystem.Transform.cs
+++ b/Content.Server/Zombies/ZombieSystem.Transform.cs
@@ -26,6 +26,7 @@ using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Systems;
+using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;
using Content.Shared.Nutrition.AnimalHusbandry;
using Content.Shared.Nutrition.Components;
@@ -232,6 +233,7 @@ public sealed partial class ZombieSystem
_faction.ClearFactions(target, dirty: false);
_faction.AddFaction(target, "Zombie");
+ EnsureComp(target); // prevent shitters biting other zombies
//gives it the funny "Zombie ___" name.
_nameMod.RefreshNameModifiers(target);
diff --git a/Content.Server/Zombies/ZombieSystem.cs b/Content.Server/Zombies/ZombieSystem.cs
index ec50e11a0ca..47f185cf7d4 100644
--- a/Content.Server/Zombies/ZombieSystem.cs
+++ b/Content.Server/Zombies/ZombieSystem.cs
@@ -226,12 +226,10 @@ namespace Content.Server.Zombies
private void OnMeleeHit(EntityUid uid, ZombieComponent component, MeleeHitEvent args)
{
+ // this prevents a player using a zombie mouse as a weapon to infect people
if (!TryComp(args.User, out _))
return;
- if (!args.HitEntities.Any())
- return;
-
foreach (var entity in args.HitEntities)
{
if (args.User == entity)
@@ -240,20 +238,14 @@ namespace Content.Server.Zombies
if (!TryComp(entity, out var mobState))
continue;
- if (HasComp(entity))
+ var canZombify = !HasComp(entity) && !HasComp(entity);
+ if (canZombify && !HasComp(args.User) && _random.Prob(GetZombieInfectionChance(entity, component)))
{
- args.BonusDamage = -args.BaseDamage;
- }
- else
- {
- if (!HasComp(entity) && !HasComp(args.User) && _random.Prob(GetZombieInfectionChance(entity, component)))
- {
- EnsureComp(entity);
- EnsureComp(entity);
- }
+ EnsureComp(entity);
+ EnsureComp(entity);
}
- if (_mobState.IsIncapacitated(entity, mobState) && !HasComp(entity) && !HasComp(entity))
+ if (_mobState.IsIncapacitated(entity, mobState) && canZombify)
{
ZombifyEntity(entity);
args.BonusDamage = -args.BaseDamage;
diff --git a/Content.Server/_DV/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs b/Content.Server/_DV/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs
index b340cbfd793..2ad8bd85194 100644
--- a/Content.Server/_DV/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs
+++ b/Content.Server/_DV/CartridgeLoader/Cartridges/LogProbeCartridgeSystem.NanoChat.cs
@@ -62,11 +62,11 @@ public sealed partial class LogProbeCartridgeSystem
EntityUid target,
NanoChatCardComponent card)
{
- _audioSystem.PlayEntity(ent.Comp.SoundScan,
+ _audio.PlayEntity(ent.Comp.SoundScan,
args.InteractEvent.User,
target,
AudioHelpers.WithVariation(0.25f, _random));
- _popupSystem.PopupCursor(Loc.GetString("log-probe-scan-nanochat", ("card", target)), args.InteractEvent.User);
+ _popup.PopupCursor(Loc.GetString("log-probe-scan-nanochat", ("card", target)), args.InteractEvent.User);
ent.Comp.PulledAccessLogs.Clear();
diff --git a/Content.Server/_DV/NanoChat/NanoChatSystem.cs b/Content.Server/_DV/NanoChat/NanoChatSystem.cs
index 54fe8377d0f..7d04d2f9180 100644
--- a/Content.Server/_DV/NanoChat/NanoChatSystem.cs
+++ b/Content.Server/_DV/NanoChat/NanoChatSystem.cs
@@ -1,11 +1,11 @@
using System.Linq;
using Content.Server.Access.Systems;
using Content.Server.Administration.Logs;
-using Content.Server.Kitchen.Components;
using Content.Server.NameIdentifier;
using Content.Shared.Database;
using Content.Shared._DV.CartridgeLoader.Cartridges;
using Content.Shared._DV.NanoChat;
+using Content.Shared.Kitchen.Components;
using Content.Shared.NameIdentifier;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
diff --git a/Content.Shared/CartridgeLoader/Cartridges/LogProbePrintMessage.cs b/Content.Shared/CartridgeLoader/Cartridges/LogProbePrintMessage.cs
new file mode 100644
index 00000000000..50097422fb5
--- /dev/null
+++ b/Content.Shared/CartridgeLoader/Cartridges/LogProbePrintMessage.cs
@@ -0,0 +1,6 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.CartridgeLoader.Cartridges;
+
+[Serializable, NetSerializable]
+public sealed class LogProbePrintMessage : CartridgeMessageEvent;
diff --git a/Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs b/Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs
index b35a35f0154..2428507bb14 100644
--- a/Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs
+++ b/Content.Shared/CartridgeLoader/Cartridges/LogProbeUiState.cs
@@ -6,6 +6,11 @@ namespace Content.Shared.CartridgeLoader.Cartridges;
[Serializable, NetSerializable]
public sealed class LogProbeUiState : BoundUserInterfaceState
{
+ ///
+ /// The name of the scanned entity.
+ ///
+ public string EntityName;
+
///
/// The list of probed network devices
///
@@ -16,8 +21,9 @@ public sealed class LogProbeUiState : BoundUserInterfaceState
///
public NanoChatData? NanoChatData { get; }
- public LogProbeUiState(List pulledLogs, NanoChatData? nanoChatData = null) // DeltaV - NanoChat support
+ public LogProbeUiState(string entityName, List pulledLogs, NanoChatData? nanoChatData = null) // DeltaV - NanoChat support
{
+ EntityName = entityName;
PulledLogs = pulledLogs;
NanoChatData = nanoChatData; // DeltaV
}
diff --git a/Content.Shared/Chemistry/Components/RehydratableComponent.cs b/Content.Shared/Chemistry/Components/RehydratableComponent.cs
index 00599498e42..440de5413f3 100644
--- a/Content.Shared/Chemistry/Components/RehydratableComponent.cs
+++ b/Content.Shared/Chemistry/Components/RehydratableComponent.cs
@@ -19,6 +19,12 @@ public sealed partial class RehydratableComponent : Component
[DataField("catalyst")]
public ProtoId CatalystPrototype = "Water";
+ ///
+ /// The type of solution it is attached to
+ ///
+ [DataField]
+ public String SolutionName = "cube";
+
///
/// The minimum amount of catalyst that must be present to be hydrated.
///
diff --git a/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs b/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs
index 0f5d51057f2..b75d9aa6896 100644
--- a/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs
+++ b/Content.Shared/Chemistry/EntitySystems/RehydratableSystem.cs
@@ -5,6 +5,8 @@ using Content.Shared.FixedPoint;
using Content.Shared.Popups;
using Robust.Shared.Network;
using Robust.Shared.Random;
+using Content.Shared.Examine;
+using Content.Shared.Kitchen.Components;
namespace Content.Shared.Chemistry.EntitySystems;
@@ -22,6 +24,8 @@ public sealed class RehydratableSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnSolutionChange);
+ SubscribeLocalEvent(OnExamine);
+ SubscribeLocalEvent(OnMicrowaved);
}
private void OnSolutionChange(Entity ent, ref SolutionContainerChangedEvent args)
@@ -34,6 +38,26 @@ public sealed class RehydratableSystem : EntitySystem
}
}
+ private void OnMicrowaved(EntityUid uid, RehydratableComponent component, BeingMicrowavedEvent args)
+ {
+ if(args.Time <= 0)
+ return;
+ if (!_solutions.TryGetSolution(uid, component.SolutionName, out _, out var solution))
+ return;
+ solution.RemoveAllSolution();
+ }
+
+ private void OnExamine(EntityUid uid, RehydratableComponent component, ExaminedEvent args)
+ {
+ if (!_solutions.TryGetSolution(uid, component.SolutionName, out _, out var solution))
+ return;
+ // This will only be true if an incorrect reagent has been added to the cube
+ if (solution.Volume == solution.MaxVolume)
+ {
+ args.PushMarkup(Loc.GetString("rehydratable-component-soaked-message"));
+ }
+ }
+
// Try not to make this public if you can help it.
private void Expand(Entity ent)
{
diff --git a/Content.Shared/Chemistry/SharedChemMaster.cs b/Content.Shared/Chemistry/SharedChemMaster.cs
index 762131d7612..f1cbc72bb78 100644
--- a/Content.Shared/Chemistry/SharedChemMaster.cs
+++ b/Content.Shared/Chemistry/SharedChemMaster.cs
@@ -18,17 +18,6 @@ namespace Content.Shared.Chemistry
public const uint LabelMaxLength = 50;
}
- [Serializable, NetSerializable]
- public sealed class ChemMasterSetModeMessage : BoundUserInterfaceMessage
- {
- public readonly ChemMasterMode ChemMasterMode;
-
- public ChemMasterSetModeMessage(ChemMasterMode mode)
- {
- ChemMasterMode = mode;
- }
- }
-
[Serializable, NetSerializable]
public sealed class ChemMasterSetPillTypeMessage : BoundUserInterfaceMessage
{
@@ -83,12 +72,6 @@ namespace Content.Shared.Chemistry
}
}
- public enum ChemMasterMode
- {
- Transfer,
- Discard,
- }
-
public enum ChemMasterReagentAmount
{
U1 = 1,
@@ -158,8 +141,6 @@ namespace Content.Shared.Chemistry
///
public readonly IReadOnlyList BufferReagents;
- public readonly ChemMasterMode Mode;
-
public readonly FixedPoint2? BufferCurrentVolume;
public readonly uint SelectedPillType;
@@ -168,14 +149,13 @@ namespace Content.Shared.Chemistry
public readonly bool UpdateLabel;
public ChemMasterBoundUserInterfaceState(
- ChemMasterMode mode, ContainerInfo? inputContainerInfo, ContainerInfo? outputContainerInfo,
+ ContainerInfo? inputContainerInfo, ContainerInfo? outputContainerInfo,
IReadOnlyList bufferReagents, FixedPoint2 bufferCurrentVolume,
uint selectedPillType, uint pillDosageLimit, bool updateLabel)
{
InputContainerInfo = inputContainerInfo;
OutputContainerInfo = outputContainerInfo;
BufferReagents = bufferReagents;
- Mode = mode;
BufferCurrentVolume = bufferCurrentVolume;
SelectedPillType = selectedPillType;
PillDosageLimit = pillDosageLimit;
diff --git a/Content.Shared/Forensics/Events.cs b/Content.Shared/Forensics/Events.cs
index c346d08536d..b209cc0e85d 100644
--- a/Content.Shared/Forensics/Events.cs
+++ b/Content.Shared/Forensics/Events.cs
@@ -1,4 +1,5 @@
using Content.Shared.DoAfter;
+using Content.Shared.Inventory;
using Robust.Shared.Serialization;
namespace Content.Shared.Forensics;
@@ -68,3 +69,13 @@ public record struct GenerateDnaEvent()
///
public required string DNA;
}
+
+///
+/// An event to check if the fingerprint is accessible.
+///
+public sealed class TryAccessFingerprintEvent : CancellableEntityEventArgs, IInventoryRelayEvent
+{
+ SlotFlags IInventoryRelayEvent.TargetSlots => ~SlotFlags.POCKET;
+
+ public EntityUid? Blocker;
+}
diff --git a/Content.Server/Kitchen/Components/MicrowaveComponent.cs b/Content.Shared/Kitchen/Components/MicrowaveComponent.cs
similarity index 97%
rename from Content.Server/Kitchen/Components/MicrowaveComponent.cs
rename to Content.Shared/Kitchen/Components/MicrowaveComponent.cs
index 5337d80fd17..9fb43f4153b 100644
--- a/Content.Server/Kitchen/Components/MicrowaveComponent.cs
+++ b/Content.Shared/Kitchen/Components/MicrowaveComponent.cs
@@ -6,7 +6,7 @@ using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-namespace Content.Server.Kitchen.Components
+namespace Content.Shared.Kitchen.Components
{
[RegisterComponent]
public sealed partial class MicrowaveComponent : Component
@@ -116,11 +116,13 @@ namespace Content.Server.Kitchen.Components
{
public EntityUid Microwave;
public EntityUid? User;
+ public uint Time;
- public BeingMicrowavedEvent(EntityUid microwave, EntityUid? user)
+ public BeingMicrowavedEvent(EntityUid microwave, EntityUid? user, uint time)
{
Microwave = microwave;
User = user;
+ Time = time;
}
}
}
diff --git a/Content.Shared/NPC/Components/NoFriendlyFireComponent.cs b/Content.Shared/NPC/Components/NoFriendlyFireComponent.cs
new file mode 100644
index 00000000000..02e1d3f8e4e
--- /dev/null
+++ b/Content.Shared/NPC/Components/NoFriendlyFireComponent.cs
@@ -0,0 +1,9 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.NPC.Components;
+
+///
+/// Prevents this mob from doing melee damage to friendly mobs.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class NoFriendlyFireComponent : Component;
diff --git a/Content.Shared/NPC/Systems/NoFriendlyFireSystem.cs b/Content.Shared/NPC/Systems/NoFriendlyFireSystem.cs
new file mode 100644
index 00000000000..6d1463e8a71
--- /dev/null
+++ b/Content.Shared/NPC/Systems/NoFriendlyFireSystem.cs
@@ -0,0 +1,32 @@
+using Content.Shared.NPC.Components;
+using Content.Shared.Weapons.Melee.Events;
+
+namespace Content.Shared.NPC.Systems;
+
+public sealed class NoFriendlyFireSystem : EntitySystem
+{
+ [Dependency] private readonly NpcFactionSystem _faction = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnMeleeHit);
+ }
+
+ private void OnMeleeHit(Entity ent, ref MeleeHitEvent args)
+ {
+ if (!TryComp(ent, out var faction))
+ return;
+
+ var factionEnt = (ent.Owner, faction);
+ foreach (var hit in args.HitEntities)
+ {
+ if (_faction.IsEntityFriendly(factionEnt, hit))
+ {
+ args.BonusDamage = -args.BaseDamage;
+ return; // prevent healing by swinging multiple friendlies or something
+ }
+ }
+ }
+}
diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
index 044f75dbc90..f92c5ed3a2f 100644
--- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
+++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
@@ -14,6 +14,7 @@ namespace Content.Shared.Weapons.Ranged.Systems;
public abstract partial class SharedGunSystem
{
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedInteractionSystem _interaction = default!;
protected virtual void InitializeBallistic()
@@ -117,8 +118,8 @@ public abstract partial class SharedGunSystem
void SimulateInsertAmmo(EntityUid ammo, EntityUid ammoProvider, EntityCoordinates coordinates)
{
- var evInsert = new InteractUsingEvent(args.User, ammo, ammoProvider, coordinates);
- RaiseLocalEvent(ammoProvider, evInsert);
+ // We call SharedInteractionSystem to raise contact events. Checks are already done by this point.
+ _interaction.InteractUsing(args.User, ammo, ammoProvider, coordinates, checkCanInteract: false, checkCanUse: false);
}
List<(EntityUid? Entity, IShootable Shootable)> ammo = new();
diff --git a/Content.Shared/Weapons/Reflect/ReflectComponent.cs b/Content.Shared/Weapons/Reflect/ReflectComponent.cs
index 8418c1f3efb..3d7cc9a5322 100644
--- a/Content.Shared/Weapons/Reflect/ReflectComponent.cs
+++ b/Content.Shared/Weapons/Reflect/ReflectComponent.cs
@@ -1,5 +1,6 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
+using Content.Shared.Inventory;
namespace Content.Shared.Weapons.Reflect;
@@ -16,6 +17,25 @@ public sealed partial class ReflectComponent : Component
[ViewVariables(VVAccess.ReadWrite), DataField("reflects")]
public ReflectType Reflects = ReflectType.Energy | ReflectType.NonEnergy;
+ ///
+ /// Select in which inventory slots it will reflect.
+ /// By default, it will reflect in any inventory position, except pockets.
+ ///
+ [ViewVariables(VVAccess.ReadWrite), DataField]
+ public SlotFlags SlotFlags = SlotFlags.WITHOUT_POCKET;
+
+ ///
+ /// Is it allowed to reflect while being in hands.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ public bool ReflectingInHands = true;
+
+ ///
+ /// Can only reflect when placed correctly.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ public bool InRightPlace = true;
+
///
/// Probability for a projectile to be reflected.
///
diff --git a/Content.Shared/Weapons/Reflect/ReflectSystem.cs b/Content.Shared/Weapons/Reflect/ReflectSystem.cs
index 881b547f27f..17dd582a06b 100644
--- a/Content.Shared/Weapons/Reflect/ReflectSystem.cs
+++ b/Content.Shared/Weapons/Reflect/ReflectSystem.cs
@@ -96,6 +96,7 @@ public sealed class ReflectSystem : EntitySystem
{
if (!Resolve(reflector, ref reflect, false) ||
!_toggle.IsActivated(reflector) ||
+ !reflect.InRightPlace ||
!TryComp(projectile, out var reflective) ||
(reflect.Reflects & reflective.Reflective) == 0x0 ||
!_random.Prob(reflect.ReflectProb) ||
@@ -165,6 +166,7 @@ public sealed class ReflectSystem : EntitySystem
{
if (!TryComp(reflector, out var reflect) ||
!_toggle.IsActivated(reflector) ||
+ !reflect.InRightPlace ||
!_random.Prob(reflect.ReflectProb))
{
newDirection = null;
@@ -193,6 +195,8 @@ public sealed class ReflectSystem : EntitySystem
if (_gameTiming.ApplyingState)
return;
+ component.InRightPlace = IsInRightPlace(component, args.SlotFlags);
+
EnsureComp(args.Equipee);
}
@@ -206,6 +210,8 @@ public sealed class ReflectSystem : EntitySystem
if (_gameTiming.ApplyingState)
return;
+ component.InRightPlace = IsInRightPlace(component, SlotFlags.NONE);
+
EnsureComp(args.User);
}
@@ -236,4 +242,15 @@ public sealed class ReflectSystem : EntitySystem
RemCompDeferred(user);
}
+
+ ///
+ /// Checks if the reflective component should work in designated place.
+ ///
+ private static bool IsInRightPlace(ReflectComponent component, SlotFlags slotFlag)
+ {
+ if (slotFlag == SlotFlags.NONE)
+ return component.ReflectingInHands;
+ else
+ return (component.SlotFlags & slotFlag) == slotFlag;
+ }
}
diff --git a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
index ceeac1be3c9..278e70286eb 100644
--- a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
+++ b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
@@ -19,6 +19,10 @@ log-probe-scan = Downloaded logs from {$device}!
log-probe-label-time = Time
log-probe-label-accessor = Accessed by
log-probe-label-number = #
+log-probe-print-button = Print Logs
+log-probe-printout-device = Scanned Device: {$name}
+log-probe-printout-header = Latest logs:
+log-probe-printout-entry = #{$number} / {$time} / {$accessor}
astro-nav-program-name = AstroNav
diff --git a/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl b/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
index 51110f12c4c..873ec7104ec 100644
--- a/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
@@ -18,8 +18,6 @@ chem-master-window-buffer-label = buffer:
chem-master-window-buffer-all-amount = All
chem-master-window-buffer-empty-text = Buffer empty.
chem-master-window-buffer-low-text = Not enough solution in buffer
-chem-master-window-transfer-button = Transfer
-chem-master-window-discard-button = Discard
chem-master-window-packaging-text = Packaging
chem-master-current-text-label = Label:
chem-master-window-pills-label = Pills:
diff --git a/Resources/Locale/en-US/chemistry/components/rehydratable-component.ftl b/Resources/Locale/en-US/chemistry/components/rehydratable-component.ftl
index c2e61e6cd48..37c699a3ce4 100644
--- a/Resources/Locale/en-US/chemistry/components/rehydratable-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/rehydratable-component.ftl
@@ -1 +1,2 @@
-rehydratable-component-expands-message = {$owner} expands!
\ No newline at end of file
+rehydratable-component-expands-message = {$owner} expands!
+rehydratable-component-soaked-message = [color=red]It is soaked in the wrong reagent![/color]
diff --git a/Resources/Locale/en-US/forensics/forensics.ftl b/Resources/Locale/en-US/forensics/forensics.ftl
index 80eea069fa9..6eae96f27d7 100644
--- a/Resources/Locale/en-US/forensics/forensics.ftl
+++ b/Resources/Locale/en-US/forensics/forensics.ftl
@@ -9,7 +9,8 @@ forensic-scanner-interface-clear = Clear
forensic-scanner-report-title = Forensics Report: {$entity}
forensic-pad-unused = It hasn't been used.
forensic-pad-sample = It has a sample: {$sample}
-forensic-pad-gloves = {CAPITALIZE($target)} is wearing gloves.
+forensic-pad-no-access-due = Can't access the fingerprint due to {THE($entity)}.
+forensic-pad-no-access = Can't access the fingerprint.
forensic-pad-start-scan-target = {CAPITALIZE($user)} is trying to take a sample of your fingerprints.
forensic-pad-start-scan-user = You start taking a sample of {CAPITALIZE($target)}'s fingerprints.
forensic-pad-already-used = This pad has already been used.
diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml
index 24f438113b9..c189535a646 100644
--- a/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml
+++ b/Resources/Prototypes/Entities/Clothing/Eyes/hud.yml
@@ -16,15 +16,22 @@
- type: ShowHealthIcons
- type: entity
- parent: ClothingEyesBase
+ parent: [ClothingEyesBase, BaseToggleClothing]
id: ClothingEyesHudDiagnostic
name: diagnostic hud
- description: A heads-up display capable of analyzing the integrity and status of robotics and exosuits. Made out of see-borg-ium.
+ description: A heads-up display capable of analyzing the integrity and status of robotics and exosuits. Made out of see-borg-ium. Has a camera mod to work with Station AI.
components:
- type: Sprite
sprite: Clothing/Eyes/Hud/diag.rsi
- type: Clothing
sprite: Clothing/Eyes/Hud/diag.rsi
+ - type: ToggleClothing
+ action: ActionToggleHudDiagnosticCamera
+ disableOnUnequip: true
+ - type: ComponentToggler
+ parent: true
+ components:
+ - type: StationAiOverlay
- type: ShowHealthBars
damageContainers:
- Inorganic
@@ -34,7 +41,7 @@
parent: [ClothingEyesBase, ShowMedicalIcons]
id: ClothingEyesHudMedical
name: medical hud
- description: A heads-up display that scans the humanoids in view and provides accurate data about their health status.
+ description: A heads-up display that scans the humas in view and provides accurate data about their health status.
components:
- type: Sprite
sprite: Clothing/Eyes/Hud/med.rsi
@@ -291,3 +298,11 @@
parent: [ClothingEyesEyepatchHudDiag, ClothingHeadEyeBaseFlipped]
id: ClothingEyesEyepatchHudDiagFlipped
name: diagnostic hud eyepatch
+
+- type: entity
+ id: ActionToggleHudDiagnosticCamera
+ name: Toggle camera mod
+ description: Toggles the camera mod on and off.
+ components:
+ - type: InstantAction
+ event: !type:ToggleActionEvent
diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml
index 4fb583ef437..3d7d33a1c6a 100644
--- a/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml
+++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/armor.yml
@@ -99,6 +99,7 @@
reflectProb: 1
reflects:
- Energy
+ reflectingInHands: false
- type: entity
parent: [ClothingOuterBaseLarge, AllowSuitStorageClothing, BaseSyndicateContraband ]
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml
index e8f16a8c3a4..212a0c25942 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml
@@ -13,6 +13,7 @@
blackboard:
NavSmash: !type:Bool
true
+ - type: NoFriendlyFire # don't let fish hurt their dragon, and dont let sentient fish bypass FactionClothing
- type: NpcFactionMember
factions:
- Dragon
diff --git a/Resources/Prototypes/Entities/Objects/Devices/forensic_scanner.yml b/Resources/Prototypes/Entities/Objects/Devices/forensic_scanner.yml
index fbb477de64b..46735247c36 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/forensic_scanner.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/forensic_scanner.yml
@@ -57,3 +57,13 @@
- type: GuideHelp
guides:
- Forensics
+
+- type: entity
+ parent: ForensicReportPaper
+ id: PaperAccessLogs
+ name: access logs
+ description: A printout from the detective's trusty LogProbe.
+ components:
+ - type: PaperVisuals
+ headerImagePath: null
+ headerMargin: 0.0, 0.0, 0.0, 0.0
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
index 15744be5853..79837116284 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sword.yml
@@ -98,6 +98,8 @@
- Back
- Belt
- type: Reflect
+ slotFlags:
+ - NONE
- type: entity
name: machete
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index 7d8290dc6a2..cd5cd5a9e35 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -651,6 +651,7 @@
- TorsoBorg
dynamicRecipes:
- ProximitySensor
+ - ClothingEyesHudDiagnostic
- BorgModuleAdvancedCleaning
- BorgModuleAdvancedTool
- BorgModuleGPS
diff --git a/Resources/Prototypes/Entities/Structures/Specific/dragon.yml b/Resources/Prototypes/Entities/Structures/Specific/dragon.yml
index 8a7f13d1a45..7dca4b5be85 100644
--- a/Resources/Prototypes/Entities/Structures/Specific/dragon.yml
+++ b/Resources/Prototypes/Entities/Structures/Specific/dragon.yml
@@ -45,3 +45,6 @@
- type: EmitSoundOnSpawn
sound:
path: /Audio/Weapons/Guns/Gunshots/rocket_launcher.ogg
+ - type: NpcFactionMember
+ factions:
+ - Dragon # prevent shitter carp from destroying rifts
diff --git a/Resources/Prototypes/Reagents/medicine.yml b/Resources/Prototypes/Reagents/medicine.yml
index b539c28596c..f5daa17c1e3 100644
--- a/Resources/Prototypes/Reagents/medicine.yml
+++ b/Resources/Prototypes/Reagents/medicine.yml
@@ -430,6 +430,7 @@
color: "#731024"
metabolisms:
Medicine:
+ metabolismRate: 0.1 # Smaller doses stabilize critical people for longer. Gives it a specific usecase as to not be entirely outclassed by dex+
effects:
- !type:HealthChange
conditions:
@@ -438,7 +439,7 @@
mobstate: Critical
damage:
types:
- Asphyxiation: -5
+ Asphyxiation: -2
- !type:ModifyBleedAmount
amount: -0.25
diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml
index 36ceff065b3..55b3c750d38 100644
--- a/Resources/Prototypes/Recipes/Lathes/robotics.yml
+++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml
@@ -53,6 +53,15 @@
Plastic: 200
Steel: 100
+- type: latheRecipe
+ parent: BaseRoboticsRecipe
+ id: ClothingEyesHudDiagnostic
+ result: ClothingEyesHudDiagnostic
+ materials:
+ Steel: 200
+ Plastic: 100
+ Glass: 300
+
- type: latheRecipe
parent: BaseRoboticsRecipe
id: CyborgEndoskeleton
diff --git a/Resources/Prototypes/Research/experimental.yml b/Resources/Prototypes/Research/experimental.yml
index 729f4d44443..1f8e9d84b14 100644
--- a/Resources/Prototypes/Research/experimental.yml
+++ b/Resources/Prototypes/Research/experimental.yml
@@ -12,6 +12,7 @@
recipeUnlocks:
- ProximitySensor
- ExosuitFabricatorMachineCircuitboard
+ - ClothingEyesHudDiagnostic
- type: technology
id: BasicAnomalousResearch