diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000000..3550a30f2d
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use flake
diff --git a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
index 0577aa1fcb..9af4c49d2a 100644
--- a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
@@ -51,6 +51,8 @@ protected override void Open()
(uint)_window.PillDosage.Value, (uint)_window.PillNumber.Value, _window.LabelLine));
_window.CreateBottleButton.OnPressed += _ => SendMessage(
new ChemMasterOutputToBottleMessage((uint)_window.BottleDosage.Value, _window.LabelLine));
+ _window.CreateCartridgeButton.OnPressed += _ => SendMessage(
+ new ChemMasterCreateCartridgeMessage((uint)_window.CartridgeDosage.Value, _window.LabelLine));
for (uint i = 0; i < _window.PillTypeButtons.Length; i++)
{
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
index e5ffeb7809..0f6fe4e763 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml
@@ -125,6 +125,14 @@
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
index 5f37206737..91186fe05a 100644
--- a/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
+++ b/Content.Client/Chemistry/UI/ChemMasterWindow.xaml.cs
@@ -6,7 +6,6 @@
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.Client.Utility;
using Robust.Shared.Prototypes;
@@ -79,6 +78,7 @@ public ChemMasterWindow()
PillDosage.InitDefaultButtons();
PillNumber.InitDefaultButtons();
BottleDosage.InitDefaultButtons();
+ CartridgeDosage.InitDefaultButtons();
// Ensure label length is within the character limit.
LabelLineEdit.IsValid = s => s.Length <= SharedChemMaster.LabelMaxLength;
@@ -114,21 +114,26 @@ public void UpdateState(BoundUserInterfaceState state)
OutputEjectButton.Disabled = output is null;
CreateBottleButton.Disabled = output is null || !output.HoldsReagents;
CreatePillButton.Disabled = output is null || output.HoldsReagents;
+ CreateCartridgeButton.Disabled = false;
var remainingCapacity = output is null ? 0 : (output.MaxVolume - output.CurrentVolume).Int();
var holdsReagents = output?.HoldsReagents ?? false;
var pillNumberMax = holdsReagents ? 0 : remainingCapacity;
var bottleAmountMax = holdsReagents ? remainingCapacity : 0;
+ var cartridgeAmountMax = holdsReagents ? remainingCapacity : 0;
PillTypeButtons[castState.SelectedPillType].Pressed = true;
PillNumber.IsValid = x => x >= 0 && x <= pillNumberMax;
PillDosage.IsValid = x => x > 0 && x <= castState.PillDosageLimit;
BottleDosage.IsValid = x => x >= 0 && x <= bottleAmountMax;
+ CartridgeDosage.IsValid = x => x >= 0 && x <= cartridgeAmountMax;
if (PillNumber.Value > pillNumberMax)
PillNumber.Value = pillNumberMax;
if (BottleDosage.Value > bottleAmountMax)
BottleDosage.Value = bottleAmountMax;
+ if (CartridgeDosage.Value > cartridgeAmountMax)
+ CartridgeDosage.Value = cartridgeAmountMax;
}
///
diff --git a/Content.Server/Chemistry/Components/HyposprayComponent.cs b/Content.Server/Chemistry/Components/HyposprayComponent.cs
index abb8ff8797..5968982543 100644
--- a/Content.Server/Chemistry/Components/HyposprayComponent.cs
+++ b/Content.Server/Chemistry/Components/HyposprayComponent.cs
@@ -1,5 +1,6 @@
using Content.Server.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Components;
+using Content.Shared.Containers.ItemSlots;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
@@ -30,8 +31,14 @@ public sealed class HyposprayComponent : SharedHyposprayComponent
public override ComponentState GetComponentState()
{
+ var itemSlotSys = _entMan.EntitySysManager.GetEntitySystem();
var solutionSys = _entMan.EntitySysManager.GetEntitySystem();
- return solutionSys.TryGetSolution(Owner, SolutionName, out var solution)
+
+ EntityUid? container = Owner;
+ if (SolutionSlot != null) {
+ container = itemSlotSys.GetItemOrNull(Owner, SolutionSlot);
+ }
+ return solutionSys.TryGetSolution(container, SolutionName, out var solution)
? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
: new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
index 535efd6070..14ebb491df 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemMasterSystem.cs
@@ -11,6 +11,7 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
+using Content.Shared.Tag;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
@@ -34,8 +35,13 @@ public sealed class ChemMasterSystem : EntitySystem
[Dependency] private readonly StorageSystem _storageSystem = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly TagSystem _tagSystem = default!;
private const string PillPrototypeId = "Pill";
+ private const string CartridgePrototypeId = "ChemicalCartridge";
+
+ private const string CartridgeEmptyTag = "ChemicalCartridgeEmpty";
+ private const string CartridgeFullTag = "ChemicalCartridge";
public override void Initialize()
{
@@ -52,6 +58,7 @@ public override void Initialize()
SubscribeLocalEvent(OnReagentButtonMessage);
SubscribeLocalEvent(OnCreatePillsMessage);
SubscribeLocalEvent(OnOutputToBottleMessage);
+ SubscribeLocalEvent(OnCreateCartridgeMessage);
}
private void UpdateUiState(ChemMasterComponent chemMaster, bool updateLabel = false)
@@ -271,6 +278,53 @@ private void OnOutputToBottleMessage(
ClickSound(chemMaster);
}
+ private void OnCreateCartridgeMessage(
+ EntityUid uid, ChemMasterComponent chemMaster, ChemMasterCreateCartridgeMessage message)
+ {
+ var user = message.Session.AttachedEntity;
+ // Make sure there's an empty cartridge in the slot
+ var maybeContainer = _itemSlotsSystem.GetItemOrNull(chemMaster.Owner, SharedChemMaster.OutputSlotName);
+ if (maybeContainer is not { Valid: true } container
+ || !_tagSystem.HasTag(container, CartridgeEmptyTag)
+ || !_solutionContainerSystem.TryGetSolution(container, SharedChemMaster.CartridgeSolutionName, out var solution))
+ {
+ return;
+ }
+
+ // Ensure the amount is valid.
+ if (message.Dosage == 0 || message.Dosage > solution.AvailableVolume)
+ return;
+
+ // Ensure label length is within the character limit.
+ if (message.Label.Length > SharedChemMaster.LabelMaxLength)
+ return;
+
+ if (!WithdrawFromBuffer(chemMaster, message.Dosage, user, out var withdrawal))
+ return;
+
+ _labelSystem.Label(container, message.Label);
+ _solutionContainerSystem.TryAddSolution(container, solution, withdrawal);
+
+ _tagSystem.RemoveTag(container, CartridgeEmptyTag);
+ _tagSystem.AddTag(container, CartridgeFullTag);
+
+ if (user.HasValue)
+ {
+ // Log bottle creation by a user
+ _adminLogger.Add(LogType.Action, LogImpact.Low,
+ $"{ToPrettyString(user.Value):user} filled {ToPrettyString(container):cartridge} {SolutionContainerSystem.ToPrettyString(solution)}");
+ }
+ else
+ {
+ // Log bottle creation by magic? This should never happen... right?
+ _adminLogger.Add(LogType.Action, LogImpact.Low,
+ $"Unknown filled {ToPrettyString(container):cartridge} {SolutionContainerSystem.ToPrettyString(solution)}");
+ }
+
+ UpdateUiState(chemMaster);
+ ClickSound(chemMaster);
+ }
+
private bool WithdrawFromBuffer(
IComponent chemMaster,
FixedPoint2 neededVolume, EntityUid? user,
@@ -329,8 +383,12 @@ private void ClickSound(ChemMasterComponent chemMaster)
var name = Name(container.Value);
{
+ Solution? solution = null;
+
if (_solutionContainerSystem.TryGetSolution(
- container.Value, SharedChemMaster.BottleSolutionName, out var solution))
+ container.Value, SharedChemMaster.BottleSolutionName, out solution)
+ || _solutionContainerSystem.TryGetSolution(
+ container.Value, SharedChemMaster.CartridgeSolutionName, out solution))
{
return BuildContainerInfo(name, solution);
}
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
index fbd9cd3250..f106856199 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs
@@ -14,21 +14,30 @@
using Content.Shared.Tag;
using Content.Shared.Popups;
using Content.Shared.Timing;
-using Robust.Shared.Player;
+using Content.Shared.Containers.ItemSlots;
+using Robust.Shared.Containers;
+using Content.Shared.Examine;
+using Robust.Shared.Prototypes;
+using Content.Shared.Chemistry.Components;
namespace Content.Server.Chemistry.EntitySystems
{
public sealed partial class ChemistrySystem
{
[Dependency] private readonly UseDelaySystem _useDelay = default!;
+ [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private void InitializeHypospray()
{
SubscribeLocalEvent(OnAfterInteract);
SubscribeLocalEvent(OnAttack);
SubscribeLocalEvent(OnSolutionChange);
+ SubscribeLocalEvent(OnContainerModified);
+ SubscribeLocalEvent(OnContainerModified);
SubscribeLocalEvent(OnUseInHand);
SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnExamine);
}
private void OnStartup(EntityUid uid, HyposprayComponent component, ComponentStartup args)
@@ -50,6 +59,11 @@ private void OnSolutionChange(EntityUid uid, HyposprayComponent component, Solut
Dirty(component);
}
+ private void OnContainerModified(EntityUid uid, HyposprayComponent component, ContainerModifiedMessage args)
+ {
+ Dirty(component);
+ }
+
public void OnAfterInteract(EntityUid uid, HyposprayComponent component, AfterInteractEvent args)
{
if (!args.CanReach)
@@ -88,9 +102,7 @@ public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, Hyposp
if (tag.Tags.Contains("HardsuitOn"))
{
if (target == null) return false;
- var taget = (EntityUid) target;
-
- _popup.PopupEntity("You cant get the needle to go through the thick plating!", taget, user, PopupType.MediumCaution);
+ _popup.PopupEntity("You cant get the needle to go through the thick plating!", target.Value, user, PopupType.MediumCaution);
return false;
}
}
@@ -103,7 +115,18 @@ public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, Hyposp
target = user;
}
- _solutions.TryGetSolution(uid, component.SolutionName, out var hypoSpraySolution);
+ EntityUid? container = uid;
+
+ if (component.SolutionSlot != null) {
+ container = _itemSlotsSystem.GetItemOrNull(uid, component.SolutionSlot);
+ }
+
+ if (container == null) {
+ _popup.PopupCursor(Loc.GetString("hypospray-component-no-container-message"), user);
+ return false;
+ }
+
+ _solutions.TryGetSolution(container, component.SolutionName, out var hypoSpraySolution);
if (hypoSpraySolution == null || hypoSpraySolution.Volume == 0)
{
@@ -145,13 +168,15 @@ public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, Hyposp
}
// Move units from attackSolution to targetSolution
- var removedSolution = _solutions.SplitSolution(uid, hypoSpraySolution, realTransferAmount);
+ var removedSolution = _solutions.SplitSolution(container.Value, hypoSpraySolution, realTransferAmount);
if (!targetSolution.CanAddSolution(removedSolution))
return true;
_reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection);
_solutions.TryAddSolution(target.Value, targetSolution, removedSolution);
+ Dirty(component);
+
//same logtype as syringes...
_adminLogger.Add(LogType.ForceFeed, $"{_entMan.ToPrettyString(user):user} injected {_entMan.ToPrettyString(target.Value):target} with a solution {SolutionContainerSystem.ToPrettyString(removedSolution):removedSolution} using a {_entMan.ToPrettyString(uid):using}");
@@ -166,5 +191,52 @@ static bool EligibleEntity([NotNullWhen(true)] EntityUid? entity, IEntityManager
return entMan.HasComponent(entity)
&& entMan.HasComponent(entity);
}
+
+ private void OnExamine(EntityUid uid, HyposprayComponent component, ExaminedEvent args)
+ {
+ if (component.SolutionSlot != null) {
+ var container = _itemSlotsSystem.GetItemOrNull(uid, component.SolutionSlot);
+ if (container == null) {
+ args.PushText(Loc.GetString("hypospray-component-on-examine-no-container"));
+ return;
+ }
+
+ if (!TryComp(container, out ExaminableSolutionComponent? examinableComponent))
+ return;
+
+ // Mostly copied from SolutionContainerSystem.OnExamineSolution
+
+ SolutionContainerManagerComponent? solutionsManager = null;
+ if (!Resolve(container.Value, ref solutionsManager)
+ || !solutionsManager.Solutions.TryGetValue(examinableComponent.Solution, out var solutionHolder))
+ return;
+
+ var primaryReagent = solutionHolder.GetPrimaryReagentId();
+
+ if (string.IsNullOrEmpty(primaryReagent))
+ {
+ args.PushText(Loc.GetString("shared-solution-container-component-on-examine-empty-container"));
+ return;
+ }
+
+ if (!_prototypeManager.TryIndex(primaryReagent, out ReagentPrototype? proto))
+ {
+ Logger.Error(
+ $"{nameof(Solution)} could not find the prototype associated with {primaryReagent}.");
+ return;
+ }
+
+ var colorHex = solutionHolder.GetColor(_prototypeManager)
+ .ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable.
+ var messageString = "shared-solution-container-component-on-examine-main-text";
+
+ args.PushMarkup(Loc.GetString(messageString,
+ ("color", colorHex),
+ ("wordedAmount", Loc.GetString(solutionHolder.Contents.Count == 1
+ ? "shared-solution-container-component-on-examine-worded-amount-one-reagent"
+ : "shared-solution-container-component-on-examine-worded-amount-multiple-reagents")),
+ ("desc", proto.LocalizedPhysicalDescription)));
+ }
+ }
}
}
diff --git a/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs b/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
index 59d3192cfb..67a73c33fb 100644
--- a/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
+++ b/Content.Shared/Chemistry/Components/SharedHyposprayComponent.cs
@@ -7,6 +7,8 @@ namespace Content.Shared.Chemistry.Components
[NetworkedComponent()]
public abstract class SharedHyposprayComponent : Component
{
+ [DataField("solutionSlot")]
+ public string? SolutionSlot = null;
[DataField("solutionName")]
public string SolutionName = "hypospray";
}
diff --git a/Content.Shared/Chemistry/SharedChemMaster.cs b/Content.Shared/Chemistry/SharedChemMaster.cs
index 0e20e91a51..cebc3cb4f4 100644
--- a/Content.Shared/Chemistry/SharedChemMaster.cs
+++ b/Content.Shared/Chemistry/SharedChemMaster.cs
@@ -15,6 +15,7 @@ public sealed class SharedChemMaster
public const string OutputSlotName = "outputSlot";
public const string PillSolutionName = "food";
public const string BottleSolutionName = "drink";
+ public const string CartridgeSolutionName = "cartridge";
public const uint LabelMaxLength = 50;
}
@@ -83,6 +84,19 @@ public ChemMasterOutputToBottleMessage(uint dosage, string label)
}
}
+ [Serializable, NetSerializable]
+ public sealed class ChemMasterCreateCartridgeMessage : BoundUserInterfaceMessage
+ {
+ public readonly uint Dosage;
+ public readonly string Label;
+
+ public ChemMasterCreateCartridgeMessage(uint dosage, string label)
+ {
+ Dosage = dosage;
+ Label = label;
+ }
+ }
+
public enum ChemMasterMode
{
Transfer,
diff --git a/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl b/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
index 51110f12c4..0eb9812da0 100644
--- a/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/chem-master-component.ftl
@@ -28,4 +28,5 @@ chem-master-window-pills-number-label = Count:
chem-master-window-dose-label = Dose (u):
chem-master-window-create-button = Create
chem-master-window-bottles-label = Bottles:
+chem-master-window-cartridges-label = Cartridges:
chem-master-window-unknown-reagent-text = Unknown reagent
diff --git a/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl b/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
index 7acbe8664c..8009608e70 100644
--- a/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
+++ b/Resources/Locale/en-US/chemistry/components/hypospray-component.ftl
@@ -7,7 +7,9 @@ hypospray-volume-text = Volume: [color=white]{$currentVolume}/{$totalVolume}[/co
hypospray-component-inject-other-message = You inject {$other}.
hypospray-component-inject-self-message = You inject yourself.
hypospray-component-inject-self-clumsy-message = Oops! You injected yourself.
+hypospray-component-no-container-message = It has no container to draw from!
hypospray-component-empty-message = It's empty!
hypospray-component-feel-prick-message = You feel a tiny prick!
hypospray-component-transfer-already-full-message = {$owner} is already full!
hypospray-cant-inject = Can't inject into {$target}!
+hypospray-component-on-examine-no-container = It has no solution container.
diff --git a/Resources/Maps/SimpleStation14/syndiecomms.yml b/Resources/Maps/SimpleStation14/syndiecomms.yml
index d453ff0b6d..90c28fe923 100644
--- a/Resources/Maps/SimpleStation14/syndiecomms.yml
+++ b/Resources/Maps/SimpleStation14/syndiecomms.yml
@@ -3771,19 +3771,19 @@ entities:
parent: 1
type: Transform
- uid: 331
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.484516,-22.194567
parent: 1
type: Transform
- uid: 332
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.498704,-22.393242
parent: 1
type: Transform
- uid: 333
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.512893,-22.60611
parent: 1
diff --git a/Resources/Maps/SimpleStation14/syndiecommsatmos.yml b/Resources/Maps/SimpleStation14/syndiecommsatmos.yml
index 8e1295e974..71a0409c95 100644
--- a/Resources/Maps/SimpleStation14/syndiecommsatmos.yml
+++ b/Resources/Maps/SimpleStation14/syndiecommsatmos.yml
@@ -4229,19 +4229,19 @@ entities:
parent: 1
type: Transform
- uid: 331
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.484516,-22.194567
parent: 1
type: Transform
- uid: 332
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.498704,-22.393242
parent: 1
type: Transform
- uid: 333
- type: ChemicalMedipen
+ type: CartridgeMedipen
components:
- pos: 10.512893,-22.60611
parent: 1
diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml
index 7c58533e57..7f18196816 100644
--- a/Resources/Prototypes/Catalog/Research/technologies.yml
+++ b/Resources/Prototypes/Catalog/Research/technologies.yml
@@ -147,6 +147,7 @@
- PillCanister
- ChemistryEmptyBottle01
- ChemicalPayload
+ - ChemicalCartridgeEmpty
- type: technology
name: technologies-advanced-surgery
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml
index cc08e8f409..9c5f08a727 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml
@@ -7,4 +7,4 @@
EpinephrineChemistryBottle: 3
Syringe: 3
ClothingEyesGlasses: 5
- ChemicalMedipen: 3
+ CartridgeMedipen: 3
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/wallmed.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/wallmed.yml
index 09e8e5bc43..2624f31e12 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/wallmed.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/wallmed.yml
@@ -5,4 +5,4 @@
Ointment: 4
EpinephrineChemistryBottle: 2
Syringe: 2
- ChemicalMedipen: 1
+ CartridgeMedipen: 1
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
index e1d29b2836..71a482ba5d 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
@@ -1,4 +1,4 @@
-- type: entity
+- type: entity
name: hypospray
parent: BaseItem
description: A sterile injector for rapid administration of drugs to patients.
@@ -9,15 +9,16 @@
state: hypo
- type: Item
sprite: Objects/Specific/Medical/hypospray.rsi
- - type: SolutionContainerManager
- solutions:
- hypospray:
- maxVol: 30
- - type: RefillableSolution
- solution: hypospray
- - type: ExaminableSolution
- solution: hypospray
+ - type: ItemSlots
+ slots:
+ container:
+ whitelist:
+ tags:
+ - Bottle
+ startingItem: ChemistryEmptyBottle01
- type: Hypospray
+ solutionSlot: container
+ solutionName: drink
pierceArmor: true
- type: DynamicPrice
price: 750
@@ -48,6 +49,65 @@
- type: UseDelay
delay: 0.5
+- type: entity
+ name: chemical cartridge
+ parent: BaseItem
+ description: A disposable single-use chemical cartridge. Needs to be filled in a ChemMaster.
+ id: ChemicalCartridgeEmpty
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Chemistry/bottle.rsi
+ layers:
+ - state: bottle-1
+ - state: bottle-1-1
+ map: ["enum.SolutionContainerLayers.Fill"]
+ visible: false
+ - type: Appearance
+ - type: SolutionContainerVisuals
+ maxFillLevels: 6
+ fillBaseName: bottle-1-
+ - type: Item
+ size: 3
+ - type: SolutionContainerManager
+ solutions:
+ cartridge:
+ maxVol: 15
+ - type: Tag
+ tags:
+ - Trash
+ - ChemicalCartridgeEmpty
+ - type: Recyclable
+ - type: SpaceGarbage
+ - type: DynamicPrice
+ price: 75 # These are limited supply items.
+ - type: TrashOnEmpty
+ solution: cartridge
+
+- type: entity
+ name: cartridge medipen
+ parent: BaseItem
+ description: A reusable sterile injector for rapid administration of drugs to patients from disposable cartridges.
+ id: CartridgeMedipen
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Medical/medipen.rsi
+ netsync: false
+ layers:
+ - state: medipen
+ - type: Item
+ sprite: Objects/Specific/Medical/medipen.rsi
+ size: 3
+ - type: ItemSlots
+ slots:
+ cartridge:
+ whitelist:
+ tags:
+ - ChemicalCartridge
+ - type: Hypospray
+ solutionSlot: cartridge
+ solutionName: cartridge
+ transferAmount: 15
+
- type: entity
name: chemical medipen
parent: BaseItem
@@ -86,8 +146,6 @@
price: 75 # These are limited supply items.
- type: TrashOnEmpty
solution: pen
- - type: RefillableSolution
- solution: pen
- type: entity
name: emergency medipen
diff --git a/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml b/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml
index b8f2d8e2c9..d5f64a6adf 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/chem_master.yml
@@ -82,6 +82,7 @@
tags:
- Bottle
- PillCanister
+ - ChemicalCartridgeEmpty
- type: SolutionContainerManager
solutions:
buffer: {}
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index 7510610cc7..0abaf06354 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -473,6 +473,7 @@
- Saw
- Hemostat
- ChemicalPayload
+ - ChemicalCartridgeEmpty
- Beaker
- LargeBeaker
- CryostasisBeaker
diff --git a/Resources/Prototypes/Recipes/Lathes/chemistry.yml b/Resources/Prototypes/Recipes/Lathes/chemistry.yml
index 3d5807517a..2d172f76a9 100644
--- a/Resources/Prototypes/Recipes/Lathes/chemistry.yml
+++ b/Resources/Prototypes/Recipes/Lathes/chemistry.yml
@@ -49,3 +49,10 @@
completetime: 2
materials:
Glass: 50
+
+- type: latheRecipe
+ id: ChemicalCartridgeEmpty
+ result: ChemicalCartridgeEmpty
+ completetime: 2
+ materials:
+ Plastic: 100
diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml
index ffe8954d1d..68cb95e470 100644
--- a/Resources/Prototypes/SimpleStation14/tags.yml
+++ b/Resources/Prototypes/SimpleStation14/tags.yml
@@ -6,3 +6,11 @@
- type: Tag
id: WizardBook
+
+# Can be used in a chemical medipen
+- type: Tag
+ id: ChemicalCartridge
+
+# Can be filled in ChemMaster once (changes to ChemicalCartridge afterwards)
+- type: Tag
+ id: ChemicalCartridgeEmpty
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000000..992d3d7ce3
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1682453498,
+ "narHash": "sha256-WoWiAd7KZt5Eh6n+qojcivaVpnXKqBsVgpixpV2L9CE=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "c8018361fa1d1650ee8d4b96294783cf564e8a7f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000000..abbfc25462
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,27 @@
+{
+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+
+ outputs = { self, nixpkgs, ... }: let
+ pkgs = nixpkgs.legacyPackages."x86_64-linux";
+ in {
+ devShells.x86_64-linux.default = with pkgs; stdenv.mkDerivation rec {
+ name = "dev-env";
+
+ nativeBuildInputs = [
+ dotnet-sdk_7
+ omnisharp-roslyn
+ python3
+ ];
+
+ buildInputs = [
+ freetype
+ glfw
+ libglvnd
+ openal
+ fluidsynth
+ ];
+
+ LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
+ };
+ };
+}