From 30537e13a4073c6815d0870465dd6b0e1a6bd83e Mon Sep 17 00:00:00 2001 From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Date: Sun, 18 May 2025 10:57:22 +0200 Subject: [PATCH] Bomb Deliveries (#37069) * init * BOMB!!! * review * partial review * review --- .../Delivery/DeliveryVisualizerSystem.cs | 2 + .../Delivery/DeliveryBombComponent.cs | 65 +++++++++++ .../Delivery/DeliveryModifierSystem.cs | 104 ++++++++++++++++++ Content.Shared/Delivery/DeliveryVisuals.cs | 9 ++ .../Delivery/PrimedDeliveryBombComponent.cs | 11 ++ .../Delivery/SharedDeliverySystem.cs | 7 ++ .../en-US/delivery/delivery-component.ftl | 3 + .../Objects/Deliveries/deliveries.yml | 43 ++++++++ .../{bomb-unshaded.png => bomb_unshaded.png} | Bin .../Objects/Specific/Cargo/mail.rsi/meta.json | 2 +- .../{bomb-unshaded.png => bomb_unshaded.png} | Bin .../Specific/Cargo/mail_large.rsi/meta.json | 2 +- 12 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 Content.Shared/Delivery/DeliveryBombComponent.cs create mode 100644 Content.Shared/Delivery/PrimedDeliveryBombComponent.cs rename Resources/Textures/Objects/Specific/Cargo/mail.rsi/{bomb-unshaded.png => bomb_unshaded.png} (100%) rename Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/{bomb-unshaded.png => bomb_unshaded.png} (100%) diff --git a/Content.Client/Delivery/DeliveryVisualizerSystem.cs b/Content.Client/Delivery/DeliveryVisualizerSystem.cs index bf4a8f066b..68149e248d 100644 --- a/Content.Client/Delivery/DeliveryVisualizerSystem.cs +++ b/Content.Client/Delivery/DeliveryVisualizerSystem.cs @@ -42,6 +42,8 @@ public enum DeliveryVisualLayers : byte PriorityTape, Breakage, Trash, + Bomb, + BombPrimed, } public enum DeliverySpawnerVisualLayers : byte diff --git a/Content.Shared/Delivery/DeliveryBombComponent.cs b/Content.Shared/Delivery/DeliveryBombComponent.cs new file mode 100644 index 0000000000..a51bb839ee --- /dev/null +++ b/Content.Shared/Delivery/DeliveryBombComponent.cs @@ -0,0 +1,65 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Delivery; + +/// +/// Component given to deliveries. +/// This delivery will "prime" based on circumstances defined in the datafield. +/// When primed, it will attempt to explode every few seconds, with the chance increasing each time it fails to do so. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause] +[Access(typeof(DeliveryModifierSystem))] +public sealed partial class DeliveryBombComponent : Component +{ + /// + /// How often will this bomb retry to explode. + /// + [DataField] + public TimeSpan ExplosionRetryDelay = TimeSpan.FromSeconds(5); + + /// + /// The time at which the next retry will happen + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField] + public TimeSpan NextExplosionRetry; + + /// + /// The chance this bomb explodes each time it attempts to do so. + /// + [DataField, AutoNetworkedField] + public float ExplosionChance = 0.01f; + + /// + /// How much should the chance of explosion increase each failed retry? + /// + [DataField] + public float ExplosionChanceRetryIncrease = 0.01f; + + /// + /// Should this bomb get primed when the delivery is unlocked? + /// + [DataField] + public bool PrimeOnUnlock = true; + + /// + /// Should this bomb get primed when the delivery is broken? + /// Requires to be fragile as well. + /// + [DataField] + public bool PrimeOnBreakage = true; + + /// + /// Should this bomb get primed when the delivery expires? + /// Requires to be priority as well. + /// + [DataField] + public bool PrimeOnExpire = true; + + /// + /// Multiplier to choose when a crazy person actually opens it. + /// Multiplicative, not additive. + /// + [DataField] + public float SpesoMultiplier = 1.5f; +} diff --git a/Content.Shared/Delivery/DeliveryModifierSystem.cs b/Content.Shared/Delivery/DeliveryModifierSystem.cs index 2b071b18cf..0e3f620f26 100644 --- a/Content.Shared/Delivery/DeliveryModifierSystem.cs +++ b/Content.Shared/Delivery/DeliveryModifierSystem.cs @@ -1,6 +1,10 @@ +using Content.Shared.Audio; using Content.Shared.Destructible; using Content.Shared.Examine; +using Content.Shared.Explosion.EntitySystems; using Content.Shared.NameModifier.EntitySystems; +using JetBrains.Annotations; +using Robust.Shared.Network; using Robust.Shared.Random; using Robust.Shared.Serialization; using Robust.Shared.Timing; @@ -14,8 +18,11 @@ public sealed partial class DeliveryModifierSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly NameModifierSystem _nameModifier = default!; [Dependency] private readonly SharedDeliverySystem _delivery = default!; + [Dependency] private readonly SharedExplosionSystem _explosion = default!; + [Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!; public override void Initialize() { @@ -33,6 +40,14 @@ public sealed partial class DeliveryModifierSystem : EntitySystem SubscribeLocalEvent(OnFragileBreakage); SubscribeLocalEvent(OnFragileExamine); SubscribeLocalEvent(OnGetFragileMultiplier); + + SubscribeLocalEvent(OnExplosiveStartup); + SubscribeLocalEvent(OnPrimedExplosiveMapInit); + SubscribeLocalEvent(OnExplosiveExamine); + SubscribeLocalEvent(OnGetExplosiveMultiplier); + SubscribeLocalEvent(OnExplosiveUnlock); + SubscribeLocalEvent(OnExplosiveExpire); + SubscribeLocalEvent(OnExplosiveBreak); } #region Random @@ -119,12 +134,80 @@ public sealed partial class DeliveryModifierSystem : EntitySystem } #endregion + #region Explosive + private void OnExplosiveStartup(Entity ent, ref ComponentStartup args) + { + _delivery.UpdateBombVisuals(ent); + } + + private void OnPrimedExplosiveMapInit(Entity ent, ref MapInitEvent args) + { + if (!TryComp(ent, out var bomb)) + return; + + bomb.NextExplosionRetry = _timing.CurTime; + } + + private void OnExplosiveExamine(Entity ent, ref ExaminedEvent args) + { + var trueName = _nameModifier.GetBaseName(ent.Owner); + + var isPrimed = HasComp(ent); + + if (isPrimed) + args.PushMarkup(Loc.GetString("delivery-bomb-primed-examine", ("type", trueName))); + else + args.PushMarkup(Loc.GetString("delivery-bomb-examine", ("type", trueName))); + } + + private void OnGetExplosiveMultiplier(Entity ent, ref GetDeliveryMultiplierEvent args) + { + // Big danger for big rewards + args.MultiplicativeMultiplier += ent.Comp.SpesoMultiplier; + } + + private void OnExplosiveUnlock(Entity ent, ref DeliveryUnlockedEvent args) + { + if (!ent.Comp.PrimeOnUnlock) + return; + + PrimeBombDelivery(ent); + } + + private void OnExplosiveExpire(Entity ent, ref DeliveryPriorityExpiredEvent args) + { + if (!ent.Comp.PrimeOnExpire) + return; + + PrimeBombDelivery(ent); + } + + private void OnExplosiveBreak(Entity ent, ref BreakageEventArgs args) + { + if (!ent.Comp.PrimeOnBreakage) + return; + + PrimeBombDelivery(ent); + } + + [PublicAPI] + public void PrimeBombDelivery(Entity ent) + { + EnsureComp(ent); + + _delivery.UpdateBombVisuals(ent); + + _ambientSound.SetAmbience(ent, true); + } + #endregion + #region Update Loops public override void Update(float frameTime) { base.Update(frameTime); UpdatePriorty(frameTime); + UpdateBomb(frameTime); } private void UpdatePriorty(float frameTime) @@ -148,6 +231,27 @@ public sealed partial class DeliveryModifierSystem : EntitySystem } } } + + private void UpdateBomb(float frameTime) + { + var bombQuery = EntityQueryEnumerator(); + var curTime = _timing.CurTime; + + while (bombQuery.MoveNext(out var uid, out _, out var bombData)) + { + if (bombData.NextExplosionRetry > curTime) + continue; + + bombData.NextExplosionRetry += bombData.ExplosionRetryDelay; + + // Explosions cannot be predicted. + if (_net.IsServer && _random.NextFloat() < bombData.ExplosionChance) + _explosion.TriggerExplosive(uid); + + bombData.ExplosionChance += bombData.ExplosionChanceRetryIncrease; + Dirty(uid, bombData); + } + } #endregion } diff --git a/Content.Shared/Delivery/DeliveryVisuals.cs b/Content.Shared/Delivery/DeliveryVisuals.cs index 35391854be..b63d6a20bb 100644 --- a/Content.Shared/Delivery/DeliveryVisuals.cs +++ b/Content.Shared/Delivery/DeliveryVisuals.cs @@ -9,6 +9,7 @@ public enum DeliveryVisuals : byte IsTrash, IsBroken, IsFragile, + IsBomb, PriorityState, JobIcon, } @@ -21,6 +22,14 @@ public enum DeliveryPriorityState : byte Inactive, } +[Serializable, NetSerializable] +public enum DeliveryBombState : byte +{ + Off, + Inactive, + Primed, +} + [Serializable, NetSerializable] public enum DeliverySpawnerVisuals : byte { diff --git a/Content.Shared/Delivery/PrimedDeliveryBombComponent.cs b/Content.Shared/Delivery/PrimedDeliveryBombComponent.cs new file mode 100644 index 0000000000..f3fd124f28 --- /dev/null +++ b/Content.Shared/Delivery/PrimedDeliveryBombComponent.cs @@ -0,0 +1,11 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Delivery; + +/// +/// Component given to deliveries. +/// Indicates this bomb delivery is primed. +/// +[RegisterComponent, NetworkedComponent] +[Access(typeof(DeliveryModifierSystem))] +public sealed partial class PrimedDeliveryBombComponent : Component; diff --git a/Content.Shared/Delivery/SharedDeliverySystem.cs b/Content.Shared/Delivery/SharedDeliverySystem.cs index 175dfbe70d..52f83500e1 100644 --- a/Content.Shared/Delivery/SharedDeliverySystem.cs +++ b/Content.Shared/Delivery/SharedDeliverySystem.cs @@ -259,6 +259,13 @@ public abstract class SharedDeliverySystem : EntitySystem _appearance.SetData(ent, DeliveryVisuals.IsFragile, isFragile); } + public void UpdateBombVisuals(Entity ent) + { + var isPrimed = HasComp(ent); + + _appearance.SetData(ent, DeliveryVisuals.IsBomb, isPrimed ? DeliveryBombState.Primed : DeliveryBombState.Inactive); + } + protected void UpdateDeliverySpawnerVisuals(EntityUid uid, int contents) { _appearance.SetData(uid, DeliverySpawnerVisuals.Contents, contents > 0); diff --git a/Resources/Locale/en-US/delivery/delivery-component.ftl b/Resources/Locale/en-US/delivery/delivery-component.ftl index c346b2a813..306dd9b044 100644 --- a/Resources/Locale/en-US/delivery/delivery-component.ftl +++ b/Resources/Locale/en-US/delivery/delivery-component.ftl @@ -29,3 +29,6 @@ delivery-priority-expired-examine = This is a [color=orange]priority {$type}[/co delivery-fragile-examine = This is a [color=red]fragile {$type}[/color]. Deliver it intact for a bonus. delivery-fragile-broken-examine = This is a [color=red]fragile {$type}[/color]. It looks badly damaged. + +delivery-bomb-examine = This is a [color=purple]bomb {$type}[/color]. Oh no. +delivery-bomb-primed-examine = This is a [color=purple]bomb {$type}[/color]. Reading this is a bad use of your time. diff --git a/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml b/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml index a209f5c6f7..acf88fc8b3 100644 --- a/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml +++ b/Resources/Prototypes/Entities/Objects/Deliveries/deliveries.yml @@ -27,6 +27,15 @@ enum.DeliveryVisualLayers.Trash: True: { visible: true } False: { visible: false } + enum.DeliveryVisuals.IsBomb: + enum.DeliveryVisualLayers.Bomb: + Off: { visible: false } + Inactive: { visible: true } + Primed: { visible: true } + enum.DeliveryVisualLayers.BombPrimed: + Off: { visible: false } + Inactive: { visible: false } + Primed: { visible: true } - type: Label examinable: false - type: FingerprintReader @@ -74,6 +83,13 @@ - state: broken map: [ "enum.DeliveryVisualLayers.Breakage" ] visible: false + - state: bomb + map: [ "enum.DeliveryVisualLayers.Bomb" ] + visible: false + - state: bomb_unshaded + map: [ "enum.DeliveryVisualLayers.BombPrimed" ] + shader: unshaded + visible: false - type: MultiHandedItem - type: Item size: Huge @@ -117,6 +133,13 @@ - state: broken map: [ "enum.DeliveryVisualLayers.Breakage" ] visible: false + - state: bomb + map: [ "enum.DeliveryVisualLayers.Bomb" ] + visible: false + - state: bomb_unshaded + map: [ "enum.DeliveryVisualLayers.BombPrimed" ] + shader: unshaded + visible: false - type: Item storedRotation: 90 - type: Delivery @@ -139,6 +162,8 @@ prob: 0.25 - id: DeliveryModifierFragile prob: 0.25 + - id: DeliveryModifierBomb + prob: 0.02 # Should happen maybe once or twice per game. - type: entity id: DeliveryModifierPriority @@ -177,3 +202,21 @@ collection: DeliveryOpenSounds - !type:DoActsBehavior acts: [ "Breakage" ] + +- type: entity + id: DeliveryModifierBomb + description: Components to add when a delivery is rolled as a bomb. + categories: [ HideSpawnMenu ] + components: + - type: DeliveryBomb + - type: AmbientSound + enabled: false + range: 8 + sound: + path: /Audio/Effects/lightburn.ogg + - type: Explosive + explosionType: MicroBomb + totalIntensity: 120 + intensitySlope: 4 + maxIntensity: 30 + canCreateVacuum: false diff --git a/Resources/Textures/Objects/Specific/Cargo/mail.rsi/bomb-unshaded.png b/Resources/Textures/Objects/Specific/Cargo/mail.rsi/bomb_unshaded.png similarity index 100% rename from Resources/Textures/Objects/Specific/Cargo/mail.rsi/bomb-unshaded.png rename to Resources/Textures/Objects/Specific/Cargo/mail.rsi/bomb_unshaded.png diff --git a/Resources/Textures/Objects/Specific/Cargo/mail.rsi/meta.json b/Resources/Textures/Objects/Specific/Cargo/mail.rsi/meta.json index 9aa97992b1..500d1632fc 100644 --- a/Resources/Textures/Objects/Specific/Cargo/mail.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Cargo/mail.rsi/meta.json @@ -43,7 +43,7 @@ "name": "bomb" }, { - "name": "bomb-unshaded", + "name": "bomb_unshaded", "delays": [ [ 0.2, diff --git a/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/bomb-unshaded.png b/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/bomb_unshaded.png similarity index 100% rename from Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/bomb-unshaded.png rename to Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/bomb_unshaded.png diff --git a/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/meta.json b/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/meta.json index a265c4aada..67fafe31b3 100644 --- a/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/meta.json +++ b/Resources/Textures/Objects/Specific/Cargo/mail_large.rsi/meta.json @@ -43,7 +43,7 @@ "name": "bomb" }, { - "name": "bomb-unshaded", + "name": "bomb_unshaded", "delays": [ [ 0.125,