Roblox · Приключение · урок 2
Житель даёт задание, на экране видно, что сделать и сколько осталось. Первый квест — собрать мешки с песком.
Синим — что добавляем на этом уроке.
ReplicatedStorage └─ Events (Folder) └─ CompleteEvent, CancelEvent (RemoteEvent) ServerScriptService └─ QuestSystem (Script) Workspace ├─ Elder (Model) │ ├─ Head (MeshPart) │ │ └─ ProximityPrompt (ProximityPrompt) — «Взять задание» │ └─ QuestGiver (Script) │ ├─ Title, Description (StringValue) │ └─ Objective, Reward (IntValue) — 5 и 20 └─ Sandbags (Folder) └─ Sandbag (Part) ├─ ProximityPrompt (ProximityPrompt) └─ QuestItem (Script) StarterGui └─ QuestGui (ScreenGui) — ResetOnSpawn выкл. ├─ QuestFrame (Frame) — Title, Description, Progress, CancelButton ├─ DoneLabel (TextLabel) — Visible выкл. └─ QuestLocal (LocalScript)
Где: ServerScriptService · Script
Зачем: Монеты, квест игрока, награда, отмена.
-- игроки
local Players = game:GetService("Players")
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- папка событий
local events = RS:WaitForChild("Events")
-- квест выполнен — сообщить игроку
local completeEvent = events:WaitForChild("CompleteEvent")
-- игрок отменил квест
local cancelEvent = events:WaitForChild("CancelEvent")
-- создаёт контейнер со значением
local function Value(parent, class, name, value)
-- контейнер
local v = Instance.new(class)
-- имя
v.Name = name
-- значение
v.Value = value
-- на место
v.Parent = parent
-- отдаём
return v
-- конец функции
end
-- у игрока нет квеста
local function ClearQuest(quest)
-- сначала цель: теперь сброс прогресса ничего не засчитает
quest.Objective.Value = 0
-- прогресс
quest.Progress.Value = 0
-- название пустое = квеста нет
quest.Title.Value = ""
-- описание
quest.Description.Value = ""
-- награда
quest.Reward.Value = 0
-- конец функции
end
-- игрок зашёл
Players.PlayerAdded:Connect(function(player)
-- таблица по Tab
local leaderstats = Instance.new("Folder")
-- имя строго такое
leaderstats.Name = "leaderstats"
-- в игрока
leaderstats.Parent = player
-- монеты
local coins = Value(leaderstats, "IntValue", "Coins", 0)
-- текущий квест игрока
local quest = Instance.new("Folder")
-- имя
quest.Name = "QuestInfo"
-- в игрока — клиент тоже видит
quest.Parent = player
-- название
Value(quest, "StringValue", "Title", "")
-- что сделать
Value(quest, "StringValue", "Description", "")
-- сколько нужно
Value(quest, "IntValue", "Objective", 0)
-- сколько уже
local progress = Value(quest, "IntValue", "Progress", 0)
-- награда в монетах
Value(quest, "IntValue", "Reward", 0)
-- прогресс изменился
progress.Changed:Connect(function(value)
-- цель
local objective = quest.Objective.Value
-- квеста нет или ещё не всё
if objective <= 0 or value < objective then return end
-- запоминаем награду
local reward = quest.Reward.Value
-- и название
local title = quest.Title.Value
-- квест закрыт — второй раз награда не выдастся
ClearQuest(quest)
-- награда
coins.Value += reward
-- сообщение на экране
completeEvent:FireClient(player, title, reward)
-- конец функции
end)
-- конец функции
end)
-- кнопка «Отменить»
cancelEvent.OnServerEvent:Connect(function(player)
-- квест игрока
local quest = player:FindFirstChild("QuestInfo")
-- очищаем
if quest then ClearQuest(quest) end
-- конец функции
end)Где: Workspace → Elder · Script
Зачем: Выдаёт квест.
-- персонаж, который даёт квест
local npc = script.Parent
-- «Взять задание»
local prompt = npc:WaitForChild("Head"):WaitForChild("ProximityPrompt")
-- игрок нажал E
prompt.Triggered:Connect(function(player)
-- квест игрока
local quest = player:FindFirstChild("QuestInfo")
-- уже есть другой квест
if not quest or quest.Title.Value ~= "" then return end
-- название — из значений под скриптом
quest.Title.Value = script.Title.Value
-- описание
quest.Description.Value = script.Description.Value
-- награда
quest.Reward.Value = script.Reward.Value
-- с нуля
quest.Progress.Value = 0
-- цель — последней: квест начался
quest.Objective.Value = script.Objective.Value
-- конец функции
end)Где: Workspace → Sandbags → Sandbag · Script
Зачем: Предмет для квеста.
-- мешок с песком
local item = script.Parent
-- «Взять»
local prompt = item:WaitForChild("ProximityPrompt")
-- для какого квеста — как Title у квестодателя
local QUEST = "Мешки с песком"
-- через сколько секунд мешок вернётся
local RESPAWN = 60
-- игрок нажал E
prompt.Triggered:Connect(function(player)
-- квест игрока
local quest = player:FindFirstChild("QuestInfo")
-- мешки нужны только с этим квестом
if not quest or quest.Title.Value ~= QUEST then return end
-- +1 к прогрессу
quest.Progress.Value += 1
-- второй раз не взять
prompt.Enabled = false
-- мешок пропал
item.Transparency = 1
-- и не мешает
item.CanCollide = false
-- ждём
task.wait(RESPAWN)
-- вернулся
item.Transparency = 0
-- снова твёрдый
item.CanCollide = true
-- можно взять
prompt.Enabled = true
-- конец функции
end)Где: StarterGui → QuestGui · LocalScript
Зачем: Окно квеста.
-- игроки
local Players = game:GetService("Players")
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- этот игрок
local player = Players.LocalPlayer
-- его квест
local quest = player:WaitForChild("QuestInfo")
-- события
local events = RS:WaitForChild("Events")
-- квест выполнен
local completeEvent = events:WaitForChild("CompleteEvent")
-- отмена
local cancelEvent = events:WaitForChild("CancelEvent")
-- QuestGui
local gui = script.Parent
-- окно квеста
local frame = gui:WaitForChild("QuestFrame")
-- надпись «Выполнено»
local doneLabel = gui:WaitForChild("DoneLabel")
-- обновить окно
local function Update()
-- квест есть — окно видно
frame.Visible = quest.Title.Value ~= ""
-- название
frame.Title.Text = quest.Title.Value
-- описание
frame.Description.Text = quest.Description.Value
-- прогресс: 2 / 5
frame.Progress.Text = quest.Progress.Value .. " / " .. quest.Objective.Value
-- конец функции
end
-- все значения квеста
for _, value in ipairs(quest:GetChildren()) do
-- изменилось — обновляем
value.Changed:Connect(Update)
-- конец перебора
end
-- сразу при входе
Update()
-- «Отменить»
frame.CancelButton.MouseButton1Click:Connect(function()
-- просим сервер
cancelEvent:FireServer()
-- конец функции
end)
-- квест выполнен
completeEvent.OnClientEvent:Connect(function(title, reward)
-- текст
doneLabel.Text = "Квест «" .. title .. "» выполнен! +" .. reward .. " монет"
-- показываем
doneLabel.Visible = true
-- 3 секунды
task.wait(3)
-- прячем
doneLabel.Visible = false
-- конец функции
end)Запусти Play (или Run) и убедись: