[{"data":1,"prerenderedAt":91},["ShallowReactive",2],{"site":3,"config-slug-site":15,"config-product-en-x3d-dailylogin":21,"config-public-x3d-dailylogin":86},{"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":49,"latest_released_at":50,"published_at":51,"has_docs":52,"config":53,"rent_price_satang":54,"description_md":55,"docs_md":56,"seo_title":57,"seo_description":58,"media":59,"versions":71},"7a9dd386-11c0-4f21-8c2e-cfa7dc24d15d","x3d-dailylogin","X3D Daily Login","Free daily check-in with streaks and a fully editable reward table, no database required, a full bag never costs the reward, works with any framework.",0,"none","public\u002Fproducts\u002Fx3d-dailylogin\u002Fcover\u002Fffcad7901926aa67.jpg","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fcover\u002Fffcad7901926aa67.jpg",[31],"gameplay",[33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"esx","standalone","เช็คอินรายวัน","daily login","daily reward","สตรีค","รางวัลรายวัน","ฟรี","free","ล็อคอินรายวัน","รางวัลค้างรับ","รับย้อนหลัง","โบนัสเวลาเล่น","รางวัลเข้าเกม","เช็คชื่อรายวัน","ไม่ต้องใช้ฐานข้อมูล","1.4.3","2026-10-12T17:21:47.885233Z","2026-09-20T10:37:48.155794Z",true,"public",null,"# A daily check-in where the player never loses a reward\n\nLog in, claim, keep the streak. Miss a day and the streak either resets or keeps counting — your call. The reward table is yours to write. **Nothing else to install**: no database. Works with ESX out of the box, and standalone with no framework installed — QBCore needs the one adapter file filled in first.\n\n---\n\n## Features\n\n- [+] Easy setup: tune everything in config, or set it through the web builder\n- [+] Reward table of any length, looping or ending after the last day\n- [+] Mixed rewards: items, cash\u002Fbank\u002Fblack money, weapons, tokens\n- [+] Missed a day: reset the streak or keep counting, your choice\n- [+] Optional back-claim for missed days, with your own day limit\n- [+] Playtime bonus: play N hours to unlock a reward or claim the next day\n- [+] Several tracks at once, with time windows or one-time calendars\n- [+] Claim by hand, auto-claim, or auto-open the panel on join\n- [+] Full bag never loses the reward: held as pending, with a limit\n- [+] Double-claim safe: paid once, a failed delivery gives the day back\n- [+] Send rewards to x3d_mailbox (safe) instead of the bag\n- [+] Hook into other scripts through addons\u002F\n\n---\n\n## A full bag never costs the reward\n\nIf the bag is full at claim time the reward is **held for that player inside this resource**. The day still counts, the streak keeps running, and the player claims it from the same panel once there is room. No other system is involved and the reward cannot quietly disappear.\n\n## Treated like money, because it is\n\n- Claiming twice pays once — the day is consumed before delivery, with a single-flight lock per player\n- A delivery that lands nothing gives the day back instead of burning it silently\n- Counts are floored and duplicate item rows aggregated before the capacity check\n- One open and one claim per second per player\n- The day boundary comes from the server clock and `Config.TimezoneOffset`, never the player's\n\n## It talks to your inventory, not to a guess\n\nOn a server whose inventory is replaced (x3d_inventory, ox_inventory, NC …) ESX's own weight numbers go stale and rewards get refused as \"bag full\" on an empty bag. Point `Config.CanCarryExport` at your inventory's own export and it is gone. Item icons come from your inventory's image folder too.\n\n## Everything is configurable\n\nAny number of reward days, looping or ending; manual claim or automatic on spawn; Thai item and account labels; JSON file storage by default, or paste in the oxmysql block that ships commented in the same file.\n\n**Free** · modify it as you like · just don't resell it or re-upload it under another name.\n\n- **With X3D Admin Panel (optional):** edit the reward calendar per track, add, disable or schedule tracks for festivals, edit playtime bonus tiers and browse claim history — all applied live, no restart. Without the panel it runs exactly as before\n- **One-time tracks:** set `loop` per track so a track such as a 31-day new-player calendar ends after its last day while the regular calendar keeps repeating\n- **Rewards to the mailbox:** send items and money to the X3D Mailbox safe instead of the bag\n- **Auto-open and notifications:** open once per connection after a delay, and notify each auto-claimed reward\n","## Installation\n\n1. Unzip and **rename the folder to `x3d_dailylogin`** (other scripts call the exports by this name)\n2. Drop it in `resources\u002F`\n3. Add to `server.cfg`:\n\n```\nensure x3d_dailylogin\n```\n\nNo database, no license required. Works with ESX out of the box, and standalone with no framework installed (QBCore needs its adapter filled in first).\n\nOpen the panel with **F6** or `\u002Fdailylogin` — or let it open itself (`Config.AutoOpen = true`, default) whenever there is something to claim.\n\nAuto-open options in `config.lua`:\n\n- `Config.AutoOpen = 'always'` — open once per connection (after `Config.AutoDelay`), not on every respawn\n- `Config.AutoDelay` — delay before it opens\n- `Config.AutoNotify` — notify each auto-claimed reward (reward name + track and day)\n\n## Back-claim (off by default)\n\nLet a player who missed days collect the rewards they skipped. In `config.lua`:\n\n```lua\nConfig.BackClaim = {\n    enabled = true,\n    maxDays = 3,     -- reach back at most three days\n}\n```\n\n| Situation | Off (default) | On, maxDays = 3 |\n|---|---|---|\n| Missed 3 days, then returns | One claim, today's reward only, the missed days are gone | Four claims, walking the gap one day at a time up to today |\n| Missed 9 days, then returns | Same, one claim | Only the last three days plus today are reachable |\n| Brand new player's first claim | Starts today | Also starts today — no free days for a time they never played |\n\nWalking the gap day by day means **the streak does not break**, and the panel shows how many catch-up days are left.\n\n## Reward table\n\nEdit `config.lua` — any number of days.\n\n```lua\nConfig.Rewards = {\n    [1] = { money = { { account = 'money', amount = 500 } } },\n    [2] = { items = { { item = 'bread', count = 2 } } },\n    [3] = { weapon = { { name = 'WEAPON_PISTOL', ammo = 30 } } },\n    [7] = { money = { { account = 'bank', amount = 5000 } }, label = 'Weekly reward' },\n}\n\nConfig.LoopRewards = true   -- loops back to the first day once the table is done (keys don't need to be consecutive — this 3-day example reaches day 7 on the 3rd claim)\nConfig.ResetOnMiss = true   -- missing a day resets the streak to 1\nConfig.AutoClaim   = false  -- true = claim automatically on spawn\n```\n\nWant several tracks at once (a regular calendar plus a time-limited launch event)? Set `Config.Tracks` — each track keeps its own streak and held rewards, with an optional `from`\u002F`to` (unix) window. Leave it unset and it works exactly as one `'default'` track, as above.\n\n- Per-track `loop` in `Config.Tracks` (unset = `Config.LoopRewards`): `loop = false` makes a one-time track (e.g. a 31-day new-player calendar) that ends after its last day\n- `Config.TokenLabels` — readable names for token rewards\n- `Config.Mailbox` + `Reward.ToMailbox` — send that reward's items\u002Fmoney to a mailbox (x3d_mailbox safe by default) instead of the bag\n- **If you use the X3D Admin Panel:** edits made in the panel are stored under the storage key `__admin` and override `Config.Rewards` \u002F `Config.Tracks` \u002F `Config.PlaytimeBonusHours` at boot — the config only seeds the first run. `Daily.Rebuild()` rebuilds the reward tables from `Config` at runtime\n\n## Playtime bonus\n\nPlaying N hours today unlocks another reward to claim by hand (separate from the calendar, keeps counting across a reconnect):\n\n```lua\nConfig.PlaytimeBonusHours = {\n    [2] = { money = { { account = 'money', amount = 300 } } },\n    [5] = { money = { { account = 'bank', amount = 800 } } },\n}\n```\n\nLeave it empty to turn the whole feature off — it won't show in the panel at all.\n\n`Config.PlaytimeMode = 'extra_day'` — each playtime tier claims the next day of every active track at once, instead of a separate reward.\n\n## Day boundary\n\n```lua\nConfig.TimezoneOffset = 7 * 3600   -- Thailand GMT+7\n```\n\nComputed from the server clock, never the player's — turning back the player's own system clock does nothing.\n\n## Full bag at claim time\n\nThe reward is not lost, and the day is not wasted — it is kept as a **held reward** for that player. Claim it later, once there is room, from the same panel.\n\n| Setting | Result |\n|---|---|\n| `Config.HoldWhenFull = true` (default) | Held as a pending reward, the day is consumed as normal, the streak keeps running |\n| `Config.HoldWhenFull = false` | The day is not consumed, clear the bag and claim again |\n| `Config.MaxPending` | Maximum held rewards per player (default 10) — at the cap the day is not consumed either |\n\nHeld rewards live inside x3d_dailylogin itself, **with no involvement from the mailbox** (the mailbox is for staff sends and redeem codes):\n\n```lua\nexports['x3d_dailylogin']:GetPending(src)      --> the held-reward list\nexports['x3d_dailylogin']:ClaimPending(src, 1) --> ok, reason\n\nAddEventHandler('x3d_dailylogin:onPending', function(src, entry, ok, trackId) end)\n```\n\n## Servers running their own inventory\n\n| Setting | Purpose |\n|---|---|\n| `Config.CanCarryExport` | Your inventory's own export used to check capacity — **seeing \"bag full\" on an empty bag? set this** (ESX's own weight numbers go stale when another inventory owns them) |\n| `Config.ItemImage` | Path to the icons of the inventory in use (`{item}` = item name), empty = no icon |\n| `Config.ItemLabels` \u002F `Config.AccountLabels` | Thai display names for items and money accounts |\n\nReady-made examples already in `config.lua`: x3d_inventory, ox_inventory, qb-inventory\n\n## Calling from another resource\n\n```lua\nexports['x3d_dailylogin']:GetStreak(src, trackId)   --> number — trackId omitted = 'default'\nexports['x3d_dailylogin']:CanClaim(src, trackId)    --> true \u002F false\nexports['x3d_dailylogin']:Claim(src, trackId)       --> ok, reason\nexports['x3d_dailylogin']:ClaimPlaytime(src, hours) --> ok, reason\n\nAddEventHandler('x3d_dailylogin:onClaim', function(src, streak, reward, ok, trackId)\n    -- ok = false means delivery was incomplete (some part didn't land) — log it if you want to check (an old listener with no trackId still works)\n    print(('player %s claimed day %d on track %s (complete: %s)'):format(src, streak, trackId, tostring(ok)))\nend)\n```\n\n## Admin commands\n\n`\u002Fdailyreset \u003Cserver id>` — wipes that player's streak, last day and every held reward. For fixing a problem for a player, not a toy. Always callable from the console; a player needs the `Config.AdminAce` ace (default `x3d_dailylogin.admin`) in-game. Running it pushes the now-cleared state to the target's screen without stealing focus — the panel only shows it if that player already had it open; it does not force the panel open.\n\n## Storage with oxmysql instead of the JSON file\n\nDefault storage is `data\u002Fdailylogin.json` — no database required at all. To use a database instead: open `addons\u002Fstorage\u002Fserver.lua`, copy the oxmysql block at the bottom over the four functions above it, then run `install.sql`.\n\nSaving happens every 30 seconds (`Config.Storage.FlushSeconds`), on player drop, and on a normal resource stop · a sudden server crash can lose at most whatever happened since the last save.\n\n## Support\n\nDiscord: discord.gg\u002Fx3d-developer · Web: x3d-developer.com\n","Free FiveM Daily Login Streak Script","Free FiveM daily check-in with streaks and an editable reward table. No database, any framework, a full bag never loses the reward. Backed by 49 tests.",[60,63,65,67,69],{"kind":61,"url":62},"image","\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fmedia\u002Faf63b761b443b974.png",{"kind":61,"url":64},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fmedia\u002Fb5026093f5d59f28.png",{"kind":61,"url":66},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fmedia\u002F207d4f9572b33005.png",{"kind":61,"url":68},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fmedia\u002F4139bf7de3314fd7.png",{"kind":61,"url":70},"\u002Fapi\u002Fv1\u002Fmedia\u002Fpublic\u002Fproducts\u002Fx3d-dailylogin\u002Fmedia\u002Fa2cbf95b87dd92e7.png",[72,74,78,82],{"version":49,"released_at":50,"changelog_md":73},"### Changed\n\n- Store images now carry English captions for the English store page",{"version":75,"released_at":76,"changelog_md":77},"1.4.1","2026-10-12T03:25:11.338905Z","### 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)",{"version":79,"released_at":80,"changelog_md":81},"1.4.0","2026-10-05T03:00:08.391317Z","### Added\r\n- Optional x3d_adminpanel menu (`admin.lua`): edit the reward calendar per track, add\u002Fdisable\u002Fschedule tracks for festivals, edit playtime bonus tiers and browse claim history, all applied live without a restart; runs the same as before when the panel is not installed\r\n- Panel edits are stored in the storage key `__admin` and override `Config.Rewards`\u002F`Config.Tracks`\u002F`Config.PlaytimeBonusHours` at boot (the config only seeds the first run)\r\n- `Daily.Rebuild()` rebuilds the reward tables from `Config` at runtime\r\n- Per-track `loop` in `Config.Tracks` (unset = `Config.LoopRewards`): a one-time track such as a 31-day new-player calendar ends after its last day while the regular calendar keeps repeating\r\n- `Config.TokenLabels` shows a readable name for token rewards\r\n- `Config.AutoOpen = 'always'`, `Config.AutoDelay`, `Config.AutoNotify`: open once per connection after a delay and notify each auto-claimed reward (reward name + track and day)\r\n- `Config.PlaytimeMode = 'extra_day'`: each playtime tier claims the next day of every active track at once\r\n- `Config.Mailbox` + `Reward.ToMailbox`: send items\u002Fmoney to a mailbox (x3d_mailbox safe by default) instead of the bag\r\n- Calendar footer shows the event period, where rewards go, today's auto-claimed days and playtime progress; tabs show progress against the track length and a check mark when finished\r\n### Fixed\r\n- A finished one-time track counted as claimable, so the panel opened on every spawn and the calendar jumped back to day 1 with no stamps\r\n- Auto-claim\u002Fauto-open ran again on every respawn; it now runs once per connection\r\n- Days claimed today now get the stamp animation when the calendar opens, not only after a manual click\r\n### Changed\r\n- Item names on the calendar fall back to the framework's item label when `Config.ItemLabels` has no entry, instead of showing the raw key",{"version":83,"released_at":84,"changelog_md":85},"1.2.1","2026-09-20T10:37:46.445431Z","### Fixed\r\n- Playtime bonus tiers could be claimed twice by sending the same tier once as an integer and once as a float (e.g. `2` then `2.0`) — the reward lookup, the claimed flag and the in-flight lock now all derive from one floored integer, and a non-integer or unconfigured tier is refused cleanly\r\n- `Daily.Claim`\u002F`Daily.ClaimPending` threw a script error (no toast) instead of answering when `trackId` was not a string, since it was concatenated into the lock key before being validated\r\n- `Config.PlaytimeBonusHours = nil` (documented as \"feature off\") produced a misleading `deliver_failed` instead of a clean refusal\r\n- The last few seconds of a session's playtime, between the last periodic tick and a disconnect, are now credited instead of lost\r\n### Changed\r\n- README\u002Fdocs corrected: `\u002Fdailyreset` only refreshes a target's calendar if it is already open, it does not force the panel open",{"slug":23,"version":49,"latest_version":49,"files":87,"options":54},[88],{"path":89,"content":90},"config.lua","-- ═══════════════════════════════════════════════════════════════\n--  x3d_dailylogin — ตั้งค่า\n--  X3D-Developer · https:\u002F\u002Fx3d-developer.com\n-- ═══════════════════════════════════════════════════════════════\n\nConfig = {}\n\n-- ===== ทั่วไป \u002F General =====\n\n-- เฟรมเวิร์กที่ใช้: 'auto' (ESX ถ้ามี ไม่มีก็ standalone) | 'esx' | 'standalone'\n-- Framework: 'auto' (ESX if present, otherwise standalone) | 'esx' | 'standalone'\nConfig.Framework = 'auto'\n\n-- ภาษาของหน้าต่างและข้อความ: 'th' | 'en' \u002F UI and message language: 'th' | 'en'\nConfig.Locale  = 'th'\n\n-- คำสั่งเปิดหน้าต่าง (\u002Fdailylogin) \u002F Command that opens the panel (\u002Fdailylogin)\nConfig.Command = 'dailylogin'\n\n-- ปุ่มเปิดหน้าต่าง ('' = ไม่ผูกปุ่ม) \u002F Key that opens the panel ('' = no key bound)\nConfig.Key     = 'F6'\n\n-- สิทธิ์ ACE ของแอดมิน (ใช้กับ \u002Fdailyreset) \u002F Admin ACE permission (used by \u002Fdailyreset)\nConfig.AdminAce = 'x3d_dailylogin.admin'\n\n-- ===== เวลาและสตรีค \u002F Time and streak =====\n\n-- เส้นแบ่งวัน — วินาทีที่บวกเพิ่มจากเวลา UTC (ไทย GMT+7 = 7 * 3600)\n-- Day boundary: seconds added to UTC time (Thailand GMT+7 = 7 * 3600)\nConfig.TimezoneOffset = 7 * 3600\n\n-- ขาดวันแล้วสตรีคกลับไปเริ่มที่ 1 ใหม่ไหม (false = นับต่อจากเดิมเรื่อย ๆ)\n-- Reset the streak to 1 after a missed day (false = keep counting)\nConfig.ResetOnMiss = true\n\n-- ===== รับอัตโนมัติ \u002F Auto claim and auto open =====\n\n-- รับรางวัลให้อัตโนมัติตอนเข้าเกม (true = ไม่ต้องเปิดหน้าต่าง แค่เด้งแจ้งเตือน)\n-- Claim automatically on join (true = no window needed, only a notification)\nConfig.AutoClaim = false\n\n-- เปิดหน้าต่างให้อัตโนมัติตอนมีรางวัลให้กด (แยกจาก AutoClaim — เปิดโชว์ปฏิทินเฉย ๆ ไม่ได้กดรับให้)\n-- ไม่เปิดถ้าผู้เล่นตายอยู่\u002Fค้าง pause menu (เช็คฝั่ง client ด้วย Framework.IsBusy)\n-- Open the panel automatically when there is something to claim (separate from AutoClaim, it only shows the calendar)\n-- Skipped while the player is dead or in the pause menu (client side check via Framework.IsBusy)\n-- 'always' = เปิดปฏิทินทุกครั้งที่เข้าเกม (ครั้งแรกของการเชื่อมต่อ) แม้ไม่มีอะไรให้รับ\n-- 'always' = open the calendar on every join (first spawn of the session) even with nothing to claim\nConfig.AutoOpen = true\n\n-- รอกี่มิลลิวินาทีหลังเกิดในเมืองก่อนรับ\u002Fเปิดอัตโนมัติ (ให้ HUD\u002Fกระเป๋าโหลดเสร็จก่อน)\n-- Milliseconds after spawning before the auto-claim\u002Fauto-open runs (lets the HUD and bag load first)\nConfig.AutoDelay = 3000\n\n-- แจ้งเตือนรางวัลที่รับอัตโนมัติทีละรายการ (ชื่อรางวัล + กิจกรรม วันที่ N)\n-- Notify each auto-claimed reward (reward name + track and day)\nConfig.AutoNotify = true\n\n-- ===== กล่องจดหมาย \u002F Mailbox delivery =====\n\n-- ส่งไอเทม\u002Fเงินเข้ากล่องจดหมายแทนกระเป๋า — กระเป๋าเต็มก็ไม่มีวันเสียของ\n--   resource = ชื่อสคริปต์กล่องจดหมาย ('' = เข้ากระเป๋าตรง) · ส่งยังไงดูที่ Reward.ToMailbox ใน addons\u002Freward\u002Fserver.lua\n--   box = กล่องปลายทาง ('safe' = ตู้นิรภัยไม่หมดอายุของ x3d_mailbox) · sender = ชื่อผู้ส่งบนจดหมาย\n-- Send items\u002Fmoney to a mailbox instead of the bag, so a full bag never loses a reward\n--   resource = the mailbox script ('' = straight to the bag) · see Reward.ToMailbox in addons\u002Freward\u002Fserver.lua\n--   box = target box ('safe' = x3d_mailbox's non-expiring safe) · sender = sender name on the mail\n-- เช่น \u002F e.g. { resource = 'x3d_mailbox', box = 'safe', sender = 'รางวัลเช็คชื่อ' }\nConfig.Mailbox = { resource = '', box = 'safe', sender = 'รางวัลเช็คชื่อ' }\n\n-- ===== รับย้อนหลัง \u002F Back-claim =====\n\n-- รับย้อนหลัง — ขาดไปหลายวันแล้วยังตามเก็บรางวัลวันที่พลาดได้\n--   enabled = false (ค่าเริ่มต้น) คือกดครั้งเดียวจบที่รางวัลของวันนี้ ของวันที่ขาดหายไปเลย\n--   enabled = true  คือกดได้ทีละวัน ไล่เก็บจากวันที่เก่าสุดที่ยังตามได้ มาจนถึงวันนี้\n--                   สตรีคเดินต่อเนื่องเพราะตัดวันทีละวัน ไม่กระโดด\n--   maxDays = ตามเก็บย้อนหลังได้ไกลสุดกี่วัน (3 = ขาดไป 5 วันก็ตามเก็บได้แค่ 3 วันหลังสุด)\n-- Back-claim: after missing several days the player can still collect the missed days\n--   enabled = false (default) means one press pays only today's reward, the missed days are gone\n--   enabled = true  means one day per press, oldest reachable day first, up to today\n--                   the streak stays continuous because days are consumed one at a time\n--   maxDays = how far back the player may collect (3 = after missing 5 days only the last 3 can be collected)\nConfig.BackClaim = {\n    enabled = false,\n    maxDays = 3,\n}\n\n-- ===== กระเป๋าเต็ม \u002F Full bag =====\n\n-- กระเป๋าเต็มตอนกดรับ: เก็บรางวัลไว้เป็น \"รางวัลค้างรับ\" ของผู้เล่นคนนั้น\n-- แล้วให้มากดรับทีหลังตอนมีที่ว่าง (สตรีคเดินต่อตามปกติ ไม่เสียวัน)\n-- false = ไม่ตัดวันให้เลย ผู้เล่นต้องเคลียร์กระเป๋าแล้วมากดใหม่\n-- Bag full at claim time: keep the reward as a \"pending reward\" for that player\n-- and let them claim it later when there is room (the streak continues, no day lost)\n-- false = the day is not consumed, the player clears the bag and claims again\nConfig.HoldWhenFull = true\n\n-- เก็บรางวัลค้างรับได้สูงสุดกี่ชุดต่อคน (เกินกว่านี้ต้องเคลียร์ของเก่าก่อน)\n-- Maximum pending rewards held per player (clear old ones before more are accepted)\nConfig.MaxPending = 10\n\n-- ===== ตารางรางวัล \u002F Reward table =====\n\n-- ตารางรางวัล — วันที่ 1..N ของสตรีค\n--   items  = { { item = 'ชื่อไอเทม', count = 1 } }\n--   money  = { { account = 'bank', amount = 500 } }\n--   weapon = { { name = 'WEAPON_PISTOL', ammo = 30 } }\n--   token  = { { kind = 'battle', amount = 5 } }   -- ต้องเซิร์ฟมีระบบเหรียญของตัวเอง ดู Reward.GiveToken\n--   label  = ชื่อรางวัลที่โชว์บนปฏิทิน (ไม่ใส่ก็ได้)\n-- Reward table: day 1..N of the streak\n--   items  = { { item = 'item name', count = 1 } }\n--   money  = { { account = 'bank', amount = 500 } }\n--   weapon = { { name = 'WEAPON_PISTOL', ammo = 30 } }\n--   token  = { { kind = 'battle', amount = 5 } }   -- needs your own token system, see Reward.GiveToken\n--   label  = reward name shown on the calendar (optional)\n-- เช่น \u002F e.g. [8] = { items = { { item = 'bread', count = 2 } } }\nConfig.Rewards = {\n    [1] = { money = { { account = 'money', amount = 500 } } },\n    [2] = { money = { { account = 'money', amount = 750 } } },\n    [3] = { money = { { account = 'bank', amount = 1000 } } },\n    [4] = { money = { { account = 'money', amount = 1250 } } },\n    [5] = { money = { { account = 'bank', amount = 1500 } } },\n    [6] = { money = { { account = 'money', amount = 2000 } } },\n    [7] = { money = { { account = 'bank', amount = 5000 } }, label = 'รางวัลครบสัปดาห์' },\n}\n\n-- วันที่ 8 วนกลับไปรับรางวัลวันที่ 1 ใหม่ (false = วันที่เกินตารางไม่มีรางวัล)\n-- Day 8 loops back to day 1's reward (false = days past the table give nothing)\nConfig.LoopRewards = true\n\n-- ===== แทร็กรางวัล \u002F Reward tracks =====\n\n-- แทร็กรางวัลหลายชุดพร้อมกัน (เช่น ปฏิทินปกติ + กิจกรรมเปิดตัวจำกัดเวลา) — แต่ละแทร็กมีสตรีค\u002Fปฏิทินของตัวเอง\n-- ปล่อยเป็น nil (ค่าเริ่มต้น) = ใช้ Config.Rewards ด้านบนเป็นแทร็กเดียวชื่อ 'default' เหมือนเดิมทุกอย่าง ไม่กระทบ config เดิม\n-- ตั้งเองแล้วอยากได้แทร็กเดิมด้วย ต้องใส่ id = 'default' รับ rewards = Config.Rewards เองในลิสต์\n--   id      = ชื่ออ้างอิง (unique)\n--   label   = ชื่อแท็บที่โชว์ในพาแนล (ไม่ใส่ก็โชว์ id)\n--   enabled = false = ปิดแทร็กนี้ไปเลย ไม่โชว์ไม่ให้กด\n--   loop    = true\u002Ffalse ครบตารางแล้ววนใหม่ไหม (ไม่ใส่ = ตาม Config.LoopRewards) — false = รับครั้งเดียวจบ เช่นแทร็กผู้เล่นใหม่\n--   from\u002Fto = os.time() ของช่วงเวลาที่แทร็กนี้เปิดอยู่ (unix, nil = ไม่จำกัด) — นอกช่วงนี้ = มองไม่เห็น กดไม่ได้\n--   rewards = ตารางรางวัลของแทร็กนี้ (รูปแบบเดียวกับ Config.Rewards)\n-- Several reward tracks at once (e.g. the normal calendar + a limited launch event), each with its own streak\u002Fcalendar\n-- nil (default) = Config.Rewards above is used as the single track 'default', nothing changes for old configs\n-- If you set this and still want the original track, add id = 'default' with rewards = Config.Rewards yourself\n--   id      = reference name (unique)\n--   label   = tab name shown in the panel (id is shown when omitted)\n--   enabled = false = track fully off, hidden and not claimable\n--   loop    = true\u002Ffalse whether the track loops after the last day (omitted = follows Config.LoopRewards), false = one time only, e.g. a new-player track\n--   from\u002Fto = os.time() window when the track is open (unix, nil = unlimited), outside it the track is hidden and locked\n--   rewards = reward table of this track (same format as Config.Rewards)\n-- Config.Tracks = {\n--     { id = 'default', label = 'เช็คอินรายวัน', enabled = true, rewards = Config.Rewards },\n--     { id = 'grand_open', label = 'เปิดเซิร์ฟใหม่', enabled = true, from = 1758000000, to = 1759000000, rewards = {\n--         [1] = { items = { { item = 'bread', count = 5 } } },\n--         [2] = { money = { { account = 'bank', amount = 3000 } } },\n--     } },\n-- }\nConfig.Tracks = nil\n\n-- ===== โบนัสเวลาเล่น \u002F Playtime bonus =====\n\n-- โบนัสเวลาเล่น — เล่นครบ N ชม. ในวันนี้ (นับตั้งแต่เข้าเกม ไม่รวมเวลาที่ออกจากเซิร์ฟ) ปลดล็อกรางวัลให้กด\n-- key = จำนวนชั่วโมง — ต้องกดรับเอง (ไม่ auto), รับได้ระดับละ 1 ครั้งต่อวัน, รีเซ็ตพร้อมเส้นแบ่งวันเดียวกับเช็คอิน\n-- Playtime bonus: playing N hours today (counted from join, offline time excluded) unlocks a reward to claim\n-- key = number of hours; claimed by hand (never automatic), once per tier per day, resets on the same day boundary as check-in\n-- เช่น \u002F e.g. [10] = { money = { { account = 'bank', amount = 2000 } }, label = 'เล่นครบ 10 ชม.' }\nConfig.PlaytimeBonusHours = {\n    [2] = { money = { { account = 'money', amount = 300 } }, label = 'เล่นครบ 2 ชม.' },\n    [5] = { money = { { account = 'bank', amount = 800 } }, label = 'เล่นครบ 5 ชม.' },\n}\n-- เช็ก\u002Fนับเวลาเล่นทุกกี่วินาที \u002F How often (seconds) playtime is checked and counted\nConfig.PlaytimeTickSeconds = 60\n\n-- โบนัสเวลาเล่นให้อะไร\n--   'reward'    = ครบชั่วโมงแล้วปลดล็อกของรางวัลในตาราง Config.PlaytimeBonusHours ให้กดรับเอง\n--   'extra_day' = ครบชั่วโมงแล้วรับวันถัดไปของทุกกิจกรรมให้ทันที (ไม่ต้องรอพรุ่งนี้) ไม่ใช้ของในตาราง\n-- What the playtime bonus gives\n--   'reward'    = each tier unlocks its Config.PlaytimeBonusHours reward to claim by hand\n--   'extra_day' = each tier instantly claims the next day of every active track (no waiting for tomorrow)\nConfig.PlaytimeMode = 'reward'\n\n-- ===== ชื่อที่โชว์ \u002F Display labels =====\n\n-- ชื่อไอเทมที่จะโชว์ (ไม่ใส่ก็ได้ — ไม่ใส่จะโชว์ชื่อ key ตรง ๆ)\n-- Item names to show (optional, the raw key is shown when missing)\n-- เช่น \u002F e.g. bread = 'ขนมปัง'\nConfig.ItemLabels = {\n    -- bread = 'ขนมปัง',\n}\n\n-- ชื่อบัญชีเงินที่จะโชว์ \u002F Money account names to show\nConfig.AccountLabels = {\n    money       = 'เงินสด',\n    bank        = 'ธนาคาร',\n    black_money = 'เงินดำ',\n}\n\n-- ชื่อเหรียญ\u002Fสกุลเงินพิเศษที่จะโชว์ (key = kind ใน token) ไม่ใส่ = โชว์ kind ตรง ๆ\n-- Token\u002Fcurrency names to show (key = kind in a token reward), the raw kind is shown when missing\n-- เช่น \u002F e.g. event = 'เหรียญกิจกรรม'\nConfig.TokenLabels = {\n    -- event = 'เหรียญกิจกรรม',\n}\n\n-- ชื่ออาวุธที่จะโชว์ (ไม่ใส่ก็ได้ — ไม่ใส่จะโชว์ชื่อ key ตรง ๆ)\n-- Weapon names to show (optional, the raw key is shown when missing)\n-- เช่น \u002F e.g. WEAPON_PISTOL = 'ปืนพก'\nConfig.WeaponLabels = {\n    -- WEAPON_PISTOL = 'ปืนพก',\n}\n\n-- ===== Inventory =====\n\n-- รูปไอเทมบนปฏิทิน — path รูปของ inventory ที่เซิร์ฟใช้ ({item} = ชื่อไอเทม)\n-- ปล่อยเป็น '' = ไม่โชว์รูป โชว์แค่ชื่อไอเทม\n-- Item image on the calendar: image path of your inventory ({item} = item name)\n-- '' = no image, only the item name is shown\nConfig.ItemImage = ''\n-- Config.ItemImage = 'nui:\u002F\u002Fx3d_inventory\u002Fweb\u002Fbuild\u002Fimg\u002Fitems\u002F{item}.png'\n-- Config.ItemImage = 'nui:\u002F\u002Fox_inventory\u002Fweb\u002Fimages\u002F{item}.png'\n-- Config.ItemImage = 'nui:\u002F\u002Fqb-inventory\u002Fhtml\u002Fimages\u002F{item}.png'\n-- ไม่มีในลิสต์นี้? เปิดโฟลเดอร์รูปไอเทมของ inventory resource ที่ใช้อยู่ แล้วคัดลอก path มาแทน\n-- Not in this list? Open your inventory's item image folder and copy the path\n\n-- เช็กว่ากระเป๋ารับของไหวก่อนจ่ายรางวัล — ใส่เฉพาะตอนเซิร์ฟใช้ inventory ของตัวเอง\n-- (x3d_inventory\u002Fox_inventory ฯลฯ) เพราะเลขน้ำหนักของ ESX เองจะเพี้ยนเมื่อ inventory\n-- ตัวอื่นเป็นคนคุม ทำให้รางวัลถูกปฏิเสธว่า \"กระเป๋าเต็ม\" ทั้งที่ยังว่าง\n-- ปล่อยว่าง = เช็กผ่าน ESX canCarryItem ถ้ามี ไม่มีก็ปล่อยผ่าน\n-- Check the bag can take the reward before paying; set it only when the server runs its own inventory\n-- (x3d_inventory\u002Fox_inventory etc.), because ESX's own weight numbers go stale when another inventory\n-- controls the bag and rewards get refused as \"bag full\" on an empty bag\n-- Empty = ESX canCarryItem if available, otherwise the check passes\nConfig.CanCarryExport = { resource = '', method = '' }\n-- Config.CanCarryExport = { resource = 'x3d_inventory', method = 'CanCarryItemSrc' }\n-- Config.CanCarryExport = { resource = 'ox_inventory', method = 'CanCarryItem' }\n\n-- ===== ที่เก็บข้อมูล \u002F Storage =====\n\n-- ไฟล์ JSON ที่เก็บข้อมูล และความถี่การเซฟ (วินาที)\n-- JSON file that holds the data, and how often it is saved (seconds)\nConfig.Storage = {\n    File         = 'data\u002Fdailylogin.json',\n    FlushSeconds = 30,\n}\n",1792316316454]