DRS Battle Pass

Passe de temporada com trilho grátis e premium, 30 níveis, raridades, missões diárias e semanais e códigos para a tua loja VIP ou Tebex.

v2.1.2 QBCoreQboxESX drs_battlepass
Ver na loja

Passe de temporada com trilho grátis e premium, 30 níveis com raridades, missões diárias e semanais, XP por tempo de jogo e códigos de premium / tiers <n>para a tua loja VIP ou Tebex. O perfil mostra a foto do Discord do jogador.

#Requisitos

FrameworkQBCore, Qbox ou ESX (deteção automática)
Base de dadosoxmysql
OpcionalDRS Mining e DRS Crafting (missões de minerar, fundir e fabricar)

#Instalação

  1. Coloca a pasta drs_battlepass em resources e adiciona ao server.cfg, depois do oxmysql, do framework e do inventário:
server.cfg
ensure drs_battlepass
  1. As tabelas drs_battlepass e drs_battlepass_codes são criadas sozinhas.
  2. Define a temporada, as recompensas e as missões no config.lua.
  3. Opcional — foto do Discord no perfil:
server.cfg
set drs_discord_bot_token "TOKEN_DO_TEU_BOT"

#Como funciona

  • O jogador abre o passe com F10 ou /passe (cada um pode mudar a tecla nas definições do GTA).
  • Ganha XP com o tempo de jogo e com as missões; cada Config.XPPerTier XP é um nível.
  • Em cada nível há uma recompensa grátis e uma premium. O botão Resgatar tudo recebe tudo o que já desbloqueou.
  • As recompensas têm raridade (comum, rara, épica, lendária). Sem rarity definido: níveis 10/20/30 são lendários, 5/15/25 épicos, o resto premium / tiers <n>é raro.
  • As missões diárias mudam à meia-noite e as semanais à segunda-feira (hora do servidor).

#Temporadas

Muda Config.Season.id para começar uma temporada nova. O progresso das anteriores fica guardado na base de dados. Depois da data Config.Season.ends já não se ganha XP, mas ainda se resgata.

#Premium e códigos

Por defeito o premium / tiers <n>só se obtém por código (Config.Premium.buyWithMoney = false).

ComoExemplo
Consola / Tebexdrsbp_code {transaction} premium ou drsbp_code CODIGO tiers 10
Outro script (ex.: loja VIP)exports.drs_battlepass:CreateCode('premium') → devolve BP-XXXX-XXXX-XXXX
O jogador resgata/passecodigo CODIGO ou no separador Loja

Dica

No Tebex, põe no pacote o comando de servidor drsbp_code {transaction} premium. O jogador recebe o ID da transação por email e resgata-o no jogo. Cada código só se usa uma vez.

#Missões

Tipos incluídos: playtime (minutos), drive (km), mining e smelting (DRS Mining) e crafting (DRS Crafting). As missões de um script que não está a correr não aparecem.

config.lua
{ id = 'd_play30', type = 'playtime', goal = 30, xp = 250, label = { pt = 'Joga 30 minutos', en = 'Play for 30 minutes' } },

Qualquer outro script pode acrescentar progresso com um tipo teu:

server
exports.drs_battlepass:AddProgress(src, 'fishing', 1)   -- e crias missões com type = 'fishing'

#Comandos

ComandoQuemO que faz
/passe (ou F10)todosAbre o passe
/passecodigo [código]todosResgata um código
/passexp [id] [quantidade]staffDá ou tira XP
drsbp_code <código> premium ou tiers <n>consolaCria um código

#Opções principais

OpçãoPor defeitoDescrição
Config.Seasonid 1, fim 2026-12-31Temporada atual
Config.MaxTier / Config.XPPerTier30 / 1000Níveis e XP por nível
Config.PlaytimeXP60 XP a cada 10 minXP por tempo de jogo
Config.Premium.buyWithMoneyfalsetrue = também se compra com dinheiro do jogo
Config.Premium.retroactivetrueQuem compra a meio recebe as premium / tiers <n>dos níveis que já tem
Config.TierPurchase.enabledfalseCompra de níveis com dinheiro do jogo
Config.DailyCount / Config.WeeklyCount3 / 3Missões sorteadas por jogador
Config.MaxDriveSpeed75Limite anti-batota para os km (m/s)

#Configuração completa

config.lua
Config = {}

-- Idioma / Language: 'pt' ou 'en'
Config.Locale = 'pt'

-- Framework: 'auto' deteta Qbox/QBCore/ESX (ou 'qbx' | 'qb' | 'esx')
Config.Framework = 'auto'

-- Abrir o passe / Opening the pass
Config.Command = 'passe'
Config.OpenKey = 'F10'              -- tecla por defeito (cada jogador pode mudar nas definições do GTA) / default key

-- Foto do Discord no perfil. Precisa do token de um bot no server.cfg: set drs_discord_bot_token "TOKEN"
-- Discord picture on the profile. Needs a bot token in server.cfg: set drs_discord_bot_token "TOKEN"
Config.DiscordAvatar = { enabled = true, convar = 'drs_discord_bot_token' }

