VGRoid support (#27659)
* Dungeon spawn support for grid spawns * Recursive dungeons working * Mask approach working * zack * More work * Fix recursive dungeons * Heap of work * weh * the cud * rar * Job * weh * weh * weh * Master merges * orch * weh * vgroid most of the work * Tweaks * Tweaks * weh * do do do do do do * Basic layout * Ore spawning working * Big breaking changes * Mob gen working * weh * Finalising * emo * More finalising * reverty * Reduce distance
This commit is contained in:
13
Content.Shared/Procedural/Components/EntityRemapComponent.cs
Normal file
13
Content.Shared/Procedural/Components/EntityRemapComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates this entity prototype should be re-mapped to another
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class EntityRemapComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public Dictionary<EntProtoId, EntProtoId> Mask = new();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Content.Shared.Procedural.Distance;
|
||||
|
||||
/// <summary>
|
||||
/// Produces a rounder shape useful for more natural areas.
|
||||
/// </summary>
|
||||
public sealed partial class DunGenEuclideanSquaredDistance : IDunGenDistance
|
||||
{
|
||||
[DataField]
|
||||
public float BlendWeight { get; set; } = 0.50f;
|
||||
}
|
||||
10
Content.Shared/Procedural/Distance/DunGenSquareBump.cs
Normal file
10
Content.Shared/Procedural/Distance/DunGenSquareBump.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Content.Shared.Procedural.Distance;
|
||||
|
||||
/// <summary>
|
||||
/// Produces a squarish-shape that's better for filling in most of the area.
|
||||
/// </summary>
|
||||
public sealed partial class DunGenSquareBump : IDunGenDistance
|
||||
{
|
||||
[DataField]
|
||||
public float BlendWeight { get; set; } = 0.50f;
|
||||
}
|
||||
14
Content.Shared/Procedural/Distance/IDunGenDistance.cs
Normal file
14
Content.Shared/Procedural/Distance/IDunGenDistance.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Content.Shared.Procedural.Distance;
|
||||
|
||||
/// <summary>
|
||||
/// Used if you want to limit the distance noise is generated by some arbitrary config
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public partial interface IDunGenDistance
|
||||
{
|
||||
/// <summary>
|
||||
/// How much to blend between the original noise value and the adjusted one.
|
||||
/// </summary>
|
||||
float BlendWeight { get; }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
namespace Content.Shared.Procedural;
|
||||
|
||||
/// <summary>
|
||||
/// Procedurally generated dungeon data.
|
||||
/// </summary>
|
||||
public sealed class Dungeon
|
||||
{
|
||||
public readonly List<DungeonRoom> Rooms;
|
||||
public static Dungeon Empty = new Dungeon();
|
||||
|
||||
private List<DungeonRoom> _rooms;
|
||||
private HashSet<Vector2i> _allTiles = new();
|
||||
|
||||
public IReadOnlyList<DungeonRoom> Rooms => _rooms;
|
||||
|
||||
/// <summary>
|
||||
/// Hashset of the tiles across all rooms.
|
||||
@@ -17,18 +25,64 @@ public sealed class Dungeon
|
||||
|
||||
public readonly HashSet<Vector2i> Entrances = new();
|
||||
|
||||
public Dungeon()
|
||||
public IReadOnlySet<Vector2i> AllTiles => _allTiles;
|
||||
|
||||
public Dungeon() : this(new List<DungeonRoom>())
|
||||
{
|
||||
Rooms = new List<DungeonRoom>();
|
||||
}
|
||||
|
||||
public Dungeon(List<DungeonRoom> rooms)
|
||||
{
|
||||
Rooms = rooms;
|
||||
// This reftype is mine now.
|
||||
_rooms = rooms;
|
||||
|
||||
foreach (var room in Rooms)
|
||||
foreach (var room in _rooms)
|
||||
{
|
||||
Entrances.UnionWith(room.Entrances);
|
||||
InternalAddRoom(room);
|
||||
}
|
||||
|
||||
RefreshAllTiles();
|
||||
}
|
||||
|
||||
public void RefreshAllTiles()
|
||||
{
|
||||
_allTiles.Clear();
|
||||
_allTiles.UnionWith(RoomTiles);
|
||||
_allTiles.UnionWith(RoomExteriorTiles);
|
||||
_allTiles.UnionWith(CorridorTiles);
|
||||
_allTiles.UnionWith(CorridorExteriorTiles);
|
||||
_allTiles.UnionWith(Entrances);
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
_allTiles.Clear();
|
||||
|
||||
RoomTiles.Clear();
|
||||
RoomExteriorTiles.Clear();
|
||||
Entrances.Clear();
|
||||
|
||||
foreach (var room in _rooms)
|
||||
{
|
||||
InternalAddRoom(room, false);
|
||||
}
|
||||
|
||||
RefreshAllTiles();
|
||||
}
|
||||
|
||||
public void AddRoom(DungeonRoom room)
|
||||
{
|
||||
_rooms.Add(room);
|
||||
InternalAddRoom(room);
|
||||
}
|
||||
|
||||
private void InternalAddRoom(DungeonRoom room, bool refreshAll = true)
|
||||
{
|
||||
Entrances.UnionWith(room.Entrances);
|
||||
RoomTiles.UnionWith(room.Tiles);
|
||||
RoomExteriorTiles.UnionWith(room.Exterior);
|
||||
|
||||
if (refreshAll)
|
||||
RefreshAllTiles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,53 @@
|
||||
using Content.Shared.Procedural.DungeonGenerators;
|
||||
using Content.Shared.Procedural.PostGeneration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural;
|
||||
|
||||
[Prototype("dungeonConfig")]
|
||||
[Prototype]
|
||||
public sealed partial class DungeonConfigPrototype : IPrototype
|
||||
{
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField("generator", required: true)]
|
||||
public IDunGen Generator = default!;
|
||||
/// <summary>
|
||||
/// <see cref="Data"/>
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public DungeonData Data = DungeonData.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Ran after the main dungeon is created.
|
||||
/// The secret sauce, procedural generation layers that get run.
|
||||
/// </summary>
|
||||
[DataField("postGeneration")]
|
||||
public List<IPostDunGen> PostGeneration = new();
|
||||
[DataField(required: true)]
|
||||
public List<IDunGenLayer> Layers = new();
|
||||
|
||||
/// <summary>
|
||||
/// Should we reserve the tiles generated by this config so no other dungeons can spawn on it within the same job?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool ReserveTiles;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum times to run the config.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MinCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum times to run the config.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MaxCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum amount we can offset the dungeon by.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MinOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount we can offset the dungeon by.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MaxOffset;
|
||||
}
|
||||
|
||||
105
Content.Shared/Procedural/DungeonData.cs
Normal file
105
Content.Shared/Procedural/DungeonData.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
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 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,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Generates the specified config on an exterior tile of the attached dungeon.
|
||||
/// Useful if you're using <see cref="GroupDunGen"/> or otherwise want a dungeon on the outside of a grid.
|
||||
/// </summary>
|
||||
public sealed partial class ExteriorDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<DungeonConfigPrototype> Proto;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Fills unreserved tiles with the specified entity prototype.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// DungeonData keys are:
|
||||
/// - Fill
|
||||
/// </remarks>
|
||||
public sealed partial class FillGridDunGen : IDunGenLayer;
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public partial interface IDunGen
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Content.Shared.Procedural.Distance;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Like <see cref="Content.Shared.Procedural.DungeonGenerators.NoiseDunGenLayer"/> except with maximum dimensions
|
||||
/// </summary>
|
||||
public sealed partial class NoiseDistanceDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField]
|
||||
public IDunGenDistance? DistanceConfig;
|
||||
|
||||
[DataField]
|
||||
public Vector2i Size;
|
||||
|
||||
[DataField(required: true)]
|
||||
public List<NoiseDunGenLayer> Layers = new();
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Procedural.Distance;
|
||||
using Robust.Shared.Noise;
|
||||
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.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Generates dungeon flooring based on the specified noise.
|
||||
/// </summary>
|
||||
public sealed partial class NoiseDunGen : IDunGen
|
||||
public sealed partial class NoiseDunGen : IDunGenLayer
|
||||
{
|
||||
/*
|
||||
* Floodfills out from 0 until it finds a valid tile.
|
||||
|
||||
@@ -1,30 +1,20 @@
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Places rooms in pre-selected pack layouts. Chooses rooms from the specified whitelist.
|
||||
/// </summary>
|
||||
public sealed partial class PrefabDunGen : IDunGen
|
||||
/// <remarks>
|
||||
/// DungeonData keys are:
|
||||
/// - FallbackTile
|
||||
/// - Rooms
|
||||
/// </remarks>
|
||||
public sealed partial class PrefabDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Rooms need to match any of these tags
|
||||
/// </summary>
|
||||
[DataField("roomWhitelist", customTypeSerializer:typeof(PrototypeIdListSerializer<TagPrototype>))]
|
||||
public List<string> RoomWhitelist = new();
|
||||
|
||||
/// <summary>
|
||||
/// Room pack presets we can use for this prefab.
|
||||
/// </summary>
|
||||
[DataField("presets", required: true, customTypeSerializer:typeof(PrototypeIdListSerializer<DungeonPresetPrototype>))]
|
||||
public List<string> Presets = new();
|
||||
|
||||
/// <summary>
|
||||
/// Fallback tile.
|
||||
/// </summary>
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
[DataField(required: true)]
|
||||
public List<ProtoId<DungeonPresetPrototype>> Presets = new();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Runs another <see cref="DungeonConfigPrototype"/>.
|
||||
/// Used for storing data on 1 system.
|
||||
/// </summary>
|
||||
public sealed partial class PrototypeDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<DungeonConfigPrototype> Proto;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.Noise;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonGenerators;
|
||||
|
||||
/// <summary>
|
||||
/// Replaces existing tiles if they're not empty.
|
||||
/// </summary>
|
||||
public sealed partial class ReplaceTileDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Chance for a non-variant tile to be used, in case they're too noisy.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float VariantWeight = 0.1f;
|
||||
|
||||
[DataField(required: true)]
|
||||
public List<ReplaceTileLayer> Layers = new();
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public record struct ReplaceTileLayer
|
||||
{
|
||||
public ProtoId<ContentTileDefinition> Tile;
|
||||
|
||||
public float Threshold;
|
||||
|
||||
public FastNoiseLite Noise;
|
||||
}
|
||||
21
Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs
Normal file
21
Content.Shared/Procedural/DungeonLayers/MobsDunGen.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Content.Shared.Storage;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonLayers;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Spawns mobs inside of the dungeon randomly.
|
||||
/// </summary>
|
||||
public sealed partial class MobsDunGen : IDunGenLayer
|
||||
{
|
||||
// Counts separate to config to avoid some duplication.
|
||||
|
||||
[DataField]
|
||||
public int MinCount = 1;
|
||||
|
||||
[DataField]
|
||||
public int MaxCount = 1;
|
||||
|
||||
[DataField(required: true)]
|
||||
public List<EntitySpawnEntry> Groups = new();
|
||||
}
|
||||
42
Content.Shared/Procedural/DungeonLayers/OreDunGen.cs
Normal file
42
Content.Shared/Procedural/DungeonLayers/OreDunGen.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.DungeonLayers;
|
||||
|
||||
/// <summary>
|
||||
/// Generates veins inside of the specified dungeon.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Generates on top of existing entities for sanity reasons moreso than performance.
|
||||
/// </remarks>
|
||||
public sealed partial class OreDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// If the vein generation should occur on top of existing entities what are we replacing.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId? Replacement;
|
||||
|
||||
/// <summary>
|
||||
/// Entity to spawn.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public EntProtoId Entity;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount of group spawns
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int Count = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum entities to spawn in one group.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MinGroupSize = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum entities to spawn in one group.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MaxGroupSize = 1;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Procedural;
|
||||
|
||||
// TODO: Cache center and bounds and shit and don't make the caller deal with it.
|
||||
public sealed record DungeonRoom(HashSet<Vector2i> Tiles, Vector2 Center, Box2i Bounds, HashSet<Vector2i> Exterior)
|
||||
{
|
||||
public readonly List<Vector2i> Entrances = new();
|
||||
|
||||
7
Content.Shared/Procedural/IDunGenLayer.cs
Normal file
7
Content.Shared/Procedural/IDunGenLayer.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Content.Shared.Procedural;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public partial interface IDunGenLayer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Runs cables throughout the dungeon.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// DungeonData keys are:
|
||||
/// - Cabling
|
||||
/// </remarks>
|
||||
public sealed partial class AutoCablingDunGen : IDunGenLayer;
|
||||
@@ -1,12 +0,0 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Runs cables throughout the dungeon.
|
||||
/// </summary>
|
||||
public sealed partial class AutoCablingPostGen : IPostDunGen
|
||||
{
|
||||
[DataField]
|
||||
public EntProtoId Entity = "CableApcExtension";
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Shared.Parallax.Biomes;
|
||||
using Content.Shared.Procedural.PostGeneration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
@@ -8,7 +7,7 @@ namespace Content.Shared.Procedural.PostGeneration;
|
||||
/// Generates a biome on top of valid tiles, then removes the biome when done.
|
||||
/// Only works if no existing biome is present.
|
||||
/// </summary>
|
||||
public sealed partial class BiomePostGen : IPostDunGen
|
||||
public sealed partial class BiomeDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<BiomeTemplatePrototype> BiomeTemplate;
|
||||
@@ -1,5 +1,3 @@
|
||||
using Content.Shared.Parallax.Biomes.Markers;
|
||||
using Content.Shared.Procedural.PostGeneration;
|
||||
using Content.Shared.Random;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -8,7 +6,7 @@ namespace Content.Shared.Procedural.PostGeneration;
|
||||
/// <summary>
|
||||
/// Spawns the specified marker layer on top of the dungeon rooms.
|
||||
/// </summary>
|
||||
public sealed partial class BiomeMarkerLayerPostGen : IPostDunGen
|
||||
public sealed partial class BiomeMarkerLayerDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// How many times to spawn marker layers; can duplicate.
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Iterates room edges and places the relevant tiles and walls on any free indices.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - CornerWalls (Optional)
|
||||
/// - FallbackTile
|
||||
/// - Walls
|
||||
/// </remarks>
|
||||
public sealed partial class BoundaryWallDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField]
|
||||
public BoundaryWallFlags Flags = BoundaryWallFlags.Corridors | BoundaryWallFlags.Rooms;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum BoundaryWallFlags : byte
|
||||
{
|
||||
Rooms = 1 << 0,
|
||||
Corridors = 1 << 1,
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Iterates room edges and places the relevant tiles and walls on any free indices.
|
||||
/// </summary>
|
||||
public sealed partial class BoundaryWallPostGen : IPostDunGen
|
||||
{
|
||||
[DataField]
|
||||
public ProtoId<ContentTileDefinition> Tile = "FloorSteel";
|
||||
|
||||
[DataField]
|
||||
public EntProtoId Wall = "WallSolid";
|
||||
|
||||
/// <summary>
|
||||
/// Walls to use in corners if applicable.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string? CornerWall;
|
||||
|
||||
[DataField]
|
||||
public BoundaryWallFlags Flags = BoundaryWallFlags.Corridors | BoundaryWallFlags.Rooms;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum BoundaryWallFlags : byte
|
||||
{
|
||||
Rooms = 1 << 0,
|
||||
Corridors = 1 << 1,
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Spawns entities inside corners.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - CornerClutter
|
||||
/// </remarks>
|
||||
public sealed partial class CornerClutterDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField]
|
||||
public float Chance = 0.50f;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Content.Shared.Storage;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Spawns entities inside corners.
|
||||
/// </summary>
|
||||
public sealed partial class CornerClutterPostGen : IPostDunGen
|
||||
{
|
||||
[DataField]
|
||||
public float Chance = 0.50f;
|
||||
|
||||
/// <summary>
|
||||
/// The default starting bulbs
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public List<EntitySpawnEntry> Contents = new();
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace Content.Shared.Procedural.PostGeneration;
|
||||
/// <summary>
|
||||
/// Adds entities randomly to the corridors.
|
||||
/// </summary>
|
||||
public sealed partial class CorridorClutterPostGen : IPostDunGen
|
||||
public sealed partial class CorridorClutterDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField]
|
||||
public float Chance = 0.05f;
|
||||
@@ -7,29 +7,23 @@ namespace Content.Shared.Procedural.PostGeneration;
|
||||
/// <summary>
|
||||
/// Applies decal skirting to corridors.
|
||||
/// </summary>
|
||||
public sealed partial class CorridorDecalSkirtingPostGen : IPostDunGen
|
||||
public sealed partial class CorridorDecalSkirtingDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Color to apply to decals.
|
||||
/// </summary>
|
||||
[DataField("color")]
|
||||
public Color? Color;
|
||||
|
||||
/// <summary>
|
||||
/// Decal where 1 edge is found.
|
||||
/// </summary>
|
||||
[DataField("cardinalDecals")]
|
||||
[DataField]
|
||||
public Dictionary<DirectionFlag, string> CardinalDecals = new();
|
||||
|
||||
/// <summary>
|
||||
/// Decal where 1 corner edge is found.
|
||||
/// </summary>
|
||||
[DataField("pocketDecals")]
|
||||
[DataField]
|
||||
public Dictionary<Direction, string> PocketDecals = new();
|
||||
|
||||
/// <summary>
|
||||
/// Decal where 2 or 3 edges are found.
|
||||
/// </summary>
|
||||
[DataField("cornerDecals")]
|
||||
[DataField]
|
||||
public Dictionary<DirectionFlag, string> CornerDecals = new();
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Connects room entrances via corridor segments.
|
||||
/// </summary>
|
||||
public sealed partial class CorridorPostGen : IPostDunGen
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - FallbackTile
|
||||
/// </remarks>
|
||||
public sealed partial class CorridorDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// How far we're allowed to generate a corridor before calling it.
|
||||
@@ -17,9 +18,6 @@ public sealed partial class CorridorPostGen : IPostDunGen
|
||||
[DataField]
|
||||
public int PathLimit = 2048;
|
||||
|
||||
[DataField]
|
||||
public ProtoId<ContentTileDefinition> Tile = "FloorSteel";
|
||||
|
||||
/// <summary>
|
||||
/// How wide to make the corridor.
|
||||
/// </summary>
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Selects [count] rooms and places external doors to them.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - Entrance
|
||||
/// - FallbackTile
|
||||
/// </remarks>
|
||||
public sealed partial class DungeonEntranceDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// How many rooms we place doors on.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int Count = 1;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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>
|
||||
/// Selects [count] rooms and places external doors to them.
|
||||
/// </summary>
|
||||
public sealed partial class DungeonEntrancePostGen : IPostDunGen
|
||||
{
|
||||
/// <summary>
|
||||
/// How many rooms we place doors on.
|
||||
/// </summary>
|
||||
[DataField("count")]
|
||||
public int Count = 1;
|
||||
|
||||
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string?> Entities = new()
|
||||
{
|
||||
"CableApcExtension",
|
||||
"AirlockGlass",
|
||||
};
|
||||
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Spawns entities on either side of an entrance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - FallbackTile
|
||||
/// -
|
||||
/// </remarks>
|
||||
public sealed partial class EntranceFlankDunGen : IDunGenLayer;
|
||||
@@ -1,16 +0,0 @@
|
||||
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 partial class EntranceFlankPostGen : IPostDunGen
|
||||
{
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
|
||||
[DataField("entities")]
|
||||
public List<string?> Entities = new();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// If external areas are found will try to generate windows.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - EntranceFlank
|
||||
/// - FallbackTile
|
||||
/// </remarks>
|
||||
public sealed partial class ExternalWindowDunGen : IDunGenLayer;
|
||||
@@ -1,22 +0,0 @@
|
||||
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>
|
||||
/// If external areas are found will try to generate windows.
|
||||
/// </summary>
|
||||
public sealed partial class ExternalWindowPostGen : IPostDunGen
|
||||
{
|
||||
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string?> Entities = new()
|
||||
{
|
||||
"Grille",
|
||||
"Window",
|
||||
};
|
||||
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Ran after generating dungeon rooms. Can be used for additional loot, contents, etc.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public partial interface IPostDunGen
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// If internal areas are found will try to generate windows.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - FallbackTile
|
||||
/// - Window
|
||||
/// </remarks>
|
||||
public sealed partial class InternalWindowDunGen : IDunGenLayer;
|
||||
@@ -1,22 +0,0 @@
|
||||
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>
|
||||
/// If internal areas are found will try to generate windows.
|
||||
/// </summary>
|
||||
public sealed partial class InternalWindowPostGen : IPostDunGen
|
||||
{
|
||||
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string?> Entities = new()
|
||||
{
|
||||
"Grille",
|
||||
"Window",
|
||||
};
|
||||
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
}
|
||||
18
Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs
Normal file
18
Content.Shared/Procedural/PostGeneration/JunctionDunGen.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Places the specified entities at junction areas.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dungeon data keys are:
|
||||
/// - Entrance
|
||||
/// - FallbackTile
|
||||
/// </remarks>
|
||||
public sealed partial class JunctionDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Width to check for junctions.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int Width = 3;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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 partial 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"
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Places the specified entities on the middle connections between rooms
|
||||
/// </summary>
|
||||
public sealed partial class MiddleConnectionDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// How much overlap there needs to be between 2 rooms exactly.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int OverlapCount = -1;
|
||||
|
||||
/// <summary>
|
||||
/// How many connections to spawn between rooms.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int Count = 1;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
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 on the middle connections between rooms
|
||||
/// </summary>
|
||||
public sealed partial class MiddleConnectionPostGen : IPostDunGen
|
||||
{
|
||||
/// <summary>
|
||||
/// How much overlap there needs to be between 2 rooms exactly.
|
||||
/// </summary>
|
||||
[DataField("overlapCount")]
|
||||
public int OverlapCount = -1;
|
||||
|
||||
/// <summary>
|
||||
/// How many connections to spawn between rooms.
|
||||
/// </summary>
|
||||
[DataField("count")]
|
||||
public int Count = 1;
|
||||
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
|
||||
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
|
||||
public List<string?> Entities = new()
|
||||
{
|
||||
"CableApcExtension",
|
||||
"AirlockGlass"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// If overlap > 1 then what should spawn on the edges.
|
||||
/// </summary>
|
||||
[DataField("edgeEntities")] public List<string?> EdgeEntities = new();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Places tiles / entities onto room entrances.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// DungeonData keys are:
|
||||
/// - Entrance
|
||||
/// - FallbackTile
|
||||
/// </remarks>
|
||||
public sealed partial class RoomEntranceDunGen : IDunGenLayer;
|
||||
@@ -1,22 +0,0 @@
|
||||
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 partial 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";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Connects dungeons via points that get subdivided.
|
||||
/// </summary>
|
||||
public sealed partial class SplineDungeonConnectorDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Will divide the distance between the start and end points so that no subdivision is more than these metres away.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int DivisionDistance = 10;
|
||||
|
||||
/// <summary>
|
||||
/// How much each subdivision can vary from the middle.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float VarianceMax = 0.35f;
|
||||
}
|
||||
13
Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs
Normal file
13
Content.Shared/Procedural/PostGeneration/WallMountDunGen.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Spawns on the boundary tiles of rooms.
|
||||
/// </summary>
|
||||
public sealed partial class WallMountDunGen : IDunGenLayer
|
||||
{
|
||||
/// <summary>
|
||||
/// Chance per free tile to spawn a wallmount.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public double Prob = 0.1;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Storage;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// Spawns on the boundary tiles of rooms.
|
||||
/// </summary>
|
||||
public sealed partial class WallMountPostGen : IPostDunGen
|
||||
{
|
||||
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
|
||||
public string Tile = "FloorSteel";
|
||||
|
||||
[DataField("spawns")]
|
||||
public List<EntitySpawnEntry> Spawns = new();
|
||||
|
||||
/// <summary>
|
||||
/// Chance per free tile to spawn a wallmount.
|
||||
/// </summary>
|
||||
[DataField("prob")]
|
||||
public double Prob = 0.1;
|
||||
}
|
||||
@@ -1,14 +1,10 @@
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Procedural.DungeonGenerators;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Procedural.PostGeneration;
|
||||
|
||||
// Ime a worm
|
||||
/// <summary>
|
||||
/// Generates worm corridors.
|
||||
/// </summary>
|
||||
public sealed partial class WormCorridorPostGen : IPostDunGen
|
||||
public sealed partial class WormCorridorDunGen : IDunGenLayer
|
||||
{
|
||||
[DataField]
|
||||
public int PathLimit = 2048;
|
||||
@@ -31,9 +27,6 @@ public sealed partial class WormCorridorPostGen : IPostDunGen
|
||||
[DataField]
|
||||
public Angle MaxAngleChange = Angle.FromDegrees(45);
|
||||
|
||||
[DataField]
|
||||
public ProtoId<ContentTileDefinition> Tile = "FloorSteel";
|
||||
|
||||
/// <summary>
|
||||
/// How wide to make the corridor.
|
||||
/// </summary>
|
||||
@@ -32,14 +32,14 @@ public abstract partial class SharedSalvageSystem
|
||||
var layers = new Dictionary<string, int>();
|
||||
|
||||
// If we ever add more random layers will need to Next on these.
|
||||
foreach (var layer in configProto.PostGeneration)
|
||||
foreach (var layer in configProto.Layers)
|
||||
{
|
||||
switch (layer)
|
||||
{
|
||||
case BiomePostGen:
|
||||
case BiomeDunGen:
|
||||
rand.Next();
|
||||
break;
|
||||
case BiomeMarkerLayerPostGen marker:
|
||||
case BiomeMarkerLayerDunGen marker:
|
||||
for (var i = 0; i < marker.Count; i++)
|
||||
{
|
||||
var proto = _proto.Index(marker.MarkerTemplate).Pick(rand);
|
||||
|
||||
@@ -18,7 +18,7 @@ public abstract partial class SharedShuttleSystem : EntitySystem
|
||||
[Dependency] protected readonly SharedTransformSystem XformSystem = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
||||
|
||||
public const float FTLRange = 512f;
|
||||
public const float FTLRange = 256f;
|
||||
public const float FTLBufferRange = 8f;
|
||||
|
||||
private EntityQuery<MapGridComponent> _gridQuery;
|
||||
|
||||
@@ -5,6 +5,19 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
|
||||
|
||||
namespace Content.Shared.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Prototype wrapper around <see cref="EntitySpawnEntry"/>
|
||||
/// </summary>
|
||||
[Prototype]
|
||||
public sealed class EntitySpawnEntryPrototype : IPrototype
|
||||
{
|
||||
[IdDataField]
|
||||
public string ID { get; } = string.Empty;
|
||||
|
||||
[DataField]
|
||||
public List<EntitySpawnEntry> Entries = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictates a list of items that can be spawned.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user