# NPC Interaction

<figure><img src="https://2088945756-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkHcyR2RbVMcj5NHJ2HEa%2Fuploads%2FWyZ5hpymExoN8m6LEofN%2Fimage.png?alt=media&#x26;token=d85e1293-be99-4cc3-828f-097ad35809fc" alt=""><figcaption></figcaption></figure>

The NPC Interaction module provides a highly immersive, cinematic dialogue system for your server. When a player interacts with an NPC, the script automatically aligns the player, creates a cinematic camera angle focusing on the NPC, and displays a sleek UI for dialogues and options. It fully supports nested submenus, conditional options, and event triggering.

***

### 📚 Available Exports

#### `RegisterNpcInteract`

Registers an interaction menu to a specific NPC entity. This must be called before attempting to show the menu.

Syntax:

```lua
exports['ak47_lib']:RegisterNpcInteract(entity, data)
```

Parameters:

| **Parameter** | **Type**  | **Description**                                                      |
| ------------- | --------- | -------------------------------------------------------------------- |
| `entity`      | `integer` | The network ID or handle of the ped/entity.                          |
| `data`        | `table`   | The configuration object containing dialogues, styling, and options. |

#### `ShowNpcInteract`

Opens a previously registered NPC interaction menu.

Syntax:

```lua
exports['ak47_lib']:ShowNpcInteract(id, focusIndex)
```

Parameters:

| **Parameter** | **Type**             | **Description**                                                 |
| ------------- | -------------------- | --------------------------------------------------------------- |
| `id`          | `string`             | The unique ID defined in your `RegisterNpcInteract` data table. |
| `focusIndex`  | `integer` (Optional) | The index of the option you want to be pre-selected/focused.    |

#### `HideNpcInteract`

Forcefully closes the currently open NPC interaction menu.

Syntax:

```lua
exports['ak47_lib']:HideNpcInteract(runOnExit)
```

Parameters:

| **Parameter** | **Type**  | **Description**                                                            |
| ------------- | --------- | -------------------------------------------------------------------------- |
| `runOnExit`   | `boolean` | If `true`, triggers the `onExit` callback defined in the NPC's data table. |

***

### ⚙️ Configuration Objects

#### The `data` Table

This table configures the overarching menu for the NPC.

| **Property** | **Type**   | **Description**                                                                       |
| ------------ | ---------- | ------------------------------------------------------------------------------------- |
| `id`         | `string`   | Required. A unique identifier for this interaction menu.                              |
| `colors`     | `table`    | Optional. Override default UI colors (`colorPrimary`, `colorSecondary`, `colorText`). |
| `dialogues`  | `table`    | An array of strings. The menu will pick one at random to display as a greeting.       |
| `menu`       | `string`   | Optional. The `id` of a parent menu. Enables native "Back" button functionality.      |
| `onExit`     | `function` | Optional. A callback triggered when the menu is closed.                               |
| `options`    | `table`    | Required. An array of `Option` objects.                                               |

#### The `Option` Object

Each item inside the `options` array represents a clickable button.

| **Property**  | **Type**   | **Description**                                                                |
| ------------- | ---------- | ------------------------------------------------------------------------------ |
| `label`       | `string`   | Required. The text displayed on the button.                                    |
| `icon`        | `string`   | FontAwesome icon name (e.g., `car`, `comments`, `person-walking-arrow-right`). |
| `iconColor`   | `string`   | Hex code to color the icon (e.g., `#3498db`).                                  |
| `isVisible`   | `function` | Returns a boolean. If `false`, the option is completely hidden.                |
| `disabled`    | `boolean`  | If `true`, the option is shown but grayed out/unclickable.                     |
| `canInteract` | `function` | Returns a boolean. Overrides `disabled` dynamically based on logic.            |
| `onSelect`    | `function` | Callback triggered when the player clicks this option.                         |
| `event`       | `string`   | A Client event to trigger when clicked.                                        |
| `serverEvent` | `string`   | A Server event to trigger when clicked.                                        |
| `menu`        | `string`   | Automatically opens another registered NPC menu `id` (acts as a submenu).      |

