> For the complete documentation index, see [llms.txt](https://docs.tworst.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tworst.com/scripts/diving-job/configuration.md).

# Configuration

{% hint style="success" %}
**Your settings survive updates.** In 3.0 every value you change is saved by tw-lib in the database (`tw_lib_settings`). When you install an update, tw-lib writes your values back into the new config file. You never have to back up or merge a config again.
{% endhint %}

***

## Three Ways to Change a Setting

| Way                              | Best for                                                                                                                                                                      |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **In game: `/twlib` → Settings** | Pay, XP, cooldown, crew size, reward split, interaction style. Saved values apply when the job restarts: use the **Restart** button in the menu.                              |
| **Edit `defaults/config.lua`**   | Everything else. Save the file and restart `tw-diving`: tw-lib notices your edit and stores it.                                                                               |
| **Server console: `twlib set`**  | Quick changes without opening a file: `twlib set tw-diving Config.MaxPlayersInLobby 3`, then `restart tw-diving`. Undo with `twlib unset tw-diving Config.MaxPlayersInLobby`. |

{% hint style="info" %}
After tw-lib stores a value, the line in the config file shows the shipped default next to it, for example `Config.MaxPlayersInLobby = 3 --[[twlib:4]]`. That marker is how tw-lib tells your value from ours. Leave it there.
{% endhint %}

***

## Configuration Files

| File                     | What is inside                                                                                                                       |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `defaults/config.lua`    | General settings, lobby, commands, UI colours, job location, dive sites & rewards, daily missions, market, loot, scuba tubes, levels |
| `defaults/locales/*.lua` | Texts in 7 languages                                                                                                                 |
| `hooks/*.lua`            | Your own functions (end hook, notifications, progress bar)                                                                           |

{% hint style="info" %}
There is no `Config.Framework`, `Config.Inventory` or `Config.SQL` anymore: tw-lib detects them. The old key, fuel and skin functions are gone too; `Config.Vehiclekey`, `Config.Removekeys` and `Config.ChangeClothesSystem` still switch those features off.
{% endhint %}

***

## General

```lua
Config.Locale             = TwLibLocale or 'en' -- Language: en, tr, de, fr, pt, ru, ar
Config.CurrencyUnit       = '$'
Config.ServeName          = "TWORST"            -- Server name, max 10 characters
Config.MoneyType2         = "bank"              -- Account for payouts and the market: 'bank' or 'cash'
```

### Language

Default is English. To change it, run `twlib set tw-diving Config.Locale tr` in the server console and restart the job, or change `'en'` in the `Config.Locale` line and restart the job. Both are kept across updates.

***

## Interaction

```lua
Config.InteractionHandler = 'default' -- 'default' | 'drawtext' | 'ox-target' | 'qb-target' | 'auto'
Config.DrawTextUI         = 'twlib'   -- 'twlib' (Tworst prompt) | '3dtext'
```

| Value                         | Meaning                                                                                                                          |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `'default'`                   | Use the choice made once for **all** Tworst jobs in `/twlib` → Settings → All jobs (or `twlib set tw-lib interaction ox-target`) |
| `'drawtext'`                  | Tworst prompt with **E**                                                                                                         |
| `'ox-target'` / `'qb-target'` | Target eye                                                                                                                       |
| `'auto'`                      | ox\_target if running, else qb-target, else the Tworst prompt                                                                    |

***

## Lobby & Job

```lua
Config.MaxPlayersInLobby    = 4               -- Crew size
Config.LetOwnerSplitRewards = true            -- The owner sets each member's share of the money reward
Config.jobCoolDownHours     = 0               -- Hours before the same player can work again (0 = none); every crew member counts
Config.ChangeClothesSystem  = true            -- Job uniform on start; the player's own clothes come back at the end
Config.Vehiclekey           = true            -- Give keys for the boat
Config.Removekeys           = true            -- Take them back at the end
Config.OpenSuitCaseWeapon   = "WEAPON_KNIFE"  -- Weapon needed to open a suitcase (WEAPON_UNARMED = none)
Config.Debug                = false
```

### Who Can Take the Job

```lua
Config.Diving = {
    ['job'] = 'all', -- 'all', a job name ('mechanic') or a list ({ 'mechanic', 'police' })
    ...
}
```

The job rule is checked on the server when a lobby is opened **and** when an invite is accepted. On frameworks without jobs (standalone, vRP, TMC) everyone can join.

### Commands

```lua
Config.AnchorCommand     = "anchor"          -- Drop / raise the anchor
Config.AnchorKey         = "H"               -- Default key; players can rebind it in FiveM key bindings
Config.JobResetCommand   = "jobresetdiving"  -- Reset the job
Config.DeleteGearCommand = "deletegear"      -- Take off the scuba gear
```

***

## Job Menu Look

The job menu is the shared Tworst job UI inside tw-lib. Diving's colours and pictures:

```lua
Config.UI = {
    primary            = 'rgb(72, 189, 255)',      -- Accent: buttons, titles, bars
    primaryHover       = 'rgb(52, 140, 190)',
    primaryTransparent = 'rgba(72, 189, 255, 0.1)',
    background         = 'rgba(22, 28, 32, 0.94)',
    titleBg            = 'rgba(30, 38, 44, 1)',
    titleFont          = 'Nature',
    logo               = 'img/newLogo.png',        -- Path inside html/ or an https:// link
    scoreIcon          = 'img/teamScoreImg.png',
    regionImage        = 'img/region1.png',
    scriptName         = 'Diving',
}
```

`Config.DefaultUIPositions` sets where the crew list, score, invite and notification boxes sit on screen. Players can also move them in game.

***

## Job Location & Blip

```lua
Config.Diving = {
    ['coords'] = {
        ['intreactionCoords'] = vector3(-273.87, 6641.97, 7.39),
        ['ped'] = true,
        ['pedCoords'] = vector3(-273.87, 6641.97, 7.39),
        ['pedHeading'] = 232.23,
        ['pedHash'] = 0x49EA5685,
    },
    ['blip'] = { show = true, blipName = 'Diving Job', blipType = 317, blipColor = 3, blipScale = 0.55 },
    ['jobVehicle'] = 'tug', -- The crew's boat
    ...
}
```

***

## Dive Sites & Rewards

Each dive site is one entry in `Config.Diving['Mission']`:

```lua
['Mission'] = {
    {
        regionName  = "mission1",
        regionLabel = "Paleto Bay",
        minLevel    = 0,                -- Level needed to pick this site
        jobTask = {
            { name = "seaChanged",  label = "Take Coral",   amount = 20, areaDistance = 30, coords = vector3(-929.52, 6666.6, -27.55) },
            { name = "seaClean",    label = "Sea Clean",    amount = 20, areaDistance = 30, coords = vector3(-929.52, 6666.6, -27.55) },
            { name = "sealooting",  label = "Sea Box",      amount = 15, areaDistance = 40, coords = vector3(-929.52, 6666.6, -27.55) },
            { name = "seaSuitCase", label = "Sea SuitCase", amount = 10, areaDistance = 30, coords = vector3(-929.52, 6666.6, -27.55) },
        },
        awards = {
            money = 10000,               -- Paid to the crew at the end
            xp = 1000,
            onlinejobextra = 1,          -- Multiplier per extra crew member
        },
        vehicleSpawnCoords = { vector4(-306.97, 6678.08, 0.62, 33.31), ... }, -- Where the boat spawns
        jobDeliverTheVehicleCoords = vector3(-306.97, 6678.08, 1),            -- Where the boat is handed in
        ...
    },
},
```

| Site | Label              | Min. level | Money   | XP    |
| ---- | ------------------ | ---------- | ------- | ----- |
| 1    | Paleto Bay         | 0          | $10,000 | 1,000 |
| 2    | Port of Los Santos | 2          | $20,000 | 2,000 |
| 3    | East Coast         | 3          | $30,000 | 3,000 |
| 4    | North Coast        | 4          | $40,000 | 4,000 |

Remove a `jobTask` line to drop that kind of work from a site. The `sealooting` (treasure box) task is on Paleto Bay and North Coast by default.

{% hint style="info" %}
Your changes to a site are saved against its entry. If a later update adds or reorders sites, your money and XP stay with the right site. Keep `regionName` values unique and do not reuse them.
{% endhint %}

### Reward Split

With `Config.LetOwnerSplitRewards = true` the lobby owner sets each member's share in the lobby menu: the crew's total (the reward per player × the members online at the payout) is shared by those percentages. With `false` every member gets the same reward.

### Mission Completion Items

`Config.Diving['missioncompletedItems']` gives extra items at the end of a dive. Set `giveItemPlayer = true` to turn it on.

***

## Daily Missions

```lua
['dailyMission'] = {
    { name = 'jobtask_one',   label = 'dailyjobone',   count = 50, xp = 2500, money = 1000 },
    { name = 'jobtask_two',   label = 'dailyjobtwo',   count = 50, xp = 1000, money = 3000 },
    { name = 'jobtask_three', label = 'dailyjobthree', count = 5,  xp = 3500, money = 5000 },
},
```

`label` is a locale key, so the mission text follows each player's language.

{% hint style="info" %}
Changes to a daily mission are saved against its `name`. Keep the names unique.
{% endhint %}

***

## Scuba Tubes

```lua
Config.Tube = {
    ['level1'] = { waitTime = 3, model = `xm_prop_x17_scuba_tank` },
    ['level2'] = { waitTime = 5, model = `p_michael_scuba_tank_s` },
    ['level3'] = { waitTime = 7, model = `p_s_scuba_tank_s` },
    ['mask']   = { model = `p_d_scuba_mask_s` },
}
```

`waitTime` is the number of seconds between each drop of the oxygen bar while under water. A higher value means a longer dive.

***

## Market

Buying and selling happen only at the diving NPC. A purchase that does not fit in the player's inventory gives the money back.

```lua
["Market"] = {
    ["BuyItems"] = {
        { itemName = "scuba_tube_l1", itemLabel = "Scuba Tube Level 1", itemPrice = 500,  itemImage = "img/diving-tube-level1.png" },
        { itemName = "scuba_tube_l2", itemLabel = "Scuba Tube Level 2", itemPrice = 1000, itemImage = "img/diving-tube-level2.png" },
        { itemName = "scuba_tube_l3", itemLabel = "Scuba Tube Level 3", itemPrice = 1500, itemImage = "img/diving-tube-level3.png" },
        { itemName = "scuba_gear",    itemLabel = "Scuba Mask",         itemPrice = 700,  itemImage = "img/mask.png" },
        { itemName = "liftbag",       itemLabel = "Diving Liftbag",     itemPrice = 200,  itemImage = "img/liftbag.png" },
        { itemName = "weapon_knife",  itemLabel = "Knife",              itemPrice = 500,  itemImage = "img/knife.png" },
    },
    ["SellItems"] = {
        { itemName = "dendrogyra_coral",   itemLabel = "Dendrogyra",   itemPrice = 1500 },
        { itemName = "antipatharia_coral", itemLabel = "Antipatharia", itemPrice = 1500 },
        { itemName = "rolex",              itemLabel = "Rolex",        itemPrice = 750 },
        { itemName = "diamond_ring",       itemLabel = "Diamond Ring", itemPrice = 2000 },
        { itemName = "goldbar",            itemLabel = "Gold Bar",     itemPrice = 2500 },
    },
},
```

***

## Loot

```lua
Config.RandomCoral = {
    { item = "dendrogyra_coral",   probability = 70, amount = math.random(1, 3) },
    { item = "antipatharia_coral", probability = 20, amount = math.random(1, 3) },
}
Config.RandomSuitCase = {
    { item = "rolex",        probability = 70, amount = math.random(1, 3) },
    { item = "diamond_ring", probability = 20, amount = math.random(1, 3) },
    { item = "goldbar",      probability = 10, amount = math.random(1, 2) },
}
Config.RandomShipBox = {
    { item = "rolex",        probability = 40, amount = math.random(1, 3) },
    { item = "diamond_ring", probability = 40, amount = math.random(1, 3) },
    { item = "goldbar",      probability = 20, amount = math.random(1, 2) },
}
```

`probability` is the chance in percent. Corals come from `Config.RandomCoral`, suitcases from `Config.RandomSuitCase` and treasure boxes from `Config.RandomShipBox`.

***

## Levels

`Config.RequiredXP` holds the XP needed for each of the 70 levels. XP above the requirement carries over to the next level.

***

## Texts

All texts are in `defaults/locales/<language>.lua`. Edit the file and restart the job: tw-lib keeps your edited texts across updates like any other setting. A text missing in a language falls back to English.

***

## Hooks

Functions cannot be stored in the database, so they live in `hooks/`. Copy `hooks/hooks.example.lua` to `hooks/my-hooks.lua` and edit it there. An update replaces only the example; your file is never touched, and it is loaded after the settings, so it wins.

```lua
-- Runs for every player when the boat is delivered and the crew is paid.
Config.EndJob = function(source, scoreAmount, owneridentifier)
    print(('diving finished: %s scored %s'):format(owneridentifier, scoreAmount))
end

-- Your own notification system instead of the built-in one (client side). type: 'success' | 'error' | 'info'.
Config.Notification = function(message, type)
    exports['my-notify']:Send(message, type)
end

-- Your own progress bar (client side). time is in seconds.
Config.ProgressBar = function(label, time)
    exports['my-progress']:Start(label, time * 1000)
end
```

***

## Need Help?

{% hint style="info" %}
Join our [Discord](https://discord.gg/tworst) and open a ticket.
{% endhint %}
