How to add a job on ESX Legacy: jobs and job_grades SQL, setjob
Add a custom job to ESX Legacy with two SQL inserts into jobs and job_grades, set it with /setjob, read it in scripts with xPlayer.job, and link it to a society account.
ESX does not have a jobs file. A job is rows in your database: one in jobs, and one per rank in job_grades. This guide adds a job, gives it to a player, reads it in code, and links it to a society account.
1. Insert the job
The jobs table holds the job itself, and job_grades holds its ranks. Run this in HeidiSQL, phpMyAdmin or the mysql CLI, on the database your server uses:
INSERT INTO `jobs` (`name`, `label`) VALUES
('mechanic2', 'Mechanic');
INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES
('mechanic2', 0, 'recruit', 'Recruit', 200, '{}', '{}'),
('mechanic2', 1, 'novice', 'Novice', 300, '{}', '{}'),
('mechanic2', 2, 'boss', 'Boss', 500, '{}', '{}');The rules that matter:
nameis the code name: lowercase, no spaces, and the same everywhere.labelis what players see.job_nameinjob_gradesmust equal the job'sname.- Grade
0must exist, because new players of the job start at it. Number the grades without gaps. salaryis paid at each pay interval, if your paychecks run.- A job that is missing from
job_gradesbreaks/setjoband can throw errors when a player loads.
Columns can differ a little between ESX versions, so open job_grades in your tool and match the column list to the table you see. If an insert fails, import errors are covered in Unknown column and table errors.
2. Restart so ESX reloads jobs
ESX reads jobs from the database when es_extended starts, so a new row is invisible until then:
restart es_extendedOn a live server, restarting the core can break the scripts that depend on it, so restart the whole server at a quiet time if you are not sure.
3. Give the job to a player
In game or from the console, as an admin:
/setjob <player id> mechanic2 0The three values are the player id, the job name and the grade number. If it fails, check the spelling against the jobs table and that the grade exists, then see ACE permissions for admins if the command is refused.
4. Read the job in your scripts
On the server, get the player and read the job:
local ESX = exports['es_extended']:getSharedObject()
RegisterNetEvent('my_script:doWork', function()
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return end
local job = xPlayer.getJob()
if job.name ~= 'mechanic2' then
return xPlayer.showNotification('You are not a mechanic')
end
if job.grade < 1 then
return xPlayer.showNotification('You need a higher rank')
end
-- allowed
end)xPlayer.getJob() returns a table, and xPlayer.job holds the same data. The fields you will use most are name, label, grade, grade_name and grade_label.
To change a player's job from code:
xPlayer.setJob('mechanic2', 1)If ESX is nil in your script, fix that first with ESX is nil: fixing esx:getSharedObject.
On the client
local ESX = exports['es_extended']:getSharedObject()
local function isMechanic()
local data = ESX.GetPlayerData()
return data.job and data.job.name == 'mechanic2'
end
RegisterNetEvent('esx:setJob', function(job)
-- job changed while the player is online
print(job.name, job.grade)
end)The esx:setJob event fires when the job changes, so keep your own copy up to date instead of asking every frame.
5. Society accounts with esx_society
If the job needs a shared bank account, a boss menu or a stock room, it relies on esx_society. A job with a society needs:
- A boss grade. The top grade is named
boss, as in the insert above. The boss menu looks for that name. - A society account. Society money lives in the
addon_accounttable, in an account calledsociety_plus the job name, for examplesociety_mechanic2. Add a row for it, and for its inventory and datastore if your job uses them. - The registration. The job's own script registers the society with esx_society on the server when it starts, using the same job name.
Where the registration lives depends on the script that runs the job. Check how an existing job on your server does it, such as the police or mechanic job, and mirror it for yours.
Tip: if the boss menu opens empty or money does not move, the society account name does not match
society_plus the job name exactly.
Checklist
| Symptom | Fix |
|---|---|
Job not found by /setjob |
Restart es_extended after the insert |
| Errors when the player loads | The job has no grade 0 in job_grades |
| Name mismatch | job_name must equal the job name, lowercase |
| Wrong rank paid | Check the salary of that grade |
| No boss menu | Name the top grade boss and register the society |
| Society money missing | Create society_<job> in addon_account with the exact job name |
Quick answers
Where are ESX jobs stored?
In the database: the jobs table holds the job, and the job_grades table holds its ranks with a salary each. There is no jobs file to edit on ESX Legacy.
Why does /setjob say the job does not exist?
ESX loads jobs when es_extended starts. Restart it after the insert, and check that the job name and the grade number exist in job_grades.
How do I get the boss menu for my job?
Name the top grade boss. esx_society checks that grade name for the boss menu, and it also needs a society account for the job.
Scripts that skip this problem
Advanced BoostingTablet-driven vehicle boosting: contracts from class D to S+, crews and a live queue.View script →
Shop CreatorBuild a shop in under a minute — owners, employees, vaults and robberies included.View script →
Pawn Shop AppA player-to-player pawn market inside lb-phone.View script →