using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Cielonos.MainGame.Characters.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
}
}