From e4fdd91b12a46da80ab76d0da2bec31d3074ffa4 Mon Sep 17 00:00:00 2001 From: min Date: Sun, 7 Jun 2026 13:49:06 +0300 Subject: [PATCH] =?UTF-8?q?fix(studio):=20=D0=BE=D1=80=D1=83=D0=B6=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=BE=D0=BF=D0=B0=D0=B4=D0=B0=D0=B5=D1=82=20?= =?UTF-8?q?=D0=BF=D0=BE=20NPC=20(pickable+npcId)=20=E2=86=92=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE-floater=20=D1=83=D1=80=D0=BE=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Меши NPC ставились isPickable=false → raycast бластера/меча проходил сквозь них, урон и авто-floater не срабатывали. Теперь меши NPC pickable + npcId в metadata; damageByMesh находит NPC по metadata (быстро) или по rootMesh. Co-Authored-By: Claude Opus 4.8 --- src/editor/engine/NpcManager.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) 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; }