feat: 50 игр на Lua + импорт Roblox для всех + поддержка Lua в плеере #39

Merged
min merged 215 commits from feat/lua-50-games-bundle into main 2026-06-09 21:59:25 +00:00
2 changed files with 86 additions and 5 deletions
Showing only changes of commit cce9d2e293 - Show all commits

View File

@ -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;

View File

@ -5550,7 +5550,7 @@ game.self.onInteract(() => {
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
<ScriptKind kind="global" />
<Code>{`// === ИГРА «БАШНЯ — СТРОЙКА» — главный скрипт ===
<CodeBoth game="tower-build" script="g39_main">{`// === ИГРА «БАШНЯ — СТРОЙКА» — главный скрипт ===
const STEPS = 8;
let placed = 0; // сколько блоков поставлено
@ -5580,7 +5580,7 @@ game.onMessage('place', (d) => {
} else {
game.ui.showText('Блок ' + placed + ' из ' + STEPS, 1.5);
}
});`}</Code>
});`}</CodeBoth>
<p>Разберём:</p>
<ul>
<li><code>placed</code> сколько блоков уже стоит;</li>
@ -5599,7 +5599,7 @@ game.onMessage('place', (d) => {
у остальных поменяй число в <code>place</code>.
</p>
<ScriptKind kind="object" on="каждое место-призрак" />
<Code>{`// === Скрипт места под блок 1 ===
<CodeBoth game="tower-build" script="g39_spot_1">{`// === Скрипт места под блок 1 ===
let built = false;
game.self.onInteract(() => {
if (built) return;
@ -5610,7 +5610,7 @@ game.self.onInteract(() => {
game.scene.setCollide(game.self.ref, true);
built = true;
game.broadcast('place', { n: 1 });
}, { text: 'Поставить блок', distance: 4 });`}</Code>
}, { text: 'Поставить блок', distance: 4 });`}</CodeBoth>
<p>Что происходит при нажатии:</p>
<ul>
<li><code>passThrough(ref, false)</code> сквозь блок