Tutorial 2026-04-19

Criar Addons de Roupa Personalizada para FiveM

OntelMonke

OntelMonke

Admin & Developer na Agency Scripts

Compreendendo o sistema de roupas do GTA V

GTA V usa um sistema de roupas baseado em componentes onde cada peça de roupa é um "drawable" dentro de um slot de componente específico. Existem 12 slots de componentes em um ped, que vão desde a cabeça (componente 0), passando pelos sapatos (componente 6), até bolsas e acessórios. Cada slot de componente pode conter vários drawables e cada drawable pode ter diversas variações de textura. Por exemplo, o componente 11 (tops) pode ter o drawable 15 (uma jaqueta de couro) com texturas de 0 a 3 representando variantes de cores preta, marrom, vermelha e branca. Compreender essa hierarquia de componentes, drawables e texturas é essencial antes de criar roupas personalizadas, porque cada peça adicionada deve se encaixar nessa estrutura existente. O modelo multiplayer (MP) ped adiciona outra camada com seu próprio mapeamento drawable que difere dos personagens single-player, e os servidores FiveM usam exclusivamente os modelos MP freemode.

Estrutura de recursos e streaming

Roupas personalizadas no FiveM funcionam por meio do sistema de streaming. Você cria um recurso que instrui o jogo a carregar arquivos drawable e de textura adicionais junto com os ativos básicos do jogo. A estrutura de recursos segue convenções de nomenclatura rígidas que o mecanismo de jogo usa para identificar a qual modelo ped, componente e índice drawable cada arquivo pertence. Errar na estrutura das pastas é a causa mais comum de roupas não aparecerem no jogo. Seu recurso precisa de um fxmanifest.lua que declare os arquivos de streaming, e os dados reais das roupas vão para um diretório stream com a hierarquia de subpastas correta.

-- fxmanifest.lua for a clothing addon
fx_version 'cerulean'
game 'gta5'

-- The resource name matters: it determines load priority
-- Prefix with zzz_ to ensure it loads after base game assets
this_is_a_map 'yes'
lua54 'yes'

-- All streaming assets inside /stream/ are auto-detected
-- No need to list individual files

A pasta stream segue uma hierarquia precisa. Para roupas masculinas MP freemode, os arquivos vão para stream/mp_m_freemode_01_mp_m_[dlcname]/. Para mulheres, substitua mp_m por mp_f. Dentro dessa pasta, você coloca os arquivos YDD (dicionário drawable), YTD (dicionário de textura) e YMT (metadados). A convenção de nomenclatura codifica qual componente e índice desenhável cada arquivo representa. Um arquivo chamado mp_m_freemode_01_mp_m_mypack_jbib_000_u.ydd é drawable 0 para o componente 11 (jbib = jaqueta/tops) no ped freemode masculino do pacote DLC "mypack".

-- Folder structure example
stream/
  mp_m_freemode_01_mp_m_mypack/
    mp_m_freemode_01_mp_m_mypack.ymt          -- metadata file
    mp_m_freemode_01_mp_m_mypack_jbib_000_u.ydd   -- tops drawable 0
    mp_m_freemode_01_mp_m_mypack_jbib_diff_000_a_uni.ytd  -- texture for tops 0
    mp_m_freemode_01_mp_m_mypack_jbib_001_u.ydd   -- tops drawable 1
    mp_m_freemode_01_mp_m_mypack_jbib_diff_001_a_uni.ytd  -- texture for tops 1
    mp_m_freemode_01_mp_m_mypack_lowr_000_u.ydd   -- pants drawable 0
    mp_m_freemode_01_mp_m_mypack_lowr_diff_000_a_uni.ytd  -- texture for pants 0

IDs de componentes e convenções de nomenclatura

Cada componente da roupa possui uma abreviatura específica usada na nomenclatura de arquivos. Memorizá-los é fundamental porque um único erro de digitação significa que o jogo não consegue encontrar seu ativo. O mapa de componentes é:cabeça(componente 0, sem roupa),berdo(1, máscaras),cabelo(2),uppr(3, braços/luvas),mais baixo(4, calças/pernas),mão(5, bolsas/pára-quedas),pés(6, sapatos),tesão(7, acessórios como correntes),contas(8, camisetas/acessórios corporais),tarefa(9, armadura corporal),declinar(10, decalques/emblemas), ejbib(11, tops/jaquetas). Os adereços usam um sistema diferente:p_head(chapéus),p_olhos(copos),p_ears(brincos) ep_lwrist/p_rpulso(relógios/pulseiras).

