refactor: Round 53 remove all legacy backward-compatibility code
- QuestSO: remove giverNpcId, prerequisiteQuests/Flags/FlagsLogic, failCondition, conditionFlags, npcDialogueKey fields; simplify GiverNpcId property to giverNpc?.npcId; clean ValidatePrerequisiteCycles/HasPrerequisiteCycle to use prerequisites.questDependencies; remove ValidateBranchDialogueKeys migration warning block; clean QuestPrerequisite doc - QuestManager: remove OnLoad DataVersion 1/2 migration paths (ProgressCounts, hasNewFormat/ useNewFormat); remove CheckQuestDepsAndFlags old-field fallback (prerequisiteQuests/Flags); remove UnlockBranches conditionFlags fallback; remove DispatchEvent failCondition fallback; fix ValidatePrerequisites DFS to scan prerequisites.questDependencies - SaveData: remove ProgressCounts (Obsolete), ObjectiveIndex (unused), GiverNpcId (never written) fields from QuestState; simplify DataVersion doc comment - QuestSOEditor: replace migration-only editor with minimal DrawDefaultInspector - QuestModule: update all prerequisiteQuests/conditionFlags/npcDialogueKey/failCondition references to canonical new fields; update ValidateBranchFlags check 10 - FlagAuditModule: replace conditionFlags/prerequisiteFlags scans with conditionFlagEntries/ prerequisites.flagCondition.flags - NpcSO: remove QuestSO.giverNpcId reference from npcId tooltip - NpcAffinityEvent/RewardSO: update doc comments to reference giverNpc instead of giverNpcId Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -155,17 +155,17 @@ namespace BaseGames.Editor.Modules
|
||||
// 3. 扫描 QuestSO
|
||||
foreach (var quest in AssetOperations.FindAll<QuestSO>())
|
||||
{
|
||||
// branches[i].conditionFlags → 读取
|
||||
// branches[i].conditionFlagEntries → 读取
|
||||
if (quest.branches != null)
|
||||
foreach (var branch in quest.branches)
|
||||
if (branch.conditionFlags != null)
|
||||
foreach (var fid in branch.conditionFlags)
|
||||
if (!string.IsNullOrEmpty(fid))
|
||||
GetOrCreate(fid).readLocations.Add(($"任务分支条件 [{quest.name}]", quest));
|
||||
if (branch.conditionFlagEntries != null)
|
||||
foreach (var entry in branch.conditionFlagEntries)
|
||||
if (!string.IsNullOrEmpty(entry.flagId))
|
||||
GetOrCreate(entry.flagId).readLocations.Add(($"任务分支条件 [{quest.name}]", quest));
|
||||
|
||||
// prerequisiteFlags → 读取
|
||||
if (quest.prerequisiteFlags != null)
|
||||
foreach (var fid in quest.prerequisiteFlags)
|
||||
// prerequisites.flagCondition.flags → 读取
|
||||
if (quest.prerequisites.flagCondition.flags != null)
|
||||
foreach (var fid in quest.prerequisites.flagCondition.flags)
|
||||
if (!string.IsNullOrEmpty(fid))
|
||||
GetOrCreate(fid).readLocations.Add(($"任务前置标志 [{quest.name}]", quest));
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace BaseGames.Editor.Modules
|
||||
Folder, Prefix,
|
||||
s =>
|
||||
{
|
||||
bool hasPre = s.prerequisiteQuests != null && s.prerequisiteQuests.Length > 0;
|
||||
bool hasPre = s.prerequisites.questDependencies != null && s.prerequisites.questDependencies.Length > 0;
|
||||
// 徽章:分类 + 有前置
|
||||
string catLabel = s.category switch
|
||||
{
|
||||
@@ -88,7 +88,7 @@ namespace BaseGames.Editor.Modules
|
||||
}
|
||||
_listPane.ExtraFilter = q =>
|
||||
{
|
||||
if (filterPrereq && (q.prerequisiteQuests == null || q.prerequisiteQuests.Length == 0)) return false;
|
||||
if (filterPrereq && (q.prerequisites.questDependencies == null || q.prerequisites.questDependencies.Length == 0)) return false;
|
||||
if (filterNoObj && (q.objectives != null && q.objectives.Length > 0)) return false;
|
||||
if (filterCanFail && !q.canFail) return false;
|
||||
if (filterCategory.HasValue && q.category != filterCategory.Value) return false;
|
||||
@@ -223,16 +223,16 @@ namespace BaseGames.Editor.Modules
|
||||
};
|
||||
SkillModule.AddChip(card, "分类", catDisplay);
|
||||
|
||||
// 发布 NPC:优先显示 giverNpc.npcId,回退旧 giverNpcId
|
||||
// 发布 NPC
|
||||
string giverId = s.GiverNpcId;
|
||||
if (!string.IsNullOrEmpty(giverId))
|
||||
SkillModule.AddChip(card, "发布 NPC", giverId);
|
||||
|
||||
if (s.prerequisiteQuests != null && s.prerequisiteQuests.Length > 0)
|
||||
if (s.prerequisites.questDependencies != null && s.prerequisites.questDependencies.Length > 0)
|
||||
{
|
||||
// 显示每个前置任务的 questId,方便策划一眼看清依赖链
|
||||
var preIds = new System.Text.StringBuilder();
|
||||
foreach (var pre in s.prerequisiteQuests)
|
||||
foreach (var pre in s.prerequisites.questDependencies)
|
||||
{
|
||||
if (pre == null) continue;
|
||||
if (preIds.Length > 0) preIds.Append(", ");
|
||||
@@ -384,12 +384,8 @@ namespace BaseGames.Editor.Modules
|
||||
SkillModule.AddChip(row, "条件", condition);
|
||||
SkillModule.AddChip(row, "后续任务", next);
|
||||
|
||||
// 优先显示新 SO 引用;回退到旧字段(Obsolete)
|
||||
string seqName = branch.npcDialogueSequence != null
|
||||
? branch.npcDialogueSequence.name
|
||||
#pragma warning disable CS0618
|
||||
: branch.npcDialogueKey;
|
||||
#pragma warning restore CS0618
|
||||
// 优先显示 SO 引用名称
|
||||
string seqName = branch.npcDialogueSequence != null ? branch.npcDialogueSequence.name : null;
|
||||
if (!string.IsNullOrEmpty(seqName))
|
||||
SkillModule.AddChip(row, "对话序列", seqName);
|
||||
card.Add(row);
|
||||
@@ -401,7 +397,7 @@ namespace BaseGames.Editor.Modules
|
||||
/// 构建当前任务的依赖关系可视图(折叠面板形式):
|
||||
/// - 上方:前置任务链(此任务需要哪些任务先完成)
|
||||
/// - 下方:后续任务链(此任务完成后可解锁哪些任务)
|
||||
/// 数据来源:allQuests 中所有 QuestSO 的 prerequisiteQuests 引用,无运行时副作用。
|
||||
/// 数据来源:allQuests 中所有 QuestSO 的 prerequisites.questDependencies 引用,无运行时副作用。
|
||||
/// 节点可点击→选中对应资产(EditorGUIUtility.PingObject)。
|
||||
/// </summary>
|
||||
private static VisualElement BuildDependencyGraph(QuestSO s)
|
||||
@@ -436,10 +432,10 @@ namespace BaseGames.Editor.Modules
|
||||
var allQuests = s_allQuestCache;
|
||||
|
||||
// ── 前置任务(上游)────────────────────────────────────────────────
|
||||
bool hasPrereqs = s.prerequisiteQuests != null && s.prerequisiteQuests.Length > 0;
|
||||
bool hasPrereqs = s.prerequisites.questDependencies != null && s.prerequisites.questDependencies.Length > 0;
|
||||
AddDepSection(container, "▲ 前置任务(需先完成)",
|
||||
hasPrereqs
|
||||
? System.Array.ConvertAll(s.prerequisiteQuests, q => (q, "前置"))
|
||||
? System.Array.ConvertAll(s.prerequisites.questDependencies, q => (q, "前置"))
|
||||
: null,
|
||||
hasPrereqs ? null : "(无前置条件,可直接接取)");
|
||||
|
||||
@@ -448,8 +444,8 @@ namespace BaseGames.Editor.Modules
|
||||
foreach (var quest in allQuests)
|
||||
{
|
||||
if (quest == null || quest == s) continue;
|
||||
if (quest.prerequisiteQuests == null) continue;
|
||||
foreach (var pre in quest.prerequisiteQuests)
|
||||
if (quest.prerequisites.questDependencies == null) continue;
|
||||
foreach (var pre in quest.prerequisites.questDependencies)
|
||||
{
|
||||
if (pre == s) { downstream.Add((quest, "解锁")); break; }
|
||||
}
|
||||
@@ -492,8 +488,8 @@ namespace BaseGames.Editor.Modules
|
||||
/// </summary>
|
||||
private static bool HasPrerequisiteCycle(QuestSO origin, QuestSO current, System.Collections.Generic.HashSet<string> visited)
|
||||
{
|
||||
if (current?.prerequisiteQuests == null) return false;
|
||||
foreach (var pre in current.prerequisiteQuests)
|
||||
if (current?.prerequisites.questDependencies == null) return false;
|
||||
foreach (var pre in current.prerequisites.questDependencies)
|
||||
{
|
||||
if (pre == null || string.IsNullOrEmpty(pre.questId)) continue;
|
||||
if (pre == origin) return true; // 回到起点,发现循环
|
||||
@@ -705,13 +701,13 @@ namespace BaseGames.Editor.Modules
|
||||
/// 1. questId 为空
|
||||
/// 2. questId 重复
|
||||
/// 3. objectives 为空(无目标任务)
|
||||
/// 4. prerequisiteQuests 含空引用
|
||||
/// 4. prerequisites.questDependencies 含空引用
|
||||
/// 5. 前置任务循环依赖(DFS)
|
||||
/// 6. canFail=true 但 failCondition 为空
|
||||
/// 7. reward.affinityBonus != 0 但 giverNpcId 为空(好感度会丢失)
|
||||
/// 6. canFail=true 但 failConditions 为空
|
||||
/// 7. reward.affinityBonus != 0 但 giverNpc 为空(好感度会丢失)
|
||||
/// 8. TriggerZone ↔ ReachAreaObjective markerTag 孤儿交叉检测
|
||||
/// 9. 同任务内 objectiveId 重复(运行时 compositeKey 碰撞)
|
||||
/// 10. branches[i].conditionFlags 含空白字符串(策划配置遗漏 flag 名)
|
||||
/// 10. branches[i].conditionFlagEntries 含空 flagId(策划配置遗漏 flag 名)
|
||||
/// 11. reward.itemIds 含空白字符串或无对应 Collectible 预制件(孤儿奖励 ID)
|
||||
/// 结果在可交互的 QuestValidationResultWindow 中展示,每项问题附"选中"按钮可一键定位资产。
|
||||
/// </summary>
|
||||
@@ -778,18 +774,18 @@ namespace BaseGames.Editor.Modules
|
||||
if (q.objectives == null || q.objectives.Length == 0)
|
||||
addWarn($"{q.questId}: objectives 为空,任务无任何目标。", q);
|
||||
|
||||
if (q.prerequisiteQuests != null)
|
||||
foreach (var pre in q.prerequisiteQuests)
|
||||
if (pre == null) { addWarn($"{q.questId}: prerequisiteQuests 含空引用,请清理 Inspector 中的空槽。", q); break; }
|
||||
if (q.prerequisites.questDependencies != null)
|
||||
foreach (var pre in q.prerequisites.questDependencies)
|
||||
if (pre == null) { addWarn($"{q.questId}: prerequisites.questDependencies 含空引用,请清理 Inspector 中的空槽。", q); break; }
|
||||
|
||||
if (HasCircularPrerequisite(q, idMap, new HashSet<string>(StringComparer.Ordinal)))
|
||||
addError($"{q.questId}: 前置任务链存在循环依赖,将导致任务永远无法变为 Available!", q);
|
||||
|
||||
if (q.canFail && q.failCondition == null)
|
||||
addWarn($"{q.questId}: canFail=true 但 failCondition 为空,失败条件永不触发。", q);
|
||||
if (q.canFail && (q.failConditions == null || q.failConditions.Length == 0))
|
||||
addWarn($"{q.questId}: canFail=true 但 failConditions 为空,失败条件永不触发。", q);
|
||||
|
||||
if (q.reward != null && q.reward.affinityBonus != 0 && string.IsNullOrEmpty(q.GiverNpcId))
|
||||
addWarn($"{q.questId}: reward.affinityBonus={q.reward.affinityBonus} 但 GiverNpcId 为空,好感度增量将丢失。", q);
|
||||
addWarn($"{q.questId}: reward.affinityBonus={q.reward.affinityBonus} 但 giverNpc 未配置,好感度增量将丢失。", q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -839,7 +835,7 @@ namespace BaseGames.Editor.Modules
|
||||
}
|
||||
}
|
||||
|
||||
// 检查 10:branches[i].conditionFlags 含空白字符串
|
||||
// 检查 10:branches[i].conditionFlagEntries 含空 flagId
|
||||
private static void ValidateBranchFlags(
|
||||
List<QuestSO> allQuests,
|
||||
System.Action<string, UnityEngine.Object> addWarn)
|
||||
@@ -850,10 +846,10 @@ namespace BaseGames.Editor.Modules
|
||||
for (int bi = 0; bi < q.branches.Length; bi++)
|
||||
{
|
||||
var branch = q.branches[bi];
|
||||
if (branch.conditionFlags == null || branch.conditionFlags.Length == 0) continue;
|
||||
for (int fi = 0; fi < branch.conditionFlags.Length; fi++)
|
||||
if (string.IsNullOrWhiteSpace(branch.conditionFlags[fi]))
|
||||
addWarn($"任务 '{q.questId}' 分支[{bi}].conditionFlags[{fi}] 为空白字符串,运行时将被跳过,请检查是否遗漏标志名。", q);
|
||||
if (branch.conditionFlagEntries == null || branch.conditionFlagEntries.Length == 0) continue;
|
||||
for (int fi = 0; fi < branch.conditionFlagEntries.Length; fi++)
|
||||
if (string.IsNullOrWhiteSpace(branch.conditionFlagEntries[fi].flagId))
|
||||
addWarn($"任务 '{q.questId}' 分支[{bi}].conditionFlagEntries[{fi}].flagId 为空白字符串,运行时将被跳过,请检查是否遗漏标志名。", q);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -895,8 +891,8 @@ namespace BaseGames.Editor.Modules
|
||||
HashSet<string> visited)
|
||||
{
|
||||
if (!visited.Add(start.questId)) return true;
|
||||
if (start.prerequisiteQuests == null) return false;
|
||||
foreach (var pre in start.prerequisiteQuests)
|
||||
if (start.prerequisites.questDependencies == null) return false;
|
||||
foreach (var pre in start.prerequisites.questDependencies)
|
||||
{
|
||||
if (pre == null || string.IsNullOrEmpty(pre.questId)) continue;
|
||||
if (!idMap.TryGetValue(pre.questId, out var preQuest)) continue;
|
||||
|
||||
Reference in New Issue
Block a user