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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|