feat: 50 игр на Lua + импорт Roblox для всех + поддержка Lua в плеере #39
@ -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)`,
|
||||
},
|
||||
|
||||
|
||||
@ -4019,7 +4019,7 @@ game.self.onTouch(() => {
|
||||
продаёт ключ, открывает дверь.
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`// === ИГРА «МАГАЗИН» — главный скрипт ===
|
||||
<CodeBoth game="shop" script="g29_main">{`// === ИГРА «МАГАЗИН» — главный скрипт ===
|
||||
|
||||
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 });
|
||||
});`}</Code>
|
||||
});`}</CodeBoth>
|
||||
<p>
|
||||
Каждый объект магазина — монетка, прилавок, дверь, финиш —
|
||||
работает в своей «песочнице» и не видит переменные
|
||||
@ -4100,23 +4100,23 @@ game.onMessage('win', () => {
|
||||
|
||||
<h3 className="lessonH">Шаг 3. Скрипт монетки</h3>
|
||||
<ScriptKind kind="object" on="каждую монетку" />
|
||||
<Code>{`// === Скрипт монетки ===
|
||||
<CodeBoth game="shop" script="g29_coin_1">{`// === Скрипт монетки ===
|
||||
game.self.onTouch(() => {
|
||||
game.broadcast('coin');
|
||||
game.self.delete();
|
||||
});`}</Code>
|
||||
});`}</CodeBoth>
|
||||
|
||||
<h3 className="lessonH">Шаг 4. Скрипт прилавка и двери</h3>
|
||||
<ScriptKind kind="object" on="прилавок" />
|
||||
<Code>{`// === Скрипт прилавка ===
|
||||
<CodeBoth game="shop" script="g29_shop">{`// === Скрипт прилавка ===
|
||||
game.self.onInteract(() => {
|
||||
game.broadcast('buy');
|
||||
}, { text: 'Купить ключ (5 монет)', distance: 4 });`}</Code>
|
||||
}, { text: 'Купить ключ (5 монет)', distance: 4 });`}</CodeBoth>
|
||||
<ScriptKind kind="object" on="дверь" />
|
||||
<Code>{`// === Скрипт двери ===
|
||||
<CodeBoth game="shop" script="g29_door">{`// === Скрипт двери ===
|
||||
game.self.onInteract(() => {
|
||||
game.broadcast('open-door');
|
||||
}, { text: 'Открыть дверь', distance: 4 });`}</Code>
|
||||
}, { text: 'Открыть дверь', distance: 4 });`}</CodeBoth>
|
||||
<p>
|
||||
И прилавок, и дверь — это объекты с взаимодействием по
|
||||
<kbd className="kbd">E</kbd>. Подошёл к прилавку и нажал
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user