Promo Codes
The promo code system allows administrators to create codes that players can redeem for rewards. Codes can be defined in mod assets (read-only) or created at runtime via admin commands. <span class="since-badge">v2.9.0</span>
Code Types
| Type | Description |
|---|---|
single | One use total on the server (first come, first served) |
personal | One use per player |
multi | Limited total uses (see maxUses) |
unlimited | No usage limits |
Reward Types
| Type | Description | Fields |
|---|---|---|
actionItem | Gives an action item by ID from itemconfig.json | itemId, amount, applyQuality, forceQuality |
item | Gives a vanilla/modded item by asset code | itemCode or itemId, amount |
quest | Starts a quest | questId |
reputation | Adds reputation | reputationId, reputationAmount, reputationType ("npc" or "faction") |
Conditions
Promo codes can have redemption conditions:
| Field | Type | Description |
|---|---|---|
validFrom | string | Code is only valid after this date (UTC ISO format) |
validUntil | string | Code is only valid until this date (UTC ISO format) |
requiredQuests | string[] | Player must have completed these quests |
Security
- Rate limiting: max
maxAttemptsPerMinute(default 5) failed attempts per minute - Lockout: after
lockoutThreshold(default 15) failed attempts, player is locked out forlockoutMinutes(default 10) minutes - Case insensitive: codes are case-insensitive by default
- Security by obscurity: invalid codes return the same error regardless of whether the code exists
Redemption Flow
graph TD
A[Player types /promo] --> B[Enter code dialog]
B --> C{Player locked out?}
C -->|Yes| D[Show lockout timer]
C -->|No| E{Code exists?}
E -->|No| F[Generic error:
invalid or expired]
E -->|Yes| G{Type valid?}
G -->|No| F
G -->|Yes| H{Conditions met?}
H -->|No| I[Condition fail message]
H -->|Yes| J{Uses left?}
J -->|No| K[Already redeemed]
J -->|Yes| L[Grant rewards]
L --> M[Mark used]
M --> N[Show success message]
N --> O[Sync to database]Asset-based Configuration
Defined in mod assets (config/promocodes.json), read-only:
{
"settings": {
"maxAttemptsPerMinute": 5,
"lockoutMinutes": 10,
"lockoutThreshold": 15,
"caseInsensitive": true
},
"codes": [
{
"code": "WELCOME2025",
"type": "personal",
"maxUses": 0,
"enabled": true,
"message": "yourmod:promo-welcome-success",
"rewards": [
{
"type": "actionItem",
"itemId": "starter-sword",
"amount": 1,
"applyQuality": true
}
],
"conditions": {
"validFrom": "2025-01-01T00:00:00Z",
"validUntil": "2025-12-31T23:59:59Z",
"requiredQuests": []
}
}
]
}Runtime Configuration
Stored in ModConfig/alegacyvsquest/promocodes-runtime.json. Created and managed via /avq promo commands.
Commands
Admin Commands (/avq promo)
Require give privilege.
| Command | Arguments | Description |
|---|---|---|
/avq promo create | <code> [type] [maxUses] | Create a new promo code |
/avq promo delete | <code> | Delete a promo code |
/avq promo list | — | List all promo codes |
/avq promo info | <code> | Show info about a promo code |
/avq promo addreward | <code> <rewardType> <itemId> [amount] | Add a reward to an existing code |
/avq promo reload | — | Reload promo code configs |
/avq promo reset | <playerName> <code> | Reset a player's usage of a code |
Player Command
| Command | Privilege | Description |
|---|---|---|
/promo | chat | Opens the promo code redemption dialog |
Database Sync
When a code is redeemed, the data is synced to an external database (if configured):
- Fields:
player_uid,player_name,code,rewards_json - Endpoint:
POST /vsquest/promo-redemptions
Complete Example
Starter pack code (asset-based)
{
"code": "WELCOME2025",
"type": "personal",
"enabled": true,
"message": "yourmod:promo-welcome",
"rewards": [
{
"type": "actionItem",
"itemId": "starter-sword",
"amount": 1,
"applyQuality": true
},
{
"type": "item",
"itemCode": "game:healthpotion",
"amount": 5
}
],
"conditions": {
"validFrom": "2025-01-01T00:00:00Z",
"validUntil": "2025-12-31T23:59:59Z"
}
}Event raffle code (runtime)
/avq promo create RAFFLE50 multi 50
/avq promo addreward RAFFLE50 item game:gear-rusty 1
/avq promo addreward RAFFLE50 actionItem yourmod:firework-launcher 1Reputation reward code
{
"code": "LOYALFAN",
"type": "single",
"enabled": true,
"rewards": [
{
"type": "reputation",
"reputationId": "yourmod:community",
"reputationAmount": 100,
"reputationType": "faction"
}
]
}Quest-start code
{
"code": "SECRETQUEST",
"type": "personal",
"enabled": true,
"rewards": [
{
"type": "quest",
"questId": "yourmod:hidden-quest"
}
],
"conditions": {
"requiredQuests": ["yourmod:main-story-5"]
}
}Examples
Creating a promo code via command
/avq promo create NEWYEAR personal
/avq promo addreward NEWYEAR actionItem firework-launcher 3Limited-use code
/avq promo create RAFFLE50 multi 50
/avq promo addreward RAFFLE50 item game:gear-rusty 1Resetting player usage
/avq promo reset PlayerName WELCOME2025Localization
{
"yourmod:promo-welcome": "Welcome! Here's your starter pack.",
"yourmod:promo-invalid": "Invalid or expired code.",
"yourmod:promo-locked": "Too many attempts. Try again in {0} minutes.",
"yourmod:promo-already": "You already redeemed this code.",
"yourmod:promo-conditions": "You don't meet the requirements for this code."
}