/** * docsGamesBuildersLua.js — Lua-эквиваленты скриптов для уроков. * * Структура: LUA_OVERRIDES[gameId][scriptId] = 'lua-code' * Может быть строкой или функцией (script) => 'lua-code' для случаев, * когда код зависит от target/name (например, имя примитива). * * Когда юзер нажимает «Открыть копию → Lua» в LessonPage, * buildGameProject(id, {lang:'lua'}) подменяет JS-скрипт на Lua-версию * отсюда. Геометрия (примитивы, блоки) остаётся той же — отличается * только язык скриптов. * * Lua-код пишется в стандартном Roblox-стиле: * game:GetService("Players"), workspace, Instance.new, Vector3, CFrame, * :Connect, RunService.Heartbeat, BindableEvent через ReplicatedStorage. * * Конвенции: * - target=null (глобальный JS-скрипт) → в Lua это просто script в workspace, * общение через ReplicatedStorage:BindableEvent. * - target.kind='primitive' (на объекте) → script лежит ВНУТРИ части, * обращение к ней через script.Parent. Имя части совпадает с тем что * в JS-builder указано (Монетка_N, Платформа_N и т.д.). * * Помощники общего назначения: * getPlayerFromHit — извлекает Player из hit события Touched. * getOrCreateEvent — общая BindableEvent в ReplicatedStorage для broadcast. */ // ══════════════════════════════════════════════════════════════════ // Общие сниппеты — вставляются в начало многих скриптов. // ══════════════════════════════════════════════════════════════════ const SNIPPET_BROADCAST = `local ReplicatedStorage = game:GetService("ReplicatedStorage") local function getEvent(name) local ev = ReplicatedStorage:FindFirstChild(name) if not ev then ev = Instance.new("BindableEvent") ev.Name = name ev.Parent = ReplicatedStorage end return ev end`; const SNIPPET_PLAYER_HIT = `local Players = game:GetService("Players") local function getPlayerFromHit(hit) if not hit or not hit.Parent then return nil end return Players:GetPlayerFromCharacter(hit.Parent) end`; export const LUA_OVERRIDES = { // ═══════════════════════════════════════════════════════════════ // ИГРА 1 — «Собери монетки» // ═══════════════════════════════════════════════════════════════ 'collect-coins': { g1_main: `-- === ИГРА «СОБЕРИ МОНЕТКИ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local score = 0 local TOTAL = 8 -- HUD: счётчик в правом верхнем углу local player = Players.LocalPlayer local screenGui = Instance.new("ScreenGui", player.PlayerGui) screenGui.Name = "CoinHUD" local label = Instance.new("TextLabel", screenGui) label.Size = UDim2.new(0, 220, 0, 50) label.Position = UDim2.new(1, -240, 0, 20) label.BackgroundColor3 = Color3.fromRGB(0, 0, 0) label.BackgroundTransparency = 0.4 label.TextColor3 = Color3.fromRGB(255, 215, 0) label.TextScaled = true label.Font = Enum.Font.SourceSansBold label.Text = "Монеты: 0 / " .. TOTAL -- Подсказка по центру (на 2 секунды) local hintGui = Instance.new("ScreenGui", player.PlayerGui) local hint = Instance.new("TextLabel", hintGui) hint.Size = UDim2.new(0, 400, 0, 60) hint.Position = UDim2.new(0.5, -200, 0.3, 0) hint.BackgroundColor3 = Color3.fromRGB(0, 0, 0) hint.BackgroundTransparency = 0.4 hint.TextColor3 = Color3.fromRGB(255, 255, 255) hint.TextScaled = true hint.Text = "Собери все монетки!" task.delay(2, function() hintGui:Destroy() end) -- Звуки local coinSound = Instance.new("Sound", workspace) coinSound.SoundId = "coin" coinSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win" winSound.Volume = 1 -- Подписка на сбор монетки local coinEvent = getEvent("CoinCollected") coinEvent.Event:Connect(function() score = score + 1 label.Text = "Монеты: " .. score .. " / " .. TOTAL coinSound:Play() if score >= TOTAL then -- Победный текст local winGui = Instance.new("ScreenGui", player.PlayerGui) local winLabel = Instance.new("TextLabel", winGui) winLabel.Size = UDim2.new(0, 500, 0, 80) winLabel.Position = UDim2.new(0.5, -250, 0.4, 0) winLabel.BackgroundColor3 = Color3.fromRGB(0, 100, 0) winLabel.BackgroundTransparency = 0.2 winLabel.TextColor3 = Color3.fromRGB(255, 255, 0) winLabel.TextScaled = true winLabel.Font = Enum.Font.SourceSansBold winLabel.Text = "Победа! Все монетки твои!" winSound:Play() end end)`, // Скрипт каждой монетки — генератор по script-объекту g1_coin_1: makeCoinScript(), g1_coin_2: makeCoinScript(), g1_coin_3: makeCoinScript(), g1_coin_4: makeCoinScript(), g1_coin_5: makeCoinScript(), g1_coin_6: makeCoinScript(), g1_coin_7: makeCoinScript(), g1_coin_8: makeCoinScript(), }, // ═══════════════════════════════════════════════════════════════ // ИГРА 2 — «Прыгай по платформам» // ═══════════════════════════════════════════════════════════════ 'platform-jump': { g2_main: `-- === ИГРА «ПРЫГАЙ ПО ПЛАТФОРМАМ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local won = false -- Подсказка по центру (паритет с JS game.ui.showText) __rbxl_show_text("Допрыгай до зелёной площадки!", 3) -- Звуки local loseSound = Instance.new("Sound", workspace) loseSound.SoundId = "lose" loseSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win" winSound.Volume = 1 -- Каждый кадр следим: не упал ли игрок RunService.Heartbeat:Connect(function() if won then return end local char = player.Character if not char then return end local hrp = char:FindFirstChild("HumanoidRootPart") if hrp and hrp.Position.Y < -3 then player:LoadCharacter() loseSound:Play() __rbxl_show_text("Упал! Пробуй снова.", 1.5) end end) -- Финиш-зона шлёт BindableEvent local finishEvent = getEvent("FinishReached") finishEvent.Event:Connect(function() if won then return end won = true winSound:Play() __rbxl_show_text("Победа! Ты дошёл до финиша!", 5) -- Конфетти над игроком (паритет с JS game.scene.spawnParticles) 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)`, g2_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 fired = true local ev = ReplicatedStorage:FindFirstChild("FinishReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 3 — «Не упади» (платформа сужается) // ═══════════════════════════════════════════════════════════════ 'dont-fall': (function() { const overrides = { g3_main: `-- === ИГРА «НЕ УПАДИ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local won = false __rbxl_show_text("Беги вперёд! Плитки исчезают!", 3) local loseSound = Instance.new("Sound", workspace) loseSound.SoundId = "lose"; loseSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 RunService.Heartbeat:Connect(function() if won then return end local char = player.Character if not char then return end local hrp = char:FindFirstChild("HumanoidRootPart") if hrp and hrp.Position.Y < -3 then player:LoadCharacter() loseSound:Play() __rbxl_show_text("Упал! Снова.", 1.5) end end) local finishEvent = getEvent("FinishReached") finishEvent.Event:Connect(function() if won then return end won = true winSound:Play() __rbxl_show_text("Победа! Ты добежал!", 5) 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)`, g3_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 fired = true local ev = ReplicatedStorage:FindFirstChild("FinishReached") if ev then ev:Fire() end end)`, }; // Скрипт каждой плитки — генератор (одинаковый код) const tileScript = `-- === Скрипт исчезающей плитки (Lua) === local Debris = game:GetService("Debris") local part = script.Parent local triggered = false local clickSound = Instance.new("Sound", part) clickSound.SoundId = "click"; clickSound.Volume = 0.6 part.Touched:Connect(function(hit) if triggered then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end triggered = true clickSound:Play() -- через 1.2с плитка пропадает Debris:AddItem(part, 1.2) end)`; for (let i = 1; i <= 14; i++) overrides['g3_tile_' + i] = tileScript; return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 4 — «Кнопка и дверь» // ═══════════════════════════════════════════════════════════════ 'button-door': { g4_main: `-- === ИГРА «КНОПКА-ОТКРЫВАШКА» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} __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 TweenService = game:GetService("TweenService") local RunService = game:GetService("RunService") local part = script.Parent local opened = false local hintVisible = false -- Подсказка над кнопкой. BillboardGui в shim — generic instance, -- управляем видимостью через label.Visible. local 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] Открыть дверь" label.Visible = false -- скрыт по умолчанию local clickSound = Instance.new("Sound", part) clickSound.SoundId = "click"; clickSound.Volume = 0.8 -- Каждый кадр проверяем расстояние до игрока. Подсказку показываем -- только если игрок в радиусе 4 единиц. RunService.Heartbeat:Connect(function() if opened then return end local px = __rbxl_player_x() 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) local near = dist <= 4 if near ~= hintVisible then hintVisible = near label.Visible = near end end) UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if opened or not hintVisible then return end if input.KeyCode ~= Enum.KeyCode.E then return end opened = true label.Visible = false -- скрываем подсказку (Destroy не уничтожает GUI-overlay) label:Destroy() hintGui:Destroy() clickSound:Play() __rbxl_show_text("Дверь открывается!", 2) part.Color = Color3.fromRGB(100, 255, 100) local door = workspace:FindFirstChild("Дверь") if door then local dp = door.Position local goal = { Position = Vector3.new(dp.X, dp.Y + 6, dp.Z) } 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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 5 — «Лабиринт» // ═══════════════════════════════════════════════════════════════ 'maze': { g5_main: `-- === ИГРА «ЛАБИРИНТ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} __rbxl_show_text("Найди выход из лабиринта!", 3) 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)`, g5_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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 6 — «Угадай цвет» // ═══════════════════════════════════════════════════════════════ 'color-tiles': (function() { const overrides = { g6_main: `-- === ИГРА «ЦВЕТНЫЕ ПЛИТКИ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local player = Players.LocalPlayer local painted = 0 local TOTAL = 36 local won = false __rbxl_show_text("Наступи на все плитки!", 3) -- Счётчик в правом верхнем углу local screenGui = Instance.new("ScreenGui", player.PlayerGui) local label = Instance.new("TextLabel", screenGui) label.Size = UDim2.new(0, 220, 0, 50) label.Position = UDim2.new(1, -240, 0, 20) label.BackgroundColor3 = Color3.fromRGB(0, 0, 0) label.BackgroundTransparency = 0.4 label.TextColor3 = Color3.fromRGB(160, 255, 160) label.TextScaled = true label.Font = Enum.Font.SourceSansBold label.Text = "Плитки: 0 / " .. TOTAL local pickupSound = Instance.new("Sound", workspace) pickupSound.SoundId = "pickup"; pickupSound.Volume = 0.7 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 local paintEvent = getEvent("TilePainted") paintEvent.Event:Connect(function() if won then return end painted = painted + 1 label.Text = "Плитки: " .. painted .. " / " .. TOTAL pickupSound:Play() if painted >= TOTAL then won = true winSound:Play() __rbxl_show_text("Победа! Все плитки раскрашены!", 5) 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 end)`, }; // Скрипт для каждой из 36 плиток — одинаковый код через генератор const tileScript = `-- === Скрипт цветной плитки (Lua) === local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent local painted = false part.Touched:Connect(function(hit) if painted then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end painted = true part.Color = Color3.fromRGB(51, 221, 85) -- ярко-зелёный local ev = ReplicatedStorage:FindFirstChild("TilePainted") if ev then ev:Fire() end end)`; for (let i = 1; i <= 36; i++) overrides['g6_tile_' + i] = tileScript; return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 7 — «Ловишка предметов» // ═══════════════════════════════════════════════════════════════ 'catch-falling': { g7_main: `-- === ИГРА «ПОЙМАЙ ПАДАЮЩЕЕ» — главный скрипт (Lua) === local Players = game:GetService("Players") local Debris = game:GetService("Debris") local player = Players.LocalPlayer local score = 0 local GOAL = 15 local won = false __rbxl_show_text("Лови падающие кубы! Нужно 15", 3) -- Счётчик в правом верхнем углу local screenGui = Instance.new("ScreenGui", player.PlayerGui) local label = Instance.new("TextLabel", screenGui) label.Size = UDim2.new(0, 220, 0, 50) label.Position = UDim2.new(1, -240, 0, 20) label.BackgroundColor3 = Color3.fromRGB(0, 0, 0) label.BackgroundTransparency = 0.4 label.TextColor3 = Color3.fromRGB(255, 215, 0) label.TextScaled = true label.Font = Enum.Font.SourceSansBold label.Text = "Поймано: 0 / " .. GOAL local coinSound = Instance.new("Sound", workspace) coinSound.SoundId = "coin"; coinSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Каждые 1.5 сек роняем куб (через Heartbeat — task.spawn не умеет yield) local RunService = game:GetService("RunService") local _spawnTimer = 0 local function spawnCube() -- Используем хелпер __rbxl_spawn_part — он сразу создаёт примитив -- с правильными свойствами (включая anchored=false → реальная гравитация). local cube = __rbxl_spawn_part({ type = "cube", x = math.random(-6, 6), y = 14, z = math.random(-6, 6), sx = 0.8, sy = 0.8, sz = 0.8, color = "#ffcc33", anchored = false, -- падает canCollide = true, }) if not cube then return end Debris:AddItem(cube, 6) local caught = false cube.Touched:Connect(function(hit) if caught or won then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end caught = true score = score + 1 label.Text = "Поймано: " .. score .. " / " .. GOAL coinSound:Play() cube:Destroy() if score >= GOAL then won = true winSound:Play() __rbxl_show_text("Победа! Ты поймал 15 кубов!", 5) 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 end) end RunService.Heartbeat:Connect(function(dt) if won then return end _spawnTimer = _spawnTimer + (dt or 0.016) if _spawnTimer >= 1.5 then _spawnTimer = 0 spawnCube() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 8 — «Беги до финиша» // ═══════════════════════════════════════════════════════════════ 'run-to-finish': { g8_main: `-- === ИГРА «БЕГИ К ФИНИШУ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local finished = false local time = 0 __rbxl_show_text("Беги к зелёному финишу — на время!", 3) -- Секундомер вверху по центру local screenGui = Instance.new("ScreenGui", player.PlayerGui) local timerLabel = Instance.new("TextLabel", screenGui) timerLabel.Size = UDim2.new(0, 220, 0, 60) timerLabel.Position = UDim2.new(0.5, -110, 0, 20) timerLabel.BackgroundColor3 = Color3.fromRGB(0, 0, 0) timerLabel.BackgroundTransparency = 0.4 timerLabel.TextColor3 = Color3.fromRGB(255, 255, 255) timerLabel.TextScaled = true timerLabel.Font = Enum.Font.SourceSansBold timerLabel.Text = "0.0 сек" local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Каждый кадр прибавляем dt к таймеру RunService.Heartbeat:Connect(function(dt) if finished then return end time = time + (dt or 0.016) -- Округляем до одного знака для отображения local rounded = math.floor(time * 10) / 10 timerLabel.Text = string.format("%.1f сек", rounded) end) -- Финиш-зона шлёт BindableEvent local finishEvent = getEvent("FinishReached") finishEvent.Event:Connect(function() if finished then return end finished = true local t = math.floor(time * 10) / 10 winSound:Play() __rbxl_show_text("Финиш! Твоё время: " .. string.format("%.1f", t) .. " сек", 6) 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)`, g8_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 fired = true local ev = ReplicatedStorage:FindFirstChild("FinishReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 9 — «Светофор» // ═══════════════════════════════════════════════════════════════ 'traffic-light': { g9_main: `-- === ИГРА «СВЕТОФОР» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local won = false local phase = "green" -- "green" (беги) или "red" (замри) local phaseTimer = 0 local GREEN_TIME = 3 local RED_TIME = 2.5 __rbxl_show_text("Зелёный — беги! Красный — замри!", 3) local loseSound = Instance.new("Sound", workspace) loseSound.SoundId = "lose"; loseSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Находим светофор и сразу красим в зелёный local light = workspace:FindFirstChild("Светофор") if light then light.Color = Color3.fromRGB(34, 221, 85) end __rbxl_show_text("ЗЕЛЁНЫЙ — беги!", 1.2) -- Каждый кадр считаем таймер фазы и проверяем движение local prevX, prevZ = nil, nil RunService.Heartbeat:Connect(function(dt) if won then return end dt = dt or 0.016 -- Переключение фаз phaseTimer = phaseTimer + dt if phase == "green" and phaseTimer >= GREEN_TIME then phaseTimer = 0 phase = "red" if light then light.Color = Color3.fromRGB(226, 59, 59) end __rbxl_show_text("КРАСНЫЙ — замри!", 1.2) elseif phase == "red" and phaseTimer >= RED_TIME then phaseTimer = 0 phase = "green" if light then light.Color = Color3.fromRGB(34, 221, 85) end __rbxl_show_text("ЗЕЛЁНЫЙ — беги!", 1.2) end -- Если красный и игрок шевелится — респаун local px = __rbxl_player_x() local pz = __rbxl_player_z() if prevX and phase == "red" then local dx = px - prevX local dz = pz - prevZ local moved = math.sqrt(dx*dx + dz*dz) if moved / dt > 0.8 then player:LoadCharacter() loseSound:Play() __rbxl_show_text("Двинулся на красный! На старт.", 2) end end prevX, prevZ = px, pz end) -- Финиш-зона шлёт BindableEvent local winEvent = getEvent("WinReached") winEvent.Event:Connect(function() if won then return end won = true winSound:Play() __rbxl_show_text("Победа! Ты дошёл до финиша!", 5) 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)`, g9_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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 10 — «Прыжки на пружинах» // ═══════════════════════════════════════════════════════════════ 'spring-jump': (function() { const overrides = { g10_main: `-- === ИГРА «ПРЫЖОК-ПРУЖИНА» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local won = false __rbxl_show_text("Прыгай по батутам всё выше!", 3) local loseSound = Instance.new("Sound", workspace) loseSound.SoundId = "lose"; loseSound.Volume = 1 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Каждый кадр проверяем: упал вниз — на старт RunService.Heartbeat:Connect(function() if won then return end local py = __rbxl_player_y() if py < -3 then player:LoadCharacter() loseSound:Play() end end) -- Финиш-зона шлёт BindableEvent local winEvent = getEvent("WinReached") winEvent.Event:Connect(function() if won then return end won = true winSound:Play() __rbxl_show_text("Победа! Ты допрыгал до верха!", 5) 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)`, g10_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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }; // Скрипт каждого батута — одинаковый код const trampScript = `-- === Скрипт батута (Lua) === -- Игрок встал на батут — мощный подброс вверх. local part = script.Parent local jumpSound = Instance.new("Sound", part) jumpSound.SoundId = "jump"; jumpSound.Volume = 0.7 local lastBoost = 0 part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end -- Не зацикливаем подброс — минимум 0.5с между активациями local now = tick() if now - lastBoost < 0.5 then return end lastBoost = now __rbxl_boost_jump(3.2) -- 3.2 = втрое выше обычного прыжка jumpSound:Play() end)`; // Батуты в JS-builder имеют id 4, 5, 6 (после трёх этажей) for (const tid of [4, 5, 6]) { overrides['g10_tramp_' + tid] = trampScript; } return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 11 — «Эхо» (нажми кнопку → звук) // ═══════════════════════════════════════════════════════════════ 'echo-room': (function() { // Звуки и цвета для 6 плиток — должны совпадать с JS-builder const tiles = [ { sound: 'coin', color: '#e23b3b' }, // 1 { sound: 'jump', color: '#f59e0b' }, // 2 { sound: 'pickup', color: '#facc15' }, // 3 { sound: 'click', color: '#22c55e' }, // 4 { sound: 'hit', color: '#3b82f6' }, // 5 { sound: 'coin', color: '#a855f7' }, // 6 ]; const TOTAL = tiles.length; const overrides = { g11_main: `-- === ИГРА «ЭХО-КОМНАТА» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local player = Players.LocalPlayer local stepped = 0 local TOTAL = ${TOTAL} local won = false __rbxl_show_text("Наступи на все цветные плитки!", 3) -- Счётчик в правом верхнем углу local screenGui = Instance.new("ScreenGui", player.PlayerGui) local label = Instance.new("TextLabel", screenGui) label.Size = UDim2.new(0, 240, 0, 50) label.Position = UDim2.new(1, -260, 0, 20) label.BackgroundColor3 = Color3.fromRGB(0, 0, 0) label.BackgroundTransparency = 0.4 label.TextColor3 = Color3.fromRGB(255, 255, 255) label.TextScaled = true label.Font = Enum.Font.SourceSansBold label.Text = "Плитки: 0 / " .. TOTAL local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Плитка впервые засчитана local stepEvent = getEvent("EchoStep") stepEvent.Event:Connect(function() stepped = stepped + 1 label.Text = "Плитки: " .. stepped .. " / " .. TOTAL if stepped >= TOTAL then __rbxl_show_text("Все плитки звучали! Иди на финиш.", 3) end end) -- Игрок встал на финиш local finishEvent = getEvent("EchoFinish") finishEvent.Event:Connect(function() if won then return end if stepped < TOTAL then __rbxl_show_text("Сначала пройди все " .. TOTAL .. " плиток!", 2) return end won = true winSound:Play() __rbxl_show_text("Победа! Эхо-комната пройдена!", 5) 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)`, g11_finish: `-- === Скрипт финиша (Lua) === local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end local ev = ReplicatedStorage:FindFirstChild("EchoFinish") if ev then ev:Fire() end end)`, }; // Скрипт каждой звуковой плитки — со своим звуком и цветом for (let i = 0; i < TOTAL; i++) { const t = tiles[i]; overrides['g11_tile_' + (i + 1)] = `-- === Скрипт звуковой плитки (Lua) === local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent local used = false local lastSound = 0 local tileSound = Instance.new("Sound", part) tileSound.SoundId = "${t.sound}"; tileSound.Volume = 0.8 part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end -- Звук эхом — каждый раз, но не чаще 0.4с local now = tick() if now - lastSound > 0.4 then lastSound = now tileSound:Play() -- Вспышка частиц над плиткой local pos = part.Position __rbxl_spawn_particles("sparks", pos.X, pos.Y + 1, pos.Z, 0.6, 1) end -- Засчитываем плитку только в первый раз if not used then used = true local ev = ReplicatedStorage:FindFirstChild("EchoStep") if ev then ev:Fire() end end end)`; } return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 12 — «Кодовая дверь» // ═══════════════════════════════════════════════════════════════ 'code-door': (function() { const overrides = { g12_main: `-- === ИГРА «ДВЕРЬ ПО КОДУ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local TweenService = game:GetService("TweenService") local CODE = { 3, 1, 4, 2 } local entered = {} local opened = false local won = false __rbxl_show_text("Нажми кнопки в правильном порядке (E)", 4) local clickSound = Instance.new("Sound", workspace) clickSound.SoundId = "click"; clickSound.Volume = 0.7 local loseSound = Instance.new("Sound", workspace) loseSound.SoundId = "lose"; loseSound.Volume = 0.8 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 local pressEvent = getEvent("ButtonPress") pressEvent.Event:Connect(function(num) if opened then return end clickSound:Play() table.insert(entered, num) local i = #entered if entered[i] ~= CODE[i] then -- ошибка — сброс entered = {} __rbxl_show_text("Неверно! Код сброшен.", 1.5) loseSound:Play() return end if #entered == #CODE then opened = true __rbxl_show_text("Код верный! Дверь открывается.", 3) winSound:Play() local door = workspace:FindFirstChild("Дверь") if door then local dp = door.Position local goal = { Position = Vector3.new(dp.X, dp.Y + 6, dp.Z) } TweenService:Create(door, TweenInfo.new(1.2), goal):Play() door.CanCollide = false end else __rbxl_show_text("Верно! Дальше...", 1) end end) local winEvent = getEvent("WinReached") winEvent.Event:Connect(function() if won then return end won = true __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)`, g12_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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }; // 4 кнопки — каждая шлёт свой номер при нажатии E (если игрок рядом) for (let num = 1; num <= 4; num++) { overrides['g12_btn_' + num] = `-- === Скрипт кнопки-цифры ${num} (Lua) === local UserInputService = game:GetService("UserInputService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local part = script.Parent local hintVisible = false -- Подсказка над кнопкой (виден когда игрок рядом) local hintGui = Instance.new("BillboardGui", part) hintGui.Size = UDim2.new(4, 0, 1, 0) hintGui.StudsOffset = Vector3.new(0, 1.5, 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] Нажать ${num}" label.Visible = false -- Каждый кадр проверяем дистанцию до игрока RunService.Heartbeat:Connect(function() local px = __rbxl_player_x() 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) local near = dist <= 3 if near ~= hintVisible then hintVisible = near label.Visible = near end end) UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if not hintVisible then return end if input.KeyCode ~= Enum.KeyCode.E then return end local ev = ReplicatedStorage:FindFirstChild("ButtonPress") if ev then ev:Fire(${num}) end end)`; } return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 13 — «Торговец» // ═══════════════════════════════════════════════════════════════ 'trader': { g13_main: `-- === ИГРА «ТОРГОВЕЦ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local player = Players.LocalPlayer local hasKey = false local won = false __rbxl_show_text("Поговори с торговцем — нажми E у прилавка", 4) local pickupSound = Instance.new("Sound", workspace) pickupSound.SoundId = "pickup"; pickupSound.Volume = 0.8 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Спавним NPC-торговца за прилавком (паритет с JS spawnNpc) local traderRef = __rbxl_spawn_npc("character-a", 0, 1, 5, "Торговец Боб", 100, 0) -- Определяем итем "Ключ" в инвентаре и показываем hotbar __rbxl_inventory_define("key", "Ключ", "#ffd700") -- Игрок заговорил с торговцем local talkEvent = getEvent("TalkTrader") talkEvent.Event:Connect(function() if hasKey then __rbxl_npc_say(traderRef, "Иди к двери, ключ у тебя!", 3) return end hasKey = true __rbxl_npc_say(traderRef, "Привет! Вот тебе ключ от двери. Удачи!", 4) __rbxl_inventory_add("key", 1) __rbxl_show_text("Ты получил Ключ!", 2) pickupSound:Play() end) -- Игрок пытается открыть дверь local openEvent = getEvent("OpenDoor") openEvent.Event:Connect(function() if not __rbxl_inventory_has("key") then __rbxl_show_text("Дверь заперта. Нужен ключ от торговца.", 2) return end __rbxl_show_text("Ключ подошёл! Дверь открыта.", 3) winSound:Play() local door = workspace:FindFirstChild("Дверь") if door then local dp = door.Position local goal = { Position = Vector3.new(dp.X, dp.Y + 6, dp.Z) } TweenService:Create(door, TweenInfo.new(1.2), goal):Play() door.CanCollide = false end end) -- Игрок встал на финиш local winEvent = getEvent("WinReached") winEvent.Event:Connect(function() if won then return end won = true __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)`, g13_counter: `-- === Скрипт прилавка (Lua) === -- Подойди и нажми E чтобы поговорить с торговцем. local UserInputService = game:GetService("UserInputService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local part = script.Parent local hintVisible = false RunService.Heartbeat:Connect(function() local px = __rbxl_player_x() 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) local near = dist <= 4 if near ~= hintVisible then hintVisible = near if near then __rbxl_hud_set("g13_counter_hint", "[E] Поговорить с торговцем", 50, 75, "#ffe44a", 20) else __rbxl_hud_set("g13_counter_hint", nil) end end end) UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if not hintVisible then return end if input.KeyCode ~= Enum.KeyCode.E then return end local ev = ReplicatedStorage:FindFirstChild("TalkTrader") if ev then ev:Fire() end end)`, g13_door: `-- === Скрипт двери (Lua) === -- Подойди и нажми E чтобы открыть дверь (нужен ключ). local UserInputService = game:GetService("UserInputService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local part = script.Parent local hintVisible = false RunService.Heartbeat:Connect(function() local px = __rbxl_player_x() 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) local near = dist <= 4 if near ~= hintVisible then hintVisible = near if near then __rbxl_hud_set("g13_door_hint", "[E] Открыть дверь", 50, 75, "#ffe44a", 20) else __rbxl_hud_set("g13_door_hint", nil) end end end) UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if not hintVisible then return end if input.KeyCode ~= Enum.KeyCode.E then return end local ev = ReplicatedStorage:FindFirstChild("OpenDoor") if ev then ev:Fire() end end)`, g13_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 fired = true local ev = ReplicatedStorage:FindFirstChild("WinReached") if ev then ev:Fire() end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 14 — «Собери по тегу» // ═══════════════════════════════════════════════════════════════ 'collect-by-tag': (function() { const TOTAL = 7; const overrides = { g14_main: `-- === ИГРА «СОБЕРИ ПО ТЕГАМ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} local CollectionService = game:GetService("CollectionService") local Players = game:GetService("Players") local player = Players.LocalPlayer local TOTAL = ${TOTAL} local won = false __rbxl_show_text("Собери все ЖЁЛТЫЕ звёзды!", 3) -- Счётчик в правом верхнем углу local screenGui = Instance.new("ScreenGui", player.PlayerGui) local label = Instance.new("TextLabel", screenGui) label.Size = UDim2.new(0, 220, 0, 50) label.Position = UDim2.new(1, -240, 0, 20) label.BackgroundColor3 = Color3.fromRGB(0, 0, 0) label.BackgroundTransparency = 0.4 label.TextColor3 = Color3.fromRGB(255, 215, 0) label.TextScaled = true label.Font = Enum.Font.SourceSansBold label.Text = "Звёзды: 0 / " .. TOTAL local coinSound = Instance.new("Sound", workspace) coinSound.SoundId = "coin"; coinSound.Volume = 0.8 local winSound = Instance.new("Sound", workspace) winSound.SoundId = "win"; winSound.Volume = 1 -- Помечаем все звёзды тегом 'звезда' (с небольшой задержкой — -- скрипты звёзд должны успеть запуститься и зарегистрировать part). task.delay(0.2, function() for i = 1, TOTAL do local star = workspace:FindFirstChild("Звезда_" .. i) if star then CollectionService:AddTag(star, "звезда") end end end) -- Звёзды сообщают о сборе. Главный скрипт считает оставшиеся через -- CollectionService:GetTagged — паритет с JS game.scene.getTagged. local collectEvent = getEvent("StarCollected") collectEvent.Event:Connect(function() if won then return end local left = #CollectionService:GetTagged("звезда") label.Text = "Звёзды: " .. (TOTAL - left) .. " / " .. TOTAL coinSound:Play() if left == 0 then won = true winSound:Play() __rbxl_show_text("Победа! Все звёзды собраны!", 5) 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 end)`, }; // Скрипт каждой звезды — одинаковый: на touch → untag + destroy + Fire const starScript = `-- === Скрипт звезды (Lua) === local CollectionService = game:GetService("CollectionService") local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent local picked = false part.Touched:Connect(function(hit) if picked then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end picked = true -- Снимаем тег и удаляем звезду, потом шлём событие. CollectionService:RemoveTag(part, "звезда") part:Destroy() local ev = ReplicatedStorage:FindFirstChild("StarCollected") if ev then ev:Fire() end end)`; for (let i = 1; i <= TOTAL; i++) { overrides['g14_star_' + i] = starScript; } return overrides; })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 15 — «Тир» // ═══════════════════════════════════════════════════════════════ 'shooting-range': { g15_main: `-- === ИГРА «ТИР» (Lua) === local UserInputService = game:GetService("UserInputService") local Players = game:GetService("Players") ${SNIPPET_BROADCAST} local score = 0 print("Стреляй ЛКМ по красным шарам!") local ev = getEvent("TargetHit") ev.Event:Connect(function() score = score + 1 print("Попал! Очки: " .. score) end) -- ЛКМ — пускаем луч из камеры UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end local player = Players.LocalPlayer local mouse = player:GetMouse() local target = mouse.Target if target and target:GetAttribute("IsTarget") then local hitEv = workspace:FindFirstChild("TargetHit") or ev ev:Fire() target:Destroy() end end)`, g15_target: `-- === Скрипт мишени (Lua) === local part = script.Parent part:SetAttribute("IsTarget", true)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 16 — «Лавовый пол» // ═══════════════════════════════════════════════════════════════ 'lava-floor': { g16_main: `-- === ИГРА «ЛАВОВЫЙ ПОЛ» (Lua) === print("Прыгай по островкам, не упади в лаву!")`, g16_lava: `-- === Скрипт лавы (Lua) === local part = script.Parent part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if h then h.Health = 0 end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 17 — «Ключ от сундука» // ═══════════════════════════════════════════════════════════════ 'key-chest': { g17_main: `-- === ИГРА «КЛЮЧ ОТ СУНДУКА» (Lua) === local Players = game:GetService("Players") Players.PlayerAdded:Connect(function(player) local stats = Instance.new("Folder", player); stats.Name = "leaderstats" local key = Instance.new("BoolValue", stats); key.Name = "Ключ" end) for _, p in ipairs(Players:GetPlayers()) do if not p:FindFirstChild("leaderstats") then local stats = Instance.new("Folder", p); stats.Name = "leaderstats" local key = Instance.new("BoolValue", stats); key.Name = "Ключ" end end print("Найди ключ и открой сундук!")`, g17_key: `-- === Скрипт ключа (Lua) === local Players = game:GetService("Players") local part = script.Parent part.Touched:Connect(function(hit) local player = Players:GetPlayerFromCharacter(hit.Parent) if not player then return end local stats = player:FindFirstChild("leaderstats") if stats and stats:FindFirstChild("Ключ") then stats['Ключ'].Value = true print("Подобрал ключ!") part:Destroy() end end)`, g17_chest: `-- === Скрипт сундука (Lua) === local Players = game:GetService("Players") local part = script.Parent part.Touched:Connect(function(hit) local player = Players:GetPlayerFromCharacter(hit.Parent) if not player then return end local stats = player:FindFirstChild("leaderstats") if stats and stats['Ключ'] and stats['Ключ'].Value then print("Сундук открыт! ПОБЕДА!") part.Color = Color3.fromRGB(255, 215, 0) else print("Нужен ключ!") end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 18 — «Качели» // ═══════════════════════════════════════════════════════════════ 'swing': { g18_main: `-- === ИГРА «КАЧЕЛИ» (Lua) === local TweenService = game:GetService("TweenService") local swing = workspace:WaitForChild("Качели") local startPos = swing.Position -- Качаем туда-сюда бесконечно task.spawn(function() while true do local up = TweenService:Create(swing, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), { Position = startPos + Vector3.new(0, 0, 5) }) up:Play(); up.Completed:Wait() local down = TweenService:Create(swing, TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), { Position = startPos + Vector3.new(0, 0, -5) }) down:Play(); down.Completed:Wait() end end) print("Запрыгни на качающуюся платформу!")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 19 — «Лифт» // ═══════════════════════════════════════════════════════════════ 'elevator': { g19_main: `-- === ИГРА «ЛИФТ» (Lua) === local TweenService = game:GetService("TweenService") local elevator = workspace:WaitForChild("Лифт") local startPos = elevator.Position local topPos = startPos + Vector3.new(0, 10, 0) local goingUp = true elevator.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end local goal = { Position = goingUp and topPos or startPos } TweenService:Create(elevator, TweenInfo.new(3), goal):Play() goingUp = not goingUp end) print("Встань на лифт — он повезёт тебя наверх!")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 20 — «Имена врагов» // ═══════════════════════════════════════════════════════════════ 'enemy-names': { g20_main: `-- === ИГРА «ИМЕНА ВРАГОВ» (Lua) === local function addLabel(part, text, color) local bb = Instance.new("BillboardGui", part) bb.Size = UDim2.new(4, 0, 1, 0) bb.StudsOffset = Vector3.new(0, 2.5, 0) bb.AlwaysOnTop = true local label = Instance.new("TextLabel", bb) label.Size = UDim2.new(1, 0, 1, 0) label.BackgroundTransparency = 1 label.Text = text label.TextColor3 = color or Color3.new(1, 1, 1) label.TextScaled = true end for _, child in ipairs(workspace:GetChildren()) do if child:IsA("BasePart") and child.Name:match("^Враг") then addLabel(child, child.Name, Color3.fromRGB(255, 80, 80)) end end print("Над врагами появились имена")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 21 — «Догонялки» // ═══════════════════════════════════════════════════════════════ 'chaser': { g21_main: `-- === ИГРА «ДОГОНЯЛКИ» (Lua) === local Players = game:GetService("Players") local RunService = game:GetService("RunService") local enemy = workspace:WaitForChild("Догонщик") RunService.Heartbeat:Connect(function(dt) local player = Players:GetPlayers()[1] if not player or not player.Character then return end local target = player.Character:FindFirstChild("HumanoidRootPart") if not target then return end -- Двигаемся в сторону игрока со скоростью 5 local dir = (target.Position - enemy.Position) if dir.Magnitude > 1 then enemy.Position = enemy.Position + dir.Unit * 5 * dt else -- Поймал local h = player.Character:FindFirstChild("Humanoid") if h then h:TakeDamage(10) end end end) print("Убегай от догонщика!")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 22 — «Опасная зона» // ═══════════════════════════════════════════════════════════════ 'danger-zone': { g22_main: `-- === ИГРА «ОПАСНАЯ ЗОНА» (Lua) === print("Не стой в красной зоне!")`, g22_zone: `-- === Скрипт опасной зоны (Lua) === local part = script.Parent local insiders = {} part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if h then insiders[h] = true end end) part.TouchEnded:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if h then insiders[h] = nil end end) -- Урон каждые 0.5 сек пока стоят while true do task.wait(0.5) for h in pairs(insiders) do if h.Parent then h:TakeDamage(5) end end end`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 23 — «3 переключателя» // ═══════════════════════════════════════════════════════════════ 'switches': { g23_main: `-- === ИГРА «3 ПЕРЕКЛЮЧАТЕЛЯ» (Lua) === ${SNIPPET_BROADCAST} local activated = {false, false, false} print("Активируй все 3 переключателя!") local ev = getEvent("SwitchToggled") ev.Event:Connect(function(idx) activated[idx] = true print("Переключатель " .. idx .. " активирован") if activated[1] and activated[2] and activated[3] then print("ПОБЕДА! Все 3 активированы!") end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 24 — «Падающий мост» // ═══════════════════════════════════════════════════════════════ 'falling-bridge': { g24_main: `-- === ИГРА «ПАДАЮЩИЙ МОСТ» (Lua) === print("Беги по мосту — плиты падают!")`, g24_plate: `-- === Скрипт падающей плиты (Lua) === local part = script.Parent local fell = false part.Touched:Connect(function(hit) if fell then return end local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end fell = true task.delay(0.5, function() part.Anchored = false part.CanCollide = false game:GetService("Debris"):AddItem(part, 3) end) end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 25 — «Облёт камеры» // ═══════════════════════════════════════════════════════════════ 'flyby-camera': { g25_main: `-- === ИГРА «ОБЛЁТ КАМЕРЫ» (Lua) === local TweenService = game:GetService("TweenService") local camera = workspace.CurrentCamera camera.CameraType = Enum.CameraType.Scriptable local points = { CFrame.new(Vector3.new(0, 20, -30), Vector3.new(0, 5, 0)), CFrame.new(Vector3.new(20, 15, 0), Vector3.new(0, 5, 0)), CFrame.new(Vector3.new(0, 25, 30), Vector3.new(0, 5, 0)), } for _, cf in ipairs(points) do local tween = TweenService:Create(camera, TweenInfo.new(2), { CFrame = cf }) tween:Play(); tween.Completed:Wait() end camera.CameraType = Enum.CameraType.Custom print("Облёт окончен — теперь играй!")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 26 — «Магнит монет» // ═══════════════════════════════════════════════════════════════ 'coin-magnet': { g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» (Lua) === local Players = game:GetService("Players") local RunService = game:GetService("RunService") local CollectionService = game:GetService("CollectionService") ${SNIPPET_BROADCAST} local score = 0 local ev = getEvent("CoinCollected") ev.Event:Connect(function() score = score + 1 print("Собрано: " .. score) end) RunService.Heartbeat:Connect(function(dt) local player = Players:GetPlayers()[1] if not player or not player.Character then return end local hrp = player.Character:FindFirstChild("HumanoidRootPart") if not hrp then return end for _, coin in ipairs(CollectionService:GetTagged("magnetcoin")) do local dist = (coin.Position - hrp.Position).Magnitude if dist < 8 then coin.Position = coin.Position + (hrp.Position - coin.Position).Unit * 20 * dt if dist < 1 then ev:Fire() coin:Destroy() end end end end) print("Монетки сами летят к тебе!")`, g26_coin: `-- === Скрипт магнит-монетки (Lua) === local CollectionService = game:GetService("CollectionService") CollectionService:AddTag(script.Parent, "magnetcoin")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 27 — «Двойной прыжок» // ═══════════════════════════════════════════════════════════════ 'double-jump': { g27_main: `-- === ИГРА «ДВОЙНОЙ ПРЫЖОК» (Lua) === local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") local function setupDoubleJump(player) local jumpsLeft = 2 local char = player.Character or player.CharacterAdded:Wait() local h = char:WaitForChild("Humanoid") -- Восстанавливаем прыжки при касании земли h.StateChanged:Connect(function(_, newState) if newState == Enum.HumanoidStateType.Landed then jumpsLeft = 2 end end) UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if input.KeyCode == Enum.KeyCode.Space and jumpsLeft > 0 then jumpsLeft = jumpsLeft - 1 if jumpsLeft == 1 then local hrp = char:FindFirstChild("HumanoidRootPart") if hrp then hrp.Velocity = Vector3.new(hrp.Velocity.X, 50, hrp.Velocity.Z) end end end end) end Players.PlayerAdded:Connect(setupDoubleJump) for _, p in ipairs(Players:GetPlayers()) do setupDoubleJump(p) end print("Жми Space дважды — двойной прыжок!")`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 28 — «Призрачные стены» // ═══════════════════════════════════════════════════════════════ 'ghost-walls': { g28_main: `-- === ИГРА «ПРИЗРАЧНЫЕ СТЕНЫ» (Lua) === print("Некоторые стены — призрачные. Найди проход!")`, g28_ghost: `-- === Скрипт призрачной стены (Lua) === local part = script.Parent part.CanCollide = false part.Transparency = 0.5`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 29 — «Магазин» // ═══════════════════════════════════════════════════════════════ 'shop': { g29_main: `-- === ИГРА «МАГАЗИН» (Lua) === local Players = game:GetService("Players") Players.PlayerAdded:Connect(function(player) local stats = Instance.new("Folder", player); stats.Name = "leaderstats" local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 20 end) for _, p in ipairs(Players:GetPlayers()) do if not p:FindFirstChild("leaderstats") then local stats = Instance.new("Folder", p); stats.Name = "leaderstats" local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 20 end end print("У тебя 20 монет — купи что-нибудь!")`, g29_item: `-- === Скрипт товара (Lua) === local Players = game:GetService("Players") local part = script.Parent local price = part:GetAttribute("Price") or 5 local bought = false part.Touched:Connect(function(hit) if bought then return end local player = Players:GetPlayerFromCharacter(hit.Parent) if not player then return end local stats = player:FindFirstChild("leaderstats") if not stats then return end if stats['Монеты'].Value >= price then stats['Монеты'].Value = stats['Монеты'].Value - price bought = true print("Куплено! Цена: " .. price) part.Transparency = 0.7 else print("Не хватает! Нужно " .. price .. " монет") end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 30 — «Квесты» // ═══════════════════════════════════════════════════════════════ 'quest-tasks': { g30_main: `-- === ИГРА «КВЕСТЫ» (Lua) === ${SNIPPET_BROADCAST} local quests = { { name = "Собери 5 ягод", goal = 5, current = 0 }, { name = "Победи врага", goal = 1, current = 0 }, { name = "Дойди до башни", goal = 1, current = 0 }, } print("Квесты:") for i, q in ipairs(quests) do print(" " .. i .. ". " .. q.name) end local ev = getEvent("QuestProgress") ev.Event:Connect(function(idx, amount) quests[idx].current = quests[idx].current + (amount or 1) local q = quests[idx] print(q.name .. ": " .. q.current .. "/" .. q.goal) if q.current >= q.goal then print("Квест выполнен: " .. q.name) end end)`, }, // ═══════════════════════════════════════════════════════════════ // ИГРА 31-50: упрощённые версии (главные скрипты) // ═══════════════════════════════════════════════════════════════ 'base-defense': { g31_main: simpleMain("Защити базу от волн врагов!") }, 'lap-race': { g32_main: simpleMain("Проедь все круги первым!") }, 'boss-platformer': { g33_main: simpleMain("Победи босса прыжками на голову!") }, 'harvest': { g34_main: simpleMain("Собирай урожай, продавай в магазин!") }, 'hide-from-npc': { g35_main: simpleMain("Прячься от NPC — не попадайся!") }, 'box-puzzle': { g36_main: simpleMain("Двигай ящики на места!") }, 'obstacle-course': { g37_main: simpleMain("Пройди полосу препятствий!") }, 'music-game': { g38_main: simpleMain("Жми клавиши в ритм музыки!") }, 'tower-build': { g39_main: simpleMain("Построй самую высокую башню!") }, 'wave-survival': { g40_main: simpleMain("Выживай в волнах врагов!") }, 'adventure-platformer': { g41_main: simpleMain("Приключение — собирай артефакты!") }, 'rpg-village': { g42_main: simpleMain("Бегай по деревне, выполняй квесты!") }, 'obstacle-race': { g43_main: simpleMain("Гонка с препятствиями — финишируй!") }, 'tower-defense': { g44_main: simpleMain("Расставь башни — не пускай врагов!") }, 'arena-shooter': { g45_main: simpleMain("Стреляй по противникам на арене!") }, 'clicker': { g46_main: simpleClicker() }, 'escape-quest': { g47_main: simpleMain("Найди подсказки и выберись!") }, 'mp-tag': { g48_main: simpleMain("Поймай других игроков (мультиплеер)!") }, 'mp-race': { g49_main: simpleMain("Гонка на нескольких игроков!") }, 'make-your-own': { g50_main: simpleMain("Это твоя пустая площадка — твори!") }, }; // ══════════════════════════════════════════════════════════════════ // Хелперы для генерации часто повторяющихся скриптов // ══════════════════════════════════════════════════════════════════ /** Возвращает Lua-код скрипта монетки. */ function makeCoinScript() { return `-- === Скрипт монетки (Lua) === local ReplicatedStorage = game:GetService("ReplicatedStorage") local part = script.Parent part.Touched:Connect(function(hit) local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid") if not h then return end local ev = ReplicatedStorage:FindFirstChild("CoinCollected") if ev then ev:Fire() end part:Destroy() end)`; } /** Простой главный скрипт со стартовой подсказкой. */ function simpleMain(message) { return `-- === Главный скрипт (Lua) === print("${message.replace(/"/g, '\\"')}") -- TODO: эта игра-урок ещё не имеет полной Lua-реализации. -- Переключи язык на JS в редакторе, чтобы увидеть рабочую механику.`; } /** Кликер. */ function simpleClicker() { return `-- === КЛИКЕР (Lua) === local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") Players.PlayerAdded:Connect(function(player) local stats = Instance.new("Folder", player); stats.Name = "leaderstats" local cnt = Instance.new("IntValue", stats); cnt.Name = "Клики"; cnt.Value = 0 end) for _, p in ipairs(Players:GetPlayers()) do if not p:FindFirstChild("leaderstats") then local stats = Instance.new("Folder", p); stats.Name = "leaderstats" local cnt = Instance.new("IntValue", stats); cnt.Name = "Клики"; cnt.Value = 0 end end local function onClick(player) local stats = player:FindFirstChild("leaderstats") if stats and stats:FindFirstChild("Клики") then stats['Клики'].Value = stats['Клики'].Value + 1 end end UserInputService.InputBegan:Connect(function(input, gp) if gp then return end if input.UserInputType == Enum.UserInputType.MouseButton1 then onClick(Players.LocalPlayer) end end) print("Кликай ЛКМ — копи клики!")`; }