> For the complete documentation index, see [llms.txt](https://s1h.gitbook.io/info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://s1h.gitbook.io/info/resources/s1h_uipack/editable-files/exports/textui.md).

# TextUI

***

### showTextUI

Manually shows a TextUI panel on the player's screen without registering a world zone.

**You can use it when you want full manual control over when the TextUI appears and disappears — for example inside a script that manages its own proximity loop.**

```lua
exports["s1h_uipack"]:showTextUI(id, data)
```

**Parameters :**

| Name         | Type   | Description                                                                        |
| ------------ | ------ | ---------------------------------------------------------------------------------- |
| id           | string | Unique identifier for this UI instance                                             |
| data.key     | string | The key displayed on the interaction button (e.g. `"E"`, `"F"`). Defaults to `"E"` |
| data.options | table  | Array of option items — see option fields below                                    |

**Option item fields :**

| Name        | Type    | Description                                                         |
| ----------- | ------- | ------------------------------------------------------------------- |
| value       | string  | Unique internal identifier for this option                          |
| label       | string  | Display title shown on the button                                   |
| description | string  | Sub-text shown below the label                                      |
| icon        | string  | FontAwesome class (e.g. `"fas fa-university"`)                      |
| event       | string  | Event name to trigger when the player selects this option           |
| isServer    | boolean | If `true`, triggers a server event. Default: `false` (client event) |
| args        | table   | Extra data passed along with the event                              |

**Example — single option :**

```lua
exports["s1h_uipack"]:showTextUI("atm_zone", {
    key = "E",
    options = {
        {
            value       = "use_atm",
            label       = "Use ATM",
            description = "Access your bank account",
            icon        = "fas fa-university",
            event       = "bank:client:openATM",
            isServer    = false
        }
    }
})
```

**Example — multiple options, with args and server event :**

```lua
exports["s1h_uipack"]:showTextUI("police_duty_board", {
    key = "E",
    options = {
        {
            value       = "duty_on",
            label       = "Go On Duty",
            description = "Clock in and start your shift",
            icon        = "fas fa-sign-in-alt",
            event       = "police:server:toggleDuty",
            isServer    = true,
            args        = { state = true }
        },
        {
            value       = "open_armory",
            label       = "Open Armory",
            description = "Access police weapons and equipment",
            icon        = "fas fa-shield-alt",
            event       = "police:client:openArmory",
            isServer    = false,
            args        = { type = "weapons" }
        },
        {
            value       = "open_garage",
            label       = "Police Garage",
            description = "Spawn a police vehicle",
            icon        = "fas fa-car",
            event       = "police:client:openGarage",
            isServer    = false
        }
    }
})
```

***

### hideTextUI

Hides the currently visible TextUI panel.

**You can use it to hide the TextUI manually after a cutscene, dialogue, or any other custom trigger.**

```lua
exports["s1h_uipack"]:hideTextUI(id)
```

**Parameters :**

| Name | Type          | Description                                                             |
| ---- | ------------- | ----------------------------------------------------------------------- |
| id   | string \| nil | The ID of the UI to hide. Pass `nil` to hide whatever is currently open |

**Example :**

```lua
-- Hide a specific UI
exports["s1h_uipack"]:hideTextUI("atm_zone")

-- Hide whatever is currently visible
exports["s1h_uipack"]:hideTextUI(nil)
```

***

### addZone

Registers a 3D world zone. The TextUI panel appears automatically when the player walks into the interact radius and disappears when they leave.

**You can use it to create persistent interaction points anywhere in the world — ATMs, shops, garages, police armories, job boards, hospitals, and more.**

```lua
exports["s1h_uipack"]:addZone(id, coords, interactRadius, markerRadius, showIndicator, uiData, autoReset)
```

**Parameters :**

| Name           | Type                        | Description                                                                                              |
| -------------- | --------------------------- | -------------------------------------------------------------------------------------------------------- |
| id             | string                      | Unique zone identifier                                                                                   |
| coords         | vector3 \| vector4 \| table | World position of the zone center                                                                        |
| interactRadius | number                      | Distance at which the TextUI appears and the key press is detected. Default: `1.0`                       |
| markerRadius   | number                      | Distance at which the floating 3D indicator icon becomes visible. Default: `2.5`                         |
| showIndicator  | boolean                     | Whether to show a floating 3D icon above the zone when approaching. Default: `true`                      |
| uiData         | table                       | The TextUI configuration and options (see uiData fields below)                                           |
| autoReset      | boolean                     | If `true`, the interaction lock resets 1 second after use, allowing the UI to reappear. Default: `false` |

**uiData fields :**

| Name                  | Type    | Description                                                                         |
| --------------------- | ------- | ----------------------------------------------------------------------------------- |
| key                   | string  | The interaction key displayed on the button. Default: `"E"`                         |
| autoReset             | boolean | Same as the top-level `autoReset` parameter — can also be set here                  |
| allowlist.jobs        | table   | Restricts zone access to matching jobs. Format: `{ jobName = minGrade }`            |
| allowlist.identifiers | table   | Restricts zone to specific player identifiers. Format: `{ ["license:abc"] = true }` |
| options               | table   | Array of option items (same fields as `showTextUI`)                                 |

**Example — simple zone :**

```lua
exports["s1h_uipack"]:addZone("bank_atm", vector3(145.35, -1037.17, 29.37), 2.0, 5.0, true, {
    key = "E",
    options = {
        {
            value    = "open_bank",
            label    = "Open Bank",
            icon     = "fas fa-university",
            event    = "bank:client:openBank",
            isServer = false
        }
    }
}, false)
```

**Example — multiple options with server args :**

```lua
exports["s1h_uipack"]:addZone("mechanic_shop", vector3(340.23, -162.46, 65.00), 2.0, 5.0, true, {
    key = "E",
    options = {
        {
            value       = "repair",
            label       = "Repair Vehicle",
            description = "Full repair - $500",
            icon        = "fas fa-wrench",
            event       = "mechanic:server:repairVehicle",
            isServer    = true,
            args        = { price = 500 }
        },
        {
            value       = "tune",
            label       = "Tune Engine",
            description = "Boost engine performance - $1,200",
            icon        = "fas fa-cogs",
            event       = "mechanic:server:tuneEngine",
            isServer    = true,
            args        = { price = 1200 }
        }
    }
}, false)
```

**Example — job restricted zone (police only) :**

```lua
exports["s1h_uipack"]:addZone("police_armory", vector3(457.82, -989.10, 30.69), 1.5, 3.0, true, {
    key = "E",
    autoReset = true,
    allowlist = {
        jobs = { police = 0 }   -- any police officer (grade 0 and above)
    },
    options = {
        {
            value    = "open_armory",
            label    = "Open Armory",
            icon     = "fas fa-shield-alt",
            event    = "police:client:openArmory",
            isServer = false
        }
    }
}, false)
```

**Example — zone restricted by player identifier :**

```lua
exports["s1h_uipack"]:addZone("owner_only_door", vector3(200.0, -500.0, 30.0), 1.5, 3.0, false, {
    key = "E",
    allowlist = {
        identifiers = {
            ["license:a1b2c3d4e5f6a1b2c3d4e5f6"] = true,
            ["license:deadbeefdeadbeefdeadbeef"] = true
        }
    },
    options = {
        {
            value = "enter",
            label = "Enter Private Area",
            icon  = "fas fa-door-open",
            event = "myScript:client:openDoor"
        }
    }
}, false)
```

***

### removeZone

Removes a registered zone from the world and deletes any NPC ped that was spawned alongside it.

**You can use it to dynamically remove interaction zones — for example after a mission ends, a shop closes for the night, or an NPC is killed.**

```lua
exports["s1h_uipack"]:removeZone(id)
```

**Parameters :**

| Name | Type   | Description                  |
| ---- | ------ | ---------------------------- |
| id   | string | The ID of the zone to remove |

**Example :**

```lua
-- Remove a single zone
exports["s1h_uipack"]:removeZone("bank_atm")

-- Remove multiple zones (loop example)
local zonesToRemove = { "bank_atm", "mechanic_shop", "police_armory" }
for _, id in ipairs(zonesToRemove) do
    exports["s1h_uipack"]:removeZone(id)
end
```

***

### textUICreatePed

Spawns an NPC ped at a world location and automatically registers a TextUI interaction zone around it.

**You can use it when you want an NPC with an attached interaction menu — for example a shop keeper, mechanic, doctor, quest giver, or dealer.**

```lua
exports["s1h_uipack"]:textUICreatePed(id, pedData, interactRadius, markerRadius, showIndicator, uiData, autoReset)
```

**Parameters :**

| Name                            | Type    | Description                                                                         |
| ------------------------------- | ------- | ----------------------------------------------------------------------------------- |
| id                              | string  | Unique zone/ped identifier                                                          |
| pedData.model                   | string  | Ped model name (e.g. `"s_m_y_construct_01"`)                                        |
| pedData.coords                  | vector4 | World position and heading: `vector4(x, y, z, heading)`                             |
| pedData.freeze                  | boolean | Freeze the ped in place so it cannot move                                           |
| pedData.invincible              | boolean | Make the ped immune to all damage                                                   |
| pedData.blockevents             | boolean | Prevent the ped from fleeing, reacting to gunshots, etc.                            |
| pedData.animDict                | string  | Animation dictionary to load and play                                               |
| pedData.anim                    | string  | Animation clip name within the dictionary                                           |
| pedData.scenario                | string  | Scenario name to use instead of animDict + anim (e.g. `"WORLD_HUMAN_AA_SMOKE"`)     |
| pedData.pedrelations            | table   | Set the ped's relationship group — controls how it reacts to players and other peds |
| pedData.pedrelations.groupname  | string  | Relationship group name (e.g. `"AMBIENT_GANG_BALLAS"`)                              |
| pedData.pedrelations.toowngroup | number  | Relationship to own group (0 = companion, 5 = hate)                                 |
| pedData.pedrelations.toplayer   | number  | Relationship to the player (3 = neutral, 5 = hate)                                  |
| interactRadius                  | number  | Distance at which TextUI appears. Default: `1.5`                                    |
| markerRadius                    | number  | Distance at which the 3D icon is visible. Default: `3.0`                            |
| showIndicator                   | boolean | Show a floating 3D icon above the ped. Default: `false`                             |
| uiData                          | table   | Same format as `addZone` uiData                                                     |
| autoReset                       | boolean | Reset interaction lock after use. Default: `false`                                  |

**Example — shop ped with scenario :**

```lua
exports["s1h_uipack"]:textUICreatePed("clothing_shop_ped", {
    model    = "a_f_y_business_02",
    coords   = vector4(712.45, -960.20, 30.40, 178.5),
    freeze   = true,
    invincible  = true,
    blockevents = true,
    scenario = "WORLD_HUMAN_STAND_IMPATIENT"
}, 1.8, 3.5, false, {
    key = "E",
    options = {
        {
            value    = "browse",
            label    = "Browse Clothes",
            icon     = "fas fa-shirt",
            event    = "clothing:client:openShop",
            isServer = false
        }
    }
})
```

**Example — mechanic ped with animation :**

```lua
exports["s1h_uipack"]:textUICreatePed("mechanic_ped", {
    model       = "s_m_y_construct_01",
    coords      = vector4(340.23, -162.46, 65.00, 270.0),
    freeze      = true,
    invincible  = true,
    blockevents = true,
    animDict    = "amb@world_human_smoking@male@idle_a",
    anim        = "idle_a"
}, 1.5, 3.0, false, {
    key = "E",
    options = {
        {
            value       = "repair",
            label       = "Repair Vehicle",
            description = "Full vehicle repair service",
            icon        = "fas fa-wrench",
            event       = "mechanic:server:repairVehicle",
            isServer    = true,
            args        = { price = 500 }
        },
        {
            value    = "tune",
            label    = "Performance Upgrade",
            icon     = "fas fa-bolt",
            event    = "mechanic:server:tuneVehicle",
            isServer = true
        }
    }
})
```

**Example — ped with pedrelations (neutral NPC) :**

```lua
exports["s1h_uipack"]:textUICreatePed("dealer_ped", {
    model       = "a_m_m_business_01",
    coords      = vector4(139.01, -995.46, 29.36, 174.63),
    freeze      = true,
    invincible  = true,
    blockevents = true,
    scenario    = "WORLD_HUMAN_AA_SMOKE",
    pedrelations = {
        groupname   = "AMBIENT_GANG_BALLAS",
        toowngroup  = 0,   -- friendly to own group
        toplayer    = 3    -- neutral to the player
    }
}, 2.0, 5.0, true, {
    key = "E",
    options = {
        {
            value    = "open_shop",
            label    = "Open Shop",
            icon     = "fas fa-shopping-cart",
            event    = "inventory:client:openShop",
            isServer = false
        }
    }
})
```

***

### resetInteraction

Resets the "already interacted" cooldown lock for a zone, allowing the TextUI to reappear immediately.

**You can use it after completing an async action so the player can interact with the same zone again without having to leave and re-enter it.**

```lua
exports["s1h_uipack"]:resetInteraction(id)
```

**Parameters :**

| Name | Type          | Description                                             |
| ---- | ------------- | ------------------------------------------------------- |
| id   | string \| nil | Zone ID to reset. Pass `nil` to reset ALL zones at once |

**Example :**

```lua
-- Reset a specific zone after a server response
RegisterNetEvent("bank:client:transactionComplete", function()
    exports["s1h_uipack"]:resetInteraction("bank_atm")
end)

-- Reset all zones at once (e.g. on player respawn)
AddEventHandler("hospital:client:playerRespawned", function()
    exports["s1h_uipack"]:resetInteraction(nil)
end)
```

***

### updatePlayerJob

Manually updates the player's current job data used for zone allowlist checks.

**You can use it when your framework is not automatically detected, or when you need to force a job refresh — for example after a player changes jobs mid-session.**

```lua
exports["s1h_uipack"]:updatePlayerJob(jobData)
```

**Parameters :**

| Name          | Type   | Description                                   |
| ------------- | ------ | --------------------------------------------- |
| jobData.name  | string | The job name (e.g. `"police"`, `"ambulance"`) |
| jobData.grade | number | The job grade level (e.g. `2`)                |

**Example :**

```lua
-- Manually update after a job change event
RegisterNetEvent("myScript:client:jobChanged", function(newJob, newGrade)
    exports["s1h_uipack"]:updatePlayerJob({
        name  = newJob,
        grade = newGrade
    })
end)
```

***

### Event: onAction

Fired on the client whenever a player selects any option from any TextUI panel.

**You can use this as a global listener to react to any TextUI interaction across all zones.**

```lua
AddEventHandler("t1TextUI:onAction", function(zoneId, actionValue)
    -- zoneId     : the ID of the zone where the action happened
    -- actionValue: the "value" field of the option the player selected
    print("Zone:", zoneId, "| Action:", actionValue)
end)
```

**Example — react to a specific zone and action :**

```lua
AddEventHandler("t1TextUI:onAction", function(zoneId, actionValue)
    if zoneId == "police_armory" and actionValue == "open_armory" then
        -- do something extra when the armory is opened
        TriggerEvent("police:client:logArmoryAccess")
    end
end)
```
