βHow to Create Job2 on ESX
This guide will walk you through the process of adding this functionality directly to your ESX core.
Important
This tutorial is specifically tailored for ESX 1.12.4+. The structure of the framework can change between versions, so the exact file paths and code blocks might differ if you're on a newer or older release. You'll need to locate the equivalent sections in your version of es_extended. Always back up your files before making any changes! A simple mistake can take your server offline.
Step 1 - Modify the Database Schema
First, we need to tell the database to store the new job2 and job_grade2 information for each player. We'll do this by adding two new columns to the users table.
Run the following SQL query in your database management tool (like phpMyAdmin, HeidiSQL, or through a console command).
ALTER TABLE `users`
ADD COLUMN `job2` VARCHAR(20) DEFAULT 'unemployed',
ADD COLUMN `job_grade2` INT(11) DEFAULT 0;Step 2 - Add the Client-Side Event Handler
Now, we need to teach the client-side part of the script how to handle updates to the player's secondary job. This ensures the player's data updates in real-time without needing to relog.
Navigate to:
es_extended/client/modules/events.luaAdd the following code block to the file. This listens for a secure network event from the server and updates the local player data accordingly.
ESX.SecureNetEvent("esx:setJob2", function(Job2)
ESX.SetPlayerData('job2', Job2)
end)Step 3 - Overhaul the Server-Side Player Loading
This is the most involved step. We need to modify the server-side code to load, validate, and manage the secondary job data when a player connects.
3.1. Update the Database Query
We first need to tell the server to request the new job2 and job_grade2 columns from the database.
Navigate to:
es_extended/server/main.luaFind the line that begins with
local loadPlayer =.Replace it with the following line to include the new columns in the selection:
3.2. Integrate Job2 into the Player Object
Next, we need to integrate the loaded data into the ESX player object, mirroring the functionality of the primary job.
Inside the same file, find the function
function loadESXPlayer.Locate the section where the primary
jobdata is loaded and validated (look forlocal job, grade =).After the block of code for the primary job (you'll see an
endstatement), add the following code forjob2:
3.3. Modify the Player Constructor
Now, we need to pass this new userData.job2 into the function that creates the player object.
Find the line:
local xPlayer = CreateExtendedPlayer(In the list of arguments being passed, locate
userData.job.Add
userData.job2as a new argument immediately after it.
3.4. Update Server Callbacks
Finally, we need to ensure the job2 data is included when other scripts request player information. We'll update two key callbacks.
Find the callback:
ESX.RegisterServerCallback("esx:getPlayerData"Inside the callback function, locate where the data table is built (
cb({...})).Add a line for
job2right after the line forjob.
Repeat this process for the other player data callback:
ESX.RegisterServerCallback("esx:getOtherPlayerData".
Step 4 - Ensure Data is Saved Correctly
Now that the server can load job2 data, we must ensure it gets saved back to the database properly. We'll update the functions responsible for saving player data, both for individual players and for bulk saves.
4.1. Update the Single Player Save Function
Navigate to:
es_extended/server/functions.luaFind the function
function Core.SavePlayer(xPlayer, cb).Replace the entire function with the following code. The key changes are adding
xPlayer.job2.nameandxPlayer.job2.gradeto the SQL parameters.
4.2. Update the Bulk Save Function
This function saves all online players at once, typically during a server restart.
In the same file, find the function
function Core.SavePlayers(cb).Replace the entire function with the code below. Again, we add the
job2data to the parameters for every player.
Step 5 - Extend the Player Class
The final step is to fully integrate job2 into the core Player object. This involves modifying its constructor, state bags, and adding methods to get and set the secondary job.
Navigate to:
es_extended/server/classes/player.lua
5.1. Modify the Constructor
We need to accept the job2 parameter when a player object is created and store it internally.
Find the
CreateExtendedPlayerfunction definition.Add
job2to the list of parameters.
Inside the function, find where
self.job = jobis set.Add a line directly below it to store the secondary job.
5.2. Add State Bag Support
State bags allow data to be efficiently synchronized between the server and client. We need to add one for job2.
Find the line:
stateBag:set("job", self.job, true)Add a new line below it to create a state bag for
job2.
5.3. Create a Getter Function
We need a method for other scripts to retrieve the player's job2 data.
Find the function
function self.getJob().Add a new function directly below it to get the secondary job.
5.4. Create a Setter Function
This is the most crucial part. We need a method to change a player's job2, which will handle validation, update the player object, trigger events, and sync the change to the client instantly.
Find the function
function self.setJob(newJob, grade, onDuty).Add a new function directly below it to set the secondary job. This function mirrors the logic of
setJobbut for thejob2property.
Step 6 - Create an Admin Command for Testing
Now let's add a convenient admin command. This will allow you to change a player's secondary job on the fly.
Navigate to:
es_extended/server/modules/commands.luaRegister a new command by adding the following code block to the file. This leverages the
setJob2function we created in the previous step.
π Implementation Complete!
You have now successfully integrated a complete secondary job system into your ESX framework. The functionality includes:
Database Storage: Saving and loading from the
userstable.Client-Sync: Real-time updates via events and state bags.
Server-Side API: Methods to
getandseta player'sjob2.Persistence: Data is correctly saved during manual and automatic save operations.
Accessibility: An admin command for easy testing and management.
Important Final Note: The job2 system works by reusing your existing jobs and job_grades database tables. This is a efficient design choice. It means you can assign any job you've already defined (e.g., 'police', 'mechanic', 'gang') to a player as either their primary job (job) or their secondary job (job2). They are separate slots that draw from the same list of available occupations.
To test your work:
Restart your server.
Join your server.
Use the command:
/setjob2 [PLAYER_ID] [JOB2_NAME] [JOB2_GRADE]Example:
/setjob2 1 gang 0
If everything is configured correctly, the target player's secondary job will update immediately, and the change will be saved to the database. You can now use xPlayer.setJob2('gangname', 0) in your server scripts and ESX.PlayerData.job2 in your client scripts, just like you would with the primary job.
Last updated