Files
ichni_Official/Assets/Scripts/NewStorySystem/YarnFunctions/StoryTreeCommands.cs

135 lines
6.2 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 Ichni.Story.Dialogue;
using Ichni.Story.UI;
using UnityEngine;
using UnityEngine.Localization.Settings;
using Yarn.Unity;
namespace Ichni.Story.YarnFunctions
{
/// <summary>
/// 包含与故事树节点控制、全局进程、存档交互相关的 Yarn 自定义命令注册器。
/// </summary>
public static class StoryTreeCommands
{
// ── Yarn Commands ────────────────────────────────────────────────────────
/// <summary>
/// 兼容既有 Yarn 脚本:授予歌曲相关的解锁 Key并在当前对话结束后弹出提示。
/// 格式: &lt;&lt;unlock_song unlock_key&gt;&gt;
/// <para>Key 必须使用小写字母、数字和下划线,例如 <c>story_ch0_prologue_completed</c>。</para>
/// 新内容若不需要歌曲提示,优先使用 <see cref="GrantUnlock"/>。
/// </summary>
/// <param name="songUnlockKey">要授予的稳定解锁 Key而不是歌曲显示名称。</param>
[YarnCommand("unlock_song")]
public static void UnlockSong(string songUnlockKey)
{
if (!TryGrantUnlockKey(songUnlockKey, out bool wasNewlyGranted) || !wasNewlyGranted)
{
return;
}
// 将歌曲提示加入对话结束队列。弹窗本地化将由后续 Localization 阶段替换,
// 这里不参与内容是否解锁的授权判断。
if (StoryDialogueController.instance != null)
{
StoryDialogueController.instance.dialogueEndActions.Add(() =>
{
if (MessageUIPage.instance != null)
{
MessageUIPage.instance.ShowUnlockMessage(songUnlockKey);
}
else
{
Debug.LogError("[StoryTreeCommands] 弹窗失败:场景中未找到 StoryMessageBoxUIPage 实例!");
}
});
}
else
{
Debug.LogError("[StoryTreeCommands] 弹窗队列注册失败:未找到 StoryDialogueController 实例!");
}
}
/// <summary>
/// 通用内容解锁命令,可用于章节、歌曲、教程及未来内容。
/// 格式: &lt;&lt;grant_unlock unlock_key&gt;&gt;。
/// 本命令只授予并保存 Key不绑定任何 UI 提示;需要提示时应由 Yarn 额外调用 <c>show_message</c>。
/// </summary>
/// <param name="unlockKey">符合 <see cref="UnlockSaveModule.KeyNamingRule"/> 的稳定解锁 Key。</param>
[YarnCommand("grant_unlock")]
public static void GrantUnlock(string unlockKey)
{
TryGrantUnlockKey(unlockKey, out _);
}
/// <summary>
/// 在对话结束后,弹出一个自定义 MessageBox 提示。
/// 会尝试使用 Unity Localization 进行翻译如果找不到对应条目则回退显示原文本Key
/// 格式: &lt;&lt;show_message titleKey contentKey [tableName]&gt;&gt;
/// </summary>
/// <param name="titleKey">标题文本或本地化键</param>
/// <param name="contentKey">正文文本或本地化键</param>
/// <param name="tableName">Unity Localization 中的 String Table 名称</param>
[YarnCommand("show_message")]
public static void ShowMessage(string titleKey, string contentKey, string tableName = "Message")
{
string translatedTitle = GetTranslatedText(tableName, titleKey);
string translatedContent = GetTranslatedText(tableName, contentKey);
Debug.Log($"[StoryTreeCommands] 准备在对话结束后显示自定义弹窗:标题='{translatedTitle}',内容='{translatedContent}'");
StoryDialogueController.instance.dialogueEndActions.Add(() =>
{
MessageUIPage.instance.ShowCustomMessage(translatedTitle, translatedContent);
});
}
/// <summary>
/// 所有 Yarn 解锁命令共用的授予入口。它负责模块存在性检查、重复授予的幂等处理及立即 ES3 保存。
/// </summary>
/// <returns>模块已正常处理该 Key 时返回 trueKey 非法或模块尚未初始化时返回 false。</returns>
private static bool TryGrantUnlockKey(string unlockKey, out bool wasNewlyGranted)
{
wasNewlyGranted = false;
UnlockSaveModule unlockSaveModule = GameSaveManager.instance?.UnlockSaveModule;
if (unlockSaveModule == null)
{
Debug.LogError("[StoryTreeCommands] 无法授予解锁 KeyUnlockSaveModule 尚未初始化!");
return false;
}
if (unlockSaveModule.HasKey(unlockKey))
{
Debug.Log($"[StoryTreeCommands] 解锁 Key 已存在:{unlockKey}");
return true;
}
wasNewlyGranted = unlockSaveModule.GrantKey(unlockKey);
if (wasNewlyGranted)
{
Debug.Log($"[StoryTreeCommands] 已成功写入并保存解锁 Key{unlockKey}");
}
return wasNewlyGranted;
}
// ── 内部辅助 ─────────────────────────────────────────────────────────────
private static string GetTranslatedText(string tableName, string key)
{
if (string.IsNullOrEmpty(key)) return string.Empty;
try
{
// 尝试从 Unity Localization 中获取翻译文本
string translated = LocalizationSettings.StringDatabase.GetLocalizedString(tableName, key);
// 若获取失败或为空,则直接原样返回 key 作为兜底文本
return string.IsNullOrEmpty(translated) ? key : translated;
}
catch
{
// 如果表不存在或其他异常,返回原 key
return key;
}
}
}
}