Storyline+Dialog初步
This commit is contained in:
139
Assets/Scripts/NewStorySystem/Data/StoryConditionNode.cs
Normal file
139
Assets/Scripts/NewStorySystem/Data/StoryConditionNode.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user