diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js index 6f128a9..f526c48 100644 --- a/src/community/docsGamesBuildersLua.js +++ b/src/community/docsGamesBuildersLua.js @@ -4228,7 +4228,122 @@ end)`; })(), // ═══════════════════════════════════════════════════════════════ - // ИГРЫ 45-50: явных Lua-версий пока нет. + // ИГРА 45 — «Стрелялка-арена» + // ═══════════════════════════════════════════════════════════════ + 'arena-shooter': { + g45_main: `-- === ИГРА «СТРЕЛЯЛКА-АРЕНА» — главный скрипт (Lua) === +${SNIPPET_BROADCAST} + +local Players = game:GetService("Players") +local RunService = game:GetService("RunService") +local player = Players.LocalPlayer + +local GOAL = 15 +local score = 0 +local over = false + +-- Враги: { ref → { ref, alive, lastDmg } } +local enemies = {} + +__rbxl_score_set(0) +__rbxl_show_text("Перебей 15 врагов! Кликай по ним", 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 + +-- Подписка на смерть игрока +task.delay(0.5, function() + local char = player.Character or player.CharacterAdded:Wait() + local h = char:WaitForChild("Humanoid", 2) + if h then + h.Died:Connect(function() + if over then return end + over = true + __rbxl_show_text("Поражение! Тебя одолели враги.", 5) + end) + end +end) + +-- Клик по врагу: EnemyClicked:Fire(ref) +local clickEvent = getEvent("EnemyClicked") +clickEvent.Event:Connect(function(localRef) + if over then return end + local e = enemies[localRef] + if not e or not e.alive 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 < 6 then + e.alive = false + __rbxl_npc_remove(localRef) + __rbxl_spawn_particles("explosion", ex, 2, ez, 0.4, 1) + hitSound:Play() + score = score + 1 + __rbxl_score_set(score) + if score >= GOAL and not over then + over = true + __rbxl_show_text("Победа! Арена зачищена!", 5) + winSound:Play() + __rbxl_spawn_particles("confetti", px, 3, pz, 3, 3) + end + end +end) + +-- Спавн каждые 1.8с +local spawnTimer = 0 +RunService.Heartbeat:Connect(function(dt) + if over or score >= GOAL then return end + spawnTimer = spawnTimer + dt + if spawnTimer < 1.8 then return end + spawnTimer = 0 + local angle = math.random() * math.pi * 2 + local ex = math.cos(angle) * 11 + local ez = math.sin(angle) * 11 + local ref = __rbxl_spawn_npc("character-b", ex, 1, ez, "Враг", 30, 2.2) + enemies[ref] = { ref = ref, alive = true, lastDmg = 0 } + 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) + +-- Враги бьют игрока вблизи (каждые 0.7с) +RunService.Heartbeat:Connect(function() + if over then return end + local px = __rbxl_player_x() + local pz = __rbxl_player_z() + local now = tick() + for _, e in pairs(enemies) do + if e.alive then + local ex = __rbxl_npc_x(e.ref) + local ez = __rbxl_npc_z(e.ref) + 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.8 and now - e.lastDmg > 0.7 then + e.lastDmg = now + __rbxl_damage_player(10) + hitSound:Play() + end + end + end + end +end)`, + }, + + // ═══════════════════════════════════════════════════════════════ + // ИГРЫ 46-50: явных Lua-версий пока нет. // buildGameProject в docsGamesBuilders.js использует generateFallbackLua // (главный скрипт → показ подсказки + слушает FinishReached → // победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached; diff --git a/src/community/docsLessons.jsx b/src/community/docsLessons.jsx index fffb30a..c04cc64 100644 --- a/src/community/docsLessons.jsx +++ b/src/community/docsLessons.jsx @@ -6291,7 +6291,7 @@ game.self.onTouch(() => { стрелять и проверяет, кто победил.
{`// === ИГРА «TOWER DEFENSE» — главный скрипт ===
+ {`// === ИГРА «TOWER DEFENSE» — главный скрипт ===
let leaked = 0; // врагов прошло до базы
const MAX_LEAK = 8;
@@ -6374,7 +6374,7 @@ game.every(0.5, () => {
}
}
}
-});`}
+});`}
Разберём:
towers и enemies — два списка:
@@ -6395,7 +6395,7 @@ game.every(0.5, () => {
{`// === Скрипт площадки под башню ===
+ {`// === Скрипт площадки под башню ===
let built = false;
game.self.onInteract(() => {
if (built) return;
@@ -6408,7 +6408,7 @@ game.self.onInteract(() => {
color: '#ffcc33',
});
game.broadcast('addTower', { x: pos.x, z: pos.z });
-}, { text: 'Построить башню', distance: 4 });`}
+}, { text: 'Построить башню', distance: 4 });`}
При нажатии E скрипт создаёт жёлтый цилиндр-башню над площадкой и шлёт сообщение