From 05a7eaf37184bd9a19ffb52aa50e0ffa04669146 Mon Sep 17 00:00:00 2001 From: min Date: Tue, 9 Jun 2026 13:32:42 +0300 Subject: [PATCH] =?UTF-8?q?feat(lua-games):=20=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BF=D0=B0=D1=80=D0=B8=D1=82=D0=B5=D1=82=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=B3=D1=80=D1=8B=204=20=C2=AB?= =?UTF-8?q?=D0=9A=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0-=D0=BE=D1=82=D0=BA=D1=80?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=88=D0=BA=D0=B0=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JS-версия: - ui.showText('Подойди и нажми E', 4) - onMessage 'win' → showText + win sound + confetti - g4_button: onInteract (E) → click + tween двери (y:8) + showText 'Дверь открывается!' - g4_finish: onTouch → broadcast 'win' Lua-версия (паритет): - __rbxl_show_text подсказка + 'Победа!' - BindableEvent WinReached - g4_button: UserInputService.InputBegan + ProximityHint через BillboardGui ('[E] Открыть дверь' над кнопкой когда игрок в радиусе 4) E → click Sound + TweenService:Create двери (Position +6 по Y, 1.2с) + CanCollide=false + showText 'Дверь открывается!' - g4_finish: Touched → ev:Fire с fired-флагом Shim фиксы: - UserInputService.InputBegan/InputEnded теперь фейерятся на keyDown/keyUp. Передаётся InputObject с KeyCode = ССЫЛКА на Enum.KeyCode. (важно для сравнения == Enum.KeyCode.E). --- src/community/docsGamesBuildersLua.js | 112 +++++++++++++++++++++----- src/editor/engine/lua/RobloxShim.js | 23 +++++- 2 files changed, 112 insertions(+), 23 deletions(-) diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js index 09347df..69b86fd 100644 --- a/src/community/docsGamesBuildersLua.js +++ b/src/community/docsGamesBuildersLua.js @@ -275,36 +275,106 @@ end)`; // ИГРА 4 — «Кнопка и дверь» // ═══════════════════════════════════════════════════════════════ 'button-door': { - g4_main: `-- === ИГРА «КНОПКА И ДВЕРЬ» — главный скрипт (Lua) === + g4_main: `-- === ИГРА «КНОПКА-ОТКРЫВАШКА» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} -print("Найди кнопку и открой дверь!") --- Глобальный канал для оповещения двери -getEvent("DoorOpen")`, + +__rbxl_show_text("Подойди к красной кнопке и нажми E", 4) + +local winSound = Instance.new("Sound", workspace) +winSound.SoundId = "win"; winSound.Volume = 1 + +local winEvent = getEvent("WinReached") +winEvent.Event:Connect(function() + __rbxl_show_text("Победа! Дверь открыта, ты прошёл!", 5) + winSound:Play() + local px = __rbxl_player_x() + local py = __rbxl_player_y() + local pz = __rbxl_player_z() + __rbxl_spawn_particles("confetti", px, py + 3, pz, 3, 3) +end)`, g4_button: `-- === Скрипт кнопки (Lua) === +-- Висит на красной кнопке. Реагирует на E когда игрок рядом. +local UserInputService = game:GetService("UserInputService") +local Players = game:GetService("Players") +local RunService = game:GetService("RunService") +local TweenService = game:GetService("TweenService") + +local part = script.Parent +local player = Players.LocalPlayer +local opened = false +local inRange = false +local hintGui = nil + +-- Подсказка над кнопкой при подходе +local function showHint() + if hintGui then return end + hintGui = Instance.new("BillboardGui", part) + hintGui.Size = UDim2.new(4, 0, 1, 0) + hintGui.StudsOffset = Vector3.new(0, 2, 0) + hintGui.AlwaysOnTop = true + local label = Instance.new("TextLabel", hintGui) + label.Size = UDim2.new(1, 0, 1, 0) + label.BackgroundTransparency = 1 + label.TextColor3 = Color3.fromRGB(255, 255, 255) + label.TextStrokeTransparency = 0 + label.TextScaled = true + label.Text = "[E] Открыть дверь" +end +local function hideHint() + if hintGui then hintGui:Destroy(); hintGui = nil end +end + +-- Каждый кадр проверяем расстояние до игрока +RunService.Heartbeat:Connect(function() + if opened then return end + local px = __rbxl_player_x() + local py = __rbxl_player_y() + local pz = __rbxl_player_z() + local dx = part.Position.X - px + local dz = part.Position.Z - pz + local dist = math.sqrt(dx*dx + dz*dz) + if dist <= 4 and not inRange then + inRange = true + showHint() + elseif dist > 4 and inRange then + inRange = false + hideHint() + end +end) + +local clickSound = Instance.new("Sound", part) +clickSound.SoundId = "click"; clickSound.Volume = 0.8 + +UserInputService.InputBegan:Connect(function(input, gp) + if gp then return end + if opened or not inRange then return end + if input.KeyCode ~= Enum.KeyCode.E then return end + opened = true + hideHint() + clickSound:Play() + __rbxl_show_text("Дверь открывается!", 2) + part.Color = Color3.fromRGB(100, 255, 100) -- зелёная + + -- Находим дверь по имени и поднимаем её + local door = workspace:FindFirstChild("Дверь") + if door then + local goal = { Position = door.Position + Vector3.new(0, 6, 0) } + TweenService:Create(door, TweenInfo.new(1.2), goal):Play() + door.CanCollide = false + end +end)`, + g4_finish: `-- === Скрипт финиша (Lua) === local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent +local fired = false part.Touched:Connect(function(hit) + if fired then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end - local ev = ReplicatedStorage:FindFirstChild("DoorOpen") + fired = true + local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end - print("Кнопка нажата!") - part.Color = Color3.fromRGB(100, 255, 100) -- зелёная -end)`, - g4_door: `-- === Скрипт двери (Lua) === -local TweenService = game:GetService("TweenService") -local ReplicatedStorage = game:GetService("ReplicatedStorage") -local door = script.Parent -local startPos = door.Position - -local ev = ReplicatedStorage:WaitForChild("DoorOpen") -ev.Event:Connect(function() - -- Поднимаем дверь вверх - local goal = { Position = startPos + Vector3.new(0, 5, 0) } - TweenService:Create(door, TweenInfo.new(1), goal):Play() - door.CanCollide = false - print("Дверь открыта!") end)`, }, diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index 7078249..90fb45a 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -2083,10 +2083,29 @@ export function registerRobloxShim(lua, opts) { try { playerMouse.Button1Up.Fire(); } catch (_) {} } if (p.type === 'keyDown') { - try { playerMouse.KeyDown.Fire(String(p.key || '').toLowerCase()); } catch (_) {} + const k = String(p.key || '').toLowerCase(); + try { playerMouse.KeyDown.Fire(k); } catch (_) {} + // Также фейерим UserInputService.InputBegan с InputObject. + // KeyCode должна быть та же ссылка что и Enum.KeyCode.E, + // чтобы скрипт мог сравнивать input.KeyCode == Enum.KeyCode.E. + try { + const keyEnum = global.get('Enum')?.KeyCode || {}; + const kc = keyEnum[k.toUpperCase()] + || { Name: k.toUpperCase(), Value: k.toUpperCase() }; + const inputObj = { UserInputType: 'Keyboard', KeyCode: kc }; + uis.InputBegan.Fire(inputObj, false); + } catch (_) {} } if (p.type === 'keyUp') { - try { playerMouse.KeyUp.Fire(String(p.key || '').toLowerCase()); } catch (_) {} + const k = String(p.key || '').toLowerCase(); + try { playerMouse.KeyUp.Fire(k); } catch (_) {} + try { + const keyEnum = global.get('Enum')?.KeyCode || {}; + const kc = keyEnum[k.toUpperCase()] + || { Name: k.toUpperCase(), Value: k.toUpperCase() }; + const inputObj = { UserInputType: 'Keyboard', KeyCode: kc }; + uis.InputEnded.Fire(inputObj, false); + } catch (_) {} } }, // Tool registry (для GameRuntime: какой Tool сделать script.Parent)