Bomb Deliveries (#37069)
* init * BOMB!!! * review * partial review * review
This commit is contained in:
@@ -42,6 +42,8 @@ public enum DeliveryVisualLayers : byte
|
|||||||
PriorityTape,
|
PriorityTape,
|
||||||
Breakage,
|
Breakage,
|
||||||
Trash,
|
Trash,
|
||||||
|
Bomb,
|
||||||
|
BombPrimed,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeliverySpawnerVisualLayers : byte
|
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.Destructible;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Explosion.EntitySystems;
|
||||||
using Content.Shared.NameModifier.EntitySystems;
|
using Content.Shared.NameModifier.EntitySystems;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -14,8 +18,11 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly INetManager _net = default!;
|
||||||
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
|
[Dependency] private readonly NameModifierSystem _nameModifier = default!;
|
||||||
[Dependency] private readonly SharedDeliverySystem _delivery = default!;
|
[Dependency] private readonly SharedDeliverySystem _delivery = default!;
|
||||||
|
[Dependency] private readonly SharedExplosionSystem _explosion = default!;
|
||||||
|
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -33,6 +40,14 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<DeliveryFragileComponent, BreakageEventArgs>(OnFragileBreakage);
|
SubscribeLocalEvent<DeliveryFragileComponent, BreakageEventArgs>(OnFragileBreakage);
|
||||||
SubscribeLocalEvent<DeliveryFragileComponent, ExaminedEvent>(OnFragileExamine);
|
SubscribeLocalEvent<DeliveryFragileComponent, ExaminedEvent>(OnFragileExamine);
|
||||||
SubscribeLocalEvent<DeliveryFragileComponent, GetDeliveryMultiplierEvent>(OnGetFragileMultiplier);
|
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
|
#region Random
|
||||||
@@ -119,12 +134,80 @@ public sealed partial class DeliveryModifierSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
#endregion
|
#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
|
#region Update Loops
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
UpdatePriorty(frameTime);
|
UpdatePriorty(frameTime);
|
||||||
|
UpdateBomb(frameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePriorty(float 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
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public enum DeliveryVisuals : byte
|
|||||||
IsTrash,
|
IsTrash,
|
||||||
IsBroken,
|
IsBroken,
|
||||||
IsFragile,
|
IsFragile,
|
||||||
|
IsBomb,
|
||||||
PriorityState,
|
PriorityState,
|
||||||
JobIcon,
|
JobIcon,
|
||||||
}
|
}
|
||||||
@@ -21,6 +22,14 @@ public enum DeliveryPriorityState : byte
|
|||||||
Inactive,
|
Inactive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum DeliveryBombState : byte
|
||||||
|
{
|
||||||
|
Off,
|
||||||
|
Inactive,
|
||||||
|
Primed,
|
||||||
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum DeliverySpawnerVisuals : byte
|
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);
|
_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)
|
protected void UpdateDeliverySpawnerVisuals(EntityUid uid, int contents)
|
||||||
{
|
{
|
||||||
_appearance.SetData(uid, DeliverySpawnerVisuals.Contents, contents > 0);
|
_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-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-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:
|
enum.DeliveryVisualLayers.Trash:
|
||||||
True: { visible: true }
|
True: { visible: true }
|
||||||
False: { visible: false }
|
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
|
- type: Label
|
||||||
examinable: false
|
examinable: false
|
||||||
- type: FingerprintReader
|
- type: FingerprintReader
|
||||||
@@ -74,6 +83,13 @@
|
|||||||
- state: broken
|
- state: broken
|
||||||
map: [ "enum.DeliveryVisualLayers.Breakage" ]
|
map: [ "enum.DeliveryVisualLayers.Breakage" ]
|
||||||
visible: false
|
visible: false
|
||||||
|
- state: bomb
|
||||||
|
map: [ "enum.DeliveryVisualLayers.Bomb" ]
|
||||||
|
visible: false
|
||||||
|
- state: bomb_unshaded
|
||||||
|
map: [ "enum.DeliveryVisualLayers.BombPrimed" ]
|
||||||
|
shader: unshaded
|
||||||
|
visible: false
|
||||||
- type: MultiHandedItem
|
- type: MultiHandedItem
|
||||||
- type: Item
|
- type: Item
|
||||||
size: Huge
|
size: Huge
|
||||||
@@ -117,6 +133,13 @@
|
|||||||
- state: broken
|
- state: broken
|
||||||
map: [ "enum.DeliveryVisualLayers.Breakage" ]
|
map: [ "enum.DeliveryVisualLayers.Breakage" ]
|
||||||
visible: false
|
visible: false
|
||||||
|
- state: bomb
|
||||||
|
map: [ "enum.DeliveryVisualLayers.Bomb" ]
|
||||||
|
visible: false
|
||||||
|
- state: bomb_unshaded
|
||||||
|
map: [ "enum.DeliveryVisualLayers.BombPrimed" ]
|
||||||
|
shader: unshaded
|
||||||
|
visible: false
|
||||||
- type: Item
|
- type: Item
|
||||||
storedRotation: 90
|
storedRotation: 90
|
||||||
- type: Delivery
|
- type: Delivery
|
||||||
@@ -139,6 +162,8 @@
|
|||||||
prob: 0.25
|
prob: 0.25
|
||||||
- id: DeliveryModifierFragile
|
- id: DeliveryModifierFragile
|
||||||
prob: 0.25
|
prob: 0.25
|
||||||
|
- id: DeliveryModifierBomb
|
||||||
|
prob: 0.02 # Should happen maybe once or twice per game.
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: DeliveryModifierPriority
|
id: DeliveryModifierPriority
|
||||||
@@ -177,3 +202,21 @@
|
|||||||
collection: DeliveryOpenSounds
|
collection: DeliveryOpenSounds
|
||||||
- !type:DoActsBehavior
|
- !type:DoActsBehavior
|
||||||
acts: [ "Breakage" ]
|
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"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bomb-unshaded",
|
"name": "bomb_unshaded",
|
||||||
"delays": [
|
"delays": [
|
||||||
[
|
[
|
||||||
0.2,
|
0.2,
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
@@ -43,7 +43,7 @@
|
|||||||
"name": "bomb"
|
"name": "bomb"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bomb-unshaded",
|
"name": "bomb_unshaded",
|
||||||
"delays": [
|
"delays": [
|
||||||
[
|
[
|
||||||
0.125,
|
0.125,
|
||||||
|
|||||||
Reference in New Issue
Block a user