diff --git a/src/editor/engine/GameplayKits.js b/src/editor/engine/GameplayKits.js index 93518b9..f6d8cee 100644 --- a/src/editor/engine/GameplayKits.js +++ b/src/editor/engine/GameplayKits.js @@ -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(() => { +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 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', '', {}); - } + 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); // дверь уезжает вниз (открыта) + if (String(text).trim() === CODE){ + 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}); - } + 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}); });` }], }, { @@ -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);` }],