Commit Graph
47 Commits
Author SHA1 Message Date
devbox c02c982853 Playerbot: fix core-hooks patch for 12.1 CharacterHandler.cpp layout
The 12.1 update added '#include <algorithm>' and '#include "MapManager.h"'
between ItemUpgradeMgr.h and the LoginQueryHolder class, breaking the
patch hunk. Adjust the LoginQueryHolder-removal hunk context/lines.
2026-08-23 13:27:35 +10:00
devbox 0d590f912a Core: wire OnPlayerTalkToCreature hook in Player::TalkedToCreature
The module's OnTalkToCreature quest-mimic handler was never reachable — the
hook had no call site. 'Use item on NPC' objectives (quest 433, Runes of
Return on Trapped Miners) credit through TalkedToCreature (often via the
NPC's SmartAI), so bots never received the TALKTO objective credit when the
owner used the item. Add the hunk to the ThordekkCore patch.
2026-08-22 22:12:32 +10:00
devbox d89337946e Playerbot: auto-learn riding skill + mount; owner-mount party sync
- Riding (skill 762) granted automatically at modern thresholds (L10
  Journeyman 150, L20 Expert 225, L30 Master 375). One tier-appropriate
  mount spell learned per tier, data-driven from the Mount DB2.
- Runs on bot login, level-up and alt finalize.
- Owner-mount sync: Unit::Mount/Unit::Dismount hooks push
  MountIntent/DismountIntent to owned bots so the party travels together.
- Add Unit.cpp mount/dismount hunks to the core-hooks patch.
2026-08-22 21:58:17 +10:00
devbox 416cd51298 Playerbot: hearthstone party port + priest keeps healing spec at L10
- Hearthstone/return-to-inn sync: module teleports every owned bot to its
  (owner-synced) homebind when the owner spell-ports to their own homebind.
- Leveling spec for Priest now Holy (257) instead of Shadow (258): the L10
  real-spec promotion was forcing Shadow, flipping her role to Dps and
  stopping her healing.
- Add the TeleportTo hearthstone hunk to the core-hooks patch.
2026-08-22 21:18:49 +10:00
devbox dd4efda8d5 Playerbot: single quest-item propagation path + bot spec control
- OnLootUnit's corpse-open quest-item scan double-granted every creature
  quest item (owner opens corpse -> +1, owner takes item -> +1 via
  OnLootItem). Remove the redundant scan; OnLootItem is now the single
  propagation path (covers creature AND GO loot). Fixes double loot.
- BotGear: add specialization control. New GEAR_SPECS_REQ lists the bot's
  specs; GEAR_SET_SPEC switches via Player::ActivateTalentGroup. Addon
  renders a spec button row on the panel; active spec is highlighted.
2026-08-22 20:54:53 +10:00
devbox 7126c19714 Playerbot: never down-level bots below their natural level
The alt/companion finalize paths used 'bot->GetLevel() != targetLevel' and
called GiveLevel(owner level) — a bot that naturally out-leveled the owner
(e.g. hit 10 while owner was 9) got reset back DOWN to the owner's level,
wiping XP and breaking progression, and jumbling the bot's stats (the
recurring 'bots show the player's 1110/1000 stats' bug). Only level UP:
change the guards to '<' so bots are never reset below where they already
are.
2026-08-22 19:35:44 +10:00
devbox 19a88e347b Core-hooks: drop the Loot::AutoStore OnPlayerLootItem hook (fix double loot)
Chests with chestPushLoot auto-store via Loot::AutoStore AND the player also
takes the item via StoreLootItem — both fired the quest-item propagation hook,
double-granting bound quest items (Bundle of Wood). Remove the AutoStore hunk;
the non-gated StoreLootItem hook already covers loot-window takes including
bound items.
2026-08-22 18:31:21 +10:00
devbox 7719255851 Core-hooks: fix StoreLootItem hunk line count (13 -> 15)
The previous edit added two comment lines to the StoreLootItem hook hunk but
the hunk header still said 13 new lines (now 15), so git apply rejected the
patch as corrupt. Correct the count.
2026-08-22 17:43:52 +10:00
devbox 7cd4b9ca59 Core-hooks: fire OnPlayerLootItem for quest-BOUND loot items too
Player::StoreLootItem gated the quest-item propagation hook on 'newitem' —
but quest-BOUND items (Bundle of Wood 13872, ground-pickup quest items)
return nullptr from StoreNewItem (the bound-objective guard), so the hook
never fired and owned bots missed those items. Fire it regardless.
2026-08-22 17:40:32 +10:00
devbox 9702ae65b2 Core-hooks: propagate quest items to bots for GameObject loot (ground-pickup)
OnPlayerLootItem was only wired into Player::StoreLootItem (creature-corpse
loot windows). GameObject loot — ground-pickup quest items like Bundle of
Wood (13872), gathering nodes, chests — routes through Loot::AutoStore and
never fired the hook, so owned bots missed those quest items. Add the
TRINITY_PLAYERBOT_V2 hook in Loot::AutoStore, mirroring the creature path.
2026-08-22 16:53:43 +10:00
devbox 5a2c4b1ed8 Playerbot: skip grouped bots for ALL kill/NPC-click credit (fix double count)
The core's party-share credits every grouped bot for BOTH combat kills AND
NPC-click objectives (Fear No Evil click fires OnKillCredit for each grouped
bot once, guid empty or not). The empty-guid special case pushed to all bots
and double-counted. Simplify: skip grouped bots unconditionally (the core
handles them); only ungrouped owned bots need the module push.
2026-08-21 21:45:04 +10:00
devbox 359c587a41 Playerbot: distinguish combat kills vs NPC-click credit in OnKillCredit
Combat kills carry a creature guid and are ALREADY shared to grouped bots by
the core — pushing again double-counts, so skip grouped bots for those (only
ungrouped bots get the push). NPC-click credits (Fear No Evil etc.) pass guid
EMPTY and are single-caster/not reliably shared, so push to ALL owned bots for
those. Distinguishes on guid.IsEmpty(): combat kill (non-empty) -> skip
grouped; click (empty) -> push all.
2026-08-20 18:37:47 +10:00
devbox b801aae9ab Playerbot: REVERT save-bots-on-logout — it corrupts player data
LogoutBot's LogoutPlayer(true) ran the FULL account-scoped SaveToDB on a
headless bot sharing the owner's account, corrupting player/character data on
logout and server-reset (confirmed: corruption started exactly with this
change; fresh characters then crash the client at world-enter with
CombatLogEntry empty-guid-type). Revert to LogoutPlayer(false) (the safe,
long-standing behaviour).
2026-08-20 18:22:05 +10:00
devbox 342ef94868 Playerbot: push kill/click credit to ALL owned bots (fix missed clicks)
NPC-click objectives (quest 63447 'Fear No Evil') are single-caster spell-script
credits the core does not reliably share to party members — when the owner
rushed the clicks, an out-of-range/sync bot (Lica) missed a click. Pushing
KilledMonsterCredit to every owned in-world bot regardless of group makes it
robust; it is idempotent (core ignores already-complete objectives) and the
per-bot OnKillCredit re-entry is filtered by IsBot(), so no double count.
2026-08-20 18:01:00 +10:00
devbox f0d39d3248 Playerbot: stop double-crediting grouped bots on kill/NPC-click credit
The core's party-shared credit fires OnKillCredit for every grouped bot on the
quest for both combat kills and non-combat NPC-click objectives. The module
only skipped grouped bots IN combat, so non-combat credits (quest 63447 'Fear
No Evil' clicking Injured Stormwind Infantry) were pushed again ->
KilledMonsterCredit -> double count. Skip the push for any grouped bot; only
ungrouped bots need the module's credit.
2026-08-18 18:39:26 +10:00
devbox 0111a2efee Playerbot: honour blacklisted turn-ins when the bot is already at the ender
The wedge-remediation blacklists a turn-in the bot can't path to, and the
picker then skips it — but that also strands a bot that HAS reached the NPC:
it stands next to the quest giver with a complete quest, current_quest_id=0
([picker_none]), and never turns in (so the chain stalls). If the bot is
within ~40y of the resolved ender, the turn-in is trivially reachable — let
the picker select it despite the blacklist.
2026-08-18 18:32:40 +10:00
devbox 5b66a9656f Playerbot: save bots on logout so quests/progress persist
LogoutBot called LogoutPlayer(false), which skips SaveToDB — a quest pushed
and progressed this session was lost on logout unless a 15-min autosave
happened to fire first. Bots then couldn't complete the quest the player
finished, breaking the chain (follow-up quest un-pushable). Use
LogoutPlayer(true), matching the BotSession idle-timeout path.
2026-08-18 14:51:40 +10:00
devbox c9467af711 Playerbot: only assist targets the owner is actually fighting
ResolveOwnerAssistTarget preferred GetSelectedUnit() over the victim, so
merely targeting a neutral/yellow mob made every bot attack it. Now the
victim (real combat target) is preferred, and the selected-unit fallback
only counts when the owner is IN combat and targeting that unit (a cast
in flight) — a selected-but-unattacked mob never pulls the squad.
2026-08-18 11:11:35 +10:00
devbox 9c201a2b98 Playerbot: sell_trash — drop the 4y vendor proximity gate + result log
Bots follow the owner at formation distance (2.5-8y), so when the owner uses
sell-all-junk the bot is usually beyond GetNPCIfCanInteractWith's ~4y range and
sell_trash bailed with InvalidTarget — nothing was ever sold. Bots are
headless, so look the vendor up directly (flag-checked) without the proximity
requirement, and log the sold-item count.
2026-08-17 20:09:59 +10:00
devbox d3fa3e5db8 Playerbot: log the real reason a quest-source item grant is rejected
'bag full' was misleading — with free slots AddItem can still return false
via CanStoreNewItem/StoreNewItem rejection (bound-item guard etc). Include the
CanStoreNewItem result (ir), noSpace, actual free backpack slots, and current
item count in the failure log so the rejection reason is visible.
2026-08-17 19:53:41 +10:00
devbox 9afd9baed9 Playerbot: grant quest-source items so item-started quests push to bots
Item-started quests (e.g. item 1307 'Gold Pickup Schedule' -> quest 123 'The
Collector') require the source item in the bag for CanAddQuest to pass, but
the module only copied quest-OBJECTIVE items — so the push was skipped with
'(CanAddQuest)' and the bots never got the quest.

- GiveQuestItem (loot path): when the owner loots an item whose template
  starts a quest (GetStartQuest()>0), grant one to each bot.
- TryPushQuestToBot (accept path): backstop — grant the quest's SrcItemId
  if the bot lacks it before the CanAddQuest check.
2026-08-17 19:39:04 +10:00
devbox fb4c13c4ef Playerbot: BotGear addon — register the PBC addon-message prefix
The client only fires CHAT_MSG_ADDON events for prefixes registered via
RegisterAddonMessagePrefix. BotGear never registered 'PBC' (PlayerbotControl
does), so the server's GEAR_BAGS_RESP / GEAR_EQUIP_RESP replies were dropped
client-side and the panel stayed blank even though the round-trip reached the
server. Register the prefix on PLAYER_LOGIN.
2026-08-17 19:20:31 +10:00
devbox f9e14ae7bc Playerbot: BotGear addon — self-whisper to the owner (the only working target)
The server's addon OnChat hook only fires inside Player::WhisperAddon, which
requires the whisper target to resolve to a real connected player. The fake
'PBCFLEET' name is dropped before the hook, so BotGear requests never reached
the server. Whisper the OWNER's own name instead (self-whisper) — the exact
path PlayerbotControl uses (it re-points its fleet target at UnitName('player')
on PLAYER_LOGIN). The bot identity rides in the payload.
2026-08-17 19:05:12 +10:00
devbox fed250e96c Playerbot: BotGear uses bot name end-to-end + retry first-open resolution
The client's UnitGUID format is unreliable across builds (the parser kept
extracting the realm/sub field), so the request resolved the wrong player and
no GEAR response was ever returned. The bot's NAME is stable, so:
- Server: GEAR_* handlers resolve fields[0] as a name OR numeric guid-low via
  ResolveGearBot(), and authorize via the resolved bot's guid.
- Addon: ResolveTarget returns UnitName('target'); all requests send the name;
  responses are matched by name; slash handler retries RefreshTarget after
  0.25s so the first open still populates when the unit is transiently
  unavailable right after targeting.
2026-08-17 18:41:58 +10:00
devbox 9fb79b4ea8 Playerbot: BotGear addon — fix target guid extraction
The UnitGUID parser grabbed the realm/sub field (-(%d+)-%x+$) instead of the
low counter, so the request carried the owner's guid (1) and the server
resolved the owner, not the bot — FindConnectedPlayer + IsOwner both failed
and no GEAR response was ever sent. Parse the LAST '-' group as hex (the
character counter), and reset the title hint when no target resolves.
2026-08-17 18:25:19 +10:00
devbox 33cb7143c6 Playerbot: BotGear addon — send via PBCFLEET target, not the bot's name
Whispering the bot's character name routes the server's OnChat hook to the
headless bot's session (pool account), so GEAR responses were never sent to
the owner. Match PlayerbotControl: whisper the magic 'PBCFLEET' target; the
bot guid is carried in the payload and the handlers authorize via Owners().
2026-08-17 18:20:02 +10:00
devbox f630f7fa8d Playerbot: BotGear addon — use a non-zero sequence number
The server rejects any PBC frame with seq == 0 (AddonControl envelope
check), so GEAR_BAGS_REQ/GEAR_EQUIP_REQ were silently dropped and the panel
rendered with no data. Send uses an incrementing seq like PlayerbotControl.
2026-08-17 18:15:35 +10:00
devbox 09d3397238 Playerbot: fix role verb alias + BotGear addon frame build
- BotCommandParser: accept 'role' (addon verb) and 'role_all'/'roleall' as
  aliases for 'setrole'/'setrole_all' so the PlayerbotControl roster role menu
  works (was refused as unknown verb).
- BotGear.lua: create frames/buttons with 'BackdropTemplate' so SetBackdrop
  doesn't throw (retail 11.x+ requirement) — /botgear did nothing because the
  frame build errored out. Also fix the goldText/bagScroll/bagContent locals
  being declared after first use.
2026-08-17 08:04:25 +10:00
devbox 0fdbc36f58 Playerbot: wire AddonControl::OnSessionLogout on owner logout (fixes .so load)
AddonControl.o was never pulled into the worldserver binary: nothing in the
worldserver link referenced its symbols (OnAddonWhisper is only called from the
scripts module, OnSessionLogout was declared but never called), so -rdynamic
could not export OnAddonWhisper and libscripts_commands.so failed to load with
'undefined symbol'. OnPlayerLogout now calls AddonControl::OnSessionLogout for
real players (its documented purpose), anchoring AddonControl.o into the
worldserver link so both symbols are exported.
2026-08-17 07:48:24 +10:00
devbox 9bd1371a04 Playerbot: bot character & inventory controller (gear, bags, destroy, move)
Server (AddonControl.cpp):
- GEAR_BAGS_REQ now returns gold, the four equipped bag containers (entry+size),
  and items from the backpack AND all bags (bagNum 0..4).
- GEAR_EQUIP_ITEM accepts items from any bag slot (not just the backpack).
- New GEAR_DESTROY_ITEM <guid> <bag> <slot> — permanent item destruction.
- New GEAR_MOVE_ITEM <guid> <srcBag> <srcSlot> <dstBag> <dstSlot> — rearrange
  items between bag slots (empty destination only).

Addon (BotGear.lua):
- Full 3D character preview (ModelScene) of the targeted bot, live-updating.
- Renders backpack + real bag containers with gold display.
- Left-click pick up / left-click place to move items between slots.
- Right-click bag item to equip; shift+right-click to destroy; right-click
  equipped item to unequip.
2026-08-16 22:10:56 +10:00
devbox 34edb51e7e Playerbot: abandon the bot's class-equivalent quest when owner abandons
OnAbandonQuest was checking/removing the owner's raw quest_id on the bots, but
bots hold the class/race VARIANT (ResolveBotQuestId, same as OnAcceptQuest). For
variants like 28767 -> 28763 the status check hit NONE and the bot kept the
quest. Resolve the bot's equivalent before taking source items / removing the
active quest, and use the variant's template for timed/PvP cleanup.
2026-08-16 21:44:20 +10:00
devbox a784252a15 Playerbot: grant quest-bound-item objectives correctly (fix wedged quest chains)
QUEST_OBJECTIVE_FLAG_2_QUEST_BOUND_ITEM objectives (e.g. Westfall 'Collecting
Kelp' item 1256) are never stored in inventory — the objective counter is the
source of truth and the core rejects StoreNewItem/AddItem for them. The module
was calling AddItem anyway, which failed as 'inventory full or unplaceable'
despite free bag space, leaving bots unable to complete the quest and
therefore ineligible for the follow-up (112 -> 114).

EnsureBotQuestItems and GiveQuestItem now detect bound objectives and tick the
counter via SetQuestObjectiveData instead of granting a physical item.
2026-08-16 21:21:47 +10:00
devbox 19a3b76fba Playerbot: fix O(n²) formation-slot reassignment in companion tick
The formation slot block sat inside the per-alt loop and re-iterated every
alt of the account for every alt (O(n²)) every 250ms. Move it before the
per-bot loop so it runs once per owner per tick (O(n)).
2026-08-16 18:18:30 +10:00
devbox e26e54fb83 Playerbot: defer quest push for not-in-world bots; tighten follow formation
- OnAcceptQuest parks class-equivalent quests for companions still mid-login
  (connected but not in-world) in g_pending_quests; OnPlayerLogin drains them
  once the bot lands. Freshly-added bots no longer miss the owner's quest.
- Tighten AltFollow to match mod-playerbots (followDistance 1.5y): formation
  slots at 1.5y, slot tolerance 2y, min recall radius 2y (was 4y).
- Default companion formation Spread (ring 2.5y, surrounds leader) instead of
  Line (trailing fan); Spread ring tightened 5y -> 2.5y.
2026-08-16 15:04:29 +10:00
devbox aef4b58c64 Revert "Add auth build support for client 12.1.0 (build 69299)"
This reverts commit 18ffac05d8.
2026-08-15 11:38:45 +10:00
devbox 18ffac05d8 Add auth build support for client 12.1.0 (build 69299)
Keys extracted from Wow - Copy.exe (Win x64). Win A64 and Mac variants
not yet available (no client binaries).
2026-08-15 11:37:28 +10:00
devbox f7e7d201b9 Remove stray add_subdirectory(TestModule) from modules CMakeLists 2026-08-15 10:19:50 +10:00
devbox 6337911bbc Regenerate thordekk core-hooks patch against thordekk/main b8a06fe8ba 2026-08-15 10:07:44 +10:00
devbox 8df7cce6e1 Fix core-hooks patches: correct cs_playerbot_v2.cpp hunk count/hash; LFGHandler hunk matches thordekk/main 2026-08-14 15:21:07 +10:00
devbox 6ae455b869 Define TRINITY_PLAYERBOT_V2 for the scripts command target
cs_playerbot_v2.cpp is compiled into the scripts_commands shared lib,
whose body is gated on #if TRINITY_PLAYERBOT_V2. That macro only ever
reached the module sub-libs linked into worldserver, so the command
script compiled to an empty stub and .playerbot was never registered.
Propagate the define to every SCRIPT_MODULE target when
BUILD_PLAYERBOT_V2 is on so GM commands/live PBC listener register.
2026-08-14 13:01:01 +10:00
devbox 8c236e7119 Register connected altbots missing intents in the follow loop
Connected altbots whose AI was never attached by OnPlayerLogin (stale
core hook or is_bot false at login time) never got has_intents, so the
companion loop skipped them forever. Late-register them idempotently on
the next companion tick so they can follow without a relog.
2026-08-14 11:13:18 +10:00
devbox 521e2a3c8a Add [AltFollow] diagnostics to the companion follow loop
Throttled (5s) log lines give the exact gate when a spawned altbot does
not follow: different_map / no_intents skip, combat skip, and the
formation decision (formed slot_dist vs owner_dist vs rad) that decides
move_to_slot vs follow_intent vs hold-in-place.
2026-08-13 21:53:40 +10:00
devbox 3b459e152d Fix alt-create zombie login (never 'login already in flight' again)
HandleAltCreate submitted the login via SessionMgr().LoginBot immediately
after BotCharacterFactory::Create. SaveToDB is async, so the character
row is not committed yet: BeginLogin's holder loads nothing, the BotSession
never completes and never leaves sessions_ — the bot appears 'stuck in
login' and every later .playerbot login fails with 'login already in
flight'. The .playerbot squad path already avoided this ('Do NOT log a
just-created char in on the same call'); alt create now matches it by
deferring to DrainAltFinalizes, which submits the login on the next world
tick against the committed row + CharacterCache entry.

Also hardened DrainAltFinalizes: an in-flight session older than 25s is a
wedged zombie — reap it (LogoutBot) and resubmit once so a leftover zombie
from a pre-fix build (or any future race) self-heals instead of wedging
that bot forever.
2026-08-12 17:02:21 +10:00
devbox 93f280d257 Seed name pool into the SHARED playerbot schema (fixes generated bot names)
BotNamePool reads {Playerbot.SharedDatabase}.playerbots_names (default
'playerbot'), but migration 0015 created+seeded an unqualified
playerbots_names which the PlayerbotMigrationMgr executes against the
CHARACTERS DB. On a fresh install (or any server where the shared
playerbot schema was not hand-imported) the shared table stays empty,
so every bot name came from the syllable-generator fallback instead of
the curated pool ('Serpil', 'Ghielstan', ...).

0015 now targets playerbot.playerbots_names like migration 0000 does.
Existing installs must backfill once:
  INSERT IGNORE INTO playerbot.playerbots_names (name,gender,race_mask)
  SELECT name,gender,race_mask FROM characters.playerbots_names;
2026-08-12 16:28:15 +10:00
devbox 1be68e5723 Fix pool-account starvation on fresh/renamed characters DBs
Start the next PBV2_NNNN pool index past BOTH the realm-local counter and
any PBV2_* bnet account already present in the shared auth DB, so a fresh
or renamed characters DB no longer restarts numbering at 1 and collides
with the existing fleet (AOR_NAME_ALREADY_EXIST x8 -> pool starvation).
2026-08-12 15:17:05 +10:00
devbox d9a6ff01e0 Sync module with latest upstream changes
- Gate ambient fleet behind PlayerbotsV2.FleetBots (default 0: alt-bot-only
  mode); config plumbed through ConfigReader and documented.
- BotNamePool orphan sweep sources the characters DB name from server
  config (CharacterDatabase connection info) instead of hardcoding
  characters.characters, so renamed characters schemas keep working.
- Shared playerbot bootstrap uses utf8mb4_general_ci (utf8mb4_uca1400_ai_ci
  is MariaDB-only and breaks CREATE DATABASE on MySQL).
2026-08-12 14:40:30 +10:00
devbox f48f626bad PlayerbotV2 module + SQL 2026-08-11 17:02:51 +10:00