108 lines
2.7 KiB
C#
108 lines
2.7 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|