Files
2026-05-10 11:47:55 -04:00

164 lines
6.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<GameObject> 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<int> unitedStackThreshold = 1;
[Tooltip("开启:检测独立堆叠模块(IndependentStackSubmodule) 的总层数")]
public bool checkIndependentStack = false;
public Operation independentStackOperation = Operation.GreaterThanOrEqualTo;
[Tooltip("所需的堆叠总层数 (IndependentStack)")]
public SharedVariable<int> independentStackThreshold = 1;
[Tooltip("开启:检测时间模块(TimeSubmodule) 的剩余时间")]
public bool checkTimeSubmodule = false;
public Operation timeOperation = Operation.LessThanOrEqualTo;
[Tooltip("所需的剩余时间")]
public SharedVariable<float> timeThreshold = 3f;
private CharacterBase GetTarget()
{
if (target != null && target.Value != null)
return target.Value.GetComponent<CharacterBase>();
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;
}
}
}