Bomb Deliveries (#37069)
* init * BOMB!!! * review * partial review * review
This commit is contained in:
@@ -42,6 +42,8 @@ public enum DeliveryVisualLayers : byte
|
||||
PriorityTape,
|
||||
Breakage,
|
||||
Trash,
|
||||
Bomb,
|
||||
BombPrimed,
|
||||
}
|
||||
|
||||
public enum DeliverySpawnerVisualLayers : byte
|
||||
|
||||
65
Content.Shared/Delivery/DeliveryBombComponent.cs
Normal file
65
Content.Shared/Delivery/DeliveryBombComponent.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Delivery;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
[Access(typeof(DeliveryModifierSystem))]
|
||||
public sealed partial class DeliveryBombComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// How often will this bomb retry to explode.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan ExplosionRetryDelay = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// The time at which the next retry will happen
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan NextExplosionRetry;
|
||||
|
||||
/// <summary>
|
||||
/// The chance this bomb explodes each time it attempts to do so.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public float ExplosionChance = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// How much should the chance of explosion increase each failed retry?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ExplosionChanceRetryIncrease = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// Should this bomb get primed when the delivery is unlocked?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool PrimeOnUnlock = true;
|
||||
|
||||
/// <summary>
|
||||
/// Should this bomb get primed when the delivery is broken?
|
||||
/// Requires to be fragile as well.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool PrimeOnBreakage = true;
|
||||
|
||||
/// <summary>
|
||||
/// Should this bomb get primed when the delivery expires?
|
||||
/// Requires to be priority as well.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool PrimeOnExpire = true;
|
||||
|
||||
/// <summary>
|
||||
/// Multiplier to choose when a crazy person actually opens it.
|
||||
/// Multiplicative, not additive.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float SpesoMultiplier = 1.5f;
|
||||
}
|
||||
@@ -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<DeliveryFragileComponent, BreakageEventArgs>(OnFragileBreakage);
|
||||
SubscribeLocalEvent<DeliveryFragileComponent, ExaminedEvent>(OnFragileExamine);
|
||||
SubscribeLocalEvent<DeliveryFragileComponent, GetDeliveryMultiplierEvent>(OnGetFragileMultiplier);
|
||||
|
||||
SubscribeLocalEvent<DeliveryBombComponent, ComponentStartup>(OnExplosiveStartup);
|
||||
SubscribeLocalEvent<PrimedDeliveryBombComponent, MapInitEvent>(OnPrimedExplosiveMapInit);
|
||||
SubscribeLocalEvent<DeliveryBombComponent, ExaminedEvent>(OnExplosiveExamine);
|
||||
SubscribeLocalEvent<DeliveryBombComponent, GetDeliveryMultiplierEvent>(OnGetExplosiveMultiplier);
|
||||
SubscribeLocalEvent<DeliveryBombComponent, DeliveryUnlockedEvent>(OnExplosiveUnlock);
|
||||
SubscribeLocalEvent<DeliveryBombComponent, DeliveryPriorityExpiredEvent>(OnExplosiveExpire);
|
||||
SubscribeLocalEvent<DeliveryBombComponent, BreakageEventArgs>(OnExplosiveBreak);
|
||||
}
|
||||
|
||||
#region Random
|
||||
@@ -119,12 +134,80 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Explosive
|
||||
private void OnExplosiveStartup(Entity<DeliveryBombComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
_delivery.UpdateBombVisuals(ent);
|
||||
}
|
||||
|
||||
private void OnPrimedExplosiveMapInit(Entity<PrimedDeliveryBombComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<DeliveryBombComponent>(ent, out var bomb))
|
||||
return;
|
||||
|
||||
bomb.NextExplosionRetry = _timing.CurTime;
|
||||
}
|
||||
|
||||
private void OnExplosiveExamine(Entity<DeliveryBombComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
var trueName = _nameModifier.GetBaseName(ent.Owner);
|
||||
|
||||
var isPrimed = HasComp<PrimedDeliveryBombComponent>(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<DeliveryBombComponent> ent, ref GetDeliveryMultiplierEvent args)
|
||||
{
|
||||
// Big danger for big rewards
|
||||
args.MultiplicativeMultiplier += ent.Comp.SpesoMultiplier;
|
||||
}
|
||||
|
||||
private void OnExplosiveUnlock(Entity<DeliveryBombComponent> ent, ref DeliveryUnlockedEvent args)
|
||||
{
|
||||
if (!ent.Comp.PrimeOnUnlock)
|
||||
return;
|
||||
|
||||
PrimeBombDelivery(ent);
|
||||
}
|
||||
|
||||
private void OnExplosiveExpire(Entity<DeliveryBombComponent> ent, ref DeliveryPriorityExpiredEvent args)
|
||||
{
|
||||
if (!ent.Comp.PrimeOnExpire)
|
||||
return;
|
||||
|
||||
PrimeBombDelivery(ent);
|
||||
}
|
||||
|
||||
private void OnExplosiveBreak(Entity<DeliveryBombComponent> ent, ref BreakageEventArgs args)
|
||||
{
|
||||
if (!ent.Comp.PrimeOnBreakage)
|
||||
return;
|
||||
|
||||
PrimeBombDelivery(ent);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public void PrimeBombDelivery(Entity<DeliveryBombComponent> ent)
|
||||
{
|
||||
EnsureComp<PrimedDeliveryBombComponent>(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<PrimedDeliveryBombComponent, DeliveryBombComponent>();
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
11
Content.Shared/Delivery/PrimedDeliveryBombComponent.cs
Normal file
11
Content.Shared/Delivery/PrimedDeliveryBombComponent.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Delivery;
|
||||
|
||||
/// <summary>
|
||||
/// Component given to deliveries.
|
||||
/// Indicates this bomb delivery is primed.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(DeliveryModifierSystem))]
|
||||
public sealed partial class PrimedDeliveryBombComponent : Component;
|
||||
@@ -259,6 +259,13 @@ public abstract class SharedDeliverySystem : EntitySystem
|
||||
_appearance.SetData(ent, DeliveryVisuals.IsFragile, isFragile);
|
||||
}
|
||||
|
||||
public void UpdateBombVisuals(Entity<DeliveryBombComponent> ent)
|
||||
{
|
||||
var isPrimed = HasComp<PrimedDeliveryBombComponent>(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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
@@ -43,7 +43,7 @@
|
||||
"name": "bomb"
|
||||
},
|
||||
{
|
||||
"name": "bomb-unshaded",
|
||||
"name": "bomb_unshaded",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
|
||||
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
@@ -43,7 +43,7 @@
|
||||
"name": "bomb"
|
||||
},
|
||||
{
|
||||
"name": "bomb-unshaded",
|
||||
"name": "bomb_unshaded",
|
||||
"delays": [
|
||||
[
|
||||
0.125,
|
||||
|
||||
Reference in New Issue
Block a user