Scripting

Guia do ox_inventory: como instalar e adicionar itens

Aprenda a instalar o ox_inventory e adicionar itens personalizados: campos do items.lua, imagens, itens usáveis, metadata e erros comuns no FiveM.

· 12 min de leitura

O ox_inventory é o inventário por slots da Overextended, a equipe por trás do ox_lib e do ox_target. Ele substitui os sistemas de itens, inventário e armas do seu framework por um único resource que cuida de inventário de jogador, stashes, shops, porta-malas, porta-luvas e drops, com cada movimentação de item validada no servidor. É o inventário padrão no Qbox e um upgrade bem popular no ESX.

Este guia mostra o que o ox_inventory suporta, como instalar e, principalmente, como adicionar itens no ox_inventory: os campos do data/items.lua, imagens dos itens, como deixar um item usável, como dar itens via código, metadata e os erros que você mais vai encontrar.

Resumindo: instale o oxmysql e o ox_lib, baixe o release ox_inventory.zip, defina inventory:framework no server.cfg e dê start logo depois do seu framework. Para adicionar um item, defina ele no data/items.lua, coloque um <item_name>.png em web/images/, reinicie e dê o item com exports.ox_inventory:AddItem(source, 'item_name', 1).

O que o ox_inventory suporta

O ox_inventory conversa com o seu framework através de um bridge, escolhido pela convar inventory:framework. Os frameworks com suporte oficial são:

FrameworkValor da convarObservações
ox_coreoxO framework da própria Overextended
ESX LegacyesxExige ESX Legacy 1.6.0 ou mais recente. Também é o padrão se a convar não for definida
QboxqbxO Qbox foi construído em volta do ox_inventory
ND Corend

O QBCore não está na lista. O release atual só traz bridges para ox, ESX, Qbox e ND. Se você usa QBCore e quer o ox_inventory, o caminho prático é o Qbox, que roda a maioria dos scripts de QBCore pelo próprio bridge. Veja Qbox vs QBCore vs ESX para entender os prós e contras.

Também não existe modo standalone. Sem um framework suportado, você precisa escrever seu próprio módulo de bridge, o que a documentação descreve como possível, mas sem suporte.

Lembre também que o ox_inventory trata armas como itens e não tem loadouts. Scripts que dependem do comportamento padrão do inventário do framework, como esx_shops ou esx_trunkinventory, vão dar conflito com ele.

Como instalar o ox_inventory

Você precisa de um servidor com OneSync ativado e mais duas dependências:

  • oxmysql para o banco de dados
  • ox_lib para UI, callbacks e utilitários

O ox_target é opcional, mas recomendado para shops e stashes com zonas de interação.

  1. Baixe o ox_inventory.zip do último release no GitHub. Não use o download "Source code"; ele não vem com a UI buildada.
  2. Extraia na sua pasta resources de forma que a pasta se chame ox_inventory.
  3. Defina a convar do framework e a ordem de start no server.cfg:
setr inventory:framework "qbx"   # or "esx", "ox", "nd"

start oxmysql
start ox_lib
start qbx_core      # your framework
start ox_target
start ox_inventory

A configuração fica em convars, não em um arquivo de config. As primeiras que você vai mexer:

setr inventory:slots 50          # player inventory slots
setr inventory:weight 30000      # max carry weight, in grams
setr inventory:target true       # use ox_target for shops and stashes
setr inventory:keys ["F2", "K", "TAB"]

Migrando do ESX? Suba o servidor uma vez e rode convertinventory esx no console do servidor para converter os inventários dos jogadores, depois reinicie. Se o seu banco do ESX tiver uma tabela items, o ox_inventory copia para o data/items.lua os itens que ele ainda não conhece e pede para você reiniciar.

Se você está montando um servidor do zero, Como criar um servidor de FiveM explica antes o txAdmin e os recipes de framework.

Como adicionar um item personalizado

Todo item precisa estar definido em ox_inventory/data/items.lua antes de poder existir em qualquer inventário. O arquivo retorna uma tabela: a key é o spawn name do item (por convenção, minúsculo e sem espaços) e o valor são as opções do item.

Como um item do ox_inventory é montado

O item válido mais simples:

['gold_ring'] = {
    label = 'Anel de ouro',
    weight = 20,
},

Campos do item

Estes são os campos documentados para o data/items.lua. O peso é em gramas.

CampoTipoO que faz
labelstringNome exibido. Obrigatório
weightnumberPeso de uma unidade, em gramas
stackbooleanColoque false para o item não empilhar em um slot
closebooleanColoque false para o inventário continuar aberto depois do uso
descriptionstringTexto exibido no tooltip do item
consumenumberQuantos são removidos ao usar. O padrão é 1. Um decimal como 0.2 remove 20% de durabilidade em vez disso. 0 não remove nada
degradenumberMinutos até o item degradar por completo
decaybooleanApaga o item quando a durabilidade chega a 0
allowArmedbooleanPermite usar com uma arma na mão
clienttableOpções de uso no client (abaixo)
servertableOpções no server, principalmente export
buttonstableAções extras no menu de clique direito, cada uma com label e action(slot)

