Creating job2 on ESX
If you want to use the gang menu, but don't have job2 registered on your server, here is a step-by-step tutorial on how to register it.
Important
The following tutorial is prepared for ESX 1.12.4 - if you have a different version of your ESX, the lines may not match, you need to make changes to the equivalent lines in your es_extended.
STEP 1
Create new columns for your users table.
Not sure how to do it?
No worries - we've prepared a short guide that shows you step by step how to import an SQL file into your database: 👉 Click here to view the tutorial.
ALTER TABLE `users`
ADD COLUMN `job2` VARCHAR(20) DEFAULT 'unemployed',
ADD COLUMN `job_grade2` INT(11) DEFAULT 0;
STEP 2
Go to your es_extended/client/modules/events.lua
Register a new event:
ESX.SecureNetEvent("esx:setJob2", function(Job2)
ESX.SetPlayerData('job2', Job2)
end)
STEP 3
Go to your es_extended/server/main.lua
Find
local loadPlayer
(will be available in the first lines)Replace with the following code:
local loadPlayer = "SELECT `accounts`, `job`, `job_grade`, `job2`, `job_grade2`, `group`, `position`, `inventory`, `skin`, `loadout`, `metadata`"
Find function
function loadESXPlayer(
Inside this function, find
local job, grade =
Find the
job
registration end here and add the following code:
-- Job2
local job2, grade2 = result.job2, tostring(result.job_grade2)
if not ESX.DoesJobExist(job2, grade2) then
print(("[^3WARNING^7] Ignoring invalid job2 for ^5%s^7 [job2: ^5%s^7, grade: ^5%s^7]"):format(identifier, job2, grade2))
job2, grade2 = "unemployed", "0"
end
local job2Object, grade2Object = ESX.Jobs[job2], ESX.Jobs[job2].grades[grade2]
userData.job2 = {
id = job2Object.id,
name = job2Object.name,
label = job2Object.label,
grade = tonumber(grade),
grade_name = grade2Object.name,
grade_label = grade2Object.label,
grade_salary = grade2Object.salary,
skin_male = grade2Object.skin_male and json.decode(grade2Object.skin_male) or {},
skin_female = grade2Object.skin_female and json.decode(grade2Object.skin_female) or {},
}
Just after
userData.job
adduserData.job2
local xPlayer = CreateExtendedPlayer(
playerId,
identifier,
userData.group,
userData.accounts,
userData.inventory,
userData.weight,
userData.job,
userData.job2, -- HERE ADDED
userData.loadout,
GetPlayerName(playerId),
userData.coords,
userData.metadata
)
Add
job2 = xPlayer.getJob2(),
to callback data:
ESX.RegisterServerCallback("esx:getPlayerData", function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
cb({
identifier = xPlayer.identifier,
accounts = xPlayer.getAccounts(),
inventory = xPlayer.getInventory(),
job = xPlayer.getJob(),
job2 = xPlayer.getJob2(), -- HERE ADDED
loadout = xPlayer.getLoadout(),
money = xPlayer.getMoney(),
position = xPlayer.getCoords(true),
metadata = xPlayer.getMeta(),
})
end)
Add
job2 = xPlayer.getJob2(),
to callback data:
ESX.RegisterServerCallback("esx:getOtherPlayerData", function(_, cb, target)
local xPlayer = ESX.GetPlayerFromId(target)
cb({
identifier = xPlayer.identifier,
accounts = xPlayer.getAccounts(),
inventory = xPlayer.getInventory(),
job = xPlayer.getJob(),
job2 = xPlayer.getJob2(), -- HERE ADDED
loadout = xPlayer.getLoadout(),
money = xPlayer.getMoney(),
position = xPlayer.getCoords(true),
metadata = xPlayer.getMeta(),
})
end)
STEP 4
Go to your es_extended/server/functions.lua
Replace with the following code:
function Core.SavePlayer(xPlayer, cb)
if not xPlayer.spawned then
return cb and cb()
end
updateHealthAndArmorInMetadata(xPlayer)
local parameters <const> = {
json.encode(xPlayer.getAccounts(true)),
xPlayer.job.name,
xPlayer.job.grade,
xPlayer.job2.name, -- HERE ADDED
xPlayer.job2.grade, -- HERE ADDED
xPlayer.group,
json.encode(xPlayer.getCoords(false, true)),
json.encode(xPlayer.getInventory(true)),
json.encode(xPlayer.getLoadout(true)),
json.encode(xPlayer.getMeta()),
xPlayer.identifier,
}
MySQL.prepare( -- HERE ADDED
"UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `job2` = ?, `job_grade2` = ?, `group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?",
parameters,
function(affectedRows)
if affectedRows == 1 then
print(('[^2INFO^7] Saved player ^5"%s^7"'):format(xPlayer.name))
TriggerEvent("esx:playerSaved", xPlayer.playerId, xPlayer)
end
if cb then
cb()
end
end
)
end
Replace with the following code:
function Core.SavePlayers(cb)
local xPlayers <const> = ESX.Players
if not next(xPlayers) then
return
end
local startTime <const> = os.time()
local parameters = {}
for _, xPlayer in pairs(ESX.Players) do
updateHealthAndArmorInMetadata(xPlayer)
parameters[#parameters + 1] = {
json.encode(xPlayer.getAccounts(true)),
xPlayer.job.name,
xPlayer.job.grade,
xPlayer.job2.name, -- HERE ADDED
xPlayer.job2.grade, -- HERE ADDED
xPlayer.group,
json.encode(xPlayer.getCoords(false, true)),
json.encode(xPlayer.getInventory(true)),
json.encode(xPlayer.getLoadout(true)),
json.encode(xPlayer.getMeta()),
xPlayer.identifier,
}
end
MySQL.prepare( -- HERE ADDED
"UPDATE `users` SET `accounts` = ?, `job` = ?, `job_grade` = ?, `job2` = ?, `job_grade2` = ?,`group` = ?, `position` = ?, `inventory` = ?, `loadout` = ?, `metadata` = ? WHERE `identifier` = ?",
parameters,
function(results)
if not results then
return
end
if type(cb) == "function" then
return cb()
end
print(("[^2INFO^7] Saved ^5%s^7 %s over ^5%s^7 ms"):format(#parameters, #parameters > 1 and "players" or "player", ESX.Math.Round((os.time() - startTime) / 1000000, 2)))
end
)
end
STEP 5
Go to your es_extended/server/classes/player.lua
Enter inside the parameters of the
job2
function just after thejob
function CreateExtendedPlayer(playerId, identifier, group, accounts, inventory, weight, job, job2, loadout, name, coords, metadata)
A few lines below find
self.job = job
and just below it addself.job2 = job2
self.job = job
self.job2 = job2 -- HERE ADDED
Another few lines below find
stateBag:set("job", self.job, true)
And under it, add job2 statebag registration -
stateBag:set("job2", self.job2, true)
stateBag:set("job", self.job, true)
stateBag:set("job2", self.job2, true) -- HERE ADDED
Register a new function for job2 below:
function self.getJob2()
return self.job2
end
Register a new function for job2 below:
function self.setJob2(newJob2, grade2, onDuty)
grade2 = tostring(grade2)
local lastJob = self.job2
if not ESX.DoesJobExist(newJob2, grade2) then
return print(("[ESX] [^3WARNING^7] Ignoring invalid ^5.setJob2()^7 usage for ID: ^5%s^7, Job2: ^5%s^7"):format(self.source, newJob2))
end
local jobObject2, gradeObject2 = ESX.Jobs[newJob2], ESX.Jobs[newJob2].grades[grade2]
self.job2 = {
id = jobObject2.id,
name = jobObject2.name,
label = jobObject2.label,
grade = tonumber(grade2),
grade_name = gradeObject2.name,
grade_label = gradeObject2.label,
grade_salary = gradeObject2.salary,
skin_male = gradeObject2.skin_male and json.decode(gradeObject2.skin_male) or {},
skin_female = gradeObject2.skin_female and json.decode(gradeObject2.skin_female) or {},
}
TriggerEvent("esx:setJob2", self.source, self.job2, lastJob)
self.triggerEvent("esx:setJob2", self.job2, lastJob)
Player(self.source).state:set("job2", self.job2, true)
end
STEP 6
Go to your es_extended/server/modules/commands.lua
Register a new command:
ESX.RegisterCommand(
"setjob2",
"admin",
function(xPlayer, args, showError)
if not ESX.DoesJobExist(args.job2, args.grade2) then
return showError(TranslateCap("command_setjob_invalid"))
end
args.playerId.setJob2(args.job2, args.grade2)
end,
true,
{
help = TranslateCap("command_setjob"),
validate = true,
arguments = {
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
{ name = "job2", help = "Job2", type = "string" },
{ name = "grade2", help = "Grade2", type = "number" },
},
}
)
Job2 works on a job basis, but is separate, so you still use the jobs table and job_grades in your database. You can set the jobs you have there as both jobs and job2.
Last updated
Was this helpful?