RedM documentation

Murphy's Craft

Crafting System

Recipes


This comprehensive guide explains how to create and configure craft categories and recipes.

Table of Contents


Craft interface showing categories, recipe choices, an amount selector and required ingredients
Craft interface showing categories, recipe choices, an amount selector and required ingredients

Source: storefront gallery. These images show the source presentation; interface details and displayed values may differ in your installed version. Select an image to enlarge it.

File Structure

All craft categories are defined in Lua files located in:

text
murphy_craft/shared/craft/

Each file typically contains one category. The file is automatically loaded by the resource.

Existing files:

  • basic.lua - Basic recipes accessible everywhere
  • cuisinier.lua - Cooking recipes
  • docteur.lua - Medical recipes
  • armurier.lua - Gunsmith recipes
  • bricoleur.lua - Tinkering recipes
  • recyclage.lua - Recycling recipes
  • food.lua - Food recipes

Creating a Category

Basic Structure

lua
Craft["category_id"] = {
name = "Category Display Name",
recipes = {
-- Recipes go here
}
}

Parameters

Parameter Type Required Description
category_id string Yes Unique identifier for the category (used in config)
name string Yes Display name shown in the UI
job string No Restrict entire category to a job
jobgrade number No Minimum grade required (requires job)
recipes table Yes Array of recipe definitions

Example - New Category File

Create a new file: shared/craft/mining.lua

lua
Craft["mining"] = {
name = "Mining & Smelting",
recipes = {
-- Add recipes here
}
}

Creating Recipes

Basic Recipe Structure

lua
{
tree_ref = "root", -- Specialization tree reference
xp = 5, -- XP gained when crafting
name = "Item Name", -- Display name
freeaccess = true, -- Accessible without unlocking
image = "nui://path/to/image.png", -- Item image
desc = "Item description", -- Description shown in UI
duration = 10, -- Crafting time in seconds
amount = 1, -- Amount produced
item = "item_name", -- Output item name
ressources = { -- Required materials
{ name = "Material Name", neededQuantity = 2, item = "material_item" },
}
}

Multiple Output Items

You can output multiple different items:

lua
{
tree_ref = "root",
name = "Salvage Kit",
freeaccess = true,
image = "nui://path/image.png",
desc = "Salvage materials from items",
duration = 5,
amount = 1,
item = {
["iron_scrap"] = 3,
["wood_scrap"] = 2,
["cloth"] = 1
},
ressources = {
{ name = "Broken Tool", neededQuantity = 1, item = "broken_tool" },
}
}

Recipe Parameters Reference

Parameter Type Required Default Description
tree_ref string Yes - Reference to specialization node ("root" for base)
xp number No 0 XP gained when crafting this recipe
name string Yes - Display name of the recipe
freeaccess boolean No false If true, accessible without specialization unlock
image string Yes - Path to the item image
desc string No "" Description shown in the UI
duration number Yes - Crafting duration in seconds
amount number Yes - Quantity produced per craft
item string/table Yes - Output item name or table of items
ressources table Yes - Array of required materials
job string No nil Required job to see this recipe
jobgrade number No nil Minimum job grade required

Resources Configuration

Each resource in the ressources array requires:

lua
{
name = "Display Name", -- Name shown in UI
neededQuantity = 5, -- Amount required
item = "item_name" -- Item identifier in inventory
}

Example with Multiple Resources

lua
ressources = {
{ name = "Iron Ore", neededQuantity = 3, item = "iron_ore" },
{ name = "Coal", neededQuantity = 2, item = "coal" },
{ name = "Water", neededQuantity = 1, item = "water_bucket" },
}

Specialization System

The specialization system allows players to unlock recipes by progressing through a skill tree.

How it Works

  1. tree_ref - Links a recipe to a specialization node
  2. freeaccess - If true, recipe is available without unlocking the node
  3. xp - XP gained contributes to specialization progression

Tree Reference Values

Value Description
"root" Base node, always accessible if freeaccess = true
"node1", "node2", etc. Requires unlocking that node in the specialization tree
"branch1_node1" Nested nodes in specialization branches

