feat(player): порт — авто-floater над мобами + урон NPC от оружия (задача 40 доп)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8f229e2cfb
commit
08143b837c
@ -5678,6 +5678,10 @@ export class BabylonScene {
|
||||
if (hit?.mesh && this.zombieManager) {
|
||||
this.zombieManager.damageByMesh(hit.mesh, hit.damage || 25);
|
||||
}
|
||||
// Урон скриптовым NPC (киты-враги) → авто-floater над мобом (задача 40).
|
||||
if (hit?.mesh && this.npcManager) {
|
||||
try { this.npcManager.damageByMesh(hit.mesh, hit.damage || 25); } catch (e) {}
|
||||
}
|
||||
if (this._onWeaponHit) {
|
||||
try { this._onWeaponHit(hit); } catch (e) {}
|
||||
}
|
||||
|
||||
@ -1772,6 +1772,15 @@ export class GameRuntime {
|
||||
} catch (e) { /* ignore */ }
|
||||
return;
|
||||
}
|
||||
if (cmd === 'fx.autoMobFloaters') {
|
||||
try {
|
||||
if (this.scene3d?.npcManager) {
|
||||
this.scene3d.npcManager._autoFloater = payload?.enabled
|
||||
? { opts: payload?.opts || {} } : null;
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd === 'fx.create') {
|
||||
// payload: { kind: 'beam'|'trail', localRef, ... }
|
||||
|
||||
@ -293,10 +293,36 @@ export class NpcManager {
|
||||
damage(id, amount) {
|
||||
const npc = this.npcs.get(Number(id));
|
||||
if (!npc || npc.dead) return;
|
||||
npc.hp = Math.max(0, npc.hp - (Number(amount) || 0));
|
||||
const amt = Number(amount) || 0;
|
||||
npc.hp = Math.max(0, npc.hp - amt);
|
||||
// Авто-floater над мобом (задача 40 доп): game.fx.autoMobFloaters(true).
|
||||
if (this._autoFloater && amt > 0 && this.scene3d?.floaters) {
|
||||
try {
|
||||
this.scene3d.floaters.spawn(
|
||||
{ x: npc.x, y: (npc.y || 0) + 2.2, z: npc.z }, amt, this._autoFloater.opts || {});
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
if (npc.hp <= 0) this._killNpc(npc);
|
||||
}
|
||||
|
||||
/** Нанести урон NPC по мешу-попаданию (бластер/оружие). Ищет NPC, чьи меши
|
||||
* содержат hit-меш (или предка). Вызывает damage() → авто-floater. */
|
||||
damageByMesh(mesh, amount) {
|
||||
if (!mesh) return false;
|
||||
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++) { // вверх по иерархии до rootMesh
|
||||
if (m === root) { hit = true; break; }
|
||||
m = m.parent;
|
||||
}
|
||||
if (hit) { this.damage(npc.id, amount); return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Удалить NPC по id (без эффекта смерти — просто убрать). */
|
||||
removeNpc(id) {
|
||||
const npc = this.npcs.get(Number(id));
|
||||
|
||||
@ -3029,6 +3029,16 @@ const game = {
|
||||
const pos = _normFxPoint(position);
|
||||
_send('fx.damageFloater', { position: pos, value, opts: opts || {} });
|
||||
},
|
||||
/**
|
||||
* Авто-floater'ы над мобами (NPC) при потере HP (задача 40 доп).
|
||||
* Включил один раз — и любой урон по NPC (от бластера, скрипта, врага)
|
||||
* сам показывает облачко «-N» над целью.
|
||||
* game.fx.autoMobFloaters(true);
|
||||
* game.fx.autoMobFloaters(true, { color:'#ff5a4a' });
|
||||
*/
|
||||
autoMobFloaters(enabled, opts) {
|
||||
_send('fx.autoMobFloaters', { enabled: enabled !== false, opts: opts || {} });
|
||||
},
|
||||
/**
|
||||
* Луч между двумя точками. opts: { from, to — {x,y,z} или ref
|
||||
* объекта (тогда луч следит за ним); color: '#hex', width }.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user