ox_lib — Notifiche, Menu, Progress Bar

INFO

ox_lib è la libreria UI di Overextended. Fornisce notifiche, menu contestuali, progress bar, input dialog e molto altro.

ObiettivoDettagli
Cosa imparerai• Usare notifiche, progress bar e menu contestuali
• Creare input dialog e text UI
• Integrare ox_lib con ESX e ox_inventory
Prerequisiti• ox_lib installato e avviato prima della risorsa
• Conoscenza base FiveM events

1. Setup

ox_lib deve essere avviato PRIMA della tua risorsa:

# server.cfg
ensure ox_lib
ensure es_extended
ensure ox_inventory
ensure tua_risorsa

Nella tua risorsa:

-- fxmanifest.lua
shared_scripts {
    '@ox_lib/init.lua',  -- Importa tutte le funzioni ox_lib
    'config.lua'
}

2. Notifiche

Base

lib.notify({
    title = 'Titolo',
    description = 'Testo della notifica',
    type = 'success'      -- 'success', 'error', 'info', 'warning'
})

Con Durata Personalizzata

lib.notify({
    title = 'Arma Acquistata',
    description = 'M4A1 Tactical - €5,000',
    type = 'success',
    duration = 5000,  -- 5 secondi (default: 3000)
    position = 'top-right',  -- 'top-right', 'top-left', 'bottom-right', 'bottom-left'
})

Esempi Pratici

-- Acquisto riuscito
lib.notify({
    title = 'Acquisto',
    description = 'Hai comprato la M4A1 Tactical',
    type = 'success'
})
 
-- Errore
lib.notify({
    title = 'Errore',
    description = 'Non hai abbastanza denaro',
    type = 'error'
})
 
-- Informazione
lib.notify({
    title = 'Informazione',
    description = 'Premi E per interagire',
    type = 'info'
})

3. Progress Bar

Utile per azioni che richiedono tempo (crafting, riparazione, ricerca):

WARNING

I dizionari di animazione (anim.dict) devono esistere in GTA V. Usa animazioni native esistenti o testale prima. Un dict inesistente blocca la progress bar senza errori visibili.

Base

lib.progressBar({
    duration = 5000,           -- 5 secondi
    label = 'Crafting in corso...',
    useWhileDead = false,
    canCancel = true,          -- Il giocatore può annullare
    disable = {
        move = true,
        car = true,
        combat = true,
    },
    anim = {
        dict = 'mini@repair',
        clip = 'fixing_a_ped',
    },
})
 
-- Dopo il progress, esegui il codice
print('Crafting completato!')

Con Controllo di Annullamento

local success = lib.progressBar({
    duration = 10000,
    label = 'Riparazione veicolo in corso...',
    useWhileDead = false,
    canCancel = true,
    disable = { move = true, car = true },
    anim = { dict = 'mini@repair', clip = 'fixing_a_ped' },
})
 
if success then
    -- Non annullato
    TriggerServerEvent('myresource:finishRepair')
    lib.notify({
        title = 'Riparazione',
        description = 'Veicolo riparato con successo!',
        type = 'success'
    })
else
    -- Annullato
    lib.notify({
        title = 'Riparazione',
        description = 'Riparazione annullata',
        type = 'info'
    })
end

Esempio: Crafting Arma

RegisterNetEvent('myresource:craftWeapon')
AddEventHandler('myresource:craftWeapon', function()
    -- Verifica che il giocatore abbia i materiali (server-side)
    local hasMaterials = lib.callback.await('myresource:checkCraftMaterials')
 
    if not hasMaterials then
        lib.notify({
            title = 'Crafting',
            description = 'Materiali insufficienti',
            type = 'error'
        })
        return
    end
 
    -- Avvia crafting
    local success = lib.progressBar({
        duration = 15000,  -- 15 secondi
        label = 'Creazione M4A1 in corso...',
        canCancel = true,
        disable = { move = true, car = true, combat = true },
        anim = {
            dict = 'amb@prop_human_bum_shopping_cart@male@idle_a',
            clip = 'idle_c',
        },
    })
 
    if success then
        TriggerServerEvent('myresource:craftComplete')
    end
end)

