βš™οΈConfiguration

Default Configuration & Translations

Config = {}

Config.OpenCommand = "playtime" -- Command to open the Play To Earn UI

Config.PlayToEarn = {
    AutoCreateTables = true
}

Config.Mysql = "oxmysql" -- ghmattimysql , oxmysql , mysql-async 
Config.AddRewardCode = "ptr_generatecode" -- Usage - ptr_generatecode code reward (Example: ptr_generatecode ZR-ONCODEREDEEM 150)

Config.VehicleDB = {
    table = "player_vehicles",  -- owned_vehicles for ESX, player_vehicles for QBCore
    garage = "pillboxgarage", -- legionsquare or any other garage you want the vehicle to be spawned in.
    state = 1   -- 1 for vehicle in garage, 0 for vehicle in impound.
}

Config.Reward = {
    Interval = 60 * 60, -- 1 hour in seconds , 15 minutes = 15 * 60
    Amount = 10         -- Coins rewarded every interval
}

Config.Redeem = true -- to activate or desactived redeem

Config.Notification = {
    System = "ox_lib", -- options: qb-core, qbox-core, esx, mythic_notify, ox_lib
    Duration = 10000 -- Default notification duration in milliseconds 
}

Config.UI = {
    Position = 'left', -- Switch between 'right' or 'left'.
    Color = '#00CCB8' -- Default playtime Hex color
}

Config.ItemImagePath = "nui://qb-inventory/html/images/" -- nui://ox_inventory/web/images/
Config.Avatar = '/zr-nui/zr-assets/zr-img/zr-default-avatar.png' -- Default avatar to display if you don't setup your discord API.
Config.Link = "https://0bugscripts.tebex.io/" -- Tebex store link for buying coins.


-- Battlepass XP
Config.BattlepassXP = false -- Enable or disable giving Battlepass XP on reward if you have our Battlepass script.
Config.BattlepassXPAmount = 10 -- Amount of XP to give per reward interval.

-- Translations

Config.Translations = {
    ["invalid_code"] = "Invalid code.",
    ["code_already_used"] = "Code already used.",
    ["invalid_request"] = "Invalid request.",
    ["buy_success"] = "You bought %sx %s for %s coins. New balance: %s.",
    ["buy_vehicle_success"] = "You bought vehicle '%s' for %s coins and we'll send it to your Garage. New balance: %s.",
    ["not_enough_coins"] = "You need %s coins to buy '%s'. You only have %s.",
    ["earned_coins"] = "You've earned %s coins for playing %d minute(s)."
}

