JS-версия имела:
- ui.showText('Допрыгай до зелёной площадки!', 3)
- onTick: y<-3 → respawn + 'Упал!' + sound 'lose'
- broadcast 'finish' → 'Победа!' + sound 'win' + конфетти
- finish-зона: onTouch → broadcast 'finish'
Lua-версия (паритет):
- ScreenGui подсказка 'Допрыгай до зелёной площадки!' на 3с
- RunService.Heartbeat: hrp.Y < -3 → player:LoadCharacter() + Sound
'lose' + красный TextLabel 'Упал! Пробуй снова.' на 1.5с
- BindableEvent FinishReached в ReplicatedStorage
- g2_finish: Touched на финиш-зоне → ev:Fire (только 1 раз через fired-флаг)
- g2_main: FinishReached → Sound 'win' + зелёный 'Победа! Ты дошёл до финиша!'
Юзер: открой копию ЗАНОВО на Lua — старый проект 2908 был со старым
кодом (только print), новая копия получит обновлённые скрипты.
1103 lines
52 KiB
JavaScript
1103 lines
52 KiB
JavaScript
/**
|
||
* 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
|
||
|
||
-- Подсказка по центру (на 3 секунды)
|
||
local hintGui = Instance.new("ScreenGui", player.PlayerGui)
|
||
hintGui.Name = "Hint"
|
||
local hint = Instance.new("TextLabel", hintGui)
|
||
hint.Size = UDim2.new(0, 480, 0, 60)
|
||
hint.Position = UDim2.new(0.5, -240, 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.Font = Enum.Font.SourceSansBold
|
||
hint.Text = "Допрыгай до зелёной площадки!"
|
||
task.delay(3, function() hintGui:Destroy() end)
|
||
|
||
-- Звуки
|
||
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()
|
||
local fallGui = Instance.new("ScreenGui", player.PlayerGui)
|
||
local fallLabel = Instance.new("TextLabel", fallGui)
|
||
fallLabel.Size = UDim2.new(0, 400, 0, 60)
|
||
fallLabel.Position = UDim2.new(0.5, -200, 0.35, 0)
|
||
fallLabel.BackgroundColor3 = Color3.fromRGB(120, 0, 0)
|
||
fallLabel.BackgroundTransparency = 0.3
|
||
fallLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
||
fallLabel.TextScaled = true
|
||
fallLabel.Font = Enum.Font.SourceSansBold
|
||
fallLabel.Text = "Упал! Пробуй снова."
|
||
task.delay(1.5, function() fallGui:Destroy() end)
|
||
end
|
||
end)
|
||
|
||
-- Финиш-зона шлёт BindableEvent
|
||
local finishEvent = getEvent("FinishReached")
|
||
finishEvent.Event:Connect(function()
|
||
if won then return end
|
||
won = true
|
||
winSound:Play()
|
||
local winGui = Instance.new("ScreenGui", player.PlayerGui)
|
||
local winLabel = Instance.new("TextLabel", winGui)
|
||
winLabel.Size = UDim2.new(0, 540, 0, 80)
|
||
winLabel.Position = UDim2.new(0.5, -270, 0.4, 0)
|
||
winLabel.BackgroundColor3 = Color3.fromRGB(0, 120, 0)
|
||
winLabel.BackgroundTransparency = 0.2
|
||
winLabel.TextColor3 = Color3.fromRGB(255, 255, 0)
|
||
winLabel.TextScaled = true
|
||
winLabel.Font = Enum.Font.SourceSansBold
|
||
winLabel.Text = "Победа! Ты дошёл до финиша!"
|
||
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': {
|
||
g3_main: `-- === ИГРА «НЕ УПАДИ» — главный скрипт (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local RunService = game:GetService("RunService")
|
||
|
||
print("Удержись на платформе как можно дольше!")
|
||
|
||
local startTime = tick()
|
||
local alive = true
|
||
|
||
RunService.Heartbeat:Connect(function()
|
||
if not alive then return end
|
||
for _, player in ipairs(Players:GetPlayers()) do
|
||
local char = player.Character
|
||
if char then
|
||
local hrp = char:FindFirstChild("HumanoidRootPart")
|
||
if hrp and hrp.Position.Y < -5 then
|
||
alive = false
|
||
local elapsed = math.floor(tick() - startTime)
|
||
print("Ты упал! Продержался: " .. elapsed .. " сек")
|
||
task.delay(2, function()
|
||
player:LoadCharacter()
|
||
startTime = tick()
|
||
alive = true
|
||
end)
|
||
end
|
||
end
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 4 — «Кнопка и дверь»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'button-door': {
|
||
g4_main: `-- === ИГРА «КНОПКА И ДВЕРЬ» — главный скрипт (Lua) ===
|
||
${SNIPPET_BROADCAST}
|
||
print("Найди кнопку и открой дверь!")
|
||
-- Глобальный канал для оповещения двери
|
||
getEvent("DoorOpen")`,
|
||
g4_button: `-- === Скрипт кнопки (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("DoorOpen")
|
||
if ev then ev:Fire() end
|
||
print("Кнопка нажата!")
|
||
part.Color = Color3.fromRGB(100, 255, 100) -- зелёная
|
||
end)`,
|
||
g4_door: `-- === Скрипт двери (Lua) ===
|
||
local TweenService = game:GetService("TweenService")
|
||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||
local door = script.Parent
|
||
local startPos = door.Position
|
||
|
||
local ev = ReplicatedStorage:WaitForChild("DoorOpen")
|
||
ev.Event:Connect(function()
|
||
-- Поднимаем дверь вверх
|
||
local goal = { Position = startPos + Vector3.new(0, 5, 0) }
|
||
TweenService:Create(door, TweenInfo.new(1), goal):Play()
|
||
door.CanCollide = false
|
||
print("Дверь открыта!")
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 5 — «Лабиринт»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'maze': {
|
||
g5_main: `-- === ИГРА «ЛАБИРИНТ» — главный скрипт (Lua) ===
|
||
print("Найди выход из лабиринта!")`,
|
||
g5_finish: `-- === Финиш лабиринта (Lua) ===
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
print("ПОБЕДА! Ты нашёл выход!")
|
||
h.WalkSpeed = 0
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 6 — «Угадай цвет»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'color-tiles': {
|
||
g6_main: `-- === ИГРА «УГАДАЙ ЦВЕТ» — главный скрипт (Lua) ===
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local colors = { "red", "green", "blue", "yellow" }
|
||
local target = colors[math.random(1, #colors)]
|
||
print("Встань на плитку цвета: " .. target)
|
||
|
||
local ev = getEvent("TileStepped")
|
||
ev.Event:Connect(function(color)
|
||
if color == target then
|
||
print("Верно! +1 очко")
|
||
target = colors[math.random(1, #colors)]
|
||
print("Теперь встань на: " .. target)
|
||
else
|
||
print("Неверно! Нужен " .. target)
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 7 — «Ловишка предметов»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'catch-falling': {
|
||
g7_main: `-- === ИГРА «ЛОВИШКА ПРЕДМЕТОВ» — главный скрипт (Lua) ===
|
||
local Debris = game:GetService("Debris")
|
||
|
||
local score = 0
|
||
local function showScore()
|
||
print("Поймано: " .. score)
|
||
end
|
||
showScore()
|
||
|
||
-- Каждую секунду создаём падающий предмет
|
||
task.spawn(function()
|
||
while true do
|
||
task.wait(1)
|
||
local ball = Instance.new("Part")
|
||
ball.Shape = Enum.PartType.Ball
|
||
ball.Size = Vector3.new(1, 1, 1)
|
||
ball.Position = Vector3.new(math.random(-8, 8), 20, math.random(-8, 8))
|
||
ball.Color = Color3.fromRGB(255, 215, 0)
|
||
ball.Material = Enum.Material.Neon
|
||
ball.Anchored = false
|
||
ball.Parent = workspace
|
||
Debris:AddItem(ball, 10)
|
||
|
||
-- Скрипт на ловлю
|
||
ball.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if h and ball.Parent then
|
||
score = score + 1
|
||
showScore()
|
||
ball:Destroy()
|
||
end
|
||
end)
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 8 — «Беги до финиша»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'run-to-finish': {
|
||
g8_main: `-- === ИГРА «БЕГИ ДО ФИНИША» — главный скрипт (Lua) ===
|
||
print("Беги к зелёной плите!")`,
|
||
g8_finish: `-- === Финишная плита (Lua) ===
|
||
local part = script.Parent
|
||
local won = false
|
||
part.Touched:Connect(function(hit)
|
||
if won then return end
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
won = true
|
||
print("ПОБЕДА! Ты добежал!")
|
||
h.WalkSpeed = 0
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 9 — «Светофор»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'traffic-light': {
|
||
g9_main: `-- === ИГРА «СВЕТОФОР» — главный скрипт (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local RunService = game:GetService("RunService")
|
||
|
||
local isGreen = true
|
||
print("ЗЕЛЁНЫЙ — беги!")
|
||
|
||
-- Каждые 3-5 сек переключаем свет
|
||
task.spawn(function()
|
||
while true do
|
||
task.wait(math.random(3, 5))
|
||
isGreen = not isGreen
|
||
if isGreen then
|
||
print("ЗЕЛЁНЫЙ — беги!")
|
||
else
|
||
print("КРАСНЫЙ — стой!")
|
||
end
|
||
end
|
||
end)
|
||
|
||
-- Следим за движением игрока во время красного
|
||
local lastPos = {}
|
||
RunService.Heartbeat:Connect(function()
|
||
if isGreen then return end
|
||
for _, player in ipairs(Players:GetPlayers()) do
|
||
local char = player.Character
|
||
local hrp = char and char:FindFirstChild("HumanoidRootPart")
|
||
if hrp then
|
||
local prev = lastPos[player]
|
||
if prev and (hrp.Position - prev).Magnitude > 0.5 then
|
||
print(player.Name .. " двигался на красный! Респаун")
|
||
player:LoadCharacter()
|
||
end
|
||
lastPos[player] = hrp.Position
|
||
end
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 10 — «Прыжки на пружинах»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'spring-jump': {
|
||
g10_main: `-- === ИГРА «ПРЫЖКИ НА ПРУЖИНАХ» — главный скрипт (Lua) ===
|
||
print("Прыгай с пружины на пружину до финиша!")`,
|
||
g10_spring: `-- === Скрипт пружины (Lua) ===
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
local hrp = hit.Parent and hit.Parent:FindFirstChild("HumanoidRootPart")
|
||
if h and hrp then
|
||
-- Подбрасываем игрока вверх
|
||
hrp.Velocity = Vector3.new(hrp.Velocity.X, 80, hrp.Velocity.Z)
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 11 — «Эхо» (нажми кнопку → звук)
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'echo-room': {
|
||
g11_main: `-- === ИГРА «ЭХО» (Lua) ===
|
||
print("Касайся блоков — они отвечают звуком!")`,
|
||
g11_block: `-- === Скрипт звукового блока (Lua) ===
|
||
local part = script.Parent
|
||
local lastTouch = 0
|
||
part.Touched:Connect(function(hit)
|
||
local now = tick()
|
||
if now - lastTouch < 0.5 then return end
|
||
lastTouch = now
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
print("Блок " .. part.Name .. " звенит!")
|
||
part.Color = Color3.fromRGB(math.random(0,255), math.random(0,255), math.random(0,255))
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 12 — «Кодовая дверь»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'code-door': {
|
||
g12_main: `-- === ИГРА «КОДОВАЯ ДВЕРЬ» — главный скрипт (Lua) ===
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local correctCode = "1234"
|
||
local currentInput = ""
|
||
|
||
print("Введи код 1234 (касайся кнопок по порядку)")
|
||
|
||
local ev = getEvent("CodeButton")
|
||
ev.Event:Connect(function(digit)
|
||
currentInput = currentInput .. tostring(digit)
|
||
print("Ввод: " .. currentInput)
|
||
if #currentInput == 4 then
|
||
if currentInput == correctCode then
|
||
print("Верно! Дверь открывается")
|
||
local doorEv = getEvent("DoorOpen")
|
||
doorEv:Fire()
|
||
else
|
||
print("Неверный код, попробуй ещё")
|
||
end
|
||
currentInput = ""
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 13 — «Торговец»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'trader': {
|
||
g13_main: `-- === ИГРА «ТОРГОВЕЦ» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
|
||
Players.PlayerAdded:Connect(function(player)
|
||
local stats = Instance.new("Folder", player); stats.Name = "leaderstats"
|
||
local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 10
|
||
end)
|
||
for _, p in ipairs(Players:GetPlayers()) do
|
||
if not p:FindFirstChild("leaderstats") then
|
||
local stats = Instance.new("Folder", p); stats.Name = "leaderstats"
|
||
local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 10
|
||
end
|
||
end
|
||
print("У тебя 10 монет. Купи зелье у торговца!")`,
|
||
g13_npc: `-- === Скрипт торговца (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local player = Players:GetPlayerFromCharacter(hit.Parent)
|
||
if not player then return end
|
||
local stats = player:FindFirstChild("leaderstats")
|
||
if not stats then return end
|
||
if stats['Монеты'].Value >= 5 then
|
||
stats['Монеты'].Value = stats['Монеты'].Value - 5
|
||
local h = hit.Parent:FindFirstChild("Humanoid")
|
||
if h then h.Health = math.min(h.MaxHealth, h.Health + 50) end
|
||
print("Купил зелье! +50 HP. Осталось монет: " .. stats['Монеты'].Value)
|
||
else
|
||
print("Не хватает монет! Нужно 5")
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 14 — «Собери по тегу»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'collect-by-tag': {
|
||
g14_main: `-- === ИГРА «СОБЕРИ ПО ТЕГУ» (Lua) ===
|
||
local CollectionService = game:GetService("CollectionService")
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local total = #CollectionService:GetTagged("звезда")
|
||
local collected = 0
|
||
print("Собери все " .. total .. " звёзд!")
|
||
|
||
local ev = getEvent("StarCollected")
|
||
ev.Event:Connect(function()
|
||
collected = collected + 1
|
||
print("Собрано: " .. collected .. "/" .. total)
|
||
if collected >= total then
|
||
print("ПОБЕДА! Все звёзды собраны!")
|
||
end
|
||
end)`,
|
||
g14_star: `-- === Скрипт звезды (Lua) ===
|
||
local CollectionService = game:GetService("CollectionService")
|
||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||
local part = script.Parent
|
||
CollectionService:AddTag(part, "звезда")
|
||
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
local ev = ReplicatedStorage:FindFirstChild("StarCollected")
|
||
if ev then ev:Fire() end
|
||
part:Destroy()
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 15 — «Тир»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'shooting-range': {
|
||
g15_main: `-- === ИГРА «ТИР» (Lua) ===
|
||
local UserInputService = game:GetService("UserInputService")
|
||
local Players = game:GetService("Players")
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local score = 0
|
||
print("Стреляй ЛКМ по красным шарам!")
|
||
|
||
local ev = getEvent("TargetHit")
|
||
ev.Event:Connect(function()
|
||
score = score + 1
|
||
print("Попал! Очки: " .. score)
|
||
end)
|
||
|
||
-- ЛКМ — пускаем луч из камеры
|
||
UserInputService.InputBegan:Connect(function(input, gp)
|
||
if gp then return end
|
||
if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
||
local player = Players.LocalPlayer
|
||
local mouse = player:GetMouse()
|
||
local target = mouse.Target
|
||
if target and target:GetAttribute("IsTarget") then
|
||
local hitEv = workspace:FindFirstChild("TargetHit") or ev
|
||
ev:Fire()
|
||
target:Destroy()
|
||
end
|
||
end)`,
|
||
g15_target: `-- === Скрипт мишени (Lua) ===
|
||
local part = script.Parent
|
||
part:SetAttribute("IsTarget", true)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 16 — «Лавовый пол»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'lava-floor': {
|
||
g16_main: `-- === ИГРА «ЛАВОВЫЙ ПОЛ» (Lua) ===
|
||
print("Прыгай по островкам, не упади в лаву!")`,
|
||
g16_lava: `-- === Скрипт лавы (Lua) ===
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if h then h.Health = 0 end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 17 — «Ключ от сундука»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'key-chest': {
|
||
g17_main: `-- === ИГРА «КЛЮЧ ОТ СУНДУКА» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
Players.PlayerAdded:Connect(function(player)
|
||
local stats = Instance.new("Folder", player); stats.Name = "leaderstats"
|
||
local key = Instance.new("BoolValue", stats); key.Name = "Ключ"
|
||
end)
|
||
for _, p in ipairs(Players:GetPlayers()) do
|
||
if not p:FindFirstChild("leaderstats") then
|
||
local stats = Instance.new("Folder", p); stats.Name = "leaderstats"
|
||
local key = Instance.new("BoolValue", stats); key.Name = "Ключ"
|
||
end
|
||
end
|
||
print("Найди ключ и открой сундук!")`,
|
||
g17_key: `-- === Скрипт ключа (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local player = Players:GetPlayerFromCharacter(hit.Parent)
|
||
if not player then return end
|
||
local stats = player:FindFirstChild("leaderstats")
|
||
if stats and stats:FindFirstChild("Ключ") then
|
||
stats['Ключ'].Value = true
|
||
print("Подобрал ключ!")
|
||
part:Destroy()
|
||
end
|
||
end)`,
|
||
g17_chest: `-- === Скрипт сундука (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local part = script.Parent
|
||
part.Touched:Connect(function(hit)
|
||
local player = Players:GetPlayerFromCharacter(hit.Parent)
|
||
if not player then return end
|
||
local stats = player:FindFirstChild("leaderstats")
|
||
if stats and stats['Ключ'] and stats['Ключ'].Value then
|
||
print("Сундук открыт! ПОБЕДА!")
|
||
part.Color = Color3.fromRGB(255, 215, 0)
|
||
else
|
||
print("Нужен ключ!")
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 18 — «Качели»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'swing': {
|
||
g18_main: `-- === ИГРА «КАЧЕЛИ» (Lua) ===
|
||
local TweenService = game:GetService("TweenService")
|
||
local swing = workspace:WaitForChild("Качели")
|
||
local startPos = swing.Position
|
||
|
||
-- Качаем туда-сюда бесконечно
|
||
task.spawn(function()
|
||
while true do
|
||
local up = TweenService:Create(swing,
|
||
TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut),
|
||
{ Position = startPos + Vector3.new(0, 0, 5) })
|
||
up:Play(); up.Completed:Wait()
|
||
local down = TweenService:Create(swing,
|
||
TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut),
|
||
{ Position = startPos + Vector3.new(0, 0, -5) })
|
||
down:Play(); down.Completed:Wait()
|
||
end
|
||
end)
|
||
print("Запрыгни на качающуюся платформу!")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 19 — «Лифт»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'elevator': {
|
||
g19_main: `-- === ИГРА «ЛИФТ» (Lua) ===
|
||
local TweenService = game:GetService("TweenService")
|
||
local elevator = workspace:WaitForChild("Лифт")
|
||
local startPos = elevator.Position
|
||
local topPos = startPos + Vector3.new(0, 10, 0)
|
||
|
||
local goingUp = true
|
||
elevator.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
local goal = { Position = goingUp and topPos or startPos }
|
||
TweenService:Create(elevator, TweenInfo.new(3), goal):Play()
|
||
goingUp = not goingUp
|
||
end)
|
||
print("Встань на лифт — он повезёт тебя наверх!")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 20 — «Имена врагов»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'enemy-names': {
|
||
g20_main: `-- === ИГРА «ИМЕНА ВРАГОВ» (Lua) ===
|
||
local function addLabel(part, text, color)
|
||
local bb = Instance.new("BillboardGui", part)
|
||
bb.Size = UDim2.new(4, 0, 1, 0)
|
||
bb.StudsOffset = Vector3.new(0, 2.5, 0)
|
||
bb.AlwaysOnTop = true
|
||
local label = Instance.new("TextLabel", bb)
|
||
label.Size = UDim2.new(1, 0, 1, 0)
|
||
label.BackgroundTransparency = 1
|
||
label.Text = text
|
||
label.TextColor3 = color or Color3.new(1, 1, 1)
|
||
label.TextScaled = true
|
||
end
|
||
|
||
for _, child in ipairs(workspace:GetChildren()) do
|
||
if child:IsA("BasePart") and child.Name:match("^Враг") then
|
||
addLabel(child, child.Name, Color3.fromRGB(255, 80, 80))
|
||
end
|
||
end
|
||
print("Над врагами появились имена")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 21 — «Догонялки»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'chaser': {
|
||
g21_main: `-- === ИГРА «ДОГОНЯЛКИ» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local RunService = game:GetService("RunService")
|
||
|
||
local enemy = workspace:WaitForChild("Догонщик")
|
||
|
||
RunService.Heartbeat:Connect(function(dt)
|
||
local player = Players:GetPlayers()[1]
|
||
if not player or not player.Character then return end
|
||
local target = player.Character:FindFirstChild("HumanoidRootPart")
|
||
if not target then return end
|
||
-- Двигаемся в сторону игрока со скоростью 5
|
||
local dir = (target.Position - enemy.Position)
|
||
if dir.Magnitude > 1 then
|
||
enemy.Position = enemy.Position + dir.Unit * 5 * dt
|
||
else
|
||
-- Поймал
|
||
local h = player.Character:FindFirstChild("Humanoid")
|
||
if h then h:TakeDamage(10) end
|
||
end
|
||
end)
|
||
print("Убегай от догонщика!")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 22 — «Опасная зона»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'danger-zone': {
|
||
g22_main: `-- === ИГРА «ОПАСНАЯ ЗОНА» (Lua) ===
|
||
print("Не стой в красной зоне!")`,
|
||
g22_zone: `-- === Скрипт опасной зоны (Lua) ===
|
||
local part = script.Parent
|
||
local insiders = {}
|
||
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if h then insiders[h] = true end
|
||
end)
|
||
part.TouchEnded:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if h then insiders[h] = nil end
|
||
end)
|
||
|
||
-- Урон каждые 0.5 сек пока стоят
|
||
while true do
|
||
task.wait(0.5)
|
||
for h in pairs(insiders) do
|
||
if h.Parent then h:TakeDamage(5) end
|
||
end
|
||
end`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 23 — «3 переключателя»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'switches': {
|
||
g23_main: `-- === ИГРА «3 ПЕРЕКЛЮЧАТЕЛЯ» (Lua) ===
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local activated = {false, false, false}
|
||
print("Активируй все 3 переключателя!")
|
||
|
||
local ev = getEvent("SwitchToggled")
|
||
ev.Event:Connect(function(idx)
|
||
activated[idx] = true
|
||
print("Переключатель " .. idx .. " активирован")
|
||
if activated[1] and activated[2] and activated[3] then
|
||
print("ПОБЕДА! Все 3 активированы!")
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 24 — «Падающий мост»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'falling-bridge': {
|
||
g24_main: `-- === ИГРА «ПАДАЮЩИЙ МОСТ» (Lua) ===
|
||
print("Беги по мосту — плиты падают!")`,
|
||
g24_plate: `-- === Скрипт падающей плиты (Lua) ===
|
||
local part = script.Parent
|
||
local fell = false
|
||
part.Touched:Connect(function(hit)
|
||
if fell then return end
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
fell = true
|
||
task.delay(0.5, function()
|
||
part.Anchored = false
|
||
part.CanCollide = false
|
||
game:GetService("Debris"):AddItem(part, 3)
|
||
end)
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 25 — «Облёт камеры»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'flyby-camera': {
|
||
g25_main: `-- === ИГРА «ОБЛЁТ КАМЕРЫ» (Lua) ===
|
||
local TweenService = game:GetService("TweenService")
|
||
local camera = workspace.CurrentCamera
|
||
camera.CameraType = Enum.CameraType.Scriptable
|
||
|
||
local points = {
|
||
CFrame.new(Vector3.new(0, 20, -30), Vector3.new(0, 5, 0)),
|
||
CFrame.new(Vector3.new(20, 15, 0), Vector3.new(0, 5, 0)),
|
||
CFrame.new(Vector3.new(0, 25, 30), Vector3.new(0, 5, 0)),
|
||
}
|
||
|
||
for _, cf in ipairs(points) do
|
||
local tween = TweenService:Create(camera, TweenInfo.new(2), { CFrame = cf })
|
||
tween:Play(); tween.Completed:Wait()
|
||
end
|
||
|
||
camera.CameraType = Enum.CameraType.Custom
|
||
print("Облёт окончен — теперь играй!")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 26 — «Магнит монет»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'coin-magnet': {
|
||
g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local RunService = game:GetService("RunService")
|
||
local CollectionService = game:GetService("CollectionService")
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local score = 0
|
||
local ev = getEvent("CoinCollected")
|
||
ev.Event:Connect(function()
|
||
score = score + 1
|
||
print("Собрано: " .. score)
|
||
end)
|
||
|
||
RunService.Heartbeat:Connect(function(dt)
|
||
local player = Players:GetPlayers()[1]
|
||
if not player or not player.Character then return end
|
||
local hrp = player.Character:FindFirstChild("HumanoidRootPart")
|
||
if not hrp then return end
|
||
for _, coin in ipairs(CollectionService:GetTagged("magnetcoin")) do
|
||
local dist = (coin.Position - hrp.Position).Magnitude
|
||
if dist < 8 then
|
||
coin.Position = coin.Position + (hrp.Position - coin.Position).Unit * 20 * dt
|
||
if dist < 1 then
|
||
ev:Fire()
|
||
coin:Destroy()
|
||
end
|
||
end
|
||
end
|
||
end)
|
||
print("Монетки сами летят к тебе!")`,
|
||
g26_coin: `-- === Скрипт магнит-монетки (Lua) ===
|
||
local CollectionService = game:GetService("CollectionService")
|
||
CollectionService:AddTag(script.Parent, "magnetcoin")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 27 — «Двойной прыжок»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'double-jump': {
|
||
g27_main: `-- === ИГРА «ДВОЙНОЙ ПРЫЖОК» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local UserInputService = game:GetService("UserInputService")
|
||
|
||
local function setupDoubleJump(player)
|
||
local jumpsLeft = 2
|
||
local char = player.Character or player.CharacterAdded:Wait()
|
||
local h = char:WaitForChild("Humanoid")
|
||
|
||
-- Восстанавливаем прыжки при касании земли
|
||
h.StateChanged:Connect(function(_, newState)
|
||
if newState == Enum.HumanoidStateType.Landed then
|
||
jumpsLeft = 2
|
||
end
|
||
end)
|
||
|
||
UserInputService.InputBegan:Connect(function(input, gp)
|
||
if gp then return end
|
||
if input.KeyCode == Enum.KeyCode.Space and jumpsLeft > 0 then
|
||
jumpsLeft = jumpsLeft - 1
|
||
if jumpsLeft == 1 then
|
||
local hrp = char:FindFirstChild("HumanoidRootPart")
|
||
if hrp then
|
||
hrp.Velocity = Vector3.new(hrp.Velocity.X, 50, hrp.Velocity.Z)
|
||
end
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
Players.PlayerAdded:Connect(setupDoubleJump)
|
||
for _, p in ipairs(Players:GetPlayers()) do setupDoubleJump(p) end
|
||
print("Жми Space дважды — двойной прыжок!")`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 28 — «Призрачные стены»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'ghost-walls': {
|
||
g28_main: `-- === ИГРА «ПРИЗРАЧНЫЕ СТЕНЫ» (Lua) ===
|
||
print("Некоторые стены — призрачные. Найди проход!")`,
|
||
g28_ghost: `-- === Скрипт призрачной стены (Lua) ===
|
||
local part = script.Parent
|
||
part.CanCollide = false
|
||
part.Transparency = 0.5`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 29 — «Магазин»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'shop': {
|
||
g29_main: `-- === ИГРА «МАГАЗИН» (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
Players.PlayerAdded:Connect(function(player)
|
||
local stats = Instance.new("Folder", player); stats.Name = "leaderstats"
|
||
local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 20
|
||
end)
|
||
for _, p in ipairs(Players:GetPlayers()) do
|
||
if not p:FindFirstChild("leaderstats") then
|
||
local stats = Instance.new("Folder", p); stats.Name = "leaderstats"
|
||
local coins = Instance.new("IntValue", stats); coins.Name = "Монеты"; coins.Value = 20
|
||
end
|
||
end
|
||
print("У тебя 20 монет — купи что-нибудь!")`,
|
||
g29_item: `-- === Скрипт товара (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local part = script.Parent
|
||
local price = part:GetAttribute("Price") or 5
|
||
local bought = false
|
||
|
||
part.Touched:Connect(function(hit)
|
||
if bought then return end
|
||
local player = Players:GetPlayerFromCharacter(hit.Parent)
|
||
if not player then return end
|
||
local stats = player:FindFirstChild("leaderstats")
|
||
if not stats then return end
|
||
if stats['Монеты'].Value >= price then
|
||
stats['Монеты'].Value = stats['Монеты'].Value - price
|
||
bought = true
|
||
print("Куплено! Цена: " .. price)
|
||
part.Transparency = 0.7
|
||
else
|
||
print("Не хватает! Нужно " .. price .. " монет")
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 30 — «Квесты»
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'quest-tasks': {
|
||
g30_main: `-- === ИГРА «КВЕСТЫ» (Lua) ===
|
||
${SNIPPET_BROADCAST}
|
||
|
||
local quests = {
|
||
{ name = "Собери 5 ягод", goal = 5, current = 0 },
|
||
{ name = "Победи врага", goal = 1, current = 0 },
|
||
{ name = "Дойди до башни", goal = 1, current = 0 },
|
||
}
|
||
|
||
print("Квесты:")
|
||
for i, q in ipairs(quests) do print(" " .. i .. ". " .. q.name) end
|
||
|
||
local ev = getEvent("QuestProgress")
|
||
ev.Event:Connect(function(idx, amount)
|
||
quests[idx].current = quests[idx].current + (amount or 1)
|
||
local q = quests[idx]
|
||
print(q.name .. ": " .. q.current .. "/" .. q.goal)
|
||
if q.current >= q.goal then
|
||
print("Квест выполнен: " .. q.name)
|
||
end
|
||
end)`,
|
||
},
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// ИГРА 31-50: упрощённые версии (главные скрипты)
|
||
// ═══════════════════════════════════════════════════════════════
|
||
'base-defense': { g31_main: simpleMain("Защити базу от волн врагов!") },
|
||
'lap-race': { g32_main: simpleMain("Проедь все круги первым!") },
|
||
'boss-platformer': { g33_main: simpleMain("Победи босса прыжками на голову!") },
|
||
'harvest': { g34_main: simpleMain("Собирай урожай, продавай в магазин!") },
|
||
'hide-from-npc': { g35_main: simpleMain("Прячься от NPC — не попадайся!") },
|
||
'box-puzzle': { g36_main: simpleMain("Двигай ящики на места!") },
|
||
'obstacle-course': { g37_main: simpleMain("Пройди полосу препятствий!") },
|
||
'music-game': { g38_main: simpleMain("Жми клавиши в ритм музыки!") },
|
||
'tower-build': { g39_main: simpleMain("Построй самую высокую башню!") },
|
||
'wave-survival': { g40_main: simpleMain("Выживай в волнах врагов!") },
|
||
'adventure-platformer': { g41_main: simpleMain("Приключение — собирай артефакты!") },
|
||
'rpg-village': { g42_main: simpleMain("Бегай по деревне, выполняй квесты!") },
|
||
'obstacle-race': { g43_main: simpleMain("Гонка с препятствиями — финишируй!") },
|
||
'tower-defense': { g44_main: simpleMain("Расставь башни — не пускай врагов!") },
|
||
'arena-shooter': { g45_main: simpleMain("Стреляй по противникам на арене!") },
|
||
'clicker': { g46_main: simpleClicker() },
|
||
'escape-quest': { g47_main: simpleMain("Найди подсказки и выберись!") },
|
||
'mp-tag': { g48_main: simpleMain("Поймай других игроков (мультиплеер)!") },
|
||
'mp-race': { g49_main: simpleMain("Гонка на нескольких игроков!") },
|
||
'make-your-own': { g50_main: simpleMain("Это твоя пустая площадка — твори!") },
|
||
};
|
||
|
||
// ══════════════════════════════════════════════════════════════════
|
||
// Хелперы для генерации часто повторяющихся скриптов
|
||
// ══════════════════════════════════════════════════════════════════
|
||
|
||
/** Возвращает Lua-код скрипта монетки. */
|
||
function makeCoinScript() {
|
||
return `-- === Скрипт монетки (Lua) ===
|
||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||
local part = script.Parent
|
||
|
||
part.Touched:Connect(function(hit)
|
||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||
if not h then return end
|
||
local ev = ReplicatedStorage:FindFirstChild("CoinCollected")
|
||
if ev then ev:Fire() end
|
||
part:Destroy()
|
||
end)`;
|
||
}
|
||
|
||
/** Простой главный скрипт со стартовой подсказкой. */
|
||
function simpleMain(message) {
|
||
return `-- === Главный скрипт (Lua) ===
|
||
print("${message.replace(/"/g, '\\"')}")
|
||
-- TODO: эта игра-урок ещё не имеет полной Lua-реализации.
|
||
-- Переключи язык на JS в редакторе, чтобы увидеть рабочую механику.`;
|
||
}
|
||
|
||
/** Кликер. */
|
||
function simpleClicker() {
|
||
return `-- === КЛИКЕР (Lua) ===
|
||
local Players = game:GetService("Players")
|
||
local UserInputService = game:GetService("UserInputService")
|
||
|
||
Players.PlayerAdded:Connect(function(player)
|
||
local stats = Instance.new("Folder", player); stats.Name = "leaderstats"
|
||
local cnt = Instance.new("IntValue", stats); cnt.Name = "Клики"; cnt.Value = 0
|
||
end)
|
||
for _, p in ipairs(Players:GetPlayers()) do
|
||
if not p:FindFirstChild("leaderstats") then
|
||
local stats = Instance.new("Folder", p); stats.Name = "leaderstats"
|
||
local cnt = Instance.new("IntValue", stats); cnt.Name = "Клики"; cnt.Value = 0
|
||
end
|
||
end
|
||
|
||
local function onClick(player)
|
||
local stats = player:FindFirstChild("leaderstats")
|
||
if stats and stats:FindFirstChild("Клики") then
|
||
stats['Клики'].Value = stats['Клики'].Value + 1
|
||
end
|
||
end
|
||
|
||
UserInputService.InputBegan:Connect(function(input, gp)
|
||
if gp then return end
|
||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||
onClick(Players.LocalPlayer)
|
||
end
|
||
end)
|
||
print("Кликай ЛКМ — копи клики!")`;
|
||
}
|