TimberWoods / src /ServerScriptService /QuestManager.server.lua
algorembrant's picture
Upload 88 files
0712d5f verified
-- 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