using System; using System.Collections.Generic; using System.Text.Json; using Config; using Godot; /// <summary> /// 主动使用道具 /// </summary> [Tool] public partial class ActiveProp : PropActivity, IPackageItem<Role> { /// <summary> /// 配置数据 /// </summary> public ExcelConfig.ActivePropBase Attribute { get; private set; } public int PackageIndex { get; set; } /// <summary> /// 道具可使用次数 /// </summary> public int Count { get => _count; set { var temp = _count; _count = Mathf.Clamp(value, 0, _maxCount); if (temp != _count) { OnChangeCount(); } } } private int _count = 1; /// <summary> /// 道具最大叠加用次数 /// </summary> public int MaxCount { get => _maxCount; set { var temp = _maxCount; _maxCount = Mathf.Max(1, value); if (temp != _maxCount) { OnChangeMaxCount(); } if (Count > _maxCount) { Count = _maxCount; } } } private int _maxCount = 1; /// <summary> /// 道具充能进度, 必须要充能完成才能使用, 值范围: 0 - 1 /// </summary> public float ChargeProgress { get => _chargeProgress; set { var temp = _chargeProgress; _chargeProgress = Mathf.Clamp(value, 0, 1); if (temp != _chargeProgress) { OnChangeChargeProgress(); } } } private float _chargeProgress = 1; /// <summary> /// 自动充能速度, 也就是每秒充能进度, 如果为0则表示不就行自动充能 /// </summary> public float AutoChargeSpeed { get; set; } /// <summary> /// 是否正使用中 /// </summary> public bool IsUsing => _durationTimer > 0; /// <summary> /// 道具使用时间进度 (0 - 1) /// </summary> public float UsingProgress => 1 - _durationTimer / Attribute.Duration; //冷却计时器 private float _cooldownTimer = 0; //持续时间计时器 private float _durationTimer = 0; //被动属性 private readonly List<BuffFragment> _buffFragment = new List<BuffFragment>(); //条件 private readonly List<ConditionFragment> _conditionFragment = new List<ConditionFragment>(); //效果 private readonly List<EffectFragment> _effectFragment = new List<EffectFragment>(); //充能 private readonly List<ChargeFragment> _chargeFragment = new List<ChargeFragment>(); public override void OnInit() { base.OnInit(); var buffAttribute = GetActiveAttribute(ActivityBase.Id); Attribute = buffAttribute; //初始化buff属性 if (buffAttribute.Buff != null) { foreach (var keyValuePair in buffAttribute.Buff) { var buffInfo = PropFragmentRegister.BuffFragmentInfos[keyValuePair.Key]; var item = keyValuePair.Value; var buff = (BuffFragment)AddComponent(buffInfo.Type); try { buff.InitParam(item); } catch (Exception e) { Debug.LogError($"初始化道具'{ActivityBase.Id}'参数时发生异常: {e.Message}\n{e.StackTrace}"); } _buffFragment.Add(buff); } } //初始化条件属性 if (buffAttribute.Condition != null) { foreach (var keyValuePair in buffAttribute.Condition) { var buffInfo = PropFragmentRegister.ConditionFragmentInfos[keyValuePair.Key]; var item = keyValuePair.Value; var buff = (ConditionFragment)AddComponent(buffInfo.Type); try { buff.InitParam(item); } catch (Exception e) { Debug.LogError($"初始化道具'{ActivityBase.Id}'参数时发生异常: {e.Message}\n{e.StackTrace}"); } _conditionFragment.Add(buff); } } //初始化效果属性 if (buffAttribute.Effect != null) { foreach (var keyValuePair in buffAttribute.Effect) { var buffInfo = PropFragmentRegister.EffectFragmentInfos[keyValuePair.Key]; var item = keyValuePair.Value; var buff = (EffectFragment)AddComponent(buffInfo.Type); try { buff.InitParam(item); } catch (Exception e) { Debug.LogError($"初始化道具'{ActivityBase.Id}'参数时发生异常: {e.Message}\n{e.StackTrace}"); } _effectFragment.Add(buff); } } //初始化道具冷却属性数据 if (!buffAttribute.IsConsumables && buffAttribute.Charge != null) { foreach (var keyValuePair in buffAttribute.Charge) { var buffInfo = PropFragmentRegister.ChargeFragmentInfos[keyValuePair.Key]; var item = keyValuePair.Value; var buff = (ChargeFragment)AddComponent(buffInfo.Type); try { buff.InitParam(item); } catch (Exception e) { Debug.LogError($"初始化道具'{ActivityBase.Id}'参数时发生异常: {e.Message}\n{e.StackTrace}"); } _chargeFragment.Add(buff); } } //显示纹理 if (!string.IsNullOrEmpty(ActivityBase.Icon)) { SetDefaultTexture(ResourceManager.LoadTexture2D(ActivityBase.Icon)); } MaxCount = (int)Attribute.MaxCount; } /// <summary> /// 当检测是否可以使用时调用 /// </summary> public virtual bool OnCheckUse() { foreach (var fragment in _conditionFragment) { if (!fragment.OnCheckUse()) return false; } foreach (var fragment in _effectFragment) { if (!fragment.OnCheckUse()) return false; } return true; } /// <summary> /// 当道具被使用时调用 /// </summary> protected virtual void OnUse() { foreach (var fragment in _effectFragment) { fragment.OnUse(); } foreach (var fragment in _chargeFragment) { fragment.OnUse(); } } /// <summary> /// 道具使用持续时间完成时调用 /// </summary> protected virtual void OnUsingFinish() { } /// <summary> /// 道具数量改变时调用 /// </summary> protected virtual void OnChangeCount() { } /// <summary> /// 道具最大数量改变时调用 /// </summary> protected virtual void OnChangeMaxCount() { } /// <summary> /// 道具充能进度改变时调用 /// </summary> protected virtual void OnChangeChargeProgress() { } /// <summary> /// 冷却完成时调用 /// </summary> protected virtual void OnCooldownFinish() { } protected override void Process(float delta) { if (CheckAutoDestroy()) { return; } //持续时间 if (_durationTimer > 0) { _durationTimer -= delta; //持续时间完成 if (_durationTimer <= 0) { _durationTimer = 0; //冷却计时器 _cooldownTimer = Attribute.CooldownTime; UsingFinish(); } } //冷却 else if (_cooldownTimer > 0) { _cooldownTimer -= delta; //冷却完成 if (_cooldownTimer <= 0) { _cooldownTimer = 0; OnCooldownFinish(); } } //自动充能 if (AutoChargeSpeed > 0 && ChargeProgress < 1) { ChargeProgress += AutoChargeSpeed * delta; } } //检测是否达到自动销毁的条件 private bool CheckAutoDestroy() { if (Count == 0 && Attribute.IsConsumables) //用光了, 自动销毁 { if (Master != null) { Master.ActivePropsPack.RemoveItem(this); } Destroy(); return true; } return false; } /// <summary> /// 检测是否可以使用当前道具 /// </summary> public bool CheckUse() { return ChargeProgress >= 1 && _cooldownTimer <= 0 && Count > 0 && OnCheckUse(); } /// <summary> /// 触发使用道具 /// </summary> public void Use() { if (Master == null || IsUsing) { return; } if (CheckUse()) //可以使用道具 { OnUse(); if (Attribute.IsConsumables) { Count -= 1; } if (Attribute.Duration > 0) //持续时间 { _durationTimer = Attribute.Duration; } else { //冷却计时器 _cooldownTimer = Attribute.CooldownTime; UsingFinish(); } } } /// <summary> /// 获取冷却进度 0 - 1 /// </summary> public float GetCooldownProgress() { if (_cooldownTimer <= 0) { return 1; } return (Attribute.CooldownTime - _cooldownTimer) / Attribute.CooldownTime; } public override void Interactive(ActivityObject master) { if (master is Role player) { if (player.ActivePropsPack.Capacity == 0) { //容量为0 return; } var item = player.ActivePropsPack.GetItemById(ActivityBase.Id); if (item == null) //没有同类型物体 { if (!player.ActivePropsPack.HasVacancy()) //没有空位置, 扔掉当前道具 { player.ThrowActiveProp(player.ActivePropsPack.ActiveIndex); } //替换手中的道具 if (player.PickUpActiveProp(this)) { Pickup(); } } else { //处理同类型道具 if (item.Count < item.MaxCount) //允许叠加 { if (item.Count + Count > item.MaxCount) { Count -= item.MaxCount - item.Count; item.Count = item.MaxCount; } else { item.Count += Count; Count = 0; } Destroy(); } } } } public override CheckInteractiveResult CheckInteractive(ActivityObject master) { if (master is Role player) { if (player.ActivePropsPack.Capacity == 0) { //容量为0 return new CheckInteractiveResult(this); } //查找相同类型的道具 var item = player.ActivePropsPack.GetItemById(ActivityBase.Id); if (item == null) //没有同类型物体 { if (player.ActivePropsPack.HasVacancy()) //还有空位, 拾起道具 { return new CheckInteractiveResult(this, true, CheckInteractiveResult.InteractiveType.PickUp); } //替换手中的道具 return new CheckInteractiveResult(this, true, CheckInteractiveResult.InteractiveType.Replace); } //处理同类型道具 if (item.Count < item.MaxCount) //允许叠加 { return new CheckInteractiveResult(this, true, CheckInteractiveResult.InteractiveType.Bullet); } //该道具不能拾起 return new CheckInteractiveResult(this); } return new CheckInteractiveResult(this); } public override void OnPickUpItem() { foreach (var buffFragment in _buffFragment) { buffFragment.OnPickUpItem(); } foreach (var conditionFragment in _conditionFragment) { conditionFragment.OnPickUpItem(); } foreach (var effectFragment in _effectFragment) { effectFragment.OnPickUpItem(); } foreach (var chargeFragment in _chargeFragment) { chargeFragment.OnPickUpItem(); } } public override void OnRemoveItem() { foreach (var buffFragment in _buffFragment) { buffFragment.OnRemoveItem(); } foreach (var conditionFragment in _conditionFragment) { conditionFragment.OnRemoveItem(); } foreach (var effectFragment in _effectFragment) { effectFragment.OnRemoveItem(); } foreach (var chargeFragment in _chargeFragment) { chargeFragment.OnRemoveItem(); } } public virtual void OnActiveItem() { } public virtual void OnConcealItem() { } public virtual void OnOverflowItem() { Master.ThrowActiveProp(PackageIndex); } /// <summary> /// 添加被动属性 /// </summary> public void AddBuffFragment<T>(JsonElement[] arg) where T : BuffFragment, new() { var fragment = AddComponent<T>(); _buffFragment.Add(fragment); try { fragment.InitParam(arg); } catch (Exception e) { Debug.LogError($"初始化道具'{ActivityBase.Id}'参数时发生异常: {e.Message}\n{e.StackTrace}"); } if (Master != null) { fragment.OnPickUpItem(); } } //持续时间完成 private void UsingFinish() { OnUsingFinish(); foreach (var effectFragment in _effectFragment) { effectFragment.OnUsingFinish(); } foreach (var chargeFragment in _chargeFragment) { chargeFragment.OnUsingFinish(); } } private static bool _init = false; private static Dictionary<string, ExcelConfig.ActivePropBase> _activeAttributeMap = new Dictionary<string, ExcelConfig.ActivePropBase>(); /// <summary> /// 初始化主动道具属性数据 /// </summary> public static void InitActiveAttribute() { if (_init) { return; } _init = true; foreach (var buffAttr in ExcelConfig.ActivePropBase_List) { if (buffAttr.Activity != null) { if (!_activeAttributeMap.TryAdd(buffAttr.Activity.Id, buffAttr)) { Debug.LogError("发现重复注册的主动道具属性: " + buffAttr.Id); } } } } /// <summary> /// 根据 ActivityBase.Id 获取对应主动道具的属性数据 /// </summary> public static ExcelConfig.ActivePropBase GetActiveAttribute(string itemId) { if (itemId == null) { return null; } if (_activeAttributeMap.TryGetValue(itemId, out var attr)) { return attr; } throw new Exception($"主动道具'{itemId}'没有在 ActivePropBase 表中配置属性数据!"); } }