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
Place the dd-battlepass folder in your server resources.
Start oxmysql, your framework and your inventory first.
Add ensure dd-battlepass after those resources in your server configuration.
Grant the admin permission for your framework, covered in Admin panel.
Restart the server, or run refresh followed by ensure dd-battlepass in the console.
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.
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
Framework
Inventory
Auto detection
Qbox (qbx_core)
ox_inventory
Yes
QBCore (qb-core)
qb-inventory
Yes
QBCore (qb-core)
ox_inventory
Yes
ESX Legacy (es_extended)
ox_inventory
Yes
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.
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.
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:
Value
Behaviour
auto
Detect Renewed-Banking, then qb-banking, otherwise none
renewed
Renewed-Banking handleTransaction
qb
qb-banking CreateBankStatement
none
Framework 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:
Value
Behaviour
custom
Built-in toast, styled to match the menu (default)
ox
ox_lib notify
qb
QBCore: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.
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';
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.