feat: Round 52 narrative systems improvements

P1-A: QuestManager.OnLoad Enum.TryParse failure warning (dev builds)
P1-B: SaveData.QuestState ObjectiveCompleted dict; BuildObjectiveCompleted
       helper; OnSave/OnLoad wiring (DataVersion 2→3)
P2-A: Quest start/complete timestamps (_startedAtUtc/_completedAtUtc dicts;
       StartedAtUtc/CompletedAtUtc in SaveData; AcceptQuest/CompleteQuest/
       OnSave/OnLoad wiring)
P2-B: DialogueManager pending queue Queue→List + priority-eviction on full
       (lowest-priority item evicted when higher-priority request arrives)
P2-C: NpcSO.localizationTable field; NpcSOEditor uses npc.localizationTable
       in TryResolveNameKey, PingLocalizationFile, and button label
P3-A: QuestSO.failConditions[] multi-fail array; Obsolete failCondition;
       DispatchEvent updates fail check to any-of-array logic with fallback
P3-B: QuestObjectiveSO.prerequisiteObjectiveId; DispatchEvent gates objective
       event routing behind prerequisite completed check
P3-C: IQuestEventPayload interface + StringQuestPayload struct; QuestObjectiveSO
       typed TryHandleEvent(IQuestEventPayload) overload; DispatchEvent string
       overload delegates to typed IQuestEventPayload overload

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-25 00:47:44 +08:00
parent 48f018f4b8
commit 0b28cabba4
8 changed files with 189 additions and 25 deletions

View File

@@ -34,13 +34,13 @@ namespace BaseGames.Editor.Dialogue
s_previewStyle.normal.textColor = new Color(0.55f, 0.90f, 0.55f);
}
string resolved = TryResolveNameKey(npc.nameKey);
string resolved = TryResolveNameKey(npc.nameKey, npc.localizationTable);
EditorGUILayout.Space(4);
if (string.IsNullOrEmpty(resolved))
{
EditorGUILayout.HelpBox(
$"nameKey「{npc.nameKey}」在本地化表中未找到对应文本(或 LocalizationManager 未初始化)。\n" +
$"nameKey「{npc.nameKey}」在本地化表「{npc.localizationTable}」中未找到对应文本(或 LocalizationManager 未初始化)。\n" +
"请检查本地化表中是否存在此 Key。",
MessageType.Warning);
}
@@ -55,9 +55,9 @@ namespace BaseGames.Editor.Dialogue
EditorGUILayout.Space(4);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("跳转到本地化文件(UI 表)", GUILayout.Width(200)))
if (GUILayout.Button($"跳转到本地化文件({npc.localizationTable} 表)", GUILayout.Width(220)))
{
PingLocalizationFile("UI");
PingLocalizationFile(npc.localizationTable);
}
EditorGUILayout.EndHorizontal();
}
@@ -66,12 +66,12 @@ namespace BaseGames.Editor.Dialogue
/// 尝试通过 LocalizationManager若已加载解析 nameKey
/// 如未初始化或找不到 Key返回 null。
/// </summary>
private static string TryResolveNameKey(string key)
private static string TryResolveNameKey(string key, string table = "UI")
{
try
{
// LocalizationManager.Get 在编辑器下可能返回空字符串(未初始化),视为未找到
var resolved = BaseGames.Localization.LocalizationManager.Get(key, "UI");
var resolved = BaseGames.Localization.LocalizationManager.Get(key, table);
return string.IsNullOrEmpty(resolved) ? null : resolved;
}
catch