Configuration
Every meth crafting option in config.lua, logs.lua, strings.lua and strains.lua, with its default and what it changes.
Four files ship open: config.lua for everything the script does, logs.lua for logging, strings.lua for every line of text and strains.lua for the strain names. Changes apply after stop lation_meth and ensure lation_meth (never restart, see install).
The sections below follow config.lua, one per table. Keys are written inside their table, so interact under Setup is Config.Setup.interact.
Setup
Config.Setup: the systems the script talks to.
| Key | Default | What it does |
|---|---|---|
debug | false | Prints what the script is doing, draws the table's collision rays and the target zones, and adds the debug commands (see first start). Off on a live server. |
interact | 'textui' | How players use peds, tables and lab stations: 'textui' (a key prompt), 'ox_target', 'qb-target', 'interact' or 'custom'. lation interact works through 'ox_target'. |
notify | 'ox_lib' | 'lation_ui', 'ox_lib', 'esx', 'qb', 'okok', 'sd-notify', 'wasabi_notify' or 'custom' |
progress | 'ox_lib' | 'lation_ui', 'ox_lib', 'qbcore' or 'custom'. A custom bar has to play animations. |
minigame | 'ox_lib' | The police skill checks: 'lation_ui', 'ox_lib' or 'custom' |
menu | 'ox_lib' | 'lation_ui', 'ox_lib' or 'custom' |
dialogs | 'ox_lib' | Alerts and input dialogs: 'lation_ui', 'ox_lib' or 'custom' |
dispatch | 'none' | Where police calls go: 'cd_dispatch', 'ps-dispatch', 'qs-dispatch', 'core_dispatch', 'rcore_dispatch', 'aty_dispatch', 'op-dispatch', 'origen_police', 'emergencydispatch' or 'custom'. 'none' sends nothing. |
version | true | Checks for a newer version on start and prints a notice in the server console |
control | 38 (E) | The key for every prompt when interact is 'textui'. The prompts in strings.lua say "E"; change them with it. |
request | 10000 | Milliseconds to wait for a model or animation to load |
render | 100 | Meters from a table within which it's drawn |
The custom options do nothing until you add your code to client/functions.lua.
The key prompt itself is set at the top of client/functions.lua: local textui = 'ox_lib'. Also 'lation_ui', 'jg-textui', 'okokTextUI', 'qbcore' or 'custom'.
Table
Config.Table: the portable table and James, who hands it out.
| Key | Default | What it does |
|---|---|---|
item | 'ls_meth_table' | The table item |
model | 'bkr_prop_meth_table01a' | The table prop |
show_info | true | The level card and Lifetime Statistics on the table menu |
locked | false | true: only the player who placed a table can use it or pack it up |
limit | 1 | Tables one player can have down at once |
collisions | true | Colours the outline red where the table touches something. Confirming on an object is refused either way. |
unique | true | Each player has their own recipe. false: everyone uses the values in Config.Cooking.table[2]. |
placement | Q, E, W, S, A, D, X, Space | Control ids: rotateL 44, rotateR 38, forward 32, backward 33, left 34, right 35, cancel 73, confirm 22. The on-screen list is in strings.lua. |
disable | 30, 31, 44, 22, 200 | Controls switched off while placing |
restricted | one at vec3(0, 0, 0), radius 25 | Circles where tables can't go: { coords = vec3(...), radius = 25 }. The default is a placeholder. |
Mission
James. Set mission.enable to false to hand tables out another way.
| Key | Default | What it does |
|---|---|---|
mission.enable | true | James and his blip |
mission.location | vec4(2380.1011, 3348.9221, 47.9524, 42.2499) | Where he stands |
mission.model | 'a_m_m_eastsa_02' | His ped model |
mission.scenario | 'WORLD_HUMAN_SMOKING' | What he does while standing, or false |
mission.hours | { min = 1, max = 24 } | In-game hours he's there, checked as a player walks up. Only overnight windows (min later than max, such as 21 and 5) narrow it. |
mission.require.enable | false | true: he asks for an item before handing over the table |
mission.require.item | 'ls_purple_haze_joint' | The item he asks for |
mission.require.quantity | 25 | How many |
mission.blip | on, sprite 280, colour 0, scale 0.8, 'Suspicious Person' | enable, sprite, color, scale, label |
Warehouses
Config.Warehouses: the labs for sale, one entry each. Add or remove entries to change how many there are. A lab someone owns is off the market until it's sold.
| Field | What it is |
|---|---|
enter | The door, as vec3 |
heading | Which way players face when they come out |
description | The line under its price in the shop |
image | Its picture in the shop, for example 'nui://lation_meth/images/1.jpg'. Put new pictures in images/. |
icon | Its icon in the shop |
price | What it costs |
level | The level a player needs to see and buy it |
camrot | The security camera's rotation at the door. Stand at the door facing away from it, turn on debug and run /getrot. |
storage | Its stashes: id (unique on the server), label, coords, slots and weight. A finished tray goes into the first. |
The six that ship:
| # | Where | Price | Level | Stash | Weight |
|---|---|---|---|---|---|
| 1 | Just off Dutch London Street in a secluded area | $850,000 | 1 | warehouse1_stash1 | 50,000 |
| 2 | On Dry Dock Street in an industrial and safe area | $625,000 | 1 | warehouse2_stash1 | 75,000 |
| 3 | Found on Little Bighom Ave with ample space | $495,000 | 1 | warehouse3_stash1 | 75,000 |
| 4 | Nestled away in a big lot on Exceptionalists Way | $745,000 | 1 | warehouse4_stash1 | 75,000 |
| 5 | Tucked amidst South Arsenal Street and Mutiny Road | $695,000 | 1 | warehouse5_stash1 | 75,000 |
| 6 | Sizable commercial opportunity on Popular Street | $565,000 | 1 | warehouse6_stash1 | 75,000 |
Every stash has 25 slots and sits at the same spot in the lab.
Warehouse settings
Config.WarehouseSettings: what every lab shares.
| Key | Default | What it does |
|---|---|---|
show_info | false | The level card and Lifetime Statistics on Manage Facility |
accounts | { purchase = 'cash', upgrade = 'cash', sell = 'bank' } | Where money comes from and goes: 'cash', 'bank', 'black_money' or 'markedbills'. On QBCore, markedbills is an item, so it can't be used here. |
enter | vec4(997.0383, -3200.7112, -36.3937, 268.4943) | Where players stand once inside |
exit | vec3(996.9076, -3200.6777, -36.3937) | The way out |
manage | vec3(1001.948, -3194.197, -39.193) | The computer: Manage Facility, and police's Confiscate Equipment |
supplies | vec3(1005.7509, -3200.3154, -38.5211) | The supply tank |
inputs | vec3(1006.5563, -3197.6746, -38.9932) | The input panel |
temperature | vec3(1014.6307, -3198.0842, -38.9931) | The temperature panel |
break_down | vec3(1011.6850, -3194.8958, -38.9931) | The bench where trays are broken down |
bagging | vec3(1015.0386, -3194.9062, -38.9931) | The scale where boxes are bagged |
limit | 1 | Labs one player can own |
unique | true | Each player has their own recipe (the same one as at the table). false: everyone uses Config.Cooking.warehouse.input_panel. In a lab, the recipe of whoever powers it on counts. |
defaults | { style = 'empty', security = 'none', ammonia = 0, iodine = 0, acetone = 0 } | A new lab: style 'empty', 'basic' or 'upgrade'; security 'none' or 'upgrade'; tank levels 0 to 100 |
transfer | 'transfer' | The word typed to confirm a transfer |
selling.enable | true | Sell Warehouse to State |
selling.sell | 'confirm' | The word typed to confirm a sale |
selling.refund | 50 | Percent of the price paid back |
Shop
Benjamin, who sells the labs.
| Key | Default | What it does |
|---|---|---|
shop.enable | true | Benjamin and his blip. With it off, open the shop from your own script with WarehouseShop. |
shop.location | vec4(-104.4130, 976.0926, 235.7569, 201.6008) | Where he stands |
shop.model | 'a_m_m_eastsa_02' | His ped model |
shop.scenario | 'WORLD_HUMAN_SMOKING' | What he does while standing, or false |
shop.requiredLevel | 1 | The level a player needs to talk to him |
shop.hours | { min = 1, max = 24 } | In-game hours he's there. As for James, only overnight windows narrow it. |
shop.blip | on, sprite 280, colour 0, scale 0.8, 'Warehouse Shop' | enable, sprite, color, scale, label |
Upgrades
Bought at Manage Facility with accounts.upgrade. Keep the three keys; change their text, price and time. ttd is the delivery time in real minutes, counted while the server runs.
| Key | Price | ttd | What it does |
|---|---|---|---|
orderEquipment | 35000 | 120 | Equips an empty lab: the stash, the supply tank, both panels and both benches |
upgradeEquipment | 50000 | 270 | The upgraded equipment set. Its default description says it speeds up manufacturing, but it only changes the interior; cooking times come from levels. |
orderSecurity | 10000 | 75 | Manage Security: the door lock, the camera, the passcode and authorized users |
Each also has a title, description, icon and iconColor for the menu.
Cameras
The front door camera.
| Key | Default | What it does |
|---|---|---|
cameras.speed | 0.15 | How fast it pans and zooms |
cameras.timecycle | 'scanline_cam_cheap' | The screen effect while watching |
cameras.controls | W, S, A, D, Q, E, Backspace | panUp 32, panDown 33, panLeft 34, panRight 35, zoomIn 44, zoomOut 38, exit 177. zoomIn (Q) widens the view and zoomOut (E) narrows it, as the on-screen help says. |
cameras.disable | 32, 33, 34, 35, 44, 38, 29, 30, 31 | Controls switched off while watching |
cameras.limits | pitch = 30.0, yaw = 45.0, fov = { min = 35.0, max = 80.0 } | How far it tilts and pans from its start, and the zoom range |
Blip
The Meth Warehouse blip owners see at their lab's door: blip.name 'Meth Warehouse', blip.sprite 473, blip.color 0, blip.scale 0.8.
Police
Config.Police.
| Key | Default | What it does |
|---|---|---|
jobs | 'police', 'sheriff' | Jobs that count as police. On Qbox and QBCore only on-duty players count; on ESX everyone with the job. |
require | false | true: tables can't be placed with fewer than count police on |
count | 1 | Police needed when require is on |
can_interact | true | With require on and too few police: true lets players keep using tables already down, false keeps them out ("There are not enough police in the city") |
chance | 25 | Percent chance of a toxic odor call each time a cook finishes a table step. 0 turns it off. |
raids.enabled | true | The break-in prompt and skill check at a locked lab door and at a stash with a passcode |
raids.skillcheck.entrance | 10 x 'easy', keys W, A, S, D | The door's skill check: difficulty and inputs as lib.skillCheck takes them |
raids.skillcheck.stash | 10 x 'easy', keys W, A, S, D | The stash's skill check |
With raids.enabled set to false, police get no break-in prompt or skill check, but the script still lets a police job through a locked lab door and still offers Confiscate Equipment inside. To keep police out entirely, return false for them from CanEnterWarehouse in client/functions.lua (see developers).
Supplies
Config.Supplies: William and the supply runs.
| Key | Default | What it does |
|---|---|---|
start.enabled | true | William's ped and blip. With interact = 'textui', his prompt still shows at start.coords when this is off. |
start.randomize | false | false: a William at every entry in start.coords. true: one, picked when the resource starts. |
start.coords | vec4(-621.8478, 312.4206, 83.9294, 178.8072) | Where he stands; add more vec4s |
start.model | 'a_m_m_eastsa_02' | His ped model |
start.scenario | 'WORLD_HUMAN_SMOKING' | What he does while standing, or false |
start.hours | { min = 1, max = 24 } | In-game hours he's there. Only overnight windows narrow it. |
start.require.enable | false | true: he asks for an item every time a player starts runs |
start.require.item | 'ls_purple_haze_joint' | The item |
start.require.quantity | 25 | How many |
start.blip | on, sprite 303, colour 1, scale 0.8, 'Meth Supplies' | enable, sprite, color, scale, label |
crate.item | 'ls_supply_crate' | The crate a supplier hands over |
crate.rewards | 1 each of pseudoephedrine pills, ammonia, iodine, acetone, hydrochloric acid | What a crate can hold, as { item, quantity }. One reward per crate, picked among the ones the player has none of. |
crate.limit | 10 | Runs each player can finish until the resource restarts. Set it high for no limit. |
pickups | 20 vec4s around the city | Where suppliers wait, picked at random for each run |
models | 20 ped models | The suppliers' models, picked at random |
blip | sprite 280, colour 5, scale 0.8, 'Supplier' | The blip on the current pickup |
The ammonia, iodine and acetone a crate gives come with their fill level at 100. That applies to whatever items are named in Config.Cooking.table[2].
Cooking
Config.Cooking.
At the table
Config.Cooking.table: the six steps, by number.
| Key | Default | What it does |
|---|---|---|
table[1].start | { item = 'ls_pseudoephedrine', quantity = 1 } | Step 1 takes this |
table[1].finish | { item = 'ls_crushed_pseudoephedrine', quantity = 1 } | and gives this; step 2 takes it back |
table[2].ammonia | { item = 'ls_ammonia', value = 86 } | The ammonia item, and the perfect value when Config.Table.unique is false |
table[2].iodine | { item = 'ls_iodine', value = 32 } | Same for iodine |
table[2].acetone | { item = 'ls_acetone', value = 48 } | Same for acetone |
table[2].finish | { item = 'ls_liquid_meth', quantity = 1 } | Step 2 gives this, with its purity and strain |
table[3].start | { item = 'ls_liquid_meth', quantity = 1 } | Step 3 takes this |
table[3].duration | 60 | Minutes of heating, before the level's efficiency |
table[3].temperature | { min = 190, max = 195 } | °C with no loss of purity |
table[3].penalty | 50 | How hard a wrong temperature hits. The loss is penalty x the degrees outside the range / 250, so the largest at a table is 31% of the purity. |
table[4].start | { item = 'ls_hydrochloric_acid', quantity = 1 } | Step 4 takes this |
table[5].duration | 90 | Minutes of cooling, before the level's efficiency |
table[6].finish | { item = 'ls_meth' } | Step 6 gives this; how many comes from yields |
The item names in table[2] are also the ones crates give with a fill level. If you rename them, also rename them in the ox_inventory hook at the bottom of server/functions.lua.
In a lab
Config.Cooking.warehouse.
| Key | Default | What it does |
|---|---|---|
warehouse.add_supplies | { ammonia = 'ls_ammonia', iodine = 'ls_iodine', acetone = 'ls_acetone' } | The items poured into the supply tank |
warehouse.input_panel | { ammonia = 50, iodine = 25, acetone = 10 } | The perfect values when Config.WarehouseSettings.unique is false |
warehouse.temperature | { min = 185, max = 200, penalty = 50 } | °C with no loss, and the penalty, as at the table (largest loss 30%) |
warehouse.stages | five stages | Each has a label (with %d%% for the progress) and a duration in minutes: 1, 5, 30, 3 and 60. Stages 3 and 5 get shorter with level. |
warehouse.stages[1].power_surge | { enable = true, chance = 25 } | The power surge as the lab powers on: flickering lights for everyone inside and a Power Surge call, sent from the owner's game when the owner is inside |
warehouse.stages[5].finish | { item = 'ls_meth_tray', quantity = 1 } | What lands in the lab's first stash |
warehouse.break_down | 'ls_meth_box' | What a tray becomes at the bench, as many as the tray's quantity |
warehouse.bagging | 'ls_meth' | What a box becomes at the scale; how many comes from yields |
Stage 4 only fails when no values were set on either panel. Wrong values don't fail a batch; they lower its purity.
Meth
Config.Meth: using a bag. Each effect has an enable.
| Key | Default | What it does |
|---|---|---|
item | 'ls_meth' | The usable item |
health | amount = 50, max = 200 | Health added, up to max |
armor | amount = 100, max = 100 | Armor added, up to max |
speed | multiplier = 1.49, duration = 45000 | Sprint speed (1.49 at most) for that many milliseconds |
screen | effect = 'stoned_monkeys', duration = 45000 | A timecycle effect |
walk | clipset = 'move_m@drunk@a', duration = 45000 | A walking style |
shake | name = 'DRUNK_SHAKE', intensity = 2.0, duration = 45000 | Camera shake |
overdose | chance = 10 | Percent chance per use; the player dies after 25 to 30 seconds of fading in and out |
Who can use it is up to CanUseMeth in client/functions.lua; by default anyone alive.
Mask
Config.Mask: the gas mask and the fumes.
| Key | Default | What it does |
|---|---|---|
item | 'ls_gas_mask' | The usable item |
model | 'prop_player_gasmask' | The prop on the player's face |
boneId | 12844 | The bone it's attached to |
duration | 800 | Milliseconds to put it on or take it off |
anim | { dict = 'mp_masks@van@ds@', clip = 'put_on_mask' } | The animation |
pos | vec3(0.0, 0.0, 0.0) | Its offset from the bone |
rot | vec3(180.0, 90.0, 0.0) | Its rotation |
flag | 49 | The animation flag |
timecycle | 'CarDamageHit' | The pulsing effect on players without a mask |
damage | 4 | Health lost every second without a mask |
distance | 5 | Meters from a heating table where the fumes reach |
Experience
Config.Experience: one entry per level, starting at [1]. Add entries for more levels.
| Field | What it is |
|---|---|
required_xp | Total XP to reach the level. Level 1 must be 0. |
efficiency | Percent off table heating and cooling and lab stages 3 and 5 |
yields.table | { min, max } bags from a table batch |
yields.warehouse | { min, max } bags from a lab batch |
exp | { min, max } XP per bag; one roll per batch, times the bags |
The defaults:
| Level | required_xp | efficiency | yields.table | yields.warehouse | exp |
|---|---|---|---|---|---|
| 1 | 0 | 0 | 1-3 | 2-6 | 4-8 |
| 2 | 240 | 5 | 1-4 | 2-8 | 5-10 |
| 3 | 803 | 11 | 1-5 | 3-11 | 6-12 |
| 4 | 2063 | 16 | 2-7 | 4-14 | 7-14 |
| 5 | 4898 | 22 | 2-8 | 5-16 | 8-16 |
| 6 | 9938 | 27 | 3-9 | 6-19 | 9-18 |
| 7 | 20063 | 33 | 3-11 | 7-22 | 10-20 |
| 8 | 39638 | 38 | 4-12 | 8-24 | 11-22 |
| 9 | 75278 | 44 | 4-13 | 9-27 | 12-24 |
| 10 | 140078 | 50 | 5-15 | 10-30 | 13-26 |
Animations
Config.Animations: every animation and prop, by what it's for. The progress bar ones have a label, description, icon, duration (ms), position, useWhileDead, canCancel, disable, anim and prop, passed to the progress bar you picked.
| Key | Used for | Default |
|---|---|---|
place_table | Placing a table | "Placing table..", 1.5 s |
pickup_table | Packing it up | "Picking up table..", 1.5 s |
thinking | Standing at the table menu or a dialog | animation only |
collect_supply | The handoff at a supplier | animation and box prop |
open_supply | Opening a crate | "Opening supplies..", 2.5 s |
create_base | Step 1 | "Crushing pseudoephedrine..", 20 s |
mix_chemicals | Step 2 | "Mixing chemicals..", 20 s |
heat_mixture | Step 3 | "Turning temperature up..", 2.5 s |
add_acid | Step 4 | "Adding acid..", 4.25 s |
pour_cool | Step 5 | "Pouring into tray..", 4.25 s |
break_down | Step 6 | "Breaking down..", 10 s, with a hammer |
add_supplies | Filling the lab's tank | a synced scene, 73 s |
input_panel, set_temp | At the lab's panels | animation, clipboard prop and a fixed spot |
break_tray | Breaking down a tray | a synced scene, 51 s |
bagging | Bagging a box | a synced scene, 56.5 s |
manage_facility | At the lab's computer | animation only |
raid_door, raid_stash | Police breaking in | animation only |
confiscate | Police confiscating | animation only |
use_meth | Using a bag | "Sniffing meth..", 4.5 s |
logs.lua
Logs: what is logged, and where.
| Key | Default | What it does |
|---|---|---|
Logs.Service | 'none' | 'fivemanage' (needs fmsdk), 'fivemerr' (needs fm-logs), 'discord' or 'none' |
Logs.Screenshots | false | Adds a screenshot of the player to each log, on Fivemanage and Fivemerr |
Logs.Discord | name = 'Meth Logs', link = '' | The webhook's name, link, image and footer image |
Logs.Events turns each event on or off. Only warehouse_door is on by default.
| Event | When |
|---|---|
table_received | James hands out a table |
table_placed | A table goes down |
table_removed | A table is packed up |
table_batch | A table batch is broken down, with its bags, strain and purity |
supply_run_completed | A crate is collected |
supply_crate_opened | A crate is opened, with what it held |
warehouse_buy | A lab is bought |
warehouse_upgrade | An upgrade is delivered |
warehouse_door | A lab door is locked or unlocked (not by police) |
warehouse_transfer | A lab changes owner |
warehouse_sale | A lab is sold back |
warehouse_batch | A lab batch is bagged, with its bags, strain and purity |
raid_warehouse | Police break into a lab |
raid_stash | Police break into a stash |
The messages are in Strings.Logs.
strings.lua
Strings holds every line players read, in English, grouped by where it shows: Strings.Notify (notifications), Strings.Menu (every menu, with its icons and colours), Strings.Target (target labels, icons and distances), Strings.TextUI (key prompts, including the placement and camera control lists), Strings.Input (dialogs), Strings.Alert (confirmations and what James and William say), Strings.Dispatch (the two police calls, with their codes and blips) and Strings.Logs. Edit the text in place to reword it or translate it.
The two police calls:
| Call | Code | Message | Blip |
|---|---|---|---|
toxic_smell: Suspicious Area | 10-87 | An anonymous caller has reported a strong toxic odor in the area near %s | sprite 310, colour 1, radius 100 |
power_surge: Power Surge | 10-25 | Citizens have reported an unusual power surge in the area near %s | sprite 354, colour 5, radius 100 |
strains.lua
Strains names a batch by its purity: entry 1 is the name at 1%, entry 100 at 100%. The defaults run from Rusty Scrap to Ultimate Crystal, in four bands: 1 to 30 low, 31 to 60 mid, 61 to 90 high, 91 to 100 perfect. Rename any of them; keep all 100.
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated
Cooking
How players run supplies, cook on a portable table, get purity right, buy and run a lab, face police raids, level up and use meth in meth crafting.
Developers
The meth crafting server and client exports, the open functions you can change in client/functions.lua and server/functions.lua, and the record shapes they return.