Tattoo catalog
The catalog brings together tattoos from CXG Base and the packs you have installed. External packs are optional: you can enable none, one, or several. If a pack is missing or stopped, its tattoos are hidden from the shop and the CXG Base catalog remains available.
Also see Introduction, Installation, Configuration, Integrations, and Interface.
Optional packs
The initial configuration includes these optional sources:
| ID | Resource | Catalog file |
|---|---|---|
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 |
Install only packs you own and start them before cxg-tattoos. Keep the resource name and path as they exist on your server, respecting uppercase and lowercase letters. To temporarily hide a source, set its enabled to false; to show it again, set it to true and make sure the resource is started.
CXG Base uses shared/tattoos.json inside the resource. The native-game source reads native in-game tattoos and is disabled by default. To use it, also configure the validation sources in native.serverMetas with the actual resources and files on your server. The example entry points to tatto and shop_tattoo.meta; it does not assume that resource is installed. Setting enabled by itself does not guarantee that those designs can be purchased.
Add a JSON source
Each object in Config.TattooCatalog.sources configures a source. This example follows the pack resource format and can be adapted with the actual resource name and its file:
{
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 must identify the source consistently; label and color help identify it in the interface. resource and path point to the JSON file. The file must be inside an available resource. Do not add the same design to two sources unless you want it to appear twice; deduplicateAcrossSources can remove duplicates between them.
These general settings are in Config.TattooCatalog:
| Field | Initial value | Purpose |
|---|---|---|
deduplicate | true | Removes duplicate designs within a source. |
deduplicateAcrossSources | false | Keeps designs from different sources separate. |
serverFallback | true | Requests a source from the server when the client cannot read it. |
serverFallbackTimeoutMs | 7000 | Maximum wait for that request, in milliseconds. |
The read fallback does not make a stopped pack available.
Tattoo entry format
The file can be a JSON array or an object whose property contains the array. With root.mode = 'auto', the reader accepts both formats; with root.mode = 'field', root.field specifies where the list is. root.mode = 'array' forces an array at the root.
This array shows the JSON format. The collection and hashes in the example are fictional: replace them with the actual names from the installed pack. Adding a JSON entry does not install the graphic overlays.
[
{
"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 and at least one overlay hash are required to identify the design. Include HashNameMale and HashNameFemale if the tattoo has a variant for each character. Use one of these zones: ZONE_HEAD, ZONE_TORSO, ZONE_LEFT_ARM, ZONE_RIGHT_ARM, ZONE_LEFT_LEG, or ZONE_RIGHT_LEG. Name is the name buyers will see. If you omit Price, the source's default price is used; if you omit RequiredLevel, defaults.requiredLevel is used, initially set to 1. XP can come from the tattoo or the level configuration.
For files with different field names, adjust fields in Config.TattooCatalog. Each entry in that table is a list of aliases checked to find the corresponding value. For example, a file that uses OverlayHash, Cost, and BodyZone can be mapped like this:
fields = {
collection = { 'Collection', 'CollectionName' },
name = { 'Name', 'DisplayName' },
overlay = { 'OverlayHash' },
hashNameMale = { 'MaleOverlay' },
hashNameFemale = { 'FemaleOverlay' },
zone = { 'BodyZone' },
price = { 'Cost' },
xp = { 'Xp', 'Experience' },
requiredLevel = { 'RequiredLevel' },
}
You can also assign common values through rootFields, such as a collection name or zone defined once in the root object. Each source's defaults fills in any missing values. If your JSON contains a single generic field, such as OverlayHash, defaults.overlayTarget specifies whether it should be treated as a male (male) or female (female) tattoo.
Very different formats can be transformed with the optional functions converters.decode(decoded, settings) or converters.entry(entry, context) in the configuration. The first adapts the entire document; the second adapts each design. Return a table with the fields prepared for normal mapping.
Thumbnails
To use images stored in the same pack, keep its miniatures/ folder in that resource and define a pattern such as:
thumbnailPattern = 'miniatures/{Name}.webp'
{Name}, {HashNameMale}, {HashNameFemale}, and {HashName} are replaced with tattoo data. The resulting file must exist in the resource, for example miniatures/Rosa del desierto.webp, and the resource must be started. The interface requests each thumbnail when needed; do not copy images into the CXG package.
You can also set Thumbnail or ThumbnailUrl on an entry to specify an image. http://, https://, and data: URLs are used as-is. A local pack thumbnail path must match its thumbnailPattern; the file must exist and the resource must be able to serve it to the NUI. External resources must keep their file inside the pack.
Changes through configuration and administration
Edit the configuration to add sources, change how they are read, enable or disable packs, and adjust their default values. Use catalog administration to change tattoo names, prices, levels, and availability without editing the JSON. Administrative changes are saved and persist across catalog synchronization. The restore action returns that tattoo to its source values.
Tattoos a player has already purchased remain linked to their character even if the pack that provided them is temporarily turned off. The pack does not appear in the shop again until it is available.