explosion minor rework + fix (#21718)
This commit is contained in:
@@ -1,16 +1,11 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
|
||||||
using Content.Server.Explosion.Components;
|
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
|
||||||
using Content.Shared.Explosion;
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Mind.Components;
|
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Content.Shared.Projectiles;
|
using Content.Shared.Projectiles;
|
||||||
using Robust.Shared.Spawners;
|
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
@@ -55,6 +50,13 @@ public sealed partial class ExplosionSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int _previousTileIteration;
|
private int _previousTileIteration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This list is used when raising <see cref="BeforeExplodeEvent"/> to avoid allocating a new list per event.
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<EntityUid> _containedEntities = new();
|
||||||
|
|
||||||
|
private readonly List<(EntityUid, DamageSpecifier)> _toDamage = new();
|
||||||
|
|
||||||
private List<EntityUid> _anchored = new();
|
private List<EntityUid> _anchored = new();
|
||||||
|
|
||||||
private void OnMapChanged(MapChangedEvent ev)
|
private void OnMapChanged(MapChangedEvent ev)
|
||||||
@@ -84,8 +86,6 @@ public sealed partial class ExplosionSystem
|
|||||||
Stopwatch.Restart();
|
Stopwatch.Restart();
|
||||||
var x = Stopwatch.Elapsed.TotalMilliseconds;
|
var x = Stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
|
||||||
var availableTime = MaxProcessingTime;
|
|
||||||
|
|
||||||
var tilesRemaining = TilesPerTick;
|
var tilesRemaining = TilesPerTick;
|
||||||
while (tilesRemaining > 0 && MaxProcessingTime > Stopwatch.Elapsed.TotalMilliseconds)
|
while (tilesRemaining > 0 && MaxProcessingTime > Stopwatch.Elapsed.TotalMilliseconds)
|
||||||
{
|
{
|
||||||
@@ -369,64 +369,73 @@ public sealed partial class ExplosionSystem
|
|||||||
return SpaceQueryCallback(ref state, in uid);
|
return SpaceQueryCallback(ref state, in uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DamageSpecifier GetDamage(EntityUid uid,
|
||||||
|
string id, DamageSpecifier damage)
|
||||||
|
{
|
||||||
|
// TODO Explosion Performance
|
||||||
|
// Cache this? I.e., instead of raising an event, check for a component?
|
||||||
|
var resistanceEv = new GetExplosionResistanceEvent(id);
|
||||||
|
RaiseLocalEvent(uid, ref resistanceEv);
|
||||||
|
resistanceEv.DamageCoefficient = Math.Max(0, resistanceEv.DamageCoefficient);
|
||||||
|
|
||||||
|
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||||
|
if (resistanceEv.DamageCoefficient != 1)
|
||||||
|
damage *= resistanceEv.DamageCoefficient;
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetEntitiesToDamage(EntityUid uid, DamageSpecifier originalDamage, string prototype)
|
||||||
|
{
|
||||||
|
_toDamage.Clear();
|
||||||
|
_toDamage.Add((uid, GetDamage(uid, prototype, originalDamage)));
|
||||||
|
|
||||||
|
for (var i = 0; i < _toDamage.Count; i++)
|
||||||
|
{
|
||||||
|
var (ent, damage) = _toDamage[i];
|
||||||
|
_containedEntities.Clear();
|
||||||
|
var ev = new BeforeExplodeEvent(damage, prototype, _containedEntities);
|
||||||
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
|
if (_containedEntities.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||||
|
if (ev.DamageCoefficient != 1)
|
||||||
|
damage *= ev.DamageCoefficient;
|
||||||
|
|
||||||
|
_toDamage.EnsureCapacity(_toDamage.Count + _containedEntities.Count);
|
||||||
|
foreach (var contained in _containedEntities)
|
||||||
|
{
|
||||||
|
var newDamage = GetDamage(contained, prototype, damage);
|
||||||
|
_toDamage.Add((contained, newDamage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function actually applies the explosion affects to an entity.
|
/// This function actually applies the explosion affects to an entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ProcessEntity(
|
private void ProcessEntity(
|
||||||
EntityUid uid,
|
EntityUid uid,
|
||||||
MapCoordinates epicenter,
|
MapCoordinates epicenter,
|
||||||
DamageSpecifier? damage,
|
DamageSpecifier? originalDamage,
|
||||||
float throwForce,
|
float throwForce,
|
||||||
string id,
|
string id,
|
||||||
TransformComponent? xform)
|
TransformComponent? xform)
|
||||||
{
|
{
|
||||||
// damage
|
if (originalDamage != null)
|
||||||
if (damage != null && _damageQuery.TryGetComponent(uid, out var damageable))
|
|
||||||
{
|
{
|
||||||
// TODO Explosion Performance
|
GetEntitiesToDamage(uid, originalDamage, id);
|
||||||
// Cache this? I.e., instead of raising an event, check for a component?
|
foreach (var (entity, damage) in _toDamage)
|
||||||
var ev = new GetExplosionResistanceEvent(id);
|
|
||||||
RaiseLocalEvent(uid, ref ev);
|
|
||||||
|
|
||||||
ev.DamageCoefficient = Math.Max(0, ev.DamageCoefficient);
|
|
||||||
|
|
||||||
// TODO explosion entity
|
|
||||||
// Move explosion data into the existing explosion visuals entity
|
|
||||||
// Give each explosion a unique name, include in admin logs.
|
|
||||||
|
|
||||||
// TODO Explosion Performance
|
|
||||||
// This creates a new dictionary. Maybe we should just re-use a private local damage specifier and update it.
|
|
||||||
// Though most entities shouldn't have explosion resistance, so maybe its fine.
|
|
||||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
|
||||||
if (ev.DamageCoefficient != 1)
|
|
||||||
damage *= ev.DamageCoefficient;
|
|
||||||
|
|
||||||
// Log damage to players. Damage is logged before dealing damage so that the position can be logged before
|
|
||||||
// the entity gets deleted.
|
|
||||||
if (_mindQuery.HasComponent(uid))
|
|
||||||
{
|
{
|
||||||
_adminLogger.Add(LogType.Explosion, LogImpact.Medium,
|
// TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin.
|
||||||
$"Explosion caused [{damage.Total}] damage to {ToPrettyString(uid):target} at {xform?.Coordinates}");
|
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: true);
|
||||||
}
|
|
||||||
|
|
||||||
_damageableSystem.TryChangeDamage(uid, damage, ignoreResistances: true, damageable: damageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's a container, try to damage all its contents
|
|
||||||
if (_containersQuery.TryGetComponent(uid, out var containers))
|
|
||||||
{
|
|
||||||
foreach (var container in containers.Containers.Values)
|
|
||||||
{
|
|
||||||
foreach (var ent in container.ContainedEntities)
|
|
||||||
{
|
|
||||||
// setting throw force to 0 to prevent offset items inside containers
|
|
||||||
ProcessEntity(ent, epicenter, damage, 0f, id, _transformQuery.GetComponent(uid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw
|
// throw
|
||||||
if (xform != null // null implies anchored
|
if (xform != null // null implies anchored or in a container
|
||||||
&& !xform.Anchored
|
&& !xform.Anchored
|
||||||
&& throwForce > 0
|
&& throwForce > 0
|
||||||
&& !EntityManager.IsQueuedForDeletion(uid)
|
&& !EntityManager.IsQueuedForDeletion(uid)
|
||||||
@@ -442,10 +451,6 @@ public sealed partial class ExplosionSystem
|
|||||||
_projectileQuery,
|
_projectileQuery,
|
||||||
throwForce);
|
throwForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO EXPLOSION puddle / flammable ignite?
|
|
||||||
|
|
||||||
// TODO EXPLOSION deaf/ear damage? other explosion effects?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -845,4 +850,3 @@ sealed class Explosion
|
|||||||
_tileUpdateDict.Clear();
|
_tileUpdateDict.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ using Robust.Server.GameStates;
|
|||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Containers;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
@@ -53,11 +52,9 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||||
|
|
||||||
private EntityQuery<TransformComponent> _transformQuery;
|
private EntityQuery<TransformComponent> _transformQuery;
|
||||||
private EntityQuery<ContainerManagerComponent> _containersQuery;
|
|
||||||
private EntityQuery<DamageableComponent> _damageQuery;
|
private EntityQuery<DamageableComponent> _damageQuery;
|
||||||
private EntityQuery<PhysicsComponent> _physicsQuery;
|
private EntityQuery<PhysicsComponent> _physicsQuery;
|
||||||
private EntityQuery<ProjectileComponent> _projectileQuery;
|
private EntityQuery<ProjectileComponent> _projectileQuery;
|
||||||
private EntityQuery<MindComponent> _mindQuery;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Tile-size" for space when there are no nearby grids to use as a reference.
|
/// "Tile-size" for space when there are no nearby grids to use as a reference.
|
||||||
@@ -107,11 +104,9 @@ public sealed partial class ExplosionSystem : EntitySystem
|
|||||||
InitVisuals();
|
InitVisuals();
|
||||||
|
|
||||||
_transformQuery = GetEntityQuery<TransformComponent>();
|
_transformQuery = GetEntityQuery<TransformComponent>();
|
||||||
_containersQuery = GetEntityQuery<ContainerManagerComponent>();
|
|
||||||
_damageQuery = GetEntityQuery<DamageableComponent>();
|
_damageQuery = GetEntityQuery<DamageableComponent>();
|
||||||
_physicsQuery = GetEntityQuery<PhysicsComponent>();
|
_physicsQuery = GetEntityQuery<PhysicsComponent>();
|
||||||
_projectileQuery = GetEntityQuery<ProjectileComponent>();
|
_projectileQuery = GetEntityQuery<ProjectileComponent>();
|
||||||
_mindQuery = GetEntityQuery<MindComponent>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnReset(RoundRestartCleanupEvent ev)
|
private void OnReset(RoundRestartCleanupEvent ev)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Server.Stunnable;
|
|||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Body.Part;
|
using Content.Shared.Body.Part;
|
||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.Hands;
|
using Content.Shared.Hands;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
@@ -54,6 +55,8 @@ namespace Content.Server.Hands.Systems
|
|||||||
|
|
||||||
SubscribeLocalEvent<HandsComponent, ComponentGetState>(GetComponentState);
|
SubscribeLocalEvent<HandsComponent, ComponentGetState>(GetComponentState);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<HandsComponent, BeforeExplodeEvent>(OnExploded);
|
||||||
|
|
||||||
CommandBinds.Builder
|
CommandBinds.Builder
|
||||||
.Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem))
|
.Bind(ContentKeyFunctions.ThrowItemInHand, new PointerInputCmdHandler(HandleThrowItem))
|
||||||
.Bind(ContentKeyFunctions.SmartEquipBackpack, InputCmdHandler.FromDelegate(HandleSmartEquipBackpack))
|
.Bind(ContentKeyFunctions.SmartEquipBackpack, InputCmdHandler.FromDelegate(HandleSmartEquipBackpack))
|
||||||
@@ -73,6 +76,15 @@ namespace Content.Server.Hands.Systems
|
|||||||
args.State = new HandsComponentState(hands);
|
args.State = new HandsComponentState(hands);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnExploded(Entity<HandsComponent> ent, ref BeforeExplodeEvent args)
|
||||||
|
{
|
||||||
|
foreach (var hand in ent.Comp.Hands.Values)
|
||||||
|
{
|
||||||
|
if (hand.HeldEntity is {} uid)
|
||||||
|
args.Contents.Add(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnDisarmed(EntityUid uid, HandsComponent component, DisarmedEvent args)
|
private void OnDisarmed(EntityUid uid, HandsComponent component, DisarmedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Storage.EntitySystems;
|
using Content.Server.Storage.EntitySystems;
|
||||||
using Content.Shared.Clothing.Components;
|
using Content.Shared.Clothing.Components;
|
||||||
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
@@ -15,11 +16,26 @@ namespace Content.Server.Inventory
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<InventoryComponent, BeforeExplodeEvent>(OnExploded);
|
||||||
|
|
||||||
SubscribeLocalEvent<ClothingComponent, UseInHandEvent>(OnUseInHand);
|
SubscribeLocalEvent<ClothingComponent, UseInHandEvent>(OnUseInHand);
|
||||||
|
|
||||||
SubscribeNetworkEvent<OpenSlotStorageNetworkMessage>(OnOpenSlotStorage);
|
SubscribeNetworkEvent<OpenSlotStorageNetworkMessage>(OnOpenSlotStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnExploded(Entity<InventoryComponent> ent, ref BeforeExplodeEvent args)
|
||||||
|
{
|
||||||
|
if (!TryGetContainerSlotEnumerator(ent, out var slots, ent.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// explode each item in their inventory too
|
||||||
|
while (slots.MoveNext(out var slot))
|
||||||
|
{
|
||||||
|
if (slot.ContainedEntity != null)
|
||||||
|
args.Contents.Add(slot.ContainedEntity.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnUseInHand(EntityUid uid, ClothingComponent component, UseInHandEvent args)
|
private void OnUseInHand(EntityUid uid, ClothingComponent component, UseInHandEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled || !component.QuickEquip)
|
if (args.Handled || !component.QuickEquip)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Content.Server.Construction;
|
|||||||
using Content.Server.Construction.Components;
|
using Content.Server.Construction.Components;
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Shared.Destructible;
|
using Content.Shared.Destructible;
|
||||||
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.Foldable;
|
using Content.Shared.Foldable;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
@@ -46,6 +47,7 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<EntityStorageComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<EntityStorageComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<EntityStorageComponent, WeldableAttemptEvent>(OnWeldableAttempt);
|
SubscribeLocalEvent<EntityStorageComponent, WeldableAttemptEvent>(OnWeldableAttempt);
|
||||||
|
SubscribeLocalEvent<EntityStorageComponent, BeforeExplodeEvent>(OnExploded);
|
||||||
|
|
||||||
SubscribeLocalEvent<InsideEntityStorageComponent, InhaleLocationEvent>(OnInsideInhale);
|
SubscribeLocalEvent<InsideEntityStorageComponent, InhaleLocationEvent>(OnInsideInhale);
|
||||||
SubscribeLocalEvent<InsideEntityStorageComponent, ExhaleLocationEvent>(OnInsideExhale);
|
SubscribeLocalEvent<InsideEntityStorageComponent, ExhaleLocationEvent>(OnInsideExhale);
|
||||||
@@ -98,6 +100,15 @@ public sealed class EntityStorageSystem : SharedEntityStorageSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnExploded(Entity<EntityStorageComponent> ent, ref BeforeExplodeEvent args)
|
||||||
|
{
|
||||||
|
if (ent.Comp.ExplosionDamageCoefficient <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Contents.AddRange(ent.Comp.Contents.ContainedEntities);
|
||||||
|
args.DamageCoefficient *= ent.Comp.ExplosionDamageCoefficient;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void TakeGas(EntityUid uid, SharedEntityStorageComponent component)
|
protected override void TakeGas(EntityUid uid, SharedEntityStorageComponent component)
|
||||||
{
|
{
|
||||||
if (!component.Airtight)
|
if (!component.Airtight)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Administration.Managers;
|
using Content.Server.Administration.Managers;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Explosion;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Hands;
|
using Content.Shared.Hands;
|
||||||
using Content.Shared.Lock;
|
using Content.Shared.Lock;
|
||||||
@@ -27,6 +28,7 @@ public sealed partial class StorageSystem : SharedStorageSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<ActivationVerb>>(AddUiVerb);
|
SubscribeLocalEvent<StorageComponent, GetVerbsEvent<ActivationVerb>>(AddUiVerb);
|
||||||
SubscribeLocalEvent<StorageComponent, BoundUIClosedEvent>(OnBoundUIClosed);
|
SubscribeLocalEvent<StorageComponent, BoundUIClosedEvent>(OnBoundUIClosed);
|
||||||
|
SubscribeLocalEvent<StorageComponent, BeforeExplodeEvent>(OnExploded);
|
||||||
|
|
||||||
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
||||||
}
|
}
|
||||||
@@ -97,6 +99,11 @@ public sealed partial class StorageSystem : SharedStorageSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnExploded(Entity<StorageComponent> ent, ref BeforeExplodeEvent args)
|
||||||
|
{
|
||||||
|
args.Contents.AddRange(ent.Comp.Container.ContainedEntities);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the storage UI for an entity
|
/// Opens the storage UI for an entity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.Administration.Logs;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
|
using Content.Shared.Mind.Components;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Content.Shared.Radiation.Events;
|
using Content.Shared.Radiation.Events;
|
||||||
@@ -16,12 +18,14 @@ namespace Content.Shared.Damage
|
|||||||
public sealed class DamageableSystem : EntitySystem
|
public sealed class DamageableSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
[Dependency] private readonly INetManager _netMan = default!;
|
[Dependency] private readonly INetManager _netMan = default!;
|
||||||
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
|
[Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
|
||||||
|
|
||||||
private EntityQuery<AppearanceComponent> _appearanceQuery;
|
private EntityQuery<AppearanceComponent> _appearanceQuery;
|
||||||
private EntityQuery<DamageableComponent> _damageableQuery;
|
private EntityQuery<DamageableComponent> _damageableQuery;
|
||||||
|
private EntityQuery<MindContainerComponent> _mindContainerQuery;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -33,6 +37,7 @@ namespace Content.Shared.Damage
|
|||||||
|
|
||||||
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
_appearanceQuery = GetEntityQuery<AppearanceComponent>();
|
||||||
_damageableQuery = GetEntityQuery<DamageableComponent>();
|
_damageableQuery = GetEntityQuery<DamageableComponent>();
|
||||||
|
_mindContainerQuery = GetEntityQuery<MindContainerComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Robust.Shared.Map;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Explosion;
|
namespace Content.Shared.Explosion;
|
||||||
|
|
||||||
@@ -20,3 +19,34 @@ public record struct GetExplosionResistanceEvent(string ExplosionPrototype) : II
|
|||||||
|
|
||||||
SlotFlags IInventoryRelayEvent.TargetSlots => ~SlotFlags.POCKET;
|
SlotFlags IInventoryRelayEvent.TargetSlots => ~SlotFlags.POCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is raised directed at an entity that is about to receive damage from an explosion. It can be used to
|
||||||
|
/// recursively add contained/child entities that should also receive damage. E.g., entities in a player's inventory
|
||||||
|
/// or backpack. This event will be raised recursively so a matchbox in a backpack in a player's inventory
|
||||||
|
/// will also receive this event.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct BeforeExplodeEvent(DamageSpecifier Damage, string Id, List<EntityUid> Contents)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The damage that will be received by this entity. Note that the entity's explosion resistance has already been
|
||||||
|
/// used to modify this damage.
|
||||||
|
/// </summary>
|
||||||
|
public readonly DamageSpecifier Damage = Damage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ID of the explosion prototype.
|
||||||
|
/// </summary>
|
||||||
|
public readonly string Id = Id;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Damage multiplier for modifying the damage that will get dealt to contained entities.
|
||||||
|
/// </summary>
|
||||||
|
public float DamageCoefficient = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contained/child entities that should receive recursive explosion damage.
|
||||||
|
/// </summary>
|
||||||
|
public readonly List<EntityUid> Contents = Contents;
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,6 +124,12 @@ public abstract partial class SharedEntityStorageComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public Container Contents = default!;
|
public Container Contents = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplier for explosion damage that gets applied to contained entities.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float ExplosionDamageCoefficient = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# TODO BODY: Part damage
|
# TODO BODY: Part damage
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PartSlime
|
id: PartSlime
|
||||||
parent: [BaseItem, PartBase]
|
parent: [BaseItem, BasePart]
|
||||||
name: "slime body part"
|
name: "slime body part"
|
||||||
abstract: true
|
abstract: true
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user