[Parity][panels][S1][R] NPC 菜单:靠任务解锁的选项一直显示;鉴定的显示条件和收费形态缺失;Akara 没有洗点项 #655

Closed
opened 2026-10-02 11:42:52 +00:00 by troytt · 0 comments
Owner

1.13c 客户端保真度审计立项(基准快照:7bd1090 / main @ 77a20c7)

证据标记说明:V-data = 1.13c MPQ 数据表 (.txt / animdata.d2 / .tbl / pal.pl2);V-src = D2MOO 逆向源码;V-bin = 1.13c DLL 反汇编;K = 1.13c 公认行为。

来源审计项:panels#1 — [S1][R] NPC 菜单:靠任务解锁的选项一直显示;鉴定的显示条件和收费形态缺失;Akara 没有洗点项

  • 位置
    • src/client/ui/world-panels.ts:373-495(buildNpcMenuOptions)
    • src/client/ui/world-panels.ts:1236-1243(effectiveContext:hasUnidentifiedItems ?? true)
    • src/client/ui-model/hud-model.ts:986-990(生产路径固定传 hasUnidentifiedItems: true,从不传 includeQuestRewards)
    • 数据在 src/common/units/npc-table.ts 的 travelActions / questRewardActions / canHire / canIdentify
  • 代码:if (context?.includeQuestRewards !== false) { … imbue / add_sockets / personalize };for (const travelAct of descriptor.travelActions ?? []) 无条件追加;if (descriptor.canHire) opts.push({ id: 'hire' … })。
  • 原版(V-bin)
    • D2Client 的 NPC 菜单静态表在 0x6fba3ba0:每项 39 字节,共 48 项,计数在 0x6fba42f0。查找方式是从 0x6faf8c9c 起按 class 线性查找,取第一个匹配项。
    • 下列 NPC 的静态项只有 talk:warriv1(155) #13 @0x6fba3d9b、meshif1(210) #15 @0x6fba3de9、tyrael2(367) #21 @0x6fba3ed3、kashya(150) #11 @0x6fba3d4d、qual-kehk(515) #43 @0x6fba422d。
    • charsi #3 @0x6fba3c15 和 larzuk #39 @0x6fba4191 只有 talk + trade/repair;drehya #41 @0x6fba41df 只有 talk/trade/gamble。
    • 所以 go east / sail east / travel to harrogath / imbue / add sockets / personalize / Qual-Kehk 的 hire 都不在静态表里,是运行时按任务状态追加的。追加代码本次没有逐条逆向。具体门控条件属于公认行为(K高):Warriv 要完成 A1Q6;Meshif 要完成 A2Q6;Tyrael 要完成 A4Q2;Charsi imbue 要交还 Malus 且奖励未领;Larzuk 打孔是 A5Q1 奖励,未领时才有;Anya 个人化是 A5Q4 奖励,未领时才有;Qual-Kehk 雇佣要完成 A5Q2。
    • Kashya 的 hire 也不在静态表里,追加条件没有逆向,见 §3。
    • 0x6faf8d22 起的特例处理:
      • id 0xfb4(4020 "Identify Items"):调用 0x6fabcdf0 统计未鉴定物品,数量为 0 时删掉这一项;任务 4(A1Q4)的标志 0/1 都没置位时,文字改为 tbl #4021 "Identify Items: " + 数量×100(收费鉴定)。
      • id 0x2ba0(tbl #11168 respec "Reset Stat/Skill Points"):由任务记录 0x29 的标志位控制。0x29 = 41,超出 D2MOO D2Game/include/QUESTS/Quests.h 的 MAX_QUEST_STATUS = 41(1.10f),应是 1.13 新增的记录。
      • id 0x1507:复活雇佣兵,文字 "Resurrect %s: %d"。
  • 影响(正常游玩可见)
    • 任何进度下,Warriv / Meshif / Act4 Tyrael 都显示旅行项;Charsi / Larzuk / Anya 永远显示奖励项;Qual-Kehk 从一开始就能雇。
    • Cain 身上没有未鉴定物品时也显示"辨识物品",也不会出现收费形态。
    • Akara 完全没有"重置属性/技能点数"。
    • 我自己用 npx tsx 跑了 buildNpcMenuOptions,输出:charsi: Talk | Trade/Repair | Imbue | Cancel、larzuk: … | Add Sockets |、drehya: … | Personalize |、warriv1 / meshif1: Talk | Travel East、367: Talk | Travel to Harrogath、qual-kehk: Talk | Hire。
  • 建议
    • 以 0x6fba3ba0 静态表为底;门控项按 world.quests 的 QUESTSTATEFLAG 位和未鉴定物品数动态追加。
    • 鉴定的收费形态用 tbl #4021。
    • 补上 Akara 的 #11168。
  • 已有 issue:—
> **1.13c 客户端保真度审计立项**(基准快照:`7bd1090` / `main @ 77a20c7`) > 证据标记说明:`V-data` = 1.13c MPQ 数据表 (`.txt` / `animdata.d2` / `.tbl` / `pal.pl2`);`V-src` = D2MOO 逆向源码;`V-bin` = 1.13c DLL 反汇编;`K` = 1.13c 公认行为。 ### 来源审计项:`panels#1` — [S1][R] NPC 菜单:靠任务解锁的选项一直显示;鉴定的显示条件和收费形态缺失;Akara 没有洗点项 - **位置** - `src/client/ui/world-panels.ts:373-495`(`buildNpcMenuOptions`) - `src/client/ui/world-panels.ts:1236-1243`(`effectiveContext`:`hasUnidentifiedItems ?? true`) - `src/client/ui-model/hud-model.ts:986-990`(生产路径固定传 `hasUnidentifiedItems: true`,从不传 `includeQuestRewards`) - 数据在 `src/common/units/npc-table.ts` 的 `travelActions` / `questRewardActions` / `canHire` / `canIdentify` - **代码**:`if (context?.includeQuestRewards !== false) { … imbue / add_sockets / personalize }`;`for (const travelAct of descriptor.travelActions ?? [])` 无条件追加;`if (descriptor.canHire) opts.push({ id: 'hire' … })`。 - **原版**(V-bin) - D2Client 的 NPC 菜单静态表在 0x6fba3ba0:每项 39 字节,共 48 项,计数在 0x6fba42f0。查找方式是从 0x6faf8c9c 起按 class 线性查找,取第一个匹配项。 - 下列 NPC 的静态项**只有 talk**:warriv1(155) #13 @0x6fba3d9b、meshif1(210) #15 @0x6fba3de9、tyrael2(367) #21 @0x6fba3ed3、kashya(150) #11 @0x6fba3d4d、qual-kehk(515) #43 @0x6fba422d。 - charsi #3 @0x6fba3c15 和 larzuk #39 @0x6fba4191 只有 talk + trade/repair;drehya #41 @0x6fba41df 只有 talk/trade/gamble。 - 所以 go east / sail east / travel to harrogath / imbue / add sockets / personalize / Qual-Kehk 的 hire 都**不在静态表里**,是运行时按任务状态追加的。追加代码本次没有逐条逆向。具体门控条件属于公认行为(K高):Warriv 要完成 A1Q6;Meshif 要完成 A2Q6;Tyrael 要完成 A4Q2;Charsi imbue 要交还 Malus 且奖励未领;Larzuk 打孔是 A5Q1 奖励,未领时才有;Anya 个人化是 A5Q4 奖励,未领时才有;Qual-Kehk 雇佣要完成 A5Q2。 - Kashya 的 hire 也不在静态表里,追加条件没有逆向,见 §3。 - 0x6faf8d22 起的特例处理: - id 0xfb4(4020 "Identify Items"):调用 0x6fabcdf0 统计未鉴定物品,数量为 0 时**删掉这一项**;任务 4(A1Q4)的标志 0/1 都没置位时,文字改为 tbl #4021 "Identify Items: " + 数量×100(收费鉴定)。 - id 0x2ba0(tbl #11168 respec "Reset Stat/Skill Points"):由任务记录 0x29 的标志位控制。0x29 = 41,超出 D2MOO `D2Game/include/QUESTS/Quests.h` 的 `MAX_QUEST_STATUS = 41`(1.10f),应是 1.13 新增的记录。 - id 0x1507:复活雇佣兵,文字 "Resurrect %s: %d"。 - **影响**(正常游玩可见) - 任何进度下,Warriv / Meshif / Act4 Tyrael 都显示旅行项;Charsi / Larzuk / Anya 永远显示奖励项;Qual-Kehk 从一开始就能雇。 - Cain 身上没有未鉴定物品时也显示"辨识物品",也不会出现收费形态。 - Akara 完全没有"重置属性/技能点数"。 - 我自己用 `npx tsx` 跑了 `buildNpcMenuOptions`,输出:`charsi: Talk | Trade/Repair | Imbue | Cancel`、`larzuk: … | Add Sockets |`、`drehya: … | Personalize |`、`warriv1 / meshif1: Talk | Travel East`、`367: Talk | Travel to Harrogath`、`qual-kehk: Talk | Hire`。 - **建议** - 以 0x6fba3ba0 静态表为底;门控项按 `world.quests` 的 QUESTSTATEFLAG 位和未鉴定物品数动态追加。 - 鉴定的收费形态用 tbl #4021。 - 补上 Akara 的 #11168。 - **已有 issue**:—
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#655
No description provided.