Add limited-reagent dispensers (#23907)
* Add limited-reagent dispensers * Add empty versions for all dispensers * Fix lint * Set initial window size so all buttons are visible * Simplify logic, add parenthesis * Use localized name for initial labels * Adjust button style * Avoid touching items before MapInit * Remove pre-labeling * Reduce diff * Clean up YAML * Fix test * Really fix test * Document * Adjust based on review * Add labels for obnoxiously long bottles --------- Co-authored-by: AWF <you@example.com>
This commit is contained in:
@@ -57,13 +57,23 @@ namespace Content.Client.Chemistry.UI
|
||||
_window.OnDispenseReagentButtonMouseEntered += (args, button) =>
|
||||
{
|
||||
if (_lastState is not null)
|
||||
_window.UpdateContainerInfo(_lastState, button.ReagentId);
|
||||
_window.UpdateContainerInfo(_lastState);
|
||||
};
|
||||
_window.OnDispenseReagentButtonMouseExited += (args, button) =>
|
||||
{
|
||||
if (_lastState is not null)
|
||||
_window.UpdateContainerInfo(_lastState);
|
||||
};
|
||||
|
||||
_window.OnEjectJugButtonPressed += (args, button) => SendMessage(new ItemSlotButtonPressedEvent(button.ReagentId));
|
||||
_window.OnEjectJugButtonMouseEntered += (args, button) => {
|
||||
if (_lastState is not null)
|
||||
_window.UpdateContainerInfo(_lastState);
|
||||
};
|
||||
_window.OnEjectJugButtonMouseExited += (args, button) => {
|
||||
if (_lastState is not null)
|
||||
_window.UpdateContainerInfo(_lastState);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
Title="{Loc 'reagent-dispenser-bound-user-interface-title'}"
|
||||
SetSize="620 450"
|
||||
MinSize="620 450">
|
||||
MinSize="680 450">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}"/>
|
||||
@@ -18,10 +17,8 @@
|
||||
<Button Name="DispenseButton100" Access="Public" Text="100" StyleClasses="OpenLeft"/>
|
||||
</BoxContainer>
|
||||
<Control MinSize="0 10"/>
|
||||
<ScrollContainer HScrollEnabled="False" HorizontalExpand="True" MinSize="0 170">
|
||||
<GridContainer Name="ChemicalList" Access="Public" Columns="4">
|
||||
<GridContainer Name="ChemicalList" HorizontalExpand="True" VerticalExpand="True" Access="Public" Columns="6">
|
||||
</GridContainer>
|
||||
</ScrollContainer>
|
||||
<Control MinSize="0 10"/>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'reagent-dispenser-window-container-label'}"/>
|
||||
|
||||
@@ -23,6 +23,10 @@ namespace Content.Client.Chemistry.UI
|
||||
public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseEntered;
|
||||
public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseExited;
|
||||
|
||||
public event Action<BaseButton.ButtonEventArgs, EjectJugButton>? OnEjectJugButtonPressed;
|
||||
public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseEntered;
|
||||
public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseExited;
|
||||
|
||||
/// <summary>
|
||||
/// Create and initialize the dispenser UI client-side. Creates the basic layout,
|
||||
/// actual data isn't filled in until the server sends data about the dispenser.
|
||||
@@ -48,25 +52,25 @@ namespace Content.Client.Chemistry.UI
|
||||
/// Update the button grid of reagents which can be dispensed.
|
||||
/// </summary>
|
||||
/// <param name="inventory">Reagents which can be dispensed by this dispenser</param>
|
||||
public void UpdateReagentsList(List<ReagentId> inventory)
|
||||
public void UpdateReagentsList(List<KeyValuePair<string, KeyValuePair<string,string>>> inventory)
|
||||
{
|
||||
if (ChemicalList == null)
|
||||
return;
|
||||
|
||||
ChemicalList.Children.Clear();
|
||||
|
||||
foreach (var entry in inventory
|
||||
.OrderBy(r => {_prototypeManager.TryIndex(r.Prototype, out ReagentPrototype? p); return p?.LocalizedName;}))
|
||||
foreach (KeyValuePair<string, KeyValuePair<string, string>> entry 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);
|
||||
var button = new DispenseReagentButton(entry.Key, entry.Value.Key, entry.Value.Value);
|
||||
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 ejectButton = new EjectJugButton(entry.Key);
|
||||
ejectButton.OnPressed += args => OnEjectJugButtonPressed?.Invoke(args, ejectButton);
|
||||
ejectButton.OnMouseEntered += args => OnEjectJugButtonMouseEntered?.Invoke(args, ejectButton);
|
||||
ejectButton.OnMouseExited += args => OnEjectJugButtonMouseExited?.Invoke(args, ejectButton);
|
||||
ChemicalList.AddChild(ejectButton);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,9 +125,8 @@ namespace Content.Client.Chemistry.UI
|
||||
/// <para>Also highlights a reagent if it's dispense button is being mouse hovered.</para>
|
||||
/// </summary>
|
||||
/// <param name="state">State data for the dispenser.</param>
|
||||
/// <param name="highlightedReagentId">Prototype ID of the reagent whose dispense button is currently being mouse hovered,
|
||||
/// or null if no button is being hovered.</param>
|
||||
public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state, ReagentId? highlightedReagentId = null)
|
||||
public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state)
|
||||
{
|
||||
ContainerInfo.Children.Clear();
|
||||
|
||||
@@ -161,12 +164,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,
|
||||
@@ -180,13 +177,27 @@ namespace Content.Client.Chemistry.UI
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DispenseReagentButton : Button {
|
||||
public ReagentId ReagentId { get; }
|
||||
|
||||
public DispenseReagentButton(ReagentId reagentId, string text)
|
||||
public sealed class DispenseReagentButton : Button
|
||||
{
|
||||
public string ReagentId { get; }
|
||||
|
||||
public DispenseReagentButton(string reagentId, string text, string amount)
|
||||
{
|
||||
AddStyleClass("OpenRight");
|
||||
ReagentId = reagentId;
|
||||
Text = text;
|
||||
Text = text + " " + amount;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EjectJugButton : Button
|
||||
{
|
||||
public string ReagentId { get; }
|
||||
|
||||
public EjectJugButton(string reagentId)
|
||||
{
|
||||
AddStyleClass("OpenLeft");
|
||||
ReagentId = reagentId;
|
||||
Text = "⏏";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(ReagentDispenserComponent.BeakerSlotId);
|
||||
await SendBui(ReagentDispenserUiKey.Key, ev);
|
||||
|
||||
// Beaker is back in the player's hands
|
||||
|
||||
@@ -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,57 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
|
||||
namespace Content.Server.Chemistry.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A machine that dispenses reagents into a solution container.
|
||||
/// A machine that dispenses reagents into a solution container from containers in its storage slots.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[Access(typeof(ReagentDispenserSystem))]
|
||||
public sealed partial class ReagentDispenserComponent : Component
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? PackPrototypeId = default!;
|
||||
|
||||
[DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentDispenserInventoryPrototype>))]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? EmagPackPrototypeId = default!;
|
||||
/// <summary>
|
||||
/// Maximum number of internal storage slots. Dispenser can't store (or dispense) more than
|
||||
/// this many chemicals (without unloading and reloading).
|
||||
/// </summary>
|
||||
[DataField("numStorageSlots")]
|
||||
public int NumSlots = 25;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist? StorageWhitelist;
|
||||
|
||||
/// <summary>
|
||||
/// Slot for container to dispense into.
|
||||
/// </summary>
|
||||
public static string BeakerSlotId = "ReagentDispenser-beakerSlot";
|
||||
|
||||
[DataField]
|
||||
public ItemSlot BeakerSlot = new();
|
||||
|
||||
/// <summary>
|
||||
/// Prefix for automatically-generated slot name for storage, up to NumSlots.
|
||||
/// </summary>
|
||||
public static string BaseStorageSlotId = "ReagentDispenser-storageSlot";
|
||||
|
||||
/// <summary>
|
||||
/// List of storage slots that were created at MapInit.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<string> StorageSlotIds = new List<string>();
|
||||
|
||||
[DataField]
|
||||
public List<ItemSlot> StorageSlots = new List<ItemSlot>();
|
||||
|
||||
[DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Server.Labels.Components;
|
||||
using Content.Server.Chemistry;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.Dispenser;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Emag.Components;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -28,10 +32,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 IAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly OpenableSystem _openable = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -41,11 +48,12 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, GotEmaggedEvent>(OnEmagged);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserSetDispenseAmountMessage>(OnSetDispenseAmountMessage);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserDispenseReagentMessage>(OnDispenseReagentMessage);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ReagentDispenserClearContainerSolutionMessage>(OnClearContainerSolutionMessage);
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, MapInitEvent>(OnMapInit, before: new []{typeof(ItemSlotsSystem)});
|
||||
}
|
||||
|
||||
private void SubscribeUpdateUiState<T>(Entity<ReagentDispenserComponent> ent, ref T ev)
|
||||
@@ -80,35 +88,38 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ReagentId> GetInventory(Entity<ReagentDispenserComponent> ent)
|
||||
private List<KeyValuePair<string, KeyValuePair<string, string>>> GetInventory(ReagentDispenserComponent reagentDispenser)
|
||||
{
|
||||
var reagentDispenser = ent.Comp;
|
||||
var inventory = new List<ReagentId>();
|
||||
var inventory = new List<KeyValuePair<string, KeyValuePair<string, string>>>();
|
||||
|
||||
if (reagentDispenser.PackPrototypeId is not null
|
||||
&& _prototypeManager.TryIndex(reagentDispenser.PackPrototypeId, out ReagentDispenserInventoryPrototype? packPrototype))
|
||||
for (var i = 0; i < reagentDispenser.NumSlots; i++)
|
||||
{
|
||||
inventory.AddRange(packPrototype.Inventory.Select(x => new ReagentId(x, null)));
|
||||
var storageSlotId = ReagentDispenserComponent.BaseStorageSlotId + i;
|
||||
var storedContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser.Owner, storageSlotId);
|
||||
|
||||
// Set label from manually-applied label, or metadata if unavailable
|
||||
string reagentLabel;
|
||||
if (TryComp<LabelComponent>(storedContainer, out var label) && !string.IsNullOrEmpty(label.CurrentLabel))
|
||||
reagentLabel = label.CurrentLabel;
|
||||
else if (storedContainer != null)
|
||||
reagentLabel = Name(storedContainer.Value);
|
||||
else
|
||||
continue;
|
||||
|
||||
// Add volume remaining label
|
||||
FixedPoint2 quantity = 0f;
|
||||
if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
|
||||
{
|
||||
quantity = sol.Volume;
|
||||
}
|
||||
var storedAmount = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", quantity));
|
||||
|
||||
if (HasComp<EmaggedComponent>(ent)
|
||||
&& reagentDispenser.EmagPackPrototypeId is not null
|
||||
&& _prototypeManager.TryIndex(reagentDispenser.EmagPackPrototypeId, out ReagentDispenserInventoryPrototype? emagPackPrototype))
|
||||
{
|
||||
inventory.AddRange(emagPackPrototype.Inventory.Select(x => new ReagentId(x, null)));
|
||||
inventory.Add(new KeyValuePair<string, KeyValuePair<string, string>>(storageSlotId, new KeyValuePair<string, string>(reagentLabel, storedAmount)));
|
||||
}
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
private void OnEmagged(Entity<ReagentDispenserComponent> reagentDispenser, ref GotEmaggedEvent args)
|
||||
{
|
||||
// adding component manually to have correct state
|
||||
EntityManager.AddComponent<EmaggedComponent>(reagentDispenser);
|
||||
UpdateUiState(reagentDispenser);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSetDispenseAmountMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserSetDispenseAmountMessage message)
|
||||
{
|
||||
reagentDispenser.Comp.DispenseAmount = message.ReagentDispenserDispenseAmount;
|
||||
@@ -119,18 +130,23 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
private void OnDispenseReagentMessage(Entity<ReagentDispenserComponent> 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 _))
|
||||
return;
|
||||
|
||||
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);
|
||||
@@ -152,5 +168,41 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
_audioSystem.PlayPvs(reagentDispenser.Comp.ClickSound, reagentDispenser, AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically generate storage slots for all NumSlots, and fill them with their initial chemicals.
|
||||
/// The actual spawning of entities happens in ItemSlotsSystem's MapInit.
|
||||
/// </summary>
|
||||
private void OnMapInit(EntityUid uid, ReagentDispenserComponent component, MapInitEvent args)
|
||||
{
|
||||
// Get list of pre-loaded containers
|
||||
List<string> preLoad = new List<string>();
|
||||
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, ReagentDispenserComponent.BeakerSlotId, component.BeakerSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ReagentPrototype>))]
|
||||
[DataField("inventory", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string> Inventory = new();
|
||||
|
||||
[ViewVariables, IdDataField]
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Content.Shared.Chemistry
|
||||
/// </summary>
|
||||
public sealed class SharedReagentDispenser
|
||||
{
|
||||
public const string OutputSlotName = "beakerSlot";
|
||||
public const string OutputSlotName = "ReagentDispenser-beakerSlot";
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
@@ -25,11 +25,11 @@ namespace Content.Shared.Chemistry
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ReagentDispenserDispenseReagentMessage : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly ReagentId ReagentId;
|
||||
public readonly string SlotId;
|
||||
|
||||
public ReagentDispenserDispenseReagentMessage(ReagentId reagentId)
|
||||
public ReagentDispenserDispenseReagentMessage(string slotId)
|
||||
{
|
||||
ReagentId = reagentId;
|
||||
SlotId = slotId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,11 +59,11 @@ namespace Content.Shared.Chemistry
|
||||
/// <summary>
|
||||
/// A list of the reagents which this dispenser can dispense.
|
||||
/// </summary>
|
||||
public readonly List<ReagentId> Inventory;
|
||||
public readonly List<KeyValuePair<string, KeyValuePair<string, string>>> Inventory;
|
||||
|
||||
public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount;
|
||||
|
||||
public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, List<ReagentId> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
|
||||
public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, List<KeyValuePair<string, KeyValuePair<string, string>>> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
|
||||
{
|
||||
OutputContainer = outputContainer;
|
||||
Inventory = inventory;
|
||||
|
||||
@@ -67,8 +67,8 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
CopyFrom(other);
|
||||
}
|
||||
|
||||
|
||||
[DataField("whitelist")]
|
||||
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
[DataField("blacklist")]
|
||||
@@ -179,6 +179,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// The actual deconstruction logic is handled by the server-side EmptyOnMachineDeconstructSystem.
|
||||
/// </remarks>
|
||||
[DataField("ejectOnDeconstruct")]
|
||||
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
||||
[NonSerialized]
|
||||
public bool EjectOnDeconstruct = true;
|
||||
|
||||
@@ -187,6 +188,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// ejected when it is broken or destroyed?
|
||||
/// </summary>
|
||||
[DataField("ejectOnBreak")]
|
||||
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
||||
[NonSerialized]
|
||||
public bool EjectOnBreak = false;
|
||||
|
||||
@@ -205,6 +207,7 @@ namespace Content.Shared.Containers.ItemSlots
|
||||
/// want to insert more than one item that matches the same whitelist.
|
||||
/// </remarks>
|
||||
[DataField("swap")]
|
||||
[Access(typeof(ItemSlotsSystem), Other = AccessPermissions.ReadWriteExecute)]
|
||||
public bool Swap = true;
|
||||
|
||||
public string? ID => ContainerSlot?.ID;
|
||||
|
||||
@@ -1,61 +1,43 @@
|
||||
- type: reagentDispenserInventory
|
||||
id: SodaDispenserInventory
|
||||
inventory:
|
||||
- Ice
|
||||
- Coffee
|
||||
- Cream
|
||||
- Tea
|
||||
- GreenTea
|
||||
- IcedTea
|
||||
- IcedGreenTea
|
||||
- Cola
|
||||
- SpaceMountainWind
|
||||
- DrGibb
|
||||
- RootBeer
|
||||
- SpaceUp
|
||||
- TonicWater
|
||||
- SodaWater
|
||||
- LemonLime
|
||||
- Sugar
|
||||
- JuiceOrange
|
||||
- JuiceLime
|
||||
- JuiceWatermelon
|
||||
###Hacked
|
||||
#- Fourteen Loko
|
||||
#- GrapeSoda
|
||||
- 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
|
||||
|
||||
@@ -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
|
||||
- JugAluminium
|
||||
- JugCarbon
|
||||
- JugChlorine
|
||||
- JugCopper
|
||||
- JugEthanol
|
||||
- JugFluorine
|
||||
- JugSugar
|
||||
- JugHydrogen
|
||||
- JugIodine
|
||||
- JugIron
|
||||
- JugLithium
|
||||
- JugMercury
|
||||
- JugNitrogen
|
||||
- JugOxygen
|
||||
- JugPhosphorus
|
||||
- JugPotassium
|
||||
- JugRadium
|
||||
- JugSilicon
|
||||
- JugSodium
|
||||
- JugSulfur
|
||||
|
||||
- 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
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
id: DrinkBottlePlasticBaseFull
|
||||
abstract: true
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- DrinkBottle
|
||||
- type: Openable
|
||||
sound:
|
||||
collection: bottleOpenSounds
|
||||
@@ -13,6 +16,7 @@
|
||||
maxVol: 100
|
||||
- type: Sprite
|
||||
state: icon
|
||||
sprite: Objects/Consumable/Drinks/water.rsi # fallback to boring water jug
|
||||
- type: Item
|
||||
size: Normal
|
||||
- type: Damageable
|
||||
@@ -285,6 +289,8 @@
|
||||
reagents:
|
||||
- ReagentId: Rum
|
||||
Quantity: 100
|
||||
- type: Label
|
||||
currentLabel: rum
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/rumbottle.rsi
|
||||
|
||||
@@ -332,6 +338,8 @@
|
||||
reagents:
|
||||
- ReagentId: Tequila
|
||||
Quantity: 100
|
||||
- type: Label
|
||||
currentLabel: tequila
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/tequillabottle.rsi
|
||||
|
||||
@@ -347,6 +355,8 @@
|
||||
reagents:
|
||||
- ReagentId: Vermouth
|
||||
Quantity: 100
|
||||
- type: Label
|
||||
currentLabel: vermouth
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/vermouthbottle.rsi
|
||||
|
||||
@@ -377,6 +387,8 @@
|
||||
reagents:
|
||||
- ReagentId: Whiskey
|
||||
Quantity: 100
|
||||
- type: Label
|
||||
currentLabel: whiskey
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/whiskeybottle.rsi
|
||||
|
||||
@@ -392,6 +404,8 @@
|
||||
reagents:
|
||||
- ReagentId: Wine
|
||||
Quantity: 100
|
||||
- type: Label
|
||||
currentLabel: wine
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/winebottle.rsi
|
||||
|
||||
@@ -417,6 +431,22 @@
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottleGlassBaseFull
|
||||
id: DrinkBeerGrowler # Needs to be renamed DrinkBeerBottleFull
|
||||
name: Beer Growler # beer it is. coffee. beer? coff-ee? be-er? c-o... b-e
|
||||
description: An alcoholic beverage made from malted grains, hops, yeast, and water. XL growler bottle.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: Beer
|
||||
Quantity: 150
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/beer.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkAleBottleFull
|
||||
name: Magm-Ale
|
||||
description: A true dorf's drink of choice.
|
||||
@@ -433,6 +463,22 @@
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/alebottle.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkAleBottleFullGrowler
|
||||
name: Magm-Ale Growler
|
||||
description: A true dorf's drink of choice. XL growler bottle.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: Ale
|
||||
Quantity: 150
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/alebottle.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkWaterBottleFull
|
||||
@@ -451,3 +497,258 @@
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/waterbottle.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkSodaWaterBottleFull
|
||||
name: soda water bottle
|
||||
description: Like water, but angry!
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: SodaWater
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/waterbottle.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkTonicWaterBottleFull
|
||||
name: tonic water bottle
|
||||
description: Like soda water, but angrier maybe? Often sweeter.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: TonicWater
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/waterbottle.rsi
|
||||
|
||||
# Cartons, TODO: this needs to be moved elsewhere eventually, since cartons shouldnt smash into glass shards
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkJuiceLimeCartonXL
|
||||
name: lime juice XL
|
||||
description: Sweet-sour goodness.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: JuiceLime
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/limejuice.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkJuiceOrangeCartonXL
|
||||
name: orange juice XL
|
||||
description: Full of vitamins and deliciousness!
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: JuiceOrange
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/orangejuice.rsi
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkCreamCartonXL
|
||||
name: Milk Cream XL
|
||||
description: It's cream. Made from milk. What else did you think you'd find in there?
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: Cream
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Drinks/cream.rsi
|
||||
|
||||
#boring jugs some more sprites are made
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkSugarJug
|
||||
name: sugar
|
||||
suffix: for drinks
|
||||
description: some people put this in their coffee...
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: Sugar
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkLemonLimeJug
|
||||
name: lemon lime
|
||||
description: a dual citrus sensation.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: LemonLime
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkMeadJug
|
||||
name: mead jug
|
||||
description: storing mead in a plastic jug should be a crime.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 150
|
||||
reagents:
|
||||
- ReagentId: Mead
|
||||
Quantity: 150
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkIceJug
|
||||
name: ice jug
|
||||
description: stubborn water. pretty cool.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: Ice
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkCoffeeJug
|
||||
name: coffee jug
|
||||
description: wake up juice, of the heated kind.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: Coffee
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkTeaJug
|
||||
name: tea jug
|
||||
description: the drink of choice for the Bri'ish and hipsters.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: Tea
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkGreenTeaJug
|
||||
name: green tea jug
|
||||
description: its like tea... but green! great for settling the stomach.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: GreenTea
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkIcedTeaJug
|
||||
name: iced tea jug
|
||||
description: for when the regular tea is too hot for you boohoo
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: IcedTea
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkDrGibbJug
|
||||
name: dr gibb jug
|
||||
description: yeah I don't know either...
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: DrGibb
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkRootBeerJug
|
||||
name: root beer jug
|
||||
description: this drink makes Australians giggle
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: RootBeer
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
- type: entity
|
||||
parent: DrinkBottlePlasticBaseFull
|
||||
id: DrinkWaterMelonJuiceJug
|
||||
name: watermelon juice jug
|
||||
description: May include leftover seeds
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drink:
|
||||
maxVol: 300
|
||||
reagents:
|
||||
- ReagentId: JuiceWatermelon
|
||||
Quantity: 300
|
||||
- type: Drink
|
||||
|
||||
@@ -553,7 +553,7 @@
|
||||
- type: Sprite
|
||||
state: medical
|
||||
- type: MachineBoard
|
||||
prototype: ChemDispenser
|
||||
prototype: ChemDispenserEmpty
|
||||
requirements:
|
||||
Capacitor: 1
|
||||
materialRequirements:
|
||||
@@ -1145,7 +1145,7 @@
|
||||
- type: Sprite
|
||||
state: service
|
||||
- type: MachineBoard
|
||||
prototype: BoozeDispenser
|
||||
prototype: BoozeDispenserEmpty
|
||||
materialRequirements:
|
||||
Steel: 5
|
||||
tagRequirements:
|
||||
@@ -1178,7 +1178,7 @@
|
||||
- type: Sprite
|
||||
state: service
|
||||
- type: MachineBoard
|
||||
prototype: soda_dispenser
|
||||
prototype: SodaDispenserEmpty
|
||||
materialRequirements:
|
||||
Steel: 5
|
||||
tagRequirements:
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
price: 60
|
||||
- type: Label
|
||||
originalName: jug
|
||||
- type: Tag
|
||||
tags:
|
||||
- ChemDispensable
|
||||
|
||||
- type: entity
|
||||
parent: Jug
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- type: entity
|
||||
- type: entity
|
||||
abstract: true
|
||||
id: ReagentDispenserBase
|
||||
parent: ConstructibleMachine
|
||||
@@ -55,18 +55,20 @@
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- type: ReagentDispenser
|
||||
- type: ItemSlots
|
||||
slots:
|
||||
storageWhitelist:
|
||||
tags:
|
||||
- Bottle
|
||||
beakerSlot:
|
||||
whitelistFailPopup: reagent-dispenser-component-cannot-put-entity-message
|
||||
whitelist:
|
||||
components:
|
||||
- FitsInDispenser
|
||||
- type: ItemSlots
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
beakerSlot: !type:ContainerSlot
|
||||
ReagentDispenser-beakerSlot: !type:ContainerSlot
|
||||
- type: StaticPrice
|
||||
price: 1000
|
||||
- type: Wires
|
||||
|
||||
@@ -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
|
||||
@@ -24,3 +27,14 @@
|
||||
- Bartender
|
||||
- type: StealTarget
|
||||
stealGroup: BoozeDispenser
|
||||
|
||||
- type: entity
|
||||
id: BoozeDispenserEmpty
|
||||
suffix: Empty
|
||||
parent: BoozeDispenser
|
||||
components:
|
||||
- type: ReagentDispenser
|
||||
storageWhitelist:
|
||||
tags:
|
||||
- DrinkBottle
|
||||
pack: EmptyInventory
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
- type: entity
|
||||
- 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
|
||||
@@ -37,3 +40,12 @@
|
||||
- Chemist
|
||||
- type: StealTarget
|
||||
stealGroup: ChemDispenser
|
||||
|
||||
- type: entity
|
||||
id: ChemDispenserEmpty
|
||||
name: chemical dispenser
|
||||
suffix: Empty
|
||||
parent: ChemDispenser
|
||||
components:
|
||||
- type: ReagentDispenser
|
||||
pack: EmptyInventory
|
||||
|
||||
@@ -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
|
||||
@@ -22,3 +25,14 @@
|
||||
- type: GuideHelp
|
||||
guides:
|
||||
- Bartender
|
||||
|
||||
- type: entity
|
||||
id: SodaDispenserEmpty
|
||||
suffix: Empty
|
||||
parent: soda_dispenser
|
||||
components:
|
||||
- type: ReagentDispenser
|
||||
storageWhitelist:
|
||||
tags:
|
||||
- DrinkBottle
|
||||
pack: EmptyInventory
|
||||
|
||||
@@ -305,6 +305,9 @@
|
||||
- type: Tag
|
||||
id: Chicken
|
||||
|
||||
- type: Tag
|
||||
id: ChemDispensable # container that can go into the chem dispenser
|
||||
|
||||
- type: Tag
|
||||
id: Cigarette
|
||||
|
||||
@@ -458,6 +461,9 @@
|
||||
- type: Tag
|
||||
id: DrinkSpaceGlue
|
||||
|
||||
- type: Tag
|
||||
id: DrinkBottle
|
||||
|
||||
- type: Tag
|
||||
id: DroneUsable
|
||||
|
||||
|
||||
Reference in New Issue
Block a user