using System; using System.Collections.Generic; using UnityEngine; namespace BaseGames.Player { /// /// 武器管理器。 /// 监听 FormController.OnFormChanged,依据当前形态切换 ActiveWeapon。 /// 支持护符 Override:护符调用 SetOverride() 临时替换特定形态的武器。 /// 架构 05_PlayerModule §7。 /// public class WeaponManager : MonoBehaviour { [SerializeField] private FormController _formController; [SerializeField] private WeaponSO _startingWeapon; // 无 FormController 时的回退武器 [Header("HitBox 挂载点")] [Tooltip("武器 HitBox Prefab 实例化的父节点,应为 Player 层级下的 [WeaponSocket] 子节点。")] [SerializeField] private Transform _weaponSocket; public WeaponSO ActiveWeapon { get; private set; } public WeaponHitBoxInstance ActiveHitBoxInstance { get; private set; } public event Action OnWeaponChanged; // 护符注入的武器覆盖:Key = FormSO.formId,Value = 替换武器(架构 05 §7) private readonly Dictionary _overrides = new(); // 对象池:避免每次切换形态时 Instantiate/Destroy(Key = WeaponSO,Value = 已创建实例) private readonly Dictionary _hitBoxPool = new(); private void Awake() { if (_formController != null && _formController.CurrentForm != null) ApplyWeapon(_formController.CurrentForm); else if (_startingWeapon != null) SetDirectWeapon(_startingWeapon); } private void OnEnable() { if (_formController != null) _formController.OnFormChanged += HandleFormChanged; } private void OnDisable() { if (_formController != null) _formController.OnFormChanged -= HandleFormChanged; } private void Start() { // 若 FormController 在 Awake 时 CurrentForm 尚未初始化,在 Start 重试 if (ActiveWeapon == null && _formController != null && _formController.CurrentForm != null) ApplyWeapon(_formController.CurrentForm); else if (ActiveWeapon == null && _startingWeapon != null) SetDirectWeapon(_startingWeapon); } // ── 内部切换 ─────────────────────────────────────────────────────────── private void HandleFormChanged() => ApplyWeapon(_formController.CurrentForm); private void ApplyWeapon(FormSO form) { if (form == null) return; WeaponSO next = _overrides.TryGetValue(form.formId, out var ov) ? ov : form.defaultWeapon; if (next == ActiveWeapon) return; SetDirectWeapon(next); } private void SetDirectWeapon(WeaponSO weapon) { // 归还旧实例到池(SetActive(false) 会触发 HitBox.OnDisable → Deactivate,自动关闭 Collider2D) ActiveHitBoxInstance?.gameObject.SetActive(false); ActiveWeapon = weapon; ActiveHitBoxInstance = null; if (weapon?.hitBoxPrefab != null && _weaponSocket != null) { if (!_hitBoxPool.TryGetValue(weapon, out var pooled) || pooled == null) { var go = Instantiate(weapon.hitBoxPrefab, _weaponSocket); pooled = go.GetComponent(); _hitBoxPool[weapon] = pooled; } pooled.gameObject.SetActive(true); ActiveHitBoxInstance = pooled; } // 通知订阅者(PlayerCombat 取消旧实例事件订阅,订阅新实例) OnWeaponChanged?.Invoke(weapon); } private void OnDestroy() { foreach (var inst in _hitBoxPool.Values) if (inst != null) Destroy(inst.gameObject); _hitBoxPool.Clear(); } // ── 护符 Override API(由 WeaponOverrideEffect 调用,架构 05 §7)────── /// 为指定形态设置武器覆盖。formId 为空 = 覆盖所有形态。 public void SetOverride(string formId, WeaponSO weapon) { if (string.IsNullOrEmpty(formId)) { if (_formController != null) foreach (var f in _formController.AllForms) _overrides[f.formId] = weapon; } else { _overrides[formId] = weapon; } if (_formController?.CurrentForm != null) ApplyWeapon(_formController.CurrentForm); } /// 移除覆盖,恢复默认武器。formId 为空 = 移除所有形态覆盖。 public void ClearOverride(string formId) { if (string.IsNullOrEmpty(formId)) { _overrides.Clear(); } else { _overrides.Remove(formId); } if (_formController?.CurrentForm != null) ApplyWeapon(_formController.CurrentForm); } } }