diff --git a/Content.Server/SimpleStation14/BloodstreamFiller/Components/BloodstreamFillerComponent.cs b/Content.Server/SimpleStation14/BloodstreamFiller/Components/BloodstreamFillerComponent.cs
new file mode 100644
index 0000000000..d435331d32
--- /dev/null
+++ b/Content.Server/SimpleStation14/BloodstreamFiller/Components/BloodstreamFillerComponent.cs
@@ -0,0 +1,167 @@
+using Content.Shared.Damage;
+using Content.Shared.Damage.Prototypes;
+using Robust.Shared.Audio;
+
+namespace Content.Server.SimpleStation14.BloodstreamFiller.Components;
+
+[RegisterComponent]
+public sealed class BloodstreamFillerComponent : Component
+{
+ ///
+ /// The duration of the fill DoAfter, in seconds.
+ ///
+ [DataField("fillTime"), ViewVariables(VVAccess.ReadWrite)]
+ public float FillTime = 1.0f;
+
+ ///
+ /// The multiplier for the DoAfter time when attempting to fill yourself.
+ ///
+ [DataField("selfFillMutli"), ViewVariables(VVAccess.ReadWrite)]
+ public float SelfFillMutli = 3.5f;
+
+ ///
+ /// The name of the volume to refill.
+ ///
+ ///
+ /// Should match the name or otherwise.
+ ///
+ [DataField("solution"), ViewVariables(VVAccess.ReadWrite)]
+ public string Solution { get; } = "filler";
+
+ ///
+ /// The amount of reagent that this bloodstream filler will fill with at most.
+ ///
+ [DataField("amount"), ViewVariables(VVAccess.ReadWrite)]
+ public float Amount = 100.0f;
+
+ ///
+ /// The regent allowed to be used by this filler.
+ ///
+ ///
+ /// If null, any reagent will be allowed.
+ ///
+ [DataField("reagents"), ViewVariables(VVAccess.ReadWrite)]
+ public List Reagents = new();
+
+ ///
+ /// Will this filler only fill Silicons?
+ ///
+ ///
+ /// Somewhat niche use case, but Bloodstreams are very inflexible.
+ ///
+ [DataField("siliconOnly"), ViewVariables(VVAccess.ReadWrite)]
+ public bool SiliconOnly = true;
+
+ ///
+ /// Can this bloodfiller be used to overfill someone?
+ ///
+ ///
+ /// If true, the bloodfiller will be able to fill someone already at max blood, causing damage and spilling blood.
+ ///
+ [DataField("overfill"), ViewVariables(VVAccess.ReadWrite)]
+ public bool Overfill = true;
+
+ ///
+ /// The multiplier for the DoAfter time when attempting to overfill someone.
+ ///
+ [DataField("overfillMulti"), ViewVariables(VVAccess.ReadWrite)]
+ public float OverfillMulti = 5.5f;
+
+ ///
+ /// The amount of damage dealt when overfilling someone.
+ ///
+ ///
+ /// This must be specified in YAML.
+ ///
+ [DataField("overfillDamage"), ViewVariables(VVAccess.ReadWrite)]
+ public DamageSpecifier OverfillDamage = default!;
+
+ #region Player Feedback
+ ///
+ /// The sound played when the filler is used.
+ ///
+ [DataField("useSound")]
+ public SoundSpecifier UseSound = new SoundPathSpecifier("/Audio/Effects/bang.ogg");
+
+ ///
+ /// The sound played when the filler refills.
+ ///
+ [DataField("refillSound")]
+ public SoundSpecifier RefillSound = new SoundPathSpecifier("/Audio/Effects/buckle.ogg");
+
+ ///
+ /// The sound played when overfilling someone.
+ ///
+ [DataField("overfillSound")]
+ public SoundSpecifier OverfillSound = new SoundPathSpecifier("/Audio/Effects/demon_dies.ogg");
+
+ ///
+ /// The popup text when the filler is used.
+ ///
+ [DataField("usePopup")]
+ public string UsePopup = "bloodfiller-use-user";
+
+ ///
+ /// The popup text when the filler is used on you.
+ ///
+ [DataField("usedOnPopup")]
+ public string UsedOnPopup = "bloodfiller-use-target";
+
+ ///
+ /// The popup text when the bloodfiller is empty.
+ ///
+ [DataField("emptyPopup")]
+ public string EmptyPopup = "bloodfiller-use-empty";
+
+ ///
+ /// The popup text when the bloodfiller can't be used on the target.
+ ///
+ ///
+ /// Due to or otherwise.
+ ///
+ [DataField("targetInvalidPopup")]
+ public string TargetInvalidPopup = "bloodfiller-use-invalid-target";
+
+ ///
+ /// The popup text when the bloodfiller doesn't have the target's blood.
+ ///
+ [DataField("targetBloodInvalidPopup")]
+ public string TargetBloodInvalidPopup = "bloodfiller-use-invalid-blood";
+
+ ///
+ /// The popup text when the filler is already full.
+ ///
+ [DataField("refillFullPopup")]
+ public string RefillFullPopup = "bloodfiller-refill-filler-full";
+
+ ///
+ /// The popup text when the tank is empty.
+ ///
+ [DataField("refillTankEmptyPopup")]
+ public string RefillTankEmptyPopup = "bloodfiller-refill-tank-empty";
+
+ ///
+ /// The popup text when trying to refill the bloodfiller from a tank with the wrong reagent.
+ ///
+ [DataField("refillReagentInvalidPopup")]
+ public string RefillReagentInvalidPopup = "bloodfiller-refill-reagent-invalid";
+
+ ///
+ /// The popup text when either a tank or filler contains a dirty mixture.
+ ///
+ [DataField("dirtyPopup")]
+ public string DirtyPopup = "bloodfiller-reagent-dirty";
+
+ ///
+ /// The popup text when trying to overfill someone.
+ ///
+ [DataField("targetOverfillPopup")]
+ public string TargetOverfillPopup = "bloodfiller-user-overfill";
+
+ ///
+ /// The popup text when getting overfilled.
+ ///
+ [DataField("overfilledPopup")]
+ public string OverfilledPopup = "bloodfiller-target-overfill";
+ #endregion Player Feedback
+}
diff --git a/Content.Server/SimpleStation14/BloodstreamFiller/Systems/BloodstreamFillerSystem.cs b/Content.Server/SimpleStation14/BloodstreamFiller/Systems/BloodstreamFillerSystem.cs
new file mode 100644
index 0000000000..5045f65e9c
--- /dev/null
+++ b/Content.Server/SimpleStation14/BloodstreamFiller/Systems/BloodstreamFillerSystem.cs
@@ -0,0 +1,251 @@
+using Content.Server.Body.Components;
+using Content.Server.SimpleStation14.BloodstreamFiller.Components;
+using Content.Shared.DoAfter;
+using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
+using Content.Server.Body.Systems;
+using Content.Server.Chemistry.Components;
+using Content.Server.Chemistry.EntitySystems;
+using Content.Shared.FixedPoint;
+using Content.Shared.SimpleStation14.BloodstreamFiller;
+using Robust.Shared.Utility;
+using Content.Server.Popups;
+using Robust.Server.GameObjects;
+using Content.Shared.Popups;
+using Content.Shared.Damage;
+using Content.Server.Fluids.EntitySystems;
+
+namespace Content.Server.SimpleStation14.BloodstreamFiller.Systems;
+
+public sealed class BloodstreamFillerSystem : EntitySystem
+{
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly BloodstreamSystem _bloodstream = default!;
+ [Dependency] private readonly DamageableSystem _damageable = default!;
+ [Dependency] private readonly PuddleSystem _puddle = default!;
+ [Dependency] private readonly SolutionContainerSystem _solution = default!;
+ [Dependency] private readonly PopupSystem _popup = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnUseInWorld);
+ SubscribeLocalEvent(OnUseInHand);
+
+ SubscribeLocalEvent(OnDoAfter);
+ }
+
+ private void OnUseInWorld(EntityUid uid, BloodstreamFillerComponent component, AfterInteractEvent args)
+ {
+ if (!args.CanReach || args.Target == null)
+ return;
+
+ if (!EntityManager.TryGetComponent(args.Target, out var bloodComp))
+ {
+ TryRefill(args.User, uid, args.Target.Value, component);
+ return;
+ }
+
+ TryFill(args.User, args.Target.Value, args.Used, component);
+ }
+
+ private void OnUseInHand(EntityUid uid, BloodstreamFillerComponent component, UseInHandEvent args)
+ {
+ if (!EntityManager.TryGetComponent(args.User, out var bloodComp))
+ return;
+
+ TryFill(args.User, args.User, uid, component);
+ }
+
+ private void TryFill(EntityUid user, EntityUid target, EntityUid filler, BloodstreamFillerComponent fillComp)
+ {
+ // if (fillComp.SiliconOnly && !HasComp(target)) // To be turned on once Silicons are merged :)
+ // {
+ // _popup.PopupCursor(Loc.GetString(fillComp.TargetInvalidPopup, ("filler", filler)), user);
+ // return;
+ // }
+
+ var bloodComp = EntityManager.GetComponent(target);
+
+ if (!_solution.TryGetSolution(filler, fillComp.Solution!, out var fillerSolution)) // No solution
+ return;
+
+ if (fillComp.Reagents.Count > 0 && !fillComp.Reagents.Contains(bloodComp.BloodReagent)) // Wrong reagent as specified by the component
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.TargetInvalidPopup, ("filler", filler)), user);
+ return;
+ }
+
+ if (fillerSolution.Contents.Count == 0) // Empty
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.EmptyPopup, ("filler", filler)), user);
+ return;
+ }
+
+ if (fillerSolution.Contents.Count > 1) // Extra dorty
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.DirtyPopup, ("volume", filler)), user);
+ return;
+ }
+
+ if (fillerSolution.Contents[0].ReagentId != bloodComp.BloodReagent) // Wrong reagent contained
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.TargetBloodInvalidPopup, ("filler", filler), ("target", target)), user);
+ return;
+ }
+
+ var overfill = false;
+
+ var delay = fillComp.FillTime;
+ if (user == target)
+ delay *= fillComp.SelfFillMutli;
+
+ // If the bloodstream is already full, and the filler can overfill, and target is not the user, then overfill.
+ if (fillComp.Overfill && bloodComp.BloodSolution.AvailableVolume == 0 && user != target)
+ {
+ overfill = true;
+ delay *= fillComp.OverfillMulti;
+ }
+
+ _doAfter.TryStartDoAfter(new DoAfterArgs(user, delay, new BloodstreamFillerDoAfterEvent(overfill), target, target, filler)
+ {
+ BreakOnDamage = true,
+ BreakOnTargetMove = true,
+ BreakOnUserMove = true,
+ MovementThreshold = 0.2f,
+ CancelDuplicate = true
+ });
+
+ if (!overfill)
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.UsePopup, ("target", target)), user);
+ _popup.PopupEntity(Loc.GetString(fillComp.UsedOnPopup), target, target, PopupType.Medium);
+ }
+ else
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.TargetOverfillPopup, ("target", target)), user, PopupType.MediumCaution);
+ _popup.PopupEntity(Loc.GetString(fillComp.OverfilledPopup), target, target, PopupType.LargeCaution);
+ }
+ }
+
+ private void OnDoAfter(EntityUid uid, BloodstreamComponent component, BloodstreamFillerDoAfterEvent args)
+ {
+ if (args.Handled || args.Cancelled)
+ return;
+
+ if (args.Args.Target == null)
+ return;
+
+ if (!TryComp(args.Args.Used, out var fillComp))
+ {
+ DebugTools.Assert("Filler component not found");
+ Logger.ErrorS("bloodfiller", $"Filler component not found on entity {ToPrettyString(args.Args.Used.Value)}");
+
+ return;
+ }
+ if (!EntityManager.TryGetComponent(args.Args.Target, out var bloodComp))
+ {
+ DebugTools.Assert("Bloodstream component not found");
+ Logger.ErrorS("bloodfiller", $"Bloodstream component not found on entity {ToPrettyString(args.Args.Target.Value)}");
+
+ return;
+ }
+
+ if (!args.Overfill)
+ Fill(args.Args.Target.Value, args.Args.Used!.Value, fillComp, bloodComp);
+ else
+ Overfill(args.Args.User, args.Args.Target.Value, args.Args.Used!.Value, fillComp, bloodComp);
+
+ args.Handled = true;
+ }
+
+ private void Fill(EntityUid target, EntityUid filler, BloodstreamFillerComponent fillComp, BloodstreamComponent bloodComp)
+ {
+ if (!_solution.TryGetSolution(filler, fillComp.Solution!, out var fillerSolution))
+ return;
+
+ var tansfAmount = FixedPoint2.Min(bloodComp.BloodSolution.AvailableVolume, Math.Min((float) fillerSolution.Volume, fillComp.Amount));
+
+ if (tansfAmount > 0)
+ {
+ var drained = _solution.SplitSolution(filler, fillerSolution, tansfAmount);
+
+ _bloodstream.TryModifyBloodLevel(target, drained.Volume, bloodComp);
+
+ _audio.PlayPvs(fillComp.RefillSound, filler);
+ }
+ }
+
+ private void Overfill(EntityUid user, EntityUid target, EntityUid filler, BloodstreamFillerComponent fillComp, BloodstreamComponent bloodComp)
+ {
+ if (!_solution.TryGetSolution(filler, fillComp.Solution!, out var fillerSolution) ||
+ !TryComp(target, out var damageableComp))
+ return;
+
+ _damageable.TryChangeDamage(target, fillComp.OverfillDamage, origin: user, damageable: damageableComp);
+
+ _puddle.TrySplashSpillAt(target, Transform(target).Coordinates, fillerSolution, out _, user: user);
+
+ Fill(target, filler, fillComp, bloodComp);
+ }
+
+ private void TryRefill(EntityUid user, EntityUid filler, EntityUid target, BloodstreamFillerComponent fillComp)
+ {
+ if (!EntityManager.TryGetComponent(target, out _) ||
+ !_solution.TryGetDrainableSolution(target, out var targetSolution) ||
+ !_solution.TryGetSolution(filler, fillComp.Solution!, out var fillerSolution))
+ return;
+
+ // Check that the tank is not empty.
+ if (targetSolution.Contents.Count == 0)
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.RefillTankEmptyPopup, ("tank", target)), user);
+ return;
+ }
+
+ // Check that the tank has one, and only one reagent.
+ if (targetSolution.Contents.Count > 1)
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.DirtyPopup, ("volume", target)), user);
+ return;
+ }
+
+ // Check that the tank's solution matches the filler's listed reagent.
+ // This is seperate from checking the actual solution to prevent any funny business.
+ if (fillComp.Reagents.Count > 0 && !fillComp.Reagents.Contains(targetSolution.Contents[0].ReagentId))
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.RefillReagentInvalidPopup, ("tank", target)), user);
+ return;
+ }
+
+ // Check that if the filler isn't empty, that it only has one reagent.
+ if (fillerSolution.Contents.Count > 1)
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.DirtyPopup, ("volume", filler)), user);
+ return;
+ }
+
+ // Check that if the filler isn't empty, that it's reagent matches the tank's reagent.
+ if (fillerSolution.Contents.Count == 1 && fillerSolution.Contents[0].ReagentId != targetSolution.Contents[0].ReagentId)
+ {
+ _popup.PopupCursor(Loc.GetString(fillComp.RefillReagentInvalidPopup, ("filler", filler)), user);
+ return;
+ }
+
+ var tansfAmount = FixedPoint2.Min(fillerSolution.AvailableVolume, targetSolution.Volume);
+
+ if (tansfAmount > 0)
+ {
+ var drained = _solution.Drain(target, targetSolution, tansfAmount);
+ _solution.TryAddSolution(filler, fillerSolution, drained);
+
+ _audio.PlayPvs(fillComp.UseSound, filler);
+ }
+ else if (fillerSolution.AvailableVolume <= 0)
+ _popup.PopupCursor(Loc.GetString(fillComp.RefillFullPopup, ("filler", filler)), user);
+ else
+ _popup.PopupCursor(Loc.GetString(fillComp.RefillTankEmptyPopup, ("tank", target)), user);
+ }
+}
diff --git a/Content.Shared/SimpleStation14/Silicon/BloodstreamFillerEvents.cs b/Content.Shared/SimpleStation14/Silicon/BloodstreamFillerEvents.cs
new file mode 100644
index 0000000000..8ed999bdaf
--- /dev/null
+++ b/Content.Shared/SimpleStation14/Silicon/BloodstreamFillerEvents.cs
@@ -0,0 +1,25 @@
+using Content.Shared.DoAfter;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.SimpleStation14.BloodstreamFiller;
+
+[Serializable, NetSerializable]
+public sealed class BloodstreamFillerDoAfterEvent : DoAfterEvent
+{
+ [DataField("overfill")]
+ public readonly bool Overfill = false;
+
+ private BloodstreamFillerDoAfterEvent()
+ {
+
+ }
+ public BloodstreamFillerDoAfterEvent(bool overfill)
+ {
+ Overfill = overfill;
+ }
+
+ public override DoAfterEvent Clone()
+ {
+ return this;
+ }
+}
diff --git a/Resources/Locale/en-US/SimpleStation14/Content/BloodFiller/bloodFiller.ftl b/Resources/Locale/en-US/SimpleStation14/Content/BloodFiller/bloodFiller.ftl
new file mode 100644
index 0000000000..df003261bc
--- /dev/null
+++ b/Resources/Locale/en-US/SimpleStation14/Content/BloodFiller/bloodFiller.ftl
@@ -0,0 +1,13 @@
+bloodfiller-use-user = You begin filling { THE($target) }.
+bloodfiller-use-target = You feel your bloodstream beginning to pressurize...
+bloodfiller-use-empty = { CAPITALIZE(THE($filler)) } is empty.
+bloodfiller-use-invalid-target = { CAPITALIZE(THE($filler)) } can't be used here.
+bloodfiller-use-invalid-blood = { CAPITALIZE(THE($filler)) } does not contain the blood required by { THE($target) }.
+
+bloodfiller-refill-filler-full = { CAPITALIZE(THE($filler)) } is already full.
+bloodfiller-refill-tank-empty = { CAPITALIZE(THE($tank)) } is empty.
+bloodfiller-refill-reagent-invalid = { CAPITALIZE(THE($tank)) } does not contain the correct reagent.
+bloodfiller-reagent-dirty = { CAPITALIZE(THE($volume)) } contains a dirty mixture.
+
+bloodfiller-user-overfill = You begin overpressurizing { THE($target) }...
+bloodfiller-target-overfill = You feel like your veins are bursting at the seams...
diff --git a/Resources/Prototypes/SimpleStation14/Catalog/Cargo/cargo_medical.yml b/Resources/Prototypes/SimpleStation14/Catalog/Cargo/cargo_medical.yml
new file mode 100644
index 0000000000..b2bec36ff7
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Catalog/Cargo/cargo_medical.yml
@@ -0,0 +1,23 @@
+- type: cargoProduct
+ id: MedicalBloodTank
+ name: Blood tank crate
+ description: "Contains a tank of blood."
+ icon:
+ sprite: SimpleStation14/Structures/Storage/tanks.rsi
+ state: bloodtankblood
+ product: CrateMedicalBloodTank
+ cost: 2500
+ category: Medical
+ group: market
+
+- type: cargoProduct
+ id: MedicalSlimeTank
+ name: slime tank crate
+ description: "Contains a tank of slime."
+ icon:
+ sprite: SimpleStation14/Structures/Storage/tanks.rsi
+ state: bloodtankblood
+ product: CrateMedicalSlimeTank
+ cost: 2500
+ category: Medical
+ group: market
diff --git a/Resources/Prototypes/SimpleStation14/Catalog/Fills/Crates/medical.yml b/Resources/Prototypes/SimpleStation14/Catalog/Fills/Crates/medical.yml
new file mode 100644
index 0000000000..d77447d901
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Catalog/Fills/Crates/medical.yml
@@ -0,0 +1,21 @@
+- type: entity
+ id: CrateMedicalBloodTank
+ name: blood tank crate
+ description: "Contains a tank of blood."
+ parent: CrateMedicalSecure
+ components:
+ - type: StorageFill
+ contents:
+ - id: BloodTankBloodFull
+ amount: 1
+
+- type: entity
+ id: CrateMedicalSlimeTank
+ name: slime tank crate
+ description: "Contains a tank of slime."
+ parent: CrateMedicalSecure
+ components:
+ - type: StorageFill
+ contents:
+ - id: BloodTankSlimeFull
+ amount: 1
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Specific/Medical/hypospray.yml
index 37cc523db6..2fe77c73a9 100644
--- a/Resources/Prototypes/SimpleStation14/Entities/Objects/Specific/Medical/hypospray.yml
+++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Specific/Medical/hypospray.yml
@@ -49,3 +49,65 @@
- reagents:
- ReagentId: CellularDivider
Quantity: 100
+
+- type: entity
+ abstract: true
+ parent: BaseItem
+ id: BloodFillerBase
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Medical/hypospray.rsi
+ state: hypo
+ - type: Item
+ sprite: Objects/Specific/Medical/hypospray.rsi
+ - type: BloodstreamFiller
+ solution: filler
+ overfillDamage:
+ groups:
+ Brute: 18
+ - type: UseDelay
+ delay: 2
+ - type: SolutionContainerManager
+ solutions:
+ filler:
+ maxVol: 250
+ # - type: RefillableSolution
+ # solution: filler
+ - type: ExaminableSolution
+ solution: filler
+
+- type: entity
+ parent: BloodFillerBase
+ id: BloodFillerBlood
+ name: bloodfiller
+ description: A pump to inject blood into your body. Also accepts Slime.
+ components:
+ - type: UseDelay
+ delay: 6
+ - type: BloodstreamFiller
+ amount: 60
+ fillTime: 1.3
+ reagents:
+ - Blood
+ - Slime
+ - Water
+ - type: SolutionContainerManager
+ solutions:
+ filler:
+ maxVol: 120
+
+- type: entity
+ parent: BloodFillerBase
+ id: BloodFillerSilicon
+ name: IPC coolant injector
+ description: A pump to inject coolant into an IPC.
+ components:
+ - type: BloodstreamFiller
+ reagents: [ Water ]
+ amount: 150
+ fillTime: 0.85
+ siliconOnly: true
+ - type: SolutionContainerManager
+ solutions:
+ filler:
+ maxVol: 250
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Storage/Tanks/tanks.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Storage/Tanks/tanks.yml
new file mode 100644
index 0000000000..7a808cf49a
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Storage/Tanks/tanks.yml
@@ -0,0 +1,55 @@
+- type: entity
+ abstract: true
+ id: BloodTankBase
+ parent: StorageTank
+ suffix: Empty
+ components:
+ - type: DynamicPrice
+ price: 2000
+ - type: Sprite
+ sprite: SimpleStation14/Structures/Storage/tanks.rsi
+ state: bloodtankblood
+ - type: ExaminableSolution
+ solution: tank
+
+- type: entity
+ id: BloodTankBlood
+ parent: BloodTankBase
+ suffix: Empty
+ components:
+ - type: Sprite
+ state: bloodtankblood
+
+- type: entity
+ parent: BloodTankBlood
+ id: BloodTankBloodFull
+ suffix: Full
+ components:
+ - type: SolutionContainerManager
+ solutions:
+ tank:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 1500
+
+- type: entity
+ id: BloodTankSlime
+ parent: BloodTankBase
+ suffix: Empty
+ components:
+ - type: DynamicPrice
+ price: 2500
+ - type: Sprite
+ state: bloodtankslime
+
+- type: entity
+ parent: BloodTankSlime
+ id: BloodTankSlimeFull
+ suffix: Full
+ components:
+ - type: SolutionContainerManager
+ solutions:
+ tank:
+ reagents:
+ - ReagentId: Slime
+ Quantity: 1500
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-left.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-left.png
index 0f1f047472..fc2247ba5e 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-left.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-right.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-right.png
index c55b8d6fd6..c999a4c65a 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-right.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/1-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-left.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-left.png
index 0f1f047472..54307dc069 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-left.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-right.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-right.png
index c55b8d6fd6..afd31cbeb4 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-right.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/2-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-left.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-left.png
index 3bbc9fe683..5fe7f1f943 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-left.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-right.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-right.png
index 71ecded6f6..cba15421ff 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-right.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/3-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-left.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-left.png
index 2d4447acb7..2a0575895c 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-left.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-right.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-right.png
index fa55e86eb9..92d9a14b1f 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-right.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/4-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe1.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe1.png
index 74cfa72ab4..82af39342e 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe1.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe1.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe2.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe2.png
index 74cfa72ab4..1e952a5d30 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe2.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe2.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe3.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe3.png
index 9aa237b136..64e3e409d5 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe3.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe3.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe4.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe4.png
index d8b7e8a701..d6c2e08ff1 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe4.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe4.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base0.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base0.png
index 9cf92274d4..55e8e6081d 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base0.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base0.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base1.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base1.png
index 2d455682f4..6cae5f27fd 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base1.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base1.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base2.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base2.png
index b898840c30..a81f1c6ff2 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base2.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base2.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base3.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base3.png
index 35e22c6454..9a560e6d30 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base3.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base3.png differ
diff --git a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base4.png b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base4.png
index 834ae95f9f..cce9207cc1 100644
Binary files a/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base4.png and b/Resources/Textures/Objects/Specific/Chemistry/syringe.rsi/syringe_base4.png differ
diff --git a/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankblood.png b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankblood.png
new file mode 100644
index 0000000000..0745546669
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankblood.png differ
diff --git a/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankslime.png b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankslime.png
new file mode 100644
index 0000000000..28da368552
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/bloodtankslime.png differ
diff --git a/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/meta.json b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/meta.json
new file mode 100644
index 0000000000..3dafefc256
--- /dev/null
+++ b/Resources/Textures/SimpleStation14/Structures/Storage/tanks.rsi/meta.json
@@ -0,0 +1,17 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Modified by Pspritechologist from tgstation at commit https://github.com/tgstation/tgstation/commit/8442af39ee82b813194f71db82edd2923d97818d",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "bloodtankblood"
+ },
+ {
+ "name": "bloodtankslime"
+ }
+ ]
+}