# Configuration

***

### Overview

The entire script is configured through a single `Config.lua` file. It controls framework detection, default vault values, portable safe limits, available 3D objects, language, Discord webhooks, and all in-game text strings.

***

### Default Values

```lua
Config.DefaultSlots  = 30
Config.DefaultWeight = 300000
```

| Option                 | Type   | Description                                                     |
| ---------------------- | ------ | --------------------------------------------------------------- |
| `Config.DefaultSlots`  | number | Default slot count when creating a vault without specifying one |
| `Config.DefaultWeight` | number | Default max weight in grams (300000 = 300kg)                    |

> These values are pre-filled in the creation menu but can be changed per-vault during creation.

***

### Resource Detection — `Config.x8`

Controls which framework, inventory, and target system the script uses. Set any option to `'auto'` to let the bridge detect it automatically based on running resources.

#### Framework

```lua
Framework = 'auto',
```

| Value        | Behavior                                   |
| ------------ | ------------------------------------------ |
| `'auto'`     | Detects qbx\_core or qb-core automatically |
| `'qb-core'`  | Forces QBCore                              |
| `'qbx_core'` | Forces Qbox                                |

#### Inventory

```lua
Inventory = 'auto',
```

| Value            | Behavior                                            |
| ---------------- | --------------------------------------------------- |
| `'auto'`         | Detects ox\_inventory or qb-inventory automatically |
| `'ox_inventory'` | Forces ox\_inventory                                |
| `'qb-inventory'` | Forces qb-inventory                                 |

#### Target

```lua
Target = 'auto',
```

| Value         | Behavior                                                 |
| ------------- | -------------------------------------------------------- |
| `'auto'`      | Detects ox\_target, qb-target, or interact automatically |
| `'ox_target'` | Forces ox\_target                                        |
| `'qb-target'` | Forces qb-target                                         |
| `'interact'`  | Forces interact                                          |

> **Recommendation:** Leave all three on `'auto'` unless you have multiple compatible resources running and need to pick a specific one.

***

### Permissions

```lua
StashCreationPermission = {
    job   = "police",
    grade = 2
},
```

Controls who can create and manage vaults using the in-game commands.

| Field   | Type   | Description                                                        |
| ------- | ------ | ------------------------------------------------------------------ |
| `job`   | string | The job name required (must match exactly as registered in QBCore) |
| `grade` | number | Minimum grade level required                                       |

#### Examples

```lua
-- Police chief and above
StashCreationPermission = { job = "police", grade = 4 }

-- Any sheriff with grade 1+
StashCreationPermission = { job = "sheriff", grade = 1 }

-- Mechanic boss only
StashCreationPermission = { job = "mechanic", grade = 5 }
```

> The check uses `Bridge.Core.HasPermission` which validates job name and grade level server-side.

***

### Commands

```lua
command       = "createvault",
manageCommand = "managevault",
giveCommand   = "givevault",
```

| Option          | Default       | Used For                                                          |
| --------------- | ------------- | ----------------------------------------------------------------- |
| `command`       | `createvault` | Opens the vault creation menu                                     |
| `manageCommand` | `managevault` | Opens the vault management panel (search, edit, delete, teleport) |
| `giveCommand`   | `givevault`   | Gives a portable safe item to a player                            |

#### Customization Example

```lua
command       = "newsafe",
manageCommand = "vaults",
giveCommand   = "givebox",
```

> All three commands respect the same `StashCreationPermission` check, except `givevault` which typically requires admin permissions (handled server-side).

***

### Portable Safes — `Config.Portable`

Controls everything related to the portable safe item that players can carry, drop, and pick up.

```lua
Config.Portable = {
    itemName      = "portable_safe",
    itemLabel     = "Portable Safe",
    minSlots      = 5,
    maxSlots      = 50,
    minWeight     = 10000,
    maxWeight     = 500000,
    defaultSlots  = 20,
    defaultWeight = 100000,
}
```

| Field           | Type   | Description                                           |
| --------------- | ------ | ----------------------------------------------------- |
| `itemName`      | string | Item name as registered in your inventory's items.lua |
| `itemLabel`     | string | Display label shown in the inventory                  |
| `minSlots`      | number | Minimum slots an admin can set when giving a safe     |
| `maxSlots`      | number | Maximum slots an admin can set                        |
| `minWeight`     | number | Minimum max-weight in grams                           |
| `maxWeight`     | number | Maximum max-weight in grams                           |
| `defaultSlots`  | number | Default slot count in the give menu                   |
| `defaultWeight` | number | Default weight in the give menu                       |

#### Important

The value of `itemName` **must match** the item name you register in `ox_inventory/data/items.lua` or `qb-core/shared/items.lua`. See the **Item Setup** page for full instructions.

***

### 3D Objects — `Config.Objects`

List of physical models that can be used as a vault. When creating a vault with the "Use Object" mode, the player picks one of these from a dropdown.

```lua
Config.Objects = {
    { label = 'Small Safe (Default)', model = 'prop_ld_int_safe_01' },
    { label = 'Locker',               model = 'v_ind_rc_lockeropn' },
    { label = 'Gun Locker',           model = 'xm_prop_xm_gunlocker_01a' },
    { label = 'Black Box',            model = 'prop_box_wood02a' },
    { label = 'Metal Cabinet',        model = 'h4_prop_h4_safe_01a' },
}
```

| Field   | Type   | Description                                       |
| ------- | ------ | ------------------------------------------------- |
| `label` | string | Friendly name shown in the dropdown               |
| `model` | string | GTA V prop name (used by `Bridge.Core.LoadModel`) |

#### Adding Custom Models

You can add any valid GTA V prop or addon prop:

