The client's IsSellAllJunkEnabled requires PlayerInteractionManager+48 to be
set to Merchant(5). NIOR(Merchant) case 5 queues a UI event that sets this
field, but it does not set it synchronously during packet processing. When
VendorInventory was sent in the same flush as NIOR, MerchantFrame opened
before the event fired, so PIM+48 was not yet 5 and IsSellAllJunkEnabled
returned false.
Fix: On gossip vendor click, send only NIOR(Merchant) and start the
interaction. The client event handler sets PIM+48, opens MerchantFrame,
which then sends CMSG_LIST_INVENTORY to fetch vendor data in a second
round-trip. Also handle direct CMSG_LIST_INVENTORY (non-gossip vendors)
by sending NIOR first if the interaction is not yet started.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Send SMSG_NPC_INTERACTION_OPEN_RESULT with PlayerInteractionType::Merchant
from the gossip handler instead of from SendListInventory. This sets PIM+48
to the value the client expects for IsSellAllJunkEnabled() without causing
an infinite CMSG_LIST_INVENTORY loop (the client's MerchantFrame OnShow
re-requests the item list, which would re-trigger NIOR if placed inside
SendListInventory).
Also closes the gossip dialog before opening the vendor frame, matching
the PetitionVendor pattern.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Adds the source code for the road network navigation system:
- RoadNetworkManager: Loads and manages road graph data per map
- RoadGraphPathfinder: A* pathfinding on the road graph with
spatial index acceleration for nearest-node lookups
- RoadSpatialIndex: Grid-based spatial index for fast node queries
- RoadNetworkTypes: Shared type definitions (nodes, edges, paths)
Companion to 41e62e15a4 which added the road network data files.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
BotActionProcessor::GetBot() used ObjectAccessor::GetPlayer(nullptr, guid)
which compares player->GetMap() == nullptr — always false for bots on BG
maps. This caused 100% action failure rate (39/39 failed). All deferred
actions (orb pickup, flag capture, node interaction) were silently dropped.
Fix: Use ObjectAccessor::FindPlayer(guid) which does a global lookup
without map comparison.
Also adds TrimExcessBotsLocked() to detect and remove excess bots when
teams are overpopulated, called from both PopulateBattlegroundLocked()
and ProcessPendingPopulations().
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Replace TerrainMgr::GetZoneId() calls with direct reads from the
gameobject table's zoneId/areaId columns. This avoids loading 62+ map
terrain trees (with recursive child maps, grid file I/O, and VMap/MMap
load/unload cycles) during startup.
destinationZoneId is unused by any consumer — the travel route planner
already uses exact destinationPosition coordinates for distance-based
routing, which is strictly more precise than zone-level comparison.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements the previously unhandled CMSG_SET_CURRENCY_FLAGS opcode, which
allows players to toggle per-currency display preferences (e.g. "Show on
Backpack"). Wire format decoded from IDA disassembly of WoW 12.x client:
{ uint32 CurrencyID; uint8 Flags; }
Changes:
- Add SetCurrencyFlags ClientPacket class (MiscPackets.h/cpp)
- Add Player::SetCurrencyFlags() with ClientFlags mask validation
- Add WorldSession::HandleSetCurrencyFlags() with DB2 currency validation
- Wire opcode as STATUS_LOGGEDIN, PROCESS_THREADUNSAFE
The flags (CurrencyDbFlags::InBackpack, UnusedInUI) are persisted via the
existing _SaveCurrency() path — no schema changes needed.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
GetZoneIdForPosition() calls sTerrainMgr.GetZoneId() per portal, which
uses weak_ptr caching. During startup no Map objects hold terrain refs,
so each call loads the entire terrain tree from disk (including all child
instance maps) then immediately unloads it. For continent maps with dozens
of children, this repeats hundreds of times causing extreme startup delay.
Hold shared_ptr<TerrainInfo> in a temporary cache during initialization so
each map's terrain is loaded exactly once.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Two critical bugs fixed:
1. BotActionManager::ProcessActions() was never called in production.
The BotActionManagerSubsystem had updateOrder=0 (never updated) and
no Update() method. All deferred actions (INTERACT_OBJECT, ENTER_VEHICLE,
etc.) queued by worker threads accumulated forever without execution.
This broke ToK orb pickup, CTF flag return, node captures, vehicle
boarding, and all other deferred GO interactions added in Phase 1A.
Fix: Added Update() override with updateOrder=250.
2. Dead bots in BGs ran to their corpse instead of resurrecting.
HandleResurrecting with AUTO_RESURRECT passively waited 30s for
IsAlive(), but BG spirit guides require gossip interaction that bots
never perform. After timeout, retry via GHOST_DECIDING could choose
CORPSE_RUN if BG ended during the wait (InBattleground() false).
Fix: Force-resurrect bots in BGs after 30s wave timer instead of
falling through to corpse run retry path.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
- Fix silent orb pickup failure: deferred Use() via BotActionMgr caused bots
to move away before main thread processed the spell cast. Added
m_pendingOrbPickup hold-position state so bots stay at orb for up to 2s
until the main thread processes the deferred GO interaction.
- Fix uneven orb split (1 vs 8+ bots): replaced race-prone m_orbTargeters
map with GUID-based deterministic slot assignment (GUID % ORB_COUNT with
round-robin fallback) for even distribution without shared mutable state.
- Fix missing combat engagement: bots now check for nearby enemies via
coordinator during orb approach movement and initiate Attack().
- Fix claim-aware hasFreeOrb: ExecuteStrategy Priority 2 now skips orbs
with active m_orbClaimedUntil and m_orbSearchFailed cooldowns, so bots
correctly fall through to escort/hunt instead of re-entering PickupOrb.
- Fix carrier waypoint oscillation: replaced forward-only waypoint scan
with center-distance comparison so carriers don't oscillate between
midway waypoint and center.
- Fix missing OnBattlegroundEnd hook: PlayerbotBGScript now detects
STATUS_WAIT_LEAVE transition and calls BGBotManager::OnBattlegroundEnd()
to prevent resource leaks and dangling pointers.
- Fix Map::SendObjectUpdates crash: RemovePlayerBot now clears Account
and Item BaseEntity objects from _updateObjects, not just Player.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Bug 1: BG under-population (7v4) - Skip bots on wrong map in in-transit
counting. Bots that failed teleport sit on their home map but were
counted as "in-transit", making teams appear full prematurely.
Bug 2 (CRITICAL): Spatial cache faction bug - BGSpatialQueryCache used a
single _faction from the first bot for ALL enemy/ally queries. Half the
bots saw their own team as enemies and enemies as allies. Added
callerFaction parameter to all 8 spatial query methods and excludeGuid
to GetNearestEnemy to prevent self-targeting. Updated all 15 call sites
across BGScriptBase, CTFScriptBase, and TempleOfKotmoguScript.
Bug 3: Dual orb pickup race - Two bots at orb location could both call
Use() in the same tick before RefreshOrbState() detected the aura. Added
m_orbClaimedUntil timestamp map with 3-second claim window.
Bug 4: Carrier circling - Fully caused by Bug 2. Carrier's
GetNearestEnemy() returned itself, causing self-attack which disrupted
movement. Resolved by callerFaction + excludeGuid parameters.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
When a human queued for a BG, warm pool bots failed to populate the
queue due to 5 cascading failures:
1. Human player was only registered in _humanPlayers after botsQueued>0,
but warm pool bots are async so botsQueued=0 — human never tracked,
breaking GetQueuedHumanForBG() for all warm pool bots
2. Dead bots from previous sessions silently failed IsBotAvailable()
with no logging — 10/19 warm pool bots rejected
3. IsBotAvailable() had no diagnostic logging for any rejection path
4. QueueStatePoller immediately unregistered after warm pool claimed
success, with no verification that bots actually queued
Fixes:
- Move human registration before bot loop (always register)
- Resurrect dead bots in BotPostLoginConfigurator before BG queue
- Add TC_LOG_DEBUG to every IsBotAvailable rejection path
- Replace immediate unregister with 30s verification re-poll that
re-registers the queue if actual counts are insufficient
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
BotPacketSimulator previously polled every 100ms scanning all 9 speed types
plus teleport/knockback/magnitude flags for every bot. Now BotSession::SendPacket()
intercepts outgoing SMSGs and sets atomic flags via OnPacketSent(), and Update()
processes only the flagged ACKs with O(1) cost when idle.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
- TankSwapCoordinator: Automated tank swap detection with taunt rotation and debuff tracking
- CooldownSyncCoordinator: Raid-wide defensive/offensive CD synchronization with priority queuing
- StructuredCombatLog: Ring-buffer combat event logging with DPS/HPS metrics and encounter tracking
- ReagentManager: Reagent/consumable inventory management with auto-purchase and crafting support
- TransmogManager: Per-bot transmog outfit management with appearance collection and themed outfits
- ArchaeologyManager: Full archaeology profession state machine (survey/triangulate/collect/solve)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Prevents duplicate raid-wide buff casting when multiple bots of the same
class are in a group. Uses claim-based system: bot claims buff responsibility,
others skip. Tracks 7 WoW 12.0 categories (Intellect, Stamina, Versatility,
Attack Power, Physical/Magic damage, Movement Speed).
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Tracks packet counts, bytes sent/received, and filter savings per bot
session. Provides per-opcode breakdown, top-N bots by bandwidth, and
formatted reports. Uses sharded atomic counters for lock-free recording.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Tracks water state (DRY/WADING/SWIMMING/UNDERWATER/SURFACING/DROWNING),
monitors breath timer, and triggers proactive surfacing at 30% breath.
Detects water breathing auras and aquatic form availability for druids.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Enables operators to set verbose log levels (DEBUG/TRACE) for individual
bots without flooding logs from hundreds of other bots. Supports category
filters, timed auto-expiry, and convenience macros (BOT_LOG_DEBUG, etc.).
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Tracks active proc auras and escalates rotation priority when procs are
about to expire unused. Covers all major class procs (Hot Streak, Brain
Freeze, Rime, Art of War, Maelstrom Weapon, etc.) with configurable
urgency thresholds and stack-aware consumption logic.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Bots now auto-respond to warlock summons and meeting stone requests with
human-like delays (1.5-4s randomized). Evaluates combat state, CC, BG/arena,
and group membership before accepting. Tracks summon history and statistics.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements RacialAbilityManager with complete database of racial abilities
for all 25+ playable races including TWW Earthen. Evaluates racials by
priority: CC-break > defensive > offensive (burst-aligned) > resource >
AoE CC. Includes spell availability validation, cooldown tracking, burst
window detection, and CC-state awareness.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Adds a .bot config reload chat command that reloads playerbots.conf,
synchronizes runtime ConfigManager, refreshes BotSpawner config, and
reloads trade configuration. Reports per-subsystem success/failure with
step counts. Also available from server console.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements CombatMetricsTracker providing WoW-style damage/healing meters:
rolling-window DPS/HPS/DTPS, per-spell breakdowns with crit rates and
efficiency, encounter tracking with auto-detect, formatted reports for
chat commands, and session history. Uses fixed-size circular buffer for
zero-allocation combat event recording.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements StringInterningPool with shared_mutex for read-heavy concurrent access,
FNV-1a hashing, transparent heterogeneous lookup via string_view, and per-category
profiling. Pre-interns common class/spec/resource names at startup. Eliminates
duplicate string allocations across all bot instances (~6.4MB savings at 500 bots).
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements ProactiveLoSFixer component that intercepts spell cast
attempts, checks LOS, and repositions the bot to a valid position
before casting. Completes all missing LineOfSightManager method
implementations and upgrades MovementIntegration to use smart
position-finding instead of naive movement toward target.
Key additions:
- ProactiveLoSFixer: pre-cast LOS check with queued cast + reposition
- Healer group LOS maintenance: proactive repositioning to see group
- 30+ missing LineOfSightManager method implementations completed
- LoSUtils::DoLinesIntersect segment intersection implementation
- MovementIntegration::CheckLineOfSight upgraded to use FindBestLoSPosition
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>
Per-bot component that scans EQUIPMENT_SLOT_TRINKET1/TRINKET2 for
items with ITEM_SPELLTRIGGER_ON_USE effects and activates them at
optimal times during combat:
- Offensive trinkets: aligned with burst/opener windows, then on-CD
- Defensive trinkets: reactive when health drops below 35%
- PvP trinkets: reactive CC-break on stun/fear/charm/confuse
- Utility trinkets: used on cooldown for maximum uptime
Features:
- SpellInfo-based effect classification (aura types determine category)
- Equipment change detection via lightweight checksum comparison
- Cooldown tracking via SpellHistory::HasCooldown()
- CastSpellExtraArgs(item) for proper item-sourced spell casting
- 500ms update throttle to minimize per-bot overhead
- Debug summary for diagnostics
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Signed-off-by: luis <[email protected]>