diff --git a/Content.Server/Delivery/DeliverySystem.cs b/Content.Server/Delivery/DeliverySystem.cs
index 0ddfde49ae..5fc9b53316 100644
--- a/Content.Server/Delivery/DeliverySystem.cs
+++ b/Content.Server/Delivery/DeliverySystem.cs
@@ -135,20 +135,6 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
DirtyField(ent.Owner, ent.Comp, nameof(DeliveryComponent.WasPenalized));
}
- ///
- /// Gathers the total multiplier for a delivery.
- /// This is done by components having subscribed to GetDeliveryMultiplierEvent and having added onto it.
- ///
- /// The delivery for which to get the multiplier.
- /// Total multiplier.
- private float GetDeliveryMultiplier(Entity ent)
- {
- var ev = new GetDeliveryMultiplierEvent();
- RaiseLocalEvent(ent, ref ev);
-
- return ev.Multiplier;
- }
-
public override void Update(float frameTime)
{
base.Update(frameTime);
diff --git a/Content.Shared/Delivery/DeliveryModifierSystem.cs b/Content.Shared/Delivery/DeliveryModifierSystem.cs
new file mode 100644
index 0000000000..505975732c
--- /dev/null
+++ b/Content.Shared/Delivery/DeliveryModifierSystem.cs
@@ -0,0 +1,30 @@
+using Robust.Shared.Random;
+
+namespace Content.Shared.Delivery;
+
+///
+/// System responsible for managing multipliers and logic for different delivery modifiers.
+///
+public sealed partial class DeliveryModifierSystem : EntitySystem
+{
+ [Dependency] private readonly IRobustRandom _random = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnRandomMultiplierMapInit);
+ SubscribeLocalEvent(OnGetRandomMultiplier);
+ }
+
+ private void OnRandomMultiplierMapInit(Entity ent, ref MapInitEvent args)
+ {
+ ent.Comp.CurrentMultiplierOffset = _random.NextFloat(ent.Comp.MinMultiplierOffset, ent.Comp.MaxMultiplierOffset);
+ Dirty(ent);
+ }
+
+ private void OnGetRandomMultiplier(Entity ent, ref GetDeliveryMultiplierEvent args)
+ {
+ args.AdditiveMultiplier += ent.Comp.CurrentMultiplierOffset;
+ }
+}
diff --git a/Content.Shared/Delivery/DeliveryRandomMultiplierComponent.cs b/Content.Shared/Delivery/DeliveryRandomMultiplierComponent.cs
new file mode 100644
index 0000000000..d753d8aff2
--- /dev/null
+++ b/Content.Shared/Delivery/DeliveryRandomMultiplierComponent.cs
@@ -0,0 +1,32 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Delivery;
+
+///
+/// Component given to deliveries.
+/// Applies a random multiplier to the delivery on init.
+/// Added additively to the total multiplier.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+[Access(typeof(DeliveryModifierSystem))]
+public sealed partial class DeliveryRandomMultiplierComponent : Component
+{
+ ///
+ /// The highest the random multiplier can go.
+ ///
+ [DataField]
+ public float MaxMultiplierOffset = 0.2f;
+
+ ///
+ /// The lowest the random multiplier can go.
+ ///
+ [DataField]
+ public float MinMultiplierOffset = -0.2f;
+
+ ///
+ /// The current multiplier this component provides.
+ /// Gets randomized between MaxMultiplierOffset and MinMultiplierOffset on MapInit.
+ ///
+ [DataField, AutoNetworkedField]
+ public float CurrentMultiplierOffset;
+}
diff --git a/Content.Shared/Delivery/SharedDeliverySystem.cs b/Content.Shared/Delivery/SharedDeliverySystem.cs
index 53c5224940..1667035dac 100644
--- a/Content.Shared/Delivery/SharedDeliverySystem.cs
+++ b/Content.Shared/Delivery/SharedDeliverySystem.cs
@@ -54,12 +54,23 @@ public abstract class SharedDeliverySystem : EntitySystem
var jobTitle = ent.Comp.RecipientJobTitle ?? Loc.GetString("delivery-recipient-no-job");
var recipientName = ent.Comp.RecipientName ?? Loc.GetString("delivery-recipient-no-name");
- if (ent.Comp.IsOpened)
+ using (args.PushGroup(nameof(DeliveryComponent), 1))
{
- args.PushText(Loc.GetString("delivery-already-opened-examine"));
+ if (ent.Comp.IsOpened)
+ {
+ args.PushText(Loc.GetString("delivery-already-opened-examine"));
+ }
+
+ args.PushText(Loc.GetString("delivery-recipient-examine", ("recipient", recipientName), ("job", jobTitle)));
}
- args.PushText(Loc.GetString("delivery-recipient-examine", ("recipient", recipientName), ("job", jobTitle)));
+ if (ent.Comp.IsLocked)
+ {
+ var multiplier = GetDeliveryMultiplier(ent);
+ var totalSpesos = Math.Round(ent.Comp.BaseSpesoReward * multiplier);
+
+ args.PushMarkup(Loc.GetString("delivery-earnings-examine", ("spesos", totalSpesos)));
+ }
}
private void OnSpawnerExamine(Entity ent, ref ExaminedEvent args)
@@ -235,6 +246,20 @@ public abstract class SharedDeliverySystem : EntitySystem
_appearance.SetData(uid, DeliverySpawnerVisuals.Contents, contents > 0);
}
+ ///
+ /// Gathers the total multiplier for a delivery.
+ /// This is done by components having subscribed to GetDeliveryMultiplierEvent and having added onto it.
+ ///
+ /// The delivery for which to get the multiplier.
+ /// Total multiplier.
+ protected float GetDeliveryMultiplier(Entity ent)
+ {
+ var ev = new GetDeliveryMultiplierEvent();
+ RaiseLocalEvent(ent, ref ev);
+
+ return ev.AdditiveMultiplier * ev.MultiplicativeMultiplier;
+ }
+
protected virtual void GrantSpesoReward(Entity ent) { }
protected virtual void HandlePenalty(Entity ent, string? reason = null) { }
@@ -243,13 +268,16 @@ public abstract class SharedDeliverySystem : EntitySystem
}
///
-/// Used to gather the multiplier from all different delivery components.
+/// Used to gather the total multiplier for deliveries.
+/// This is done by various modifier components subscribing to this and adding accordingly.
///
+/// The additive multiplier.
+/// The multiplicative multiplier.
[ByRefEvent]
-public record struct GetDeliveryMultiplierEvent(float Multiplier)
+public record struct GetDeliveryMultiplierEvent(float AdditiveMultiplier, float MultiplicativeMultiplier)
{
// we can't use an optional parameter because the default parameterless constructor defaults everything
- public GetDeliveryMultiplierEvent() : this(1.0f) { }
+ public GetDeliveryMultiplierEvent() : this(1.0f, 1.0f) { }
}
///
diff --git a/Resources/Locale/en-US/delivery/delivery-component.ftl b/Resources/Locale/en-US/delivery/delivery-component.ftl
index a6bbc79343..5903094690 100644
--- a/Resources/Locale/en-US/delivery/delivery-component.ftl
+++ b/Resources/Locale/en-US/delivery/delivery-component.ftl
@@ -1,5 +1,6 @@
delivery-recipient-examine = This one is meant for {$recipient}, {$job}.
delivery-already-opened-examine = It was already opened.
+delivery-earnings-examine = Delivering this will earn the station [color=yellow]{$spesos}[/color] spesos.
delivery-recipient-no-name = Unnamed
delivery-recipient-no-job = Unknown
diff --git a/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml b/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml
index 19789cd7eb..2ff5e9daf7 100644
--- a/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml
+++ b/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml
@@ -36,6 +36,7 @@
failPopup: fingerprint-reader-fail
failGlovesPopup: fingerprint-reader-fail-gloves
- type: Delivery
+ - type: DeliveryRandomMultiplier
- type: ContainerContainer
containers:
delivery: !type:Container