Dungeon generation refactor (#17121)
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Runs cables throughout the dungeon.
|
||||
/// </summary>
|
||||
public sealed class AutoCablingPostGen : IPostDunGen
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
31
Content.Shared/Procedural/PostGeneration/CorridorPostGen.cs
Normal file
31
Content.Shared/Procedural/PostGeneration/CorridorPostGen.cs
Normal 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,
|
||||
}
|
||||
@@ -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>))]
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
28
Content.Shared/Procedural/PostGeneration/JunctionPostGen.cs
Normal file
28
Content.Shared/Procedural/PostGeneration/JunctionPostGen.cs
Normal 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"
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
6
Content.Shared/Procedural/SharedDungeonSystem.cs
Normal file
6
Content.Shared/Procedural/SharedDungeonSystem.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared.Procedural;
|
||||
|
||||
public abstract class SharedDungeonSystem : EntitySystem
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user