[P1][T1-3] 还原 DRLGOUTDOORS_SpawnAct12Waypoint:格子洗牌顺序 + Cold Plains 特例 #80
Labels
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: troytt/diablo2-web#80
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
问题
src/game/wilderness.ts:5314 spawnOutdoorWaypoint()与原版算法完全不同:既丢了洗牌、也丢了 Cold Plains 特例,落点分布和 RNG 消耗次数都对不上。
原版逻辑(1.13c 反汇编确认)
分支 A:Cold Plains 特例(
levelId == LEVEL_COLDPLAINS)即:冷平原的航路点被钉在「通往血腥荒地的那个连接格」旁边,完全确定,不消耗随机数。
分支 B:通用路径
关键约束:
nGridWidth/nGridHeight),不是瓦片;D2CoordStrc pCoord[256](1.13c 两处add esp,0x808佐证),nArea > 256会溢出,原版就这样;2 * nArea次,这个数字必须一致,否则后续 pass 全部错位。现状
wilderness.ts:5314 spawnOutdoorWaypoint():COLDPLAINS|BLOODMOOR无匹配)marginX/marginY步长 2 扫描roadsideClearings/campsiteCandidates/centralHubCandidates/openCandidates四类,依赖LANDMARK_REGEX、isNearDirtRoad()、hubRadiustx>=4 && tx<30 && ty>=32 && ty<160(:5363-5365)修改方案
pGrid[1]/pGrid[2]是逐格的 flag 位图。若仓库还没有等价结构,本 issue 需要先建立它——这也是 P2 那条(顶点/土路)的前置,
两者可以合并排期。
TestGridCellSpawnValid:1.13c 内联为test DWORD PTR [grid], 0x1b81,即
(gridEntry & 0x1B81) == 0才算合法。请务必回二进制复核这个掩码的取反语义(
jne/je分支方向:0x6FD92611 jne跳过、0x6FD928CB je继续,即有位命中就跳过 ⇒ 掩码为 0 才合法)。GetVisArrayFromLevelId的等价物(关卡的 8 个邻接槽)。仓库已有
seamConstraints/world-graph.ts可作为数据来源,但要确认槽位顺序与原版i一致,因为
nFlags = 1 << (i + 4)直接依赖槽位下标。DRLGOUTJUNG_,而非魔法数字。验收标准
2 * nArea次,有测试断言LANDMARK_REGEX/hubRadius/ 丛林硬编码特判verify-packs1671/1671nArea > 256的行为溯源
113c-divergence-audit.md(条目编号与本 issue 标题中的 T 编号对应)D2Common.dll,PE 时间戳0x4B95C439= 2010-03-09,ImageBase0x6FD50000依赖关系
本 issue 是 8×8 格子网格基础设施的第一个使用者,请先做本条,再做 #82。
pGrid[1]/pGrid[2]等价的逐格 flag 位图,以及TestGridCellSpawnValid(1.13c 内联为
test DWORD PTR [grid], 0x1b81)。verify-packs基线。先在本条把基础设施跑通、验证掩码语义无误,能显著降低 #82 的风险。
相关:#82
修复验证与修改逻辑报告 (Issue #80)
1. 问题背景与 1.13c 原版逻辑比对
经反汇编对照暴雪原版 1.13c
D2Common.dll(≈0x6FD92700),原版户外航路点放置包含两条严格路径:levelId === 3):levelId === 2) 的边界门坐标与 seam 连通网格。if (!j) j = 1; if (!i) i = 1; if (j == nGridWidth - 1) --j; if (i == nGridHeight - 1) --i;0x20000(DRLG_GRID_FLAG_WAYPOINT_COLDPLAINS),精确消耗 0 次 RNG rolls,直接返回。(nGridWidth - 2) * (nGridHeight - 2)个格子建表(nArea个单元)。nArea轮双向对调打乱(2 * nArea次rollLimited(rng, nArea)抽取),保证与原版 1.13c 随机流消耗严格对齐。打乱后线性遍历不再消耗 RNG。TestGridCellSpawnValid,采用 1.13c 原版内联掩码(flags & 0x1B81) === 0,避让预置、障碍与不可通行区域,写入0x10000(DRLG_GRID_FLAG_WAYPOINT)。LANDMARK_REGEX、isNearDirtRoad、hubRadius及硬编码 Act 3 判定区),导致落点与 RNG 消耗严重失真。2. 修改逻辑
src/game/wilderness.ts:spawnOutdoorWaypoint(绑定DRLGOUTDOORS_SpawnAct12Waypoint)。generateWilderness完整传递request.seamConstraints支持精确连缝。tests/outdoor-waypoint-113c.test.ts(13 项单元测试):rollLimited随机数消耗计数与分布。tests/wilderness-waypoints-shrines.test.ts。3. 验证结果
npm run typecheck: 0 errorsnpx vitest run: 全部测试通过 (32/32 outdoor waypoint 相关测试全部通过)7187154(基于 worktree commita985dea6d3998b1079374cb8035d08baf3cbee16)