> Note on Navigation: You can navigate to a submenu using the `menu = 'target_id'` property inside an option, or manually inside the `onSelect` function by calling `exports['ak47_lib']:ShowNpcInteract('target_id')`.

***

### 💡 Examples

#### Example 1: Basic Shop Ped

A simple interaction with a single ped offering basic choices.

```lua
local shopPedId = 0 -- Assuming you have already spawned your ped here

exports['ak47_lib']:RegisterNpcInteract(shopPedId, {
    id = 'hardware_store_main',
    colors = {
        colorPrimary = "rgba(20, 20, 20, 0.95)", 
        colorSecondary = "#ffaa00",
        colorText = "#ffffff",
    },
    dialogues = {
        "Need some tools?",
        "Welcome to the hardware store. What can I get ya?",
        "Make it quick, I'm busy."
    },
    onExit = function()
        print("Player walked away from the hardware store.")
    end,
    options = {
        {
            label = 'Open Shop',
            icon = 'basket-shopping',
            iconColor = '#ffaa00',
            onSelect = function()
                -- Put your shop opening logic here
                TriggerEvent('inventory:client:openShop', 'hardware')
            end
        },
        {
            label = 'Leave',
            icon = 'person-walking-arrow-right',
            iconColor = '#e74c3c'
        }
    }
})

-- To open it (usually triggered via target system like qb-target or ox_target):
-- exports['ak47_lib']:ShowNpcInteract('hardware_store_main')
```

#### Example 2: Dialogue Trees (Submenus & Back Buttons)

This example demonstrates how to create a conversation tree where the player can ask questions, go into a submenu, and hit a "Back" button to return to the main choices.

```lua
local guidePedId = 0 -- Assuming spawned ped

-- 1. Register the Main Menu
exports['ak47_lib']:RegisterNpcInteract(guidePedId, {
    id = 'tour_guide_main',
    dialogues = {
        "Hello traveler! Want to know more about the city?"
    },
    options = {
        {
            label = 'Ask about the City',
            icon = 'city',
            iconColor = '#3498db',
            -- Use the `menu` parameter to automatically link a submenu!
            menu = 'tour_guide_city_info' 
        },
        {
            label = 'Goodbye',
            icon = 'hand-wave',
            iconColor = '#e74c3c'
        }
    }
})

-- 2. Register the Submenu
exports['ak47_lib']:RegisterNpcInteract(guidePedId, {
    id = 'tour_guide_city_info',
    menu = 'tour_guide_main', -- Defining this parent menu enables the native "Back" button
    dialogues = {
        "The city was founded in 1904. We have a rich history!"
    },
    options = {
        {
            label = 'Ask about the Mayor',
            icon = 'user-tie',
            iconColor = '#9b59b6',
            onSelect = function()
                print("The mayor is currently out of town.")
            end
        },
        {
            label = 'Ask about local gangs',
            icon = 'skull',
            iconColor = '#e67e22',
            onSelect = function()
                print("We don't talk about them around here...")
            end
        }
    }
})
```

#### Example 3: Conditional & Restricted Options

Sometimes you only want specific players (like police) to see an option, or you want to show an option but disable it if they don't have enough money.

```lua
local shadyPedId = 0

exports['ak47_lib']:RegisterNpcInteract(shadyPedId, {
    id = 'shady_dealer',
    dialogues = {
        "You got the cash or what?"
    },
    options = {
        {
            label = 'Buy Lockpick ($500)',
            icon = 'key',
            iconColor = '#f1c40f',
            -- Option is visible, but might be disabled
            canInteract = function()
                local hasEnoughMoney = true -- Replace with actual framework money check
                return hasEnoughMoney 
            end,
            onSelect = function()
                TriggerServerEvent('shadydealer:buyLockpick')
            end
        },
        {
            label = '(Police) Confiscate Goods',
            icon = 'shield-halved',
            iconColor = '#3498db',
            -- This completely hides the option if they aren't a cop
            isVisible = function()
                local isCop = false -- Replace with actual framework job check
                return isCop
            end,
            onSelect = function()
                TriggerServerEvent('police:confiscateNPC')
            end
        },
        {
            label = 'Walk away',
            icon = 'person-walking-arrow-right',
            iconColor = '#e74c3c'
        }
    }
})
```
