[动画] 单位转向按 1.13c 转向表逐帧过渡(D2Common 0x6FDE41C8),目前是瞬间转向 #543

Closed
opened 2026-10-02 05:22:00 +00:00 by troytt · 1 comment
Owner

现象

fix/unit-facing 修复后,单位的朝向(dir64)在每段路径开始时一步跳到目标方向,行走/跑步动画也立刻切到新方向那一行。1.13c 原版大角度转身(例如 180° 掉头)时会逐帧经过中间方向转过去,不会一帧跳变。

1.13c 依据

  • 转向步长表:D2Common 0x6FDE41C8,64 字节,按 diff = (new − cur) & 63 取步长,加到当前方向上(& 63)。

    diff 0 1–8 9–16 17–31 32–47 48–55 56–63
    step 0 +1 +4 +8 −8 −4 −1
  • 设置目标方向:D2Common 0x6FD850B0 和 #10425 0x6FD85270。

    • 字段(D2DynamicPathStrc):+0x64 nDirection(当前)、+0x65 目标方向、+0x66 diff。
  • 单步推进:D2Common #10603 0x6FD84D70,对应 D2MOO PATH_AdjustDirection(Path.cpp:822-846)。

  • D2Client 调用点:

    • 0x6FACC507(玩家)
    • 0x6FAFF665(怪物)
    • 两处都经 thunk 0x6FABCD84 调用。

代码现状(fix/unit-facing 合并后)

  • src/client/motion/predictor.ts:本地玩家每段路径开始时直接 dir64 = dir64FromPoints(...)。
  • src/client/motion/interpolate.ts:远端单位同样直接赋值。
  • src/client/scene/world-renderer.ts:dir64ToClipDirection(unit.direction, dirCount) 直接选动画行。

上面三处都没有 current/target 之分,也没有按表逐步推进。

待确认(不要猜常数)

  • #10603 在 D2Client 里多久调用一次:每个逻辑帧(25 fps)、每个渲染帧,还是每走一个路径步?需要从 0x6FACC507 / 0x6FAFF665 所在函数及其调用者确认。
  • 站立模式(NU/TN)下是否也逐步转向,还是只在移动模式下。
  • 服务器包(0x0D / 0x0F / 0x67 / 0x68 / 0x6D 等)里的方向或目标坐标,客户端是当作目标方向(逐步转过去)还是直接设为当前方向。
  • 攻击和施法(施法朝向目标)是走这张表逐步转,还是立即转向。

期望修复

  • 单位朝向拆成 current / target 两个值,按 1.13c 的调用频率用 0x6FDE41C8 推进 current,渲染只用 current。
  • 测试:
    • 以 0x6FDE41C8 表为黄金值,校验各个 diff 的逐步推进序列。
    • 用二进制比对测试读取 samples/d2/D2Common.dll 中的表(参照 tests/unit-direction.test.ts 读 0x6FDDD470 / 0x6FE2F4D8 的写法)。
    • dir64 越界照旧直接抛错(fail fast)。

相关

  • 前置修复:branch fix/unit-facing,commit 0712b80 fix(client): keep unit animation facing aligned with movement direction(dir64 规范化、dir64FromPoints / dir64ToClipDirection)。该分支尚未合并到 main:main 工作区里有其他进行中的未提交改动,ff 合并被拒。
  • 参考:#3、#31、#145
