Vestiti e Skin con ESX

INFO

Integrare vestiti custom in ESX significa renderli acquistabili nei negozi di abbigliamento e applicabili con il sistema skin di ESX.

ObiettivoDettagli
Cosa imparerai• Come funziona il sistema skin di ESX
• Aggiungere vestiti al negozio con ox_inventory
• Usare ox_lib per menu outfit e salvataggio
Prerequisiti• ESX con modulo skin attivo
• ox_inventory configurato
• Conoscenza componenti ped GTA V

1. Sistema Skin di ESX

ESX gestisce l’outfit del giocatore tramite eventi skin. Di default usa esx_skin o esx_clothes (deprecato) o si integra con sistemi come illenium-appearance.

Come Funziona

ESX salva l'outfit così:
┌─────────────────────────┐
│   Giocatore nel DB       │
│   skin = JSON string     │
│   {                      │
│     "tshirt_1": 0,       │ ← Drawable ID
│     "tshirt_2": 0,       │ ← Texture ID
│     "pants_1": 0,        │
│     "pants_2": 0,        │
│     "shoes_1": 0,        │
│     ...                  │
│   }                      │
└─────────────────────────┘

I campi seguono la nomenclatura di esx_skin (collegata ai componenti GTA V):

Campo ESXComponent GTA VDescrizione
mask_11Maschera
hair_12Capelli
arms_13Torso + braccia (maglie, camicie)
pants_14Gambe
bags_15Borsa / zaino
shoes_16Scarpe
chain_17Collane, catene
tshirt_18Undershirt (sottocamicia)
vest_19Gilet / giubbotto antiproiettile
decals_110Decals / loghi
torso_111Giacca esterna
helmet_1Prop 0Cappello / elmetto
glasses_1Prop 1Occhiali

WARNING

Tabella esx_skin reale: tshirt è l’undershirt (component 8), torso è la giacca esterna (component 11), arms è torso+braccia (component 3). Molte guide online invertono questi ID. Coerente con la tabella standard freemode nei moduli Ped Custom e Vestiti EUP.


2. Aggiungere Vestiti Custom al Negozio

Usando shop_ped_apparel.meta

TIP

Vedi shop_ped_apparel.meta — questo file registra i vestiti nei negozi nativi di GTA V.

Usando ox_inventory come negozio vestiti

-- ox_inventory/data/shops.lua
return {
    ['clothes_shop'] = {
        name = 'Negozio Abbigliamento',
        blip = { id = 73, colour = 2, scale = 0.7 },
        targets = {
            {
                loc = vec3(80.0, -1400.0, 29.0),
                length = 1.5, width = 1.5, heading = 0,
                minZ = 28.0, maxZ = 30.0,
                distance = 2.5,
            }
        },
        inventory = {
            -- Ogni item è un "capo" che il giocatore compra
            { name = 'police_shirt', price = 200 },
            { name = 'police_pants', price = 150 },
            { name = 'police_hat', price = 100 },
        }
    }
}

Poi, all’uso dell’item, cambi l’outfit:

WARNING

I component ID (3 = torso, 4 = gambe, 6 = scarpe) sono specifici di GTA V. Usare l’ID sbagliato non avrà effetto o applicherà il componente errato. Verifica sempre con la tabella nella sezione 1.

-- client.lua
-- Quando il giocatore usa "police_shirt" dall'inventario
RegisterNetEvent('myresource:applyClothing')
AddEventHandler('myresource:applyClothing', function(itemName)
    local playerPed = PlayerPedId()
    
    if itemName == 'police_shirt' then
        SetPedComponentVariation(playerPed, 3, 0, 0, 0)  -- Component 3, Drawable 0
    elseif itemName == 'police_pants' then
        SetPedComponentVariation(playerPed, 4, 0, 0, 0)
    elseif itemName == 'police_hat' then
        SetPedPropIndex(playerPed, 0, 0, 0, true)
    end
end)

3. Usare ox_lib per un Menu Vestiti

NOTE

La callback esx_skin:getPlayerSkin varia tra versioni/moduli skin. Il pattern più robusto è leggere lo skin dal server (dove ESX lo carica al login) oppure usare l’evento standard esx_skin:openSaveableMenu. Gli esempi sotto sono didattici: verifica i nomi esatti nella tua versione di esx_skin/illenium-appearance.

-- client.lua
local ESX = exports['es_extended']:getSharedObject()
 
RegisterCommand('outfit', function()
    lib.registerContext({
        id = 'clothing_menu',
        title = 'Outfit',
        options = {
            {
                title = 'Uniforme Polizia',
                description = 'Applica uniforme di servizio',
                onSelect = function()
                    TriggerEvent('myresource:setUniform', 'police')
                end
            },
            {
                title = 'Divisa Operativa',
                description = 'Applica divisa tattica',
                onSelect = function()
                    TriggerEvent('myresource:setUniform', 'tactical')
                end
            },
            {
                title = 'Azzera Outfit',
                description = 'Torna ai vestiti base',
                onSelect = function()
                    TriggerEvent('myresource:resetClothes')
                end
            }
        }
    })
    lib.showContext('clothing_menu')
end, false)

