Configuration
| File | Contents |
|---|---|
config/shared.lua | Language, debug, framework, integrations, job injection, multijob, accounts, audit log, Discord, roleplay lines, laundering |
config/server.lua | ACE permissions, rate limiting, spatial checks, payroll, society, actions, billing, custom billing, limits |
config/client.lua | Interaction, world streaming, markers, actions menu, admin command |
config/items.lua | Weapon attachments and skins for weapon upgraders |
Restart the resource after editing.
config/shared.lua
Basics
locale = 'en', -- en es fr de pt it pl ro
debug = false, -- verbose logging; OFF on a live server
framework = 'auto', -- 'auto' | 'qbox' | 'qbcore' | 'esx'
To add a language, copy locales/en.json and translate it. Anything left out falls back to English.
Integrations
adapters = {
menu = 'auto', -- native | ox_lib | esx_default
notify = 'auto', -- kyo_notify | ox_lib | okok | vms_notifyv2 | origen | brutal | t_notify | mythic | framework
inventory = 'auto', -- ox_inventory | qb_inventory | qs_inventory | origen_inventory | core_inventory | codem_inventory | esx_native
target = 'auto', -- ox_target | qb_target
clothing = 'auto', -- illenium | fivem_appearance | qb_clothing | esx_skin
keys = 'auto', -- qbx_vehiclekeys | qb_vehiclekeys
society = 'auto', -- qbx_management | qb_management | esx_addonaccount
billing = 'auto', -- origen | qs_billing | okok | ox_billing | qb_phone | esx_billing | custom
medical = 'auto', -- qbx_medical | brutal_ambulancejob | qb_ambulancejob | esx_ambulancejob
identity = 'auto',
},
auto is almost always right. Pin one when two are installed. The adapter id and the resource name both work (qs_inventory = qs-inventory). An unknown name stops the server at boot and lists the valid ones.
menu = 'native'uses kyoJobCreator’s own menus (icons, prices, keyboard).notify = 'kyo_notify'uses kyoNotify, the only one that also draws the world prompt.
How jobs reach the framework
injectionStrategy = 'auto', -- 'auto' | 'runtime' | 'persisted' | 'hybrid' | 'none'
unemployedJob = 'unemployed',
unemployedGrade = 0,
| Value | Meaning |
|---|---|
auto | Whatever your framework’s adapter recommends |
runtime | Registered in memory, applied instantly |
persisted | Written to the framework’s own tables |
hybrid | Both |
none | Never injected; only works with jobs that already exist |
Multijob
multijob = {
enabled = true,
maxJobs = 3,
command = 'jobs',
},
Accounts
accounts = { cash = 'cash', bank = 'bank', dirty = 'dirty' },
Each adapter maps these to its own names. Change only the values, never the keys.
Audit log
audit = {
database = {
jobs = true, locations = true, employment = true, wages = true,
society = true, trade = true, production = true, vehicles = true,
storage = true, -- the big one: one row per item moved
actions = true, panel = true, security = true,
},
retentionDays = 90, -- 0 = no limit
maxRows = 500000, -- 0 = no limit (~1 KB per row)
pruneHours = 6,
pruneBatch = 5000,
securityBatchSeconds = 30,
storagePollSeconds = 3,
},
Turning a category off stops it being stored and searchable. locations is what the undo button uses, and security is the only record of refused requests.
Discord
discord = {
enabled = false,
general = '', -- catch-all channel
channels = {
jobs = '', locations = '', employment = '', wages = '', society = '', trade = '',
production = '', vehicles = '', storage = '', actions = '', panel = '', security = '',
},
},
A category with its own webhook goes there and nowhere else; one without goes to general; one with neither is not sent.
Roleplay lines
roleplay = { enabled = true, meCommand = 'me', doCommand = 'do' },
The texts are in locales/ as action.<id>.me and action.<id>.do. Leave doCommand empty if your server has no /do.
Money laundering
laundering = {
enabled = true,
returnRate = 85, -- % the player gets back
maxPerCycle = 100000,
durationSeconds = 300,
},
It also has to be switched on in the boss point itself.
config/server.lua
Permissions
aceRoot = 'kyo',
aceAdmin = 'kyo.admin', -- bypasses every individual check
trustFrameworkAdmins = false, -- treat your framework's admins as kyo.admin
showSetupHelp = true, -- show the add_ace line to people without access
Rate limiting
Token bucket per player and action group: burst calls allowed back to back, refill tokens per second. Reviving and invoicing are limited the hardest.
Spatial checks
spatial = {
tolerance = 3.0, -- added to each point's radius, for lag
suspiciousDistance = 25.0, -- further than this is logged as suspicious
},
Every interaction is re-checked against the server’s coordinates, never the client’s.
Payroll
payroll = {
enabled = true,
interval = 30, -- minutes between payments
onDutyOnly = true,
source = 'society', -- 'society' (job account) | 'server' (creates the money)
account = 'bank',
suppressFramework = false, -- true = only kyoJobCreator pays wages
},
With source = 'society', an empty company account pays nobody. Each job can override the source in its Economy tab.
Society, actions and billing
society = { mirror = true }, -- copy balances into your society resource
actions = {
requireDuty = true,
reach = 3.0,
vehicleReach = 6.0,
invoice = { min = 1, max = 25000 },
},
billing = {
enabled = true,
societyCut = 0.10,
maxAmount = 50000,
},
Custom billing
For a billing resource with no adapter, set adapters.billing = 'custom' and describe it:
customBilling = {
resource = 'some_billing',
kind = 'server-event', -- 'server-event' | 'client-event' | 'export'
name = 'some_billing:create',
args = { 'target', 'amount', 'reason', 'societyKey' },
},
Names you can use in args: target, targetId, identifier, amount, reason, society, societyKey, societyLabel, author, authorSource, resourceName. Anything else is passed as a literal.
Limits
limits = {
maxJobs = 200,
maxGradesPerJob = 20,
maxLocationsPerJob = 100,
maxJobNameLength = 50,
maxLabelLength = 64,
maxRosterPage = 500,
},
config/client.lua
interaction = {
provider = 'auto', -- 'auto' | 'target' | 'marker'
key = 38, -- E, for markers
promptDistance = 1.5,
},
world = {
cellSize = 100.0, -- grid cell size for the proximity loop
scanInterval = 1000,
entityDistance = 50.0, -- distance at which peds and props are created
modelTimeout = 10000,
},
marker = { type = 1, scale = { x = 1.5, y = 1.5, z = 0.5 }, colour = { r = 46, g = 204, b = 176, a = 160 }, drawDistance = 20.0 },
actions = {
command = 'jobactions',
key = 'F6', -- default only; players rebind it in FiveM's settings
duration = { repair = 12, wash = 6, lockpick = 8, search = 5, heal = 8, revive = 12 },
animation = { ... }, -- animation and prop per action
},
command = 'jobcreator', -- opens the admin panel
config/items.lua
blockIncompatiblePurchase = false, -- refuse parts the weapon in hand cannot take
attachments = { -- weapon parts, one list per inventory
ox_inventory = { ... },
qb_inventory = { ... },
default = { ... },
},
skins = { -- weapon skins
tintPrice = 750, -- price of a tint, on inventories where skins are tints
ox_inventory = { ... },
qb_inventory = { ... },
default = { ... },
},
Each entry has item, price and label. Your inventory uses its own list, or default if it has none. On inventories where skins are weapon tints (no item behind them), every tint costs tintPrice. Unknown item names are reported in the console at boot.
See Locations.