Boss teleporter

This commit is contained in:
Marco 2025-04-29 18:14:09 +02:00
commit a1e87af061
10 changed files with 178 additions and 13 deletions

View file

@ -15,7 +15,7 @@ public partial class Teleporter : Activable
public bool IsEnabled { get; set; }
[Export]
public bool Invisible { get; private set; } = false;
public bool Invisible { get; set; } = false;
public bool IsPrimed { get; private set; }

View file

@ -0,0 +1,72 @@
using Cirno.Scripts.Activables;
using Cirno.Scripts.Resources;
using Godot;
namespace Cirno.Scripts.Actors;
[Tool]
public partial class TeleporterMarker : FeatureMarker
{
private Texture2D _markerTexture;
private Teleporter _spawnedTeleporter;
public Teleporter SpawnedTeleporter => _spawnedTeleporter;
[Export]
public TeleporterMarkerType Type { get; set; }
[Export]
public Texture2D MarkerTexture
{
get => _markerTexture;
set
{
_markerTexture = value;
if (Engine.IsEditorHint())
{
QueueRedraw();
}
}
}
public override void _Draw()
{
if (!Engine.IsEditorHint()) return;
if (MarkerTexture is null) return;
DrawTexture(MarkerTexture, -new Vector2(MarkerTexture.GetWidth() / 2f, MarkerTexture.GetHeight() / 2f));
}
public TeleporterMarker Spawn(RogueliteMapTheme mapTheme)
{
if (Engine.IsEditorHint()) return null;
if (_spawnedTeleporter is not null) return this;
_spawnedTeleporter = this.CreateSibling<Teleporter>(mapTheme.TeleporterPrefab);
if (Type is TeleporterMarkerType.Receiver or TeleporterMarkerType.Start)
{
_spawnedTeleporter.IsEnabled = false;
}
else
{
_spawnedTeleporter.IsEnabled = true;
}
if (Type is TeleporterMarkerType.InvisibleReceiver)
{
_spawnedTeleporter.Invisible = true;
}
return this;
}
}
public enum TeleporterMarkerType
{
Receiver,
InvisibleReceiver,
Start,
BranchReturn,
Boss,
NextLevel
}

View file

@ -0,0 +1 @@
uid://g6oraxgd87ij

View file

@ -67,6 +67,8 @@ public partial class RogueliteRoom : Node2D
private List<RoomConnection> _connections = [];
private List<EnemyFSMProxy> _enemies = [];
public List<TeleporterMarker> Teleporters { get; private set; } = [];
private Array<EnemyResource> SpawnableEnemies => RoomResource.SpawnableEnemies;
private BlackCover _shroud;
@ -340,7 +342,7 @@ public partial class RogueliteRoom : Node2D
if (!hasLoot)
{
GD.Print("Ran out of loot to spawn");
return;
continue;
}
var chest = marker.CreateChild<Chest>(MapTheme.ChestPrefab);
@ -348,8 +350,13 @@ public partial class RogueliteRoom : Node2D
chest.LootTable.Add(loot);
}
}
else if (markerNode is TeleporterMarker teleporterMarker)
{
var tp = teleporterMarker.Spawn(MapTheme);
MapTheme.TeleportersList.Add(tp);
Teleporters.Add(tp);
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cirno.Scripts.Actors;
using Cirno.Scripts.Enums;
using Cirno.Scripts.Resources;
using Cirno.Scripts.Resources.Roguelite;
@ -41,8 +42,10 @@ public partial class RogueliteRoomManager : Node2D
[Export] public int MaxTreasures = 2;
[Export] public int MinShops = 1;
[Export] public int MaxShops = 1;
[Export] public ulong Seed = 0;
[Export] public string ManualSeed { get; private set; }
private ulong _seed;
[Export] public Vector2I TileSize { get; set; } = new Vector2I(16, 16);
[Export] public Vector2I RoomSizeInTiles { get; set; } = new Vector2I(20, 10);
@ -93,12 +96,27 @@ public partial class RogueliteRoomManager : Node2D
public List<RoomConnection> Connections => _connections;
private void SetSeed()
{
if (!string.IsNullOrWhiteSpace(ManualSeed) && ulong.TryParse(ManualSeed, out var seed))
{
_seed = seed;
}
else
{
var rng = new RandomNumberGenerator();
_seed = rng.GetSeed();
rng.Dispose();
}
GD.Print($"Seed: {_seed}");
}
private void GenerateStraightLineDungeon()
{
if (Seed > 0)
{
GD.Seed(Seed);
}
SetSeed();
MapTheme.MakeChestLootQueue();
MapTheme.TeleportersList = [];
Vector2I origin = Vector2I.Zero;
var starterRoom = MapTheme.Rooms.Where(r => r.Type == RoomType.Starter).PickRandom();
@ -121,7 +139,7 @@ public partial class RogueliteRoomManager : Node2D
var shuffledOffshoots = offshoots.Shuffle().ToList();
MapTheme.MakeChestLootQueue();
// var offshootsQueue = new Queue<RoomType>();
// offshootsQueue.EnqueueRange(shuffledOffshoots);
@ -235,12 +253,34 @@ public partial class RogueliteRoomManager : Node2D
//return _roomGrid.ContainsKey(neighborPos);
});
}
// Debug teleporter matching
MatchBossTeleporter();
EmitSignalMapCreated();
//CallDeferred(MethodName.OpenStartDoorsDeferred, spawnedBeginRoom);
}
private void MatchBossTeleporter()
{
var bossTeleporters = MapTheme.TeleportersList.Where(x => x.Type is TeleporterMarkerType.Boss);
foreach (var teleporterMarker in bossTeleporters)
{
var bossRoom = SpawnedRooms.FirstOrDefault(x => x.RoomResource.Type is RoomType.Boss);
if (bossRoom is null) return;
var teleporter = bossRoom.Teleporters.FirstOrDefault(x =>
x.Type is TeleporterMarkerType.Receiver or TeleporterMarkerType.InvisibleReceiver);
if (teleporter is null) return;
teleporterMarker.SpawnedTeleporter.Target = teleporter.SpawnedTeleporter;
}
}
private RogueliteRoom TrySpawnRoom(List<RogueliteRoomResource> roomsList, RogueliteRoom lastRoom,
Direction direction)
{

View file

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Cirno.Scripts.Activables;
using Cirno.Scripts.Actors;
using Cirno.Scripts.Resources.Loot;
using Cirno.Scripts.Resources.Roguelite;
using Cirno.Scripts.Utils;
@ -31,6 +32,8 @@ public partial class RogueliteMapTheme : Resource
[Export] public PackedScene ShroudPrefab { get; set; }
[Export] public LootItem PointItemResource { get; set; }
[Export] public PackedScene TeleporterPrefab { get; set; }
[ExportGroup("Chances")]
[Export] public double ChestChance { get; set; }
@ -53,4 +56,7 @@ public partial class RogueliteMapTheme : Resource
return ChestLootQueue;
}
public List<TeleporterMarker> TeleportersList { get; set; } = [];
}