[Skill Parity] 强化 (Enchant) 释放后身周火焰特效 (FireEnchant) 应仅单次播放 (One-shot),而非在 buff 期间持续循环播放 (loop: true) #438

Closed
opened 2026-09-24 08:29:05 +00:00 by troytt · 0 comments
Owner

问题描述 (Bug Description)

在当前游戏中,法师释放技能 强化 (Enchant, 技能 ID 52) 后,围绕在角色身周旋转升腾的火焰特效 (FireEnchant) 会随着角色不断循环播放(每隔约 1 秒循环一次),在长达数分钟的 buff 持续期间一直存在。

原版 Diablo II 1.13c 中,强化施放成功后身周升腾的火焰特效为一次性赋能/生效特效 (One-shot Cast/Application Overlay),播放完 17 帧后自然消散,绝非持续在角色身周死循环旋转的常驻火圈。


原版 1.13c 地面真理 (Diablo II 1.13c Ground Truth Invariants)

  1. 技能与特效配置 (Skills.txt & Overlay.txt):
    • 技能: Enchant (Skill ID 52, aurastate: enchant)。
    • 对应特效: Overlay.txt 中的 enchant (Filename: FireEnchant.dc6)。
    • 素材参数: Frames: 17, AnimRate: 16, Trans: 3(耗时约 1.06 秒 / 27 帧逻辑帧)。
  2. 机制差异对照 (Buff Shield vs One-shot Buff Application):
    • 体表常驻护盾 (Buff Shield Overlays):例如冰系三甲(Frozen Armor、Shiver Armor、Chilling Armor)和能量护盾(Energy Shield),属于持续防护罩,在整个持续时间内需要在角色体表常驻循环显示 (loop: true)。
    • 强化赋能特效 (Enchant Overlay):强化属于给武器赋予火焰伤害与命中率加成的技能。在对自身或盟友/随从施法命中时,仅在目标体表播放一次火焰旋涡升腾散去的 17 帧动画 (One-shot),播放完毕后该 Overlay 即自然销毁。
    • 强化持续生效期间(数分钟),角色体表不应存在持续循环旋转的火焰特效。

缺陷代码定位 (Root Cause Analysis)

  1. 施法逻辑错误开启了 loop: true:

    • 在 src/scene/act-scene.ts (行 1813):
      engine.spawnOverlay('enchant', { x: player.x, y: player.y }, 'player', { loop: true })
      
      此处错误传入了 { loop: true },导致引擎在动画播完第 17 帧后执行取模循环:
      overlay.frame = overlay.frame % overlay.maxFrames,从而无限重复播放。
  2. 引擎将 Overlay 存活绑定到整个 Buff 持续时长:

    • 在 src/game/engine.ts (行 651-655):
      if (player.enchantTicks <= 0) {
        player.enchantTicks = 0
        player.enchantDamage = undefined
        player.enchantAttackRatingPercent = undefined
        for (const ov of this.overlays) {
          if (ov.overlayName === 'enchant' && ov.casterId === 'player') {
            ov.expired = true
          }
        }
      }
      
      引擎误将 enchant overlay 的生命周期设计为与 player.enchantTicks(数千 ticks)强绑定,进一步助长了长时间循环播放的问题。

修复建议 (Proposed Fix)

  1. 取消循环播放标志:
    • 在 src/scene/act-scene.ts 中,将 spawnOverlay('enchant', ...) 的 { loop: true } 移除(或置为 { loop: false }):
      engine.spawnOverlay('enchant', { x: player.x, y: player.y }, 'player')
      
  2. 利用引擎原生单次播放自动销毁机制:
    • engine.ts 中已有完善的非循环 Overlay 逻辑:当 overlay.frame >= overlay.maxFrames 时,若非 overlay.loop,则直接标记 overlay.expired = true 并过滤清理。
    • 这样强化火���将在播放完 17 帧(约 1 秒)后自然熄灭消散,完美还原 1.13c 原版表现。