Recipe Accessibility

lua
-- Always accessible (no specialization needed)
{
tree_ref = "root",
freeaccess = true,
-- ...
}
-- Requires "root" node to be unlocked
{
tree_ref = "root",
freeaccess = false, -- or just omit freeaccess
-- ...
}
-- Requires "node1" to be unlocked in specialization tree
{
tree_ref = "node1",
-- ...
}

Job-Locked Crafting

Restrict categories or recipes to specific jobs.

Category-Level Lock

lua
Craft["medical"] = {
name = "Medical Supplies",
job = "doctor", -- Only doctors see this category
jobgrade = 2, -- Minimum grade 2
recipes = { ... }
}

Recipe-Level Lock

lua
{
tree_ref = "root",
name = "Advanced Medicine",
job = "doctor", -- Only doctors can craft
jobgrade = 3, -- Requires grade 3+
freeaccess = true,
-- ...
}

Behavior Rules

Category Job Recipe Job Result
Not set Not set Everyone can access
"doctor" Not set Only doctors (inherits from category)
Not set "doctor" Only that recipe restricted
"doctor" "sheriff" Recipe overrides to sheriff only

See JOB_LOCK_GUIDE.md for detailed job-locking documentation.


Crafting Tables Configuration

Define where categories are accessible in shared/config.lua:

Adding a Crafting Table

lua
Config.CraftingTables = {
{
name = "Blacksmith Workshop", -- Blip name
cat = { "mining", "blacksmith" }, -- Available categories
coords = vector3(100.0, 200.0, 30.0), -- Location
radius = 5.0, -- Interaction radius
blip = {
hash = "blip_shop_blacksmith",
displaydistance = 50.0,
scale = 0.3,
},
},
}

Crafting Table Parameters

Parameter Type Required Description
name string Yes Display name and blip label
cat table Yes Array of category IDs available here
coords vector3 Yes World coordinates
radius number Yes Radius where crafting menu is accessible
blip table/nil No Blip configuration, nil for no blip

Basic Categories (Accessible Everywhere)

In shared/config.lua:

lua
Config.BasicsCategory = { "basic" } -- These categories work anywhere

Complete Examples

Example 1: Simple Cooking Category

lua
-- File: shared/craft/cooking.lua
Craft["cooking"] = {
name = "Cooking",
recipes = {
{
tree_ref = "root",
xp = 2,
name = "Cooked Meat",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/cooked_meat.png",
desc = "A well-cooked piece of meat",
duration = 8,
amount = 1,
item = "cooked_meat",
ressources = {
{ name = "Raw Meat", neededQuantity = 1, item = "raw_meat" },
}
},
{
tree_ref = "root",
xp = 5,
name = "Stew",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/stew.png",
desc = "Hearty stew that restores health",
duration = 15,
amount = 1,
item = "stew",
ressources = {
{ name = "Raw Meat", neededQuantity = 2, item = "raw_meat" },
{ name = "Carrots", neededQuantity = 2, item = "carrot" },
{ name = "Potatoes", neededQuantity = 2, item = "potato" },
{ name = "Water", neededQuantity = 1, item = "water" },
}
},
{
tree_ref = "node1",
xp = 15,
name = "Gourmet Meal",
-- No freeaccess = requires node1 unlock
image = "nui://redemrp_inventory/html/items/gourmet.png",
desc = "An exquisite culinary creation",
duration = 30,
amount = 1,
item = "gourmet_meal",
ressources = {
{ name = "Prime Meat", neededQuantity = 3, item = "prime_meat" },
{ name = "Herbs", neededQuantity = 5, item = "herbs" },
{ name = "Spices", neededQuantity = 3, item = "spices" },
{ name = "Wine", neededQuantity = 1, item = "wine" },
}
},
}
}

Example 2: Job-Restricted Category

