Mini bomb changes (#7454)

This commit is contained in:
Leon Friedrich
2022-04-09 09:07:02 +12:00
committed by GitHub
parent 8d885d7425
commit 53f5a283ca
4 changed files with 63 additions and 29 deletions

View File

@@ -60,13 +60,20 @@ public sealed class ExplosiveComponent : Component
public float TileBreakScale = 1f; public float TileBreakScale = 1f;
/// <summary> /// <summary>
/// Maximum number of times that an explosive can break a tile. Currently, for normal space ships breaking a /// Maximum number of times that an explosive can break a tile. Currently, for normal space stations breaking a
/// tile twice will result in a vacuum. /// tile twice will generally result in a vacuum.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("maxTileBreak")] [DataField("maxTileBreak")]
public int MaxTileBreak = int.MaxValue; public int MaxTileBreak = int.MaxValue;
/// <summary>
/// Whether this explosive should be able to create a vacuum by breaking tiles.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("canCreateVacuum")]
public bool CanCreateVacuum = true;
/// <summary> /// <summary>
/// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion. /// Avoid somehow double-triggering this explosion (e.g. by damaging this entity from its own explosion.
/// </summary> /// </summary>

View File

@@ -182,8 +182,7 @@ public sealed partial class ExplosionSystem : EntitySystem
string id, string id,
EntityQuery<TransformComponent> xformQuery, EntityQuery<TransformComponent> xformQuery,
EntityQuery<DamageableComponent> damageQuery, EntityQuery<DamageableComponent> damageQuery,
EntityQuery<PhysicsComponent> physicsQuery, EntityQuery<PhysicsComponent> physicsQuery)
EntityQuery<MetaDataComponent> metaQuery)
{ {
var gridBox = new Box2(tile * grid.TileSize, (tile + 1) * grid.TileSize); var gridBox = new Box2(tile * grid.TileSize, (tile + 1) * grid.TileSize);
@@ -216,11 +215,23 @@ public sealed partial class ExplosionSystem : EntitySystem
// process anchored entities // process anchored entities
var tileBlocked = false; var tileBlocked = false;
foreach (var entity in grid.GetAnchoredEntities(tile).ToList()) var anchoredList = grid.GetAnchoredEntities(tile).ToList();
foreach (var entity in anchoredList)
{ {
processed.Add(entity); processed.Add(entity);
ProcessEntity(entity, epicenter, damage, throwForce, id, damageQuery, physicsQuery); ProcessEntity(entity, epicenter, damage, throwForce, id, damageQuery, physicsQuery);
tileBlocked |= IsBlockingTurf(entity, physicsQuery); }
// Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for
// the purposes of destroying floors. Again, ideally the process of damaging an entity should somehow return
// information about the entities that were spawned as a result, but without that information we just have to
// re-check for new anchored entities. Compared to entity spawning & deleting, this should still be relatively minor.
if (anchoredList.Count > 0)
{
foreach (var entity in grid.GetAnchoredEntities(tile))
{
tileBlocked |= IsBlockingTurf(entity, physicsQuery);
}
} }
// Next, we get the intersecting entities AGAIN, but purely for throwing. This way, glass shards spawned from // Next, we get the intersecting entities AGAIN, but purely for throwing. This way, glass shards spawned from
@@ -261,8 +272,7 @@ public sealed partial class ExplosionSystem : EntitySystem
string id, string id,
EntityQuery<TransformComponent> xformQuery, EntityQuery<TransformComponent> xformQuery,
EntityQuery<DamageableComponent> damageQuery, EntityQuery<DamageableComponent> damageQuery,
EntityQuery<PhysicsComponent> physicsQuery, EntityQuery<PhysicsComponent> physicsQuery)
EntityQuery<MetaDataComponent> metaQuery)
{ {
var gridBox = new Box2(tile * DefaultTileSize, (DefaultTileSize, DefaultTileSize)); var gridBox = new Box2(tile * DefaultTileSize, (DefaultTileSize, DefaultTileSize));
var worldBox = spaceMatrix.TransformBox(gridBox); var worldBox = spaceMatrix.TransformBox(gridBox);
@@ -370,10 +380,15 @@ public sealed partial class ExplosionSystem : EntitySystem
public void DamageFloorTile(TileRef tileRef, public void DamageFloorTile(TileRef tileRef,
float effectiveIntensity, float effectiveIntensity,
int maxTileBreak, int maxTileBreak,
bool canCreateVacuum,
List<(Vector2i GridIndices, Tile Tile)> damagedTiles, List<(Vector2i GridIndices, Tile Tile)> damagedTiles,
ExplosionPrototype type) ExplosionPrototype type)
{ {
var tileDef = _tileDefinitionManager[tileRef.Tile.TypeId]; if (_tileDefinitionManager[tileRef.Tile.TypeId] is not ContentTileDefinition tileDef)
return;
if (tileDef.IsSpace)
canCreateVacuum = true; // is already a vacuum.
int tileBreakages = 0; int tileBreakages = 0;
while (maxTileBreak > tileBreakages && _robustRandom.Prob(type.TileBreakChance(effectiveIntensity))) while (maxTileBreak > tileBreakages && _robustRandom.Prob(type.TileBreakChance(effectiveIntensity)))
@@ -381,14 +396,17 @@ public sealed partial class ExplosionSystem : EntitySystem
tileBreakages++; tileBreakages++;
effectiveIntensity -= type.TileBreakRerollReduction; effectiveIntensity -= type.TileBreakRerollReduction;
if (tileDef is not ContentTileDefinition contentTileDef)
break;
// does this have a base-turf that we can break it down to? // does this have a base-turf that we can break it down to?
if (contentTileDef.BaseTurfs.Count == 0) if (tileDef.BaseTurfs.Count == 0)
break; break;
tileDef = _tileDefinitionManager[contentTileDef.BaseTurfs[^1]]; if (_tileDefinitionManager[tileDef.BaseTurfs[^1]] is not ContentTileDefinition newDef)
break;
if (newDef.IsSpace && !canCreateVacuum)
break;
tileDef = newDef;
} }
if (tileDef.TileId == tileRef.Tile.TypeId) if (tileDef.TileId == tileRef.Tile.TypeId)
@@ -493,7 +511,6 @@ sealed class Explosion
private readonly EntityQuery<TransformComponent> _xformQuery; private readonly EntityQuery<TransformComponent> _xformQuery;
private readonly EntityQuery<PhysicsComponent> _physicsQuery; private readonly EntityQuery<PhysicsComponent> _physicsQuery;
private readonly EntityQuery<DamageableComponent> _damageQuery; private readonly EntityQuery<DamageableComponent> _damageQuery;
private readonly EntityQuery<MetaDataComponent> _metaQuery;
/// <summary> /// <summary>
/// Total area that the explosion covers. /// Total area that the explosion covers.
@@ -510,6 +527,11 @@ sealed class Explosion
/// </summary> /// </summary>
private readonly int _maxTileBreak; private readonly int _maxTileBreak;
/// <summary>
/// Whether this explosion can turn non-vacuum tiles into vacuum-tiles.
/// </summary>
private readonly bool _canCreateVacuum;
private readonly IEntityManager _entMan; private readonly IEntityManager _entMan;
private readonly ExplosionSystem _system; private readonly ExplosionSystem _system;
@@ -526,6 +548,7 @@ sealed class Explosion
int area, int area,
float tileBreakScale, float tileBreakScale,
int maxTileBreak, int maxTileBreak,
bool canCreateVacuum,
IEntityManager entMan, IEntityManager entMan,
IMapManager mapMan) IMapManager mapMan)
{ {
@@ -537,12 +560,12 @@ sealed class Explosion
_tileBreakScale = tileBreakScale; _tileBreakScale = tileBreakScale;
_maxTileBreak = maxTileBreak; _maxTileBreak = maxTileBreak;
_canCreateVacuum = canCreateVacuum;
_entMan = entMan; _entMan = entMan;
_xformQuery = entMan.GetEntityQuery<TransformComponent>(); _xformQuery = entMan.GetEntityQuery<TransformComponent>();
_physicsQuery = entMan.GetEntityQuery<PhysicsComponent>(); _physicsQuery = entMan.GetEntityQuery<PhysicsComponent>();
_damageQuery = entMan.GetEntityQuery<DamageableComponent>(); _damageQuery = entMan.GetEntityQuery<DamageableComponent>();
_metaQuery = entMan.GetEntityQuery<MetaDataComponent>();
if (spaceData != null) if (spaceData != null)
{ {
@@ -682,12 +705,11 @@ sealed class Explosion
ExplosionType.ID, ExplosionType.ID,
_xformQuery, _xformQuery,
_damageQuery, _damageQuery,
_physicsQuery, _physicsQuery);
_metaQuery);
// If the floor is not blocked by some dense object, damage the floor tiles. // If the floor is not blocked by some dense object, damage the floor tiles.
if (canDamageFloor) if (canDamageFloor)
_system.DamageFloorTile(tileRef, _currentIntensity * _tileBreakScale, _maxTileBreak, tileUpdateList, ExplosionType); _system.DamageFloorTile(tileRef, _currentIntensity * _tileBreakScale, _maxTileBreak, _canCreateVacuum, tileUpdateList, ExplosionType);
} }
else else
{ {
@@ -703,8 +725,7 @@ sealed class Explosion
ExplosionType.ID, ExplosionType.ID,
_xformQuery, _xformQuery,
_damageQuery, _damageQuery,
_physicsQuery, _physicsQuery);
_metaQuery);
} }
if (!MoveNext()) if (!MoveNext())

