Delivery system now has the possibility of penalisation (#36660)
* Add new fields to DeliveryComponent for #36636 * Setting the baseSpesoPenalty for currently available deliveries * Small fixes * Basic delivery penalization * Penalty and reward multiplier calculation in place Also fixes an issue in SharedCargoSystem when opening a delivery in dev server due to trying to allocate cargo twice. * Calling penalty no longer happens on opening * Extract multiplier getting * Removing unused include * Changing method description. \n\n Not actually sure what I meant by the first one * Localising default delivery messages * Unused include removal * minor tweaks * slarti changes * forgot * stuffs * yippee * Locn't * doc * Apply suggestions from code review --------- Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
using Content.Server.Cargo.Systems;
|
using Content.Server.Cargo.Systems;
|
||||||
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Server.StationRecords.Systems;
|
using Content.Server.StationRecords.Systems;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Content.Shared.Delivery;
|
using Content.Shared.Delivery;
|
||||||
using Content.Shared.FingerprintReader;
|
using Content.Shared.FingerprintReader;
|
||||||
using Content.Shared.Labels.EntitySystems;
|
using Content.Shared.Labels.EntitySystems;
|
||||||
using Content.Shared.StationRecords;
|
using Content.Shared.StationRecords;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Delivery;
|
namespace Content.Server.Delivery;
|
||||||
|
|
||||||
@@ -25,6 +28,13 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
|
|||||||
[Dependency] private readonly FingerprintReaderSystem _fingerprintReader = default!;
|
[Dependency] private readonly FingerprintReaderSystem _fingerprintReader = default!;
|
||||||
[Dependency] private readonly LabelSystem _label = default!;
|
[Dependency] private readonly LabelSystem _label = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
|
[Dependency] private readonly ChatSystem _chat = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default reason to use if the penalization is triggered
|
||||||
|
/// </summary>
|
||||||
|
private static readonly LocId DefaultMessage = "delivery-penalty-default-reason";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -39,19 +49,15 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
|
|||||||
{
|
{
|
||||||
_container.EnsureContainer<Container>(ent, ent.Comp.Container);
|
_container.EnsureContainer<Container>(ent, ent.Comp.Container);
|
||||||
|
|
||||||
var stationId = _station.GetStationInMap(Transform(ent).MapID);
|
if (_station.GetStationInMap(Transform(ent).MapID) is not { } stationId)
|
||||||
|
|
||||||
if (stationId == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_records.TryGetRandomRecord<GeneralStationRecord>(stationId.Value, out var entry);
|
if (!_records.TryGetRandomRecord<GeneralStationRecord>(stationId, out var entry))
|
||||||
|
|
||||||
if (entry == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ent.Comp.RecipientName = entry.Name;
|
ent.Comp.RecipientName = entry.Name;
|
||||||
ent.Comp.RecipientJobTitle = entry.JobTitle;
|
ent.Comp.RecipientJobTitle = entry.JobTitle;
|
||||||
ent.Comp.RecipientStation = stationId.Value;
|
ent.Comp.RecipientStation = stationId;
|
||||||
|
|
||||||
_appearance.SetData(ent, DeliveryVisuals.JobIcon, entry.JobIcon);
|
_appearance.SetData(ent, DeliveryVisuals.JobIcon, entry.JobIcon);
|
||||||
|
|
||||||
@@ -73,10 +79,74 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
|
|||||||
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var account))
|
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var account))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var stationAccountEnt = (ent.Comp.RecipientStation.Value, account);
|
||||||
|
|
||||||
|
var multiplier = GetDeliveryMultiplier(ent!); // Resolve so we know it's got the component
|
||||||
|
|
||||||
_cargo.UpdateBankAccount(
|
_cargo.UpdateBankAccount(
|
||||||
(ent.Comp.RecipientStation.Value, account),
|
stationAccountEnt,
|
||||||
ent.Comp.SpesoReward,
|
(int)(ent.Comp.BaseSpesoReward * multiplier),
|
||||||
_cargo.CreateAccountDistribution((ent.Comp.RecipientStation.Value, account)));
|
_cargo.CreateAccountDistribution((ent.Comp.RecipientStation.Value, account)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the penalty logic: Announcing the penalty and calculating how much to charge the designated account
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ent">The delivery for which to run the penalty.</param>
|
||||||
|
/// <param name="reason">The penalty reason, displayed in front of the message.</param>
|
||||||
|
protected override void HandlePenalty(Entity<DeliveryComponent> ent, string? reason = null)
|
||||||
|
{
|
||||||
|
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var stationAccount))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.WasPenalized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_protoMan.TryIndex(ent.Comp.PenaltyBankAccount, out var accountInfo))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var multiplier = GetDeliveryMultiplier(ent);
|
||||||
|
|
||||||
|
var localizedAccountName = Loc.GetString(accountInfo.Name);
|
||||||
|
|
||||||
|
reason ??= Loc.GetString(DefaultMessage);
|
||||||
|
|
||||||
|
var dist = new Dictionary<ProtoId<CargoAccountPrototype>, double>()
|
||||||
|
{
|
||||||
|
{ ent.Comp.PenaltyBankAccount, 1.0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var penaltyAccountBalance = stationAccount.Accounts[ent.Comp.PenaltyBankAccount];
|
||||||
|
var calculatedPenalty = (int)(ent.Comp.BaseSpesoPenalty * multiplier);
|
||||||
|
|
||||||
|
// Prevents cargo from going into negatives
|
||||||
|
if (calculatedPenalty > penaltyAccountBalance )
|
||||||
|
calculatedPenalty = Math.Max(0, penaltyAccountBalance);
|
||||||
|
|
||||||
|
_cargo.UpdateBankAccount(
|
||||||
|
(ent.Comp.RecipientStation.Value, stationAccount),
|
||||||
|
-calculatedPenalty,
|
||||||
|
dist);
|
||||||
|
|
||||||
|
var message = Loc.GetString("delivery-penalty-message", ("reason", reason), ("spesos", calculatedPenalty), ("account", localizedAccountName.ToUpper()));
|
||||||
|
_chat.TrySendInGameICMessage(ent, message, InGameICChatType.Speak, hideChat: true);
|
||||||
|
|
||||||
|
ent.Comp.WasPenalized = true;
|
||||||
|
DirtyField(ent.Owner, ent.Comp, nameof(DeliveryComponent.WasPenalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gathers the total multiplier for a delivery.
|
||||||
|
/// This is done by components having subscribed to GetDeliveryMultiplierEvent and having added onto it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ent">The delivery for which to get the multiplier.</param>
|
||||||
|
/// <returns>Total multiplier.</returns>
|
||||||
|
private float GetDeliveryMultiplier(Entity<DeliveryComponent> ent)
|
||||||
|
{
|
||||||
|
var ev = new GetDeliveryMultiplierEvent();
|
||||||
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
|
return ev.Multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Delivery;
|
namespace Content.Shared.Delivery;
|
||||||
|
|
||||||
@@ -23,10 +25,16 @@ public sealed partial class DeliveryComponent : Component
|
|||||||
public bool IsLocked = true;
|
public bool IsLocked = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of spesos that gets added to the station bank account on unlock.
|
/// The base amount of spesos that gets added to the station bank account on unlock.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public int SpesoReward = 500;
|
public int BaseSpesoReward = 500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The base amount of spesos that will be removed from the station bank account on a penalized delivery
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public int BaseSpesoPenalty = 250;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the recipient of this delivery.
|
/// The name of the recipient of this delivery.
|
||||||
@@ -48,6 +56,19 @@ public sealed partial class DeliveryComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntityUid? RecipientStation;
|
public EntityUid? RecipientStation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bank account ID of the account to subtract funds from in case of penalization
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public ProtoId<CargoAccountPrototype> PenaltyBankAccount = "Cargo";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this delivery has already received a penalty.
|
||||||
|
/// Used to avoid getting penalized several times.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool WasPenalized;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The sound to play when the delivery is unlocked.
|
/// The sound to play when the delivery is unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using Content.Shared.EntityTable.EntitySelectors;
|
using Content.Shared.EntityTable.EntitySelectors;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Shared.Delivery;
|
namespace Content.Shared.Delivery;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -210,9 +210,21 @@ public abstract class SharedDeliverySystem : EntitySystem
|
|||||||
|
|
||||||
protected virtual void GrantSpesoReward(Entity<DeliveryComponent?> ent) { }
|
protected virtual void GrantSpesoReward(Entity<DeliveryComponent?> ent) { }
|
||||||
|
|
||||||
|
protected virtual void HandlePenalty(Entity<DeliveryComponent> ent, string? reason = null) { }
|
||||||
|
|
||||||
protected virtual void SpawnDeliveries(Entity<DeliverySpawnerComponent?> ent) { }
|
protected virtual void SpawnDeliveries(Entity<DeliverySpawnerComponent?> ent) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to gather the multiplier from all different delivery components.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct GetDeliveryMultiplierEvent(float Multiplier)
|
||||||
|
{
|
||||||
|
// we can't use an optional parameter because the default parameterless constructor defaults everything
|
||||||
|
public GetDeliveryMultiplierEvent() : this(1.0f) { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event raised on the delivery when it is unlocked.
|
/// Event raised on the delivery when it is unlocked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
4
Resources/Locale/en-US/delivery/delivery-messages.ftl
Normal file
4
Resources/Locale/en-US/delivery/delivery-messages.ftl
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
delivery-penalty-default-reason = WARNING
|
||||||
|
delivery-penalty-default-account-name = UNKNOWN ACCOUNT
|
||||||
|
|
||||||
|
delivery-penalty-message = {$reason}! INVOKING A PENALTY OF {$spesos} SPESOS ON {$account}!
|
||||||
@@ -74,7 +74,10 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
size: Huge
|
size: Huge
|
||||||
- type: Delivery
|
- type: Delivery
|
||||||
spesoReward: 1000
|
baseSpesoReward: 1000
|
||||||
|
baseSpesoPenalty: 500
|
||||||
|
- type: Speech
|
||||||
|
speechVerb: Robotic
|
||||||
- type: EntityTableContainerFill
|
- type: EntityTableContainerFill
|
||||||
containers:
|
containers:
|
||||||
delivery: !type:NestedSelector
|
delivery: !type:NestedSelector
|
||||||
@@ -111,7 +114,10 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
storedRotation: 90
|
storedRotation: 90
|
||||||
- type: Delivery
|
- type: Delivery
|
||||||
spesoReward: 500
|
baseSpesoReward: 500
|
||||||
|
baseSpesoPenalty: 250
|
||||||
|
- type: Speech
|
||||||
|
speechVerb: Robotic
|
||||||
- type: EntityTableContainerFill
|
- type: EntityTableContainerFill
|
||||||
containers:
|
containers:
|
||||||
delivery: !type:NestedSelector
|
delivery: !type:NestedSelector
|
||||||
|
|||||||
Reference in New Issue
Block a user