diff --git a/Content.Client/Chemistry/UI/ButtonGrid.cs b/Content.Client/Chemistry/UI/ButtonGrid.cs
new file mode 100644
index 0000000000..0abd9ef8a4
--- /dev/null
+++ b/Content.Client/Chemistry/UI/ButtonGrid.cs
@@ -0,0 +1,119 @@
+using System;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface.Controls;
+
+namespace Content.Client.Chemistry.UI;
+
+///
+/// Creates a grid of buttons given a comma-seperated list of Text
+///
+public sealed class ButtonGrid : GridContainer
+{
+ private string _buttonList = "";
+
+ ///
+ /// A comma-seperated list of text to use for each button. These will be inserted sequentially.
+ ///
+ public string ButtonList
+ {
+ get => _buttonList;
+ set
+ {
+ _buttonList = value;
+ Update();
+ }
+ }
+
+ public bool RadioGroup { get; set; } = false;
+
+ private string? _selected;
+
+ ///
+ /// Which button is currently selected. Only matters when is true.
+ ///
+ public string? Selected
+ {
+ get => _selected;
+ set
+ {
+ _selected = value;
+ Update();
+ }
+ }
+
+ public Action? OnButtonPressed;
+
+ ///
+ ///
+ ///
+ public new int Columns
+ {
+ get => base.Columns;
+ set
+ {
+ base.Columns = value;
+ Update();
+ }
+ }
+
+ ///
+ ///
+ ///
+ public new int Rows
+ {
+ get => base.Rows;
+ set
+ {
+ base.Rows = value;
+ Update();
+ }
+ }
+
+ private void Update()
+ {
+ if (ButtonList == "")
+ return;
+
+ this.Children.Clear();
+ var i = 0;
+ var list = ButtonList.Split(",");
+
+ var group = new ButtonGroup();
+
+ foreach (var button in list)
+ {
+ var btn = new Button();
+ btn.Text = button;
+ btn.OnPressed += _ =>
+ {
+ if (RadioGroup)
+ btn.Pressed = true;
+ Selected = button;
+ OnButtonPressed?.Invoke(button);
+ };
+ if (button == Selected)
+ btn.Pressed = true;
+ var sep = HSeparationOverride ?? 0;
+ // ReSharper disable once PossibleLossOfFraction
+ // btn.SetWidth = (this.PixelWidth - sep * (Columns - 1)) / 3;
+ btn.Group = group;
+
+ var row = i / Columns;
+ var col = i % Columns;
+ var last = i == list.Length - 1;
+ var lastCol = i == Columns - 1;
+ var lastRow = row == list.Length / Columns - 1;
+
+ if (row == 0 && (lastCol || last))
+ btn.AddStyleClass("OpenLeft");
+ else if (col == 0 && lastRow)
+ btn.AddStyleClass("OpenRight");
+ else
+ btn.AddStyleClass("OpenBoth");
+
+ this.Children.Add(btn);
+
+ i++;
+ }
+ }
+}
diff --git a/Content.Client/Chemistry/UI/ReagentCardControl.xaml b/Content.Client/Chemistry/UI/ReagentCardControl.xaml
new file mode 100644
index 0000000000..257b0b6c52
--- /dev/null
+++ b/Content.Client/Chemistry/UI/ReagentCardControl.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs b/Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs
new file mode 100644
index 0000000000..f7cadcc264
--- /dev/null
+++ b/Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs
@@ -0,0 +1,32 @@
+using Content.Shared.Chemistry;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Chemistry.UI;
+
+[GenerateTypedNameReferences]
+public sealed partial class ReagentCardControl : Control
+{
+ public string StorageSlotId { get; }
+ public Action? OnPressed;
+ public Action? OnEjectButtonPressed;
+
+ public ReagentCardControl(ReagentInventoryItem item)
+ {
+ RobustXamlLoader.Load(this);
+
+ StorageSlotId = item.StorageSlotId;
+ ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
+ ReagentNameLabel.Text = item.ReagentLabel;
+ FillLabel.Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", item.Quantity));;
+ EjectButtonIcon.Text = Loc.GetString("reagent-dispenser-window-eject-container-button");
+
+ if (item.Quantity == 0.0)
+ MainButton.Disabled = true;
+
+ MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId);
+ EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId);
+ }
+}
diff --git a/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs b/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
index c94759a6c1..fce57a6ec5 100644
--- a/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
+++ b/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
@@ -42,28 +42,11 @@ namespace Content.Client.Chemistry.UI
// Setup static button actions.
_window.EjectButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName));
_window.ClearButton.OnPressed += _ => SendMessage(new ReagentDispenserClearContainerSolutionMessage());
- _window.DispenseButton1.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U1));
- _window.DispenseButton5.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U5));
- _window.DispenseButton10.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U10));
- _window.DispenseButton15.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U15));
- _window.DispenseButton20.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U20));
- _window.DispenseButton25.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U25));
- _window.DispenseButton30.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U30));
- _window.DispenseButton50.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U50));
- _window.DispenseButton100.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U100));
- // Setup reagent button actions.
- _window.OnDispenseReagentButtonPressed += (args, button) => SendMessage(new ReagentDispenserDispenseReagentMessage(button.ReagentId));
- _window.OnDispenseReagentButtonMouseEntered += (args, button) =>
- {
- if (_lastState is not null)
- _window.UpdateContainerInfo(_lastState, button.ReagentId);
- };
- _window.OnDispenseReagentButtonMouseExited += (args, button) =>
- {
- if (_lastState is not null)
- _window.UpdateContainerInfo(_lastState);
- };
+ _window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s));
+
+ _window.OnDispenseReagentButtonPressed += (id) => SendMessage(new ReagentDispenserDispenseReagentMessage(id));
+ _window.OnEjectJugButtonPressed += (id) => SendMessage(new ItemSlotButtonPressedEvent(id));
}
///
diff --git a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml
index 20bff6f966..9da340f8a7 100644
--- a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml
+++ b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml
@@ -1,53 +1,78 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+ Orientation="Vertical"
+ HorizontalExpand="True"
+ VerticalExpand="True"
+ Margin="5">
+
-
+
-
+
diff --git a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
index 93c2758db4..c462dbfc69 100644
--- a/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
+++ b/Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
@@ -1,11 +1,9 @@
-using System.Linq;
using Content.Client.Stylesheets;
+using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Reagent;
using Robust.Client.AutoGenerated;
-using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using static Robust.Client.UserInterface.Controls.BoxContainer;
@@ -16,14 +14,12 @@ namespace Content.Client.Chemistry.UI
/// Client-side UI used to control a .
///
[GenerateTypedNameReferences]
- public sealed partial class ReagentDispenserWindow : DefaultWindow
+ public sealed partial class ReagentDispenserWindow : FancyWindow
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
-
- public event Action? OnDispenseReagentButtonPressed;
- public event Action? OnDispenseReagentButtonMouseEntered;
- public event Action? OnDispenseReagentButtonMouseExited;
+ public event Action? OnDispenseReagentButtonPressed;
+ public event Action? OnEjectJugButtonPressed;
///
/// Create and initialize the dispenser UI client-side. Creates the basic layout,
@@ -33,45 +29,27 @@ namespace Content.Client.Chemistry.UI
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
-
- var dispenseAmountGroup = new ButtonGroup();
- DispenseButton1.Group = dispenseAmountGroup;
- DispenseButton5.Group = dispenseAmountGroup;
- DispenseButton10.Group = dispenseAmountGroup;
- DispenseButton15.Group = dispenseAmountGroup;
- DispenseButton20.Group = dispenseAmountGroup;
- DispenseButton25.Group = dispenseAmountGroup;
- DispenseButton30.Group = dispenseAmountGroup;
- DispenseButton50.Group = dispenseAmountGroup;
- DispenseButton100.Group = dispenseAmountGroup;
}
///
/// Update the button grid of reagents which can be dispensed.
///
/// Reagents which can be dispensed by this dispenser
- public void UpdateReagentsList(List inventory)
+ public void UpdateReagentsList(List inventory)
{
- if (ChemicalList == null)
+ if (ReagentList == null)
return;
- ChemicalList.Children.Clear();
+ ReagentList.Children.Clear();
+ //Sort inventory by reagentLabel
+ inventory.Sort((x, y) => x.ReagentLabel.CompareTo(y.ReagentLabel));
- foreach (var entry in inventory.OrderBy(r =>
- {
- _prototypeManager.TryIndex(r.Prototype, out ReagentPrototype? p);
- return p?.LocalizedName;
- }))
+ foreach (var item in inventory)
{
- var localizedName = _prototypeManager.TryIndex(entry.Prototype, out ReagentPrototype? p)
- ? p.LocalizedName
- : Loc.GetString("reagent-dispenser-window-reagent-name-not-found-text");
-
- var button = new DispenseReagentButton(entry, localizedName);
- button.OnPressed += args => OnDispenseReagentButtonPressed?.Invoke(args, button);
- button.OnMouseEntered += args => OnDispenseReagentButtonMouseEntered?.Invoke(args, button);
- button.OnMouseExited += args => OnDispenseReagentButtonMouseExited?.Invoke(args, button);
- ChemicalList.AddChild(button);
+ var card = new ReagentCardControl(item);
+ card.OnPressed += OnDispenseReagentButtonPressed;
+ card.OnEjectButtonPressed += OnEjectJugButtonPressed;
+ ReagentList.Children.Add(card);
}
}
@@ -92,36 +70,7 @@ namespace Content.Client.Chemistry.UI
ClearButton.Disabled = castState.OutputContainer is null;
EjectButton.Disabled = castState.OutputContainer is null;
- switch (castState.SelectedDispenseAmount)
- {
- case ReagentDispenserDispenseAmount.U1:
- DispenseButton1.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U5:
- DispenseButton5.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U10:
- DispenseButton10.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U15:
- DispenseButton15.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U20:
- DispenseButton20.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U25:
- DispenseButton25.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U30:
- DispenseButton30.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U50:
- DispenseButton50.Pressed = true;
- break;
- case ReagentDispenserDispenseAmount.U100:
- DispenseButton100.Pressed = true;
- break;
- }
+ AmountGrid.Selected = ((int)castState.SelectedDispenseAmount).ToString();
}
///
@@ -129,31 +78,22 @@ namespace Content.Client.Chemistry.UI
/// Also highlights a reagent if it's dispense button is being mouse hovered.
///
/// State data for the dispenser.
- /// Prototype ID of the reagent whose dispense button is currently being mouse hovered,
/// or null if no button is being hovered.
- public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state, ReagentId? highlightedReagentId = null)
+ public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state)
{
ContainerInfo.Children.Clear();
if (state.OutputContainer is null)
{
+ ContainerInfoName.Text = "";
+ ContainerInfoFill.Text = "";
ContainerInfo.Children.Add(new Label { Text = Loc.GetString("reagent-dispenser-window-no-container-loaded-text") });
return;
}
- ContainerInfo.Children.Add(new BoxContainer // Name of the container and its fill status (Ex: 44/100u)
- {
- Orientation = LayoutOrientation.Horizontal,
- Children =
- {
- new Label {Text = $"{state.OutputContainer.DisplayName}: "},
- new Label
- {
- Text = $"{state.OutputContainer.CurrentVolume}/{state.OutputContainer.MaxVolume}",
- StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
- }
- }
- });
+ // Set Name of the container and its fill status (Ex: 44/100u)
+ ContainerInfoName.Text = state.OutputContainer.DisplayName;
+ ContainerInfoFill.Text = state.OutputContainer.CurrentVolume + "/" + state.OutputContainer.MaxVolume;
foreach (var (reagent, quantity) in state.OutputContainer.Reagents!)
{
@@ -169,12 +109,6 @@ namespace Content.Client.Chemistry.UI
StyleClasses = { StyleNano.StyleClassLabelSecondaryColor },
};
- // Check if the reagent is being moused over. If so, color it green.
- if (reagent == highlightedReagentId) {
- nameLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood);
- quantityLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood);
- }
-
ContainerInfo.Children.Add(new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
@@ -187,14 +121,4 @@ namespace Content.Client.Chemistry.UI
}
}
}
-
- public sealed class DispenseReagentButton : Button {
- public ReagentId ReagentId { get; }
-
- public DispenseReagentButton(ReagentId reagentId, string text)
- {
- ReagentId = reagentId;
- Text = text;
- }
- }
}
diff --git a/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs b/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs
index 13a0bee28e..a5449308be 100644
--- a/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs
+++ b/Content.IntegrationTests/Tests/Chemistry/DispenserTest.cs
@@ -1,6 +1,7 @@
using Content.Client.Chemistry.UI;
using Content.IntegrationTests.Tests.Interaction;
using Content.Shared.Chemistry;
+using Content.Server.Chemistry.Components;
using Content.Shared.Containers.ItemSlots;
namespace Content.IntegrationTests.Tests.Chemistry;
@@ -24,7 +25,7 @@ public sealed class DispenserTest : InteractionTest
await Interact();
// Eject beaker via BUI.
- var ev = new ItemSlotButtonPressedEvent(SharedChemMaster.InputSlotName);
+ var ev = new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName);
await SendBui(ReagentDispenserUiKey.Key, ev);
// Beaker is back in the player's hands
diff --git a/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs b/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
index 832f584ecb..33d0da12d7 100644
--- a/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
+++ b/Content.Server/Chemistry/Components/ReagentDispenserComponent.cs
@@ -1,3 +1,5 @@
+using Content.Shared.Whitelist;
+using Content.Shared.Containers.ItemSlots;
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Dispenser;
@@ -7,20 +9,52 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Server.Chemistry.Components
{
///
- /// A machine that dispenses reagents into a solution container.
+ /// A machine that dispenses reagents into a solution container from containers in its storage slots.
///
[RegisterComponent]
[Access(typeof(ReagentDispenserSystem), typeof(ChemMasterSystem))]
public sealed partial class ReagentDispenserComponent : Component
{
-
+ ///
+ /// String with the pack name that stores the initial fill of the dispenser. The initial
+ /// fill is added to the dispenser on MapInit. Note that we don't use ContainerFill because
+ /// we have to generate the storage slots at MapInit first, then fill them.
+ ///
[DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer))]
[ViewVariables(VVAccess.ReadWrite)]
public string? PackPrototypeId = default!;
- [DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer))]
- [ViewVariables(VVAccess.ReadWrite)]
- public string? EmagPackPrototypeId = default!;
+ ///
+ /// Maximum number of internal storage slots. Dispenser can't store (or dispense) more than
+ /// this many chemicals (without unloading and reloading).
+ ///
+ [DataField("numStorageSlots")]
+ public int NumSlots = 25;
+
+ ///
+ /// For each created storage slot for the reagent containers being dispensed, apply this
+ /// entity whitelist. Makes sure weird containers don't fit in the dispenser and that beakers
+ /// don't accidentally get slotted into the source slots.
+ ///
+ [DataField]
+ public EntityWhitelist? StorageWhitelist;
+
+ [DataField]
+ public ItemSlot BeakerSlot = new();
+
+ ///
+ /// Prefix for automatically-generated slot name for storage, up to NumSlots.
+ ///
+ public static string BaseStorageSlotId = "ReagentDispenser-storageSlot";
+
+ ///
+ /// List of storage slots that were created at MapInit.
+ ///
+ [DataField]
+ public List StorageSlotIds = new List();
+
+ [DataField]
+ public List StorageSlots = new List();
[DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
diff --git a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
index 8b1bc4c8c1..2c58be074c 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
@@ -1,6 +1,5 @@
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
-using Content.Server.DeviceLinking.Systems;
using Content.Server.Labels;
using Content.Server.Popups;
using Content.Server.Storage.EntitySystems;
@@ -11,7 +10,6 @@ using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
-using Content.Shared.DeviceLinking.Events;
using Content.Shared.FixedPoint;
using Content.Shared.Storage;
using JetBrains.Annotations;
@@ -25,7 +23,6 @@ using System.Linq;
namespace Content.Server.Chemistry.EntitySystems
{
-
///
/// Contains all the server-side logic for ChemMasters.
///
@@ -41,8 +38,6 @@ namespace Content.Server.Chemistry.EntitySystems
[Dependency] private readonly StorageSystem _storageSystem = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
- [Dependency] private readonly ReagentDispenserSystem _dispenserSystem = default!; // WD
- [Dependency] private readonly DeviceLinkSystem _signalSystem = default!; // WD
[ValidatePrototypeId]
private const string PillPrototypeId = "Pill";
@@ -56,14 +51,7 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent(SubscribeUpdateUiState);
SubscribeLocalEvent(SubscribeUpdateUiState);
SubscribeLocalEvent(SubscribeUpdateUiState);
-
- // WD START
- SubscribeLocalEvent(OnComponentInit);
- SubscribeLocalEvent(OnPortDisconnected);
- SubscribeLocalEvent(OnAnchor);
- // WD END
-
-
+
SubscribeLocalEvent(OnSetModeMessage);
SubscribeLocalEvent(OnSetPillTypeMessage);
SubscribeLocalEvent(OnReagentButtonMessage);
@@ -71,30 +59,6 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent(OnOutputToBottleMessage);
}
- // WD START
- private void OnComponentInit(EntityUid uid, ChemMasterComponent clonePod, ComponentInit args)
- {
- _signalSystem.EnsureSinkPorts(uid, ChemMasterComponent.ChemMasterPort);
- }
-
- private void OnPortDisconnected(EntityUid uid, ChemMasterComponent component, PortDisconnectedEvent args)
- {
- component.ConnectedDispenser = null;
- }
-
- private void OnAnchor(EntityUid uid, ChemMasterComponent component, ref AnchorStateChangedEvent args)
- {
- if (component.ConnectedDispenser == null ||
- !TryComp(component.ConnectedDispenser, out var dispenserComp))
- return;
-
- if (!args.Anchored)
- return;
-
- _dispenserSystem.UpdateConnection(component.ConnectedDispenser.Value, uid, dispenserComp, component);
- }
- // WD END
-
private void SubscribeUpdateUiState(Entity ent, ref T ev)
{
UpdateUiState(ent);
diff --git a/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs b/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs
index 7d638bf111..2361125d96 100644
--- a/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs
@@ -1,26 +1,20 @@
+using Content.Server.Administration.Logs;
using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Containers.EntitySystems;
-using Content.Server.DeviceLinking.Systems;
+using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Containers.ItemSlots;
-using Content.Shared.Database;
-using Content.Shared.DeviceLinking;
-using Content.Shared.DeviceLinking.Events;
-using Content.Shared.Emag.Components;
-using Content.Shared.Emag.Systems;
using Content.Shared.FixedPoint;
+using Content.Shared.Nutrition.EntitySystems;
using JetBrains.Annotations;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
-using System.Linq;
-using Content.Server.Administration.Logs;
-using Content.Shared.Chemistry.Components.SolutionManager;
-using Content.Shared.Chemistry.Reagent;
+using Content.Shared.Labels.Components;
namespace Content.Server.Chemistry.EntitySystems
{
@@ -33,13 +27,13 @@ namespace Content.Server.Chemistry.EntitySystems
{
[Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
+ [Dependency] private readonly SolutionTransferSystem _solutionTransferSystem = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly DeviceLinkSystem _signalSystem = default!; // WD
- [Dependency] private readonly ChemMasterSystem _chemMasterSystem = default!; // WD
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
-
+ [Dependency] private readonly OpenableSystem _openable = default!;
+
public override void Initialize()
{
base.Initialize();
@@ -50,108 +44,13 @@ namespace Content.Server.Chemistry.EntitySystems
SubscribeLocalEvent(SubscribeUpdateUiState);
SubscribeLocalEvent(SubscribeUpdateUiState);
- // WD START
- SubscribeLocalEvent(OnInit);
- SubscribeLocalEvent(OnMapInit);
- SubscribeLocalEvent(OnNewLink);
- SubscribeLocalEvent(OnPortDisconnected);
- SubscribeLocalEvent(OnAnchorChanged);
- // WD END
-
- SubscribeLocalEvent(OnEmagged);
-
SubscribeLocalEvent(OnSetDispenseAmountMessage);
SubscribeLocalEvent(OnDispenseReagentMessage);
SubscribeLocalEvent(OnClearContainerSolutionMessage);
+
+ SubscribeLocalEvent(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
}
- // WD START
- private void OnInit(EntityUid uid, ReagentDispenserComponent component, ComponentInit args)
- {
- _signalSystem.EnsureSourcePorts(uid, ReagentDispenserComponent.ChemMasterPort);
- }
-
- private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
- {
- if (!TryComp(uid, out var receiver))
- return;
-
- foreach (var port in receiver.Outputs.Values.SelectMany(ports => ports))
- {
- if (!TryComp(port, out var master))
- continue;
-
- UpdateConnection(uid, port, component, master);
- break;
- }
- }
-
- private void OnNewLink(EntityUid uid, ReagentDispenserComponent component, NewLinkEvent args)
- {
- if (TryComp(args.Sink, out var master) && args.SourcePort == ReagentDispenserComponent.ChemMasterPort)
- UpdateConnection(uid, args.Sink, component, master);
- }
-
- private void OnPortDisconnected(EntityUid uid, ReagentDispenserComponent component, PortDisconnectedEvent args)
- {
- if (args.Port != ReagentDispenserComponent.ChemMasterPort)
- return;
-
- component.ChemMaster = null;
- component.ChemMasterInRange = false;
- }
-
- private void OnAnchorChanged(EntityUid uid, ReagentDispenserComponent component, ref AnchorStateChangedEvent args)
- {
- if (args.Anchored)
- RecheckConnections(uid, component);
- }
-
- public void UpdateConnection(
- EntityUid dispenser,
- EntityUid chemMaster,
- ReagentDispenserComponent? dispenserComp = null,
- ChemMasterComponent? chemMasterComp = null)
- {
- if (!Resolve(dispenser, ref dispenserComp) || !Resolve(chemMaster, ref chemMasterComp))
- return;
-
- if (dispenserComp.ChemMaster.HasValue && dispenserComp.ChemMaster.Value != chemMaster &&
- TryComp(dispenserComp.ChemMaster, out ChemMasterComponent? oldMaster))
- {
- oldMaster.ConnectedDispenser = null;
- }
-
- if (chemMasterComp.ConnectedDispenser.HasValue && chemMasterComp.ConnectedDispenser.Value != dispenser &&
- TryComp(dispenserComp.ChemMaster, out ReagentDispenserComponent? oldDispenser))
- {
- oldDispenser.ChemMaster = null;
- oldDispenser.ChemMasterInRange = false;
- }
-
- dispenserComp.ChemMaster = chemMaster;
- chemMasterComp.ConnectedDispenser = dispenser;
-
- RecheckConnections(dispenser, dispenserComp);
- }
-
- private void RecheckConnections(EntityUid dispenser, ReagentDispenserComponent? component = null)
- {
- if (!Resolve(dispenser, ref component))
- return;
-
- if (component.ChemMaster == null)
- {
- component.ChemMasterInRange = false;
- return;
- }
-
- Transform(component.ChemMaster.Value).Coordinates
- .TryDistance(EntityManager, Transform(dispenser).Coordinates, out var distance);
- component.ChemMasterInRange = distance <= 1.5f;
- }
- // WD END
-
private void SubscribeUpdateUiState(Entity ent, ref T ev)
{
UpdateUiState(ent);
@@ -184,35 +83,39 @@ namespace Content.Server.Chemistry.EntitySystems
return null;
}
- private List GetInventory(Entity ent)
+ private List GetInventory(Entity reagentDispenser)
{
- var reagentDispenser = ent.Comp;
- var inventory = new List();
+ var inventory = new List();
- if (reagentDispenser.PackPrototypeId is not null
- && _prototypeManager.TryIndex(reagentDispenser.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
+ for (var i = 0; i < reagentDispenser.Comp.NumSlots; i++)
{
- inventory.AddRange(packPrototype.Inventory.Select(x => new ReagentId(x, null)));
- }
+ var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
+ var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser.Owner, storageSlotId);
- if (HasComp(ent)
- && reagentDispenser.EmagPackPrototypeId is not null
- && _prototypeManager.TryIndex(reagentDispenser.EmagPackPrototypeId, out ReagentDispenserInventoryPrototype? emagPackPrototype))
- {
- inventory.AddRange(emagPackPrototype.Inventory.Select(x => new ReagentId(x, null)));
+ // Set label from manually-applied label, or metadata if unavailable
+ string reagentLabel;
+ if (TryComp(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel))
+ reagentLabel = label.CurrentLabel;
+ else if (storedContainer != null)
+ reagentLabel = Name(storedContainer.Value);
+ else
+ continue;
+
+ // Get volume remaining and color of solution
+ FixedPoint2 quantity = 0f;
+ var reagentColor = Color.White;
+ if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
+ {
+ quantity = sol.Volume;
+ reagentColor = sol.GetColor(_prototypeManager);
+ }
+
+ inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, quantity, reagentColor));
}
return inventory;
}
- private void OnEmagged(Entity reagentDispenser, ref GotEmaggedEvent args)
- {
- // adding component manually to have correct state
- EntityManager.AddComponent(reagentDispenser);
- UpdateUiState(reagentDispenser);
- args.Handled = true;
- }
-
private void OnSetDispenseAmountMessage(Entity reagentDispenser, ref ReagentDispenserSetDispenseAmountMessage message)
{
reagentDispenser.Comp.DispenseAmount = message.ReagentDispenserDispenseAmount;
@@ -223,33 +126,23 @@ namespace Content.Server.Chemistry.EntitySystems
private void OnDispenseReagentMessage(Entity reagentDispenser, ref ReagentDispenserDispenseReagentMessage message)
{
// Ensure that the reagent is something this reagent dispenser can dispense.
- if (!GetInventory(reagentDispenser).Contains(message.ReagentId))
+ var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, message.SlotId);
+ if (storedContainer == null)
return;
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
- {
- // WD EDIT START
- var chemMasterUid = reagentDispenser.Comp.ChemMaster;
- if (!reagentDispenser.Comp.ChemMasterInRange ||
- !TryComp(chemMasterUid, out ChemMasterComponent? chemMaster) ||
- !TryComp(chemMasterUid, out SolutionContainerManagerComponent? solutionContainer) ||
- !_solutionContainerSystem.TryGetSolution((chemMasterUid.Value, solutionContainer),
- SharedChemMaster.BufferSolutionName, out var bufferSolution))
- return;
-
- bufferSolution.Value.Comp.Solution.AddReagent(message.ReagentId, FixedPoint2.New((int)reagentDispenser.Comp.DispenseAmount));
- _chemMasterSystem.UpdateUiState((chemMasterUid.Value, chemMaster));
- ClickSound(reagentDispenser);
-
return;
- } // WD EDIT END
- if (_solutionContainerSystem.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
- && message.Session.AttachedEntity is not null)
+ if (_solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out var src, out _) &&
+ _solutionContainerSystem.TryGetRefillableSolution(outputContainer.Value, out var dst, out _))
{
- _adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium,
- $"{ToPrettyString(message.Session.AttachedEntity.Value):player} dispensed {dispensedAmount}u of {message.ReagentId} into {ToPrettyString(outputContainer.Value):entity}");
+ // force open container, if applicable, to avoid confusing people on why it doesn't dispense
+ _openable.SetOpen(storedContainer.Value, true);
+ _solutionTransferSystem.Transfer(reagentDispenser,
+ storedContainer.Value, src.Value,
+ outputContainer.Value, dst.Value,
+ (int)reagentDispenser.Comp.DispenseAmount);
}
UpdateUiState(reagentDispenser);
@@ -271,5 +164,41 @@ namespace Content.Server.Chemistry.EntitySystems
{
_audioSystem.PlayPvs(reagentDispenser.Comp.ClickSound, reagentDispenser, AudioParams.Default.WithVolume(-2f));
}
+
+ ///
+ /// Automatically generate storage slots for all NumSlots, and fill them with their initial chemicals.
+ /// The actual spawning of entities happens in ItemSlotsSystem's MapInit.
+ ///
+ private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
+ {
+ // Get list of pre-loaded containers
+ List preLoad = new List();
+ if (component.PackPrototypeId is not null
+ && _prototypeManager.TryIndex(component.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
+ {
+ preLoad.AddRange(packPrototype.Inventory);
+ }
+
+ // Populate storage slots with base storage slot whitelist
+ for (var i = 0; i < component.NumSlots; i++)
+ {
+ var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
+ ItemSlot storageComponent = new();
+ storageComponent.Whitelist = component.StorageWhitelist;
+ storageComponent.Swap = false;
+ storageComponent.EjectOnBreak = true;
+
+ // Check corresponding index in pre-loaded container (if exists) and set starting item
+ if (i < preLoad.Count)
+ storageComponent.StartingItem = preLoad[i];
+
+ component.StorageSlotIds.Add(storageSlotId);
+ component.StorageSlots.Add(storageComponent);
+ component.StorageSlots[i].Name = "Storage Slot " + (i+1);
+ _itemSlotsSystem.AddItemSlot(uid, component.StorageSlotIds[i], component.StorageSlots[i]);
+ }
+
+ _itemSlotsSystem.AddItemSlot(uid, SharedReagentDispenser.OutputSlotName, component.BeakerSlot);
+ }
}
}
diff --git a/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs b/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs
index c362535e4f..5cdc8aed80 100644
--- a/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs
+++ b/Content.Shared/Chemistry/Dispenser/ReagentDispenserInventoryPrototype.cs
@@ -1,4 +1,4 @@
-using Content.Shared.Chemistry.Reagent;
+using Content.Shared.Chemistry.Reagent;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
@@ -14,8 +14,7 @@ namespace Content.Shared.Chemistry.Dispenser
[Serializable, NetSerializable, Prototype("reagentDispenserInventory")]
public sealed partial class ReagentDispenserInventoryPrototype : IPrototype
{
- // TODO use ReagentId
- [DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer))]
+ [DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer))]
public List Inventory = new();
[ViewVariables, IdDataField]
diff --git a/Content.Shared/Chemistry/SharedReagentDispenser.cs b/Content.Shared/Chemistry/SharedReagentDispenser.cs
index bfae45ea95..c7ecd0ff43 100644
--- a/Content.Shared/Chemistry/SharedReagentDispenser.cs
+++ b/Content.Shared/Chemistry/SharedReagentDispenser.cs
@@ -1,67 +1,133 @@
using Content.Shared.Chemistry.Reagent;
+using Content.Shared.FixedPoint;
using Robust.Shared.Serialization;
-namespace Content.Shared.Chemistry;
-
-///
-/// This class holds constants that are shared between client and server.
-///
-public sealed class SharedReagentDispenser
+namespace Content.Shared.Chemistry
{
- public const string OutputSlotName = "beakerSlot";
-}
-
-[Serializable, NetSerializable]
-public sealed class ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount amount)
- : BoundUserInterfaceMessage
-{
- public readonly ReagentDispenserDispenseAmount ReagentDispenserDispenseAmount = amount;
-}
-
-[Serializable, NetSerializable]
-public sealed class ReagentDispenserDispenseReagentMessage(ReagentId reagentId) : BoundUserInterfaceMessage
-{
- public readonly ReagentId ReagentId = reagentId;
-}
-
-[Serializable, NetSerializable]
-public sealed class ReagentDispenserClearContainerSolutionMessage : BoundUserInterfaceMessage;
-
-public enum ReagentDispenserDispenseAmount
-{
- U1 = 1,
- U5 = 5,
- U10 = 10,
- U15 = 15,
- U20 = 20,
- U25 = 25,
- U30 = 30,
- U50 = 50,
- U100 = 100,
-}
-
-[Serializable, NetSerializable]
-public sealed class ReagentDispenserBoundUserInterfaceState(
- ContainerInfo? outputContainer,
- NetEntity? outputContainerEntity,
- List inventory,
- ReagentDispenserDispenseAmount selectedDispenseAmount)
- : BoundUserInterfaceState
-{
- public readonly ContainerInfo? OutputContainer = outputContainer;
-
- public readonly NetEntity? OutputContainerEntity = outputContainerEntity;
-
///
- /// A list of the reagents which this dispenser can dispense.
+ /// This class holds constants that are shared between client and server.
///
- public readonly List Inventory = inventory;
+ public sealed class SharedReagentDispenser
+ {
+ public const string OutputSlotName = "beakerSlot";
+ }
- public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount = selectedDispenseAmount;
+ [Serializable, NetSerializable]
+ public sealed class ReagentDispenserSetDispenseAmountMessage : BoundUserInterfaceMessage
+ {
+ public readonly ReagentDispenserDispenseAmount ReagentDispenserDispenseAmount;
+
+ public ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount amount)
+ {
+ ReagentDispenserDispenseAmount = amount;
+ }
+
+ ///
+ /// Create a new instance from interpreting a String as an integer,
+ /// throwing an exception if it is unable to parse.
+ ///
+ public ReagentDispenserSetDispenseAmountMessage(String s)
+ {
+ switch (s)
+ {
+ case "1":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U1;
+ break;
+ case "5":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U5;
+ break;
+ case "10":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U10;
+ break;
+ case "15":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U15;
+ break;
+ case "20":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U20;
+ break;
+ case "25":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U25;
+ break;
+ case "30":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U30;
+ break;
+ case "50":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U50;
+ break;
+ case "100":
+ ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U100;
+ break;
+ default:
+ throw new Exception($"Cannot convert the string `{s}` into a valid ReagentDispenser DispenseAmount");
+ }
+ }
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage
+ {
+ public readonly string SlotId;
+
+ public ReagentDispenserDispenseReagentMessage(string slotId)
+ {
+ SlotId = slotId;
+ }
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class ReagentDispenserClearContainerSolutionMessage : BoundUserInterfaceMessage
+ {
+
+ }
+
+ public enum ReagentDispenserDispenseAmount
+ {
+ U1 = 1,
+ U5 = 5,
+ U10 = 10,
+ U15 = 15,
+ U20 = 20,
+ U25 = 25,
+ U30 = 30,
+ U50 = 50,
+ U100 = 100,
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class ReagentInventoryItem(string storageSlotId, string reagentLabel, FixedPoint2 quantity, Color reagentColor)
+ {
+ public string StorageSlotId = storageSlotId;
+ public string ReagentLabel = reagentLabel;
+ public FixedPoint2 Quantity = quantity;
+ public Color ReagentColor = reagentColor;
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState
+ {
+ public readonly ContainerInfo? OutputContainer;
+
+ public readonly NetEntity? OutputContainerEntity;
+
+ ///
+ /// A list of the reagents which this dispenser can dispense.
+ ///
+ public readonly List Inventory;
+
+ public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount;
+
+ public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, NetEntity? outputContainerEntity, List inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
+ {
+ OutputContainer = outputContainer;
+ OutputContainerEntity = outputContainerEntity;
+ Inventory = inventory;
+ SelectedDispenseAmount = selectedDispenseAmount;
+ }
+ }
+
+ [Serializable, NetSerializable]
+ public enum ReagentDispenserUiKey
+ {
+ Key
+ }
}
-
-[Serializable, NetSerializable]
-public enum ReagentDispenserUiKey
-{
- Key
-}
\ No newline at end of file
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
index 7904816f57..372d9a980b 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
@@ -12,14 +12,16 @@ namespace Content.Shared.Containers.ItemSlots
/// Used for entities that can hold items in different slots. Needed by ItemSlotSystem to support basic
/// insert/eject interactions.
///
- [RegisterComponent, Access(typeof(ItemSlotsSystem)), NetworkedComponent]
+ [RegisterComponent]
+ [Access(typeof(ItemSlotsSystem))]
+ [NetworkedComponent]
public sealed partial class ItemSlotsComponent : Component
{
///
/// The dictionary that stores all of the item slots whose interactions will be managed by the .
///
- [DataField(readOnly: true)]
+ [DataField("slots", readOnly:true)]
public Dictionary Slots = new();
// There are two ways to use item slots:
@@ -39,21 +41,26 @@ namespace Content.Shared.Containers.ItemSlots
}
[Serializable, NetSerializable]
- public sealed class ItemSlotsComponentState(Dictionary slots) : ComponentState
+ public sealed class ItemSlotsComponentState : ComponentState
{
- public readonly Dictionary Slots = slots;
+ public readonly Dictionary Slots;
+
+ public ItemSlotsComponentState(Dictionary slots)
+ {
+ Slots = slots;
+ }
}
///
/// This is effectively a wrapper for a ContainerSlot that adds content functionality like entity whitelists and
/// insert/eject sounds.
///
- [DataDefinition, Access(typeof(ItemSlotsSystem)), Serializable, NetSerializable]
+ [DataDefinition]
+ [Access(typeof(ItemSlotsSystem))]
+ [Serializable, NetSerializable]
public sealed partial class ItemSlot
{
- public ItemSlot()
- {
- }
+ public ItemSlot() { }
public ItemSlot(ItemSlot other)
{
@@ -61,6 +68,7 @@ namespace Content.Shared.Containers.ItemSlots
}
[DataField]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
public EntityWhitelist? Whitelist;
[DataField]
@@ -79,8 +87,8 @@ namespace Content.Shared.Containers.ItemSlots
/// This will be passed through Loc.GetString. If the name is an empty string, then verbs will use the name
/// of the currently held or currently inserted entity instead.
///
- [DataField(readOnly: true), Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
- // FIXME Friends
+ [DataField(readOnly: true)]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
public string Name = string.Empty;
///
@@ -91,9 +99,9 @@ namespace Content.Shared.Containers.ItemSlots
/// property of that component (e.g., cell slot size category), and this can lead to unnecessary changes
/// when mapping.
///
- [DataField(readOnly: true, customTypeSerializer: typeof(PrototypeIdSerializer)),
- Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute), NonSerialized]
- // FIXME Friends
+ [DataField(readOnly: true, customTypeSerializer: typeof(PrototypeIdSerializer))]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+ [NonSerialized]
public string? StartingItem;
///
@@ -103,8 +111,9 @@ namespace Content.Shared.Containers.ItemSlots
/// This doesn't have to mean the slot is somehow physically locked. In the case of the item cabinet, the
/// cabinet may simply be closed at the moment and needs to be opened first.
///
- [DataField(readOnly: true), ViewVariables(VVAccess.ReadWrite)]
- public bool Locked;
+ [DataField(readOnly: true)]
+ [ViewVariables(VVAccess.ReadWrite)]
+ public bool Locked = false;
///
/// Prevents adding the eject alt-verb, but still lets you swap items.
@@ -113,7 +122,7 @@ namespace Content.Shared.Containers.ItemSlots
/// This does not affect EjectOnInteract, since if you do that you probably want ejecting to work.
///
[DataField, ViewVariables(VVAccess.ReadWrite)]
- public bool DisableEject;
+ public bool DisableEject = false;
///
/// Whether the item slots system will attempt to insert item from the user's hands into this slot when interacted with.
@@ -131,7 +140,7 @@ namespace Content.Shared.Containers.ItemSlots
/// contents when clicked on normally.
///
[DataField]
- public bool EjectOnInteract;
+ public bool EjectOnInteract = false;
///
/// If true, and if this slot is attached to an item, then it will attempt to eject slot when to the slot is
@@ -143,7 +152,7 @@ namespace Content.Shared.Containers.ItemSlots
/// menu, nor will it disable alt-click interactions.
///
[DataField]
- public bool EjectOnUse;
+ public bool EjectOnUse = false;
///
/// Override the insert verb text. Defaults to using the slot's name (if specified) or the name of the
@@ -160,7 +169,7 @@ namespace Content.Shared.Containers.ItemSlots
public string? EjectVerbText;
[ViewVariables, NonSerialized]
- public ContainerSlot? ContainerSlot;
+ public ContainerSlot? ContainerSlot = default!;
///
/// If this slot belongs to some de-constructible component, should the item inside the slot be ejected upon
@@ -169,15 +178,19 @@ namespace Content.Shared.Containers.ItemSlots
///
/// The actual deconstruction logic is handled by the server-side EmptyOnMachineDeconstructSystem.
///
- [DataField, NonSerialized]
+ [DataField]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
+ [NonSerialized]
public bool EjectOnDeconstruct = true;
///
/// If this slot belongs to some breakable or destructible entity, should the item inside the slot be
/// ejected when it is broken or destroyed?
///
- [DataField, NonSerialized]
- public bool EjectOnBreak;
+ [DataField]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
+ [NonSerialized]
+ public bool EjectOnBreak = false;
///
/// When specified, a popup will be generated whenever someone attempts to insert a bad item into this slot.
@@ -207,23 +220,20 @@ namespace Content.Shared.Containers.ItemSlots
/// want to insert more than one item that matches the same whitelist.
///
[DataField]
+ [Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
public bool Swap = true;
public string? ID => ContainerSlot?.ID;
// Convenience properties
public bool HasItem => ContainerSlot?.ContainedEntity != null;
-
public EntityUid? Item => ContainerSlot?.ContainedEntity;
///
/// Priority for use with the eject & insert verbs for this slot.
///
[DataField]
- public int Priority;
-
- [DataField("maxStackAmount")] // WD
- public int MaxStackAmount;
+ public int Priority = 0;
///
/// If false, errors when adding an item slot with a duplicate key are suppressed. Local==true implies that
@@ -232,6 +242,9 @@ namespace Content.Shared.Containers.ItemSlots
[NonSerialized]
public bool Local = true;
+ [DataField] // WD
+ public int MaxStackAmount;
+
public void CopyFrom(ItemSlot other)
{
// These fields are mutable reference types. But they generally don't get modified, so this should be fine.
@@ -247,10 +260,10 @@ namespace Content.Shared.Containers.ItemSlots
InsertVerbText = other.InsertVerbText;
EjectVerbText = other.EjectVerbText;
WhitelistFailPopup = other.WhitelistFailPopup;
- LockedFailPopup = other.LockedFailPopup;
- InsertSuccessPopup = other.InsertSuccessPopup;
Swap = other.Swap;
Priority = other.Priority;
+
+ MaxStackAmount = other.MaxStackAmount;
}
}
@@ -258,21 +271,11 @@ namespace Content.Shared.Containers.ItemSlots
/// Event raised on the slot entity and the item being inserted to determine if an item can be inserted into an item slot.
///
[ByRefEvent]
- public record struct ItemSlotInsertAttemptEvent(
- EntityUid SlotEntity,
- EntityUid Item,
- EntityUid? User,
- ItemSlot Slot,
- bool Cancelled = false);
+ public record struct ItemSlotInsertAttemptEvent(EntityUid SlotEntity, EntityUid Item, EntityUid? User, ItemSlot Slot, bool Cancelled = false);
///
/// Event raised on the slot entity and the item being inserted to determine if an item can be ejected from an item slot.
///
[ByRefEvent]
- public record struct ItemSlotEjectAttemptEvent(
- EntityUid SlotEntity,
- EntityUid Item,
- EntityUid? User,
- ItemSlot Slot,
- bool Cancelled = false);
-}
\ No newline at end of file
+ public record struct ItemSlotEjectAttemptEvent(EntityUid SlotEntity, EntityUid Item, EntityUid? User, ItemSlot Slot, bool Cancelled = false);
+}
diff --git a/Resources/Locale/en-US/_white/reagents/fun.ftl b/Resources/Locale/en-US/_white/reagents/fun.ftl
new file mode 100644
index 0000000000..71016fb0c1
--- /dev/null
+++ b/Resources/Locale/en-US/_white/reagents/fun.ftl
@@ -0,0 +1,2 @@
+reagent-name-tranquility = tranquility
+reagent-desc-tranquility = Emits a strange aura of tranquility...
\ No newline at end of file
diff --git a/Resources/Locale/en-US/chemistry/components/reagent-dispenser-component.ftl b/Resources/Locale/en-US/chemistry/components/reagent-dispenser-component.ftl
index 48ec8f5213..37697c4517 100644
--- a/Resources/Locale/en-US/chemistry/components/reagent-dispenser-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/reagent-dispenser-component.ftl
@@ -10,9 +10,9 @@ reagent-dispenser-bound-user-interface-title = Reagent dispenser
## UI
reagent-dispenser-window-amount-to-dispense-label = Amount
-reagent-dispenser-window-container-label = Container:
reagent-dispenser-window-clear-button = Clear
reagent-dispenser-window-eject-button = Eject
+reagent-dispenser-window-eject-container-button = ⏏
reagent-dispenser-window-no-container-loaded-text = No container loaded.
reagent-dispenser-window-reagent-name-not-found-text = Reagent name not found
reagent-dispenser-window-unknown-reagent-text = Unknown reagent
diff --git a/Resources/Locale/en-US/reagents/meta/fun.ftl b/Resources/Locale/en-US/reagents/meta/fun.ftl
index a4a8c0f150..127fb7f45b 100644
--- a/Resources/Locale/en-US/reagents/meta/fun.ftl
+++ b/Resources/Locale/en-US/reagents/meta/fun.ftl
@@ -26,4 +26,4 @@ reagent-name-laughter = laughter
reagent-desc-laughter = Some say that this is the best medicine, but recent studies have proven that to be untrue.
reagent-name-weh = juice that makes you Weh
-reagent-desc-weh = Pure essence of lizard plush. Makes you Weh!
+reagent-desc-weh = Pure essence of lizard plush. Makes you Weh!
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/object/chemical/containers.ftl b/Resources/Locale/ru-RU/_white/object/chemical/containers.ftl
new file mode 100644
index 0000000000..9ffd8ca174
--- /dev/null
+++ b/Resources/Locale/ru-RU/_white/object/chemical/containers.ftl
@@ -0,0 +1,48 @@
+ent-ChemicalCartridge = химический картридж
+ .desc = Используется для хранения огромного количества химикатов. Используется в химических раздатчиках
+ent-ChemicalCartridgeCarbon = химический картридж (углерод)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeIodine = химический картридж (йод)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeFluorine = химический картридж (фтор)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeChlorine = химический картридж (хлор)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeAluminium = химический картридж (алюминий)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgePhosphorus = химический картридж (фосфор)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSulfur = химический картридж (сера)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSilicon = химический картридж (кремний)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeHydrogen = химический картридж (водород)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeLithium = химический картридж (литий)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSodium = химический картридж (натрий)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgePotassium = химический картридж (калий)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeRadium = химический картридж (радий)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeIron = химический картридж (железо)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeCopper = химический картридж (медь)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeGold = химический картридж (золото)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSugar = химический картридж (сахар)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeMercury = химический картридж (ртуть)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSilver = химический картридж (серебро)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeEthanol = химический картридж (этанол)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeSugar = химический картридж (сахар)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeNitrogen = химический картридж (азот)
+ .desc = { ent-ChemicalCartridge.desc }
+ent-ChemicalCartridgeOxygen = химический картридж (кислород)
+ .desc = { ent-ChemicalCartridge.desc }
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/reagents/fun.ftl b/Resources/Locale/ru-RU/_white/reagents/fun.ftl
index a6ac973807..bb938db24b 100644
--- a/Resources/Locale/ru-RU/_white/reagents/fun.ftl
+++ b/Resources/Locale/ru-RU/_white/reagents/fun.ftl
@@ -1 +1,4 @@
reagent-popup-tranquility = Вы чувствуете себя странно спокойными...
+
+reagent-name-tranquility = спокойствие
+reagent-desc-tranquility = Источает странную ауру спокойствия...
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/_white/reagents/meta/medicine.ftl b/Resources/Locale/ru-RU/_white/reagents/meta/medicine.ftl
deleted file mode 100644
index 04619f4cba..0000000000
--- a/Resources/Locale/ru-RU/_white/reagents/meta/medicine.ftl
+++ /dev/null
@@ -1,4 +0,0 @@
-reagent-name-potassium-iodide = Йодид калия
-reagent-desc-potassium-iodide = Снижает поражающее действие радиации на 90%. Только для профилактического применения.
-reagent-name-haloperidol = Галоперидол
-reagent-desc-haloperidol = Выводит большинство стимулирующих/галлюциногенных препаратов. Уменьшает наркотические эффекты и нервозность. Вызывает сонливость.
diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-29.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-29.ftl
index e14a3f1356..173188e814 100644
--- a/Resources/Locale/ru-RU/locales-new/autotranslate-29.ftl
+++ b/Resources/Locale/ru-RU/locales-new/autotranslate-29.ftl
@@ -2,41 +2,32 @@ ent-EnergyShield = энергетический щит
.desc = Экзотический энергетический щит в сложенном виде может поместиться даже в кармане.
ent-BrokenEnergyShield = сломанный энергетический щит
.desc = Что-то внутри сгорело, оно больше не работает.
-ent-Jug = кувшин
- .desc = Используется для содержания очень большого количества химикатов или растворов. Пыхтение крайне опрометчиво.
-ent-JugCarbon = кувшин (углерод)
- .desc = { ent-Jug.desc }
-ent-JugIodine = кувшин (йод)
- .desc = { ent-Jug.desc }
-ent-JugFluorine = кувшин (фтор)
- .desc = { ent-Jug.desc }
-ent-JugChlorine = кувшин (хлор)
- .desc = { ent-Jug.desc }
-ent-JugAluminium = кувшин (алюминий)
- .desc = { ent-Jug.desc }
-ent-JugPhosphorus = кувшин (фосфор)
- .desc = { ent-Jug.desc }
-ent-JugSulfur = кувшин (сера)
- .desc = { ent-Jug.desc }
-ent-JugSilicon = кувшин (кремний)
- .desc = { ent-Jug.desc }
-ent-JugHydrogen = кувшин (водород)
- .desc = { ent-Jug.desc }
-ent-JugLithium = кувшин (литий)
- .desc = { ent-Jug.desc }
-ent-JugSodium = кувшин (натрий)
- .desc = { ent-Jug.desc }
-ent-JugPotassium = кувшин (калий)
- .desc = { ent-Jug.desc }
-ent-JugRadium = кувшин (радий)
- .desc = { ent-Jug.desc }
-ent-JugIron = кувшин (железо)
- .desc = { ent-Jug.desc }
-ent-JugCopper = кувшин (медь)
- .desc = { ent-Jug.desc }
-ent-JugGold = кувшин (золото)
- .desc = { ent-Jug.desc }
-ent-JugSugar = кувшин (сахар)
- .desc = { ent-Jug.desc }
-ent-JugWeldingFuel = кувшин (сварочное топливо)
- .desc = { ent-Jug.desc }
+
+ent-CognizineChemistryBottle = бутылка когнизина
+ .desc = { ent-BaseChemistryEmptyBottle.desc }
+ent-ToxinChemistryBottle = бутылка с токсином
+ .desc = { ent-BaseChemistryEmptyBottle.desc }
+ent-BaseBeakerMetallic = ""
+ .desc = ""
+ent-CryoxadoneBeakerSmall = стакан криоксадона
+ .desc = Заполнен реагентом, используемым в криогенных пробирках.
+ent-SyringeBluespace = блюспейс шприц
+ .desc = Внедрение передовой технологии bluespace.
+ent-SyndicateSponge = куб обезьяны
+ .desc = Просто добавь воды!
+ent-WatermelonSeeds = пакет арбузных семечек
+ .desc = { ent-SeedBase.desc }
+ent-GrapeSeeds = пакет виноградных косточек
+ .desc = { ent-SeedBase.desc }
+ent-MopBucketFull = Ведро для мытья пола
+ .desc = { ent-MopBucket.desc }
+ent-WetFloorSignMineExplosive = табличка 'Мокрый пол'
+ .desc = Осторожность! Мокрый пол!
+ent-Plunger = вантуз
+ .desc = Вантуз с красной пластиковой присоской и деревянной ручкой. Используется для прочистки стоков.
+ent-MegaSprayBottle = мега распылитель
+ .desc = Огромный распылитель, способный на непревзойденную уборочную мощь.
+ent-BigVapor = ""
+ .desc = ""
+ent-MechEquipmentGrabberSmall = небольшой гидравлический зажим
+ .desc = Дает меху возможность хватать предметы и перетаскивать их.
diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-30.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-30.ftl
deleted file mode 100644
index e3dac21515..0000000000
--- a/Resources/Locale/ru-RU/locales-new/autotranslate-30.ftl
+++ /dev/null
@@ -1,40 +0,0 @@
-ent-JugMercury = кувшин (ртуть)
- .desc = { ent-Jug.desc }
-ent-JugSilver = кувшин (серебро)
- .desc = { ent-Jug.desc }
-ent-JugEthanol = кувшин (этанол)
- .desc = { ent-Jug.desc }
-ent-JugSugar = jug (sugar)
- .desc = { ent-Jug.desc }
-ent-JugNitrogen = кувшин (азот)
- .desc = { ent-Jug.desc }
-ent-JugOxygen = кувшин (кислород)
- .desc = { ent-Jug.desc }
-ent-CognizineChemistryBottle = бутылка когнизина
- .desc = { ent-BaseChemistryEmptyBottle.desc }
-ent-ToxinChemistryBottle = бутылка с токсином
- .desc = { ent-BaseChemistryEmptyBottle.desc }
-ent-BaseBeakerMetallic = ""
- .desc = ""
-ent-CryoxadoneBeakerSmall = стакан криоксадона
- .desc = Заполнен реагентом, используемым в криогенных пробирках.
-ent-SyringeBluespace = блюспейс шприц
- .desc = Внедрение передовой технологии bluespace.
-ent-SyndicateSponge = куб обезьяны
- .desc = Просто добавь воды!
-ent-WatermelonSeeds = пакет арбузных семечек
- .desc = { ent-SeedBase.desc }
-ent-GrapeSeeds = пакет виноградных косточек
- .desc = { ent-SeedBase.desc }
-ent-MopBucketFull = Ведро для мытья пола
- .desc = { ent-MopBucket.desc }
-ent-WetFloorSignMineExplosive = табличка 'Мокрый пол'
- .desc = Осторожность! Мокрый пол!
-ent-Plunger = вантуз
- .desc = Вантуз с красной пластиковой присоской и деревянной ручкой. Используется для прочистки стоков.
-ent-MegaSprayBottle = мега распылитель
- .desc = Огромный распылитель, способный на непревзойденную уборочную мощь.
-ent-BigVapor = ""
- .desc = ""
-ent-MechEquipmentGrabberSmall = небольшой гидравлический зажим
- .desc = Дает меху возможность хватать предметы и перетаскивать их.
diff --git a/Resources/Locale/ru-RU/locales-new/autotranslate-40.ftl b/Resources/Locale/ru-RU/locales-new/autotranslate-40.ftl
index 6f04806b8d..ed86317f5e 100644
--- a/Resources/Locale/ru-RU/locales-new/autotranslate-40.ftl
+++ b/Resources/Locale/ru-RU/locales-new/autotranslate-40.ftl
@@ -26,8 +26,8 @@ ent-CrystalBlue = синий кристалл
.desc = Это блестящий синий кристалл.
ent-CrystalCyan = голубой кристалл
.desc = Это блестящий голубой кристалл.
-ent-ChemDispenser = дозатор химикатов
- .desc = Дозатор химикатов промышленного класса с большим запасом химикатов.
+ent-ChemDispenser = раздатчик химикатов
+ .desc = Раздатчик химикатов промышленного класса с большим запасом химикатов.
ent-AirlockExternalCargoLocked = { ent-AirlockExternal }
.desc = { ent-AirlockExternal.desc }
.suffix = Внешний, Карго, Закрыт
diff --git a/Resources/Locale/ru-RU/objects/chemical/storage.ftl b/Resources/Locale/ru-RU/objects/chemical/storage.ftl
new file mode 100644
index 0000000000..3fac71e9f0
--- /dev/null
+++ b/Resources/Locale/ru-RU/objects/chemical/storage.ftl
@@ -0,0 +1,50 @@
+ent-Jug = кувшин
+ .desc = Используется для содержания очень большого количества химикатов или растворов. Пыхтение крайне опрометчиво.
+ent-JugCarbon = кувшин (углерод)
+ .desc = { ent-Jug.desc }
+ent-JugIodine = кувшин (йод)
+ .desc = { ent-Jug.desc }
+ent-JugFluorine = кувшин (фтор)
+ .desc = { ent-Jug.desc }
+ent-JugChlorine = кувшин (хлор)
+ .desc = { ent-Jug.desc }
+ent-JugAluminium = кувшин (алюминий)
+ .desc = { ent-Jug.desc }
+ent-JugPhosphorus = кувшин (фосфор)
+ .desc = { ent-Jug.desc }
+ent-JugSulfur = кувшин (сера)
+ .desc = { ent-Jug.desc }
+ent-JugSilicon = кувшин (кремний)
+ .desc = { ent-Jug.desc }
+ent-JugHydrogen = кувшин (водород)
+ .desc = { ent-Jug.desc }
+ent-JugLithium = кувшин (литий)
+ .desc = { ent-Jug.desc }
+ent-JugSodium = кувшин (натрий)
+ .desc = { ent-Jug.desc }
+ent-JugPotassium = кувшин (калий)
+ .desc = { ent-Jug.desc }
+ent-JugRadium = кувшин (радий)
+ .desc = { ent-Jug.desc }
+ent-JugIron = кувшин (железо)
+ .desc = { ent-Jug.desc }
+ent-JugCopper = кувшин (медь)
+ .desc = { ent-Jug.desc }
+ent-JugGold = кувшин (золото)
+ .desc = { ent-Jug.desc }
+ent-JugSugar = кувшин (сахар)
+ .desc = { ent-Jug.desc }
+ent-JugWeldingFuel = кувшин (сварочное топливо)
+ .desc = { ent-Jug.desc }
+ent-JugMercury = кувшин (ртуть)
+ .desc = { ent-Jug.desc }
+ent-JugSilver = кувшин (серебро)
+ .desc = { ent-Jug.desc }
+ent-JugEthanol = кувшин (этанол)
+ .desc = { ent-Jug.desc }
+ent-JugSugar = кувшин (сахар)
+ .desc = { ent-Jug.desc }
+ent-JugNitrogen = кувшин (азот)
+ .desc = { ent-Jug.desc }
+ent-JugOxygen = кувшин (кислород)
+ .desc = { ent-Jug.desc }
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/reagents/meta/biological.ftl b/Resources/Locale/ru-RU/reagents/meta/biological.ftl
index f32e92faa4..c0f3154565 100644
--- a/Resources/Locale/ru-RU/reagents/meta/biological.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/biological.ftl
@@ -7,9 +7,15 @@ reagent-desc-insect-blood = Окей, это уже реально мерзко.
reagent-name-slime = слизь
reagent-desc-slime = Сначала вам показалось, что это градиент крови, но вы ошиблись.
+reagent-name-sap = живица
+reagent-desc-sap = Липкая, сладкая кровь деревьев.
+
reagent-name-hemocyanin-blood = синяя кровь
reagent-desc-hemocyanin-blood = Содержит медь, а не железо, что придаёт ей ярко выраженный голубой цвет.
+reagent-name-ammonia-blood = анаэробная кровь
+reagent-desc-ammonia-blood = Ничто во всей вселенной не пахнет так ужасно.
+
reagent-name-zombie-blood = кровь зомби
reagent-desc-zombie-blood = Не рекомендуется употреблять в пищу. Может быть использована для создания вакцины от инфекции.
@@ -21,3 +27,6 @@ reagent-desc-fat = Независимо от того, как он был пол
reagent-name-vomit = рвота
reagent-desc-vomit = Вы можете увидеть в ней несколько кусков чьей-то последней еды.
+
+reagent-name-grey-matter = серое вещество
+reagent-desc-grey-matter = Сок мыслей, вытекающий из ваших ушей.
diff --git a/Resources/Locale/ru-RU/reagents/meta/chemicals.ftl b/Resources/Locale/ru-RU/reagents/meta/chemicals.ftl
index a22a0cb8fc..4778af0a23 100644
--- a/Resources/Locale/ru-RU/reagents/meta/chemicals.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/chemicals.ftl
@@ -6,3 +6,22 @@ reagent-name-sodium-carbonate = карбонат натрия
reagent-desc-sodium-carbonate = Белая водорастворимая соль без запаха, которая образует щелочной раствор в воде. Также известен как кальцинированная сода.
reagent-name-artifexium = артистизм
reagent-desc-artifexium = Лавандовая смесь микроскопических фрагментов артефакта и сильной кислоты. Обладает способностью активировать артефакты..
+
+reagent-name-benzene = бензол
+reagent-desc-benzene = Ароматическое, слегка канцерогенное углеродное кольцо, образующее основу для многих органических соединений.
+
+reagent-name-hydroxide = гидроксид
+reagent-desc-hydroxide = Сильнощелочное химическое вещество, образующее основу для многих органических соединений.
+
+reagent-name-sodium-hydroxide = гидроксид натрия
+reagent-desc-sodium-hydroxide = Белая водорастворимая соль без запаха, образующая в воде сильный щелочной раствор. При проглатывании вызывает ожоги и рвоту.
+
+reagent-name-fersilicite = ферсилицит
+reagent-desc-fersilicite = Интерметаллическое соединение с необычными магнитными свойствами при низких температурах.
+
+reagent-name-sodium-polyacrylate = полиакрилат натрия
+reagent-desc-sodium-polyacrylate = Супервпитывающий полимер, имеющий разнообразное промышленное применение.
+
+reagent-name-cellulose = целлюлозные волокна
+reagent-desc-cellulose = Кристаллический полимер полидекстрозы. Растения любят этот материал.
+
diff --git a/Resources/Locale/ru-RU/reagents/meta/consumable/drink/drinks.ftl b/Resources/Locale/ru-RU/reagents/meta/consumable/drink/drinks.ftl
index 3a9706b5e3..0268d7063e 100644
--- a/Resources/Locale/ru-RU/reagents/meta/consumable/drink/drinks.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/consumable/drink/drinks.ftl
@@ -30,8 +30,8 @@ reagent-name-nothing = ничего
reagent-desc-nothing = Абсолютно ничего.
reagent-name-nuclear-cola = ядерная кола
reagent-desc-nuclear-cola = Кола, кола никогда не меняется.
-reagent-name-soda-water = содовая
-reagent-desc-soda-water = Газированная вода. Почему бы не сделать виски с содовой?
+reagent-name-soda-water = газировка
+reagent-desc-soda-water = Газированная вода. Почему бы не сделать виски с газировкой?
reagent-name-soy-latte = соевый латте
reagent-desc-soy-latte = Кофейный напиток, приготовленный из эспрессо и подогретого соевого молока.
reagent-name-tea = чай
diff --git a/Resources/Locale/ru-RU/reagents/meta/consumable/food/condiments.ftl b/Resources/Locale/ru-RU/reagents/meta/consumable/food/condiments.ftl
index a6848b4319..a61813e3d1 100644
--- a/Resources/Locale/ru-RU/reagents/meta/consumable/food/condiments.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/consumable/food/condiments.ftl
@@ -14,6 +14,10 @@ reagent-name-ketchup = кетчуп
reagent-desc-ketchup = Приготовлен из томатного пюре с добавлением специяй.
reagent-name-ketchunaise = кетчюнез
reagent-desc-ketchunaise = Так называемый русский соус, популярный среди космонавтов.
+
+reagent-name-laughin-syrup = Ржачный сироп
+reagent-desc-laughin-syrup = Сок Ржачных Бобов. Шипучий, и меняет вкус в зависимости от того, с чем его едят!
+
reagent-name-mayo = майонез
reagent-desc-mayo = Соус, сделанный из масла, яйца и немного (съедобной) кислоты.
reagent-name-vinaigrette = винегрет
@@ -22,3 +26,9 @@ reagent-name-soysauce = соевый соус
reagent-desc-soysauce = Соленая приправа на основе сои.
reagent-name-table-salt = столовая соль
reagent-desc-table-salt = Хлорид натрия, широко известный как соль, часто используется в качестве пищевой приправы или для мгновенного уничтожения мозговых червей.
+
+reagent-name-mustard = горчица
+reagent-desc-mustard = Желтая горчица, изготовленная из семян горчичного растения.
+
+reagent-name-syrup = сироп
+reagent-desc-syrup = Вкусный сироп из древесного сока, более липкий, чем клей.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/reagents/meta/consumable/food/food.ftl b/Resources/Locale/ru-RU/reagents/meta/consumable/food/food.ftl
index 662c95485d..305beb965a 100644
--- a/Resources/Locale/ru-RU/reagents/meta/consumable/food/food.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/consumable/food/food.ftl
@@ -6,3 +6,12 @@ reagent-name-vitamin = витамины
reagent-desc-vitamin = Содержатся в здоровом, полноценном питании.
reagent-name-protein = протеины
reagent-desc-protein = Также известные как белки. Содержатся в некоторых блюдах, полезны для здоровья организма.
+
+reagent-name-cocoapowder = какао порошок
+reagent-desc-cocoapowder = Из лучших сортов какао-бобов
+
+reagent-name-butter = масло
+reagent-desc-butter = Вы можете ему верить!
+
+reagent-name-pumpkin-flesh = тыквенная мякоть
+reagent-desc-pumpkin-flesh = Мягкий, сладкий плод тыквы.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/reagents/meta/consumable/food/ingredients.ftl b/Resources/Locale/ru-RU/reagents/meta/consumable/food/ingredients.ftl
index 5971c5a5e4..9b56e3fb00 100644
--- a/Resources/Locale/ru-RU/reagents/meta/consumable/food/ingredients.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/consumable/food/ingredients.ftl
@@ -6,8 +6,12 @@ reagent-name-oats = овёс
reagent-desc-oats = Используется для различных вкусных целей.
reagent-name-enzyme = универсальный фермент
reagent-desc-enzyme = Используется в приготовлении различных блюд.
-reagent-name-egg = яйцо
-reagent-desc-egg = Используется в выпечке.
+reagent-name-egg = приготовленное яйцо
+reagent-desc-egg = Вареный куриный эмбрион. Очень вкусно!
+
+reagent-name-raw-egg = сырое яйцо
+reagent-desc-raw-egg = используется в готовке.
+
reagent-name-sugar = сахар
reagent-desc-sugar = Вкусный космический сахар!
reagent-name-blackpepper = чёрный перец
diff --git a/Resources/Locale/ru-RU/reagents/meta/fun.ftl b/Resources/Locale/ru-RU/reagents/meta/fun.ftl
index c460b83366..e36d6b9fac 100644
--- a/Resources/Locale/ru-RU/reagents/meta/fun.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/fun.ftl
@@ -10,3 +10,12 @@ reagent-name-saxoite = саксонит
reagent-desc-saxoite = Отдаёт джазом.
reagent-name-licoxide = ликоксид
reagent-desc-licoxide = Это выглядит... электризующе.
+
+reagent-name-fresium = Фрезиум
+reagent-desc-fresium = Загадочное соединение, замедляющее вибрацию атомов и молекул... каким-то образом. По-простому, от него становится холодно... ОЧЕНЬ холодно. При проглатывании может вызвать длительные проблемы с передвижением.
+
+reagent-name-weh = Сок, заставляющий вас Weh!
+reagent-desc-weh = Чистая эссенция игрушки ящера. Заставляет вас Weh!
+
+reagent-name-razorium = разориум
+reagent-desc-razorium = Странное неньютоновское химическое вещество. Образуется при объединении двух лекарств от физических повреждений. При попадании в организм образует миллионы крошечных острых лезвий. Очень острых.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/reagents/meta/medicine.ftl b/Resources/Locale/ru-RU/reagents/meta/medicine.ftl
index f8198140ab..be9cfc81a0 100644
--- a/Resources/Locale/ru-RU/reagents/meta/medicine.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/medicine.ftl
@@ -52,6 +52,9 @@ reagent-desc-barozine = Сильнодействующий химикат, пр
reagent-name-phalanximine = фалангимин
reagent-desc-phalanximine = Современный препарат, используемый при лечении рака. Вызывает умеренное лучевое поражение организма и тошноту. Потенциально может удалить ген смерти у растений.
+reagent-name-polypyrylium-oligomers = Полипирилиевые олигомеры
+reagent-desc-polypyrylium-oligomers = Пурпурная смесь коротких полиэлектролитных цепей, не синтезируемых в лаборатории. Лечат удушье и физические травмы. Со временем останавливает кровотечение.
+
reagent-name-ambuzol = амбузол
reagent-desc-ambuzol = Высокотехнологичный препарат, способный остановить развитие зомби-вируса.
@@ -138,3 +141,15 @@ reagent-desc-silversulfadiazine = Это соединение, обладающ
reagent-name-stypticpowder = кровоостанавливающая пудра
reagent-desc-stypticpowder = Кровоостанавливающий порошок из сульфата алюминия помогает остановить кровотечение и способствует заживлению телесных повреждений.
+
+reagent-name-mannitol = маннитол
+reagent-desc-mannitol = Устраняет повреждения мозга.
+
+reagent-name-psicodine = псикодин
+reagent-desc-psicodine = Подавляет тревогу и прочие формы ментальных проблем. Передозировка вызывает галлюцинации и интоксикацию.
+
+reagent-name-potassium-iodide = йодистый калий
+reagent-desc-potassium-iodide = Снижает поражающее действие от радиации на 90%. Только профилактическое применение.
+
+reagent-name-haloperidol = галоперидол
+reagent-desc-haloperidol = Выводит из организма большую часть стимулирующих или галлюцигенных химикатов. Вызывает сонливость.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/reagents/meta/narcotics.ftl b/Resources/Locale/ru-RU/reagents/meta/narcotics.ftl
index 9e05e41c63..51b3efd90b 100644
--- a/Resources/Locale/ru-RU/reagents/meta/narcotics.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/narcotics.ftl
@@ -10,7 +10,11 @@ reagent-name-thc = ТГК
reagent-desc-thc = Он же тетрагидроканнабинол. Основное психоактивное вещество в конопле.
reagent-name-thc-oil = масло ТГК
reagent-desc-thc-oil = Чистое масло ТГК, полученное из листьев конопли. Оно намного сильнее, чем в натуральной форме, и может использоваться для снятия хронической боли у пациентов.
-reagent-name-nicotine = никотин
+
+reagent-name-bananadine = бананадин
+reagent-desc-bananadine = Слабый психоделик, содержащийся в небольших в шкурках от бананов.
+
+reagent-name-nicotine = никотинколичествах
reagent-desc-nicotine = Опасен и вызывает сильное привыкание.
reagent-name-impedrezene = импедризин
reagent-desc-impedrezene = Наркотик, который лишает человека дееспособности, замедляя высшие функции клеток мозга. Вызывает обширные повреждения мозга.
@@ -22,3 +26,10 @@ reagent-name-mute-toxin = токсин немоты
reagent-desc-mute-toxin = Лишает вас возможности разговаривать пока в организме.
reagent-name-norepinephric-acid = норэпинефриновая кислота
reagent-desc-norepinephric-acid = Лишает вас возможности видеть пока усваивается организмом.
+
+reagent-name-tear-gas = слезоточивый газ
+reagent-desc-tear-gas = Химическое вещество, вызывающее сильное раздражение и слезы, обычно используемое при борьбе с толпой.
+
+reagent-name-happiness = счастье
+reagent-desc-happiness = Наполняет экстатическим оцепенением и вызывает незначительные травмы мозга. Вызывает привыкание крайне быстро. Передозировка вызывает резкие перепады настроения.
+
diff --git a/Resources/Locale/ru-RU/reagents/meta/toxins.ftl b/Resources/Locale/ru-RU/reagents/meta/toxins.ftl
index b7c8fc4d79..eabd9de90b 100644
--- a/Resources/Locale/ru-RU/reagents/meta/toxins.ftl
+++ b/Resources/Locale/ru-RU/reagents/meta/toxins.ftl
@@ -13,6 +13,9 @@ reagent-desc-polytrinic-acid = Чрезвычайно едкое химичес
reagent-name-chloral-hydrate = хлоралгидрат
reagent-desc-chloral-hydrate = Успокаивающее и гипнотическое химическое вещество. Обычно используется для усыпления других людей, независимо от того, хотят они этого или нет.
+reagent-name-gastrotoxin = гастротоксин
+reagent-desc-gastrotoxin = Токсичный побочный продукт разложения. Чаще всего встречается в просроченых продуктах.
+
reagent-name-ferrochromic-acid = феррохромовая кислота
reagent-desc-ferrochromic-acid = Слабоагрессивный раствор, не способный вызвать серьезную опасность, если только его не выпить.
@@ -72,3 +75,6 @@ reagent-desc-vestine = Вызывает негативную реакцию в
reagent-name-tazinide = тазинид
reagent-desc-tazinide = Очень опасная металлическая смесь, которая может нарушить возможность передвигаться благодаря электризующему воздействию.
+
+reagent-name-lipolicide = липолицид
+reagent-desc-lipolicide = Мощный токсин, который разрушает жировые клетки, значительно снижая массу тела за короткое время. Смертельно для тех, у кого нет питательных веществ в организме.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/crates/medical.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/crates/medical.ftl
index dd63709e48..f83fcef3b2 100644
--- a/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/crates/medical.ftl
+++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/catalog/fills/crates/medical.ftl
@@ -31,3 +31,10 @@ ent-CrateEmergencyAdvancedKit = Продвинутый аварийный наб
ent-CrateEmergencyRadiationKit = Аварийный набор выведения радиации
.desc = Ящик, содержащий 4 набора для выведения радиации.
.suffix = { "" }
+
+ent-CrateChemistryP = ящик химикатов (P)
+ .desc = Содержит химикаты из P-блока периодической таблицы элементов.
+ent-CrateChemistryS = ящик химикатов (S)
+ .desc = Содержит химикаты из S-блока периодической таблицы элементов.
+ent-CrateChemistryD = ящик химикатов (D)
+ .desc = Содержит химикаты из D-блока периодической таблицы элементов.
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks.ftl
index b0b3cc2817..6dae16068e 100644
--- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks.ftl
+++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks.ftl
@@ -71,7 +71,7 @@ ent-DrinkBooger = козявка
.desc = Фууу...
.suffix = { "" }
ent-DrinkBraveBullGlass = бокал храброго быка
- .desc = Текилла и кофейный ликер, объединенные в аппетитный микс. Выпьем.
+ .desc = Текила и кофейный ликер, объединенные в аппетитный микс. Выпьем.
.suffix = { "" }
ent-DrinkCarrotJuice = морковный сок
.desc = Как морковь, но не хрустит.
@@ -394,3 +394,7 @@ ent-DrinkGlassCoupeShaped = бокал
ent-DrinkFlaskBar = металлическая фляжка
.desc = Металлическая фляжка, часто выдаваемая барменом взаймы. Не забудьте вернуть ее!
.suffix = { "" }
+ent-DrinkIcedTeaJug = бидон холодного чая
+ .desc = Для тех, кто считает обычный чай слишком "горячим". Слабаки.
+ent-DrinkSugarJug = кувшин сахара
+ .desc = Некоторые люди кладут его в свое кофе. Отвратительно!
diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks_bottles.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks_bottles.ftl
index 37d337aa2b..781b02ab48 100644
--- a/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks_bottles.ftl
+++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/entities/objects/consumable/drinks/drinks_bottles.ftl
@@ -32,7 +32,7 @@ ent-DrinkMelonLiquorBottleFull = дынный ликёр Эмеральдин
.desc = Бутылка 23-градусного Дынного ликёра Эмеральдин. Сладкий и легкий.
.suffix = { "" }
ent-DrinkPatronBottleFull = бутылка покровителя в художественной обёртке
- .desc = Текилла с привкусом серебра, которую подают в ночных клубах по всей галактике.
+ .desc = Текила с привкусом серебра, которую подают в ночных клубах по всей галактике.
.suffix = { "" }
ent-DrinkPoisonWinebottleFull = бутылка колдовского бархата
.desc = Какая восхитительная упаковка для несомненно высококачественного вина! Урожай, должно быть, потрясающий!
diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml
index ccdc74d1b6..49cd51cd38 100644
--- a/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml
+++ b/Resources/Prototypes/Catalog/Cargo/cargo_vending.yml
@@ -114,7 +114,7 @@
sprite: Objects/Specific/Service/vending_machine_restock.rsi
state: base
product: CrateVendingMachineRestockChemVendFilled
- cost: 3820
+ cost: 4000
category: cargoproduct-category-name-medical
group: market
diff --git a/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml b/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml
index 089f560dc3..62b166ebc1 100644
--- a/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml
+++ b/Resources/Prototypes/Catalog/ReagentDispensers/beverage.yml
@@ -1,57 +1,43 @@
- type: reagentDispenserInventory
id: SodaDispenserInventory
inventory:
- - CoconutWater
- - Coffee
- - Cola
- - Cream
- - DrGibb
- - GreenTea
- - Ice
- - JuiceLime
- - JuiceOrange
- - LemonLime
- - RootBeer
- - SodaWater
- - SpaceMountainWind
- - SpaceUp
- - Sugar
- - Tea
- - TonicWater
- - JuiceWatermelon
+ - DrinkIceJug
+ - DrinkCoffeeJug
+ - DrinkCreamCartonXL
+ - DrinkTeaJug
+ - DrinkGreenTeaJug
+ - DrinkIcedTeaJug
+ - DrinkColaBottleFull
+ - DrinkSpaceMountainWindBottleFull
+ - DrinkDrGibbJug
+ - DrinkRootBeerJug
+ - DrinkSpaceUpBottleFull
+ - DrinkTonicWaterBottleFull
+ - DrinkSodaWaterBottleFull
+ - DrinkLemonLimeJug
+ - DrinkSugarJug
+ - DrinkJuiceOrangeCartonXL
+ - DrinkJuiceLimeCartonXL
+ - DrinkWaterMelonJuiceJug
- type: reagentDispenserInventory
id: BoozeDispenserInventory
inventory:
- - Beer
- - CoffeeLiqueur
- - Whiskey
- - Wine
- - Vodka
- - Gin
- - Rum
- - Tequila
- - Vermouth
- - Cognac
- - Ale
- - Mead
- ###Hacked
- #- Goldschlager
- #- Patron
- #- JuiceWatermelon
- #- JuiceBerry
-
-
-- type: reagentDispenserInventory
- id: SodaDispenserEmagInventory
- inventory:
- - FourteenLoko
- - Ephedrine
- - Histamine
-
-- type: reagentDispenserInventory
- id: BoozeDispenserEmagInventory
- inventory:
- - AtomicBomb
- - Ethanol
- - Iron
+ - DrinkLemonLimeJug
+ - DrinkSugarJug
+ - DrinkJuiceOrangeCartonXL
+ - DrinkJuiceLimeCartonXL
+ - DrinkTonicWaterBottleFull
+ - DrinkSodaWaterBottleFull
+ - DrinkBeerGrowler
+ - DrinkCoffeeLiqueurBottleFull
+ - DrinkWhiskeyBottleFull
+ - DrinkWineBottleFull
+ - DrinkVodkaBottleFull
+ - DrinkGinBottleFull
+ - DrinkRumBottleFull
+ - DrinkTequilaBottleFull
+ - DrinkVermouthBottleFull
+ - DrinkCognacBottleFull
+ - DrinkAleBottleFullGrowler
+ - DrinkMeadJug
diff --git a/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml b/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml
index 6d9c729fc9..f03eae1ff4 100644
--- a/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml
+++ b/Resources/Prototypes/Catalog/ReagentDispensers/chemical.yml
@@ -1,31 +1,26 @@
- type: reagentDispenserInventory
id: ChemDispenserStandardInventory
inventory:
- - Aluminium
- - Carbon
- - Chlorine
- - Copper
- - Ethanol
- - Fluorine
- - Sugar
- - Hydrogen
- - Iodine
- - Iron
- - Lithium
- - Mercury
- - Nitrogen
- - Oxygen
- - Phosphorus
- - Potassium
- - Radium
- - Silicon
- - Sodium
- - Sulfur
+ - ChemicalCartridgeAluminium
+ - ChemicalCartridgeCarbon
+ - ChemicalCartridgeChlorine
+ - ChemicalCartridgeCopper
+ - ChemicalCartridgeEthanol
+ - ChemicalCartridgeFluorine
+ - ChemicalCartridgeSugar
+ - ChemicalCartridgeHydrogen
+ - ChemicalCartridgeIodine
+ - ChemicalCartridgeIron
+ - ChemicalCartridgeLithium
+ - ChemicalCartridgeMercury
+ - ChemicalCartridgeNitrogen
+ - ChemicalCartridgeOxygen
+ - ChemicalCartridgePhosphorus
+ - ChemicalCartridgePotassium
+ - ChemicalCartridgeRadium
+ - ChemicalCartridgeSilicon
+ - ChemicalCartridgeSodium
+ - ChemicalCartridgeSulfur
- type: reagentDispenserInventory
- id: ChemDispenserEmaggedInventory
- inventory: ##Feel free to change this to something more interesting when more chems are added
- - Napalm
- - Toxin
- - Epinephrine
- - Ultravasculine
+ id: EmptyInventory
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/chemvend.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/chemvend.yml
index e8e47bade2..1c6ca424f3 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/chemvend.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/chemvend.yml
@@ -1,27 +1,28 @@
- type: vendingMachineInventory
id: ChemVendInventory
startingInventory:
- Jug: 2
- JugAluminium: 1
- JugCarbon: 1
- JugChlorine: 1
- JugCopper: 1
- JugEthanol: 1
- JugFluorine: 1
- JugHydrogen: 1
- JugIodine: 1
- JugIron: 1
- JugLithium: 1
- JugMercury: 1
- JugNitrogen: 1
- JugOxygen: 1
- JugPhosphorus: 1
- JugPotassium: 1
- JugRadium: 1
- JugSilicon: 1
- JugSodium: 1
- JugSugar: 1
- JugSulfur: 1
+ Jug: 8
+ ChemicalCartridge: 2
+ ChemicalCartridgeAluminium: 1
+ ChemicalCartridgeCarbon: 1
+ ChemicalCartridgeChlorine: 1
+ ChemicalCartridgeCopper: 1
+ ChemicalCartridgeEthanol: 1
+ ChemicalCartridgeFluorine: 1
+ ChemicalCartridgeHydrogen: 1
+ ChemicalCartridgeIodine: 1
+ ChemicalCartridgeIron: 1
+ ChemicalCartridgeLithium: 1
+ ChemicalCartridgeMercury: 1
+ ChemicalCartridgeNitrogen: 1
+ ChemicalCartridgeOxygen: 1
+ ChemicalCartridgePhosphorus: 1
+ ChemicalCartridgePotassium: 1
+ ChemicalCartridgeRadium: 1
+ ChemicalCartridgeSilicon: 1
+ ChemicalCartridgeSodium: 1
+ ChemicalCartridgeSugar: 1
+ ChemicalCartridgeSulfur: 1
emaggedInventory:
ToxinChemistryBottle: 1
diff --git a/Resources/Prototypes/Entities/Effects/chemistry_effects.yml b/Resources/Prototypes/Entities/Effects/chemistry_effects.yml
index e773cda116..9c80bbc15e 100644
--- a/Resources/Prototypes/Entities/Effects/chemistry_effects.yml
+++ b/Resources/Prototypes/Entities/Effects/chemistry_effects.yml
@@ -91,9 +91,8 @@
animationState: foam-dissolve
- type: Slippery
- type: StepTrigger
- # disabled until foam reagent duplication is fixed
- #- type: ScoopableSolution
- # solution: solutionArea
+ - type: ScoopableSolution
+ solution: solutionArea
- type: entity
id: MetalFoam
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
index 0b0f7e2af7..435fd2636d 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
@@ -212,7 +212,7 @@
- ReagentId: Cognac
Quantity: 100
- type: Label
- currentLabel: cognac
+ currentLabel: коньяк
- type: Sprite
sprite: Objects/Consumable/Drinks/cognacbottle.rsi
- type: Sealable
@@ -230,7 +230,7 @@
- ReagentId: Cola
Quantity: 100
- type: Label
- currentLabel: cola
+ currentLabel: кола
- type: Sprite
sprite: Objects/Consumable/Drinks/colabottle.rsi
- type: Sealable
@@ -268,7 +268,7 @@
- ReagentId: Gin
Quantity: 100
- type: Label
- currentLabel: gin
+ currentLabel: джин
- type: Sprite
sprite: Objects/Consumable/Drinks/ginbottle.rsi
- type: Sealable
@@ -302,7 +302,7 @@
- ReagentId: CoffeeLiqueur
Quantity: 100
- type: Label
- currentLabel: coffee liqueur
+ currentLabel: кофейный ликёр
- type: Sprite
sprite: Objects/Consumable/Drinks/coffeeliqueurbottle.rsi
- type: Sealable
@@ -378,7 +378,7 @@
- ReagentId: Rum
Quantity: 100
- type: Label
- currentLabel: rum
+ currentLabel: ром
- type: Sprite
sprite: Objects/Consumable/Drinks/rumbottle.rsi
- type: Sealable
@@ -397,7 +397,7 @@
Quantity: 100
- type: Drink
- type: Label
- currentLabel: space mountain wind
+ currentLabel: маунтин винд
- type: Sprite
sprite: Objects/Consumable/Drinks/space_mountain_wind_bottle.rsi
- type: Sealable
@@ -416,7 +416,7 @@
Quantity: 100
- type: Drink
- type: Label
- currentLabel: space-up
+ currentLabel: спейс-ап
- type: Sprite
sprite: Objects/Consumable/Drinks/space-up_bottle.rsi
- type: Sealable
@@ -434,7 +434,7 @@
- ReagentId: Tequila
Quantity: 100
- type: Label
- currentLabel: tequila
+ currentLabel: текила
- type: Sprite
sprite: Objects/Consumable/Drinks/tequillabottle.rsi
- type: Sealable
@@ -452,7 +452,7 @@
- ReagentId: Vermouth
Quantity: 100
- type: Label
- currentLabel: vermouth
+ currentLabel: вермут
- type: Sprite
sprite: Objects/Consumable/Drinks/vermouthbottle.rsi
- type: Sealable
@@ -470,7 +470,7 @@
- ReagentId: Vodka
Quantity: 100
- type: Label
- currentLabel: vodka
+ currentLabel: водка
- type: Sprite
sprite: Objects/Consumable/Drinks/vodkabottle.rsi
- type: Sealable
@@ -488,7 +488,7 @@
- ReagentId: Whiskey
Quantity: 100
- type: Label
- currentLabel: whiskey
+ currentLabel: виски
- type: Sprite
sprite: Objects/Consumable/Drinks/whiskeybottle.rsi
- type: Sealable
@@ -506,7 +506,7 @@
- ReagentId: Wine
Quantity: 100
- type: Label
- currentLabel: wine
+ currentLabel: вино
- type: Sprite
sprite: Objects/Consumable/Drinks/winebottle.rsi
- type: Sealable
@@ -553,7 +553,7 @@
- ReagentId: Beer
Quantity: 150
- type: Label
- currentLabel: beer
+ currentLabel: пиво
- type: Sprite
sprite: Objects/Consumable/Drinks/beer.rsi
- type: Openable
@@ -597,7 +597,7 @@
- ReagentId: Ale
Quantity: 150
- type: Label
- currentLabel: ale
+ currentLabel: эль
- type: Sprite
sprite: Objects/Consumable/Drinks/alebottle.rsi
- type: Openable
@@ -649,7 +649,7 @@
- ReagentId: SodaWater
Quantity: 150
- type: Label
- currentLabel: soda water
+ currentLabel: газировка
- type: entity
parent: DrinkWaterBottleFull
@@ -665,7 +665,7 @@
- ReagentId: TonicWater
Quantity: 150
- type: Label
- currentLabel: tonic water
+ currentLabel: тоник
- type: entity
parent: [DrinkBottleVisualsOpenable, DrinkBottleGlassBaseFull]
@@ -680,7 +680,7 @@
- ReagentId: Sake
Quantity: 50
- type: Label
- currentLabel: Sake
+ currentLabel: Саке
- type: Sprite
sprite: Objects/Consumable/Drinks/sakebottle.rsi
- type: Sealable
@@ -702,7 +702,7 @@
Quantity: 150
- type: Drink
- type: Label
- currentLabel: lime juice
+ currentLabel: лаймовый сок
- type: Sprite
sprite: Objects/Consumable/Drinks/limejuice.rsi
@@ -721,7 +721,7 @@
Quantity: 150
- type: Drink
- type: Label
- currentLabel: orange juice
+ currentLabel: апельсиновый сок
- type: Sprite
sprite: Objects/Consumable/Drinks/orangejuice.rsi
@@ -740,7 +740,7 @@
Quantity: 150
- type: Drink
- type: Label
- currentLabel: cream
+ currentLabel: сливки
- type: Sprite
sprite: Objects/Consumable/Drinks/cream.rsi
@@ -777,7 +777,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: lemon-lime
+ currentLabel: лимон-лайм
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -794,7 +794,7 @@
Quantity: 150
- type: Drink
- type: Label
- currentLabel: mead
+ currentLabel: медовуха
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -811,7 +811,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: ice
+ currentLabel: лёд
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -828,7 +828,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: coconut water
+ currentLabel: кокосовая вода
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -845,7 +845,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: coffee
+ currentLabel: кофе
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -862,7 +862,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: tea
+ currentLabel: чай
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -879,7 +879,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: green tea
+ currentLabel: зеленый чай
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -895,6 +895,8 @@
- ReagentId: IcedTea
Quantity: 300
- type: Drink
+ - type: Label
+ currentLabel: холодный чай
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -911,7 +913,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: dr gibb
+ currentLabel: доктор Гибб
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -928,7 +930,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: root beer
+ currentLabel: рутбир
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -945,7 +947,7 @@
Quantity: 300
- type: Drink
- type: Label
- currentLabel: watermelon juice
+ currentLabel: арбузный сок
- type: entity
parent: DrinkBottlePlasticBaseFull
@@ -962,7 +964,7 @@
Quantity: 100
- type: Drink
- type: Label
- currentLabel: red bool
+ currentLabel: редбул
- type: entity
parent: DrinkBottlePlasticBaseFull
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
index 3e2acf30ec..8d7641b01c 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
@@ -569,7 +569,7 @@
- type: Sprite
state: medical
- type: MachineBoard
- prototype: ChemDispenser
+ prototype: ChemDispenserEmpty
requirements:
Capacitor: 1
materialRequirements:
@@ -1187,7 +1187,7 @@
- type: Sprite
state: service
- type: MachineBoard
- prototype: BoozeDispenser
+ prototype: BoozeDispenserEmpty
materialRequirements:
Steel: 5
tagRequirements:
@@ -1220,7 +1220,7 @@
- type: Sprite
state: service
- type: MachineBoard
- prototype: soda_dispenser
+ prototype: SodaDispenserEmpty
materialRequirements:
Steel: 5
tagRequirements:
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml b/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
index 040ceb6b30..170e61efe2 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
@@ -43,40 +43,10 @@
- type: SolutionContainerVisuals
maxFillLevels: 6
fillBaseName: jug
- inHandsMaxFillLevels: 5
- inHandsFillBaseName: -fill-
- type: StaticPrice
price: 60
- - type: Damageable
- damageContainer: Inorganic
- - type: Destructible
- thresholds:
- - trigger:
- !type:DamageTrigger
- damage: 200
- behaviors:
- - !type:DoActsBehavior
- acts: [ "Destruction" ]
- - trigger:
- !type:DamageTrigger
- damage: 20
- behaviors:
- - !type:PlaySoundBehavior
- sound:
- collection: MetalBreak
- params:
- volume: -4
- - !type:SpillBehavior { }
- - !type:SpawnEntitiesBehavior
- spawn:
- SheetPlastic1:
- min: 0
- max: 1
- transferForensics: true
- - !type:DoActsBehavior
- acts: [ "Destruction" ]
- type: Label
- originalName: jug
+ originalName: кувшин
- type: MeleeWeapon
canBeBlocked: false
soundNoDamage:
diff --git a/Resources/Prototypes/Entities/Structures/Dispensers/base_structuredispensers.yml b/Resources/Prototypes/Entities/Structures/Dispensers/base_structuredispensers.yml
index c7df5e6ef4..8507bfed13 100644
--- a/Resources/Prototypes/Entities/Structures/Dispensers/base_structuredispensers.yml
+++ b/Resources/Prototypes/Entities/Structures/Dispensers/base_structuredispensers.yml
@@ -55,13 +55,15 @@
sound:
collection: MetalGlassBreak
- type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - Bottle
+ beakerSlot:
+ whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
+ whitelist:
+ components:
+ - FitsInDispenser
- type: ItemSlots
- slots:
- beakerSlot:
- whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
- whitelist:
- components:
- - FitsInDispenser
- type: ContainerContainer
containers:
machine_board: !type:Container
diff --git a/Resources/Prototypes/Entities/Structures/Dispensers/booze.yml b/Resources/Prototypes/Entities/Structures/Dispensers/booze.yml
index 712083b7ff..7bc12ca966 100644
--- a/Resources/Prototypes/Entities/Structures/Dispensers/booze.yml
+++ b/Resources/Prototypes/Entities/Structures/Dispensers/booze.yml
@@ -1,6 +1,7 @@
- type: entity
id: BoozeDispenser
name: booze dispenser
+ suffix: Filled
description: A booze dispenser with a single slot for a container to be filled.
parent: ReagentDispenserBase
components:
@@ -10,8 +11,10 @@
drawdepth: SmallObjects
state: booze
- type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - DrinkBottle
pack: BoozeDispenserInventory
- emagPack: BoozeDispenserEmagInventory
- type: Transform
noRot: false
- type: Machine
@@ -21,3 +24,14 @@
- Bartender
- type: StealTarget
stealGroup: BoozeDispenser
+
+- type: entity
+ id: BoozeDispenserEmpty
+ suffix: Empty
+ parent: BoozeDispenser
+ components:
+ - type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - DrinkBottle
+ pack: EmptyInventory
diff --git a/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml b/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml
index 09ec0a812e..6c70cf9bca 100644
--- a/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml
+++ b/Resources/Prototypes/Entities/Structures/Dispensers/chem.yml
@@ -1,16 +1,19 @@
- type: entity
id: ChemDispenser
name: chemical dispenser
+ suffix: Filled
parent: ReagentDispenserBase
- description: An industrial grade chemical dispenser with a sizeable chemical supply.
+ description: An industrial grade chemical dispenser.
components:
- type: Sprite
sprite: Structures/dispensers.rsi
state: industrial-working
snapCardinals: true
- type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - ChemDispensable
pack: ChemDispenserStandardInventory
- emagPack: ChemDispenserEmaggedInventory
- type: ApcPowerReceiver
- type: ExtensionCableReceiver
- type: Destructible
@@ -28,12 +31,21 @@
acts: ["Destruction"]
- type: Machine
board: ChemDispenserMachineCircuitboard
+ - type: Wires
+ boardName: wires-board-name-chemdispenser
+ layoutId: ChemDispenser
- type: GuideHelp
guides:
- Chemicals
- Chemist
- type: StealTarget
stealGroup: ChemDispenser
- - type: DeviceNetwork
- deviceNetId: Wired
- receiveFrequencyId: BasicDevice
+
+- type: entity
+ id: ChemDispenserEmpty
+ name: chemical dispenser
+ suffix: Empty
+ parent: ChemDispenser
+ components:
+ - type: ReagentDispenser
+ pack: EmptyInventory
diff --git a/Resources/Prototypes/Entities/Structures/Dispensers/soda.yml b/Resources/Prototypes/Entities/Structures/Dispensers/soda.yml
index 59fd97b2cf..72468973ee 100644
--- a/Resources/Prototypes/Entities/Structures/Dispensers/soda.yml
+++ b/Resources/Prototypes/Entities/Structures/Dispensers/soda.yml
@@ -1,6 +1,7 @@
- type: entity
id: soda_dispenser
name: soda dispenser
+ suffix: Filled
parent: ReagentDispenserBase
description: A beverage dispenser with a selection of soda and several other common beverages. Has a single fill slot for containers.
components:
@@ -10,8 +11,10 @@
drawdepth: SmallObjects
state: soda
- type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - DrinkBottle
pack: SodaDispenserInventory
- emagPack: SodaDispenserEmagInventory
- type: Transform
noRot: false
- type: Machine
@@ -19,3 +22,14 @@
- type: GuideHelp
guides:
- Bartender
+
+- type: entity
+ id: SodaDispenserEmpty
+ suffix: Empty
+ parent: soda_dispenser
+ components:
+ - type: ReagentDispenser
+ storageWhitelist:
+ tags:
+ - DrinkBottle
+ pack: EmptyInventory
diff --git a/Resources/Prototypes/_White/Entities/Objects/Specific/Chemical/containers.yml b/Resources/Prototypes/_White/Entities/Objects/Specific/Chemical/containers.yml
new file mode 100644
index 0000000000..605dbf690b
--- /dev/null
+++ b/Resources/Prototypes/_White/Entities/Objects/Specific/Chemical/containers.yml
@@ -0,0 +1,370 @@
+- type: entity
+ id: ChemicalCartridge
+ name: chemical cartridge
+ parent: [DrinkBottleVisualsOpenable, BaseItem]
+ description: Used to contain a very large amount of chemicals or solutions. Used in chemical dispensers
+ components:
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ maxVol: 500
+ canMix: true
+ - type: Openable
+ sound:
+ collection: bottleCloseSounds
+ closeable: true
+ closeSound:
+ collection: bottleCloseSounds
+ - type: Sprite
+ sprite: White/Objects/Specific/Chemical/chemical_cartridge.rsi
+ state: icon
+ scale: 0.8, 0.8
+ - type: Item
+ size: Huge
+ - type: RefillableSolution
+ solution: beaker
+ - type: DrainableSolution
+ solution: beaker
+ - type: ExaminableSolution
+ solution: beaker
+ - type: SolutionTransfer
+ canChangeTransferAmount: false
+ - type: Spillable
+ solution: beaker
+ - type: StaticPrice
+ price: 150
+ - type: Label
+ originalName: химический картридж
+ - type: Tag
+ tags:
+ - ChemDispensable
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (carbon)
+ id: ChemicalCartridgeCarbon
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-carbon
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Carbon
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (iodine)
+ id: ChemicalCartridgeIodine
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-iodine
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Iodine
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (fluorine)
+ id: ChemicalCartridgeFluorine
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-fluorine
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Fluorine
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (chlorine)
+ id: ChemicalCartridgeChlorine
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-chlorine
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Chlorine
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (aluminium)
+ id: ChemicalCartridgeAluminium
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-aluminium
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Aluminium
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (phosphorus)
+ id: ChemicalCartridgePhosphorus
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-phosphorus
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Phosphorus
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (sulfur)
+ id: ChemicalCartridgeSulfur
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-sulfur
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Sulfur
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (silicon)
+ id: ChemicalCartridgeSilicon
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-silicon
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Silicon
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (hydrogen)
+ id: ChemicalCartridgeHydrogen
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-hydrogen
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Hydrogen
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (lithium)
+ id: ChemicalCartridgeLithium
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-lithium
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Lithium
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (sodium)
+ id: ChemicalCartridgeSodium
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-sodium
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Sodium
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (potassium)
+ id: ChemicalCartridgePotassium
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-potassium
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Potassium
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (radium)
+ id: ChemicalCartridgeRadium
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-radium
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Radium
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (iron)
+ id: ChemicalCartridgeIron
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-iron
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Iron
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (copper)
+ id: ChemicalCartridgeCopper
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-copper
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Copper
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (gold)
+ id: ChemicalCartridgeGold
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-gold
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Gold
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (mercury)
+ id: ChemicalCartridgeMercury
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-mercury
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Mercury
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (silver)
+ id: ChemicalCartridgeSilver
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-silver
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Silver
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (ethanol)
+ id: ChemicalCartridgeEthanol
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-ethanol
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Ethanol
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (Sugar)
+ id: ChemicalCartridgeSugar
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-sugar
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Sugar
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (nitrogen)
+ id: ChemicalCartridgeNitrogen
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-nitrogen
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Nitrogen
+ Quantity: 500
+
+- type: entity
+ parent: ChemicalCartridge
+ name: chemical cartridge (oxygen)
+ id: ChemicalCartridgeOxygen
+ noSpawn: true
+ components:
+ - type: Label
+ currentLabel: reagent-name-oxygen
+ - type: SolutionContainerManager
+ solutions:
+ beaker:
+ reagents:
+ - ReagentId: Oxygen
+ Quantity: 500
\ No newline at end of file
diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml
index 72c2e46d9b..b05d664b08 100644
--- a/Resources/Prototypes/tags.yml
+++ b/Resources/Prototypes/tags.yml
@@ -263,7 +263,7 @@
- type: Tag
id: CannonBall
-
+
- type: Tag
id: CannonRestrict
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon.png
new file mode 100644
index 0000000000..5330b43eb3
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon_open.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon_open.png
new file mode 100644
index 0000000000..9acb493764
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/icon_open.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left-open.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left-open.png
new file mode 100644
index 0000000000..4631bf6295
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left-open.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left.png
new file mode 100644
index 0000000000..0565dd5fb8
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-left.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right-open.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right-open.png
new file mode 100644
index 0000000000..c6931fae90
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right-open.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right.png b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right.png
new file mode 100644
index 0000000000..f72d03ca3c
Binary files /dev/null and b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/inhand-right.png differ
diff --git a/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/meta.json b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/meta.json
new file mode 100644
index 0000000000..6af17830f7
--- /dev/null
+++ b/Resources/Textures/White/Objects/Specific/Chemical/chemical_cartridge.rsi/meta.json
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by 6mirage6",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ },
+ {
+ "name": "icon_open"
+ },
+ {
+ "name": "inhand-left-open",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right-open",
+ "directions": 4
+ }
+ ]
+}