diablo2-web/docs/issue-386-cast-overlay-spec.md

93 lines
6.9 KiB
Markdown
Raw 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.

## 暗黑破坏神 II (v1.13c) 施法视觉效果 (Cast Overlay) 底层调查与实现设计规范
### 一、 机制调查与 1.13c 真实底层数据 (Ground Truth Invariant)
在暗黑破坏神 II v1.13c 引擎体系(`D2Common.dll`、`D2Client.dll`)中,释放法术时角色脚下涌现并包裹全身的动画效果并非角色自身动作(Action Frame)或飞弹(Missile),而是属于 **Unit Overlay(单位覆盖动画系统)**。
#### 1. 数据驱动关系
1. **`Skills.txt`**:包含列 **`castoverlay`**,定义技能施展时触发的覆盖效果标识(例如技能 36 火弹绑定 `fire_cast_1`)。
2. **`Overlay.txt`**:集中定义所有覆盖效果的物理与渲染属性:
- **`Filename`**:指向 DCC 动画资源路径(位于 `d2data.mpq: data/global/overlays/{Filename}.dcc`)。
- **`Frames`**:动画总帧数。
- **`AnimRate`**:动画播放速率。法术施法特效原版均为 **16**(代表在 25 FPS 逻辑刻下,每 25 tick 播放 16 帧动画,即步长 `16 / 25 = 0.64` 帧/刻,总时长约 0.88 秒)。
- **`Trans`**:混合渲染模式。原版为 **3**(**Additive Blending / 增色叠加混合**),呈现火焰、电光与寒冰的自发光半透明视觉质感。
- **`PreDraw`**:渲染层级。原版均为 **0**(**Foreground / 前景层**),先绘制施法者角色精灵,再在前景叠加该 Overlay,形成火焰包裹躯干的立体层次。
- **`Xoffset` / `Yoffset` / `Height1..4`**:均为 **0**,严格以施法者单位脚底地面中心点 `(0, 0)` 为基准。
- **`InitRadius` / `Radius` / `Red, Green, Blue`**:动态点光源参数(半径均为 9 个子网格)。Overlay 激活期间会在角色周围投射对应属性的动态光晕。
---
### 二、 核心法术原版 Overlay 映射与 DCC 规格表
经解析 `samples/d2/Patch_D2.mpq` 与 `d2data.mpq`,法师三大元素系法术完整映射如下:
| 技能类别 | 技能名称 (Id) | `Skills.txt` `castoverlay` | DCC 文件名 (`data/global/overlays/`) | 帧数 | DCC 碰撞盒 (Left, Top, W, H) | 光照颜色 (R, G, B, Radius) | 视觉特征 |
| :--- | :--- | :--- | :--- | :---: | :--- | :--- | :--- |
| **火焰系** | **火弹 Fire Bolt (36)** | `fire_cast_1` | `FireCast_for_Sorceress.dcc` | 14 | `[-55, -127, 117, 164]` | (255, 178, 64, 9) | **从脚底升腾直窜头顶的火焰柱 (即 Issue 附件效果)** |
| **火焰系** | 火球 (47), 强化/火焰强化 (46), 火墙 (51), 陨石 (56), 九头海蛇 (62) | `fire_cast_2` | `FireCast2.dcc` | 16 | `[-74, -89, 145, 133]` | (255, 178, 64, 9) | 范围更大、旋转包裹的炽热烈焰 |
| **冰霜系** | 冰弹 (39), 冰封甲 (40), 冰风暴 (45) | `ice_cast_1` | `IceCastNew01.dcc` | 15 | `[-49, -90, 97, 55]` | (81, 81, 255, 9) | 脚下微弱旋起的寒冰碎屑与白霜冷雾 |
| **冰霜系** | 霜之新星 (44), 碎冰甲 (50), 冰尖柱 (55) | `ice_cast_2` | `IceCastNew02.dcc` | 15 | `[-58, -100, 115, 123]` | (81, 81, 255, 9) | 向上旋转升腾的深蓝冰柱与霜雾 |
| **冰霜系** | 暴风雪 (59), 寒冰甲 (60), 冰封球 (64) | `ice_cast_3` | `IceCastNew03.dcc` | 16 | `[-63, -113, 127, 148]` | (81, 81, 255, 9) | 强烈的暴风雪霜华与立体冰凌环绕 |
| **闪电系** | 充能弹 (38), 静电场 (42), 新星 (48), 闪电 (49), 连锁闪电 (53) | `light_cast_1` | `LightningCast.dcc` | 10 | `[-79, -107, 164, 144]` | (255, 255, 255, 9) | 脚底向外炸裂并包裹全身的电弧跳跃 |
| **闪电系** | 心灵传动 (43), 雷云风暴 (57), 能量护盾 (58) | `light_cast_2` | `LightningCastRunesFront.dcc` | 10 | `[-73, -154, 147, 190]` | (255, 255, 255, 9) | 闪电符文闪耀与高耸电光柱 |
| **特殊** | 传送 Teleport (54) | `teleport` | `Teleport.dcc` | 18 | `[-61, -108, 136, 154]` | (255, 255, 200, 5) | 金黄色空间坍缩与残影粒子 |
---
### 三、 系统架构与实现方案 (diablo2-web)
遵循项目 **Zero Runtime MPQ Invariant** 及 **Anti-Silent Failures** 原则:
#### 1. 离线资源烘焙流水线 (`scripts/pack-overlays.ts`)
- 提取 `d2data.mpq` 中上述 8 个关键施法 Overlay DCC 精灵文件。
- 读取 `data/global/palette/ACT1/pal.pl2` 进行真实调色板色彩映射。
- 将单向动画打包成 PNG 纹理图集并导出 JSON 元数据至 `public/overlays/` 与 `samples/d2-packs/overlays/`。
- 自动生成类型定义 `src/render/overlays-meta.ts`,提供精确的 `box.left, box.top, width, height, animRate, trans` 常量。
#### 2. 运行时数据契约与实体抽象 (`src/game/skills.ts` & `src/game/engine.ts`)
- 扩展 `SkillDef` 接口,包含 `castOverlay?: string`。
- 建立 `CANONICAL_113C_OVERLAYS` 真值表,包含 overlay 标识到对应资源与物理属性的映射。
- 在 `GameEngine` 中引入 `ActiveOverlay` 活跃实体管理:
```typescript
export interface ActiveOverlay {
readonly id: string
readonly overlayName: string
readonly casterId: string
x: number
y: number
frame: number
readonly maxFrames: number
readonly animRate: number
readonly preDraw: boolean
readonly trans: number
readonly lightRadius: number
readonly lightColor: readonly [number, number, number]
expired: boolean
}
```
- **生命周期规则**:
- 玩家或怪物在 `executePlayerSkillCast` 触发施法动作时,根据技能 `castoverlay` 生成 `ActiveOverlay`。
- 每个逻辑 tick(25 FPS):`overlay.frame += overlay.animRate / 25`。
- 当 `Math.floor(overlay.frame) >= overlay.maxFrames` 时,标记 `expired = true` 并在 tick 结束时销毁(单次播放不循环)。
- Overlay 坐标实时同步施法者当前脚下位置 `(caster.x, caster.y)`。
#### 3. 渲染管线集成 (`src/scene/act-scene.ts`)
- 资源载入:通过 `loadOverlayArtMap` 预载 `overlays/*.png`。
- 深度层级(Z-Order):
- 角色绘制完成后、飞弹绘制前,执行前景 Overlay 渲染。
- 混合模式(Blend Mode):
- 遇到 `trans === 3`,切换 Canvas2D `ctx.globalCompositeOperation = 'lighter'` 或 WebGL Additive 混合状态,绘制完成后恢复 `source-over`。
- 锚点投影(Anchor Projection):
- 精确应用 DCC 包围盒偏移:`drawX = overlay.x + frameMeta.anchorX`,`drawY = overlay.y + frameMeta.anchorY`。
- 动态光照反馈:
- 在 Overlay 存活期间,将其注册为动态点光源(如火焰投射 9 码的 RGB(255, 178, 64) 暖黄光晕)。
---
### 四、 验证与回归测试策略
1. **表格对齐测试**:验证 `parseSkillsTxt` 与 `Skills.txt`、`Overlay.txt` 的 `castoverlay` 字段及参数完全一致。
2. **生命周期测试**:验证 14 帧的 `fire_cast_1` 在 25 FPS 模拟下,在第 22 个 tick 精确结束并移除。
3. **渲染与图集测试**:验证 `FireCast_for_Sorceress`、`IceCastNew01`、`LightningCast` 纹理图集无缺失、锚点边界无裁切、Additive 模式下正确渲染。
4. **全场景稳定性**:自动化 Headless 运行,保障全 136 个关卡环境施法 Overlay 无跨法术贴图污染或未定义崩溃。