From 2e8bf828612b77815e8c23b18fb658c195edcc81 Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Sat, 16 Dec 2023 19:54:23 -0600 Subject: [PATCH] [Bots] Expand ^itemuse options (#3756) Adds additional options to **^itemuse** to narrow down the list of accepting bots. You can now specify by class, casters, hybrids, melee, WIS caster, INT caster or plate/chain/leather/cloth wearing. --- zone/bot_command.cpp | 100 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index cc4e8a03b..00d246d50 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -3906,16 +3906,77 @@ void bot_command_invisibility(Client *c, const Seperator *sep) void bot_command_item_use(Client* c, const Seperator* sep) { if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(Chat::White, "usage: %s ([empty])", sep->arg[0]); + c->Message(Chat::White, "usage: [%s empty] will display only bots that can use the item in an empty slot.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s byclass classID] - Example: [%s byclass 7] will display only bots that match the class that can use the item. Example is a Monk, use [^create help] for a list of class IDs.", sep->arg[0], sep->arg[0]); + c->Message(Chat::White, "usage: [%s casteronly] will display only caster bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s hybridonly] will display only hybrid bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s meleeonly] will display only melee bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s wiscasteronly] will display only Wisdom-based Caster bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s intcasteronly] will display only Intelligence-based Caster bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s plateonly] will display only Plate-wearing bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s chainonly] will display only Chain-wearing bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s leatheronly] will display only Leather-wearing bots that can use the item.", sep->arg[0]); + c->Message(Chat::White, "usage: [%s clothonly] will display only Cloth-wearing bots that can use the item.", sep->arg[0]); return; } bool empty_only = false; + int8 class_mask = 0; + bool caster_only = false; + bool hybrid_only = false; + bool melee_only = false; + bool wis_caster_only = false; + bool int_caster_only = false; + bool plate_only = false; + bool chain_only = false; + bool leather_only = false; + bool cloth_only = false; + std::string arg1 = sep->arg[1]; + std::string arg2 = sep->arg[2]; if (arg1.compare("empty") == 0) { empty_only = true; } - + else if (arg1.compare("byclass") == 0) { + if (Strings::IsNumber(sep->arg[2])) { + class_mask = Strings::ToUnsignedInt(sep->arg[2]); + if (!(class_mask >= WARRIOR && class_mask <= BERSERKER)) { + c->Message(Chat::White, "Invalid class range, you must choose between 1 (Warrior) and 15 (Beastlord)"); + return; + } + } + } + else if (arg1.compare("casteronly") == 0) { + caster_only = true; + } + else if (arg1.compare("hybridonly") == 0) { + hybrid_only = true; + } + else if (arg1.compare("meleeonly") == 0) { + melee_only = true; + } + else if (arg1.compare("wiscasteronly") == 0) { + wis_caster_only = true; + } + else if (arg1.compare("intcasteronly") == 0) { + int_caster_only = true; + } + else if (arg1.compare("plateonly") == 0) { + plate_only = true; + } + else if (arg1.compare("chainonly") == 0) { + chain_only = true; + } + else if (arg1.compare("leatheronly") == 0) { + leather_only = true; + } + else if (arg1.compare("clothonly") == 0) { + cloth_only = true; + } + else if (!arg1.empty()) { + c->Message(Chat::White, "Please choose the correct subtype. For help use %s help.", sep->arg[0]); + return; + } const auto item_instance = c->GetInv().GetItem(EQ::invslot::slotCursor); if (!item_instance) { c->Message(Chat::White, "No item found on cursor!"); @@ -3948,11 +4009,41 @@ void bot_command_item_use(Client* c, const Seperator* sep) std::list sbl; MyBots::PopulateSBL_BySpawnedBots(c, sbl); + if (class_mask) { + ActionableBots::Filter_ByClasses(c, sbl, GetPlayerClassBit(class_mask)); + } + for (const auto& bot_iter : sbl) { if (!bot_iter) { continue; } - + if (caster_only && !IsCasterClass(bot_iter->GetClass())) { + continue; + } + if (hybrid_only && !IsSpellFighterClass(bot_iter->GetClass())) { + continue; + } + if (melee_only && !IsNonSpellFighterClass(bot_iter->GetClass())) { + continue; + } + if (wis_caster_only && !IsWISCasterClass(bot_iter->GetClass())) { + continue; + } + if (int_caster_only && !IsINTCasterClass(bot_iter->GetClass())) { + continue; + } + if (plate_only && !IsPlateClass(bot_iter->GetClass())) { + continue; + } + if (chain_only && !IsChainClass(bot_iter->GetClass())) { + continue; + } + if (leather_only && !IsLeatherClass(bot_iter->GetClass())) { + continue; + } + if (cloth_only && !IsClothClass(bot_iter->GetClass())) { + continue; + } if (((~item_data->Races) & GetPlayerRaceBit(bot_iter->GetRace())) || ((~item_data->Classes) & GetPlayerClassBit(bot_iter->GetClass()))) { continue; } @@ -3997,7 +4088,8 @@ void bot_command_item_use(Client* c, const Seperator* sep) ); bot_iter->DoAnim(29); - } else if (!equipped_item) { + } + else if (!equipped_item) { c->Message( Chat::Say, fmt::format(