-- IMPORTANT: Each item across Config.PTEItems and Config.DealsSessions must have a UNIQUE id.
-- Duplicate IDs will cause purchase issues (deals may be ignored if same id exists in PTEItems and DealsSessions).
-- Leaving image empty for vehicle items will use the default vehicle image from the game.
Config.PTEItems = {
    -- πŸ” Consumables 
    { id = 1,  itemName = "water", label = "Water Bottle", price = 25,  count = 20, itemType = "item",   category = "tools", image = "water_bottle.png", description = "Stay hydrated on the go." },
    { id = 2,  itemName = "sandwich",     label = "Sandwich",      price = 10,  count = 50, itemType = "item",   category = "tools", image = "sandwich.png",     description = "A quick snack to fill your stomach." },
    { id = 3,  itemName = "coffee",       label = "Coffee",        price = 15,  count = 30, itemType = "item",   category = "tools", image = "coffee.png",       description = "Keeps you awake and alert." },
    { id = 4,  itemName = "cola",         label = "Cola",          price = 10,  count = 35, itemType = "item",   category = "tools", image = "cola.png",         description = "Sugary fizz to keep you going." },

    -- πŸ”§ Tools & Utility
    { id = 5,  itemName = "repairkit",         label = "Repair Kit",         price = 15,  count = 30, itemType = "item",   category = "tools", image = "repairkit.png",          description = "Essential for quick repairs." },
   
    { id = 7,  itemName = "cleaningkit",       label = "Cleaning Kit",       price = 20,  count = 25, itemType = "item",   category = "tools", image = "cleaningkit.png",        description = "Make that ride sparkle." },
    { id = 8,  itemName = "lockpick",          label = "Lockpick",           price = 100, count = 20, itemType = "item",   category = "tools", image = "lockpick.png",           description = "Open basic locks and vehicles." },
    { id = 9,  itemName = "advancedlockpick",  label = "Advanced Lockpick",  price = 300, count = 10, itemType = "item",   category = "tools", image = "advancedlockpick.png",   description = "Higher success rate on tough locks." },
    { id = 10, itemName = "phone",             label = "Phone",              price = 250, count = 10, itemType = "item",   category = "tools", image = "phone.png",              description = "Stay connected with your contacts." },
    { id = 11, itemName = "radio",             label = "Radio",              price = 150, count = 15, itemType = "item",   category = "tools", image = "radio.png",              description = "Group comms on custom frequencies." },
    { id = 12, itemName = "drill",             label = "Drill",              price = 350, count = 8,  itemType = "item",   category = "tools", image = "drill.png",              description = "For… legitimate construction. Sure." },
    { id = 13, itemName = "thermite",          label = "Thermite",           price = 600, count = 6,  itemType = "item",   category = "tools", image = "thermite.png",           description = "Melts locks and panels. Handle carefully." },
    { id = 14, itemName = "electronickit",     label = "Electronic Kit",     price = 250, count = 12, itemType = "item",   category = "tools", image = "electronickit.png",      description = "Wiring & modules for advanced tinkering." },
    { id = 15, itemName = "handcuffs",         label = "Handcuffs",          price = 120, count = 10, itemType = "item",   category = "tools", image = "handcuffs.png",          description = "Secure restraint device." },
    { id = 16, itemName = "binoculars",        label = "Binoculars",         price = 75,  count = 15, itemType = "item",   category = "tools", image = "binoculars.png",         description = "See far, stay hidden." },
    { id = 17, itemName = "harness",           label = "Racing Harness",     price = 180, count = 10, itemType = "item",   category = "tools", image = "harness.png",            description = "Keeps you secure under heavy braking." },
    { id = 18, itemName = "bandage",           label = "Bandage",            price = 50,  count = 25, itemType = "item",   category = "tools", image = "bandage.png",            description = "Stops bleeding and stabilizes wounds." },
    { id = 19, itemName = "firstaid",          label = "First Aid Kit",      price = 150, count = 10, itemType = "item",   category = "tools", image = "firstaid.png",           description = "Emergency medical kit." },
    { id = 20, itemName = "armor",             label = "Armor",              price = 60,  count = 1,  itemType = "item",   category = "tools", image = "armor.png",              description = "Protective gear for enhanced safety." },

    -- πŸ”« Weapons
    { id = 21, itemName = "weapon_pistol",     label = "Pistol",             price = 50,  count = 50, itemType = "weapon", category = "weapons", image = "weapon_pistol.png",  description = "A reliable sidearm for self-defense." },
    { id = 22, itemName = "weapon_knife",      label = "Knife",              price = 40,  count = 20, itemType = "weapon", category = "weapons", image = "weapon_knife.png",   description = "A sharp blade for close combat." },
    { id = 23, itemName = "weapon_bat",        label = "Baseball Bat",       price = 30,  count = 20, itemType = "weapon", category = "weapons", image = "weapon_bat.png",     description = "Handy for, uh, batting practice." },
    { id = 24, itemName = "weapon_assaultrifle", label = "Assault Rifle",         price = 20,  count = 25, itemType = "weapon", category = "weapons", image = "weapon_assaultrifle.png", description = "Reliable in combat with high damage." },

    -- πŸš— Vehicles (images intentionally empty)
    { id = 25, itemName = "sultan",   label = "Sultan",   price = 200, count = 1, itemType = "vehicle", category = "vehicles", image = "", description = "A fast and stylish car." },
    { id = 26, itemName = "banshee",  label = "Banshee",  price = 400, count = 1, itemType = "vehicle", category = "vehicles", image = "", description = "A stylish high-performance car." },
    { id = 27, itemName = "buffalo",  label = "Buffalo",  price = 300, count = 1, itemType = "vehicle", category = "vehicles", image = "", description = "A sporty and durable car." },
    { id = 28, itemName = "faggio",   label = "Faggio",   price = 100, count = 1, itemType = "vehicle", category = "vehicles", image = "", description = "A scooter for city cruising." },
    
   -- Add more items as needed
   -- { id = 7, itemName = "customcarwithfileimage", label = "Custom Car", price = 10, count = 1, itemType = "vehicle", category = "vehicles", image = "/zr-nui/zr-assets/zr-img/zr-custom-car.png", description = "A fast and stylish car." },
   -- { id = 8, itemName = "customcarwithlinkimage", label = "Custom Car 2", price = 100, count = 1, itemType = "vehicle", category = "vehicles", image = "https://r2.fivemanage.com/Nx4HzokyVspdndCjdswsc/images/zr-logo1.png", description = "A luxury car with high performance." },

}


