From f69df55e3b656c5fa96347160f163f3b63798c6c Mon Sep 17 00:00:00 2001
From: min
Date: Tue, 9 Jun 2026 22:06:27 +0300
Subject: [PATCH] =?UTF-8?q?docs:=20CodeBoth=20=D1=83=D1=80=D0=BE=D0=BA?=
=?UTF-8?q?=D0=B0=2029=20+=20feat(g30):=20=D0=BF=D0=BE=D0=BB=D0=BD=D1=8B?=
=?UTF-8?q?=D0=B9=20=D0=BF=D0=B0=D1=80=D0=B8=D1=82=D0=B5=D1=82=20=C2=AB?=
=?UTF-8?q?=D0=9A=D0=B2=D0=B5=D1=81=D1=82=20=D1=81=20=D0=B7=D0=B0=D0=B4?=
=?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8=C2=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
g29 docs: 5 скриптов под CodeBoth (main, coin_1, shop, door, finish).
g30 паритет:
- stage 0→1→2→3→4 (talk/coin/flag/talk)
- setObjective через __rbxl_hud_set 50,8 цвет/размер
- NPC 'Старейшина' spawnNpc + npc_say на этапах
- BindableEvents Talk/CoinDone/FlagDone
- g30_npc: Heartbeat distance-check (4) + '[E] Поговорить' + InputBegan E
- g30_coin: Touched → CoinDone:Fire + Destroy (taken-флаг)
- g30_flag: Touched → FlagDone:Fire (fired-флаг)
- На stage 3: showText + confetti + win sound
---
src/community/docsGamesBuildersLua.js | 133 +++++++++++++++++++++++---
src/community/docsLessons.jsx | 16 ++--
2 files changed, 126 insertions(+), 23 deletions(-)
diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js
index 259533c..84cfddd 100644
--- a/src/community/docsGamesBuildersLua.js
+++ b/src/community/docsGamesBuildersLua.js
@@ -2607,26 +2607,129 @@ end)`;
// ИГРА 30 — «Квесты»
// ═══════════════════════════════════════════════════════════════
'quest-tasks': {
- g30_main: `-- === ИГРА «КВЕСТЫ» (Lua) ===
+ g30_main: `-- === ИГРА «КВЕСТ С ЗАДАНИЯМИ» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
-local quests = {
- { name = "Собери 5 ягод", goal = 5, current = 0 },
- { name = "Победи врага", goal = 1, current = 0 },
- { name = "Дойди до башни", goal = 1, current = 0 },
-}
+local stage = 0 -- 0=не начат, 1=собрать монетку, 2=дойти до флага, 3=вернуться, 4=готово
-print("Квесты:")
-for i, q in ipairs(quests) do print(" " .. i .. ". " .. q.name) end
+local function setObjective(text, color)
+ __rbxl_hud_set("objective", "ЦЕЛЬ: " .. text, 50, 8, color or "#ffe066", 24)
+end
+setObjective("подойди к квестодателю и нажми E")
-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)
+-- Спавним 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)`,
},
diff --git a/src/community/docsLessons.jsx b/src/community/docsLessons.jsx
index fea3530..80ff32e 100644
--- a/src/community/docsLessons.jsx
+++ b/src/community/docsLessons.jsx
@@ -4019,7 +4019,7 @@ game.self.onTouch(() => {
продаёт ключ, открывает дверь.
- {`// === ИГРА «МАГАЗИН» — главный скрипт ===
+ {`// === ИГРА «МАГАЗИН» — главный скрипт ===
let coins = 0;
const PRICE = 5; // ключ стоит 5 монет
@@ -4070,7 +4070,7 @@ game.onMessage('win', () => {
const p = game.player.position;
game.scene.spawnParticles('confetti',
{ x: p.x, y: p.y + 3, z: p.z }, { duration: 3, count: 3 });
-});`}
+});`}
Каждый объект магазина — монетка, прилавок, дверь, финиш —
работает в своей «песочнице» и не видит переменные
@@ -4100,23 +4100,23 @@ game.onMessage('win', () => {
Шаг 3. Скрипт монетки
- {`// === Скрипт монетки ===
+ {`// === Скрипт монетки ===
game.self.onTouch(() => {
game.broadcast('coin');
game.self.delete();
-});`}
+});`}
Шаг 4. Скрипт прилавка и двери
- {`// === Скрипт прилавка ===
+ {`// === Скрипт прилавка ===
game.self.onInteract(() => {
game.broadcast('buy');
-}, { text: 'Купить ключ (5 монет)', distance: 4 });`}
+}, { text: 'Купить ключ (5 монет)', distance: 4 });`}
- {`// === Скрипт двери ===
+ {`// === Скрипт двери ===
game.self.onInteract(() => {
game.broadcast('open-door');
-}, { text: 'Открыть дверь', distance: 4 });`}
+}, { text: 'Открыть дверь', distance: 4 });`}
И прилавок, и дверь — это объекты с взаимодействием по
E. Подошёл к прилавку и нажал