Home Scripts Docs Customers Contact
All documentation DD Battlepass

Install it,
configure it, run it.

Setup, configuration and troubleshooting for dd-battlepass, written alongside the code and shipped with every download.

A seasonal battlepass for QBCore, Qbox and ESX. Free and premium tracks, item and money rewards, challenges, and a full in-game admin panel. Resource name is dd-battlepass, and that exact spelling matters when installing or calling exports.

Installation

  1. Place the dd-battlepass folder in your server resources.
  2. Start oxmysql, your framework and your inventory first.
  3. Add ensure dd-battlepass after those resources in your server configuration.
  4. Grant the admin permission for your framework, covered in Admin panel.
  5. Restart the server, or run refresh followed by ensure dd-battlepass in the console.
  6. Open /battlepass or press F7. Escape and the close button release NUI focus.

Nothing else is framework-specific. The same folder runs on Qbox, QBCore and ESX, and both the framework and the inventory are detected automatically.

There is no ox_lib dependency. OneSync is required. Default key bindings can be changed in FiveM Settings, Key Bindings. Changing the config default does not replace a binding a player has already saved.

Database

The six SQL tables are created automatically on first start, on every supported framework. oxmysql must already have a working database connection.

If the database account has no CREATE permission, import sql/install.sql yourself with an account that does, then set this in config.server.lua:

DigitalDEN.AutoCreateTables = false

sql/README.md in the download covers import instructions and the runtime grants the resource needs.

Admin panel

Access is a standard FiveM ACE, digitalden.battlepass.admin. All three frameworks build their admin systems on ACEs, so the only difference is which principal your admins already hold. Add the matching line to server.cfg and restart.

Qbox

Admins are ACE principals of group.admin:

add_ace group.admin digitalden.battlepass.admin allow

QBCore

Permission groups are the qbcore.* principals assigned by /addpermission:

add_ace qbcore.god digitalden.battlepass.admin allow
add_ace qbcore.admin digitalden.battlepass.admin allow

ESX Legacy

Groups from the users table are registered as ACE principals:

add_ace group.admin digitalden.battlepass.admin allow
add_ace group.superadmin digitalden.battlepass.admin allow

One person instead of a group

add_ace identifier.license:0000000000000000000000000000000000000000 digitalden.battlepass.admin allow

The player must already hold the principal you granted it to. Open /battlepass and select Manage pass. The tab is hidden from ordinary players, and every admin request is re-checked on the server, so hiding the tab is not the security boundary.

What the panel controls

  • Season. Title, subtitle, brand, UTC dates, XP per level, online-minute XP, integration limits, pause and resume, and trusted job resources. To start a new season use a new season ID and publish; an ID with saved progress cannot be reused.
  • Rewards. Edit either track, choose any registered inventory item or bank/cash reward, change quantities and metadata, add levels or remove the last one. Select Apply reward to draft, then Publish changes.
  • Challenges. Add, edit or remove daily, weekly and season challenges. Playtime works automatically; job-specific progress needs that job's trusted server integration.
  • Inventory. Search every loaded item and preview its real image, select Use in reward, set an alternate image folder or override one item's image.
  • Players. Load an online player or an offline character identifier and set progress by level or by total XP, the two fields staying in step. Grant or remove premium, or deliver a registered item to an online player.
  • Activity. Recent admin actions and pending reward claims, including older seasons.

Publish changes applies immediately: no Lua editing and no resource restart for season or reward changes. A revision check stops one administrator overwriting another's newer configuration, and every mutation is recorded in digitalden_battlepass_audit.

After first initialization, saved database settings take priority over the defaults in config.server.lua. Framework, inventory override, ACE permission, key mapping, auto-create and starter-seeding stay installation settings and are deliberately outside the remote editor.

Compatibility

FrameworkInventoryAuto detection
Qbox (qbx_core)ox_inventoryYes
QBCore (qb-core)qb-inventoryYes
QBCore (qb-core)ox_inventoryYes
ESX Legacy (es_extended)ox_inventoryYes

A resource counts as present when its public export responds or the resource manager reports it running, so detection survives a hot restart where resource state briefly lags. Detection prefers Qbox, then QBCore, then ESX, and prefers ox_inventory.

Overrides in config.server.lua are qbx, qb, esx for the framework and ox, qb for the inventory. Use them if more than one framework or inventory resource is running. qb-inventory needs a QB-compatible framework, so ESX with qb-inventory is deliberately rejected, and Qbox should use ox_inventory. Restart the resource after changing either.

