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')
Seit v1.2.0 gibt GetItemData(source, item, meta) ein Item dieses Namens zurück, dessen Metadaten jeden Schlüssel und Wert von meta enthalten, oder nil, wenn keines passt:
local card = exports['hz_lib']:GetItemData(source, 'id_card', { citizenid = 'ABC12345' })
if not card then
-- der Spieler trägt genau diese Karte nicht
end
- ox_inventory, qb-inventory und das native QBCore-Inventar durchsuchen alle Stapel des Items; ps, qs, codem, origen, tgiann, core und ak47 prüfen den Stapel, den das Inventar zuerst liefert.
- Das native ESX-Inventar speichert keine Metadaten, daher gibt eine Suche mit
metanilzurück.GetItemDatagibt außerdemnilzurück, wenn der Spieler das Item nicht besitzt,RemoveItemgibtfalsezurück, wenn er nicht genug davon hat, undAddItemgibtfalsefür ein unbekanntes Item zurück.
Bank / Firmenkonten (Server)
Geld auf einem Firmenkonto (Chefkonto eines Jobs oder einer Gang), weitergeleitet an die Bank, die in HZBridge.Banking eingestellt ist.
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 }
Manche Banken erlauben nur das Einzahlen. Wenn supports.get oder supports.remove false ist, bedeutet ein Kontostand von 0 oder ein false von RemoveSocietyMoney „nicht unterstützt“, nicht „leer“. Mit HZBridge.Banking = 'none' geben Einzahlen und Abheben false zurück, und der Kontostand ist 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'})
NPC-Dialog (Client)
Ein Dialogfenster am unteren Bildschirmrand, um mit einem NPC zu sprechen. Der Satz des NPCs wird geschrieben, im Takt seiner Stimme, wenn Sie duration übergeben, danach erscheinen bis zu vier nummerierte Antworten. Solange der Dialog offen ist, zeigt die Kamera den NPC über die Schulter des Spielers, der NPC bewegt beim Sprechen die Lippen und beide Figuren sehen sich an. Das HUD ist ausgeblendet, Pausenmenü, Kampf und Bewegung sind bis zum Schließen gesperrt.
Der Spieler wählt mit den Tasten 1 bis 4, den Pfeiltasten und Enter oder mit der Maus. Enter (oder ein Klick auf den Satz) zeigt den ganzen Satz sofort an. Escape schließt das Fenster. Die Tastenhinweise folgen HZBridge.Locale ('en' oder 'fr').
| Export | Parameter | Rückgabe |
|---|---|---|
OpenDialogue | (data) | Dialog-ID, oder 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, -- der NPC, der spricht
name = 'Rosa Ortiz',
role = 'Mechanic',
text = 'Hey. What can I do for you?',
duration = 1900, -- Länge der Sprachzeile, die Sie abspielen (ms), optional
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' oder 'stopped'
end,
})
if not dialogueId then
-- der Dialog einer anderen Ressource ist auf dem Bildschirm
end
Felder von OpenDialogue (SayDialogue nimmt dieselben, außer ped und camera):
| Feld | Standard | Beschreibung |
|---|---|---|
ped | — | Der NPC, der spricht. Ohne ihn: keine Kamera und keine Abstandsprüfung |
name | — | Name als Titel |
role | — | Kleine Zeile über dem Namen. false in SayDialogue entfernt sie |
text | — | Der Satz des NPCs |
duration | Lesetempo | Länge der Sprachzeile in ms: Der Text wird genau in dieser Zeit geschrieben |
options | keine | Bis zu 4 { id, label, close? }, sichtbar, sobald der Satz geschrieben ist. close = true schließt das Fenster nach der Wahl |
camera | true | Den NPC ins Bild nehmen. false behält die Spielkamera |
focus | true | Tastatur und Maus gehen an das Fenster. false = nur Anzeige, keine Eingabe |
talk | true | false = hz_lib bewegt die Lippen des NPCs nicht (wenn Ihre Ressource sie selbst animiert) |
maxDistance | 4.0 | Abstand zum NPC in Metern, ab dem der Dialog schließt |
onSelect | — | function(optionId, dialogueId), bei jeder Wahl aufgerufen |
onClose | — | function(reason), einmal am Ende des Dialogs aufgerufen |
| Grund | Wann |
|---|---|
'select' | Der Spieler hat eine Option mit close = true gewählt |
'escape' | Der Spieler hat Escape gedrückt |
'replaced' | Ihre Ressource hat einen neuen Dialog geöffnet |
'closed' | Sie haben CloseDialogue aufgerufen |
'too_far' | Der Spieler hat sich weiter als maxDistance entfernt, der NPC ist verschwunden, oder NPC oder Spieler ist gestorben |
'stopped' | Ihre Ressource (oder hz_lib) wurde gestoppt |
- Immer nur ein Dialog auf dem Bildschirm. Ein neues
OpenDialogueIhrer Ressource ersetzt Ihren Dialog. Den Dialog einer anderen Ressource übernimmt es nie: Sie erhaltennil, 'busy'. SayDialogueundCloseDialoguewirken nur auf Ihren eigenen Dialog; ohneidbeziehen sie sich auf ihn.- Wahl mit
close = true: Zuerst kehren Kamera, HUD und Steuerung zurück, dann folgtonSelect, dannonClose('select'). So können Sie inonSelectIhr eigenes Menü öffnen. - Wahl ohne
close: Antworten Sie inonSelectmitSayDialogue. Andernfalls erscheinen dieselben Antworten erneut. Ein Satz mitoptions = {}(oder ohne Optionen) zeigt keine Antworten. - Fehlen
nameundroleinSayDialogue, bleiben sie unverändert. - hz_lib spielt keine Stimme ab: Spielen Sie die Sprachzeile des NPCs selbst ab und übergeben Sie ihre Länge in
duration. Die Menü-Sounds des Spiels begleiten Hover, Auswahl und Escape. SelectDialogue(id, optionId)wählt eine Option anstelle des Spielers (geskriptete Szenen, Tutorials): Die Zeile erscheint kurz ausgewählt, dann läuft die Wahl genau wie die eines Spielers ab. Gibtfalsezurück, solange der Satz noch geschrieben wird, oder bei unbekannter ID oder Option.- Keine Kamera, wenn der Spieler in einem Fahrzeug sitzt oder die Kamera eines anderen Scripts bereits aktiv ist. Steht eine Wand hinter der Schulter des Spielers, wird ein anderer Winkel verwendet.
- Texte werden unverändert angezeigt: Übersetzen Sie sie in Ihrer Ressource. Ein Fehler in Ihren Callbacks erscheint in der F8-Konsole, ohne den Dialog abzubrechen.
Missionsziele (Client)
Zeigt die Schritte eines Jobs oder einer Mission auf dem Bildschirm des Spielers: einen Titel, darunter jeden Schritt mit seinem Status. Der laufende Schritt kann eine Detailzeile, einen Zähler und eine Fortschrittsanzeige tragen. hz_lib zeichnet die Liste selbst: Alle HZ-Scripts teilen dasselbe Aussehen, die Farben Ihres Themes und einen einzigen Platz auf dem Bildschirm.
| Export | Parameter | Rückgabe |
|---|---|---|
SetObjectives | (id, { kicker?, title, steps }) | boolean |
UpdateObjective | (id, stepId, patch) | boolean |
ClearObjectives | (id) | boolean |
-- Erstellt (oder ersetzt) die Liste 'delivery' Ihrer Ressource
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' },
},
})
-- Fortschritt, dann der nächste Schritt
exports['hz_lib']:UpdateObjective('delivery', 'load', { value = 5 })
exports['hz_lib']:UpdateObjective('delivery', 'load', { state = 'done' })
exports['hz_lib']:UpdateObjective('delivery', 'drop', { state = 'current' })
-- Job beendet
exports['hz_lib']:ClearObjectives('delivery')
Felder eines Schritts:
| Feld | Typ | Beschreibung |
|---|---|---|
id | string | Kennung des Schritts, verwendet von UpdateObjective |
text | string | Bezeichnung des Schritts |
state | string | 'todo' (Standard), 'current' oder 'done' |
detail | string | Zweite Zeile, nur unter dem laufenden Schritt sichtbar |
value | number | Zähler rechts neben dem Schritt |
max | number | Mit value: zeigt value / max und eine Fortschrittsanzeige am laufenden Schritt |
unit | string | Einheit hinter dem Zähler (L, crates…) |
UpdateObjectiveführtpatchmit einem Schritt zusammen (value,state,text,detail…). Gibtfalsezurück, wenn die Liste oder der Schritt nicht existiert.- Kennungen gehören Ihrer Ressource: Zwei Ressourcen können beide
'delivery'verwenden, ohne sich zu stören. Mehrere Listen werden in einer Spalte gestapelt. - Höchstens fünf Zeilen: Die ältesten erledigten Schritte verschwinden zuerst, sonst vier Schritte und eine Zeile
+N. - Texte werden unverändert angezeigt: Übersetzen Sie sie in Ihrer Ressource.
- Die Liste wird ausgeblendet, solange das Pausenmenü oder die Karte geöffnet ist, und verschwindet, wenn Ihre Ressource stoppt.
- Beim Neustart von hz_lib wird das Client-Event
hz_lib:objectives:readyausgelöst: Senden Sie Ihre Listen von dort aus erneut.
AddEventHandler('hz_lib:objectives:ready', function()
if onJob then exports['hz_lib']:SetObjectives('delivery', currentTracker) end
end)
Standardmäßig erscheint die Liste links auf dem Bildschirm. Sie können sie unter /hzpanel > Appearance > Objectives tracker verschieben: Screen side (left oder right) und Height (% von oben, Standard 26). Erhöhen Sie den Wert, wenn die Liste ein anderes HUD-Element verdeckt.
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.
