NPC 反应动作表与 Godot 动作库

2026-09-20。本批补原模型 HIT / IDLE 资源、索引选择和实际播放接口。它是上一批 52CE50 分派器的模型端准备,不是普通 NPC 的 AI / 技能中断已经全部接通。

来源与覆盖

新增 tools/build_reaction_animations.py,扫描原怪物单位定义并沿继承链解析模型:

  • 1114 个单位名映射到 343 个模型。
  • 264 个模型的当前正常骨架载入路径可解析。
  • 79 个模型保留 unverified 原因,不用目录文件名或 IDLE 回退补齐。
  • 当前地图涉及的模型导出 30 份独立反应动作库。
  • tools/rebuild_scenes.py 已接入生成步骤,可从源数据重建。
  • 没有覆盖原地图的既有角色模型,新增库只向同一个 AnimationPlayer 提供动作。

主要未验证原因包括:48 个缺少模型同名清单、重复导入、源骨架文件不存在、源 XML 不完整等。数字是本次语料结果,不能当作全部 NPC 模型已支持。

原动画表不等于目录文件排序

对照 5A2440 / 5A14D0 / 598030 / 598790:

  1. 正常模型先加入基础骨架已有的动画,过滤星号开头的内部项。
  2. 再按 .ANIMATION 子块顺序载入 FILE 指向的骨架。
  3. 使用骨架文件里的实际动画名字;正常实体路径不能直接用清单 NAME 代替。
  4. 同基础骨架的 BIND 导入不凭空增加另一条索引。
  5. 当前未证明的多动画基础骨架顺序、重复导入覆盖等仍拒绝。

这条路径不是模型 +598 的特殊模式,也不覆盖外部骨架替换。清单保留 source hash、原名、索引、骨架时长、清单时长和 KEY 属性;尚未消费的 KEY 事件没有被删除后宣称完成。

ECHO PASS 受测 C_STURM_RANGED01_IMMOBILE 的真实表:

  • index 12:HIT1,0.533333 秒;
  • index 13:HIT2,0.533333 秒;
  • index 14:IDLE,3.33333 秒。

选择规则

NativeModelAnimations 实现:

  • 前缀存在性检查大写化请求,不消耗 RNG;
  • 选择保留原表顺序,支持原大小写分支;
  • 无候选返回 -1,不掷骰;
  • 单候选仍做原浮点随机选择,推进两步 MWC;
  • 使用 float 归一化权重、严格大于比较;
  • 极少数权重总和略低于 1 时,保留原 index 0 回退,不能改成第一个前缀候选或安全异常。

例如 25 个等权条目、roll=.99999999 时可走 index 0 回退。该索引不保证属于 HIT 前缀。

这些索引仍在单位 527440 ANIMATION_ALTS 解析之前;显示端接收已经解析好的索引,不自行决定持武器变体。

严格导出与姿态边界

现有转换器新增显式 clip_sources 路径:

  • 来源文件和骨架内部名字必须精确存在,不调用“缺失就 IDLE”的通用回退。
  • 复用已有独立 TRS 时间流处理,不用其他骨骼的时间点进行 nearest-key 重采样。
  • 保留缩放轨道。
  • 合法的静止 IDLE(如训练假人)输出常量轨道,不输出无 channel 的无效 glTF 动画。
  • 旧调用路径未被批量重建或无条件改写。

仍保留 native_pose_parity=false。Ogre 1.7 上游默认旋转模式是 RIM_LINEAR;不能把 glTF / Godot 插值直接说成与原版逐位相同。Ogre 1.7 Animation 源码

正常场景接线

CoreSimBridge.ReactionAnimations 与 NativeReactionAnimationView:

  • NPC 初始化尝试安装对应库,并保留明确的 readiness / reason。
  • 校验骨骼名字、父子关系和静止姿态;使用已有原骨架合并的 1e-3 身份容差。
  • 实测 Spear_Case 的旧导出 / 新导出旋转差约为 7e-7,逐矩阵元素相对比较会误拒绝;没有取消骨架检查,也不允许任意模型套用。
  • 安装前停止播放器,保留原动作、位置、速度与队列后恢复。
  • 对未知暂停速度的情况明确拒绝,不猜恢复倍率。
  • 循环 / 非循环使用独立动作资源,不修改共享库。
  • Play / Queue / Active 接收原索引;不消耗战斗 RNG,不写 AI 或技能状态。
  • 节点退出清理视图引用。

骨骼 pose 是局部姿态,reset 会从 rest 写回局部 TRS;不是把任意骨架名字相同就认为兼容。Godot Skeleton3D 实现。本项目实际验证使用本地 Godot 4.7。

验证

  • 2045 条核心断言通过。
  • 440 项相关 Python 回归通过。
  • Godot C# 构建零警告 / 零错误,190 个核心文件静态检查无硬错。
  • 实际 Vulkan ECHO PASS 受测 NPC 正常初始化装入库。
  • 原索引 12 / 13 都改变实际骨骼姿态。
  • 活跃动作检查不引起重启,播放完成进入排队的原 IDLE。
  • 动作传递前后模拟快照完全相同,不篡改 HP / RNG。
  • 静止 IDLE、源文件哈希、导出动作集合、原索引和数据诊断均有回归。

GPU 探针显式提供已解析动作索引,隔离验证显示端;没有用它证明完整 NPC 反应决策已工作。

产物:

  • build/f2/reaction_animations.json
  • torchlight-2-poc/vanilla/reactions/
  • build/reaction_animation_core.log
  • build/reaction_animation_regression.log
  • build/reaction_animation_visual/result.json
  • build/reaction_animation_visual/reaction_12.webp
  • build/reaction_animation_visual/reaction_13.webp

局部画面检查

已查看短边 512 的 HIT1 / HIT2 GPU 截图。两种动作姿态不同,身体 / 武器随骨架运动,未见分离或复制残影。UI 在探针中隐藏,没有据此评价正式 HUD。

Receptor分数 / 2
COMP-FOCAL-SINGLE2
COMP-SIL-ACTION2
MOT-VOL2
MOT-GHOST2
LIGHT-KEY-FILL1

9/10(90%,局部 A),零分项无;夜雨暗部仍影响观察。这是动作接线裁剪,不是原版逐帧姿态对拍或全游戏视觉认证。

继续清单

  • 将 52CE50 的普通 NPC 分支接入真实 AI 标志、技能活动、取消和附着效果清理。
  • 接入 ANIMATION_ALTS 与原活跃动画状态 / 排队语义。
  • 消费反应动作的 KEY 音效 / 粒子事件。
  • 核查并补齐 79 个未验证模型和其他地图所需导出库。
  • 继续仇恨及 Charged Bolt,再逐武器开放并验收。

武器构造检查保持 1099 / 1419,273 阻塞、47 基础缺口、0 构造异常。全武器目标未完成。

按 godot-master 保持共享资源不被运行时改写、模拟决策与显示分离,并实际检查 GPU 画面。main 原地、未提交。默认存档 SHA256 未变: 9840fe858b6e311c73f8c2d4ed49912d59d71365f6278392811730e012d32a7f