Bridges use public exports. A renamed or modified framework, or an older inventory with different exports, needs an adjustment in the editable bridge.

Configuration

  • config.lua holds the command, key, brand, tablet prop and animation, and the rarity ladder.
  • config.server.lua holds framework selection, season, rewards, XP, challenges, trusted integrations and the administrator permission.
  • locales/en.lua holds server messages. UI copy is editable in html/index.html and html/app.js; colours, spacing and typography in html/style.css.

The default season has 30 levels at 1,000 XP each. The two tracks are deliberately different: free pays cash, premium pays larger bank deposits with a bigger payout every tenth level, and levels 1 to 3 carry inventory items on both. Players start at level zero and level one unlocks at 1,000 XP. XP stops at the final level. Premium unlocks the second track at already-earned levels without resetting progress.

startsAt and endsAt are UTC Unix timestamps in seconds, and zero removes that boundary. An inactive season can be viewed but cannot award XP or deliver claims. The shipped sample has no expiry, so set the real dates before release. Premium entitlements are per character and per season.

Editing an existing reward changes future payouts while already collected rewards stay claimed. Changing a challenge ID creates new progress entries. Think about existing players before changing XP thresholds or trimming levels mid-season. Season IDs must be unique and at most 64 characters.

Rewards and rarities

Replace an individual reward with an item:

DigitalDEN.Tiers[5].premium = {
    type = 'item', item = 'water', amount = 3,
    metadata = {}, label = 'Water ×3', icon = 'item',
    rarity = 'epic'
}

Use an item name registered in the target inventory. Money rewards support bank and cash, and cash maps to ESX's money account. Amounts must be positive integers. Icons are cash, vault or item. rarity is optional and defaults to common; passes saved before rarities existed still load. Each track has one atomic reward per level, with no multi-item bundles in this version.

The rarity ladder

common · rare · epic · legendary · mythic

The menu colours the whole reward card by rank: tinted frame, colour wash behind the artwork, and a solid rarity bar across the top. Rarity is selectable per reward in the panel, and reward search matches on it, so typing legendary filters the pass to those levels.

The ladder is a single source of truth: the server validates against it, the admin dropdown is built from it, and the menu styles from it. To add or rename a rank, edit the list in config.lua and add a matching .reward.r-<name> rule in html/style.css with its --rarity and --rarity-rgb values. Order matters, lowest to highest.

Progression and challenges

Every complete sampled minute online earns PlaytimeXP, with the first sample establishing the session. There is no AFK detection: these are online-time rewards. Set PlaytimeXP = 0 to disable that XP, and remove the playtime challenges if you want their rewards gone too. Restarting the resource or reconnecting discards partial minutes. The server checks the loaded character, never a client-supplied elapsed time.

Daily challenges reset at 00:00 UTC and weekly ones on Monday at 00:00 UTC. Season challenges use period = 'season'. Completion XP is awarded once per period. The UI refreshes every 30 seconds and offers a manual refresh.

Job-specific challenges

Add the challenge, then call the progress export from that job's trusted server-side handler:

DigitalDEN.TrustedResources['delivery-job'] = true
DigitalDEN.Challenges[#DigitalDEN.Challenges + 1] = {
    id = 'daily_delivery', title = 'On the road',
    description = 'Complete five deliveries.', event = 'delivery',
    target = 5, xp = 500, period = 'daily'
}
exports['dd-battlepass']:DigitalDEN_AddProgress(source, 'delivery', 1)
exports['dd-battlepass']:DigitalDEN_AddXP(source, 100)
local progress = exports['dd-battlepass']:DigitalDEN_GetProgress(source)

All three are server-only and require the calling resource in TrustedResources. Amounts must be integers between 1 and MaxAward. AddXP and AddProgress return a success boolean, and a busy character returns false so callers can retry shortly. GetProgress returns a snapshot, or nil when unavailable. Do not expose these exports through unvalidated network events. Built-in playtime progress cannot be submitted by integrations.

Client export:

exports['dd-battlepass']:DigitalDEN_OpenBattlepass()

Item images

QBCore with qb-inventory uses the registered QBCore.Shared.Items catalogue and each item's image field under qb-inventory/html/images. ox_inventory uses its public Items() exports, the configured inventory:imagepath and client item image definitions, including custom filenames. Legacy nui:// paths are converted to secure https://cfx-nui-... URLs, and a missing image falls back to an icon.

