How Integrations Work#
Crutches talks to your framework, your inventory and your notification system through a few small bridges. The framework is detected on start by looking for a running resource, so there is nothing to set by hand.
Layer | Supported | Without it |
|---|---|---|
Framework |
| Required. The item, the EMS menu and saving do not work. |
Inventory | Any inventory that honours your framework's usable items — qs-inventory, ox_inventory, qb-inventory, the ESX default. | The item cannot be used. EMS and exports still work. |
Menu and dialogs |
| Required. The resource does not start. |
Database |
| Required. Prescriptions cannot be saved or restored. |
Notifications |
| Falls back to the next one in line. |
Discord | Any Discord webhook | No logs are sent. |
Qbox is supported through its
qb-corecompatibility, whichqbx_coreprovides out of the box. Characters are identified byidentifieron ESX and bycitizenidon QBCore and Qbox, so prescriptions follow the character, not the Rockstar account.
The Files You Can Edit#
Most of qs-crutches is encrypted. These files are left open on purpose, so you can adapt it to your server:
File | Contents |
|---|---|
| Language, jobs, duration, model, walk, pickup animation, prop position, debug. |
| Every message players see, per language. |
| How notifications are shown, and how the dropped crutch is picked up. |
| When the client asks the server for its saved crutch state. |
| The Discord webhook and the look of the log embed. |
Notifications#
Every message goes through one function, Notification(msg, notifyType) in client/custom/custom.lua. It uses qs-interface if it is running, otherwise ox_lib, otherwise the native GTA feed. The type is one of success, error, warning or inform.
To use a different notification resource, replace the body of the function:
-- client/custom/custom.lua
function Notification(msg, notifyType)
notifyType = notifyType or 'inform'
exports['okokNotify']:Alert('Crutches', msg, 5000, notifyType == 'inform' and 'info' or notifyType)
endThe EMS menu's own "no nearby player" and "invalid ID" warnings are ox_lib notifications and do not pass through this function.
Discord Logs#
Every time crutches are applied or removed — except a manual crutch — an embed can be posted to a Discord channel. Paste your webhook URL in server/webhook.lua:
Webhook.URL = 'https://discord.com/api/webhooks/...' -- empty = no logs
Webhook.Name = 'Crutches' -- the webhook's display name
Webhook.Avatar = '' -- an image URL for its avatar
Webhook.Color = 16753920 -- the embed colour, as a decimal
Webhook.IncludeIdentifiers = true -- add license, steam, fivem and discord IDsAction | Logged when |
|---|---|
| A player uses the crutch item. |
| A paramedic applies crutches from the menu. |
| A paramedic removes crutches from the menu. |
| Another script calls |
| Another script calls |
Each embed shows the action, the minutes, the reason, who gave it and to whom (name and server ID), the time in UTC and, with IncludeIdentifiers, both players' identifiers. Expiry is not logged.
Character Loading#
A player's saved crutches are restored when their character loads. The script listens for esx:playerLoaded on ESX and QBCore:Client:OnPlayerLoaded on QBCore and Qbox, and checks once more a few seconds after the player spawns.
If your multicharacter or spawn selector loads the character later than that, ask for the state again once the player is in the world:
-- client/custom/framework/esx.lua (or qb.lua)
RegisterNetEvent('my-multichar:client:spawned', function()
Wait(500)
TriggerServerEvent('crutch:server:syncState')
end)The Crutch Prop#
The prop is v_med_crutch01, streamed by the crutches resource. To use another model, set Config.CrutchModel and adjust Config.Attach until it sits right in the hand:
Field | Meaning |
|---|---|
|
|
| The bone the crutch is attached to. |
| Offset from that bone, in metres. |
| Rotation from that bone, in degrees. |
The pickup prompt, its key (E) and its reach (2.2 metres) live in startPickupThread in client/custom/custom.lua, if you want the crutch picked up some other way — through a target, for instance.
Languages#
29 translations ship in locales/. Pick one with Config.Language:
Config.Language = 'en'
-- ar · bg · ca · cs · da · de · el · en · es · fa · fr · he · hi · hu · it
-- jp · ko · nl · no · pl · pt · ro · ru · sl · sv · th · tk · tr · zh-CNA code with no file behind it falls back to English. To add a language, copy locales/en.lua to a new file, change Locales["en"] to your code, translate the text and set Config.Language to it. Keep the %d and %s placeholders — they are where the minutes, IDs and reasons go.



