# แคตตาล็อกรอยสัก

แคตตาล็อกรวมรอยสักจาก CXG Base และแพ็กที่คุณติดตั้ง แพ็กภายนอกเป็นตัวเลือก คุณจะไม่เปิดใช้แพ็กใดเลย เปิดใช้หนึ่งแพ็ก หรือหลายแพ็กก็ได้ หากแพ็กไม่มีอยู่หรือหยุดทำงาน รอยสักจากแพ็กนั้นจะถูกซ่อนจากร้าน ส่วนแคตตาล็อก CXG Base ยังใช้งานได้

อ่านเพิ่มเติมได้ที่ [บทนำ](https://docs.cxgstudios.com/docs/th/01-cxg-tattoos/01-introduccion.md), [การติดตั้ง](https://docs.cxgstudios.com/docs/th/01-cxg-tattoos/02-instalacion.md), [การตั้งค่า](https://docs.cxgstudios.com/docs/th/01-cxg-tattoos/03-configuracion.md), [การเชื่อมต่อระบบ](https://docs.cxgstudios.com/docs/th/01-cxg-tattoos/05-integraciones.md) และ [อินเทอร์เฟซ](https://docs.cxgstudios.com/docs/th/01-cxg-tattoos/06-interfaz.md)

## แพ็กเสริม

การตั้งค่าเริ่มต้นมีแหล่งข้อมูลเสริมต่อไปนี้:

| ID | รีซอร์ส | ไฟล์แคตตาล็อก |
| --- | --- | --- |
| `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` |

ติดตั้งเฉพาะแพ็กที่คุณมี และเริ่มทำงานก่อน `cxg-tattoos` ใช้ชื่อรีซอร์สและเส้นทางตามที่มีอยู่บนเซิร์ฟเวอร์ โดยคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ หากต้องการซ่อนแหล่งข้อมูลชั่วคราว ให้ตั้ง `enabled` เป็น `false`; หากต้องการแสดงอีกครั้ง ให้ตั้งเป็น `true` และตรวจสอบว่ารีซอร์สเริ่มทำงานแล้ว

CXG Base ใช้ `shared/tattoos.json` ภายในรีซอร์ส แหล่งข้อมูล `native-game` ดึงดีไซน์จากรอยสักดั้งเดิมในเกมและปิดใช้งานไว้ หากต้องการใช้ ให้ตั้งค่าแหล่งข้อมูลสำหรับตรวจสอบใน `native.serverMetas` ให้ตรงกับรีซอร์สและไฟล์จริงบนเซิร์ฟเวอร์ของคุณด้วย รายการตัวอย่างชี้ไปที่ `tatto` และ `shop_tattoo.meta`; ไม่ได้ยืนยันว่ามีรีซอร์สนั้นติดตั้งอยู่ การเปิด `enabled` อย่างเดียวไม่ได้รับประกันว่าจะซื้อดีไซน์เหล่านั้นได้

## เพิ่มแหล่งข้อมูล JSON

ออบเจ็กต์แต่ละรายการใน `Config.TattooCatalog.sources` ใช้ตั้งค่าแหล่งข้อมูล ตัวอย่างนี้ใช้รูปแบบของรีซอร์สแพ็ก และปรับใช้ได้โดยใส่ชื่อรีซอร์สกับไฟล์จริง:

```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` ต้องระบุแหล่งข้อมูลได้อย่างคงที่ ส่วน `label` และ `color` ใช้แยกแหล่งข้อมูลในอินเทอร์เฟซ `resource` และ `path` ชี้ไปยัง JSON ไฟล์ต้องอยู่ภายในรีซอร์สที่พร้อมใช้งาน อย่าเพิ่มดีไซน์เดียวกันไว้ในสองแหล่งข้อมูล เว้นแต่ต้องการให้แสดงซ้ำ; `deduplicateAcrossSources` ใช้ลบรายการซ้ำระหว่างแหล่งข้อมูลได้

การตั้งค่าทั่วไปเหล่านี้อยู่ใน `Config.TattooCatalog`:

| ฟิลด์ | ค่าเริ่มต้น | การใช้งาน |
| --- | --- | --- |
| `deduplicate` | `true` | ลบดีไซน์ที่ซ้ำกันภายในแหล่งข้อมูลเดียวกัน |
| `deduplicateAcrossSources` | `false` | อนุญาตให้คงดีไซน์จากแหล่งข้อมูลต่างกันแยกจากกัน |
| `serverFallback` | `true` | ขอแหล่งข้อมูลจากเซิร์ฟเวอร์เมื่อไคลเอนต์อ่านไม่ได้ |
| `serverFallbackTimeoutMs` | `7000` | เวลารอสูงสุดสำหรับคำขอนั้น หน่วยเป็นมิลลิวินาที |

กลไก fallback สำหรับการอ่านไม่ทำให้แพ็กที่หยุดทำงานกลับมาใช้งานได้

## รูปแบบของรอยสักแต่ละรายการ

ไฟล์อาจเป็น JSON array หรือออบเจ็กต์ที่มี property ซึ่งเก็บ array นั้น เมื่อใช้ `root.mode = 'auto'` ตัวอ่านจะรองรับทั้งสองรูปแบบ; เมื่อใช้ `root.mode = 'field'`, `root.field` จะระบุตำแหน่งของรายการ ส่วน `root.mode = 'array'` บังคับให้ใช้ array ที่ root

array นี้แสดงรูปแบบ JSON โดย collection และ hashes ในตัวอย่างเป็นข้อมูลสมมติ ให้แทนที่ด้วยชื่อจริงของแพ็กที่ติดตั้ง การเพิ่มรายการ JSON ไม่ได้ติดตั้งกราฟิก overlay

```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` และ overlay hash อย่างน้อยหนึ่งรายการเพื่อระบุดีไซน์ ใส่ทั้ง `HashNameMale` และ `HashNameFemale` หากรอยสักมีรูปแบบสำหรับตัวละครแต่ละเพศ ใช้หนึ่งในโซนต่อไปนี้: `ZONE_HEAD`, `ZONE_TORSO`, `ZONE_LEFT_ARM`, `ZONE_RIGHT_ARM`, `ZONE_LEFT_LEG` หรือ `ZONE_RIGHT_LEG` `Name` คือชื่อที่ผู้ซื้อจะเห็น หากไม่ระบุ `Price` จะใช้ราคาเริ่มต้นของแหล่งข้อมูล; หากไม่ระบุ `RequiredLevel` จะใช้ `defaults.requiredLevel` ซึ่งมีค่าเริ่มต้นเป็น 1 XP อาจมาจากตัวรอยสักหรือการตั้งค่าระดับ

หากไฟล์ใช้ชื่อฟิลด์อื่น ให้ปรับ `fields` ใน `Config.TattooCatalog` แต่ละรายการในตารางนั้นเป็นรายการ alias ที่ใช้ค้นหาค่าที่ตรงกัน ตัวอย่างเช่น ไฟล์ที่ใช้ `OverlayHash`, `Cost` และ `BodyZone` สามารถแมปได้ดังนี้:

```lua
fields = {
    collection = { 'Collection', 'CollectionName' },
    name = { 'Name', 'DisplayName' },
    overlay = { 'OverlayHash' },
    hashNameMale = { 'MaleOverlay' },
    hashNameFemale = { 'FemaleOverlay' },
    zone = { 'BodyZone' },
    price = { 'Cost' },
    xp = { 'Xp', 'Experience' },
    requiredLevel = { 'RequiredLevel' },
}
```

คุณยังกำหนดค่าทั่วไปผ่าน `rootFields` ได้ เช่น ชื่อ collection หรือโซนที่ระบุครั้งเดียวในออบเจ็กต์ root ส่วน `defaults` ของแต่ละแหล่งข้อมูลจะเติมค่าที่ขาด หาก JSON มีฟิลด์ทั่วไปเพียงฟิลด์เดียว เช่น `OverlayHash`, `defaults.overlayTarget` จะระบุว่าควรจัดเป็นรอยสักชาย (`male`) หรือหญิง (`female`)

รูปแบบที่แตกต่างกันมากสามารถแปลงด้วยฟังก์ชันเสริม `converters.decode(decoded, settings)` หรือ `converters.entry(entry, context)` ในการตั้งค่า ฟังก์ชันแรกปรับเอกสารทั้งชุด ส่วนฟังก์ชันที่สองปรับแต่ละดีไซน์ ให้คืนตารางที่เตรียมฟิลด์ไว้สำหรับการแมปตามปกติ

## ภาพขนาดย่อ

หากใช้รูปภาพที่อยู่ในแพ็กเดียวกัน ให้เก็บโฟลเดอร์ `miniatures/` ไว้ในรีซอร์สนั้น และกำหนด pattern เช่น:

```lua
thumbnailPattern = 'miniatures/{Name}.webp'
```

ระบบแทนที่ `{Name}`, `{HashNameMale}`, `{HashNameFemale}` และ `{HashName}` ด้วยข้อมูลของรอยสัก ไฟล์ปลายทางต้องมีอยู่ในรีซอร์ส เช่น `miniatures/Rosa del desierto.webp` และรีซอร์สต้องเริ่มทำงาน อินเทอร์เฟซจะร้องขอภาพขนาดย่อเมื่อจำเป็น อย่าคัดลอกรูปภาพมาไว้ในแพ็กเกจ CXG

คุณยังใส่ `Thumbnail` หรือ `ThumbnailUrl` ในรายการเพื่อระบุรูปภาพที่ต้องการได้ URL `http://`, `https://` และ `data:` จะถูกใช้ตามที่ระบุ เส้นทางภาพขนาดย่อในเครื่องของแพ็กต้องสอดคล้องกับ `thumbnailPattern`; ไฟล์ต้องมีอยู่และรีซอร์สต้องให้บริการไฟล์นั้นแก่ NUI ได้ รีซอร์สภายนอกต้องเก็บไฟล์ไว้ภายในแพ็ก

## การเปลี่ยนแปลงจากการตั้งค่าและการจัดการ

แก้การตั้งค่าเพื่อเพิ่มแหล่งข้อมูล เปลี่ยนวิธีอ่าน เปิดหรือปิดแพ็ก และปรับค่าเริ่มต้น ใช้การจัดการแคตตาล็อกเพื่อเปลี่ยนชื่อ ราคา ระดับ และสถานะพร้อมใช้งานของรอยสักโดยไม่แก้ JSON การเปลี่ยนแปลงจากผู้ดูแลจะถูกบันทึกและคงอยู่เมื่อซิงก์แคตตาล็อก การคืนค่าเริ่มต้นจะคืนรอยสักนั้นเป็นค่าจากแหล่งข้อมูล

รอยสักที่ผู้เล่นซื้อไปแล้วจะยังผูกกับตัวละคร แม้ปิดแพ็กที่ให้รอยสักนั้นไว้ชั่วคราว แพ็กจะไม่แสดงในร้านจนกว่าจะกลับมาใช้งานได้
