Hi! This is part 3 of my quest system tutorial. This part deals with the goal of the quest and changing the quest GUI.
NOTE: Sorry for the super delayed post.
If you haven’t read the other parts then here is the link:
~Part 1: How to make a Quest System
~Part 2: How to make a Quest System Part 2
Let’s Begin!
First, you’re going to need a folder with all the objects you need to collect, grab, etc. Make sure that all the models or parts has a proximity prompt inside.
Like this:
Put the folder in the ReplicatedStorage
Then, you need a leaderstats
script in the ServerScriptService
with this code:
game.Players.PlayerAdded:Connect(function(player)
local questsFolder = Instance.new("Folder", player)
questsFolder.Name = "QuestsFolder"
end)
This code checks if a player joins the game. If it detects a player joining the game, then it makes a folder inside the player named “QuestsFolder”. This folder will contain all the player’s quests.
Now we’re going back to our quest giver script. If you don’t know about this script, make sure to read the parts 1 and 2 above. Now we’re going to add a function to the script. Like this:
local questModule = require(game:GetService("ReplicatedStorage"):WaitForChild("QuestModule"))
local prompt = script.Parent:WaitForChild("ProximityPrompt")
local addQuestToGUI = game:GetService("ReplicatedStorage"):WaitForChild("AddQuest")
local bunniesFolder = game.ReplicatedStorage:WaitForChild("Bunnies")
local quest = "Grab 2 bunnies"
local number = 2
local parentName = script.Parent.Name
local function findQuest()
for _,questInModule in pairs(questModule.Quests) do
if questInModule.Name == quest then
print("Found quest")
return questInModule
end
end
end
local function makeFolder(questsFolder, questFound, parentName, number)
local folder = Instance.new("Folder", questsFolder)
folder.Name = questFound.Name
local counter = Instance.new("NumberValue", folder)
counter.Name = "Counter"
counter.Value = number
local maxCounter = Instance.new("NumberValue", folder)
maxCounter.Name = "MaxCounter"
maxCounter.Value = number
return folder
end
prompt.Triggered:Connect(function(player)
if game.Players:FindFirstChild(player.Name) then
local questFound = findQuest()
local questsFolder = player:WaitForChild("QuestsFolder")
if not questsFolder:FindFirstChild(questFound.Name) then
local folder = makeFolder(questsFolder, questFound, parentName, number)
addQuestToGUI:FireClient(player, questFound, parentName, number)
bunniesFolderClone.Parent = workspace
for _,promptInBunny in pairs(bunniesFolder:GetDescendants()) do
if promptInBunny:IsA("ProximityPrompt") then
promptInBunny.Triggered:Connect(function()
folder.Counter.Value -= 1
promptInBunny.Parent.Parent:Destroy()
end)
end
end
end
end
end)
The new function we made, makeFolder
, makes a folder in the QuestsFolder
we made earlier. Then it makes a NumberValue
name “Counter” in the folder that handles the number of objects you need to collect or grab in the quest. Then we fire it when the prompt is triggered. We have also fixed the bug where the player can get the same quest even if the player already has the quest. The fix for this is the if-statement “if not questsFolder:FindFirstChild(questFound.Name) then
”. This if-statement checks whether there is a quest also named as the quest we’re giving to the player. If it doesn’t find one, the code below the if-statement fires. There is also a new variable named bunniesFolder
. This folder, which is in the ReplicatedStorage, is the one I mentioned earlier:
First, you’re going to need a folder with all the objects you need to collect, grab, etc. Make sure that all the models or parts has a proximity prompt inside.
Then we clone the bunniesFolder
and put it in the workspace for the player to see. After that, we make a for loop so that when each bunny is grabbed or interacted, the bunny is destroyed and we minus the value of the counter with 1.
Now we’re going back to the local script in the StarterGui
.
local event = game.ReplicatedStorage:WaitForChild("AddQuest")
local questsGUI = script.Parent:WaitForChild("Quests")
local questFrameTemp = game.ReplicatedStorage:WaitForChild("TempQuestFrame")
local mainFrame = questsGUI:WaitForChild("BGFrame")
local questsFrame = mainFrame:WaitForChild("QuestsFrame")
local player = game.Players.LocalPlayer
local questsFolder = player:WaitForChild("QuestsFolder")
questsFolder.ChildAdded:Connect(function(child)
local counter = child:WaitForChild("Counter")
local maxCounter = child:WaitForChild("MaxCounter")
counter:GetPropertyChangedSignal("Value"):Connect(function()
local frame = questsFrame:WaitForChild(child.Name)
if frame then
local counterFrame = frame:WaitForChild("Counter"):WaitForChild("MainCounter")
local counterText = frame:WaitForChild("Counter"):WaitForChild("CounterText")
counterFrame.Size = UDim2.new(counter.Value / maxCounter.Value,0,1,0)
counterText.Text = counter.Value.."/"..maxCounter.Value
end
end)
end)
local function makeFrame(questName, parentName, number)
local clone = questFrameTemp:Clone()
clone.Name = questName.Name
local counter = clone:WaitForChild("Counter")
local NPCname = clone:WaitForChild("NPCName")
if parentName == nil then
NPCname.Text = ""
else
NPCname.Text = tostring(parentName)
end
local counterText = counter:WaitForChild("CounterText")
counterText.Text = number.."/"..number
local QuestName = clone:WaitForChild("QuestName")
QuestName.Text = tostring(questName.Name)
clone.Parent = questsFrame
end
event.OnClientEvent:Connect(function(questName, parentName, number)
if mainFrame.Visible == false then
mainFrame.Visible = true
end
if questsFolder:FindFirstChild(questName.Name) then
makeFrame(questName, parentName, number)
else
print("No quest found")
end
end)
As you can see, we have added a ChildAdded
event that fires when there’s a new object parented to another object. In our case, the object we parented is the folder we made for the quest. So when a new folder for the quest is parented to the Quests Folder, the code below the ChildAdded
event fires. The code below the ChildAdded
event is simple. When the counter’s value in the folder is decreased, we change the counterFrame's
size.
Let’s test it out!
Thanks for going through my tutorial! I hope you learned something in this tutorial. If you did, please give a like and feel free to give a feedback. Stay tuned for part 4!