§ How to · with Forge AI
How to make a Roblox quest system (with AI)
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
A Roblox quest system needs five pieces: NPC quest givers, objective tracking, progress saves, reward delivery, and a quest log UI. Forge AI generates all five in 1m 18s — including branching dialogue and step-by-step objective text.
9 files · 310 lines · 1m 18s · 1 credit. ProfileService-style save flow.
NPC quest givers
Tag any character model with CollectionService 'QuestGiver' and a QuestId attribute. The proximity prompt + dialogue UI is automatic.
Objective types
Kill X enemies, collect X items, reach X location, talk to X NPC. Mix-and-match per quest. Objectives complete in any order or sequentially (configurable).
Progress tracking
Server stores per-player quest state — active quests, completed objectives, completed quests. DataStore-backed with retry.
Branching objectives
Quest can have multiple choice paths (kill the dragon OR negotiate with it). Player choice locks the path; downstream quests reference the choice.
Reward delivery
Cash, items, XP, gamepass-style unlocks. Multiple rewards per quest. Delivered atomically on quest completion.
Quest log UI
Slide-out panel showing active quests, current objectives, completed quests. Tabbed by category (main, side, daily). Tap a quest to set it as the tracked quest on the HUD.
Files Forge AI ships for this prompt
9 files · 310 lines · 1m 18s · 1 credit
ServerScriptService/QuestManager.lua
Quest state, objective progress, reward delivery
96 lines
ServerScriptService/QuestSaveService.lua
Per-player quest state DataStore
42 lines
ReplicatedStorage/Modules/QuestConfig.lua
Quest definitions — objectives, rewards, prerequisites
78 lines
ReplicatedStorage/Remotes/QuestAccept
Player accepts quest from NPC
instance
ReplicatedStorage/Remotes/QuestUpdate
Server → client progress update
instance
ReplicatedStorage/Remotes/QuestTurnIn
Player turns in to NPC
instance
StarterGui/QuestLog.lua
Slide-out quest log panel
52 lines
StarterGui/QuestHUD.lua
Currently tracked quest objective overlay
24 lines
StarterGui/QuestPrompt.lua
NPC dialogue + accept/decline UI
28 lines
Sample output: ServerScriptService/QuestManager.lua
--!strict
-- ServerScriptService/QuestManager.lua (Forge AI · excerpt)
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local QuestConfig = require(ReplicatedStorage.Modules.QuestConfig)
local SaveService = require(script.Parent.QuestSaveService)
local QuestUpdate = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("QuestUpdate")
type Quest = { id: string, active: { [string]: number }, completed: { [string]: boolean } }
local function getState(player: Player): Quest
return SaveService:Get(player) or { id = "", active = {}, completed = {} }
end
local function notifyProgress(player: Player, questId: string, objectiveId: string, current: number)
QuestUpdate:FireClient(player, { questId = questId, objective = objectiveId, current = current })
end
local QuestManager = {}
function QuestManager:reportEvent(player: Player, eventType: string, target: string?)
-- eventType: "kill", "collect", "reach", "talk"
local state = getState(player)
for activeId, _ in pairs(state.active) do
local def = QuestConfig[activeId]
if not def then continue end
for _, obj in ipairs(def.objectives) do
if obj.type == eventType and (not obj.target or obj.target == target) then
local key = activeId .. ":" .. obj.id
state.active[key] = (state.active[key] or 0) + 1
notifyProgress(player, activeId, obj.id, state.active[key])
if state.active[key] >= obj.required then
-- Check if all objectives done → complete quest
QuestManager:tryComplete(player, activeId, def, state)
end
end
end
end
SaveService:Set(player, state)
end
return QuestManagerBuilding a Roblox quest system
Quest systems are the backbone of RPG-style Roblox games. The defining property of a good quest system is that adding new quests does not require touching the engine — only adding data. Forge AI ships exactly that pattern.
The Forge AI quest prompt produces a 9-file system in 1m 18s. QuestConfig.lua is the data layer — adding a new quest is adding a table entry. QuestManager.lua is the engine layer — it reads QuestConfig and never needs to change. This separation is why production RPG games scale to hundreds of quests without becoming unmaintainable.
Objective tracking is event-driven. The Combat system calls QuestManager:reportEvent(player, 'kill', 'goblin') on every kill. QuestManager checks every active quest for objectives matching ('kill' + 'goblin') and increments their counters. The player gets a HUD popup ('3/10 goblins defeated'). Adding a new objective type is one method, not a refactor.
Branching paths are the design depth. A quest can have a 'choice' group — kill the dragon or negotiate with it. Completing either locks the others, the choice is recorded, and downstream quests can read the choice from state.completed. This enables player-driven story arcs without scripting each branch separately.
The quest log UI is the player-facing payoff. A slide-out panel shows active quests, current objective text, and completed quests. Tap any active quest to set it as the 'tracked quest' — its current objective shows in a HUD overlay. Players never lose track of what to do next, which is the single biggest retention factor in quest-driven games.
See more on the Luau generator, the game builder, or browse the full blog.
Frequently asked
How do I add a new quest?+
Add an entry to QuestConfig.lua: id, name, description, objectives table, rewards table. The QuestManager picks it up automatically — no code changes. Forge generates new quest entries on follow-up prompts.
Can quests have prerequisites (must complete Quest A before Quest B)?+
Yes. Each quest definition has a 'requires' field listing prerequisite quest IDs. QuestManager:canAccept() checks the player's completed quests before allowing acceptance.
How do branching quests work?+
An objective can have multiple sub-objectives marked with a 'choice' group. Completing any one locks the others. Downstream quests can check which path was taken via state.completed['questA:choiceB'].
How is progress saved?+
QuestSaveService writes the state table to DataStore on every objective progress event. To minimize writes, the actual save is debounced — the table updates in memory immediately, but DataStore writes happen at most every 30 seconds (or on PlayerRemoving).
Can I have repeatable daily quests?+
Yes. Daily quests reset every 24 hours via the server clock authority pattern. Forge integrates with the daily-rewards system if you have one already — the clock check is shared.
Related Forge AI prompts
Roblox dialogue system
6 files · 180 lines · 52 seconds · 1 credit. Tree-structured dialogue, modular config.
Roblox daily rewards
5 files · 170 lines · 49 seconds · 1 credit. 7-day cycle by default, configurable.
How to use Roblox DataStore the right way
3 files · 140 lines · 36 seconds · 1 credit. Drop-in save service for any game.