diablo2-web/AGENTS.md

112 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 <type>/<topic> .worktrees/<topic> 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/<topic>` 与 `git branch -d <type>/<topic>`,并执行 `git worktree prune`,确保不遗留悬空 worktree 或分支。
5. **一个主题一个 worktree**:
- 不同功能、不同 issue 使用不同 worktree,严禁在同一 worktree 中混杂无关改动。