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:

sql
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:

  • name is the code name: lowercase, no spaces, and the same everywhere. label is what players see.
  • job_name in job_grades must equal the job's name.
  • Grade 0 must exist, because new players of the job start at it. Number the grades without gaps.
  • salary is paid at each pay interval, if your paychecks run.
  • A job that is missing from job_grades breaks /setjob and 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:

text
restart es_extended

On 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:

text
/setjob <player id> mechanic2 0

The 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:

lua
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:

lua
xPlayer.setJob('mechanic2', 1)

If ESX is nil in your script, fix that first with ESX is nil: fixing esx:getSharedObject.

On the client

lua
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_account table, in an account called society_ plus the job name, for example society_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 →

Keep reading