MysteriaFool

ObjectiveServer

Nov 11th, 2025 (edited)
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.97 KB | None | 0 0
  1. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  2. local Players = game:GetService("Players")
  3.  
  4. local AllQuestData = require(ReplicatedStorage:WaitForChild("ObjectiveData"))
  5.  
  6. local eventsFolder = ReplicatedStorage:FindFirstChild("ObjectiveEvents") or Instance.new("Folder")
  7. eventsFolder.Name = "ObjectiveEvents"
  8. eventsFolder.Parent = ReplicatedStorage
  9.  
  10. local function ensureEvent(name)
  11.     local event = eventsFolder:FindFirstChild(name) or Instance.new("RemoteEvent")
  12.     event.Name = name
  13.     event.Parent = eventsFolder
  14.     return event
  15. end
  16.  
  17. local updateEvent = ensureEvent("UpdateObjective")
  18. local initEvent = ensureEvent("InitObjectives")
  19. local questStartEvent = ensureEvent("QuestStarted")
  20. local questCompleteEvent = ensureEvent("QuestCompleted")
  21.  
  22. local playerData = {}
  23. local globalProgress = {}
  24.  
  25. for _, quest in ipairs(AllQuestData) do
  26.     globalProgress[quest.QuestName] = {}
  27.     for _, obj in ipairs(quest.Objectives) do
  28.         if obj.Type == "Global" then
  29.             globalProgress[quest.QuestName][obj.Name] = false
  30.         end
  31.     end
  32. end
  33.  
  34. local function hasTool(player, required)
  35.     if not required then return true end
  36.     local backpack = player:FindFirstChildOfClass("Backpack")
  37.     local character = player.Character
  38.     if not backpack or not character then return false end
  39.     return (backpack:FindFirstChild(required) or character:FindFirstChild(required)) ~= nil
  40. end
  41.  
  42. local function isQuestComplete(player, questName)
  43.     local data = playerData[player.UserId]
  44.     if not data or not data.Quests[questName] then return false end
  45.     for _, completed in pairs(data.Quests[questName].Completed) do
  46.         if not completed then return false end
  47.     end
  48.     return true
  49. end
  50.  
  51. local function startQuestline(player, questName)
  52.     local data = playerData[player.UserId]
  53.     if not data then return end
  54.  
  55.     if data.Quests[questName] and data.Quests[questName].Started then
  56.         initEvent:FireClient(player, questName, data.Quests[questName].Completed)
  57.         return
  58.     end
  59.  
  60.     local quest
  61.     for _, q in ipairs(AllQuestData) do
  62.         if q.QuestName == questName then
  63.             quest = q
  64.             break
  65.         end
  66.     end
  67.  
  68.     if not quest then
  69.         warn("Questline not found:", questName)
  70.         return
  71.     end
  72.  
  73.     data.Quests[questName] = { Started = true, Completed = {} }
  74.     for _, obj in ipairs(quest.Objectives) do
  75.         data.Quests[questName].Completed[obj.Name] = globalProgress[quest.QuestName][obj.Name] or false
  76.     end
  77.  
  78.     initEvent:FireClient(player, questName, data.Quests[questName].Completed)
  79.     questStartEvent:FireClient(player, questName)
  80. end
  81.  
  82. local function startNextObjective(player, quest, currentObj)
  83.     local nextName = currentObj.NextObjective
  84.     if not nextName then return end
  85.     local data = playerData[player.UserId]
  86.     if not data or not data.Quests[quest.QuestName] then return end
  87.     if data.Quests[quest.QuestName].Completed[nextName] ~= nil then
  88.         data.Quests[quest.QuestName].Completed[nextName] = false
  89.         updateEvent:FireClient(player, quest.QuestName, nextName, false)
  90.     end
  91. end
  92.  
  93. local function completeObjective(player, quest, obj)
  94.     local questName, objName = quest.QuestName, obj.Name
  95.     local data = playerData[player.UserId]
  96.     if not data or not data.Quests[questName] then return end
  97.    
  98.     if data.Quests[questName].Completed[objName] then return end
  99.  
  100.     if obj.Type == "Global" then
  101.         if not globalProgress[questName][objName] then
  102.             globalProgress[questName][objName] = true
  103.         end
  104.         data.Quests[questName].Completed[objName] = true
  105.  
  106.         for _, plr in ipairs(Players:GetPlayers()) do
  107.             local pdata = playerData[plr.UserId]
  108.             if pdata and pdata.Quests[questName] and pdata.Quests[questName].Started then
  109.                 if not pdata.Quests[questName].Completed[objName] then
  110.                     pdata.Quests[questName].Completed[objName] = true
  111.                     updateEvent:FireClient(plr, questName, objName, true)
  112.                 end
  113.             end
  114.         end
  115.  
  116.     else
  117.         data.Quests[questName].Completed[objName] = true
  118.         updateEvent:FireClient(player, questName, objName, true)
  119.     end
  120.  
  121.     if isQuestComplete(player, questName) then
  122.         questCompleteEvent:FireClient(player, questName)
  123.     end
  124.  
  125.     if obj.NextQuestline then
  126.         task.wait(1)
  127.         startQuestline(player, obj.NextQuestline)
  128.     elseif obj.EndQuest then
  129.         questCompleteEvent:FireClient(player, questName)
  130.     else
  131.         startNextObjective(player, quest, obj)
  132.     end
  133. end
  134.  
  135. for _, quest in ipairs(AllQuestData) do
  136.     for _, obj in ipairs(quest.Objectives) do
  137.         local trigger = obj.Trigger
  138.         if not trigger then continue end
  139.  
  140.         if trigger:IsA("ProximityPrompt") then
  141.             trigger.Triggered:Connect(function(player)
  142.                 if hasTool(player, obj.Requires) then
  143.                     completeObjective(player, quest, obj)
  144.                 end
  145.             end)
  146.  
  147.         elseif trigger:IsA("BasePart") then
  148.             trigger.Touched:Connect(function(hit)
  149.                 local player = Players:GetPlayerFromCharacter(hit.Parent)
  150.                 if player and hasTool(player, obj.Requires) then
  151.                     completeObjective(player, quest, obj)
  152.                 end
  153.             end)
  154.  
  155.         elseif obj.TriggerType == "CanCollideChange" then
  156.             trigger:GetPropertyChangedSignal("CanCollide"):Connect(function()
  157.                 if trigger.CanCollide then
  158.                     for _, plr in ipairs(Players:GetPlayers()) do
  159.                         local pdata = playerData[plr.UserId]
  160.                         if pdata and pdata.Quests[quest.QuestName] and pdata.Quests[quest.QuestName].Started then
  161.                             completeObjective(plr, quest, obj)
  162.                         end
  163.                     end
  164.                 end
  165.             end)
  166.  
  167.         elseif obj.TriggerType == "ColorChange" and obj.ColorTarget then
  168.             trigger:GetPropertyChangedSignal("Color"):Connect(function()
  169.                 if trigger.Color == obj.ColorTarget then
  170.                     for _, plr in ipairs(Players:GetPlayers()) do
  171.                         local pdata = playerData[plr.UserId]
  172.                         if pdata and pdata.Quests[quest.QuestName] and pdata.Quests[quest.QuestName].Started then
  173.                             completeObjective(plr, quest, obj)
  174.                         end
  175.                     end
  176.                 end
  177.             end)
  178.  
  179.         else
  180.             warn("Unsupported trigger type for", obj.Name)
  181.         end
  182.     end
  183. end
  184.  
  185. for _, quest in ipairs(AllQuestData) do
  186.     if quest.StartTrigger then
  187.         local start = quest.StartTrigger
  188.         local function startQuest(player)
  189.             startQuestline(player, quest.QuestName)
  190.         end
  191.  
  192.         if start:IsA("BasePart") then
  193.             start.Touched:Connect(function(hit)
  194.                 local player = Players:GetPlayerFromCharacter(hit.Parent)
  195.                 if player then startQuest(player) end
  196.             end)
  197.         elseif start:IsA("ProximityPrompt") then
  198.             start.Triggered:Connect(startQuest)
  199.         else
  200.             warn("Invalid StartTrigger type for quest:", quest.QuestName)
  201.         end
  202.     end
  203. end
  204.  
  205. Players.PlayerAdded:Connect(function(player)
  206.     playerData[player.UserId] = playerData[player.UserId] or { Quests = {} }
  207.  
  208.     player.CharacterAdded:Connect(function()
  209.         task.wait(1)
  210.         local data = playerData[player.UserId]
  211.         if not data then return end
  212.  
  213.         for questName, questInfo in pairs(data.Quests) do
  214.             if questInfo.Started then
  215.                 for objName, _ in pairs(questInfo.Completed) do
  216.                     if globalProgress[questName] and globalProgress[questName][objName] then
  217.                         questInfo.Completed[objName] = true
  218.                     end
  219.                 end
  220.                 initEvent:FireClient(player, questName, questInfo.Completed)
  221.             end
  222.         end
  223.     end)
  224. end)
  225.  
  226. Players.PlayerRemoving:Connect(function(player)
  227.     playerData[player.UserId] = nil
  228. end)
  229.  
Advertisement
Add Comment
Please, Sign In to add comment