# Orbit Studios Documentation (/docs)
# Orbit Studios Documentation [#orbit-studios-documentation]
Welcome to the official Orbit Studios documentation. These guides cover setup, configuration, and integration notes for Orbit Studios FiveM resources.
Every page is also available through `/llms.txt`, `/llms-full.txt`, and the copyable Markdown link in the page toolbar.
# Commands (/docs/orbit-studios-resources/orbit-craftingsystem/commands)
# Commands [#commands]
Commands are typed in the FiveM chat by a player with permission, or executed from the server console when supported. The crafting system currently exposes one developer command for giving blueprint items during setup and testing.
`createblueprint` is only available when developer mode is enabled.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.DeveloperMode = true
```
Turn developer mode back off after setup if you do not want this test command available on production servers.
## Parameters [#parameters]
```text title="FiveM console"
/createblueprint 12 weapon_pistol
/createblueprint 12 weapon_pistol 3
```
The first example gives player ID `12` one blueprint that unlocks `weapon_pistol`. The second example gives the same player three blueprint items.
`blueprintName` must match a key in `Config.Blueprints.items`, not the display label. If you use `Config.CustomBlueprints`, the command still receives the original blueprint content name, such as `weapon_pistol`.
## Permission Notes [#permission-notes]
The command is registered as restricted and developer-mode gated. If the chat suggestion appears but nothing happens, check the server console for the developer-mode warning first, then confirm the player running the command has permission to use restricted commands.
# Configuration (/docs/orbit-studios-resources/orbit-craftingsystem/configuration)
# Configuration [#configuration]
`orbit-craftingsystem` has two public config files. Use `shared/config.lua` for gameplay and recipes. Use `server/config.lua` for server-only logging, image paths, and Discord webhooks.
Put craftable items, benches, stations, blueprints, XP, and access rules in `shared/config.lua`. Put webhook URLs and logging callbacks in `server/config.lua`.
## File Map [#file-map]
## Setup Workflow [#setup-workflow]
### Choose where the item belongs [#choose-where-the-item-belongs]
Use a station item when the recipe should be available at a fixed world location. Use a bench non-blueprint item when the recipe should always be available on a portable bench. Use a blueprint item when players must own or install a blueprint first.
### Add the inventory items first [#add-the-inventory-items-first]
Every final item and every required material must exist in your inventory or framework item list before testing. If the inventory does not know `metalscrap`, `steel`, or `weapon_pistol`, the crafting system cannot add or remove them correctly.
### Add one recipe and test it [#add-one-recipe-and-test-it]
Add one recipe to `shared/config.lua`, restart the resource, open the station or bench, and test one craft. After that works, duplicate the same structure for the rest of your recipes.
### Enable logging [#enable-logging]
Add your Discord webhook URL in `server/config.lua`, then keep or customize `Config.Server.OnCraft` and `Config.Server.SuspiciousActivity`.
## Shared Config Shape [#shared-config-shape]
`shared/config.lua` is read in this order. Keeping the same order makes it much easier to compare your file with the shipped config when you update the resource.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config = Config or {}
Config.DeveloperMode = false
Config.CraftingWithWheel = true
Config.NuiState = function(bool)
if not Config.DeveloperMode then return end
print("NUI Open:", bool)
end
Config.Celebration = {
animDict = "anim@mp_player_intcelebrationmale@air_guitar",
animName = "air_guitar"
}
Config.BenchAnimations = {
putting_down_bench = {
duration = 5000,
animDict = "amb@world_human_hammering@male@base",
anim = "base",
flag = 1
},
moving_bench = {
duration = 1000,
animDict = "amb@world_human_hammering@male@base",
anim = "base",
flag = 1
}
}
Config.LevelValues = {
xpGainMultiplier = 10,
levelUpXPMultiplier = 100,
loseMultiplier = 0.5
}
Config.MainRoutingBucket = 0
Config.Benches = {}
Config.Blueprints = {}
Config.CustomBlueprints = {}
Config.Stations = {}
```
The empty tables above are only an outline. In your real file, `Config.Benches`, `Config.Blueprints`, and `Config.Stations` contain the actual bench types, blueprint recipes, fixed stations, recipes, targets, and access groups.
## Add Bench Items To Inventory [#add-bench-items-to-inventory]
Every key inside `Config.Benches.benchTypes` must also exist as an inventory item. The default config includes `weapon-crafting_bench` and `medical_bench`, so those item names need to be added before players can place those benches.
If the bench type is `["weapon-crafting_bench"]`, the inventory item must also be `weapon-crafting_bench`. Bench item names cannot start with `weapon_` and must include `bench`.
Add the bench item inside your inventory resource. For ESX servers using `ox_inventory`, this is usually `ox_inventory/data/items.lua`.
```lua title="resources/[standalone]/ox_inventory/data/items.lua"
["weapon-crafting_bench"] = {
label = "Weapon Crafting Bench",
weight = 1000,
stack = false,
close = true,
description = "Places a weapon crafting bench."
},
["medical_bench"] = {
label = "Medical Crafting Bench",
weight = 1000,
stack = false,
close = true,
description = "Places a medical crafting bench."
},
```
If your ESX server uses a different inventory, add the same item names using that inventory's item format. The important part is that the item name exactly matches the bench key in `Config.Benches.benchTypes`.
Add the bench item in QBCore's shared item file, not inside the crafting resource.
```lua title="resources/[qb]/qb-core/shared/items.lua"
["weapon-crafting_bench"] = {
name = "weapon-crafting_bench",
label = "Weapon Crafting Bench",
weight = 1000,
type = "item",
image = "weapon-crafting_bench.png",
unique = true,
useable = true,
shouldClose = true,
combinable = nil,
description = "Places a weapon crafting bench."
},
["medical_bench"] = {
name = "medical_bench",
label = "Medical Crafting Bench",
weight = 1000,
type = "item",
image = "medical_bench.png",
unique = true,
useable = true,
shouldClose = true,
combinable = nil,
description = "Places a medical crafting bench."
},
```
`unique = true` is recommended because benches can carry metadata, especially when `Config.Blueprints.store = "bench"`.
Add the bench item inside your inventory resource. For most Qbox/QBX servers this is the inventory item file, for example `ox_inventory/data/items.lua`.
```lua title="resources/[standalone]/ox_inventory/data/items.lua"
["weapon-crafting_bench"] = {
label = "Weapon Crafting Bench",
weight = 1000,
stack = false,
close = true,
description = "Places a weapon crafting bench."
},
["medical_bench"] = {
label = "Medical Crafting Bench",
weight = 1000,
stack = false,
close = true,
description = "Places a medical crafting bench."
},
```
If you rename or add a bench type in `Config.Benches.benchTypes`, add the same item name here too.
The crafting system registers each bench type as a usable item through `orbit-lib`. That means players use the inventory item, the resource previews the bench prop, and then the bench is placed if the player confirms the position.
## Where To Add Items [#where-to-add-items]
Craftable items can live in three places. The recipe shape is mostly the same, but the location decides how the player accesses it.
Put fixed-location recipes inside `Config.Stations[stationId].items`.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Stations = {
HideStationDistance = 50,
["weapon_station"] = {
title = "Weapon Crafting Station",
secondaryTitle = "Orbit Studios",
blip = {
haveBlip = true,
sprite = 110,
color = 1,
scale = 0.8,
coords = vector3(502.64, -1338.17, 29.31)
},
target = {
type = "npc",
model = "s_m_m_ammucountry",
coords = vector3(502.64, -1338.17, 29.31),
heading = 37.18
},
groups = {
jobs = {},
gangs = {}
},
items = {
["weapon_pistol"] = {
type = "weapon",
itemLevel = 1,
baseOdds = 50,
maxOdds = 90,
amountToCraft = 1,
requirements = {
{ item = "plastic", amount = 5, removeOnSuccess = true, removeOnFail = true },
{ item = "iron", amount = 5, removeOnSuccess = true, removeOnFail = false }
}
}
}
}
}
```
Leave `groups.jobs` and `groups.gangs` empty for a public station. Add job or gang names only when the station should be restricted.
Put bench recipes that do not need blueprints inside `Config.Benches.benchTypes[benchItemName].nonBlueprintItems`.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Benches = {
onlyOwnerCanMove = true,
enableBenches = true,
enablePersistentBenches = true,
HideBenchDistance = 50,
benchTypes = {
["weapon-crafting_bench"] = {
benchProp = "prop_tool_bench02",
benchLabel = "Weapon Bench",
title = "Weapon Crafting Bench",
secondaryTitle = "Orbit Studios",
nonBlueprintItems = {
["weapon_knife"] = {
type = "weapon",
itemLevel = 1,
baseOdds = 50,
maxOdds = 90,
amountToCraft = 1,
requirements = {
{ item = "metalscrap", amount = 10, removeOnSuccess = true, removeOnFail = true },
{ item = "steel", amount = 5, removeOnSuccess = true, removeOnFail = false }
}
}
}
}
}
}
```
The bench type key, such as `weapon-crafting_bench`, must match the bench inventory item name. Bench item names cannot start with `weapon_` and must include `bench`.
Put blueprint-locked recipes inside `Config.Blueprints.items`.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Blueprints = {
store = "bench",
items = {
["weapon_pistol"] = {
bench = "weapon-crafting_bench",
type = "weapon",
itemLevel = 1,
baseOdds = 60,
maxOdds = 90,
amountToCraft = 1,
requirements = {
{ item = "metalscrap", amount = 10, removeOnSuccess = true, removeOnFail = true },
{ item = "steel", amount = 5, removeOnSuccess = true, removeOnFail = false }
}
}
}
}
```
`store = "bench"` stores learned blueprints on the bench. `store = "player"` stores learned blueprints on the player. The `bench` value must match a key in `Config.Benches.benchTypes`.
Use `Config.CustomBlueprints` when the physical inventory item has a different name from the recipe key.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Blueprints = {
store = "bench",
items = {
["weapon_pistol"] = {
bench = "weapon-crafting_bench",
type = "weapon",
itemLevel = 1,
baseOdds = 60,
maxOdds = 90,
requirements = {
{ item = "metalscrap", amount = 10, removeOnSuccess = true, removeOnFail = true }
}
}
}
}
Config.CustomBlueprints = {
["weapon_pistol"] = {
customBlueprintName = "blueprint_weapon_pistol"
}
}
```
In this example, the blueprint content is still `weapon_pistol`, but the inventory item given to the player is `blueprint_weapon_pistol`.
## Recipe Fields [#recipe-fields]
Every recipe uses the same core fields whether it is placed in a station, bench, or blueprint list.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
["firstaid"] = {
itemLevel = 2,
baseOdds = 40,
maxOdds = 90,
amountToCraft = 2,
requirements = {
{ item = "bandage", amount = 5, removeOnSuccess = true, removeOnFail = true },
{ item = "painkillers", amount = 2, removeOnSuccess = true, removeOnFail = true }
}
}
```
Set `removeOnSuccess` and `removeOnFail` explicitly for each requirement while learning the config. That makes it obvious whether materials disappear on a successful craft, a failed craft, or both.
## Core Shared Options [#core-shared-options]
### Crafting Wheel [#crafting-wheel]
`Config.CraftingWithWheel` decides how strict the crafting level system is.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.CraftingWithWheel = true
```
When this is `true`, players use the success-percentage crafting wheel. `itemLevel`, `baseOdds`, and `maxOdds` decide how difficult the craft is and how much the chance can improve.
When this is `false`, crafting becomes level-gated. Players can craft items at their level or below their level, and the percentage wheel is not used.
### NUI State Callback [#nui-state-callback]
`Config.NuiState` runs whenever the crafting UI opens or closes. Use it when another resource needs to know that the player is inside the crafting interface.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.NuiState = function(bool)
if not Config.DeveloperMode then return end
print("NUI Open:", bool)
end
```
`bool = true` means the UI opened. `bool = false` means it closed.
Set it to `nil` if you do not need this callback:
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.NuiState = nil
```
### Celebration Animation [#celebration-animation]
`Config.Celebration` is the animation played after a successful craft.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Celebration = {
animDict = "anim@mp_player_intcelebrationmale@air_guitar",
animName = "air_guitar"
}
```
To change the animation, replace both values with a valid GTA animation dictionary and animation name. To disable the celebration, set both values to `nil`.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Celebration = {
animDict = nil,
animName = nil
}
```
### Bench Animations [#bench-animations]
`Config.BenchAnimations` is used by the `orbit-lib` progress integration when a player places or moves a bench.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.BenchAnimations = {
putting_down_bench = {
duration = 5000,
animDict = "amb@world_human_hammering@male@base",
anim = "base",
flag = 1
},
moving_bench = {
duration = 1000,
animDict = "amb@world_human_hammering@male@base",
anim = "base",
flag = 1
}
}
```
`duration` is in milliseconds. `animDict`, `anim`, and `flag` are passed to the progress animation. If you make the duration very short, bench placement will feel instant and players may not understand that the bench is being placed.
### Level Values [#level-values]
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.LevelValues = {
xpGainMultiplier = 10,
levelUpXPMultiplier = 100,
loseMultiplier = 0.5
}
```
`loseMultiplier = 0.5` means a failed craft gives half of the XP the craft would normally give.
## Bench Placement [#bench-placement]
Bench placement controls where portable benches can be placed.
Blacklist mode allows bench placement everywhere except inside listed zones.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Benches.benchPlacement = {
enabled = true,
mode = "blacklist",
zones = {
{
vectors = {
vector3(494.22, -1328.00, 29.00),
vector3(494.70, -1333.96, 29.00),
vector3(500.11, -1335.09, 29.00)
},
height = 10
}
}
}
```
Whitelist mode blocks bench placement everywhere except inside listed zones.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
Config.Benches.benchPlacement = {
enabled = true,
mode = "whitelist",
zones = {
{
vectors = {
vector3(493.93, -1335.25, 29.00)
},
radius = 5.0
}
}
}
```
Use `vectors` plus `height` for polygon zones. Use `vectors` plus `radius` for sphere zones. Use `vectors` plus `size = vec3(...)` for box zones.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
{
vectors = {
vector3(493.93, -1335.25, 29.00)
},
size = vec3(2, 2, 2)
}
```
## Station Access [#station-access]
Access groups live inside each station. Leave both tables empty for public use.
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
groups = {
jobs = {},
gangs = {}
}
```
Restrict by job or gang name with a minimum grade:
```lua title="resources/[orbit]/orbit-craftingsystem/shared/config.lua"
groups = {
jobs = {
["police"] = 0,
["ambulance"] = 2
},
gangs = {
["lostmc"] = 1
}
}
```
`["ambulance"] = 2` means the player must have the ambulance job at grade 2 or higher. Job and gang names must match the data returned by your framework through `orbit-lib`.
## Server Config [#server-config]
`resources/[orbit]/orbit-craftingsystem/server/config.lua` is server-only. This is where inventory image URLs, Discord webhooks, and logging callbacks live.
## Inventory Image URLs [#inventory-image-urls]
Use `Config.Server.CustomImageURL` when item images are missing in the crafting UI.
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.CustomImageURL = false
```
For `ox_inventory`, this is a common value:
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.CustomImageURL = "cfx-nui-ox_inventory/web/images/"
```
The image file name should match the inventory item name. For example, `weapon_pistol` normally needs an image named like `weapon_pistol.png` in the configured image directory.
## Webhooks [#webhooks]
Add your Discord webhook URL in `server/config.lua`. Do not put webhook URLs in `shared/config.lua`, because shared files can be loaded client-side.
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.Webhook = {
url = "https://discord.com/api/webhooks/...",
username = nil,
avatar = nil
}
```
Use `username` and `avatar` only if you want to override the Discord webhook defaults:
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.Webhook = {
url = "https://discord.com/api/webhooks/...",
username = "Orbit Crafting Logs",
avatar = "https://example.com/logo.png"
}
```
The included sender uses Discord embeds:
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
function Config.Server.SendWebhook(embed)
local webhook = Config.Server.Webhook
if not webhook.url or webhook.url == "" then return end
PerformHttpRequest(
webhook.url,
function() end,
"POST",
json.encode({
username = webhook.username,
avatar_url = webhook.avatar,
embeds = { embed }
}),
{ ["Content-Type"] = "application/json" }
)
end
```
## Crafting Log Webhook [#crafting-log-webhook]
`Config.Server.OnCraft` runs after a valid crafting attempt. It receives the player, station or bench ID, item name, crafted amount, item level, and whether the craft succeeded.
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.Colors = {
success = "#2ecc71",
failed = "#e74c3c",
suspicious = "#ff0000"
}
local function HexToDecimal(hex)
return tonumber(hex:gsub("#", ""), 16)
end
Config.Server.OnCraft = function(source, stationId, itemName, craftedAmount, itemLevel, isWin)
local playerName = GetPlayerName(source) or "Unknown"
local playerId = source
local embed = {
title = isWin and "Crafting Successful" or "Crafting Failed",
description = isWin and "The player successfully crafted an item." or "The crafting attempt failed.",
color = HexToDecimal(isWin and Config.Server.Colors.success or Config.Server.Colors.failed),
author = {
name = playerName .. " (" .. playerId .. ")"
},
fields = {
{
name = "Station or Bench",
value = tostring(stationId),
inline = false
},
{
name = "Item",
value = tostring(itemName),
inline = true
},
{
name = "Amount",
value = tostring(craftedAmount),
inline = true
},
{
name = "Item Level",
value = tostring(itemLevel),
inline = true
}
},
footer = {
text = "Orbit Crafting System"
},
timestamp = os.date("!%Y-%m-%dT%H:%M:%SZ")
}
Config.Server.SendWebhook(embed)
end
```
Set `Config.Server.OnCraft = nil` if you want to disable normal crafting logs entirely:
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.OnCraft = nil
```
## Suspicious Activity Webhook [#suspicious-activity-webhook]
`Config.Server.SuspiciousActivity` runs when the server detects an invalid crafting attempt. This is useful for exploit attempts, invalid items, missing requirements, or other rejected craft requests.
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.SuspiciousActivity = function(source, stationId, itemName, craftedAmount, reason, isWin)
local playerName = GetPlayerName(source) or "Unknown"
local playerId = source
local embed = {
title = "Suspicious Crafting Activity",
description = "Potential exploit or invalid crafting attempt detected.",
color = HexToDecimal(Config.Server.Colors.suspicious),
author = {
name = playerName .. " (" .. playerId .. ")"
},
fields = {
{
name = "Station or Bench",
value = tostring(stationId),
inline = false
},
{
name = "Item",
value = tostring(itemName),
inline = true
},
{
name = "Attempted Amount",
value = tostring(craftedAmount),
inline = true
},
{
name = "Reason",
value = tostring(reason),
inline = false
}
},
footer = {
text = "Orbit Crafting System - monitor recommended"
},
timestamp = os.date("!%Y-%m-%dT%H:%M:%SZ")
}
Config.Server.SendWebhook(embed)
end
```
Set `Config.Server.SuspiciousActivity = nil` if you want to disable suspicious activity logs:
```lua title="resources/[orbit]/orbit-craftingsystem/server/config.lua"
Config.Server.SuspiciousActivity = nil
```
## Webhook Testing [#webhook-testing]
### Add the webhook URL [#add-the-webhook-url]
Paste the Discord webhook URL into `Config.Server.Webhook.url` in `server/config.lua`.
### Keep `OnCraft` enabled [#keep-oncraft-enabled]
Make sure `Config.Server.OnCraft` is a function, not `nil`.
### Craft one test item [#craft-one-test-item]
Join the server, open a station or bench, and craft an item. Discord should receive a success or failure embed.
### Check the server console [#check-the-server-console]
If no message arrives, confirm the URL is not empty, outbound HTTP is allowed, and the config file is saved on the server.
## Common Mistakes [#common-mistakes]
Make sure the recipe is inside the correct table: `Config.Stations[stationId].items`, `Config.Benches.benchTypes[benchName].nonBlueprintItems`, or `Config.Blueprints.items`. Also confirm the player has access to the station or bench.
Confirm the final item and every requirement item exists in your inventory or framework item list. Also check `removeOnSuccess` and `removeOnFail` so required materials are handled the way you expect.
Put the URL in `Config.Server.Webhook.url`, keep `Config.Server.OnCraft` or `Config.Server.SuspiciousActivity` enabled, and make sure the webhook URL is valid. Webhook code belongs in `server/config.lua`, not `shared/config.lua`.
Job and gang names must match the values returned by your framework through `orbit-lib`. Remove access groups temporarily to confirm the station itself works, then add restrictions back one at a time.
# Dependencies (/docs/orbit-studios-resources/orbit-craftingsystem/dependencies)
# Dependencies [#dependencies]
`orbit-craftingsystem` needs database, library, inventory, target, and bridge resources to be started before the crafting resource.
## Required [#required]
| Dependency | Why it is needed | Link |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `ox_lib` | Loads `@ox_lib/init.lua`, locales, callbacks, UI helpers, notifications, and target helper utilities used by the resource. | [overextended/ox\_lib](https://github.com/overextended/ox_lib) |
| `oxmysql` | Loads `@oxmysql/lib/MySQL.lua` and stores persistent crafting data such as progression and bench data. | [overextended/oxmysql](https://github.com/overextended/oxmysql) |
| `orbit-lib` | Provides the framework, inventory, target, notification, progress, player, item, and metadata bridge used by Orbit resources. | [orbit-lib](/docs/orbit-studios-resources/orbit-lib) |
| Supported inventory | Required for checking materials, removing requirements, giving crafted items, blueprint metadata, and bench items. | [Supported inventories](/docs/orbit-studios-resources/orbit-lib/configuration#supported-providers) |
| Supported target | Required for station and bench interactions. Use `ox_target` or `qb-target` through `orbit-lib`. | [ox\_target](https://github.com/overextended/ox_target), [qb-target](https://github.com/qbcore-framework/qb-target) |
## Supported Inventories [#supported-inventories]
The inventory is selected in `orbit-lib`, not inside the crafting resource.
| `Config.Inventory` | Inventory |
| ------------------ | --------------------------------------------------------------------------------- |
| `ox_inventory` | [overextended/ox\_inventory](https://github.com/overextended/ox_inventory) |
| `qb-inventory` | [qbcore-framework/qb-inventory](https://github.com/qbcore-framework/qb-inventory) |
| `ps-inventory` | [Project-Sloth/ps-inventory](https://github.com/Project-Sloth/ps-inventory) |
| `lj-inventory` | [loljoshie/lj-inventory](https://github.com/loljoshie/lj-inventory) |
| `qb-like` | Custom QB-style inventory exports |
| `ox-like` | Custom OX-style inventory exports |
## Start Order [#start-order]
```properties title="server.cfg"
ensure oxmysql
ensure ox_lib
ensure [framework-resources]
ensure [inventory]
ensure [target]
ensure orbit-lib
ensure orbit-craftingsystem
```
If the crafting UI opens but materials or rewards fail, check the inventory provider in `orbit-lib` first. If stations or benches do not show, check the target provider and start order.
# Exports (/docs/orbit-studios-resources/orbit-craftingsystem/exports)
# Exports [#exports]
Use server exports from another server script and client exports from another client script. Calling a client export from server code, or a server export from client code, will not work.
## Server Examples [#server-examples]
```lua title="resources/[custom]/server/main.lua"
local source = source
local created = exports['orbit-craftingsystem']:CreateBlueprint(source, 'weapon_pistol', 1)
if not created then
print('[my-resource] Blueprint could not be created')
end
```
```lua title="resources/[custom]/server/main.lua"
local level, xp = exports['orbit-craftingsystem']:getPlayerLevel(source)
print(('Player level: %s, XP: %s'):format(level, xp))
```
```lua title="resources/[custom]/server/main.lua"
local itemData = exports['orbit-craftingsystem']:getItemData(true, 'weapon_station', 'weapon_pistol', false)
if itemData then
print(('Base odds: %s'):format(itemData.baseOdds))
end
```
## Client Examples [#client-examples]
```lua title="resources/[custom]/client/main.lua"
exports['orbit-craftingsystem']:previewProp('weapon-crafting_bench', 'prop_tool_bench02', nil, nil)
```
```lua title="resources/[custom]/client/main.lua"
exports['orbit-craftingsystem']:checkNearbyBenches('weapon_pistol', nil, nil)
```
The client helpers are mainly useful for advanced integrations. For normal setup, let the included bench item and blueprint item handlers call them automatically.
# Installation (/docs/orbit-studios-resources/orbit-craftingsystem)
# Installation [#installation]
`orbit-craftingsystem` is Orbit Studios' configurable crafting resource for stations, benches, blueprints, crafting levels, XP, and optional crafting minigame odds.
Start `orbit-lib`, `ox_lib`, `oxmysql`, your target resource, and your inventory before `orbit-craftingsystem`.
This page gets the resource running. Use the configuration page when you are ready to add your own craftable items, benches, stations, blueprint requirements, webhook logging, and image paths.
## File Structure [#file-structure]
## What You Edit [#what-you-edit]
Most server owners only need the two config files:
Use `shared/config.lua` for gameplay rules such as craftable items, benches, stations, blueprint requirements, levels, and XP. Use `server/config.lua` for image URLs, webhooks, and server-side hooks after crafting attempts.
## Installation [#installation-1]
### Configure orbit-lib [#configure-orbit-lib]
Set your framework, target, inventory, notifications, and progress provider in [`orbit-lib`](../orbit-lib).
### Configure crafting [#configure-crafting]
Edit `shared/config.lua` for stations, benches, blueprints, XP, and access rules. Edit `server/config.lua` for image URLs and webhook logging. Keep item names exactly the same as your inventory item names.
### Ensure resources [#ensure-resources]
```properties title="server.cfg"
ensure oxmysql
ensure ox_lib
ensure [framework-resources]
ensure [inventory]
ensure [target]
ensure orbit-lib
ensure orbit-craftingsystem
```
### Test one station or bench [#test-one-station-or-bench]
Join the server, walk to one configured station, and confirm the target opens. If it does not, check the target resource, station coords, job/gang access, and the server console before adding more recipes.
## Framework Notes [#framework-notes]
Use `Config.Framework = 'esx'` in `orbit-lib`. Jobs in crafting access rules should match ESX job names and minimum grades.
Use `Config.Framework = 'qb'` in `orbit-lib`. Jobs and gangs should match QBCore names and minimum grades.
Use `Config.Framework = 'qbx'` in `orbit-lib`. QBX gang and job access works through normalized data from `orbit-lib`.
Use `Config.Framework = 'standalone'` in `orbit-lib`. Crafting can still run, but any job, gang, player name, money, or usable-item behavior depends on the standalone adapters you configured in `orbit-lib`.
# Language Support (/docs/orbit-studios-resources/orbit-craftingsystem/language-support)
# Language Support [#language-support]
`orbit-craftingsystem` includes locale files in `resources/[orbit]/orbit-craftingsystem/locales`.
## Available Locales [#available-locales]
| Locale | File |
| ------- | --------- |
| English | `en.json` |
| German | `de.json` |
| Spanish | `es.json` |
| French | `fr.json` |
| Italian | `it.json` |
| Swedish | `sv.json` |
| Turkish | `tr.json` |
## Set The Locale [#set-the-locale]
Set the active `ox_lib` locale in `server.cfg`.
```properties title="server.cfg"
setr ox:locale en
```
Change `en` to the locale file name without `.json`.
```properties title="server.cfg"
setr ox:locale sv
```
## Edit Text [#edit-text]
Edit the matching JSON file to change labels, descriptions, errors, and UI messages.
```json title="resources/[orbit]/orbit-craftingsystem/locales/en.json"
{
"example_key": "Example text"
}
```
Keep JSON valid: use double quotes, commas between entries, and no trailing comma after the final entry.
# Troubleshooting (/docs/orbit-studios-resources/orbit-craftingsystem/troubleshooting)
# Troubleshooting [#troubleshooting]
Confirm `orbit-lib`, `ox_lib`, the target resource, inventory, and `oxmysql` start before `orbit-craftingsystem`. Then test one station with no job or gang restriction. If that opens, the problem is likely station access rules instead of the UI itself.
Set `Config.Server.CustomImageURL` in `server/config.lua` when your inventory image directory differs from the default inventory image path. Use a path that the NUI can load, such as `cfx-nui-ox_inventory/web/images/`, and make sure the image filename matches the item name.
Check `HideStationDistance`, `HideBenchDistance`, target model, coords, heading, routing bucket, and access groups. Start by standing very close to the configured coords. If the target appears only after removing `groups.jobs` or `groups.gangs`, the access rule names or grades do not match your framework data.
Enable `Config.DeveloperMode = true` in `shared/config.lua`. The command is disabled when developer mode is off. The second parameter must be a key from `Config.Blueprints.items`, for example `weapon_pistol`, not the label shown to players.
# Commands (/docs/orbit-studios-resources/orbit-dynamichud/commands)
# Commands [#commands]
The shipped `cash` and `bank` command implementation reads QB/QBX-style `PlayerData.money` from `QBCore.Functions.GetPlayer`. Disable or adapt those commands if you run ESX or standalone mode.
Command names come from the locale files, so the default English names are shown below. If you translate `locales/en.json` or change locale strings, use the translated command names in-game.
## Parameters [#parameters]
```text title="FiveM console"
/cash
/cash 12
/bank
/bank 12
/setstress 25
/setstress 12 25
```
Square brackets mean optional. Angle brackets mean required. For example, `/cash [targetId]` can be used as `/cash` or `/cash 12`, while `/setstress ` needs a stress value.
Server command availability is controlled from `server/config.lua`.
```lua title="resources/[orbit]/orbit-dynamichud/server/config.lua"
Config.Commands.setstress = {
enabled = true,
allow = 'group.admin'
}
```
`allow` is the `ox_lib` restricted command group. Use the same shape for `cash`, `bank`, and `setstress`. Leave it empty only if normal players should be able to run the command.
```lua title="resources/[orbit]/orbit-dynamichud/server/config.lua"
Config.Commands.cash = {
enabled = false,
allow = 'group.admin'
}
```
# Configuration (/docs/orbit-studios-resources/orbit-dynamichud/configuration)
# Configuration [#configuration]
`orbit-dynamichud` exposes several non-escrowed config files. Start with `shared/config.lua`, then review default player settings, server commands, framework handlers, and weapon metadata.
The HUD runtime is escrowed. Configure the resource through `shared/config.lua`, `shared/settingsConfig.lua`, `shared/weapons.lua`, `server/config.lua`, and `server/handlers.lua`.
## File Map [#file-map]
## Shared Config [#shared-config]
`resources/[orbit]/orbit-dynamichud/shared/config.lua` controls the global HUD behavior.
```lua title="resources/[orbit]/orbit-dynamichud/shared/config.lua"
Config = Config or {}
Config.Debug = false
Config.ServerInfo = {
serverBgColor = "#FF00F2"
}
Config.HeadingType = "camera"
Config.Onboarding = true
Config.DriverPermissionAsPassenger = false
Config.DynamicBar = {
enable = true,
hourFormat = "24",
postCodes = false
}
Config.PerformanceSettings = {
performance = 300,
balanced = 100,
ultra = 30
}
Config.CustomMap = {
usingCustomMap = true,
radarZoom = 1100,
waitTime = 300
}
Config.Keybinds = {
indicator_keybinds = {
right_indicator_keybind = "RIGHT",
left_indicator_keybind = "LEFT",
hazard_indicator_keybind = "UP"
},
ui_keybinds = {
focus_ui = "F4"
}
}
Config.GetVehicleFuelLevel = function(veh)
if not veh then
return 0.0
end
return GetVehicleFuelLevel(veh) or 0.0
end
Config.EnabledValues = {
health = true,
armor = true,
hunger = true,
thirst = true,
stamina = true,
stress = true
}
Config.Accounts = {
cash = true,
bank = true,
dirty = false
}
Config.SettingsLocked = false
Config.CinematicHeight = 0.2
```
Do not delete keys from `Config.EnabledValues`. Use `true` to show a supported value and `false` to hide it. The HUD does not support custom status keys in this table yet.
## Status Sources [#status-sources]
DynamicHUD listens for common framework events and state bags, but the exact source depends on your framework and supporting resources.
ESX money and status updates come from ESX events such as `esx:setAccountMoney`, `esx_status:onTick`, and spawn/death events. Keep the ESX death handlers in `server/handlers.lua` unless your ambulance resource uses different events.
```lua title="resources/[orbit]/orbit-dynamichud/server/handlers.lua"
AddEventHandler("esx:onPlayerDeath", function(data)
local src = source
Player(src)?.state:set("hud:deathState", 3, true)
end)
AddEventHandler("playerSpawned", function(spawn)
local src = source
Player(src)?.state:set("hud:deathState", 1, true)
end)
```
QB status and money updates are read from common QBCore HUD events like `hud:client:UpdateNeeds`, `hud:client:UpdateStress`, and `hud:client:OnMoneyChange`. The default death handlers support `qb-ambulancejob` style hospital events.
```lua title="resources/[orbit]/orbit-dynamichud/server/handlers.lua"
AddEventHandler("hospital:server:SetLaststandStatus", function(state)
local src = source
local state = state and 2 or 1
Player(src)?.state:set("hud:deathState", state, true)
end)
AddEventHandler("hospital:server:SetDeathStatus", function(state)
local src = source
local state = state and 3 or 1
Player(src)?.state:set("hud:deathState", state, true)
end)
```
QBX/Qbox can use the same common HUD events for needs and stress. DynamicHUD also listens to the `qbx_medical:deathState` player state and mirrors it into `hud:deathState`.
```lua title="resources/[custom]/server/death-state.lua"
Player(source)?.state:set("hud:deathState", 3, true)
```
Use the numeric death-state values from the handlers section if your medical resource does not already publish a compatible state.
Standalone servers must feed the HUD with the same events or state bags that the HUD expects. For death state, set `hud:deathState` on the player state. For stress, use `LocalPlayer.state.stress` through `orbit-dynamichud-stress` or your own resource.
```lua title="resources/[custom]/server/death-state.lua"
Player(source)?.state:set("hud:deathState", 1, true)
```
## Default Player Settings [#default-player-settings]
`resources/[orbit]/orbit-dynamichud/shared/settingsConfig.lua` defines the default settings used before a player customizes the HUD.
```lua title="resources/[orbit]/orbit-dynamichud/shared/settingsConfig.lua"
local function layout(visible)
return {
x = 0,
y = 0,
scale = 1,
locked = false,
visible = visible ~= false
}
end
Config.DefaultSettings = {
resolution = {
width = 1920,
height = 1080
},
preset = "balanced",
unit = "kmh",
shape = "square",
hud = "waveseries",
speedometer = "Apex",
icons = {
health = 1,
armor = 1,
hunger = 1,
thirst = 1,
stamina = 1,
stress = 1
},
component_layouts = {
notification = layout(),
dynamicbar = layout(),
cash = layout(),
bank = layout(),
dirty_money = layout(),
voice = layout(),
weapon = layout(),
job = layout(),
gang = layout(),
radio = layout(),
compass = layout()
},
sounds_enabled = true,
ui_volume = 50,
music_enabled = true,
show_hud_bg = true,
show_player_data_bg = true,
default = true
}
```
Existing players may keep saved preferences, so changing defaults does not always reset everyone immediately. Use this file to decide what a new player sees first.
## Server Commands [#server-commands]
`resources/[orbit]/orbit-dynamichud/server/config.lua` enables or disables helper commands and controls who can run them.
```lua title="resources/[orbit]/orbit-dynamichud/server/config.lua"
Config = Config or {}
Config.Commands = {
cash = {
enabled = true,
allow = "group.admin"
},
bank = {
enabled = true,
allow = "group.admin"
},
setstress = {
enabled = true,
allow = "group.admin"
}
}
```
`allow` is passed to `ox_lib` command restrictions. Use an empty string only when everyone should be able to run the command.
| Command | Parameters | What it does |
| ------------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `/cash` | Optional player ID: `/cash 12` | Shows your cash, or the target player's cash if an ID is provided. |
| `/bank` | Optional player ID: `/bank 12` | Shows your bank money, or the target player's bank money if an ID is provided. |
| `/setstress` | `/setstress ` or `/setstress ` | Sets your stress, or the target player's stress. Values are clamped between `0` and `100`. |
## Handlers [#handlers]
Use `resources/[orbit]/orbit-dynamichud/server/handlers.lua` for integration glue. This is where you connect inventory visibility, death state, and any custom framework events.
### Inventory Open And Close [#inventory-open-and-close]
The default file includes `ox_inventory` handlers that hide the HUD while the inventory is open.
```lua title="resources/[orbit]/orbit-dynamichud/server/handlers.lua"
AddEventHandler("ox_inventory:openedInventory", function(source)
TriggerClientEvent("orbit-dynamichud:client:toggleHud", source, false)
end)
AddEventHandler("ox_inventory:closedInventory", function(source)
TriggerClientEvent("orbit-dynamichud:client:toggleHud", source, true)
end)
```
If you use a different inventory, replace the event names with your inventory's open and close events. Keep the `false` call on open and the `true` call on close.
### Death State [#death-state]
DynamicHUD uses numeric death states:
| Value | Meaning |
| ----- | ---------- |
| `1` | Alive |
| `2` | Last stand |
| `3` | Dead |
The default QBCore hospital handlers translate booleans into these values.
```lua title="resources/[orbit]/orbit-dynamichud/server/handlers.lua"
AddEventHandler("hospital:server:SetLaststandStatus", function(state)
local src = source
local state = state and 2 or 1
Player(src)?.state:set("hud:deathState", state, true)
end)
AddEventHandler("hospital:server:SetDeathStatus", function(state)
local src = source
local state = state and 3 or 1
Player(src)?.state:set("hud:deathState", state, true)
end)
```
The default ESX handlers set dead on death and alive on spawn.
```lua title="resources/[orbit]/orbit-dynamichud/server/handlers.lua"
AddEventHandler("esx:onPlayerDeath", function(data)
local src = source
Player(src)?.state:set("hud:deathState", 3, true)
end)
AddEventHandler("playerSpawned", function(spawn)
local src = source
Player(src)?.state:set("hud:deathState", 1, true)
end)
```
For a custom ambulance resource, set the same player state from that resource's server event.
```lua title="resources/[custom]/server/death-state.lua"
AddEventHandler("my_ambulance:server:setDeathState", function(target, state)
Player(target)?.state:set("hud:deathState", state, true)
end)
```
Make sure `state` is `1`, `2`, or `3`. If the HUD always shows the wrong death state, this file is the first place to check.
## Weapons [#weapons]
`resources/[orbit]/orbit-dynamichud/shared/weapons.lua` controls the weapon label and ammo data shown by the HUD.
```lua title="resources/[orbit]/orbit-dynamichud/shared/weapons.lua"
Config.AmmoInfo = {
getAmmoFrom = "inventory"
}
Config.Weapons = {
[`weapon_unarmed`] = {
name = "weapon_unarmed",
label = "Fists",
ammotype = nil
},
[`weapon_pistol`] = {
name = "weapon_pistol",
label = "Pistol",
ammotype = "ammo-9"
},
[`weapon_assaultrifle`] = {
name = "weapon_assaultrifle",
label = "Assault Rifle",
ammotype = "AMMO_RIFLE"
}
}
```
Add custom weapons by adding another hash entry with the same shape.
```lua title="resources/[orbit]/orbit-dynamichud/shared/weapons.lua"
Config.Weapons[`weapon_customrifle`] = {
name = "weapon_customrifle",
label = "Custom Rifle",
ammotype = "ammo-rifle"
}
```
If weapon ammo is wrong, check `Config.AmmoInfo.getAmmoFrom` first, then check that the `ammotype` matches your inventory ammo item name or native ammo type.
## Common Mistakes [#common-mistakes]
Keep `Config.EnabledValues.stress = true`, install and start `orbit-dynamichud-stress`, then confirm `LocalPlayer.state.stress` is a number.
Add open and close handlers for your inventory in `server/handlers.lua`. The default file only includes `ox_inventory` events.
Your ambulance resource probably uses different events. Add a server handler that sets `Player(source)?.state:set("hud:deathState", 3, true)` on death and `1` on revive/spawn.
Update `shared/weapons.lua`. The weapon hash key, `name`, `label`, and `ammotype` must match the weapon and ammo system your server actually uses.
# Dependencies (/docs/orbit-studios-resources/orbit-dynamichud/dependencies)
# Dependencies [#dependencies]
`orbit-dynamichud` has a small required dependency set, then several optional integrations depending on which HUD modules you want to use.
## Required [#required]
| Dependency | Why it is needed | Link |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `ox_lib` | Loads `@ox_lib/init.lua`, cache helpers, locale helpers, callbacks, and command helpers used by the HUD. | [overextended/ox\_lib](https://github.com/overextended/ox_lib) |
| `orbit-lib` | Provides normalized framework player data, item counts, money, jobs, gangs, inventory access, notifications, and progress integration. | [orbit-lib](/docs/orbit-studios-resources/orbit-lib) |
## Optional Integrations [#optional-integrations]
| Dependency | What it adds | Link |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `orbit-dynamichud-stress` | Adds replicated stress state, speeding stress, weapon stress, stress relief events, and screen effects. | [Docs](/docs/orbit-studios-resources/orbit-dynamichud-stress) / [GitHub](https://github.com/orbitstudiossoftware/orbit-dynamichud-stress) |
| `orbit-dynamichud-addons` | Adds Orbit's seatbelt and cruise-control state bags/events for the HUD. | [Docs](/docs/orbit-studios-resources/orbit-dynamichud-addons) / [GitHub](https://github.com/orbitstudiossoftware/orbit-dynamichud-addons) |
| `pma-voice` | Provides voice/radio state used by voice and radio status UI on many FiveM servers. | [AvarianKnight/pma-voice](https://github.com/AvarianKnight/pma-voice) |
| Supported inventory | Used for inventory-backed ammo, item count callbacks, and inventory open/close HUD behavior when wired in `server/handlers.lua`. | [Supported inventories](/docs/orbit-studios-resources/orbit-lib/configuration#supported-providers) |
| Framework resources | Used for money, hunger, thirst, stress, death, spawn, and player-loaded events depending on ESX, QB, QBX, or standalone mode. | [orbit-lib framework config](/docs/orbit-studios-resources/orbit-lib/configuration#framework-presets) |
## Start Order [#start-order]
```properties title="server.cfg"
ensure ox_lib
ensure [framework-resources]
ensure [inventory]
ensure orbit-lib
ensure orbit-dynamichud
# Optional HUD integrations
ensure orbit-dynamichud-addons
ensure orbit-dynamichud-stress
```
Start optional integrations after the base HUD so they can update the state bags and events DynamicHUD expects.
# Exports (/docs/orbit-studios-resources/orbit-dynamichud/exports)
# Exports [#exports]
DynamicHUD exposes both client and server integration points. Use the client exports from client scripts when you want to update the local player's HUD UI, and use the server export when server code needs to show or hide a player's HUD.
```lua title="resources/[custom]/client/main.lua"
exports['orbit-dynamichud']:SeatbeltState(true)
exports['orbit-dynamichud']:CruiseControlState(false)
exports['orbit-dynamichud']:toggleHud(false)
```
The client `toggleHud(false)` export asks the server to set `Player(source).state["hud:showHud"] = false`. Use `toggleHud(true)` to show it again.
```lua title="resources/[custom]/server/main.lua"
exports['orbit-dynamichud']:toggleHud(source, true)
```
Notification examples now live in [Interface](/docs/orbit-studios-resources/orbit-dynamichud/interface).
For custom seatbelt or cruise resources, prefer setting `LocalPlayer.state.seatbelt` and `LocalPlayer.state.cruise` when possible. The Orbit addon does this automatically and also triggers the compatibility events DynamicHUD listens for.
# Installation (/docs/orbit-studios-resources/orbit-dynamichud)
# Installation [#installation]
`orbit-dynamichud` is Orbit Studios' interactive FiveM HUD with customizable status UI, speedometers, DynamicBar, car controls, music, notifications, commands, and state-bag integrations.
Start `orbit-lib` and `ox_lib` before `orbit-dynamichud`.
Use this page to install the base HUD. Seatbelt, cruise control, and stress are separate resources so you can decide whether to use the Orbit addons or wire in your own existing systems.
## File Structure [#file-structure]
## What You Edit [#what-you-edit]
The base HUD has several public config files. Start with these before touching custom integrations:
Use `shared/config.lua` for visible HUD features, update intervals, DynamicBar, and enabled status values. Use `settingsConfig.lua` for the default HUD preset a new player receives. Use `server/handlers.lua` only when you need to adapt money, death, inventory-open, or framework-specific state events.
## Installation [#installation-1]
```properties title="server.cfg"
ensure ox_lib
ensure [framework-resources]
ensure orbit-lib
ensure orbit-dynamichud
```
Install the optional addon resources after the base HUD:
```properties title="server.cfg"
ensure orbit-dynamichud-addons
ensure orbit-dynamichud-stress
```
After joining the server, use `/restarthud` once and confirm that health, armor, hunger, thirst, and vehicle UI values update before adding custom integrations.
## Framework Notes [#framework-notes]
ESX money updates are handled through `esx:setAccountMoney`. Death state can be set through ESX death and spawn handlers.
QB uses QBCore player-loaded, money-change, needs, and stress events.
QBX works through QB-style HUD events plus normalized player data from `orbit-lib`.
Use `Config.Framework = 'standalone'` in `orbit-lib`. DynamicHUD reads normalized player data from `orbit-lib`; configure standalone money/job adapters there when the default values are not enough.
# Interface (/docs/orbit-studios-resources/orbit-dynamichud/interface)
# Interface [#interface]
Interface integrations are UI features exposed through DynamicHUD or planned for DynamicHUD-style integration.
DynamicHUD notifications use the client event `orbit-dynamichud:notify`.
```lua title="resources/[custom]/client/notifications.lua"
TriggerEvent('orbit-dynamichud:notify', {
description = 'Vehicle locked',
type = 'success',
duration = 3000
})
```
Server scripts should send the notification to a specific player with `TriggerClientEvent`.
```lua title="resources/[custom]/server/main.lua"
TriggerClientEvent('orbit-dynamichud:notify', source, {
description = 'Welcome back',
type = 'info',
duration = 3000
})
```
When using `orbit-lib`, set `Config.Notify = 'orbit-dynamichud'` if you want supported Orbit resources to send notifications through DynamicHUD.
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Notify = 'orbit-dynamichud'
```
Replace `lib.notify` if you want every existing `lib.notify({...})` call to use DynamicHUD notifications without editing every resource.
Open `ox_lib/resource/interface/client/notify.lua`, find the client-side `lib.notify` function, and replace the function body with the DynamicHUD event.
```lua title="resources/[standalone]/ox_lib/resource/interface/client/notify.lua"
---`client`
---@param data NotifyProps
---@diagnostic disable-next-line: duplicate-set-field
function lib.notify(data)
TriggerEvent('orbit-dynamichud:notify', data)
end
```
After this, calls like `lib.notify({ description = 'Saved', type = 'success' })` are displayed through Orbit DynamicHUD.
Replace QBCore's notify helper if you want existing `QBCore.Functions.Notify(...)` calls to use DynamicHUD.
Open `qb-core/client/functions.lua`, find `QBCore.Functions.Notify`, and replace the whole function.
```lua title="resources/[qb]/qb-core/client/functions.lua"
function QBCore.Functions.Notify(text, texttype, length, icon)
local data = {}
if type(text) == "table" then
local ttext = text.text or "Placeholder"
local caption = text.caption or nil
local ttype = texttype or "primary"
local duration = length or 5000
data = {
title = caption,
description = ttext,
duration = duration,
type = ttype,
icon = icon
}
else
local ttype = texttype or "primary"
local duration = length or 5000
data = {
title = nil,
description = text,
duration = duration,
type = ttype,
icon = icon
}
end
TriggerEvent('orbit-dynamichud:notify', data)
end
```
This preserves both common QBCore notify styles: string messages and table messages with `text` and `caption`.
Replace `ESX.ShowNotification` if you want existing ESX scripts to use DynamicHUD notifications.
Open `es_extended/client/functions.lua`, find `ESX.ShowNotification`, and replace the whole function.
```lua title="resources/[esx]/es_extended/client/functions.lua"
---@param message string The message to show
---@param notifyType? string The type of notification to show
---@param length? number The length of the notification
---@param title? string The title of the notification
---@param position? string The position of the notification
---@return nil
function ESX.ShowNotification(message, notifyType, length, title, position)
local data = {
title = title or nil,
description = message,
duration = length or 5000,
type = notifyType or "info"
}
TriggerEvent('orbit-dynamichud:notify', data)
end
```
The `position` argument is kept in the function signature for compatibility, but DynamicHUD handles notification placement itself.
# Language Support (/docs/orbit-studios-resources/orbit-dynamichud/language-support)
# Language Support [#language-support]
`orbit-dynamichud` includes locale files in `resources/[orbit]/orbit-dynamichud/locales`.
## Available Locales [#available-locales]
| Locale | File |
| ------- | --------- |
| English | `en.json` |
| German | `de.json` |
| Spanish | `es.json` |
| French | `fr.json` |
| Swedish | `sv.json` |
| Turkish | `tr.json` |
## Set The Locale [#set-the-locale]
DynamicHUD uses `ox_lib` locale loading. Set the active locale in `server.cfg`.
```properties title="server.cfg"
setr ox:locale en
```
For Swedish:
```properties title="server.cfg"
setr ox:locale sv
```
## Edit Text [#edit-text]
Edit the matching JSON file when you want to change command names, HUD labels, onboarding text, control panel text, vehicle labels, or notification text.
```json title="resources/[orbit]/orbit-dynamichud/locales/en.json"
{
"commands": {
"restarthud": "restarthud"
}
}
```
If you rename command locale values, the in-game command names change too.
# Troubleshooting (/docs/orbit-studios-resources/orbit-dynamichud/troubleshooting)
# Troubleshooting [#troubleshooting]
Confirm `ox_lib`, framework resources, `orbit-lib`, and `orbit-dynamichud` start in that order. Then run `/restarthud` in-game. If the command works but the HUD disappears again, check whether another resource is calling `toggleHud(false)` or setting `Player(source).state["hud:showHud"]` to false.
Check the framework notes and make sure the matching ESX, QB, or QBX handlers are enabled in `server/handlers.lua`. QB/QBX needs `hud:client:OnMoneyChange` and `hud:client:UpdateNeeds` style events. ESX needs account and status events such as `esx:setAccountMoney` and `esx_status:onTick`.
Install and start `orbit-dynamichud-stress`, then enable the stress value in `shared/config.lua`. Confirm `LocalPlayer.state.stress` has a number in client debug code, and test `/setstress 25` if the command is enabled.
Install `orbit-dynamichud-addons` or make your own vehicle resource set the same state bags/events expected by DynamicHUD. The Orbit addon sets `LocalPlayer.state.seatbelt` and `LocalPlayer.state.cruise` and triggers the compatibility toggle events.
Trigger `orbit-dynamichud:notify` from your wrapper, or set `orbit-lib` notification config to use DynamicHUD. The event is client-side, so server scripts should use `TriggerClientEvent('orbit-dynamichud:notify', source, data)`.
# Configuration (/docs/orbit-studios-resources/orbit-dynamichud-addons/configuration)
# Configuration [#configuration]
All public configuration lives in `resources/[orbit]/orbit-dynamichud-addons/config.lua`.
This resource is client-heavy. Most settings affect how the local player toggles seatbelt or cruise control, what DynamicHUD receives through state bags, and when GTA's windscreen ejection behavior is allowed.
```lua title="resources/[orbit]/orbit-dynamichud-addons/config.lua"
Config.Seatbelt = {
enable = true,
keybind = 'B',
useMPH = false,
minSpeedUnbuckled = 20.0,
minSpeedBuckled = 160.0,
harness = {
disableFlyingThroughWindscreen = true,
minSpeed = 200.0
}
}
```
`useMPH` changes how `minSpeedUnbuckled`, `minSpeedBuckled`, and harness speed values are interpreted. Set it to `true` only when you want those thresholds written as miles per hour.
`harness.disableFlyingThroughWindscreen = true` prevents windscreen ejection while a harness is active. If you set it to `false`, `harness.minSpeed` becomes the ejection threshold while harnessed.
```lua title="resources/[orbit]/orbit-dynamichud-addons/config.lua"
Config.Cruise = {
enable = true,
keybind = 'Y'
}
```
Cruise can only enable when the player is driving, the vehicle is moving forward, and the vehicle class is supported by the client script.
```lua title="resources/[orbit]/orbit-dynamichud-addons/config.lua"
Config.Notify = function(message, type)
TriggerEvent("orbit-dynamichud:notify", {
description = message,
type = type or 'info',
duration = 3000
})
end
```
Replace this function if you do not use DynamicHUD notifications. Keep it client-side and keep the `(message, type)` parameters so the seatbelt and cruise scripts can call it normally.
## Locales [#locales]
The addon uses `ox_lib` locales. Set the locale in `server.cfg`, then edit the matching JSON file if you want different labels or messages.
```properties title="server.cfg"
setr ox:locale en
```
```json title="resources/[orbit]/orbit-dynamichud-addons/locales/en.json"
{
"actions": {
"toggle_cruise_control": "Toggle Cruise Control"
},
"success": {
"cruise_control_enabled": "Cruise control enabled"
},
"error": {
"cruise_control_disabled": "Cruise control disabled",
"cruise_control_unavailable": "Cruise control is not available for this vehicle"
},
"seatbelt_desc": "Toggle Seatbelt"
}
```
# Dependencies (/docs/orbit-studios-resources/orbit-dynamichud-addons/dependencies)
# Dependencies [#dependencies]
`orbit-dynamichud-addons` provides seatbelt and cruise-control behavior for DynamicHUD. Source and releases are available on [GitHub](https://github.com/orbitstudiossoftware/orbit-dynamichud-addons).
## Required [#required]
| Dependency | Why it is needed | Link |
| ------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `ox_lib` | Loads `@ox_lib/init.lua`, keybind helpers, cache helpers, and locale helpers. | [overextended/ox\_lib](https://github.com/overextended/ox_lib) |
| `orbit-dynamichud` | Receives seatbelt/cruise state through events and state bags. | [orbit-dynamichud](/docs/orbit-studios-resources/orbit-dynamichud) |
## Optional [#optional]
| Dependency | What it adds | Link |
| ----------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `orbit-lib` | Recommended when the rest of your Orbit stack uses shared notifications and framework bridging. | [orbit-lib](/docs/orbit-studios-resources/orbit-lib) |
| Custom harness resource | Can set `LocalPlayer.state.harness` for harness compatibility. | Custom resource |
## Start Order [#start-order]
```properties title="server.cfg"
ensure ox_lib
ensure orbit-lib
ensure orbit-dynamichud
ensure orbit-dynamichud-addons
```
If you do not use `orbit-lib` for this addon, keep `ox_lib` and `orbit-dynamichud` before `orbit-dynamichud-addons`.
# Exports and Events (/docs/orbit-studios-resources/orbit-dynamichud-addons/exports-and-events)
# Exports and Events [#exports-and-events]
The addon communicates through local player state bags and local client events. DynamicHUD reads the same state values, so custom resources can use them too.
## Read Current State [#read-current-state]
```lua title="resources/[custom]/client/main.lua"
local seatbeltOn = LocalPlayer.state.seatbelt == true
local cruiseOn = LocalPlayer.state.cruise == true
local harnessOn = LocalPlayer.state.harness == true
```
State bag values are local booleans. They can be `nil` before the player enters a vehicle, so compare with `== true` when you need a strict boolean.
## Listen For Toggles [#listen-for-toggles]
```lua title="resources/[custom]/client/seatbelt-listener.lua"
AddEventHandler('seatbelt:client:ToggleSeatbelt', function()
local seatbeltOn = LocalPlayer.state.seatbelt == true
end)
```
```lua title="resources/[custom]/client/cruise-listener.lua"
AddEventHandler('seatbelt:client:ToggleCruise', function()
local cruiseOn = LocalPlayer.state.cruise == true
end)
```
## Harness Compatibility [#harness-compatibility]
`HasHarness()` is kept for older integrations, but new code should read the state bag directly.
```lua title="resources/[custom]/client/harness.lua"
local hasHarness = exports['orbit-dynamichud-addons']:HasHarness()
```
```lua title="resources/[custom]/client/harness.lua"
LocalPlayer.state.harness = true
```
# Installation (/docs/orbit-studios-resources/orbit-dynamichud-addons)
# Installation [#installation]
`orbit-dynamichud-addons` is a standalone seatbelt and cruise control resource adapted for `orbit-dynamichud`. It uses `ox_lib` keybinds, locale files, DynamicHUD notifications, and client state bags.
This addon is adapted from QBX GPL resources and is provided as-is. Keep the GPL attribution and license with the resource if you redistribute or modify it.
Install this resource when you want Orbit's seatbelt and cruise-control states to feed directly into DynamicHUD. If your server already has seatbelt or cruise control, you can skip this addon and instead make your existing resource set the same state bags described in the exports page.
## File Structure [#file-structure]
## What You Edit [#what-you-edit]
Most configuration lives in `resources/[orbit]/orbit-dynamichud-addons/config.lua`. This is where you change keybinds, enable or disable cruise and seatbelt behavior, adjust crash thresholds, and replace the notification function if you do not want to use `orbit-dynamichud:notify`.
## Installation [#installation-1]
```properties title="server.cfg"
ensure ox_lib
ensure orbit-lib
ensure orbit-dynamichud
ensure orbit-dynamichud-addons
```
After installing, sit in the driver seat and toggle the seatbelt key once. DynamicHUD should react to `LocalPlayer.state.seatbelt`. Then start driving forward and test the cruise key from the driver seat.
## Framework Notes [#framework-notes]
The addon is framework-light. Keep the DynamicHUD notification bridge or replace it with your ESX notification wrapper.
The addon is isolated from QB/QBX core requirements. If you use a custom harness system, update `LocalPlayer.state.harness`.
The source is adapted from QBX seatbelt and cruise resources, but normal QBX startup requirements were removed.
The addon does not require framework player data. Keep `ox_lib` started before it and use `Config.Notify` if you need to replace the DynamicHUD notification event.
# Language Support (/docs/orbit-studios-resources/orbit-dynamichud-addons/language-support)
# Language Support [#language-support]
`orbit-dynamichud-addons` includes locale files in `resources/[orbit]/orbit-dynamichud-addons/locales`.
## Available Locales [#available-locales]
| Locale | File |
| ------- | --------- |
| English | `en.json` |
| German | `de.json` |
| Spanish | `es.json` |
| French | `fr.json` |
| Swedish | `sv.json` |
| Turkish | `tr.json` |
## Set The Locale [#set-the-locale]
Set the active `ox_lib` locale in `server.cfg`.
```properties title="server.cfg"
setr ox:locale en
```
For Turkish:
```properties title="server.cfg"
setr ox:locale tr
```
## Edit Text [#edit-text]
Edit the matching JSON file to change seatbelt, cruise-control, keybind, success, and error messages.
```json title="resources/[orbit]/orbit-dynamichud-addons/locales/en.json"
{
"actions": {
"toggle_cruise_control": "Toggle Cruise Control"
}
}
```
# Troubleshooting (/docs/orbit-studios-resources/orbit-dynamichud-addons/troubleshooting)
# Troubleshooting [#troubleshooting]
Confirm `ox_lib` starts before the addon and restart the client after changing default keys. FiveM stores keybind choices per client, so changing `Config.Seatbelt.keybind` or `Config.Cruise.keybind` only changes the default for players who have not overridden it.
Confirm `orbit-dynamichud-addons` starts after `orbit-dynamichud`, then inspect `LocalPlayer.state.seatbelt` and `LocalPlayer.state.cruise`. If those values change but the HUD does not, check the DynamicHUD seatbelt and cruise compatibility events.
Cruise only enables from the driver seat, while the vehicle is moving forward, and only for supported vehicle classes. It also disables when the driver leaves the seat, the vehicle disappears, the gear is not forward, or `Config.Cruise.enable` is false.
Replace `Config.Notify` with your own client notification export or event if you are not using the default DynamicHUD notification event. Keep the function signature as `function(message, type)` so cruise and seatbelt code can call it without changes.
# Configuration (/docs/orbit-studios-resources/orbit-dynamichud-stress/configuration)
# Configuration [#configuration]
All public stress behavior lives in `resources/[orbit]/orbit-dynamichud-stress/config.lua`.
Stress is stored from `0` to `100`. The client can add stress from speeding and weapon usage, while server events can add or remove stress from other integrations.
```lua title="resources/[orbit]/orbit-dynamichud-stress/config.lua"
Config.Stress.stressSpeedFormat = 'kmh'
Config.Stress.minForSpeeding = 1000
Config.Stress.minForSpeedingUnbuckled = 50
```
`stressSpeedFormat` decides whether the thresholds are read as KMH or MPH. `minForSpeeding` is used while the player is buckled, and `minForSpeedingUnbuckled` is used while unbuckled. The default buckled value is very high, which effectively makes normal buckled speeding much less likely to add stress.
```lua title="resources/[orbit]/orbit-dynamichud-stress/config.lua"
Config.Stress.chance = 0.1
Config.Stress.whitelistedWeapons = {
`weapon_petrolcan`,
`weapon_hazardcan`,
`weapon_fireextinguisher`,
}
```
`chance` is a decimal chance from `0` to `1`. For example, `0.1` means a 10 percent chance per eligible shot. Weapons in `whitelistedWeapons` never add weapon stress.
```lua title="resources/[orbit]/orbit-dynamichud-stress/config.lua"
Config.Stress.minForShaking = 50
Config.Stress.blurIntensity = {
[1] = { min = 50, max = 60, intensity = 1500 },
[2] = { min = 60, max = 70, intensity = 2000 },
[3] = { min = 70, max = 80, intensity = 2500 },
[4] = { min = 80, max = 90, intensity = 2700 },
[5] = { min = 90, max = 100, intensity = 3000 },
}
```
`minForShaking` is the first stress value where effects can run. Each `blurIntensity` range controls how strong blur can be for that stress band. Each matching `effectInterval` range controls how often the effect can repeat.
```lua title="resources/[orbit]/orbit-dynamichud-stress/config.lua"
Config.Stress.whitelistedJobs = {
'police'
}
```
Whitelisted jobs skip server-side stress gain from `hud:server:GainStress`. They can still have their state changed directly by custom code that writes to `Player(source).state.stress`.
## Framework Notes [#framework-notes]
Whitelisted jobs should match the ESX job names returned by `orbit-lib`.
Whitelisted jobs should match `PlayerData.job.name`.
The stress logic is adapted from the QBX HUD stress system and keeps the same state-bag style integration.
Whitelisted jobs are based on the job data returned by `Config.Standalone.fetchJob` in `orbit-lib`, or the `Config.Standalone.defaultJob` fallback.
# Dependencies (/docs/orbit-studios-resources/orbit-dynamichud-stress/dependencies)
# Dependencies [#dependencies]
`orbit-dynamichud-stress` manages the replicated stress state used by DynamicHUD. Source and releases are available on [GitHub](https://github.com/orbitstudiossoftware/orbit-dynamichud-stress).
## Required [#required]
| Dependency | Why it is needed | Link |
| ------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `ox_lib` | Loads `@ox_lib/init.lua` and cache helpers used by the client-side stress logic. | [overextended/ox\_lib](https://github.com/overextended/ox_lib) |
| `orbit-lib` | Provides normalized player/job data so whitelisted jobs and framework data work consistently. | [orbit-lib](/docs/orbit-studios-resources/orbit-lib) |
| `orbit-dynamichud` | Displays the stress value and reacts to the replicated `stress` state. | [orbit-dynamichud](/docs/orbit-studios-resources/orbit-dynamichud) |
## Optional [#optional]
| Dependency | What it adds | Link |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `orbit-dynamichud-addons` | Provides `LocalPlayer.state.seatbelt`, which the stress resource uses to choose buckled or unbuckled speeding thresholds. | [Docs](/docs/orbit-studios-resources/orbit-dynamichud-addons) / [GitHub](https://github.com/orbitstudiossoftware/orbit-dynamichud-addons) |
| Inventory usable items | Lets consumable items reduce stress through the stress relief item examples. | [Stress relief items](/docs/orbit-studios-resources/orbit-dynamichud-stress/stress-relief-items) |
## Start Order [#start-order]
```properties title="server.cfg"
ensure ox_lib
ensure [framework-resources]
ensure orbit-lib
ensure orbit-dynamichud
ensure orbit-dynamichud-addons
ensure orbit-dynamichud-stress
```
`orbit-dynamichud-addons` is optional, but without a seatbelt state provider the stress resource cannot know whether the player is buckled.
# Events (/docs/orbit-studios-resources/orbit-dynamichud-stress/events)
# Events [#events]
Stress is stored as a replicated state bag value from 0 to 100.
Use the server events when you want the stress resource to handle clamping and whitelist checks. Read the state bag when you only need to display or react to the current value.
```lua title="resources/[custom]/client/main.lua"
local stress = LocalPlayer.state.stress or 0
```
```lua title="resources/[custom]/server/main.lua"
local src = source
local stress = Player(src)?.state?.stress or 0
Player(src)?.state:set("stress", 25, true)
```
## Client Integration [#client-integration]
```lua title="resources/[custom]/client/main.lua"
TriggerServerEvent('hud:server:GainStress', 10)
TriggerServerEvent('hud:server:RelieveStress', 15)
```
Use client triggers for gameplay actions that happen locally, such as a minigame failure, consuming an item, or a custom vehicle script detecting stressful behavior.
## Server-Side Admin Or Script Integration [#server-side-admin-or-script-integration]
```lua title="resources/[custom]/server/main.lua"
local src = 12
local stress = math.max(0, math.min(100, 25))
Player(src)?.state:set("stress", stress, true)
```
Use direct state writes when server code already knows the target player ID, such as an admin command or another server-only system. Clamp the value yourself so it stays between `0` and `100`.
`hud:server:GainStress` clamps at `100`. `hud:server:RelieveStress` clamps at `0`. `hud:server:GainStress` also checks `Config.Stress.whitelistedJobs`.
# Installation (/docs/orbit-studios-resources/orbit-dynamichud-stress)
# Installation [#installation]
`orbit-dynamichud-stress` adds the stress state used by `orbit-dynamichud`. It can increase stress from speeding and weapon usage, reduce stress from custom integrations, and apply blur or ragdoll effects at high stress levels.
Start `ox_lib`, `orbit-lib`, and `orbit-dynamichud` before `orbit-dynamichud-stress`.
Use this resource when you want DynamicHUD to manage stress as a replicated player state value. Other resources can read `LocalPlayer.state.stress` on the client or `Player(source).state.stress` on the server.
## File Structure [#file-structure]
## What You Edit [#what-you-edit]
Only the public `config.lua` is needed for normal setup:
Use it to change stress gain chance, speeding thresholds, whitelisted jobs, blur strength, ragdoll timing, and weapon exclusions. Use the stress relief items page when you want cigarettes, consumables, or other inventory items to reduce stress.
## Installation [#installation-1]
```properties title="server.cfg"
ensure ox_lib
ensure [framework-resources]
ensure orbit-lib
ensure orbit-dynamichud
ensure orbit-dynamichud-addons
ensure orbit-dynamichud-stress
```
`orbit-dynamichud-stress` reads `LocalPlayer.state.seatbelt` when deciding whether to use the buckled or unbuckled speeding threshold.
If you do not use `orbit-dynamichud-addons`, your own seatbelt resource should set `LocalPlayer.state.seatbelt` to `true` or `false`. Without that state, the stress resource cannot know whether the player is buckled.
# Stress Relief Items (/docs/orbit-studios-resources/orbit-dynamichud-stress/stress-relief-items)
# Stress Relief Items [#stress-relief-items]
Stress relief items lower the replicated `stress` state value that DynamicHUD reads. The examples below show where the item logic belongs for each inventory or framework style.
The `ox_inventory` example uses the same server-side item export pattern as the GitBook docs. Put the export in `ox_inventory/modules/items/server.lua`, not in a custom client export.
Add the item handler in `ox_inventory/modules/items/server.lua`:
```lua title="ox_inventory/modules/items/server.lua"
exports('cigarette', function(event, item, inventory, slot, data)
local src = inventory.id
-- Player is attempting to use the item
if event == 'usingItem' then
local currentStress = Player(src)?.state?.stress or 0
local relief = math.random(5, 10)
local newStress = math.max(currentStress - relief, 0)
Player(src)?.state:set("stress", newStress, true)
end
-- Player finished using the item
if event == 'usedItem' then
TriggerClientEvent('ox_lib:notify', src, {
description = 'You feel better already'
})
end
end)
```
Then define the usable item in `ox_inventory/data/items.lua`:
```lua title="ox_inventory/data/items.lua"
cigarette = {
label = "Cigarette",
weight = 10,
stack = true,
consume = 1
}
```
`usingItem` runs when the player starts using the item. The handler reads the current stress state, removes a random amount from 5 to 10, clamps the result so it never goes below 0, and replicates the new value with `Player(src)?.state:set("stress", newStress, true)`.
`usedItem` runs after the item finishes consuming. The GitBook implementation uses this event to show an `ox_lib` notification.
To change the relief amount, only change the `relief` line:
```lua title="ox_inventory/modules/items/server.lua"
local relief = 10
```
```lua title="ox_inventory/modules/items/server.lua"
local relief = math.random(5, 10)
```
```lua title="ox_inventory/modules/items/server.lua"
local relief = math.random(20, 30)
```
Use this pattern when your server uses QBCore usable items instead of `ox_inventory` item exports. Put the server callback in any started server resource, then trigger the stress resource server event with the amount you want to remove.
```lua title="resources/[custom]/server/main.lua"
QBCore.Functions.CreateUseableItem('stress_relief', function(source)
TriggerClientEvent('my_resource:client:relieveStress', source, 20)
end)
```
```lua title="resources/[custom]/client/main.lua"
RegisterNetEvent('my_resource:client:relieveStress', function(amount)
TriggerServerEvent('hud:server:RelieveStress', amount)
end)
```
Add the item to your QB inventory item list using the same item name, `stress_relief`. If the inventory item name does not match the usable item name, the callback will never run.
Use this pattern when your server uses ESX usable items. The ESX callback runs on the server, sends a small client event to the player, and the client asks the stress addon to remove stress.
```lua title="resources/[custom]/server/main.lua"
ESX.RegisterUsableItem('stress_relief', function(source)
TriggerClientEvent('my_resource:client:relieveStress', source, 20)
end)
```
```lua title="resources/[custom]/client/main.lua"
RegisterNetEvent('my_resource:client:relieveStress', function(amount)
TriggerServerEvent('hud:server:RelieveStress', amount)
end)
```
Add the `stress_relief` item to your ESX inventory or item database before testing the usable item callback.
# Troubleshooting (/docs/orbit-studios-resources/orbit-dynamichud-stress/troubleshooting)
# Troubleshooting [#troubleshooting]
Confirm `orbit-dynamichud` starts before the stress addon and that `Config.EnabledValues.stress` is enabled in the HUD config. Then check that `LocalPlayer.state.stress` becomes a number after joining the server. If it stays nil, the stress resource is not initializing the player state.
Match `Config.Stress.stressSpeedFormat` to the unit you used for thresholds, then check whether your seatbelt resource sets `LocalPlayer.state.seatbelt`. When that state is false or missing, the resource uses `Config.Stress.minForSpeedingUnbuckled`.
Check that the job name in `Config.Stress.whitelistedJobs` exactly matches the job name returned by `orbit-lib`. The whitelist only affects `hud:server:GainStress`; custom scripts that set `Player(source).state.stress` directly bypass the whitelist.
Increase `Config.Stress.effectInterval` timeouts or reduce `Config.Stress.blurIntensity` values for the affected stress ranges. Change one stress range at a time, restart the resource, and test with `/setstress` so you know which range feels wrong.
# Configuration (/docs/orbit-studios-resources/orbit-lib/configuration)
# Configuration [#configuration]
Edit `resources/[orbit]/orbit-lib/config.lua`.
`orbit-lib` is the bridge layer. Other Orbit resources call it when they need player data, inventory actions, item counts, notifications, progress bars, and framework-specific helpers. If a value here points at the wrong framework or resource name, the dependent resource usually fails later with missing exports, missing items, or empty player data.
## Framework Presets [#framework-presets]
Pick one framework preset first, then adjust the target, inventory, notification, and progress providers to match the resources actually started on your server.
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Framework = 'esx'
Config.TargetResource = 'ox_target'
Config.Inventory = 'ox_inventory'
Config.Notify = 'ox_lib'
Config.Progress = 'ox_lib'
```
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Framework = 'qb'
Config.TargetResource = 'qb-target'
Config.Inventory = 'qb-inventory'
Config.Notify = 'framework'
Config.Progress = 'framework'
```
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Framework = 'qbx'
Config.TargetResource = 'ox_target'
Config.Inventory = 'ox_inventory'
Config.Notify = 'ox_lib'
Config.Progress = 'ox_lib'
```
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Framework = 'standalone'
Config.TargetResource = 'ox_target'
Config.Inventory = 'ox_inventory'
Config.Notify = 'ox_lib'
Config.Progress = 'ox_lib'
Config.Standalone = {
identifierType = 'license',
playerDataCache = 1000,
defaultMoney = {
cash = 0,
bank = 0,
dirty = 0
},
defaultJob = {
name = 'unemployed',
label = 'Unemployed',
grade = {
name = 'Unemployed',
level = 0
}
},
fetchName = nil,
fetchCharInfo = nil,
fetchMoney = nil,
fetchJob = nil,
createUsableItem = nil
}
```
## Supported Providers [#supported-providers]
These are the supported values from `config.lua`. Use the exact lowercase key in the config, not the display name.
| Config value | Use when |
| ------------ | --------------------------------------------------------------------------------- |
| `esx` | Your server runs ESX Legacy or another ESX-compatible setup. |
| `qb` | Your server runs QBCore and exposes QB-style player data. |
| `qbx` | Your server runs QBX/Qbox and uses QB-style data with modern Qbox resources. |
| `standalone` | You do not use ESX, QB, or QBX and will provide standalone adapters where needed. |
Framework selection controls how `orbit-lib` reads player identifiers, names, character info, money, jobs, gangs, and usable-item behavior.
| Config value | Resource | GitHub |
| ------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `ox_target` | Overextended target system for entity, zone, and world interactions. | [overextended/ox\_target](https://github.com/overextended/ox_target) |
| `qb-target` | QBCore target interaction system. | [qbcore-framework/qb-target](https://github.com/qbcore-framework/qb-target) |
Target resources are used when Orbit resources create interaction points, such as crafting stations.
| Config value | Resource or mode | GitHub |
| -------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `ox_inventory` | Overextended inventory. Recommended for OX/QBX style servers. | [overextended/ox\_inventory](https://github.com/overextended/ox_inventory) |
| `qb-inventory` | Official QBCore inventory. | [qbcore-framework/qb-inventory](https://github.com/qbcore-framework/qb-inventory) |
| `ps-inventory` | Project Sloth inventory. | [Project-Sloth/ps-inventory](https://github.com/Project-Sloth/ps-inventory) |
| `lj-inventory` | LJ inventory. | [loljoshie/lj-inventory](https://github.com/loljoshie/lj-inventory) |
| `qb-like` | Custom inventory with QB-style exports. | Custom resource |
| `ox-like` | Custom inventory with OX-style exports. | Custom resource |
Inventory support is used for item counts, adding/removing items, metadata, image paths, and usable-item behavior. For `qb-like` or `ox-like`, set `Config.CustomInventory` to the actual resource name and `Config.CustomExport` only when the export name differs from the resource name.
| Config value | Provider | Use when |
| ------------------ | --------------------------------------- | --------------------------------------------------------------------------------------------- |
| `framework` | ESX/QB/QBX native notification wrapper. | You want Orbit resources to use your framework's normal notification behavior. |
| `ox_lib` | `lib.notify`. | You have `ox_lib` installed and want consistent ox\_lib notifications. |
| `orbit-dynamichud` | DynamicHUD notification event. | You have `orbit-dynamichud` installed and want notifications shown through the HUD interface. |
Do not use `orbit-dynamichud` as the notification provider unless `orbit-dynamichud` is installed and started after `orbit-lib`.
| Config value | Provider | Use when |
| ------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------- |
| `framework` | ESX/QB/QBX progress wrapper. | Your framework already provides a progress bar you want Orbit resources to use. |
| `ox_lib` | `lib.progressBar` / `lib.progressCircle`. | You want progress handled by `ox_lib`. |
| `orbit-dynamichud` | DynamicHUD interface integration. | You want Orbit resources to integrate progress UI through DynamicHUD where supported. |
## Provider Rules [#provider-rules]
Use real resource names and supported provider keys:
Do not set a provider to a resource that is not running. For example, `Config.Notify = 'orbit-dynamichud'` only makes sense when `orbit-dynamichud` is installed and started after `orbit-lib`.
## Standalone Adapters [#standalone-adapters]
Standalone mode uses defaults until you provide adapters.
The default standalone data is useful for testing, but production standalone servers usually need at least money and job adapters so HUDs, access checks, and logs show real values.
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Standalone.fetchMoney = function(source, playerState, defaults)
return {
cash = defaults.cash,
bank = defaults.bank,
dirty = defaults.dirty
}
end
```
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Standalone.fetchJob = function(source, playerState, defaults)
return {
name = defaults.name,
label = defaults.label,
grade = defaults.grade
}
end
```
If you use standalone mode with a custom inventory, implement `createUsableItem` only when another Orbit resource needs usable-item registration and your inventory does not already provide a native framework callback.
## Custom Inventory [#custom-inventory]
Use this only when the inventory follows a QB-like or OX-like export shape but runs under a custom resource name.
```lua title="resources/[orbit]/orbit-lib/config.lua"
Config.Inventory = 'qb-like'
Config.CustomInventory = 'my_inventory'
Config.CustomExport = 'my_inventory'
```
Set `Config.CustomExport` only when the export name is different from the resource name.
# Installation (/docs/orbit-studios-resources/orbit-lib)
# Installation [#installation]
`orbit-lib` is the required bridge library for Orbit Studios resources. It connects Orbit resources to your framework, target system, inventory, notifications, progress provider, and optional gang data.
`orbit-lib` is escrowed. Only document and edit `config.lua`.
Use this page as the setup checklist before installing any other Orbit Studios resource. If `orbit-lib` is not configured first, later resources can start successfully but still fail when they try to read player data, open targets, register usable items, or send notifications.
## File Structure [#file-structure]
## What You Edit [#what-you-edit]
Only edit `resources/[orbit]/orbit-lib/config.lua`. Do not rename the resource folder, move internal files, or edit escrowed files. The public config decides which framework adapter is used and which installed resources should handle target zones, inventory actions, notifications, and progress bars.
## Start Order [#start-order]
```properties title="server.cfg"
ensure ox_lib
ensure [framework-resources]
ensure [inventory]
ensure [target]
ensure orbit-lib
# Other Orbit Studios resources start after orbit-lib.
ensure orbit-dynamichud
ensure orbit-craftingsystem
```
Start `orbit-lib` after the resources it bridges to, then start the Orbit resource that depends on it. For example, if `Config.TargetResource = 'ox_target'`, `ox_target` must start before `orbit-lib`.
## Framework Selector [#framework-selector]
Use the same selector pattern across Orbit docs.
Set `Config.Framework = 'esx'`. Use ESX job names, ESX account names, and an ESX-compatible inventory bridge.
Set `Config.Framework = 'qb'`. Use QBCore job/gang names and QB-compatible inventory, target, and notification resources.
Set `Config.Framework = 'qbx'`. QBX servers usually pair `ox_inventory`, `ox_target`, and `ox_lib` with Orbit resources.
Set `Config.Framework = 'standalone'`. Configure `Config.Standalone` adapters when you need custom names, money, jobs, character info, or usable-item behavior without ESX/QB/QBX.
# Troubleshooting (/docs/orbit-studios-resources/orbit-lib/troubleshooting)
# Troubleshooting [#troubleshooting]
Confirm `orbit-lib` starts after framework, inventory, target, and `ox_lib` dependencies, and before other Orbit resources. Then check that `Config.Framework`, `Config.Inventory`, and `Config.TargetResource` match the resources actually running on the server. A typo here can make downstream resources fail even when `orbit-lib` itself starts.
Check `Config.TargetResource` and make sure the selected target resource is started before `orbit-lib`. If you changed from `qb-target` to `ox_target`, update the config and restart `orbit-lib` plus the resource that creates the interaction zones.
Match `Config.Inventory`, `Config.CustomInventory`, and `Config.CustomExport` to the resource and export names that are actually running. Use built-in adapters like `ox_inventory` or `qb-inventory` where possible. Use `qb-like` or `ox-like` only when the custom inventory exposes compatible exports.
Set `Config.Notify` and `Config.Progress` to a provider installed on the server. Use `ox_lib` or `orbit-dynamichud` only when those resources are running. If `orbit-dynamichud` is selected for notifications, confirm the HUD starts after `orbit-lib`.
Confirm `Config.Framework` matches the live framework and that job/gang names in dependent resources match the framework data. Standalone servers should configure `Config.Standalone.fetchJob` when access rules need real job data instead of the default unemployed job.