-- Each session has its own item list
Config.DealsSessions = {
    {
        start   = "2025-08-06 00:00:00",
        endTime = "2025-10-31 23:57:00",
        items = {
            { id = 201, itemName = "metalscrap",   label = "Metal Scrap",   originalPrice = 50,  price = 30, count = 20, itemType = "item",   category = "tools",   image = "metalscrap.png",  discount = 40, description = "Essential material used for crafting." },
            { id = 202, itemName = "plastic",      label = "Plastic",       originalPrice = 40,  price = 28, count = 20, itemType = "item",   category = "tools",   image = "plastic.png",     discount = 30, description = "Lightweight material used for crafting." },
            { id = 203, itemName = "rubber",       label = "Rubber",        originalPrice = 35,  price = 20, count = 25, itemType = "item",   category = "tools",   image = "rubber.png",      discount = 42, description = "Durable crafting material." },
            { id = 204, itemName = "lockpick",     label = "Lockpick",      originalPrice = 100, price = 70, count = 2,  itemType = "item",   category = "tools",   image = "lockpick.png",    discount = 30, description = "Open basic locks and vehicles." },
            { id = 205, itemName = "advancedlockpick", label = "Advanced Lockpick", originalPrice = 300, price = 210, count = 1, itemType = "item", category = "tools", image = "advancedlockpick.png", discount = 30, description = "Higher success rate on tough locks." },
            { id = 206, itemName = "repairkit",    label = "Repair Kit",    originalPrice = 30,  price = 20, count = 2,  itemType = "item",   category = "tools",   image = "repairkit.png",   discount = 33, description = "Essential for quick repairs." },
            { id = 207, itemName = "armor",        label = "Armor",         originalPrice = 60,  price = 40, count = 1,  itemType = "item",   category = "tools",   image = "armor.png",       discount = 33, description = "Protective gear for enhanced safety." },
            { id = 208, itemName = "weapon_microsmg", label = "Micro SMG",  originalPrice = 250, price = 200, count = 1, itemType = "weapon", category = "weapons", image = "weapon_microsmg.png", discount = 20, description = "Compact SMG, good for drive-bys." },
            { id = 209, itemName = "weapon_knife", label = "Knife",         originalPrice = 40,  price = 25, count = 1,  itemType = "weapon", category = "weapons", image = "weapon_knife.png", discount = 38, description = "A sharp blade for close combat." },
            { id = 210, itemName = "zentorno",     label = "Zentorno",      originalPrice = 900, price = 680, count = 1, itemType = "vehicle", category = "vehicles", image = "", discount = 25, description = "Exotic supercar with insane performance." }
        }
    },
    {
        start   = "2025-09-01 00:00:00",
        endTime = "2025-11-07 23:59:59",
        items = {
            { id = 211, itemName = "metalscrap",   label = "Metal Scrap",   originalPrice = 50,  price = 35, count = 15, itemType = "item",   category = "tools",   image = "metalscrap.png",  discount = 30, description = "Essential material used for crafting." },
            { id = 212, itemName = "plastic",      label = "Plastic",       originalPrice = 40,  price = 25, count = 20, itemType = "item",   category = "tools",   image = "plastic.png",     discount = 38, description = "Lightweight material used for crafting." },
            { id = 213, itemName = "rubber",       label = "Rubber",        originalPrice = 35,  price = 22, count = 25, itemType = "item",   category = "tools",   image = "rubber.png",      discount = 37, description = "Durable crafting material." },
            { id = 214, itemName = "firstaid",     label = "First Aid Kit", originalPrice = 150, price = 100, count = 1, itemType = "item",   category = "tools",   image = "firstaid.png",    discount = 33, description = "Emergency medical kit." },
            { id = 215, itemName = "bandage",      label = "Bandage",       originalPrice = 50,  price = 35, count = 5,  itemType = "item",   category = "tools",   image = "bandage.png",     discount = 30, description = "Stops bleeding and stabilizes wounds." },
            { id = 216, itemName = "armor",        label = "Armor",         originalPrice = 60,  price = 42, count = 1,  itemType = "item",   category = "tools",   image = "armor.png",       discount = 30, description = "Protective gear for enhanced safety." },
            { id = 217, itemName = "weapon_sawnoffshotgun", label = "Sawed-Off Shotgun", originalPrice = 300, price = 210, count = 1, itemType = "weapon", category = "weapons", image = "weapon_sawnoffshotgun.png", discount = 30, description = "Powerful close-range shotgun." },
            { id = 218, itemName = "weapon_bat",   label = "Baseball Bat",  originalPrice = 30,  price = 20, count = 1,  itemType = "weapon", category = "weapons", image = "weapon_bat.png",   discount = 33, description = "Handy for, uh, batting practice." },
            { id = 219, itemName = "bati",         label = "Bati 801",      originalPrice = 150, price = 110, count = 1, itemType = "vehicle", category = "vehicles", image = "", discount = 27, description = "A sleek racing bike, perfect for city cruising." },
            { id = 220, itemName = "hakuchou",     label = "Hakuchou",      originalPrice = 200, price = 150, count = 1, itemType = "vehicle", category = "vehicles", image = "", discount = 25, description = "Luxury superbike for speed lovers." }
        }
    },
    {
        start   = "2025-10-01 00:00:00",
        endTime = "2025-12-07 23:59:59",
        items = {
            { id = 221, itemName = "metalscrap",   label = "Metal Scrap",   originalPrice = 50,  price = 32, count = 20, itemType = "item",   category = "tools",   image = "metalscrap.png",  discount = 36, description = "Essential material used for crafting." },
            { id = 222, itemName = "plastic",      label = "Plastic",       originalPrice = 40,  price = 27, count = 20, itemType = "item",   category = "tools",   image = "plastic.png",     discount = 32, description = "Lightweight material used for crafting." },
            { id = 223, itemName = "rubber",       label = "Rubber",        originalPrice = 35,  price = 18, count = 25, itemType = "item",   category = "tools",   image = "rubber.png",      discount = 48, description = "Durable crafting material." },
            { id = 224, itemName = "lockpick",     label = "Lockpick",      originalPrice = 100, price = 75, count = 2,  itemType = "item",   category = "tools",   image = "lockpick.png",    discount = 25, description = "Open basic locks and vehicles." },
            { id = 225, itemName = "advancedlockpick", label = "Advanced Lockpick", originalPrice = 300, price = 220, count = 1, itemType = "item", category = "tools", image = "advancedlockpick.png", discount = 27, description = "Higher success rate on tough locks." },
            { id = 226, itemName = "thermite",     label = "Thermite",      originalPrice = 600, price = 450, count = 1, itemType = "item",   category = "tools",   image = "thermite.png",    discount = 25, description = "Melts locks and panels. Handle carefully." },
            { id = 227, itemName = "weapon_compactrifle", label = "Compact Rifle", originalPrice = 400, price = 280, count = 1, itemType = "weapon", category = "weapons", image = "weapon_compactrifle.png", discount = 30, description = "Portable rifle with strong firepower." },
            { id = 228, itemName = "weapon_flashlight", label = "Flashlight", originalPrice = 20, price = 12, count = 1, itemType = "weapon", category = "weapons", image = "weapon_flashlight.png", discount = 40, description = "Light up dark corners." },
            { id = 229, itemName = "hakuchou",     label = "Hakuchou",      originalPrice = 200, price = 150, count = 1, itemType = "vehicle", category = "vehicles", image = "", discount = 25, description = "Luxury superbike for speed lovers." },
            { id = 230, itemName = "banshee",      label = "Banshee",       originalPrice = 400, price = 300, count = 1, itemType = "vehicle", category = "vehicles", image = "", discount = 25, description = "A stylish high-performance car." }
        }
    }
}