Applicare un Outfit Preimpostato

-- client.lua
RegisterNetEvent('myresource:setUniform')
AddEventHandler('myresource:setUniform', function(type)
    local playerPed = PlayerPedId()
 
    if type == 'police' then
        -- Applica ogni componente uno per uno
        SetPedComponentVariation(playerPed, 3, 0, 0, 0)  -- Torso+braccia
        SetPedComponentVariation(playerPed, 4, 0, 0, 0)  -- Gambe
        SetPedComponentVariation(playerPed, 6, 0, 0, 0)  -- Scarpe
        SetPedPropIndex(playerPed, 0, 0, 0, true)        -- Cappello
        SetPedPropIndex(playerPed, 1, 0, 0, true)        -- Occhiali
 
    elseif type == 'tactical' then
        SetPedComponentVariation(playerPed, 3, 1, 0, 0)  -- Torso alternativo
        SetPedComponentVariation(playerPed, 4, 1, 0, 0)  -- Pantaloni tattici
        SetPedComponentVariation(playerPed, 6, 1, 0, 0)  -- Stivali
        SetPedPropIndex(playerPed, 0, 0, 1, true)        -- Berretto
    end
 
    -- Notifica locale
    lib.notify({
        title = 'Outfit',
        description = 'Uniforme applicata!',
        type = 'success'
    })
end)

WARNING

I componenti qui (3 = torso, 4 = gambe, 6 = scarpe) sono quelli nativi SetPedComponentVariation (numerazione freemode), non i campi esx_skin. Nativi e campi ESX usano numerazioni diverse: vedi la tabella in sezione 1.


4. Integrazione con illenium-appearance

Se usi illenium-appearance (molto comune con ESX), i vestiti custom vengono caricati dai drawable del tuo pack e mostrati automaticamente nel menu. Non esiste una config Config.CustomClothing standard: la struttura esatta cambia tra versioni.

-- configuration/clothing.lua (esempio indicativo — controlla la tua versione)
-- Ogni voce lega una parte del corpo (drawable) a un outfit con nome
-- e a un insieme di componenti nativi da applicare.
 
Config.CustomOutfits = {
    ['police'] = {
        label = 'Uniforme Polizia',
        components = {
            [3] = { drawable = 0, texture = 0 },  -- Torso+braccia
            [4] = { drawable = 0, texture = 0 },  -- Gambe
            [6] = { drawable = 0, texture = 0 },  -- Scarpe
            [8] = { drawable = 0, texture = 0 },  -- Undershirt
        },
        props = {
            [0] = { drawable = 0, texture = 0 },  -- Cappello
        },
    },
    ['tactical'] = {
        label = 'Divisa Operativa',
        components = {
            [3] = { drawable = 1, texture = 0 },
            [4] = { drawable = 1, texture = 0 },
            [6] = { drawable = 1, texture = 0 },
        },
        props = {},
    },
}

WARNING

Non esiste Config.CustomClothing nello standard di illenium-appearance. Se cerchi online e trovi nomi di config “che non matchano”, è perché molti tutorial usano risorse fork o versioni personalizzate. Verifica sempre contro il repo della versione che usi.


5. Salvare l’Outfit

Quando il giocatore cambia vestito, aggiorna lo skin salvato in ESX tramite callback tua (non inventare nomi di callback esistenti):

-- client.lua
RegisterNetEvent('myresource:saveCurrentOutfit')
AddEventHandler('myresource:saveCurrentOutfit', function(name)
    local playerPed = PlayerPedId()
 
    local outfit = {
        name = name,
        components = {}
    }
 
    -- Leggi tutti i componenti
    for i = 0, 11 do
        local drawable, texture = GetPedDrawableVariation(playerPed, i), GetPedTextureVariation(playerPed, i)
        outfit.components[i] = { drawable = drawable, texture = texture }
    end
 
    -- Chiama una callback che registri tu (es. esx_skin:setPlayerSkin o una tua)
    ESX.TriggerServerCallback('myresource:saveOutfit', function(success)
        if success then
            lib.notify({
                title = 'Outfit Salvato',
                description = name .. ' salvato con successo!',
                type = 'success'
            })
        end
    end, outfit)
end)
-- server.lua
ESX.RegisterServerCallback('myresource:saveOutfit', function(source, cb, outfit)
    local xPlayer = ESX.GetPlayerFromId(source)
    -- Salva la skin nella tabella users (colonna skin) come JSON
    MySQL.update('UPDATE users SET skin = ? WHERE identifier = ?', {
        json.encode(outfit.components),
        xPlayer.identifier
    }, function()
        cb(true)
    end)
end)

TIP

Con illenium-appearance il salvataggio è già gestito: i vestiti custom vanno aggiunti alla sua config e il menu salva da solo. Non serve replicare il codice qui sopra se usi quel modulo.


TIP


Torna alla: Indice Generale