Commands#
Garbage Job is played at the NPC, not from chat. Every action is a keypress or a target option, and the job panel holds everything else — there is nothing for players to bind or type.
A practice command for the cleaning minigame#
Adding a command to Config.CleanDumpster registers a chat command that opens the cleaning minigame on the spot, in front of the player — handy for feeling out the timer and the threshold while you tune them. A practice run never moves a route forward and never pays experience.
Config.CleanDumpster = {
duration = 45000,
threshold = 0.90,
patches = 5,
bonusExperience = 15,
command = 'clean', -- /clean opens a practice run
}Leave command out — the default — and no command is registered.
Client Exports#
For opening the job's views from your own scripts — an NPC manager, a laptop prop, a radial menu.
openLeaderboard
Opens the Statistics view — the same one the panel's button opens, with all three rankings, the prizes and the last winners. It does nothing while Config.EnableLeaderboard is false.
exports['qs-garbagejob']:openLeaderboard()For example, a rankings board on a ped of your own:
exports.ox_target:addLocalEntity(myPed, {
{
name = 'garbage_leaderboard',
label = 'Garbage rankings',
icon = 'fa-solid fa-trophy',
onSelect = function()
exports['qs-garbagejob']:openLeaderboard()
end,
},
})From the server, open it on one player's screen with the client event:
TriggerClientEvent('qs-garbagejob:openLeaderboard', source)Server Exports#
How another resource asks about the job — a city-hall screen, a dispatch, a script that should not run while somebody is out on a route.
IsPlayerOnMission
Whether the server has a route assigned to that player right now. It is read from the server's own record — set when a route starts, cleared when it is paid, abandoned, or the player is removed or disconnects — so it is the answer to trust.
local working = exports['qs-garbagejob']:IsPlayerOnMission(source) -- true / falseFor example, keeping a collector out of another job until they finish their route:
RegisterNetEvent('myjobs:start', function()
local src = source
if exports['qs-garbagejob']:IsPlayerOnMission(src) then
return -- finish the garbage route first
end
-- start your job here
end)getOnDutyCount
How many players are working a route right now.
local collectors = exports['qs-garbagejob']:getOnDutyCount()
-- e.g. a city-hall screen
lib.callback.register('cityhall:jobStats', function()
return { garbage = exports['qs-garbagejob']:getOnDutyCount() }
end)isPlayerOnDuty
Whether a player is on duty, as their own client last reported it. It is kept for scripts that already use it; for anything that pays or permits something, use IsPlayerOnMission, which the server decides on its own.
local onDuty = exports['qs-garbagejob']:isPlayerOnDuty(source) -- true / falseNetwork Events#
Apart from qs-garbagejob:openLeaderboard, every network event the resource registers is internal. Each one is checked on the server against its own records — the route it assigned, the stop being worked, the invitation it sent — so firing them from another resource does nothing useful. Drive the job through the exports above instead.
About the Messages#
Every refusal reaches the player as a notification in the server's language, built from a key in config/translations.lua — NOTIFY_NOT_GARBAGE, PARKING_FULL, NOTIFY_ROUTE_NOT_FINISHED and the rest. Reword any of them there. Common Errors lists what each one means.



