[Parity][render][S1][R] 循环 missile / overlay 动画被推进了两次(约 2 倍速,相位跟着全局时钟走) #602

Closed
opened 2026-10-02 11:42:45 +00:00 by troytt · 0 comments
Owner

1.13c 客户端保真度审计立项(基准快照:7bd1090 / main @ 77a20c7)

证据标记说明:V-data = 1.13c MPQ 数据表 (.txt / animdata.d2 / .tbl / pal.pl2);V-src = D2MOO 逆向源码;V-bin = 1.13c DLL 反汇编;K = 1.13c 公认行为。

来源审计项:render#1 — [S1][R] 循环 missile / overlay 动画被推进了两次(约 2 倍速,相位跟着全局时钟走)

  • 位置:
    • src/client/scene/world-renderer.ts:932-936(drawSceneMissileDrawable)
    • src/client/scene/world-renderer.ts:992-996(drawSceneOverlayDrawable)
    • 帧号来源:src/client/world/client-world.ts:1214-1219(missile:floor(ageTicks*animSpeed/16))、client-world.ts:1511-1521(overlay:floor(ageTicks*animRate/16))、src/client/view/unit-drawables.ts:390-393、:449-452(没有 frame 时用 tick)、:525(状态 overlay:tick % meta.totalFrames)
  • 代码:
    : (missile.frame + computeAnimDataFrameIndex(nowMs, animSpeed * 16, frameCount, true)) % frameCount
    : (overlay.frame + computeAnimDataFrameIndex(nowMs, animRate * 16, frameCount, true)) % frameCount
    
  • 原版:每个单位只有一个 8.8 定点帧累加器(nSeqCurrentFramePrecise += wAnimSpeed)。missile 的速度和帧数在切换模式时由行数据一次性确定:wAnimSpeed = (animrate<<8)/1024,dwFrameCountPrecise = AnimLen<<8(证据:V-src D2MOO/source/D2Common/src/Units/Units.cpp:795-802)。不存在"单位自身帧号 + 全局时钟帧号"两路相加。
  • 影响:所有 loop 的 missile(火球、冰弹、电球、火墙、冰封球……)以及所有 loop 的 overlay(状态 overlay、光环)大约以 2 倍速播放;而且起始相位取决于 nowMs 在出生那一刻的值(等于随机),同类 missile 之间不同步。客户端 tick 已经推进的 frame 又被时钟再推一次。
  • 建议:只保留一路推进:要么完全用 unit.frame(client-world 已按 tick 推进),要么完全用 (nowMs - spawnMs) 计算。速度用 missiles.txt 当前行的速度列(见 S2「missile 动画参数」与待确认 #2),帧数用 AnimLen。
  • 已有 issue:—(#552 只改了玩家 / 怪物的一次性动画,没有涉及 missile / overlay)
> **1.13c 客户端保真度审计立项**(基准快照:`7bd1090` / `main @ 77a20c7`) > 证据标记说明:`V-data` = 1.13c MPQ 数据表 (`.txt` / `animdata.d2` / `.tbl` / `pal.pl2`);`V-src` = D2MOO 逆向源码;`V-bin` = 1.13c DLL 反汇编;`K` = 1.13c 公认行为。 ### 来源审计项:`render#1` — [S1][R] 循环 missile / overlay 动画被推进了两次(约 2 倍速,相位跟着全局时钟走) - 位置: - `src/client/scene/world-renderer.ts:932-936`(`drawSceneMissileDrawable`) - `src/client/scene/world-renderer.ts:992-996`(`drawSceneOverlayDrawable`) - 帧号来源:`src/client/world/client-world.ts:1214-1219`(missile:`floor(ageTicks*animSpeed/16)`)、`client-world.ts:1511-1521`(overlay:`floor(ageTicks*animRate/16)`)、`src/client/view/unit-drawables.ts:390-393`、`:449-452`(没有 frame 时用 `tick`)、`:525`(状态 overlay:`tick % meta.totalFrames`) - 代码: ```ts : (missile.frame + computeAnimDataFrameIndex(nowMs, animSpeed * 16, frameCount, true)) % frameCount : (overlay.frame + computeAnimDataFrameIndex(nowMs, animRate * 16, frameCount, true)) % frameCount ``` - 原版:每个单位只有一个 8.8 定点帧累加器(`nSeqCurrentFramePrecise += wAnimSpeed`)。missile 的速度和帧数在切换模式时由行数据一次性确定:`wAnimSpeed = (animrate<<8)/1024`,`dwFrameCountPrecise = AnimLen<<8`(证据:V-src `D2MOO/source/D2Common/src/Units/Units.cpp:795-802`)。不存在"单位自身帧号 + 全局时钟帧号"两路相加。 - 影响:所有 loop 的 missile(火球、冰弹、电球、火墙、冰封球……)以及所有 loop 的 overlay(状态 overlay、光环)大约以 2 倍速播放;而且起始相位取决于 `nowMs` 在出生那一刻的值(等于随机),同类 missile 之间不同步。客户端 tick 已经推进的 `frame` 又被时钟再推一次。 - 建议:只保留一路推进:要么完全用 `unit.frame`(client-world 已按 tick 推进),要么完全用 `(nowMs - spawnMs)` 计算。速度用 `missiles.txt` 当前行的速度列(见 S2「missile 动画参数」与待确认 #2),帧数用 `AnimLen`。 - 已有 issue:—(#552 只改了玩家 / 怪物的一次性动画,没有涉及 missile / overlay)
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#602
No description provided.