Configuration — ns-illegal
Editable under escrow: config.lua, data/*.lua (server-only content), locales/*.lua, bridge/*.lua.
The configuration is validated on every start (/illegal validate re-runs it); errors name the exact key and keep
the system disabled (err_not_ready) until fixed.
config.lua
| Option | Default | Description |
|---|---|---|
Framework / Locale / FallbackLocale / Debug | 'auto' / 'en' / 'en' / false | Standard ns-core options (DebugCategories filters debug output, e.g. { career = true }) |
UseOxLib / UseOxTarget / Inventory | true / true / 'auto' | ox_lib UI, ox_target zones, inventory bridge ('ox', 'framework') |
Features.* | all true | Directory, Missions, Locations, Contracts, VehicleTheft, HouseRobbery, Dismantle, Cultivation, Trade, ArrestPenalty |
Database.autoMigrate | true | Create / update tables on start |
Security.* / Admin.* | see file | RPC flood bucket, rate limit, kick threshold; ACE ns-illegal.admin, useFrameworkAdmin, command = 'illegal' |
Tablet.item | 'dark_tablet' | The tablet item |
Tablet.registerUsable | true | Register the item through the framework (set false when using the ox_inventory server.export) |
Tablet.requiredForActivities | true | Starting activities / trading also requires carrying the tablet |
Tablet.openCooldownMs / watchIntervalMs | 1500 / 4000 | Open rate limit; item re-check interval while open |
Tablet.directoryPageSize / recentEvents | 8 / 8 | Dashboard sizes |
Tablet.username | min 3, max 16, pattern, allowChange = false, changeCooldownDays = 30, reserved = {...} | Username policy (the pattern is a Lua pattern; uniqueness is case-insensitive) |
Progression.maxLevel / thresholds | 30 / 30 values | thresholds[L] = total XP for level L (strictly increasing). Level 0 = 0 XP |
Progression.maxXp | 2000000000 | XP keeps counting after level 30, capped here |
Progression.cycleOffsetHours | 0 | Daily / weekly objectives and daily caps reset at 00:00 UTC + this (Turkey: 3) |
Tiers | entry 0, operator 10, distributor 20, kingpin 30 | Milestones (id → locale tier_<id> / tier_<id>_desc) |
Reputation.start / min / max | 0 / -100 / 100 | Reputation range |
Reputation.ranks | Snitch … Known Figure | { min, max, key }, sorted, no gaps / overlaps, must cover min..max (key → locale rank_<key>) |
Arrest.penalty / repeatWindowHours / repeatExtraPenalty / maxPenalty | 10 / 24 / 5 / 25 | Penalty = min(max, penalty + extra × earlier arrests in the window) |
Arrest.dedupeSeconds | 120 | Second report for the same character inside this window is ignored |
Arrest.requireOfficerJob | true | A passed officer id must have a Police.jobs job |
Arrest.allowedResources | policejob, qbx_police, qb-policejob, esx_policejob | Resources allowed to call ReportArrest |
Police.jobs | police, sheriff | Used for minPolice and officer checks |
Economy.payout | { method = 'cash' } | 'cash', 'bank', 'item' (+ item = 'black_money') or 'custom' (Economy.custom(src, amount, reason) -> bool) |
ItemCategories | valuables, vehicle_parts, drugs, rare | Buyers only accept items of their categories |
Hud.enabled / durationMs / levelUpDurationMs / sound / reducedMotion | true / 6500 / 4500 / true / false | Progress HUD |
Contracts.maxActive / defaultHours / maxHours / maxRequired | 6 / 24 / 168 / 50 | Anonymous contract limits |
Contracts.limits | xp 5000, rep 20, money 250000, itemCount 25 | Max reward an admin can set |
Contracts.showWinnerName | true | Players see the winner's username |
Contracts.deliveryItems | {} | Allowed delivery items (empty = any item of ItemCategories) |
Contracts.dropPoints | 2 examples | { id, label, coords = vector3, radius } hand-in points for delivery contracts |
ClientHooks.policeAlert(kind, coords) | no-op | Client: send a dispatch alert with your dispatch resource |
ClientHooks.giveVehicleKeys(vehicle, plate) | no-op | Client: give keys with your key resource |
World.pedSpawnDistance / tabletProp / tabletAnim | 50.0 / prop / anim | Contact peds and the tablet animation |
Integrations.activityReporters | {} | [resource] = { activity ids } allowed to call ReportActivity |
data/activities.lua — rewards and gameplay
Config.Activities[id] = { minLevel, minRep?, xp, rep, failRep, cooldown, dailyCap, minPolice } is the only
source of XP / reputation per completion. cooldown (seconds) and dailyCap are per character and survive relogs:
a completion inside them is recorded but awards nothing. failRep is applied only when a started activity runs
out of time.
Gameplay blocks: Config.VehicleTheft (models, spots, drop-offs, payout, lockpick), Config.Dismantle (parts),
Config.HouseRobbery (interiors, houses, loot, cash, buckets), Config.Cultivation (seed, yield, grow time).
Add an activity module
- Add
my_activity = { minLevel = 10, xp = 100, rep = 2, cooldown = 300, dailyCap = 10 }and the locale keyact_my_activity(EN + TR). - Validate the gameplay server-side (state, distance, timing, items) and then call
Career.RecordActivity(src, 'my_activity', { uid = <server-generated unique id>, units = n, money = paid }). Never take an amount from the client. Objectives and contracts update automatically. - From another resource use the export instead (see below) and allow it in
Config.Integrations.activityReporters.
data/locations.lua — hidden contacts
{
id = 'my_buyer', tier = 2, codename = 'loc_my_buyer', hint = 'loc_my_buyer_hint', -- locale keys or text
minLevel = 12, minRep = 20, price = 9000, currency = 'cash',
coords = vector4(0.0, 0.0, 0.0, 0.0), radius = 2.0, ped = 's_m_y_dealer_01',
hours = { from = 20, to = 4 }, -- optional
permanentAccess = false, -- true: reputation is not re-checked after buying
services = {
sell = { categories = { 'vehicle_parts' }, prices = { car_door = 140 }, maxPerSale = 10,
dailyUnits = 60, cooldown = 30, activity = 'parts_sale' },
},
},
Services: theft, house, chop, grow, sell, shop = { items = { [item] = { price, max } } }.
autoUnlock = true makes a contact known for free once its requirements are met; visibleFrom shows the blurred
card before the requirement level. Every sell price must belong to one of the buyer's categories.
data/objectives.lua — automatic missions
{ id = 'my_goal', title = 'obj_my_goal', description = 'obj_my_goal_desc', minLevel = 10, minRep = nil,
activities = { 'vehicle_dismantle' }, required = 10, measure = 'completions', cycle = 'weekly',
reward = { xp = 500, rep = 2, money = 2500, item = { name = 'lockpick', count = 2 } } },
measure = 'units' counts units (e.g. items sold). cycle: once, daily, weekly. Progress only counts while
the player meets minLevel / minRep, and only for rewarded completions.
Anonymous contracts
Admins open the tablet → Anonymous → Post contract: title, description, type (activity: complete N of an
activity after publishing; delivery: hand in N of an item at a drop point), requirements, duration and rewards
(within Contracts.limits). The first eligible player wins; others see it as taken. Manage with /illegal contracts, /illegal cancel <id>, /illegal retry <id> (re-delivers a failed / pending reward without paying a
part twice). Every create / cancel / retry is written to ns_illegal_audit.
Admin commands (/illegal, ACE ns-illegal.admin, framework admin or console)
profile <id> · setxp <id> <xp> · setrep <id> <rep> · clearname <id> · contracts · cancel <contract> ·
retry <contract> · testarrest <id> (only with Config.Debug = true, applies a real audited penalty) · validate.
Players can cancel their own job with /illegalcancel.
Integration API (server exports)
| Export | Allowed callers | Returns / errors |
|---|---|---|
ReportArrest(targetSrc, incidentId?, officerSrc?) | Config.Arrest.allowedResources | { penalty, reputation, rank } / nil, 'err_no_permission' | 'err_duplicate' | 'err_player_unknown' | 'err_profile' | 'err_database' |
ReportArrestByIdentifier(identifier, incidentId?) | same | same |
ReportActivity(targetSrc, activityId, completionId, { units?, ref?, detail? }) | Config.Integrations.activityReporters[resource] contains activityId | career result (xp, rep, after, levels, capped, …) / nil, 'err_no_permission' | 'err_duplicate' | 'err_level_required' | 'err_rep_required' | 'err_not_registered' |
GetCareer(targetSrc) | any server resource (read-only) | { registered, username, level, xp, reputation, rank, tier, kingpin, arrests } / nil |
CanDoActivity(targetSrc, activityId) | any (read-only) | true / false, errKey (level, reputation, cooldown, police) |
GetItemCategory(item) | any (read-only) | category id / nil |
useDarkTablet | ox_inventory only | ox item export |
Hook: AddEventHandler('ns-illegal:hook:securityFlag', function(src, reason, detail) end) — suspicious requests.