剧情+对话完善

This commit is contained in:
SoulliesOfficial
2026-07-21 15:24:42 -04:00
parent 8f230831e9
commit 810d019619
161 changed files with 7271 additions and 1893 deletions

View File

@@ -19,6 +19,13 @@ namespace Ichni.Story
/// <param name="getVariable">按变量名返回其整型值的委托。</param>
/// <param name="isBlockCompleted">按 blockId 判断该 Block 是否已完成的委托。</param>
public abstract bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted);
#if UNITY_EDITOR
/// <summary>
/// 返回 Inspector 中使用的紧凑摘要。条件编辑器只读取该文本,不影响运行时求值逻辑。
/// </summary>
public virtual string GetEditorSummary() => GetType().Name;
#endif
}
/// <summary>
@@ -43,6 +50,10 @@ namespace Ichni.Story
return true;
}
#if UNITY_EDITOR
public override string GetEditorSummary() => $"All Of ({conditions?.Count ?? 0})";
#endif
}
/// <summary>
@@ -70,6 +81,10 @@ namespace Ichni.Story
return false;
}
#if UNITY_EDITOR
public override string GetEditorSummary() => $"Any Of ({conditions?.Count ?? 0})";
#endif
}
/// <summary>
@@ -87,6 +102,10 @@ namespace Ichni.Story
{
return condition == null || !condition.Evaluate(getVariable, isBlockCompleted);
}
#if UNITY_EDITOR
public override string GetEditorSummary() => $"Not ({condition?.GetEditorSummary() ?? "None"})";
#endif
}
/// <summary>
@@ -97,12 +116,20 @@ namespace Ichni.Story
public class BlockCompletedCondition : StoryConditionNode
{
[LabelText("Block ID")]
[LabelWidth(50)]
[Tooltip("必须已完成的 StoryBlock ID。可用于表达显式前置条件通常连接关系已由 Connected Rule 自动处理。")]
public string blockId;
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
{
return !string.IsNullOrEmpty(blockId) && isBlockCompleted(blockId);
}
#if UNITY_EDITOR
public override string GetEditorSummary() => string.IsNullOrWhiteSpace(blockId)
? "Block Completed: <missing ID>"
: $"Block Completed: {blockId}";
#endif
}
/// <summary>
@@ -113,13 +140,22 @@ namespace Ichni.Story
[LabelText("Variable Compare")]
public class VariableCondition : StoryConditionNode
{
[LabelText("Variable Name")]
[HorizontalGroup("VariableComparison", 0.50f)]
[LabelText("Var")]
[LabelWidth(24)]
[Tooltip("章节剧情变量名。使用小写英文、数字和下划线;可由 Yarn 的 set_* 指令写入。")]
public string variableName;
[LabelText("Comparison")]
[HorizontalGroup("VariableComparison", 0.22f)]
[LabelText("Op")]
[LabelWidth(20)]
[Tooltip("变量值与目标值之间的比较方式。")]
public VariableComparison comparison;
[HorizontalGroup("VariableComparison")]
[LabelText("Value")]
[LabelWidth(35)]
[Tooltip("用于比较的整数目标值。Bool 条件使用 0 / 1。")]
public int value;
public override bool Evaluate(Func<string, int> getVariable, Func<string, bool> isBlockCompleted)
@@ -136,5 +172,67 @@ namespace Ichni.Story
_ => false
};
}
#if UNITY_EDITOR
public override string GetEditorSummary()
{
string variable = string.IsNullOrWhiteSpace(variableName) ? "<missing variable>" : variableName;
string operation = comparison switch
{
VariableComparison.Equal => "==",
VariableComparison.NotEqual => "!=",
VariableComparison.Greater => ">",
VariableComparison.GreaterOrEqual => ">=",
VariableComparison.Less => "<",
VariableComparison.LessOrEqual => "<=",
_ => "?"
};
return $"{variable} {operation} {value}";
}
#endif
}
}
#if UNITY_EDITOR
namespace Ichni.Story.Editor
{
/// <summary>
/// 通用 StoryCondition 的 Odin Inspector Drawer。
/// <para>Unlock、Forbidden 与 Helper Availability 共用同一条件模型;此 Drawer 只改变编辑器中的
/// 折叠呈现方式,不修改条件树的序列化结构或运行时求值结果。</para>
/// <para>默认仅显示可读摘要。需要调整条件时再展开,避免 SerializeReference 条件树长期占据 Block 的编辑空间。</para>
/// </summary>
public class StoryConditionDrawer : Sirenix.OdinInspector.Editor.OdinValueDrawer<StoryCondition>
{
private bool _isExpanded;
protected override void DrawPropertyLayout(UnityEngine.GUIContent label)
{
StoryCondition condition = ValueEntry.SmartValue;
string summary = condition == null ? "None" : condition.GetEditorSummary();
// 父属性若保留了简短标签(例如 Helper 的 Availability则与摘要合并显示
// StoryBlock 中使用 HideLabel 时只保留摘要,避免重复占用左侧标签列。
string prefix = label == null || string.IsNullOrWhiteSpace(label.text)
? string.Empty
: $"{label.text}: ";
UnityEngine.GUIContent foldoutLabel = new UnityEngine.GUIContent(
prefix + summary,
"留空表示未配置条件。展开后可选择 All Of (AND)、Any Of (OR)、Not、Block Completed 或 Variable Compare。"
);
_isExpanded = UnityEditor.EditorGUILayout.Foldout(_isExpanded, foldoutLabel, true);
if (!_isExpanded)
{
return;
}
UnityEditor.EditorGUI.indentLevel++;
// 继续调用 Odin 的默认 SerializeReference 绘制链,使类型选择、嵌套条件和 Undo 行为保持原样。
CallNextDrawer(UnityEngine.GUIContent.none);
UnityEditor.EditorGUI.indentLevel--;
}
}
}
#endif