File size: 4,032 Bytes
0712d5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
-- src/ServerScriptService/QuestManager.server.lua

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local QuestConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("QuestConfig"))
local QuestUpdateEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("QuestUpdateEvent")
local NotificationEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("NotificationEvent")

-- Player quest state: [userId] = { [questId] = { progress, completed } }
local playerQuests = {}

local function initPlayerQuests(player)
	playerQuests[player.UserId] = {}

	-- Assign starter quests
	for _, questId in ipairs(QuestConfig.StarterQuests) do
		playerQuests[player.UserId][questId] = {
			progress = 0,
			completed = false,
		}
	end

	-- Send initial quest data to client
	task.delay(4, function()
		if player.Parent then
			QuestUpdateEvent:FireClient(player, "Init", playerQuests[player.UserId])
		end
	end)
end

local function isQuestActive(player, questId)
	local quests = playerQuests[player.UserId]
	if not quests then return false end
	local quest = quests[questId]
	if not quest then return false end
	return not quest.completed
end

local function progressQuest(player, questType, amount)
	local quests = playerQuests[player.UserId]
	if not quests then return end

	for questId, questState in pairs(quests) do
		if questState.completed then continue end

		local questDef = QuestConfig.Quests[questId]
		if not questDef then continue end

		if questDef.Type == questType then
			questState.progress = questState.progress + amount

			if questState.progress >= questDef.Target then
				questState.progress = questDef.Target
				questState.completed = true

				-- Grant rewards
				if questDef.Reward.Cash then
					local leaderstats = player:FindFirstChild("leaderstats")
					if leaderstats then
						local cash = leaderstats:FindFirstChild("Cash")
						if cash then
							cash.Value = cash.Value + questDef.Reward.Cash
						end
					end
				end

				NotificationEvent:FireClient(player, "Quest Complete", questDef.Title .. " completed! +" .. tostring(questDef.Reward.Cash or 0) .. " Cash")

				-- Unlock follow-up quests
				unlockNextQuests(player, questId)
			end

			-- Update client
			QuestUpdateEvent:FireClient(player, "Update", {
				questId = questId,
				progress = questState.progress,
				target = questDef.Target,
				completed = questState.completed,
			})
		end
	end
end

function unlockNextQuests(player, completedQuestId)
	-- Simple linear progression: unlock quests based on what was completed
	local unlockMap = {
		ChopFirstTree = {"Chop10Trees"},
		Chop10Trees = {"Chop50Trees"},
		Chop50Trees = {"Chop200Trees"},
		SellFirstWood = {"Earn5000"},
		Earn5000 = {"Earn50000"},
		BuildFirstStructure = {"Build10Structures"},
		BuyFirstItem = {"ProcessFirstPlank"},
		ProcessFirstPlank = {"ExploreAllBiomes"},
	}

	local nextQuests = unlockMap[completedQuestId]
	if nextQuests then
		for _, nextId in ipairs(nextQuests) do
			if not playerQuests[player.UserId][nextId] then
				playerQuests[player.UserId][nextId] = {
					progress = 0,
					completed = false,
				}

				local questDef = QuestConfig.Quests[nextId]
				if questDef then
					NotificationEvent:FireClient(player, "New Quest", "New quest unlocked: " .. questDef.Title)
				end
			end
		end
	end
end

-- Expose globally for other managers to trigger quest progress
_G.ProgressQuest = function(player, questType, amount)
	progressQuest(player, questType, amount or 1)
end

_G.GetPlayerQuests = function(player)
	return playerQuests[player.UserId]
end

Players.PlayerAdded:Connect(initPlayerQuests)
Players.PlayerRemoving:Connect(function(player)
	playerQuests[player.UserId] = nil
end)

-- Handle players already in game
for _, player in ipairs(Players:GetPlayers()) do
	task.spawn(function()
		initPlayerQuests(player)
	end)
end