Every roleplay server needs work. Players need ways to earn money, police need to arrest people, and medics need to pick players up off the street. Quasar Framework (qs-core) comes with all of it: a Job Center, four civilian jobs (miner, lumberjack, fisher and delivery driver), a complete FiveM police job, a FiveM EMS / ambulance job with body-zone injuries and a stretcher, and a drug economy with weed, cocaine and meth. Everything runs on the same job system that ESX and QBCore scripts read. A player you hire with /setjob is a cop for qs-police, for an ESX script that checks xPlayer.job.name and for a QBCore script that checks job.type == 'leo'.
This page explains how jobs, grades and paychecks work, then goes through each job: what the player does, where to go, what it pays and every setting that controls it.
Resource | Folder | What it adds | Needs |
|---|---|---|---|
|
| Job Center, miner, lumberjack, fisher, delivery driver |
|
|
| Police job: cuffs, escort, search, fines, evidence, forensics lab, armory, garage, dispatch alerts |
|
|
| EMS job: injuries, treatment, revive, stretcher, garage, hospital check-in, EMS calls |
|
|
| Weed, cocaine and meth: gather, process, sell to dealers |
|
The txAdmin recipe installs and starts all four. Job definitions, grades, salaries and the death system live in qs-core itself. Every message these jobs show follows the server language you set with setr qs:locale "<code>" in server.cfg.
How jobs work in Quasar Framework#
A job is a name (police), a label players see (Police) and a list of grades. Each grade has its own label and salary. Every character holds exactly one job and one grade at a time. The job is saved with the character and shown on the HUD.
Jobs are defined in one file, [core]/qs-core/shared/jobs.lua:
['police'] = {
label = 'Police',
defaultDuty = false,
grades = {
[0] = { name = 'recruit', label = 'Recruit', salary = 500 },
[1] = { name = 'officer', label = 'Officer', salary = 750 },
[2] = { name = 'sergeant', label = 'Sergeant', salary = 1000 },
[3] = { name = 'boss', label = 'Chief', salary = 2000, isBoss = true },
},
},Grade field | What it does |
|---|---|
| The grade level. Level |
| Internal grade name. ESX scripts read it as |
| Name players and scripts see ( |
| Paid into the bank every paycheck. |
| Marks the boss grade. ESX and QBCore boss menus and scripts read it ( |
Default jobs#
Job ( | Label | Grades (level · label · salary) | Used by |
|---|---|---|---|
| Civilian | 0 · Freelancer · $200 | New characters. Also the job you get when you quit at the Job Center. |
| Police | 0 · Recruit · $500 — 1 · Officer · $750 — 2 · Sergeant · $1,000 — 3 · Chief · $2,000 (boss) |
|
| EMS | 0 · Trainee · $500 — 1 · Paramedic · $800 — 2 · Doctor · $1,200 — 3 · Chief · $2,000 (boss) |
|
| Delivery Driver | 0 · Driver · $200 |
|
| Miner | 0 · Miner · $175 |
|
| Lumberjack | 0 · Lumberjack · $175 |
|
| Fisherman | 0 · Fisherman · $150 |
|
| Hunter | 0 · Hunter · $200 | Defined only. No activity ships for it, so it is ready for your own or a third-party hunting script. |
New characters start as unemployed grade 0. You can change this with Config.DefaultJob and Config.DefaultJobGrade in [core]/qs-core/shared/config.lua. The job you set there must exist in jobs.lua.
Paychecks#
Quasar Framework pays salaries itself, so no job script has to. Every 30 minutes, every player online with a loaded character receives the salary of their current grade in their bank account and sees Paycheck received: $X. A grade with salary = 0 gets nothing.
Option ( | Default | What it does |
|---|---|---|
|
| Turns paychecks on or off. |
|
| Time between paychecks, in milliseconds. |
Giving someone a job#
How | Example | Notes |
|---|---|---|
Job Center | Walk in and apply | Civilian jobs only, always at grade |
Admin command |
|
|
Admin menu | Player list → set job | See Administration. |
Your scripts |
| Server side. ESX and QBCore equivalents are in the tabs below. |
If you ask for a grade the job doesn't have, the player gets the job's lowest grade. Police and EMS are not offered at the Job Center. They are whitelisted jobs, so you hire officers and medics with /setjob or the admin menu. Promotions work the same way: run /setjob again with the new grade.
# hire player 12 as a Police Officer, promote them later to Sergeant
setjob 12 police 1
setjob 12 police 2
# hire player 7 as an EMS Trainee
setjob 7 ambulance 0ESX and QBCore jobs: how scripts see them#
The es_extended and qb-core compatibility bridges read the job straight from qs-core, and they write it back to qs-core too. A job set by any script is the same job everywhere.
xPlayer.job and xPlayer.getJob() return the job in ESX Legacy shape:
-- xPlayer.getJob() for a Police Sergeant
{
id = 1, name = 'police', label = 'Police',
grade = 2, grade_name = 'sergeant', grade_label = 'Sergeant', grade_salary = 1000,
skin_male = {}, skin_female = {},
}ESX.GetJobs()returns every qs-core job in ESX shape (grades["0"],grades["1"]…).ESX.DoesJobExist(job, grade)checks qs-core jobs.ESX.GetExtendedPlayers('job', 'police')returns every online officer.esx:setJobfires on the server (source, job, lastJob) and on the client (job, lastJob) whenever the job changes.xPlayer.setJob(name, grade)writes to qs-core. If the job doesn't exist yet, it is created with grades0employee,1experienced,2advanced and3boss.
Player.PlayerData.job returns the job in QBCore shape:
-- PlayerData.job for an EMS Paramedic
{
name = 'ambulance', label = 'EMS', payment = 800,
type = 'ems', onduty = true, isboss = false,
grade = { name = 'Paramedic', level = 1 },
}typeisleoforpoliceandemsforambulance, so QBCore scripts that check the job type recognise both.On the server,
QBCore.Shared.Jobscontains every qs-core job in QBCore shape (grades['0'] = { name, payment, isboss }).QBCore:Server:OnJobUpdate(source, job) andQBCore:Client:OnJobUpdate(job) fire on every job change.Player.Functions.SetJob(name, grade)writes to qs-core. Unknown jobs are created fromQBCore.Shared.Jobsif you defined them there, otherwise with grades0–4.Jobs you put in
[bridge]/qb-core/shared/jobs.lua(QBCore format) are registered in qs-core when the server starts. That makes it easy to paste the jobs a QBCore script ships with.
Native scripts use qs-core directly:
-- server
exports['qs-core']:SetJob(source, 'ambulance', 1)
local jobs = exports['qs-core']:GetJobs()
local player = exports['qs-core']:GetPlayer(source)
local job = player.getJob()
-- { name, label, grade, gradeName, gradeLabel, salary, isBoss, onduty }
AddEventHandler('qs:server:jobChange', function(src, job)
print(src, job.name, job.grade)
end)-- client
AddEventHandler('qs:client:onJobUpdate', function(job)
print('My job is now', job.label, job.gradeLabel)
end)exports['qs-core']:RegisterJob(name, def) adds a job at runtime on the server, using the same table shape as jobs.lua.
Installing an ESX or QBCore job script? Define the jobs and grades it expects in
jobs.lua(or inqb-core/shared/jobs.luafor QBCore scripts) before you start it. See ESX & QBCore Compatibility.
FiveM Job Center#
The Job Center is where civilians find work. It is a public blip labelled Job Center in downtown Los Santos (vec4(-268.24, -957.29, 31.22, 205.0)), with a businessman holding a clipboard. New characters spawn right next to it (qs-core's Config.DefaultSpawn), so it is the first thing a new player sees.
Walk up to the clerk
Within 2.2 m you see Press E to browse jobs.
Press E
The Job Center window opens. Each job has a card with its name, a short description and its paycheck (the grade
0salary). Your current job is marked Current job.Apply
Click Apply on a job. You are hired at grade
0(You are now employed as Miner), the window closes and that job's blips appear on your map.Quit
Click Quit job to go back to Civilian (
unemployed). You see You quit your job.
You have to stay at the Job Center while you apply, and you can't apply for the job you already have. Changing job has no cooldown.
Jobs offered#
Job | Label on the card | Paycheck (every 30 min) | Earns mostly from |
|---|---|---|---|
| Delivery Driver | $200 | $45–65 per package plus a $150 route bonus |
| Miner | $175 | Metal ingots and gold nuggets |
| Lumberjack | $175 | Wood planks |
| Fisherman | $150 | Mackerel, bass and tuna |
Adding a job to the Job Center#
The Job Center only lists jobs that exist in both places: qs-core's job list and the Job Center's own list. Add a new job to both.
Define the job in qs-core
Add it to
[core]/qs-core/shared/jobs.lua:lua ['mechanic'] = { label = 'Mechanic', defaultDuty = true, grades = { [0] = { name = 'apprentice', label = 'Apprentice', salary = 250 }, [1] = { name = 'mechanic', label = 'Mechanic', salary = 400 }, [2] = { name = 'boss', label = 'Owner', salary = 800, isBoss = true }, }, },Add it to the Job Center list
In
[addons]/qs-jobs/config.lua, add the job name toConfig.Center.jobs:lua Config.Center = { -- ... jobs = { 'delivery', 'miner', 'lumberjack', 'fisher', 'mechanic' }, }Give it a description (optional)
The card text comes from the key
desc_<job>in qs-jobs' language files. Add a line to[addons]/qs-jobs/locales/en.luaand to every other language you use:lua desc_mechanic = 'Repair and tune vehicles for the people of Los Santos.',Without it the card has no description. Jobs without a built-in icon get a generic one.
Restart the server
The new job shows up on the Job Center list. Applicants always start at grade
0.
Civilian jobs: miner, lumberjack, fisher and delivery (qs-jobs)#
qs-jobs adds four legal jobs for roleplay servers: three gather → process → sell jobs (miner, lumberjack, fisher) and a delivery driver route. They all work the same way:
You need the job. Each job's blips appear only on the map of players who hold it. At another job's point you see You don't have the right job for this. The peds, rocks and trees are visible to everyone.
Press E within 2.2 m of a point. A progress bar runs while you are frozen in place. Press X to cancel, which gives no reward.
Spots deplete. A rock, tree or fishing spot you have just used is empty for you for 20 seconds. Move to the next one.
Full inventory. If the reward doesn't fit, you get Your inventory is full and nothing is lost.
You're paid in cash. Sales, delivery pay, the delivery bonus and the van deposit all use the
cashaccount (Config.PayAccount).Selling is all at once. At a buyer, one press of E sells every sellable item you carry. The buyer rolls one price per item type, within that item's range, and pays it for every unit of that type. The total goes into your cash (You sold your goods for $X).
Miner#
Mine stone at the quarry, smelt it into ingots at the foundry and sell them. Keep an eye out for gold.
Mine at the Quarry
Go to one of the four Quarry zones at the Davis Quartz quarry. Each zone has 7 rocks, 28 in total. Press E at a rock to hammer for 7 seconds and get 1–2 Stone. Every successful swing also has a 6 % chance of a bonus Gold Nugget (You found something rare: Gold Nugget!).
Smelt at the Foundry
At the Foundry, press E to turn 3 Stone into 1 Metal Ingot (6 seconds). Repeat for each batch. If you don't have enough stone you see You don't have enough materials.
Sell to the Metal Buyer
Bring your ingots and nuggets to the Metal Buyer and press E to sell them all.
Item | Comes from | Weight | Sold for (each) |
|---|---|---|---|
| Quarry, 1–2 per swing | 0.9 kg | — (smelt it) |
| Foundry, 3 stone → 1 ingot | 1.2 kg | $70–90 |
| Quarry, 6 % bonus | 0.2 kg | $250–350 |
Point | Blip | Location |
|---|---|---|
Quarry (4 zones) | Quarry |
|
Foundry | Foundry |
|
Metal Buyer | Metal Buyer |
|
Lumberjack#
Chop logs in the Paleto forest, cut them into planks at the sawmill and sell the lot.
Chop at the Forest
Six birch trees stand in the Forest in Paleto Forest. Press E at a tree to swing your axe for 7 seconds and get 1–2 Wood Logs.
Cut at the Sawmill
At the Sawmill, press E to turn 2 Wood Logs into 1 Wood Plank (5 seconds).
Sell to the Wood Buyer
Take your planks to the Wood Buyer and press E to sell them all.
Item | Comes from | Weight | Sold for (each) |
|---|---|---|---|
| Forest, 1–2 per tree | 1.5 kg | — (cut it) |
| Sawmill, 2 logs → 1 plank | 0.8 kg | $45–60 |
Point | Blip | Location |
|---|---|---|
Forest (6 trees) | Forest |
|
Sawmill | Sawmill |
|
Wood Buyer | Wood Buyer |
|
Logs are heavy (1.5 kg each), so empty your pockets before a long chopping run.
Fisher#
Cast your line off the pier. Different fish sell for different prices at the fish market. There is nothing to process.
Fish at a Fishing Spot
Stand at one of the three Fishing Spots at the end of Del Perro Pier and press E. Your character fishes for 9 seconds and catches one fish: Mackerel 60 % of the time, Bass 30 %, Tuna 10 %.
Sell at the Fish Market
Take your catch to the Fish Market and press E to sell every fish you carry.
Item | Chance per catch | Weight | Sold for (each) |
|---|---|---|---|
| 60 % | 0.4 kg | $25–35 |
| 30 % | 0.7 kg | $50–65 |
| 10 % | 2.5 kg | $110–150 |
Point | Blip | Location |
|---|---|---|
Fishing Spots (3) | Fishing Spot |
|
Fish Market | Fish Market |
|
Delivery driver#
Grab a van at the depot and deliver packages across the city. Finish the route for a bonus.
Start a shift at the Depot
Go to the Delivery Depot and press E (Press E to start a delivery shift). A $100 deposit is taken from your cash for the van. If you don't have it, you see You need $100 cash for the van deposit. You are given 5 stops, picked at random from 7 addresses across south and central Los Santos.
Take the van
A random van (Burrito, Rumpo or Speedo) spawns at the first free spot in the depot lot, with a full tank and a Delivery Van blip. If every spot is blocked, you see No room to spawn the van, try again. The shift is cancelled and your deposit refunded.
Follow the GPS
A Delivery route on your map leads to the current stop. Within 3 m of it, press E (Press E to deliver the package). Your character hands the package over for 3.5 seconds and you are paid $45–65 in cash on the spot. The route then moves to the next stop.
Return to the depot
After the last package (Last package delivered. Return the van to the depot!), the route leads back to the depot. Press E at the depot clerk to end the shift (Press E to end your shift).
Get paid
If you delivered every stop, you get a $150 bonus. Your $100 deposit is refunded in every case. The van is removed wherever it is.
What | Amount | Account |
|---|---|---|
Van deposit | −$100 at the start, +$100 back at the end | Cash |
Per package | $45–65 (paid at each stop) | Cash |
Route bonus | $150 (all 5 stops delivered, shift ended at the depot) | Cash |
A full route | $375–475 in total | Cash |
Situation | What happens |
|---|---|
You end the shift early at the depot | You keep what you earned per stop and get your deposit back, but no bonus. |
You change job during a shift | The shift ends, the deposit is refunded, no bonus, the van is removed. |
You disconnect during a shift | The shift is lost and so is the deposit. |
Point | Location |
|---|---|
Delivery Depot (clerk) |
|
Van spawn spots |
|
Stops (pool of 7) |
|
qs-jobs configuration#
Everything lives in [addons]/qs-jobs/config.lua.
Option | Default | What it does |
|---|---|---|
|
| Interact control (E). |
|
| How close (in metres) you must be to a point. |
|
| Account for sales, delivery pay, the bonus and the van deposit. |
|
| Milliseconds a rock, tree or fishing spot stays empty after you use it. |
| see above | Job Center |
| ped | Depot clerk and its blip. |
| 3 spots | Where the van spawns (first free spot). |
|
| Van models, picked at random. |
|
| Stops per shift (never more than the number of stops). |
|
| Pay per package. |
|
| Bonus for a completed route. |
|
| Van deposit. |
|
| Milliseconds to hand over a package. |
| 7 × | The pool of delivery addresses. |
| per job | Harvest points (see below). |
| per job | Processing point. Optional (the fisher has none). |
| per job | Buyer ped, location, blip and |
Keys inside Config.Jobs.<job>:
Block | Keys |
|---|---|
|
|
|
|
|
|
Adding your own gather → process → sell job#
You can build a new activity job without writing any code. The key in Config.Jobs must be the job name.
Create the job and its items
Add the job to
[core]/qs-core/shared/jobs.lua, as in Adding a job to the Job Center above. Then add any new items to thebasetable in[core]/qs-core/shared/items.lua:lua scrap_metal = { label = 'Scrap Metal', weight = 1000, useable = false, description = 'Rusty scrap, worth smelting.' },Get your coordinates
Stand where each point should be and run
/coords(admin). It printsvec4(x, y, z, h)to F8 and on screen.Add the job to qs-jobs
In
[addons]/qs-jobs/config.lua, add a block toConfig.Jobs:lua Config.Jobs.recycler = { gather = { prop = 'prop_rock_4_e', perZone = 5, spread = 4.0, item = 'scrap_metal', min = 1, max = 3, time = 6000, anim = { dict = 'amb@world_human_hammering@male@base', clip = 'base' }, blip = { sprite = 618, color = 21, scale = 0.7, label = 'Scrapyard' }, locations = { vec3(0.0, 0.0, 0.0), -- replace with your /coords output }, }, process = { input = 'scrap_metal', inputAmount = 4, output = 'metal_ingot', outputAmount = 1, time = 6000, anim = { dict = 'anim@amb@business@weed@weed_inspecting_lo_med_hi@', clip = 'weed_spraybottle_stand_spraying_02_inspector' }, blip = { sprite = 436, color = 17, scale = 0.7, label = 'Smelter' }, locations = { vec4(0.0, 0.0, 0.0, 0.0), -- replace with your /coords output }, }, sell = { ped = 's_m_y_construct_01', scenario = 'WORLD_HUMAN_CLIPBOARD', coords = vec4(0.0, 0.0, 0.0, 0.0), -- replace with your /coords output blip = { sprite = 431, color = 5, scale = 0.7, label = 'Scrap Buyer' }, prices = { metal_ingot = { min = 70, max = 90 } }, }, }Offer it at the Job Center
Add
'recycler'toConfig.Center.jobsand, if you like, adesc_recyclerline to the language files. Then restart the server.
FiveM police job (qs-police)#
qs-police is a complete FiveM police job for Quasar Framework. Officers can cuff, escort, search and confiscate, put suspects in vehicles and issue fines. They can collect bullet casings and blood samples at crime scenes, match DNA in a forensics lab, store evidence in a shared evidence locker, draw gear from the armory and take vehicles from the police garage. Dispatch alerts warn every officer about gunfire, vehicle break-ins and anything your own scripts report.
Everything requires the job police. Every grade can use every feature. Grades only set the salary, from Recruit ($500) to Chief ($2,000), and the boss flag that ESX and QBCore scripts read. Hire officers with /setjob <id> police <grade>.
Mission Row station#
The station is at Mission Row. Its Police Station blip is public. All the other points work only for police: other players standing there see You are not a police officer.
Point | Location ( | How to use it |
|---|---|---|
Station blip |
| Public map blip Police Station. |
Armory |
| Press E to open the armory, then Take any item. |
Evidence locker |
| Shared stash for all officers. See below. |
Forensics lab |
| Press E to use the forensics lab: analyse blood samples. |
Garage |
| Press E to open the garage: spawn a police vehicle. Officers also get a Police Garage blip. |
Garage spawn |
| Where garage vehicles appear. |
Armory#
The armory hands out gear for free, with no stock limit and no grade restriction. Each Take gives the count below (as long as it fits in your inventory).
Item | Count per Take |
|---|---|
| 1 |
| 2 |
| 1 |
| 1 |
| 5 |
| 3 |
Change the list in Config.Armory. Any item that exists in the item catalogue works, including the weapons from qs-coreweapons:
Config.Armory = {
{ name = 'weapon_pistol', count = 1 },
{ name = 'ammo_pistol', count = 2 },
{ name = 'weapon_stungun', count = 1 },
{ name = 'weapon_nightstick', count = 1 },
{ name = 'weapon_flashlight', count = 1 },
{ name = 'armor', count = 1 },
{ name = 'handcuffs', count = 1 },
{ name = 'evidence_bag', count = 5 },
{ name = 'bandage', count = 3 },
}Evidence locker#
A shared stash, police_evidence (Evidence Locker), with 50 slots and 200 kg of space. Every officer sees the same contents, and they are saved by the inventory, so they survive restarts.
With
qs-coreinventory: stand at the locker and open your inventory (F1). The locker opens next to it.With
qs-inventory: stand at the locker and press E.
Only police get access to the locker. There is no marker or prompt on the spot, so show new officers where it is.
Police garage#
On foot at the garage point, press E and pick a vehicle. It spawns at the garage spawn with a full tank, unless something is parked there (The spawn point is blocked). To put it back, drive onto the garage point and press E from the driver's seat (Vehicle stored).
Model | Label |
|---|---|
| Police Cruiser |
| Police Buffalo |
| Police Interceptor |
| Police Bike |
Add more in Config.Garage, for example { model = 'police4', label = 'Unmarked Cruiser' }.
Field actions: cuff, escort, search, transport, fine#
Officers use chat commands, and each one acts on the nearest player. With nobody in range you see No one nearby.
Cuff the suspect
Stand within 3.5 m and type
/cuff. You need handcuffs in your inventory (they are not used up). The suspect is put in the cuffed pose and their weapon is holstered (You have been cuffed).Search them
/searchopens a window with everything in the suspect's inventory, and they are told You are being searched. You can search anyone within 3.5 m. To Confiscate an item, the suspect must be cuffed and within 5 m: the whole stack moves into your inventory, if you can carry it.Escort them
/escortattaches the cuffed suspect to you so they walk where you walk. Run/escortagain to let go.Put them in the car
Park nearby and type
/putincar. The suspect is seated in the closest vehicle within 8 m of them, in the first free seat out of rear-left, rear-right and front passenger. This also ends the escort.Fine them
/fine 500 Speeding through a red lighttakes the amount from the suspect's bank account. They see You received a $500 fine: …. If they can't pay, you see They can't afford that fine.Release them
/outcartakes the cuffed suspect out of the vehicle, and/cuffagain uncuffs them (no handcuffs needed to uncuff).
Action | Range | Rules |
|---|---|---|
Cuff / uncuff | 3.5 m | Cuffing needs |
Escort | 3.5 m | Target must be cuffed. Ends by itself if the officer leaves the server. |
Put in vehicle | 5.5 m | Target must be cuffed. Seats: rear-left, rear-right, front passenger. |
Take out of vehicle | 5.5 m | Target must be cuffed. |
Search | 3.5 m | No cuffs needed to look. Confiscating needs the target cuffed and within 5 m. |
Fine | 5 m |
|
While cuffed, a player cannot sprint, jump, get into or out of vehicles, attack, aim, open the weapon wheel, take cover, reload, throw or melee. The cuffed state is shared with other scripts through the state bag Player(source).state.cuffed (LocalPlayer.state.cuffed on the client).
Police commands#
Command | Key | Who | Description |
|---|---|---|---|
| — |
| Cuff or uncuff the nearest person (needs |
| — |
| Start or stop escorting the nearest cuffed person. |
| — |
| Put the nearest cuffed person in a vehicle. |
| — |
| Take the nearest cuffed person out of a vehicle. |
| — |
| Search the nearest person. Confiscating needs them cuffed. |
| — |
|
|
The commands have no default keys. Officers can bind any of them from the F8 console, for example bind keyboard F6 cuff.
Evidence and forensics#
Crime scenes leave evidence that only police can see.
Evidence | How it appears |
|---|---|
Bullet casings | Every shot fired by any player's firearm leaves a casing where the bullet hit (or at the shooter's feet if it hit nothing), at most one every 0.5 s per shooter. It records the weapon (Pistol, Carbine Rifle…) and the time. |
Blood samples | Every time a player goes down, a blood sample is left where they fell. It carries their DNA, which is their citizen ID. |
Lifetime | Each point lasts 30 minutes. Up to 400 points are kept at once, and all of them are cleared when |
Seeing it | Officers see markers within 25 m: yellow for casings, red for blood. |
Find the markers
Walk the scene as an officer. Casings and blood show up as markers on the ground.
Bag each piece
Within 2 m: Press E to collect the bullet casing (or blood sample). You need an Evidence Bag. Your character kneels for 3 seconds (X cancels), one bag is used, and you get an Evidence item. The marker disappears for every officer.
Read the evidence
Each Evidence item records the type, the weapon (casings), the DNA (blood), the time and the location (
x, y).Analyse blood at the lab
At the forensics lab, press E to see the evidence you carry. Press Analyze on a blood sample: after 4 seconds the DNA is matched to the character's name, whether that player is online or not, or to No match. The result is written on the item (Analysis result: John Doe). Casings already show the weapon and can't be analysed.
Store it
Put the bagged evidence in the evidence locker so the next shift can use it.
Body armor#
armor (Body Armor) is a usable item from the armory. Use it from your inventory: after 3 seconds your armour is set to 100 (Body armor equipped).
Police items#
Item | Label | Weight | Where to get it | Use |
|---|---|---|---|---|
| Handcuffs | 0.45 kg | Armory | Required to cuff (not consumed). |
| Evidence Bag | 0.03 kg | Armory (5 per Take) | Used up when you collect a piece of evidence. |
| Evidence | 0.12 kg | Collecting a casing or blood sample | Holds the evidence data. Blood samples can be analysed at the lab. |
| Body Armor | 2 kg | Armory | Usable: sets armour to 100. |
| Pistol, Pistol ammo | — | Armory | Standard sidearm. See Inventory, Items & Weapons. |
| Bandage | 0.1 kg | Armory, shops | First aid. See the EMS section. |
Dispatch alerts#
Every player with the job police receives each alert as a red notification (6 seconds) and a flashing red blip on the map for 60 seconds, named after the alert.
Alert | Sent when |
|---|---|
Shots fired | Each shot has a 25 % chance of alerting police at the shooter's real position, at most once every 15 seconds per shooter. |
Vehicle break-in reported | A player fails to hotwire a vehicle with a lockpick ( |
Your own alerts | Any server script calls the |
exports['qs-police']:Alert(coords, label)
Server-side. Sends a dispatch alert to every online player whose job is police. label is optional and defaults to Shots fired.
-- server side, e.g. in your store robbery script
local function alertPolice(source, text)
if GetResourceState('qs-police') ~= 'started' then return end
local c = GetEntityCoords(GetPlayerPed(source))
exports['qs-police']:Alert({ x = c.x, y = c.y, z = c.z }, text)
end
alertPolice(source, 'Store robbery in progress')coords must be a plain table with x, y and z. A vector3 (what GetEntityCoords returns) is ignored, so always copy the values into { x = …, y = …, z = … } as above.
Player(source).state.cuffed
Replicated state bag, true while the player is cuffed. Read it on the server with Player(source).state.cuffed or on the client with LocalPlayer.state.cuffed, for example to block your own phone or emote menu while someone is cuffed.
qs-police configuration#
[addons]/qs-police/config.lua:
Option | Default | What it does |
|---|---|---|
|
| Interact control (E). |
|
| Reach for the armory, lab and garage points. |
|
| Reach for cuff, escort and search. Put-in and take-out vehicle get a little extra. |
| Mission Row |
|
| 6 items | Items and the count per Take. |
| 4 vehicles |
|
|
| Allowed fine range. |
|
| Milliseconds an evidence point lasts. |
|
| Maximum evidence points kept at once. |
|
| Minimum milliseconds between casings from one shooter. |
|
| Maximum distance between the shooter and a reported casing. |
|
| Chance per shot of a Shots fired alert. |
|
| Minimum milliseconds between Shots fired alerts per shooter. |
|
| Milliseconds an alert blip stays on the map (all alerts). |
|
| Distance at which officers see evidence markers. |
|
| Distance to collect evidence. |
| 25 weapons |
|
FiveM EMS and ambulance job (qs-ambulance)#
qs-ambulance is the FiveM EMS / ambulance job of Quasar Framework. Every hit you take becomes an injury on a body part: bleeding, bruising or burns, from Light to Critical. Medics diagnose patients, treat each injury with the right item, revive downed players (and get paid for it), carry patients on a stretcher into the ambulance, and get alerts whenever someone goes down. Players without a medic around can pay for treatment at the hospital.
The job is ambulance (label EMS). Every grade can use every feature. Grades set the salary, from Trainee ($500) to Chief ($2,000). Hire medics with /setjob <id> ambulance <grade>.
Going down and calling EMS#
Death is handled by qs-core (see Characters & Players). When your health runs out you go down: you lie on the ground and can only look around and use the chat.
Key | When | What it does |
|---|---|---|
G | Any time while down (30 s cooldown) | Calls EMS. Every medic gets EMS CALL: <name> needs a paramedic! and a blip at your position. |
E | After 20 seconds | Respawn at the nearest hospital: Pillbox Hill |
Admins can revive with /revive [id], the admin menu or the txAdmin menu's Heal. The timer, hospitals and cooldown are in Config.Death in [core]/qs-core/shared/config.lua.
Injuries: how damage becomes an injury#
Every time you take damage, the body part that was hit gets one level of an injury type.
Body region | Covers |
|---|---|
Head | Head and neck |
Upper Body | Spine, chest and pelvis. Any hit that can't be placed counts here. |
Left Arm / Right Arm | Upper arm, forearm, hand and fingers |
Left Leg / Right Leg | Thigh, calf and foot |
What hurt you | Injury type (shown as) | Treated with |
|---|---|---|
Falling | Bruising (Beat) | Ice Pack |
Being on fire | Burning (Burn) | Burn Cream |
Someone holding fists or a blunt weapon: unarmed, bat, crowbar, golf club, hammer, knuckle duster, nightstick, wrench, pool cue, flashlight | Bruising (Beat) | Ice Pack |
Someone holding a molotov, flare, petrol can or flare gun | Burning (Burn) | Burn Cream |
Being hit or run over by a vehicle | Bruising (Beat) | Ice Pack |
Guns, knives and everything else | Bleeding (Bleeding) | Bandage |
Each hit adds +1 level of that type on that region, up to 4: 1 Light, 2 Moderate, 3 Severe, 4 Critical. One region can carry several types at once, for example a bleeding arm that is also bruised.
Injuries have effects while you are up and about, checked every 5 seconds:
Injury | Effect |
|---|---|
Bleeding (any region) | You slowly lose health, faster at higher levels. Bleeding alone never puts you down. |
Bruising on a leg | You move more slowly. At Severe or worse you also walk with an injured limp. |
Burns on the head or upper body | At Moderate or worse your screen is blurred. |
Injuries stay until they are treated. Respawning or an admin revive brings your health back but does not clear injuries. A medic, a bandage (for bleeding) or the hospital check-in does. Injuries are cleared when you disconnect.
Treating yourself#
Option | How | Result |
|---|---|---|
Bandage | Use a | Takes 3.5 s. Lowers your worst bleeding by one level and heals +25 HP. |
Hospital check-in | At the doctor in Pillbox Hill hospital ( | 5 seconds, then $250 cash is taken. Restores full health and clears all injuries and blood. Without the cash: You need $250 in cash. Works for anyone, whatever their job. |
Diagnosing and treating patients#
Open the injury report
Next to a downed player (within 4 m) you see Press E to treat the patient. For anyone else, or for yourself when nobody is near, type
/diagnose. The camera frames the patient and the Treat Patient report opens.Read the report
For each body region the report shows the most urgent injury and its severity, in the order bleeding, then bruising, then burns. A downed patient with no recorded injuries is given Moderate bleeding on a random region, so every downed patient needs at least one bandage.
Drag the right item onto the region
Your bandages, ice packs and burn cream are listed with their counts. Drag one onto the injured body part. Treating takes 6 seconds (X cancels) and uses one item. If the item matches an injury on that region, that injury type is cleared completely on that region (Injury treated), and if the region had another type, it now shows. The wrong item gives That is not the right treatment for this injury and uses nothing.
Repeat until the patient is stable
When the last injury on a downed patient is treated, they are revived with full health (A medic has treated your wounds). You see Patient stabilized! and receive a $250 cash payout (Service payout: $250). There is no payout for treating yourself.
The report closes if you move more than 6 m away or the patient leaves. Patients who are not down can be treated the same way, without a revive or a payout.
Treatment items#
Item | Label | Weight | Treats | Where to get it |
|---|---|---|---|---|
| Bandage | 0.1 kg | Bleeding | Supply cabinet (3, free), Medical Supplies ($25), 24/7 and LTD stores ($25), Ammu-Nation ($25), police armory |
| Ice Pack | 0.35 kg | Bruising | Supply cabinet (2, free), Medical Supplies ($40) |
| Burn Cream | 0.3 kg | Burning | Supply cabinet (2, free), Medical Supplies ($45) |
Point | Location | Who | What it does |
|---|---|---|---|
Supply cabinet |
|
| Press E to grab medical supplies: 3 bandages, 2 ice packs and 2 burn creams for free. Once a minute per medic (The supply cabinet is being restocked, wait a moment). |
Medical Supplies shop |
|
| A |
EMS alerts#
Alert | When | What medics see |
|---|---|---|
EMS ALERT | Any player goes down (once each time they go down) | EMS ALERT: <name> is down! for 7 seconds and a flashing Injured person blip for 60 seconds. |
EMS CALL | A downed player presses G | EMS CALL: <name> needs a paramedic! and the same blip at their position. At most one call every 15 seconds per player. |
Every player with the job ambulance gets these alerts, except the player who went down.
Stretcher#
Medics carry downed patients on a hospital bed and load it into the ambulance.
Action | How |
|---|---|
Deploy |
|
Carry | While carrying you can't jump, attack, aim, melee or get into vehicles. Press E to put it down. |
Next to a stretcher (2.2 m) | The on-screen buttons show your options: E move, G load or unload a patient, H into the ambulance or store. |
Load a patient | G puts the nearest downed player within 4 m on the stretcher. G again unloads them. |
Into the ambulance | With an ambulance within 6 m, H opens the rear doors and locks the stretcher, patient included, in the back. To take it out, stand next to it and press E to carry it again. |
Store | With no ambulance near, H removes the stretcher. Only its owner can. |
Patient | When the patient is revived, they are taken off the stretcher automatically. |
Any medic can move or load any stretcher. A stretcher disappears when its owner leaves the server, and its patient is released.
EMS garage#
At vec4(295.51, -606.76, 43.33), next to the hospital (EMS Garage blip for medics): on foot, Press E to take out an ambulance spawns an ambulance at vec4(281.83, -604.14, 43.13) with a full tank, unless the spot is blocked. Drive back onto the point and press E from the driver's seat to store it.
EMS commands and keys#
Command / key | Key | Who | Description |
|---|---|---|---|
| — |
| Open the injury report for the nearest person, or for yourself. |
| — |
| Deploy your stretcher, or remove it. |
Treat patient | E |
| Next to a downed player. |
Stretcher | E / G / H |
| Move or put down / load or unload / into the ambulance or store. |
Call EMS | G | Anyone who is down | Pages every medic (30 s cooldown). |
Respawn | E | Anyone who is down | After 20 s, at the nearest hospital. |
Page EMS from your own client script
TriggerEvent('qs:client:emsCall') sends an EMS CALL with the caller's name and position to every medic. For example, use it from a phone app's "Call 911 (EMS)" button.
Revive a player from your own server script
exports['qs-core']:SetPlayerDead(source, false) revives a player, and true puts them down. Players also send EMS ALERT to medics when they go down this way.
qs-ambulance configuration#
[addons]/qs-ambulance/config.lua:
Option | Default | What it does |
|---|---|---|
|
| Interact control (E). |
|
| Reach for the hospital doctor, supply cabinet and garage. |
|
| Reach for treating patients. |
| doctor at | Paid check-in: ped, location, price (cash), duration and blip. |
| 6 regions | Which ped bones belong to each body region. |
|
| The item that treats each injury type. |
|
| Milliseconds per treatment. |
| see the table above | Attacker weapons that cause |
|
| Milliseconds between injury effect checks. |
|
| Health loss from bleeding. |
|
| Slower movement and injured walk from leg bruising. |
|
| Blurred screen from head and upper-body burns. |
|
| Health a bandage restores. |
|
| Milliseconds to apply a bandage. |
|
| Milliseconds an EMS alert blip stays. |
|
| Free supply cabinet for medics. |
| point | EMS garage. |
|
| Cash paid to a medic for stabilising a downed patient. |
|
| Stretcher prop (a hospital bed). |
|
| E move / put down / get off, G load / unload, H into ambulance / store. |
|
| Vehicle models that take a stretcher, and where it sits inside. Add an entry to make another ambulance model work. |
To let another ambulance model carry the stretcher, add it to vehicleOffsets with its own position inside the vehicle (tune coords and rotation in game):
vehicleOffsets = {
[`ambulance`] = { coords = vec3(0.15, -3.0, 0.97), rotation = vec3(-1.3, 0.0, 90.0) },
[`your_ambulance_model`] = { coords = vec3(0.0, -2.5, 0.9), rotation = vec3(0.0, 0.0, 90.0) },
},FiveM drugs: weed, cocaine and meth (qs-coredrugs)#
qs-coredrugs is the FiveM drugs script of Quasar Framework: weed, cocaine and meth, each with its own field, lab and multi-step processing, sold to street dealers for dirty cash (black_money). It is open to everyone: there is no job requirement and every field, lab and dealer has a public blip. Drug activity doesn't alert police by itself, but gunfire around it does, through the police evidence system.
How the drug loop works#
Gather
At a field or supply point, walk up to a plant or barrel (within 2 m): Press E to harvest Marijuana. Your character works for a few seconds (X cancels) and you get the raw material. Each gather point has 8 plants or barrels scattered around it, and they never run out.
Process
At the lab, walk up to the table: Press E to process …. You need the full batch of raw material (You need 3x Weed Leaf). Processing runs through several stages: trimming, cutting or cooking, then weighing and packaging. Each stage has its own animation and prop. Cancel any stage and you get nothing, but you keep your materials.
Package
When the last stage finishes, the raw material is turned into one packaged bag.
Sell to a dealer
Talk to a dealer (Press E to talk to the dealer). The dealer window shows the price for each drug on this visit, how many bags you have and your dirty cash. Sell some or Sell all. The money goes into your
black_moneyaccount (Sold 10x for $1200 dirty cash).
Weed#
Step | Where | What you do | Time | In → Out |
|---|---|---|---|---|
Gather | Weed Field, 3 points near Grapeseed, around | Harvest a weed plant | 6 s | → 1–3 |
Process 1 | Weed Lab | Trimming buds | 4.5 s | |
Process 2 | Weighing the batch | 4 s | ||
Process 3 | Packaging | 4 s | 3 | |
Sell | Any dealer |
|
Cocaine#
Step | Where | What you do | Time | In → Out |
|---|---|---|---|---|
Gather | Coca Field, 3 points around | Harvest a coca plant | 6.5 s | → 1–2 |
Process 1 | Cocaine Lab, Sandy Shores | Cutting the brick | 5 s | |
Process 2 | Weighing the batch | 4.5 s | ||
Process 3 | Packaging | 4 s | 4 | |
Sell | Any dealer |
|
Meth#
Step | Where | What you do | Time | In → Out |
|---|---|---|---|---|
Gather | Chemical Supply, 3 points at the port, around | Search a chemical barrel | 7 s | → 1–2 |
Process 1 | Meth Lab, Sandy Shores | Cooking the mix (with toxic smoke) | 6 s | |
Process 2 | Weighing the batch | 4.5 s | ||
Process 3 | Packaging | 4.5 s | 4 | |
Sell | Any dealer |
|
Drug items#
Item | Label | Weight | From | Sold for |
|---|---|---|---|---|
| Weed Leaf | 0.08 kg | Weed Field | — (3 per bag) |
| Bag of Weed | 0.12 kg | Weed Lab | $55–85 |
| Coca Leaf | 0.06 kg | Coca Field | — (4 per bag) |
| Bag of Cocaine | 0.1 kg | Cocaine Lab | $120–180 |
| Chemicals | 0.09 kg | Chemical Supply | — (4 per bag) |
| Bag of Meth | 0.11 kg | Meth Lab | $150–210 |
These items are registered automatically from the drug config. You don't need to add them to any item list.
Dealers and prices#
Dealer | Location |
|---|---|
Dealer 1 |
|
Dealer 2 |
|
Prices roll per visit. When you open the dealer window, the dealer rolls one price per drug within its range. That price holds until you close the window.
25 bags per visit. A dealer buys at most 25 bags each time you open the window (
Config.SellLimitPerVisit). After that you see The dealer won't buy any more right now. Closing and reopening the window starts a new visit with new prices.Dirty cash. Sales pay into
black_money(Config.SellAccount), shown as Dirty Cash in the dealer window. See Economy & Banking.
qs-coredrugs configuration#
[addons]/qs-coredrugs/config.lua:
Option | Default | What it does |
|---|---|---|
|
| Interact control (E). |
|
| Reach to plants, barrels and lab tables. Dealers get 1 m more. |
|
| Account dealer sales pay into. |
|
| Maximum bags a dealer buys per window. |
|
| Plants or barrels spawned at each gather point. |
|
| Radius (m) they are scattered in. |
|
| Name used in prompts and progress text. |
| per drug |
|
| per drug |
|
| 3 per drug | Each stage: |
| per drug |
|
| ped | Dealer |
Adding a drug#
You can add a drug in config alone. The example adds a premium weed strain that reuses the weed props and animations.
Pick your locations
Stand at each field point, at the lab table and wherever you want new dealers, and run
/coords(admin) to getvec4(x, y, z, h). The lab table is placed exactly at the coordinate you give, so use the floor height: about 1 m below thezthat/coordsprints.Add the drug to Config.Drugs
lua Config.Drugs.kush = { label = 'Kush', gather = { item = 'kush_leaf', min = 1, max = 2, time = 7000, weight = 80, label = 'Kush Leaf', prop = 'prop_weed_01', anim = { dict = 'amb@world_human_gardener_plant@male@base', clip = 'base' }, blip = { sprite = 496, color = 25, scale = 0.6, label = 'Kush Field' }, locations = { vec3(0.0, 0.0, 0.0), -- replace with your /coords output }, }, process = { input = 'kush_leaf', inputAmount = 4, output = 'kush_baggie', outputAmount = 1, time = 8000, weight = 120, label = 'Bag of Kush', prop = 'prop_table_03', anim = { dict = 'anim@amb@business@weed@weed_inspecting_lo_med_hi@', clip = 'weed_spraybottle_stand_spraying_02_inspector' }, stages = { { label = 'stage_trim', time = 5000, anim = { dict = 'anim@amb@business@weed@weed_inspecting_lo_med_hi@', clip = 'weed_spraybottle_stand_spraying_02_inspector' }, prop = { model = 'bkr_prop_weed_bud_01a', bone = 18905, pos = vec3(0.04, 0.02, -0.02), rot = vec3(10.0, 0.0, 0.0) } }, { label = 'stage_pack', time = 4000, anim = { dict = 'anim@amb@business@weed@weed_inspecting_lo_med_hi@', clip = 'weed_spraybottle_stand_spraying_02_inspector' }, prop = { model = 'bkr_prop_weed_bag_01a', bone = 57005, pos = vec3(0.12, 0.02, 0.0), rot = vec3(0.0, 90.0, 0.0) } }, }, blip = { sprite = 499, color = 25, scale = 0.6, label = 'Kush Lab' }, locations = { vec4(0.0, 0.0, 0.0, 0.0), -- floor height, see the first step }, }, sell = { item = 'kush_baggie', min = 90, max = 130 }, }Use existing stage labels, or add your own
A stage
labelis a key from qs-coredrugs' language files:stage_trim,stage_cut,stage_cook,stage_weighorstage_pack. For new text, add the key to every file in[addons]/qs-coredrugs/locales/, for examplestage_dry = 'Drying the buds...'.Restart qs-coredrugs
The raw item and the bag are registered from
gather.label/gather.weightandprocess.label/process.weight, the props and blips appear, and every dealer starts buying the new drug.
To add a dealer, add another vec4 to Config.Dealer.locations. Every dealer buys every drug.
Troubleshooting#
"You don't have the right job for this"
That point belongs to a different job. Apply for the job at the Job Center, or have an admin run /setjob. Job blips also only appear for the job you hold.
My new job doesn't show up at the Job Center
It must be in [core]/qs-core/shared/jobs.lua and in Config.Center.jobs in [addons]/qs-jobs/config.lua, with exactly the same name. Restart the server after editing.
"You are not a police officer" / "You are not a medic"
The commands and station points check the job name, police or ambulance. Set it with /setjob <id> police <grade> or /setjob <id> ambulance <grade>.
The hospital doctor or EMS garage is floating in an empty space
The hospital_map interior isn't loaded. Make sure [maps]/hospital_map exists and ensure [maps] is in server.cfg.
"The spawn point is blocked"
Another vehicle is parked on the garage spawn (police or EMS). Move it, or store it from the driver's seat on the garage point.
exports['qs-police']:Alert does nothing
Pass a plain table { x = c.x, y = c.y, z = c.z }, not a vector3, and check that qs-police is started.
Bandages heal only 20 HP or body armor stops working after a restart
qs-coreinventory has its own simple bandage. If you restart qs-coreinventory on a running server, also restart qs-ambulance and qs-police afterwards so their bandage and body armor handlers are registered again.
More fixes are in Common Errors.
Driving it from your own scripts? Every command, key and export of these jobs, together with qs-core's
SetJob,GetJobs,RegisterJobandSetPlayerDead, is listed in Commands and Exports.



