using System; using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine; namespace SLSUtilities.Narrative { /// /// 一个 NarrativeEntry 对应一个“剧情触发源”(如一个 NPC、一个区域、一个道具)。 /// 它包含一个有序的条件→节点路由列表。 /// [CreateAssetMenu(fileName = "NarrativeEntry", menuName = "SLSUtilities/Story System/Narrative Entry")] public class NarrativeEntry : SerializedScriptableObject { [TitleGroup("Identity", "剧情触发源身份标识", Alignment = TitleAlignments.Centered)] [Required] [Tooltip("全局唯一标识,对应 NPC 或触发器的 storyId (如 'OldMan', 'Forest_Gate')")] public string storyId; [TitleGroup("Routing Rules", "路由规则表 (从上到下评估,首个满足的生效)", Alignment = TitleAlignments.Centered)] [ListDrawerSettings(ShowPaging = true, NumberOfItemsPerPage = 10)] public List routes = new List(); [TitleGroup("Fallback", "兜底处理 (当所有路由条件都不满足时播什么)", Alignment = TitleAlignments.Centered)] [Tooltip("兜底节点(可为空,为空则不播放任何对话)")] public string fallbackNode; } /// /// 单条路由规则:描述备注 + 条件列表 + 目标 Yarn 节点。 /// [Serializable] public class NarrativeRoute { [LabelText("描述 (仅编辑器备注)")] [Required] [Tooltip("例如:'第一次见面'、'已购买提灯后'")] public string editorNote; [LabelText("条件列表 (全部满足才匹配)")] [ListDrawerSettings(ShowIndexLabels = false)] public List conditions = new List(); [LabelText("目标 Yarn 节点")] [Required] [Tooltip("满足上述条件时播放的 Yarn Node 名称 (如 'OldMan_FirstMeet')")] public string targetNode; } /// /// 单个变量匹配条件:变量类型 + 变量名 + 比较方式 + 目标值。 /// [Serializable] public class NarrativeCondition { public enum ConditionType { Bool, Int, Float, String } public enum CompareOp { [LabelText("==")] Equal, [LabelText("!=")] NotEqual, [LabelText(">")] Greater, [LabelText(">=")] GreaterOrEqual, [LabelText("<")] Less, [LabelText("<=")] LessOrEqual } [HorizontalGroup("Cond", Width = 70)] [HideLabel] public ConditionType type = ConditionType.Bool; [HorizontalGroup("Cond")] [HideLabel] [Required] [Tooltip("StorySystem 变量名 (如 'has_lantern')")] public string key; [HorizontalGroup("Cond", Width = 60)] [HideLabel] public CompareOp op = CompareOp.Equal; [HorizontalGroup("Cond")] [HideLabel] [Required] [Tooltip("对比的值,布尔值请填 true/false,其他按相应格式填写")] public string value; } }