Underworld + Overworld (#151)

* Setup new dungeon system (v2)

* add custom basic generation

* add maps linking

shitcode, boo

* add auto linking sub-world portal

* fix deleted component

* clearing otherside of the tiles manually (im stuck in wall, brother!)

* Upgrade cave biome generation

* add TODO

* add ladder and hole sprites

* add dungeon entrance prototypes

* clean up, add docs

* add many ambient sounds

* Update CP14StationDungeonMapSystem.cs

* remove bugs
This commit is contained in:
Ed
2024-05-17 17:07:29 +03:00
committed by GitHub
parent a2c164bb07
commit 811cc8a41d
30 changed files with 454 additions and 57 deletions

View File

@@ -0,0 +1,13 @@
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.DungeonPortal;
/// <summary>
/// Automatically creates a linked portal of a certain prototype on the opposite linked world, if it exists.
/// </summary>
[RegisterComponent, Access(typeof(CP14AutoDungeonPortalSystem))]
public sealed partial class CP14AutoDungeonPortalComponent : Component
{
[DataField(required: true)]
public EntProtoId OtherSidePortal;
}

View File

@@ -0,0 +1,78 @@
using Content.Shared.Maps;
using Content.Shared.Teleportation.Components;
using Content.Shared.Teleportation.Systems;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Random;
namespace Content.Server._CP14.DungeonPortal;
public sealed partial class CP14AutoDungeonPortalSystem : EntitySystem
{
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly SharedMapSystem _maps = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14AutoDungeonPortalComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<CP14AutoDungeonPortalComponent> autoPortal, ref MapInitEvent args)
{
if (!TryComp<PortalComponent>(autoPortal, out var portalComp))
return;
var mapId = Transform(autoPortal).MapID;
_map.TryGetMap(mapId, out var mapUid);
if (mapUid == null)
return;
if (!TryComp<LinkedEntityComponent>(mapUid, out var link))
return;
if (link.LinkedEntities.Count > 1) //Bruh, we don't want more than 1 linked maps for now
return;
var targetMapUid = _random.Pick(link.LinkedEntities);
var targetMapId = Transform(targetMapUid).MapID;
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
var targetMapPos = new MapCoordinates(currentWorldPos, targetMapId);
var otherSidePortal = Spawn(autoPortal.Comp.OtherSidePortal, targetMapPos);
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
RemComp<CP14AutoDungeonPortalComponent>(autoPortal);
ClearOtherSide(otherSidePortal, targetMapUid);
}
private void ClearOtherSide(EntityUid otherSidePortal, EntityUid targetMapUid)
{
var tiles = new List<(Vector2i Index, Tile Tile)>();
var originF = _transform.GetWorldPosition(otherSidePortal);
var origin = new Vector2i((int) originF.X, (int) originF.Y);
var tileDef = _tileDefManager["CP14FloorStonebricks"]; //TODO: Remove hardcode
var seed = _random.Next();
var random = new Random(seed);
var grid = Comp<MapGridComponent>(targetMapUid);
for (var x = -2; x <= 2; x++) //TODO: Remove hardcode
{
for (var y = -2; y <= 2; y++)
{
tiles.Add((new Vector2i(x, y) + origin, new Tile(tileDef.TileId, variant: _tile.PickVariant((ContentTileDefinition) tileDef, random))));
}
}
_maps.SetTiles(targetMapUid, grid, tiles);
}
}

View File

@@ -1,19 +0,0 @@
using Content.Shared.Parallax.Biomes;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationBiome;
/// <summary>
/// allows you to initialize a planet on a specific map at initialization time.
/// </summary>
[RegisterComponent, Access(typeof(CP14StationBiomeSystem))]
public sealed partial class CP14StationBiomeComponent : Component
{
[DataField]
public ProtoId<BiomeTemplatePrototype> Biome = "Grasslands";
// If null, its random
[DataField]
public int? Seed = null;
}

View File

@@ -1,35 +0,0 @@
using Content.Server.Parallax;
using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationBiome;
public sealed partial class CP14StationBiomeSystem : EntitySystem
{
[Dependency] private readonly BiomeSystem _biome = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly StationSystem _station = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14StationBiomeComponent, StationPostInitEvent>(OnStationPostInit);
}
private void OnStationPostInit(Entity<CP14StationBiomeComponent> map, ref StationPostInitEvent args)
{
if (!TryComp(map, out StationDataComponent? dataComp))
return;
var station = _station.GetLargestGrid(dataComp);
if (station == null) return;
var mapId = Transform(station.Value).MapID;
var mapUid = _mapManager.GetMapEntityId(mapId);
_biome.EnsurePlanet(mapUid, _proto.Index(map.Comp.Biome), map.Comp.Seed);
}
}

View File