lua
-- File: shared/craft/lawenforcement.lua
Craft["lawenforcement"] = {
name = "Law Enforcement",
job = "sheriff", -- Only sheriffs can access
recipes = {
{
tree_ref = "root",
xp = 0,
name = "Wanted Poster",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/wanted_poster.png",
desc = "Post bounties for outlaws",
duration = 5,
amount = 5,
item = "wanted_poster",
ressources = {
{ name = "Paper", neededQuantity = 1, item = "paper" },
{ name = "Ink", neededQuantity = 1, item = "ink" },
}
},
{
tree_ref = "root",
xp = 0,
name = "Deputy Badge",
jobgrade = 3, -- Only grade 3+ sheriffs
freeaccess = true,
image = "nui://redemrp_inventory/html/items/badge.png",
desc = "Badge for deputizing citizens",
duration = 10,
amount = 1,
item = "deputy_badge",
ressources = {
{ name = "Silver", neededQuantity = 2, item = "silver" },
{ name = "Leather", neededQuantity = 1, item = "leather" },
}
},
}
}

Example 3: Mixed Access Category

lua
-- File: shared/craft/alchemy.lua
Craft["alchemy"] = {
name = "Alchemy",
-- No job restriction on category
recipes = {
-- Public recipe - anyone can craft
{
tree_ref = "root",
xp = 3,
name = "Health Tonic",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/health_tonic.png",
desc = "Restores a small amount of health",
duration = 10,
amount = 1,
item = "health_tonic",
ressources = {
{ name = "Ginseng", neededQuantity = 2, item = "ginseng" },
{ name = "Yarrow", neededQuantity = 2, item = "yarrow" },
{ name = "Empty Bottle", neededQuantity = 1, item = "empty_bottle" },
}
},
-- Doctor-only recipe
{
tree_ref = "root",
xp = 10,
name = "Miracle Cure",
job = "doctor",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/miracle_cure.png",
desc = "Cures all ailments instantly",
duration = 30,
amount = 1,
item = "miracle_cure",
ressources = {
{ name = "Rare Herb", neededQuantity = 5, item = "rare_herb" },
{ name = "Snake Oil", neededQuantity = 2, item = "snake_oil" },
{ name = "Moonshine", neededQuantity = 1, item = "moonshine" },
}
},
-- Outlaw-only recipe
{
tree_ref = "root",
xp = 8,
name = "Poison Vial",
job = "outlaw",
freeaccess = true,
image = "nui://redemrp_inventory/html/items/poison.png",
desc = "A deadly concoction",
duration = 20,
amount = 1,
item = "poison_vial",
ressources = {
{ name = "Venom Gland", neededQuantity = 3, item = "venom_gland" },
{ name = "Nightshade", neededQuantity = 2, item = "nightshade" },
{ name = "Empty Bottle", neededQuantity = 1, item = "empty_bottle" },
}
},
}
}

Quick Reference Card

Minimal Recipe Template

lua
{
tree_ref = "root",
name = "Recipe Name",
freeaccess = true,
image = "nui://inventory/html/items/item.png",
desc = "Description",
duration = 10,
amount = 1,
item = "output_item",
ressources = {
{ name = "Material", neededQuantity = 1, item = "material_item" },
}
}

Minimal Category Template

lua
Craft["category_id"] = {
name = "Category Name",
recipes = {
-- Add recipes here
}
}

Troubleshooting

Recipe Not Showing

  1. Check if freeaccess = true is set (if you want it immediately available)
  2. Verify the tree_ref node is unlocked if freeaccess is false
  3. Check job requirements match player's job exactly
  4. Ensure the category is added to a CraftingTable in config

Category Not Showing

  1. Verify category ID is added to cat array in Config.CraftingTables
  2. Check if job requirements are met
  3. Ensure at least one recipe in the category is accessible

Items Not Given

  1. Verify item name matches your inventory system
  2. Check amount is greater than 0
  3. Review server console for errors

Tips & Best Practices

Naming Convention: Use lowercase with underscores for category_id and item names (e.g., "health_tonic")

Images: Use the nui:// protocol to reference images from your inventory resource

Testing: Enable Config.Debug = true in shared/config.lua to see detailed logs

Balance: Consider crafting duration and resource costs for game balance

Job Names: Must exactly match your framework's job identifiers


Last updated: September 9, 2026