fix(client): 角色动画播放速度未关联 1.13c AnimData.d2 与属性装备 (FCR/IAS/WSM) 且单次动作循环播放不恢复待机 (NU) #552
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
问题描述
当前客户端角色动画系统(关联 #544 与 #546)存在两个核心失真问题,违背 Diablo II 1.13c 原版动画引擎(
D2Common.dll/D2Client.dll+AnimData.d2+Weapons.txt)规范:1. 动画播放速度忽略
AnimData.d2基准速率与角色属性/装备加成(FCR / IAS / 武器 WSM)WorldRenderer.drawSceneUnitDrawable(src/client/scene/world-renderer.ts) 在计算角色帧索引时,忽略了char-*.json中从 1.13cAnimData.d2导出的每段动作 8.8 定点数基准步进速率(clip.speed,256= 1 帧 / 40ms tick),而是使用硬编码除数:wl/rn):Math.floor(ctx.animTimeMs / 65) % frameCountnu/tn/sc/a1/a2):Math.floor(ctx.animTimeMs / 140) % frameCountClientWorld.applySkillCastToUnit(src/client/world/client-world.ts) 使用硬编码的400ms(untilMs: now + 400) 作为所有施法与攻击动作的统一持续时间,完全未读取:statId = 105,item_fastercastrate)statId = 93,item_fasterattackrate) 与技能 IAS (statId = 68)world.containers.equipment) 及镶嵌物 (world.containers.sockets) 上的 FCR / IAS 词缀Weapons.txt中的武器基础速度修正 WSM (speed列,例如 Phase Blade7cr为-30、Maulmau为+20)2. 单次动作(
SC/A1/A2/GH/DT等loop: false)无限循环且结束后不恢复待机状态(NU)ClientWorld.applySkillCastToUnit将unit.mode设为10(SC) 或7/8(A1/A2) 并写入unit.castState(含untilMs),但在ClientWorld.tick()与OnlineSession.buildRenderableUnits()中从未检查nowMs >= castState.untilMs来清理castState并将unit.mode恢复为1(NU待机)。WorldRenderer.drawSceneUnitDrawable对所有动作无条件使用% frameCount取模,且使用全局累加的ctx.animTimeMs而非动作起始时间startedAtMs,导致非循环动作(clip.loop === false,如sc、a1、a2、gh、dt、dd):0帧起始播放;frameCount - 1)后不会停留在末帧或切回NU待机,而是周而复始无限鬼畜循环;predictor的dir64)也未能保持施法目标方向直到下一次移动。修复方案(1.13c Ground Truth 对齐)
AnimData.d28.8 定点数动画步进与边际递减公式:diminished = floor(120 * rate / (120 + rate))(与服务端src/server/engine/anim-dispatcher.ts保持一致)。SC, mode 10):汇总角色StatList与已装备物品/镶嵌物的 FCR (statId = 105),计算EFCR = clamp(diminished(fcr), -85, 75)。A1/A2, mode 7/8):汇总角色StatList与已装备物品/镶嵌物的 IAS (statId = 93)、技能 IAS (statId = 68) 以及Weapons.txt中已穿戴武器的 WSM (speed),计算EIAS = clamp(diminished(itemIas) + skillIas - weaponWsm, -85, 75)。stepSpeed256 = max(32, floor(baseSpeed * (100 + effRate) / 100))。durationMs = ceil(frames * 256 / stepSpeed256) * 40(基于 1.13c 25Hz = 40ms tick)。clip.loop === false的动作从startedAtMs的第0帧开始按stepSpeed256推进,并在frameCount - 1处截断(不再使用% frameCount循环)。nowMs >= castState.untilMs时,自动清理unit.castState与world.self.castState,并将unit.mode恢复为1(NU待机),同时保持施法结束时的角色朝向直到下次移动。UnitMove或本地predictor移动)或切换其他状态时,立即打断并清理残留的castState,切入WL/RN移动动画。已在提交
7bd10903f6修复并合并至 main:严格对齐 1.13c AnimData.d2 步进速度与 FCR/IAS/WSM 边际递减计算,消除单次动作无限循环并在动作周期结束后自动复位至 NU 待机模式。