Dungeon generation refactor (#17121)

This commit is contained in:
metalgearsloth
2023-06-27 19:17:42 +10:00
committed by GitHub
parent b3d395f214
commit cca1a78384
26 changed files with 1528 additions and 496 deletions

View File

@@ -2,17 +2,16 @@ namespace Content.Shared.Procedural;
public sealed class Dungeon
{
/// <summary>
/// Starting position used to generate the dungeon from.
/// </summary>
public Vector2i Position;
public Vector2i Center;
public List<DungeonRoom> Rooms = new();
public readonly List<DungeonRoom> Rooms = new();
/// <summary>
/// Hashset of the tiles across all rooms.
/// </summary>
public HashSet<Vector2i> RoomTiles = new();
public readonly HashSet<Vector2i> RoomTiles = new();
public readonly HashSet<Vector2i> RoomExteriorTiles = new();
public readonly HashSet<Vector2i> CorridorTiles = new();
public readonly HashSet<Vector2i> CorridorExteriorTiles = new();
}

View File

@@ -1,3 +1,11 @@
namespace Content.Shared.Procedural;
public sealed record DungeonRoom(HashSet<Vector2i> Tiles, Vector2 Center);
public sealed record DungeonRoom(HashSet<Vector2i> Tiles, Vector2 Center, Box2i Bounds, HashSet<Vector2i> Exterior)
{
public List<Vector2i> Entrances = new();
/// <summary>
/// Nodes adjacent to tiles, including the corners.
/// </summary>
public readonly HashSet<Vector2i> Exterior = Exterior;
}

View File

@@ -0,0 +1,9 @@
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Runs cables throughout the dungeon.
/// </summary>
public sealed class AutoCablingPostGen : IPostDunGen
{
}

View File

@@ -0,0 +1,18 @@
using Content.Shared.Storage;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns entities inside corners.
/// </summary>
public sealed class CornerClutterPostGen : IPostDunGen
{
[DataField("chance")]
public float Chance = 0.50f;
/// <summary>
/// The default starting bulbs
/// </summary>
[DataField("contents", required: true)]
public List<EntitySpawnEntry> Contents = new();
}

View File

@@ -0,0 +1,35 @@
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;
/// <summary>
/// Applies decal skirting to corridors.
/// </summary>
public sealed class CorridorDecalSkirtingPostGen : IPostDunGen
{
/// <summary>
/// Color to apply to decals.
/// </summary>
[DataField("color")]
public Color? Color;
/// <summary>
/// Decal where 1 edge is found.
/// </summary>
[DataField("cardinalDecals")]
public Dictionary<DirectionFlag, string> CardinalDecals = new();
/// <summary>
/// Decal where 1 corner edge is found.
/// </summary>
[DataField("pocketDecals")]
public Dictionary<Direction, string> PocketDecals = new();
/// <summary>
/// Decal where 2 or 3 edges are found.
/// </summary>
[DataField("cornerDecals")]
public Dictionary<DirectionFlag, string> CornerDecals = new();
}

View File

@@ -0,0 +1,31 @@
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Connects room entrances via corridor segments.
/// </summary>
public sealed class CorridorPostGen : IPostDunGen
{
/// <summary>
/// How far we're allowed to generate a corridor before calling it.
/// </summary>
/// <remarks>
/// Given the heavy weightings this needs to be fairly large for larger dungeons.
/// </remarks>
[DataField("pathLimit")]
public int PathLimit = 2048;
[DataField("method")]
public CorridorPostGenMethod Method = CorridorPostGenMethod.MinimumSpanningTree;
/// <summary>
/// How wide to make the corridor.
/// </summary>
[DataField("width")]
public int Width = 3;
}
public enum CorridorPostGenMethod : byte
{
Invalid,
MinimumSpanningTree,
}

View File

@@ -8,7 +8,7 @@ namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Selects [count] rooms and places external doors to them.
/// </summary>
public sealed class EntrancePostGen : IPostDunGen
public sealed class DungeonEntrancePostGen : IPostDunGen
{
/// <summary>
/// How many rooms we place doors on.
@@ -17,9 +17,10 @@ public sealed class EntrancePostGen : IPostDunGen
public int Count = 1;
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
public List<string?> Entities = new()
{
"AirlockGlass"
"CableApcExtension",
"AirlockGlass",
};
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]

View File

@@ -0,0 +1,16 @@
using Content.Shared.Maps;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns entities on either side of an entrance.
/// </summary>
public sealed class EntranceFlankPostGen : IPostDunGen
{
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
[DataField("entities")]
public List<string?> Entities = new();
}

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Procedural.PostGeneration;
public sealed class ExternalWindowPostGen : IPostDunGen
{
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
public List<string?> Entities = new()
{
"Grille",
"Window",

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Procedural.PostGeneration;
public sealed class InternalWindowPostGen : IPostDunGen
{
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
public List<string?> Entities = new()
{
"Grille",
"Window",

View File

@@ -0,0 +1,28 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places the specified entities at junction areas.
/// </summary>
public sealed class JunctionPostGen : IPostDunGen
{
/// <summary>
/// Width to check for junctions.
/// </summary>
[DataField("width")]
public int Width = 3;
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string?> Entities = new()
{
"CableApcExtension",
"AirlockGlass"
};
}

View File

@@ -26,7 +26,7 @@ public sealed class MiddleConnectionPostGen : IPostDunGen
public string Tile = "FloorSteel";
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
public List<string?> Entities = new()
{
"CableApcExtension",
"AirlockGlass"
@@ -35,5 +35,5 @@ public sealed class MiddleConnectionPostGen : IPostDunGen
/// <summary>
/// If overlap > 1 then what should spawn on the edges.
/// </summary>
[DataField("edgeEntities")] public List<string>? EdgeEntities;
[DataField("edgeEntities")] public List<string?> EdgeEntities = new();
}

View File

@@ -0,0 +1,22 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places tiles / entities onto room entrances.
/// </summary>
public sealed class RoomEntrancePostGen : IPostDunGen
{
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string?> Entities = new()
{
"CableApcExtension",
"AirlockGlass",
};
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
}

View File

@@ -0,0 +1,6 @@
namespace Content.Shared.Procedural;
public abstract class SharedDungeonSystem : EntitySystem
{
}