+using System.Linq;
using System.Numerics;
using Content.Server.Atmos.EntitySystems;
+using Content.Server.Explosion.Components;
using Content.Shared.CCVar;
using Content.Shared.Damage;
+using Content.Shared.Database;
using Content.Shared.Explosion;
using Content.Shared.Explosion.Components;
using Content.Shared.Explosion.EntitySystems;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Dynamics;
+using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
MapCoordinates epicenter,
HashSet<EntityUid> processed,
string id,
- float? fireStacks)
+ float? fireStacks,
+ EntityUid? cause)
{
var size = grid.Comp.TileSize;
var gridBox = new Box2(tile * size, (tile + 1) * size);
// process those entities
foreach (var (uid, xform) in list)
{
- ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks);
+ ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, cause);
}
// process anchored entities
foreach (var entity in _anchored)
{
processed.Add(entity);
- ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks);
+ ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks, cause);
}
// Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for
{
// Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but
// they should handle their own damage pass-through, with their own damage reduction calculation.
- ProcessEntity(uid, epicenter, null, throwForce, id, xform, null);
+ ProcessEntity(uid, epicenter, null, throwForce, id, xform, null, cause);
}
return !tileBlocked;
MapCoordinates epicenter,
HashSet<EntityUid> processed,
string id,
- float? fireStacks)
+ float? fireStacks,
+ EntityUid? cause)
{
var gridBox = Box2.FromDimensions(tile * DefaultTileSize, new Vector2(DefaultTileSize, DefaultTileSize));
var worldBox = spaceMatrix.TransformBox(gridBox);
foreach (var (uid, xform) in state.Item1)
{
processed.Add(uid);
- ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks);
+ ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, cause);
}
if (throwForce <= 0)
foreach (var (uid, xform) in list)
{
- ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks);
+ ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks, cause);
}
}
float throwForce,
string id,
TransformComponent? xform,
- float? fireStacksOnIgnite)
+ float? fireStacksOnIgnite,
+ EntityUid? cause)
{
if (originalDamage != null)
{
GetEntitiesToDamage(uid, originalDamage, id);
foreach (var (entity, damage) in _toDamage)
{
+ if (damage.GetTotal() > 0 && TryComp<ActorComponent>(entity, out var actorComponent))
+ {
+ // Log damage to player entities only, cause this will create a massive amount of log spam otherwise.
+ if (cause != null)
+ {
+ _adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion of {ToPrettyString(cause):actor} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
+ }
+ else
+ {
+ _adminLogger.Add(LogType.ExplosionHit, LogImpact.Medium, $"Explosion at {epicenter:epicenter} dealt {damage.GetTotal()} damage to {ToPrettyString(entity):subject}");
+ }
+
+ }
+
// TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin.
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: true);
public readonly EntityUid VisualEnt;
+ public readonly EntityUid? Cause;
+
/// <summary>
/// Initialize a new instance for processing
/// </summary>
bool canCreateVacuum,
IEntityManager entMan,
IMapManager mapMan,
- EntityUid visualEnt)
+ EntityUid visualEnt,
+ EntityUid? cause)
{
VisualEnt = visualEnt;
+ Cause = cause;
_system = system;
ExplosionType = explosionType;
_tileSetIntensity = tileSetIntensity;
Epicenter,
ProcessedEntities,
ExplosionType.ID,
- ExplosionType.FireStacks);
+ ExplosionType.FireStacks,
+ Cause);
// If the floor is not blocked by some dense object, damage the floor tiles.
if (canDamageFloor)
Epicenter,
ProcessedEntities,
ExplosionType.ID,
- ExplosionType.FireStacks);
+ ExplosionType.FireStacks,
+ Cause);
}
if (!MoveNext())
public float TotalIntensity, Slope, MaxTileIntensity, TileBreakScale;
public int MaxTileBreak;
public bool CanCreateVacuum;
+ public EntityUid? Cause; // The entity that exploded, for logging purposes.
}
var posFound = _transformSystem.TryGetMapOrGridCoordinates(uid, out var gridPos, pos);
- QueueExplosion(mapPos, typeId, totalIntensity, slope, maxTileIntensity, tileBreakScale, maxTileBreak, canCreateVacuum, addLog: false);
+ QueueExplosion(mapPos, typeId, totalIntensity, slope, maxTileIntensity, uid, tileBreakScale, maxTileBreak, canCreateVacuum, addLog: false);
if (!addLog)
return;
float totalIntensity,
float slope,
float maxTileIntensity,
+ EntityUid? cause,
float tileBreakScale = 1f,
int maxTileBreak = int.MaxValue,
bool canCreateVacuum = true,
MaxTileIntensity = maxTileIntensity,
TileBreakScale = tileBreakScale,
MaxTileBreak = maxTileBreak,
- CanCreateVacuum = canCreateVacuum
+ CanCreateVacuum = canCreateVacuum,
+ Cause = cause
};
_explosionQueue.Enqueue(boom);
_queuedExplosions.Add(boom);
queued.CanCreateVacuum,
EntityManager,
_mapManager,
- visualEnt);
+ visualEnt,
+ queued.Cause);
}
private void CameraShake(float range, MapCoordinates epicenter, float totalIntensity)