diff --git a/src/editor/engine/NpcManager.js b/src/editor/engine/NpcManager.js index b7e9ff7..f452f81 100644 --- a/src/editor/engine/NpcManager.js +++ b/src/editor/engine/NpcManager.js @@ -161,6 +161,20 @@ export class NpcManager { r15Animator, }; this.npcs.set(id, npc); + // Пометить меши NPC для попаданий оружия (бластер/меч): pickable + npcId + // в metadata. Без pickable raycast оружия проходит сквозь NPC и урон/ + // floater'ы не срабатывают (задача 40). + try { + const root = npc.data && npc.data.rootMesh; + if (root) { + root.isPickable = true; + root.metadata = Object.assign({}, root.metadata, { npcId: id }); + for (const m of root.getChildMeshes(false)) { + m.isPickable = true; + m.metadata = Object.assign({}, m.metadata, { npcId: id }); + } + } + } catch (e) { /* ignore */ } return id; } @@ -308,16 +322,23 @@ export class NpcManager { * содержат hit-меш (или предка). Вызывает damage() → авто-floater. */ damageByMesh(mesh, amount) { if (!mesh) return false; + // 1) Быстрый путь: npcId в metadata меша (или предка). + let m = mesh; + for (let i = 0; i < 8 && m; i++) { + const nid = m.metadata && m.metadata.npcId; + if (nid != null && this.npcs.has(nid)) { this.damage(nid, amount); return true; } + m = m.parent; + } + // 2) Fallback: сравнение с rootMesh по иерархии. for (const npc of this.npcs.values()) { if (npc.dead) continue; const root = npc.data && npc.data.rootMesh; if (!root) continue; - let m = mesh, hit = false; - for (let i = 0; i < 8 && m; i++) { - if (m === root) { hit = true; break; } - m = m.parent; + let mm = mesh; + for (let i = 0; i < 8 && mm; i++) { + if (mm === root) { this.damage(npc.id, amount); return true; } + mm = mm.parent; } - if (hit) { this.damage(npc.id, amount); return true; } } return false; }