fix(studio): дверь-код подсказка E только при открытой, NPC=R15-скин (анимация рук/ног), торговец видимый
1) Дверь по коду: подсказка «E закрыть» теперь только когда дверь открыта и игрок рядом (через onKey+onTick, без постоянного interact-промпта). 2) NPC-киты используют R15-скин 'skin_roblox-noob' → процедурная анимация бега/покоя с руками и ногами (R15Animator), вместо безжизненного покачивания. 3) Торговец-кит: невидимый триггер (insertGameplayKit теперь уважает prim.visible=false, раньше хардкод visible:true) + NPC-персонаж рядом — синий куб больше не виден. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9903719f9d
commit
26e6306f6e
@ -800,7 +800,7 @@ const KubikonEditor = () => {
|
|||||||
x: px + (p.x || 0), y: py + (p.y != null ? p.y : 1), z: pz + (p.z || 0),
|
x: px + (p.x || 0), y: py + (p.y != null ? p.y : 1), z: pz + (p.z || 0),
|
||||||
sx: p.sx, sy: p.sy, sz: p.sz,
|
sx: p.sx, sy: p.sy, sz: p.sz,
|
||||||
color: p.color, material: p.material,
|
color: p.color, material: p.material,
|
||||||
canCollide: p.canCollide !== false, visible: true, anchored: true,
|
canCollide: p.canCollide !== false, visible: p.visible !== false, anchored: true,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
});
|
});
|
||||||
if (newId != null) {
|
if (newId != null) {
|
||||||
|
|||||||
@ -617,10 +617,15 @@ function place(a){
|
|||||||
}
|
}
|
||||||
game.onTick((dt) => {
|
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 (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 pl = game.player.position;
|
||||||
const d = Math.sqrt((pl.x-p0.x)**2 + (pl.z-p0.z)**2);
|
const d = Math.sqrt((pl.x-p0.x)**2 + (pl.z-p0.z)**2);
|
||||||
|
if (opened){
|
||||||
|
// Дверь открыта: подсказка «E закрыть» только когда игрок рядом.
|
||||||
|
if (d < RADIUS && !near){ near = true; game.ui.set('codehint','Нажми E чтобы закрыть дверь', {x:50,y:80,anchor:'bottom',color:'#fff',size:16}); }
|
||||||
|
else if (d >= RADIUS && near){ near = false; game.ui.set('codehint','',{}); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Дверь закрыта: поле ввода кода по дистанции.
|
||||||
if (d < RADIUS && !near){ near = true;
|
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.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}); }
|
game.ui.set('codehint', '🔢 Введи код двери (1234) и нажми Enter', {x:50,y:78,anchor:'bottom',color:'#fff',size:16}); }
|
||||||
@ -629,19 +634,21 @@ game.onTick((dt) => {
|
|||||||
game.gui.onSubmit('codein', (text) => {
|
game.gui.onSubmit('codein', (text) => {
|
||||||
if (opened) return;
|
if (opened) return;
|
||||||
if (String(text).trim() === CODE){
|
if (String(text).trim() === CODE){
|
||||||
opened = true; target = Math.PI/2; // плавно распахнуть
|
opened = true; near = false; target = Math.PI/2; // плавно распахнуть
|
||||||
game.gui.remove('codein');
|
game.gui.remove('codein');
|
||||||
game.ui.set('codehint','✓ Открыто! Нажми E чтобы закрыть.', {x:50,y:78,anchor:'bottom',color:'#36d57a',size:16});
|
game.ui.set('codehint','✓ Открыто!', {x:50,y:78,anchor:'bottom',color:'#36d57a',size:18});
|
||||||
game.after(2.5, () => game.ui.set('codehint','',{}));
|
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});
|
||||||
});
|
});
|
||||||
// Закрыть открытую дверь по E → снова можно вводить код.
|
// Закрыть дверь по E (только если открыта и игрок рядом).
|
||||||
game.self.onInteract(() => {
|
game.onKey('e', () => {
|
||||||
if (!opened) return;
|
if (!opened) return;
|
||||||
opened = false; near = false; target = 0; // плавно закрыть
|
const pl = game.player.position;
|
||||||
game.ui.set('codehint','🔒 Дверь закрыта.', {x:50,y:78,anchor:'bottom',color:'#fff',size:16});
|
if (Math.sqrt((pl.x-p0.x)**2 + (pl.z-p0.z)**2) >= RADIUS) return;
|
||||||
game.after(2, () => game.ui.set('codehint','',{}));
|
opened = false; near = false; target = 0;
|
||||||
}, { text: 'Закрыть дверь', key: 'e', distance: 4 });` }],
|
game.ui.set('codehint','🔒 Дверь закрыта.', {x:50,y:80,anchor:'bottom',color:'#fff',size:16});
|
||||||
|
game.after(1.5, () => game.ui.set('codehint','',{}));
|
||||||
|
});` }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'name-label',
|
id: 'name-label',
|
||||||
@ -708,7 +715,7 @@ game.onTick(() => {
|
|||||||
icon: 'chase', category: 'npc',
|
icon: 'chase', category: 'npc',
|
||||||
scripts: [{ attachTo: 'global', code:
|
scripts: [{ attachTo: 'global', code:
|
||||||
`// Спавним NPC, который преследует игрока.
|
`// Спавним NPC, который преследует игрока.
|
||||||
const enemy = game.scene.spawnNpc('character-a', { x: 8, z: 8, name: 'Охотник', speed: 4 });
|
const enemy = game.scene.spawnNpc('skin_roblox-noob', { x: 8, z: 8, name: 'Охотник', speed: 4 });
|
||||||
if (enemy && enemy.follow) enemy.follow('player');` }],
|
if (enemy && enemy.follow) enemy.follow('player');` }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -721,7 +728,7 @@ if (enemy && enemy.follow) enemy.follow('player');` }],
|
|||||||
scripts: [{ attachTo: 'on-target', code:
|
scripts: [{ attachTo: 'on-target', code:
|
||||||
`// Торговец — настоящий NPC-персонаж. Триггер (этот объект) держит диалог по E.
|
`// Торговец — настоящий NPC-персонаж. Триггер (этот объект) держит диалог по E.
|
||||||
const p = game.self.position;
|
const p = game.self.position;
|
||||||
const npc = game.scene.spawnNpc('character-a', { x: p.x, z: p.z, name: 'Торговец Боб' });
|
const npc = game.scene.spawnNpc('skin_roblox-noob', { x: p.x, z: p.z, name: 'Торговец Боб' });
|
||||||
game.self.onInteract(() => {
|
game.self.onInteract(() => {
|
||||||
game.modal.dialog('Торговец Боб', [
|
game.modal.dialog('Торговец Боб', [
|
||||||
'Привет, путник! Заходи за товарами.',
|
'Привет, путник! Заходи за товарами.',
|
||||||
@ -777,7 +784,7 @@ game.self.onClick(() => {
|
|||||||
`// Каждые 5с спавнит 2 врагов из точки портала, они идут к игроку.
|
`// Каждые 5с спавнит 2 врагов из точки портала, они идут к игроку.
|
||||||
const p = game.self.position;
|
const p = game.self.position;
|
||||||
function wave(){
|
function wave(){
|
||||||
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 });
|
for (let i=0;i<2;i++){ const e = game.scene.spawnNpc('skin_roblox-noob', { 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'); }
|
if (e && e.follow) e.follow('player'); }
|
||||||
}
|
}
|
||||||
game.after(2, wave); game.every(5, wave);` }],
|
game.after(2, wave); game.every(5, wave);` }],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user