[Interaction Parity] 鼠标悬停在地面掉落物品图标上时应即时显示该物品名称标签 (Hover Ground Item Icon to Reveal Name Label) #447

Closed
opened 2026-09-24 12:32:52 +00:00 by troytt · 0 comments
Owner

1. 问题背景与现状 (Bug Description & Current Behavior)

在当前客户端中,怪物掉落或玩家从包裹扔到地上的物品会以等距地面图标(Ground Sprite / Flippy 动画)形式展示在世界场景中。

然而,目前的地面名称标签(Ground Item Label)完全绑定在键盘 Alt 键的按下状态上:

  • 仅当玩家按住 Alt 键(hudManager.showGroundLabels === true)时,系统才会批量计算并显示所有地面物品的名称标签。
  • 当玩家未按住 Alt 键时,即使将鼠标光标移动并悬停在地面物品图标正上方,屏幕上也毫无任何反馈(没有名称提示框、没有品质颜色提示)。

这导致玩家若不按住 Alt 键,便无法通过鼠标悬停来快速查验地上的掉落物究竟为何物,与原版《暗黑破坏神 2》经典交互体验严重脱节。


2. 原版 Diablo II v1.13c 地面交互规范 (Ground Truth Invariants)

在《暗黑破坏神 2》原版(v1.13c)中,地面的每个掉落物(UNIT_ITEM,animmode = ITEMMODE_ONGROUND / 0)均属于可悬停高亮的目标实体:

  1. 单体鼠标悬停显名 (Single Hover Label Trigger):
    • 当玩家未按 Alt 键时,鼠标指针滑过地面任意掉落物品的碰撞/判定区域(D2Client.dll 命中测试 pItemUnderMouse)时,该物品的正上方会立即单独浮现该物品的名称标签框。
    • 标签外观与 Alt 标签规范严格保持一致:经典半透明黑底背景(rgba(0, 0, 0, 0.88))、1px 细线边框、点阵字体、原版 1.13c 品质文字色彩(D2WinFont 调色板)。
  2. 原版品质色彩严格对应 (Item Quality Colors):
    • 普通装备 / 底材 / 卷轴 / 钥匙:白色 / 银灰 (#FFFFFF / #D8D8D8)
    • 低质 / 破损 / 无形 / 带孔:灰色 (#808080)
    • 魔法装备:经典蓝 (#6868FF)
    • 稀有装备:黄金黄 (#FFFF64)
    • 套装装备:明亮绿 (#00FC00)
    • 暗金装备:古铜暗金 (#C8A15A)
    • 符文 / 橙色手工:鲜艳橙 (#FF9C18)
    • 金币:亮金黄色(展示具体金额,如 150 金币)
  3. 悬停移出即刻隐退 (Hover Leave Auto-Dismiss):
    • 鼠标光标移出该地面物品判定区后,该名称标签即时隐藏。
  4. Alt 键协同过渡机制 (Alt Key Concurrency):
    • 按住 Alt 键时:视野内所有地面物品标签全屏展开(执行防重叠垂直阶梯排列);
    • 松开 Alt 键时:所有非悬停标签隐去;若此时鼠标仍停留在某物品图标上,该悬停物品的名称标签应无缝保留显示。
  5. 交互与拾取闭环 (Click-to-Pickup Loop):
    • 悬停浮现标签后,鼠标左键点击该地面物品图标或直接点击该名称标签,均会触发自动寻路走近并在判定半径(48px)内执行 pickupGroundItem 将其收回背包。

3. 缺陷代码定位与根因分析 (Root Cause Analysis)

  1. 标签渲染更新缺乏悬停判断分支:
    在 src/scene/act-scene.ts (第 6985–7005 行):

    if (groundLabelOverlay !== null) {
      const showLabels = Boolean(hudManager?.showGroundLabels)
      if (showLabels && engine.groundItems.count > 0) {
        // ... 全量计算标签并 resolveLadderCollisions
        groundLabelOverlay.update(true, resolvedLayouts)
      } else {
        // showLabels 为 false 时,无条件清空所有标签!
        groundLabelOverlay.update(false, [])
      }
    }
    

    此处仅依据 hudManager.showGroundLabels(即键盘 Alt 键按下事件)决定是否显示标签,完全缺失 hoveredGroundItem 的单体标签显示分支。

  2. onPointerMove 未针对地面物品做拾取碰撞检测 (Hit-Test Missing):
    在 src/scene/act-scene.ts (第 3156–3176 行):
    onPointerMove 仅记录了 lastClientPos,未在鼠标划过场景时使用 engine.groundItems.findAtPoint(worldX, worldY, radius) 测定鼠标下的地面物品,因此系统无法得知当前是否有物品处于悬停状态。


4. 修复方案建议 (Proposed Implementation Plan)

  1. 维护 hoveredGroundItem 状态:
    在 ActScene(或其输入控制器中):
    • 在 onPointerMove 时计算光标世界坐标 (worldX, worldY);
    • 通过 engine.groundItems.findAtPoint(worldX, worldY, 28) 判定是否悬停在地面物品上,并缓存在场景状态中。
  2. 扩展地面标签更新逻辑:
    • 若 hudManager.showGroundLabels 为 true:全量显示所有物品标签(阶梯避让);
    • 若 hudManager.showGroundLabels 为 false 但存在 hoveredGroundItem:将该单个物品作为 GroundLabelLayout 传入,单独在该物品正上方渲染其名称标签;
    • 两者皆无:调用 groundLabelOverlay.update(false, []) 隐藏。
  3. 确保点击拾取兼容性:
    • 确保单独悬停浮现的标签绑定相同的 pointerdown / 点击拾取回调,保证点击标签和点击图标均能触发物品捡拾。

5. 验收标准 (Acceptance Criteria)

  1. 悬停显名:不按 Alt 键时,鼠标移至地面任意掉落物(武器、防具、药剂、卷轴、金币等)上方,立即显示该物品对应名称标签。
  2. 品质着色:单体悬停标签严格按照原版 1.13c 品质调色板渲染文字与边框(白、灰、蓝、黄、绿、暗金、橙、金币黄)。
  3. 移出消失:鼠标光标移开物品判定范围后,标签立即消失。
  4. Alt 键协同:Alt 释放后,若光标仍在物品上,该物品标签保持显示;其他物品标签隐藏。
  5. 点击拾取:在悬停状态下点击图标或标签,角色正常寻路靠近并拾入包裹。
  6. 测试验证:npm run typecheck 与自动化测试 100% 通过。
### 1. 问题背景与现状 (Bug Description & Current Behavior) 在当前客户端中,怪物掉落或玩家从包裹扔到地上的物品会以等距地面图标(Ground Sprite / Flippy 动画)形式展示在世界场景中。 然而,目前的地面名称标签(Ground Item Label)**完全绑定在键盘 `Alt` 键的按下状态上**: - 仅当玩家按住 `Alt` 键(`hudManager.showGroundLabels === true`)时,系统才会批量计算并显示所有地面物品的名称标签。 - **当玩家未按住 `Alt` 键时,即使将鼠标光标移动并悬停在地面物品图标正上方,屏幕上也毫无任何反馈**(没有名称提示框、没有品质颜色提示)。 这导致玩家若不按住 `Alt` 键,便无法通过鼠标悬停来快速查验地上的掉落物究竟为何物,与原版《暗黑破坏神 2》经典交互体验严重脱节。 --- ### 2. 原版 Diablo II v1.13c 地面交互规范 (Ground Truth Invariants) 在《暗黑破坏神 2》原版(v1.13c)中,地面的每个掉落物(`UNIT_ITEM`,`animmode = ITEMMODE_ONGROUND` / 0)均属于可悬停高亮的目标实体: 1. **单体鼠标悬停显名 (Single Hover Label Trigger)**: - 当玩家未按 `Alt` 键时,鼠标指针滑过地面任意掉落物品的碰撞/判定区域(`D2Client.dll` 命中测试 `pItemUnderMouse`)时,**该物品的正上方会立即单独浮现该物品的名称标签框**。 - 标签外观与 Alt 标签规范严格保持一致:经典半透明黑底背景(`rgba(0, 0, 0, 0.88)`)、1px 细线边框、点阵字体、原版 1.13c 品质文字色彩(`D2WinFont` 调色板)。 2. **原版品质色彩严格对应 (Item Quality Colors)**: - 普通装备 / 底材 / 卷轴 / 钥匙:白色 / 银灰 (`#FFFFFF` / `#D8D8D8`) - 低质 / 破损 / 无形 / 带孔:灰色 (`#808080`) - 魔法装备:经典蓝 (`#6868FF`) - 稀有装备:黄金黄 (`#FFFF64`) - 套装装备:明亮绿 (`#00FC00`) - 暗金装备:古铜暗金 (`#C8A15A`) - 符文 / 橙色手工:鲜艳橙 (`#FF9C18`) - 金币:亮金黄色(展示具体金额,如 `150 金币`) 3. **悬停移出即刻隐退 (Hover Leave Auto-Dismiss)**: - 鼠标光标移出该地面物品判定区后,该名称标签即时隐藏。 4. **Alt 键协同过渡机制 (Alt Key Concurrency)**: - 按住 `Alt` 键时:视野内所有地面物品标签全屏展开(执行防重叠垂直阶梯排列); - 松开 `Alt` 键时:所有非悬停标签隐去;若此时鼠标仍停留在某物品图标上,**该悬停物品的名称标签应无缝保留显示**。 5. **交互与拾取闭环 (Click-to-Pickup Loop)**: - 悬停浮现标签后,鼠标左键点击该地面物品图标或直接点击该名称标签,均会触发自动寻路走近并在判定半径(48px)内执行 `pickupGroundItem` 将其收回背包。 --- ### 3. 缺陷代码定位与根因分析 (Root Cause Analysis) 1. **标签渲染更新缺乏悬停判断分支**: 在 `src/scene/act-scene.ts` (第 6985–7005 行): ```typescript if (groundLabelOverlay !== null) { const showLabels = Boolean(hudManager?.showGroundLabels) if (showLabels && engine.groundItems.count > 0) { // ... 全量计算标签并 resolveLadderCollisions groundLabelOverlay.update(true, resolvedLayouts) } else { // showLabels 为 false 时,无条件清空所有标签! groundLabelOverlay.update(false, []) } } ``` 此处仅依据 `hudManager.showGroundLabels`(即键盘 Alt 键按下事件)决定是否显示标签,完全缺失 `hoveredGroundItem` 的单体标签显示分支。 2. **`onPointerMove` 未针对地面物品做拾取碰撞检测 (Hit-Test Missing)**: 在 `src/scene/act-scene.ts` (第 3156–3176 行): `onPointerMove` 仅记录了 `lastClientPos`,未在鼠标划过场景时使用 `engine.groundItems.findAtPoint(worldX, worldY, radius)` 测定鼠标下的地面物品,因此系统无法得知当前是否有物品处于悬停状态。 --- ### 4. 修复方案建议 (Proposed Implementation Plan) 1. **维护 `hoveredGroundItem` 状态**: 在 `ActScene`(或其输入控制器中): - 在 `onPointerMove` 时计算光标世界坐标 `(worldX, worldY)`; - 通过 `engine.groundItems.findAtPoint(worldX, worldY, 28)` 判定是否悬停在地面物品上,并缓存在场景状态中。 2. **扩展地面标签更新逻辑**: - 若 `hudManager.showGroundLabels` 为 true:全量显示所有物品标签(阶梯避让); - 若 `hudManager.showGroundLabels` 为 false 但存在 `hoveredGroundItem`:将该单个物品作为 `GroundLabelLayout` 传入,单独在该物品正上方渲染其名称标签; - 两者皆无:调用 `groundLabelOverlay.update(false, [])` 隐藏。 3. **确保点击拾取兼容性**: - 确保单独悬停浮现的标签绑定相同的 `pointerdown` / 点击拾取回调,保证点击标签和点击图标均能触发物品捡拾。 --- ### 5. 验收标准 (Acceptance Criteria) 1. **悬停显名**:不按 Alt 键时,鼠标移至地面任意掉落物(武器、防具、药剂、卷轴、金币等)上方,立即显示该物品对应名称标签。 2. **品质着色**:单体悬停标签严格按照原版 1.13c 品质调色板渲染文字与边框(白、灰、蓝、黄、绿、暗金、橙、金币黄)。 3. **移出消失**:鼠标光标移开物品判定范围后,标签立即消失。 4. **Alt 键协同**:Alt 释放后,若光标仍在物品上,该物品标签保持显示;其他物品标签隐藏。 5. **点击拾取**:在悬停状态下点击图标或标签,角色正常寻路靠近并拾入包裹。 6. **测试验证**:`npm run typecheck` 与自动化测试 100% 通过。
troytt added this to the [M18] 打怪掉落物品:怪物死亡掉落全链路 1.13c 还原 milestone 2026-09-24 12:32:52 +00:00
Sign in to join this conversation.
No Label
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#447
No description provided.