Questing Difficulties

Im being troubled by how to track quest progress modularly for my game, I cant provide much info as im in a rush to post this and go somewhere, hopefully you understand what i mean. Im using Profile Service.

Hierarchy:

image

Quest Module:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage.Modules

local Data = require(Modules.Data)
local Dialog = require(Modules.Dialog)

local Module = {}

function Module.Fetch(Key)
	for _, Child in script:GetChildren() do
		if Child.Name == Key then
			if Child:HasTag("COMMENT") then continue end
			
			return require(Child)
		end
	end
	
	warn("No Dialog Data for: "..Key)
end

function Module.Assign(Player, QuestData)
	if Player then
		Data:Update(Player, "Quests", function(Old)
			local New = Old

			New[QuestData.QuestGiver].Claimed = true

			return New
		end)

		print(QuestData)

		local NewQuestUI = game.ReplicatedStorage.Resources.QuestTemplate:Clone()
		NewQuestUI.Title.Text = QuestData.QuestName
		NewQuestUI.Description.Text = QuestData.QuestDescription

		NewQuestUI.Greyscale.Fill.Size = UDim2.fromScale(0, 1)
		NewQuestUI.Greyscale.Progress.Text = QuestData.Requirements[1].." / "..QuestData.Requirements[1].Amount

		NewQuestUI.Parent = Player.PlayerGui.QuestUI.Container.Frame
	end
end

function Module.CheckCompletion(Player, QuestData)
	local Completed = false
	for i,v in pairs(QuestData) do
		if v.Collected >= v.Amount then
			Completed = true
		else
			Completed = false
			break
		end
	end
	
	return Completed
end

function Module.Reward(Player, Rewards)
	for _, Item in Rewards do
		if not Item.Type or not Item.Item or not Item.Amount then return end
		
		if Item.Type == "Currency" then
			Data:Update(Player, Item.Item, function(Old)
				local New = Old
				New += Item.Amount
				
				return New
			end)
		elseif Item.Type == "Ability" then
			-- TODO: Add Ability functionality (Optional)
		elseif Item.Type == "Item" then
			Data:Update(Player, "Inventory", function(Old)
				local New = Old
				New[Item.Item] += Item.Amount
				
				return New
			end)
		elseif Item.Type == "XP" then
			-- TODO: Add XP functionality (Optional)
		end
	end
end

function Module.Talk(Player, NPC)
	local QuestsFolder = Data:Get(Player, "Quests")
	local QuestData = QuestsFolder[NPC]

	local Claimed = QuestData.Claimed
	local Completed = QuestData.Completed
	local Quest = QuestData.Quest

	local QuestModule = Module.Fetch(NPC)
	if not Claimed and not Completed and #QuestModule >= Quest then
		for i, _ in ipairs(QuestModule[Quest].Dialog.Unclaimed) do
			local FinalMessage = false
			
			if i == #QuestModule[Quest].Dialog.Unclaimed then
				FinalMessage = true
			end
			
			local Yield = Dialog.Write(Player, NPC, QuestModule[Quest].Dialog.Unclaimed[i].Text, QuestModule[Quest].Dialog.Unclaimed[i].Options, FinalMessage)
			repeat task.wait(.1) until Yield
		end

		Module.Assign(Player, QuestModule[Quest])
	elseif Claimed and not Completed and #QuestModule >= Quest then
		for i, _ in ipairs(QuestModule[Quest].Dialog.Claimed) do
			local FinalMessage = false

			if i == #QuestModule[Quest].Dialog.Claimed then
				FinalMessage = true
			end

			local Yield = Dialog.Write(Player, NPC, QuestModule[Quest].Dialog.Claimed[i].Text, QuestModule[Quest].Dialog.Claimed[i].Options, FinalMessage)
			repeat task.wait(.1) until Yield
		end
		Data:Update(Player, "Quests", function(Old)
			local New = Old
			
			print(New)
			New[QuestModule[Quest].QuestGiver].Completed = true

			return New
		end)
	elseif Claimed and Completed and #QuestModule >= Quest then
		for i, _ in ipairs(QuestModule[Quest].Dialog.Completed) do
			local FinalMessage = false

			if i == #QuestModule[Quest].Dialog.Completed then
				FinalMessage = true
			end

			local Yield = Dialog.Write(Player, NPC, QuestModule[Quest].Dialog.Completed[i].Text, QuestModule[Quest].Dialog.Completed[i].Options, FinalMessage)
			repeat task.wait(.1) until Yield
		end
		
		Data:Update(Player, "Quests", function(Old)
			local New = Old

			New[QuestModule[Quest].QuestGiver].Claimed = false
			New[QuestModule[Quest].QuestGiver].Completed = false
			
			if #QuestModule >= (Quest + 1) then
				New[QuestModule[Quest].QuestGiver].Quest += 1
			end

			return New
		end)
		Module.Reward(Player, QuestModule[Quest].Rewards)
	end
end

if game["Run Service"]:IsClient() then
	return warn("Client Attempt Access: Quest Module")
end

return Module

Quest Data Module: (Template)

return {
	[1] = {
		QuestName = "Bingo's Stolen Bongos",
		QuestGiver = "Bingo",
		QuestDescription = "Retrieve all 3 of Bingo's missing bongos by fighting off the nasty goblins!",

		Requirements = {
			[1] = {Type="Gather", Amount=3, Collected=0}
		},

		Rewards = {
			[1] = {Type="Currency", Item="BUX", Amount=50}	
		},

		Dialog = {
			Unclaimed = {
				[1] = {Text="Hi, I'm Bingo!", Options={}},
				[2] = {Text="Some nasty goblins stole my bongos!", Options={}},
				[3] = {Text="If you get them back, I must reward you...", Options={}},
			},
			Claimed = {
				[1] = {Text="Goblins are strong! Be careful!", Options={}},

			},
			Completed = {
				[1] = {Text="Wow! You actually managed to fend of the goblins!", Options={}},
				[2] = {Text="Im suprised that's even possible to slay goblins.", Options={}},
			}
		}
	},
}

Any support is appreciated!! :smiley:

1 Like