-- Component ID reference for scripting
local ComponentNames = {
    [0]  = 'head',   -- Face (not clothing)
    [1]  = 'berd',   -- Masks
    [2]  = 'hair',   -- Hair styles
    [3]  = 'uppr',   -- Arms / Gloves
    [4]  = 'lowr',   -- Pants / Legs
    [5]  = 'hand',   -- Bags / Parachutes
    [6]  = 'feet',   -- Shoes
    [7]  = 'teef',   -- Accessories (chains, ties)
    [8]  = 'accs',   -- Undershirts
    [9]  = 'task',   -- Body Armor
    [10] = 'decl',   -- Decals / Badges
    [11] = 'jbib',   -- Tops / Jackets
}

-- Get total drawables for a component (useful for clothing menus)
local function GetMaxDrawables(ped, componentId)
    return GetNumberOfPedDrawableVariations(ped, componentId)
end

-- Get texture count for a specific drawable
local function GetMaxTextures(ped, componentId, drawableId)
    return GetNumberOfPedTextureVariations(ped, componentId, drawableId)
end

-- Apply clothing to ped
local function SetClothing(ped, componentId, drawableId, textureId)
    SetPedComponentVariation(ped, componentId, drawableId, textureId, 0)
end

Compreendendo os arquivos YMT

O arquivo YMT (Ped Metadata) é a cola que mantém unida uma embalagem de roupas. É um arquivo baseado em XML que informa ao mecanismo de jogo quantos drawables existem em cada componente, quantas texturas cada drawable possui, que áudio reproduzir quando a roupa se move e várias propriedades de renderização. Sem um YMT configurado corretamente, o jogo não reconhecerá seus drawables, mesmo que os arquivos YDD e YTD sejam perfeitamente elaborados. O YMT deve listar cada combinação de drawable e textura em seu pacote. Uma única entrada ausente significa que o item ficará invisível. A edição manual de arquivos YMT está sujeita a erros, e é por isso que a maioria dos criadores usa ferramentas como CodeWalker ou geradores YMT dedicados que criam o arquivo automaticamente a partir do conteúdo da pasta de ativos.

<!-- Simplified YMT structure (XML representation) -->
<CPedVariationInfo>
  <availComp>
    <!-- Bitfield indicating which components have data -->
    <Item value="2048" />  <!-- Only jbib (component 11) -->
  </availComp>
  <compInfos>
    <Item> <!-- Component 11 (jbib / tops) -->
      <drawblDict>
        <Item>  <!-- Drawable 0 -->
          <numAlternatives value="0" />
          <numTexVariations value="3" />  <!-- 3 color variants -->
          <clothData>
            <ownsCloth value="false" />
          </clothData>
        </Item>
        <Item>  <!-- Drawable 1 -->
          <numAlternatives value="0" />
          <numTexVariations value="2" />  <!-- 2 color variants -->
          <clothData>
            <ownsCloth value="false" />
          </clothData>
        </Item>
      </drawblDict>
    </Item>
  </compInfos>
</CPedVariationInfo>

Variações de textura e qualidade

Cada drawable pode ter múltiplas variações de textura, que representam diferentes cores ou padrões do mesmo modelo de roupa. O arquivo de textura base usa o padrão de nomenclatura [pack]_[component]_diff_[drawableIndex]_[textureIndex]_uni.ytd. As texturas devem ser criadas em potências de dois (512x512, 1024x1024, 2048x2048) para compatibilidade ideal de GPU. Texturas de resolução mais alta parecem melhores, mas consomem mais VRAM, o que é um recurso limitado, especialmente em servidores onde os jogadores carregam dezenas de pacotes de roupas personalizados simultaneamente. Uma orientação prática é usar 1024x1024 para a maioria dos itens de vestuário e reservar 2048x2048 para itens com detalhes finos, como logotipos bordados ou padrões complexos. Cada arquivo YTD pode conter várias camadas de textura, incluindo mapas difusos (cor), normais (detalhes da superfície) e especulares (brilho), embora a maioria dos pacotes de roupas FiveM use apenas a camada difusa para manter os tamanhos dos arquivos gerenciáveis.

Construindo um script de menu de roupas

Depois que seu recurso de streaming estiver funcionando, você precisará de uma maneira para os jogadores navegarem e aplicarem as roupas. Um script de menu de roupas percorre todos os drawables disponíveis por componente e permite que os jogadores os visualizem em seu personagem em tempo real. A lógica principal usa GetNumberOfPedDrawableVariations para determinar quantos drawables existem para cada componente e, em seguida, SetPedComponentVariation para aplicar o selecionado. Envolva isso em um menu ox_lib ou NUI para uma experiência de usuário refinada. A parte complicada é lidar com visualizações em primeira pessoa e ângulos de câmera para que os jogadores possam ver o que estão experimentando sem problemas de recorte ou zoom.

