studio/src/community/docsGamesBuildersLua.js
min 0fcc5b85d0 docs(37) + feat(g38): «Музыкальная игра»
g37 docs: CodeBoth main+spike_1+cp+finish.

g38 паритет:
- SOUNDS [coin,jump,click,hit], SEQ [1,3,2,4,1]
- task.delay 1 + i*0.8 → play sound + 'Нота N из 5'
- После последней task.delay → canPress=true + 'Повтори!'
- BindableEvent NotePressed(n)
- 4 g38_tile_N: Heartbeat distance(3) → '[E] Сыграть ноту'
  E → tileSound + sparks + NotePressed:Fire(n)
- Правильная → playerStep++, при #SEQ → win + confetti
- Ошибка → playerStep=0 + lose + 'Слушай снова'
2026-06-09 22:35:40 +03:00

3575 lines
139 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) ===
${SNIPPET_BROADCAST}
local won = false
-- При старте — облёт уровня камерой по точкам.
-- 1-й arg — путь камеры (4 точки x,y,z),
-- 2-й — длительность одного отрезка,
-- 3-й — куда камера смотрит в каждой точке (тоже 4 точки).
__rbxl_camera_cutscene(
"0,18,-10, 12,12,8, -12,12,18, 0,10,28", 1.8,
"0,2,8, 0,2,14, 0,2,20, 0,2,27"
)
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Когда облёт закончился — отдаём камеру игроку и пишем подсказку
__rbxl_on_cutscene_done(function()
__rbxl_show_text("Вперёд, к зелёному финишу!", 3)
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)`,
g25_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 26 — «Магнит монет»
// ═══════════════════════════════════════════════════════════════
'coin-magnet': (function() {
const TOTAL = 8;
const overrides = {
g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local TOTAL = ${TOTAL}
local score = 0
__rbxl_score_set(0)
__rbxl_show_text("Подходи к монеткам — они притянутся!", 3)
local coinSound = Instance.new("Sound", workspace)
coinSound.SoundId = "coin"; coinSound.Volume = 0.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Монетки шлют ev:Fire() при сборе
local coinEvent = getEvent("CoinCollected")
coinEvent.Event:Connect(function()
score = score + 1
__rbxl_score_set(score)
coinSound:Play()
if score >= TOTAL then
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)`,
};
// 8 монеток — каждая со своим Heartbeat: при dist<6 летит к игроку, при dist<1.2 собрана
const coinScript = `-- === Скрипт магнитной монетки (Lua) ===
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local part = script.Parent
local flying = false
local taken = false
RunService.Heartbeat:Connect(function()
if taken then return end
local cp = part.Position
local px = __rbxl_player_x()
local py = __rbxl_player_y()
local pz = __rbxl_player_z()
-- ждём пока позиция игрока придёт
if px == 0 and py == 0 and pz == 0 then return end
local dx = px - cp.X
local dz = pz - cp.Z
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 1.2 then
taken = true
local ev = ReplicatedStorage:FindFirstChild("CoinCollected")
if ev then ev:Fire() end
part:Destroy()
return
end
if not flying and dist < 6 then
flying = true
local goal = { Position = Vector3.new(px, py + 1, pz) }
TweenService:Create(part, TweenInfo.new(0.5), goal):Play()
end
end)`;
for (let i = 1; i <= TOTAL; i++) {
overrides['g26_coin_' + i] = coinScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 27 — «Двойной прыжок»
// ═══════════════════════════════════════════════════════════════
'double-jump': {
g27_main: `-- === ИГРА «ДВОЙНОЙ ПРЫЖОК» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local won = false
-- Включаем игроку двойной прыжок — теперь можно прыгнуть ещё раз в воздухе
__rbxl_set_double_jump(true)
__rbxl_show_text("Жми Space ДВАЖДЫ — двойной прыжок!", 4)
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()
loseSound:Play()
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)`,
g27_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)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 28 — «Призрачные стены»
// ═══════════════════════════════════════════════════════════════
'ghost-walls': (function() {
const WALL_IDS = [1, 2, 3, 4];
const overrides = {
g28_main: `-- === ИГРА «ПРИЗРАЧНЫЕ СТЕНЫ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local won = false
__rbxl_show_text("Кликай по фиолетовым стенам — пройди сквозь!", 4)
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Финиш сообщает о победе
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)`,
g28_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 фиолетовые стены — клик через ClickDetector делает стену проходимой
const wallScript = `-- === Скрипт призрачной стены (Lua) ===
local part = script.Parent
local ghost = false
local clickSound = Instance.new("Sound", part)
clickSound.SoundId = "click"; clickSound.Volume = 0.7
-- ClickDetector — даёт стене кликабельность (как в игре «Тир»)
local cd = Instance.new("ClickDetector")
cd.Parent = part
cd.MouseClick:Connect(function()
if ghost then return end
ghost = true
part.CanCollide = false
part.Transparency = 0.75
clickSound:Play()
__rbxl_show_text("Стена стала призрачной!", 1.5)
end)`;
for (const wid of WALL_IDS) {
overrides['g28_wall_' + wid] = wallScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 29 — «Магазин»
// ═══════════════════════════════════════════════════════════════
'shop': (function() {
const COIN_IDS = [1, 2, 3, 4, 5, 6, 7];
const overrides = {
g29_main: `-- === ИГРА «МАГАЗИН» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local TweenService = game:GetService("TweenService")
local PRICE = 5
local coins = 0
local bought = false
local hasKey = false
local doorOpen = false
local won = false
__rbxl_score_set(0)
__rbxl_show_text("Собери монетки и купи ключ у продавца!", 4)
local coinSound = Instance.new("Sound", workspace)
coinSound.SoundId = "coin"; coinSound.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
-- Сбор монетки
local coinEvent = getEvent("CoinCollected")
coinEvent.Event:Connect(function()
coins = coins + 1
__rbxl_score_set(coins)
coinSound:Play()
end)
-- Покупка ключа у прилавка
local buyEvent = getEvent("BuyKey")
buyEvent.Event:Connect(function()
if bought then
__rbxl_show_text("Ключ уже куплен, иди к двери!", 2)
return
end
if coins < PRICE then
__rbxl_show_text("Мало монет! Нужно " .. PRICE .. ", есть " .. coins, 2)
loseSound:Play()
return
end
bought = true
hasKey = true
coins = coins - PRICE
__rbxl_score_set(coins)
__rbxl_inventory_define("key", "Ключ", "#ffd700")
__rbxl_inventory_add("key", 1)
__rbxl_show_text("Куплен Ключ! Открой дверь.", 3)
winSound:Play()
end)
-- Открытие двери
local doorEvent = getEvent("OpenDoor")
doorEvent.Event:Connect(function()
if doorOpen then return end
if not hasKey then
__rbxl_show_text("Дверь заперта. Купи ключ в магазине.", 2)
return
end
doorOpen = true
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
__rbxl_show_text("Дверь открыта!", 2)
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)`,
g29_shop: `-- === Скрипт прилавка (Lua) ===
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local part = script.Parent
local hintVisible = false
-- Спавним продавца ЗА прилавком (z=5 → z=6)
local sellerRef = __rbxl_spawn_npc("character-a", 0, 1.6, 6, "Продавец", 100, 0)
task.delay(0.3, function()
__rbxl_set_label(sellerRef, "Продавец", "#ffe44a", 2.5)
end)
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("g29_shop_hint", "[E] Купить ключ (5 монет)", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g29_shop_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("BuyKey")
if ev then ev:Fire() end
end)`,
g29_door: `-- === Скрипт двери (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 <= 4
if near ~= hintVisible then
hintVisible = near
if near then
__rbxl_hud_set("g29_door_hint", "[E] Открыть дверь", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g29_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)`,
g29_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)`,
};
// 7 монеток — Touched → CoinCollected:Fire + Destroy
const coinScript = `-- === Скрипт монетки (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("CoinCollected")
if ev then ev:Fire() end
part:Destroy()
end)`;
for (const cid of COIN_IDS) {
overrides['g29_coin_' + cid] = coinScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 30 — «Квесты»
// ═══════════════════════════════════════════════════════════════
'quest-tasks': {
g30_main: `-- === ИГРА «КВЕСТ С ЗАДАНИЯМИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local stage = 0 -- 0=не начат, 1=собрать монетку, 2=дойти до флага, 3=вернуться, 4=готово
local function setObjective(text, color)
__rbxl_hud_set("objective", "ЦЕЛЬ: " .. text, 50, 8, color or "#ffe066", 24)
end
setObjective("подойди к квестодателю и нажми E")
-- Спавним NPC рядом с тумбой (NPC = квестодатель)
local npcRef = __rbxl_spawn_npc("character-a", 1.5, 1, 2, "Старейшина", 100, 0)
local coinSound = Instance.new("Sound", workspace)
coinSound.SoundId = "coin"; coinSound.Volume = 0.7
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
-- Поговорить с NPC
local talkEvent = getEvent("Talk")
talkEvent.Event:Connect(function()
if stage == 0 then
stage = 1
__rbxl_npc_say(npcRef, "Задание 1: найди жёлтую монетку!", 4)
setObjective("собери жёлтую монетку (слева)")
elseif stage == 3 then
stage = 4
__rbxl_npc_say(npcRef, "Молодец! Квест выполнен!", 4)
__rbxl_hud_set("objective", "КВЕСТ ПРОЙДЕН!", 50, 8, "#22dd55", 26)
__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)
elseif stage == 4 then
__rbxl_npc_say(npcRef, "Спасибо, герой!", 3)
elseif stage == 1 then
__rbxl_npc_say(npcRef, "Ты ещё не собрал монетку!", 3)
elseif stage == 2 then
__rbxl_npc_say(npcRef, "Сначала дойди до синего флага!", 3)
end
end)
-- Монетка собрана
local coinEvent = getEvent("CoinDone")
coinEvent.Event:Connect(function()
if stage ~= 1 then return end
stage = 2
coinSound:Play()
__rbxl_npc_say(npcRef, "Отлично! Теперь дойди до синего флага.", 4)
__rbxl_show_text("Монетка собрана!", 2)
setObjective("дойди до синего флага (справа)")
end)
-- Флаг достигнут
local flagEvent = getEvent("FlagDone")
flagEvent.Event:Connect(function()
if stage ~= 2 then return end
stage = 3
pickupSound:Play()
__rbxl_show_text("Флаг найден!", 2)
setObjective("вернись к квестодателю и нажми E")
end)`,
g30_npc: `-- === Скрипт квестодателя (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 <= 4
if near ~= hintVisible then
hintVisible = near
if near then
__rbxl_hud_set("g30_npc_hint", "[E] Поговорить", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g30_npc_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("Talk")
if ev then ev:Fire() end
end)`,
g30_coin: `-- === Скрипт квест-монетки (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("CoinDone")
if ev then ev:Fire() end
part:Destroy()
end)`,
g30_flag: `-- === Скрипт квест-флага (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("FlagDone")
if ev then ev:Fire() end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 31 — «Защита базы»
// ═══════════════════════════════════════════════════════════════
'base-defense': {
g31_main: `-- === ИГРА «ЗАЩИТА БАЗЫ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local killed = 0
local leaked = 0
local total = 0
local over = false
local GOAL = 12
local MAX_LEAK = 5
__rbxl_score_set(0)
__rbxl_show_text("Защити базу! Кликай по врагам", 3)
local hitSound = Instance.new("Sound", workspace)
hitSound.SoundId = "hit"; hitSound.Volume = 0.6
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
-- Все живые враги: { ref, dead }
local enemies = {}
-- Клик по NPC (target.kind=npc) — наносим урон ближайшему в радиусе 5
local clickEvent = getEvent("EnemyClicked")
clickEvent.Event:Connect(function(localRef)
if over then return end
for _, e in ipairs(enemies) do
if not e.dead and e.ref == localRef then
-- Проверка расстояния (в радиусе 5)
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
local ex = __rbxl_npc_x(e.ref)
local ez = __rbxl_npc_z(e.ref)
local dx = px - ex
local dz = pz - ez
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 5 then
e.dead = true
__rbxl_spawn_particles("explosion", ex, 2, ez, 0.4, 1)
__rbxl_npc_remove(e.ref)
hitSound:Play()
killed = killed + 1
__rbxl_score_set(killed)
if killed >= GOAL and not over then
over = true
winSound:Play()
__rbxl_show_text("Победа! База защищена!", 5)
local px2 = __rbxl_player_x()
local py2 = __rbxl_player_y()
local pz2 = __rbxl_player_z()
__rbxl_spawn_particles("confetti", px2, py2 + 3, pz2, 3, 3)
end
end
return
end
end
end)
-- Регистрируем общий callback на клик по NPC — он шлёт ref в общий event
-- (фейерим один раз — при появлении каждого врага зовём __rbxl_npc_on_click)
-- Спавн врага каждые 2 секунды
local spawnTimer = 0
RunService.Heartbeat:Connect(function(dt)
if over then return end
if total >= GOAL + MAX_LEAK then return end
spawnTimer = spawnTimer + dt
if spawnTimer >= 2 then
spawnTimer = 0
total = total + 1
local x = math.random(-8, 8)
local ref = __rbxl_spawn_npc("character-b", x, 1, 38, "Враг", 30, 2.5)
local e = { ref = ref, dead = false }
table.insert(enemies, e)
-- Отложим moveTo пока NPC создастся
task.delay(0.3, function()
__rbxl_npc_moveto(ref, 0, 2)
end)
-- Клик по этому NPC → шлём в общий event
__rbxl_npc_on_click(ref, function()
local ev = game:GetService("ReplicatedStorage"):FindFirstChild("EnemyClicked")
if ev then ev:Fire(ref) end
end)
end
end)
-- Проверка прорыва каждые 0.4с
local leakTimer = 0
RunService.Heartbeat:Connect(function(dt)
if over then return end
leakTimer = leakTimer + dt
if leakTimer < 0.4 then return end
leakTimer = 0
for _, e in ipairs(enemies) do
if not e.dead then
local ez = __rbxl_npc_z(e.ref)
local ex = __rbxl_npc_x(e.ref)
-- ez=0 ex=0 пока NPC не зарезолвлен — пропускаем
if not (ex == 0 and ez == 0) and ez < 4 then
e.dead = true
__rbxl_npc_remove(e.ref)
leaked = leaked + 1
loseSound:Play()
__rbxl_show_text("Враг прорвался! (" .. leaked .. "/" .. MAX_LEAK .. ")", 2)
if leaked >= MAX_LEAK and not over then
over = true
__rbxl_show_text("База разрушена! Поражение.", 5)
end
end
end
end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 32 — «Гонка с кругами»
// ═══════════════════════════════════════════════════════════════
'lap-race': (function() {
const CP_COUNT = 4;
const overrides = {
g32_main: `-- === ИГРА «ГОНКА С КРУГАМИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local RunService = game:GetService("RunService")
local LAPS = 2
local CP_COUNT = ${CP_COUNT}
local nextCp = 0
local lap = 0
local time = 0
local won = false
__rbxl_timer_set(0)
__rbxl_show_text("Проедь 2 круга через чекпоинты!", 3)
local clickSound = Instance.new("Sound", workspace)
clickSound.SoundId = "click"; clickSound.Volume = 0.6
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
local function updateProgress()
__rbxl_hud_set("race",
"Круг " .. (lap + 1) .. "/" .. LAPS .. " • чекпоинт " .. (nextCp + 1) .. "/" .. CP_COUNT,
50, 8, "#ffe066", 22)
end
updateProgress()
-- Таймер каждый кадр
RunService.Heartbeat:Connect(function(dt)
if won then return end
time = time + dt
__rbxl_timer_set(time)
end)
-- Чекпоинты шлют CheckpointReached:Fire(num)
local cpEvent = getEvent("CheckpointReached")
cpEvent.Event:Connect(function(num)
if won then return end
if num - 1 ~= nextCp then return end
clickSound:Play()
nextCp = nextCp + 1
if nextCp >= CP_COUNT then
nextCp = 0
lap = lap + 1
if lap >= LAPS then
won = true
local t = math.floor(time * 10) / 10
__rbxl_hud_set("race", "ФИНИШ! " .. t .. " сек", 50, 8, "#22dd55", 24)
__rbxl_show_text("Финиш! Круги пройдены за " .. t .. " сек", 6)
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)
else
__rbxl_show_text("Круг " .. lap .. " из " .. LAPS .. "!", 2)
updateProgress()
end
else
updateProgress()
end
end)`,
};
// 4 чекпоинта — Touched → CheckpointReached:Fire(num)
for (let i = 1; i <= CP_COUNT; i++) {
overrides['g32_cp_' + i] = `-- === Скрипт чекпоинта ${i} (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("CheckpointReached")
if ev then ev:Fire(${i}) end
end)`;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 33 — «Платформер с боссом»
// ═══════════════════════════════════════════════════════════════
'boss-platformer': {
g33_main: `-- === ИГРА «ПЛАТФОРМЕР С БОССОМ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local won = false
local bossSpawned = false
local bossHp = 120
local MAX_HP = 120
local bossRef = nil
__rbxl_show_text("Пройди паркур до арены босса!", 3)
local hitSound = Instance.new("Sound", workspace)
hitSound.SoundId = "hit"; hitSound.Volume = 0.6
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
-- Клик по боссу (через __rbxl_npc_on_click при спавне)
local function onBossHit()
if won then return end
local pp_x = __rbxl_player_x()
local pp_z = __rbxl_player_z()
local bp_x = __rbxl_npc_x(bossRef)
local bp_z = __rbxl_npc_z(bossRef)
local dx = pp_x - bp_x
local dz = pp_z - bp_z
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 5 then
bossHp = bossHp - 20
if bossHp < 0 then bossHp = 0 end
__rbxl_npc_damage(bossRef, 20)
__rbxl_set_label(bossRef, "БОСС HP: " .. bossHp, "#ff3333", 2.5)
__rbxl_spawn_particles("sparks", bp_x, 2, bp_z, 0.4, 1)
hitSound:Play()
end
end
-- Heartbeat: респаун при падении + спавн босса при подходе к арене
RunService.Heartbeat:Connect(function()
if won then return end
local py = __rbxl_player_y()
if py < -3 then
player:LoadCharacter()
loseSound:Play()
return
end
if not bossSpawned then
local pz = __rbxl_player_z()
if pz > 24 and py > 5 then
bossSpawned = true
bossRef = __rbxl_spawn_npc("character-b", 0, 7, 32, "БОСС", MAX_HP, 2)
task.delay(0.3, function()
__rbxl_npc_follow(bossRef, "player")
__rbxl_set_label(bossRef, "БОСС HP: " .. MAX_HP, "#ff3333", 2.5)
end)
__rbxl_show_text("БОСС! Кликай по нему!", 3)
-- Подписка на клик по боссу
__rbxl_npc_on_click(bossRef, onBossHit)
-- Подписка на смерть
__rbxl_npc_on_death(bossRef, function()
if won then return end
won = true
__rbxl_clear_label(bossRef)
__rbxl_show_text("Победа! Босс повержен!", 5)
winSound:Play()
local px = __rbxl_player_x()
local py2 = __rbxl_player_y()
local pz2 = __rbxl_player_z()
__rbxl_spawn_particles("confetti", px, py2 + 3, pz2, 3, 3)
end)
end
end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 34 — «Сбор урожая»
// ═══════════════════════════════════════════════════════════════
'harvest': (function() {
const PLANT_COUNT = 6;
const overrides = {
g34_main: `-- === ИГРА «СБОР УРОЖАЯ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local GOAL = ${PLANT_COUNT}
local harvested = 0
__rbxl_score_set(0)
__rbxl_show_text("Дождись, пока растения вырастут, и собери!", 4)
local coinSound = Instance.new("Sound", workspace)
coinSound.SoundId = "coin"; coinSound.Volume = 0.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
local ev = getEvent("Harvested")
ev.Event:Connect(function()
harvested = harvested + 1
__rbxl_score_set(harvested)
coinSound:Play()
if harvested >= GOAL then
__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
end)`,
};
// 6 растений — растут 5с (TweenService size+y), потом ripe, E собирает
const plantScript = `-- === Скрипт растения (Lua) ===
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local part = script.Parent
local ripe = false
local picked = false
local hintVisible = false
-- Растение растёт 5 секунд (size + y чтобы низ оставался на земле)
local goal = {
Size = Vector3.new(1.3, 2.6, 1.3),
Position = Vector3.new(part.Position.X, 2.3, part.Position.Z),
}
local tween = TweenService:Create(part, TweenInfo.new(5), goal)
tween:Play()
tween.Completed:Connect(function()
ripe = true
part.Color = Color3.fromRGB(255, 204, 51) -- спелое жёлтое
end)
-- Подсказка [E] Собрать когда близко
RunService.Heartbeat:Connect(function()
if picked 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 <= 3
if near ~= hintVisible then
hintVisible = near
local hid = "g34_plant_" .. part.Name .. "_hint"
if near then
__rbxl_hud_set(hid, "[E] Собрать", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set(hid, 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
if picked then return end
if not ripe then
__rbxl_show_text("Ещё не выросло! Подожди.", 1.5)
return
end
picked = true
-- Скрыть подсказку
__rbxl_hud_set("g34_plant_" .. part.Name .. "_hint", nil)
local ev = ReplicatedStorage:FindFirstChild("Harvested")
if ev then ev:Fire() end
part:Destroy()
end)`;
for (let i = 1; i <= PLANT_COUNT; i++) {
overrides['g34_plant_' + i] = plantScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 35 — «Прятки от NPC»
// ═══════════════════════════════════════════════════════════════
'hide-from-npc': {
g35_main: `-- === ИГРА «ПРЯТКИ ОТ NPC» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local SURVIVE = 40
local time = 0
local won = false
local lastCaughtTime = 0
__rbxl_timer_set(0)
__rbxl_show_text("Прячься за стенами 40 секунд!", 4)
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-искатель ходит за игроком
local seekerRef = __rbxl_spawn_npc("character-b", 0, 1, 10, "Искатель", 100, 3)
task.delay(0.3, function()
__rbxl_npc_follow(seekerRef, "player")
end)
RunService.Heartbeat:Connect(function(dt)
if won then return end
time = time + dt
__rbxl_timer_set(time)
-- Поймал — респаун
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
local ex = __rbxl_npc_x(seekerRef)
local ez = __rbxl_npc_z(seekerRef)
if not (ex == 0 and ez == 0) then
local dx = px - ex
local dz = pz - ez
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 1.7 then
local now = tick()
if now - lastCaughtTime > 2 then
lastCaughtTime = now
player:LoadCharacter()
__rbxl_show_text("Найден! Прячься снова!", 1.5)
loseSound:Play()
end
end
end
-- Продержался 40 секунд — победа
if time >= SURVIVE then
won = true
__rbxl_npc_stop(seekerRef)
__rbxl_show_text("Победа! Ты прятался 40 секунд!", 5)
winSound:Play()
__rbxl_spawn_particles("confetti", px, 1, pz, 3, 3)
end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРА 36 — «Головоломка с ящиками»
// ═══════════════════════════════════════════════════════════════
'box-puzzle': (function() {
const BOX_COUNT = 3;
const overrides = {
g36_main: `-- === ИГРА «ГОЛОВОЛОМКА С ЯЩИКАМИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local onPlate = { false, false, false }
local won = false
__rbxl_show_text("Поставь все 3 ящика на зелёные плиты!", 4)
local clickSound = Instance.new("Sound", workspace)
clickSound.SoundId = "click"; clickSound.Volume = 0.6
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- Ящики шлют BoxMoved:Fire(i, on)
local boxEvent = getEvent("BoxMoved")
boxEvent.Event:Connect(function(i, on)
onPlate[i] = on
if on then clickSound:Play() end
if not won and onPlate[1] and onPlate[2] and onPlate[3] then
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
end)`,
};
// 3 ящика — E двигает по ряду Z=[-6,-3,0,3,6], плита на z=6
for (let i = 1; i <= BOX_COUNT; i++) {
overrides['g36_box_' + i] = `-- === Скрипт ящика ${i} (Lua) ===
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local part = script.Parent
local ROW = { -6, -3, 0, 3, 6 }
local PLATE_Z = 6
local cell = 1
local hintVisible = false
local moving = 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("g36_box_${i}_hint", "[E] Двинуть ящик", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g36_box_${i}_hint", nil)
end
end
end)
UserInputService.InputBegan:Connect(function(input, gp)
if gp then return end
if not hintVisible then return end
if moving then return end
if input.KeyCode ~= Enum.KeyCode.E then return end
cell = cell + 1
if cell > #ROW then cell = 1 end
local newZ = ROW[cell]
moving = true
local goal = { Position = Vector3.new(part.Position.X, part.Position.Y, newZ) }
local tween = TweenService:Create(part, TweenInfo.new(0.4), goal)
tween:Play()
tween.Completed:Connect(function() moving = false end)
local ev = ReplicatedStorage:FindFirstChild("BoxMoved")
if ev then ev:Fire(${i}, newZ == PLATE_Z) end
end)`;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 37 — «Полоса препятствий»
// ═══════════════════════════════════════════════════════════════
'obstacle-course': (function() {
const SPIKE_IDS = [1, 2, 3, 4, 5, 6]; // id 1-6 — шипы
const overrides = {
g37_main: `-- === ИГРА «ПОЛОСА ПРЕПЯТСТВИЙ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local won = false
__rbxl_show_text("Пройди полосу: шипы, ямы, платформа!", 4)
local loseSound = Instance.new("Sound", workspace)
loseSound.SoundId = "lose"; loseSound.Volume = 0.7
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
-- Движущаяся платформа: tween yoyo x: -0.5 ↔ 3, 2с
task.delay(0.2, function()
local mover = workspace:FindFirstChild("ДвижПлатформа")
if mover then
local mp = mover.Position
local startX = mp.X
local function loopMove()
local g1 = { Position = Vector3.new(3, mp.Y, mp.Z) }
local t1 = TweenService:Create(mover, TweenInfo.new(2), g1)
t1:Play()
t1.Completed:Connect(function()
local g2 = { Position = Vector3.new(startX, mp.Y, mp.Z) }
local t2 = TweenService:Create(mover, TweenInfo.new(2), g2)
t2:Play()
t2.Completed:Connect(loopMove)
end)
end
loopMove()
end
end)
-- Респаун при падении
RunService.Heartbeat:Connect(function()
if won then return end
local py = __rbxl_player_y()
if py < -3 then
player:LoadCharacter()
loseSound:Play()
end
end)
-- Чекпоинт — обновляем точку возрождения
local cpEvent = getEvent("CheckpointReached")
cpEvent.Event:Connect(function()
__rbxl_set_spawn(-0.5, 1, 24)
__rbxl_show_text("Чекпоинт сохранён!", 2)
pickupSound:Play()
end)
-- Финиш
local winEvent = getEvent("FinishReached")
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)`,
g37_cp: `-- === Скрипт чекпоинта (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("CheckpointReached")
if ev then ev:Fire() end
end)`,
g37_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)`,
};
// Шипы — Touched → damage 25 + hit
const spikeScript = `-- === Скрипт шипа (Lua) ===
local part = script.Parent
local lastHit = 0
local hitSound = Instance.new("Sound", part)
hitSound.SoundId = "hit"; hitSound.Volume = 0.6
part.Touched:Connect(function(hit)
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
local now = tick()
if now - lastHit < 0.5 then return end -- i-frames
lastHit = now
__rbxl_damage_player(25)
hitSound:Play()
end)`;
for (const sid of SPIKE_IDS) {
overrides['g37_spike_' + sid] = spikeScript;
}
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРА 38 — «Музыкальная игра»
// ═══════════════════════════════════════════════════════════════
'music-game': (function() {
const TILES = [
{ snd: 'coin', color: '#e23b3b' },
{ snd: 'jump', color: '#facc15' },
{ snd: 'click', color: '#22c55e' },
{ snd: 'hit', color: '#3b82f6' },
];
const overrides = {
g38_main: `-- === ИГРА «МУЗЫКАЛЬНАЯ ИГРА» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local SOUNDS = { "coin", "jump", "click", "hit" }
local SEQ = { 1, 3, 2, 4, 1 }
local playerStep = 0
local won = false
local canPress = false
__rbxl_show_text("Слушай мелодию, потом повтори!", 3)
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
local loseSound = Instance.new("Sound", workspace)
loseSound.SoundId = "lose"; loseSound.Volume = 0.7
-- Проигрываем мелодию: нота за нотой каждые 0.8 сек
for i, note in ipairs(SEQ) do
task.delay(1 + (i - 1) * 0.8, function()
local s = Instance.new("Sound", workspace)
s.SoundId = SOUNDS[note]; s.Volume = 0.8
s:Play()
__rbxl_show_text("Нота " .. i .. " из " .. #SEQ, 0.7)
task.delay(0.6, function() s:Destroy() end)
end)
end
-- После мелодии разрешаем игроку
task.delay(1 + #SEQ * 0.8 + 0.5, function()
canPress = true
__rbxl_show_text("Теперь повтори мелодию!", 3)
end)
-- Плитки шлют NotePressed:Fire(n)
local pressEvent = getEvent("NotePressed")
pressEvent.Event:Connect(function(n)
if won or not canPress then return end
if n == SEQ[playerStep + 1] then
playerStep = playerStep + 1
if playerStep >= #SEQ then
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
else
playerStep = 0
__rbxl_show_text("Ошибка! Слушай и пробуй снова.", 2)
loseSound:Play()
end
end)`,
};
// 4 плитки — E проигрывает звук + sparks + NotePressed:Fire(n)
TILES.forEach((t, idx) => {
const n = idx + 1;
overrides['g38_tile_' + 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
local tileSound = Instance.new("Sound", part)
tileSound.SoundId = "${t.snd}"; tileSound.Volume = 0.8
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("g38_tile_${n}_hint", "[E] Сыграть ноту", 50, 75, "#ffe44a", 20)
else
__rbxl_hud_set("g38_tile_${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
tileSound:Play()
__rbxl_spawn_particles("sparks", part.Position.X, part.Position.Y + 1, part.Position.Z, 0.4, 1)
local ev = ReplicatedStorage:FindFirstChild("NotePressed")
if ev then ev:Fire(${n}) end
end)`;
});
return overrides;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРЫ 39-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("Кликай ЛКМ — копи клики!")`;
}