[P0][T19] 用 TC 树替换 rollDrop,接线 MonStats.TreasureClass → engine → act-scene #107

Closed
opened 2026-09-18 10:50:53 +00:00 by troytt · 1 comment
Owner

问题

前面所有 issue 都是「造零件」。本 issue 把零件装到生产路径上,并删掉占位实现。

现状

DEMO_BASES(3 件) / DEMO_AFFIXES(2 条)
   → act-scene.ts → GameEngine → rollDrop()

rollDrop 是三行随机挑选,与 D2 模型无关。

金标准数据

MonStats.txt 有 12 个 TC 列:

TreasureClass1..4           ← 普通难度
TreasureClass1(N)..4(N)     ← 噩梦
TreasureClass1(H)..4(H)     ← 地狱

四列按怪物类型选:1 = 普通、2 = Champion、3 = Unique、4 = 任务掉落。(列名已在 D2Common 字符串表确证;四列的类型对应关系为高可信推断。)

入口流程(D2Game!6FC32D60):

① 若 expansion 且 pUnit 是怪物:nLevel = GetStat(pUnit, 12 /*level*/)
② pTC = ResolveTreasureClass(nTcIndex, nLevel)   // 同 group 内取 level <= 怪物等级的最高一档
③ 调 D2Game!6FC32380 展开

实现要求

  1. 加载 MonStats.txt 的 12 个 TC 列(表本身已在 loadActTables 里)。
  2. 怪物死亡时按「怪物类型 + 难度」选出 TC 索引。
  3. 走 T-13 的展开 → T-14 的品质判定 → T-24 的基底升级 → T-15 的词缀抽取 → T-09/T-10 的暗金 / 套装落点。
  4. 替换 rollDrop 的实现,保持对外接口尽量兼容(或同步改调用方)。
  5. 删除 DEMO_BASES 与 DEMO_AFFIXES,以及所有回退到它们的代码路径。
  6. 接线到 act-scene.ts → GameEngine。

陷阱

[!IMPORTANT]
删除 demo 兜底路径时沿用 #58 确立的「响亮失败」原则 —— demo-data.ts 顶部的注释已经写明:DEMO_MONSTERS 被删除的理由是「数据失败不能伪装成内容」。物品表加载失败时应当明确报错,而不是静默回退到 3 件假物品。请在 CL 描述里沿用同样的措辞。

[!CAUTION]
TC 升级只在顶层做(用怪物等级),子 TC 不再升级。这点 T-13 已实现,本 issue 只要正确传入怪物等级即可。

[!WARNING]
掉落链全程用怪物的 seed,物品创建后切到物品的 seed。切换点在物品实例化的那一刻,不要提前也不要延后。

验收标准

  • DEMO_BASES / DEMO_AFFIXES 从代码库中完全移除,无任何引用残留
  • 物品表加载失败时抛出明确错误,不静默降级
  • 在 acts.html 里打死一只 Act 1 普通怪,掉出的是真实基础物品(不再是 demo-sword)
  • 掉出的魔法物品带真实词缀名,属性生效
  • 打死 Champion / Unique 怪走的是不同的 TC 列
  • 三个难度走各自的 (N)/(H) 列
  • 怪物等级正确驱动 TC group 升级
  • npm run typecheck 0 error
  • npx vitest run 全绿
  • npx tsx scripts/verify-items.ts 新增断言通过

溯源

金标准(数据) 1.13c MPQ data\global\excel\ 下的 MonStats.txt / TreasureClassEx.txt(本机 /usr/local/google/home/taodao/d2-data,挂载序 d2data → d2exp → Patch_D2,Patch_D2 优先)
金标准(算法) 1.13c 反汇编:D2Game!6FC32D60(objdump -d,D2Common 基址 0x6FD50000、D2Game 0x6FC10000)
参考 issue #58 确立的「���据失败不能伪装成内容」原则
本 issue 结论强度 调用链逐指令确证;「四列对应普通/Champion/Unique/任务」为高可信推断

[!WARNING]
D2MOO 是 1.10f,不是本项目的金标准。 它只能作线索使用。任何涉及常量、列序、整数截断位置或 RNG 消耗次数的结论,都必须回到 1.13c 的表格或 DLL 复核后再落地。

