[{"data":1,"prerenderedAt":96},["ShallowReactive",2],{"site":3,"config-slug-site":15,"config-product-en-x3d-skin":21,"config-public-x3d-skin":91},{"site":4,"contact":10,"seo":13,"payment":14},{"name":5,"host":6,"default_locale":7,"locales":8},"X3D Developer","fivem.x3d-developer.com","th",[7,9],"en",{"discord_invite":11,"email":12,"line":12},"https:\u002F\u002Fdiscord.gg\u002FNA5kPVynFv","",{"google_site_verification":12,"bing_site_verification":12},{"bank_name":12,"account_name":12,"account_no":12,"promptpay_id":12},{"site":16,"contact":18,"seo":19,"payment":20},{"name":5,"host":6,"default_locale":7,"locales":17},[7,9],{"discord_invite":11,"email":12,"line":12},{"google_site_verification":12,"bing_site_verification":12},{"bank_name":12,"account_name":12,"account_no":12,"promptpay_id":12},{"id":22,"slug":23,"name":24,"summary":25,"price_thb":26,"license_mode":27,"cover_key":28,"cover_url":29,"category_slugs":30,"tags":32,"latest_version":50,"latest_released_at":51,"published_at":52,"has_docs":53,"config":54,"rent_price_satang":55,"description_md":56,"docs_md":57,"seo_title":58,"seo_description":59,"media":60,"versions":72},"7c86bf83-0df0-4e59-ab59-461ac4a2bff8","x3d-skin","X3D Character Skin","A 77-slot character editor with an orbiting camera, poses and lighting. No skinchanger, no database, any framework.",0,"none","public\u002Fproducts\u002Fx3d-skin\u002Fcover\u002Fdb520ac6e2e3d502.jpg","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fcover\u002Fdb520ac6e2e3d502.jpg",[31],"hud",[33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49],"esx","standalone","ตกแต่งตัวละคร","skin","character customization","skin creator","แต่งตัวละคร","ร้านเสื้อผ้า","ร้านตัดผม","ฟรี","free","ตู้เสื้อผ้า","ร้านเสริมสวย","ร้านหน้ากาก","ท่าโพส","แต่งหน้า","ไม่ต้องใช้ skinchanger","1.5.4","2026-10-12T17:21:14.159219Z","2026-09-22T04:02:41.988907Z",true,"public",null,"# Character customization — free, no skinchanger, no database\n\nA full 77-slot character editor: face, hair, beard, makeup, clothing and accessories, with an orbiting camera, poses, character lighting and a button that hides the other players standing on top of you. `x3d_skin` ships all of it in one resource, behind a ready-made Nuxt 4 panel.\n\n---\n\n## Features\n\n- [+] Easy setup: tune everything in config, or set it through the web builder\n- [+] 77-slot editor: face, hair, beard, makeup, clothing and accessories\n- [+] No skinchanger needed, same-name exports for your existing scripts\n- [+] Orbiting camera, zoom and pan, 4 poses and face lighting\n- [+] Button to hide other players within 50 m on a crowded spawn area\n- [+] Clothing, beauty and mask shops built in, with spots and blips\n- [+] Set each shop type's price yourself, 0 means free to use\n- [+] Wardrobe: save named outfits, with a per-player limit\n- [+] 46 ready-made faces, or a mom\u002Fdad blend with nose, cheek and chin sliders\n- [+] Works alongside an existing skinchanger \u002F esx_skin through Config.Backend\n- [+] No database needed: JSON file storage, or switch to MySQL\n- [+] Hook into other scripts through addons\u002F\n\n---\n\n## No skinchanger — the ped applier lives in this script\n\n`skin.lua` is plain game natives, and it exposes the export names other scripts already call (`GetSkin` \u002F `LoadSkin` \u002F `LoadClothes` \u002F `Change`), so a clothing shop or a uniform system that used to point at skinchanger can point at `x3d_skin` instead. Every slot is listed in `components.lua` with its default, its ceiling and its camera framing — and the real ceiling is asked from the game at runtime, never hardcoded, so add-on clothing packs the server installs are fully selectable.\n\n## The camera follows what you are editing, without fighting you\n\nPick a hairstyle and it frames the head; pick shoes and it drops to the feet. The moment the player rotates or zooms by hand, the camera stops moving on its own until they switch to another group. LMB drag rotates, RMB drag pans, scroll zooms. Four poses, three-point character lighting, and hiding every player within 50 m for a crowded spawn area.\n\n## Barbers and clothing shops can open it with a restricted slot list\n\nOpen the panel locked to the slots that shop sells, pass a price and the confirm button becomes \"Purchase\" with the amount on it. Submit and cancel callbacks let you charge for it yourself — this script never touches anyone's money — and the server-side `x3d_skin:onSave` hook fires every time a player saves a new appearance.\n\n## No database\n\nSaved appearances live in a JSON file inside the resource, keyed by the player's permanent identifier rather than a reusable server id, and written on a timer, on disconnect and on a graceful stop. Want MySQL? Swap four functions for the commented oxmysql block at the bottom of the same file and run `install.sql`.\n\nNothing the panel sends is trusted: the slot name must be known, the value is floored and clamped into range, saves are limited to one per second per player, and `\u002Fskin \u003Cid>` always needs the ace.\n\n## Requirements\n\nNone · no skinchanger, no database, no framework, no license · drop it in and `ensure` it\n\n**Free** · edit it however you like · just don't resell it or re-upload it as your own\n","## Installation\n\n1. Unzip and **rename the folder to `x3d_skin`** (other scripts call the exports by this name)\n2. Drop it in `resources\u002F`\n3. Add `ensure x3d_skin` to `server.cfg`\n\nThat is the whole setup: no database, no extra resource, and nothing on the server has to change. Works on ESX, QBCore and standalone.\n\nPlayers open it with `\u002Fskin`; an admin opens it for someone else with `\u002Fskin \u003Cid>`.\n\nGrant the admin permission:\n\n```\nadd_ace group.admin x3d_skin.admin allow\n```\n\n⚠ On a server that already runs `esx_skin`, it registers `\u002Fskin` too — whichever resource is `ensure`d last answers it. Put `ensure x3d_skin` after `ensure esx_skin`, or change `Config.Command`.\n\n## What can be edited\n\n77 slots in the default mode, grouped into the six tabs on the bottom bar:\n\n| Group | Slots |\n|---|---|\n| Basics | Gender · face · skin tone |\n| Hair & eyes | Hair style, colour, highlight · eye colour · eyebrow style, colour, opacity |\n| Clothing | Undershirt, torso, decals, arms, body armour, pants, shoes (each with its colour slot) |\n| Accessories | Mask, chain, hat, glasses, watch, bracelet, earrings |\n| Makeup | Makeup, lipstick, blush, beard |\n| Details | Age, blemishes, complexion, sun damage, moles, chest hair, body blemishes |\n\nEvery ceiling is asked from the game at runtime (`GetNumberOfPedDrawableVariations` and friends) rather than hardcoded — install an add-on clothing pack and players can reach all of it without a config change.\n\nSet `Config.AdvancedFace = true` to swap the 46 preset faces for the GTA Online heritage system: mother, father, blend weights and per-feature nose\u002Fcheek\u002Fchin sliders.\n\n⚠ Flipping that after the server has been live breaks the faces players already saved — the two modes store different value sets.\n\n## Panel controls\n\n| Input | What it does |\n|---|---|\n| LMB + drag | Rotate the character |\n| RMB + drag | Pan the camera (bounded — it cannot be used to look around the map) |\n| Scroll | Zoom in \u002F out |\n| Q \u002F E | Rotate a degree at a time |\n| Click a slot + Scroll | Change that slot's value |\n| Shift + Scroll | Step by ±10 |\n| Arrow keys | Fine adjustment |\n\nThe bottom-left toolbar: focus head · focus body · reset camera · character lighting · cycle pose (4) · hide every player within 50 m.\n\nThe camera moves to whatever is being edited, but the moment the player rotates or zooms by hand it stops moving on its own within that group, until a slot from another group is selected.\n\n## Opening it from a shop (barber, clothing store)\n\n```lua\nexports['x3d_skin']:OpenEditor({\n    title    = 'Barber',\n    price    = 500,\n    restrict = { 'hair_1', 'hair_2', 'hair_color_1', 'hair_color_2',\n                 'beard_1', 'beard_2', 'beard_3', 'beard_4' },\n    onSubmit = function() TriggerServerEvent('myshop:charge', 500) end,\n    onCancel = function() print('cancelled') end,\n})\n```\n\n`restrict` limits which slots can be edited; `price` turns the confirm button into \"Purchase\" with the amount on it.\n\n⚠ Calling `OpenEditor` yourself **never charges anyone** — take the money in your own `onSubmit`. The shops in `Config.Shops` are the other path: there the server charges and saves in one step.\n\n\n## Working with an existing skinchanger \u002F esx_skin\n\nNothing to configure — the script checks at startup:\n\n- **`skinchanger` is installed** → it dresses the ped and `esx_skin` keeps storing the skin its own way. x3d_skin is just the UI, the shops and the wardrobe.\n- **It is not** → x3d_skin dresses the ped itself and stores skins in a JSON file.\n\nEither way nothing has to be stopped and nothing has to be migrated; existing characters are untouched.\n\nForce one side with `Config.Backend` (`'skinchanger'` \u002F `'self'`) if you ever need to.\n\n## Bundled in the zip: `optional\u002Fskinchanger` + `optional\u002Fesx_skin`\n\nMost ESX servers already run both — **if yours does, skip the `optional\u002F` folder entirely**; x3d_skin already works with what you have.\n\nIf it does not, move them into `resources\u002F` and `ensure` them before `x3d_skin`:\n\n```\nensure skinchanger\nensure esx_skin\nensure x3d_skin\n```\n\n- `skinchanger` is ESX Legacy's own, with the `@include` of the es_extended locale file removed so it installs without erroring\n- `esx_skin` is trimmed to the API only (the `skin` column plus the old event names) so no second UI competes with the panel, and the player table name is a config value\n\nBoth belong to ESX Legacy and are GPL v3 — details in `optional\u002FREADME.md`.\n\nThe bundled `esx_skin` keeps `esx_skin:save`, the `esx_skin:getPlayerSkin` callback and the old open-menu events — those events now open the x3d_skin panel, so scripts that still call them keep working.\n\n## Shops (`Config.Shops`)\n\nFourteen clothing stores, seven beauty salons and one mask shop ship in this resource — no separate shop script.\n\n- Map blips reveal within 120 m (`blipDistance = 0` shows them always)\n- A ground marker plus an `[E] Clothing Store ($500)` prompt\n- Each type sets its own price and editable slots in `Config.ShopTypes`, with sub-tabs (clothing \u002F accessories, hair \u002F makeup)\n- `Config.Shops.enabled = false` turns the whole shop layer off and leaves `\u002Fskin`\n- `price = 0` makes a shop free and never reaches the money bridge\n\n**The charge and the save happen in one server-side step.** On confirm the server re-checks that the player is still at that shop and can still pay, then charges and saves. If the charge fails nothing is written; if the write fails the money is refunded.\n\n⚠ The original flow (a separate clothing-shop script + esx_skin) charged from the shop script while the editor saved separately, so a player who blocked the charge event kept the clothes for free. That hole is closed here.\n\nWire your own money system in `addons\u002Fframework\u002Fserver.lua` (ESX included, QBCore commented). Until it is wired, a priced shop refuses to open and says so — it never gives clothes away.\n\n## Wardrobe (`Config.Wardrobe`)\n\nSave what you are wearing under a name, wear it again in one click, rename it, overwrite it or delete it. Each player keeps up to `maxPerType` outfits (default 20) and names must be unique.\n\nWearing a saved outfit swaps the clothing only — **the face is never touched**.\n\nThe list is owned by the server and pushed to the panel after every change; the panel never decides what exists.\n\n## Server exports\n\n```lua\nexports['x3d_skin']:GetSkin(src)          --> the saved table, or nil\nexports['x3d_skin']:SetSkin(src, skin)    --> boolean (validated exactly like a player save)\nexports['x3d_skin']:OpenEditor(src)       --> boolean\n```\n\n`GetSkin` takes either a server id or an identifier. `SetSkin` is not rate limited, so a uniform system can dress a whole gang at once.\n\n## Client exports\n\n```lua\nexports['x3d_skin']:GetSkin()\nexports['x3d_skin']:GetMaxValues()\nexports['x3d_skin']:LoadSkin(skin)\nexports['x3d_skin']:LoadClothes(playerSkin, clothesSkin)   -- clothing only, the face is left alone\nexports['x3d_skin']:Change('torso_1', 5)\nexports['x3d_skin']:OpenEditor(opts)\nexports['x3d_skin']:CloseEditor()\nexports['x3d_skin']:IsOpen()\n```\n\n## Hook\n\n```lua\n-- server-internal, not a net event — a client cannot fire it\nAddEventHandler('x3d_skin:onSave', function(src, identifier, skin)\n    print(('%s saved a new appearance'):format(identifier))\nend)\n```\n\nClient-side there are `x3d_skin:opened` and `x3d_skin:closed` so another resource can hide its own HUD while the panel is up.\n\n## Where the data lives\n\nSaved appearances are server-side in one JSON file (`Config.Storage.File`, default `data\u002Fskins.json`), loaded once at resource start and written back every `Config.Storage.FlushSeconds`, on player drop and on a graceful stop. The key is the player's permanent identifier (license\u002Fdiscord\u002Fsteam), never a server id.\n\nA corrupt file is preserved as `data\u002Fskins.broken.json` and the store starts empty, with a console warning — it is never overwritten silently.\n\nTo use MySQL instead:\n\n1. Run `install.sql` through oxmysql\n2. Open `addons\u002Fstorage\u002Fserver.lua`, scroll to the bottom and copy the oxmysql block over the four `Storage.Get\u002FSet\u002FAll\u002FFlush` functions above it\n\n## Safety, backed by tests\n\n- **Nothing the panel sends is trusted** — the slot name must exist in `components.lua`, the value must be a number, and it is floored and clamped into range; unknown keys are dropped\n- **The storage key is always a stable identifier**, never a reusable server id\n- **One save per second per player**, and a player's cooldown is cleared the moment they disconnect\n- **`\u002Fskin \u003Cid>` always needs the ace**, even when `Config.PlayersCanEdit` lets everyone edit themselves\n- **An out-of-range index is clamped for the native call only, never written back into the saved skin** — an add-on pack that has not mounted yet cannot permanently zero a player's outfit\n- **The panel closes itself on death and on resource stop**, releasing the cursor and the player's controls every time\n\n```bash\npip install lupa\npython tools\u002Flua-test\u002Fx3d_skin_check.py\n```\n\n## Config (`config.lua`)\n\n| Key | What it does |\n|---|---|\n| `Config.Locale` | Language of the Lua-side strings (`th`\u002F`en`) — separate from the panel's own switch |\n| `Config.Command` \u002F `Config.Key` | The open command (`\u002Fskin`) and the key binding (empty = none) |\n| `Config.AdminAce` | The ace required to open the editor for another player |\n| `Config.PlayersCanEdit` | `false` = only ace holders may edit at all |\n| `Config.AdvancedFace` | Preset faces, or the mother\u002Ffather heritage system |\n| `Config.ApplyOnSpawn` \u002F `Config.FirstTimeSetup` | Apply the saved skin on spawn · open the editor for a player who has never saved |\n| `Config.Storage.File` \u002F `.FlushSeconds` | Where appearances are written and how often |\n| `Config.Camera` | Zoom range, pan limits, character lighting |\n| `Config.HideHud` | Hide the radar\u002FHUD while the panel is open |\n| `Config.Shops` \u002F `Config.ShopTypes` \u002F `Config.ShopLocations` | The shops — on\u002Foff, prices, editable slots and locations |\n| `Config.Wardrobe` | The wardrobe — on\u002Foff and how many outfits each player may keep |\n| `Config.Backend` | `auto` \u002F `skinchanger` \u002F `self` — who dresses the ped and who stores the skin |\n\n## Support\n\nDiscord: discord.gg\u002Fx3d-developer · Web: x3d-developer.com\n","Free FiveM Character Customization, No Skinchanger","Free FiveM character editor: 77 slots for face, hair, beard, makeup and clothing, orbiting camera, poses. No skinchanger, no database, shops can open it.",[61,64,66,68,70],{"kind":62,"url":63},"image","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fmedia\u002Fa08a6d9506a7700b.png",{"kind":62,"url":65},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fmedia\u002Fcaf6452bf3d960de.png",{"kind":62,"url":67},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fmedia\u002F69e3657b291a300b.png",{"kind":62,"url":69},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fmedia\u002Fc67ad3f8f1dd1295.png",{"kind":62,"url":71},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-skin\u002Fmedia\u002Fb9dbff8a1dd766e4.png",[73,75,79,83,87],{"version":50,"released_at":51,"changelog_md":74},"### Changed\n\n- Store images now carry English captions for the English store page",{"version":76,"released_at":77,"changelog_md":78},"1.5.2","2026-10-12T03:23:58.490433Z","### Changed\n\n- UI font is now Kanit (one family for Thai and English), bundled inside the script; the Thai font now really loads in game (FiveM's browser dropped the old font declaration and fell back to a system font)\n- New store images",{"version":80,"released_at":81,"changelog_md":82},"1.5.1","2026-10-11T09:23:09.364562Z","### Changed\n\n- Clothing shop `[E]` label uses the X3D 3D-text standard (outlined Thai text, amber key line)",{"version":84,"released_at":85,"changelog_md":86},"1.4.0","2026-09-22T04:06:09.988343Z","### Added\n- `optional\u002Fskinchanger` and `optional\u002Fesx_skin` ship in the zip for servers that do not already have them, so nothing has to be hunted down elsewhere. A server that already runs them skips the folder and keeps its own.\n- The bundled `skinchanger` drops the `@include` of es_extended's locale file (a local `shim.lua` supplies `TranslateCap`), so it installs without erroring\n- The bundled `esx_skin` is trimmed to the API: the `skin` column, `esx_skin:save`, the `esx_skin:getPlayerSkin` callback and the old open-menu events, which now open the x3d_skin panel. No second UI, and the player table name is a config value.",{"version":88,"released_at":89,"changelog_md":90},"1.3.0","2026-09-22T04:02:29.316247Z","### Removed\r\n- The mode that answered as `skinchanger` and `esx_skin` so both could be deleted. Servers keep those two as their interface layer, so a mode built around removing them only made setup look frightening. Installing is now: drop the folder in, `ensure x3d_skin`, done.\r\n- The storage block that wrote the `users.skin` column — with the two originals left in place, `esx_skin` still owns that column.",{"slug":23,"version":50,"latest_version":50,"files":92,"options":55},[93],{"path":94,"content":95},"config.lua","-- ═══════════════════════════════════════════════════════════════\r\n--  X3D SKIN  ·  config\r\n--  แก้ไฟล์นี้ไฟล์เดียวพอ ไม่ต้องแตะโค้ดส่วนอื่น\r\n--  Edit this one file only, no other code needs touching\r\n-- ═══════════════════════════════════════════════════════════════\r\n\r\nConfig = {}\r\n\r\n-- ===== ทั่วไป \u002F General =====\r\n\r\n--- เฟรมเวิร์ก: 'auto' หาเองจาก es_extended · 'esx' บังคับ ESX · 'standalone' ไม่ใช้เฟรมเวิร์ก\r\n--- Framework: 'auto' detects es_extended · 'esx' forces ESX · 'standalone' uses no framework\r\nConfig.Framework = 'auto'\r\n\r\n--- ภาษาของข้อความฝั่ง Lua ('th' | 'en') — พาเนลมีปุ่มสลับภาษาของตัวเอง\r\n--- Language of Lua-side messages ('th' | 'en'), the panel has its own language switch\r\nConfig.Locale = 'th'\r\n\r\n--- คำสั่งเปิดหน้าตกแต่งตัวละครของตัวเอง\r\n--- Command that opens your own character editor\r\nConfig.Command = 'skin'\r\n\r\n--- ปุ่มลัด ปล่อยว่าง = ไม่ผูกปุ่ม (ผู้เล่นเปลี่ยนเองได้ที่ Settings > Key Bindings)\r\n--- Shortcut key, empty = no key bound (players can rebind it in Settings > Key Bindings)\r\nConfig.Key = ''\r\n\r\n--- ace ที่ต้องมีถึงจะเปิดให้คนอื่นได้ (`\u002Fskin \u003Cid>`)\r\n--- คอนโซลเซิร์ฟเวอร์ใช้ได้เสมอ ไม่ต้องมี ace\r\n--- เพิ่มให้แอดมิน: add_ace group.admin x3d_skin.admin allow\r\n--- ACE needed to open the editor for other players (`\u002Fskin \u003Cid>`)\r\n--- The server console always works without the ACE\r\n--- Grant to admins: add_ace group.admin x3d_skin.admin allow\r\nConfig.AdminAce = 'x3d_skin.admin'\r\n\r\n--- true = ผู้เล่นทั่วไปเปิด `\u002Fskin` แก้หน้าตัวเองได้ตลอดเวลา\r\n--- false = เปิดได้เฉพาะคนที่มี ace ข้างบน (เซิร์ฟที่อยากให้แก้ได้เฉพาะที่ร้าน)\r\n--- true = every player can open `\u002Fskin` and edit themselves at any time\r\n--- false = only holders of the ACE above (for servers that allow editing only at shops)\r\nConfig.PlayersCanEdit = true\r\n\r\n--- ระบบหน้า\r\n---   false = face + skin (เลือกหน้าสำเร็จรูป 46 แบบ) — ค่าเริ่มต้น เข้าใจง่าย\r\n---   true  = mom + dad + น้ำหนักหน้า + ดัดจมูก\u002Fแก้ม\u002Fคาง ทีละจุด (แบบ MP)\r\n--- ⚠ สลับค่านี้หลังเปิดเซิร์ฟแล้ว หน้าที่ผู้เล่นเซฟไว้จะเพี้ยน เพราะคนละชุดค่า\r\n--- Face system\r\n---   false = face + skin (46 ready-made faces), the default and easy to understand\r\n---   true  = mom + dad + face blend + nose\u002Fcheek\u002Fchin one by one (MP style)\r\n--- ⚠ Switching this on a running server breaks faces players already saved, the values differ\r\nConfig.AdvancedFace = false\r\n\r\n--- โหลดหน้าที่เซฟไว้ให้อัตโนมัติทุกครั้งที่ผู้เล่นเกิด\r\n--- Apply the saved appearance every time the player spawns\r\nConfig.ApplyOnSpawn = true\r\n\r\n--- เปิดหน้าตกแต่งอัตโนมัติให้ผู้เล่นที่ยังไม่เคยเซฟหน้าเลย (สร้างตัวละครครั้งแรก)\r\n--- Open the editor automatically for a player who has never saved an appearance (first character)\r\nConfig.FirstTimeSetup = true\r\n\r\n-- ===== ที่เก็บข้อมูล \u002F Storage =====\r\n\r\n--- ที่เก็บหน้าตัวละคร\r\n--- Where character appearances are stored\r\nConfig.Storage = {\r\n    --- ไฟล์ JSON ที่เก็บ (เทียบจากโฟลเดอร์สคริปต์)\r\n    --- JSON file used for storage (relative to the script folder)\r\n    File = 'data\u002Fskins.json',\r\n    --- เขียนลงไฟล์ทุกกี่วินาที (เขียนตอนผู้เล่นออกและตอนปิดสคริปต์อยู่แล้ว)\r\n    --- Seconds between writes to the file (it is also written on disconnect and on stop)\r\n    FlushSeconds = 60,\r\n}\r\n\r\n-- ===== กล้อง \u002F Camera =====\r\n\r\n--- กล้อง\r\n--- Camera\r\nConfig.Camera = {\r\n    --- ระยะซูมเริ่มต้น \u002F ต่ำสุด \u002F สูงสุด\r\n    --- Default \u002F minimum \u002F maximum zoom distance\r\n    zoom = 2.0,\r\n    zoomMin = 0.15,\r\n    zoomMax = 3.5,\r\n    --- ระยะที่ตัวละครขยับไปทางขวาของจอ (หลบพาเนลด้านซ้าย)\r\n    --- How far the character shifts to the right of the screen (clear of the left panel)\r\n    xOffset = 0.55,\r\n    --- ขอบเขตการเลื่อนกล้อง (กันส่องไปที่อื่น)\r\n    --- Camera pan limits (keeps it from drifting away)\r\n    panLimitX = 1.0,\r\n    panLimitUp = 1.2,\r\n    panLimitDown = 0.3,\r\n    --- ไฟส่องตัวละคร ปิดได้ถ้าเซิร์ฟมี ENB\u002Fgraphics mod ที่ตีกัน\r\n    --- Character lighting, turn it off if an ENB\u002Fgraphics mod conflicts\r\n    lights = true,\r\n}\r\n\r\n--- ซ่อน HUD\u002Fเรดาร์ระหว่างเปิดพาเนล\r\n--- Hide the HUD\u002Fradar while the panel is open\r\nConfig.HideHud = true\r\n\r\n-- ===== ตู้เสื้อผ้า \u002F Wardrobe =====\r\n\r\n--  ตู้เสื้อผ้า — เซฟชุดเป็นเซ็ตแล้วตั้งชื่อ กดใส่ทีเดียวทั้งชุด\r\n--  Wardrobe: save a whole look as a named set and apply it in one click\r\n\r\nConfig.Wardrobe = {\r\n    --- เปิด\u002Fปิดตู้เสื้อผ้า \u002F Wardrobe on\u002Foff\r\n    enabled = true,\r\n    --- เซฟได้กี่ชุดต่อคนต่อประเภท (outfit \u002F hairstyle \u002F mask)\r\n    --- Saved sets allowed per player per type (outfit \u002F hairstyle \u002F mask)\r\n    maxPerType = 20,\r\n    --- ความยาวชื่อชุดสูงสุด\r\n    --- Maximum outfit name length\r\n    nameLength = 50,\r\n}\r\n\r\n-- ===== ร้านค้า \u002F Shops =====\r\n\r\n-- ═══════════════════════════════════════════════════════════════\r\n--  ร้าน — ร้านเสื้อผ้า ร้านเสริมสวย ร้านหน้ากาก\r\n--  Shops: clothing, beauty and mask shops\r\n--\r\n--  ปิดทั้งระบบด้วย Config.Shops.enabled = false (เหลือแค่ \u002Fskin)\r\n--  ตั้ง price = 0 = เข้าใช้ฟรี ไม่แตะเงินใครเลย\r\n--\r\n--  ⚠ เงินถูกหักและชุดถูกบันทึกในก้าวเดียวกันฝั่งเซิร์ฟเวอร์\r\n--    ผู้เล่นบล็อกข้อความคิดเงินแล้วได้ชุดฟรีไม่ได้\r\n--\r\n--  Turn the whole system off with Config.Shops.enabled = false (only \u002Fskin remains)\r\n--  price = 0 means free to use and never touches anyone's money\r\n--\r\n--  ⚠ Money is charged and the outfit saved in one server-side step,\r\n--    so a player cannot block the charge message and keep the outfit for free\r\n-- ═══════════════════════════════════════════════════════════════\r\n\r\nConfig.Shops = {\r\n    --- เปิด\u002Fปิดระบบร้านทั้งหมด \u002F Shops system on\u002Foff\r\n    enabled = true,\r\n\r\n    --- ระยะที่เริ่มวาดวงกลมบนพื้น \u002F ระยะที่กด [E] ได้\r\n    --- Distance where the ground circle starts drawing \u002F distance where [E] works\r\n    drawDistance = 20.0,\r\n    interactDistance = 3.0,\r\n\r\n    --- วงกลมบนพื้นหน้าร้าน (ปิดด้วย marker = false)\r\n    --- Ground circle at the shop (turn off with marker = false)\r\n    marker = true,\r\n    --- ขนาดและสีของวงกลม \u002F Circle size and color\r\n    markerSize = vector3(4.0, 4.0, 0.2),\r\n    markerColor = { r = 212, g = 144, b = 122, a = 70 },\r\n\r\n    --- หมุดบนแผนที่ โผล่เมื่อเข้าใกล้ภายใน blipDistance เมตร (0 = โชว์ตลอด)\r\n    --- Map blip, shown within blipDistance meters (0 = always shown)\r\n    blips = true,\r\n    blipDistance = 120.0,\r\n}\r\n\r\n-- ===== ประเภทร้าน \u002F Shop types =====\r\n\r\n--- ประเภทร้าน — ราคาและช่องที่แก้ได้ในร้านนั้น\r\n--- `categories` = แท็บย่อยในพาเนล (components = nil คือแท็บ \"ทั้งหมด\")\r\n--- Shop types: price and editable slots per shop\r\n--- `categories` = sub-tabs in the panel (components = nil is the \"all\" tab)\r\n--- label = ชื่อร้าน \u002F shop name · price = ราคา (0 = ฟรี) \u002F price (0 = free)\r\n--- blip = ไอคอนและสีหมุด \u002F blip icon and color · components = ช่องที่แก้ได้ \u002F editable slots\r\n-- เช่น \u002F e.g. masks = { label = 'ร้านหน้ากาก', price = 200, blip = { sprite = 362, color = 1 }, components = { 'mask_1', 'mask_2' } }\r\nConfig.ShopTypes = {\r\n    clothing = {\r\n        label = 'ร้านเสื้อผ้า',\r\n        price = 500,\r\n        blip = { sprite = 73, color = 47 },\r\n        categories = {\r\n            { id = 'all', name = 'ทั้งหมด', components = nil },\r\n            { id = 'clothing', name = 'เสื้อผ้า', components = {\r\n                'tshirt_1', 'tshirt_2', 'torso_1', 'torso_2', 'arms', 'arms_2',\r\n                'pants_1', 'pants_2', 'shoes_1', 'shoes_2', 'bags_1', 'bags_2',\r\n                'decals_1', 'decals_2', 'bproof_1', 'bproof_2',\r\n            } },\r\n            { id = 'accessories', name = 'เครื่องประดับ', components = {\r\n                'helmet_1', 'helmet_2', 'glasses_1', 'glasses_2', 'watches_1', 'watches_2',\r\n                'bracelets_1', 'bracelets_2', 'ears_1', 'ears_2', 'chain_1', 'chain_2',\r\n            } },\r\n        },\r\n        components = {\r\n            'tshirt_1', 'tshirt_2', 'torso_1', 'torso_2', 'arms', 'arms_2',\r\n            'pants_1', 'pants_2', 'shoes_1', 'shoes_2', 'bags_1', 'bags_2',\r\n            'decals_1', 'decals_2', 'bproof_1', 'bproof_2',\r\n            'helmet_1', 'helmet_2', 'glasses_1', 'glasses_2', 'watches_1', 'watches_2',\r\n            'bracelets_1', 'bracelets_2', 'ears_1', 'ears_2', 'chain_1', 'chain_2',\r\n        },\r\n    },\r\n\r\n    beauty = {\r\n        label = 'ร้านเสริมสวย',\r\n        price = 200,\r\n        blip = { sprite = 71, color = 40 },\r\n        categories = {\r\n            { id = 'all', name = 'ทั้งหมด', components = nil },\r\n            { id = 'hair', name = 'ผมและเครา', components = {\r\n                'hair_1', 'hair_2', 'hair_color_1', 'hair_color_2',\r\n                'beard_1', 'beard_2', 'beard_3', 'beard_4',\r\n                'eyebrows_1', 'eyebrows_2', 'eyebrows_3', 'eyebrows_4',\r\n            } },\r\n            { id = 'makeup', name = 'แต่งหน้า', components = {\r\n                'makeup_1', 'makeup_2', 'makeup_3', 'makeup_4',\r\n                'lipstick_1', 'lipstick_2', 'lipstick_3', 'lipstick_4',\r\n                'blush_1', 'blush_2', 'blush_3', 'complexion_1', 'complexion_2',\r\n                'sun_1', 'sun_2', 'moles_1', 'moles_2', 'age_1', 'age_2',\r\n                'blemishes_1', 'blemishes_2',\r\n            } },\r\n        },\r\n        components = {\r\n            'hair_1', 'hair_2', 'hair_color_1', 'hair_color_2',\r\n            'beard_1', 'beard_2', 'beard_3', 'beard_4',\r\n            'eyebrows_1', 'eyebrows_2', 'eyebrows_3', 'eyebrows_4',\r\n            'makeup_1', 'makeup_2', 'makeup_3', 'makeup_4',\r\n            'lipstick_1', 'lipstick_2', 'lipstick_3', 'lipstick_4',\r\n            'blush_1', 'blush_2', 'blush_3', 'complexion_1', 'complexion_2',\r\n            'sun_1', 'sun_2', 'moles_1', 'moles_2', 'age_1', 'age_2',\r\n            'blemishes_1', 'blemishes_2',\r\n        },\r\n    },\r\n\r\n    masks = {\r\n        label = 'ร้านหน้ากาก',\r\n        price = 200,\r\n        blip = { sprite = 362, color = 1 },\r\n        components = { 'mask_1', 'mask_2' },\r\n    },\r\n}\r\n\r\n-- ===== ที่ตั้งร้าน \u002F Shop locations =====\r\n\r\n--- ที่ตั้งร้าน — `type` ต้องตรงกับคีย์ใน Config.ShopTypes\r\n--- Shop locations: `type` must match a key in Config.ShopTypes\r\n-- เช่น \u002F e.g. { type = 'clothing', coords = vector3(124.21, -219.85, 54.55) }\r\nConfig.ShopLocations = {\r\n    { type = 'clothing', coords = vector3(124.21, -219.85, 54.55) },      -- Vinewood\r\n    { type = 'clothing', coords = vector3(72.25, -1399.10, 28.37) },      -- Strawberry\r\n    { type = 'clothing', coords = vector3(-703.77, -152.25, 36.41) },     -- Burton\r\n    { type = 'clothing', coords = vector3(-167.86, -298.96, 38.73) },     -- Downtown\r\n    { type = 'clothing', coords = vector3(428.69, -800.10, 28.49) },      -- Pillbox Hill\r\n    { type = 'clothing', coords = vector3(-829.41, -1073.71, 10.32) },    -- Vespucci Canals\r\n    { type = 'clothing', coords = vector3(-1447.79, -242.46, 48.82) },    -- Morningwood\r\n    { type = 'clothing', coords = vector3(11.63, 6514.22, 30.87) },       -- Paleto Bay\r\n    { type = 'clothing', coords = vector3(1696.29, 4829.31, 41.06) },     -- Grapeseed\r\n    { type = 'clothing', coords = vector3(618.09, 2759.62, 41.08) },      -- Harmony\r\n    { type = 'clothing', coords = vector3(1190.55, 2713.44, 37.22) },     -- Grand Senora\r\n    { type = 'clothing', coords = vector3(-1193.42, -772.26, 16.32) },    -- Del Perro\r\n    { type = 'clothing', coords = vector3(-3172.49, 1048.13, 19.86) },    -- Chumash\r\n    { type = 'clothing', coords = vector3(-1108.44, 2708.92, 18.10) },    -- Zancudo\r\n\r\n    { type = 'beauty', coords = vector3(-814.30, -183.82, 36.56) },       -- Burton\r\n    { type = 'beauty', coords = vector3(136.82, -1708.37, 28.29) },       -- Davis\r\n    { type = 'beauty', coords = vector3(-1282.60, -1116.75, 5.99) },      -- Del Perro\r\n    { type = 'beauty', coords = vector3(1931.51, 3729.67, 31.84) },       -- Sandy Shores\r\n    { type = 'beauty', coords = vector3(1212.84, -472.92, 65.20) },       -- Mirror Park\r\n    { type = 'beauty', coords = vector3(-32.88, -152.31, 56.07) },        -- Hawick\r\n    { type = 'beauty', coords = vector3(-278.07, 6228.46, 30.69) },       -- Paleto Bay\r\n\r\n    { type = 'masks', coords = vector3(-1337.40, -1278.15, 4.87) },       -- Vespucci Beach\r\n}\r\n\r\n-- ===== ตัวใส่ค่า \u002F Backend =====\r\n\r\n--- ใครใส่หน้าตา\u002Fเสื้อผ้าลงร่าง — ปกติไม่ต้องแตะ\r\n--- Who applies the appearance to the ped, normally leave it alone\r\n---   'auto'        มี skinchanger อยู่แล้วก็ใช้ของเดิม ไม่มีก็ใช้ตัวในสคริปต์ (ค่าเริ่มต้น)\r\n---   'skinchanger' บังคับใช้ skinchanger\r\n---   'self'        บังคับใช้ตัวในสคริปต์\r\n---   'auto'        uses an existing skinchanger if present, otherwise the built-in one (default)\r\n---   'skinchanger' forces skinchanger\r\n---   'self'        forces the built-in applier\r\nConfig.Backend = 'auto'\r\n\r\n",1792316315779]