enemy spawner
This commit is contained in:
107
Game/Scripts/Runtime/Data/SpawnTable.cs
Normal file
107
Game/Scripts/Runtime/Data/SpawnTable.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user