Extra Translations JS Side - (/zr-nui/zr-js/zr-translation.js)

const texts = {
    coins: 'Coins',
    coinsBalance: 'Coins Balance',
    nextRewardIn: 'Next reward in',
    premiumShop: 'Premium Shop',
    deals: 'Deals',
    leaderboard: 'Leaderboard',
    settings: 'Settings',
    endingIn: 'Ending In:',
    tools: 'Tools',
    weapons: 'Weapons',
    vehicles: 'Vehicles',
    shopEmpty: 'Shop is empty',
    shopEmptyText: "No supplies are in stock right now. Come back soon.",
    off: 'OFF',
    dealsLocked: 'Deals Locked',
    dealsLockedText: "Check back soon for exclusive time-limited offers.",
    purchase: 'Purchase',
    positioning: 'Positioning',
    poisitioningText: "Select an option to change the playtime's position. It applies instantly click 'Save' to confirm.",
    leftSide: 'Left side',
    rightSide: 'Right side',
    colorSettings: 'Color Settings',
    colorSettingsText: "Use the selector to change the primary color.",
    edit: 'Edit',
    resetSettings: 'Reset Settings',
    resetSettingsText: "Revert and reset all settings.",
    reset: 'Reset',
    success: 'Success',
    successQuantity: 'You’ve received +',
    successMessage: 'Thank you for your purchase!',
    youRecived: 'You recived',
    newBalance: 'Your new balance',
    close: 'Close',
    transactionFailed: 'Transaction Failed',
    failedMessage: "We couldn't complete your coin purchase.",
    cancel: 'Cancel',
    tryAgain: 'Try Again',
    confirmPurchase: 'Confirm Purchase',
    areYouSure: 'Are you sure you want to buy',
    thisWillCost: 'This will cost',
    buy: 'Buy',
    enterTheCode: 'Enter the code',
    redeem: 'Redeem',
    buyMoreCoins: 'Buy more coins'
};

