From 2fdfb4b14a6d5ff2463c410fe7dc11b1dacb0186 Mon Sep 17 00:00:00 2001 From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Date: Mon, 21 Apr 2025 11:32:18 +0200 Subject: [PATCH] Reworked Mail Spawning (#36774) * init * stuff --- .../Delivery/DeliveryVisualizerSystem.cs | 6 +++ .../Delivery/DeliverySystem.Spawning.cs | 42 +++++++++------ .../Delivery/DeliverySpawnerComponent.cs | 21 +++++++- Content.Shared/Delivery/DeliveryVisuals.cs | 6 +++ .../Delivery/SharedDeliverySystem.cs | 50 ++++++++++++++++-- .../en-US/delivery/delivery-component.ftl | 8 +++ .../Structures/Machines/mail_teleporter.yml | 7 +++ .../Structures/mailbox.rsi/contents.png | Bin 0 -> 7319 bytes .../Textures/Structures/mailbox.rsi/meta.json | 5 +- 9 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 Resources/Textures/Structures/mailbox.rsi/contents.png diff --git a/Content.Client/Delivery/DeliveryVisualizerSystem.cs b/Content.Client/Delivery/DeliveryVisualizerSystem.cs index 8ed15344a4..bf4a8f066b 100644 --- a/Content.Client/Delivery/DeliveryVisualizerSystem.cs +++ b/Content.Client/Delivery/DeliveryVisualizerSystem.cs @@ -43,3 +43,9 @@ public enum DeliveryVisualLayers : byte Breakage, Trash, } + +public enum DeliverySpawnerVisualLayers : byte +{ + Contents, +} + diff --git a/Content.Server/Delivery/DeliverySystem.Spawning.cs b/Content.Server/Delivery/DeliverySystem.Spawning.cs index 19087e7448..a7496a343b 100644 --- a/Content.Server/Delivery/DeliverySystem.Spawning.cs +++ b/Content.Server/Delivery/DeliverySystem.Spawning.cs @@ -1,6 +1,6 @@ -using Content.Server.Power.EntitySystems; -using Content.Server.StationRecords; using Content.Shared.Delivery; +using Content.Shared.Power.EntitySystems; +using Content.Server.StationRecords; using Content.Shared.EntityTable; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -16,7 +16,7 @@ public sealed partial class DeliverySystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly EntityTableSystem _entityTable = default!; - [Dependency] private readonly PowerReceiverSystem _power = default!; + [Dependency] private readonly SharedPowerReceiverSystem _power = default!; private void InitializeSpawning() { @@ -28,16 +28,14 @@ public sealed partial class DeliverySystem ent.Comp.NextDelivery = _timing.CurTime + ent.Comp.MinDeliveryCooldown; // We want an early wave of mail so cargo doesn't have to wait } - private void SpawnDelivery(Entity ent, int amount) + protected override void SpawnDeliveries(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp)) return; var coords = Transform(ent).Coordinates; - _audio.PlayPvs(ent.Comp.SpawnSound, ent.Owner); - - for (int i = 0; i < amount; i++) + for (int i = 0; i < ent.Comp.ContainedDeliveryAmount; i++) { var spawns = _entityTable.GetSpawns(ent.Comp.Table); @@ -46,9 +44,12 @@ public sealed partial class DeliverySystem Spawn(id, coords); } } + + ent.Comp.ContainedDeliveryAmount = 0; + Dirty(ent); } - private void SpawnStationDeliveries(Entity ent) + private void AdjustStationDeliveries(Entity ent) { if (!TryComp(ent, out var records)) return; @@ -72,7 +73,7 @@ public sealed partial class DeliverySystem { foreach (var spawner in spawners) { - SpawnDelivery(spawner, deliveryCount); + AddDeliveriesToSpawner(spawner, deliveryCount); } } else @@ -87,18 +88,18 @@ public sealed partial class DeliverySystem } for (int j = 0; j < spawners.Count; j++) { - SpawnDelivery(spawners[j], amounts[j]); + AddDeliveriesToSpawner(spawners[j], amounts[j]); } } } - private List GetValidSpawners(Entity ent) + private List> GetValidSpawners(Entity ent) { - var validSpawners = new List(); + var validSpawners = new List>(); var spawners = EntityQueryEnumerator(); - while (spawners.MoveNext(out var spawnerUid, out _)) + while (spawners.MoveNext(out var spawnerUid, out var spawnerComp)) { var spawnerStation = _station.GetOwningStation(spawnerUid); @@ -108,12 +109,23 @@ public sealed partial class DeliverySystem if (!_power.IsPowered(spawnerUid)) continue; - validSpawners.Add(spawnerUid); + if (spawnerComp.ContainedDeliveryAmount >= spawnerComp.MaxContainedDeliveryAmount) + continue; + + validSpawners.Add((spawnerUid, spawnerComp)); } return validSpawners; } + private void AddDeliveriesToSpawner(Entity ent, int amount) + { + ent.Comp.ContainedDeliveryAmount += Math.Clamp(amount, 0, ent.Comp.MaxContainedDeliveryAmount - ent.Comp.ContainedDeliveryAmount); + _audio.PlayPvs(ent.Comp.SpawnSound, ent.Owner); + UpdateDeliverySpawnerVisuals(ent, ent.Comp.ContainedDeliveryAmount); + Dirty(ent); + } + private void UpdateSpawner(float frameTime) { var dataQuery = EntityQueryEnumerator(); @@ -125,7 +137,7 @@ public sealed partial class DeliverySystem continue; deliveryData.NextDelivery += _random.Next(deliveryData.MinDeliveryCooldown, deliveryData.MaxDeliveryCooldown); // Random cooldown between min and max - SpawnStationDeliveries((uid, deliveryData)); + AdjustStationDeliveries((uid, deliveryData)); } } } diff --git a/Content.Shared/Delivery/DeliverySpawnerComponent.cs b/Content.Shared/Delivery/DeliverySpawnerComponent.cs index 4491509cb3..9ed3ff1b91 100644 --- a/Content.Shared/Delivery/DeliverySpawnerComponent.cs +++ b/Content.Shared/Delivery/DeliverySpawnerComponent.cs @@ -9,7 +9,7 @@ namespace Content.Shared.Delivery; /// Used to mark entities that are valid for spawning deliveries on. /// If this requires power, it needs to be powered to count as a valid spawner. /// -[RegisterComponent, NetworkedComponent] +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class DeliverySpawnerComponent : Component { /// @@ -18,9 +18,28 @@ public sealed partial class DeliverySpawnerComponent : Component [DataField(required: true)] public EntityTableSelector Table = default!; + /// + /// The max amount of deliveries this spawner can hold at a time. + /// + [DataField] + public int MaxContainedDeliveryAmount = 20; + + /// + /// The currently held amount of deliveries. + /// They are stored as an int and only spawned on use, as to not create additional entities without the need to. + /// + [DataField, AutoNetworkedField] + public int ContainedDeliveryAmount; + /// /// The sound to play when the spawner spawns a delivery. /// [DataField] public SoundSpecifier? SpawnSound = new SoundCollectionSpecifier("DeliverySpawnSounds", AudioParams.Default.WithVolume(-7)); + + /// + /// The sound to play when a spawner is opened, and spills all the deliveries out. + /// + [DataField] + public SoundSpecifier? OpenSound = new SoundCollectionSpecifier("storageRustle"); } diff --git a/Content.Shared/Delivery/DeliveryVisuals.cs b/Content.Shared/Delivery/DeliveryVisuals.cs index 6da45b6277..69eb5fda9e 100644 --- a/Content.Shared/Delivery/DeliveryVisuals.cs +++ b/Content.Shared/Delivery/DeliveryVisuals.cs @@ -13,3 +13,9 @@ public enum DeliveryVisuals : byte IsPriorityInactive, JobIcon, } + +[Serializable, NetSerializable] +public enum DeliverySpawnerVisuals : byte +{ + Contents, +} diff --git a/Content.Shared/Delivery/SharedDeliverySystem.cs b/Content.Shared/Delivery/SharedDeliverySystem.cs index 319bf41fce..8d343b4acb 100644 --- a/Content.Shared/Delivery/SharedDeliverySystem.cs +++ b/Content.Shared/Delivery/SharedDeliverySystem.cs @@ -38,12 +38,15 @@ public abstract class SharedDeliverySystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnDeliveryExamine); SubscribeLocalEvent(OnUseInHand); - SubscribeLocalEvent>(OnGetVerbs); + SubscribeLocalEvent>(OnGetDeliveryVerbs); + + SubscribeLocalEvent(OnSpawnerExamine); + SubscribeLocalEvent>(OnGetSpawnerVerbs); } - private void OnExamine(Entity ent, ref ExaminedEvent args) + private void OnDeliveryExamine(Entity ent, ref ExaminedEvent args) { var jobTitle = ent.Comp.RecipientJobTitle ?? Loc.GetString("delivery-recipient-no-job"); var recipientName = ent.Comp.RecipientName ?? Loc.GetString("delivery-recipient-no-name"); @@ -56,6 +59,11 @@ public abstract class SharedDeliverySystem : EntitySystem args.PushText(Loc.GetString("delivery-recipient-examine", ("recipient", recipientName), ("job", jobTitle))); } + private void OnSpawnerExamine(Entity ent, ref ExaminedEvent args) + { + args.PushMarkup(Loc.GetString("delivery-teleporter-amount-examine", ("amount", ent.Comp.ContainedDeliveryAmount)), 50); + } + private void OnUseInHand(Entity ent, ref UseInHandEvent args) { args.Handled = true; @@ -69,7 +77,7 @@ public abstract class SharedDeliverySystem : EntitySystem OpenDelivery(ent, args.User); } - private void OnGetVerbs(Entity ent, ref GetVerbsEvent args) + private void OnGetDeliveryVerbs(Entity ent, ref GetVerbsEvent args) { if (!args.CanAccess || !args.CanInteract || args.Hands == null || ent.Comp.IsOpened) return; @@ -92,6 +100,33 @@ public abstract class SharedDeliverySystem : EntitySystem }); } + private void OnGetSpawnerVerbs(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || args.Hands == null) + return; + + var user = args.User; + + args.Verbs.Add(new AlternativeVerb() + { + Act = () => + { + _audio.PlayPredicted(ent.Comp.OpenSound, ent.Owner, user); + + if(ent.Comp.ContainedDeliveryAmount == 0) + { + _popup.PopupPredicted(Loc.GetString("delivery-teleporter-empty", ("entity", ent)), null, ent, user); + return; + } + + SpawnDeliveries(ent.Owner); + + UpdateDeliverySpawnerVisuals(ent, ent.Comp.ContainedDeliveryAmount); + }, + Text = Loc.GetString("delivery-teleporter-empty-verb"), + }); + } + private bool TryUnlockDelivery(Entity ent, EntityUid user, bool rewardMoney = true) { // Check fingerprint access if there is a reader on the mail @@ -168,7 +203,14 @@ public abstract class SharedDeliverySystem : EntitySystem _appearance.SetData(uid, DeliveryVisuals.IsPriority, false); } + protected void UpdateDeliverySpawnerVisuals(EntityUid uid, int contents) + { + _appearance.SetData(uid, DeliverySpawnerVisuals.Contents, contents > 0); + } + protected virtual void GrantSpesoReward(Entity ent) { } + + protected virtual void SpawnDeliveries(Entity ent) { } } /// diff --git a/Resources/Locale/en-US/delivery/delivery-component.ftl b/Resources/Locale/en-US/delivery/delivery-component.ftl index 499b708284..fbe4e74937 100644 --- a/Resources/Locale/en-US/delivery/delivery-component.ftl +++ b/Resources/Locale/en-US/delivery/delivery-component.ftl @@ -10,3 +10,11 @@ delivery-opened-others = {CAPITALIZE($recipient)} opened the {$delivery}. delivery-unlock-verb = Unlock delivery-open-verb = Open + +delivery-teleporter-amount-examine = + { $amount -> + [one] It contains [color=yellow]{$amount}[/color] delivery. + *[other] It contains [color=yellow]{$amount}[/color] deliveries. + } +delivery-teleporter-empty = The {$entity} is empty. +delivery-teleporter-empty-verb = Take mail diff --git a/Resources/Prototypes/Entities/Structures/Machines/mail_teleporter.yml b/Resources/Prototypes/Entities/Structures/Machines/mail_teleporter.yml index a03f166bbe..6842e3c958 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/mail_teleporter.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/mail_teleporter.yml @@ -20,6 +20,9 @@ snapCardinals: true layers: - state: icon + - state: contents + map: [ "enum.DeliverySpawnerVisualLayers.Contents" ] + visible: false - state: unlit shader: unshaded visible: false @@ -32,6 +35,10 @@ - type: Appearance - type: GenericVisualizer visuals: + enum.DeliverySpawnerVisuals.Contents: + enum.DeliverySpawnerVisualLayers.Contents: + True: { visible: true } + False: { visible: false } enum.PowerDeviceVisuals.Powered: enum.PowerDeviceVisualLayers.Powered: True: { visible: true } diff --git a/Resources/Textures/Structures/mailbox.rsi/contents.png b/Resources/Textures/Structures/mailbox.rsi/contents.png new file mode 100644 index 0000000000000000000000000000000000000000..45fab01257b9271f8c302e228534876da78b7a39 GIT binary patch literal 7319 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 jKN*}FGn3MW^kJ&=c(&3XVJM%nKpKbpK7*>40 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/mailbox.rsi/meta.json b/Resources/Textures/Structures/mailbox.rsi/meta.json index ce3494c3d4..711646c2b3 100644 --- a/Resources/Textures/Structures/mailbox.rsi/meta.json +++ b/Resources/Textures/Structures/mailbox.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Created by meijunkie on Discord, funkystation.org at commit https://github.com/funky-station/funky-station/commit/430be9247ac220367f338c2c1a716a7503b1446d", + "copyright": "Created by meijunkie on Discord, funkystation.org at commit https://github.com/funky-station/funky-station/commit/430be9247ac220367f338c2c1a716a7503b1446d, contents by ScarKy0 (Github)", "size": { "x": 32, "y": 32 @@ -12,6 +12,9 @@ }, { "name": "unlit" + }, + { + "name": "contents" } ] } -- 2.51.2