# Catálogo de tatuagens

O catálogo reúne tatuagens de CXG Base e dos packs instalados. Packs externos são opcionais: você pode ativar nenhum, um ou vários. Se um pack estiver ausente ou parado, suas tatuagens ficam ocultas na loja e o catálogo CXG Base continua disponível.

Consulte também [Introdução](https://docs.cxgstudios.com/docs/pt-BR/01-cxg-tattoos/01-introduccion.md), [Instalação](https://docs.cxgstudios.com/docs/pt-BR/01-cxg-tattoos/02-instalacion.md), [Configuração](https://docs.cxgstudios.com/docs/pt-BR/01-cxg-tattoos/03-configuracion.md), [Integrações](https://docs.cxgstudios.com/docs/pt-BR/01-cxg-tattoos/05-integraciones.md) e [Interface](https://docs.cxgstudios.com/docs/pt-BR/01-cxg-tattoos/06-interfaz.md).

## Packs opcionais

A configuração inicial inclui estas fontes opcionais:

| ID | Recurso | Arquivo do catálogo |
| --- | --- | --- |
| `xgc-classic` | `xgc_TattooClasic` | `tatoo_clasic_full_packconfigdump.json` |
| `xgc-gangs` | `xgc_TattooGangs` | `gangs_full_packconfigdump.json` |
| `xgc-japanese-mafia` | `xgc_TattooJapaneseMafia` | `japanese_mafia_full_packconfigdump.json` |
| `xgc-police` | `xgc_TattooPolice` | `police_full_packconfigdump.json` |
| `xgc-world-countries` | `xgc_TattooWorldCountries` | `world_country_full_packconfigdump.json` |
| `cxg-blackout` | `CXGtatoo_balckout` | `blackout_full_packconfigdump.json` |

Instale apenas os packs que possui e inicie-os antes de `cxg-tattoos`. Mantenha o nome do recurso e o caminho exatamente como existem no servidor, respeitando maiúsculas e minúsculas. Para ocultar temporariamente uma fonte, defina `enabled` como `false`; para exibi-la novamente, use `true` e confirme que o recurso foi iniciado.

CXG Base usa `shared/tattoos.json` dentro do recurso. A fonte `native-game` obtém designs das tatuagens nativas do jogo e vem desativada. Para usá-la, configure também as fontes de validação em `native.serverMetas` com os recursos e arquivos reais do servidor. A entrada de exemplo aponta para `tatto` e `shop_tattoo.meta`; ela não presume que esse recurso esteja instalado. Ativar apenas `enabled` não garante que esses designs possam ser comprados.

## Adicionar uma fonte JSON

Cada objeto em `Config.TattooCatalog.sources` configura uma fonte. Este exemplo segue o formato dos recursos de pack e pode ser adaptado ao nome real do recurso e do arquivo:

```lua
{
    id = 'mi-pack',
    label = 'Mi Pack',
    color = '#62b6cb',
    enabled = true,
    resource = 'mi_pack',
    path = 'tattoos.json',
    thumbnailPattern = 'miniatures/{Name}.webp',
    root = { mode = 'auto', field = 'Overlays' },
    defaults = {
        collection = 'mi_pack_overlays',
        zone = 'ZONE_TORSO',
        price = 5000,
        requiredLevel = 1,
        overlayTarget = 'male',
    },
}
```

`id` deve identificar a fonte de forma estável; `label` e `color` ajudam a reconhecê-la na interface. `resource` e `path` apontam para o JSON. O arquivo deve estar em um recurso disponível. Não adicione o mesmo design em duas fontes, a menos que queira exibi-lo duas vezes; `deduplicateAcrossSources` permite remover duplicatas entre elas.

Estes ajustes gerais ficam em `Config.TattooCatalog`:

| Campo | Valor inicial | Uso |
| --- | --- | --- |
| `deduplicate` | `true` | Remove designs duplicados dentro de uma fonte. |
| `deduplicateAcrossSources` | `false` | Permite manter separados designs de fontes diferentes. |
| `serverFallback` | `true` | Solicita ao servidor uma fonte que o cliente não consegue ler. |
| `serverFallbackTimeoutMs` | `7000` | Tempo máximo de espera dessa solicitação, em milissegundos. |

O fallback de leitura não torna disponível um pack parado.

## Formato de cada tatuagem

O arquivo pode ser um array JSON ou um objeto cuja propriedade contenha o array. Com `root.mode = 'auto'`, o leitor aceita os dois formatos; com `root.mode = 'field'`, `root.field` indica onde está a lista. `root.mode = 'array'` exige um array na raiz.

Este array mostra o formato JSON. A coleção e os hashes do exemplo são fictícios: substitua-os pelos nomes reais do pack instalado. Adicionar uma entrada JSON não instala os overlays gráficos.

```json
[
  {
    "Collection": "mi_pack_overlays",
    "Name": "Rosa del desierto",
    "HashNameMale": "MP_MI_PACK_ROSE_M",
    "HashNameFemale": "MP_MI_PACK_ROSE_F",
    "Zone": "ZONE_TORSO",
    "Price": 5000,
    "Xp": 15,
    "RequiredLevel": 2
  }
]
```

`Collection` e pelo menos um hash de overlay são necessários para identificar o design. Inclua `HashNameMale` e `HashNameFemale` se a tatuagem tiver uma variante para cada personagem. Use uma destas zonas: `ZONE_HEAD`, `ZONE_TORSO`, `ZONE_LEFT_ARM`, `ZONE_RIGHT_ARM`, `ZONE_LEFT_LEG` ou `ZONE_RIGHT_LEG`. `Name` é o nome exibido ao comprador. Se omitir `Price`, será usado o preço padrão da fonte; se omitir `RequiredLevel`, será usado `defaults.requiredLevel`, cujo valor inicial é 1. A XP pode vir da tatuagem ou da configuração de níveis.

Para arquivos com nomes de campos diferentes, ajuste `fields` em `Config.TattooCatalog`. Cada entrada dessa tabela é uma lista de aliases consultados para localizar o valor correspondente. Por exemplo, um arquivo que usa `OverlayHash`, `Cost` e `BodyZone` pode ser mapeado assim:

```lua
fields = {
    collection = { 'Collection', 'CollectionName' },
    name = { 'Name', 'DisplayName' },
    overlay = { 'OverlayHash' },
    hashNameMale = { 'MaleOverlay' },
    hashNameFemale = { 'FemaleOverlay' },
    zone = { 'BodyZone' },
    price = { 'Cost' },
    xp = { 'Xp', 'Experience' },
    requiredLevel = { 'RequiredLevel' },
}
```

Você também pode atribuir valores comuns por `rootFields`, como um nome de coleção ou zona definido uma única vez no objeto raiz. `defaults` de cada fonte preenche os valores ausentes. Se o JSON tiver apenas um campo genérico, como `OverlayHash`, `defaults.overlayTarget` indica se deve ser tratado como tatuagem masculina (`male`) ou feminina (`female`).

Formatos muito diferentes podem ser transformados pelas funções opcionais `converters.decode(decoded, settings)` ou `converters.entry(entry, context)` na configuração. A primeira adapta o documento inteiro; a segunda adapta cada design. Retorne uma tabela com os campos preparados para o mapeamento normal.

## Miniaturas

Para usar imagens que ficam no próprio pack, mantenha a pasta `miniatures/` nesse recurso e defina um padrão como:

```lua
thumbnailPattern = 'miniatures/{Name}.webp'
```

`{Name}`, `{HashNameMale}`, `{HashNameFemale}` e `{HashName}` são substituídos por dados da tatuagem. O arquivo resultante deve existir no recurso, por exemplo `miniatures/Rosa del desierto.webp`, e o recurso deve estar iniciado. A interface solicita cada miniatura quando necessário; não copie as imagens para o pacote CXG.

Também é possível definir `Thumbnail` ou `ThumbnailUrl` em uma entrada para indicar uma imagem específica. URLs `http://`, `https://` e `data:` são usadas diretamente. O caminho de uma miniatura local de um pack deve corresponder a `thumbnailPattern`; o arquivo deve existir e o recurso precisa servi-lo à NUI. Recursos externos devem manter o arquivo dentro do pack.

## Alterações pela configuração e pela administração

Edite a configuração para adicionar fontes, alterar sua leitura, ativar ou desativar packs e ajustar valores padrão. Use a administração do catálogo para mudar nomes, preços, níveis e disponibilidade das tatuagens sem editar o JSON. Alterações administrativas são salvas e permanecem após sincronizações do catálogo. A ação de restaurar valores devolve a tatuagem aos valores da fonte.

As tatuagens já compradas por um jogador continuam vinculadas ao personagem mesmo quando o pack de origem é temporariamente desativado. O pack volta a aparecer na loja quando estiver disponível novamente.
