using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Sirenix.OdinInspector; using UnityEngine; namespace Cielonos.MainGame.Inventory { /// /// 扩展器基类:作为 PassiveEquipment 附着在指定类型的宿主道具上,为其提供额外能力。 /// /// 获取时自动在背包中查找第一个类型匹配的宿主并绑定;丢弃时自动解绑。 /// /// public abstract class ExtenderBase : PassiveEquipmentBase { [ValueDropdown("GetHostTypeOptions")] public Type hostType; /// /// 当前绑定的宿主道具。未绑定时为 null。 /// public ItemBase Host { get; private set; } /// /// 当前扩展器是否已成功绑定到宿主。 /// public bool IsAttached => Host != null; public override void OnObtained() { if (hostType == null) throw new Exception("尚未对Host类型进行初始化,检查子类OnObtained函数,或者在Prefab中否设置了hostType"); base.OnObtained(); ItemBase host = FindHost(); if (host != null) { Attach(host); } else { Debug.LogWarning($"[{GetType().Name}] 背包中未找到类型为 {hostType} 的宿主道具,扩展器暂不生效。"); } } public override void OnDiscarded() { if (IsAttached) { Detach(); } base.OnDiscarded(); } /// /// 将扩展器绑定到指定宿主。若已绑定到其它宿主,会先解绑。 /// public void Attach(ItemBase host) { if (host == null) { Debug.LogWarning($"[{GetType().Name}] 尝试绑定到 null 宿主。"); return; } if (Host == host) return; // 如果已绑定到别的宿主,先解绑 if (IsAttached) { Detach(); } Host = host; host.RegisterExtender(this); OnAttached(host); } /// /// 从当前宿主解绑。 /// public void Detach() { if (!IsAttached) return; ItemBase previousHost = Host; previousHost.UnregisterExtender(this); Host = null; OnDetached(previousHost); } /// /// 扩展器成功绑定到宿主后调用。子类在此订阅事件、修改数据或注入行为。 /// /// 已绑定的宿主道具实例。 protected virtual void OnAttached(ItemBase host) { } /// /// 扩展器从宿主解绑后调用。子类在此清理事件订阅和还原修改。 /// /// 之前绑定的宿主道具实例。 protected virtual void OnDetached(ItemBase previousHost) { } /// /// 在背包中查找第一个类型匹配的宿主道具。 /// 默认搜索所有道具列表(主武器、辅助装备、被动装备)。 /// 子类可重写以自定义查找逻辑(如指定特定实例)。 /// /// 找到的宿主实例,不存在则返回 null。 protected virtual ItemBase FindHost() { var backpack = player.inventorySc.backpackSm; foreach (var mainWeapon in backpack.mainWeapons.Where(mainWeapon => mainWeapon.GetType() == hostType)) { return mainWeapon; } foreach (var support in backpack.supportEquipments.Where(support => support.GetType() == hostType)) { return support; } foreach (var passive in backpack.passiveEquipments.Where(passive => passive.GetType() == hostType)) { return passive; } return null; } #if UNITY_EDITOR /// /// 收集所有可作为宿主的具体道具类型:MainWeaponBase、SupportEquipmentBase、PassiveEquipmentBase /// 的非抽象子类,但排除 ExtenderBase 及其子类。 /// private static IEnumerable> GetHostTypeOptions() { Type[] baseTypes = { typeof(MainWeaponBase), typeof(SupportEquipmentBase), typeof(PassiveEquipmentBase) }; Type extenderType = typeof(ExtenderBase); IEnumerable candidateTypes = Assembly.GetAssembly(typeof(ItemBase)) .GetTypes() .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition) .Where(t => baseTypes.Any(bt => bt.IsAssignableFrom(t))) .Where(t => !extenderType.IsAssignableFrom(t)) .OrderBy(t => t.Name); foreach (Type type in candidateTypes) { string category = GetCategoryLabel(type); yield return new ValueDropdownItem($"{category}/{type.Name}", type); } } private static string GetCategoryLabel(Type type) { if (typeof(MainWeaponBase).IsAssignableFrom(type)) return "MainWeapon"; if (typeof(SupportEquipmentBase).IsAssignableFrom(type)) return "SupportEquipment"; return "PassiveEquipment"; } #endif } }