# Catalogue de tatouages

Le catalogue rassemble les tatouages de CXG Base et des packs que vous avez installés. Les packs externes sont facultatifs : vous pouvez choisir de n’en activer aucun, un seul ou plusieurs. Si un pack manque ou est arrêté, ses tatouages sont masqués dans la boutique et le catalogue CXG Base reste disponible.

Consultez aussi [Introduction](https://docs.cxgstudios.com/docs/fr/01-cxg-tattoos/01-introduccion.md), [Installation](https://docs.cxgstudios.com/docs/fr/01-cxg-tattoos/02-instalacion.md), [Configuration](https://docs.cxgstudios.com/docs/fr/01-cxg-tattoos/03-configuracion.md), [Intégrations](https://docs.cxgstudios.com/docs/fr/01-cxg-tattoos/05-integraciones.md) et [Interface](https://docs.cxgstudios.com/docs/fr/01-cxg-tattoos/06-interfaz.md).

## Packs facultatifs

La configuration initiale comprend les sources facultatives suivantes :

| ID | Ressource | Fichier du catalogue |
| --- | --- | --- |
| `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` |

Installez uniquement les packs que vous possédez et démarrez-les avant `cxg-tattoos`. Conservez le nom de la ressource et son chemin tels qu’ils existent sur votre serveur, en respectant les majuscules et minuscules. Pour masquer temporairement une source, définissez `enabled` sur `false` ; pour la réafficher, repassez-le à `true` et vérifiez que la ressource est démarrée.

CXG Base utilise `shared/tattoos.json` dans la ressource. La source `native-game` récupère les modèles des tatouages natifs du jeu et est désactivée par défaut. Pour l’utiliser, configurez également les sources de validation de `native.serverMetas` avec les ressources et fichiers réels de votre serveur. L’entrée d’exemple pointe vers `tatto` et `shop_tattoo.meta` ; elle ne suppose pas que cette ressource est installée. Activer `enabled` ne garantit pas à lui seul que ces modèles pourront être achetés.

## Ajouter une source JSON

Chaque objet de `Config.TattooCatalog.sources` configure une source. Cet exemple suit la structure des ressources de pack et peut être adapté au nom réel de la ressource et à son fichier :

```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` doit identifier la source de manière stable ; `label` et `color` permettent de la reconnaître dans l’interface. `resource` et `path` pointent vers le JSON. Le fichier doit se trouver dans une ressource disponible. N’ajoutez pas deux fois le même modèle dans des sources différentes, sauf si vous voulez l’afficher en double ; `deduplicateAcrossSources` permet de supprimer les doublons entre sources.

Ces réglages généraux se trouvent dans `Config.TattooCatalog` :

| Champ | Valeur initiale | Utilisation |
| --- | --- | --- |
| `deduplicate` | `true` | Supprime les modèles en double dans une source. |
| `deduplicateAcrossSources` | `false` | Permet de conserver séparés les modèles de sources différentes. |
| `serverFallback` | `true` | Demande au serveur une source que le client ne peut pas lire. |
| `serverFallbackTimeoutMs` | `7000` | Délai d’attente maximal de cette requête, en millisecondes. |

La lecture de secours ne rend pas disponible un pack arrêté.

## Format de chaque tatouage

Le fichier peut être un tableau JSON ou un objet dont une propriété contient le tableau. Avec `root.mode = 'auto'`, le lecteur accepte les deux formats ; avec `root.mode = 'field'`, `root.field` indique où se trouve la liste. `root.mode = 'array'` impose un tableau à la racine.

Ce tableau montre le format JSON. La collection et les hashes de l’exemple sont fictifs : remplacez-les par les noms réels du pack installé. Ajouter une entrée JSON n’installe pas les overlays graphiques.

```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` et au moins un hash d’overlay sont nécessaires pour identifier le modèle. Incluez `HashNameMale` et `HashNameFemale` si le tatouage possède une variante pour chaque personnage. Utilisez l’une de ces zones : `ZONE_HEAD`, `ZONE_TORSO`, `ZONE_LEFT_ARM`, `ZONE_RIGHT_ARM`, `ZONE_LEFT_LEG` ou `ZONE_RIGHT_LEG`. `Name` est le nom affiché à l’acheteur. Si vous omettez `Price`, le prix par défaut de la source est utilisé ; si vous omettez `RequiredLevel`, `defaults.requiredLevel` est utilisé, dont la valeur initiale est 1. L’XP peut être définie par le tatouage ou par la configuration des niveaux.

Pour les fichiers utilisant d’autres noms de champs, réglez `fields` dans `Config.TattooCatalog`. Chaque entrée de cette table est une liste d’alias consultés pour trouver la valeur correspondante. Par exemple, un fichier qui utilise `OverlayHash`, `Cost` et `BodyZone` peut être mappé ainsi :

```lua
fields = {
    collection = { 'Collection', 'CollectionName' },
    name = { 'Name', 'DisplayName' },
    overlay = { 'OverlayHash' },
    hashNameMale = { 'MaleOverlay' },
    hashNameFemale = { 'FemaleOverlay' },
    zone = { 'BodyZone' },
    price = { 'Cost' },
    xp = { 'Xp', 'Experience' },
    requiredLevel = { 'RequiredLevel' },
}
```

Vous pouvez également attribuer des valeurs communes depuis `rootFields`, par exemple un nom de collection ou une zone définis une seule fois dans l’objet racine. Les `defaults` de chaque source complètent les valeurs manquantes. Si votre JSON contient un seul champ générique, comme `OverlayHash`, `defaults.overlayTarget` indique s’il doit être traité comme un tatouage masculin (`male`) ou féminin (`female`).

Les formats très différents peuvent être transformés à l’aide des fonctions facultatives `converters.decode(decoded, settings)` ou `converters.entry(entry, context)` dans la configuration. La première adapte le document entier ; la seconde adapte chaque modèle. Renvoyez une table contenant les champs préparés pour le mappage normal.

## Miniatures

Pour utiliser les images fournies dans le même pack, conservez le dossier `miniatures/` dans cette ressource et définissez un modèle tel que :

```lua
thumbnailPattern = 'miniatures/{Name}.webp'
```

`{Name}`, `{HashNameMale}`, `{HashNameFemale}` et `{HashName}` sont remplacés par les données du tatouage. Le fichier obtenu doit exister dans la ressource, par exemple `miniatures/Rosa del desierto.webp`, et la ressource doit être démarrée. L’interface demande chaque miniature lorsqu’elle en a besoin ; ne copiez pas les images dans le paquet CXG.

Vous pouvez également définir `Thumbnail` ou `ThumbnailUrl` dans une entrée pour indiquer une image précise. Les URL `http://`, `https://` et `data:` sont utilisées telles quelles. Le chemin d’une miniature locale d’un pack doit correspondre à son `thumbnailPattern` ; le fichier doit exister et la ressource doit pouvoir le servir à la NUI. Les ressources externes doivent conserver leur fichier dans le pack.

## Modifications depuis la configuration et l’administration

Modifiez la configuration pour ajouter des sources, changer leur lecture, activer ou désactiver des packs et régler leurs valeurs par défaut. Utilisez l’administration du catalogue pour changer le nom, le prix, le niveau et la disponibilité des tatouages sans modifier le JSON. Les modifications administratives sont enregistrées et résistent aux synchronisations du catalogue. L’action de réinitialisation rétablit les valeurs de ce tatouage telles qu’elles sont définies par sa source.

Les tatouages déjà achetés par un joueur restent associés à son personnage même si le pack qui les fournissait est temporairement désactivé. Le pack reste absent de la boutique jusqu’à ce qu’il soit de nouveau disponible.

