diff --git a/Content.Server/Chemistry/Components/InjectorComponent.cs b/Content.Server/Chemistry/Components/InjectorComponent.cs
index 466f49a22a..4783cc4c21 100644
--- a/Content.Server/Chemistry/Components/InjectorComponent.cs
+++ b/Content.Server/Chemistry/Components/InjectorComponent.cs
@@ -1,6 +1,9 @@
using System.Threading;
using Content.Shared.Chemistry.Components;
using Content.Shared.FixedPoint;
+using Content.Server.UserInterface;
+using Robust.Server.GameObjects;
+using Content.Shared.Chemistry;
namespace Content.Server.Chemistry.Components
{
@@ -22,6 +25,20 @@ namespace Content.Server.Chemistry.Components
[DataField("injectOnly")]
public bool InjectOnly;
+ ///
+ /// The minimum amount of solution that can be transferred at once from this solution.
+ ///
+ [DataField("minTransferAmount")]
+ [ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 MinimumTransferAmount { get; set; } = FixedPoint2.New(5);
+
+ ///
+ /// The maximum amount of solution that can be transferred at once from this solution.
+ ///
+ [DataField("maxTransferAmount")]
+ [ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 MaximumTransferAmount { get; set; } = FixedPoint2.New(50);
+
///
/// Amount to inject or draw on each usage. If the injector is inject only, it will
/// attempt to inject it's entire contents upon use.
diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
index db61b9f522..caf2327af1 100644
--- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
+++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs
@@ -15,13 +15,22 @@ using Content.Shared.MobState.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using System.Threading;
+using Content.Shared.Verbs;
+using Robust.Server.GameObjects;
+using Content.Shared.Popups;
namespace Content.Server.Chemistry.EntitySystems;
public sealed partial class ChemistrySystem
{
+
+ ///
+ /// Default transfer amounts for the set-transfer verb.
+ ///
+ public static readonly List TransferAmounts = new() { 5, 10, 15};
private void InitializeInjector()
{
+ SubscribeLocalEvent>(AddSetTransferVerbs);
SubscribeLocalEvent(OnSolutionChange);
SubscribeLocalEvent(OnInjectorDeselected);
SubscribeLocalEvent(OnInjectorStartup);
@@ -33,6 +42,38 @@ public sealed partial class ChemistrySystem
SubscribeLocalEvent(OnInjectionCancelled);
}
+ private void AddSetTransferVerbs(EntityUid uid, InjectorComponent component, GetVerbsEvent args)
+ {
+ if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+ return;
+
+ if (!EntityManager.TryGetComponent(args.User, out var actor))
+ return;
+
+ // Add specific transfer verbs according to the container's size
+ var priority = 0;
+ foreach (var amount in TransferAmounts)
+ {
+ if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
+ continue;
+
+ AlternativeVerb verb = new();
+ verb.Text = Loc.GetString("comp-solution-transfer-verb-amount", ("amount", amount));
+ verb.Category = VerbCategory.SetTransferAmount;
+ verb.Act = () =>
+ {
+ component.TransferAmount = FixedPoint2.New(amount);
+ args.User.PopupMessage(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)));
+ };
+
+ // we want to sort by size, not alphabetically by the verb text.
+ verb.Priority = priority;
+ priority--;
+
+ args.Verbs.Add(verb);
+ }
+ }
+
private static void OnInjectionCancelled(InjectionCancelledEvent ev)
{
ev.Component.CancelToken = null;
@@ -196,6 +237,10 @@ public sealed partial class ChemistrySystem
return;
var actualDelay = MathF.Max(component.Delay, 1f);
+
+ // Injections take 1 second longer per additional 5u
+ actualDelay += (float) component.TransferAmount / component.Delay - 1;
+
if (user != target)
{
// Create a pop-up for the target