A dynamic XP redistribution module for AzerothCore (WotLK 3.3.5a) designed for playerbot groups.
When a real player and their bot party members kill creatures together, this module redistributes the accumulated kill XP so that lower-level characters catch up to the highest-level member of the group — keeping everyone on a similar progression track.
- XP Equalization — Collects kill XP from all party members into a shared pool and redistributes it based on each member's progress relative to the master
- Two Distribution Modes:
- Lowest (default) — gives the entire XP pool to the single character furthest behind
- Dynamic — splits the pool proportionally, weighted by how far behind each character is
- Configurable Level Window — only characters within N levels of the master participate (default: 7 levels)
- Real Player Master — the party leader must be a real player; bot-only parties are ignored by default
- Kill XP Only — quest XP, reputation XP, and other sources are left untouched
- Configurable & Debuggable — toggle features and enable debug logging to watch the redistribution in real time
- Party members kill a creature. All XP from that kill is collected into a redistribution pool — no XP is lost, it all flows through the pool.
- The pool accumulates XP from every group member for that victim (tracked by victim GUID).
- When all members have contributed, the pool is redistributed — either all to the lowest-XP member (lowest mode), or split proportionally by XP deficit (dynamic mode).
- Members above the master's level are excluded from receiving redistribution.
Party leader (Audin, level 8): 10,000 / 12,000 XP (83.3% progress — master)
Bot Ally (level 8): 5,000 / 12,000 XP (41.7% progress)
Bot Bob (level 8): 3,000 / 12,000 XP (25.0% progress)
Bot Bard (level 8): 7,000 / 12,000 XP (58.3% progress)
Bot Dave (level 8): 9,000 / 12,000 XP (75.0% progress)
In lowest mode, Bot Bob gets the entire redistributed pool (lowest progress ratio).
In dynamic mode, weights combine level deficit (100% per level) plus XP progress ratio deficit relative to the master. Members above the master's level are excluded:
- Bot Ally (0 levels, ratio deficit 41.7%) → weight 4167 → ~31% of pool
- Bot Bob (0 levels, ratio deficit 58.3%) → weight 5833 → ~44% of pool
- Bot Bard (0 levels, ratio deficit 25.0%) → weight 2500 → ~19% of pool
- Bot Dave (0 levels, ratio deficit 8.3%) → weight 833 → ~6% of pool
If a bot is 2 levels below the master, it gets a 200% base deficit on top of its ratio deficit:
- Bot Newbie (level 6, 30% progress) vs master (83.3%) → weight = 20000 + 5330 = 25330
- AzerothCore Playerbots Branch
- MySQL 8.0+
- Compiler with C++17 support
Navigate to your AzerothCore modules directory:
cd <ACoreDir>/modules
git clone https://github.com/Jellypowered/mod-playerbot-catchup.gitRe-compile AzerothCore:
If using the acore.sh script:
cd <ACoreDir>
./acore.sh compiler buildManually:
cd <ACoreDir>/build
cmake ../ -DCMAKE_INSTALL_PREFIX=/path/to/server
make -j $(nproc)
make installThe module is compiled statically into the modules library and loaded automatically — no separate module loading needed.
Edit <ACoreDir>/env/dist/etc/modules/xpcatchup.conf in your server's config directory:
# XP Catch-Up Module Configuration
# Main toggle - enables or disables the XP catch-up system
XPCatchup.Enable = true
# Level difference window - members more than this far from the master's
# level are excluded from XP redistribution
# Recommended: 7 (matches the effective party XP sharing range in WotLK)
# Higher values allow catch-up for wider level spreads but may include
# members who receive negligible XP from kills.
XPCatchup.LevelWindow = 7
# If the party leader is a bot, skip catch-up entirely
# Set to false to allow catch-up even when the master is a bot
XPCatchup.RequireRealMaster = true
# Distribution algorithm:
# 0 = lowest - gives entire pool to the single lowest-XP member (default)
# 1 = dynamic - splits pool proportionally, weighted by XP deficit
XPCatchup.Distribution = 0
# Chat debug mode - sends what each bot received to party chat after each kill
# Messages appear like: "[XP Catch-Up] received 840 XP (weight 4200; deficit: 42.00%)"
XPCatchup.ChatDebug = false
# Debug logging - enables LOG_INFO messages to console and Server.log
# Requires logger level 4 or 5 in worldserver.conf (e.g. Logger.XPCatchup=4,Console Server)
XPCatchup.Logging = false
If you want console logs for the mods output to monitor what the mod is doing add this line to your worldserver.conf:
Logger.XPCatchup=4,Console Server
Restart your worldserver to load the module:
./worldserver| Option | Type | Default | Description |
|---|---|---|---|
XPCatchup.Enable |
Boolean | true |
Enable or disable the XP catch-up system globally |
XPCatchup.LevelWindow |
Integer | 7 |
Maximum level difference from master for eligible members. Recommended: 7 (matches WotLK party XP sharing range) |
XPCatchup.RequireRealMaster |
Boolean | true |
Party leader must be a real player; bot leaders are ignored |
XPCatchup.Distribution |
Integer | 0 |
0 = lowest, 1 = dynamic weighted distribution |
XPCatchup.ChatDebug |
Boolean | false |
Send redistribution details to party chat after each kill |
XPCatchup.Logging |
Boolean | false |
Enable detailed LOG_INFO output to console and Server.log |
The module hooks into AzerothCore's PlayerScript::OnPlayerGiveXP callback, which fires once per group member after a creature kill. The amount parameter is passed by reference, allowing the module to intercept the XP before it's applied.
- For each player who kills — the core calculates their XP share, then
OnPlayerGiveXPfires. The module intercepts it and adds it to a pending pool (tracked by victim GUID). The player's XP is zeroed at this point. - Pool accumulation — the module waits for every group member to contribute. The pool contains the sum of all players' XP for that specific kill.
- Redistribution — once all members have contributed, the pool is redistributed according to the selected algorithm. No XP is lost; it flows through the pool and out to the recipients.
- In lowest mode, the entire pool goes to the single lowest-XP member. In dynamic mode, it is split proportionally by XP progress ratio deficit weighted by level difference.
- Only
XPSOURCE_KILLXP is intercepted (quest XP, reputation, etc. pass through) - The party leader must be a real player (configurable via
RequireRealMaster) - Members more than
LevelWindowlevels from the master are excluded - Members above the master's level get zero from redistribution
- Dead members are naturally excluded (core doesn't call
OnPlayerGiveXPfor them)
A world script runs every 5 seconds to clean up expired pending XP entries (older than 2 seconds), preventing memory leaks from stale state.
- Bot Party Leaders — If
RequireRealMaster = trueand the party leader is a bot, no redistribution occurs. Set tofalseto allow bot-master parties (uses lowest-XP member as target). - Level 80 Players — Level 80 players receive zero XP from the core. The module sees already-zero XP and has no effect.
- Rest XP — Rest XP bonuses apply to redistributed XP automatically (interception happens before
GiveXP()is called). - Pets — Pet XP (
GivePetXP) is not intercepted; bots control their own pets. - Party Leader Changes — The new leader becomes the master for subsequent kills. No special handling needed.
WARNING: This can be VERY spammy in busy dungeons. Only enable for verification/debugging.
Enable chat debug mode by setting XPCatchup.ChatDebug = true. After each kill, a party chat message appears for each beneficiary bot, showing what they received:
[XP Catch-Up] received 840 XP (weight 4200; deficit: 42.00%)
[XP Catch-Up] received 465 XP (weight 2000; deficit: 20.00%)
[XP Catch-Up] received 93 XP (weight 100; deficit: 1.00%)
These appear in party chat as if the bot sent them. All group members will see each message.
- weight — proportional weight for XP distribution (higher = further behind). Combines level deficit (100% per level) plus XP progress ratio deficit.
- deficit — XP progress ratio deficit relative to the master (percentage), before this kill. A higher percentage means further behind the master's progress.
WARNING: This can be VERY spammy in busy dungeons. Only enable for verification/debugging.
Enable debug logging by setting XPCatchup.Logging = true. This outputs all LOG_INFO messages (first contributions, pool redistribution, target selection, etc.) to both the Server.log file and the console (if the logger level allows).
Note: LOG_INFO messages also require the logger level in worldserver.conf to be set to at least 4 (INFO) or 5 (DEBUG):
Logger.XPCatchup=4,Console Server
Or enable it at runtime:
.server.log XPCatchup 4
Both XPCatchup.Logging and the logger level must be enabled for messages to appear.
This module was tested against the following commit hashes:
AzerothCore Playerbots Branch: 4d380b987
mod-ah-bot-plus:9fbcbe6mod-aoe-loot:2ddf6ffmod-autobalance:73d4ad3mod-dungeon-master:a488836mod-guildfunds:f69bff1mod-individual-progression:fd0673dmod-junk-to-gold:2134690mod-multibot-bridge:fba3d24mod-playerbot-catchup:d356cd4mod-player-bot-level-brackets:b03737fmod-playerbots:1041b0b0mod-quest-loot-party:6f073c1
mod-playerbot-catchup/
├── src/
│ ├── XPCatchup.h # Main class declarations
│ ├── XPCatchup.cpp # Hook implementations
│ └── XPCatchup_loader.cpp # Module entry point
├── conf/
│ └── xpcatchup.conf.dist # Configuration template
└── data/
└── sql/
└── db-world/
└── skeleton_module_acore_string.sql
This module is released under the GNU AGPL v3 License.
Built for AzerothCore Playerbots Branch — open-source WoW 3.3.5a server emulator with playerbots.