using Content.Server.Cargo.Components;
using Content.Server.Cargo.Systems;
using Content.Server.CartridgeLoader.Cartridges;
using Content.Server.Chat.Systems;
using Content.Server.Station.Systems;
using Content.Server.StationRecords.Systems;
using Content.Shared.Chat;
using Content.Shared.Delivery;
using Content.Shared.Destructible;
using Content.Shared.FingerprintReader;
using Content.Shared.Labels.EntitySystems;
using Content.Shared.StationRecords;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
namespace Content.Server.Delivery;
///
/// System for managing deliveries spawned by the mail teleporter.
/// This covers for mail spawning, as well as granting cargo money.
///
public sealed partial class DeliverySystem : SharedDeliverySystem
{
[Dependency] private readonly CargoSystem _cargo = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly StationRecordsSystem _records = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly FingerprintReaderSystem _fingerprintReader = default!;
[Dependency] private readonly SharedLabelSystem _label = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly MailMetricsCartridgeSystem _mailMetricsCartridge = default!;
[Dependency] private readonly LogisticStatsSystem _logisticsStats = default!;
[Dependency] private readonly ChatSystem _chat = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnMapInit);
InitializeSpawning();
}
private void OnMapInit(Entity ent, ref MapInitEvent args)
{
_container.EnsureContainer(ent, ent.Comp.Container);
var stationId = _station.GetStationInMap(Transform(ent).MapID);
if (stationId == null)
return;
_records.TryGetRandomRecord(stationId.Value, out var entry);
_mailMetricsCartridge.UpdateAllCartridges(stationId.Value);
if (entry == null)
return;
ent.Comp.RecipientName = entry.Name;
ent.Comp.RecipientJobTitle = entry.JobTitle;
ent.Comp.RecipientStation = stationId.Value;
_appearance.SetData(ent, DeliveryVisuals.JobIcon, entry.JobIcon);
_label.Label(ent, ent.Comp.RecipientName);
if (TryComp(ent, out var reader) && entry.Fingerprint != null)
{
_fingerprintReader.AddAllowedFingerprint((ent.Owner, reader), entry.Fingerprint);
}
Dirty(ent);
}
protected override void OnDestruction(Entity ent, ref DestructionEventArgs args)
{
base.OnDestruction(ent, ref args);
if (!ent.Comp.IsLocked)
return;
ExecuteForEachLogisticsStats(
ent,
(station, logisticStats) =>
{
_logisticsStats.AddTamperedMailLosses(
station,
logisticStats,
ent.Comp.IsProfitable ? ent.Comp.SpesoPenalty : 0);
});
WithdrawSpesoPenalty(ent.AsNullable());
}
protected override void OnBreak(Entity ent, ref BreakageEventArgs args)
{
base.OnBreak(ent, ref args);
if (!ent.Comp.IsFragile)
return;
WithdrawSpesoPenalty(ent.AsNullable());
ExecuteForEachLogisticsStats(
ent,
(station, logisticStats) =>
{
_logisticsStats.AddDamagedMailLosses(
station,
logisticStats,
ent.Comp.IsProfitable ? ent.Comp.SpesoPenalty : 0);
});
}
private void ExecuteForEachLogisticsStats(EntityUid uid, Action action)
{
var query = EntityQueryEnumerator();
while (query.MoveNext(out var station, out var logisticStats))
{
if (_station.GetOwningStation(uid) != station)
continue;
action(station, logisticStats);
}
}
protected override void OpenDelivery(Entity ent, EntityUid user, bool attemptPickup = true)
{
base.OpenDelivery(ent, user, attemptPickup);
ExecuteForEachLogisticsStats(
ent,
(station, logisticStats) =>
{
_logisticsStats.AddOpenedMailEarnings(
station,
logisticStats,
ent.Comp.IsProfitable ? ent.Comp.SpesoReward : 0);
});
}
protected override void GrantSpesoReward(Entity ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
if (!ent.Comp.IsProfitable)
return;
if (!TryComp(ent.Comp.RecipientStation, out var account))
return;
_cargo.UpdateBankAccount(ent, account, ent.Comp.SpesoReward);
}
protected override void WithdrawSpesoPenalty(Entity ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
if (ent.Comp.IsPriority)
_appearance.SetData(ent, DeliveryVisuals.IsPriorityInactive, true);
if (!ent.Comp.IsProfitable)
return;
_chat.TrySendInGameICMessage(ent, Loc.GetString("delivery-penalty", ("credits", ent.Comp.SpesoPenalty)), InGameICChatType.Speak, false);
_audio.PlayPvs(ent.Comp.PenaltySound, ent);
if (!TryComp(ent.Comp.RecipientStation, out var account))
return;
_cargo.UpdateBankAccount(ent, account, ent.Comp.SpesoPenalty);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
UpdateSpawner(frameTime);
}
}