Configuration

Every oxide-pills setting — how database-backed settings and the /pills settings menu work, which values live only in the config files, and each setting's menu location and default.

oxide-pills is configured in game, from a settings menu. You don't edit script files on a running server. This page explains how that works, then lists every setting so you know what each one does.

How Configuration Is Stored

oxide-pills keeps its live configuration in your database, in a shared table called oxide_settings. The shared/config.lua file and the files in shared/config/ are the factory defaults: the starting values the resource ships with. The table is created automatically on first start (you don't run any SQL by hand).

How it works:

  1. The first time the resource starts, the values from the config files are copied into oxide_settings. If you edited those files before that first start, your edits are what gets copied.
  2. From then on, the database is what the resource reads. Settings you save in the menu are stored there and win over the files. Editing a config file on a server that has already started once will not change a setting that's stored in the database.

What this means for you:

  • Setting up for the very first time? You can edit the config files before the first start, and your values will be imported. The easier path is to start with the defaults and adjust everything in game.
  • Changing a setting on a server that has already run the resource? Use the in-game settings menu (below).
  • A resource update adds new settings? Those aren't in your database yet, so they come from the updated config file automatically on the next start. No action needed.

The in-game settings menu

As an admin, run /pills settings in game. It opens an editor for the settings. Changes apply live and are saved to the database right away, with no restart.

  • Settings are grouped into a sidebar of four categories: Core, Lab, Players, and Advanced, holding 12 sections between them.
  • A Basic / Advanced switch at the top of the menu picks which settings you see, and the search box searches the settings on that side. Three sections (Usage Whitelist, Quality, Dispatch) only have Advanced settings, so they only appear in the sidebar once you switch to Advanced.
  • A setting you've edited but not saved yet is marked changed. Save Changes saves everything you've edited.
  • Reset to default puts a setting back to its factory value from the config files and saves it straight away. It resets the whole setting: resetting Pharma delivery run, for example, also puts back the contact and the drop points.
  • The in-world placement zones are drawn directly in the world: the menu hides, you place the corners of the area, then the menu comes back. Each zone also has a Teleport button.
  • Item fields have a picker that lists the items your inventory knows about.

Almost every change takes effect the moment you save. The exceptions:

  • Changing the workbench's model or slot count only affects workbenches placed afterwards.
  • Changing a model replacement rebuilds the placed stations for everyone.

Developers can also read and write settings from another resource. See API Reference.

The setting names below (like Config.RequireOwnership) are the names in the config files. In the menu each one has a plain label instead (like "Require ownership"). The tables list both where they differ.

Settings That Aren't In The Menu

The menu covers everything most servers want to change. A few settings, mostly lists and layouts that a form can't show well, live only in the config files. They come in two kinds, and the difference matters:

1. Config file only: always read from the file. These are never stored in the database, so the config file always wins:

  • Config.Skill (how much each level reveals) in shared/config/profile.lua
  • Config.Buyers (the street buyer types) in shared/config/world.lua
  • Config.SettingsCommand (the command named in missing-model warnings, '/pills settings') in shared/config/models.lua

To change one: edit the file, save it, and restart the server.

2. Not in the menu, but part of a section that is. Some settings sit inside a section the menu does show, but aren't shown themselves. For example, the product line recipes are part of "Product line unlocks", and the bottle label templates are part of "Packaging". They're marked (not in menu) in the tables below. Only the values the menu shows are taken from the database; these are read from the config file on every start.

To change one: edit the file, save it, and restart the server.

One exception: when the server starts, each saved setting is checked the same way the menu checks it. If a saved setting fails that check (for example the delivery run is switched on with no drop points), it is loaded exactly as it was saved, and file edits to its (not in menu) values are ignored. Fix that setting in the menu and save it, then restart.

The Config Files

FileWhat's in itMenu location
shared/config.luaGeneral settings, placement zones, usage whitelist, police alerts, batch retentionCore, Advanced → Dispatch, Lab → Production
shared/config/equipment.luaThe lab workbench and the placeable machinesLab → Workbench, Lab → Machines
shared/config/production.luaEvery production stage, packaging, and the product line formulasLab → Production (the level for each line is under Players → Progression)
shared/config/profile.luaTablet Profile tuning, and what each level revealsLab → Quality (the reveal table is file only)
shared/config/scenes.luaStage animations and camerasLab → Production (Advanced tab)
shared/config/progression.luaXP rewards, levels and level-10 perksPlayers → Progression
shared/config/world.luaPills breaking, reagent tests, dust, taking pills, evidence, buyers, reputation, the delivery runPlayers → World, Players → Selling (buyers are file only)
shared/config/models.luaModel replacements, and the command missing-model warnings point toAdvanced → Compatibility (the command is file only)

Core

General

SettingMenu labelTypeDefaultWhat it does
Config.RequireOwnershipRequire ownershipbooleantrueOnly the player who placed a station can pack it up, and only the player who placed a workbench can mount machines on it. Set false to let anyone do both.
Config.SpawnDistanceProp spawn distancenumber100.0How close (in metres) a player must be before placed stations appear for them.
Config.AnimateDistanceAnimation distancenumber30.0Machine parts only move for players within this range (metres).
Config.PlaceDistancePlacement reachnumber4.0How far from the player a station can be placed (metres).
Config.DebugDebug modebooleanfalse(Advanced) Prints extra [oxide-pills] lines to the console, and adds a Machine Test option on every machine (every player sees it, but only admins can use it; see Admin). Leave it off on a live server.
Config.AnimsShared animationstablebase-game clips(Advanced) The animations played when placing (place) or packing up (remove) a station. Each has a dict, name and duration (ms, default 1000). Both default to weapons@first_person@aim_rng@generic@projectile@sticky_bomb@ / plant_floor.

Placement Zones

SettingMenu labelTypeDefaultWhat it does
Config.ZoneModeZone modestring'blacklist'How placement zones work: 'off' (place anywhere), 'blacklist' ("Blocked areas": blocked inside SafeZones), or 'whitelist' ("Allowed areas only": blocked outside AllowedZones).
Config.SafeZonesBlocked areastable{} (empty)Areas where stations can't be placed, used in Blocked areas mode. Drawn in the world.
Config.AllowedZonesAllowed areastable{} (empty)The only areas where stations may be placed, used in Allowed areas only mode. Both lists are kept whichever mode is active. Leaving this empty in Allowed areas only mode blocks placement everywhere.

Zones apply to workbenches and floor machines. Benchtop machines sit on a workbench, so they go wherever the workbench is.

Usage Whitelist

(Advanced tab.)

SettingMenu labelTypeDefaultWhat it does
Config.UsageWhitelistItem usage rulestable{} (empty)Per-item rules: { item, jobs, gangs, minRank, dutyOnly }. Items with no rule stay usable by everyone.

Each rule:

FieldWhat it does
itemThe item name the rule applies to. One rule per item.
jobsJob names allowed to use it. With jobs and gangs both empty, any job passes (rank and duty still apply). Capital letters don't matter.
gangsGang names allowed to use it. ESX has no gang system, so gang names never match on ESX.
minRankThe minimum job or gang grade number. 0 means any rank.
dutyOnlyJob holders must be on duty. Ignored for gangs.

A player passes if they match on the job side or the gang side. The rules cover items used from the inventory: station items, the mortar, the sieve, the dust mask, the reagent kit, the Pressing Manual, and every pill, loose or packed.

To limit an item to gangs, fill in only gangs. With jobs empty and at least one gang listed, only members of those gangs can use the item.

Lab

Workbench

Config.Workbench (menu: Lab workbench).

SettingTypeDefaultWhat it does
itemstring'pill_workbench'The inventory item that places the workbench
modelstring'bkr_prop_weed_table_01b'The table model. Any table works: slots are measured from its top surface.
slotsnumber2How many benchtop machines fit along one workbench (1–4)
facingOffsetnumber0Turns the workbench by this many degrees when placed

Changing the model or slot count only affects workbenches placed afterwards. Workbenches already standing keep the model and slots they were placed with.

Machines

Config.Equipment (menu: Placeable machines). One entry per machine:

Machine keyitemrequiredLevelMounts on
hand_presspill_crank_press1Workbench
mixerpill_mixer1Workbench
grinderpill_grinder2Workbench
lightboxpill_lightbox3Workbench
engraverpill_engraver3Workbench
electric_presspill_electric_press5Workbench
label_printerpill_label_printer5Workbench
hardness_testerpill_hardness_tester6Workbench
capsule_boardpill_capsule_board7Workbench
ball_millpill_ball_mill7Workbench
blister_sealerpill_blister_sealer8Workbench
reject_binpill_reject_binnoneFloor
dust_collectorpill_dust_collectornoneFloor
drum_tumblerpill_drum_tumbler6Floor
pan_coaterpill_pan_coater7Floor
rotary_presspill_rotary_press9Floor
  • item: the inventory item that places the machine. If you rename it, register the new name in your inventory too.
  • requiredLevel: the pill level needed to place the machine and to work it, including a machine someone else placed. It is the only level a machine has. Mixing a product line also needs that line's own level (Formulas).
  • facingOffset (not set by default): turns a floor machine by this many degrees when placed. Benchtop machines always face the way their workbench does.
  • machine and mount (not in menu) tie the entry to its model and decide bench or floor. Don't change them.

Production

All of these are under Lab → Production in the menu. A stage worked on a machine needs that machine's level, set under Machines. Only the stages with no machine of their own have a level here: bagging at the workbench and the sieve in the menu, and the mortar in the config file only.

Milling

Config.Mill (menu: Milling).

SettingTypeDefaultWhat it does
minRevMsnumber210Mortar turns arriving faster than this (ms) are ignored. A real hand can't beat about 200 ms, so lowering it only helps cheaters.
maxRevsnumber80The most turns one mortar session can count
minTimenumber3A grind finished sooner than this (seconds) produces nothing
inputstablesee below(not in menu) The raw actives that can be milled
outputtable{ item = 'pill_milled', count = 1 }(not in menu) What milling produces
regrindFinesnumber25(not in menu) Extra fines reground Reject Tablets come back with
regrindSharenumber1.0(not in menu) How many Reject Tablets one regrind takes, as a share of the line's tabletsPerBlend (so 48 by default, 30 for capsules). Below 1.0, regrinding makes more pills than were broken.
tools.mortartablesee below(not in menu) Mortar tuning
tools.grindertablesee below(not in menu) Blade grinder tuning

inputs lists party_powder, pharma_bottle, mystery_powder and pill_rejects (marked regrind = true), each with the container model the grinder shows (the stock ones use oxide_pill_powder_pouch). You can add another raw active here (for example an oxy item from another script), but it's only useful if a formula in Config.Formulas accepts it.

Mortar (tools.mortar):

SettingDefaultWhat it does
item'pill_mortar'The mortar item
requiredLevel1Level to use it
grindPerRev3.4Grind added per turn
finesAfterRev24Turns before fines start
finesPerRev3.2Fines added per turn after that

Blade grinder (tools.grinder):

SettingDefaultWhat it does
station'grinder'The machine it runs on. Its level is the Blade Grinder's requiredLevel under Machines.
grindPerSecond9.0Grind per second of running, with a clean chamber
cakePerSecond14.0How fast powder cakes on the chamber wall while the blade runs
cakeChoke0.85How much of the grind rate a fully caked chamber loses
finesPerSecond7.0Fines per second with a fully caked chamber (none when clean)
knockClears55.0Cake cleared by one knock
knockCooldownMs400How often you can knock (ms)
maxPulseMs8000The longest one pulse can count for (ms)
cakeLightAt / cakeHeavyAt33.0 / 66.0When the chamber shows as caking and choked
pouchtableWhere the powder container stands and the chamber mouth, relative to the grinder

Blending

Config.Blend (menu: Blending).

SettingTypeDefaultWhat it does
runSecondsnumber8.0How long the mixer runs once started
minTimenumber5A blend finished sooner than this (seconds) produces nothing
fillBandtable{ low = 0.55, high = 0.85, falloff = 0.35 }How full the bowl should be (as a fraction of a full bowl) to mix evenly. Outside low–high, uniformity drops to nothing over falloff.
pourRatenumber26.0Units per second for anything without its own rate (filler, dye)
pourRatestable{ active = 14.0, binder = 5.0, lubricant = 1.0 }Slower rates for the small ingredients, so their targets can be hit by holding rather than tapping
dyestable6 coloursThe dye colours players can pick at the bowl, in order: rose, violet, cyan, lime, gold, white. Each has a key (its name comes from the locale entry dye_<key>) and a tint (the tablet colour: 0 pink, 1 blue, 2 yellow, 3 purple, 4 green, 5 ivory, 6 orange, 7 teal).
containerUnitsnumber70.0How much one ingredient item can pour before it's empty
batchUnitsnumber100.0A full bowl, which the gauges and the fill band are measured against
station, output, overlay, containers, dragHeight, dropRadius, pickRadius(not in menu) The machine, the output item, how the bowl looks while mixing, and where the ingredients stand on the bench

The locale file already has names for dye_orange and dye_teal if you want to add those colours.

Pressing

Config.Press (menu: Pressing).

SettingTypeDefaultWhat it does
minTimenumber3A run can't be stopped by hand sooner than this (seconds)
fill.fullAtnumber0.9Seconds per crank turn that fills the die completely. Faster than this gives light tablets.
fill.minChargenumber0.35How full the die gets on the fastest possible turn
jitterSpannumber0.6How much one turn's pace may differ from the last before the tablet counts as unevenly pressed (0.6 = 60%)
minStrokeMsnumber260Crank turns faster than this (ms) are ignored. Lowering it only helps cheaters.
residuePerStrokenumber2.2Residue each tablet leaves on the die (out of 100)
residueRushednumber4.0Extra residue from cranking at full speed
residueLightAt / residueHeavyAtnumber28.0 / 62.0When the die looks dirty and filthy
wearPerStrokenumber0.35Die wear per tablet (out of 100). At the default a die lasts about six blends.
maxWearnumber100Wear at which a die set is finished
rampMsnumber950How long a tablet takes to travel from the die to the tray (ms)
pendingDaysnumber7Days a tray left on a press waits for its owner before it's cleared (checked when the server starts). 0 keeps trays forever.
clean.perScrubnumber7.0Residue removed per brush stroke
clean.minScrubMsnumber120Brush strokes faster than this (ms) are ignored
clean.strokeLengthnumber0.02Brush travel that counts as one stroke (metres)
clean.reachnumber0.035How far from the die centre the brush reaches (metres)
stationstablesee below(not in menu) Which machines are presses, and how each is driven
fillDepthstable{ 30, 40, 50, 60, 75 }(not in menu) The fill depth dial's positions
forcestable{ 35, 48, 58, 68, 82 }(not in menu) The force dial's positions
input, rejects, toolingtablepill_blend, pill_rejects, punch_die_set(not in menu) The blend, reject and die set items
clean.inputstable1 cleaning_brush + 1 cleaning_solvent(not in menu) What a clean costs (also a rotary service)
maxSecondsnumber900(not in menu) A press session still open after this long (seconds) is closed. Any tablets stay on the press for their owner.
persistEverynumber8(not in menu) Saves the tray every this many tablets, so it survives a restart

In the menu, pendingDays is labelled Keep an abandoned tray for.

stations (not in menu):

StationSettingDefault
hand_pressdrive'crank'
electric_pressdrive'motor'
electric_pressspeeds{ 1.2, 0.9, 0.6, 0.45 } seconds per tablet
electric_pressfill{ fullAt = 0.6, minCharge = 0.35 }
capsule_boarddrive, lines'board', { 'capsule' }

Sorting

Config.Sort (menu: Sorting).

SettingTypeDefaultWhat it does
pickRadiusnumber0.045How close the cursor must be to a tablet (fraction of screen height). A large value picks neighbours.
flickMsnumber480How long a rejected tablet takes to fly to the bin (ms)
flickArcnumber0.30How high a rejected tablet is tossed (metres)
binDistancenumber3.5How close a Reject Bin must be for rejects to go into it. Without one they're swept off the tray; a bin is never required.
loupebooleanfalseShows a magnifier on the cursor while sorting. Purely cosmetic: the HUD names the tablet either way.
loupeHeightnumber0.09Height of that magnifier (metres)

Inspecting

Config.Inspect (menu: Inspecting).

SettingTypeDefaultWhat it does
costnumber1Tablets of the batch the first reading destroys
stationstring'lightbox'(not in menu) The machine inspections happen at

Engraving

Config.Engrave (menu: Engraving).

SettingTypeDefaultWhat it does
secondsnumber3.2How long a cut takes (matches the machine's animation)
brandLevelnumber4Level needed to register a brand and engrave it
maxBrandsnumber2Brands one character can hold
blocklisttable{} (empty)Brand names nobody may register (whole name, capital letters ignored)
nametable{ min = 3, max = 20 }(not in menu) Brand name length limits
stationstring'engraver'(not in menu) The machine it runs on

Packaging

Config.Packaging (menu: Packaging).

SettingTypeDefaultWhat it does
requiredLevelnumber1Level to bag pills. Bottles and blister cards need the level of their machine (Label Printer, Blister Sealer) instead.
bagItemstring'pill_baggie'The empty baggie item used per bag
perBagnumber12Pills per baggie
maxBagsPerSessionnumber10The most bags in one go
minBagMsnumber700(not in menu) The fastest a bag can be filled by hand, in milliseconds
bottle.itemstring'pill_bottle'The empty bottle item used per bottle
bottle.perBottlenumber30Pills per bottle
bottle.maxPerSessionnumber4The most bottles in one go
bottle.linestable{ 'bar', 'blues', 'perc' }Product lines that can be bottled
blister.itemstring'blister_sheet'The blister sheet item used per card
blister.perBlisternumber10Pills per card
blister.maxPerSessionnumber5The most cards in one go
protectiontableloose 0.0, baggie 0.25, bottle 0.6, blister 0.95, coated 0.3How much each packing shields pills from breaking (0–1). coated is added on top for coated batches.
station, bottle.station, blister.stationstring'workbench', 'label_printer', 'blister_sealer'(not in menu) Where each kind of packing happens
bottle.labelstablesee below(not in menu) The label templates for each line

bottle.labels (not in menu): players pick from these when filling bottles, so a bottle can only claim what you wrote here. Each has a key, a name and directions.

Linekeynamedirections
percaxia_10AXIA 10/325Take 1 tablet by mouth every 6 hours as needed for pain.
percaxia_5AXIA 5/325Take 1 to 2 tablets by mouth every 6 hours as needed.
bluesvela_30VELA 30 mgTake 1 tablet by mouth every 4 to 6 hours as needed.
barnova_2NOVA 2 mgTake one half tablet at bedtime. May cause drowsiness.
barnova_1NOVA 1 mgTake 1 tablet by mouth up to three times daily.

A line in bottle.lines with no templates can't be bottled.

Granulating (sieve)

Config.Granulate (menu: Granulating (sieve)).

SettingTypeDefaultWhat it does
requiredLevelnumber6Level to use the sieve
pourRatenumber22.0Wetness added per second of pouring
wetBandtable{ low = 40, high = 60, falloff = 30 }The wetness that granulates well
passPerStrokenumber0.07Share of the mass one stroke pushes through at a good wetness
clognumber0.75How much less a soaked mass passes per stroke
minStrokeMsnumber110Strokes faster than this (ms) are ignored
minTimenumber3A granulation finished sooner than this (seconds) produces nothing
tool, fluidstring'pill_sieve', 'granulating_fluid'(not in menu) The sieve and fluid items
strokeLength, heavyUntil, layerUntil, screen, reach, bench, jerrycan, dropRadius, dragHeight(not in menu) Scene layout and how the screen looks as it clears

What granulating is worth is set under Quality (Granulation).

Drum tumbler

Config.Tumble (menu: Drum tumbler).

SettingTypeDefaultWhat it does
capacitynumber4Blends it holds
runSecondsnumber12How long it runs
bandtable{ low = 0.5, high = 0.75, falloff = 0.5 }The fill (share of capacity) that tumbles best
boostnumber30Uniformity added by a good fill
maxUniformitynumber97The highest uniformity tumbling can reach
stationstring'drum_tumbler'(not in menu) The machine it runs on

Ball mill

Config.BallMill (menu: Ball mill).

SettingTypeDefaultWhat it does
capacitynumber6Raw actives it holds
runSecondsnumber15How long it runs
bandtable{ low = 0.34, high = 0.67, falloff = 0.5 }The fill that grinds best
grindtable{ ideal = 72, fine = 96, coarse = 34 }(not in menu) Grind at a good fill, at the emptiest and at the fullest
finestable{ ideal = 4, max = 80 }(not in menu) Fines at a good fill, and at the emptiest
stationstring'ball_mill'(not in menu) The machine it runs on

Hardness tester

Config.Hardness (menu: Hardness tester).

SettingTypeDefaultWhat it does
costnumber3Tablets broken per test
kpPerPointnumber0.12Break force (kp) shown per point of integrity
stationstring'hardness_tester'(not in menu) The machine it runs on

Pan coater

Config.Coat (menu: Pan coater).

SettingTypeDefaultWhat it does
itemstring'coating_solution'The coating solution item used per run
capacitynumber48Tablets it holds
runSecondsnumber14How long it runs
bandtable{ low = 0.5, high = 1.0, falloff = 0.5 }The fill that coats evenly
finishGainnumber0.45Share of the gap to a perfect finish an even coat closes
integrityGainnumber8Integrity an even coat adds
stationstring'pan_coater'(not in menu) The machine it runs on

Capsule board

Config.Capsule (menu: Capsule board). The level to use the board is the Capsule Filling Board's under Machines, and capsules also need the capsule line's level (Formulas).

SettingTypeDefaultWhat it does
shellItemstring'empty_capsule'The empty capsule item (30 per board)
perPassnumber0.34Dose added to a column each time the spreader crosses it (1.0 is a full dose)
heapAtnumber1.2A column filled past this is heaped and spills
idealTampsnumber2The number of tamps the board's gauge marks as right
minPassMsnumber90Crossings of the same column faster than this (ms) are ignored
tampForcetable{ 30, 42, 56, 68, 82 }(not in menu) The compaction from 0, 1, 2, 3 and 4 tamps
spillResiduenumber90(not in menu) How much a heaped column dirties its capsules

Rotary press (crew)

Config.Rotary (menu: Rotary press (crew)). Starting a run as the feeder needs the Rotary Press's level under Machines. Crew who join a run don't need it.

SettingTypeDefaultWhat it does
hopperBlendsnumber3Blends the hopper holds
trayCapacitynumber24Tablets the output tray holds before the sorter has to clear it (max 24)
residuePerStrokenumber0.25Residue per tablet
wearPerStrokenumber0.05Die wear per tablet
serviceSecondsnumber4How long a service takes
perBagnumber12Pills per bag the packer makes
crewDistancenumber6.0How close a crew member must stay to keep their role (metres)
speedstable{ 2.0, 3.0, 4.0, 5.0 }(not in menu) Turret speeds, in tablets per second
filltable{ fullAt = 0.3, minCharge = 0.4 }(not in menu) How fast the turret's stations fill
xptable{ blend = 6, tray = 4, bag = 1 }XP to the feeder per blend the turret uses up, to the sorter per full tray's worth sorted, and to the packer per bag
station, tickMs'rotary_press', 250(not in menu) The machine, and how often the turret updates

Stage animations and cameras

(Advanced tab.)

  • Config.SceneAnims (menu: Stage animations): what other players see your character doing while you're inside a stage. The stage camera is only on your screen, so without these your character would stand frozen at the bench. Each stage (mill, blend, press, engrave, printer, sealer, bagging, granulate, hardness, ballmill, tumble, coat, rotary, reagent) has a dict, clip and flag.
  • Config.SceneCameras (menu: Stage cameras): where the camera sits for each stage and what it frames. Each has an offset (from the station: -Y is in front, +Z is up), a lookAt point and a fov. The press, electric press, capsule board and mixer also have extra shots (over the tray, on the die, while mixing) and an ease time. Change these live, walk into the stage, and adjust until the whole working area is in shot.

Keep unchecked batches for

(Advanced tab.)

SettingTypeDefaultWhat it does
Config.BatchRetentionDaysnumber0Deletes the stats of batches nobody ever inspected once they're older than this many days (checked when the server starts). 0 keeps them forever. Inspected batches are always kept.

Pills whose batch has been deleted become "unknown": they can't be inspected, packed or tested, and taking one uses it up with no effect. Only raise this if old pills no longer matter on your server.

Formulas

Config.Formulas in shared/config/production.lua defines the five product lines. Only each line's requiredLevel is in the menu, under Players → Progression → Product line unlocks. Everything else here is (not in menu) and read from the file on every start.

Line keyrequiredLevelaccepts (raw actives)productstampstabletsPerBlendOther
party1party_powderparty_pillplain, brand48Takes dye
bar3pharma_bottlebar_pillplain, ref48
blues5pharma_bottleblue_pillplain, ref48counterfeit = true
perc5pharma_bottleperc_pillplain, ref48counterfeit = true
capsule7party_powder, mystery_powdermolly_capsuleplain30Filled on the capsule board
  • requiredLevel is the level to make that line (mix it, and cut a die for it).
  • accepts is which raw actives' milled powder the line takes.
  • stamps is what the engraver may put on the line's dies: plain (a blank face), ref (the line's reference imprint) or brand (a player brand).
  • pourable lists what can go in the bowl (milled powder, filler, binder, lubricant, and dye for party pills).
  • packed names the item each packing turns the line's pills into, for NOVA Bars packed = { baggie = 'bar_pill_bag', bottle = 'bar_pill_bottle', blister = 'bar_pill_blister' }. Party pills and capsules have no bottle, since they can't be bottled. If you let a line into a packing it has no item for, its packed pills stay the loose item.

Changing the line keys, items or the capsule setup can break other parts of the resource. Adjust levels and accepts, and leave the rest as shipped unless you're sure.

Quality

Config.Profile (menu: Lab → Quality → Tablet Profile, Advanced tab). This is what makes a good tablet. Every "window" is a target range, not a maximum: going over costs as much as falling short.

SettingTypeDefaultWhat it does
PotencyWindowtable{ low = 45, high = 68 }The potency target for Party Pills and AURA Capsules. The other lines have their own (see Lines).
PotencyRefnumber0.30The dose that reads as a potency of 50. Raise it to make the same formula read weaker.
ForceWindowtable{ low = 48, high = 66, falloff = 20 }The compression that gives solid tablets
DepthForceRefnumber50The fill depth at which a force setting delivers exactly itself. This ties the two press dials together.
TimingFloornumber0.45What a completely uneven stroke still scores, so bad timing never zeroes a stat
WearSpannumber130Die wear at which wear's effect on imprint reaches zero
ResidueSpannumber95Residue at which residue's effect on imprint reaches zero
FillerFloornumber0.35Below this share of filler, tablets can't form a clean face
GrindWindowtable{ low = 60, high = 80, falloff = 25 }The grind that compacts well
Granulationtable{ spreadRelief = 0.45, finesRelief = 0.65, flowBonus = 0.45 }What a fully granulated blend is worth: less spread, fines that stop counting, faster die filling
BinderWindowtable{ low = 0.07, high = 0.12, falloff = 0.05 }Binder as a share of the formula
LubeWindowtable{ low = 0.008, high = 0.018, falloff = 0.010 }Lubricant as a share of the formula
Variancetable{ base = 30.0, floor = 1.5, levelRelief = 0.8 }Tablet-to-tablet spread at a poor blend and a perfect one, and how much each level above 1 narrows it
ConsistencyScalenumber12.0The spread (in stat points) that scores zero consistency
BaseDefectChancenumber0.04The chance of a cosmetic dud even on a flawless run
Weightstable(not in menu) How much each input counts toward integrity, imprint and finish
Defectstable(not in menu) The stat levels at which each defect starts to appear
GradestableExcellent 85, Good 70, Fair 52, Poor 34, Bad 0(not in menu) The grade bands
ImpressionCrumbly, ImpressionChipped, ImpressionRough, ImpressionUneven, ImpressionCleannumber35, 45, 45, 50, 75(not in menu) When each impression shows on an uninspected batch
Linestablesee below(not in menu) Per-line overrides

Lines (not in menu) overrides the base values for one product line:

LineOverrides
barPotencyWindow = { low = 40, high = 60 }, and adds the snapped defect
bluesPotencyWindow = { low = 52, high = 72 }, and a Match (counterfeit) score: stamp weights ref = 1.0, plain = 0.25; term weights stamp 30, imprint 30, finish 25, consistency 15
percPotencyWindow = { low = 38, high = 58 }, and the same Match as blues
capsuleNo imprint; the tablet defects are switched off and replaced with dented and leaking

Skill (file only)

Config.Skill.Reveal in shared/config/profile.lua maps each level to how much the gauges and readings show: 'zones' (words, no numbers), 'values' (exact numbers) or 'preview' (numbers, plus each tablet's defect called out and the fuller light-box reading). Defaults: levels 1–2 zones, 3–5 values, 6–10 preview. It's always read from the file: edit it and restart.

Players

World

All under Players → World.

Pills breaking

Config.Decay (menu: Pills breaking).

SettingTypeDefaultWhat it does
enabledbooleantrueTurns pills breaking on or off
maxLossnumber0.6Share of a stack a full-strength knock breaks, for a batch with no integrity and no packing
exponentnumber1.5How much integrity protects. Higher means sound batches barely notice knocks.
time.everyMinutesnumber20How often weak batches crumble over time
time.integrityFloornumber55Only batches below this integrity crumble over time
time.severitynumber0.25How big a knock time counts as
crash.minDropnumber9.0The smallest sudden speed drop that counts as a crash (m/s)
crash.fullDropnumber30.0The speed drop that counts as a full-strength knock
fall.minHeightnumber3.0The shortest fall that counts (metres)
fall.fullHeightnumber12.0The fall that counts as a full-strength knock
cooldownSecondsnumber4Knocks closer together than this count as one

How much packing protects is set under Packaging (protection).

Dust

Config.Dust (menu: Dust).

SettingTypeDefaultWhat it does
enabledbooleantrueTurns dust on or off
perSecondnumber1.2Exposure gained per second in a dusty stage
decayPerSecondnumber2.5Exposure lost per second otherwise
hazeAtnumber20Exposure at which the screen starts to haze
coughAtnumber55Exposure at which the character starts coughing
damagenumber0Health lost every few seconds while coughing. 0 does no harm. Never takes a player below 101 health.
stagestable{ mill = true, press = true, rotary = true }(not in menu) Which stages throw dust. A press only counts while it's striking tablets or the capsule board is being filled, not while sorting or scrubbing.
collector.rangenumber4.0A running dust collector this close to the player clears the air entirely (metres)
mask.shieldnumber0.85Share of dust exposure the mask stops
mask.animtablemp_masks@standard_car@ds@ / put_on_mask, 1200 msPlayed putting the mask on and taking it off. The mask changes halfway through.
collector.stationstring'dust_collector'(not in menu) The machine that counts as a dust collector
mask.itemstring'dust_mask'(not in menu) The item that puts the mask on and takes it off
mask.modelstring'oxide_pill_dust_mask_worn'(not in menu) The model shown on the wearer's face. It ships with the resource
mask.bonenumber31086(not in menu) The head bone the model is attached to
mask.offsetvector3vec3(0.0, 0.0, 0.0)(not in menu) Nudges the model on the face, in metres
mask.rotationvector3vec3(0.0, 0.0, 0.0)(not in menu) Turns the model on the face, in degrees

Taking pills

Config.Consume (menu: Taking pills).

SettingTypeDefaultWhat it does
enabledbooleantrueWhether pills can be taken at all. When off, using a pill does nothing.
overdose.enabledbooleantrueTurns overdoses on or off
overdose.perPointOvernumber0.035Overdose chance per point of potency over the window
overdose.severeSharenumber0.35Share of overdoses that are severe
overdose.mildDamagenumber15Health lost in a mild overdose
overdose.severeDamagenumber150Health lost in a severe overdose
overdose.brandPenaltynumber25Reputation a brand loses when one of its pills overdoses someone because the batch was too strong (not when the player simply took too many)
overdose.stack.limitnumber3Pills a player can take inside the window before each extra one adds risk, however good the batch
overdose.stack.windowSecondsnumber600The window, in seconds
overdose.stack.perExtranumber0.12Overdose chance added per pill past the limit
linestablesee below(not in menu) Each line's effect and length
effectstablesee below(not in menu) What each effect does
animtablemp_suicide / pill, 2200 ms(not in menu) The pill-taking animation
overdose.linestableparty 1.0, capsule 1.0, bar 0.8, blues 2.0, perc 1.2(not in menu) Overdose risk per line
overdose.medicaltablemild: sickness / overdose, severity 2, expires after 600 s; severe: severity 4(not in menu) The condition recorded by a medical resource such as oxide-medical, if you run one

lines (not in menu): party and capsule are euphoria for 240 s; bar is sedated for 300 s; blues is opioid for 300 s; perc is opioid for 240 s. Lengths are for a batch in the middle of its potency window.

effects (not in menu):

EffectScreen effectStrengthOtherStress
euphoriadrug_flying_base0.35Sprint ×1.12 (run)-15
sedateddrug_drive_blend010.45Drunk walk (walk, move_m@drunk@slightlydrunk)-30
opioiddrug_wobbly0.3+3 health every 5 seconds (health, tick)-10

Stress changes need a framework with a stress system (QBCore and QBX; ESX has none).

Reagent testing

Config.Reagent (menu: Reagent testing).

SettingTypeDefaultWhat it does
itemstring'reagent_kit'The kit item
usesnumber5Tests in a new kit
secondsnumber3.0How long a test takes
classestable(not in menu) The vial colour for each class: mdma black, meth orange, opioid purple, fentanyl blue, benzo and cut clear
activestableparty_powder = 'mdma', pharma_bottle = 'opioid'(not in menu) What each known raw active really is, for powder not yet made into a line
linestableparty/capsule 'mdma', bar 'benzo', blues/perc 'opioid'(not in menu) What each product line tests as. A line's class wins over its active's
mysterytablesee below(not in menu) What mystery powder can turn out to be

mystery (not in menu): each lot is rolled once from these, by weight.

ClassWeightStrength (scale)Overdose risk (overdose)
mdma451.01.0
cut250.51.0
meth151.251.5
fentanyl151.83.0

Police evidence

Config.Evidence (menu: Police evidence).

SettingTypeDefaultWhat it does
jobstable{ 'police', 'sheriff' }Jobs that can log evidence in Pill ID. Capital letters don't matter.
dutyOnlybooleantrueOnly while on duty
destroybooleanfalseRemove the pills once logged. Off keeps them in the officer's inventory, marked as evidence.
serialTrailbooleanfalseGives every press placed from now on a serial number, and shows it on seized batches
showOwnerbooleanfalseWith the serial trail on, evidence also names who placed the press

Selling

All under Players → Selling.

Brand reputation

Config.Reputation (menu: Brand reputation).

SettingTypeDefaultWhat it does
perUnitnumber0.5The most reputation one pill sold can add (a better batch adds more)
maxBonusnumber0.25Extra price a brand gets at the reputation cap (0.25 = 25%). A brand below zero sells for up to this much less.
seizurePenaltynumber10Reputation lost per police seizure
maxnumber1000The reputation cap
minnumber-100The reputation floor
tierstablebad -100, shaky -25, known 25, respected 150, notorious 400(not in menu) What Pill ID calls each reputation level

Pharma delivery run

Config.Delivery (menu: Pharma delivery run).

SettingTypeDefaultWhat it does
enabledbooleantrueTurns the delivery run and its contact on or off
requiredLevelnumber5Level to take work
contact.coordsvector4vec4(283.81, 30.70, 88.47, 160.0)Where the contact stands and which way they face. Place previews the ped in the world: scroll to turn, click to confirm.
contact.modelstring'a_m_m_business_01'The contact's ped model
pointslist7 doorstepsWhere buyers come out. A run picks dropsPerRun of them at random. Add and each point's Place button open the in-world picker: aim at the doorstep and click. The menu won't save the run turned on with no points.
perDropnumber10Tablets handed over per drop
dropsPerRunnumber4Drops in a run
perTablettable{ blues = 60, perc = 45, bar = 35 }Cash per tablet at full price, before the buyer judges the batch
launder.enabledbooleantrueWash dirty money at each drop
launder.typestring'auto'Where dirty money comes from: 'auto', 'account', 'item' or 'bills' (see Laundering)
launder.namestring'black_money'The account or item name (not used by 'auto')
launder.itemValuenumber1What one dirty-money item is worth ('item' only)
launder.metadataKeystring'worth'The field on each bill that holds its worth ('bills' only)
launder.perDropnumber2000The most dirty money washed per drop
launder.rate.min / launder.rate.maxnumber0.55 / 0.9Clean money back per dirty dollar, for a poor batch and for a perfect one
cooldownMinutesnumber15Wait after a run ends before the next (also applied if the player logs out mid-run)
timeLimitMinutesnumber25Time limit for a run
xpPerDropnumber12XP per drop
contact.scenariostring'WORLD_HUMAN_STAND_IMPATIENT'(not in menu) The contact's idle animation
buyerModelstable4 models(not in menu) The buyer character models: a_m_y_business_02, a_f_y_business_02, a_m_m_prolhost_01, a_f_m_bevhills_01
linestable{ 'blues', 'perc', 'bar' }(not in menu) Product lines the buyers take
packingstring'blister'(not in menu) How the pills must be packed
handoffDistancenumber6.0(not in menu) How close to the doorstep the handoff must happen (metres)

The 7 default doorsteps are vec3(772.54, -152.31, 74.42), vec3(839.75, -181.45, 74.18), vec3(920.87, -238.29, 70.17), vec3(1060.83, -378.49, 68.22), vec3(1099.41, -438.71, 67.78), vec3(1207.42, -620.35, 66.43) and vec3(525.93, 207.16, 104.73).

The contact has no map blip, and is stood on the ground wherever you put them, so the height only needs to be close. A moved contact appears at the new spot within a couple of seconds for anyone nearby.

Police alerts for handoffs are set under Dispatch (the Delivery handoff stage).

Laundering

Players → Selling → Pharma delivery run → Laundering → Dirty money is decides where the dirty money comes from:

typeTakes dirty money from
'auto' (default)The framework's own: markedbills with their worth in the worth field on QBCore, black_money items worth $1 each on QBX, the black_money account on ESX
'account'The money account named in name
'item'The item named in name, each worth itemValue
'bills'The item named in name, each worth what its metadataKey field says (like QB marked bills)

On QBX, check which one your server uses. The default matches a stock Qbox install, which keeps dirty money as black_money items. If your server uses markedbills instead, set Dirty money is to Bills with their worth in metadata, Account or item name to markedbills and Bill worth field to worth.

Each drop takes up to perDrop dollars of it and pays back clean cash. With bills, the biggest bills go first and any change comes back as one new bill. If the player has none, the laundering step does nothing and the drop still pays its normal cash. To switch laundering off entirely, turn off Laundering → Enabled.

Buyers (file only)

Config.Buyers in shared/config/world.lua defines the four street buyer types used for oxide-drugselling sales. It's always read from the file: edit it and restart. Each archetype has:

FieldWhat it does
shareHow many buyers are this type, relative to the others (club 35, street 35, pharma 15, bulk 15)
weightsHow much each stat counts to them (potency, integrity, imprint, finish, consistency, match)
hotPrice multiplier for a batch over its potency window
linesPrice multiplier per product line
packingPrice multiplier per packing (loose, baggie, bottle, blister)
rangeThe multiplier a worthless batch and a perfect one fetch

The default values for each type are in Features. The delivery run pays by the pharma type.

Progression

Config.Progression (menu: Players → Progression).

Levels (in the menu)

LevelXP required
10
2100
3300
4650
51200
62000
73200
85000
97500
1011000

Levels must go up in order. If you add levels beyond 10, also look at Config.Skill (above) so the new levels reveal what you want.

XP rewards (in the menu)

Config.Progression.xpRewards (menu: XP per stage):

KeyDefaultEarned for
mill6Milling a powder
blend10Mixing a blend
press14Finishing a press run
clean3Cleaning a die
sort8Sorting a tray
package6Packing pills: once per bagging visit (if at least one bag was filled), and once per confirm at the label printer or blister sealer
engrave4Cutting a die: its first shape, and the stamp that finishes it. Re-cutting a blank die to another shape pays nothing
granulate6Granulating a blend
tumble6A drum tumbler run
ballmill6A ball mill run
coat8A pan coater run

Inspecting, hardness tests and reagent tests pay nothing on purpose: they already cost tablets. Rotary press and delivery XP are set in their own sections (Config.Rotary.xp, Config.Delivery.xpPerDrop). XP for street sales is set in oxide-drugselling.

Product line unlocks (in the menu)

The level needed to mix each product line (Config.Formulas.<line>.requiredLevel, see Formulas):

LineLevel
Party Pills1
NOVA Bars3
VELA Blues5
AXIA Percs5
AURA Capsules7

A line also needs its machines: capsules need the Capsule Filling Board, for example, whose level is set under Machines.

Perks (not in menu)

Config.Progression.perks:

KeyLevelEffect
tooling10wearMultiplier = 0.6: die sets wear 40% slower
reputation10reputationMultiplier = 1.25: brand reputation from sales builds 25% faster

Advanced

Dispatch

Config.Dispatch (menu: Advanced → Dispatch → Police alerts, Advanced tab). Production is risk-free out of the box.

When a player starts a stage, the server rolls once. On a hit, a dispatch call goes out at the station's saved location, not the player's, so a suspect can't fake or move it.

SettingMenu labelDefaultWhat it does
chanceAlert chance0.0Chance of an alert each time a stage is started. 0 turns production alerts off. 0.15 is roughly one in seven.
stageChancePer-stage chanceall -1A different chance for one stage. -1 means "use the alert chance above".
cooldownSite cooldown300Seconds after a station alerts before it can alert again. A roll that doesn't alert doesn't start it. Other stations are unaffected.
jobsAlert jobs{ 'police' }Jobs that receive the alert. Type each name exactly as your framework spells it (usually lowercase, like police).
code, title, messageCall code, Title, Message'10-15', 'Suspected Narcotics Lab', 'Reports of chemical odour and unusual activity at this location.'The text responders see. The default message doesn't say what's being made.
stageAlerts(not in menu)delivery: title 'Suspicious Handoff', message 'A caller reports what looks like a drug handoff at their door.'Different wording for a stage that isn't a lab. Anything not set here uses the lines above.
priorityPriority21 is highest
iconIcon'fas fa-pills'Font Awesome icon
blipDataMap blip{ sprite = 51, color = 5, scale = 1.0, radius = 100 }The map blip, and the size of the search circle around the site (metres), for dispatch resources that draw one

The stages you can tune separately are mill, blend, press, package (baggies), bottle, blister, granulate, tumble, ballmill, coat, rotary and delivery (a delivery run handoff, labelled Delivery handoff in the menu). A common setup is to leave the master chance low and raise just the press.

What "chance" means in practice: it's rolled when a stage is started, not per batch finished. After a station alerts, it doesn't alert again until the Site cooldown has passed. So with the defaults, each station sends at most one alert every 5 minutes, however many times players start stages on it. A roll that doesn't alert leaves the station free to roll again on the next stage.

Delivery handoffs alert where the player hands over the card (within a few metres of the doorstep), with their own wording (stageAlerts, above). Their cooldown is per player rather than per station. Like every other stage they follow the master Alert chance unless you set Delivery handoff yourself, so with the defaults they're off.

What you need installed

Alerts go through whatever dispatch resource you run, as long as o-link supports it: ps-dispatch, cd_dispatch, qs_dispatch, lb-tablet, oxide-dispatch, tk_dispatch, fd_dispatch, emergencydispatch, linden_outlawalert, origen_police, bub-mdt, kartik-mdt, redutzu-mdt, wasabi_mdt and piotreq_gpt.

Without one, the fallback is basic. Players with the alert job get a short notification ([10-15] plus the message; the title isn't shown) and a map blip on the station that disappears after 30 seconds.

If nobody with the alert job is online, the alert is dropped. That's on purpose: there's no queue of old calls waiting for the first officer to log in. (oxide-dispatch is the exception: it records the call whether or not anyone is online.)

Compatibility

Config.ModelSwaps (menu: Advanced → Compatibility → Model replacements).

SettingTypeDefaultWhat it does
Config.ModelSwapstable{} (empty)Rows of { from = 'model', to = 'model' }. If a model is missing on your game build, the resource warns admins and skips it. Add a row to use a different model instead.

For example, to replace the workbench table with a different base-game table (add the row in the menu on a server that has already started once):

Config.ModelSwaps = {
    { from = 'bkr_prop_weed_table_01b', to = 'prop_table_03' },
}

Every pill station and tablet model ships in this resource's stream/ folder, so a warning about one of those means the install is incomplete (the folder is missing or damaged), not an old game build. Re-copy the resource. The warning tells you which case it is.

Next Steps