From a3ca438bef24e3fae4089a679b47bcd0880b9f40 Mon Sep 17 00:00:00 2001 From: Lichborne Date: Sat, 30 May 2026 10:03:22 -0400 Subject: [PATCH] Make .playerbots bot commands case-insensitive (#2419) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Pull Request Description \`.playerbots bot add jared\` fails with "Character 'jared' not found" even when \`Jared\` exists, because the lookup is case-sensitive. Same issue hits \`remove\`, \`init=<...>\`, \`refresh\`, \`addaccount\`, and any other subcommand that takes a character name. Fix at the parser layer in \`HandlePlayerbotCommand\`: every subcommand that takes a charname flows through one shared name-lookup step. Normalize the typed name to canonical form (first letter upper, rest lower) at that step so \`jared\`, \`JARED\`, \`JaReD\` all resolve to \`Jared\`. The \`addaccount\` path still tries the raw token as an account name first (account names are case-insensitive on the auth side), then falls back to a normalized character-name lookup. No subcommand's behavior changes — only the name lookup that precedes them. Subcommands with no charname (\`initself\`, \`list\`, \`reload\`, \`tweak\`, \`self\`, \`lookup\`, \`addclass\`) are unaffected. ## Feature Evaluation - Describe the **minimum logic** required to achieve the intended behavior. One \`normalizePlayerName(s)\` call on each comma-separated token before the existing \`GetCharacterGuidByName(s)\` lookup. Uses the helper this module already calls in four other places. - Describe the **processing cost** when this logic executes across many bots. Runs only when a player types a \`.playerbots bot ...\` command, on the typed tokens. Not in any bot-tick or per-bot path. Cost does not scale with bot count. ## How to Test the Changes \`\`\` .playerbots bot add Jared → adds Jared .playerbots bot add jared → adds Jared .playerbots bot add JARED → adds Jared .playerbots bot add JaReD → adds Jared .playerbots bot remove Jared → removes Jared .playerbots bot remove jared → removes Jared .playerbots bot init=auto jared → re-rolls Jared's gear .playerbots bot levelup jared → re-rolls Jared at his current level .playerbots bot refresh jared → refreshes Jared (HP/mana restored) .playerbots bot refresh=raid jared → unbinds Jared from saved raid IDs .playerbots bot add jAred,saLLy,BOB → adds all three .playerbots bot add nonexistent → still reports not found .playerbots bot initself → still works (untouched path) \`\`\` All cases verified in-game. ## Impact Assessment - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - [x] No, not at all - [ ] Minimal impact (**explain below**) - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - [x] No - [ ] Yes (**explain why**) - Does this change add new decision branches or increase maintenance complexity? - [x] No - [ ] Yes (**explain below**) ## AI Assistance Was AI assistance used while working on this change? - [ ] No - [x] Yes (**explain below**) Used Claude to help trace the call graph (confirming which subcommands are affected and which are untouched) and to draft the patch. Reviewed and tested in-game before pushing. ## Final Checklist - [x] Stability is not compromised. - [x] Performance impact is understood, tested, and acceptable. - [x] Added logic complexity is justified and explained. - [x] Any new bot dialogue lines are translated. - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers Diff is small (~25 lines in one file). One minor cosmetic side effect: "Character 'X' not found" errors now echo the normalized form (\`Bogus\` instead of \`bogus\`). --------- Co-authored-by: Lichborne-AC Co-authored-by: Claude Opus 4.7 (1M context) --- src/Bot/PlayerbotMgr.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Bot/PlayerbotMgr.cpp b/src/Bot/PlayerbotMgr.cpp index a6d4a3b79..d38e7720e 100644 --- a/src/Bot/PlayerbotMgr.cpp +++ b/src/Bot/PlayerbotMgr.cpp @@ -22,6 +22,7 @@ #include "GuildMgr.h" #include "ObjectAccessor.h" #include "ObjectGuid.h" +#include "ObjectMgr.h" #include "PlayerbotAIConfig.h" #include "PlayerbotRepository.h" #include "PlayerbotFactory.h" @@ -1240,7 +1241,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg std::vector chars = split(charnameStr, ','); for (std::vector::iterator i = chars.begin(); i != chars.end(); i++) { - std::string const s = *i; + std::string s = *i; if (!strcmp(cmd, "addaccount")) { @@ -1249,7 +1250,13 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!accountId) { // If not found, try to get account ID from character name - ObjectGuid charGuid = sCharacterCache->GetCharacterGuidByName(s); + std::string charName = s; + if (!normalizePlayerName(charName)) + { + messages.push_back("Neither account nor character '" + s + "' found"); + continue; + } + ObjectGuid charGuid = sCharacterCache->GetCharacterGuidByName(charName); if (!charGuid) { messages.push_back("Neither account nor character '" + s + "' found"); @@ -1277,6 +1284,11 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg else { // For regular add command, only add the specific character + if (!normalizePlayerName(s)) + { + messages.push_back("Character '" + *i + "' not found"); + continue; + } ObjectGuid charGuid = sCharacterCache->GetCharacterGuidByName(s); if (!charGuid) {