Crafting
Crafting
Drop one ingredient onto another and the recipe lights up.
The gesture
Crafting has no menu. You drag an item onto another item in your own inventory; if the pair names a recipe, the interface shows what it would make, what it costs, which tools are needed and the chance of failure. Confirm and the hands get busy for time milliseconds.
Two constraints follow from making it a gesture rather than a menu:
A drag names two items. A recipe can need any number of ingredients, but a drag has two ends, so any two of a recipe's ingredients start it — scrap onto plastic or plastic onto scrap, the same recipe answers. What else it needs is taken from the rest of the bag, and the confirm window lists every line with what you have beside it.
A pair belongs to one recipe. If scrap onto plastic could make either a lockpick or a crowbar, the drag would have to ask which — and then it is a menu again. The admin panel refuses to save a recipe that shares a pair with another one, and names the recipe it clashes with. data/recipes.lua is not checked the same way, so keep the pairs in the file distinct.
Defining a recipe
data/recipes.lua:
Recipes = {
{
id = 'lockpick',
ingredients = {
{ item = 'scrap', count = 2 },
{ item = 'plastic', count = 1 },
},
results = { { item = 'lockpick', count = 1 } },
time = 2500,
},
}
| Field | Meaning |
|---|---|
id |
Unique name |
ingredients |
Each { item, count }. Add consume = false to make it a tool — needed, not spent |
results |
What comes out. More than one entry is allowed |
time |
Milliseconds the hands are busy. Left out, it is 3000, as in ox_inventory. 0 is instant (see below) |
chance |
Percent success. Below 100, failure costs the materials |
keepOnFail |
Return the ingredients when it fails |
label |
The name shown for it; defaults to the first result's label |
job / grade |
Only that job, at that grade or above |
licence |
A licence the player must hold |
skill / level |
A skill level, answered by whichever resource registered RegisterSkillProvider; with none registered the recipe is refused |
bench |
true = only at a Config.Workbench location |
enabled |
false turns it off without deleting it |
The shipped first-aid recipe demonstrates the long form: three ingredients, one of which is a tool, a failure chance, and waste out the other end.
The time it takes
A recipe with a time is a timed action, as it is in ox_inventory. Confirming it closes the inventory and runs a progress bar with ox's crafting animation (Config.Anim.craft), on the same bar a meal or a body search uses, so Config.Consume.progress picks it too. Nothing is spent while the bar runs. The cancel key (X) or dying stops it, and the materials stay where they were.
The server keeps the clock. When the bar reports it has finished, the server checks that the full time has passed, then asks every rule again: the pair must still make the same recipe, the materials must still be there, the bench must still be in reach and the result must still fit. A bar that finished early, or a bag that changed underneath it, crafts nothing.
Carrying the result
A craft that would put you over weight is refused before the materials are spent, and so is one whose result your job may not hold (restrictJobs). Free slots are not reserved ahead: if the bag runs out of slots while the results go in, what was spent stays spent, what was made stays made, and the ledger records exactly that.
Two places a recipe can live
| Source | Where it is stored | Who edits it |
|---|---|---|
data/recipes.lua |
The file | A developer |
| Admin panel → Recipes | aty_recipes table |
An admin, live, no restart |
Panel recipes are never written back to the file. The file stays the developer's copy; the table is the layer on top. Both are read by the same loader, so a recipe behaves identically whichever it came from.
invrecipes list what is loaded, and where each came from
invcraft SELF-TEST — crafts the shipped recipes in a throwaway
stash and checks every way a craft must refuse
invrecipewrite SELF-TEST — exercises the editor through the panel's
own endpoint. It writes nothing to disk.