A tabela client controla o que acontece do lado do jogador quando o item é usado:

CampoO que faz
usetimeDuração da barra de progresso em milissegundos
anim{ dict = '...', clip = '...' } tocada durante a barra de progresso
propProp anexado: model, pos, rot, e opcionalmente bone e rotOrder
disableControles desativados durante o uso: move, car, combat, mouse, sprint
cancelDeixa o jogador cancelar a barra de progresso
exportExport do client chamado no uso, no formato 'resourceName.exportName'
eventEvento do client disparado depois do uso
statusAlterações de status depois do uso (fome, sede e afins)
add / removeFunções chamadas quando o jogador ganha ou perde o item, recebendo o novo total

Um exemplo completo

Aqui vai um energético que toca uma animação de beber com uma lata na mão e depois dá um boost rápido de corrida. Ele é baseado no item sprunk que já vem no ox_inventory.

['energy_drink'] = {
    label = 'Energético',
    weight = 350,
    stack = true,
    close = true,
    description = 'Corra um pouco mais rápido por um tempinho.',
    client = {
        anim = { dict = 'mp_player_intdrink', clip = 'loop_bottle' },
        prop = {
            model = `prop_ld_can_01`,
            pos = vec3(0.01, 0.01, 0.06),
            rot = vec3(5.0, 5.0, -180.5)
        },
        usetime = 2500,
        export = 'my_items.energy_drink',
    },
},

O prop precisa ser um modelo que o jogo consiga carregar. Se você quer uma lata ou ferramenta personalizada na mão do jogador, precisa fazer o stream dela antes; Props personalizados no FiveM explica como.

Imagens dos itens

As imagens dos itens ficam em ox_inventory/web/images/, com o nome exatamente igual à key do item:

Um ícone de inventário gerado com a ferramenta de imagens do BLDR

ox_inventory/web/images/energy_drink.png

