Developer API
← README · Install · Configuration · FAQ
Exports
Server
lua
local inMatch = exports['lumo-battleroyale']:IsInMatch(source) -- boolean
local m = exports['lumo-battleroyale']:GetMatch(source)
-- nil, or { id = 3, mode = 'squad', map = 'paleto', state = 'live', alive = true, kills = 4 }
-- state: 'warmup' | 'live' (aircraft and fight) | 'ended' (results screen)Client
lua
local inMatch = exports['lumo-battleroyale']:IsInMatch() -- boolean
exports['lumo-battleroyale']:OpenLobby() -- open the lobby panel (e.g. from your own menu or ped)Server events
lua
AddEventHandler('lumo-battleroyale:server:matchStarted', function(matchId, roster)
-- roster = { { src = 12, name = 'John Doe', team = 1 }, … } (players only, no bots)
end)
AddEventHandler('lumo-battleroyale:server:matchEnded', function(matchId, winner)
-- winner = the winning team's label, or nil (time limit / ended by an admin)
end)These are local server events, so they can't be triggered from a client.
State bags
| Bag | On | Value |
|---|---|---|
lumoBR | player | the match id while the player is in a match |
lumoBR_alive | player | true while still in the fight |
lumoBR_knocked | player | true while knocked (Duo/Squad) |
lumo_quiet | player | true for the whole match, cleared a few seconds after the player is home |
Keeping your other scripts quiet during a match
A match is a separate game. City HUDs, phone notifications, dispatch alerts, evidence (casings, GSR) and wound systems shouldn't react to it. Lumo's own resources already check lumo_quiet. For anything else, add one line at the top of the function that alerts, notifies or records:
lua
-- client
if LocalPlayer.state.lumo_quiet then return end
-- server
if Player(source).state.lumo_quiet then return endTypical places: a dispatch script's "shots fired" trigger, an evidence script's casing drop, a medical script's damage handler, and a phone's notification handler.
The wanted level is held at 0 during a match and restored afterwards. Weather sync scripts are paused (see below).
The framework layer (framework/)
Every call into a framework, inventory, target, medical or key script lives in framework/client.lua and framework/server.lua. Both files stay readable in the escrow edition, so you can adapt the resource to a custom or renamed core without touching the rest.
Server (FW.*)
| Function | Purpose |
|---|---|
FW.name | 'qbx', 'qb', 'esx' or 'standalone' |
FW.getIdentifier(src) | stable id for stats (citizenid / identifier / licence) |
FW.getName(src) | character name, falling back to the FiveM name |
FW.hasMoney(), FW.getMoney, FW.addMoney, FW.removeMoney | rewards |
FW.addItem(src, item, amount) | item rewards (ox_inventory first, else the framework) |
FW.isAdmin(src) | Config.Admin.permissions groups or the ACE |
FW.notify(src, msg, kind) | notification on that client |
FW.matchJoin(src) / FW.matchLeave(src) | called as a player enters / leaves a match (QB/Qbox hunger, thirst and stress hold + restore; ESX ammo save and restore) |
FW.giveKeys(src, vehicle) | server-side vehicle keys (qbx_vehiclekeys) |
FW.setRadio(src, channel) | team radio (pma-voice); 0 leaves |
Client (FW.*)
| Function | Purpose |
|---|---|
FW.notify(msg, kind, ms) | framework / ox_lib / GTA feed notification |
FW.showPrompt(text, key) / FW.hidePrompt() | key prompt (lumo-interact, ox_lib, qb DrawText or GTA help text) |
FW.addZone(name, opts) / FW.removeZone(name) | target zones (ox_target, qb-target or a built-in E prompt) |
FW.lockInventory(lock) | lock the city inventory and hotbar for the match (ox weapon-mismatch off, qbx_medical bleeding off), and restore the city weapons afterwards |
FW.cityHud(show) | runs Config.CityHud(show) and fires the client event lumo-battleroyale:cityHud |
FW.needs(lock) | ESX: holds esx_status hunger/thirst full for the match and restores them |
FW.inventoryImages() | the installed inventory's image folder (Config.Images.base = 'auto') |
FW.giveKeys(vehicle) | client-side vehicle keys (qb-vehiclekeys, wasabi_carlock) |
FW.weatherSync(enabled) | pause / resume qb-weathersync or cd_easytime |
FW.revive() | framework revive, used only after a lethal fall the health floor couldn't stop |
Using another inventory for pictures? Add a line to IMAGE_FOLDERS in framework/client.lua, or set Config.Images.base to its folder.
Using another medical script? Change FW.revive() to fire its revive event.
Health model, in short
During a match the ped's max health is 800 and it is never allowed below 700. Match HP is health − 700, so frameworks and medical scripts never see a death. Damage is reshaped on the victim's client (headshots, helmets, vest durability), and GTA's own armour bar isn't used. If you read GetEntityHealth for a player in a match, subtract Config.Health.floor.