fix(studio): NPC-киты (robot→character-a), дверь по коду плавно распахивается
1) NPC-преследователь/торговец/волна: spawnNpc('robot') → 'character-a'
(модели 'robot' не существует в ModelTypes → spawnNpc возвращал null → ошибка).
2) Дверь по коду: верный код → ПЛАВНОЕ открытие вокруг петли (как дверь по E),
декор-панели вращаются вместе с полотном. Раньше полотно уезжало вниз,
декор оставался.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
3bf1e77230
commit
fe8b6b5b38
@ -591,38 +591,49 @@ game.hud.setHpVisible(false);` }],
|
||||
{ type: 'cube', x: 0, y: 4.1, z: 0, sx: 0.4, sy: 0.4, sz: 3.5, color: '#3a4250', material: 'metal', name: 'Перемычка' },
|
||||
],
|
||||
scripts: [{ attachTo: 'on-target', code:
|
||||
`// Дверь по коду 1234. Поле ввода появляется ТОЛЬКО когда игрок рядом.
|
||||
`// Дверь по коду 1234. Поле ввода появляется ТОЛЬКО рядом. Верный код →
|
||||
// дверь ПЛАВНО распахивается вокруг петли (вместе с панелями).
|
||||
const CODE = '1234';
|
||||
const p0 = game.self.position;
|
||||
const halfW = 1.3; // полуширина полотна (sz=2.6)
|
||||
const hingeX = p0.x, hingeZ = p0.z - halfW;
|
||||
const RADIUS = 6;
|
||||
let opened = false, near = false, inp = null;
|
||||
game.ui.set('codehint', '', {});
|
||||
game.onTick(() => {
|
||||
if (opened) return;
|
||||
const pl = game.player.position;
|
||||
const dx = pl.x - p0.x, dz = pl.z - p0.z;
|
||||
const d = Math.sqrt(dx*dx + dz*dz);
|
||||
if (d < RADIUS && !near) {
|
||||
near = true;
|
||||
inp = game.gui.create('textbox', { id:'codein', x:50, y:86, w:24, h:8, anchor:'center', placeholder:'Код...', textSize:20 });
|
||||
game.ui.set('codehint', '🔢 Введи код двери и нажми Enter', {x:50,y:78,anchor:'bottom',color:'#fff',size:16});
|
||||
} else if (d >= RADIUS && near) {
|
||||
near = false;
|
||||
if (inp) game.gui.remove('codein');
|
||||
game.ui.set('codehint', '', {});
|
||||
let opened = false, near = false, cur = 0, target = 0;
|
||||
const SPEED = Math.PI; // ~0.5с на 90°
|
||||
|
||||
// Декор полотна — двигается вместе с дверью.
|
||||
const decorNames = ['Панель двери', 'Панель двери низ', 'Кодовая панель'];
|
||||
const decor = [];
|
||||
for (const nm of decorNames) {
|
||||
const o = game.scene.findOne(nm);
|
||||
if (o && o.position) decor.push({ obj:o, dx:o.position.x-p0.x, dy:o.position.y-p0.y, dz:o.position.z-p0.z });
|
||||
}
|
||||
function rotY(lx, lz, a){ const s=Math.sin(a),c=Math.cos(a); return { x: lx*c+lz*s, z: -lx*s+lz*c }; }
|
||||
function place(a){
|
||||
const pc = rotY(0, halfW, a);
|
||||
const cx = hingeX + pc.x, cz = hingeZ + pc.z;
|
||||
game.self.move(cx, p0.y, cz); game.self.rotate(a);
|
||||
for (const d of decor){ const r = rotY(d.dx, d.dz, a); d.obj.move(cx+r.x, p0.y+d.dy, cz+r.z); if (d.obj.rotate) d.obj.rotate(a); }
|
||||
}
|
||||
game.onTick((dt) => {
|
||||
if (cur !== target){ const st=SPEED*dt; cur = Math.abs(target-cur)<=st ? target : cur+Math.sign(target-cur)*st; place(cur); }
|
||||
if (opened) return;
|
||||
// Поле ввода появляется/прячется по дистанции.
|
||||
const pl = game.player.position;
|
||||
const d = Math.sqrt((pl.x-p0.x)**2 + (pl.z-p0.z)**2);
|
||||
if (d < RADIUS && !near){ near = true;
|
||||
game.gui.create('textbox', { id:'codein', x:50, y:86, w:24, h:8, anchor:'center', placeholder:'Код...', textSize:20 });
|
||||
game.ui.set('codehint', '🔢 Введи код двери (1234) и нажми Enter', {x:50,y:78,anchor:'bottom',color:'#fff',size:16}); }
|
||||
else if (d >= RADIUS && near){ near = false; game.gui.remove('codein'); game.ui.set('codehint','',{}); }
|
||||
});
|
||||
game.gui.onSubmit('codein', (text) => {
|
||||
if (opened) return;
|
||||
if (String(text).trim() === CODE){
|
||||
opened = true;
|
||||
game.self.move(p0.x, p0.y - 4.2, p0.z); // дверь уезжает вниз (открыта)
|
||||
opened = true; target = Math.PI/2; // плавно распахнуть
|
||||
game.gui.remove('codein');
|
||||
game.ui.set('codehint','✓ Открыто!', {x:50,y:78,anchor:'bottom',color:'#36d57a',size:18});
|
||||
game.after(2, () => game.ui.set('codehint','',{}));
|
||||
} else {
|
||||
game.ui.set('codehint', '✗ Неверный код', {x:50,y:78,anchor:'bottom',color:'#ff5555',size:18});
|
||||
}
|
||||
} else game.ui.set('codehint','✗ Неверный код', {x:50,y:78,anchor:'bottom',color:'#ff5555',size:18});
|
||||
});` }],
|
||||
},
|
||||
{
|
||||
@ -690,7 +701,7 @@ game.onTick(() => {
|
||||
icon: 'chase', category: 'npc',
|
||||
scripts: [{ attachTo: 'global', code:
|
||||
`// Спавним NPC, который преследует игрока.
|
||||
const enemy = game.scene.spawnNpc('robot', { x: 8, z: 8, name: 'Охотник', speed: 4 });
|
||||
const enemy = game.scene.spawnNpc('character-a', { x: 8, z: 8, name: 'Охотник', speed: 4 });
|
||||
if (enemy && enemy.follow) enemy.follow('player');` }],
|
||||
},
|
||||
{
|
||||
@ -760,7 +771,7 @@ game.self.onClick(() => {
|
||||
`// Каждые 5с спавнит 2 врагов из точки портала, они идут к игроку.
|
||||
const p = game.self.position;
|
||||
function wave(){
|
||||
for (let i=0;i<2;i++){ const e = game.scene.spawnNpc('robot', { x:p.x+(Math.random()-0.5)*2, z:p.z+(Math.random()-0.5)*2, name:'Враг', speed:3 });
|
||||
for (let i=0;i<2;i++){ const e = game.scene.spawnNpc('character-a', { x:p.x+(Math.random()-0.5)*2, z:p.z+(Math.random()-0.5)*2, name:'Враг', speed:3 });
|
||||
if (e && e.follow) e.follow('player'); }
|
||||
}
|
||||
game.after(2, wave); game.every(5, wave);` }],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user