O que você precisa saber:

  • Use PNG. A UI monta o caminho como <name>.png, e o fxmanifest.lua do resource só inclui web/images/*.png. Um .webp ou .jpg não vai carregar.
  • Tamanho: as imagens que vêm com o ox_inventory têm 100 x 100 pixels com fundo transparente. Siga esse padrão para ficar tudo consistente.
  • Os nomes diferenciam maiúsculas e minúsculas em hosts Linux. Energy_Drink.png não é energy_drink.png.
  • Dá para mudar o caminho base com a convar inventory:imagepath se você hospeda as imagens em outro lugar.

Se você não tem um ícone, o gerador de imagens da BLDR cria um a partir de um prompt de texto; peça um único objeto com fundo transparente e depois redimensione para 100 x 100.

Como deixar um item usável

O ox_inventory te dá três formas de rodar código quando um item é usado. Escolha uma por item.

1. Export no client (o recomendado pela documentação)

Defina client.export no item e depois crie esse export no seu próprio resource. Sua função recebe os dados do item e o slot, decide se o item pode ser usado e devolve o controle para o ox_inventory com useItem. Essa chamada roda as validações no servidor, toca a barra de progresso, a animação e o prop, e remove o item.

-- my_items/client.lua
exports('energy_drink', function(data, slot)
    if IsPedInAnyVehicle(cache.ped, false) then
        return lib.notify({ type = 'error', description = 'Não dá enquanto dirige' })
    end

    exports.ox_inventory:useItem(data, function(data)
        if not data then return end

        SetRunSprintMultiplierForPlayer(cache.playerId, 1.2)
        lib.notify({ description = 'Você está a mil' })

        SetTimeout(30000, function()
            SetRunSprintMultiplierForPlayer(cache.playerId, 1.0)
        end)
    end)
end)

A tabela cache vem do ox_lib, então adicione shared_script '@ox_lib/init.lua' no fxmanifest.lua do seu resource. Se o useItem retornar nil em data, o servidor recusou o uso e o item não é consumido.

2. Export no server

Em vez disso, defina server.export = 'my_items.energy_drink' e o export é chamado no servidor com um nome de evento. Retorne false durante usingItem para bloquear o uso.

-- my_items/server.lua
exports('energy_drink', function(event, item, inventory, slot, data)
    if event == 'usingItem' then
        -- validações antes do uso; retorne false para cancelar
    end

    if event == 'usedItem' then
        -- o item foi usado e consumido
    end
end)

3. Itens usáveis do framework

Se um item não tem opções de uso em client, nem server.export, nem valor de consume, o ox_inventory repassa o uso para o seu framework. O código que você já tem continua funcionando:

  • ESX: ESX.RegisterUsableItem('energy_drink', function(source) ... end)
  • Qbox: exports.qbx_core:CreateUseableItem('energy_drink', function(source, item) ... end)

A documentação lembra que o sistema nativo é mais seguro e já te dá barra de progresso, animações e props de graça, então prefira as opções 1 ou 2 para itens novos.

Como dar e remover itens

Toda alteração de item acontece no servidor. Verifique a capacidade primeiro, depois adicione:

local ox_inventory = exports.ox_inventory

local function giveEnergyDrink(source, count)
    if not ox_inventory:CanCarryItem(source, 'energy_drink', count) then
        return false
    end

    local success, response = ox_inventory:AddItem(source, 'energy_drink', count)
    if not success then
        print(('AddItem failed: %s'):format(response))
    end

    return success
end

O AddItem retorna false mais um motivo, como invalid_item (o item não está no items.lua), invalid_count ou invalid_inventory.

Outros exports do server que você vai usar o tempo todo:

ExportPara que serve
RemoveItem(inv, item, count, metadata, slot)Remover itens
GetItemCount(inv, itemName, metadata)Contar quantos um jogador tem
Search(inv, 'count', items)Contar vários itens em uma só chamada
CanCarryItem(inv, item, count, metadata)Verificar peso e slots livres

O argumento inv aceita o server id de um jogador, o id de um stash ou uma tabela com id e owner.

Metadata

A metadata permite que uma única definição de item se comporte como vários itens. É uma tabela presa a cada slot, passada como quarto argumento do AddItem:

exports.ox_inventory:AddItem(source, 'gold_ring', 1, {
    label = 'Anel de ouro gravado',
    description = 'Para M, para sempre.',
    engraving = 'M + J',
})

Algumas keys são especiais: label, weight, description, image (um nome de arquivo na pasta de imagens, sem .png) e imageurl sobrescrevem o que o jogador vê, e type aparece no canto do tooltip. Qualquer outra key fica salva e pode ser lida pelos seus scripts. Para mostrar keys personalizadas no tooltip, chame o export do client exports.ox_inventory:displayMetadata({ engraving = 'Gravação' }).

Itens com degrade ganham automaticamente um valor durability na metadata.

Shops e stashes, por cima

Os shops são definidos no data/shops.lua com um nome, uma lista inventory de entradas { name = 'item', price = 10 }, e locations ou targets. Você também pode registrar em runtime pelo servidor com exports.ox_inventory:RegisterShop(name, data), mas shops criados em runtime não ganham blips nem zonas de target.

Os stashes são registrados no server e abertos no client:

-- server
exports.ox_inventory:RegisterStash('mechanic_parts', 'Peças da mecânica', 50, 100000, false, { mechanic = 0 })

-- client
exports.ox_inventory:openInventory('stash', 'mechanic_parts')

Os argumentos são id, label, slots, peso máximo, owner e groups. Um owner igual a true dá a cada jogador sua própria cópia; false cria um único stash compartilhado.

Erros comuns e como resolver

SintomaCausa provável
UI has not been builtVocê baixou o source code. Use o asset ox_inventory.zip do release
No such export ... in resource ox_inventoryO ox_inventory não conseguiu iniciar (olhe o console logo acima), ou seu script dá start antes dele
Item aparece sem imagemO arquivo não é .png, o nome não bate com a key do item ou as maiúsculas estão diferentes
AddItem retorna invalid_itemErro de digitação no nome do item, ou você editou o items.lua sem reiniciar
Item não faz nada ao usarNão tem client.export, server.export nem handler de item usável do framework registrado, ou o nome do export não bate com 'resource.export'
Conteúdo de stash ou porta-malas some depois do restartO servidor foi derrubado em vez de reiniciado pelo txAdmin. Os inventários salvam a cada 5 minutos, nos restarts do txAdmin e com o comando de console saveinv
Inventário do ESX vazio depois da trocaO convertinventory esx não foi rodado, ou o servidor não foi reiniciado depois

Confira também se o inventory:framework bate com o seu framework. O padrão é esx, então um servidor Qbox sem a convar vai quebrar de jeitos bem confusos.

Escrevendo scripts de itens mais rápido

A maioria dos itens personalizados segue o mesmo padrão: uma entrada no items.lua, uma imagem e um export de client ou server com o efeito. O gerador de scripts da BLDR conhece Qbox, QBCore, ESX, ox_lib, ox_target e ox_inventory, então você descreve um item e o efeito dele e recebe um Lua que já usa useItem e as chamadas certas do framework desde o começo.

Perguntas frequentes

O ox_inventory funciona com QBCore?

Não oficialmente. O release atual suporta ox_core, ESX, Qbox e ND Core. Servidores QBCore que querem o ox_inventory normalmente migram para o Qbox, que mantém a maioria dos scripts de QBCore funcionando pelo bridge de compatibilidade.

Preciso reiniciar o servidor depois de adicionar um item?

Sim. O data/items.lua é lido quando o ox_inventory inicia, então itens novos ou alterados só aparecem depois de um restart.

Onde coloco os itens no Qbox?

No ox_inventory/data/items.lua, igual em qualquer outro framework. O Qbox usa o ox_inventory como sistema de itens, então não existe um arquivo separado de shared items para editar.

Dá para fazer um item que abre o próprio armazenamento, tipo uma mochila?

Dá. O ox_inventory chama isso de containers. Defina o item com stack = false e depois configure os slots e o peso máximo em modules/items/containers.lua ou com o export do server setContainerProperties.

Continue lendo