## 问题 前面所有 issue 都是「造零件」。本 issue 把零件装到生产路径上,并**删掉占位实现**。 ## 现状 ``` DEMO_BASES(3 件) / DEMO_AFFIXES(2 条) → act-scene.ts → GameEngine → rollDrop() ``` [`rollDrop`](https://git.projectdiablo2.cn/troytt/diablo2-web/src/branch/main/src/game/items.ts) 是三行随机挑选,与 D2 模型无关。 ## 金标准数据 `MonStats.txt` 有 **12 个 TC 列**: ``` TreasureClass1..4 ← 普通难度 TreasureClass1(N)..4(N) ← 噩梦 TreasureClass1(H)..4(H) ← 地狱 ``` 四列按怪物类型选:**1 = 普通、2 = Champion、3 = Unique、4 = 任务掉落**。(列名已在 D2Common 字符串表确证;四列的类型对应关系为高可信推断。) 入口流程(`D2Game!6FC32D60`): ``` ① 若 expansion 且 pUnit 是怪物:nLevel = GetStat(pUnit, 12 /*level*/) ② pTC = ResolveTreasureClass(nTcIndex, nLevel) // 同 group 内取 level <= 怪物等级的最高一档 ③ 调 D2Game!6FC32380 展开 ``` ## 实现要求 1. 加载 `MonStats.txt` 的 12 个 TC 列(表本身已在 `loadActTables` 里)。 2. 怪物死亡时按「怪物类型 + 难度」选出 TC 索引。 3. 走 T-13 的展开 → T-14 的品质判定 → T-24 的基底升级 → T-15 的词缀抽取 → T-09/T-10 的暗金 / 套装落点。 4. 替换 `rollDrop` 的实现,保持对外接口尽量兼容(或同步改调用方)。 5. **删除 `DEMO_BASES` 与 `DEMO_AFFIXES`**,以及所有回退到它们的代码路径。 6. 接线到 `act-scene.ts` → `GameEngine`。 ## 陷阱 > [!IMPORTANT] > **删除 demo 兜底路径时沿用 #58 确立的「响亮失败」原则** —— [`demo-data.ts`](https://git.projectdiablo2.cn/troytt/diablo2-web/src/branch/main/src/game/demo-data.ts) 顶部的注释已经写明:`DEMO_MONSTERS` 被删除的理由是「数据失败不能伪装成内容」。物品表加载失败时应当**明确报错**,而不是静默回退到 3 件假物品。请在 CL 描述里沿用同样的措辞。 > [!CAUTION] > **TC 升级只在顶层做**(用怪物等级),子 TC 不再升级。这点 T-13 已实现,本 issue 只要正确传入怪物等级即可。 > [!WARNING] > 掉落链全程用**怪物的 seed**,物品创建后切到**物品的 seed**。切换点在物品实例化的那一刻,不要提前也不要延后。 ## 验收标准 - [ ] `DEMO_BASES` / `DEMO_AFFIXES` 从代码库中**完全移除**,无任何引用残留 - [ ] 物品表加载失败时抛出明确错误,不静默降级 - [ ] 在 `acts.html` 里打死一只 Act 1 普通怪,掉出的是真实基础物品(不再是 `demo-sword`) - [ ] 掉出的魔法物品带真实词缀名,属性生效 - [ ] 打死 Champion / Unique 怪走的是不同的 TC 列 - [ ] 三个难度走各自的 `(N)`/`(H)` 列 - [ ] 怪物等级正确驱动 TC group 升级 - [ ] `npm run typecheck` 0 error - [ ] `npx vitest run` 全绿 - [ ] `npx tsx scripts/verify-items.ts` 新增断言通过 --- ### 溯源 | | | |---|---| | 金标准(数据) | 1.13c MPQ `data\global\excel\` 下的 `MonStats.txt` / `TreasureClassEx.txt`(本机 `/usr/local/google/home/taodao/d2-data`,挂载序 d2data → d2exp → Patch_D2,**Patch_D2 优先**) | | 金标准(算法) | 1.13c 反汇编:`D2Game!6FC32D60`(`objdump -d`,D2Common 基址 `0x6FD50000`、D2Game `0x6FC10000`) | | 参考 | issue #58 确立的「���据失败不能伪装成内容」原则 | | 本 issue 结论强度 | 调用链**逐指令确证**;「四列对应普通/Champion/Unique/任务」为高可信推断 | > [!WARNING] > **D2MOO 是 1.10f,不是本项目的金标准。** 它只能作线索使用。任何涉及常量、列序、整数截断位置或 RNG 消耗次数的结论,都必须回到 1.13c 的表格或 DLL 复核后再落地。
troytt added this to the [M10] 真实物品系统:500 基础物品、1000 词缀、TreasureClassEx 掉落树 milestone 2026-09-18 10:50:53 +00:00
Author
Owner

已完成用 TC 树替换 rollDrop,连通 MonStats.TreasureClass 12列 -> TC group 升级 -> 展开树 -> 品质判定 -> 词缀抽取 -> engine -> act-scene 全链路,彻底移除 DEMO_BASES / DEMO_AFFIXES,合并入 main (commit 分支 issue-107)。

已完成用 TC 树替换 rollDrop,连通 MonStats.TreasureClass 12列 -> TC group 升级 -> 展开树 -> 品质判定 -> 词缀抽取 -> engine -> act-scene 全链路,彻底移除 DEMO_BASES / DEMO_AFFIXES,合并入 main (commit 分支 issue-107)。
Sign in to join this conversation.
No Label
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#107
No description provided.