Exports & API
hz_lib expose 140+ exports utilisables depuis n'importe quelle ressource. Tous les exports sont disponibles via exports['hz_lib'].
Meta / Detection
-- Client & server
local Bridge = exports['hz_lib']:GetBridge() -- full Bridge table (advanced usage)
local framework = exports['hz_lib']:GetDetectedFramework() -- 'esx', 'qbcore', 'qbox', etc.
local inventory = exports['hz_lib']:GetDetectedInventory() -- 'ox_inventory', etc.
-- Client only
local notify = exports['hz_lib']:GetDetectedNotifications() -- 'ox_lib', etc.
local dispatch = exports['hz_lib']:GetDetectedDispatch() -- 'cd_dispatch', etc.
local target = exports['hz_lib']:GetDetectedTarget() -- 'ox_target', etc.
local menu = exports['hz_lib']:GetDetectedMenu() -- 'ox_lib', 'qb-menu', etc.
-- Server only
local banking = exports['hz_lib']:GetDetectedBanking() -- 'qb-banking', 'hz_banking', 'none', etc.
Framework
Client
-- Get current player job
local job = exports['hz_lib']:GetPlayerJob()
-- Get full player data
local data = exports['hz_lib']:GetPlayerData()
Server
-- Get player info
local job = exports['hz_lib']:GetPlayerJob(source)
local data = exports['hz_lib']:GetPlayerData(source)
local charId = exports['hz_lib']:GetPlayerCharId(source)
local name = exports['hz_lib']:GetPlayerName(source)
-- Money
local canPay = exports['hz_lib']:CanAfford(source, 500)
exports['hz_lib']:AddMoney(source, 500, 'bank')
exports['hz_lib']:RemoveMoney(source, 500, 'cash')
-- Job queries
local cops = exports['hz_lib']:GetPlayersWithJob({'police', 'sheriff'}, 0)
-- Usable items
exports['hz_lib']:RegisterUsableItem('phone', function(source)
-- player used the item
end)
Inventaire (Server)
-- Check items
local count = exports['hz_lib']:GetItemCount(source, 'bread')
local itemData = exports['hz_lib']:GetItemData(source, 'bread')
local has = exports['hz_lib']:HasItem(source, 'bread', 1)
local canFit = exports['hz_lib']:CanCarry(source, 'bread', 5)
-- Add / Remove
exports['hz_lib']:AddItem(source, 'bread', 5)
exports['hz_lib']:RemoveItem(source, 'bread', 1)
exports['hz_lib']:AddItemToFit(source, 'bread', 5) -- Only add if can carry
-- Stash
exports['hz_lib']:OpenStash(source, 'my_stash', 'My Stash', 50, 100000)
local content = exports['hz_lib']:GetStashContent('my_stash')
Desde a v1.2.0, GetItemData(source, item, meta) retorna um item com esse nome cujos metadados contêm cada chave e valor de meta, ou nil se nenhum corresponder:
local card = exports['hz_lib']:GetItemData(source, 'id_card', { citizenid = 'ABC12345' })
if not card then
-- o jogador não carrega esse cartão específico
end
- ox_inventory, qb-inventory e o inventário nativo do QBCore percorrem todas as pilhas do item; ps, qs, codem, origen, tgiann, core e ak47 verificam a pilha que o inventário retorna primeiro.
- O inventário nativo do ESX não guarda metadados, então uma busca com
metaretornanil.GetItemDatatambém retornanilquando o jogador não tem o item,RemoveItemretornafalsequando ele não tem o suficiente eAddItemretornafalsepara um item desconhecido.
Banco / Sociedade (Server)
O dinheiro de uma conta de sociedade (a conta do chefe de um emprego ou de uma gangue), enviado ao banco definido em HZBridge.Banking.
local balance = exports['hz_lib']:GetSocietyMoney('mechanic')
exports['hz_lib']:AddSocietyMoney('mechanic', 500, 'Repair')
local paid = exports['hz_lib']:RemoveSocietyMoney('mechanic', 200, 'Parts') -- false if refused
-- Can the detected bank really read balances and take money?
local supports = exports['hz_lib']:GetBankingSupports() -- { get = true|false, remove = true|false }
Alguns bancos só permitem adicionar dinheiro. Quando supports.get ou supports.remove é false, um saldo de 0 ou um false de RemoveSocietyMoney significa "não suportado", não "vazio". Com HZBridge.Banking = 'none', adicionar e retirar retornam false e o saldo é 0.
Notifications
Client
exports['hz_lib']:Notify('Item added!', 'success', 3000)
Server
-- Notify one player
exports['hz_lib']:NotifyPlayer(source, 'Welcome!', 'info', 5000)
-- Notify all players
exports['hz_lib']:NotifyAll('Server restart in 5 minutes', 'warning', 10000)
Types : 'info', 'success', 'warning', 'error'
Dispatch (Client)
exports['hz_lib']:SendDispatch({
title = 'Robbery in progress',
message = '10-90 at Fleeca Bank',
coords = GetEntityCoords(PlayerPedId()),
jobs = {'police'},
blip = { sprite = 161, color = 1, scale = 1.0 },
})
Target (Client)
-- Add target to entity
exports['hz_lib']:AddTargetEntity(entity, {
{ label = 'Open', icon = 'fas fa-door-open', action = function(e) end },
})
-- Add target to zone
exports['hz_lib']:AddTargetZone('my_zone', {
coords = vector3(0, 0, 0),
size = vec3(2.0, 2.0, 2.0), -- box size, optional (default 2 x 2 x 2)
rotation = 0.0, -- optional
options = { { label = 'Interact', action = function() end } },
})
-- Add target to model
exports['hz_lib']:AddTargetModel('prop_vendmach_01', {
{ label = 'Buy drink', icon = 'fas fa-coffee', action = function() end },
})
-- Remove
exports['hz_lib']:RemoveTarget('my_zone')
Menu / UI (Client)
Menu contextuel
-- Quick: register + show in one call
exports['hz_lib']:ContextMenu('my_menu', 'My Menu', {
{
title = 'Option 1',
description = 'Description here',
icon = 'fas fa-star',
onSelect = function(args) print('selected!') end,
},
{
title = 'Sub Menu',
menu = 'my_submenu', -- Opens another registered context
},
})
-- Or register and show separately
exports['hz_lib']:RegisterContext({
id = 'my_menu',
title = 'My Menu',
options = { --[[ ... ]] },
})
exports['hz_lib']:ShowContext('my_menu')
-- Hide / Query
exports['hz_lib']:HideContext()
local openId = exports['hz_lib']:GetOpenContext()
Dialogue de saisie
local result = exports['hz_lib']:InputDialog('Enter Details', {
{ type = 'input', label = 'Name', placeholder = 'John Doe', required = true },
{ type = 'number', label = 'Amount', default = 100 },
{ type = 'select', label = 'Type', options = {
{ value = 'a', label = 'Option A' },
{ value = 'b', label = 'Option B' },
}},
})
if result then
local name, amount, type = result[1], result[2], result[3]
end
Dialogue d'alerte
local response = exports['hz_lib']:AlertDialog({
header = 'Confirm Action',
content = 'Are you sure you want to proceed?',
centered = true,
cancel = true,
})
if response == 'confirm' then
-- User confirmed
end
TextUI
exports['hz_lib']:ShowTextUI('[E] Interact', {
position = 'right-center',
icon = 'fas fa-hand-pointer',
})
exports['hz_lib']:HideTextUI()
local isOpen = exports['hz_lib']:IsTextUIOpen()
Barre de progression
local completed = exports['hz_lib']:ProgressBar({
duration = 5000,
label = 'Crafting...',
canCancel = true,
disable = { move = true, combat = true },
anim = { dict = 'mini@repair', clip = 'fixing_a_player' },
})
if completed then
-- Finished
else
-- Cancelled
end
-- Circle variant
local done = exports['hz_lib']:ProgressCircle({ duration = 3000, label = 'Loading...' })
-- Query / Cancel
local active = exports['hz_lib']:IsProgressActive()
exports['hz_lib']:CancelProgress()
Menu liste
exports['hz_lib']:RegisterMenu({
id = 'my_list',
title = 'Select Item',
options = {
{ label = 'Item 1', description = 'First item' },
{ label = 'Item 2', description = 'Second item' },
},
}, function(selected, scrollIndex, args)
print('Selected index:', selected)
end)
exports['hz_lib']:ShowMenu('my_list')
exports['hz_lib']:HideMenu()
Tout fermer
exports['hz_lib']:CloseAllMenus() -- Close any open menu/context/input/alert/progress
Callbacks
Server
-- Register a server callback
exports['hz_lib']:RegisterCallback('myResource:getData', function(source, arg1, arg2)
return { money = 1000, name = 'John' }
end)
-- Call a client callback from server
local result = exports['hz_lib']:TriggerClientCallback(source, 'myResource:clientCheck')
Client
-- Call a server callback (blocking)
local data = exports['hz_lib']:TriggerCallback('myResource:getData', arg1, arg2)
print(data.money) -- 1000
-- Register a client callback
exports['hz_lib']:RegisterClientCallback('myResource:clientCheck', function()
return GetEntityCoords(PlayerPedId())
end)
Minijeux (Client)
-- Progress with coordinates
local success = exports['hz_lib']:MinigameProgress(coords, 5000, {
label = 'Searching...',
})
-- Sequence minigame
local passed = exports['hz_lib']:SequenceMinigame(coords, 5, {
label = 'Enter code',
})
-- Skill check
local passed = exports['hz_lib']:SkillCheck('medium', {'w', 'a', 's', 'd'})
Diálogo com NPC (Client)
Uma caixa de diálogo na parte de baixo da tela para conversar com um NPC. A fala do NPC é digitada, no ritmo da voz dele se você passar duration, e depois aparecem até quatro escolhas numeradas. Enquanto ela está aberta, a câmera enquadra o NPC por cima do ombro do jogador, o NPC mexe os lábios ao falar e os dois personagens se olham. O HUD fica oculto, e o menu de pausa, o combate e o movimento ficam bloqueados até o fechamento.
O jogador escolhe com as teclas 1 a 4, as setas e Enter, ou com o mouse. Enter (ou um clique na fala) mostra a fala inteira de uma vez. Esc fecha a caixa. As dicas de teclas seguem HZBridge.Locale ('en' ou 'fr').
| Export | Parâmetros | Retorno |
|---|---|---|
OpenDialogue | (data) | id do diálogo, ou nil, 'busy' / nil, 'invalid' |
SayDialogue | (id, data) | boolean |
CloseDialogue | (id?) | boolean |
IsDialogueOpen | () | boolean |
SelectDialogue | (id, optionId) | boolean |
local dialogueId
dialogueId = exports['hz_lib']:OpenDialogue({
ped = ped, -- o NPC que fala
name = 'Rosa Ortiz',
role = 'Mechanic',
text = 'Hey. What can I do for you?',
duration = 1900, -- duração da fala gravada que você toca (ms), opcional
options = {
{ id = 'repair', label = 'Repair my car' },
{ id = 'leave', label = 'Never mind', close = true },
},
onSelect = function(optionId)
if optionId == 'repair' then
exports['hz_lib']:SayDialogue(dialogueId, {
text = 'That will be $250. Deal?',
options = {
{ id = 'pay', label = 'Deal', close = true },
{ id = 'no', label = 'Too expensive', close = true },
},
})
elseif optionId == 'pay' then
TriggerServerEvent('my_garage:repair')
end
end,
onClose = function(reason)
-- 'select', 'escape', 'replaced', 'closed', 'too_far' ou 'stopped'
end,
})
if not dialogueId then
-- o diálogo de outro recurso está na tela
end
Campos de OpenDialogue (SayDialogue aceita os mesmos, exceto ped e camera):
| Campo | Padrão | Descrição |
|---|---|---|
ped | — | O NPC que fala. Sem ele: sem câmera e sem verificação de distância |
name | — | Nome exibido como título |
role | — | Linha pequena acima do nome. false em SayDialogue a remove |
text | — | A fala do NPC |
duration | ritmo de leitura | Duração da fala gravada em ms: o texto é digitado exatamente nesse tempo |
options | nenhuma | Até 4 { id, label, close? }, exibidas quando a fala termina de ser digitada. close = true fecha a caixa após a escolha |
camera | true | Enquadrar o NPC. false mantém a câmera do jogo |
focus | true | Teclado e mouse vão para a caixa. false = só exibição, sem entrada |
talk | true | false = o hz_lib não mexe os lábios do NPC (quando seu recurso já os anima) |
maxDistance | 4.0 | Distância do NPC, em metros, a partir da qual o diálogo fecha |
onSelect | — | function(optionId, dialogueId), chamada a cada escolha |
onClose | — | function(reason), chamada uma vez quando o diálogo termina |
| Motivo | Quando |
|---|---|
'select' | O jogador escolheu uma opção com close = true |
'escape' | O jogador apertou Esc |
'replaced' | Seu recurso abriu um novo diálogo |
'closed' | Você chamou CloseDialogue |
'too_far' | O jogador se afastou além de maxDistance, o NPC sumiu, ou o NPC ou o jogador morreu |
'stopped' | Seu recurso (ou o hz_lib) parou |
- Um diálogo por vez na tela. Um novo
OpenDialoguedo seu recurso substitui o seu. O diálogo de outro recurso nunca é tomado: você recebenil, 'busy'. SayDialogueeCloseDialoguesó agem sobre o seu próprio diálogo; semid, eles se aplicam a ele.- Escolha com
close = true: câmera, HUD e controles voltam primeiro, depois vemonSelecte entãoonClose('select'). Assim você pode abrir seu próprio menu emonSelect. - Escolha sem
close: responda comSayDialoguedentro deonSelect. Se não responder, as mesmas escolhas voltam. Uma fala enviada comoptions = {}(ou sem opções) não mostra escolhas. nameeroleomitidos emSayDialoguecontinuam como estavam.- O hz_lib não toca nenhuma voz: toque você mesmo a fala gravada do NPC e passe a duração dela em
duration. Os sons do menu do jogo acompanham o hover, a escolha e o Esc. SelectDialogue(id, optionId)escolhe uma opção no lugar do jogador (cenas roteirizadas, tutoriais): a linha aparece selecionada por um instante e a escolha é executada exatamente como a de um jogador. Retornafalseenquanto a fala ainda está sendo digitada, ou para um id ou opção desconhecidos.- Sem câmera quando o jogador está em um veículo, ou quando a câmera de outro script já está ativa. Se houver uma parede atrás do ombro do jogador, outro ângulo é usado.
- Os textos aparecem como enviados: traduza-os no seu recurso. Um erro nos seus callbacks aparece no console F8 sem quebrar o diálogo.
Rastreador de objetivos (Client)
Mostra as etapas de um trabalho ou missão na tela do jogador: um título e, abaixo, cada etapa com seu estado. A etapa em andamento pode ter uma linha de detalhe, um contador e uma barra de progresso. Quem desenha é o hz_lib: todos os scripts HZ compartilham o mesmo visual, as cores do seu tema e um único lugar na tela.
| Export | Parâmetros | Retorno |
|---|---|---|
SetObjectives | (id, { kicker?, title, steps }) | boolean |
UpdateObjective | (id, stepId, patch) | boolean |
ClearObjectives | (id) | boolean |
-- Cria (ou substitui) o rastreador 'delivery' do seu recurso
exports['hz_lib']:SetObjectives('delivery', {
kicker = 'Delivery',
title = 'Objectives',
steps = {
{ id = 'load', text = 'Load the truck', detail = 'Warehouse 3, Elysian Island', value = 0, max = 12, unit = 'crates', state = 'current' },
{ id = 'drop', text = 'Deliver to Grove Street', state = 'todo' },
},
})
-- Progresso e, depois, a próxima etapa
exports['hz_lib']:UpdateObjective('delivery', 'load', { value = 5 })
exports['hz_lib']:UpdateObjective('delivery', 'load', { state = 'done' })
exports['hz_lib']:UpdateObjective('delivery', 'drop', { state = 'current' })
-- Trabalho concluído
exports['hz_lib']:ClearObjectives('delivery')
Campos de uma etapa:
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador da etapa, usado por UpdateObjective |
text | string | Texto da etapa |
state | string | 'todo' (padrão), 'current' ou 'done' |
detail | string | Segunda linha, exibida só abaixo da etapa em andamento |
value | number | Contador à direita da etapa |
max | number | Com value: mostra value / max e uma barra na etapa em andamento |
unit | string | Unidade depois do contador (L, crates…) |
UpdateObjectivemesclapatchem uma etapa (value,state,text,detail…). Retornafalsese o rastreador ou a etapa não existir.- Os identificadores pertencem ao seu recurso: dois recursos podem usar
'delivery'sem conflito. Vários rastreadores se empilham na mesma coluna. - No máximo cinco linhas: as etapas concluídas mais antigas saem primeiro; senão, quatro etapas e uma linha
+N. - Os textos aparecem como enviados: traduza-os no seu recurso.
- O rastreador some enquanto o menu de pausa ou o mapa está aberto, e é removido quando seu recurso para.
- Quando o hz_lib reinicia, ele dispara o evento de cliente
hz_lib:objectives:ready: envie seus rastreadores de novo a partir dele.
AddEventHandler('hz_lib:objectives:ready', function()
if onJob then exports['hz_lib']:SetObjectives('delivery', currentTracker) end
end)
Por padrão, a lista aparece à esquerda da tela. Você pode movê-la em /hzpanel > Appearance > Objectives tracker: Screen side (left ou right) e Height (% a partir do topo, padrão 26). Aumente a altura se a lista cobrir outro elemento do HUD.
Admin Panel (Server)
-- Ouvre le panneau d'administration centralise pour un joueur (meme effet que taper /hzpanel).
-- Le second argument preselectionne optionnellement l'onglet d'un module.
exports['hz_lib']:OpenPanel(source)
exports['hz_lib']:OpenPanel(source, 'hz_weather')
Consultez le guide Panneau d'administration pour le DSL de schema, les types de champ et l'enregistrement de vues.
Theme (Server & Client)
L'onglet Apparence du panneau d'administration ecrit un theme partage unique utilise par chaque NUI HZ. Les ressources peuvent lire le theme actuel de maniere synchrone, ou s'abonner aux mises a jour en direct.
Server
-- Get the current effective theme (accent + surfaces + gradient mode + radii + fonts).
local theme = exports['hz_lib']:GetTheme()
-- Subscribe to admin changes server-side.
AddEventHandler('HZ-Bridge:theme:updated', function(theme)
-- theme: { preset, accent, accentHi, gold, surface, subpanel, tint,
-- gradientMode, radiusNone, radiusXs, radiusSm, ..., radiusXl,
-- fontDisplay, fontBody, fontNumber,
-- fonts = { display, body, number, href } }
end)
Client
-- Live updates from the admin panel.
RegisterNetEvent('HZ-Bridge:theme:updated', function(theme)
SendNUIMessage({ action = 'theme', data = theme })
end)
-- Pull the current theme on resource start so first paint is themed.
TriggerServerEvent('HZ-Bridge:theme:request')
Le serveur repond via TriggerClientEvent('HZ-Bridge:theme:updated', src, theme) donc le meme handler s'execute pour la synchronisation initiale et les mises a jour en direct.
