Configuration
Everything is configured from the config/ folder. The files are open (not escrow-locked), so you can edit them freely.
config/config.lua
The main file — framework, locale, economy multipliers, prompts, commands, admins, clothing, notifications
config/data/regions.lua
Region rewards, region definitions, XP curve, job NPC, blips, daily missions
config/data/notifications.lua
Notification type per message key (text itself lives in locales/)
config/data/map_baseline.lua
Terrain heights under each site, used to spot map / MLO conflicts — nothing to configure
config/data/job12_sites.json
Region 12 drop-offs added in game with /j12site — written by the editor, no need to edit by hand
config/economy.lua
Optional money/XP model derived from work volume
config/keybinds.lua
Machine control keys (crane, pump, tower crane)
config/coordinate.lua
Shared coordinates
config/jobs/*.lua
Per-region job settings
config/systems/*.lua
Feature systems (tutorial, rental, leaderboard, crane, pump...)
config/secrets/discord.lua
Server-only — your Discord webhook URLs and bot token
config/bridges/*.lua
Framework bridges — nothing to configure
config/gate/*.lua
Internals: auto-detection and command gating — nothing to configure
Core Settings
-- Framework: auto | qb | oldqb | qbox | esx | oldesx | vrp | vrp2 | tmc | standalone
-- 'auto' detects it from the running resources; a value set by hand always wins.
-- 'qbox' uses the 'qb' bridge (qbx_core compat layer).
Config.Framework = 'auto'
-- Inventory: auto | qb_inventory | esx_inventory | ox_inventory
-- | codem-inventory | qs_inventory | tgiann-inventory
Config.Inventory = "auto"
-- Path for craft/reward item icons. 'auto' = derived from the selected inventory.
Config.InventoryImagePath = "auto"
Config.SQL = "oxmysql"
-- Server default only — players pick their own language in the menu.
Config.Locale = 'en'
-- CurrencySymbol is what the UI prints next to an amount.
-- MoneyAccount is the framework account the money is added to (bank / cash).
Config.CurrencySymbol = "$"
Config.MoneyAccount = "bank"
Config.ServerName = "TWORST"
Config.ExampleProfilePicture = "https://.../LogoNEW.png"Renamed in v1.0.1. Config.MoneyType became Config.CurrencySymbol and Config.MoneyType2 became Config.MoneyAccount. The old names do nothing — if you are coming from v1.0.0, reapply your settings under the new names.
Auto-detection: leave Framework, Inventory and InventoryImagePath on auto and the script reads whatever is actually running on your server. A value you type by hand always wins. qbox uses the same bridge as qb.
The detection order is fixed in config/gate/auto_detect.lua: qbx_core → qb-core → es_extended → vrp → standalone for frameworks, and third-party inventories (ox_inventory, qs-inventory, codem-inventory, tgiann-inventory) before qb-inventory, because qb-inventory is often installed next to the one actually in use. Each detection prints what it picked to the console.
Economy Multipliers
Two global dials, both at the top of config.lua:
Config.RewardMultiplier
Multiplies money, xp, bonusExtraMoney and bonusExtraXP for every region at load time. 1.5 = 50% richer server-wide.
Config.DepositMultiplier
Multiplies every rental deposit in config/systems/vehicle_rental.lua. Set 0 to switch deposits off entirely.
This is the easiest way to balance the job for your server. You do not need to touch a single per-region number — change one multiplier and every region scales with it.
Interaction Prompt
One setting decides everything about the [E] prompt. Earlier versions used two keys; they are now derived automatically and must not be set by hand.
'badge'
Our world-space badge with an icon — default
'text'
Plain 3D text, no badge
'oxlib'
ox_lib TextUI in the screen corner — matches the rest of your server
'ox-target'
Hands interaction over to ox_target
'qb-target'
Hands interaction over to qb-target
'auto'
Uses ox_target / qb-target if either is installed, otherwise falls back to 'badge'
Config.InteractionHandler and Config.Interaction.style are derived from Config.InteractionStyle inside config/systems/interaction.lua. Do not set them by hand — your value will be overwritten.
Tuning
The rest of config/systems/interaction.lua is fine-tuning — geometry, fonts and cadence — and rarely needs touching:
Config.Interaction.badge, .pin, .label, .anim, .scale and .machine control the size, offset and animation of the badge itself.
Release Profile
Set this before you go live. While debug mode is on, ~250 debug commands register, roughly 20 server-side validation bypasses stay live, and regions play at trimmed test size.
When true, these are force-disabled no matter what they say elsewhere: Debug, DebugCommands, DebugZoneDraw, DebugZones, DebugTowerScenery, RopeProbe, Profiler, FastTest, SoloTest — and the per-region test trims are zeroed, so every region plays at full size.
Config.Debug
Diagnostic logs + per-frame measurement loops (animcontrols, rental). false on a live server.
Config.DebugCommands
Registers the debug command set. Release blocker.
Config.DebugZoneDraw
Draws zone polygons — ~75 µs/frame. Only to check a boundary.
Config.SoloTest
Relaxes crew/vehicle caps so one person can test.
Config.FastTest
Auto-spawns vehicles and skips the whole rental flow. Dev only.
Config.Profiler
Event/network profiler, writes profiler_logs/*.json.
The individual flags ship as Config.Debug = true and Config.DebugCommands = true. That is fine — Config.ReleaseBuild = true sits below them and forces them off. Read the value of ReleaseBuild, not the flags above it.
Lobby & Crew
Lobby size is fixed at 4 and is deliberately not a config option. Config.MaxPlayersInLobby lives in config/gate/auto_detect.lua because crew size feeds reward splitting, slot quotas and the coop sync budget, and all three were balanced around 4.
A region may allow fewer through its own maxPlayers in config/jobs/*.lua — the smaller of the two always wins.
Commands
Rename these freely. Debug commands never go through this table.
Reward Split by Rank
Extra percentage for the highest-scoring crew members, by crew size. Applied to money and XP after the job split and damage deductions.
Reconnection
A disconnected player gets their lobby seat, task progress and reward share back within the window. If the owner drops, ownership transfers to another member.
Regions & Rewards
Rewards — the single source
All money and XP live in one table, keyed by regionID:
money
Paid to the crew that finishes the job
xp
Experience earned
onlineJobExtraAwards
1 = apply the bonuses below
bonusExtraMoney / bonusExtraXP
Added per crew member
Config.RewardMultiplier is applied to this whole table as it loads, and config/economy.lua can overwrite it entirely when enabled.
Region Definitions
Setting enabled = false on a region removes the record from regionData entirely — it is not just hidden in the selector, so a modified client cannot send the regionID either.
Levels
70 levels are defined in config/data/regions.lua. Each region can require a minimum level via regionMinimumLevel.
Job NPC & Blips
In config/data/regions.lua:
Set job to a framework job name to restrict the script to that job, or leave 'all'. missionBlips styles the in-job task markers, and missionBlips.vehicleBlips styles the rental vehicle marker.
Restricting the job to a framework job
Checked for every crew member — one member without the job blocks the start for the whole crew.
Works on QBCore and ESX alike; both job shapes are read. This is separate from Config.Job.job, which controls who sees the NPC and blip in the first place.
Languages
14 languages ship with the script:
English (en)
Türkçe (tr)
Deutsch (de)
Español (es)
Français (fr)
Magyar (hu)
日本語 (ja)
Nederlands (nl)
Português (pt)
Română (ro)
Русский (ru)
Svenska (sv)
Slovenščina (sl)
中文 (zh)
Config.Locale sets the server default only — every player picks their own from the menu.
Adding your own language
The menu is built from the locales/ folder. Drop a new <code>.lua in there and it appears in the language menu by itself — no code change needed.
Copy
locales/en.luatolocales/<code>.luaTranslate the values (leave the keys alone)
Optionally add a display name so the menu shows it properly:
A code with no entry in Config.LanguageNames is simply shown uppercased.
Notifications
Text and type
The wording lives in locales/*.lua. config/data/notifications.lua only maps each key to a type:
Burst filter
One player action often fires several notifications at once. Two rules keep the screen readable:
error and success always pass. Keyed notifications (progress counters, which update in place) skip the filter entirely. Set enabled = false to turn the whole thing off.
Config.NotifyFilter is the function implementing this — replace it if you want different rules.
Sending through your own notification script
Point this at your own notify export to route every message through your server's notification system.
Changing Room
New in the HQ: players change into work clothes inside a marked room rather than instantly on job start.
required
true = the player must change before the job starts; false = optional
points / zMin / zMax
The room polygon and its height range
anchor
Where the player is placed for the change animation
blip
Map marker for the room
anim
The changing animation and its fade timings
Clothing
The outfit comes from Config.JobClothes and is applied through skinchanger / esx_skin events plus Config.RefreshSkin. If your clothing script differs, edit Config.RefreshSkin to match your own call.
Discord Logging
Do not put the webhook URL in config/config.lua. That file is a shared script and ships to every client — a URL there is a published secret. The URLs belong in config/secrets/discord.lua (server-only).
minGapMs, maxQueue and maxRetries are the rate limiter — they keep a busy server from flooding Discord.
Webhook URLs — config/secrets/discord.lua
The URLs live in a server-only file, one channel per category:
An empty category falls back to default. If default is empty too, that category is simply off — and leaving everything empty is a perfectly valid setup: no URL means no request is ever made, and /builderadmin → Logs reads the same event stream from server memory either way.
You can also set these as convars in server.cfg instead — see Installation → Step 8. Use set, never setr.
Admins
Config.Admins gates both /builderadmin and the /tw_bp site builder — checked at the door and again on every write event. Run /cranesiteid in-game to print your own identifier.
See Interface for what the panel and the site builder actually do.
The script ships with the developer's own Discord IDs in Config.Admins. Replace them with yours before going live.
ACE permissions
New in v1.0.1 — an ACE permission is checked first, before the identifier list:
Grant it in server.cfg:
Use this instead of maintaining Config.Admins by hand. Anyone in an ACE group you grant gets access, so admin changes happen in server.cfg alongside the rest of your permissions. Set Config.AdminAce = '' to switch it off and fall back to the identifier list only.
Vehicle Keys & Fuel
Key and fuel systems are auto-detected. Edit these functions if you run something unusual.
Job Hooks
Use these to plug the job into your own systems — a licence check before starting, a stat update on finish, and so on. Returning false from startJobFunction blocks the start.
World & Performance
Performance tuning lives in config/systems/perf_lod.lua and config/systems/perf_budget.lua.
Feature Systems
Everything under config/systems/:
interaction.lua
Prompt geometry, fonts and scan cadence (style is set in config.lua)
tutorial.lua
Training field, modules, per-job-type suggestions
vehicle_rental.lua
Rental lot, stock, deposit, damage penalty
leaderboard.lua
Top earners / most jobs, row limit
tower_crane.lua
Tower crane, cabin, ropes, scenery
vehicle_crane.lua
Mobile crane
pump.lua
Concrete pump
excavator.lua
Excavator
vehicle_anim_controls.lua
Arm and tipper controls for the excavator, tipper and mixer — custom models, bucket bone
rigger.lua / sling_profiles.lua
Rigging and sling behaviour
plank_stages.lua, panelwall.lua, job7.lua, job8.lua, job9.lua
Per-job mechanics
sound.lua / dui.lua
Site audio and prop screens
perf_lod.lua / perf_budget.lua
LOD levels and frame budget — these back the in-game Sync menu
Tutorial
Players practise the machines a region needs on a dedicated field before they work it.
Vehicle Rental
Each vehicle type has its own parking spot, stock and deposit in Config.RentalVehicles. Every deposit is then scaled by Config.DepositMultiplier.
Rental mode
rentalMode in config/systems/vehicle_rental.lua decides how vehicles are handed out:
'spawn_point'
Vehicles wait in their bays on the company lot — default
'npc'
Players rent from the rental clerk NPC. Vehicles no longer wait on the lot — they spawn when rented. The clerk's map blip only shows while you are in a job.
The rental menu shows a photo of every vehicle. Vehicles you can't rent show a short reason — "Not used in this job", "Not needed yet".
Custom excavator / tipper / mixer
Arm and tipper controls live in config/systems/vehicle_anim_controls.lua. The bucket bone can be set by name or index — run /excbones in-game to find it. Full guide: docs/CUSTOM_EXCAVATOR.txt in the package.
/excbones is an admin debug command. It only exists while debug commands are on: set Config.ReleaseBuild = false and Config.DebugCommands = true in config/config.lua (ReleaseBuild = true forces debug commands off). Set Config.ReleaseBuild = true again before going live.
Leaderboard
When disabled, the tab is hidden from the menu entirely.
Static Machines
Scenery machines that stand on a site but are never driven. They are listed in the region's UI info so players know what is waiting for them.
Economy Model (Optional)
config/economy.lua can derive money and XP from the work volume of each region instead of hand-written constants:
A long job earns more; a hard job (crane/machine work) earns more per second.
Off by default (enabled = false). Until you enable it, Config.RegionAwards stays in charge and nothing changes. The built-in durations are estimates — tune them for your server before switching over.
UI Theme
Change this one value to match your server's colours. Accept / deny colours, key caps, medals and reward colours stay as they are, so a reskin cannot break them.
UI Positions
These are only defaults — players move the HUD themselves from Settings → UI Move, and their layout is saved per player.
Last updated

