using System; using Cielonos.MainGame.Buffs.Character; using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.GraphDesigner.Runtime; using Opsive.GraphDesigner.Runtime.Variables; using Opsive.Shared.Utility; using UnityEngine; namespace Cielonos.MainGame.Characters.AI { [Description("模块化地检测目标身上是否满足指定的 Buff 状态(默认检测存在性,可选择开启堆叠或时间检测)。所有开启的条件必须同时满足。")] [NodeIcon("Assets/Sprites/Icon/Condition.png")] [Category("Cielonos/Buffs")] public class CheckBuff : AutomataConditionalBase { public enum Operation { LessThan, LessThanOrEqualTo, EqualTo, NotEqualTo, GreaterThanOrEqualTo, GreaterThan } [Tooltip("目标对象。留空则默认检测 AI 自身。")] public SharedVariable target; [Tooltip("选择要检测的 Buff 类型。")] [SerializeReference] public ICharacterBuffFactory buffFactory; [Tooltip("True 意味着该 Buff 必须存在且符合所有开启的具体指标;False 意味着该 Buff 绝不能存在。")] public bool checkExist = true; [Tooltip("开启:检测统一堆叠模块(UnitedStackSubmodule) 的层数")] public bool checkUnitedStack = false; public Operation unitedStackOperation = Operation.GreaterThanOrEqualTo; [Tooltip("所需的堆叠层数 (UnitedStack)")] public SharedVariable unitedStackThreshold = 1; [Tooltip("开启:检测独立堆叠模块(IndependentStackSubmodule) 的总层数")] public bool checkIndependentStack = false; public Operation independentStackOperation = Operation.GreaterThanOrEqualTo; [Tooltip("所需的堆叠总层数 (IndependentStack)")] public SharedVariable independentStackThreshold = 1; [Tooltip("开启:检测时间模块(TimeSubmodule) 的剩余时间")] public bool checkTimeSubmodule = false; public Operation timeOperation = Operation.LessThanOrEqualTo; [Tooltip("所需的剩余时间")] public SharedVariable timeThreshold = 3f; private CharacterBase GetTarget() { if (target != null && target.Value != null) return target.Value.GetComponent(); return self; } public override TaskStatus OnUpdate() { if (buffFactory == null) { Debug.LogWarning("[CheckBuff] 未配置检测的 Buff 类型。"); return TaskStatus.Failure; } var character = GetTarget(); if (character == null) return TaskStatus.Failure; CharacterBuffBase dummyBuff = buffFactory.Create(); Type targetBuffType = dummyBuff.GetType(); CharacterBuffBase existingBuff = character.buffSm.buffList.Find(x => x.GetType() == targetBuffType); // ============================================ // 1. 存在性判定(最高优先级的决断) // ============================================ if (checkExist == false) { // 期望 Buff 不存在。如果它确实不存在,返回 Success,反之失败。 return existingBuff == null ? TaskStatus.Success : TaskStatus.Failure; } // 从这里往下,期望 Buff【必须存在】 if (existingBuff == null) { return TaskStatus.Failure; } // ============================================ // 2. 深入各个子模块检测(只检查开启项,且必须 ALL AND) // ============================================ // 统一堆叠检查 if (checkUnitedStack) { if (existingBuff.unitedStackSubmodule == null) return TaskStatus.Failure; if (!Compare(existingBuff.unitedStackSubmodule.stackAmount, unitedStackOperation, unitedStackThreshold.Value)) return TaskStatus.Failure; } // 独立堆叠检查 if (checkIndependentStack) { if (existingBuff.independentStackSubmodule == null) return TaskStatus.Failure; if (!Compare(existingBuff.independentStackSubmodule.totalStackAmount, independentStackOperation, independentStackThreshold.Value)) return TaskStatus.Failure; } // 剩余时间检查 if (checkTimeSubmodule) { if (existingBuff.timeSubmodule == null) return TaskStatus.Failure; if (!Compare(existingBuff.timeSubmodule.timeLeft, timeOperation, timeThreshold.Value)) return TaskStatus.Failure; } // 全部过关了 return TaskStatus.Success; } private bool Compare(float value1, Operation operation, float value2) { switch (operation) { case Operation.LessThan: return value1 < value2; case Operation.LessThanOrEqualTo: return value1 <= value2; case Operation.EqualTo: return Mathf.Approximately(value1, value2); case Operation.NotEqualTo: return !Mathf.Approximately(value1, value2); case Operation.GreaterThanOrEqualTo: return value1 >= value2; case Operation.GreaterThan: return value1 > value2; } return false; } public override void Reset() { base.Reset(); target = null; buffFactory = null; checkExist = true; checkUnitedStack = false; unitedStackOperation = Operation.GreaterThanOrEqualTo; unitedStackThreshold = 1; checkIndependentStack = false; independentStackOperation = Operation.GreaterThanOrEqualTo; independentStackThreshold = 1; checkTimeSubmodule = false; timeOperation = Operation.LessThanOrEqualTo; timeThreshold = 3f; } } }