Configuration
Last updated on
Everything lives in config.lua, kept open (escrow_ignore) even when the rest of the resource is escrowed.
General
Config.Debug = false
Config.Framework = 'auto' -- 'auto' | 'qbox' | 'esx'
Config.MoneyAccount = 'cash'
Config.Locale = 'en' -- 'en' | 'id'
Config.SellCooldown = 5 -- seconds, per player+item
Config.MaxSellPerTransaction = 50
Config.HumanResponseTimeout = 300 -- seconds — Sell's staff-fallback timeout (Buy has no timeout)
Config.DecayInterval = 360 -- minutes between decay ticksColor (NUI theming)
Config.Color = {
mainColor = '#A3E635',
mainColorLight = '#D9F99D',
buttonColor = '#65A30D',
successColor = '#22C55E',
warningColor = '#F59E0B',
dangerColor = '#EF4444',
}Re-skins the NUI's accent colors without editing CSS — see Theming for a live preview and a generator that outputs this block ready to paste.
Currency format
Config.CurrencyFormat = {
symbol = '$', -- '' = none, '$', 'Rp ', etc.
position = 'before', -- 'before' | 'after'
useThousandsSeparator = true,
thousandsSeparator = ',',
decimalPlaces = 0,
}Used by Utils.FormatMoney anywhere a price is shown outside the NUI itself (the NUI formats client-side) — currently the dnd_jobmanagement purchase-document hook.
Banking (Buy revenue)
Config.Banking = {
Enabled = true,
Bridge = 'auto', -- 'auto' | 'renewed' | 'custom'
Resource = 'Renewed-Banking',
StoreHistory = true, -- mirror deposits into Renewed's own statement UI
}Printer integration
Config.Printer = 'dnd_jobmanagement' -- 'dnd_jobmanagement' | 'none'When set to 'dnd_jobmanagement', accepting a Buy order automatically calls that resource's CreatePurchaseDocument export, queuing a printable receipt. Set to 'none' if you don't run dnd_jobmanagement — the sale still completes normally either way, this only controls the paperwork step.
Commands
Config.Commands = {
sell = 'desell',
dashboard = 'dedashboard',
market = 'demarket',
pending = 'depending',
accept = 'deaccept',
}Rename any of these to avoid conflicts with other resources.
Market / Buy
Config.Market = {
demandThresholds = { high = 0.5, balanced = 1.0, low = 1.5 },
buying = {
enabled = true,
maxPerTransaction = 50,
priceAdjustment = 200, -- default instansi/gang ± amount for a NEW agency row only —
-- after that it's per-agency and Dashboard-editable
},
}Jobs (government override)
Config.Jobs = {
government = 3, -- [jobName] = minGrade — bypasses per-agency manager-grade checks
}Items
Config.Items = {
paketkayu = {
label = 'Paket Kayu',
basePrice = 1300,
sensitivity = 0.6, -- how fast price reacts to stock (power-law exponent)
decay = 0.1, -- % of target lost per decay cycle
floor = 0.2, -- min price as % of base
ceiling = 1.5, -- max price as multiplier of base
category = 'Wood Products',
},
-- ...
}Agencies
Config.Agencies = {
['disnaker'] = {
label = 'Government Agency',
job = 'government',
grade = 2, -- manager grade required to open the Dashboard
commission = 0.0, -- personal cut for staff who handle a Sell
collection = 'npc', -- informational only — Sell always tries pending-first when staff are on duty
publicStock = true,
decayMode = 'consume',
logWebhook = '',
npc = {
coords = vec4(-427.45, 1204.90, 325.76, 201.61),
model = 's_m_m_dockwork_01',
target = { distance = 2.0, label = 'Sell Items' },
},
stash = {
id = 'dnd_eco_stash_disnaker',
label = 'Government Storage',
slots = 200,
weight = 9999999,
locations = { vec3(-430.13, 1205.36, 325.76) },
},
items = {
paketkayu = { target = 50000 },
-- ...
},
},
}job doesn't need to match dnd_jobmanagement's canonical job name — if you also run that resource's purchase-document hook, add a Config.JobAliases entry there mapping its canonical name to your raw framework job name (e.g. government = 'pemerintah').
Budget enforcement
Config.Budget = {
Enabled = true,
-- Seeds for NEW agency rows only; dashboard edits take over after
enforcedByDefault = true,
quotaLimit = 2000000, -- $ per cycle. 0 = unlimited (balance still applies)
quotaCycleHours = 24,
-- Staff commission is withdrawn from the agency alongside the payout
commissionFromAgency = true,
-- Low-balance warning threshold (% of quota). Dashboard shows a red alert
-- when an agency is below this, so staff know when to request more funds
lowWarnPct = 0.2,
}When enabled, every Sell transaction withdraws the payout (and staff commission, if commissionFromAgency = true) from the agency's job account. The agency must have sufficient balance and be below its spending quota for the cycle. If either constraint fails, the sale is rejected.
Why this matters: Without budget enforcement, agencies are infinite wallets and player income has no ceiling. With it, government becomes a meaningful role — it's the entity that injects capital into agencies' accounts on demand.
- Balance is the hard constraint: an agency literally can't pay if the account is empty.
- Quota is the soft constraint: reaching the quota per cycle is a normal, expected state. When an agency hits its quota, the market for that agency simply closes until the next cycle rolls. Players are told exactly when that happens.
Per-agency overrides (available on the Dashboard):
budget_enforced— enable/disable enforcement for this one agencyquota_limit— this agency's spending capquota_cycle_hours— this agency's cycle length
Requires Renewed-Banking to work (it reads/writes the agency's job account balance).
Transaction tax
Config.Tax = {
Enabled = true,
destination = 'government', -- job name, or 'burn' to destroy the money
sellRate = 0.05, -- 5% tax on seller's proceeds
buyRate = 0.08, -- 8% tax on buyer's total
-- Stash upkeep: a recurring cost for holding inventory
upkeep = {
Enabled = true,
intervalHours = 24,
flat = 5000, -- $ per agency per cycle
perUnit = 10, -- $ per unit of inventory held
},
}Tax is collected after every Sell or Buy and routed to its destination:
- Job account (a job name): tax is transferred to that job's account in
Renewed-Banking. This keeps the money supply constant; government is a treasury that throttles it. 'burn'— tax is destroyed. Money actually leaves the supply, acting as an economic sink.
Rounding: Tax is always rounded DOWN (math.floor). If the tax on a $100 sale at 5% would be $5.00, the player gets charged $4 (the treasury gets $4), so any rounding error favors the player.
Stash upkeep: A separate charge from transaction tax. Runs hourly (not per-transaction), withdraws from the agency's job account, and is routed back to the tax destination the same way. This prevents hoarding stock to suppress prices — warehousing now has a real cost.
Requires Renewed-Banking to work (it reads/writes the destination job account).
Price spread (instansi vs gang)
Config.Market = {
demandThresholds = { high = 0.5, balanced = 1.0, low = 1.5 },
spread = {
default = 0.08, -- default spread (sell price ± buy price range)
instansiDiscount = 0.04, -- discount for buyers with a relevant job
gangMarkup = 0.06, -- markup for gang/non-instansi buyers
},
buying = {
enabled = true,
maxPerTransaction = 50,
},
}When staff accept a Buy order, they choose a purchase type:
- Instansi (buyer has the related job) → buyer gets a discount (default
instansiDiscount). Prices are lower as incentive for in-house procurement. - Gang/non-instansi (buyer doesn't) → buyer pays a markup (default
gangMarkup). Prices are higher, keeping the agency's profit margin on outside sales.
Per-agency overrides (available on the Dashboard):
instansi_discount— this agency's discount amountgang_markup— this agency's markup amountspread_pct— this agency's default spread width
The spread is applied to the dynamically-calculated mid-price (after supply/demand shifts), so the discount/markup always reflects real market conditions.