These files were loaded only by their own test_*_parity.gd and never by the runtime (transitively checked, incl. client_phase_integration_system). Removes 76 manifest implementation/evidence references across 18 contracts; contract docs get a note that conclusions based on them are void. Live systems kept: chest, consumable, item_attr, metin_socket, whisper_chat. Full headless suite: no new failures (7 failing + 5 headless-hanging render tests are identical before the deletion). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
24 KiB
quest.quest_event_navigation
Scope
审计 GC_QUEST_INFO 任务日志、任务计时/计数、任务信件按钮、GC_SCRIPT NPC 对话与 CPythonEventManager 事件标签、确认/输入/选择、任务地图信号、Atlas/小地图导航、剧情镜幕、相机/淡入淡出和副本结果提示。判断标准是当前端是否与 40250 的协议字段、任务生命周期、事件处理顺序、脚本按钮语义和地图/过场副作用统一;本地生物学家、悬赏、活动调度等脚本 helper 的独立测试不等于 40250 客户端 parity。
Reference call chain
UserInterface/PythonNetworkStreamPhaseGame.cppRecvQuestInfoPacket先按QUEST_SEND_IS_BEGIN判定 BEGIN/UPDATE/END,再按 flag 读取 title、clock name/value、counter name/value、icon;BEGIN 注册新任务并记录开始时间,UPDATE 只更新带 flag 的字段,END 删除指定任务,最后刷新任务 UI。RecvScriptPacket读取动态GC_SCRIPT,交给CPythonEventManager::RegisterEventSetFromString,然后以 server skin 打开 QuestDialog;RecvQuestConfirmPacket将 message、timeout、request PID 交给 UI。SendScriptAnswerPacket使用 8-bit answer;SendScriptButtonPacket使用 unsigned 32-bit index,任务日志点击通过-2147483648 + questIndex形成 unsigned wire value。
UserInterface/PythonQuest.cppCPythonQuest::MakeQuest/RegisterQuestInstance/SetQuestClockValue都会更新iStartTime;GetQuestLastTime用iStartTime + iClockValue - currentSecond,因此任务窗口关闭时计时仍继续。CPythonQuest保持任务实例容器的顺序,GetQuestIndex将 UI 行号映射到真实 quest index。
UserInterface/PythonEventManager.cpp/PythonEventManager.hProcessEventSet逐命令处理 42 类标签:LETTER/DELAY/ENTER/WAIT/NEXT/DONE/QUESTION、图片、QUESTBUTTON、地图信号、相机、FADE/WHITE、ITEM/MOB、WINDOW_SIZE、INPUT、CONFIRM_WAIT、SELECT_ITEM 和 DUNGEON_RESULT。NEXT/取消发送 answer 254;DONE只执行DoneEvent/CloseSelf,不发送 answer。RUN_CINEMA只在首命令时替换为.msc事件文件;FADE/WHITE 设置 wait flag,动画结束后由EndEventProcess解锁。
Client/Eternexus/root/uiquest.py/interfacemodule.py/uicharacter.py- QuestDialog 的 skin、按钮和 ESC 语义由 UI 层执行;任务信件点击发送 unsigned script button 后删除信件按钮;任务日志最多显示 5 条并使用原始任务顺序。
UserInterface/PythonMiniMap.cpp/Client/Eternexus/root/uiminimap.py/atlasinfo.txtADDMAPSIGNAL写入 CPythonMiniMap 信号点并打开 Atlas;CLEARMAPSIGNAL清除信号点;SETCMAPPOS改变 Atlas 中心,不改变玩家世界坐标。
Current call chain
- native
EntityStore::apply已解析GC_SCRIPT、GC_QUEST_CONFIRM和 flag-drivenGC_QUEST_INFO,M2Client暴露script_answer/script_button/script_select_item/quest_input/quest_confirm/quest_cancel/get_quests,M2Client::poll通过 signal 将脚本、确认和任务变更交给 Godot。 project/ui/quest_dialog.gd已实现 42 个事件标签的解析/状态机、图片、选择分页、输入、确认等待、地图信号、相机、淡入淡出、电影镜幕和副本结果信号;project/game_scene.gd已连接对话、相机、淡入淡出、选择物品、小地图和 Atlas。project/ui/quest_log.gd与project/ui/char_status_ui.gd提供任务按钮和 5 条分页列表;project/ui/atlas_ui.gd提供地图拼接、拖动、玩家/队伍/公会领地/观察者标记;project/atlas_navigation_system.gd是另一个带硬编码地图/NPC/距离规则的本地 helper。project/biologist_quest_system.gd、dynamic_bounty_event_system.gd、event_manager_system.gd、metin_spawn_event_system.gd是本地游戏规则/活动 helper,40250 Windows 客户端没有对应的客户端 authority 实现;它们不能替代任务/事件回包链。
Branch matrix
| 场景 | 40250 | 当前端 | 结论 |
|---|---|---|---|
| 任务 BEGIN/UPDATE | BEGIN 注册全新实例并记录开始时间;UPDATE 只更新带 flag 字段 | EntityStore 的 BEGIN/未知 UPDATE 会记录 clock_start_ms,并追加到 m_quest_order;普通 UPDATE 保持位置和起点,clock_value 更新会重置起点 |
PARTIAL:生命周期与本地计时已对齐,CTimer/服务端时间基准仍需端到端验证 |
| 任务 END | DeleteQuestInstance(index) 后刷新 UI |
EntityStore::apply 与 classic parser 都删除 m_quests[index]、移除 m_quest_order 项并排入一次 quest_changes 刷新 |
PARTIAL:删除和顺序分支已对齐,BEGIN 时间戳和 UI 重建仍未闭合 |
| 任务倒计时 | iStartTime 从 BEGIN 或 clock update 时记录,窗口关闭也继续倒计时 |
native 保存 clock_start_ms;QuestLog 和 CharStatusUI 每次显示按起点重新计算,关闭窗口期间不重置 |
PARTIAL:关闭/重开语义已对齐,精确 CTimer 时间基准、过期任务清理和后台恢复仍未端到端验证 |
| 任务列表顺序/索引 | vector 顺序与 GetQuestIndex(row) 一致 |
EntityStore::m_quest_order 按 CPythonQuest vector 语义枚举;UPDATE 保持位置、BEGIN 追加、END 删除 |
PARTIAL:native 顺序已对齐,真实 UI 行号/服务器序列仍未端到端验证 |
| 任务日志点击 | -2147483648 + questIndex 按 unsigned 32-bit 发 CG_SCRIPT_BUTTON |
QuestLog/CharStatusUI 传入负数 sentinel,M2Client 按 40250 的范围转换为 uint32 |
PARTIAL:wire sentinel 已对齐,真实 server 回包和任务窗口生命周期仍未测 |
| 任务信件按钮 | 新信件同 index 先删除旧按钮、插入最前;点击发送 script button 并删除按钮 | QuestLog.recv_quest 顺序/点击删除逻辑已存在 |
PARTIAL:UI 结构接近,但实际任务日志负索引门控仍会阻断另一入口,重连/服务器重新发送未测 |
| GC_SCRIPT 事件标签 | 42 标签按逐命令、等待、锁定和事件回调处理 | parser/state machine 基本覆盖 42 标签;首命令 RUN_CINEMA 会读取 .msc 并替换事件流,缺失资源不打开空窗口 |
PARTIAL:真实 .msc 资源序列和中断清理仍未验证 |
| 对话按钮语义 | QUESTION 发送 0-based answer;NEXT/取消发送 254;DONE 只关闭;ESC 根据按钮类型分支 | QUESTION/NEXT/取消、DONE 的 DoneEvent/CloseSelf 和 ESC 的 QUESTION/NEXT/CANCEL 分支已对齐 |
PARTIAL:真实 server 脚本结束/重复提交/中断时序仍未完全覆盖 |
| 输入/选择/确认 | INPUT→CG_QUEST_INPUT_STRING;SELECT_ITEM 打开选择窗;CONFIRM_WAIT 显示倒计时并超时取消;END_CONFIRM_WAIT 关闭 |
native/UI 信号和主要控件存在,选择/输入/确认测试通过 | PARTIAL:真实超时、重复提交、断线和 server close 清理未覆盖 |
| 地图信号/Atlas | ADDMAPSIGNAL 同时写小地图 signal point/Atlas waypoint 并打开 Atlas;CLEAR 清除;SETCMAPPOS 调中心 | GameScene 将同一坐标写入 Minimap 与 AtlasUI,Atlas overlay 绘制橙色 waypoint 并支持清除 | PARTIAL:两处消费链已对齐,真实 Atlas 资源、地图切换和多点生命周期仍未端到端验证 |
| 相机/淡入淡出/镜幕 | 相机设置、blend、restore 和 fade wait 由应用/事件窗完成;动画完成后释放 wait | GameScene 已连接 camera/fade,QuestCurtain 可开关 | PARTIAL:没有真实 .msc/资源和中断清理回归,skin/Done/ESC 边界与原版不一致 |
| 自定义任务/活动 helper | 40250 客户端只负责显示/请求,规则通常由服务端给回包 | 当前 helper 本地推进生物学家、悬赏、活动掉落和倍率 | GAP(custom authority):本地测试通过不能说明与 40250 Windows 客户端统一 |
Implementation-equivalence matrix
| 项目 | 状态 | 证据/限制 |
|---|---|---|
| Preconditions | PARTIAL | native 阶段、answer/input 和 script-button sentinel 边界存在;事件窗口/重复提交/服务器任务存在性缺少门控 |
| Branch structure | PARTIAL | 42 标签和 UI 主分支已覆盖;RUN_CINEMA 的缺失资源分支、Atlas 任务信号和部分中断分支已补齐/接通,真实过场消费者仍未验证 |
| Algorithms/formulas | PARTIAL | 事件等待、颜色、相机参数和地图坐标转换大体存在;任务计时缺 reference 的 start-time 算法,硬编码 Atlas/NPC/活动 helper 不是 40250 客户端算法 |
| State transition order | PARTIAL | 参考的 GC 任务包→创建/更新/删除→刷新主顺序已补齐;QuestLog 只在可见时递减,脚本 close/answer 仍有额外本地动作 |
| Constants/units | PARTIAL | 5 条任务、30/16/24 字段、42 标签、5×9/按钮布局、254/255 answer 和 uint32 script-button sentinel 已对齐;skin 和地图信号显示语义未闭合 |
| Timing/event sources | PARTIAL | native signal、毫秒事件等待和 fade callback 存在;任务 start timestamp、真实 .msc 事件、超时/断线/重连时序缺证据 |
| Resource/data sources | PARTIAL | quest icon、ITEM/MOB 名称和 minimap DDS 使用资源接口;Atlas/NPC helper 另有硬编码 registry,RUN_CINEMA 仍缺真实 .msc 资源与消费者证据 |
| Protocol side effects | PARTIAL | GC_SCRIPT/QUEST_INFO/CONFIRM parser 和基本 CG quest packets 存在;任务按钮 wire、DONE close-only、ESC 的 answer 分支已补,电影文件注册未统一 |
| Interruption/failure/cleanup | GAP | 任务结束删除已覆盖 native 两条解析路径,但地图切换、对话 ESC/DONE、确认超时、fade/cinema 中断、信号清理和任务列表重建没有完整 server-sequence 回归 |
Regression evidence
project/quest_test.gd、project/quest_event_test.gd:通过,覆盖脚本对话、确认、任务按钮和 42 标签/状态字段;使用 fake client/离线 parser,没有真实GC_QUEST_INFOEND、unsigned button 和 server sequence。project/test_quest_dialog_parity.gd:修正 DONE/ESC/CANCEL 断言后 47 项通过;该测试现在确认[DONE]处理时发done_event、按钮点击只关闭,QUESTION 的 ESC 发送最后选项,CONFIRM_WAIT 的取消发送 254。project/test_quest_hud_parity.gd:19/19 通过;任务按钮布局和 fake quest array 通过,未覆盖 native unordered map、计时持续性和M2Client::script_button负数拒绝。project/quest_curtain_test.gd、project/atlas_test.gd、project/test_atlas_navigation_parity.gd、project/test_map_name_shower_parity.gd、project/test_minimap_radar_parity.gd:通过;主要验证本地窗口、硬编码导航 registry、地图标记和假数据,未证明ADDMAPSIGNAL在 Atlas 的实际资源/生命周期等价。project/test_biologist_quest_parity.gd:28/28 通过;验证本地生物学家任务 helper,不是 40250 Windows 客户端功能实现。project/test_event_manager_parity.gd:24/24 通过;验证本地活动倍率/宝盒 helper,40250 客户端没有对应 authority,不能作为 parity PASS。build-debug/extension/net_entity_test、build-debug/extension/net_classic_session_test、build-debug/extension/net_bounds_test、build-debug/extension/net_classic_wire_test:通过基础 quest/script packet、quest END 删除、vector 顺序/UPDATE 活跃状态和负数 sentinel 检查;任务计时、DONE 语义、RUN_CINEMA 消费者和 Atlas 信号仍未覆盖。
Deep audit round 2026-09-21
Fresh regression results
godot --headless --path project --script quest_test.gd、quest_event_test.gd:均退出码 0;脚本解析、确认、任务日志和 42 标签本地状态机通过。godot --headless --path project --script test_quest_dialog_parity.gd:退出码 0,45/45 通过;但 DONE 断言明确要求发送script_answer(254),与 40250 DONE 只关闭事件的实现相反,因此该条不能作为正确 parity 证据。godot --headless --path project --script test_quest_hud_parity.gd:退出码 0,19/19 通过;fake quest array 的按钮、分页、计数和时间格式通过,但使用负数 script button 值的 fake client,未经过 native wire gate。godot --headless --path project --script quest_curtain_test.gd、atlas_test.gd、test_atlas_navigation_parity.gd、test_map_name_shower_parity.gd、test_minimap_radar_parity.gd:均退出码 0;窗口、Atlas、地图标记和小地图 helper 通过。godot --headless --path project --script test_biologist_quest_parity.gd:退出码 0,28/28 通过;只验证本地生物学家任务 helper。godot --headless --path project --script test_event_manager_parity.gd:退出码 0,24/24 通过;只验证本地活动倍率/宝盒 helper。build/extension/net_entity_test、net_classic_session_test、net_classic_wire_test:均退出码 0;基础任务/脚本包通过。
Static parity findings
- 40250
GC_QUEST_INFOBEGIN/UPDATE/END 的 END 会真正删除 quest instance;当前EntityStore对 END 未删除对应记录,旧任务可能继续出现在get_quests和日志中。 - 40250 在 BEGIN/clock update 保存
iStartTime,窗口关闭时计时仍继续;当前端已在QuestInfo::clock_start_ms保存起点,并让 QuestLog/CharStatusUI 按起点计算剩余值,仍需验证 Godot 单调时钟与参考CTimer::GetCurrentSecond()的时间基准和后台行为。 - 40250 任务列表保持 vector 顺序并通过真实 quest index 映射;当前端已加入
m_quest_order并覆盖 BEGIN/UPDATE/END 的位置语义,仍缺真实任务日志回包到 UI 行号的端到端验证。 - 40250 任务日志按钮使用
-2147483648 + questIndex的 unsigned 32-bit wire 值;当前M2Client::script_button(int)看到负数直接拒绝,虽然 fake UI 测试把负数记录为成功。 QuestDialog的 DONE、QUESTION/NEXT/CANCEL ESC 和确认取消已按 40250 分支对齐;真实 server 断线、重复输入和事件窗口中断仍缺端到端证据。RUN_CINEMA的首命令替换和.mscloose-resource 读取已在QuestDialog.begin_script();缺失/空文件现在按 40250 注册失败语义不打开空对话框,仍缺真实.msc资源序列/中断验证。ADDMAPSIGNAL 现在同时进入 Minimap 与 AtlasUI,仍缺真实地图资源和切图生命周期验证。- 本地
biologist_quest_system、活动倍率/宝盒 helper 是服务端规则的复制状态机,不属于 40250 Windows 客户端 authority,不能因 28/28、24/24 通过而标记 parity。
Round conclusion
本轮仍为 PARTIAL:任务/对话/Atlas 基础骨架和多数局部测试可运行,但 END 删除、持续计时、任务按钮 wire、DONE/ESC、电影播放消费者和 Atlas 信号消费存在明确差异,且现有 DONE 测试断言本身与 40250 不一致。本轮未修改实现代码。
Active UserInterface quest-event bridge review
PythonEventManagerMoudle.cpp暴露从文件/字符串注册 event set、清理、限制数量、逐行位置/宽度、等待/跳过/结束、handler/answer、可见起始行和SendScriptButtonPacket;位置更新使用事件管理器的坐标变换,不能只用一个对话框文本数组替代。PythonGameEventManagerModule.cpp将中心位置注入CGameEventManager后调用Update,是过场/地图事件的逐帧桥接;PythonQuest.h维护 quest instance 的标题、clock/counter 名和值、图标、创建/删除和索引查询。- 当前端有脚本解析和 QuestDialog/Atlas 骨架,但 event-set 生命周期、handler 回调、持续计时/逐帧位置、任务实例删除以及日志按钮 wire 值尚未统一;RUN_CINEMA 和地图信号也没有发现完整消费者,合同保持
PARTIAL。
Static review evidence
已将 PythonEventManagerMoudle.cpp、PythonGameEventManagerModule.cpp、PythonQuest.h 纳入 active source 证据;本轮只确认 reference bridge 的完整入口和状态字段,没有把局部脚本测试当作行为等价。
Status
PARTIAL。当前端已经有较完整的任务脚本解析、对话控件、任务 HUD、地图和过场骨架,42 个事件标签与基础 native packet 可工作;但任务生命周期/计时/顺序、ESC 语义、电影事件消费和 Atlas 任务信号存在明确差异,另有多个本地规则 helper 不是 40250 客户端实现。DONE、任务 END 和 script-button wire 已有对应修复。
Implementation fix round 2026-09-21 — quest END removes the instance
按 40250 CPythonNetworkStream::RecvQuestInfoPacket() 的明确分支复刻任务结束语义:
QUEST_SEND_IS_BEGIN 旗标存在且后续 isBegin == 0 时,参考端将包分类为
QUEST_PACKET_TYPE_END,调用 CPythonQuest::DeleteQuestInstance(index),随后刷新任务
列表。当前端此前只把 begin 改成 false,get_quests() 仍会枚举原有记录,造成已结束
任务继续显示。
现已在 EntityStore::mut_quest_info(classic parser)和 EntityStore::apply(协议兼容
路径)加入同一删除分支,并保留一次 quest_changes 刷新事件。新增的 native 回归先在
修复前确认“结束任务仍存在”失败,修复后 net_entity_test、net_classic_session_test
和 git diff --check 均通过。
合同仍为 PARTIAL:任务 BEGIN 的 start timestamp、vector 顺序、负数 script-button
sentinel、DONE/ESC、RUN_CINEMA 消费者、Atlas 信号和断线清理仍未闭合。
Implementation fix round 2026-09-21 — quest-log script-button sentinel
继续按 40250 uicharacter.py::QuestButtonClick 与
CPythonNetworkStream::SendScriptButtonPacket(unsigned int) 核对,确认任务日志入口的
-2147483648 + questIndex 不是非法参数,而是写入 uint32 wire 字段的任务索引
sentinel。此前 M2Client::script_button(int) 以 idx < 0 直接拒绝,导致
QuestLog/CharStatusUI 的任务日志点击无法到达服务器。
现已允许普通非负 uint32 索引,以及 INT32_MIN .. INT32_MIN + 0xffff 的任务索引
sentinel;其他负数仍拒绝,避免把任意错误值包装成大整数。net_bounds_test 已覆盖
普通端点、sentinel 端点和越界负值,构建与运行通过。
本合同仍为 PARTIAL:任务 BEGIN 的 start timestamp、vector 顺序、RUN_CINEMA 消费者、
Atlas 信号和断线清理仍未闭合。
Implementation fix round 2026-09-21 — CANCEL and ESC answer branches
继续按 40250 uiquest.py::MakeNextButton / OnPressEscapeKey 修复剩余对话关闭分支:
BUTTON_TYPE_CANCEL 的取消按钮发送 SCRIPT_ANSWER(254);ESC 在 QUESTION 时发送最后
一个选项索引,在 NEXT/CANCEL 时发送 254,在 DONE 时只关闭;没有可见答复按钮时才
回落到 native 的 255 cancel sentinel。此前当前端统一调用 quest_cancel(),会把
CONFIRM_WAIT 和 QUESTION/NEXT 的关闭语义压成错误的 255/取消路径。
新增回归先确认修复前 QUESTION ESC 与 CONFIRM_WAIT 取消断言失败,修复后
test_quest_dialog_parity.gd 47 项、quest_test.gd、quest_event_test.gd 和
git diff --check 通过。
本合同仍为 PARTIAL:任务时钟与列表顺序、RUN_CINEMA 资源消费者、Atlas 信号、真实
服务端脚本序列和断线/重连清理仍未闭合。
Implementation fix round 2026-09-21 — DONE event and close-only button
按 40250 PythonEventManager::ProcessEventSet(EVENT_TYPE_DONE) 与
uiquest.py::MakeNextButton(BUTTON_TYPE_DONE) 修复当前任务对话时序:[DONE] token
被消费时立即触发 DoneEvent;随后生成的“关闭”按钮只调用 CloseSelf(),不发送
CG_SCRIPT_ANSWER(254)。此前当前端把 done_event 延迟到按钮点击,并把 DONE 错误地
当成 NEXT/取消发送 254。
新增回归先把测试断言改为参考行为并确认修复前失败;修复后
test_quest_dialog_parity.gd 45 项、quest_test.gd 和 git diff --check 通过。
本合同仍为 PARTIAL:ESC 尚未按 CANCEL/DONE/NEXT 分支完全复刻,任务时钟、索引顺序、
RUN_CINEMA 消费者、Atlas 信号和断线清理仍未闭合。
Implementation fix round 2026-09-21 — quest instance vector order
按 40250 CPythonQuest::RegisterQuestInstance、MakeQuest 和
DeleteQuestInstance 的容器语义修复任务列表顺序:参考端使用 vector 保存任务实例,
普通 UPDATE 不改变位置,未知 UPDATE 在末尾创建,BEGIN 先删除同 index 的旧实例再把新
实例追加到末尾,END 同时删除实例和对应顺序项。当前端此前直接枚举
unordered_map<uint16_t, QuestInfo>,相同任务回包在不同运行中可能改变任务行顺序。
现已在 EntityStore 增加 m_quest_order,classic mutator 与协议兼容 apply 两条路径
共用相同的注册/删除规则;quest_indices() 只按该顺序返回仍存在的任务。修复前新增的
顺序回归按预期失败,修复后 net_entity_test、net_classic_session_test、
net_bounds_test 和 git diff --check 均通过。
本合同仍为 PARTIAL:精确时间基准、真实任务日志到 UI 行号映射、
RUN_CINEMA/Atlas 生命周期、服务端脚本序列和断线清理仍未闭合。
Implementation fix round 2026-09-21 — classic UPDATE keeps the quest active
复核发现 classic parser 的 mut_quest_info 与协议兼容 apply 对同一 UPDATE 的结果不
一致:前者会把已有任务的 begin 暂存字段写成 false,后者保持为有效实例。40250 在
QUEST_PACKET_TYPE_UPDATE 中只调用 MakeQuest(仅当任务不存在)和各字段 setter,
不会把已存在任务变成结束态;只有 QUEST_PACKET_TYPE_END 才删除实例。
现已让 classic mutator 对所有非 END 的任务包保持 QuestInfo.begin == true,并增加了
“UPDATE 保持活动实例且更新标题”的回归。修复前该断言失败,修复后
net_entity_test、net_classic_session_test 和 git diff --check 通过。
本合同仍为 PARTIAL:任务 start timestamp、真实 UI 行号映射、RUN_CINEMA/Atlas 生命周期、
服务端脚本序列和断线清理仍未闭合。
Implementation fix round 2026-09-21 — ADDMAPSIGNAL reaches Atlas
按 40250 PythonEventManager::ProcessEventSet(EVENT_TYPE_ADD_MAP_SIGNAL) 和
CPythonMiniMap::AddSignalPoint 核对,任务脚本坐标不只是圆形小地图的边缘提示;参考端
同时调用 AddWayPoint(TYPE_WAYPOINT, ...),因此 Atlas 也能显示同一个 waypoint,
CLEARMAPSIGNAL 会移除两处记录。
当前端的 GameScene 现在把 map_signal_added 同时转发给 Minimap 和 AtlasUI,
Atlas overlay 使用与小地图相同的 server-centimetre→world→map 坐标转换绘制橙色标记,
并由 map_signals_cleared 同时清理。atlas_test.gd 新增添加/清理回归,测试通过。
本合同仍为 PARTIAL:真实 Atlas 资源、地图切换后的 signal 生命周期、RUN_CINEMA 真实
.msc 序列和断线/中断清理仍未闭合。
Implementation fix round 2026-09-21 — missing RUN_CINEMA resource
按 40250 CPythonEventManager::RegisterEventSetFromString() 的首命令特例和
CPythonNetworkStream::RecvScriptPacket() 的返回值判断修复过场脚本失败分支:
RUN_CINEMA 指向不存在或空路径时,参考端注册返回 -1,不会调用
OnScriptEventStart();当前端现在清理临时 event set、保持窗口关闭且不发出 opened,
不再显示空白锁定的任务对话框。有效 .msc 仍沿当前 loose-resource 读取路径替换事件流。
test_quest_dialog_parity.gd 新增缺失资源回归,当前 49 项全部通过;真实 .msc 文件的
完整事件序列、过场播放器消费者和中断清理仍保持 PARTIAL。
2026-09-22 死代码删除
以下文件只被自身测试引用、运行时从不加载,已删除;本文中以它们为实现或证据的结论作废,相关行为需按 40250 源码单元重新移植:atlas_navigation_system.gd, biologist_quest_system.gd, dynamic_bounty_event_system.gd, event_manager_system.gd, metin_spawn_event_system.gd, test_atlas_navigation_parity.gd, test_biologist_quest_parity.gd, test_event_manager_parity.gd, test_map_name_shower_parity.gd。