```lua
Config.Objects = {
    { label = 'Small Safe',     model = 'prop_ld_int_safe_01' },
    { label = 'Wall Safe',      model = 'p_cs_heist_wall_safe' },
    { label = 'Bank Vault',     model = 'hei_prop_heist_safe_door' },
    { label = 'Custom Crate',   model = 'my_addon_crate_01' },
}
```

> Models must exist on the client. If the model fails to load within 5 seconds, the vault creation fails silently.

> **Tip:** Use <https://forge.plebmasters.de/objects> to browse and preview valid prop names.

***

### Language — `Config.Locale`

```lua
Config.Locale = 'en'
```

| Value  | Language |
| ------ | -------- |
| `'en'` | English  |
| `'ar'` | Arabic   |

#### Adding a New Language

1. Add a new key inside `Config.Locales`:

```lua
['fr'] = {
    no_permission_create = 'Vous n\'avez pas la permission...',
    -- copy every key from 'en' and translate
}
```

2. Set `Config.Locale = 'fr'`
3. Restart the resource

> All UI text, error messages, and notifications pull from the active locale. Missing keys will appear as `nil` in-game, so make sure every key from the `'en'` table exists in your custom locale.

***

### Discord Logging

```lua
Config.Webhook       = ""
Config.WebhookOpens  = ""
```

| Option                | Logs                                                    |
| --------------------- | ------------------------------------------------------- |
| `Config.Webhook`      | Vault creation, deletion, edits, and management actions |
| `Config.WebhookOpens` | Every time a player opens (or attempts to open) a vault |

#### Setup

1. In Discord, open your server settings → Integrations → Webhooks
2. Create a webhook for each channel
3. Copy the webhook URL
4. Paste it into the config:

```lua
Config.Webhook      = "https://discord.com/api/webhooks/123456789/abcdef..."
Config.WebhookOpens = "https://discord.com/api/webhooks/987654321/ghijkl..."
```

> Leave the strings empty (`""`) to disable logging entirely.

> **Privacy:** Open logs can be noisy on busy servers. Consider only enabling `Config.Webhook` for management actions and keeping `WebhookOpens` empty unless you need full audit trails.

***

### Locales — `Config.Locales`

Contains every text string used by the script, separated by language. The structure is:

```lua
Config.Locales = {
    ['en'] = {
        key_name = 'Translated text',
        ...
    },
    ['ar'] = {
        key_name = 'النص المترجم',
        ...
    }
}
```

#### Locale Categories

The locale keys are grouped by purpose:

**Permissions & Errors**

* `no_permission_create`, `no_permission_manage`
* `error_not_allowed_open`, `error_missing_password`
* `error_incorrect_password`, `error_owner_only`
* `error_job_grade_low`, `error_gang_grade_low`

**Access Modes**

* `option_password`, `option_job`, `option_gang`
* `option_password_job`, `option_password_gang`, `option_personal`

**Creation Dialog**

* `dialog_create_coords`, `dialog_create_object`
* `field_safe_name`, `field_slots`, `field_weight`
* `field_coords`, `field_heading`, `field_object_model`

**Management Panel**

* `manage_title`, `manage_search`, `manage_total`
* `action_teleport`, `action_set_waypoint`, `action_edit`
* `action_move`, `action_delete`, `action_back`
* `confirm_delete_title`, `confirm_delete_msg`

**Vault Metadata Display**

* `vault_meta_label`, `vault_meta_id`, `vault_meta_slots`
* `vault_meta_weight`, `vault_meta_access`, `vault_meta_coords`

**Portable Safes**

* `give_dialog_title`, `give_field_target`, `give_field_slots`
* `give_field_weight`, `give_field_label`
* `portable_no_owner`, `portable_owner_only`
* `portable_use_target`, `portable_use_pickup`
* `portable_pickup_success`, `portable_already_placed`
* `portable_no_safes_list`, `portable_action_restore`
* `portable_restored`, `portable_filter_label`

> Don't change the **keys** — only the **values**. The script references keys by name in code.

***

### Full Config Example

```lua
Config = {}

Config.DefaultSlots  = 30
Config.DefaultWeight = 300000

Config.x8 = {
    Framework = 'auto',
    Inventory = 'auto',
    Target    = 'auto',

    StashCreationPermission = {
        job   = "police",
        grade = 2
    },

    command       = "createvault",
    manageCommand = "managevault",
    giveCommand   = "givevault",
}

Config.Portable = {
    itemName      = "portable_safe",
    itemLabel     = "Portable Safe",
    minSlots      = 5,
    maxSlots      = 50,
    minWeight     = 10000,
    maxWeight     = 500000,
    defaultSlots  = 20,
    defaultWeight = 100000,
}

Config.Objects = {
    { label = 'Small Safe (Default)', model = 'prop_ld_int_safe_01' },
    { label = 'Locker',               model = 'v_ind_rc_lockeropn' },
    { label = 'Gun Locker',           model = 'xm_prop_xm_gunlocker_01a' },
}

Config.Locale       = 'en'
Config.Webhook      = ""
Config.WebhookOpens = ""
```

***

### Best Practices

* **Start with defaults.** Don't change anything until you have the script running successfully on your server.
* **Test framework detection.** Run `/createvault` once after setup. If the menu opens, detection succeeded.
* **Use `'auto'` for detection** unless you have a specific reason to force a value.
* **Keep portable safe limits realistic.** A safe with 1000 slots breaks game balance.
* **Back up your config** before editing. The script reads it on every restart, so a syntax error will prevent the resource from starting.
* **Test webhooks separately.** Use a private channel first to avoid spamming a public one with test messages.


---

# 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://x8project.gitbook.io/x8project/projects/stash/configuration.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.