View File

@@ -122,6 +122,7 @@ public sealed partial class ExplosionSystem : EntitySystem
explosive.MaxIntensity, explosive.MaxIntensity,
explosive.TileBreakScale, explosive.TileBreakScale,
explosive.MaxTileBreak, explosive.MaxTileBreak,
explosive.CanCreateVacuum,
user); user);
if (delete) if (delete)
@@ -190,13 +191,14 @@ public sealed partial class ExplosionSystem : EntitySystem
float maxTileIntensity, float maxTileIntensity,
float tileBreakScale = 1f, float tileBreakScale = 1f,
int maxTileBreak = int.MaxValue, int maxTileBreak = int.MaxValue,
bool canCreateVacuum = true,
EntityUid? user = null, EntityUid? user = null,
bool addLog = false) bool addLog = false)
{ {
var pos = Transform(uid).MapPosition; var pos = Transform(uid).MapPosition;
QueueExplosion(pos, typeId, totalIntensity, slope, maxTileIntensity, tileBreakScale, maxTileBreak, addLog: false); QueueExplosion(pos, typeId, totalIntensity, slope, maxTileIntensity, tileBreakScale, maxTileBreak, canCreateVacuum, addLog: false);
if (!addLog) if (!addLog)
return; return;
@@ -219,6 +221,7 @@ public sealed partial class ExplosionSystem : EntitySystem
float maxTileIntensity, float maxTileIntensity,
float tileBreakScale = 1f, float tileBreakScale = 1f,
int maxTileBreak = int.MaxValue, int maxTileBreak = int.MaxValue,
bool canCreateVacuum = true,
bool addLog = false) bool addLog = false)
{ {
if (totalIntensity <= 0 || slope <= 0) if (totalIntensity <= 0 || slope <= 0)
@@ -234,7 +237,7 @@ public sealed partial class ExplosionSystem : EntitySystem
_logsSystem.Add(LogType.Explosion, LogImpact.High, $"Explosion spawned at {epicenter:coordinates} with intensity {totalIntensity} slope {slope}"); _logsSystem.Add(LogType.Explosion, LogImpact.High, $"Explosion spawned at {epicenter:coordinates} with intensity {totalIntensity} slope {slope}");
_explosionQueue.Enqueue(() => SpawnExplosion(epicenter, type, totalIntensity, _explosionQueue.Enqueue(() => SpawnExplosion(epicenter, type, totalIntensity,
slope, maxTileIntensity, tileBreakScale, maxTileBreak)); slope, maxTileIntensity, tileBreakScale, maxTileBreak, canCreateVacuum));
} }
/// <summary> /// <summary>
@@ -248,7 +251,8 @@ public sealed partial class ExplosionSystem : EntitySystem
float slope, float slope,
float maxTileIntensity, float maxTileIntensity,
float tileBreakScale, float tileBreakScale,
int maxTileBreak) int maxTileBreak,
bool canCreateVacuum)
{ {
if (!_mapManager.MapExists(epicenter.MapId)) if (!_mapManager.MapExists(epicenter.MapId))
return null; return null;
@@ -283,6 +287,7 @@ public sealed partial class ExplosionSystem : EntitySystem
area, area,
tileBreakScale, tileBreakScale,
maxTileBreak, maxTileBreak,
canCreateVacuum,
EntityManager, EntityManager,
_mapManager); _mapManager);
} }

View File

@@ -80,7 +80,7 @@
- type: entity - type: entity
name: Syndicate minibomb name: Syndicate minibomb
description: A syndicate manufactured explosive used to sow destruction and chaos. description: Creates a small but powerful explosion that is strong enough to break through walls.
parent: BaseItem parent: BaseItem
id: SyndieMiniBomb id: SyndieMiniBomb
components: components:
@@ -95,10 +95,11 @@
delay: 5 delay: 5
- type: Explosive - type: Explosive
explosionType: Default explosionType: Default
# About a 3-3.5 tile radius, strong enough to break reinforced walls near centre. # About a 2.5 tile radius. If placed next to walls, will destroy a line of 3-normal walls and turn 3 reinforced walls into girders.
totalIntensity: 800 totalIntensity: 492
intensitySlope: 15 intensitySlope: 20.5
maxTileBreak: 1 # for destroying walls, not spacing the hallway maxIntensity: 41
canCreateVacuum: false # for destroying walls, not spacing the hallway
- type: ExplodeOnTrigger - type: ExplodeOnTrigger
- type: Damageable - type: Damageable
damageContainer: Inorganic damageContainer: Inorganic