Secured Discord Bot Token on Server Side (zr-token.lua)

zr_discord_avatar_token = '' -- Your discord bot token here!

Notifications System & Extra Reward Function

RegisterNetEvent('0bug-playtoearn:Notify', function(message, type, duration)
    type = type or "info"
    duration = (duration and duration >= 1000) and duration or Config.Notification.Duration

    local notifyType = type

    if Config.Notification.System == "qb-core" or Config.Notification.System == "qbox-core" then
        TriggerEvent('QBCore:Notify', message, notifyType, duration)

    elseif Config.Notification.System == "esx" then
        TriggerEvent('esx:showNotification', message)

    elseif Config.Notification.System == "mythic_notify" then
        if type == "error" then
            exports['mythic_notify']:DoHudText('error', message)
        elseif type == "success" then
            exports['mythic_notify']:DoHudText('success', message)
        else
            exports['mythic_notify']:DoHudText('inform', message)
        end

    elseif Config.Notification.System == "ox_lib" then
        local data = {
            title = type:gsub("^%l", string.upper),
            description = message,
            type = type,
            duration = duration  -- Convert ms to seconds
        }
        TriggerEvent('ox_lib:notify', data)
    end
end)


-- This is a hook that runs when a player receives a reward from play-to-earn.
-- You can add extra logic here (e.g., give items, money, XP, etc.)
AddEventHandler('0bug-playtoearn:onRewardGiven', function(src, citizenid, amount)
    -- Example: give a bonus item
    -- local Player = QBCore.Functions.GetPlayer(src)
    -- Player.Functions.AddItem('water', 1)

    -- Example: Give 0bug_BattlePass XP
    if Config.BattlepassXP then
        exports['0bug_Battlepass']:addXP(citizenid, Config.BattlepassXPAmount) -- Give XP to the player based on config 
    end 
    
    -- Example: send custom log
    -- print(("Player %s earned %s coins and got a bonus item!"):format(citizenid, amount))
end)

Last updated