-- Imagens dos itens ('auto' = pasta do inventário que estiver a correr) / Item images ('auto' = running inventory)
Config.ImagePath = 'auto'

-- ------------------------------------------------------------------ temporada / season
-- Mudar o id recomeça o passe para toda a gente (o progresso antigo fica guardado).
-- Changing the id restarts the pass for everyone (old progress stays in the database).
Config.Season = {
    id = 1,
    name = 'Temporada 1',
    ends = '2026-12-31',            -- AAAA-MM-DD; depois disto já não se ganha XP / after this no XP is earned
}

Config.MaxTier = 30
Config.XPPerTier = 1000

-- XP por tempo de jogo / XP for playtime
Config.PlaytimeXP = { every = 10, xp = 60 }   -- a cada 10 minutos / every 10 minutes

-- ------------------------------------------------------------------ premium e compras / premium and purchases
Config.Premium = {
    buyWithMoney = false,          -- false = só por código (ex.: gerado pela loja VIP) / false = codes only (e.g. from a VIP shop)
    price = 75000,
    account = 'bank',
    -- Link da loja (aparece um botão). Vazio = sem botão. / Store link (a button shows). Empty = no button.
    storeUrl = '',
    -- Quem compra o premium a meio recebe logo as recompensas premium dos níveis que já tem?
    -- Players who buy premium mid-season can claim premium rewards of the tiers they already have?
    retroactive = true,
}

Config.TierPurchase = {
    enabled = false,
    price = 6000,                  -- por nível / per tier
    account = 'bank',
    max = 10,                      -- máximo por compra / max per purchase
    bundles = { 1, 5, 10 },        -- pacotes na loja / store bundles
}

-- Códigos (ex.: para o Tebex). Na consola do servidor / In the server console:
--   drsbp_code <codigo> premium          → premium
--   drsbp_code <codigo> tiers <n>        → n níveis / n tiers
-- No Tebex, comando do pacote / Tebex package command:  drsbp_code {transaction} premium
-- O jogador resgata com / The player redeems with:  /passecodigo <codigo>
Config.RedeemCommand = 'passecodigo'
Config.CodeCommand = 'drsbp_code'

-- ------------------------------------------------------------------ recompensas / rewards
-- { item = 'nome', amount = n }  ·  { money = n, account = 'bank' }
-- Opcional / optional: label, image (URL ou nome de ficheiro / URL or file name),
--   rarity = 'common' | 'rare' | 'epic' | 'legendary' (sem isto: nível 10/20/30 lendário, 5/15/25 épico, premium raro)
Config.Rewards = {
    [1]  = { free = { item = 'water_bottle', amount = 5 },        premium = { money = 5000 } },
    [2]  = { free = { item = 'sandwich', amount = 5 },            premium = { item = 'bandage', amount = 10 } },
    [3]  = { free = { money = 2500 },                             premium = { item = 'repairkit', amount = 2 } },
    [4]  = { free = { item = 'bandage', amount = 5 },             premium = { item = 'lockpick', amount = 5 } },
    [5]  = { free = { item = 'lockpick', amount = 2 },            premium = { money = 15000 } },
    [6]  = { free = { item = 'water_bottle', amount = 10 },       premium = { item = 'radio', amount = 1 } },
    [7]  = { free = { money = 5000 },                             premium = { item = 'armor', amount = 2 } },
    [8]  = { free = { item = 'repairkit', amount = 1 },           premium = { item = 'advancedlockpick', amount = 2 } },
    [9]  = { free = { item = 'sandwich', amount = 10 },           premium = { item = 'ifaks', amount = 5 } },
    [10] = { free = { money = 10000 },                            premium = { item = 'goldbar', amount = 2 } },
    [11] = { free = { item = 'bandage', amount = 10 },            premium = { money = 20000 } },
    [12] = { free = { item = 'lockpick', amount = 3 },            premium = { item = 'advancedrepairkit', amount = 2 } },
    [13] = { free = { money = 7500 },                             premium = { item = 'electronickit', amount = 2 } },
    [14] = { free = { item = 'repairkit', amount = 2 },           premium = { item = 'armor', amount = 3 } },
    [15] = { free = { item = 'armor', amount = 1 },               premium = { money = 35000 } },
    [16] = { free = { money = 10000 },                            premium = { item = 'goldbar', amount = 3 } },
    [17] = { free = { item = 'ifaks', amount = 3 },               premium = { item = 'drill', amount = 1 } },
    [18] = { free = { item = 'advancedlockpick', amount = 1 },    premium = { money = 40000 } },
    [19] = { free = { money = 12500 },                            premium = { item = 'advancedrepairkit', amount = 3 } },
    [20] = { free = { item = 'goldbar', amount = 1 },             premium = { item = 'diamond', amount = 1 } },
    [21] = { free = { item = 'radio', amount = 1 },               premium = { money = 50000 } },
    [22] = { free = { money = 15000 },                            premium = { item = 'armor', amount = 5 } },
    [23] = { free = { item = 'advancedrepairkit', amount = 1 },   premium = { item = 'goldbar', amount = 5 } },
    [24] = { free = { item = 'ifaks', amount = 5 },               premium = { money = 60000 } },
    [25] = { free = { money = 20000 },                            premium = { item = 'diamond', amount = 2 } },
    [26] = { free = { item = 'armor', amount = 2 },               premium = { item = 'drill', amount = 2 } },
    [27] = { free = { item = 'goldbar', amount = 2 },             premium = { money = 80000 } },
    [28] = { free = { money = 25000 },                            premium = { item = 'diamond', amount = 3 } },
    [29] = { free = { item = 'diamond', amount = 1 },             premium = { item = 'goldbar', amount = 10 } },
    [30] = { free = { money = 50000 },                            premium = { money = 150000, label = 'Prémio final' } },
}