### 问题描述 (Bug Description) 在当前游戏中,法师释放技能 **强化 (Enchant, 技能 ID 52)** 后,围绕在角色身周旋转升腾的火焰特效 (`FireEnchant`) 会随着角色不断**循环播放**(每隔约 1 秒循环一次),在长达数分钟的 buff 持续期间一直存在。 原版 Diablo II 1.13c 中,强化施放成功后身周升腾的火焰特效为**一次性赋能/生效特效 (One-shot Cast/Application Overlay)**,播放完 17 帧后自然消散,绝非持续在角色身周死循环旋转的常驻火圈。 --- ### 原版 1.13c 地面真理 (Diablo II 1.13c Ground Truth Invariants) 1. **技能与特效配置 (`Skills.txt` & `Overlay.txt`)**: - 技能: `Enchant` (Skill ID 52, `aurastate: enchant`)。 - 对应特效: `Overlay.txt` 中的 `enchant` (Filename: `FireEnchant.dc6`)。 - 素材参数: `Frames: 17`, `AnimRate: 16`, `Trans: 3`(耗时约 1.06 秒 / 27 帧逻辑帧)。 2. **机制差异对照 (Buff Shield vs One-shot Buff Application)**: - **体表常驻护盾 (Buff Shield Overlays)**:例如冰系三甲(`Frozen Armor`、`Shiver Armor`、`Chilling Armor`)和能量护盾(`Energy Shield`),属于持续防护罩,在整个持续时间内需要在角色体表常驻循环显示 (`loop: true`)。 - **强化赋能特效 (Enchant Overlay)**:强化属于给武器赋予火焰伤害与命中率加成的技能。在对自身或盟友/随从施法命中时,仅在目标体表播放一次火焰旋涡升腾散去的 17 帧动画 (`One-shot`),播放完毕后该 Overlay 即自然销毁。 - 强化持续生效期间(数分钟),角色体表不应存在持续循环旋转的火焰特效。 --- ### 缺陷代码定位 (Root Cause Analysis) 1. **施法逻辑错误开启了 `loop: true`**: - 在 `src/scene/act-scene.ts` (行 1813): ```typescript engine.spawnOverlay('enchant', { x: player.x, y: player.y }, 'player', { loop: true }) ``` 此处错误传入了 `{ loop: true }`,导致引擎在动画播完第 17 帧后执行取模循环: `overlay.frame = overlay.frame % overlay.maxFrames`,从而无限重复播放。 2. **引擎将 Overlay 存活绑定到整个 Buff 持续时长**: - 在 `src/game/engine.ts` (行 651-655): ```typescript if (player.enchantTicks <= 0) { player.enchantTicks = 0 player.enchantDamage = undefined player.enchantAttackRatingPercent = undefined for (const ov of this.overlays) { if (ov.overlayName === 'enchant' && ov.casterId === 'player') { ov.expired = true } } } ``` 引擎误将 `enchant` overlay 的生命周期设计为与 `player.enchantTicks`(数千 ticks)强绑定,进一步助长了长时间循环播放的问题。 --- ### 修复建议 (Proposed Fix) 1. **取消循环播放标志**: - 在 `src/scene/act-scene.ts` 中,将 `spawnOverlay('enchant', ...)` 的 `{ loop: true }` 移除(或置为 `{ loop: false }`): ```typescript engine.spawnOverlay('enchant', { x: player.x, y: player.y }, 'player') ``` 2. **利用引擎原生单次播放自动销毁机制**: - `engine.ts` 中已有完善的非循环 Overlay 逻辑:当 `overlay.frame >= overlay.maxFrames` 时,若非 `overlay.loop`,则直接标记 `overlay.expired = true` 并过滤清理。 - 这样强化火���将在播放完 17 帧(约 1 秒)后自然熄灭消散,完美还原 1.13c 原版表现。
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#438
No description provided.