@@ -0,0 +1,27 @@
using Content.Shared.Parallax.Biomes;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationDungeonMap;
/// <summary>
/// Initializes a procedurally generated world with points of interest
/// </summary>
[RegisterComponent, Access(typeof(CP14StationDungeonMapSystem))]
public sealed partial class CP14StationDungeonMapComponent : Component
{
[DataField(required: true)]
public ProtoId<BiomeTemplatePrototype> Biome = "Caves";
// If null, its random
[DataField]
public int? Seed = null;
[DataField]
public Color MapLightColor = Color.Black;
[DataField]
public string MapName = "Dungeon map";
[DataField(serverOnly: true)]
public ComponentRegistry Components = new();
}

View File

@@ -0,0 +1,54 @@
using Content.Server.Parallax;
using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
using Content.Shared.Teleportation.Systems;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationDungeonMap;
public sealed partial class CP14StationDungeonMapSystem : EntitySystem
{
[Dependency] private readonly BiomeSystem _biome = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
[Dependency] private readonly StationSystem _station = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14StationDungeonMapComponent, StationPostInitEvent>(OnStationPostInit);
}
private void OnStationPostInit(Entity<CP14StationDungeonMapComponent> map, ref StationPostInitEvent args)
{
if (!TryComp(map, out StationDataComponent? dataComp))
return;
var mapUid = _map.CreateMap(out var mapId);
_metaData.SetEntityName(mapUid, map.Comp.MapName);
_biome.EnsurePlanet(mapUid, _proto.Index(map.Comp.Biome), map.Comp.Seed, mapLight: map.Comp.MapLightColor);
EntityManager.AddComponents(mapUid, map.Comp.Components);
TryLinkDungeonAndStationMaps(dataComp, mapUid);
}
private bool TryLinkDungeonAndStationMaps(StationDataComponent dataComp, EntityUid mapUid)
{
var station = _station.GetLargestGrid(dataComp);
if (station == null)
return false;
var stationMapId = Transform(station.Value).MapID;
_map.TryGetMap(stationMapId, out var stationMapUid);
if (stationMapUid == null)
return false;
return _linkedEntity.TryLink(mapUid, stationMapUid.Value);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,24 @@
- files: ["ambicave.ogg"]
- files: ["ambicave1.ogg"]
license: "CC-BY-4.0"
copyright: 'by Rosanajurado of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Rosanajurado/sounds/667117/"
source: "https://freesound.org/people/Rosanajurado/sounds/667117/"
- files: ["ambicreepy1.ogg"]
license: "CC-BY-SA-3.0"
copyright: 'by alextundra of Freesound.org. Mixed from stereo to mono.'
source: "https://freesound.org/people/alextundra/sounds/60893/"
- files: ["ambicreepy2.ogg"]
license: "CC-BY-SA-3.0"
copyright: 'by alextundra of Freesound.org. Mixed from stereo to mono.'
source: "https://freesound.org/people/alextundra/sounds/60892/"
- files: ["ambicreepy4.ogg"]
license: "CC-BY-4.0"
copyright: 'by 7by7 of Freesound.org. Mixed from stereo to mono.'
source: "https://freesound.org/people/7by7/sounds/72849/"
- files: ["weatherWindy.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/134699/"

Binary file not shown.

View File

@@ -0,0 +1,44 @@
- files: ["owl1.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl2.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl3.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl4.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl5.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl6.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl7.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl8.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"
- files: ["owl9.ogg"]
license: "CC-BY-4.0"
copyright: 'by Benboncan of Freesound.org. Cropped and mixed from stereo to mono.'
source: "https://freesound.org/people/Benboncan/sounds/64544/"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -27,7 +27,8 @@
- type: StationRandomTransform
enableStationRotation: false
maxStationOffset: null
- type: CP14StationBiome
- type: StationBiome
biome: Snow
- type: StationNameSetup
mapNameTemplate: "Dev"
- type: StationJobs
@@ -35,6 +36,8 @@
- Adventurer #CrystallPunk Dev replacement
availableJobs:
Adventurer: [ -1, -1 ] #CrystallPunk Dev replacement
- type: CP14StationDungeonMap
biome: CP14CavesGeneric
#- type: gameMap
# id: TestTeg

View File

@@ -0,0 +1,68 @@
- type: entity
id: CP14DungeonEntrance
name: dungeon entrance
noSpawn: true
description: The dark depths of the underworld are calling you.
placement:
mode: SnapgridCenter
components:
- type: Transform
anchored: True
- type: InteractionOutline
- type: Clickable
- type: Physics
bodyType: Static
- type: Sprite
sprite: /Textures/_CP14/Structures/Dungeon/holes.rsi
drawdepth: FloorTiles
layers:
- state: hole_big
- state: ladder_big_top_part
- type: Fixtures
fixtures:
portalFixture:
shape:
!type:PhysShapeAabb
bounds: "-0.25,-0.48,0.25,0.48"
mask:
- FullTileMask
layer:
- WallLayer
hard: false
- type: Portal
canTeleportToOtherMaps: true
randomTeleport: false
- type: entity
parent: PortalBlue
id: CP14DungeonEntranceAutolink
suffix: Autolink Dungeon
components:
- type: CP14AutoDungeonPortal
otherSidePortal: CP14DungeonExit
- type: entity
parent: CP14DungeonEntrance
id: CP14DungeonExit
noSpawn: true
name: dungeon exit
description: A way out of the dark underworld into the overworld.
components:
- type: Sprite
sprite: /Textures/_CP14/Structures/Dungeon/holes.rsi
drawdepth: Mobs
layers:
- state: ladder_bottom_part
- type: PointLight
color: White
radius: 3
energy: 1
netsync: false
- type: entity
parent: CP14DungeonExit
id: CP14DungeonExitAutolink
suffix: Autolink Dungeon
components:
- type: CP14AutoDungeonPortal
otherSidePortal: CP14DungeonEntrance

View File

@@ -0,0 +1,110 @@
- type: biomeTemplate
id: CP14SolidStone
layers:
- !type:BiomeTileLayer
threshold: -1.0
tile: CP14FloorBase
- !type:BiomeEntityLayer
threshold: -1.0
allowedTiles:
- CP14FloorBase
entities:
- CP14CaveStoneWall
- type: biomeTemplate
id: CP14CavesGeneric
layers:
- !type:BiomeTileLayer
threshold: -1.0
tile: CP14FloorBase
#Entity
- !type:BiomeEntityLayer
threshold: 0.4
noise:
seed: 1
noiseType: OpenSimplex2
fractalType: FBm
frequency: 2
allowedTiles:
- CP14FloorBase
entities:
- FloraGreyStalagmite1
- FloraGreyStalagmite2
- FloraGreyStalagmite3
- FloraGreyStalagmite4
- FloraGreyStalagmite5
- FloraRockSolid01
- FloraRockSolid02
- FloraRockSolid03
- FloraGreyStalagmite1
- FloraGreyStalagmite2
- FloraGreyStalagmite3
- FloraGreyStalagmite4
- FloraGreyStalagmite5
- FloraRockSolid01
- FloraRockSolid02
- FloraRockSolid03
- FloraGreyStalagmite1
- FloraGreyStalagmite2
- FloraGreyStalagmite3
- FloraGreyStalagmite4
- FloraGreyStalagmite5
- FloraRockSolid01
- FloraRockSolid02
- FloraRockSolid03
- CP14CrystalRubiesSmall
- CP14CrystalRubiesMedium
- CP14CrystalRubiesBig
- CP14CrystalTopazesSmall
- CP14CrystalTopazesMedium
- CP14CrystalTopazesBig
- CP14CrystalEmeraldsSmall
- CP14CrystalEmeraldsMedium
- CP14CrystalEmeraldsBig
- CP14CrystalSapphiresSmall
- CP14CrystalSapphiresMedium
- CP14CrystalSapphiresBig
- CP14CrystalAmethystsSmall
- CP14CrystalAmethystsMedium
- CP14CrystalAmethystsBig
- CP14CrystalDiamondsSmall
- CP14CrystalDiamondsMedium
- CP14CrystalDiamondsBig
#Walls
- !type:BiomeEntityLayer
threshold: -0.75
invert: true
noise:
seed: 0
noiseType: Perlin
fractalType: Ridged
octaves: 1
frequency: 0.05
gain: 0.5
allowedTiles:
- CP14FloorBase
entities:
- CP14CaveStoneWall
#Ores
- !type:BiomeEntityLayer
threshold: 0.6
noise:
seed: 0
noiseType: OpenSimplex2
fractalType: FBm
frequency: 3
allowedTiles:
- CP14FloorBase
entities:
- CP14CaveStoneWallSilverOre
- !type:BiomeEntityLayer
threshold: 0.6
noise:
seed: 10
noiseType: OpenSimplex2
fractalType: FBm
frequency: 3
allowedTiles:
- CP14FloorBase
entities:
- CP14CaveStoneWallGoldOre

View File

@@ -0,0 +1,9 @@
- type: salvageLoot
id: CP14DungeonLoot
loots:
- !type:RandomSpawnsLoot
entries:
- proto: CP14BaseThrowableSpear
prob: 0.5
- proto: CP14BaseDagger
prob: 0.5

View File

@@ -24,6 +24,9 @@
- /Audio/Ambience/ambiruin4.ogg
- /Audio/Ambience/maintambience.ogg
- /Audio/_CP14/Ambience/ambicave1.ogg
- /Audio/_CP14/Ambience/ambicreepy1.ogg
- /Audio/_CP14/Ambience/ambicreepy2.ogg
- /Audio/_CP14/Ambience/ambicreepy3.ogg
# Rules
- type: rules

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,22 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "by TheShuEd (discord)",
"size": {
"x": 64,
"y": 64
},
"states": [
{
"name": "hole_big",
"directions": 4
},
{
"name": "ladder_big_top_part",
"directions": 4
},
{
"name": "ladder_bottom_part"
}
]
}