Configuration
Config = {}
SD.Locale.LoadLocale('en') -- Load the locale language, if available. You can change 'en' to any other available language in the locales folder.
Config.Debug = false -- true/false the debug for polyzones (in regards to the duty zones)
-- How long (in seconds) bonus and message notifications persist before expiring.
Config.NotificationDuration = 259200 -- 72h (in seconds)
-- You can disable the multijob system and only have a boss menu if you wish. It's heavily recommended to keep this as true.
-- If false, messages and bonuses will be disabled.
Config.Multijob = {
enable = true, -- true/false
jobsLimit = { enable = true, amount = 5, } -- if enabled, limits the amount of jobs that player can have in their multijob. If disabled, infinite.
}
-- Enable or disable the messages menu (if false, you can't send messages to bosses and bosses can't send messages to you)
Config.EnableMessages = {
enable = true, -- true/false the messaing system as a whole
enableMessagesToBoss = true, -- true/false the ability for employees to send the bosses messages.
enableMessagesToEmployees = true, -- true/false the ability for bosses to send messages to employees.
}
Config.EnableBonuses = true -- true/false the ability for bosses to send bonuses to employees.
-- Setup a command and optionally a keybind to open the multijob menu. If Config.EnableMultijob is false, then you can ignore this.
Config.Command = {
-- the chat command to open your jobs menu
name = 'multijob',
-- whether to also register a key-mapping for it
keybind = {
enabled = true, -- set false to disable keybind entirely
key = 'F5' -- any valid FiveM key string: 'F2', 'F5', 'INSERT', etc.
}
}
-- Icons for the target options to toggle duty and open the boss menu.
Config.TargetIcons = {
duty = 'fa-solid fa-briefcase',
boss = 'fa-solid fa-users-gear'
}
Config.UseSociety = {
-- Use built-in society accounting (via this resource’s exports and the boss-menu UI). Doesn't link to anything external, all handled in-resource.
-- When useCustomLogic = true, bypass built-in handling in favor of your own logic (e.g., Renewed-Banking, fd_banking etc.).
-- Note: To have external transactions appear in the boss menu’s transaction log, implement the transactionLog export to other resources (see docs).
-- If you don't want the society to be handled AT ALL through my resource, then simply setting enable to false will suffice.
-- Do note, that disabling society entirely will result in stuff such as the bonuses and weekly goal bonuses not working.
enable = true, -- when true: shows society accounting in boss menu; when false: disables it entirely
useCustomLogic = false, -- when true: calls your custom deposit/withdraw/getBalance below; when false: uses internal methods
-- === CUSTOM BALANCE FUNCTIONS BELOW ===
-- if useCustomLogic is true, you can implement your own deposit/withdraw/getBalance functions here.
--- Deposit into a society account using Renewed-Banking.
--- @param source number The boss’s server ID performing the deposit.
--- @param jobName string The society/job key (e.g. "police").
--- @param amount number Amount to deposit (must be > 0).
--- @param moneyType string "cash" or "bank". (not used here, since Renewed-Banking tracks bank accounts)
--- @return number|false New balance on success, or false on error.
deposit = function(source, jobName, amount, moneyType)
-- Renewed Banking Integration (if you're using Renewed, you can just uncomment the code block below, if you're not, then you can add your own logic here)
--[[
if type(amount) ~= "number" or amount <= 0 then
return false
end
-- Add `amount` to the society’s Renewed-Banking account
local ok = exports['Renewed-Banking']:addAccountMoney(jobName, amount)
if not ok then
return false
end
-- Fetch and return the updated balance
local newBalance = exports['Renewed-Banking']:getAccountMoney(jobName)
return newBalance or false
]]
return false -- Just to clarify, a function can only have one return statement. So if you uncomment renewed-banking above, remove this return.
end,
--- Withdraw from a society account using Renewed-Banking.
--- @param source number The boss’s server ID performing the withdrawal.
--- @param jobName string The society/job key (e.g. "police").
--- @param amount number Amount to withdraw (must be > 0).
--- @param moneyType string "cash" or "bank". (not used here)
--- @return number|false New balance on success, or false on error.
withdraw = function(source, jobName, amount, moneyType)
-- Renewed Banking Integration (if you're using Renewed, you can just uncomment the code block below, if you're not, then you can add your own logic here)
--[[
if type(amount) ~= "number" or amount <= 0 then
return false
end
-- Remove `amount` from the society’s Renewed-Banking account
local ok = exports['Renewed-Banking']:removeAccountMoney(jobName, amount)
if not ok then
return false
end
-- Fetch and return the updated balance
local newBalance = exports['Renewed-Banking']:getAccountMoney(jobName)
return newBalance or false
]]
return false -- Just to clarify, a function can only have one return statement. So if you uncomment renewed-banking above, remove this return.
end,
--- Get the current society balance via Renewed-Banking.
--- @param source number The boss’s server ID requesting balance.
--- @param jobName string The society/job key (e.g. "police").
--- @return number|false Current balance, or false if error.
getBalance = function(source, jobName)
-- Renewed Banking Integration (if you're using Renewed, you can just uncomment the code block below, if you're not, then you can add your own logic here)
--[[
return exports['Renewed-Banking']:getAccountMoney(jobName)
]]
return false -- Just to clarify, a function can only have one return statement. So if you uncomment renewed-banking above, remove this return.
end,
}
-- Definition of each available job: its map icon, pay scales by grade, and human-readable grade labels.
-- So on qb-core for example, you'd effectively copy/mimic the entries from the shared/jobs.lua file here.
Config.Jobs = {
police = {
label = 'Police', -- Label that'll appear in the multijob for this job.
icon = "shield", -- FontAwesome icon for menus/maps
bossGrades = { 4 }, -- grade 4 (“Chief”) is boss (you can add more)
salaries = { -- Salary payout per payday, indexed by job grade (THERE IS NO PAYOUT SYSTEM, ITS ONLY FOR DISPLAY IN THE MENU.)
[0] = 50,
[1] = 75,
[2] = 100,
[3] = 125,
[4] = 150,
},
gradeLabels = { -- Display names for display in the menu.
[0] = 'Recruit',
[1] = 'Officer',
[2] = 'Sergeant',
[3] = 'Lieutenant',
[4] = 'Chief',
}
},
-- Example for other job entries
ambulance = {
label = 'Ambulance',
icon = "ambulance",
bossGrades = { 4 },
salaries = {
[0] = 50,
[1] = 75,
[2] = 100,
[3] = 125,
[4] = 150,
},
gradeLabels = {
[0] = 'Recruit',
[1] = 'Paramedic',
[2] = 'Doctor',
[3] = 'Surgeon',
[4] = 'Chief',
}
},
-- You can add more...
}
-- Locations and everything else related to every job.
Config.Zones = {
police = {
duty = {
enabled = true,
interactionType = "marker", -- how the player toggles duty: "target", "textui", or "marker"
coords = vec3(440.48, -976.02, 29.69),
distance = 3.0,
marker = { -- if target or textui this table is ignored
type = 1,
red = 0,
green = 155,
blue = 255,
opacity = 150,
},
},
dutyZone = { -- Essentially, if enabled, you HAVE to be in the zone to be on duty. You can't go on-duty outside and if you're on duty and leave you'll be forced off.
enabled = false, -- whether to auto–offduty when leaving this zone
timeout = {
enabled = true, -- if true, delayed offduty; if false, immediate offduty
seconds = 30, -- delay in seconds
},
-- polygon defining the auto–offduty area
points = {
vec3(416.3, -961.91, 25.0),
vec3(498.26, -962.05, 25.0),
vec3(494.67, -1042.9, 25.0),
vec3(403.34, -1046.47, 25.0),
},
thickness = 100.0, -- draw thickness / detection width
},
bossMenu = {
enabled = true,
interactionType = "marker", -- "marker", "target", or "textui"
coords = vec3(448.21, -973.12, 29.69),
distance = 2.5,
marker = { -- ignored for target/textui
type = 1,
red = 255,
green = 200,
blue = 0,
opacity = 150,
},
},
},
-- Example for other more entries
--[[
ambulance = {
duty = {
enabled = true,
interactionType = "textui",
coords = vector3(440.0, -980.0, 30.0),
distance = 2.0,
marker = { -- ignored by textui/target
type = 1,
red = 0,
green = 155,
blue = 255,
opacity = 150,
},
},
dutyZone = {
enabled = true, -- whether to auto–offduty when leaving this zone
timeout = {
enabled = true, -- if true, use delayed offduty; if false, offduty immediately
seconds = 30, -- how many seconds outside before auto-offduty
},
-- polygon defining the auto–offduty area
points = {
vector2(295.0, -1440.0),
vector2(315.0, -1430.0),
vector2(325.0, -1460.0),
vector2(305.0, -1470.0),
},
thickness = 1.0,
},
},
]]
-- You can add more...
}
-- Which statistics to display per job in the “View Stats” menu, and how to format each entry.
-- You can increment the stats via the updateStats export. exports['sd-multijob']:updateStats(src, jobName, statKey, increment)
-- So as an example, to increment the police arrests stat by 1 for source 1, you would call: exports['sd-multijob']:updateStats(1, 'police', 'arrests', 1)
Config.Stats = {
enable = true, -- enable/disable stat functionality
police = { -- job key
{
key = "minutesWorked", -- Internal stat name (minutesWorked works for ALL jobs as a stat by default)
title = "Time on Duty", -- Menu title
icon = "clock", -- Icon for this stat
-- no description here; uses FormatMinutesWorked
},
{
key = "arrests", -- Internal stat name
title = "Arrests Made", -- Menu title
description = "You made {amount} arrests.", -- {amount} interpolates the value
icon = "handcuffs" -- Icon for this stat
},
{
key = "ticketsIssued",
title = "Tickets Issued",
description = "You issued {amount} tickets.",
icon = "ticket"
},
{
key = "vehiclesImpounded",
title = "Vehicles Impounded",
description = "You impounded {amount} vehicles.",
icon = "car"
},
{
key = "callsResponded",
title = "Calls Responded",
description = "You responded to {amount} calls.",
icon = "phone"
},
{
key = "bonuses",
title = "Bonuses Received",
description = "You received ${amount} in bonuses.",
icon = "gift"
}
},
ambulance = {
{
key = "minutesWorked",
title = "Time on Duty",
icon = "clock"
},
{
key = "patientsSaved",
title = "Patients Saved",
description = "You saved {amount} lives.",
icon = "heart-pulse"
},
{
key = "revives",
title = "Revives Performed",
description = "You revived {amount} players.",
icon = "heart"
},
{
key = "transportsCompleted",
title = "Transports Completed",
description = "You transported {amount} patients.",
icon = "car-side"
},
{
key = "suppliesUsed",
title = "Supplies Used",
description = "You used {amount} medical supplies.",
icon = "box-medical"
},
{
key = "bonuses",
title = "Bonuses Received",
description = "You received ${amount} in bonuses.",
icon = "gift"
}
},
-- You can add more...
}
-- Leaderboard scoring weights: how much each stat contributes to overall rank.
Config.Leaderboard = {
enable = true, -- enable/disable leaderboard functionality
police = {
timeWeight = 1, -- Points per minute on duty
statWeights = {
arrests = 60, -- Points per arrest
ticketsIssued = 10, -- Points per ticket issued
vehiclesImpounded = 30, -- Points per vehicle impounded
callsResponded = 15, -- Points per call responded
bonuses = 1 -- Points per dollar in bonuses
},
},
-- Example detailed stat weights for the ambulance job
ambulance = {
timeWeight = 1, -- Points per minute on duty
statWeights = {
patientsSaved = 45, -- Points per patient saved
revives = 20, -- Points per revive performed
transportsCompleted = 15, -- Points per transport completed
suppliesUsed = 5, -- Points per supply used
bonuses = 1 -- Points per dollar in bonuses
},
},
-- You can add more...
}
Last updated