API Reference
Server exports provided by oxide-pills — progression, XP and sales, buyer pricing through PriceFor, live settings — plus the metadata every pill item carries.
Server exports provided by oxide-pills, for developers integrating other resources (selling scripts, missions, leaderboards).
Any server resource can call these after oxide-pills has started.
Server Exports
GetPlayerLevel(source)
Returns the player's pill level (1–10 with the default level table).
local level = exports['oxide-pills']:GetPlayerLevel(source)Returns 1 if the player has no character loaded. A character with no pill progression yet gets a level 1 row created.
GetPlayerProgression(source)
Returns the player's full pill progression stats.
local progression = exports['oxide-pills']:GetPlayerProgression(source)Shape:
{
level = 1,
xp = 0,
currentLevelXp = 0, -- XP threshold of the current level
nextLevelXp = 100, -- XP threshold of the next level; nil at max level
totalCreated = 0, -- pills kept from sorted trays
totalSold = 0,
unlocks = { -- stations, product lines and perks, ordered by level
{
level = 1, -- the level it unlocks at
label = 'Crank Press', -- friendly name
unlocked = true, -- whether this player has reached it
},
-- ...
},
}Returns nil if the player's character identifier can't be found (for example, not fully loaded).
AddXP(source, amount)
Adds pill XP and runs the level-up check, so the player may level up from this call.
local ok = exports['oxide-pills']:AddXP(source, 25)Parameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server ID |
amount | number | XP to add. Must be greater than zero. |
Returns: boolean. true on success, false if the player has no character loaded or amount is missing, not a number, or not greater than zero.
oxide-drugselling calls this on every pill sale.
AddSold(source, amount)
Adds to the player's sold counter for pills, so sales show in /pills stats.
local ok = exports['oxide-pills']:AddSold(source, 12)Returns: boolean, with the same rules as AddXP.
AddSold only updates the counter. It doesn't award XP (call AddXP too) and it doesn't build brand reputation. Brand reputation only grows from sales made through oxide-drugselling and from delivery run drops.
PriceFor(metadata, context)
The price multiplier a street buyer puts on a stack of pills. This is what oxide-drugselling calls (as an export_multiplier pricing modifier in its Config.Drugs.pills) to price every pill sale. It reads the batch's hidden stats on the server; the numbers never leave it.
local multiplier, details = exports['oxide-pills']:PriceFor(itemMetadata, { npcModel = GetEntityModel(buyerPed) })Parameters:
| Name | Type | Description |
|---|---|---|
metadata | table | The pill item's metadata (it needs batch) |
context | table | The sale. npcModel (number, the buyer's model hash) decides which buyer type is buying. |
Returns:
multiplier(number): multiply your base price by this. It's rounded to the nearest 0.05, so a price reads as good or bad without giving away the hidden stats.1.0when the item has no known batch, or whennpcModelis missing or0.details(tableornil): one line for a sell panel, saying who the buyer is and what they thought.nilwhen the multiplier is the plain1.0fallback.
{
{
label = 'Club kid', -- the buyer type
value = 'Likes the faces', -- what they thought
bonus = 0.2, -- multiplier - 1.0
color = 'text-emerald-400', -- text-emerald-400 when they liked it, text-orange-400 when not
type = 'variant',
},
}The multiplier includes the batch's quality, its packing, its product line, whether it's hot, and its brand's reputation. See Selling.
GetSetting(key)
Reads a live setting (the values stored in the oxide_settings table and edited from /pills settings; see Configuration). The key is the top-level config name without the Config. prefix.
local ownership = exports['oxide-pills']:GetSetting('RequireOwnership')
local delivery = exports['oxide-pills']:GetSetting('Delivery') -- the whole Config.Delivery tableReturns: the current value (any type: boolean, number, string or table), or nil for an unknown key.
SetSetting(key, value)
Changes a live setting. It applies on the server straight away, is saved to the database, and is sent to every client. It's the same as saving it in the settings menu, and it lasts through restarts.
exports['oxide-pills']:SetSetting('RequireOwnership', false)Parameters:
| Name | Type | Description |
|---|---|---|
key | string | The top-level config name without Config. |
value | any | The whole new value for that key. For a table like Delivery, pass the entire table. |
Returns: true.
SetSetting doesn't check the value against the menu's limits the way the settings menu does, so pass a complete, valid value. Only use it for keys that appear in the settings menu. Skill and Buyers are meant to be read from the config file (see Configuration).
Prefer GetSetting/SetSetting over reading or writing the oxide_settings table directly. They keep the server, database and connected clients in sync in one call.
Item Metadata
Pill items carry metadata your scripts can read through your inventory's normal metadata access. The quality numbers are never in the metadata. They stay on the server, keyed by the batch ID, so they can't be read from an inventory. Use PriceFor if you need a batch's value.
Finished pills
party_pill, bar_pill, blue_pill, perc_pill, molly_capsule, and their packed items (bar_pill_bag, bar_pill_bottle, bar_pill_blister and so on; see Installation):
| Field | Description |
|---|---|
batch | The batch ID. Every pill from one sorted tray shares it. |
line | party, bar, blues, perc or capsule |
tint | The party pill colour (0–7) |
stamp | The face: plain (blank), ref (the line's reference imprint) or brand |
brand | The brand's name, on branded party pills (public: it's on the face) |
symbol | The brand's symbol, on branded party pills |
description | The batch's impression, for example "These look clean." For bottles and blisters, the label or card text too. |
bagged | 1 when packed in a baggie |
packed | 'bottle' or 'blister' when packed that way |
label | The bottle label template key, on bottled pills |
coated | 1 on pan-coated pills |
evidence | 1 once police have logged the stack as evidence |
Pills of the same batch but different packing are separate items: loose pills are the base item, packed ones the line's packed item. The count is always tablets.
Other items
| Item | Metadata fields |
|---|---|
pill_milled | grind, fines, active (the raw active it came from), lot (mystery powder only), identified (after a reagent test), description |
pill_blend | formula, line, active, lot, activeRatio, binderRatio, lubeRatio, fillerRatio, grind, fines, uniformity, tint, granulation (after the sieve), tumbled (1 after the drum tumbler), description |
punch_die_set | wear, line (the shape it's cut for; none means party), stamp, brand (brand ID), serial (an opaque ID given the first time the die goes on a press, so the server can follow its wear), description |
reagent_kit | uses (tests left), description |
mystery_powder | lot, identified (after a reagent test) |
pill_rejects | line, lot |
A mystery powder lot is an opaque ID. What it really is lives only on the server until a reagent test reveals it.
Integration Examples
Gate a feature behind pill level
local level = exports['oxide-pills']:GetPlayerLevel(source)
if level >= 5 then
-- unlock a pharma wholesaler, a bigger stash, etc.
endPrice pills in your own selling script
-- Called from your sell handler with the pill's metadata and the buyer ped. The price is per
-- tablet, and a packed item prices as its loose line (PriceFor already weighs the packing).
local BASE_PRICE = { party = 30, capsule = 35, bar = 25, blues = 45, perc = 35 }
local function priceForPill(source, itemName, itemMetadata, buyerPed)
local base = BASE_PRICE[(itemMetadata or {}).line] or 0
local multiplier = exports['oxide-pills']:PriceFor(itemMetadata, { npcModel = GetEntityModel(buyerPed) })
local price = math.floor(base * multiplier)
-- ...remove the pill and pay the player through your framework here...
-- Credit the sale to pill progression.
exports['oxide-pills']:AddSold(source, 1)
exports['oxide-pills']:AddXP(source, 3)
return price
endA custom selling script built this way prices pills the same way oxide-drugselling does, but it won't build brand reputation. Only oxide-drugselling sales and delivery drops do that.
Read a setting from another resource
local delivery = exports['oxide-pills']:GetSetting('Delivery')
if delivery and delivery.enabled then
print(('Pill delivery runs pay $%d per VELA 30'):format(delivery.perTablet.blues))
endNext Steps
Admin Guide
The /pills command — the live settings editor, the lab kit, setting levels, the tray test, player commands, Machine Test debug mode, police alerts and permissions.
Troubleshooting
Fixes for common oxide-pills problems — setup and inventories, placing stations, milling and blending, pressing and sorting, the other stations, taking pills, selling and the delivery run, Pill ID and police, and settings.