enemy spawner

This commit is contained in:
2025-10-26 14:17:31 +01:00
parent 20d3b46834
commit 40a62b5b5a
2102 changed files with 1255290 additions and 70 deletions

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Game.Scripts.Runtime.Data
{
[CreateAssetMenu(menuName = "Game/Spawning/Spawn Table", fileName = "SpawnTable")]
public class SpawnTable : ScriptableObject
{
[Serializable]
public class Entry
{
public EnemyDefinition Def;
[Min(0)] public int Weight = 1;
public int MinWave = 0;
public int MaxWave = int.MaxValue;
[Tooltip("Optional cap per wave. Values <= 0 mean unlimited.")]
public int Cap = -1;
public bool IsWaveValid(int wave) => wave >= MinWave && wave <= MaxWave;
public bool IsUnderCap(int currentCount)
{
if (Cap <= 0)
{
return true;
}
return currentCount < Cap;
}
}
[SerializeField] private List<Entry> entries = new();
private readonly List<Entry> _eligibleBuffer = new();
public IReadOnlyList<Entry> Entries => entries;
public EnemyDefinition Pick(int wave, System.Random rng)
{
if (entries == null || entries.Count == 0)
{
return null;
}
_eligibleBuffer.Clear();
foreach (var entry in entries)
{
if (entry?.Def == null || entry.Weight <= 0)
{
continue;
}
if (entry.IsWaveValid(wave))
{
_eligibleBuffer.Add(entry);
}
}
if (_eligibleBuffer.Count == 0)
{
return null;
}
var totalWeight = 0;
foreach (var entry in _eligibleBuffer)
{
totalWeight += Mathf.Max(1, entry.Weight);
}
var roll = rng.Next(totalWeight);
foreach (var entry in _eligibleBuffer)
{
var weight = Mathf.Max(1, entry.Weight);
if (roll < weight)
{
return entry.Def;
}
roll -= weight;
}
return _eligibleBuffer[^1].Def;
}
public IEnumerable<Entry> EnumerateEligibleEntries(int wave)
{
if (entries == null)
{
yield break;
}
foreach (var entry in entries)
{
if (entry?.Def == null || entry.Weight <= 0)
{
continue;
}
if (entry.IsWaveValid(wave))
{
yield return entry;
}
}
}
}
}