NOTE

Per verificare i materiali usa lib.callback (client lib.callback.await('nome', args) → server lib.callback.register('nome', function(source, ...)). È il pattern moderno al posto di TriggerServerCallback di ESX, ed è già integrato con ox_lib.


4. Menu Contestuali (Context Menu)

lib.registerContext({
    id = 'weapon_menu',
    title = 'Armeria',
    options = {
        {
            title = 'M4A1 Tactical',
            description = 'Fucile d\'assalto - €5,000',
            icon = 'fa-solid fa-gun',
            onSelect = function()
                TriggerServerEvent('myresource:buyWeapon', 'WEAPON_M4A1_CUSTOM')
            end
        },
        {
            title = 'Munizioni Fucile',
            description = '50 proiettili 5.56mm - €100',
            icon = 'fa-solid fa-bullseye',
            onSelect = function()
                TriggerServerEvent('myresource:buyAmmo', 'ammo-rifle', 50)
            end
        },
        {
            title = 'Esci',
            icon = 'fa-solid fa-xmark',
            onSelect = function()
                -- Chiude il menu
            end
        }
    }
})
 
lib.showContext('weapon_menu')
-- Menu principale
lib.registerContext({
    id = 'main_menu',
    title = 'Menu Principale',
    options = {
        {
            title = 'Armi',
            icon = 'fa-solid fa-gun',
            menu = 'weapons_menu',  -- Apre un altro menu
        },
        {
            title = 'Veicoli',
            icon = 'fa-solid fa-car',
            menu = 'vehicles_menu',
        },
        {
            title = 'Outfit',
            icon = 'fa-solid fa-shirt',
            menu = 'outfit_menu',
        },
    }
})
 
-- Sotto-menu Armi
lib.registerContext({
    id = 'weapons_menu',
    title = 'Armi',
    options = {
        {
            title = 'M4A1 Tactical',
            description = 'Prezzo: €5,000',
            onSelect = function()
                TriggerServerEvent('myresource:buyWeapon')
            end
        },
        {
            title = 'Indietro',
            icon = 'fa-solid fa-arrow-left',
            menu = 'main_menu',  -- Torna al menu principale
        }
    }
})

TIP

Per menu con molte opzioni, usa la proprietà menu nei singoli option per creare sottomenu annidati. Ogni menu va registrato con lib.registerContext() prima di essere mostrato.


5. Input Dialog

Testo

local input = lib.inputDialog('Acquista Munizioni', {
    { type = 'number', label = 'Quantità', default = 50, min = 1, max = 500 },
    { type = 'select', label = 'Tipo', options = { '5.56mm', '9mm', '12 Gauge' } }
})
 
if input then
    local quantity = input[1]
    local ammoType = input[2]
    TriggerServerEvent('myresource:buyAmmo', ammoType, quantity)
end

Esempio: Deposito Denaro

local input = lib.inputDialog('Banca', {
    { type = 'number', label = 'Importo da depositare', icon = 'fa-solid fa-money-bill' }
})
 
if input then
    local amount = tonumber(input[1])
    if amount and amount > 0 then
        TriggerServerEvent('myresource:depositMoney', amount)
    end
end

6. Altri Utility

Text UI (Testo a Schermo)

-- Mostra
lib.showTextUI('[E] - Interagisci', {
    position = 'bottom-center',
    icon = 'fa-solid fa-hand-pointer',
})
 
-- Nascondi
lib.hideTextUI()

Telefono/Distanza

local dist = #(GetEntityCoords(PlayerPedId()) - vector3(250.0, -150.0, 30.0))
 
if dist < 50.0 then
    -- Vicino al negozio
end

TIP

Prossimo passo: 08 - Esempio Completo


Torna alla: Indice Generale