## 现象 `fix/unit-facing` 修复后,单位的朝向(dir64)在每段路径开始时一步跳到目标方向,行走/跑步动画也立刻切到新方向那一行。1.13c 原版大角度转身(例如 180° 掉头)时会逐帧经过中间方向转过去,不会一帧跳变。 ## 1.13c 依据 - **转向步长表**:D2Common `0x6FDE41C8`,64 字节,按 `diff = (new − cur) & 63` 取步长,加到当前方向上(`& 63`)。 | diff | 0 | 1–8 | 9–16 | 17–31 | 32–47 | 48–55 | 56–63 | |---|---|---|---|---|---|---|---| | step | 0 | +1 | +4 | +8 | −8 | −4 | −1 | - **设置目标方向**:D2Common `0x6FD850B0` 和 #10425 `0x6FD85270`。 - 字段(`D2DynamicPathStrc`):`+0x64` nDirection(当前)、`+0x65` 目标方向、`+0x66` diff。 - **单步推进**:D2Common #10603 `0x6FD84D70`,对应 D2MOO `PATH_AdjustDirection`(`Path.cpp:822-846`)。 - **D2Client 调用点**: - `0x6FACC507`(玩家) - `0x6FAFF665`(怪物) - 两处都经 thunk `0x6FABCD84` 调用。 ## 代码现状(`fix/unit-facing` 合并后) - `src/client/motion/predictor.ts`:本地玩家每段路径开始时直接 `dir64 = dir64FromPoints(...)`。 - `src/client/motion/interpolate.ts`:远端单位同样直接赋值。 - `src/client/scene/world-renderer.ts`:`dir64ToClipDirection(unit.direction, dirCount)` 直接选动画行。 上面三处都没有 current/target 之分,也没有按表逐步推进。 ## 待确认(不要猜常数) - #10603 在 D2Client 里多久调用一次:每个逻辑帧(25 fps)、每个渲染帧,还是每走一个路径步?需要从 `0x6FACC507` / `0x6FAFF665` 所在函数及其调用者确认。 - 站立模式(NU/TN)下是否也逐步转向,还是只在移动模式下。 - 服务器包(`0x0D` / `0x0F` / `0x67` / `0x68` / `0x6D` 等)里的方向或目标坐标,客户端是当作目标方向(逐步转过去)还是直接设为当前方向。 - 攻击和施法(施法朝向目标)是走这张表逐步转,还是立即转向。 ## 期望修复 - 单位朝向拆成 `current` / `target` 两个值,按 1.13c 的调用频率用 `0x6FDE41C8` 推进 `current`,渲染只用 `current`。 - 测试: - 以 `0x6FDE41C8` 表为黄金值,校验各个 diff 的逐步推进序列。 - 用二进制比对测试读取 `samples/d2/D2Common.dll` 中的表(参照 `tests/unit-direction.test.ts` 读 `0x6FDDD470` / `0x6FE2F4D8` 的写法)。 - dir64 越界照旧直接抛错(fail fast)。 ## 相关 - 前置修复:branch `fix/unit-facing`,commit `0712b80` `fix(client): keep unit animation facing aligned with movement direction`(dir64 规范化、`dir64FromPoints` / `dir64ToClipDirection`)。该分支**尚未合并到 main**:main 工作区里有其他进行中的未提交改动,ff 合并被拒。 - 参考:#3、#31、#145
Author
Owner

更新(2026-10-02):fix/unit-facing 已 rebase 到最新 main,fast-forward 合并并推送(6a01067..8fcd223)。正文里“尚未合并”的说法已过时。

提交 说明
531273c feat(common): add 1.13c dir64 direction helpers
ea252b0 feat(netproto): encode 1.13c C2S 0x5F UpdatePlayerPos
dd775c8 fix(client): keep unit animation facing aligned with movement direction(即正文里的 0712b80,rebase 后哈希变了)
8fcd223 fix(client): face skill-cast targets with the 1.13c dir64(新增:applySkillCastToUnit 也改为写 dir64)

本 issue 要做的逐帧转向还没有实现:dir64 仍然在每段路径开始时一步跳到目标方向。

**更新(2026-10-02)**:`fix/unit-facing` 已 rebase 到最新 main,fast-forward 合并并推送(`6a01067..8fcd223`)。正文里“尚未合并”的说法已过时。 | 提交 | 说明 | |---|---| | [`531273c`](https://git.projectdiablo2.cn/troytt/diablo2-web/commit/531273c989fa92e56deca07c57702ad9ef84940a) | feat(common): add 1.13c dir64 direction helpers | | [`ea252b0`](https://git.projectdiablo2.cn/troytt/diablo2-web/commit/ea252b0414e390f6c78053f2b74a8834acd9a0f1) | feat(netproto): encode 1.13c C2S 0x5F UpdatePlayerPos | | [`dd775c8`](https://git.projectdiablo2.cn/troytt/diablo2-web/commit/dd775c8156ad9ef2e0b30605f7c33523027bbd4f) | fix(client): keep unit animation facing aligned with movement direction(即正文里的 `0712b80`,rebase 后哈希变了) | | [`8fcd223`](https://git.projectdiablo2.cn/troytt/diablo2-web/commit/8fcd2238cc70a054a2051845d247a3a3bc0024cd) | fix(client): face skill-cast targets with the 1.13c dir64(新增:`applySkillCastToUnit` 也改为写 dir64) | 本 issue 要做的逐帧转向还没有实现:dir64 仍然在每段路径开始时一步跳到目标方向。
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#543
No description provided.