DungeonData rework (#37172)
* DungeonData rework Back to fields, serializes better, just make new layers dumby. * wawawewa * Fix this * Fixes * review * thanks fork * fix
This commit is contained in:
@@ -13,14 +13,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="AutoCablingDunGen"/>
|
/// <see cref="AutoCablingDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(AutoCablingDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(AutoCablingDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Entities.TryGetValue(DungeonDataKey.Cabling, out var ent))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(AutoCablingDunGen));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There's a lot of ways you could do this.
|
// There's a lot of ways you could do this.
|
||||||
// For now we'll just connect every LV cable in the dungeon.
|
// For now we'll just connect every LV cable in the dungeon.
|
||||||
var cableTiles = new HashSet<Vector2i>();
|
var cableTiles = new HashSet<Vector2i>();
|
||||||
@@ -157,7 +151,7 @@ public sealed partial class DungeonJob
|
|||||||
if (found)
|
if (found)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_entManager.SpawnEntity(ent, _maps.GridTileToLocal(_gridUid, _grid, tile));
|
_entManager.SpawnEntity(gen.Entity, _maps.GridTileToLocal(_gridUid, _grid, tile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="BiomeDunGen"/>
|
/// <see cref="BiomeDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(BiomeDunGen dunGen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(BiomeDunGen dunGen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!_prototype.TryIndex(dunGen.BiomeTemplate, out var indexedBiome))
|
if (!_prototype.TryIndex(dunGen.BiomeTemplate, out var indexedBiome))
|
||||||
return;
|
return;
|
||||||
@@ -15,7 +15,7 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="BiomeMarkerLayerDunGen"/>
|
/// <see cref="BiomeMarkerLayerDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(BiomeMarkerLayerDunGen dunGen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(BiomeMarkerLayerDunGen dunGen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
// If we're adding biome then disable it and just use for markers.
|
// If we're adding biome then disable it and just use for markers.
|
||||||
if (_entManager.EnsureComponent(_gridUid, out BiomeComponent biomeComp))
|
if (_entManager.EnsureComponent(_gridUid, out BiomeComponent biomeComp))
|
||||||
@@ -12,27 +12,13 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="BoundaryWallDunGen"/>
|
/// <see cref="BoundaryWallDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(BoundaryWallDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(BoundaryWallDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var protoTileDef) ||
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
!data.Entities.TryGetValue(DungeonDataKey.Walls, out var wall))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Error finding dungeon data for {nameof(gen)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tileDef = _tileDefManager[protoTileDef];
|
|
||||||
var tiles = new List<(Vector2i Index, Tile Tile)>(dungeon.RoomExteriorTiles.Count);
|
var tiles = new List<(Vector2i Index, Tile Tile)>(dungeon.RoomExteriorTiles.Count);
|
||||||
|
|
||||||
if (!data.Entities.TryGetValue(DungeonDataKey.CornerWalls, out var cornerWall))
|
var wall = gen.Wall;
|
||||||
{
|
var cornerWall = gen.CornerWall ?? gen.Wall;
|
||||||
cornerWall = wall;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cornerWall == default)
|
|
||||||
{
|
|
||||||
cornerWall = wall;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn wall outline
|
// Spawn wall outline
|
||||||
// - Tiles first
|
// - Tiles first
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Shared.Procedural;
|
using Content.Shared.Procedural;
|
||||||
using Content.Shared.Procedural.PostGeneration;
|
using Content.Shared.Procedural.PostGeneration;
|
||||||
using Content.Shared.Storage;
|
|
||||||
using Robust.Shared.Physics.Components;
|
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Procedural.DungeonJob;
|
namespace Content.Server.Procedural.DungeonJob;
|
||||||
@@ -12,16 +10,15 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="CornerClutterDunGen"/>
|
/// <see cref="CornerClutterDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(CornerClutterDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(CornerClutterDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.SpawnGroups.TryGetValue(DungeonDataKey.CornerClutter, out var corner))
|
var contentsTable = _prototype.Index(gen.Contents);
|
||||||
{
|
|
||||||
_sawmill.Error(Environment.StackTrace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tile in dungeon.CorridorTiles)
|
foreach (var tile in dungeon.CorridorTiles)
|
||||||
{
|
{
|
||||||
|
if (reservedTiles.Contains(tile))
|
||||||
|
continue;
|
||||||
|
|
||||||
var blocked = _anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask);
|
var blocked = _anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask);
|
||||||
|
|
||||||
if (blocked)
|
if (blocked)
|
||||||
@@ -45,8 +42,8 @@ public sealed partial class DungeonJob
|
|||||||
if (random.Prob(gen.Chance))
|
if (random.Prob(gen.Chance))
|
||||||
{
|
{
|
||||||
var coords = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
var coords = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
||||||
var protos = EntitySpawnCollection.GetSpawns(_prototype.Index(corner).Entries, random);
|
var protos = contentsTable.Table.GetSpawns(random, _entManager, _prototype);
|
||||||
_entManager.SpawnEntities(coords, protos);
|
_entManager.SpawnEntitiesAttachedTo(coords, protos);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -12,14 +12,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="CorridorDunGen"/>
|
/// <see cref="CorridorDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(CorridorDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(CorridorDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(CorridorDunGen));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entrances = new List<Vector2i>(dungeon.Rooms.Count);
|
var entrances = new List<Vector2i>(dungeon.Rooms.Count);
|
||||||
|
|
||||||
// Grab entrances
|
// Grab entrances
|
||||||
@@ -98,7 +92,7 @@ public sealed partial class DungeonJob
|
|||||||
WidenCorridor(dungeon, gen.Width, corridorTiles);
|
WidenCorridor(dungeon, gen.Width, corridorTiles);
|
||||||
|
|
||||||
var setTiles = new List<(Vector2i, Tile)>();
|
var setTiles = new List<(Vector2i, Tile)>();
|
||||||
var tileDef = (ContentTileDefinition) _tileDefManager[tileProto];
|
var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
|
||||||
|
|
||||||
foreach (var tile in corridorTiles)
|
foreach (var tile in corridorTiles)
|
||||||
{
|
{
|
||||||
@@ -12,10 +12,11 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="CorridorClutterDunGen"/>
|
/// <see cref="CorridorClutterDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(CorridorClutterDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(CorridorClutterDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
var physicsQuery = _entManager.GetEntityQuery<PhysicsComponent>();
|
var physicsQuery = _entManager.GetEntityQuery<PhysicsComponent>();
|
||||||
var count = (int) Math.Ceiling(dungeon.CorridorTiles.Count * gen.Chance);
|
var count = (int) Math.Ceiling(dungeon.CorridorTiles.Count * gen.Chance);
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
@@ -42,9 +43,12 @@ public sealed partial class DungeonJob
|
|||||||
|
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
var protos = EntitySpawnCollection.GetSpawns(gen.Contents, random);
|
if (reservedTiles.Contains(tile))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var protos = _entTable.GetSpawns(contents, random);
|
||||||
var coords = _maps.ToCenterCoordinates(_gridUid, tile, _grid);
|
var coords = _maps.ToCenterCoordinates(_gridUid, tile, _grid);
|
||||||
_entManager.SpawnEntities(coords, protos);
|
_entManager.SpawnEntitiesAttachedTo(coords, protos);
|
||||||
await SuspendIfOutOfTime();
|
await SuspendIfOutOfTime();
|
||||||
|
|
||||||
if (!ValidateResume())
|
if (!ValidateResume())
|
||||||
@@ -13,13 +13,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="CorridorDecalSkirtingDunGen"/>
|
/// <see cref="CorridorDecalSkirtingDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(CorridorDecalSkirtingDunGen decks, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(CorridorDecalSkirtingDunGen decks, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Colors.TryGetValue(DungeonDataKey.Decals, out var color))
|
|
||||||
{
|
|
||||||
_sawmill.Error(Environment.StackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
var directions = new ValueList<DirectionFlag>(4);
|
var directions = new ValueList<DirectionFlag>(4);
|
||||||
var pocketDirections = new ValueList<Direction>(4);
|
var pocketDirections = new ValueList<Direction>(4);
|
||||||
var doorQuery = _entManager.GetEntityQuery<DoorComponent>();
|
var doorQuery = _entManager.GetEntityQuery<DoorComponent>();
|
||||||
@@ -88,7 +83,7 @@ public sealed partial class DungeonJob
|
|||||||
{
|
{
|
||||||
// Decals not being centered biting my ass again
|
// Decals not being centered biting my ass again
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
||||||
_decals.TryAddDecal(cDir, gridPos, out _, color: color);
|
_decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +96,7 @@ public sealed partial class DungeonJob
|
|||||||
{
|
{
|
||||||
// Decals not being centered biting my ass again
|
// Decals not being centered biting my ass again
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
||||||
_decals.TryAddDecal(cDir, gridPos, out _, color: color);
|
_decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -116,7 +111,7 @@ public sealed partial class DungeonJob
|
|||||||
if (decks.CornerDecals.TryGetValue(dirFlag, out var cDir))
|
if (decks.CornerDecals.TryGetValue(dirFlag, out var cDir))
|
||||||
{
|
{
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile).Offset(offset);
|
||||||
_decals.TryAddDecal(cDir, gridPos, out _, color: color);
|
_decals.TryAddDecal(cDir, gridPos, out _, color: decks.Color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Content.Shared.Maps;
|
|
||||||
using Content.Shared.Procedural;
|
|
||||||
using Content.Shared.Procedural.DungeonGenerators;
|
|
||||||
|
|
||||||
namespace Content.Server.Procedural.DungeonJob;
|
|
||||||
|
|
||||||
public sealed partial class DungeonJob
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="FillGridDunGen"/>
|
|
||||||
/// </summary>
|
|
||||||
private async Task<Dungeon> GenerateFillDunGen(FillGridDunGen fill, DungeonData data, HashSet<Vector2i> reservedTiles)
|
|
||||||
{
|
|
||||||
if (!data.Entities.TryGetValue(DungeonDataKey.Fill, out var fillEnt))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(FillGridDunGen));
|
|
||||||
return Dungeon.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var roomTiles = new HashSet<Vector2i>();
|
|
||||||
var tiles = _maps.GetAllTilesEnumerator(_gridUid, _grid);
|
|
||||||
|
|
||||||
while (tiles.MoveNext(out var tileRef))
|
|
||||||
{
|
|
||||||
var tile = tileRef.Value.GridIndices;
|
|
||||||
|
|
||||||
if (reservedTiles.Contains(tile))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fill.AllowedTiles != null && !fill.AllowedTiles.Contains(((ContentTileDefinition) _tileDefManager[tileRef.Value.Tile.TypeId]).ID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
|
||||||
_entManager.SpawnEntity(fillEnt, gridPos);
|
|
||||||
|
|
||||||
roomTiles.Add(tile);
|
|
||||||
|
|
||||||
await SuspendDungeon();
|
|
||||||
if (!ValidateResume())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dungeon = new Dungeon();
|
|
||||||
var room = new DungeonRoom(roomTiles, Vector2.Zero, Box2i.Empty, new HashSet<Vector2i>());
|
|
||||||
dungeon.AddRoom(room);
|
|
||||||
|
|
||||||
return dungeon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,15 +14,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="PrefabDunGen"/>
|
/// <see cref="PrefabDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<Dungeon> GeneratePrefabDunGen(Vector2i position, DungeonData data, PrefabDunGen prefab, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task<Dungeon> GeneratePrefabDunGen(Vector2i position, PrefabDunGen prefab, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.Whitelists.TryGetValue(DungeonDataKey.Rooms, out var roomWhitelist))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(PrefabDunGen));
|
|
||||||
return Dungeon.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var preset = prefab.Presets[random.Next(prefab.Presets.Count)];
|
var preset = prefab.Presets[random.Next(prefab.Presets.Count)];
|
||||||
var gen = _prototype.Index(preset);
|
var gen = _prototype.Index(preset);
|
||||||
|
|
||||||
@@ -50,9 +43,9 @@ public sealed partial class DungeonJob
|
|||||||
{
|
{
|
||||||
var whitelisted = false;
|
var whitelisted = false;
|
||||||
|
|
||||||
if (roomWhitelist?.Tags != null)
|
if (prefab.RoomWhitelist?.Tags != null)
|
||||||
{
|
{
|
||||||
foreach (var tag in roomWhitelist.Tags)
|
foreach (var tag in prefab.RoomWhitelist.Tags)
|
||||||
{
|
{
|
||||||
if (proto.Tags.Contains(tag))
|
if (proto.Tags.Contains(tag))
|
||||||
{
|
{
|
||||||
@@ -164,6 +157,7 @@ public sealed partial class DungeonJob
|
|||||||
|
|
||||||
// Then for overlaps choose either 1x1 / 3x1
|
// Then for overlaps choose either 1x1 / 3x1
|
||||||
// Pick a random tile for it and then expand outwards as relevant (weighted towards middle?)
|
// Pick a random tile for it and then expand outwards as relevant (weighted towards middle?)
|
||||||
|
var fallbackTile = prefab.FallbackTile;
|
||||||
|
|
||||||
for (var i = 0; i < chosenPacks.Length; i++)
|
for (var i = 0; i < chosenPacks.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -181,29 +175,35 @@ public sealed partial class DungeonJob
|
|||||||
Angle roomRotation = Angle.Zero;
|
Angle roomRotation = Angle.Zero;
|
||||||
Matrix3x2 matty;
|
Matrix3x2 matty;
|
||||||
|
|
||||||
|
// If no room found then try rotated dimensions
|
||||||
if (!roomProtos.TryGetValue(roomDimensions, out var roomProto))
|
if (!roomProtos.TryGetValue(roomDimensions, out var roomProto))
|
||||||
{
|
{
|
||||||
roomDimensions = new Vector2i(roomDimensions.Y, roomDimensions.X);
|
roomDimensions = new Vector2i(roomDimensions.Y, roomDimensions.X);
|
||||||
|
|
||||||
|
// If nothing at all then no valid rooms, try fallback tile and log it.
|
||||||
if (!roomProtos.TryGetValue(roomDimensions, out roomProto))
|
if (!roomProtos.TryGetValue(roomDimensions, out roomProto))
|
||||||
{
|
{
|
||||||
matty = Matrix3x2.Multiply(packTransform, dungeonTransform);
|
if (fallbackTile != null)
|
||||||
|
|
||||||
for (var x = roomSize.Left; x < roomSize.Right; x++)
|
|
||||||
{
|
{
|
||||||
for (var y = roomSize.Bottom; y < roomSize.Top; y++)
|
matty = Matrix3x2.Multiply(packTransform, dungeonTransform);
|
||||||
|
|
||||||
|
for (var x = roomSize.Left; x < roomSize.Right; x++)
|
||||||
{
|
{
|
||||||
var index = Vector2.Transform(new Vector2(x, y) + _grid.TileSizeHalfVector - packCenter, matty).Floored();
|
for (var y = roomSize.Bottom; y < roomSize.Top; y++)
|
||||||
|
{
|
||||||
|
var index = Vector2.Transform(new Vector2(x, y) + _grid.TileSizeHalfVector - packCenter, matty).Floored();
|
||||||
|
|
||||||
if (reservedTiles.Contains(index))
|
if (reservedTiles.Contains(index))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tiles.Add((index, new Tile(_tileDefManager[tileProto].TileId)));
|
tiles.Add((index, new Tile(_tileDefManager[fallbackTile.Value].TileId)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_maps.SetTiles(_gridUid, _grid, tiles);
|
||||||
|
tiles.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
_maps.SetTiles(_gridUid, _grid, tiles);
|
|
||||||
tiles.Clear();
|
|
||||||
_sawmill.Error($"Unable to find room variant for {roomDimensions}, leaving empty.");
|
_sawmill.Error($"Unable to find room variant for {roomDimensions}, leaving empty.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,49 +12,43 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="ReplaceTileDunGen"/>
|
/// <see cref="ReplaceTileDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<Dungeon> GenerateTileReplacementDunGen(ReplaceTileDunGen gen, DungeonData data, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task GenerateTileReplacementDunGen(ReplaceTileDunGen gen, List<Dungeon> dungeons, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
var tiles = _maps.GetAllTilesEnumerator(_gridUid, _grid);
|
|
||||||
var replacements = new List<(Vector2i Index, Tile Tile)>();
|
var replacements = new List<(Vector2i Index, Tile Tile)>();
|
||||||
var reserved = new HashSet<Vector2i>();
|
|
||||||
|
|
||||||
while (tiles.MoveNext(out var tileRef))
|
foreach (var dungeon in dungeons)
|
||||||
{
|
{
|
||||||
var node = tileRef.Value.GridIndices;
|
foreach (var node in dungeon.AllTiles)
|
||||||
|
|
||||||
if (reservedTiles.Contains(node))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (var layer in gen.Layers)
|
|
||||||
{
|
{
|
||||||
var value = layer.Noise.GetNoise(node.X, node.Y);
|
if (reservedTiles.Contains(node))
|
||||||
|
|
||||||
if (value < layer.Threshold)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Tile tile;
|
foreach (var layer in gen.Layers)
|
||||||
|
{
|
||||||
|
var value = layer.Noise.GetNoise(node.X, node.Y);
|
||||||
|
|
||||||
if (random.Prob(gen.VariantWeight))
|
if (value < layer.Threshold)
|
||||||
{
|
continue;
|
||||||
tile = _tileDefManager.GetVariantTile(_prototype.Index(layer.Tile), random);
|
|
||||||
}
|
Tile tile;
|
||||||
else
|
|
||||||
{
|
if (random.Prob(gen.VariantWeight))
|
||||||
tile = new Tile(_prototype.Index(layer.Tile).TileId);
|
{
|
||||||
|
tile = _tileDefManager.GetVariantTile(_prototype.Index(layer.Tile), random);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tile = new Tile(_prototype.Index(layer.Tile).TileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
replacements.Add((node, tile));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
replacements.Add((node, tile));
|
await SuspendDungeon();
|
||||||
reserved.Add(node);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await SuspendDungeon();
|
_maps.SetTiles(_gridUid, _grid, replacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
_maps.SetTiles(_gridUid, _grid, replacements);
|
|
||||||
return new Dungeon(new List<DungeonRoom>()
|
|
||||||
{
|
|
||||||
new DungeonRoom(reserved, _position, Box2i.Empty, new HashSet<Vector2i>()),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,18 +12,12 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="DungeonEntranceDunGen"/>
|
/// <see cref="DungeonEntranceDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(DungeonEntranceDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(DungeonEntranceDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entrance))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(DungeonEntranceDunGen));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rooms = new List<DungeonRoom>(dungeon.Rooms);
|
var rooms = new List<DungeonRoom>(dungeon.Rooms);
|
||||||
var roomTiles = new List<Vector2i>();
|
var roomTiles = new List<Vector2i>();
|
||||||
var tileDef = (ContentTileDefinition) _tileDefManager[tileProto];
|
var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
for (var i = 0; i < gen.Count; i++)
|
for (var i = 0; i < gen.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -82,7 +76,7 @@ public sealed partial class DungeonJob
|
|||||||
var gridCoords = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
var gridCoords = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
||||||
// Need to offset the spawn to avoid spawning in the room.
|
// Need to offset the spawn to avoid spawning in the room.
|
||||||
|
|
||||||
foreach (var ent in EntitySpawnCollection.GetSpawns(_prototype.Index(entrance).Entries, random))
|
foreach (var ent in _entTable.GetSpawns(contents, random))
|
||||||
{
|
{
|
||||||
_entManager.SpawnAtPosition(ent, gridCoords);
|
_entManager.SpawnAtPosition(ent, gridCoords);
|
||||||
}
|
}
|
||||||
@@ -13,18 +13,12 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="EntranceFlankDunGen"/>
|
/// <see cref="EntranceFlankDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(EntranceFlankDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(EntranceFlankDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.EntranceFlank, out var flankProto))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Unable to get dungeon data for {nameof(gen)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tiles = new List<(Vector2i Index, Tile)>();
|
var tiles = new List<(Vector2i Index, Tile)>();
|
||||||
var tileDef = _tileDefManager[tileProto];
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
var spawnPositions = new ValueList<Vector2i>(dungeon.Rooms.Count);
|
var spawnPositions = new ValueList<Vector2i>(dungeon.Rooms.Count);
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
foreach (var room in dungeon.Rooms)
|
foreach (var room in dungeon.Rooms)
|
||||||
{
|
{
|
||||||
@@ -48,11 +42,10 @@ public sealed partial class DungeonJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
_maps.SetTiles(_gridUid, _grid, tiles);
|
_maps.SetTiles(_gridUid, _grid, tiles);
|
||||||
var entGroup = _prototype.Index(flankProto);
|
|
||||||
|
|
||||||
foreach (var entrance in spawnPositions)
|
foreach (var entrance in spawnPositions)
|
||||||
{
|
{
|
||||||
_entManager.SpawnEntities(_maps.GridTileToLocal(_gridUid, _grid, entrance), EntitySpawnCollection.GetSpawns(entGroup.Entries, random));
|
_entManager.SpawnEntitiesAttachedTo(_maps.GridTileToLocal(_gridUid, _grid, entrance), _entTable.GetSpawns(contents, random));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.NPC.Pathfinding;
|
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.NPC;
|
using Content.Shared.NPC;
|
||||||
using Content.Shared.Procedural;
|
using Content.Shared.Procedural;
|
||||||
using Content.Shared.Procedural.DungeonGenerators;
|
using Content.Shared.Procedural.DungeonGenerators;
|
||||||
using Robust.Shared.Collections;
|
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
@@ -27,7 +25,6 @@ public sealed partial class DungeonJob
|
|||||||
var startTile = new Vector2i(0, (int) distance).Rotate(angle);
|
var startTile = new Vector2i(0, (int) distance).Rotate(angle);
|
||||||
|
|
||||||
Vector2i? dungeonSpawn = null;
|
Vector2i? dungeonSpawn = null;
|
||||||
var pathfinder = _entManager.System<PathfindingSystem>();
|
|
||||||
|
|
||||||
// Gridcast
|
// Gridcast
|
||||||
SharedPathfindingSystem.GridCast(startTile, position, tile =>
|
SharedPathfindingSystem.GridCast(startTile, position, tile =>
|
||||||
@@ -52,7 +49,7 @@ public sealed partial class DungeonJob
|
|||||||
|
|
||||||
var config = _prototype.Index(dungen.Proto);
|
var config = _prototype.Index(dungen.Proto);
|
||||||
var nextSeed = random.Next();
|
var nextSeed = random.Next();
|
||||||
var dungeons = await GetDungeons(dungeonSpawn.Value, config, config.Data, config.Layers, reservedTiles, nextSeed, new Random(nextSeed));
|
var dungeons = await GetDungeons(dungeonSpawn.Value, config, config.Layers, reservedTiles, nextSeed, new Random(nextSeed));
|
||||||
|
|
||||||
return dungeons;
|
return dungeons;
|
||||||
}
|
}
|
||||||
@@ -24,15 +24,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="ExternalWindowDunGen"/>
|
/// <see cref="ExternalWindowDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(ExternalWindowDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(ExternalWindowDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Window, out var windowGroup))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Unable to get dungeon data for {nameof(gen)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate every tile with N chance to spawn windows on that wall per cardinal dir.
|
// Iterate every tile with N chance to spawn windows on that wall per cardinal dir.
|
||||||
var chance = 0.25 / 3f;
|
var chance = 0.25 / 3f;
|
||||||
|
|
||||||
@@ -42,7 +35,7 @@ public sealed partial class DungeonJob
|
|||||||
random.Shuffle(validTiles);
|
random.Shuffle(validTiles);
|
||||||
|
|
||||||
var tiles = new List<(Vector2i, Tile)>();
|
var tiles = new List<(Vector2i, Tile)>();
|
||||||
var tileDef = _tileDefManager[tileProto];
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
var count = Math.Floor(validTiles.Count * chance);
|
var count = Math.Floor(validTiles.Count * chance);
|
||||||
var index = 0;
|
var index = 0;
|
||||||
var takenTiles = new HashSet<Vector2i>();
|
var takenTiles = new HashSet<Vector2i>();
|
||||||
@@ -120,15 +113,13 @@ public sealed partial class DungeonJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
_maps.SetTiles(_gridUid, _grid, tiles);
|
_maps.SetTiles(_gridUid, _grid, tiles);
|
||||||
index = 0;
|
var contents = _prototype.Index(gen.Contents);
|
||||||
var spawnEntry = _prototype.Index(windowGroup);
|
|
||||||
|
|
||||||
foreach (var tile in tiles)
|
foreach (var tile in tiles)
|
||||||
{
|
{
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile.Item1);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile.Item1);
|
||||||
|
|
||||||
index += spawnEntry.Entries.Count;
|
_entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
|
||||||
_entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(spawnEntry.Entries, random));
|
|
||||||
await SuspendDungeon();
|
await SuspendDungeon();
|
||||||
|
|
||||||
if (!ValidateResume())
|
if (!ValidateResume())
|
||||||
39
Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs
Normal file
39
Content.Server/Procedural/DungeonJob/DungeonJob.Fill.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.Procedural;
|
||||||
|
using Content.Shared.Procedural.DungeonLayers;
|
||||||
|
|
||||||
|
namespace Content.Server.Procedural.DungeonJob;
|
||||||
|
|
||||||
|
public sealed partial class DungeonJob
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="Shared.Procedural.DungeonLayers.FillGridDunGen"/>
|
||||||
|
/// </summary>
|
||||||
|
private async Task GenerateFillDunGen(FillGridDunGen fill, List<Dungeon> dungeons, HashSet<Vector2i> reservedTiles)
|
||||||
|
{
|
||||||
|
foreach (var dungeon in dungeons)
|
||||||
|
{
|
||||||
|
foreach (var tile in dungeon.AllTiles)
|
||||||
|
{
|
||||||
|
if (reservedTiles.Contains(tile))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_maps.TryGetTileDef(_grid, tile, out var tileDef))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fill.AllowedTiles != null && !fill.AllowedTiles.Contains(tileDef.ID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_anchorable.TileFree(_grid, tile, DungeonSystem.CollisionLayer, DungeonSystem.CollisionMask))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
||||||
|
_entManager.SpawnEntity(fill.Entity, gridPos);
|
||||||
|
|
||||||
|
await SuspendDungeon();
|
||||||
|
if (!ValidateResume())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,9 +10,7 @@ namespace Content.Server.Procedural.DungeonJob;
|
|||||||
|
|
||||||
public sealed partial class DungeonJob
|
public sealed partial class DungeonJob
|
||||||
{
|
{
|
||||||
/*
|
// Various helper methods.
|
||||||
* Run after the main dungeon generation
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static readonly ProtoId<TagPrototype> WallTag = "Wall";
|
private static readonly ProtoId<TagPrototype> WallTag = "Wall";
|
||||||
|
|
||||||
@@ -12,21 +12,14 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="InternalWindowDunGen"/>
|
/// <see cref="InternalWindowDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(InternalWindowDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(InternalWindowDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Window, out var windowGroup))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Unable to find dungeon data keys for {nameof(gen)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate every room and check if there's a gap beyond it that leads to another room within N tiles
|
// Iterate every room and check if there's a gap beyond it that leads to another room within N tiles
|
||||||
// If so then consider windows
|
// If so then consider windows
|
||||||
var minDistance = 4;
|
var minDistance = 4;
|
||||||
var maxDistance = 6;
|
var maxDistance = 6;
|
||||||
var tileDef = _tileDefManager[tileProto];
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
var window = _prototype.Index(windowGroup);
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
foreach (var room in dungeon.Rooms)
|
foreach (var room in dungeon.Rooms)
|
||||||
{
|
{
|
||||||
@@ -90,7 +83,7 @@ public sealed partial class DungeonJob
|
|||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, tile);
|
||||||
_maps.SetTile(_gridUid, _grid, tile, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
_maps.SetTile(_gridUid, _grid, tile, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
||||||
|
|
||||||
_entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(window.Entries, random));
|
_entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validTiles.Count > 0)
|
if (validTiles.Count > 0)
|
||||||
@@ -12,17 +12,10 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="JunctionDunGen"/>
|
/// <see cref="JunctionDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(JunctionDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(JunctionDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Junction, out var junctionProto))
|
var contents = _prototype.Index(gen.Contents);
|
||||||
{
|
|
||||||
_sawmill.Error($"Dungeon data keys are missing for {nameof(gen)}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tileDef = _tileDefManager[tileProto];
|
|
||||||
var entranceGroup = _prototype.Index(junctionProto);
|
|
||||||
|
|
||||||
// N-wide junctions
|
// N-wide junctions
|
||||||
foreach (var tile in dungeon.CorridorTiles)
|
foreach (var tile in dungeon.CorridorTiles)
|
||||||
@@ -123,7 +116,7 @@ public sealed partial class DungeonJob
|
|||||||
_maps.SetTile(_gridUid, _grid, weh, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
_maps.SetTile(_gridUid, _grid, weh, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
||||||
|
|
||||||
var coords = _maps.GridTileToLocal(_gridUid, _grid, weh);
|
var coords = _maps.GridTileToLocal(_gridUid, _grid, weh);
|
||||||
_entManager.SpawnEntities(coords, EntitySpawnCollection.GetSpawns(entranceGroup.Entries, random));
|
_entManager.SpawnEntitiesAttachedTo(coords, _entTable.GetSpawns(contents, random));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -13,19 +13,8 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="MiddleConnectionDunGen"/>
|
/// <see cref="MiddleConnectionDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(MiddleConnectionDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(MiddleConnectionDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entranceProto) ||
|
|
||||||
!_prototype.TryIndex(entranceProto, out var entrance))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Tried to run {nameof(MiddleConnectionDunGen)} without any dungeon data set which is unsupported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.SpawnGroups.TryGetValue(DungeonDataKey.EntranceFlank, out var flankProto);
|
|
||||||
_prototype.TryIndex(flankProto, out var flank);
|
|
||||||
|
|
||||||
// Grab all of the room bounds
|
// Grab all of the room bounds
|
||||||
// Then, work out connections between them
|
// Then, work out connections between them
|
||||||
var roomBorders = new Dictionary<DungeonRoom, HashSet<Vector2i>>(dungeon.Rooms.Count);
|
var roomBorders = new Dictionary<DungeonRoom, HashSet<Vector2i>>(dungeon.Rooms.Count);
|
||||||
@@ -67,7 +56,9 @@ public sealed partial class DungeonJob
|
|||||||
// TODO: Optional loops
|
// TODO: Optional loops
|
||||||
|
|
||||||
var roomConnections = new Dictionary<DungeonRoom, List<DungeonRoom>>();
|
var roomConnections = new Dictionary<DungeonRoom, List<DungeonRoom>>();
|
||||||
var tileDef = _tileDefManager[tileProto];
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
|
_prototype.TryIndex(gen.Flank, out var flankContents);
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
foreach (var (room, border) in roomBorders)
|
foreach (var (room, border) in roomBorders)
|
||||||
{
|
{
|
||||||
@@ -118,16 +109,16 @@ public sealed partial class DungeonJob
|
|||||||
width--;
|
width--;
|
||||||
_maps.SetTile(_gridUid, _grid, node, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
_maps.SetTile(_gridUid, _grid, node, _tile.GetVariantTile((ContentTileDefinition) tileDef, random));
|
||||||
|
|
||||||
if (flank != null && nodeDistances.Count - i <= 2)
|
if (flankContents != null && nodeDistances.Count - i <= 2)
|
||||||
{
|
{
|
||||||
_entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(flank.Entries, random));
|
_entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(flankContents, random));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Iterate neighbors and check for blockers, if so bulldoze
|
// Iterate neighbors and check for blockers, if so bulldoze
|
||||||
ClearDoor(dungeon, _grid, node);
|
ClearDoor(dungeon, _grid, node);
|
||||||
|
|
||||||
_entManager.SpawnEntities(gridPos, EntitySpawnCollection.GetSpawns(entrance.Entries, random));
|
_entManager.SpawnEntitiesAttachedTo(gridPos, _entTable.GetSpawns(contents, random));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width == 0)
|
if (width == 0)
|
||||||
@@ -13,6 +13,9 @@ namespace Content.Server.Procedural.DungeonJob;
|
|||||||
|
|
||||||
public sealed partial class DungeonJob
|
public sealed partial class DungeonJob
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="MobsDunGen"/>
|
||||||
|
/// </summary>
|
||||||
private async Task PostGen(
|
private async Task PostGen(
|
||||||
MobsDunGen gen,
|
MobsDunGen gen,
|
||||||
Dungeon dungeon,
|
Dungeon dungeon,
|
||||||
@@ -21,8 +24,8 @@ public sealed partial class DungeonJob
|
|||||||
var availableRooms = new ValueList<DungeonRoom>();
|
var availableRooms = new ValueList<DungeonRoom>();
|
||||||
availableRooms.AddRange(dungeon.Rooms);
|
availableRooms.AddRange(dungeon.Rooms);
|
||||||
var availableTiles = new ValueList<Vector2i>(dungeon.AllTiles);
|
var availableTiles = new ValueList<Vector2i>(dungeon.AllTiles);
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
var entities = EntitySpawnCollection.GetSpawns(gen.Groups, random);
|
|
||||||
var count = random.Next(gen.MinCount, gen.MaxCount + 1);
|
var count = random.Next(gen.MinCount, gen.MaxCount + 1);
|
||||||
var npcs = _entManager.System<NPCSystem>();
|
var npcs = _entManager.System<NPCSystem>();
|
||||||
|
|
||||||
@@ -38,6 +41,8 @@ public sealed partial class DungeonJob
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var entities = _entTable.GetSpawns(contents, random);
|
||||||
|
|
||||||
foreach (var ent in entities)
|
foreach (var ent in entities)
|
||||||
{
|
{
|
||||||
var uid = _entManager.SpawnAtPosition(ent, _maps.GridTileToLocal(_gridUid, _grid, tile));
|
var uid = _entManager.SpawnAtPosition(ent, _maps.GridTileToLocal(_gridUid, _grid, tile));
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Content.Server.Procedural.DungeonJob;
|
|
||||||
|
|
||||||
public sealed partial class DungeonJob
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -12,23 +12,19 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="RoomEntranceDunGen"/>
|
/// <see cref="RoomEntranceDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(RoomEntranceDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(RoomEntranceDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) ||
|
|
||||||
!data.SpawnGroups.TryGetValue(DungeonDataKey.Entrance, out var entranceProtos) ||
|
|
||||||
!_prototype.TryIndex(entranceProtos, out var entranceIn))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(RoomEntranceDunGen));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var setTiles = new List<(Vector2i, Tile)>();
|
var setTiles = new List<(Vector2i, Tile)>();
|
||||||
var tileDef = _tileDefManager[tileProto];
|
var tileDef = _tileDefManager[gen.Tile];
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
foreach (var room in dungeon.Rooms)
|
foreach (var room in dungeon.Rooms)
|
||||||
{
|
{
|
||||||
foreach (var entrance in room.Entrances)
|
foreach (var entrance in room.Entrances)
|
||||||
{
|
{
|
||||||
|
if (reservedTiles.Contains(entrance))
|
||||||
|
continue;
|
||||||
|
|
||||||
setTiles.Add((entrance, _tile.GetVariantTile((ContentTileDefinition) tileDef, random)));
|
setTiles.Add((entrance, _tile.GetVariantTile((ContentTileDefinition) tileDef, random)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,9 +35,17 @@ public sealed partial class DungeonJob
|
|||||||
{
|
{
|
||||||
foreach (var entrance in room.Entrances)
|
foreach (var entrance in room.Entrances)
|
||||||
{
|
{
|
||||||
_entManager.SpawnEntities(
|
if (reservedTiles.Contains(entrance))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_entManager.SpawnEntitiesAttachedTo(
|
||||||
_maps.GridTileToLocal(_gridUid, _grid, entrance),
|
_maps.GridTileToLocal(_gridUid, _grid, entrance),
|
||||||
EntitySpawnCollection.GetSpawns(entranceIn.Entries, random));
|
_entTable.GetSpawns(contents, random));
|
||||||
|
|
||||||
|
await SuspendDungeon();
|
||||||
|
|
||||||
|
if (!ValidateResume())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,25 +15,14 @@ public sealed partial class DungeonJob
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<Dungeon> PostGen(
|
private async Task<Dungeon> PostGen(
|
||||||
SplineDungeonConnectorDunGen gen,
|
SplineDungeonConnectorDunGen gen,
|
||||||
DungeonData data,
|
|
||||||
List<Dungeon> dungeons,
|
List<Dungeon> dungeons,
|
||||||
HashSet<Vector2i> reservedTiles,
|
HashSet<Vector2i> reservedTiles,
|
||||||
Random random)
|
Random random)
|
||||||
{
|
{
|
||||||
// TODO: The path itself use the tile
|
|
||||||
// Widen it randomly (probably for each tile offset it by some changing amount).
|
|
||||||
|
|
||||||
// NOOP
|
// NOOP
|
||||||
if (dungeons.Count <= 1)
|
if (dungeons.Count <= 1)
|
||||||
return Dungeon.Empty;
|
return Dungeon.Empty;
|
||||||
|
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var fallback) ||
|
|
||||||
!data.Tiles.TryGetValue(DungeonDataKey.WidenTile, out var widen))
|
|
||||||
{
|
|
||||||
LogDataError(typeof(SplineDungeonConnectorDunGen));
|
|
||||||
return Dungeon.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodes = new List<Vector2i>();
|
var nodes = new List<Vector2i>();
|
||||||
|
|
||||||
foreach (var dungeon in dungeons)
|
foreach (var dungeon in dungeons)
|
||||||
@@ -57,7 +46,8 @@ public sealed partial class DungeonJob
|
|||||||
var tiles = new List<(Vector2i Index, Tile Tile)>();
|
var tiles = new List<(Vector2i Index, Tile Tile)>();
|
||||||
var pathfinding = _entManager.System<PathfindingSystem>();
|
var pathfinding = _entManager.System<PathfindingSystem>();
|
||||||
var allTiles = new HashSet<Vector2i>();
|
var allTiles = new HashSet<Vector2i>();
|
||||||
var fallbackTile = new Tile(_prototype.Index(fallback).TileId);
|
var pathTile = new Tile(_prototype.Index(gen.Tile).TileId);
|
||||||
|
var widen = _prototype.Index(gen.WidenTile ?? gen.Tile);
|
||||||
|
|
||||||
foreach (var pair in tree)
|
foreach (var pair in tree)
|
||||||
{
|
{
|
||||||
@@ -112,7 +102,7 @@ public sealed partial class DungeonJob
|
|||||||
|
|
||||||
if (random.Prob(0.9f))
|
if (random.Prob(0.9f))
|
||||||
{
|
{
|
||||||
tile = new Tile(_prototype.Index(widen).TileId);
|
tile = new Tile(widen.TileId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -132,7 +122,7 @@ public sealed partial class DungeonJob
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
allTiles.Add(node);
|
allTiles.Add(node);
|
||||||
tiles.Add((node, fallbackTile));
|
tiles.Add((node, pathTile));
|
||||||
}
|
}
|
||||||
|
|
||||||
_maps.SetTiles(_gridUid, _grid, tiles);
|
_maps.SetTiles(_gridUid, _grid, tiles);
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Procedural;
|
using Content.Shared.Procedural;
|
||||||
using Content.Shared.Procedural.PostGeneration;
|
using Content.Shared.Procedural.PostGeneration;
|
||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
@@ -11,25 +12,13 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="WallMountDunGen"/>
|
/// <see cref="WallMountDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(WallMountDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(WallMountDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Tried to run {nameof(WallMountDunGen)} without any dungeon data set which is unsupported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tileDef = _prototype.Index(tileProto);
|
|
||||||
if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto))
|
|
||||||
{
|
|
||||||
// caves can have no walls
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var checkedTiles = new HashSet<Vector2i>();
|
var checkedTiles = new HashSet<Vector2i>();
|
||||||
var allExterior = new HashSet<Vector2i>(dungeon.CorridorExteriorTiles);
|
var allExterior = new HashSet<Vector2i>(dungeon.CorridorExteriorTiles);
|
||||||
allExterior.UnionWith(dungeon.RoomExteriorTiles);
|
allExterior.UnionWith(dungeon.RoomExteriorTiles);
|
||||||
var count = 0;
|
var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
|
||||||
|
var contents = _prototype.Index(gen.Contents);
|
||||||
|
|
||||||
foreach (var neighbor in allExterior)
|
foreach (var neighbor in allExterior)
|
||||||
{
|
{
|
||||||
@@ -40,21 +29,18 @@ public sealed partial class DungeonJob
|
|||||||
if (!random.Prob(gen.Prob) || !checkedTiles.Add(neighbor))
|
if (!random.Prob(gen.Prob) || !checkedTiles.Add(neighbor))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (reservedTiles.Contains(neighbor))
|
||||||
|
continue;
|
||||||
|
|
||||||
_maps.SetTile(_gridUid, _grid, neighbor, _tile.GetVariantTile(tileDef, random));
|
_maps.SetTile(_gridUid, _grid, neighbor, _tile.GetVariantTile(tileDef, random));
|
||||||
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, neighbor);
|
var gridPos = _maps.GridTileToLocal(_gridUid, _grid, neighbor);
|
||||||
var protoNames = EntitySpawnCollection.GetSpawns(_prototype.Index(spawnProto).Entries, random);
|
var protoNames = _entTable.GetSpawns(contents, random);
|
||||||
|
|
||||||
_entManager.SpawnEntities(gridPos, protoNames);
|
_entManager.SpawnEntitiesAttachedTo(gridPos, protoNames);
|
||||||
count += protoNames.Count;
|
|
||||||
|
|
||||||
if (count > 20)
|
await SuspendDungeon();
|
||||||
{
|
if (!ValidateResume())
|
||||||
count -= 20;
|
return;
|
||||||
await SuspendDungeon();
|
|
||||||
|
|
||||||
if (!ValidateResume())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Procedural;
|
using Content.Shared.Procedural;
|
||||||
using Content.Shared.Procedural.PostGeneration;
|
using Content.Shared.Procedural.PostGeneration;
|
||||||
using Robust.Shared.Collections;
|
using Robust.Shared.Collections;
|
||||||
@@ -14,19 +15,14 @@ public sealed partial class DungeonJob
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="WormCorridorDunGen"/>
|
/// <see cref="WormCorridorDunGen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PostGen(WormCorridorDunGen gen, DungeonData data, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
private async Task PostGen(WormCorridorDunGen gen, Dungeon dungeon, HashSet<Vector2i> reservedTiles, Random random)
|
||||||
{
|
{
|
||||||
if (!data.Tiles.TryGetValue(DungeonDataKey.FallbackTile, out var tileProto) || !_prototype.TryIndex(tileProto, out var tileDef))
|
|
||||||
{
|
|
||||||
_sawmill.Error($"Tried to run {nameof(WormCorridorDunGen)} without any dungeon data set which is unsupported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var networks = new List<(Vector2i Start, HashSet<Vector2i> Network)>();
|
var networks = new List<(Vector2i Start, HashSet<Vector2i> Network)>();
|
||||||
|
|
||||||
// List of places to start from.
|
// List of places to start from.
|
||||||
var worm = new ValueList<Vector2i>();
|
var worm = new ValueList<Vector2i>();
|
||||||
var startAngles = new Dictionary<Vector2i, Angle>();
|
var startAngles = new Dictionary<Vector2i, Angle>();
|
||||||
|
var tileDef = (ContentTileDefinition) _tileDefManager[gen.Tile];
|
||||||
|
|
||||||
foreach (var room in dungeon.Rooms)
|
foreach (var room in dungeon.Rooms)
|
||||||
{
|
{
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Decals;
|
using Content.Server.Decals;
|
||||||
@@ -6,6 +7,7 @@ using Content.Server.NPC.HTN;
|
|||||||
using Content.Server.NPC.Systems;
|
using Content.Server.NPC.Systems;
|
||||||
using Content.Server.Shuttles.Systems;
|
using Content.Server.Shuttles.Systems;
|
||||||
using Content.Shared.Construction.EntitySystems;
|
using Content.Shared.Construction.EntitySystems;
|
||||||
|
using Content.Shared.EntityTable;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Procedural;
|
using Content.Shared.Procedural;
|
||||||
using Content.Shared.Procedural.DungeonGenerators;
|
using Content.Shared.Procedural.DungeonGenerators;
|
||||||
@@ -37,6 +39,7 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
private readonly DecalSystem _decals;
|
private readonly DecalSystem _decals;
|
||||||
private readonly DungeonSystem _dungeon;
|
private readonly DungeonSystem _dungeon;
|
||||||
private readonly EntityLookupSystem _lookup;
|
private readonly EntityLookupSystem _lookup;
|
||||||
|
private readonly EntityTableSystem _entTable;
|
||||||
private readonly TagSystem _tags;
|
private readonly TagSystem _tags;
|
||||||
private readonly TileSystem _tile;
|
private readonly TileSystem _tile;
|
||||||
private readonly SharedMapSystem _maps;
|
private readonly SharedMapSystem _maps;
|
||||||
@@ -88,6 +91,7 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
_tile = tile;
|
_tile = tile;
|
||||||
_tags = _entManager.System<TagSystem>();
|
_tags = _entManager.System<TagSystem>();
|
||||||
_maps = _entManager.System<SharedMapSystem>();
|
_maps = _entManager.System<SharedMapSystem>();
|
||||||
|
_entTable = _entManager.System<EntityTableSystem>();
|
||||||
_transform = transform;
|
_transform = transform;
|
||||||
|
|
||||||
_physicsQuery = _entManager.GetEntityQuery<PhysicsComponent>();
|
_physicsQuery = _entManager.GetEntityQuery<PhysicsComponent>();
|
||||||
@@ -108,13 +112,20 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
private async Task<List<Dungeon>> GetDungeons(
|
private async Task<List<Dungeon>> GetDungeons(
|
||||||
Vector2i position,
|
Vector2i position,
|
||||||
DungeonConfig config,
|
DungeonConfig config,
|
||||||
DungeonData data,
|
|
||||||
List<IDunGenLayer> layers,
|
List<IDunGenLayer> layers,
|
||||||
HashSet<Vector2i> reservedTiles,
|
HashSet<Vector2i> reservedTiles,
|
||||||
int seed,
|
int seed,
|
||||||
Random random)
|
Random random,
|
||||||
|
List<Dungeon>? existing = null)
|
||||||
{
|
{
|
||||||
var dungeons = new List<Dungeon>();
|
var dungeons = new List<Dungeon>();
|
||||||
|
|
||||||
|
// Don't pass dungeons back up the "stack". They are ref types though it's a caller problem if they start trying to mutate it.
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
dungeons.AddRange(existing);
|
||||||
|
}
|
||||||
|
|
||||||
var count = random.Next(config.MinCount, config.MaxCount + 1);
|
var count = random.Next(config.MinCount, config.MaxCount + 1);
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
@@ -123,10 +134,25 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
|
|
||||||
foreach (var layer in layers)
|
foreach (var layer in layers)
|
||||||
{
|
{
|
||||||
await RunLayer(dungeons, data, position, layer, reservedTiles, seed, random);
|
await RunLayer(dungeons, position, layer, reservedTiles, seed, random);
|
||||||
|
|
||||||
if (config.ReserveTiles)
|
if (config.ReserveTiles)
|
||||||
{
|
{
|
||||||
|
// Remove any dungeons passed in so we don't interfere with them
|
||||||
|
// This is kinda goofy but okay for now.
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < dungeons.Count; j++)
|
||||||
|
{
|
||||||
|
var dung = dungeons[j];
|
||||||
|
|
||||||
|
if (existing.Contains(dung))
|
||||||
|
{
|
||||||
|
dungeons.RemoveSwap(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var dungeon in dungeons)
|
foreach (var dungeon in dungeons)
|
||||||
{
|
{
|
||||||
reservedTiles.UnionWith(dungeon.AllTiles);
|
reservedTiles.UnionWith(dungeon.AllTiles);
|
||||||
@@ -152,7 +178,7 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
// Tiles we can no longer generate on due to being reserved elsewhere.
|
// Tiles we can no longer generate on due to being reserved elsewhere.
|
||||||
var reservedTiles = new HashSet<Vector2i>();
|
var reservedTiles = new HashSet<Vector2i>();
|
||||||
|
|
||||||
var dungeons = await GetDungeons(position, _gen, _gen.Data, _gen.Layers, reservedTiles, _seed, random);
|
var dungeons = await GetDungeons(position, _gen, _gen.Layers, reservedTiles, _seed, random);
|
||||||
// To make it slightly more deterministic treat this RNG as separate ig.
|
// To make it slightly more deterministic treat this RNG as separate ig.
|
||||||
|
|
||||||
// Post-processing after finishing loading.
|
// Post-processing after finishing loading.
|
||||||
@@ -181,7 +207,6 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
|
|
||||||
private async Task RunLayer(
|
private async Task RunLayer(
|
||||||
List<Dungeon> dungeons,
|
List<Dungeon> dungeons,
|
||||||
DungeonData data,
|
|
||||||
Vector2i position,
|
Vector2i position,
|
||||||
IDunGenLayer layer,
|
IDunGenLayer layer,
|
||||||
HashSet<Vector2i> reservedTiles,
|
HashSet<Vector2i> reservedTiles,
|
||||||
@@ -200,52 +225,52 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
switch (layer)
|
switch (layer)
|
||||||
{
|
{
|
||||||
case AutoCablingDunGen cabling:
|
case AutoCablingDunGen cabling:
|
||||||
await PostGen(cabling, data, dungeons[^1], reservedTiles, random);
|
await PostGen(cabling, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case BiomeMarkerLayerDunGen markerPost:
|
case BiomeMarkerLayerDunGen markerPost:
|
||||||
await PostGen(markerPost, data, dungeons[^1], reservedTiles, random);
|
await PostGen(markerPost, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case BiomeDunGen biome:
|
case BiomeDunGen biome:
|
||||||
await PostGen(biome, data, dungeons[^1], reservedTiles, random);
|
await PostGen(biome, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case BoundaryWallDunGen boundary:
|
case BoundaryWallDunGen boundary:
|
||||||
await PostGen(boundary, data, dungeons[^1], reservedTiles, random);
|
await PostGen(boundary, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case CornerClutterDunGen clutter:
|
case CornerClutterDunGen clutter:
|
||||||
await PostGen(clutter, data, dungeons[^1], reservedTiles, random);
|
await PostGen(clutter, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case CorridorClutterDunGen corClutter:
|
case CorridorClutterDunGen corClutter:
|
||||||
await PostGen(corClutter, data, dungeons[^1], reservedTiles, random);
|
await PostGen(corClutter, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case CorridorDunGen cordor:
|
case CorridorDunGen cordor:
|
||||||
await PostGen(cordor, data, dungeons[^1], reservedTiles, random);
|
await PostGen(cordor, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case CorridorDecalSkirtingDunGen decks:
|
case CorridorDecalSkirtingDunGen decks:
|
||||||
await PostGen(decks, data, dungeons[^1], reservedTiles, random);
|
await PostGen(decks, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case EntranceFlankDunGen flank:
|
case EntranceFlankDunGen flank:
|
||||||
await PostGen(flank, data, dungeons[^1], reservedTiles, random);
|
await PostGen(flank, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case ExteriorDunGen exterior:
|
case ExteriorDunGen exterior:
|
||||||
dungeons.AddRange(await GenerateExteriorDungen(position, exterior, reservedTiles, random));
|
dungeons.AddRange(await GenerateExteriorDungen(position, exterior, reservedTiles, random));
|
||||||
break;
|
break;
|
||||||
case FillGridDunGen fill:
|
case FillGridDunGen fill:
|
||||||
dungeons.Add(await GenerateFillDunGen(fill, data, reservedTiles));
|
await GenerateFillDunGen(fill, dungeons, reservedTiles);
|
||||||
break;
|
break;
|
||||||
case JunctionDunGen junc:
|
case JunctionDunGen junc:
|
||||||
await PostGen(junc, data, dungeons[^1], reservedTiles, random);
|
await PostGen(junc, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case MiddleConnectionDunGen dordor:
|
case MiddleConnectionDunGen dordor:
|
||||||
await PostGen(dordor, data, dungeons[^1], reservedTiles, random);
|
await PostGen(dordor, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case DungeonEntranceDunGen entrance:
|
case DungeonEntranceDunGen entrance:
|
||||||
await PostGen(entrance, data, dungeons[^1], reservedTiles, random);
|
await PostGen(entrance, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case ExternalWindowDunGen externalWindow:
|
case ExternalWindowDunGen externalWindow:
|
||||||
await PostGen(externalWindow, data, dungeons[^1], reservedTiles, random);
|
await PostGen(externalWindow, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case InternalWindowDunGen internalWindow:
|
case InternalWindowDunGen internalWindow:
|
||||||
await PostGen(internalWindow, data, dungeons[^1], reservedTiles, random);
|
await PostGen(internalWindow, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case MobsDunGen mob:
|
case MobsDunGen mob:
|
||||||
await PostGen(mob, dungeons[^1], random);
|
await PostGen(mob, dungeons[^1], random);
|
||||||
@@ -263,31 +288,40 @@ public sealed partial class DungeonJob : Job<List<Dungeon>>
|
|||||||
await PostGen(ore, dungeons[^1], random);
|
await PostGen(ore, dungeons[^1], random);
|
||||||
break;
|
break;
|
||||||
case PrefabDunGen prefab:
|
case PrefabDunGen prefab:
|
||||||
dungeons.Add(await GeneratePrefabDunGen(position, data, prefab, reservedTiles, random));
|
dungeons.Add(await GeneratePrefabDunGen(position, prefab, reservedTiles, random));
|
||||||
break;
|
break;
|
||||||
case PrototypeDunGen prototypo:
|
case PrototypeDunGen prototypo:
|
||||||
var groupConfig = _prototype.Index(prototypo.Proto);
|
var groupConfig = _prototype.Index(prototypo.Proto);
|
||||||
position = (position + random.NextPolarVector2(groupConfig.MinOffset, groupConfig.MaxOffset)).Floored();
|
position = (position + random.NextPolarVector2(groupConfig.MinOffset, groupConfig.MaxOffset)).Floored();
|
||||||
|
|
||||||
var dataCopy = groupConfig.Data.Clone();
|
switch (prototypo.InheritDungeons)
|
||||||
dataCopy.Apply(data);
|
{
|
||||||
|
case DungeonInheritance.All:
|
||||||
|
dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random, existing: dungeons));
|
||||||
|
break;
|
||||||
|
case DungeonInheritance.Last:
|
||||||
|
dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random, existing: dungeons.GetRange(dungeons.Count - 1, 1)));
|
||||||
|
break;
|
||||||
|
case DungeonInheritance.None:
|
||||||
|
dungeons.AddRange(await GetDungeons(position, groupConfig, groupConfig.Layers, reservedTiles, seed, random));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dungeons.AddRange(await GetDungeons(position, groupConfig, dataCopy, groupConfig.Layers, reservedTiles, seed, random));
|
|
||||||
break;
|
break;
|
||||||
case ReplaceTileDunGen replace:
|
case ReplaceTileDunGen replace:
|
||||||
dungeons.Add(await GenerateTileReplacementDunGen(replace, data, reservedTiles, random));
|
await GenerateTileReplacementDunGen(replace, dungeons, reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case RoomEntranceDunGen rEntrance:
|
case RoomEntranceDunGen rEntrance:
|
||||||
await PostGen(rEntrance, data, dungeons[^1], reservedTiles, random);
|
await PostGen(rEntrance, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case SplineDungeonConnectorDunGen spline:
|
case SplineDungeonConnectorDunGen spline:
|
||||||
dungeons.Add(await PostGen(spline, data, dungeons, reservedTiles, random));
|
dungeons.Add(await PostGen(spline, dungeons, reservedTiles, random));
|
||||||
break;
|
break;
|
||||||
case WallMountDunGen wall:
|
case WallMountDunGen wall:
|
||||||
await PostGen(wall, data, dungeons[^1], reservedTiles, random);
|
await PostGen(wall, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
case WormCorridorDunGen worm:
|
case WormCorridorDunGen worm:
|
||||||
await PostGen(worm, data, dungeons[^1], reservedTiles, random);
|
await PostGen(worm, dungeons[^1], reservedTiles, random);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ public sealed class EntityTableSystem : EntitySystem
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
public IEnumerable<EntProtoId> GetSpawns(EntityTablePrototype entTableProto, System.Random? rand = null)
|
||||||
|
{
|
||||||
|
// convenient
|
||||||
|
return GetSpawns(entTableProto.Table, rand);
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<EntProtoId> GetSpawns(EntityTableSelector? table, System.Random? rand = null)
|
public IEnumerable<EntProtoId> GetSpawns(EntityTableSelector? table, System.Random? rand = null)
|
||||||
{
|
{
|
||||||
if (table == null)
|
if (table == null)
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ namespace Content.Shared.Procedural;
|
|||||||
[Virtual, DataDefinition]
|
[Virtual, DataDefinition]
|
||||||
public partial class DungeonConfig
|
public partial class DungeonConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// <see cref="Data"/>
|
|
||||||
/// </summary>
|
|
||||||
[DataField]
|
|
||||||
public DungeonData Data = DungeonData.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The secret sauce, procedural generation layers that get run.
|
/// The secret sauce, procedural generation layers that get run.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Maps;
|
|
||||||
using Content.Shared.Storage;
|
|
||||||
using Content.Shared.Whitelist;
|
|
||||||
using Robust.Shared.Prototypes;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
|
|
||||||
namespace Content.Shared.Procedural;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used to set dungeon values for all layers.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This lets us share data between different dungeon configs without having to repeat entire configs.
|
|
||||||
/// </remarks>
|
|
||||||
[DataRecord]
|
|
||||||
public sealed partial class DungeonData
|
|
||||||
{
|
|
||||||
// I hate this but it also significantly reduces yaml bloat if we add like 10 variations on the same set of layers
|
|
||||||
// e.g. science rooms, engi rooms, cargo rooms all under PlanetBase for example.
|
|
||||||
// without having to do weird nesting. It also means we don't need to copy-paste the same prototype across several layers
|
|
||||||
// The alternative is doing like,
|
|
||||||
// 2 layer prototype, 1 layer with the specified data, 3 layer prototype, 2 layers with specified data, etc.
|
|
||||||
// As long as we just keep the code clean over time it won't be bad to maintain.
|
|
||||||
|
|
||||||
public static DungeonData Empty = new();
|
|
||||||
|
|
||||||
public Dictionary<DungeonDataKey, Color> Colors = new();
|
|
||||||
public Dictionary<DungeonDataKey, EntProtoId> Entities = new();
|
|
||||||
public Dictionary<DungeonDataKey, ProtoId<EntitySpawnEntryPrototype>> SpawnGroups = new();
|
|
||||||
public Dictionary<DungeonDataKey, ProtoId<ContentTileDefinition>> Tiles = new();
|
|
||||||
public Dictionary<DungeonDataKey, EntityWhitelist> Whitelists = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies the specified data to this data.
|
|
||||||
/// </summary>
|
|
||||||
public void Apply(DungeonData data)
|
|
||||||
{
|
|
||||||
// Copy-paste moment.
|
|
||||||
foreach (var color in data.Colors)
|
|
||||||
{
|
|
||||||
Colors[color.Key] = color.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var color in data.Entities)
|
|
||||||
{
|
|
||||||
Entities[color.Key] = color.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var color in data.SpawnGroups)
|
|
||||||
{
|
|
||||||
SpawnGroups[color.Key] = color.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var color in data.Tiles)
|
|
||||||
{
|
|
||||||
Tiles[color.Key] = color.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var color in data.Whitelists)
|
|
||||||
{
|
|
||||||
Whitelists[color.Key] = color.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DungeonData Clone()
|
|
||||||
{
|
|
||||||
return new DungeonData
|
|
||||||
{
|
|
||||||
// Only shallow clones but won't matter for DungeonJob purposes.
|
|
||||||
Colors = Colors.ShallowClone(),
|
|
||||||
Entities = Entities.ShallowClone(),
|
|
||||||
SpawnGroups = SpawnGroups.ShallowClone(),
|
|
||||||
Tiles = Tiles.ShallowClone(),
|
|
||||||
Whitelists = Whitelists.ShallowClone(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DungeonDataKey : byte
|
|
||||||
{
|
|
||||||
// Colors
|
|
||||||
Decals,
|
|
||||||
|
|
||||||
// Entities
|
|
||||||
Cabling,
|
|
||||||
CornerWalls,
|
|
||||||
Fill,
|
|
||||||
Junction,
|
|
||||||
Walls,
|
|
||||||
|
|
||||||
// SpawnGroups
|
|
||||||
CornerClutter,
|
|
||||||
Entrance,
|
|
||||||
EntranceFlank,
|
|
||||||
WallMounts,
|
|
||||||
Window,
|
|
||||||
|
|
||||||
// Tiles
|
|
||||||
FallbackTile,
|
|
||||||
WidenTile,
|
|
||||||
|
|
||||||
// Whitelists
|
|
||||||
Rooms,
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||||
@@ -6,10 +8,6 @@ namespace Content.Shared.Procedural.DungeonGenerators;
|
|||||||
/// Places rooms in pre-selected pack layouts. Chooses rooms from the specified whitelist.
|
/// Places rooms in pre-selected pack layouts. Chooses rooms from the specified whitelist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// DungeonData keys are:
|
|
||||||
/// - FallbackTile
|
|
||||||
/// - Rooms
|
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class PrefabDunGen : IDunGenLayer
|
public sealed partial class PrefabDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -17,4 +15,10 @@ public sealed partial class PrefabDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public List<ProtoId<DungeonPresetPrototype>> Presets = new();
|
public List<ProtoId<DungeonPresetPrototype>> Presets = new();
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public EntityWhitelist? RoomWhitelist;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<ContentTileDefinition>? FallbackTile;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,30 @@ namespace Content.Shared.Procedural.DungeonGenerators;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class PrototypeDunGen : IDunGenLayer
|
public sealed partial class PrototypeDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Should we pass in the current level's dungeons to the prototype.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public DungeonInheritance InheritDungeons = DungeonInheritance.None;
|
||||||
|
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public ProtoId<DungeonConfigPrototype> Proto;
|
public ProtoId<DungeonConfigPrototype> Proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum DungeonInheritance : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Don't inherit any of the current layer's dungeons for this <see cref="PrototypeDunGen"/>
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inherit only the last dungeon ran.
|
||||||
|
/// </summary>
|
||||||
|
Last,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inherit all of the current layer's dungeons.
|
||||||
|
/// </summary>
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
namespace Content.Shared.Procedural.DungeonLayers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills unreserved tiles with the specified entity prototype.
|
/// Fills unreserved tiles with the specified entity prototype.
|
||||||
@@ -17,4 +17,7 @@ public sealed partial class FillGridDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public HashSet<ProtoId<ContentTileDefinition>>? AllowedTiles;
|
public HashSet<ProtoId<ContentTileDefinition>>? AllowedTiles;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId Entity;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.DungeonLayers;
|
namespace Content.Shared.Procedural.DungeonLayers;
|
||||||
|
|
||||||
@@ -17,5 +19,5 @@ public sealed partial class MobsDunGen : IDunGenLayer
|
|||||||
public int MaxCount = 1;
|
public int MaxCount = 1;
|
||||||
|
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public List<EntitySpawnEntry> Groups = new();
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Parallax.Biomes;
|
using Content.Shared.Parallax.Biomes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.Loot;
|
namespace Content.Shared.Procedural.Loot;
|
||||||
@@ -8,6 +9,6 @@ namespace Content.Shared.Procedural.Loot;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class BiomeTemplateLoot : IDungeonLoot
|
public sealed partial class BiomeTemplateLoot : IDungeonLoot
|
||||||
{
|
{
|
||||||
[DataField("proto", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<BiomeTemplatePrototype>))]
|
[DataField("proto", required: true)]
|
||||||
public string Prototype = string.Empty;
|
public ProtoId<BiomeTemplatePrototype> Prototype = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs cables throughout the dungeon.
|
/// Runs cables throughout the dungeon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public sealed partial class AutoCablingDunGen : IDunGenLayer
|
||||||
/// DungeonData keys are:
|
{
|
||||||
/// - Cabling
|
[DataField(required: true)]
|
||||||
/// </remarks>
|
public EntProtoId Entity;
|
||||||
public sealed partial class AutoCablingDunGen : IDunGenLayer;
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -13,6 +16,15 @@ public sealed partial class BoundaryWallDunGen : IDunGenLayer
|
|||||||
{
|
{
|
||||||
[DataField]
|
[DataField]
|
||||||
public BoundaryWallFlags Flags = BoundaryWallFlags.Corridors | BoundaryWallFlags.Rooms;
|
public BoundaryWallFlags Flags = BoundaryWallFlags.Corridors | BoundaryWallFlags.Rooms;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId Wall;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId? CornerWall;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spawns entities inside corners.
|
/// Spawns entities inside corners.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// Dungeon data keys are:
|
|
||||||
/// - CornerClutter
|
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class CornerClutterDunGen : IDunGenLayer
|
public sealed partial class CornerClutterDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
[DataField]
|
[DataField]
|
||||||
public float Chance = 0.50f;
|
public float Chance = 0.50f;
|
||||||
|
|
||||||
|
[DataField(required:true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
using Content.Shared.Storage;
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
@@ -14,5 +16,5 @@ public sealed partial class CorridorClutterDunGen : IDunGenLayer
|
|||||||
/// The default starting bulbs
|
/// The default starting bulbs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
public List<EntitySpawnEntry> Contents = new();
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using Content.Shared.Decals;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,4 +22,10 @@ public sealed partial class CorridorDecalSkirtingDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public Dictionary<DirectionFlag, string> CornerDecals = new();
|
public Dictionary<DirectionFlag, string> CornerDecals = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional color to apply to the decals.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public Color? Color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connects room entrances via corridor segments.
|
/// Connects room entrances via corridor segments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// Dungeon data keys are:
|
|
||||||
/// - FallbackTile
|
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class CorridorDunGen : IDunGenLayer
|
public sealed partial class CorridorDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -23,4 +22,7 @@ public sealed partial class CorridorDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public float Width = 3f;
|
public float Width = 3f;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Selects [count] rooms and places external doors to them.
|
/// Selects [count] rooms and places external doors to them.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// Dungeon data keys are:
|
|
||||||
/// - Entrance
|
|
||||||
/// - FallbackTile
|
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class DungeonEntranceDunGen : IDunGenLayer
|
public sealed partial class DungeonEntranceDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,4 +15,10 @@ public sealed partial class DungeonEntranceDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public int Count = 1;
|
public int Count = 1;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spawns entities on either side of an entrance.
|
/// Spawns entities on either side of an entrance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public sealed partial class EntranceFlankDunGen : IDunGenLayer
|
||||||
/// Dungeon data keys are:
|
{
|
||||||
/// - FallbackTile
|
[DataField(required: true)]
|
||||||
/// -
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class EntranceFlankDunGen : IDunGenLayer;
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents = new();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If external areas are found will try to generate windows.
|
/// If external areas are found will try to generate windows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public sealed partial class ExternalWindowDunGen : IDunGenLayer
|
||||||
/// Dungeon data keys are:
|
{
|
||||||
/// - EntranceFlank
|
[DataField(required: true)]
|
||||||
/// - FallbackTile
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class ExternalWindowDunGen : IDunGenLayer;
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If internal areas are found will try to generate windows.
|
/// If internal areas are found will try to generate windows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public sealed partial class InternalWindowDunGen : IDunGenLayer
|
||||||
/// Dungeon data keys are:
|
{
|
||||||
/// - FallbackTile
|
[DataField(required: true)]
|
||||||
/// - Window
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class InternalWindowDunGen : IDunGenLayer;
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Places the specified entities at junction areas.
|
/// Places the specified entities at junction areas.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// Dungeon data keys are:
|
|
||||||
/// - Entrance
|
|
||||||
/// - FallbackTile
|
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class JunctionDunGen : IDunGenLayer
|
public sealed partial class JunctionDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,4 +15,10 @@ public sealed partial class JunctionDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public int Width = 3;
|
public int Width = 3;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -16,4 +21,13 @@ public sealed partial class MiddleConnectionDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public int Count = 1;
|
public int Count = 1;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<EntityTablePrototype>? Flank;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Places tiles / entities onto room entrances.
|
/// Places tiles / entities onto room entrances.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
public sealed partial class RoomEntranceDunGen : IDunGenLayer
|
||||||
/// DungeonData keys are:
|
{
|
||||||
/// - Entrance
|
[DataField(required: true)]
|
||||||
/// - FallbackTile
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
/// </remarks>
|
|
||||||
public sealed partial class RoomEntranceDunGen : IDunGenLayer;
|
[DataField]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -5,6 +8,12 @@ namespace Content.Shared.Procedural.PostGeneration;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
|
public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
|
||||||
{
|
{
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<ContentTileDefinition>? WidenTile;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will divide the distance between the start and end points so that no subdivision is more than these metres away.
|
/// Will divide the distance between the start and end points so that no subdivision is more than these metres away.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
using Content.Shared.EntityTable;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Storage;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -10,4 +15,10 @@ public sealed partial class WallMountDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public double Prob = 0.1;
|
public double Prob = 0.1;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<EntityTablePrototype> Contents;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Procedural.PostGeneration;
|
namespace Content.Shared.Procedural.PostGeneration;
|
||||||
|
|
||||||
// Ime a worm
|
// Ime a worm
|
||||||
@@ -32,4 +35,7 @@ public sealed partial class WormCorridorDunGen : IDunGenLayer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public float Width = 3f;
|
public float Width = 3f;
|
||||||
|
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<ContentTileDefinition> Tile;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,12 +50,8 @@ public abstract partial class SharedSalvageSystem
|
|||||||
var configProto =_proto.Index(configId);
|
var configProto =_proto.Index(configId);
|
||||||
var layers = new Dictionary<string, int>();
|
var layers = new Dictionary<string, int>();
|
||||||
|
|
||||||
var data = new DungeonData();
|
|
||||||
data.Apply(configProto.Data);
|
|
||||||
|
|
||||||
var config = new DungeonConfig
|
var config = new DungeonConfig
|
||||||
{
|
{
|
||||||
Data = data,
|
|
||||||
Layers = new(configProto.Layers),
|
Layers = new(configProto.Layers),
|
||||||
MaxCount = configProto.MaxCount,
|
MaxCount = configProto.MaxCount,
|
||||||
MaxOffset = configProto.MaxOffset,
|
MaxOffset = configProto.MaxOffset,
|
||||||
|
|||||||
@@ -76,6 +76,18 @@ public static class EntitySpawnCollection
|
|||||||
public float CumulativeProbability { get; set; } = 0f;
|
public float CumulativeProbability { get; set; } = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<string> GetSpawns(ProtoId<EntitySpawnEntryPrototype> proto, IPrototypeManager? protoManager = null, IRobustRandom? random = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref protoManager, ref random);
|
||||||
|
return GetSpawns(protoManager.Index(proto).Entries, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<string?> GetSpawns(ProtoId<EntitySpawnEntryPrototype> proto, System.Random random, IPrototypeManager? protoManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref protoManager);
|
||||||
|
return GetSpawns(protoManager.Index(proto).Entries, random);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Using a collection of entity spawn entries, picks a random list of entity prototypes to spawn from that collection.
|
/// Using a collection of entity spawn entries, picks a random list of entity prototypes to spawn from that collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
# Base configs
|
# Setups
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: PlanetBase
|
id: Experiment
|
||||||
layers:
|
layers:
|
||||||
- !type:PrefabDunGen
|
- !type:PrefabDunGen
|
||||||
|
roomWhitelist:
|
||||||
|
tags:
|
||||||
|
- SalvageExperiment
|
||||||
presets:
|
presets:
|
||||||
- Bucket
|
- Bucket
|
||||||
- Wow
|
- Wow
|
||||||
@@ -11,28 +14,49 @@
|
|||||||
|
|
||||||
- !type:CorridorDunGen
|
- !type:CorridorDunGen
|
||||||
width: 3
|
width: 3
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
- !type:DungeonEntranceDunGen
|
- !type:DungeonEntranceDunGen
|
||||||
count: 2
|
count: 2
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
- !type:RoomEntranceDunGen
|
- !type:RoomEntranceDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
- !type:EntranceFlankDunGen
|
- !type:EntranceFlankDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
- !type:ExternalWindowDunGen
|
- !type:ExternalWindowDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
- !type:WallMountDunGen
|
- !type:WallMountDunGen
|
||||||
|
contents: ScienceLabsWalls
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
- !type:BoundaryWallDunGen
|
- !type:BoundaryWallDunGen
|
||||||
|
wall: WallSolid
|
||||||
|
cornerWall: WallReinforced
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
- !type:JunctionDunGen
|
- !type:JunctionDunGen
|
||||||
width: 1
|
width: 1
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
- !type:JunctionDunGen
|
- !type:JunctionDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
- !type:AutoCablingDunGen
|
- !type:AutoCablingDunGen
|
||||||
|
entity: CableApcExtension
|
||||||
|
|
||||||
- !type:CornerClutterDunGen
|
- !type:CornerClutterDunGen
|
||||||
|
contents: BaseClutter
|
||||||
|
|
||||||
- !type:CorridorDecalSkirtingDunGen
|
- !type:CorridorDecalSkirtingDunGen
|
||||||
cardinalDecals:
|
cardinalDecals:
|
||||||
@@ -51,44 +75,8 @@
|
|||||||
NorthWest: BrickTileWhiteInnerNw
|
NorthWest: BrickTileWhiteInnerNw
|
||||||
NorthEast: BrickTileWhiteInnerNe
|
NorthEast: BrickTileWhiteInnerNe
|
||||||
|
|
||||||
# Setups
|
|
||||||
- type: dungeonConfig
|
|
||||||
id: Experiment
|
|
||||||
data:
|
|
||||||
colors:
|
|
||||||
Decals: "#D381C996"
|
|
||||||
entities:
|
|
||||||
Cabling: CableApcExtension
|
|
||||||
CornerWalls: WallReinforced
|
|
||||||
Walls: WallSolid
|
|
||||||
spawnGroups:
|
|
||||||
CornerClutter: BaseClutter
|
|
||||||
Entrance: BaseAirlock
|
|
||||||
EntranceFlank: BaseWindow
|
|
||||||
Junction: BaseAirlock
|
|
||||||
WallMounts: ScienceLabsWalls
|
|
||||||
Window: BaseWindow
|
|
||||||
tiles:
|
|
||||||
FallbackTile: FloorSteel
|
|
||||||
whitelists:
|
|
||||||
Rooms:
|
|
||||||
tags:
|
|
||||||
- SalvageExperiment
|
|
||||||
layers:
|
|
||||||
- !type:PrototypeDunGen
|
|
||||||
proto: PlanetBase
|
|
||||||
|
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: Haunted
|
id: Haunted
|
||||||
data:
|
|
||||||
entities:
|
|
||||||
Walls: WallRock
|
|
||||||
tiles:
|
|
||||||
FallbackTile: FloorCaveDrought
|
|
||||||
whitelists:
|
|
||||||
Rooms:
|
|
||||||
tags:
|
|
||||||
- Mineshaft
|
|
||||||
layers:
|
layers:
|
||||||
- !type:PrefabDunGen
|
- !type:PrefabDunGen
|
||||||
presets:
|
presets:
|
||||||
@@ -99,183 +87,304 @@
|
|||||||
|
|
||||||
- !type:WormCorridorDunGen
|
- !type:WormCorridorDunGen
|
||||||
width: 3
|
width: 3
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
|
||||||
- !type:CorridorClutterDunGen
|
- !type:CorridorClutterDunGen
|
||||||
contents:
|
contents: HauntedClutter
|
||||||
- id: FloraStalagmite
|
|
||||||
|
|
||||||
- !type:BoundaryWallDunGen
|
- !type:BoundaryWallDunGen
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
wall: WallRock
|
||||||
|
|
||||||
|
- type: entityTable
|
||||||
|
id: HauntedClutter
|
||||||
|
table: !type:GroupSelector
|
||||||
|
children:
|
||||||
|
- id: FloraStalagmite
|
||||||
|
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: LavaBrig
|
id: LavaBrig
|
||||||
data:
|
|
||||||
colors:
|
|
||||||
Decals: "#DE3A3A96"
|
|
||||||
entities:
|
|
||||||
Cabling: CableApcExtension
|
|
||||||
CornerWalls: WallReinforced
|
|
||||||
Walls: WallSolid
|
|
||||||
spawnGroups:
|
|
||||||
CornerClutter: BaseClutter
|
|
||||||
Entrance: LavaBrigEntrance
|
|
||||||
EntranceFlank: BaseWindow
|
|
||||||
Junction: BaseAirlock
|
|
||||||
WallMounts: ScienceLabsWalls
|
|
||||||
Window: BaseWindow
|
|
||||||
tiles:
|
|
||||||
FallbackTile: FloorDark
|
|
||||||
whitelists:
|
|
||||||
Rooms:
|
|
||||||
tags:
|
|
||||||
- LavaBrig
|
|
||||||
layers:
|
layers:
|
||||||
- !type:PrototypeDunGen
|
- !type:PrefabDunGen
|
||||||
proto: PlanetBase
|
roomWhitelist:
|
||||||
|
tags:
|
||||||
|
- LavaBrig
|
||||||
|
presets:
|
||||||
|
- Bucket
|
||||||
|
- Wow
|
||||||
|
- SpaceShip
|
||||||
|
- Tall
|
||||||
|
|
||||||
|
- !type:CorridorDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorDark
|
||||||
|
|
||||||
|
- !type:DungeonEntranceDunGen
|
||||||
|
count: 2
|
||||||
|
tile: FloorDark
|
||||||
|
contents: LavaBrigEntrance
|
||||||
|
|
||||||
|
- !type:RoomEntranceDunGen
|
||||||
|
tile: FloorDark
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:EntranceFlankDunGen
|
||||||
|
tile: FloorDark
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
|
- !type:ExternalWindowDunGen
|
||||||
|
tile: FloorDark
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
|
- !type:WallMountDunGen
|
||||||
|
contents: ScienceLabsWalls
|
||||||
|
tile: FloorDark
|
||||||
|
|
||||||
|
- !type:BoundaryWallDunGen
|
||||||
|
wall: WallSolid
|
||||||
|
cornerWall: WallReinforced
|
||||||
|
tile: FloorDark
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 1
|
||||||
|
tile: FloorDark
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorDark
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:AutoCablingDunGen
|
||||||
|
entity: CableApcExtension
|
||||||
|
|
||||||
|
- !type:CornerClutterDunGen
|
||||||
|
contents: BaseClutter
|
||||||
|
|
||||||
|
- !type:CorridorDecalSkirtingDunGen
|
||||||
|
cardinalDecals:
|
||||||
|
South: BrickTileWhiteLineS
|
||||||
|
East: BrickTileWhiteLineE
|
||||||
|
North: BrickTileWhiteLineN
|
||||||
|
West: BrickTileWhiteLineW
|
||||||
|
cornerDecals:
|
||||||
|
SouthEast: BrickTileWhiteCornerSe
|
||||||
|
SouthWest: BrickTileWhiteCornerSw
|
||||||
|
NorthEast: BrickTileWhiteCornerNe
|
||||||
|
NorthWest: BrickTileWhiteCornerNw
|
||||||
|
pocketDecals:
|
||||||
|
SouthWest: BrickTileWhiteInnerSw
|
||||||
|
SouthEast: BrickTileWhiteInnerSe
|
||||||
|
NorthWest: BrickTileWhiteInnerNw
|
||||||
|
NorthEast: BrickTileWhiteInnerNe
|
||||||
|
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: Mineshaft
|
id: Mineshaft
|
||||||
data:
|
|
||||||
entities:
|
|
||||||
Cabling: Catwalk
|
|
||||||
spawnGroups:
|
|
||||||
CornerClutter: MineshaftClutter
|
|
||||||
Entrance: BaseWoodWall
|
|
||||||
EntranceFlank: BaseWoodWall
|
|
||||||
Junction: BaseWoodSupport
|
|
||||||
Window: BaseWoodWall
|
|
||||||
tiles:
|
|
||||||
FallbackTile: FloorCaveDrought
|
|
||||||
whitelists:
|
|
||||||
Rooms:
|
|
||||||
tags:
|
|
||||||
- Mineshaft
|
|
||||||
layers:
|
layers:
|
||||||
- !type:PrototypeDunGen
|
- !type:PrefabDunGen
|
||||||
proto: PlanetBase
|
roomWhitelist:
|
||||||
|
tags:
|
||||||
|
- Mineshaft
|
||||||
|
presets:
|
||||||
|
- Bucket
|
||||||
|
- Wow
|
||||||
|
- SpaceShip
|
||||||
|
- Tall
|
||||||
|
|
||||||
|
- !type:CorridorDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
|
||||||
|
- !type:DungeonEntranceDunGen
|
||||||
|
count: 2
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodWall
|
||||||
|
|
||||||
|
- !type:RoomEntranceDunGen
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodWall
|
||||||
|
|
||||||
|
- !type:EntranceFlankDunGen
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodWall
|
||||||
|
|
||||||
|
- !type:ExternalWindowDunGen
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodWall
|
||||||
|
|
||||||
|
# No wallmounts
|
||||||
|
|
||||||
|
# No boundary wall
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 1
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodSupport
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorCaveDrought
|
||||||
|
contents: BaseWoodSupport
|
||||||
|
|
||||||
|
- !type:AutoCablingDunGen
|
||||||
|
entity: Catwalk
|
||||||
|
|
||||||
|
- !type:CornerClutterDunGen
|
||||||
|
contents: MineshaftClutter
|
||||||
|
|
||||||
|
# TODO: Check decal skirting fix contents in code.
|
||||||
|
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: SnowyLabs
|
id: SnowyLabs
|
||||||
data:
|
|
||||||
colors:
|
|
||||||
Decals: "#4cc7aa96"
|
|
||||||
entities:
|
|
||||||
Cabling: CableApcExtension
|
|
||||||
CornerWalls: WallSilver
|
|
||||||
Walls: WallSilver
|
|
||||||
spawnGroups:
|
|
||||||
CornerClutter: BaseClutter
|
|
||||||
Entrance: SnowyLabsEntrance
|
|
||||||
EntranceFlank: BaseWindow
|
|
||||||
Junction: BaseAirlock
|
|
||||||
WallMounts: SnowyLabsWalls
|
|
||||||
Window: BaseWindow
|
|
||||||
tiles:
|
|
||||||
FallbackTile: FloorSteel
|
|
||||||
whitelists:
|
|
||||||
Rooms:
|
|
||||||
tags:
|
|
||||||
- SnowyLabs
|
|
||||||
layers:
|
layers:
|
||||||
- !type:PrototypeDunGen
|
- !type:PrefabDunGen
|
||||||
proto: PlanetBase
|
roomWhitelist:
|
||||||
|
tags:
|
||||||
|
- SnowyLabs
|
||||||
|
presets:
|
||||||
|
- Bucket
|
||||||
|
- Wow
|
||||||
|
- SpaceShip
|
||||||
|
- Tall
|
||||||
|
|
||||||
|
- !type:CorridorDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
|
- !type:DungeonEntranceDunGen
|
||||||
|
count: 2
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:RoomEntranceDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:EntranceFlankDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
|
- !type:ExternalWindowDunGen
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseWindow
|
||||||
|
|
||||||
|
- !type:WallMountDunGen
|
||||||
|
contents: SnowyLabsWalls
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
|
- !type:BoundaryWallDunGen
|
||||||
|
wall: WallSilver
|
||||||
|
tile: FloorSteel
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 1
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:JunctionDunGen
|
||||||
|
width: 3
|
||||||
|
tile: FloorSteel
|
||||||
|
contents: BaseAirlock
|
||||||
|
|
||||||
|
- !type:AutoCablingDunGen
|
||||||
|
entity: CableApcExtension
|
||||||
|
|
||||||
# Spawn groups
|
# Spawn groups
|
||||||
# Basic
|
# Basic
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: BaseClutter
|
id: BaseClutter
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: PottedPlantRandom
|
children:
|
||||||
amount: 1
|
- id: PottedPlantRandom
|
||||||
|
amount: 1
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: BaseAirlock
|
id: BaseAirlock
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: CableApcExtension
|
children:
|
||||||
- id: AirlockGlass
|
- id: CableApcExtension
|
||||||
|
- id: AirlockGlass
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: BaseWindow
|
id: BaseWindow
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: Grille
|
children:
|
||||||
- id: Window
|
- id: Grille
|
||||||
|
- id: Window
|
||||||
|
|
||||||
# Lava brig
|
# Lava brig
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: LavaBrigEntrance
|
id: LavaBrigEntrance
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: CableApcExtension
|
children:
|
||||||
- id: AirlockSecurityGlassLocked
|
- id: CableApcExtension
|
||||||
|
- id: AirlockSecurityGlassLocked
|
||||||
|
|
||||||
# Mineshaft
|
# Mineshaft
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: BaseWoodWall
|
id: BaseWoodWall
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: RandomWoodenWall
|
children:
|
||||||
|
- id: RandomWoodenWall
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: BaseWoodSupport
|
id: BaseWoodSupport
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: RandomWoodenSupport
|
children:
|
||||||
|
- id: RandomWoodenSupport
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: MineshaftClutter
|
id: MineshaftClutter
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: RandomStalagmiteOrCrystal
|
children:
|
||||||
amount: 1
|
- id: RandomStalagmiteOrCrystal
|
||||||
|
amount: 1
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: MineshaftWalls
|
id: MineshaftWalls
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
# Ore
|
children:
|
||||||
- id: WallRockSalt
|
# Ore
|
||||||
prob: 0.6
|
- id: WallRockSalt
|
||||||
orGroup: content
|
prob: 0.6
|
||||||
- id: WallRockCoal
|
- id: WallRockCoal
|
||||||
prob: 0.6
|
prob: 0.6
|
||||||
orGroup: content
|
- id: WallRockTin
|
||||||
- id: WallRockTin
|
prob: 0.4
|
||||||
prob: 0.4
|
- id: WallMining
|
||||||
orGroup: content
|
prob: 0.8
|
||||||
- id: WallMining
|
|
||||||
prob: 0.8
|
|
||||||
orGroup: content
|
|
||||||
|
|
||||||
# Science lab
|
# Science lab
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: ScienceLabsWalls
|
id: ScienceLabsWalls
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
# Posters
|
children:
|
||||||
- id: RandomPosterLegit
|
# Posters
|
||||||
orGroup: content
|
- id: RandomPosterLegit
|
||||||
- id: ExtinguisherCabinetFilled
|
- id: ExtinguisherCabinetFilled
|
||||||
prob: 0.2
|
prob: 0.2
|
||||||
orGroup: content
|
- id: RandomPainting
|
||||||
- id: RandomPainting
|
prob: 0.05
|
||||||
prob: 0.05
|
- id: IntercomCommon
|
||||||
orGroup: content
|
prob: 0.1
|
||||||
- id: IntercomCommon
|
|
||||||
prob: 0.1
|
|
||||||
orGroup: content
|
|
||||||
|
|
||||||
# Snowy labs
|
# Snowy labs
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: SnowyLabsEntrance
|
id: SnowyLabsEntrance
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
- id: CableApcExtension
|
children:
|
||||||
- id: AirlockFreezerHydroponicsLocked
|
- id: CableApcExtension
|
||||||
|
- id: AirlockFreezerHydroponicsLocked
|
||||||
|
|
||||||
- type: entitySpawnEntry
|
- type: entityTable
|
||||||
id: SnowyLabsWalls
|
id: SnowyLabsWalls
|
||||||
entries:
|
table: !type:GroupSelector
|
||||||
# Posters
|
children:
|
||||||
- id: RandomPosterLegit
|
# Posters
|
||||||
orGroup: content
|
- id: RandomPosterLegit
|
||||||
- id: ExtinguisherCabinetFilled
|
- id: ExtinguisherCabinetFilled
|
||||||
prob: 0.2
|
prob: 0.2
|
||||||
orGroup: content
|
- id: RandomPainting
|
||||||
- id: RandomPainting
|
prob: 0.05
|
||||||
prob: 0.05
|
- id: IntercomScience
|
||||||
orGroup: content
|
prob: 0.1
|
||||||
- id: IntercomScience
|
|
||||||
prob: 0.1
|
|
||||||
orGroup: content
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
proto: VGRoidSmaller
|
proto: VGRoidSmaller
|
||||||
- !type:PrototypeDunGen
|
- !type:PrototypeDunGen
|
||||||
proto: VGRoidSmallPaths
|
proto: VGRoidSmallPaths
|
||||||
|
inheritDungeons: All
|
||||||
- !type:EntityTableDunGen
|
- !type:EntityTableDunGen
|
||||||
minCount: 7
|
minCount: 7
|
||||||
maxCount: 12
|
maxCount: 12
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
# Fill
|
# Fill
|
||||||
- !type:PrototypeDunGen
|
- !type:PrototypeDunGen
|
||||||
proto: VGRoidFill
|
proto: VGRoidFill
|
||||||
|
inheritDungeons: All
|
||||||
# Ores
|
# Ores
|
||||||
- !type:OreDunGen
|
- !type:OreDunGen
|
||||||
replacement: IronRock
|
replacement: IronRock
|
||||||
@@ -135,14 +137,12 @@
|
|||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: VGRoidExterior
|
id: VGRoidExterior
|
||||||
reserveTiles: true
|
reserveTiles: true
|
||||||
data:
|
|
||||||
tiles:
|
|
||||||
FallbackTile: PlatingAsteroid
|
|
||||||
WidenTile: FloorAsteroidSand
|
|
||||||
layers:
|
layers:
|
||||||
- !type:PrototypeDunGen
|
- !type:PrototypeDunGen
|
||||||
proto: VGRoidExteriorDungeons
|
proto: VGRoidExteriorDungeons
|
||||||
- !type:SplineDungeonConnectorDunGen
|
- !type:SplineDungeonConnectorDunGen
|
||||||
|
tile: PlatingAsteroid
|
||||||
|
widenTile: FloorAsteroidSand
|
||||||
|
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: VGRoidExteriorDungeons
|
id: VGRoidExteriorDungeons
|
||||||
@@ -185,7 +185,12 @@
|
|||||||
- !type:MobsDunGen
|
- !type:MobsDunGen
|
||||||
minCount: 8
|
minCount: 8
|
||||||
maxCount: 15
|
maxCount: 15
|
||||||
groups:
|
contents: VGRoidExteriorDungeonsMobs
|
||||||
|
|
||||||
|
- type: entityTable
|
||||||
|
id: VGRoidExteriorDungeonsMobs
|
||||||
|
table: !type:GroupSelector
|
||||||
|
children:
|
||||||
- id: SalvageSpawnerMobMiningAsteroid
|
- id: SalvageSpawnerMobMiningAsteroid
|
||||||
amount: 1
|
amount: 1
|
||||||
|
|
||||||
@@ -215,7 +220,12 @@
|
|||||||
- !type:MobsDunGen
|
- !type:MobsDunGen
|
||||||
minCount: 25
|
minCount: 25
|
||||||
maxCount: 35
|
maxCount: 35
|
||||||
groups:
|
contents: VGRoidSmallPathsMobs
|
||||||
|
|
||||||
|
- type: entityTable
|
||||||
|
id: VGRoidSmallPathsMobs
|
||||||
|
table: !type:GroupSelector
|
||||||
|
children:
|
||||||
- id: SalvageSpawnerMobMiningAsteroid
|
- id: SalvageSpawnerMobMiningAsteroid
|
||||||
amount: 1
|
amount: 1
|
||||||
|
|
||||||
@@ -225,10 +235,8 @@
|
|||||||
# Fill with rocks.
|
# Fill with rocks.
|
||||||
- type: dungeonConfig
|
- type: dungeonConfig
|
||||||
id: VGRoidFill
|
id: VGRoidFill
|
||||||
data:
|
|
||||||
entities:
|
|
||||||
Fill: IronRock
|
|
||||||
layers:
|
layers:
|
||||||
- !type:FillGridDunGen
|
- !type:FillGridDunGen
|
||||||
|
entity: IronRock
|
||||||
allowedTiles:
|
allowedTiles:
|
||||||
- FloorAsteroidSand
|
- FloorAsteroidSand
|
||||||
|
|||||||
Reference in New Issue
Block a user