diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js index f775cc2..5c717cd 100644 --- a/src/community/docsGamesBuildersLua.js +++ b/src/community/docsGamesBuildersLua.js @@ -3604,7 +3604,88 @@ end)`; })(), // ═══════════════════════════════════════════════════════════════ - // ИГРЫ 40-50: явных Lua-версий пока нет. + // ИГРА 40 — «Выживание от волн» + // ═══════════════════════════════════════════════════════════════ + 'wave-survival': { + g40_main: `-- === ИГРА «ВЫЖИВАНИЕ ОТ ВОЛН» — главный скрипт (Lua) === +${SNIPPET_BROADCAST} + +local WAVES = 3 +local wave = 0 +local won = false + +__rbxl_show_text("Отбей 3 волны врагов! Кликай по ним", 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 + +-- Текущие живые враги в волне: { ref → true } +local aliveInWave = 0 + +-- Каждый враг при клике шлёт EnemyClicked:Fire(ref). +-- Главный скрипт проверяет dist<5 и наносит урон. +local clickEvent = getEvent("EnemyClicked") +local enemiesRefs = {} -- ref → true (живые) +clickEvent.Event:Connect(function(localRef) + if won then return end + if not enemiesRefs[localRef] then return end + local px = __rbxl_player_x() + local pz = __rbxl_player_z() + local ex = __rbxl_npc_x(localRef) + local ez = __rbxl_npc_z(localRef) + 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 < 5 then + enemiesRefs[localRef] = nil + __rbxl_spawn_particles("explosion", ex, 2, ez, 0.4, 1) + __rbxl_npc_remove(localRef) + hitSound:Play() + aliveInWave = aliveInWave - 1 + if aliveInWave <= 0 then + if wave >= WAVES then + won = true + __rbxl_show_text("Победа! Все волны отбиты!", 5) + winSound:Play() + __rbxl_spawn_particles("confetti", px, 3, pz, 3, 3) + else + task.delay(2, startWave) + end + end + end +end) + +function startWave() + if won then return end + wave = wave + 1 + __rbxl_show_text("Волна " .. wave .. " из " .. WAVES .. "!", 3) + hitSound:Play() + local count = wave + 2 + aliveInWave = count + for i = 1, count do + local angle = (i - 1) / count * math.pi * 2 + local ex = math.cos(angle) * 10 + local ez = math.sin(angle) * 10 + local ref = __rbxl_spawn_npc("character-b", ex, 1, ez, "Враг", 40, 2) + enemiesRefs[ref] = true + task.delay(0.3, function() + __rbxl_npc_follow(ref, "player") + end) + __rbxl_npc_on_click(ref, function() + local ev = game:GetService("ReplicatedStorage"):FindFirstChild("EnemyClicked") + if ev then ev:Fire(ref) end + end) + end +end + +task.delay(2, startWave)`, + }, + + // ═══════════════════════════════════════════════════════════════ + // ИГРЫ 41-50: явных Lua-версий пока нет. // buildGameProject в docsGamesBuilders.js использует generateFallbackLua // (главный скрипт → показ подсказки + слушает FinishReached → // победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached; diff --git a/src/community/docsLessons.jsx b/src/community/docsLessons.jsx index 43c7134..8ce5884 100644 --- a/src/community/docsLessons.jsx +++ b/src/community/docsLessons.jsx @@ -5550,7 +5550,7 @@ game.self.onInteract(() => {

Шаг 2. Главный скрипт

- {`// === ИГРА «БАШНЯ — СТРОЙКА» — главный скрипт === + {`// === ИГРА «БАШНЯ — СТРОЙКА» — главный скрипт === const STEPS = 8; let placed = 0; // сколько блоков поставлено @@ -5580,7 +5580,7 @@ game.onMessage('place', (d) => { } else { game.ui.showText('Блок ' + placed + ' из ' + STEPS, 1.5); } -});`} +});`}

Разберём: