Files
ichni_Official/Assets/Scripts/NewStorySystem/Data/StoryConditionNode.cs
2026-07-05 16:08:23 -04:00

140 lines
4.8 KiB
C#
Raw 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 System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Ichni.Story
{
/// <summary>
/// 解锁条件树的节点基类。通过多态组合出"与 / 或 / 非 + 叶子条件"的复合表达式。
/// 由 <see cref="UnlockCondition"/> 借助 <c>[SerializeReference]</c> 序列化持有,
/// Odin 会以类型下拉框展示可选的节点类型。
/// </summary>
[Serializable]
public abstract class StoryConditionNode
{
/// <summary>
/// 对该节点求值。
/// </summary>
/// <param name="getVariable">按变量名返回其整型值的委托。</param>
/// <param name="isBlockCompleted">按 blockId 判断该 block 是否已完成的委托。</param>
public abstract bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted);
}
/// <summary>
/// 复合节点(逻辑与 AND所有子条件均满足时才满足。子列表为空视为满足。
/// </summary>
[Serializable]
[LabelText("All Of (AND)")]
public class AllOfCondition : StoryConditionNode
{
[HideLabel]
[SerializeReference]
[ListDrawerSettings(ShowFoldout = true, DefaultExpandedState = true)]
public List<StoryConditionNode> conditions = new List<StoryConditionNode>();
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
foreach (StoryConditionNode child in conditions)
{
if (child != null && !child.Evaluate(getVariable, isBlockCompleted))
return false;
}
return true;
}
}
/// <summary>
/// 复合节点(逻辑或 OR任一子条件满足即满足。子列表为空视为不满足。
/// </summary>
[Serializable]
[LabelText("Any Of (OR)")]
public class AnyOfCondition : StoryConditionNode
{
[HideLabel]
[SerializeReference]
[ListDrawerSettings(ShowFoldout = true, DefaultExpandedState = true)]
public List<StoryConditionNode> conditions = new List<StoryConditionNode>();
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
if (conditions.Count == 0)
return false;
foreach (StoryConditionNode child in conditions)
{
if (child != null && child.Evaluate(getVariable, isBlockCompleted))
return true;
}
return false;
}
}
/// <summary>
/// 复合节点(逻辑非 NOT对子条件取反。子条件为空视为满足等价于"非 假")。
/// </summary>
[Serializable]
[LabelText("Not")]
public class NotCondition : StoryConditionNode
{
[HideLabel]
[SerializeReference]
public StoryConditionNode condition;
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
return condition == null || !condition.Evaluate(getVariable, isBlockCompleted);
}
}
/// <summary>
/// 叶子节点:指定 block 已完成时满足。
/// </summary>
[Serializable]
[LabelText("Block Completed")]
public class BlockCompletedCondition : StoryConditionNode
{
[LabelText("Block ID")]
public string blockId;
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
return !string.IsNullOrEmpty(blockId) && isBlockCompleted(blockId);
}
}
/// <summary>
/// 叶子节点:将指定变量的当前值与目标值按比较方式求值。
/// </summary>
[Serializable]
[LabelText("Variable Compare")]
public class VariableCondition : StoryConditionNode
{
[LabelText("Variable Name")]
public string variableName;
[LabelText("Comparison")]
public VariableComparison comparison;
[LabelText("Value")]
public int value;
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
int actual = getVariable(variableName);
return comparison switch
{
VariableComparison.Equal => actual == value,
VariableComparison.NotEqual => actual != value,
VariableComparison.Greater => actual > value,
VariableComparison.GreaterOrEqual => actual >= value,
VariableComparison.Less => actual < value,
VariableComparison.LessOrEqual => actual <= value,
_ => false
};
}
}
}