# Diablo II Web 逆向与工程保真度开发铁律 (D2 Parity Rules) > [!IMPORTANT] > 本项目为暗黑破坏神 2(Diablo II v1.13c)Web 端移植与高保真复刻项目。 > 在任何开发、重构、修复与测试过程中,**必须严格遵守 Diablo II 1.13c 原版底层二进制(DLL 汇编与 C 逻辑)及 MPQ 官方数据表规范**。 > 严禁凭空发明伪规则,严禁通过“静默容错”掩盖管线断层。 --- ## 1. 原版权威与反伪逻辑准则 (Ground Truth Priority) 1. **原版逻辑为唯一最高准则**: - 遇到地图生成(DRLG)、掉落(TC / Drop Pipeline)、怪物属性与随从(MonStats / SuperUniques)、物理碰撞(Collision)等机制疑问时,必须严格以 1.13c 逆向工程反汇编及官方数据表(`LvlTypes.txt`, `LvlPrest.txt`, `Levels.txt`, `SuperUniques.txt`, `TreasureClassEx.txt`)为唯一事实来源。 2. **严禁凭个别样本盲目类推**: - 暗黑2共有 136 个 Level ID,包含预置建筑、迷宫拼接、野外生成等截然不同的 DRLG 范式。 - 严禁仅测试 Act 1 鲜血荒地或罗格营地即假定全图可用。任何地图算法改动必须经受全 136 关卡全量场景普查。 3. **杜绝“自创”Style / Sequence 编号**: - 程序化地貌贴图、路网、围墙、水系过渡所使用的 `style` 与 `sequence` 必须来自该关卡绑定的 DT1 库实际导出定义,严禁跨章节挪用(例如严禁在沙漠、高地、雪山中使用 Act 1 的 Style 0 泥路或 Style 2 水面)。 --- ## 2. 地图与瓦片渲染铁律 (DRLG & Tile Invariants) 1. **三通用 DT1 常驻加载机制(1.13c `DRLGROOM_LoadDt1Files`)**: - 依据 1.13c 汇编逻辑(`D2Common.dll` @ 0x6fdb8400),任何关卡在解析完其 `LvlTypes.txt` 声明的 DT1 后,**必须无条件追加加载 3 个全局通用 DT1 库**: - `data\global\tiles\Act1\Outdoors\Blank.dt1` - `data\global\tiles\Act1\Barracks\InvisWal.dt1` - `data\global\tiles\Act1\Barracks\Warp.dt1` - 其中 `InvisWal.dt1` 包含 `style=49 sequence=7` 的地面瓦片(用于行走阻挡的隐形碰撞墙,见于 Act 5 混沌避难所、地狱、世界之石等处),严禁将其作为缺少贴图(missingTile)跳过。 2. **空单元格阻挡掩码与玩家出生点定位**: - 地图未放置有效地面瓦片的纯黑虚空区域,必须在子网格(Sub-tile)上严格打满 `blocked = 1` 与 `COLLIDE_MASK_INVALID`(包含 `COLLIDE_BLANK = 0x0001` 与 `COLLIDE_WALL = 0x0004`)。 - 玩家出生点搜寻(`findIsoSpawn`)**绝对严禁**直接取地图几何中心点 `(width/2, height/2)`。在非矩形或中空地图(如遗忘之塔外景、皇宫、秘密避难所等),中心点极可能是纯黑虚空。 - 出生点必须严格落在“物理连通、有非隐藏有效地面瓦片且 `blocked === 0`”的最大可行走连通分量上,优先靠近传送门(Warp)或小站(Waypoint)。 3. **消除平铺条纹:严禁在空间离散中使用简单线性算术**: - 地块变体选择(`pickVariant`)严禁使用 `((x * A) ^ (y * B)) % count` 这类简单线性同余公式。在二维离散规则网格上,线性乘积会导致明显的 45 度斜向周期性机械几何平铺条纹。 - 变体散列必须使用高熵伪随机空间哈希(如 SplitMix64 坐标散列),并通过空间方差统计单测确保视觉离散度。 --- ## 3. 严禁以“防御性编程”掩盖系统性缺陷 (Anti-Silent Failures) 1. **严禁宽容吞错的伪 Fallback**: - 严禁编写类似 `if (availableTiles.size === 0) return true;` 这类无原则放行逻辑。核心参数(如 DT1 库、关卡配置)漏传时,必须显式抛出异常或严格判定不可用,决不能让缺失数据伪装成“全量支持”。 2. **杜绝越界贴图跨章节污染**: - 自动贴图 LUT(Auto-tiling LUT)必须在每次应用贴图更新前,严格执行 `isTileAvailable(style, sequence)` 校验,未声明的贴图一律禁止写入渲染管线。 --- ## 4. 资产管线与数据保真度 (Data & Pipeline Fidelity) 1. **离线烘焙预打包(Pack)与运行时必须全链路对齐**: - 严禁预打包脚本维护一套写死的窄白名单,而运行时又依赖动态未打包资产。 - 所有暗金怪(`SuperUniques`)必须自动推导并解析其随从(Minions)所依赖的全部 DCC/DC6 动画与材质资源,一并纳入离线打包构建。 2. **原版文本数据转录不得篡改或简化**: - `SuperUniques.txt`、`MonStats.txt` 等元数据必须严格保留原版 Class 标识(如 `scarab2`, `zombie5`, `fetishshaman4`, `nihlathakboss` 等具体变体),禁止粗暴截断变体数字后缀或自编别名。 3. **技能与投射物美术资源必须采用原版资源并离线烘焙 (Missile & Spell FX Parity)**: - 严禁长期使用由代码绘制的方块、纯几何色块或纯程序化简易图形作为技能投射物/特效替代品。 - 所有技能投射物(Missiles)、次生爆炸(Explosions)、状态光环与法术特效,必须严格以 1.13c 原版 MPQ(`d2data.mpq` / `d2exp.mpq` / `Patch_D2.mpq`)中由 `Missiles.txt` 的 `CelFile` 字段所引用的原版 DCC / DC6 动画文件为准(例如 `Firebolt.dcc`, `Fireball.dcc`, `FireArrowExplode2.dcc` 等)。 - 必须通过离线解包烘焙脚本(如 `scripts/pack-missiles.ts`)结合章节调色板(`ACT1/pal.pl2`),将原版 DCC/DC6 的全部朝向(如 16 方向)与全帧序列预打包烘焙为 Web 原生 Sprite Atlas(图集)及对应元数据,供前端 WebGL 运行时直接高效索引与渲染。 - 音效接入解耦:现阶段音效系统(`Sounds.txt` / WAV 音频资源)允许暂缓接入,但视觉动画必须具备 100% 像素级原版 DCC 贴图资产与帧率对齐。 4. **法术投射物透明度与黑边消除铁律 (Missile Transparency & Additive Blending Parity)**: - 依据 1.13c `Missiles.txt`,所有魔法投射物与爆炸(除普通物理箭矢 `arrow` 外)均声明 `Trans: 1`(Alpha / Additive 加法半透明)。 - MPQ 原版 DCC 动画帧在提取时背景或抗锯齿过渡区存在深黑底色(如调色板索引 172 对应 RGB `(4, 4, 4)`)。若直接生成仅以索引 0 透明的调色板 PNG 并使用标准混合渲染,会在画面上产生明显的黑色方框或黑色毛边瑕疵(Issue #385)。 - **材质级透明处理**:投射物图集必须离线烘焙为 32-bit RGBA PNG(`colorType = 6`),且对 `Trans: 1` 法术图集严格执行零黑边过滤——凡底色或暗色过渡像素(`max(r, g, b) <= 4`)其 Alpha 通道必须强行置为 0,暗部边缘平滑过渡,确保图集中非透明黑像素数量严格为 0。 - **着色器级混合模式**:WebGL `SpriteRenderer` 必须支持并采用加法混合(`blendMode: 'additive'`,即 `gl.blendFunc(gl.SRC_ALPHA, gl.ONE)`),实现法术发光光晕叠加与 100% 零黑边渲染;普通物理投射物(`Trans: 0`)采用常规 Alpha 混合(`gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA`)。 --- ## 5. 质量验证与门禁标准 (Verification Standards) 任何涉及地图、物品、怪物及战斗核心机制的代码提交,必须通过以下铁门禁: 1. **全量无头自动化实机走查**:涉及渲染和地图变动,必须执行全 136 个关卡的自动化走查截图或状态检验,杜绝抽检盲区。 2. **严苛静态类型与全量单测**: - `npm run typecheck` 必须保持 **0 errors**。 - `npx vitest run` 必须保持全量套件 100% 通过(包括 `global-dt1-load.test.ts`, `iso-spawn-void-guard.test.ts`, `variant-distribution.test.ts`, `superuniques-fidelity.test.ts` 等防退化单测)。 --- ## 6. 斜视角与地图物理坐标 vs 渲染图标铁律 (Isometric Perspective & Coordinate Disambiguation) 1. **2:1 斜视角投影下地面圆形的几何特征 (2:1 Isometric Projection Parity)**: - 暗黑破坏神 2 采用 2:1 二等角投影(Isometric / Dimetric Projection,菱形单元格宽 80、高 40,子图元 Sub-tile 宽 16、高 8,垂直/水平轴比 `ISO_GROUND_ASPECT_RATIO = 0.5`)。 - 任何在游戏世界地面平面(Ground Plane)上的圆形或径向扩张技能(如祝福之槌 Blessed Hammer 的阿基米德螺旋线、剧毒新星 Poison Nova 的 360 度圆环扩散、法术爆炸范围 AoE 伤害判定等),在投影到场景/屏幕像素坐标空间时,其几何形态在视觉上**绝对是椭圆**(长轴为水平 $X$,短轴为垂直 $Y$,且短半轴长为长半轴长的 $0.5$ 倍)。 - 严禁在场景坐标中使用各向同性的 1:1 正圆公式计算地面运动轨迹,否则在视觉上会呈现出立在镜头正前方的“空中竖立圆圈”,与 2:1 倾斜地貌产生严重透视断层。 2. **地图物理坐标与渲染图标严格区分 (Map Coordinates vs. Rendered Sprite Icons)**: - **地图物理坐标(Map / World Simulation Coordinates)**:`projectile.x`, `projectile.y` 以及速度向量 `vx, vy` 计算出的是投射物在地图平面上的物理世界坐标,负责与怪物碰撞盒、地形阻挡掩码(`COLLIDE_MASK_MISSILE`)进行物理检测与命中判定。 - **渲染图标(Rendered Sprite Billboard)**:投射物的视觉图元是基于原版 DCC 导出的 2.5D 公告板(Billboard),其在渲染时由 `drawMissileProjectile` 通过 `shot.x + frame.anchorX`, `shot.y + frame.anchorY` 锚点对齐绘制,并依据切线速度向量 `(vx, vy)` 的朝向动态选取 16/32 方向的 DCC 预烘焙视角图。 - **严禁混淆两者的职责**:绝对禁止通过拉伸/变形渲染图标去强行模拟椭圆,也绝对禁止把渲染图标的像素尺寸误当作物理坐标。渲染图标保持原版 DCC 原始比例,而物理轨迹坐标严格遵循 2:1 地面椭圆数学方程。 --- ## 7. Git Worktree 隔离开发铁律 (Mandatory Worktree Isolation) > [!IMPORTANT] > 适用于所有人类开发者与所有 AI Agent(包括 teamwork 多智能体编排器及其派生的全部子 Agent)。 1. **所有新改动必须在独立 worktree 中进行**: - 任何代码、脚本、资产、测试或文档改动,开工前必须先从最新 `main` 新开独立分支与 worktree,例如: `git worktree add -b / .worktrees/ main` - **严禁直接在主工作区(仓库根目录的 `main` 检出)上编辑文件或提交。** 2. **不得触碰他人未提交的改动**: - 主工作区或其他 worktree 中存在的未提交改动(modified / untracked)属于其他进行中的工作,严禁 `checkout`、`restore`、`stash`、`reset`、`clean`、覆盖或顺带提交。 - 合并时只允许带入本 worktree 分支自身的提交。 3. **完成后合并回 `main`**: - 在 worktree 内完成开发并通过门禁(`npm run typecheck` 0 errors、相关 `vitest` 全部通过)后,再合并回 `main`(优先 fast-forward;若 `main` 已前进,先在 worktree 内 rebase 到最新 `main` 并重新验证)。 - 合并后推送到 `origin/main`。 4. **合并后必须清理 worktree**: - 合并并推送成功后,立即执行 `git worktree remove .worktrees/` 与 `git branch -d /`,并执行 `git worktree prune`,确保不遗留悬空 worktree 或分支。 5. **一个主题一个 worktree**: - 不同功能、不同 issue 使用不同 worktree,严禁在同一 worktree 中混杂无关改动。