I’ve been building some quests and making tools to use with AI and NPCs to tell stories. I recently compiled a neat library of all the functions I use for building quests. What do you think? First, here’s a quest I’m working on using the library.
local function warehousepart1()
q.quicktime(Warehouse,nil,nil,function(player)
q.message(nil,nil,player,Warehouse,"Hey! Do you have any experience getting rid of bee hives?")
q.message(nil,nil,player,player.Character,"Beehives huh?")
q.registerevent(player,Warehouse,{yes=function()
q.message(nil,nil,player,Warehouse,"Alright, You're hired! You take out these bee hives and I'll give you 2000 gold. What do you say shake on it?")
q.quicktime(Warehouse,"shake hands",nil,function()
q.message(nil,nil,player,player.Character,"You got yourself a deal!")
q.message(nil,nil,player,Warehouse,"Excellent!")
q.defeatenemys(player,script.Parent.BeeHives,{[1]=function()
q.message(nil,nil,player,Warehouse,"Look's like you got one!")
q.message(nil,nil,player,player.Character,"One down, one more to go.")
end,[0]=function()
q.message(nil,nil,player,Warehouse,"Great work! Here's your 2000 gold.")
q.statmodifier(player,"Gold",2000)
q.message(nil,nil,player,Warehouse,"So, my guys who do the warehouse ran out of here for the day due to the bees. Would you move these boxes to the pallets in the shipping bay?")
q.registerevent(player,Warehouse,{yes=function()
q.message(nil,nil,player,Warehouse,"Amazing! Just get that done and I pay you another 3000 gold.")
q.boxtouchpad(script.Parent.ActivationPads,script.Parent.ActivationPads,3,function()
q.statmodifier(player,"Gold",3000)
q.message(nil,nil,player,Warehouse,"You sure are a hard worker! I can't believe you lifted those boxes like that! Here's your 3000 gold. I appreciate all your help. Stop by again sometime.")
end)
end,
no=function()
q.message(nil,nil,player,Warehouse,"No? well that's too bad...")
end,})
end,})
end)
end,
no=function()
q.message(nil,nil,player,Warehouse,"No? well that's too bad...")
end,})
end,nil,"talk")
end
The nil,nil in the message is for voiceline timings. The actual module itself is this lightweight masterpiece. All the modules are individual functions that are either doing specific things or firing nodes handling different things abstractions on the message function are huge. It displays text, plays animations.
local QuestModules = {
-- 📦 Utility
checkinvent = game.ReplicatedStorage.GlobalSpells.Questing.Util.checkinvent, -- (player,item,take,reward)
giveitem = game.ReplicatedStorage.GlobalSpells.Questing.Util.giveitem,
rewards = game.ReplicatedStorage.GlobalSpells.Questing.Util.rewards, -- (keywords,exactword)
nearestplayer = game.ReplicatedStorage.GlobalSpells.Questing.EFX.nearestplayer, -- (position,distance)
disappear = game.ReplicatedStorage.GlobalSpells.Disappear,
touched= game.ReplicatedStorage.GlobalSpells.Questing.Util.Touched,--(Trigger,payloadfunction,singleuse)
boxtouchpad = game.ReplicatedStorage.GlobalSpells.Questing.Util.MoveBoxActivationPads,--(Blocks,core,activationthreshold,payload) --if duration is nil then return puddle release.
chopminegoal = game.ReplicatedStorage.GlobalSpells.Questing.Util.ChopDownTreeGoal,--(tree,payloadfunction)
-- 🎵 Dialogue & Atmosphere
message = game.ReplicatedStorage.GlobalSpells.Questing.Util.Message2,
playsound = game.ReplicatedStorage.GlobalSpells.Questing.Util.playsound,
music = game.ReplicatedStorage.GlobalSpells.Questing.Util.PlayAtmosphere, -- (player,keyword)
cutscene = game.ReplicatedStorage.GlobalSpells.Questing.Util.Cutscene, -- (player,CutsceneData,ScenePrimaryPart)
weather = game.ReplicatedStorage.GlobalSpells.Questing.Util.weather, -- (player,weatherstate)
-- ⚡ Special Effects
dropitem = game.ReplicatedStorage.GlobalSpells.Questing.Util.dropitem, -- (player,reward:string,cframe)
droprandomitem= game.ReplicatedStorage.GlobalSpells.Questing.Util.droprandomitem,
lootarea = game.ReplicatedStorage.GlobalSpells.Questing.Util.lootarea, -- (loottable,centerobject,radius)
energyball = game.ReplicatedStorage.GlobalSpells.Questing.EFX.Energyballflash, -- (script)
statmodifier = game.ReplicatedStorage.GlobalSpells.Questing.EFX.StatModifier, -- (player,key,value)
damage = game.ReplicatedStorage.GlobalSpells.Questing.EFX.Damage, -- (hit:BasePart,Damage:number,Element:string,CombatStyle:number,Attacker:Instance,Humanoid)
damageBrick = game.ReplicatedStorage.GlobalSpells.Questing.EFX.DamageBrick, -- (part:BasePart,MaxDamage:number,Persistent:bool,Element:string,CombatStyle:number,Attacker:Instance)
dropspellcard = game.ServerStorage.ServerModules.DungeonModules.SpellCardSpawn,--(position,specific)
drippuddle = game.ReplicatedStorage.GlobalSpells.Questing.Util.PuddleUtil,--(Adornee,PuddleKey or "Blood",Duration)--if duration is nil then return puddle release.
-- AI Effects
faceoff = game.ReplicatedStorage.GlobalSpells.Questing.Util.FaceOff, -- (target,both,Player,Character)
path = game.ReplicatedStorage.GlobalSpells.Questing.Util.pathing,
simplepath = game.ReplicatedStorage.GlobalSpells.Questing.Util.SimplePath, -- (subject:model, position)
follow = game.ReplicatedStorage.GlobalSpells.Questing.Util.FollowMe, -- (model,part)
interacttool = game.ReplicatedStorage.GlobalSpells.Questing.Util.ToolUser, -- (model,object,key,objectprimarypart or nil)
interact = game.ReplicatedStorage.GlobalSpells.Questing.Util.interact,
inventory = game.ReplicatedStorage.GlobalSpells.Questing.Util.InventInterface,--(character,ItemString,player:Optional)
seat = game.ReplicatedStorage.GlobalSpells.Questing.EFX.InteractWithSeat,--(Seat,Character,ProximityPrompt,player)
readbook = game.ReplicatedStorage.GlobalSpells.Questing.EFX.ReadBook,--(player,character,wikiresult)--if duration is nil then return puddle release.
transform = game.ReplicatedStorage.GlobalSpells.Questing.EFX.TransformWrapper,-- (character,formlist)
enemyai = game.ServerStorage.ServerModules.BasicAISetup,--(model)
emote = game.ReplicatedStorage.GlobalSpells.Questing.Util.PlayAnimation,--(character,animation,duration,looped)
-- 🎯 Events & Registration
registerevent = game.ReplicatedStorage.GlobalSpells.Questing.Util.registerevent,
registerchoiceevent= game.ReplicatedStorage.GlobalSpells.Questing.Util.registerchoiceevent,
quicktime = game.ReplicatedStorage.GlobalSpells.Questing.EFX.QuicktimeEvent, -- (model:Instance,key:String,timer:Number,payload:function)
-- 🗡️ Quest Interactions
battle = game.ServerStorage.GlobalSpells.Questing.Util.Battle,--(model)
askmathquestion= game.ReplicatedStorage.GlobalSpells.Questing.Util.mathquestion, -- ({player,model},Level)
findquest = game.ReplicatedStorage.GlobalSpells.Questing.Util.FindQuest, -- (ProximityPrompt, model, script,playscript,rewards)
protectquest = game.ReplicatedStorage.GlobalSpells.Questing.Util.DarknessArise, -- (player,centerPos,Minion,Target,Radius,SpawnAmnt,MaxScale,dialogues)
chasesequence = game.ReplicatedStorage.GlobalSpells.Questing.Util.ChaseSequence, -- (player,TombRaider,paths,dialogues)
bossbattle = game.ReplicatedStorage.GlobalSpells.Questing.Util.BossBattle, -- (player,Goddess,dialogues,custombattlephases)
defeatenemys = game.ReplicatedStorage.GlobalSpells.Questing.Util.DefeatEnemys, -- (player,enemys:array)
flychasesequence = game.ServerStorage.GlobalSpells.Questing.Util.FlyingChase,--(model)
questgen = game.ReplicatedStorage.GlobalSpells.Questing.Util.QuestController, -- (player,model,ProximityPrompt,QuestType,ObjectClass,Objective,PersonalityModule,VoicelineObject)
}
local environments={
envir = game.ReplicatedStorage.GlobalSpells.EnvirMod,
}
local LoadedModules = {}
local QuestFunctions = {}
for i,v in QuestModules do
QuestFunctions[i] = function(...)
if not LoadedModules[i] then
LoadedModules[i] = require(v)
end
return LoadedModules[i](...)
end
end
for i,v in environments do
QuestFunctions[i]=v
end
QuestFunctions.spell=function(key,arguments)
game.ReplicatedStorage.GlobalSpells.Generate:Invoke(key,arguments)
end
local LoadedModules={}
local QuestFunctions={}
for i,v in QuestModules do
QuestFunctions[i]=function(...)
if LoadedModules[i]==nil then
LoadedModules[i]=require(QuestModules[i])
end
return LoadedModules[i](...)
end
end
--[[
local q=require(game.ReplicatedStorage.GlobalSpells.Questing.QuestBuilder)
local debounce={}
local envir=require(q.envir)
local player=q.nearplayer(Vector3.new(1,1,1),1000)
q.message(nil,nil,player,player.Character,"What's happening?!")
local Minion=envir.GetNPC("darkness"):Clone()
q.defeatenemys(player,{Minion},{[1]=function()
q.message(nil,nil,player,player.Character,"Hmm.. I wonder what that was all about.")
local Minion2=envir.GetNPC("darkness")
q.protectquest(player,player.Character.PrimaryPart.CFrame,Minion2,player.Character.PrimaryPart,10,4,nil,{
Opening=function()
q.message(nil,nil,player,player.Character,"More? What are these things?")
end,
--suggested if you have a target
Protected=function()
q.message(nil,nil,player,player.Character,"They are not that tough.")
end,
}
)
end,})
]]
return QuestFunctions
This organized setup is such a blast.

