UniQueue
UniQueue is a server-side queue and party system built into the bridge. It handles mission queuing, priority, police requirements, cooldowns, and concurrent task limits. Most Prodigy Studios crime and civ missions use it to control when and how missions start.
How it works
- A resource creates a queue with a name, type, police requirement, and concurrency limit.
- Players form a party (often linked to a group) and join the queue.
- The queue runs periodically: it sorts by priority, checks police and cooldowns, then runs the top party via your callback.
- The party is removed and destroyed. When the mission ends and you mark the task complete, the queue enters its cooldown before processing the next party.
Using existing Prodigy resources
You do not need to create queues or parties yourself when using an existing Prodigy Studios mission. The queue is already set up in that resource’s config. This page is for developers building custom missions.
Configuration
UniQueue is configured in config.lua under BridgeConfig.Uniqueue.
BridgeConfig.Uniqueue = {
MaxOverTimePriority = 30,
AddOverTimePriorityTime = math.floor(2.5 * 60),
HoldQueuesOnStartTime = 0,
PoliceStrengthPerPlayer = 1,
PoliceJobs = {
"lspd",
"police",
"bsco",
}
}| Option | Type | Default | Description |
|---|---|---|---|
MaxOverTimePriority | number | 30 | Max priority points a party can gain from waiting. |
AddOverTimePriorityTime | number | 150 | Seconds between each priority point gain. |
HoldQueuesOnStartTime | number | 0 | Seconds to hold all queues after server start. |
PoliceStrengthPerPlayer | number | 1 | Police power per on-duty officer. |
PoliceJobs | string[] | { "lspd", "police", "bsco" } | Job names that count as police. |
Queue types
Every queue and party has a type. A party can only join a queue of the same type.
| Type | Description |
|---|---|
"civ" | Civilian missions (fishing, mining, farming, etc.). |
"crime" | Crime missions (robberies, heists, smuggling, etc.). |
Server exports
Queue
| Export | Parameters | Returns | Description |
|---|---|---|---|
CreateQueue | (name, type, requiredPolicePower, maxConcurrentTasks, cooldown) | UniQueue | Creates a new queue. |
GetQueue | (name: string) | UniQueue? | Returns the queue by name, or nil. |
GetQueuesByType | (type: UniQueueType) | table<string, boolean> | All queue names of that type. |
Party
| Export | Parameters | Returns | Description |
|---|---|---|---|
CreateParty | (type: UniQueueType) | UniQueueParty | Creates a new party. |
GetParty | (uuid: string) | UniQueueParty? | Returns the party by UUID, or nil. |
GetPartiesByType | (queueType: UniQueueType) | table<string, boolean> | All party UUIDs of that type. |
GetPartiesFromPlayer | (identifier: string) | table<string, boolean> | All party UUIDs the player is in. |
Creating a queue
local queue = exports["prp-bridge"]:CreateQueue(
"my_mission",
"crime",
4,
1,
60
)| Parameter | Type | Description |
|---|---|---|
name | string | Unique queue identifier. |
type | UniQueueType | "civ" or "crime". |
requiredPolicePower | number | Police power required to run (each officer adds PoliceStrengthPerPlayer). |
maxConcurrentTasks | number | Max missions from this queue at once. |
cooldown | number | Seconds after a task ends before next run. |
Queue methods
setExecFunction
Sets the callback run when a party is dequeued and ready to start.
queue.setExecFunction(function(queueName, partyUuid, partyMembers, taskId)
startMission(partyMembers, taskId)
end)Task state
The queue marks the task as executing before your callback runs. Call queue.setTaskIsExecuting(taskId, false) when the mission ends to free the slot.
setCheckFunction
Optional validation before execution. Return true to allow, false to skip this party for now.
queue.setCheckFunction(function(queueName, partyUuid)
local party = exports["prp-bridge"]:GetParty(partyUuid)
if not party then return false end
return #party.getMembersAsArray() >= 2
end)setTaskIsExecuting
Marks the task as complete. Call with false when the mission ends.
queue.setTaskIsExecuting(taskId, false)stopExec
Cancels execution for a party.
queue.stopExec(partyUuid)Other queue methods
| Method | Returns | Description |
|---|---|---|
getName() | string | Queue name. |
getNumOfExecTasks() | number | Number of running tasks. |
isExecAtFullCapacity() | boolean | Whether at max concurrent tasks. |
getUsedPolicePower() | number | Police power used by running tasks. |
add(party) | { success, error? } | Adds a party. |
remove(party) | Removes a party. | |
setPartyPriority(party, priority) | Sets party priority. | |
getPartyPriority(partyUuid) | number? | Party priority. |
getPartyPosition(partyUuid) | number? | Position in queue. |
isPartyIn(partyUuid) | boolean | Whether party is in this queue. |
setCooldown(cooldown) | Sets cooldown in seconds. | |
clearCooldown() | Clears cooldown. | |
setBlocked(blocked) | Blocks or unblocks the queue. | |
isBlocked() | boolean | Whether the queue is blocked. |
Creating a party
local party = exports["prp-bridge"]:CreateParty("crime")Adding members
local result = party.addMember(playerIdentifier)
if not result.success then
print(result.error)
endOne party per type
A player can only be in one party per type. Adding them to a second "crime" party will fail if they are already in one.
Removing members
party.removeMember(playerIdentifier)Party methods
| Method | Returns | Description |
|---|---|---|
getUUID() | string | Party UUID. |
setUUID(uuid) | Sets UUID (e.g. for group link). | |
getType() | UniQueueType | Party type. |
getPosition() | number | Queue position (0 if not in a queue). |
getEnterId() | number | Entry order ID. |
getPriority() | number | Current priority. |
setPriority(priority) | Sets priority. | |
addMember(identifier) | { success, error? } | Adds a member. |
removeMember(identifier) | Removes a member. | |
getMembers() | table<string, UniQueuePartyMember> | All members. |
getMembersAsArray() | string[] | Member identifiers. |
destroy() | Destroys the party. |
Priority
Parties are sorted by priority (highest first). Same priority: first in, first out.
- Every
AddOverTimePriorityTimeseconds, a waiting party gains 1 priority (up toMaxOverTimePriority). - You can set priority with
queue.setPartyPriority(party, priority)orparty.setPriority(priority).
Groups integration
The bridge’s group system can create and manage UniQueue parties. When using groups, you usually do not create parties manually.
local group = exports["prp-bridge"]:GetGroupFromMember(source)
group.createUniqueueParty("crime")
local result = group.enterUniqueue("my_mission")
if not result.success then
print(result.error)
endWhen members join or leave the group, they are added to or removed from the party automatically.
Player disconnect
When a player disconnects or their character unloads, they are removed from all parties they were in.
Events
| Event | Parameters | Description |
|---|---|---|
prp-bridge:uniqueue:partyDestroyed | (partyUuid: string) | Fired when a party is destroyed. |
Admin commands
All commands require group.admin.
| Command | Parameters | Description |
|---|---|---|
/uni_findplayer | <identifier> | Find all parties for a player. |
/uni_setprio | <partyUuid> <priority> | Set party priority. |
/uni_rmfromque | <partyUuid> <queueName> | Remove party from queue. |
/uni_setblocked | <queueName> <0|1> | Block (1) or unblock (0) a queue. |
/uni_setcooldown | <queueName> <seconds> | Set queue cooldown. |
/uni_clearcooldown | <queueName> | Clear queue cooldown. |
/uni_totalblock | <0|1> | Block or unblock all queues. |
/uni_cleartask | <queueName> <taskId> | Clear a stuck task. |
/uni_devmode | Toggle debug logging. |
Full example
Click to expand full example
local queue = exports["prp-bridge"]:CreateQueue("bank_heist", "crime", 4, 1, 120)
queue.setExecFunction(function(queueName, partyUuid, partyMembers, taskId)
for _, identifier in ipairs(partyMembers) do
local player = getPlayerByIdentifier(identifier)
if player then
TriggerClientEvent("bank_heist:start", player)
end
end
activeHeists[partyUuid] = taskId
end)
queue.setCheckFunction(function(queueName, partyUuid)
local party = exports["prp-bridge"]:GetParty(partyUuid)
if not party then return false end
return #party.getMembersAsArray() >= 2
end)
function endHeist(partyUuid)
local taskId = activeHeists[partyUuid]
if taskId then
queue.setTaskIsExecuting(taskId, false)
activeHeists[partyUuid] = nil
end
end