164 lines
6.2 KiB
C#
164 lines
6.2 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|