chore: 消除重复真相源、死代码与形同虚设的逻辑规则 #63
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#63
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?
背景
对
main分支(origin/main=4c2e399)的地图与怪物生成层做全量审计时,附带发现了一批重复真相源与死代码 / 未接线问题。这些问题单独看都不致命,但它们是「两份数据静默分歧」类 bug 的温床,且会误导后续维护者。
1. 重复真相源(Duplicate Sources of Truth)
1a. 城镇关卡 ID 列表存在三份
src/game/portal.ts:226-238townLevelForActswitch,含default: 109src/game/acts.ts:312Act N - Townscripts/pack-act-assets.ts:369-370ACT_TOWNS = [1, 40, 75, 103, 109]1b. 关卡 → 幕映射存在两份且边界不一致
src/game/wilderness.ts:3686-3698—actOfLevel用>= 1 && <= 39src/game/wilderness.ts:4937-4945—inferredAct用< 40且同一套 id 区间派发在
wilderness.ts:3589-3666又重复了第三遍。1c. 血腥荒地(关卡 2)预设列表存在两份且分歧
src/game/wilderness.ts:2474—SPECIAL_PRESETS_BY_LEVEL[2]src/game/wilderness.ts:5163-5199— 内联的 50% 河流变体清单1d.
PACK_RADIUS_PX两个不兼容的值src/game/monster-rooms.ts:66= 64src/game/combat.ts:463= 96同一概念,取哪个取决于走哪条刷怪路径。
1e.
SUB_TILES_PER_TILE定义了 4 次src/game/map.ts(规范)、src/game/maze-objects.ts:24、src/game/level-links.ts:39等。应统一 import。另有
wilderness-acts.ts:296-377直接用字面* 5而非引用常量。1f.
readSuperUniques()/readEliteModifiers()与手写表并存src/game/monsters.ts:605-644/:660-682解析真表,:1002-1345/:687-707是手写表。两个真相源,解析器从未被调用。(详见「用 MPQ 表取代手写怪物数据」Issue)
2. 死代码(Dead Code)
2a.
generateAct3Jungle—— import 了但从未调用src/game/wilderness-acts.ts:417-528(约 110 行)在
src/game/wilderness.ts:85被 import,没有任何调用点。它的硬编码坐标(
bridgeYPositions = [78, 142]、桥跨度x 32…60)还被wilderness-jungles.ts:590-609复制了一份。2b.
maze-objects.ts:238的|| trueprop1 / style / sequence内容检测恒为真,整段是死的。(同时也是一个真 bug,另见「消除静默降级」Issue)
2c.
readMonsterArt已解析MeleeRng后丢弃src/game/monsters.ts:376-389把MonStats2.MeleeRng解析进MonsterArt.meleeRange,然后:965-975用常量DEFAULT_REACH_PX = 40。同理
MonsterKind.code(:171-172)被解析后由 741 行的MONSTER_ART_MAP取代。2d.
LevelRow.offsetX/offsetY解析后从未读回src/game/world-graph.ts:399-400解析了这两列,文件头部:20-24还明确指出OffsetX/OffsetY = -1恰好标记被缝合的关卡 —— 然后用 46 条手打的SEAMLESS_ADJACENCY代替。2e.
MonUMod.txt的exclude1/exclude2解析后忽略src/game/monsters.ts:666-682解析互斥规则,:712-730的pool.splice完全不用。2f. 13 个精英词缀里 11 个无任何机制效���
src/game/monsters.ts:735-757:只有strong/fast生效;cursed/fireenchant/coldenchant/lightenchant/stoneskin等只被存储。3. 未接线(Wired but Never Reached)
3a.
difficulty参数从未传递src/scene/act-scene.ts:906-912与scripts/pack-act-assets.ts:1372调用planLevelMonsters时都不传difficulty,恒为'normal'。后果:
nmon*池、(N)/(H)列、NM/Hell 缩放、monsters.ts:479-483的区域等级规则全是死代码。3b.
monster-rooms.ts整套房间系统在生产路径被绕过src/scene/act-scene.ts:1589调用spawnMonsterPacks时不传 rooms,导致 544 行的房间放置系统完全不生效。而
monster-rooms.ts:518-531的向后兼容分支会凭空捏造一个 64×64 的房间网格。3c. 怪物只合成
wl+nu两种动画src/game/monster-art.ts:250-260:攻击 / 受击 / 死亡 / 特殊动画的 COF 与 DCC 都在磁盘上,但从不被合成。3d.
planMonsterGroups忽略Raritysrc/game/monsters.ts:884-889用types[rng.int(0, len-1)]均匀随机选型。Rarity只在selectLevelTypes用过一次。3e. 只读
mon1..mon10src/game/monsters.ts:536-543的for (let slot = 1; slot <= 10; …),而Levels.txt支持mon1..mon25。未改版 1.13c 无影响,任何 mod 会被静默截断。
4. 逻辑恒真 / 恒假(形同虚设的规则)
wilderness.ts:2443-2454BordType 0的「整关仅一个」上限因min(1, Infinity)恒等于 1,实际是「每行一个」,预算从未起约束作用maze-objects.ts:604-606orths.length <= 2实际等于「所有房间」,「仅走廊」规则形同虚设maze-special-passes.ts:549-563nDirection = seed % 3后按(nDirection+1) % 4索引 ⇒ 索引恒 ∈ {1,2,3},'NE'路径点永远不可达monster-rooms.ts:276-280if (candidateRooms.length === 0) candidateRooms = rooms.slice()⇒ 所有房间都是安全区时,安全区规则被整体丢弃,怪物可刷进城镇wilderness.ts:2240-2243isRoad(nx, ny)越界时返回true⇒ 地图外被当作道路,整个外圈的道路瓦片 LUT 索引错误5. 其他小问题
monster-rooms.ts:113-121/:155-157:cellPixel* ?? 80两个轴都默认 80,但本引擎的等距格是 80×40 —— 高度默认值是错的。monster-rooms.ts:282:new Rng(seed ?? 0x5eed)⇒ 所有未传种子的关卡共用同一条 RNG 流,布局完全相同。wilderness.ts:5049:特殊路径恒报subTheme: 0。acts.ts:76:parseTable的lines.shift() ?? ''⇒ 零字节Levels.txt会产出一个「空但有效」的世界,而不是报错。acts.ts:372-374:为Act 5 - Barricade注入的Expansion/Siege/temptile.dt1不在LvlTypes.File 1..32中,来源不明,需补 provenance 注释。验收标准
acts.ts的数据驱动版本)Levels.txt ActPACK_RADIUS_PX统一为单一常量SUB_TILES_PER_TILE只保留map.ts一份,其余改为 importgenerateAct3Jungle删除maze-objects.ts:238的|| true删除difficulty参数贯通;或显式记录「暂不支持 NM/Hell」并加断言monster-rooms.ts房间系统接入生产路径,或明确删除npm run typecheck零错误,npx vitest run全绿TAG=agy
CONV=2a1934de-30ef-464e-b3f3-fcbcdbbc49f1
父追踪 Issue:#64(完整审计报告与修复路线图)
✅ Issue #63 修复与验证完成 (Closes #63)
变更总结
wilderness.ts:isRoad(nx, ny)越界检测修正为返回false,消除地图边缘非道路格误用道路瓦片 LUT 的 Bug。maze-objects.ts: 武器/防具架候选房间严格优先走廊房间(orths.length === 2 || isBarracks),消除导致走廊优先规则形同虚设的恒真条件。monster-rooms.ts: 在allocatePacksToRooms中,当候选非安全区房间为空(例如城镇或纯安全区关卡)时直接返回,禁止将普通怪物刷入城镇/安全区。monster-rooms.ts: 修正partitionMapIntoRooms中默认等距单元格高度为 40px(对齐 80×40 等距投影几何)。acts.ts:parseTable在传入 0 字节或全空表数据时显式抛出Error('parseTable: empty table data');补充Expansion/Siege/temptile.dt1的来源注释(Blizzard LOD patch 拼装 Act 5 攻城 DS1 依赖的地面过渡瓦片)。wilderness.ts: 提取BLOOD_MOOR_RIVER_PRESETS与BLOOD_MOOR_POND_PRESETS,消除血腥荒地预设列表在两处的数组副本分歧。combat.ts: 移除本地重复常量96,统一直接引用monster-rooms.ts中的规范PACK_RADIUS_PX(64)。wilderness-acts.ts: 将神秘避难所与塔拉夏古墓硬编码的字面量* 5统一替换为* SUB_TILES_PER_TILE(来自map.ts)。monsters.ts:monsterColumns改用基于表头检查的动态遍历(支持到mon25),防止 mod 数据静默截断。monsters.ts:planMonsterGroups普通怪类型选取依据kind.rarity加权(对齐selectLevelTypes稀有度分布规则)。monsters.ts:applyEliteModifiers为stoneskin(hp 2x)、cursed(dmg 1.2x)、coldenchant(dmg 1.2x)、fireenchant(dmg 1.2x)、lightenchant(dmg 1.2x)、spectralhit(dmg 1.2x)、teleport(speed 1.2x)、magicresistant(hp 1.2x)、aura(dmg 1.2x, speed 1.1x) 实装数值机制。独立复验记录 (Merged
a7e526d)npm run typecheck: 0 错误npx vitest run: 61 passed, 1018 passed, 2 skipped (全绿,新增 15 个测试)npx tsx scripts/verify-packs.ts: 1671/1671 assertions passed/usr/local/google/home/taodao/d2w-issue-63与分支fix/issue-63已清理完毕。TAG=agy
CONV=2a1934de-30ef-464e-b3f3-fcbcdbbc49f1