EndCore Framework

Jobs

How EndCore jobs, grades and duty work, the jobs that ship by default, and how to add your own.

A job gives a survivor a role: scavenger, medic, craftsman or trader. Each character has one active job and remembers the grade they reached in every job they have held. Other resources read the job to unlock shops, crafting benches, doors and more.

How jobs work

  • PlayerData.job is the active job: { name, label, grade, payment, isboss, onduty, type }.
  • PlayerData.jobs maps every job the character has held to its grade, for example { survivor = 0, medic = 2 }. SetJob records the entry each time.
  • Changing job resets onduty to that job's defaultDuty. A saved onduty = false is kept across logins.
  • If a character's saved job no longer exists in shared/jobs.lua, they fall back to survivor grade 0 on login.
Note

Jobs store payment and offDutyPay, but en-core has no paycheck loop. Nothing in en-core pays players on a timer.

Default jobs

JobTypeGrades (pay)
survivor (the fallback job)civilian0 Wanderer (0)
scavengersurvivor0 Novice (50), 1 Experienced (75), 2 Expert (100), 3 Master (150, boss)
medicmedical0 First Responder (75), 1 Paramedic (100), 2 Doctor (150), 3 Chief Medical Officer (200, boss)
craftsmancrafting0 Apprentice (50), 1 Craftsman (75), 2 Master Craftsman (100), 3 Guild Master (150, boss)
tradermerchant0 Peddler (40), 1 Merchant (75), 2 Senior Merchant (100), 3 Trade Master (150, boss)

Adding a job

Jobs live in shared/jobs.lua, which is loaded on both server and client. Each entry is:

FieldWhat it does
labelDisplay name
defaultDutyWhether the player is on duty when they get the job
offDutyPayStored with the job; not used by en-core
typeA free-form category other resources can check
gradesA table keyed by grade number, each { name, payment, isboss? }
lua
-- shared/jobs.lua
mechanic = {
    label = 'Mechanic',
    defaultDuty = true,
    offDutyPay = false,
    type = 'crafting',
    grades = {
        [0] = { name = 'Grease Monkey', payment = 40 },
        [1] = { name = 'Mechanic', payment = 80 },
        [2] = { name = 'Workshop Boss', payment = 120, isboss = true },
    },
},

Restart the server after editing jobs. Keep survivor in the table, because it is the fallback job.

Changing a job

  • In code: player.Functions.SetJob(jobName, grade). It returns false if the job or grade does not exist.
  • As an admin: /setjob <player> <job> [grade].

Toggle duty with player.Functions.SetDuty(onduty), or with no argument to flip it. A client can toggle its own duty by sending the net event encore:server:toggleDuty.

Exports and functions

WhereNameArgumentsReturns
Player objectFunctions.SetJobjobName, grade?, skipUpdate?boolean
Player objectFunctions.SetDutyonduty?boolean (the new duty state)
Server exportGetJobs()noneThe job table
Client exportGetJobs()noneThe job table

Events

SideEventPayload
Serverencore:server:onJobUpdatesource, job
Serverencore:server:onDutyUpdatesource, onduty
Client (net)encore:client:onJobUpdatejob
Client (net)encore:client:onDutyUpdateonduty
Client sendsencore:server:toggleDutynone

Examples

Hire a player as a medic and check their grade later:

lua
local player = exports['en-core']:GetPlayer(source)
if player and player.Functions.SetJob('medic', 1) then
    encore.notify(source, { description = 'You joined the medics.', type = 'success' })
end

-- elsewhere
local data = exports['en-core']:GetPlayer(source).PlayerData
if data.job.name == 'medic' and data.job.onduty and data.job.grade >= 2 then
    -- allow surgery
end

A duty toggle key on the client:

lua
RegisterCommand('duty', function()
    TriggerServerEvent('encore:server:toggleDuty')
end, false)

RegisterNetEvent('encore:client:onDutyUpdate', function(onduty)
    print(onduty and 'On duty' or 'Off duty')
end)

React to job changes on the server:

lua
AddEventHandler('encore:server:onJobUpdate', function(source, job)
    print(('%s is now %s (%s)'):format(GetPlayerName(source), job.label, job.grade))
end)