-- client/clothing_menu.lua
local function OpenClothingMenu()
    local ped = PlayerPedId()
    local components = {}

    for compId = 0, 11 do
        local maxDrawables = GetNumberOfPedDrawableVariations(ped, compId)
        if maxDrawables > 0 then
            local currentDrawable = GetPedDrawableVariation(ped, compId)
            local currentTexture = GetPedTextureVariation(ped, compId)
            local maxTextures = GetNumberOfPedTextureVariations(ped, compId, currentDrawable)

            table.insert(components, {
                id = compId,
                label = ComponentNames[compId] or ('Component ' .. compId),
                drawable = currentDrawable,
                texture = currentTexture,
                maxDrawable = maxDrawables - 1,
                maxTexture = maxTextures - 1,
            })
        end
    end

    -- Build menu options
    local options = {}
    for _, comp in ipairs(components) do
        options[#options + 1] = {
            title = comp.label,
            description = ('Drawable: %d/%d | Texture: %d/%d'):format(
                comp.drawable, comp.maxDrawable, comp.texture, comp.maxTexture),
            onSelect = function()
                OpenComponentEditor(comp.id)
            end
        }
    end

    lib.registerContext({ id = 'clothing_menu', title = 'Wardrobe', options = options })
    lib.showContext('clothing_menu')
end

local function OpenComponentEditor(componentId)
    local ped = PlayerPedId()
    local maxDraw = GetNumberOfPedDrawableVariations(ped, componentId) - 1

    -- Interactive drawable browser with live preview
    local input = lib.inputDialog('Select Clothing', {
        { type = 'slider', label = 'Style', min = 0, max = maxDraw, default = GetPedDrawableVariation(ped, componentId) },
    })

    if input then
        local drawableId = input[1]
        local maxTex = GetNumberOfPedTextureVariations(ped, componentId, drawableId) - 1
        SetPedComponentVariation(ped, componentId, drawableId, 0, 0)

        if maxTex > 0 then
            local texInput = lib.inputDialog('Select Color', {
                { type = 'slider', label = 'Variant', min = 0, max = maxTex, default = 0 },
            })
            if texInput then
                SetPedComponentVariation(ped, componentId, drawableId, texInput[1], 0)
            end
        end
    end
end

Problemas comuns e solução de problemas

O problema mais frequente é a roupa parecer invisível ou errada. Isso quase sempre remonta a um arquivo YMT incorreto que não declara corretamente a contagem drawable ou a contagem de texturas. Verifique se o seu YMT lista o número exato de drawables e texturas que existem na sua pasta de stream. Outro problema comum é a ordem de carregamento dos recursos: se o seu pacote de roupas for carregado antes dos ativos do jogo base, os índices drawable podem colidir e substituir as roupas básicas. Prefixe o nome do seu recurso com zzz_ para garantir que ele seja carregado por último. O desfoque da textura geralmente indica que o acumulado no ano está usando uma resolução muito baixa ou que os mipmaps não foram gerados corretamente. Sempre gere mipmaps ao exportar seus arquivos YTD no CodeWalker. Finalmente, se as roupas aparecerem em modelos masculinos, mas não femininos ou vice-versa, verifique novamente se você tem pastas separadas para mp_m_freemode_01 e mp_f_freemode_01 com arquivos de malha com gênero adequado, já que os modelos ped masculinos e femininos têm estruturas de esqueleto diferentes e exigem geometria separada.

Otimizando o desempenho do servidor

Pacotes de roupas personalizados são um dos maiores contribuintes para o tamanho de download do servidor e para o uso de VRAM do cliente. Um único pacote mal otimizado com 100 itens de alta resolução pode adicionar gigabytes aos requisitos de download do seu servidor. Para manter tudo gerenciável, compacte suas texturas acumuladas no ano usando o formato DXT5 ou BC7, que fornece boa qualidade visual em uma fração do tamanho do arquivo bruto. Limite cada pacote a um número razoável de itens, normalmente de 20 a 50 peças, e divida coleções maiores em vários recursos que podem ser carregados de forma independente. Considere oferecer uma versão "leve" de pacotes populares com texturas de 512x512 para jogadores em hardware de baixo custo. No lado do script, evite chamar SetPedComponentVariation repetidamente em um loop porque cada chamada aciona uma atualização de modelo. Altere as roupas em lote coletando todas as atualizações de componentes e aplicando-as em sequência em um único quadro para minimizar o estouro visual e a sobrecarga de renderização.

Partilhar este artigo

Pronto para melhorar o teu servidor?

Explora os nossos scripts FiveM premium na loja Agency Scripts ou junta-te à nossa comunidade no Discord para suporte e atualizações.