mirror of
https://github.com/DeltaV-Station/Delta-v.git
synced 2026-09-29 23:57:29 +00:00
Tile Stacking - attempt 2 (#42543)
* WORK IN PROGRESS 1 * ITS ALIVE, ALIVE!!!! * clean up * WIP 1 * fix small oversight * big diff of doom * added CVAR to tile history stack size * component time * filescoped namespaces + remove redundant nametag * fix silly little mistakes * typo * TileStacksTest * bweeeeeeh :P * nuke cvar * :3 * WIP2025 * Fix submodule * It's beginning to look a lot like Christmas * It's the Most Wonderful Time of the Year * tiny fix * fixed extra spacing on yaml * slightly improve tilestacking test * Part 1 out of 2 (part 2 tomorrow) * Part 2 * add a simple tile construction test for tilestacking * guh * address reviews (no documentation yet) * documentation be upon ye * remove extra spaces * prediction fix * dirt * oops :p * attempt to make this suck less * am never doing a PR that touches explosion system ever again * small fix * maybe a bit better now? * more cleanup * one last cleanup for me --------- Co-authored-by: Killerqu00 <killerqueen1777@gmail.com> Co-authored-by: Killerqu00 <47712032+Killerqu00@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
This commit is contained in:
committed by
Coryler
co-authored by
Killerqu00
Killerqu00
ScarKy0
Princess Cheeseballs
parent
dd43910f79
commit
12a7a2de67
@@ -17,6 +17,8 @@ using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using TimedDespawnComponent = Robust.Shared.Spawners.TimedDespawnComponent;
|
||||
|
||||
namespace Content.Server.Explosion.EntitySystems;
|
||||
@@ -506,10 +508,11 @@ public sealed partial class ExplosionSystem
|
||||
int maxTileBreak,
|
||||
bool canCreateVacuum,
|
||||
List<(Vector2i GridIndices, Tile Tile)> damagedTiles,
|
||||
ExplosionPrototype type)
|
||||
ExplosionPrototype type,
|
||||
TileHistoryComponent? history,
|
||||
ref (TileHistoryChunk? Chunk, Vector2i Indices)? chunk)
|
||||
{
|
||||
if (_tileDefinitionManager[tileRef.Tile.TypeId] is not ContentTileDefinition tileDef
|
||||
|| tileDef.Indestructible)
|
||||
if (_tileDefinitionManager[tileRef.Tile.TypeId] is not ContentTileDefinition tileDef || tileDef.Indestructible)
|
||||
return;
|
||||
|
||||
if (!CanCreateVacuum)
|
||||
@@ -517,18 +520,17 @@ public sealed partial class ExplosionSystem
|
||||
else if (tileDef.MapAtmosphere)
|
||||
canCreateVacuum = true; // is already a vacuum.
|
||||
|
||||
// break the tile into its underlying parts
|
||||
int tileBreakages = 0;
|
||||
while (maxTileBreak > tileBreakages && _robustRandom.Prob(type.TileBreakChance(effectiveIntensity)))
|
||||
{
|
||||
tileBreakages++;
|
||||
effectiveIntensity -= type.TileBreakRerollReduction;
|
||||
|
||||
// does this have a base-turf that we can break it down to?
|
||||
if (string.IsNullOrEmpty(tileDef.BaseTurf))
|
||||
if (GetNextTile((tileDef, tileRef.GridIndices), history, ref chunk) is not { } newId)
|
||||
break;
|
||||
|
||||
if (_tileDefinitionManager[tileDef.BaseTurf] is not ContentTileDefinition newDef)
|
||||
break;
|
||||
var newDef = (ContentTileDefinition) _tileDefinitionManager[newId];
|
||||
|
||||
if (newDef.MapAtmosphere && !canCreateVacuum)
|
||||
break;
|
||||
@@ -541,6 +543,44 @@ public sealed partial class ExplosionSystem
|
||||
|
||||
damagedTiles.Add((tileRef.GridIndices, new Tile(tileDef.TileId)));
|
||||
}
|
||||
|
||||
private ProtoId<ContentTileDefinition>? GetNextTile((ContentTileDefinition tileDef, Vector2i gridIndices) tile,
|
||||
TileHistoryComponent? history,
|
||||
ref (TileHistoryChunk? Chunk, Vector2i Indices)? chunk)
|
||||
{
|
||||
if (chunk?.Chunk == null || !chunk.Value.Chunk.History.TryGetValue(tile.gridIndices, out var stack))
|
||||
return tile.tileDef.BaseTurf; // No tile stack means we return BaseTurf if it exists!
|
||||
|
||||
// last entry in the stack
|
||||
if (stack.Count > 1)
|
||||
{
|
||||
var newId = stack[^1];
|
||||
stack.RemoveAt(stack.Count - 1);
|
||||
chunk.Value.Chunk.LastModified = _timing.CurTick;
|
||||
return newId;
|
||||
}
|
||||
|
||||
chunk.Value.Chunk.History.Remove(tile.gridIndices);
|
||||
if (chunk.Value.Chunk.History.Count == 0)
|
||||
{
|
||||
history?.ChunkHistory.Remove(chunk.Value.Indices);
|
||||
chunk = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk.Value.Chunk.LastModified = _timing.CurTick;
|
||||
}
|
||||
|
||||
return stack[0]; // If the stack is somehow empty, this will throw, but we will have at least removed it from dict first!
|
||||
}
|
||||
|
||||
public void DirtyHistory(EntityUid grid)
|
||||
{
|
||||
if (!_tileHistoryQuery.TryComp(grid, out var history))
|
||||
return;
|
||||
|
||||
Dirty(grid, history);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -573,11 +613,14 @@ sealed class Explosion
|
||||
/// <summary>
|
||||
/// The actual grid that this corresponds to. If null, this implies space.
|
||||
/// </summary>
|
||||
public Entity<MapGridComponent>? MapGrid;
|
||||
public Entity<MapGridComponent, TileHistoryComponent?>? MapGrid;
|
||||
}
|
||||
|
||||
private readonly List<ExplosionData> _explosionData = new();
|
||||
|
||||
private Entity<MapGridComponent, TileHistoryComponent?>? _currentGrid;
|
||||
private (TileHistoryChunk? Chunk, Vector2i Indices)? _currentChunk;
|
||||
|
||||
/// <summary>
|
||||
/// The explosion intensity associated with each tile iteration.
|
||||
/// </summary>
|
||||
@@ -625,7 +668,6 @@ sealed class Explosion
|
||||
private DamageSpecifier? _expectedDamage;
|
||||
#endif
|
||||
private Entity<BroadphaseComponent> _currentLookup = default!;
|
||||
private Entity<MapGridComponent>? _currentGrid;
|
||||
private float _currentIntensity;
|
||||
private float _currentThrowForce;
|
||||
private List<Vector2i>.Enumerator _currentEnumerator;
|
||||
@@ -691,7 +733,8 @@ sealed class Explosion
|
||||
EntityUid visualEnt,
|
||||
EntityUid? cause,
|
||||
SharedMapSystem mapSystem,
|
||||
Shared.Damage.Systems.DamageableSystem damageable)
|
||||
DamageableSystem damageable,
|
||||
EntityQuery<TileHistoryComponent> historyQuery)
|
||||
{
|
||||
VisualEnt = visualEnt;
|
||||
Cause = cause;
|
||||
@@ -722,7 +765,7 @@ sealed class Explosion
|
||||
{
|
||||
TileLists = spaceData.TileLists,
|
||||
Lookup = (mapUid, entMan.GetComponent<BroadphaseComponent>(mapUid)),
|
||||
MapGrid = null
|
||||
MapGrid = null,
|
||||
});
|
||||
|
||||
_spaceMatrix = spaceMatrix;
|
||||
@@ -731,11 +774,12 @@ sealed class Explosion
|
||||
|
||||
foreach (var grid in gridData)
|
||||
{
|
||||
var history = historyQuery.CompOrNull(grid.Grid);
|
||||
_explosionData.Add(new ExplosionData
|
||||
{
|
||||
TileLists = grid.TileLists,
|
||||
Lookup = (grid.Grid, entMan.GetComponent<BroadphaseComponent>(grid.Grid)),
|
||||
MapGrid = grid.Grid,
|
||||
MapGrid = (grid.Grid, entMan.GetComponent<MapGridComponent>(grid.Grid), history),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -784,10 +828,11 @@ sealed class Explosion
|
||||
_currentEnumerator = tileList.GetEnumerator();
|
||||
_currentLookup = _explosionData[_currentDataIndex].Lookup;
|
||||
_currentGrid = _explosionData[_currentDataIndex].MapGrid;
|
||||
_currentChunk = null;
|
||||
_currentDataIndex++;
|
||||
|
||||
// sanity checks, in case something changed while the explosion was being processed over several ticks.
|
||||
if (_currentLookup.Comp.Deleted || _currentGrid != null && !_entMan.EntityExists(_currentGrid.Value))
|
||||
if (_currentLookup.Comp.Deleted || (_currentGrid is { } grid && !_entMan.EntityExists(grid.Owner)))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
@@ -843,19 +888,19 @@ sealed class Explosion
|
||||
|
||||
// Is the current tile on a grid (instead of in space)?
|
||||
if (_currentGrid is { } currentGrid &&
|
||||
_mapSystem.TryGetTileRef(currentGrid, currentGrid.Comp, _currentEnumerator.Current, out var tileRef) &&
|
||||
_mapSystem.TryGetTileRef(currentGrid.Owner, currentGrid.Comp1, _currentEnumerator.Current, out var tileRef) &&
|
||||
!tileRef.Tile.IsEmpty)
|
||||
{
|
||||
if (!_tileUpdateDict.TryGetValue(currentGrid, out var tileUpdateList))
|
||||
if (!_tileUpdateDict.TryGetValue((currentGrid.Owner, currentGrid.Comp1), out var tileUpdateList))
|
||||
{
|
||||
tileUpdateList = new();
|
||||
_tileUpdateDict[currentGrid] = tileUpdateList;
|
||||
_tileUpdateDict[(currentGrid.Owner, currentGrid.Comp1)] = tileUpdateList;
|
||||
}
|
||||
|
||||
// damage entities on the tile. Also figures out whether there are any solid entities blocking the floor
|
||||
// from being destroyed.
|
||||
var canDamageFloor = _system.ExplodeTile(_currentLookup,
|
||||
currentGrid,
|
||||
(currentGrid.Owner, currentGrid.Comp1),
|
||||
_currentEnumerator.Current,
|
||||
_currentThrowForce,
|
||||
_currentDamage,
|
||||
@@ -869,7 +914,24 @@ sealed class Explosion
|
||||
|
||||
// If the floor is not blocked by some dense object, damage the floor tiles.
|
||||
if (canDamageFloor)
|
||||
_system.DamageFloorTile(tileRef, _currentIntensity * _tileBreakScale, _maxTileBreak, _canCreateVacuum, tileUpdateList, ExplosionType);
|
||||
{
|
||||
var tileIndices = _currentEnumerator.Current;
|
||||
var chunkIndices = SharedMapSystem.GetChunkIndices(tileIndices, TileSystem.ChunkSize);
|
||||
if (_currentChunk?.Indices != chunkIndices)
|
||||
{
|
||||
var chunk = currentGrid.Comp2?.ChunkHistory.GetValueOrDefault(chunkIndices);
|
||||
_currentChunk = (chunk, chunkIndices);
|
||||
}
|
||||
|
||||
_system.DamageFloorTile(tileRef,
|
||||
_currentIntensity * _tileBreakScale,
|
||||
_maxTileBreak,
|
||||
_canCreateVacuum,
|
||||
tileUpdateList,
|
||||
ExplosionType,
|
||||
currentGrid.Comp2,
|
||||
ref _currentChunk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -909,6 +971,8 @@ sealed class Explosion
|
||||
if (list.Count > 0 && _entMan.EntityExists(grid.Owner))
|
||||
{
|
||||
_mapSystem.SetTiles(grid.Owner, grid, list);
|
||||
|
||||
_system.DirtyHistory(grid.Owner);
|
||||
}
|
||||
}
|
||||
_tileUpdateDict.Clear();
|
||||
|
||||
Reference in New Issue
Block a user