Add map loading logic and spawn rate control

This commit is contained in:
2025-09-30 02:32:03 -07:00
parent 70d1871985
commit 6f582fcca1
43 changed files with 470 additions and 118 deletions

View File

@@ -12,8 +12,6 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
{
public override void _Notification(int what) => this.Notify(what);
[Node] public EnemyDatabase EnemyDatabase { get; set; } = default!;
private Transform3D _playerSpawnPoint;
public ImmutableList<IDungeonRoom> Rooms { get; private set; }
@@ -25,12 +23,16 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
Rooms = [];
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
_playerSpawnPoint = RandomizePlayerSpawnPoint();
var monsterRooms = Rooms.OfType<MonsterRoom>();
foreach (var room in monsterRooms)
room.SpawnEnemies(EnemyDatabase);
}
public Transform3D GetPlayerSpawnPoint() => new Transform3D(_playerSpawnPoint.Basis, new Vector3(_playerSpawnPoint.Origin.X, -1.75f, _playerSpawnPoint.Origin.Z));
public void SpawnEnemies(Godot.Collections.Dictionary<EnemyType, float> enemyInfo)
{
var monsterRooms = Rooms.OfType<MonsterRoom>();
foreach (var room in monsterRooms)
room.SpawnEnemies(enemyInfo);
}
public Transform3D GetPlayerSpawnPoint() => new Transform3D(_playerSpawnPoint.Basis, new Vector3(_playerSpawnPoint.Origin.X, 0f, _playerSpawnPoint.Origin.Z));
private Transform3D RandomizePlayerSpawnPoint()
{

View File

@@ -11,8 +11,6 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom
{
public override void _Notification(int what) => this.Notify(what);
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
[Node] private MeshInstance3D _minimap { get; set; } = default!;
public bool IsPlayerInRoom => _isPlayerInRoom;
@@ -30,8 +28,8 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom
public void Setup()
{
_enemiesInRoom = [];
_room.BodyEntered += Room_BodyEntered;
_room.BodyExited += Room_BodyExited;
//_room.BodyEntered += Room_BodyEntered;
//_room.BodyExited += Room_BodyExited;
}
private void Room_BodyExited(Node3D body)

View File

@@ -14,17 +14,19 @@ public partial class ExitRoom : DungeonRoom
[Node] private Area3D _exit { get; set; } = default!;
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
public override void _Ready()
{
_exit.AreaEntered += Exit_AreaEntered;
_exit.AreaEntered += Exit_AreaEntered;
}
public void ExitReached()
=> Game.FloorExitReached();
=> Game.FloorExitReached();
private void Exit_AreaEntered(Area3D area)
{
if (area.GetOwner() is IPlayer)
ExitReached();
if (area.GetOwner() is IPlayer)
ExitReached();
}
}

View File

@@ -5,8 +5,6 @@ using System.Collections.Immutable;
namespace Zennysoft.Game.Ma;
public interface IDungeonRoom : INode3D
{
Marker3D PlayerSpawn { get; }
bool IsPlayerInRoom { get; }
bool PlayerDiscoveredRoom { get; }

View File

@@ -15,51 +15,57 @@ public partial class MonsterRoom : DungeonRoom
[Node] public Node3D EnemySpawnPoints { get; set; } = default!;
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
[Node] public ItemDatabase ItemDatabase { get; set; } = default!;
public override void _Ready()
{
SpawnItems();
SpawnItems();
}
public void SpawnEnemies(EnemyDatabase enemyDatabase)
public void SpawnEnemies(Godot.Collections.Dictionary<EnemyType, float> enemyInfo)
{
var rng = new RandomNumberGenerator();
rng.Randomize();
var enemySpawnPoints = EnemySpawnPoints.GetChildren();
var numberOfEnemiesToSpawn = rng.RandiRange(1, enemySpawnPoints.Count);
var rng = new RandomNumberGenerator();
rng.Randomize();
var enemySpawnPoints = EnemySpawnPoints.GetChildren();
var numberOfEnemiesToSpawn = rng.RandiRange(1, enemySpawnPoints.Count);
foreach (var spawnPoint in enemySpawnPoints.Cast<Marker3D>())
{
if (numberOfEnemiesToSpawn <= 0)
break;
numberOfEnemiesToSpawn--;
foreach (var spawnPoint in enemySpawnPoints.Cast<Marker3D>())
{
if (numberOfEnemiesToSpawn <= 0)
break;
numberOfEnemiesToSpawn--;
var enemy = enemyDatabase.EnemyList[rng.RandWeighted(enemyDatabase.SpawnRate)];
var instantiatedEnemy = enemy.Instantiate<Enemy>();
instantiatedEnemy.Position = new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z);
AddChild(instantiatedEnemy);
}
var index = rng.RandWeighted([.. enemyInfo.Values]);
var selectedEnemy = enemyInfo.ElementAt((int)index);
var instantiatedEnemy = EnemyTypeToEnemyConverter.Convert(selectedEnemy.Key);
instantiatedEnemy.Position = new Vector3(spawnPoint.Position.X, 1.75f, spawnPoint.Position.Z);
AddChild(instantiatedEnemy);
}
}
private void SpawnItems()
{
var itemSpawnPoints = ItemSpawnPoints.GetChildren();
var rng = new RandomNumberGenerator();
rng.Randomize();
var numberOfItemsToSpawn = rng.RandiRange(1, itemSpawnPoints.Count);
itemSpawnPoints.Shuffle();
var database = new ItemDatabase();
foreach (var spawnPoint in itemSpawnPoints.Cast<Marker3D>())
{
if (numberOfItemsToSpawn <= 0)
break;
numberOfItemsToSpawn--;
if (ItemSpawnPoints == null)
return;
var selectedItem = database.PickItem<InventoryItem>();
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
duplicated.Position = new Vector3(spawnPoint.Position.X, -1.5f, spawnPoint.Position.Z);
AddChild(duplicated);
}
var itemSpawnPoints = ItemSpawnPoints.GetChildren();
var rng = new RandomNumberGenerator();
rng.Randomize();
var numberOfItemsToSpawn = rng.RandiRange(1, itemSpawnPoints.Count);
itemSpawnPoints.Shuffle();
var database = new ItemDatabase();
foreach (var spawnPoint in itemSpawnPoints.Cast<Marker3D>())
{
if (numberOfItemsToSpawn <= 0)
break;
numberOfItemsToSpawn--;
var selectedItem = database.PickItem<InventoryItem>();
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
duplicated.Position = new Vector3(spawnPoint.Position.X, -1.5f, spawnPoint.Position.Z);
AddChild(duplicated);
}
}
}