Configuration
Every scuba diving option in the four files under config/, with its key, default value and what it changes, plus the text prompt setting and languages.
scuba diving is set in four Lua files under config/, which ship open. Each one returns a table, read when the script starts, so a change applies after stop lation_diving and ensure lation_diving.
| File | Holds |
|---|---|
config/shared.lua | Setup, start, experience, gear, shops, boat rental, zones and crates |
config/client.lua | Stats and blips and animations |
config/server.lua | Logging |
config/icons.lua | Icons |
The key is the option's path inside its file, for example setup.notify in config/shared.lua.
Setup
In config/shared.lua.
| Key | Default | Notes |
|---|---|---|
setup.debug | false | Shows the zone spheres and adds the debugzones command (below). Leave it off on a live server. |
setup.interact | 'ox_target' | Also 'qb-target', 'interact' (the resource named interact) or 'custom'. It isn't detected, so set it to what you run. lation interact works with 'ox_target' or 'qb-target'. |
setup.notify | 'ox_lib' | Also 'lation_ui', 'esx', 'qb', 'okok', 'sd-notify', 'wasabi_notify' or 'custom'. |
setup.progress | 'ox_lib' | Also 'lation_ui', 'qbcore' or 'custom'. A custom bar must support animations. |
setup.menu | 'ox_lib' | Also 'lation_ui' or 'custom'. The clerk's menu and its submenus. |
setup.dialogs | 'ox_lib' | Also 'lation_ui' or 'custom'. The quantity and player ID prompts, the refill slider, Continue Diving? and the on-screen hotspot messages. |
setup.hideNames | false | true lists group members as Player 12 instead of their character names. |
setup.version | true | Checks for a newer release on start and prints a notice in the server console. |
setup.job | false | A job name, such as 'diver', to keep diving to that job: only it sees the clerk, his blip and the shops. |
setup.metric | false | true shows depth and distance in meters instead of feet. |
setup.max | 1800.0 | How long, in seconds, the game lets a diver in scuba gear stay under. The tank runs out long before; the config asks you to leave it. |
The custom options do nothing until you add your code in client/functions.lua. See developers.
With setup.debug on, debugzones (client) puts a crate on every spot of a zone as you enter it, each with a target that prints its coordinates to F8, and removes them as you leave.
Start
In config/shared.lua. The clerk, and how groups and dives start.
| Key | Default | Notes |
|---|---|---|
start.coords | vec4(-289.3029, -2770.0029, 2.1953, 48.9145) | Where the clerk stands and his heading. false removes the clerk and his blip; open the menu with openMenu instead. |
start.model | 's_m_y_shop_mask' | The clerk's ped model. |
start.scenario | 'WORLD_HUMAN_CLIPBOARD' | What he stands doing, or false for nothing. |
start.hours | { min = 0, max = 24 } | In-game hours he's there, from min up to, not including, max. With min later than max, the window runs overnight. Checked as a player comes within 100 meters. |
start.cooldown | { min = 15, max = 30 } | Seconds between Start Diving and the hotspot. |
start.continue | true | Asks the leader Continue Diving? after the last crate. false ends the dive instead. |
start.addMemberDistCheck | false | true requires the leader and the player being added to both be within 15 meters of the clerk. |
start.groupLimit | nil | Most players in a group, the leader included. nil for no limit. |
The shops, the boat deposit and its refund only go through within 15 meters of start.coords, unless it's false.
Experience
In config/shared.lua. The total XP for each level.
| Key | Default |
|---|---|
experience[1] | 0 |
experience[2] | 2500 |
experience[3] | 10000 |
experience[4] | 20000 |
experience[5] | 50000 |
Add or remove levels as you like; the highest is the top level. Always keep [1] = 0. Players earn XP only from crates, at each zone's xp (1 to 5 per crate by default), so the default ladder is slow.
Gear
In config/shared.lua.
Tanks
gear.tanks lists the scuba gear items. The number in brackets is the level needed to buy and wear that one.
| Key | Item | degrade | Air underwater |
|---|---|---|---|
gear.tanks[1] | ls_scuba_gear_1 | 3.34 | About 5 minutes |
gear.tanks[2] | ls_scuba_gear_2 | 1.67 | About 10 minutes |
gear.tanks[3] | ls_scuba_gear_3 | 1.11 | About 15 minutes |
gear.tanks[4] | ls_scuba_gear_4 | 0.84 | About 20 minutes |
gear.tanks[5] | ls_scuba_gear_5 | 0.66 | About 25 minutes |
degrade is how much air, out of 100, the gear loses for every 10 seconds underwater. For a tank that lasts a given time: degrade = 100 ÷ (seconds ÷ 10).
Refill and props
| Key | Default | Notes |
|---|---|---|
gear.refill | 'ls_oxygen_tank' | The oxygen tank item that refills gear. |
gear.mask | 'p_d_scuba_mask_s' | The mask prop worn while geared. |
gear.tank | 'p_s_scuba_tank_s' | The tank prop worn on the back. |
Clothes
gear.clothes sets what the diver wears while geared. Each part has a componentId (leave it as it is) and a male and female { drawableId, textureId }. The freemode male ped gets the male set and any other ped the female one.
| Part | componentId | Male drawable | Female drawable |
|---|---|---|---|
mask | 1 | 0 | 0 |
upperBody | 3 | 8 | 3 |
lowerBody | 4 | 94 | 97 |
bags | 5 | 0 | 0 |
shoes | 6 | 67 | 70 |
shirt | 8 | 15 | 15 |
bodyArmor | 9 | 0 | 0 |
decals | 10 | 0 | 0 |
jackets | 11 | 243 | 251 |
Every textureId is 0. Each part is applied as set, a drawable of 0 included.
Shops
In config/shared.lua. Both shops are rows in the clerk's menu, and both open a quantity prompt for the item picked.
Dive shop
| Key | Default | Notes |
|---|---|---|
shop.gear.enable | true | Shows The Dive Shop. |
shop.gear.account | 'cash' | Or 'bank'. |
shop.gear.items | Eight items, below | Each { item, price, icon, level?, metadata? }. |
level is the diving level needed to buy it. metadata is the durability the item is handed out with, so keep it at 100 on scuba gear and oxygen tanks, and leave it off items that don't use durability.
| # | item | price | level | metadata |
|---|---|---|---|---|
| 1 | ls_oxygen_tank | 100 | 100 | |
| 2 | ls_scuba_gear_1 | 250 | 1 | 100 |
| 3 | ls_scuba_gear_2 | 500 | 2 | 100 |
| 4 | ls_scuba_gear_3 | 1000 | 3 | 100 |
| 5 | ls_scuba_gear_4 | 2000 | 4 | 100 |
| 6 | ls_scuba_gear_5 | 5000 | 5 | 100 |
| 7 | burger | 5 | ||
| 8 | water | 5 |
burger and water come from your inventory and don't ship with scuba diving; rename or remove them if your inventory calls them something else.
Pawn shop
| Key | Default | Notes |
|---|---|---|
shop.pawn.enable | true | Shows The Pawn Shop. |
shop.pawn.account | 'cash' | Or 'bank'. Where the money goes. |
shop.pawn.items | 16 items, below | Each { item, price, icon }, price paid for one. |
item | price |
|---|---|
ls_old_boot, ls_wood_plank, ls_rusted_padlock, ls_rusted_key, ls_rusted_gear | 5 |
ls_seashell, ls_seaweed, ls_rusted_muffler, ls_broken_cd, ls_diving_goggles | 15 |
ls_fishing_net, ls_old_camera, ls_military_helmet | 25 |
ls_old_compass, ls_old_watch, ls_conch_shell | 50 |
The level 2 to 5 finds aren't bought by default. Add them here to give them a price.
Boat rental
In config/shared.lua.
| Key | Default | Notes |
|---|---|---|
rental.enable | true | Shows Rent a Boat and Return Boat. |
rental.account | 'cash' | Or 'bank'. The deposit comes from it and the refund goes back to it. |
rental.deposit | 500 | Paid to rent. 0 for free. |
rental.returnDeposit | 250 | Paid back on return. 0 for nothing. |
rental.models | { 'dinghy' } | One is picked at random for each rental. |
rental.teleport | false | true puts the player in the driver's seat. |
rental.coords | vec4(-291.7570, -2766.1208, 0.6787, 267.4251) | Where the boat spawns, and its heading. |
rental.anchor | true | Adds Toggle anchor to the boat. |
Zones
In config/shared.lua. zones lists the dive spots. Each dive goes to one picked at random, never the one the server handed out last, so keep at least two.
| Field | Default (every zone) | Notes |
|---|---|---|
location | Below | The middle of the zone: its circle on the map, and the sphere that spawns the crates. |
models | { 'xm3_prop_xm3_crate_supp_01a' } | Crate props, one picked at random for each crate. |
radius | 150.0 | Meters, for the map circle and the sphere. |
highlight | { enable = true, distance = 30, color = { r = 106, g = 226, b = 119 } } | Outlines crates within distance meters in color. |
crates | { min = 2, max = 6 } | Crates per dive, never more than the zone has spots. |
xp | { min = 1, max = 5 } | XP for each crate picked up. |
coords | Below | The spots crates can be on. Each dive picks different ones at random. |
The ten zones, with 127 spots between them:
| Zone | location | Spots |
|---|---|---|
| 1 | 1086.9691, -3575.9382, -50.1214 | 15 |
| 2 | 3085.2043, -1853.3246, -14.3668 | 13 |
| 3 | 1818.7792, -2984.2068, -41.2811 | 13 |
| 4 | 3150.8074, -973.6499, -26.9572 | 12 |
| 5 | 2383.6611, -2451.3289, -32.9255 | 10 |
| 6 | 280.3442, -3492.5969, -29.2227 | 10 |
| 7 | -2080.0508, -876.7839, -38.1838 | 16 |
| 8 | -2837.9504, -494.8672, -45.7883 | 15 |
| 9 | -3550.5359, 646.9001, -66.3281 | 12 |
| 10 | -3416.8613, 1701.7200, -61.6626 | 11 |
To add a zone, copy one, set its location and list its spots in coords as vec3. The debugzones command under setup shows every spot of a zone in game.
Keep at least two zones. The next dive never goes to the zone handed out last, so with only one, the second Start Diving on the server never finds a zone and hangs the server.
Crates
In config/shared.lua.
| Key | Default | Notes |
|---|---|---|
crates.item | 'ls_diving_crate' | The item a crate becomes when picked up, used to open it. |
crates.quantity | { min = 1, max = 1 } | How many crate items one pickup gives. |
crates.loot | Five tiers, below | What opening a crate can give. |
crates.loot is keyed by level. A player rolls every tier at or below their level, and every item in those tiers rolls on its own, so one crate can give several items, or only the sure ones. Each entry is { item, quantity = { min, max }, chance, metadata? }, chance from 1 to 100, and metadata an optional table put on the item.
| Tier | Entries (chance) |
|---|---|
crates.loot[1] | ls_old_boot 100, ls_wood_plank 80, ls_rusted_padlock 60, ls_rusted_key 40, ls_rusted_gear 30, ls_seashell 30, ls_seaweed 25, ls_rusted_muffler 25, ls_broken_cd 20, ls_diving_goggles 20, ls_fishing_net 15, ls_old_camera 15, ls_military_helmet 10, ls_old_compass 10, ls_old_watch 5, ls_conch_shell 5 |
crates.loot[2] | ls_bottle_of_rum 50 |
crates.loot[3] | ls_treasure_map 50 |
crates.loot[4] | ls_silver_bracelet 50 |
crates.loot[5] | ls_ancient_artifact 50 |
Every default entry gives one. The table is a starting point: put your own server's items in it. Keep at least one entry at 100 in tier 1, or a crate can roll nothing, and then it isn't used up and the console prints an error.
Stats and blips
In config/client.lua.
| Key | Default | Notes |
|---|---|---|
stats.crates | true | Crates under Statistics. |
stats.depth | true | Depth, the deepest dive. |
stats.swam | true | Swam, the distance swum underwater. With all three false, Statistics is hidden. |
leaderboard | true | The Leaderboards, the top 10 by XP. It reads saved stats, written as players leave and when the resource stops. |
blips.start.enable | true | The clerk's blip. |
blips.start.sprite | 729 | The blip's icon id. |
blips.start.color | 3 | The blip's color id. |
blips.start.scale | 0.9 | |
blips.start.label | 'Scuba Diving' | The name on the map. |
blips.zone.color | 1 | The hotspot circle's color id (red). |
blips.zone.alpha | 100 | The circle's opacity, 0 to 255. |
Animations
In config/client.lua. Each entry under anims is one progress bar: label, icon, duration in milliseconds, position, useWhileDead, allowSwimming, canCancel, disable (move, car, combat), anim (dict, clip, flag) and prop (model, bone, pos, rot).
| Key | Label | Duration | Notes |
|---|---|---|---|
anims.anchorBoat | Toggling anchor.. | 1000 | Icon fas fa-anchor, anim random@domestic pickup_low. |
anims.openCrate | Opening crate.. | 2000 | The player can walk. Anim anim@heists@box_carry@ idle holding v_serv_abox_04. |
anims.toggleGear | Changing clothes.. | 5000 | Icon fas fa-shirt, works while swimming. Anim clothingshirt try_shirt_positive_d. |
anims.pickupCrate | Picking up.. | 3000 | Icon fas fa-hand, works while swimming, can't be cancelled. |
anims.createGroup | Creating group.. | 1000 | Icon fas fa-users. |
Logging
In config/server.lua.
| Key | Default | Notes |
|---|---|---|
logs.service | 'none' | 'fivemanage' (needs fmsdk running), 'fivemerr' (needs fm-logs running), 'discord' or 'none'. |
logs.screenshots | false | Adds the player's screen to each log on Fivemanage and Fivemerr. |
logs.events.crateFound | false | A player picks up a crate, with where. |
logs.events.crateOpened | false | A player opens a crate, with what they got. |
logs.events.itemPurchased | false | A purchase from the dive shop. |
logs.events.itemPawned | false | A sale to the pawn shop. See the note below. |
logs.events.boatRented | false | A boat rented, with the deposit. |
logs.events.boatReturned | false | A boat returned, with the refund. |
logs.discord.name | 'Scuba Diving' | The webhook's name. |
logs.discord.link | '' | The webhook URL. |
logs.discord.image | An image link | The webhook's picture. |
logs.discord.footer | An image link | The footer icon. |
In 2.2.1 the pawn shop's log line expects one more value than the script gives it, so with itemPawned on, each sale prints an error in the server console instead of a log. The sale itself goes through.
Icons
config/icons.lua holds the Font Awesome icons on the targets, menus and prompts, each with an optional color in the key ending _color (empty for the default). The keys: talk (the clerk), anchor, pickup_crate, underwater (the readout), quantity and player_id (the prompts), player_level, view_stats, stats_crates, stats_depth, stats_swam, diving_leaderboard, shop, pawn, rental, create_group, manage_group, start_diving (green, #82E58B), stop_diving (red, #FF5C5C), add_group_member, remove_group_member, leave_group and leaderboard (the top three's trophy).
Text prompts
The underwater readout is a text prompt, set in client/functions.lua rather than config/, on line 13:
local textui = 'ox_lib'Also 'lation_ui', 'jg-textui', 'okokTextUI' or 'qbcore', or add your own in ShowTextUI and HideTextUI in the same file.
Language
Every string is in locales/, which ships English (en.json), German (de.json) and Dutch (nl.json). scuba diving uses ox_lib's language, so set it with ox_lib's own setting:
setr ox:locale deTo translate, copy locales/en.json to a new file named for the language, such as locales/fr.json, and translate the values. The refill slider's title and label are written in client/functions.lua and stay in English.
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated
Players
How players use scuba diving with the default settings, from the clerk's menu and the dive shop to scuba gear and air, groups, a dive, opening crates, the pawn shop, the rental boat and levels.
Developers
The scuba diving client and server exports, the functions left open for your own code, and the files that ship open, with signatures, return shapes and Lua examples.