Reload / sync inventory imports the running inventory's current catalogue and image references, including registered addon items. You do not copy the inventory's files into this resource. A new addon item must be installed in the actual inventory first and its definitions reloaded that inventory's way; then sync and pick it in the panel. The battlepass cannot deliver an item the inventory does not know about.

The automatic folder is normally enough. For a custom image resource, enter nui://your-image-resource/images in the Inventory tab, and that resource must already serve those files in its manifest. HTTPS folders work too. Per-item overrides accept a filename relative to that folder or a full HTTPS/NUI URL.

On a fresh installation the first three levels are seeded with real inventory items from a separate pool per track, so no level offers the same thing twice. Each entry tries a list of aliases against the detected inventory, and anything unregistered keeps that level's money reward instead of pointing at an item that does not exist. Seeding happens only when no saved settings exist; after that the editor is the source of truth.

Banking and notifications

Money is always paid through the framework itself, AddMoney on Qbox and QBCore or addAccountMoney on ESX, so bank and cash rewards land correctly with no banking resource installed.

Where one is present, the payout is also written to the bank statement. Set DigitalDEN.Banking in config.server.lua:

ValueBehaviour
autoDetect Renewed-Banking, then qb-banking, otherwise none
renewedRenewed-Banking handleTransaction
qbqb-banking CreateBankStatement
noneFramework only, no statement line

Only bank rewards produce a statement line, not cash. Statement writing is wrapped so a banking resource that errors or is mid-restart can never fail a reward that was already paid. The detected mode is printed at startup.

Notifications

Set DigitalDEN.Notify in config.lua:

ValueBehaviour
customBuilt-in toast, styled to match the menu (default)
oxox_lib notify
qbQBCore:Notify

ox and qb fall back to the built-in toast when that resource is not running, so a misconfiguration never loses the message. Toasts render whether the menu is open or closed and do not capture mouse input.

Premium and Tebex

The free pass always remains available, and monetisation defaults to disabled. Set DigitalDEN.Tebex.Enabled = true in config.server.lua and supply your package ID and HTTPS product URL to show Get premium.

TEBEX-INSTALL.md in the download covers connecting the store, adding the required character purchase-code variable and configuring the automatic delivery and refund commands. The code-copy step happens before checkout; after confirmed payment premium activates automatically, including for offline players.

Admin-panel manual grants work in either mode. Disabling purchases does not remove existing entitlements or block delivery of purchase codes already issued.

Trusted server export, for an existing fulfilment system:

local success = exports['dd-battlepass']:DigitalDEN_SetPremium(characterIdentifier, true)

It applies to the current configured season and controls the manual grant only. A character with a valid purchased entitlement keeps premium when their manual grant is removed, and revocation never removes rewards already delivered.

Console commands

ddbp_premium CHARACTER_IDENTIFIER season-01 on
ddbp_premium CHARACTER_IDENTIFIER season-01 off
ddbp_xp PLAYER_SERVER_ID 1000

Use a QBCore or Qbox citizenid, or the complete ESX character identifier. Not a transient server ID, a guessed license or a Tebex buyer ID. Manual premium can be granted offline, and repeated on commands are idempotent. The explicit season argument stops an old-season command granting the current one.

For purchases use the dedicated ddbp_tebex_grant and ddbp_tebex_revoke commands documented in TEBEX-INSTALL.md.

To let an in-game administrator use /ddbp_xp:

add_ace group.admin digitalden.battlepass.admin allow

Premium and recovery commands stay console-only. The ACE-protected panel exposes equivalent controls to authorised administrators, and no player principals are granted automatically.

Interrupted deliveries

Claims are reserved in SQL before inventory or money delivery and marked claimed afterwards. A unique key and a per-character lock prevent simultaneous duplicate payouts, and an inventory-full failure releases the reservation so the player can retry.

Framework balances and the battlepass database cannot share one transaction, so a crash during delivery leaves a pending record. The resource does not automatically retry an ambiguous payout. Inspect the stored snapshot and your framework and inventory logs first:

SELECT * FROM digitalden_battlepass_claims WHERE status = 'pending';

If the reward was delivered:

ddbp_resolve CHARACTER_IDENTIFIER TIER free delivered

If you verified it was not:

ddbp_resolve CHARACTER_IDENTIFIER TIER premium retry

Recovery commands apply to the current season and to pending records only. retry lets the player claim again rather than delivering immediately. Do not bulk-delete pending claims without checking delivery.

Still stuck?

Open a ticket and bring your server console output and the framework and inventory you are running. Support is 11:00 to 23:00 UK, every day.

Open a ticket