studio/src/community/docsGamesBuildersLua.js
min 5aec627b17 feat(g24): полный паритет «Падающий мост»
JS:
- showText 'Беги по мосту — доски рушатся!'
- onTick: p.y < -3 → respawn + 'Упал в пропасть! Снова.' + lose
- onMessage 'win' → 'Победа!' + win + confetti
- 18 досок: onTouch → click sound + delete через 1с
- финиш: onTouch → broadcast 'win'

Lua (паритет):
- __rbxl_show_text + Sounds
- Heartbeat: player_y < -3 → LoadCharacter + lose
- BindableEvent WinReached
- g24_plank_1..18: единый скрипт (IIFE генерит 18 ключей):
  Touched → click Sound + Debris:AddItem(part, 1)
- g24_finish: Touched → WinReached:Fire (fired-флаг)
2026-06-09 21:37:05 +03:00

2403 lines
96 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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': (function() {
// Мишени имеют id 2, 4, 6, 8, 10, 12, 14, 16 (постамент → нечётный, мишень → чётный)
const TARGET_IDS = [2, 4, 6, 8, 10, 12, 14, 16];
const TOTAL = TARGET_IDS.length;
const overrides = {
g15_main: `-- === ИГРА «ТИР» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local score = 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, 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, 100, 100)
label.TextScaled = true
label.Font = Enum.Font.SourceSansBold
label.Text = "Мишени: 0 / " .. TOTAL
local hitSound = Instance.new("Sound", workspace)
hitSound.SoundId = "hit"; hitSound.Volume = 0.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
local hitEvent = getEvent("TargetHit")
hitEvent.Event:Connect(function()
if won then return end
score = score + 1
label.Text = "Мишени: " .. score .. " / " .. TOTAL
hitSound:Play()
if score >= 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)`,
};
// Скрипт каждой мишени — ClickDetector + взрыв искр + сообщение
const targetScript = `-- === Скрипт мишени (Lua) ===
-- Клик ЛКМ по мишени = выстрел. ClickDetector ловит клик в 3D.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local part = script.Parent
local hit = false
local clickDet = Instance.new("ClickDetector", part)
clickDet.MaxActivationDistance = 50
clickDet.MouseClick:Connect(function()
if hit then return end
hit = true
-- Взрыв искр на месте мишени
local pos = part.Position
__rbxl_spawn_particles("explosion", pos.X, pos.Y, pos.Z, 0.5, 1)
-- Сообщаем главному скрипту
local ev = ReplicatedStorage:FindFirstChild("TargetHit")
if ev then ev:Fire() end
-- Мишень исчезает
part:Destroy()
end)`;
for (const tid of TARGET_IDS) {
overrides['g15_target_' + tid] = targetScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 16 — «Лавовый пол»
// ═══════════════════════════════════════════════════════════════
'lava-floor': {
g16_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 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 < -2 then
player:LoadCharacter()
end
end)
-- Финиш сообщает о победе
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)`,
g16_lava: `-- === Скрипт лавы (Lua) ===
-- Игрок коснулся лавы — урон. У damage есть защита (i-frames),
-- так что урон не каждый кадр, а раз в ~0.5 секунды.
-- ВАЖНО: проверяем что игрок НЕ над островком (по X/Z),
-- иначе урон срабатывает на островке из-за пересечения AABB.
local RunService = game:GetService("RunService")
local part = script.Parent
local hitSound = Instance.new("Sound", part)
hitSound.SoundId = "hit"; hitSound.Volume = 0.7
-- Координаты островков (из builder): { x, z }
local ISLES = {
{0, 5}, {3, 9}, {-2, 13}, {2, 17}, {-3, 21}, {1, 25},
}
local ISLE_HW = 1.4 -- половина ширины островка sx=2.4/2 + небольшой запас
local FINISH_X, FINISH_Z = -0.5, 29
local FINISH_HW, FINISH_HD = 3, 2.5
local function isOverSafeSpot()
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
-- Островки
for _, isle in ipairs(ISLES) do
if math.abs(px - isle[1]) <= ISLE_HW
and math.abs(pz - isle[2]) <= ISLE_HW then
return true
end
end
-- Финишная площадка
if math.abs(px - FINISH_X) <= FINISH_HW
and math.abs(pz - FINISH_Z) <= FINISH_HD then
return true
end
return false
end
-- Проверяем каждый кадр пока игрок касается лавы — наносим урон если он
-- НЕ над безопасным местом. Touched нам не нужен — лучше Heartbeat-проверка.
local inLava = false
part.Touched:Connect(function(hit)
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
inLava = true
end)
part.TouchEnded:Connect(function(hit)
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
inLava = false
end)
RunService.Heartbeat:Connect(function()
if not inLava then return end
if isOverSafeSpot() then return end -- стоит над островком/финишем
__rbxl_damage_player(20)
hitSound:Play()
end)`,
g16_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 17 — «Ключ от сундука»
// ═══════════════════════════════════════════════════════════════
'key-chest': {
g17_main: `-- === ИГРА «КЛЮЧ И СУНДУК» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local won = false
__rbxl_show_text("Найди ключ и открой сундук!", 3)
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
local loseSound = Instance.new("Sound", workspace)
loseSound.SoundId = "lose"; loseSound.Volume = 0.6
-- Определяем итем "Ключ" в инвентаре (показывает иконку в hotbar)
__rbxl_inventory_define("key", "Ключ", "#ffd700")
-- Игрок подобрал ключ
local takeEvent = getEvent("TakeKey")
takeEvent.Event:Connect(function()
__rbxl_inventory_add("key", 1)
__rbxl_show_text("Ты нашёл Ключ!", 2)
pickupSound:Play()
end)
-- Игрок пытается открыть сундук
local openEvent = getEvent("OpenChest")
openEvent.Event:Connect(function()
if won then return end
if not __rbxl_inventory_has("key") then
__rbxl_show_text("Сундук заперт. Сначала найди ключ.", 2)
loseSound:Play()
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)`,
g17_key: `-- === Скрипт ключа (Lua) ===
-- При касании игроком — отправляем событие и удаляем ключ.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local part = script.Parent
local taken = false
part.Touched:Connect(function(hit)
if taken then return end
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
taken = true
local ev = ReplicatedStorage:FindFirstChild("TakeKey")
if ev then ev:Fire() end
part:Destroy()
end)`,
g17_chest: `-- === Скрипт сундука (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("g17_chest_hint", "[E] Открыть сундук", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g17_chest_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("OpenChest")
if ev then ev:Fire() end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 18 — «Качели»
// ═══════════════════════════════════════════════════════════════
'swing': {
g18_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 winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Раскачиваем качели туда-сюда через изменение Position.Z.
-- WaitForChild может зависнуть — берём напрямую с задержкой.
local swing = nil
local startZ = 0
task.delay(0.2, function()
swing = workspace:FindFirstChild("Качели")
if swing then
startZ = swing.Position.Z
end
end)
local elapsed = 0
RunService.Heartbeat:Connect(function(dt)
if won then return end
if not swing then return end
elapsed = elapsed + (dt or 0.016)
-- Синусоидальное качание с амплитудой 4 и периодом ~2.8 сек
local amp = 4
local period = 2.8
local offsetZ = amp * math.sin(elapsed * 2 * math.pi / period)
local pos = swing.Position
swing.Position = Vector3.new(pos.X, pos.Y, startZ + offsetZ)
-- Если упал — респаун
local py = __rbxl_player_y()
if py < -3 then
player:LoadCharacter()
end
end)
-- Финиш сообщает о победе
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)`,
g18_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 19 — «Лифт»
// ═══════════════════════════════════════════════════════════════
'elevator': {
g19_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 winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Лифт ездит вверх-вниз. WaitForChild зависает, поэтому FindFirstChild
-- с задержкой через task.delay.
local lift = nil
local startY = 1
local TOP_Y = 12.3
local PERIOD = 7 -- полный цикл вниз→вверх→вниз (3.5с вверх + 3.5с вниз)
local elapsed = 0
task.delay(0.2, function()
lift = workspace:FindFirstChild("Лифт")
if lift then startY = lift.Position.Y end
end)
RunService.Heartbeat:Connect(function(dt)
if won then return end
dt = dt or 0.016
-- Лифт двигается
if lift then
elapsed = elapsed + dt
-- Yo-yo: 0..PERIOD/2 — вверх, PERIOD/2..PERIOD — вниз
local t = (elapsed % PERIOD) / PERIOD
local k
if t < 0.5 then
k = t * 2 -- 0..1
else
k = (1 - t) * 2 -- 1..0
end
local y = startY + (TOP_Y - startY) * k
local pos = lift.Position
lift.Position = Vector3.new(pos.X, y, pos.Z)
end
-- Падение
local py = __rbxl_player_y()
if py < -3 then
player:LoadCharacter()
end
end)
-- Финиш
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)`,
g19_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 20 — «Имена врагов»
// ═══════════════════════════════════════════════════════════════
'enemy-names': {
g20_main: `-- === ИГРА «ИМЕНА НАД ВРАГАМИ» — главный скрипт (Lua) ===
local UserInputService = game:GetService("UserInputService")
__rbxl_show_text("Победи всех врагов! Кликай по ним", 3)
local hitSound = Instance.new("Sound", workspace)
hitSound.SoundId = "hit"; hitSound.Volume = 0.6
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Данные врагов: имя, позиция, HP
local enemies = {
{ name = "Гоблин", x = -5, z = 3, hp = 60, maxHp = 60, ref = nil },
{ name = "Скелет", x = 4, z = 5, hp = 80, maxHp = 80, ref = nil },
{ name = "Орк", x = 0, z = 8, hp = 100, maxHp = 100, ref = nil },
}
local alive = #enemies
local won = false
-- Спавним всех врагов и метки над ними
for i, e in ipairs(enemies) do
e.ref = __rbxl_spawn_npc("character-b", e.x, 1, e.z, e.name, e.hp, 0)
__rbxl_set_label(e.ref, e.name .. " HP: " .. e.hp, "#ff5555", 2.5)
-- Callback на смерть NPC
__rbxl_npc_on_death(e.ref, function()
if e._dead then return end
e._dead = true
__rbxl_clear_label(e.ref)
alive = alive - 1
hitSound:Play()
if alive <= 0 and not won 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)
end
-- Клик по конкретному NPC (как в Тире — pick по 3D-объекту).
-- BabylonScene выполняет raycast при ЛКМ и шлёт click с target=NPC.
-- Регистрируем callback для каждого врага по его локальному ref.
for _, e in ipairs(enemies) do
local enemy = e -- замыкание
__rbxl_npc_on_click(enemy.ref, function()
if enemy._dead or won then return end
enemy.hp = enemy.hp - 30
if enemy.hp < 0 then enemy.hp = 0 end
__rbxl_npc_damage(enemy.ref, 30)
__rbxl_set_label(enemy.ref, enemy.name .. " HP: " .. enemy.hp, "#ff5555", 2.5)
__rbxl_spawn_particles("sparks", enemy.x, 2, enemy.z, 0.4, 1)
hitSound:Play()
end)
end`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 21 — «Догонялки»
// ═══════════════════════════════════════════════════════════════
'chaser': {
g21_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 = 0.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Спавним NPC-преследователя (speed=4, follow за игроком)
local enemyRef = __rbxl_spawn_npc("character-b", 0, 1, -3, "Охотник", 100, 4)
-- Велим NPC следовать за игроком
__rbxl_npc_follow(enemyRef, "player")
-- Каждый кадр проверяем — не догнал ли враг
local lastCaughtTime = 0
RunService.Heartbeat:Connect(function()
if won then return end
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
local ex = __rbxl_npc_x(enemyRef)
local ez = __rbxl_npc_z(enemyRef)
-- Если позиции NPC ещё не пришли (ex=0,ez=0 = до спавна) — пропускаем
if ex == 0 and ez == 0 then return end
local dx = px - ex
local dz = pz - ez
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 1.6 then
local now = tick()
if now - lastCaughtTime > 2 then
lastCaughtTime = now
player:LoadCharacter()
__rbxl_show_text("Пойман! Беги снова!", 2)
loseSound:Play()
end
end
end)
-- Финиш сообщает о победе
local winEvent = getEvent("WinReached")
winEvent.Event:Connect(function()
if won then return end
won = true
__rbxl_npc_stop(enemyRef)
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)`,
g21_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 22 — «Опасная зона»
// ═══════════════════════════════════════════════════════════════
'danger-zone': {
g22_main: `-- === ИГРА «ЗОНА ОПАСНОСТИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local RunService = game:GetService("RunService")
local inZone = false
local won = false
local damageTimer = 0
__rbxl_show_text("Пробеги через красную зону к финишу!", 3)
local hitSound = Instance.new("Sound", workspace)
hitSound.SoundId = "hit"; hitSound.Volume = 0.6
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Слушатели событий зоны
local enterEvent = getEvent("ZoneEnter")
enterEvent.Event:Connect(function()
inZone = true
__rbxl_show_text("Опасно! Беги быстрее!", 1.5)
end)
local leaveEvent = getEvent("ZoneLeave")
leaveEvent.Event:Connect(function()
inZone = false
end)
-- Урон каждые 0.6с пока игрок в зоне
RunService.Heartbeat:Connect(function(dt)
if won then return end
if not inZone then return end
damageTimer = damageTimer + (dt or 0.016)
if damageTimer >= 0.6 then
damageTimer = 0
__rbxl_damage_player(12)
hitSound:Play()
end
end)
-- Финиш сообщает о победе
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)`,
g22_zone: `-- === Скрипт зоны опасности (Lua) ===
-- Touched при входе, TouchEnded при выходе.
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("ZoneEnter")
if ev then ev:Fire() end
end)
part.TouchEnded:Connect(function(hit)
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
local ev = ReplicatedStorage:FindFirstChild("ZoneLeave")
if ev then ev:Fire() end
end)`,
g22_heal: `-- === Скрипт аптечки (Lua) ===
local part = script.Parent
local taken = false
part.Touched:Connect(function(hit)
if taken then return end
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
taken = true
-- Лечим на 60 HP (через damage с отрицательным значением неудобно;
-- используем напрямую player.Health прибавлением).
__rbxl_heal_player(60)
__rbxl_show_text("+60 HP", 1.5)
local pickupSound = Instance.new("Sound", part)
pickupSound.SoundId = "pickup"; pickupSound.Volume = 0.8
pickupSound:Play()
part:Destroy()
end)`,
g22_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 23 — «3 переключателя»
// ═══════════════════════════════════════════════════════════════
'switches': (function() {
const overrides = {
g23_main: `-- === ИГРА «ПЕРЕКЛЮЧАТЕЛИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local TweenService = game:GetService("TweenService")
local ORDER = { 2, 3, 1 } -- правильный порядок рычагов
local pressed = {}
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.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Рычаги шлют ev:Fire(num) с номером
local leverEvent = getEvent("LeverPulled")
leverEvent.Event:Connect(function(num)
if opened then return end
clickSound:Play()
table.insert(pressed, num)
local i = #pressed
if pressed[i] ~= ORDER[i] then
pressed = {}
__rbxl_show_text("Неверно! Рычаги сброшены.", 1.5)
loseSound:Play()
return
end
if #pressed == #ORDER 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)`,
g23_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)`,
};
// 3 рычага — каждый ждёт E когда игрок рядом, шлёт свой номер
for (let n = 1; n <= 3; n++) {
overrides['g23_lever_' + n] = `-- === Скрипт рычага ${n} (Lua) ===
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 <= 3
if near ~= hintVisible then
hintVisible = near
if near then
__rbxl_hud_set("g23_lever_${n}_hint", "[E] Дёрнуть рычаг ${n}", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g23_lever_${n}_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("LeverPulled")
if ev then ev:Fire(${n}) end
end)`;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 24 — «Падающий мост»
// ═══════════════════════════════════════════════════════════════
'falling-bridge': (function() {
const TILES = 18;
const overrides = {
g24_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 = 0.7
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()
__rbxl_show_text("Упал в пропасть! Снова.", 1.5)
loseSound:Play()
end
end)
-- Финиш сообщает о победе
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)`,
g24_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)`,
};
// 18 досок — каждая при касании играет click и исчезает через 1с
const plankScript = `-- === Скрипт доски моста (Lua) ===
local Debris = game:GetService("Debris")
local part = script.Parent
local cracking = false
local clickSound = Instance.new("Sound", part)
clickSound.SoundId = "click"; clickSound.Volume = 0.5
part.Touched:Connect(function(hit)
if cracking then return end
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
cracking = true
clickSound:Play()
-- через 1 секунду доска пропадает
Debris:AddItem(part, 1)
end)`;
for (let i = 1; i <= TILES; i++) {
overrides['g24_plank_' + i] = plankScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 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: явных Lua-версий пока нет.
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua
// (главный скрипт → показ подсказки + слушает FinishReached →
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;
// остальные target-скрипты → красят примитив на касание).
// Это даёт «хоть что-то рабочее» в любой игре до того как напишем
// полноценный Lua-скрипт. Когда дописываем игру — добавляем сюда явный override.
'clicker': { g46_main: simpleClicker() },
};
// ══════════════════════════════════════════════════════════════════
// Хелперы для генерации часто повторяющихся скриптов
// ══════════════════════════════════════════════════════════════════
/** Возвращает 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 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("Кликай ЛКМ — копи клики!")`;
}