Description
An ESX paycheck system: every N minutes the server pays each online player a salary derived from their job and grade, deposits it into their bank account, and pings them with a notification. This is the passive income heartbeat of a roleplay economy and pairs directly with the salary-tiers and tax scripts.
Prompt Template
You are writing a FiveM resource for es_extended. The payout MUST run server-side only.
Framework: ESX. local ESX = exports['es_extended']:getSharedObject()
Server:
- Constant PAY_INTERVAL = 10 * 60 * 1000 (ten real minutes, in ms).
- A fallback PayTable keyed by job name then grade number, e.g.
police = { [0]=250, [1]=350, ... }, plus unemployed = { [0]=50 }.
- A resolveSalary(job, grade) helper that prefers job.grade_salary when > 0,
then PayTable[job.name][job.grade], then 0.
- A CreateThread { while true do Wait(PAY_INTERVAL); for _, xPlayer in
pairs(ESX.GetExtendedPlayers()) do ... end end }. For each player resolve the
salary; if > 0 call addAccountMoney("bank", salary) and TriggerClientEvent
("paycheck:received", xPlayer.source, salary, job.label).
Client:
- A "paycheck:received" net event that ShowNotification the amount and job label.
Hard requirements:
- Loop iterates ESX.GetExtendedPlayers() (xPlayer objects), NOT GetPlayers().
- Wait FIRST inside the loop so you do not pay everyone the instant the resource
starts.
- Always have a fallback salary path so a missing grade does not silently pay 0.
- Deposit to bank, not cash, so paychecks are not lost on death/robbery.
Expected Output
The reference Lua at content/expected-outputs/economy/02-paycheck-by-job-grade.lua is a server-driven interval loop that resolves each player's salary (framework grade salary first, then a fallback table) and deposits to bank, with a tiny client notifier. The split: the loop is server_script 'server.lua'; the notification handler is client_script 'client.lua'.
-- Resource: paycheck-system (ESX)
-- Timed payout to every on-duty player, amount keyed by job + grade.
-- Server-only loop; client only shows a notification.
-- ===== server.lua =====
local ESX = exports['es_extended']:getSharedObject()
local PAY_INTERVAL = 10 * 60 * 1000 -- 10 real minutes
-- Fallback table when the grade has no salary defined in the framework.
local PayTable = {
unemployed = { [0] = 50 },
police = { [0] = 250, [1] = 350, [2] = 500, [3] = 800 },
ambulance = { [0] = 220, [1] = 320, [2] = 480, [3] = 750 },
mechanic = { [0] = 180, [1] = 260, [2] = 400 },
}
local function resolveSalary(job, grade)
-- Prefer the framework-defined grade salary, then our fallback, then 0.
if job.grade_salary and job.grade_salary > 0 then
return job.grade_salary
end
local byJob = PayTable[job.name]
if byJob and byJob[job.grade] then
return byJob[job.grade]
end
return 0
end
CreateThread(function()
while true do
Wait(PAY_INTERVAL)
local xPlayers = ESX.GetExtendedPlayers()
for _, xPlayer in pairs(xPlayers) do
local job = xPlayer.getJob()
local salary = resolveSalary(job, job.grade)
if salary > 0 then
xPlayer.addAccountMoney("bank", salary)
TriggerClientEvent("paycheck:received", xPlayer.source, salary, job.label)
end
end
end
end)
-- ===== client.lua =====
RegisterNetEvent("paycheck:received", function(amount, jobLabel)
local ESX = exports['es_extended']:getSharedObject()
ESX.ShowNotification(("Paycheck: ~g~$%d~s~ deposited (%s)"):format(amount, jobLabel))
end)
Known Failure Modes
- Client-side payout — paying from the client lets anyone forge their own salary. Require the entire loop in the server section.
- Wrong iterator —
GetPlayers()yields id strings, not xPlayer objects; calling.addAccountMoneyon them errors. RequireESX.GetExtendedPlayers(). - Missing-grade zero pay — a sparse salary table with no fallback silently pays nothing. Require a resolveSalary fallback chain.
- Instant-fire on start — looping with Wait at the end pays everyone immediately on resource start. Require Wait first.
Integration Notes
Put the loop in server.lua and the notifier in client.lua; declare both in fxmanifest.lua with server_script / client_script. Depends on es_extended. To test fast, drop PAY_INTERVAL to 15 * 1000, /setjob police 2, wait, and confirm the bank account rises by the grade-2 amount and the notification fires.
Profit Potential
$150–$1800/mo on Tebex (expected ~$500). [INFERRED] priced inside the $50-389 standalone-script band against the signal-scraper corpus (tebex_snapshot n=100, median seller $11.85K/mo) for a rising economy niche.
Trend Signal
↗ rising — [INFERRED] banking/economy is core RP-server infrastructure, steady demand.
Sales Angle
Position as the dependable passive-income heartbeat for ESX economies — grade-aware payouts on a server timer with a safe fallback table, ready to pair with tax and salary-tier add-ons. Recommended Tebex price: $59.
Difficulty & Ship Time
beginner · ships in 1-3h.