// Assets/_Project/Scripts/Gameplay/EnemyAbilities/EnemyAbilityPool.cs using System; using UnityEngine; using TD.Core; namespace TD.Gameplay.EnemyAbilities { /// /// Scene singleton holding every available this match, /// authored as a flat array in the inspector for convenience. Internally it builds a /// fixed-size table indexed by so lookups are a single array /// access, not a scan. Mirrors exactly. /// /// /// Plain MonoBehaviour: identical on every peer (same assets), so there is nothing to sync. /// /// Lookup only — no rolling. This pool used to draw a random ability per spawned /// enemy against a "no ability" weight. Under the 2.0 design abilities are chosen by the /// players' post-wave vote and apply to every enemy in the wave, so the draw moved to /// WaveVote (over cards, not abilities) and this is purely the kind→asset table /// WaveManager resolves against at spawn time. /// public class EnemyAbilityPool : MonoBehaviour { public static EnemyAbilityPool Instance { get; private set; } [Tooltip("Every EnemyAbilityDefinition asset available this match. One entry per " + "EnemyAbilityKind — order doesn't matter, Kind on the asset itself decides " + "its slot.")] [SerializeField] private EnemyAbilityDefinition[] abilities; // Fixed-size, enum-indexed lookup built once in Awake. Sized to the enum's entry count, // not authored count, so an out-of-range Kind is a compile-time impossibility rather // than a bounds check we'd otherwise need on every Get(). private EnemyAbilityDefinition[] byKind; private void Awake() { if (Instance != null && Instance != this) { Debug.LogError("[EnemyAbilityPool] Multiple instances detected. Only one per scene."); return; } Instance = this; int kindCount = Enum.GetValues(typeof(EnemyAbilityKind)).Length; byKind = new EnemyAbilityDefinition[kindCount]; if (abilities == null) return; for (int i = 0; i < abilities.Length; i++) { var def = abilities[i]; if (def == null) continue; byKind[(int)def.Kind] = def; } } private void OnDestroy() { if (Instance == this) Instance = null; } /// Returns the ability asset for , or null if none is /// authored in this pool. public EnemyAbilityDefinition Get(EnemyAbilityKind kind) { int i = (int)kind; return (byKind != null && i >= 0 && i < byKind.Length) ? byKind[i] : null; } } }