Bot Rework

This commit is contained in:
nytmyr
2024-04-26 22:38:56 -05:00
parent 77793f364e
commit 6574f780db
94 changed files with 15920 additions and 3952 deletions
+54 -15
View File
@@ -3,22 +3,61 @@
void bot_command_actionable(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_actionable", sep->arg[0], "actionable")) {
c->Message(Chat::White, "note: Lists actionable command arguments and use descriptions");
return;
}
c->Message(Chat::White, "Actionable command arguments:");
c->Message(Chat::White, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument");
c->Message(Chat::White, "byname [name] - selects single bot by name");
c->Message(Chat::White, "ownergroup - selects all bots in the owner's group");
c->Message(Chat::White, "ownerraid - selects all bots in the owner's raid");
c->Message(Chat::White, "targetgroup - selects all bots in target's group");
c->Message(Chat::White, "namesgroup [name] - selects all bots in name's group");
c->Message(Chat::White, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member");
c->Message(Chat::White, "healrotationmembers [name] - selects all member bots of a heal rotation where name is a member");
c->Message(Chat::White, "healrotationtargets [name] - selects all target bots of a heal rotation where name is a member");
c->Message(Chat::White, "byclass - selects all bots of the chosen class");
c->Message(Chat::White, "byrace - selects all bots of the chosen rsce");
c->Message(Chat::White, "spawned - selects all spawned bots");
c->Message(Chat::White, "all - selects all spawned bots .. argument use indicates en masse database updating");
c->Message(Chat::White, "You may only select your bots as actionable");
std::vector<std::string> description =
{
"Lists actionable command arguments and use descriptions."
};
std::vector<std::string> notes =
{
"[target] - uses the command on the target. Some commands will default to target if no actionable is selected.",
"[byname] [name] - selects a bot by name their name.",
"[ownergroup] - selects all bots in the owner's group.",
"[ownerraid] - selects all bots in the owner's raid.",
"[targetgroup] - selects all bots in the target's group.",
"[namesgroup] [name] - selects all bots in [name]'s group.",
"[healrotation] [name] - selects all member and target bots of a heal rotation where [name] is a member.",
"[healrotationmembers] [name] - selects all member bots of a heal rotation where [name] is a member.",
"[healrotationtargets] [name] - selects all target bots of a heal rotation where [name] is a member.",
"[mmr] - selects all bots that are currently at max melee range.",
"[byclass] - selects all bots of the chosen class.",
"[byrace] - selects all bots of the chosen race.",
"[spawned] - selects all spawned bots.",
"[all] - selects all spawned bots.",
"<br>",
"You may only select your bots as actionable"
};
std::vector<std::string> example_format = { };
std::vector<std::string> examples_one = { };
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three = { };
std::vector<std::string> actionables = { };
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
return;
}
+10 -16
View File
@@ -7,32 +7,26 @@ void bot_command_aggressive(Client* c, const Seperator* sep)
helper_command_alias_fail(c, "bot_command_aggressive", sep->arg[0], "aggressive")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(
Chat::White,
"usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))",
sep->arg[0]
);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "note: Orders a bot to use a aggressive discipline");
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string class_race_arg = sep->arg[1];
bool class_race_check = false;
const int ab_mask = ActionableBots::ABM_Type1;
int ab_arg = 1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(
c,
sep->arg[1],
sbl,
ab_mask,
!class_race_check ? sep->arg[2] : nullptr,
class_race_check ? atoi(sep->arg[2]) : 0
) == ActionableBots::ABT_None) {
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
+1 -1
View File
@@ -158,7 +158,7 @@ void bot_command_dye_armor(Client *c, const Seperator *sep)
c->Message(
Chat::White,
fmt::format(
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))",
"Usage: {} [Material Slot] [Red: 0-255] [Green: 0-255] [Blue: 0-255] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))",
sep->arg[0]
).c_str()
);
+1
View File
@@ -11,6 +11,7 @@ void bot_command_apply_poison(Client* c, const Seperator* sep)
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <rogue_bot_target> %s", sep->arg[0]);
c->Message(Chat::White, "note: Applies cursor-held poison to a rogue bot's weapon");
return;
}
+7 -2
View File
@@ -5,14 +5,17 @@ void bot_command_attack(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_attack", sep->arg[0], "attack")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "usage: <enemy_target> %s [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "note: Orders bots to attack a designated target");
return;
}
const int ab_mask = ActionableBots::ABM_Type2;
const int ab_mask = ActionableBots::ABM_Type2;
Mob* target_mob = ActionableTarget::AsSingle_ByAttackable(c);
if (!target_mob) {
c->Message(Chat::White, "You must <target> an enemy to use this command");
@@ -26,11 +29,13 @@ void bot_command_attack(Client *c, const Seperator *sep)
std::string class_race_arg(sep->arg[1]);
bool class_race_check = false;
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
class_race_check = true;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, ab_arg.c_str(), sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
return;
}
+173
View File
@@ -0,0 +1,173 @@
#include "../bot_command.h"
void bot_command_behind_mob(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_behind_mob", sep->arg[0], "behindmob")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots will stay behind the mob during combat."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set Monks to stay behind the mob:",
fmt::format(
"{} 1 byclass 7",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the behind mob status for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} stay behind mobs.'",
my_bot->GetCleanName(),
my_bot->GetBehindMob() ? "will" : "will not"
).c_str()
);
}
else {
my_bot->SetBehindMob(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} stay behind mobs.'",
first_found->GetCleanName(),
first_found->GetBehindMob() ? "will now" : "will no longer"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots {} stay behind mobs.",
success_count,
typeValue ? "will now" : "will no longer"
).c_str()
);
}
}
}
+1
View File
@@ -7,6 +7,7 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep)
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: (<friendly_target>) %s", sep->arg[0]);
c->Message(Chat::White, "note: Orders a bot to attempt an affinity binding", sep->arg[0]);
helper_send_usage_required_bots(c, BCEnum::SpT_BindAffinity);
return;
}
+212 -161
View File
@@ -18,7 +18,7 @@ void bot_command_bot(Client *c, const Seperator *sep)
subcommand_list.push_back("botstance");
subcommand_list.push_back("botstopmeleelevel");
subcommand_list.push_back("botsummon");
subcommand_list.push_back("bottogglearcher");
subcommand_list.push_back("bottoggleranged");
subcommand_list.push_back("bottogglehelm");
subcommand_list.push_back("botupdate");
@@ -33,7 +33,7 @@ void bot_command_camp(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_camp", sep->arg[0], "botcamp"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
@@ -452,8 +452,8 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_follow_distance", sep->arg[0], "botfollowdistance"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [set [1 to %i]] [distance] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0], BOT_FOLLOW_DISTANCE_DEFAULT_MAX);
c->Message(Chat::White, "usage: %s [clear] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_NoFilter;
@@ -464,7 +464,7 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
if (!strcasecmp(sep->arg[1], "set")) {
if (!sep->IsNumber(2)) {
c->Message(Chat::White, "A numeric [distance] is required to use this command");
c->Message(Chat::White, "A numeric [distance] is required to use this command. [1 to %i]", BOT_FOLLOW_DISTANCE_DEFAULT_MAX);
return;
}
@@ -492,22 +492,15 @@ void bot_command_follow_distance(Client *c, const Seperator *sep)
continue;
bot_iter->SetFollowDistance(bfd);
if (ab_type != ActionableBots::ABT_All && !database.botdb.SaveFollowDistance(bot_iter->GetBotID(), bfd)) {
return;
}
++bot_count;
}
if (ab_type == ActionableBots::ABT_All) {
if (!database.botdb.SaveAllFollowDistances(c->CharacterID(), bfd)) {
return;
}
c->Message(Chat::White, "%s all of your bot follow distances", set_flag ? "Set" : "Cleared");
c->Message(Chat::White, "%s all of your bot follow distances to %i", set_flag ? "Set" : "Cleared", bfd);
}
else {
c->Message(Chat::White, "%s %i of your spawned bot follow distances", (set_flag ? "Set" : "Cleared"), bot_count);
c->Message(Chat::White, "%s %i of your spawned bot follow distances to %i", (set_flag ? "Set" : "Cleared"), bot_count, bfd);
}
}
@@ -516,7 +509,7 @@ void bot_command_inspect_message(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_inspect_message", sep->arg[0], "botinspectmessage"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "Notes:");
if (c->ClientVersion() >= EQ::versions::ClientVersion::SoF) {
c->Message(Chat::White, "- Self-inspect and type your bot's inspect message");
@@ -764,75 +757,31 @@ void bot_command_list_bots(Client *c, const Seperator *sep)
}
}
void bot_command_out_of_combat(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_out_of_combat", sep->arg[0], "botoutofcombat"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
std::string arg1 = sep->arg[1];
bool behavior_state = false;
bool toggle_behavior = true;
int ab_arg = 1;
if (!arg1.compare("on")) {
behavior_state = true;
toggle_behavior = false;
ab_arg = 2;
}
else if (!arg1.compare("off")) {
toggle_behavior = false;
ab_arg = 2;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None)
return;
for (auto bot_iter : sbl) {
if (!bot_iter)
continue;
if (toggle_behavior)
bot_iter->SetAltOutOfCombatBehavior(!bot_iter->GetAltOutOfCombatBehavior());
else
bot_iter->SetAltOutOfCombatBehavior(behavior_state);
helper_bot_out_of_combat(c, bot_iter);
}
}
void bot_command_report(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_report", sep->arg[0], "botreport"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_NoFilter;
const int ab_mask = ActionableBots::ABM_Type1;
std::string ab_type_arg = sep->arg[1];
if (ab_type_arg.empty()) {
auto t = c->GetTarget();
if (t && t->IsClient()) {
if (t->CastToClient() == c) {
ab_type_arg = "ownergroup";
} else {
ab_type_arg = "targetgroup";
}
} else {
ab_type_arg = "spawned";
}
std::string arg1 = sep->arg[1];
int ab_arg = 1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, ab_type_arg, sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None)
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
for (auto bot_iter : sbl) {
if (!bot_iter)
@@ -1062,65 +1011,74 @@ void bot_command_spawn(Client *c, const Seperator *sep)
void bot_command_stance(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_stance", sep->arg[0], "botstance"))
if (helper_command_alias_fail(c, "bot_command_stance", sep->arg[0], "botstance")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [current | value: 1-9] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [current | value: 1-9] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(
Chat::White,
fmt::format(
"Value: {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({}), {} ({})",
"Value: {} ({}), {} ({}), {} ({})",
Stance::Passive,
Stance::GetName(Stance::Passive),
Stance::Balanced,
Stance::GetName(Stance::Balanced),
Stance::Efficient,
Stance::GetName(Stance::Efficient),
Stance::Reactive,
Stance::GetName(Stance::Reactive),
Stance::Aggressive,
Stance::GetName(Stance::Aggressive),
Stance::Assist,
Stance::GetName(Stance::Assist),
Stance::Burn,
Stance::GetName(Stance::Burn),
Stance::Efficient2,
Stance::GetName(Stance::Efficient2),
Stance::AEBurn,
Stance::GetName(Stance::AEBurn)
Stance::GetName(Stance::Aggressive)
).c_str()
);
return;
}
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
bool current_flag = false;
uint8 bst = Stance::Unknown;
const int ab_mask = ActionableBots::ABM_Type1;
if (!strcasecmp(sep->arg[1], "current"))
current_flag = true;
else if (sep->IsNumber(1)) {
bst = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[1]));
if (!Stance::IsValid(bst)) {
bst = Stance::Unknown;
std::string arg1 = sep->arg[1];
int ab_arg = 1;
bool current_check = false;
uint32 value = 0;
if (sep->IsNumber(1)) {
++ab_arg;
value = atoi(sep->arg[1]);
if (value < 0 || value > 300) {
c->Message(Chat::White, "You must enter a value within the range of 0 - 300.");
return;
}
}
if (!current_flag && bst == Stance::Unknown) {
c->Message(Chat::White, "A [current] argument or valid numeric [value] is required to use this command");
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
else {
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
return;
}
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None)
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
if (!current_check && (value == Stance::Unknown || (value != Stance::Passive && value != Stance::Balanced && value != Stance::Aggressive))) {
c->Message(Chat::White, "A [current] argument or valid numeric [value] is required to use this command");
return;
}
for (auto bot_iter : sbl) {
if (!bot_iter)
continue;
if (!current_flag) {
bot_iter->SetBotStance(bst);
if (!current_check) {
bot_iter->SetBotStance(value);
bot_iter->Save();
}
@@ -1135,50 +1093,138 @@ void bot_command_stance(Client *c, const Seperator *sep)
}
}
void bot_command_stop_melee_level(Client *c, const Seperator *sep)
void bot_command_stop_melee_level(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_stop_melee_level", sep->arg[0], "botstopmeleelevel"))
if (helper_command_alias_fail(c, "bot_command_stop_melee_level", sep->arg[0], "botstopmeleelevel")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <target_bot> %s [current | reset | sync | value: 0-255]", sep->arg[0]);
c->Message(Chat::White, "usage: %s [current | reset | sync | value: 0-255] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "note: Only caster or hybrid class bots may be modified");
c->Message(Chat::White, "note: Use [reset] to set stop melee level to server rule");
c->Message(Chat::White, "note: Use [sync] to set stop melee level to current bot level");
return;
}
auto my_bot = ActionableBots::AsTarget_ByBot(c);
if (!my_bot) {
c->Message(Chat::White, "You must <target> a bot that you own to use this command");
return;
}
if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) {
c->Message(Chat::White, "You must <target> a caster or hybrid class bot to use this command");
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
int ab_arg = 1;
uint8 sml = RuleI(Bots, CasterStopMeleeLevel);
bool sync_sml = false;
bool reset_sml = false;
bool current_check = false;
if (sep->IsNumber(1)) {
ab_arg = 2;
sml = Strings::ToInt(sep->arg[1]);
if (sml <= 0 || sml > 255) {
c->Message(Chat::White, "You must provide a value between 0-255.");
return;
}
}
else if (!strcasecmp(sep->arg[1], "sync")) {
sml = my_bot->GetLevel();
ab_arg = 2;
sync_sml = true;
}
else if (!strcasecmp(sep->arg[1], "current")) {
c->Message(Chat::White, "My current melee stop level is %u", my_bot->GetStopMeleeLevel());
else if (!arg1.compare("current")) {
ab_arg = 2;
current_check = true;
}
else if (!strcasecmp(sep->arg[1], "reset")) {
ab_arg = 2;
reset_sml = true;
}
else {
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
return;
}
else if (strcasecmp(sep->arg[1], "reset")) {
c->Message(Chat::White, "A [current] or [reset] argument, or numeric [value] is required to use this command");
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
// [reset] falls through with initialization value
my_bot->SetStopMeleeLevel(sml);
database.botdb.SaveStopMeleeLevel(my_bot->GetBotID(), sml);
sbl.remove(nullptr);
c->Message(Chat::White, "Successfully set stop melee level for %s to %u", my_bot->GetCleanName(), sml);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!IsCasterClass(my_bot->GetClass()) && !IsHybridClass(my_bot->GetClass())) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'This command only works on caster or hybrid classes.'",
my_bot->GetCleanName()
).c_str()
);
continue;
}
if (!first_found) {
first_found = my_bot;
}
if (sync_sml) {
sml = my_bot->GetLevel();
}
if (reset_sml) {
sml = my_bot->GetDefaultBotBaseSetting(BotBaseSettings::StopMeleeLevel);
}
if (current_check) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'My current stop melee level is {}.'",
my_bot->GetCleanName(),
my_bot->GetStopMeleeLevel()
).c_str()
);
continue;
}
else {
my_bot->SetStopMeleeLevel(sml);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'My stop melee level was {} to {}.'",
first_found->GetCleanName(),
reset_sml ? "reset" : "set",
sml
).c_str()
);
}
else {
c->Message(
Chat::White,
fmt::format(
"{} of your bots {} their stop melee{}'", // level to {}.
success_count,
reset_sml ? "reset" : "set",
fmt::format("{}", reset_sml ? "." : fmt::format(" level to {}.", sml).c_str()).c_str(),
sml
).c_str()
);
}
}
}
void bot_command_summon(Client *c, const Seperator *sep)
@@ -1188,19 +1234,24 @@ void bot_command_summon(Client *c, const Seperator *sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string class_race_arg = sep->arg[1];
std::string arg1 = sep->arg[1];
int ab_arg = 1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
@@ -1245,34 +1296,44 @@ void bot_command_summon(Client *c, const Seperator *sep)
}
}
void bot_command_toggle_archer(Client *c, const Seperator *sep)
void bot_command_toggle_ranged(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_toggle_archer", sep->arg[0], "bottogglearcher")) {
if (helper_command_alias_fail(c, "bot_command_toggle_ranged", sep->arg[0], "bottoggleranged")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "note: Toggles a ranged bot between melee and ranged weapon use");
return;
}
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
bool archer_state = false;
bool toggle_archer = true;
bool ranged_state = false;
bool toggle_ranged = true;
int ab_arg = 1;
if (!arg1.compare("on")) {
archer_state = true;
toggle_archer = false;
ab_arg = 2;
ranged_state = true;
toggle_ranged = false;
++ab_arg;
}
else if (!arg1.compare("off")) {
toggle_archer = false;
ab_arg = 2;
toggle_ranged = false;
++ab_arg;
}
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) {
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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;
}
@@ -1281,17 +1342,18 @@ void bot_command_toggle_archer(Client *c, const Seperator *sep)
continue;
}
if (toggle_archer) {
bot_iter->SetBotArcherySetting(!bot_iter->IsBotArcher(), true);
if (bot_iter->GetBotRangedValue() < RuleI(Combat, MinRangedAttackDist)) {
c->Message(Chat::Yellow, "%s does not have proper weapons or ammo to be at range.", bot_iter->GetCleanName());
continue;
}
if (toggle_ranged) {
bot_iter->SetBotRangedSetting(!bot_iter->IsBotRanged());
}
else {
bot_iter->SetBotArcherySetting(archer_state, true);
}
bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher());
if (bot_iter->GetClass() == Class::Ranger && bot_iter->GetLevel() >= 61) {
bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher());
bot_iter->SetBotRangedSetting(ranged_state);
}
bot_iter->ChangeBotRangedWeapons(bot_iter->IsBotRanged());
}
}
@@ -1300,7 +1362,7 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_toggle_helm", sep->arg[0], "bottogglehelm"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_NoFilter;
@@ -1313,11 +1375,11 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
if (!arg1.compare("on")) {
helm_state = true;
toggle_helm = false;
ab_arg = 2;
++ab_arg;
}
else if (!arg1.compare("off")) {
toggle_helm = false;
ab_arg = 2;
++ab_arg;
}
std::list<Bot*> sbl;
@@ -1336,9 +1398,6 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
bot_iter->SetShowHelm(helm_state);
if (ab_type != ActionableBots::ABT_All) {
if (!database.botdb.SaveHelmAppearance(bot_iter->GetBotID(), bot_iter->GetShowHelm())) {
return;
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
SpawnAppearance_Struct* saptr = (SpawnAppearance_Struct*)outapp->pBuffer;
@@ -1355,13 +1414,6 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep)
}
if (ab_type == ActionableBots::ABT_All) {
if (toggle_helm) {
database.botdb.ToggleAllHelmAppearances(c->CharacterID());
}
else {
database.botdb.SaveAllHelmAppearances(c->CharacterID(), helm_state);
}
c->Message(Chat::White, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared"));
}
else {
@@ -1439,7 +1491,6 @@ void bot_command_update(Client *c, const Seperator *sep)
if (!bot_iter || bot_iter->IsEngaged() || bot_iter->GetLevel() == c->GetLevel())
continue;
bot_iter->SetPetChooser(false);
bot_iter->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
bot_iter->SendAppearancePacket(AppearanceType::WhoLevel, bot_iter->GetLevel(), true, true);
++bot_count;
+43
View File
@@ -0,0 +1,43 @@
#include "../bot_command.h"
void bot_command_bot_settings(Client* c, const Seperator* sep)
{
std::list<const char*> subcommand_list;
subcommand_list.push_back("behindmob");
subcommand_list.push_back("casterrange");
subcommand_list.push_back("copysettings");
subcommand_list.push_back("defaultsettings");
subcommand_list.push_back("enforcespelllist");
subcommand_list.push_back("follow");
subcommand_list.push_back("followdistance");
subcommand_list.push_back("illusionblock");
subcommand_list.push_back("maxmeleerange");
subcommand_list.push_back("owneroption");
subcommand_list.push_back("petsettype");
subcommand_list.push_back("sithppercent");
subcommand_list.push_back("sitincombat");
subcommand_list.push_back("sitmanapercent");
subcommand_list.push_back("sithppercent");
subcommand_list.push_back("spellaggrocheck");
subcommand_list.push_back("spelldelays");
subcommand_list.push_back("spellengagedpriority");
subcommand_list.push_back("spellholds");
subcommand_list.push_back("spellidlepriority");
subcommand_list.push_back("spellmaxhppct");
subcommand_list.push_back("spellmaxmanapct");
subcommand_list.push_back("spellmaxthresholds");
subcommand_list.push_back("spellminhppct");
subcommand_list.push_back("spellminmanapct");
subcommand_list.push_back("spellminthresholds");
subcommand_list.push_back("spellpursuepriority");
subcommand_list.push_back("spelltargetcount");
subcommand_list.push_back("spelllist");
subcommand_list.push_back("stance");
subcommand_list.push_back("togglehelm");
subcommand_list.push_back("bottoggleranged");
if (helper_command_alias_fail(c, "bot_command_bot_settings", sep->arg[0], "botsettings"))
return;
helper_send_available_subcommands(c, "botsettings", subcommand_list);
}
+301
View File
@@ -0,0 +1,301 @@
#include "../bot_command.h"
void bot_command_cast(Client* c, const Seperator* sep)
{
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Commands bots to force cast a specific spell type, ignoring all settings (holds, delays, thresholds, etc)"
};
std::vector<std::string> notes =
{
"- This will interrupt any spell currently being cast by bots told to use the command.",
"- Bots will still check to see if they have the spell in their spell list, whether the target is immune, spell is allowed and all other sanity checks for spells"
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To tell everyone to Nuke the target:",
fmt::format(
"{} {} spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} {} spawned",
sep->arg[0],
BotSpellTypes::Nuke
)
};
std::vector<std::string> examples_two =
{
"To tell all Enchanters to slow the target:",
fmt::format(
"{} {} byclass {}",
sep->arg[0],
Class::Enchanter,
c->GetSpellTypeShortNameByID(BotSpellTypes::Slow)
),
fmt::format(
"{} {} byclass {}",
sep->arg[0],
Class::Enchanter,
BotSpellTypes::Slow
)
};
std::vector<std::string> examples_three =
{
"To tell Clrbot to resurrect the targeted corpse:",
fmt::format(
"{} {} byname Clrbot",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Resurrect)
),
fmt::format(
"{} {} byname Clrbot",
sep->arg[0],
BotSpellTypes::Resurrect
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 2;
uint16 spellType = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (
spellType == BotSpellTypes::PetBuffs ||
spellType == BotSpellTypes::PetCompleteHeals ||
spellType == BotSpellTypes::PetFastHeals ||
spellType == BotSpellTypes::PetHoTHeals ||
spellType == BotSpellTypes::PetRegularHeals ||
spellType == BotSpellTypes::PetVeryFastHeals
) {
c->Message(Chat::Yellow, "Pet type heals and buffs are not supported, use the regular spell type.");
return;
}
Mob* tar = c->GetTarget();
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme
if (spellType != BotSpellTypes::Escape && spellType != BotSpellTypes::Pet) {
if (!tar) {
c->Message(Chat::Yellow, "You need a target for that.");
return;
}
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType) && !c->IsAttackAllowed(tar)) {
c->Message(Chat::Yellow, "You cannot attack [%s].", tar->GetCleanName());
return;
}
if (BOT_SPELL_TYPES_BENEFICIAL(spellType)) {
if (!tar->IsOfClientBot() && !(tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsOfClientBot())) {
c->Message(Chat::Yellow, "[%s] is an invalid target.", tar->GetCleanName());
return;
}
}
}
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (tar ? tar->GetCleanName() : "NOBODY")); //deleteme
switch (spellType) {
case BotSpellTypes::Stun:
case BotSpellTypes::AEStun:
if (tar->GetSpecialAbility(SpecialAbility::StunImmunity)) {
c->Message(Chat::Yellow, "[%s] is immune to stuns.", tar->GetCleanName());
return;
}
break;
case BotSpellTypes::Resurrect:
if (!tar->IsCorpse() || !tar->CastToCorpse()->IsPlayerCorpse()) {
c->Message(Chat::Yellow, "[%s] is an invalid target. I can only resurrect player corpses.", tar->GetCleanName());
return;
}
break;
default:
break;
}
const int ab_mask = ActionableBots::ABM_Type1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
BotSpell botSpell;
botSpell.SpellId = 0;
botSpell.SpellIndex = 0;
botSpell.ManaCost = 0;
bool isSuccess = false;
uint16 successCount = 0;
Bot* firstFound = nullptr;
for (auto bot_iter : sbl) {
if (!bot_iter->IsInGroupOrRaid()) {
continue;
}
/*
TODO bot rewrite -
FIX: Snares, Group Cures, OOC Song, Precombat, HateRedux, Fear/AE Fear
ICB (SK) casting hate on friendly but not hostile?
NEED TO CHECK: precombat, AE Dispel, AE Lifetap
DO I NEED A PBAE CHECK???
*/
if (bot_iter->GetHoldFlag() || bot_iter->GetAppearance() == eaDead || bot_iter->IsFeared() || bot_iter->IsStunned() || bot_iter->IsMezzed() || bot_iter->DivineAura() || bot_iter->GetHP() < 0) {
continue;
}
Mob* newTar = tar;
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
if (!SpellTypeRequiresTarget(spellType, bot_iter->GetClass())) {
newTar = bot_iter;
}
if (!newTar) {
continue;
}
if (BOT_SPELL_TYPES_DETRIMENTAL(spellType, bot_iter->GetClass()) && !bot_iter->IsAttackAllowed(newTar)) {
bot_iter->BotGroupSay(
bot_iter,
fmt::format(
"I cannot attack [{}].",
newTar->GetCleanName()
).c_str()
);
continue;
}
LogTestDebug("{}: Attempting {} on {}", __LINE__, c->GetSpellTypeNameByID(spellType), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme
bot_iter->SetCommandedSpell(true);
if (bot_iter->AICastSpell(newTar, 100, spellType)) {
if (!firstFound) {
firstFound = bot_iter;
}
isSuccess = true;
++successCount;
}
bot_iter->SetCommandedSpell(false);
continue;
}
if (!isSuccess) {
c->Message(
Chat::Yellow,
fmt::format(
"No bots are capable of casting [{}] on {}.",
c->GetSpellTypeNameByID(spellType),
tar ? tar->GetCleanName() : "your target"
).c_str()
);
}
else {
c->Message( Chat::Yellow,
fmt::format(
"{} {} [{}]{}",
((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())),
((successCount == 1 && firstFound) ? "casted" : "of your bots casted"),
c->GetSpellTypeNameByID(spellType),
tar ? (fmt::format(" on {}.", tar->GetCleanName()).c_str()) : "."
).c_str()
);
}
}
+4 -5
View File
@@ -7,7 +7,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [current | value: 0 - 300] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [current | value: 0 - 300] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "note: Can only be used for Casters or Hybrids.");
c->Message(Chat::White, "note: Use [current] to check the current setting.");
c->Message(Chat::White, "note: Set the value to the minimum distance you want your bot to try to remain from its target.");
@@ -15,6 +15,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
c->Message(Chat::White, "note: This is set to (90) units by default.");
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
@@ -23,7 +24,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
uint32 crange = 0;
if (sep->IsNumber(1)) {
ab_arg = 2;
++ab_arg;
crange = atoi(sep->arg[1]);
if (crange < 0 || crange > 300) {
c->Message(Chat::White, "You must enter a value within the range of 0 - 300.");
@@ -31,7 +32,7 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
}
}
else if (!arg1.compare("current")) {
ab_arg = 2;
++ab_arg;
current_check = true;
}
else {
@@ -78,8 +79,6 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
else {
my_bot->SetBotCasterRange(crange);
++success_count;
database.botdb.SaveBotCasterRange(my_bot->GetBotID(), crange);
}
}
if (!current_check) {
+113
View File
@@ -0,0 +1,113 @@
#include "../bot_command.h"
void bot_command_class_race_list(Client* c, const Seperator* sep)
{
const std::string class_substrs[17] = {
"",
"WAR", "CLR", "PAL", "RNG",
"SHD", "DRU", "MNK", "BRD",
"ROG", "SHM", "NEC", "WIZ",
"MAG", "ENC", "BST", "BER"
};
const std::string race_substrs[17] = {
"",
"HUM", "BAR", "ERU", "ELF",
"HIE", "DEF", "HEF", "DWF",
"TRL", "OGR", "HFL", "GNM",
"IKS", "VAH", "FRG", "DRK"
};
const uint16 race_values[17] = {
Race::Doug,
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf,
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf,
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome,
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin
};
std::string window_text;
std::string message_separator;
int object_count = 0;
const int object_max = 4;
window_text.append(
fmt::format(
"<c \"#EDDA74\">Classes{}<c \"#357EC7\">",
DialogueWindow::Break()
)
);
window_text.append(
fmt::format(
"<c \"#D4A017\">--------------------------------------------------------------------<c \"#357EC7\">",
DialogueWindow::Break()
)
);
window_text.append(DialogueWindow::Break());
message_separator = " ";
object_count = 0;
for (int i = 0; i <= 15; ++i) {
window_text.append(message_separator);
if (object_count >= object_max) {
window_text.append(DialogueWindow::Break());
object_count = 0;
}
window_text.append(
fmt::format("{} ({})",
class_substrs[i + 1],
(i + 1)
)
);
++object_count;
message_separator = ", ";
}
window_text.append(DialogueWindow::Break(2));
window_text.append(
fmt::format(
"<c \"#EDDA74\">Races{}<c \"#357EC7\">",
DialogueWindow::Break()
)
);
window_text.append(
fmt::format(
"<c \"#D4A017\">--------------------------------------------------------------------<c \"#357EC7\">",
DialogueWindow::Break()
)
);
window_text.append(DialogueWindow::Break());
message_separator = " ";
object_count = 0;
for (int i = 0; i <= 15; ++i) {
window_text.append(message_separator);
if (object_count >= object_max) {
window_text.append(DialogueWindow::Break());
object_count = 0;
}
window_text.append(
fmt::format("{} ({})",
race_substrs[i + 1],
race_values[i + 1]
)
);
++object_count;
message_separator = ", ";
}
c->SendPopupToClient("Bot Creation Options", window_text.c_str());
return;
}
+2 -2
View File
@@ -8,7 +8,7 @@ void bot_command_click_item(Client* c, const Seperator* sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <slot id> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s <slot id> ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "This will cause the selected bots to click the item in the given slot ID.");
c->Message(Chat::White, "Use ^invlist to see their items along with slot IDs.");
return;
@@ -25,7 +25,7 @@ void bot_command_click_item(Client* c, const Seperator* sep)
uint32 slot_id = 0;
if (sep->IsNumber(1)) {
ab_arg = 2;
++ab_arg;
slot_id = atoi(sep->arg[1]);
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
c->Message(Chat::Yellow, "You must specify a valid inventory slot from 0 to 22. Use %s help for more information", sep->arg[0]);
+366
View File
@@ -0,0 +1,366 @@
#include "../bot_command.h"
void bot_command_copy_settings(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_copy_settings", sep->arg[0], "copysettings")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Copies settings from one bot to another bot"
};
std::vector<std::string> notes =
{
"- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [from] [to] [option]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To copy all settings from BotA to BotB:",
fmt::format(
"{} BotA BotB all",
sep->arg[0]
)
};
std::vector<std::string> examples_two =
{
"To copy only Nuke spelltypesettings from BotA to BotB:",
fmt::format(
"{} BotA BotB spelltypesettings {}",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} BotA BotB spelltypesettings {}",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
};
std::vector<std::string> examples_three = { };
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid",
"targetgroup, namesgroup, healrotationtargets",
"mmr, byclass, byrace, spawned"
};
std::vector<std::string> options =
{
"all, misc, spellsettings, spelltypesettings",
"holds, delays, minthresholds, maxthresholds",
"minmanapct, maxmanapct, minhppct, maxhppct",
"idlepriority, engagedpriority, pursuepriority",
"aggrochecks, targetcounts"
};
std::vector<std::string> options_one =
{
"[spellsettings] will copy ^spellsettings options",
"[spelltypesettings] copies all spell type settings",
"[all] copies all settings"
};
std::vector<std::string> options_two =
{
"[misc] copies all miscellaneous options such as:",
"- ^showhelm, ^followd, ^stopmeleelevel",
"- ^enforcespellsettings, ^bottoggleranged, ^petsettype",
"- ^behindmob, ^casterrange, ^illusionblock",
"- ^sitincombat, ^sithppercent and ^sitmanapercent",
};
std::vector<std::string> options_three =
{
"The remaining options copy that specific type"
};
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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 2;
bool validOption = false;
uint16 spellType = UINT16_MAX;
std::vector<std::string> options =
{
"all",
"misc"
"spellsettings",
"spelltypesettings",
"holds",
"delays",
"minthresholds",
"maxthresholds",
"aggrochecks",
"minmanapct",
"maxmanapct",
"minhppct",
"maxhppct",
"idlepriority",
"engagedpriority",
"pursuepriority",
"targetcounts"
};
for (int i = 0; i < options.size(); i++) {
if (sep->arg[3] == options[i]) {
if (options[i] != "all" && options[i] != "misc" && options[i] != "spellsettings") {
if (sep->IsNumber(4) || c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX) {
if (sep->IsNumber(4)) {
spellType = atoi(sep->arg[4]);
}
if (c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(sep->arg[4]);
}
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
}
else if (
(options[i] == "all" || options[i] == "misc" || options[i] == "spellsettings") &&
((sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[4]) != UINT16_MAX))
) {
break;
}
validOption = true;
break;
}
}
if (!validOption) {
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;
}
auto from = entity_list.GetBotByBotName(sep->arg[1]);
if (!from) {
c->Message(Chat::Yellow, "Could not find %s.", sep->arg[1]);
return;
}
if (!from->IsBot()) {
c->Message(Chat::Yellow, "%s is not a bot.", from->GetCleanName());
return;
}
if (!from->GetOwner()) {
c->Message(Chat::Yellow, "Could not find %s's owner.", from->GetCleanName());
}
if (RuleB(Bots, CopySettingsOwnBotsOnly) && from->GetOwner() != c) {
c->Message(Chat::Yellow, "You name a bot you own to use this command.");
return;
}
if (!RuleB(Bots, AllowCopySettingsAnon) && from->GetOwner() != c && from->GetOwner()->CastToClient()->GetAnon()) {
c->Message(Chat::Yellow, "You name a bot you own to use this command.");
return;
}
auto to = ActionableBots::AsNamed_ByBot(c, sep->arg[2]);
if (!to) {
c->Message(Chat::Yellow, "Could not find %s.", sep->arg[1]);
return;
}
if (!to->IsBot()) {
c->Message(Chat::Yellow, "%s is not a bot.", to->GetCleanName());
return;
}
if (!to->GetOwner()) {
c->Message(Chat::Yellow, "Could not find %s's owner.", to->GetCleanName());
}
if (to->GetOwner() != c) {
c->Message(Chat::Yellow, "You must name a spawned bot that you own to use this command.");
return;
}
if (to == from) {
c->Message(Chat::Yellow, "You cannot copy to the same bot that you're copying from.");
return;
}
std::string output = "";
if (!strcasecmp(sep->arg[3], "misc")) {
from->CopySettings(to, BotSettingCategories::BaseSetting);
output = "Miscellaneous";
}
else if (!strcasecmp(sep->arg[3], "holds")) {
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellHold);
}
else if (!strcasecmp(sep->arg[3], "delays")) {
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellDelay);
}
else if (!strcasecmp(sep->arg[3], "minthresholds")) {
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellMinThreshold);
}
else if (!strcasecmp(sep->arg[3], "maxthresholds")) {
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellMaxThreshold);
}
else if (!strcasecmp(sep->arg[3], "aggrochecks")) {
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeAggroCheck);
}
else if (!strcasecmp(sep->arg[3], "minmanapct")) {
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMinManaPct);
}
else if (!strcasecmp(sep->arg[3], "maxmanapct")) {
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMaxManaPct);
}
else if (!strcasecmp(sep->arg[3], "minhppct")) {
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMinHPPct);
}
else if (!strcasecmp(sep->arg[3], "maxhppct")) {
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeMaxHPPct);
}
else if (!strcasecmp(sep->arg[3], "idlepriority")) {
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeIdlePriority);
}
else if (!strcasecmp(sep->arg[3], "engagedpriority")) {
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeEngagedPriority);
}
else if (!strcasecmp(sep->arg[3], "pursuepriority")) {
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypePursuePriority);
}
else if (!strcasecmp(sep->arg[3], "targetcounts")) {
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
output = from->GetBotSpellCategoryName(BotSettingCategories::SpellTypeAEOrGroupTargetCount);
}
else if (!strcasecmp(sep->arg[3], "spellsettings")) {
from->CopyBotSpellSettings(to);
output = "^spellsettings";
}
else if (!strcasecmp(sep->arg[3], "spelltypesettings")) {
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
output = "spell type";
}
else if (!strcasecmp(sep->arg[3], "all")) {
from->CopySettings(to, BotSettingCategories::BaseSetting);
from->CopySettings(to, BotSettingCategories::SpellHold, spellType);
from->CopySettings(to, BotSettingCategories::SpellDelay, spellType);
from->CopySettings(to, BotSettingCategories::SpellMinThreshold, spellType);
from->CopySettings(to, BotSettingCategories::SpellMaxThreshold, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeAggroCheck, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMinManaPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMaxManaPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMinHPPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeMaxHPPct, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeIdlePriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeEngagedPriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypePursuePriority, spellType);
from->CopySettings(to, BotSettingCategories::SpellTypeAEOrGroupTargetCount, spellType);
from->CopyBotSpellSettings(to);
}
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;
}
c->Message(
Chat::Green,
fmt::format(
"{}'s{}{} settings were copied to {}.",
from->GetCleanName(),
(
spellType != UINT16_MAX ?
fmt::format(" [{}] ",
c->GetSpellTypeNameByID(spellType)
)
: " "
),
output,
to->GetCleanName()
).c_str()
);
}
+473
View File
@@ -0,0 +1,473 @@
#include "../bot_command.h"
void bot_command_default_settings(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_default_settings", sep->arg[0], "defaultsettings")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Restores a bot's setting(s) to defaults"
};
std::vector<std::string> notes =
{
"- You can put a spell type ID or shortname after any option except [all], [misc] and [spellsettings] to restore that specifc spell type only"
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [option] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To restore delays for Clerics:",
fmt::format(
"{} delays byclass 2",
sep->arg[0]
)
};
std::vector<std::string> examples_two =
{
"To restore only Snare delays for BotA:",
fmt::format(
"{} delays {} byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} delays {} byname BotA",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_three = { };
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
};
std::vector<std::string> options =
{
"all, misc, spellsettings, spelltypesettings, holds, delays, minthresholds, maxthresholds minmanapct, maxmanapct, minhppct, maxhppct, idlepriority, engagedpriority, pursuepriority, aggrocheck, targetcounts"
};
std::vector<std::string> options_one =
{
"[spellsettings] will restore ^spellsettings options",
"[spelltypesettings] restores all spell type settings",
"[all] restores all settings"
};
std::vector<std::string> options_two =
{
"[misc] restores all miscellaneous options such as:",
"- ^showhelm, ^followd, ^stopmeleelevel",
"- ^enforcespellsettings, ^bottoggleranged, ^petsettype",
"- ^behindmob, ^casterrange, ^illusionblock",
"- ^sitincombat, ^sithppercent and ^sitmanapercent",
};
std::vector<std::string> options_three =
{
"The remaining options restore that specific type"
};
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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 2;
bool validOption = false;
uint16 spellType = UINT16_MAX;
std::vector<std::string> options =
{
"all",
"misc"
"spellsettings",
"spelltypesettings",
"holds",
"delays",
"minthresholds",
"maxthresholds",
"aggrocheck",
"minmanapct",
"maxmanapct",
"minhppct",
"maxhppct",
"idlepriority",
"engagedpriority",
"pursuepriority",
"targetcounts"
};
for (int i = 0; i < options.size(); i++) {
if (sep->arg[1] == options[i]) {
if (options[i] != "all" && options[i] != "misc" && options[i] != "spellsettings") {
if (sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX) {
if (sep->IsNumber(2)) {
spellType = atoi(sep->arg[2]);
}
if (c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(sep->arg[2]);
}
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
++ab_arg;
}
}
else if (
(options[i] == "all" || options[i] == "misc" || options[i] == "spellsettings") &&
((sep->IsNumber(2) || c->GetSpellTypeIDByShortName(sep->arg[2]) != UINT16_MAX))
) {
break;
}
validOption = true;
break;
}
}
if (!validOption) {
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
std::string output = "";
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (!strcasecmp(sep->arg[1], "misc")) {
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i));
output = "miscellanous settings";
}
}
else if (!strcasecmp(sep->arg[1], "holds")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellHold(spellType, my_bot->GetDefaultSpellHold(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
}
}
output = "hold settings";
}
else if (!strcasecmp(sep->arg[1], "delays")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
}
}
output = "delay settings";
}
else if (!strcasecmp(sep->arg[1], "minthresholds")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellMinThreshold(spellType, my_bot->GetDefaultSpellMinThreshold(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
}
}
output = "minimum threshold settings";
}
else if (!strcasecmp(sep->arg[1], "maxthresholds")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellMaxThreshold(spellType, my_bot->GetDefaultSpellMaxThreshold(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
}
}
output = "maximum threshold settings";
}
else if (!strcasecmp(sep->arg[1], "aggrochecks")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypeAggroCheck(spellType, my_bot->GetDefaultSpellTypeAggroCheck(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
}
}
output = "aggro check settings";
}
else if (!strcasecmp(sep->arg[1], "minmanapct")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypeMinManaLimit(spellType, my_bot->GetDefaultSpellTypeMinManaLimit(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
}
}
output = "min mana settings";
}
else if (!strcasecmp(sep->arg[1], "maxmanapct")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypeMaxManaLimit(spellType, my_bot->GetDefaultSpellTypeMaxManaLimit(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
}
}
output = "max mana settings";
}
else if (!strcasecmp(sep->arg[1], "minhppct")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypeMinHPLimit(spellType, my_bot->GetDefaultSpellTypeMinHPLimit(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
}
}
output = "min hp settings";
}
else if (!strcasecmp(sep->arg[1], "maxhppct")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypeMaxHPLimit(spellType, my_bot->GetDefaultSpellTypeMaxHPLimit(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
}
}
output = "max hp settings";
}
else if (!strcasecmp(sep->arg[1], "idlepriority")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetClass()));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
}
}
output = "idle priority settings";
}
else if (!strcasecmp(sep->arg[1], "engagedpriority")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetClass()));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
}
}
output = "engaged priority settings";
}
else if (!strcasecmp(sep->arg[1], "pursuepriority")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetClass()));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
}
}
output = "pursue priority settings";
}
else if (!strcasecmp(sep->arg[1], "targetcounts")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
}
}
output = "ae/group count settings";
}
else if (!strcasecmp(sep->arg[1], "spellsettings")) {
my_bot->ResetBotSpellSettings();
output = "^spellsettings";
}
else if (!strcasecmp(sep->arg[1], "spelltypesettings")) {
if (spellType != UINT16_MAX) {
my_bot->SetSpellHold(spellType, my_bot->GetDefaultSpellHold(spellType));
my_bot->SetSpellDelay(spellType, my_bot->GetDefaultSpellDelay(spellType));
my_bot->SetSpellMinThreshold(spellType, my_bot->GetDefaultSpellMinThreshold(spellType));
my_bot->SetSpellMaxThreshold(spellType, my_bot->GetDefaultSpellMaxThreshold(spellType));
my_bot->SetSpellTypeAggroCheck(spellType, my_bot->GetDefaultSpellTypeAggroCheck(spellType));
my_bot->SetSpellTypeMinManaLimit(spellType, my_bot->GetDefaultSpellTypeMinManaLimit(spellType));
my_bot->SetSpellTypeMaxManaLimit(spellType, my_bot->GetDefaultSpellTypeMaxManaLimit(spellType));
my_bot->SetSpellTypeMinHPLimit(spellType, my_bot->GetDefaultSpellTypeMinHPLimit(spellType));
my_bot->SetSpellTypeMaxHPLimit(spellType, my_bot->GetDefaultSpellTypeMaxHPLimit(spellType));
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Idle, my_bot->GetClass()));
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Engaged, my_bot->GetClass()));
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(spellType, BotPriorityCategories::Pursue, my_bot->GetClass()));
my_bot->SetSpellTypeAEOrGroupTargetCount(spellType, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(spellType));
}
else {
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
}
}
output = "spell type settings";
}
else if (!strcasecmp(sep->arg[1], "all")) {
for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) {
my_bot->SetBotBaseSetting(i, my_bot->GetDefaultBotBaseSetting(i));
}
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
my_bot->SetSpellHold(i, my_bot->GetDefaultSpellHold(i));
my_bot->SetSpellDelay(i, my_bot->GetDefaultSpellDelay(i));
my_bot->SetSpellMinThreshold(i, my_bot->GetDefaultSpellMinThreshold(i));
my_bot->SetSpellMaxThreshold(i, my_bot->GetDefaultSpellMaxThreshold(i));
my_bot->SetSpellTypeAggroCheck(i, my_bot->GetDefaultSpellTypeAggroCheck(i));
my_bot->SetSpellTypeMinManaLimit(i, my_bot->GetDefaultSpellTypeMinManaLimit(i));
my_bot->SetSpellTypeMaxManaLimit(i, my_bot->GetDefaultSpellTypeMaxManaLimit(i));
my_bot->SetSpellTypeMinHPLimit(i, my_bot->GetDefaultSpellTypeMinHPLimit(i));
my_bot->SetSpellTypeMaxHPLimit(i, my_bot->GetDefaultSpellTypeMaxHPLimit(i));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Idle, my_bot->GetClass()));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Engaged, my_bot->GetClass()));
my_bot->SetSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetDefaultSpellTypePriority(i, BotPriorityCategories::Pursue, my_bot->GetClass()));
my_bot->SetSpellTypeAEOrGroupTargetCount(i, my_bot->GetDefaultSpellTypeAEOrGroupTargetCount(i));
};
my_bot->ResetBotSpellSettings();
output = "settings";
}
++success_count;
}
if (success_count == 1) {
c->Message(
Chat::Green,
fmt::format(
"{} says, '{}{} were restored.'",
first_found->GetCleanName(),
(
spellType != UINT16_MAX ?
fmt::format("My [{}] ",
c->GetSpellTypeNameByID(spellType)
)
: "My "
),
output
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bot's{}{} were restored.",
success_count,
(
spellType != UINT16_MAX ?
fmt::format(" [{}] ",
c->GetSpellTypeNameByID(spellType)
)
: " "
),
output
).c_str()
);
}
}
+8 -3
View File
@@ -6,22 +6,27 @@ void bot_command_defensive(Client *c, const Seperator *sep)
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_defensive", sep->arg[0], "defensive"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
helper_send_usage_required_bots(c, BCEnum::SpT_Stance);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string class_race_arg = sep->arg[1];
std::string arg1 = sep->arg[1];
int ab_arg = 1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, !class_race_check ? sep->arg[2] : nullptr, class_race_check ? atoi(sep->arg[2]) : 0) == ActionableBots::ABT_None) {
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
int success_count = 0;
+73 -33
View File
@@ -1,11 +1,11 @@
#include "../bot_command.h"
void bot_command_follow(Client *c, const Seperator *sep)
void bot_command_follow(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_follow", sep->arg[0], "follow"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "usage: (<friendly_target>) %s ([option: reset]) [actionable: byname | ownergroup | ownerraid | namesgroup | mmr | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "usage: %s chain", sep->arg[0]);
return;
}
@@ -26,13 +26,22 @@ void bot_command_follow(Client *c, const Seperator *sep)
}
else if (!optional_arg.compare("reset")) {
reset = true;
ab_arg = 2;
name_arg = 3;
++ab_arg;
++name_arg ;
}
else {
target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single);
//target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single);
target_mob = c->GetTarget();
if (!target_mob) {
c->Message(Chat::White, "You must <target> a friendly mob to use this command");
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
return;
}
else if (!target_mob->IsBot() && !target_mob->IsClient()) {
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
return;
}
else if ((target_mob->GetGroup() && target_mob->GetGroup() != c->GetGroup()) || (target_mob->GetRaid() && target_mob->GetRaid() != c->GetRaid())) {
c->Message(Chat::White, "You must <target> a friendly player or bot within your group or raid to use this command");
return;
}
}
@@ -51,29 +60,54 @@ void bot_command_follow(Client *c, const Seperator *sep)
sbl.remove(nullptr);
for (auto bot_iter : sbl) {
bot_iter->WipeHateList();
auto my_group = bot_iter->GetGroup();
if (my_group) {
if (reset) {
if (!my_group->GetLeader() || my_group->GetLeader() == bot_iter)
bot_iter->SetFollowID(c->GetID());
else
bot_iter->SetFollowID(my_group->GetLeader()->GetID());
bot_iter->SetManualFollow(false);
}
else {
if (bot_iter == target_mob)
bot_iter->SetFollowID(c->GetID());
else
bot_iter->SetFollowID(target_mob->GetID());
bot_iter->SetManualFollow(true);
}
}
else {
if (!bot_iter->GetGroup() && !bot_iter->GetRaid()) {
bot_iter->SetFollowID(0);
bot_iter->SetManualFollow(false);
}
else {
if (reset) {
bot_iter->SetFollowID(c->GetID());
bot_iter->SetManualFollow(false);
}
else {
if (target_mob->IsGrouped() || target_mob->IsRaidGrouped()) {
bot_iter->SetFollowID(target_mob->GetID());
bot_iter->SetManualFollow(true);
}
else if (bot_iter == target_mob) {
bot_iter->SetFollowID(c->GetID());
bot_iter->SetManualFollow(true);
}
else {
bot_iter->SetFollowID(0);
bot_iter->SetManualFollow(false);
}
}
}
//auto my_group = bot_iter->GetGroup();
//if (my_group) {
// if (reset) {
// if (!my_group->GetLeader() || my_group->GetLeader() == bot_iter)
// bot_iter->SetFollowID(c->GetID());
// else
// bot_iter->SetFollowID(my_group->GetLeader()->GetID());
//
// bot_iter->SetManualFollow(false);
// }
// else {
// if (bot_iter == target_mob)
// bot_iter->SetFollowID(c->GetID());
// else
// bot_iter->SetFollowID(target_mob->GetID());
//
// bot_iter->SetManualFollow(true);
// }
//}
//else {
// bot_iter->SetFollowID(0);
// bot_iter->SetManualFollow(false);
//}
if (!bot_iter->GetPet())
continue;
@@ -81,31 +115,37 @@ void bot_command_follow(Client *c, const Seperator *sep)
bot_iter->GetPet()->SetFollowID(bot_iter->GetID());
}
Mob* follow_mob = nullptr;
if (sbl.size() == 1) {
Mob* follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
Bot::BotGroupSay(
sbl.front(),
follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
c->Message(
Chat::White,
fmt::format(
"Following {}.",
follow_mob ? follow_mob->GetCleanName() : "no one"
follow_mob ? follow_mob->GetCleanName() : "you"
).c_str()
);
} else {
}
else {
if (reset) {
c->Message(
Chat::White,
fmt::format(
"{} of your bots are following their default assignments.",
"{} of your bots are following you.",
sbl.size()
).c_str()
);
} else {
}
else {
if (!sbl.empty()) {
follow_mob = entity_list.GetMob(sbl.front()->GetFollowID());
}
c->Message(
Chat::White,
fmt::format(
"{} of your bots are following {}.",
sbl.size(),
target_mob->GetCleanName()
follow_mob ? follow_mob->GetCleanName() : "you"
).c_str()
);
}
+3 -3
View File
@@ -7,7 +7,7 @@ void bot_command_guard(Client *c, const Seperator *sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
return;
}
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
@@ -20,8 +20,8 @@ void bot_command_guard(Client *c, const Seperator *sep)
if (!clear_arg.compare("clear")) {
clear = true;
ab_arg = 2;
name_arg = 3;
++ab_arg;
++name_arg;
}
std::string class_race_arg = sep->arg[ab_arg];
+3 -3
View File
@@ -7,7 +7,7 @@ void bot_command_hold(Client *c, const Seperator *sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | byclass | byrace | spawned]] ([actionable_name])", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([option: clear]) [actionable: byname | ownergroup | ownerraid | namesgroup | healrotation | mmr | byclass | byrace | default: spawned] ([actionable_name])", sep->arg[0]);
return;
}
const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2);
@@ -20,8 +20,8 @@ void bot_command_hold(Client *c, const Seperator *sep)
if (!clear_arg.compare("clear")) {
clear = true;
ab_arg = 2;
name_arg = 3;
++ab_arg;
++name_arg;
}
std::string class_race_arg = sep->arg[ab_arg];
+172
View File
@@ -0,0 +1,172 @@
#include "../bot_command.h"
void bot_command_illusion_block(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_illusion_block", sep->arg[0], "illusionblock")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots will block the illusion effects of spells cast by players or bots."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set BotA to block illusions:",
fmt::format(
"{} 1 byname BotA",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the illusion block status for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} block illusions.'",
my_bot->GetCleanName(),
my_bot->GetIllusionBlock() ? "will" : "will not"
).c_str()
);
}
else {
my_bot->SetIllusionBlock(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} block illusions.'",
first_found->GetCleanName(),
first_found->GetIllusionBlock() ? "will now" : "will no longer"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots {} block illusions.",
success_count,
typeValue ? "will now" : "will no longer"
).c_str()
);
}
}
}
+18 -3
View File
@@ -217,9 +217,18 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
}
const auto* itm = inst->GetItem();
EQ::SayLinkEngine linker;
linker.SetLinkType(EQ::saylink::SayLinkItemInst);
linker.SetItemInst(inst);
if (inst && itm && c->CheckLoreConflict(itm)) {
c->MessageString(Chat::White, PICK_LORE);
c->Message(
Chat::White,
fmt::format(
"You cannot pick up {} because it is a lore item you already possess.",
linker.GenerateLink()
).c_str()
);
return;
}
@@ -233,7 +242,13 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
continue;
}
c->MessageString(Chat::White, PICK_LORE);
c->Message(
Chat::White,
fmt::format(
"You cannot pick up {} because it is a lore item you already possess.",
linker.GenerateLink()
).c_str()
);
return;
}
@@ -247,7 +262,7 @@ void bot_command_inventory_remove(Client* c, const Seperator* sep)
slot_id == EQ::invslot::slotRange ||
slot_id == EQ::invslot::slotAmmo
) {
my_bot->SetBotArcherySetting(false, true);
my_bot->SetBotRangedSetting(false);
}
my_bot->RemoveBotItemBySlot(slot_id);
+172
View File
@@ -0,0 +1,172 @@
#include "../bot_command.h"
void bot_command_max_melee_range(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_max_melee_range", sep->arg[0], "maxmeleerange")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots will stay at max melee range during combat."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set BotA to stay at max melee range:",
fmt::format(
"{} 1 byname BotA",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the max melee range status for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} stay at max melee range.'",
my_bot->GetCleanName(),
my_bot->GetMaxMeleeRange() ? "will" : "will not"
).c_str()
);
}
else {
my_bot->SetMaxMeleeRange(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} stay at max melee range.'",
first_found->GetCleanName(),
first_found->GetMaxMeleeRange() ? "will now" : "will no longer"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots {} stay at max melee range.",
success_count,
typeValue ? "will now" : "will no longer"
).c_str()
);
}
}
}
+21 -23
View File
@@ -2,42 +2,40 @@
void bot_command_mesmerize(Client *c, const Seperator *sep)
{
bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Mesmerize];
if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Mesmerize) || helper_command_alias_fail(c, "bot_command_mesmerize", sep->arg[0], "mesmerize"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <enemy_target> %s", sep->arg[0]);
helper_send_usage_required_bots(c, BCEnum::SpT_Mesmerize);
return;
}
ActionableTarget::Types actionable_targets;
Bot* my_bot = nullptr;
bool isSuccess = false;
std::list<Bot*> sbl;
MyBots::PopulateSBL_BySpawnedBots(c, sbl);
for (auto list_iter : *local_list) {
auto local_entry = list_iter;
if (helper_spell_check_fail(local_entry))
continue;
for (auto bot_iter : sbl) {
std::list<BotSpell_wPriority> botSpellList = bot_iter->GetPrioritizedBotSpellsBySpellType(bot_iter, BotSpellTypes::Mez, c->GetTarget(), IsAEBotSpellType(BotSpellTypes::Mez));
auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY);
if (!target_mob)
continue;
for (const auto& s : botSpellList) {
if (!IsValidSpell(s.SpellId)) {
continue;
}
if (spells[local_entry->spell_id].max_value[EFFECTIDTOINDEX(1)] < target_mob->GetLevel())
continue;
if (!bot_iter->IsInGroupOrRaid()) {
continue;
}
my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob);
if (!my_bot)
continue;
if (!bot_iter->CastChecks(s.SpellId, c->GetTarget(), BotSpellTypes::Mez, false, false)) {
continue;
}
uint32 dont_root_before = 0;
if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before))
target_mob->SetDontRootMeBefore(dont_root_before);
break;
if (bot_iter->CommandedDoSpellCast(s.SpellIndex, c->GetTarget(), s.ManaCost)) {
bot_iter->BotGroupSay(bot_iter, "Casting %s [%s] on %s.", GetSpellName(s.SpellId), bot_iter->GetSpellTypeNameByID(BotSpellTypes::Mez), c->GetTarget()->GetCleanName());
isSuccess = true;
}
}
}
helper_no_available_bots(c, my_bot);
if (!isSuccess) {
helper_no_available_bots(c);
}
}
+38 -9
View File
@@ -19,7 +19,7 @@ void bot_command_pet_get_lost(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_pet_get_lost", sep->arg[0], "petgetlost"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
int ab_mask = ActionableBots::ABM_NoFilter;
@@ -98,7 +98,8 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_pet_set_type", sep->arg[0], "petsettype"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [type: water | fire | air | earth | monster] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s [type: auto | water | fire | air | earth | monster | epic] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "if set to 'auto', bots will choose their own pet type");
c->Message(Chat::White, "requires one of the following bot classes:");
c->Message(Chat::White, "Magician(1)");
return;
@@ -109,29 +110,41 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
uint8 pet_type = 255;
uint8 level_req = 255;
if (!pet_arg.compare("water")) {
if (!pet_arg.compare("auto")) {
pet_type = 0;
level_req = 1;
}
else if (!pet_arg.compare("fire")) {
else if (!pet_arg.compare("water")) {
pet_type = 1;
level_req = 1;
}
else if (!pet_arg.compare("fire")) {
pet_type = 2;
level_req = 3;
}
else if (!pet_arg.compare("air")) {
pet_type = 2;
pet_type = 3;
level_req = 4;
}
else if (!pet_arg.compare("earth")) {
pet_type = 3;
pet_type = 4;
level_req = 5;
}
else if (!pet_arg.compare("monster")) {
pet_type = 4;
pet_type = 5;
level_req = 30;
}
else if (!pet_arg.compare("epic")) {
pet_type = 6;
if (!RuleB(Bots, AllowMagicianEpicPet)) {
c->Message(Chat::Yellow, "Epic pets are currently disabled for bots.");
return;
}
level_req = RuleI(Bots,AllowMagicianEpicPetLevel);
}
if (pet_type == 255) {
c->Message(Chat::White, "You must specify a pet [type: water | fire | air | earth | monster]");
c->Message(Chat::White, "You must specify a pet [type: auto | water | fire | air | earth | monster | epic]");
return;
}
@@ -157,7 +170,23 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep)
if (!bot_iter)
continue;
bot_iter->SetPetChooser(true);
if (RuleI(Bots, RequiredMagicianEpicPetItemID) > 0) {
bool has_item = bot_iter->HasBotItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) != INVALID_INDEX;
if (!has_item) {
c->Message(
Chat::Say,
fmt::format(
"{} says, 'I require {} to cast an epic pet which I do not currently possess.'",
bot_iter->GetCleanName(),
(database.GetItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) ? database.CreateItemLink(RuleI(Bots, RequiredMagicianEpicPetItemID)) : "an item")
).c_str()
);
continue;
}
}
bot_iter->SetPetChooserID(pet_type);
if (bot_iter->GetPet()) {
auto pet_id = bot_iter->GetPetID();
+15 -3
View File
@@ -7,15 +7,27 @@ void bot_command_pull(Client *c, const Seperator *sep)
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <enemy_target> %s", sep->arg[0]);
c->Message(Chat::White, "usage: <enemy_target> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
int ab_mask = ActionableBots::ABM_OwnerGroup; // existing behavior - need to add c->IsGrouped() check and modify code if different behavior is desired
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
int ab_arg = 1;
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, "ownergroup", sbl, ab_mask) == ActionableBots::ABT_None) {
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
auto target_mob = ActionableTarget::VerifyEnemy(c, BCEnum::TT_Single);
+1 -1
View File
@@ -5,7 +5,7 @@ void bot_command_release(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_command_release", sep->arg[0], "release"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: <any>] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_NoFilter;
+172
View File
@@ -0,0 +1,172 @@
#include "../bot_command.h"
void bot_command_sit_hp_percent(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_sit_hp_percent", sep->arg[0], "sithppercent")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"HP % threshold when bots will sit in combat if allowed."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set Clerics to sit at 45% HP:",
fmt::format(
"{} 45 byclass 2",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the HP threshold for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I sit in combat whem at or below [{}%%] HP.'",
my_bot->GetCleanName(),
my_bot->GetHPWhenToMed()
).c_str()
);
}
else {
my_bot->SetHPWhenToMed(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I will now sit in combat whem at or below [{}%%] HP.'",
first_found->GetCleanName(),
first_found->GetHPWhenToMed()
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots will now sit in combat whem at or below [{}%%] HP.'",
success_count,
typeValue
).c_str()
);
}
}
}
+172
View File
@@ -0,0 +1,172 @@
#include "../bot_command.h"
void bot_command_sit_in_combat(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_sit_in_combat", sep->arg[0], "sitincombat")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots will sit in combat to heal or med."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set Clerics to sit in combat:",
fmt::format(
"{} 1 byclass 2",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the sit in combat state for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} sit in combat.'",
my_bot->GetCleanName(),
my_bot->GetMedInCombat() ? "will" : "will not"
).c_str()
);
}
else {
my_bot->SetMedInCombat(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I {} sit in combat.'",
first_found->GetCleanName(),
first_found->GetMedInCombat() ? "will now" : "will no longer"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots {} sit in combat.",
success_count,
typeValue ? "will now" : "will no longer"
).c_str()
);
}
}
}
+172
View File
@@ -0,0 +1,172 @@
#include "../bot_command.h"
void bot_command_sit_mana_percent(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_sit_mana_percent", sep->arg[0], "sitmanapercent")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Mana % threshold when bots will sit in combat if allowed."
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set Clerics to sit at 45% mana:",
fmt::format(
"{} 45 byclass 2",
sep->arg[0]
)
};
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three =
{
"To check the mana threshold for all bots:",
fmt::format(
"{} current spawned",
sep->arg[0]
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
int ab_arg = 1;
bool current_check = false;
uint32 typeValue = 0;
if (sep->IsNumber(1)) {
typeValue = atoi(sep->arg[1]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
return;
}
}
else if (!arg1.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I sit in combat whem at or below [{}%%] mana.'",
my_bot->GetCleanName(),
my_bot->GetManaWhenToMed()
).c_str()
);
}
else {
my_bot->SetManaWhenToMed(typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'I will now sit in combat whem at or below [{}%%] mana.'",
first_found->GetCleanName(),
first_found->GetManaWhenToMed()
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots will now sit in combat whem at or below [{}%%] mana.'",
success_count,
typeValue
).c_str()
);
}
}
}
+2 -2
View File
@@ -503,7 +503,7 @@ void bot_spell_info_dialogue_window(Client* c, const Seperator *sep)
auto results = database.QueryDatabase(
fmt::format(
"SELECT value FROM db_str WHERE id = {} and type = 6 LIMIT 1",
spells[spell_id].effect_description_id
spells[spell_id].description_id
)
);
@@ -557,7 +557,7 @@ void bot_command_enforce_spell_list(Client* c, const Seperator *sep)
}
bool enforce_state = (sep->argnum > 0) ? Strings::ToBool(sep->arg[1]) : !my_bot->GetBotEnforceSpellSetting();
my_bot->SetBotEnforceSpellSetting(enforce_state, true);
my_bot->SetBotEnforceSpellSetting(enforce_state);
c->Message(
Chat::White,
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_aggro_checks(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_aggro_checks", sep->arg[0], "spellaggrochecks")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots will cast a spell type if they think it will get them aggro"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to check aggro on nukes:",
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
BotSpellTypes::Nuke
)
};
std::vector<std::string> examples_two =
{
"To set Shadowknights to ignore aggro checks on snares:",
fmt::format(
"{} {} 0 byclass 5",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 0 byclass 5",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_three =
{
"To check the current DoT aggro check on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::DOT
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] aggro check is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeAggroCheck(spellType) ? "enabled" : "disabled"
).c_str()
);
}
else {
my_bot->SetSpellTypeAggroCheck(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] aggro check was [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeAggroCheck(spellType) ? "enabled" : "disabled"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots [{}] their [{}] aggro check.",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue ? "enabled" : "disabled"
).c_str()
);
}
}
}
+242
View File
@@ -0,0 +1,242 @@
#include "../bot_command.h"
void bot_command_spell_delays(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_delays", sep->arg[0], "spelldelays")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls how long a bot will wait between casts of different spell types"
};
std::vector<std::string> notes =
{
"- All pet types are based off the pet's owner's setting",
"- Any remaining types use the owner's setting when a pet is the target",
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
"- e.g., BotA is healing BotB using BotB's settings",
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all Necromancers to an 8s DoT delay:",
fmt::format(
"{} {} 8000 byclass 11",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
),
fmt::format(
"{} {} 8000 byclass 11",
sep->arg[0],
BotSpellTypes::DOT
)
};
std::vector<std::string> examples_two =
{
"To set all Warriors to receive Fast Heals every 2.5s:",
fmt::format(
"{} {} 2500 byclass 1",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 2500 byclass 1",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_three =
{
"To check the current Nuke delay on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Nuke
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid targetgroup, namesgroup, healrotationtargets mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 1 || typeValue > 60000) {
c->Message(Chat::Yellow, "You must enter a value between 1-60000 (1ms to 60s).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] spell delay is currently [{}] seconds.'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellDelay(spellType) / 1000.00
).c_str()
);
}
else {
my_bot->SetSpellDelay(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] spell delay was set to [{}] seconds.'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellDelay(spellType) / 1000.00
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] spell delay to [{}] seconds.",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue / 1000.00
).c_str()
);
}
}
}
@@ -0,0 +1,240 @@
#include "../bot_command.h"
void bot_command_spell_engaged_priority(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_engaged_priority", sep->arg[0], "spellengagedpriority")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Sets the order of spell casts when engaged in combat by spell type"
};
std::vector<std::string> notes =
{
"-Setting a spell type to 0 will prevent that type from being cast.",
"-If 2 or more are set to the same priority they will sort by spell type ID."
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all Shaman to cast slows first:",
fmt::format(
"{} {} 1 byclass 10",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Slow)
),
fmt::format(
"{} {} 1 byclass 10",
sep->arg[0],
BotSpellTypes::Slow
)
};
std::vector<std::string> examples_two =
{
"To set all bots to not cast snares:",
fmt::format(
"{} {} 0 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 0 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_three =
{
"To check the current engaged priority of dispels on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Dispel)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Dispel
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] engaged cast priority is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Engaged)
).c_str()
);
}
else {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Engaged, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] engaged cast priority was set to [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Engaged)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] engaged cast priority to [{}].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+229
View File
@@ -0,0 +1,229 @@
#include "../bot_command.h"
void bot_command_spell_holds(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_holds", sep->arg[0], "spellholds")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Toggles whether or not bots can cast or receive certain spell types"
};
std::vector<std::string> notes =
{
"- All pet types are based off the pet's owner's setting",
"- Any remaining types use the owner's setting when a pet is the target",
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
"- e.g., BotA is healing BotB using BotB's settings",
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to hold DoTs:",
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
),
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
BotSpellTypes::DOT
)
};
std::vector<std::string> examples_two =
{
"To check the current DoT settings on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::DOT
)
};
std::vector<std::string> examples_three = { };
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 1) {
c->Message(Chat::Yellow, "You must enter either 0 for disabled or 1 for enabled.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] spell hold is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellHold(spellType) ? "enabled" : "disabled"
).c_str()
);
}
else {
my_bot->SetSpellHold(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] spell hold was [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellHold(spellType) ? "enabled" : "disabled"
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots [{}] their [{}] spell hold.",
success_count,
typeValue ? "enabled" : "disabled",
c->GetSpellTypeNameByID(spellType)
).c_str()
);
}
}
}
+240
View File
@@ -0,0 +1,240 @@
#include "../bot_command.h"
void bot_command_spell_idle_priority(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_idle_priority", sep->arg[0], "spellidlepriority")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Sets the order of spell casts when not in combat by spell type"
};
std::vector<std::string> notes =
{
"-Setting a spell type to 0 will prevent that type from being cast.",
"-If 2 or more are set to the same priority they will sort by spell type ID."
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all Clerics to cast fast heals third:",
fmt::format(
"{} {} 3 byclass 2",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 3 byclass 2",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_two =
{
"To set all bots to not cast cures:",
fmt::format(
"{} {} 0 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Cure)
),
fmt::format(
"{} {} 0 spawned",
sep->arg[0],
BotSpellTypes::Cure
)
};
std::vector<std::string> examples_three =
{
"To check the current idle priority of buffs on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Buff)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Buff
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] idle cast priority is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Idle)
).c_str()
);
}
else {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Idle, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] idle cast priority was set to [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Idle)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] idle cast priority to [{}].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_max_hp_pct", sep->arg[0], "spellmaxhppct")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what health percentage a bot will start casting different spell types"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to start snaring when their health is at or below 100% HP:",
fmt::format(
"{} {} 100 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_two =
{
"To set BotA to start casting fast heals at 30% HP:",
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_three =
{
"To check the current Stun max HP percent on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Stun
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum HP is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeMaxHPLimit(spellType)
).c_str()
);
}
else {
my_bot->SetSpellTypeMaxHPLimit(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum HP was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeMaxHPLimit(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] maximum HP to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_max_mana_pct", sep->arg[0], "spellmaxmanapct")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what mana percentage a bot will stop casting different spell types"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to start snaring when their mana is at or below 100% HP:",
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_two =
{
"To set BotA to start casting fast heals at 30% mana:",
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_three =
{
"To check the current Stun max mana percent on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Stun
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum mana is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeMaxManaLimit(spellType)
).c_str()
);
}
else {
my_bot->SetSpellTypeMaxManaLimit(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum mana was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeMaxManaLimit(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] maximum mana to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+243
View File
@@ -0,0 +1,243 @@
#include "../bot_command.h"
void bot_command_spell_max_thresholds(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_max_thresholds", sep->arg[0], "spellmaxthresholds")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what target HP % the bot will start casting different spell types"
};
std::vector<std::string> notes =
{
"- All pet types are based off the pet's owner's setting",
"- Any remaining types use the owner's setting when a pet is the target",
"- All Heals, Cures, Buffs (DS and resists included)",
"are based off the target's setting, not the caster",
"- e.g., BotA is healing BotB using BotB's settings",
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to start snaring at 99%:",
fmt::format(
"{} {} 99 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 99 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_two =
{
"To set bot Enchbot to start casting Debuffs at 99%:",
fmt::format(
"{} {} 99 byname Enchbot",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff)
),
fmt::format(
"{} {} 99 byname Enchbot",
sep->arg[0],
BotSpellTypes::Debuff
)
};
std::vector<std::string> examples_three =
{
"To check the current Nuke max threshold on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Nuke
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum threshold is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellMaxThreshold(spellType)
).c_str()
);
}
else {
my_bot->SetSpellMaxThreshold(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] maximum threshold was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellMaxThreshold(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] maximum threshold to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_min_hp_pct", sep->arg[0], "spellminhppct")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what health percentage a bot will stop casting different spell types"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to stop snaring when their health is below 10% HP:",
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_two =
{
"To set BotA to stop casting fast heals at 30% HP:",
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_three =
{
"To check the current Stun min HP percent on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Stun
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum HP is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeMinHPLimit(spellType)
).c_str()
);
}
else {
my_bot->SetSpellTypeMinHPLimit(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum HP was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeMinHPLimit(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] minimum HP to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_min_mana_pct", sep->arg[0], "spellminmanapct")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what mana percentage a bot will stop casting different spell types"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to stop snaring when their mana is below 10% HP:",
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Snare)
),
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
BotSpellTypes::Snare
)
};
std::vector<std::string> examples_two =
{
"To set BotA to stop casting fast heals at 30% mana:",
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} 30 byname BotA",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_three =
{
"To check the current Stun min mana percent on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Stun)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Stun
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of mana).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum mana is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeMinManaLimit(spellType)
).c_str()
);
}
else {
my_bot->SetSpellTypeMinManaLimit(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum mana was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeMinManaLimit(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] minimum mana to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+244
View File
@@ -0,0 +1,244 @@
#include "../bot_command.h"
void bot_command_spell_min_thresholds(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_min_thresholds", sep->arg[0], "spellminthresholds")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Controls at what target HP % the bot will stop casting different spell types"
};
std::vector<std::string> notes =
{
"- All pet types are based off the pet's owner's setting",
"- Any remaining types use the owner's setting when a pet is the target",
"- All Heals, Cures, Buffs (DS and resists included) are based off the target's setting, not the caster",
"- e.g., BotA is healing BotB using BotB's settings",
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to stop debuffing at 10%:",
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Debuff)
),
fmt::format(
"{} {} 10 spawned",
sep->arg[0],
BotSpellTypes::Debuff
)
};
std::vector<std::string> examples_two =
{
"To set all Druids to stop casting DoTs at 15%:",
fmt::format(
"{} {} 15 byclass 6",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::DOT)
),
fmt::format(
"{} {} 15 byclass 6",
sep->arg[0],
BotSpellTypes::DOT
)
};
std::vector<std::string> examples_three =
{
"To check the current Fast Heal min threshold on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::FastHeals)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid",
"targetgroup, namesgroup, healrotationtargets",
"mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100 (0%% to 100%% of health).");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum threshold is currently [{}%%].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellMinThreshold(spellType)
).c_str()
);
}
else {
my_bot->SetSpellMinThreshold(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] minimum threshold was set to [{}%%].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellMinThreshold(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] minimum threshold to [{}%%].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+240
View File
@@ -0,0 +1,240 @@
#include "../bot_command.h"
void bot_command_spell_pursue_priority(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_pursue_priority", sep->arg[0], "spellpursuepriority")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Sets the order of spell casts when the mob is fleeing in combat by spell type"
};
std::vector<std::string> notes =
{
"- Setting a spell type to 0 will prevent that type from being cast.",
"- If 2 or more are set to the same priority they will sort by spell type ID."
};
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to cast nukes first:",
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
),
fmt::format(
"{} {} 1 spawned",
sep->arg[0],
BotSpellTypes::FastHeals
)
};
std::vector<std::string> examples_two =
{
"To set all Shaman to not cast cures:",
fmt::format(
"{} {} 0 byclass 10",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Cure)
),
fmt::format(
"{} {} 0 byclass 10",
sep->arg[0],
BotSpellTypes::Cure
)
};
std::vector<std::string> examples_three =
{
"To check the current pursue priority of buffs on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::Buff)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::Buff
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 0 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 0-100.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] pursue cast priority is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypePriority(spellType, BotPriorityCategories::Pursue)
).c_str()
);
}
else {
my_bot->SetSpellTypePriority(spellType, BotPriorityCategories::Pursue, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] pursue cast priority was set to [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypePriority(spellType, BotPriorityCategories::Pursue)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] pursue cast priority to [{}].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
#include "../bot_command.h"
void bot_command_spell_target_count(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_spell_target_count", sep->arg[0], "spelltargetcount")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Decides how many eligible targets are required for an AE or group spell to cast by spell type"
};
std::vector<std::string> notes = { };
std::vector<std::string> example_format =
{
fmt::format(
"{} [Type Shortname] [value] [actionable]"
, sep->arg[0]
),
fmt::format(
"{} [Type ID] [value] [actionable]"
, sep->arg[0]
)
};
std::vector<std::string> examples_one =
{
"To set all bots to AEMez with 5 or more targets:",
fmt::format(
"{} {} 5 spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::AEMez)
),
fmt::format(
"{} {} 5 spawned",
sep->arg[0],
BotSpellTypes::AEMez
)
};
std::vector<std::string> examples_two =
{
"To set Wizards to require 5 targets for AENukes:",
fmt::format(
"{} {} 3 byname BotA",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::AENukes)
),
fmt::format(
"{} {} 3 byname BotA",
sep->arg[0],
BotSpellTypes::AENukes
)
};
std::vector<std::string> examples_three =
{
"To check the current AESlow count on all bots:",
fmt::format(
"{} {} current spawned",
sep->arg[0],
c->GetSpellTypeShortNameByID(BotSpellTypes::AESlow)
),
fmt::format(
"{} {} current spawned",
sep->arg[0],
BotSpellTypes::AESlow
)
};
std::vector<std::string> actionables =
{
"target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned"
};
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> 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());
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], "", "", true);
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];
if (!arg1.compare("listid") || !arg1.compare("listname")) {
c->CastToBot()->SendSpellTypesWindow(c, sep->arg[0], sep->arg[1], sep->arg[2]);
return;
}
std::string arg2 = sep->arg[2];
int ab_arg = 2;
bool current_check = false;
uint16 spellType = 0;
uint32 typeValue = 0;
// String/Int type checks
if (sep->IsNumber(1)) {
spellType = atoi(sep->arg[1]);
if (spellType < BotSpellTypes::START || spellType > BotSpellTypes::END) {
c->Message(Chat::Yellow, "You must choose a valid spell type. Spell types range from %i to %i", BotSpellTypes::START, BotSpellTypes::END);
return;
}
}
else {
if (c->GetSpellTypeIDByShortName(arg1) != UINT16_MAX) {
spellType = c->GetSpellTypeIDByShortName(arg1);
}
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;
}
}
if (sep->IsNumber(2)) {
typeValue = atoi(sep->arg[2]);
++ab_arg;
if (typeValue < 1 || typeValue > 100) {
c->Message(Chat::Yellow, "You must enter a value between 1-100.");
return;
}
}
else if (!arg2.compare("current")) {
++ab_arg;
current_check = true;
}
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 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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
Bot* first_found = nullptr;
int success_count = 0;
for (auto my_bot : sbl) {
if (!first_found) {
first_found = my_bot;
}
if (current_check) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] target count is currently [{}].'",
my_bot->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
my_bot->GetSpellTypeAEOrGroupTargetCount(spellType)
).c_str()
);
}
else {
my_bot->SetSpellTypeAEOrGroupTargetCount(spellType, typeValue);
++success_count;
}
}
if (!current_check) {
if (success_count == 1 && first_found) {
c->Message(
Chat::Green,
fmt::format(
"{} says, 'My [{}] target count was set to [{}].'",
first_found->GetCleanName(),
c->GetSpellTypeNameByID(spellType),
first_found->GetSpellTypeAEOrGroupTargetCount(spellType)
).c_str()
);
}
else {
c->Message(
Chat::Green,
fmt::format(
"{} of your bots set their [{}] target count to [{}].",
success_count,
c->GetSpellTypeNameByID(spellType),
typeValue
).c_str()
);
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ void bot_command_suspend(Client *c, const Seperator *sep)
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([actionable: <any>] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_NoFilter;
+13 -6
View File
@@ -2,12 +2,15 @@
void bot_command_taunt(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
@@ -15,26 +18,30 @@ void bot_command_taunt(Client *c, const Seperator *sep)
bool taunt_state = false;
bool toggle_taunt = true;
int ab_arg = 1;
if (!arg1.compare("on")) {
taunt_state = true;
toggle_taunt = false;
ab_arg = 2;
++ab_arg;
}
else if (!arg1.compare("off")) {
toggle_taunt = false;
ab_arg = 2;
++ab_arg;
}
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
int taunting_count = 0;
+7 -2
View File
@@ -2,10 +2,12 @@
void bot_command_timer(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer"))
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer")) {
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] [actionable].", sep->arg[0]);
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name])).", sep->arg[0]);
c->Message(Chat::White, "When setting, you can leave the value blank to use the default for the item or specify a value in ms to set the timer to.");
c->Message(Chat::White, "Returns or sets the provided timer(s) for the selected bot(s) or clears the selected timer(s) for the selected bot(s).");
return;
@@ -88,14 +90,17 @@ void bot_command_timer(Client* c, const Seperator* sep)
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::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], 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.remove(nullptr);
for (auto my_bot : sbl) {