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 meta nil zurück. GetItemData gibt außerdem nil zurück, wenn der Spieler das Item nicht besitzt, RemoveItem gibt false zurück, wenn er nicht genug davon hat, und AddItem gibt false fü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')


-- 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()

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').

ExportParameterRü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):

FeldStandardBeschreibung
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
durationLesetempoLänge der Sprachzeile in ms: Der Text wird genau in dieser Zeit geschrieben
optionskeineBis zu 4 { id, label, close? }, sichtbar, sobald der Satz geschrieben ist. close = true schließt das Fenster nach der Wahl
cameratrueDen NPC ins Bild nehmen. false behält die Spielkamera
focustrueTastatur und Maus gehen an das Fenster. false = nur Anzeige, keine Eingabe
talktruefalse = hz_lib bewegt die Lippen des NPCs nicht (wenn Ihre Ressource sie selbst animiert)
maxDistance4.0Abstand 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
Gründe für das Schließen:
GrundWann
'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 OpenDialogue Ihrer Ressource ersetzt Ihren Dialog. Den Dialog einer anderen Ressource übernimmt es nie: Sie erhalten nil, 'busy'.
  • SayDialogue und CloseDialogue wirken nur auf Ihren eigenen Dialog; ohne id beziehen sie sich auf ihn.
  • Wahl mit close = true: Zuerst kehren Kamera, HUD und Steuerung zurück, dann folgt onSelect, dann onClose('select'). So können Sie in onSelect Ihr eigenes Menü öffnen.
  • Wahl ohne close: Antworten Sie in onSelect mit SayDialogue. Andernfalls erscheinen dieselben Antworten erneut. Ein Satz mit options = {} (oder ohne Optionen) zeigt keine Antworten.
  • Fehlen name und role in SayDialogue, 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. Gibt false zurü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.

ExportParameterRü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:

FeldTypBeschreibung
idstringKennung des Schritts, verwendet von UpdateObjective
textstringBezeichnung des Schritts
statestring'todo' (Standard), 'current' oder 'done'
detailstringZweite Zeile, nur unter dem laufenden Schritt sichtbar
valuenumberZähler rechts neben dem Schritt
maxnumberMit value: zeigt value / max und eine Fortschrittsanzeige am laufenden Schritt
unitstringEinheit hinter dem Zähler (L, crates…)
  • UpdateObjective führt patch mit einem Schritt zusammen (value, state, text, detail…). Gibt false zurü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:ready ausgelö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.