# Craft Menu

## 🌐 Translations

UI texts are provided by the server through `Config.Txt`.

The `translate.js` file is only a static client dictionary and does not provide a full multi-language system by itself.

To support multiple languages properly, the correct translation table must be injected server-side, or `translate.js` must be extended manually.

## 🎛️ Admin UI

The admin UI allows creating, editing, disabling, and updating recipes directly in-game.

### Access Conditions

The player must belong to one of the groups defined in `Config.AdminGroups`.

### How It Works

The `Admin` button appears in the crafting UI when the player is recognized as admin.\
The item list shown in the admin modal is loaded dynamically from the item database.\
Weapon outputs are also supported in the admin recipe output list through `Config.WeaponList`.\
Saving a recipe sends the full payload to the server and stores it in the database.\
Deleting a recipe does not remove the row from the database. It sets `enabled = 0`.

### Admin Features

* Create a new recipe
* Edit an existing recipe
* Disable a recipe
* Set required level
* Set craft duration
* Define grouped ingredients
* Choose whether a locked recipe should stay visible or be hidden until unlocked

## 🗄️ Database

Two tables are created automatically:

### `job_crafting_xp`

Stores crafting XP and level per job and character.

### `job_crafting_recipes`

Stores persistent crafting recipes.

### Important

Recipes are now fully database-driven.\
`Config.Crafts` is no longer used as a recipe source.\
There is no automatic import from config anymore.

## 🚪 Opening the Crafting Menu

The crafting menu can still be opened manually by event.

### Open the crafting menu for the player’s current job

```lua
TriggerServerEvent("bt_craft:openCraftMenu")
```

### Open a crafting menu for a specific job

```lua
TriggerServerEvent("bt_craft:openCraftMenu", "police")
```

This means the script can be opened from:

* usable items
* prompts
* NPC interactions
* zones
* props
* custom server logic

## 📍 Config.CraftPoints

`Config.CraftPoints` adds optional world interaction points for craft menus.

### Main Fields

* `id` = unique identifier for this exact interaction point
* `craft` = craft category / recipe group to open
* `coords` = fixed position to check
* `props` = nearby prop(s) to check
* `item` = usable item name

### Opening Rules

* `coords` only\
  The player can open the menu near these coordinates.
* `props` only\
  The player can open the menu near one of these props.
* `coords + props`\
  Both conditions must be valid at the same time.
* `item` only\
  Using that item opens the craft menu directly.
* `item + coords`\
  The player must have the item to open the menu at these coordinates.\
  Using the item near this point also opens the menu.
* `item + props`\
  The player must have the item to open the menu near one of these props.\
  Using the item near this point also opens the menu.
* `item + coords + props`\
  The player must have the item, be near the coordinates, and be near one of the props.\
  Using the item near this point also opens the menu.

### Notes

* `promptLabel` and `promptGroup` only affect the world prompt display.
* `distance` is used for coords/props detection.
* `item` is not consumed by `bt_craft`. It only acts as an opener / requirement.

### Examples

#### Coords + props + required item

```lua
{
    id = "campfire_blackwater",
    craft = "campfire",
    promptLabel = "Cook at Campfire",
    promptGroup = "Campfire",
    distance = 2.0,
    item = "campfire_book",
    coords = vector3(-932.45, -1390.75, 49.47),
    props = {
        "p_campfirecombined01x"
    }
}
```

#### Item only

```lua
{
    id = "blacksmith_book",
    craft = "gunsmith",
    item = "craft_book_blacksmith"
}
```

#### World interaction + required item

```lua
{
    id = "workbench_book_valentine",
    craft = "gunsmith",
    item = "craft_book_gunsmith",
    promptLabel = "Use Workbench",
    promptGroup = "Workbench",
    distance = 2.0,
    coords = vector3(-281.54, 778.92, 119.51),
    props = {
        "p_workbench01x"
    }
}
```

## 🛠️ Weapon Crafting

Recipes can craft weapons.

### Notes

Weapon labels in the UI are resolved client-side using official RDR2 weapon names.\
Weapon output selection in the admin UI is populated using `Config.WeaponList`.\
Weapon images are loaded from the VORP inventory image folder.

## 🎞️ Craft Authorization Hook

A client hook is available in `config.lua`:

```lua
Config.OnCraftAuthorized = function(pointId, craftItem, craftDuration)
end
```

This function is called only when the server validates the craft start.

### Parameters

* `pointId` = interaction point id from `Config.CraftPoints`, or `nil` if the menu was opened externally
* `craftItem` = crafted item id
* `craftDuration` = total craft duration in seconds

### Use Cases

* playing animations
* triggering emotes
* starting client-side visual effects
* adding custom sound or roleplay logic

### Example

```lua
Config.OnCraftAuthorized = function(pointId, craftItem, craftDuration)
    TriggerEvent("my_resource:onCraftAuthorized", pointId, craftItem, craftDuration)
end
```

## 🔌 Server Export

```lua
local level, xp = exports.bt_craft:GetPlayerCraftLevelXP(playerId, jobName)
```

### Returns

* `level`
* `xp`

### Defaults

If no record exists, it returns:

* `1`
* `0`

## ✅ Summary

* Fully database-driven recipe system
* Job-based progression and XP
* In-game admin recipe management
* Weapon crafting support
* World interaction support through `Config.CraftPoints`
* Optional hidden locked recipes
* Optional client hook for animations and effects
* Persistent, extensible, and secure


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://botiv.gitbook.io/rdr2/craft-menu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
