using System.Collections.Generic; using UnityEngine; namespace BaseGames.Enemies.Abilities { /// /// 能力注册表(架构 07_EnemyModule §8.3)。 /// EnemyBase.Awake 时调用 自动扫描子物体上所有 /// 组件,按 abilityId 建立 O(1) 查询字典。 /// public sealed class EnemyAbilityRegistry { private readonly Dictionary _byId = new Dictionary(8); private readonly List _all = new List(8); /// 所有已注册能力(只读)。 public IReadOnlyList All => _all; public void CollectFrom(GameObject root) { _byId.Clear(); _all.Clear(); root.GetComponentsInChildren(true, _all); for (int i = 0; i < _all.Count; i++) { var ab = _all[i]; if (ab == null || ab.Config == null || string.IsNullOrEmpty(ab.Config.abilityId)) continue; if (_byId.ContainsKey(ab.Config.abilityId)) { Debug.LogError($"[EnemyAbilityRegistry] 重复 abilityId='{ab.Config.abilityId}' 于 {ab.gameObject.name},后注册者被忽略。请检查配置。", ab); continue; } _byId.Add(ab.Config.abilityId, ab); } } public EnemyAbilityBase Get(string abilityId) { if (string.IsNullOrEmpty(abilityId)) return null; _byId.TryGetValue(abilityId, out var ab); return ab; } public T Get() where T : EnemyAbilityBase { for (int i = 0; i < _all.Count; i++) if (_all[i] is T t) return t; return null; } public bool Has(string abilityId) => _byId.ContainsKey(abilityId); public void InterruptAll(InterruptReason reason) { for (int i = 0; i < _all.Count; i++) { var ab = _all[i]; if (ab != null && ab.IsRunning) ab.Interrupt(reason); } } /// /// 中断指定互斥组内所有正在执行的能力。 /// 由 在 Execute 开始时调用,确保同组互斥。 /// public void InterruptGroup(string group, InterruptReason reason = InterruptReason.ExternalRequest) { if (string.IsNullOrEmpty(group)) return; for (int i = 0; i < _all.Count; i++) { var ab = _all[i]; if (ab != null && ab.IsRunning && ab.Config?.exclusionGroup == group) ab.Interrupt(reason); } } } }