-- ------------------------------------------------------------------ missões / missions
-- type: o que conta / what counts
--   'playtime' minutos em jogo / minutes played        'drive' km a conduzir / km driven
--   'mining' rochas partidas (drs_mining)              'smelting' barras fundidas (drs_mining)
--   'crafting' itens fabricados (drs_crafting)
--   qualquer outro nome: outro script chama exports.drs_battlepass:AddProgress(src, 'nome', n)
--   any other name: another script calls exports.drs_battlepass:AddProgress(src, 'name', n)
-- requires: só aparece se esse recurso estiver a correr / only shows if that resource is running
Config.DailyCount = 3
Config.WeeklyCount = 3
Config.Missions = {
    daily = {
        { id = 'd_play30',  type = 'playtime', goal = 30, xp = 250, label = { pt = 'Joga 30 minutos', en = 'Play for 30 minutes' } },
        { id = 'd_play60',  type = 'playtime', goal = 60, xp = 450, label = { pt = 'Joga 1 hora', en = 'Play for 1 hour' } },
        { id = 'd_drive5',  type = 'drive',    goal = 5,  xp = 250, label = { pt = 'Conduz 5 km', en = 'Drive 5 km' } },
        { id = 'd_drive15', type = 'drive',    goal = 15, xp = 500, label = { pt = 'Conduz 15 km', en = 'Drive 15 km' } },
        { id = 'd_mine10',  type = 'mining',   goal = 10, xp = 400, requires = 'drs_mining', label = { pt = 'Parte 10 rochas', en = 'Break 10 rocks' } },
        { id = 'd_smelt10', type = 'smelting', goal = 10, xp = 400, requires = 'drs_mining', label = { pt = 'Funde 10 barras', en = 'Smelt 10 bars' } },
        { id = 'd_craft5',  type = 'crafting', goal = 5,  xp = 350, requires = 'drs_crafting', label = { pt = 'Fabrica 5 itens', en = 'Craft 5 items' } },
    },
    weekly = {
        { id = 'w_play300',  type = 'playtime', goal = 300, xp = 2000, label = { pt = 'Joga 5 horas', en = 'Play for 5 hours' } },
        { id = 'w_drive60',  type = 'drive',    goal = 60,  xp = 1800, label = { pt = 'Conduz 60 km', en = 'Drive 60 km' } },
        { id = 'w_mine60',   type = 'mining',   goal = 60,  xp = 2200, requires = 'drs_mining', label = { pt = 'Parte 60 rochas', en = 'Break 60 rocks' } },
        { id = 'w_smelt50',  type = 'smelting', goal = 50,  xp = 2000, requires = 'drs_mining', label = { pt = 'Funde 50 barras', en = 'Smelt 50 bars' } },
        { id = 'w_craft30',  type = 'crafting', goal = 30,  xp = 2000, requires = 'drs_crafting', label = { pt = 'Fabrica 30 itens', en = 'Craft 30 items' } },
        { id = 'w_play600',  type = 'playtime', goal = 600, xp = 3500, label = { pt = 'Joga 10 horas', en = 'Play for 10 hours' } },
    },
}

-- Limite anti-batota para os km: metros por segundo aceites / Anti-cheat cap for km: accepted metres per second
Config.MaxDriveSpeed = 75.0

-- Comando de staff: /passexp [id] [quantidade] / Staff command
Config.XPCommand = 'passexp'
Config.StaffGroups = { 'god', 'admin', 'superadmin' }

Config.Webhook = ''
Config.Debug = false               -- mensagens de diagnóstico na consola / diagnostic messages in the console
Config.UseOxNotify = false

#Para programadores

server
exports.drs_battlepass:AddXP(src, 250)
exports.drs_battlepass:AddProgress(src, 'mining', 1)
exports.drs_battlepass:IsPremium(src)
exports.drs_battlepass:GetTier(src)
exports.drs_battlepass:GivePremium(src)
exports.drs_battlepass:CreateCode('premium')            -- ou CreateCode('tiers', 5)

#Resolução de problemas

A foto do Discord não aparece — confirma o drs_discord_bot_token no server.cfg e que o jogador tem o Discord ligado ao FiveM. O script usa discordapp.com, porque em alguns alojamentos as ligações ao discord.com ficam penduradas.

"Código inválido ou já usado." — o código não existe ou já foi resgatado. Os códigos só se criam pela consola ou pelo export.