#include "../bot_command.h" void bot_command_discipline(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_discipline", sep->arg[0], "discipline")) { return; } if (helper_is_help_or_usage(sep->arg[1])) { std::vector description = { "Tells applicable bots to use the specified disciplines" }; std::vector notes = { }; std::vector example_format = { fmt::format( "{} [aggressive | defensive | spell ID] [actionable, default: spawned]" , sep->arg[0] ) }; std::vector examples_one = { "To tell all bots to use an aggressive discipline:", fmt::format( "{} aggressive spawned", sep->arg[0] ) }; std::vector examples_two = { "To tell Warrior bots to use a defensive discipline:", fmt::format( "{} defensive byclass {}", sep->arg[0], Class::Warrior ) }; std::vector examples_three = { "To tell all bots to use their Fearless discipline:", fmt::format( "{} 4587 spawned", sep->arg[0] ) }; std::vector actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" }; std::vector options = { }; std::vector options_one = { }; std::vector options_two = { }; std::vector options_three = { }; std::string popup_text = c->SendCommandHelpWindow( c, description, notes, example_format, examples_one, examples_two, examples_three, actionables, options, options_one, options_two, options_three ); popup_text = DialogueWindow::Table(popup_text); c->SendPopupToClient(sep->arg[0], popup_text.c_str()); if (RuleB(Bots, SendClassRaceOnHelp)) { c->Message( Chat::Yellow, fmt::format( "Use {} for information about race/class IDs.", Saylink::Silent("^classracelist") ).c_str() ); } return; } std::string arg1 = sep->arg[1]; std::string arg2 = sep->arg[2]; int ab_arg = 2; bool aggressive = false; bool defensive = false; Mob* tar = c->GetTarget(); uint16 spell_id = UINT16_MAX; if (!arg1.compare("aggressive")) { aggressive = true; } else if (!arg1.compare("defensive")) { defensive = true; } else if (sep->IsNumber(1)) { if (!IsValidSpell(atoi(sep->arg[1]))) { c->Message(Chat::Yellow, "You must enter a valid spell ID."); return; } spell_id = atoi(sep->arg[1]); } else { c->Message( Chat::Yellow, fmt::format( "Incorrect argument, use {} for information regarding this command.", Saylink::Silent( fmt::format("{} help", sep->arg[0]) ) ).c_str() ); return; } const int ab_mask = ActionableBots::ABM_Type1; std::string actionableArg = sep->arg[ab_arg]; if (actionableArg.empty()) { actionableArg = "spawned"; } std::string class_race_arg = sep->arg[ab_arg]; bool class_race_check = false; if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) { class_race_check = true; } std::vector sbl; if (ActionableBots::PopulateSBL(c, actionableArg, sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) { return; } sbl.erase(std::remove(sbl.begin(), sbl.end(), nullptr), sbl.end()); bool isSuccess = false; uint16 successCount = 0; Bot* firstFound = nullptr; for (auto bot_iter : sbl) { if (!bot_iter->IsInGroupOrRaid(c)) { continue; } if (bot_iter->GetBotStance() == Stance::Passive || bot_iter->GetHoldFlag() || bot_iter->GetAppearance() == eaDead || bot_iter->IsFeared() || bot_iter->IsSilenced() || bot_iter->IsAmnesiad() || bot_iter->GetHP() < 0) { continue; } if (spell_id == UINT16_MAX) { // Aggressive/Defensive type std::vector botSpellList; if (aggressive) { botSpellList = bot_iter->BotGetSpellsByType(BotSpellTypes::DiscAggressive); } else if (defensive) { botSpellList = bot_iter->BotGetSpellsByType(BotSpellTypes::DiscDefensive); } for (int i = botSpellList.size() - 1; i >= 0; i--) { if (!IsValidSpell(botSpellList[i].spellid)) { continue; } if (!bot_iter->CheckDisciplineReuseTimer(botSpellList[i].spellid)) { uint32 remaining_time = (bot_iter->GetDisciplineReuseRemainingTime(botSpellList[i].spellid) / 1000); bot_iter->OwnerMessage( fmt::format( "I can use this discipline in {}.", Strings::SecondsToTime(remaining_time) ) ); continue; } if (bot_iter->GetEndurance() < spells[botSpellList[i].spellid].endurance_cost) { continue; } if (bot_iter->DivineAura() && !IsCastNotStandingSpell(botSpellList[i].spellid)) { continue; } if (spells[botSpellList[i].spellid].buff_duration_formula != 0 && spells[botSpellList[i].spellid].target_type == ST_Self && bot_iter->HasDiscBuff()) { continue; } if (!tar || (spells[botSpellList[i].spellid].target_type == ST_Self && tar != bot_iter)) { tar = bot_iter; } if (bot_iter->AttemptForcedCastSpell(tar, botSpellList[i].spellid, true)) { if (!firstFound) { firstFound = bot_iter; } isSuccess = true; ++successCount; spell_id = botSpellList[i].spellid; } } } else { // Direct spell ID if (!IsValidSpell(spell_id)) { continue; } SPDat_Spell_Struct spell = spells[spell_id]; if (!bot_iter->CanUseBotSpell(spell_id)) { continue; } if (!bot_iter->CheckDisciplineReuseTimer(spell_id)) { uint32 remaining_time = (bot_iter->GetDisciplineReuseRemainingTime(spell_id) / 1000); bot_iter->OwnerMessage( fmt::format( "I can use this item in {}.", Strings::SecondsToTime(remaining_time) ) ); continue; } if (bot_iter->GetEndurance() < spell.endurance_cost) { continue; } if (bot_iter->DivineAura() && !IsCastNotStandingSpell(spell_id)) { continue; } if (spell.buff_duration_formula != 0 && spell.target_type == ST_Self && bot_iter->HasDiscBuff()) { continue; } if (!tar || (spell.target_type == ST_Self && tar != bot_iter)) { tar = bot_iter; } if (bot_iter->AttemptForcedCastSpell(tar, spell_id, true)) { if (!firstFound) { firstFound = bot_iter; } isSuccess = true; ++successCount; } } continue; } if (!isSuccess) { c->Message(Chat::Yellow, "No bots were selected."); } else { if (aggressive || defensive) { c->Message( Chat::Yellow, fmt::format( "{} {} {} {} discipline.", ((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())), ((successCount == 1 && firstFound) ? "used" : "of your bots used"), (aggressive ? "an" : "a"), (aggressive ? "aggressive" : "defensive") ).c_str() ); } else { c->Message( Chat::Yellow, fmt::format( "{} {} their {} [#{}] discipline.", ((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())), ((successCount == 1 && firstFound) ? "used" : "of your bots used"), spells[spell_id].name, spell_id ).c_str() ); } } }