mirror of
https://github.com/EQEmu/Server.git
synced 2026-08-30 22:06:46 +00:00
Implement blocked_buffs and blocked_pet_buffs
This commit is contained in:
+181
-8
@@ -108,6 +108,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
|
||||
GenerateAppearance();
|
||||
GenerateBaseStats();
|
||||
bot_timers.clear();
|
||||
bot_blocked_buffs.clear();
|
||||
|
||||
// Calculate HitPoints Last As It Uses Base Stats
|
||||
current_hp = GenerateBaseHitPoints();
|
||||
@@ -247,13 +248,16 @@ Bot::Bot(
|
||||
GenerateBaseStats();
|
||||
|
||||
bot_timers.clear();
|
||||
|
||||
database.botdb.LoadTimers(this);
|
||||
|
||||
LoadDefaultBotSettings();
|
||||
|
||||
database.botdb.LoadBotSettings(this);
|
||||
|
||||
if (RuleB(Bots, AllowBotBlockedBuffs)) {
|
||||
bot_blocked_buffs.clear();
|
||||
database.botdb.LoadBotBlockedBuffs(this);
|
||||
}
|
||||
|
||||
LoadAAs();
|
||||
|
||||
if (database.botdb.LoadBuffs(this)) {
|
||||
@@ -1374,6 +1378,10 @@ bool Bot::Save()
|
||||
database.botdb.SaveStance(this);
|
||||
database.botdb.SaveBotSettings(this);
|
||||
|
||||
if (RuleB(Bots, AllowBotBlockedBuffs)) {
|
||||
database.botdb.SaveBotBlockedBuffs(this);
|
||||
}
|
||||
|
||||
if (!SavePet())
|
||||
bot_owner->Message(Chat::White, "Failed to save pet for '%s'", GetCleanName());
|
||||
|
||||
@@ -1439,6 +1447,10 @@ bool Bot::DeleteBot()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!database.botdb.DeleteBotBlockedBuffs(GetBotID())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!database.botdb.DeleteBot(GetBotID())) {
|
||||
return false;
|
||||
}
|
||||
@@ -9573,11 +9585,22 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spellType, bool doPrechec
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsBeneficialSpell(spell_id) && tar->IsBlockedBuff(spell_id)) {
|
||||
LogBotPreChecks("{} says, 'Cancelling cast of {} on {} due to IsBlockedBuff.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
|
||||
if (RuleB(Spells, EnableBlockedBuffs) && IsBeneficialSpell(spell_id) && tar->IsClient() && tar->IsBlockedBuff(spell_id)) {
|
||||
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to IsBlockedBuff.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RuleB(Bots, AllowBotBlockedBuffs) && IsBeneficialSpell(spell_id)) {
|
||||
if (tar->IsBot() && tar->IsBlockedBuff(spell_id)) {
|
||||
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to IsBlockedBuff.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
|
||||
return false;
|
||||
}
|
||||
else if (tar->IsPet() && tar->GetOwner() && tar->GetOwner()->IsBot() && tar->GetOwner()->IsBlockedPetBuff(spell_id)) {
|
||||
LogBotPreChecksDetail("{} says, 'Cancelling cast of {} on {} due to IsBlockedPetBuff.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LogBotPreChecksDetail("{} says, 'Doing CanCastSpellType checks of {} on {}.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); //deleteme
|
||||
if (!CanCastSpellType(spellType, spell_id, tar)) {
|
||||
return false;
|
||||
@@ -11887,7 +11910,7 @@ bool Bot::IsValidSpellTypeSubType(uint16 spellType, uint16 subType, uint16 spell
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case CommandedSubTypes::InvisAnimals:
|
||||
if (IsEffectInSpell(spell_id, SE_InvisVsAnimals) || IsEffectInSpell(spell_id, SE_ImprovedInvisAnimals)) {
|
||||
return true;
|
||||
@@ -11898,7 +11921,7 @@ bool Bot::IsValidSpellTypeSubType(uint16 spellType, uint16 subType, uint16 spell
|
||||
if (
|
||||
(IsEffectInSpell(spell_id, SE_ModelSize) && CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) < 100) ||
|
||||
(IsEffectInSpell(spell_id, SE_ChangeHeight) && CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) < 100)
|
||||
) {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11907,7 +11930,7 @@ bool Bot::IsValidSpellTypeSubType(uint16 spellType, uint16 subType, uint16 spell
|
||||
if (
|
||||
(IsEffectInSpell(spell_id, SE_ModelSize) && CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) > 100) ||
|
||||
(IsEffectInSpell(spell_id, SE_ChangeHeight) && CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) > 100)
|
||||
) {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11945,7 +11968,7 @@ uint16 Bot::GetSpellByAA(int id, AA::Rank*& rank) {
|
||||
if (!points || !rank) {
|
||||
LogTestDebug("{}: {} says, 'No {} found'", __LINE__, GetCleanName(), (!points ? "points" : "rank")); //deleteme
|
||||
return spell_id;
|
||||
}
|
||||
}
|
||||
|
||||
spell_id = rank->spell;
|
||||
|
||||
@@ -11953,3 +11976,153 @@ uint16 Bot::GetSpellByAA(int id, AA::Rank*& rank) {
|
||||
|
||||
return spell_id;
|
||||
}
|
||||
|
||||
void Bot::SetBotBlockedBuff(uint16 spell_id, bool block) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
OwnerMessage("Failed to set blocked buff.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bot_blocked_buffs.empty()) {
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < bot_blocked_buffs.size(); i++) {
|
||||
if (bot_blocked_buffs[i].spell_id != spell_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bot_blocked_buffs[i].blocked = block;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
BotBlockedBuffs_Struct t;
|
||||
|
||||
t.spell_id = spell_id;
|
||||
t.blocked = block;
|
||||
|
||||
bot_blocked_buffs.push_back(t);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
BotBlockedBuffs_Struct t;
|
||||
|
||||
t.spell_id = spell_id;
|
||||
t.blocked = block;
|
||||
|
||||
bot_blocked_buffs.push_back(t);
|
||||
}
|
||||
|
||||
CleanBotBlockedBuffs();
|
||||
}
|
||||
|
||||
bool Bot::IsBlockedBuff(int32 spell_id)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
OwnerMessage("Failed to get blocked buff.");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CleanBotBlockedBuffs();
|
||||
|
||||
if (!bot_blocked_buffs.empty()) {
|
||||
for (int i = 0; i < bot_blocked_buffs.size(); i++) {
|
||||
if (bot_blocked_buffs[i].spell_id != spell_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return bot_blocked_buffs[i].blocked;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Bot::SetBotBlockedPetBuff(uint16 spell_id, bool block) {
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
OwnerMessage("Failed to set blocked pet buff.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bot_blocked_buffs.empty()) {
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < bot_blocked_buffs.size(); i++) {
|
||||
if (bot_blocked_buffs[i].spell_id != spell_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bot_blocked_buffs[i].blocked_pet = block;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
BotBlockedBuffs_Struct t;
|
||||
|
||||
t.spell_id = spell_id;
|
||||
t.blocked_pet = block;
|
||||
|
||||
bot_blocked_buffs.push_back(t);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BotBlockedBuffs_Struct t;
|
||||
|
||||
t.spell_id = spell_id;
|
||||
t.blocked_pet = block;
|
||||
|
||||
bot_blocked_buffs.push_back(t);
|
||||
}
|
||||
|
||||
CleanBotBlockedBuffs();
|
||||
}
|
||||
|
||||
bool Bot::IsBlockedPetBuff(int32 spell_id)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
OwnerMessage("Failed to get blocked pet buff.");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CleanBotBlockedBuffs();
|
||||
|
||||
if (!bot_blocked_buffs.empty()) {
|
||||
for (int i = 0; i < bot_blocked_buffs.size(); i++) {
|
||||
if (bot_blocked_buffs[i].spell_id != spell_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return bot_blocked_buffs[i].blocked_pet;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Bot::CleanBotBlockedBuffs()
|
||||
{
|
||||
if (!bot_blocked_buffs.empty()) {
|
||||
int current = 0;
|
||||
int end = bot_blocked_buffs.size();
|
||||
|
||||
while (current < end) {
|
||||
if (!IsValidSpell(bot_blocked_buffs[current].spell_id) || (bot_blocked_buffs[current].blocked == 0 && bot_blocked_buffs[current].blocked_pet == 0)) {
|
||||
bot_blocked_buffs.erase(bot_blocked_buffs.begin() + current);
|
||||
}
|
||||
else {
|
||||
current++;
|
||||
}
|
||||
|
||||
end = bot_blocked_buffs.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,6 +478,12 @@ public:
|
||||
void SetBotSpellRecastTimer(uint16 spellType, Mob* spelltar, bool preCast = false);
|
||||
BotSpell GetSpellByHealType(uint16 spellType, Mob* tar);
|
||||
uint16 GetSpellByAA(int id, AA::Rank* &rank);
|
||||
void CleanBotBlockedBuffs();
|
||||
void ClearBotBlockedBuffs() { bot_blocked_buffs.clear(); }
|
||||
bool IsBlockedBuff(int32 spell_id) override; //TODO bot rewrite - fix these to call from mob.h
|
||||
bool IsBlockedPetBuff(int32 spell_id) override; //TODO bot rewrite - fix these to call from mob.h
|
||||
void SetBotBlockedBuff(uint16 spell_id, bool block);
|
||||
void SetBotBlockedPetBuff(uint16 spell_id, bool block);
|
||||
|
||||
std::string GetBotSpellCategoryName(uint8 setting_type);
|
||||
std::string GetBotSettingCategoryName(uint8 setting_type);
|
||||
@@ -882,6 +888,8 @@ public:
|
||||
bool DeleteBot();
|
||||
std::vector<BotTimer_Struct> GetBotTimers() { return bot_timers; }
|
||||
void SetBotTimers(std::vector<BotTimer_Struct> timers) { bot_timers = timers; }
|
||||
std::vector<BotBlockedBuffs_Struct> GetBotBlockedBuffs() { return bot_blocked_buffs; }
|
||||
void SetBotBlockedBuffs(std::vector<BotBlockedBuffs_Struct> blockedBuff) { bot_blocked_buffs = blockedBuff; }
|
||||
uint32 GetLastZoneID() const { return _lastZoneId; }
|
||||
int32 GetBaseAC() const { return _baseAC; }
|
||||
int32 GetBaseATK() const { return _baseATK; }
|
||||
@@ -1010,6 +1018,7 @@ protected:
|
||||
std::vector<BotSpells_Struct> AIBot_spells;
|
||||
std::vector<BotSpells_Struct> AIBot_spells_enforced;
|
||||
std::vector<BotTimer_Struct> bot_timers;
|
||||
std::vector<BotBlockedBuffs_Struct> bot_blocked_buffs;
|
||||
|
||||
private:
|
||||
// Class Members
|
||||
|
||||
@@ -1251,6 +1251,8 @@ int bot_command_init(void)
|
||||
bot_command_add("applypoison", "Applies cursor-held poison to a rogue bot's weapon", AccountStatus::Player, bot_command_apply_poison) ||
|
||||
bot_command_add("attack", "Orders bots to attack a designated target", AccountStatus::Player, bot_command_attack) ||
|
||||
bot_command_add("behindmob", "Toggles whether or not your bot tries to stay behind a mob", AccountStatus::Player, bot_command_behind_mob) ||
|
||||
bot_command_add("blockedbuffs", "Set, view and clear blocked buffs for the selected bot(s)", AccountStatus::Player, bot_command_blocked_buffs) ||
|
||||
bot_command_add("blockedpetbuffs", "Set, view and clear blocked pet buffs for the selected bot(s)", AccountStatus::Player, bot_command_blocked_pet_buffs) ||
|
||||
bot_command_add("bot", "Lists the available bot management [subcommands]", AccountStatus::Player, bot_command_bot) ||
|
||||
bot_command_add("botappearance", "Lists the available bot appearance [subcommands]", AccountStatus::Player, bot_command_appearance) ||
|
||||
bot_command_add("botbeardcolor", "Changes the beard color of a bot", AccountStatus::Player, bot_command_beard_color) ||
|
||||
@@ -2216,6 +2218,7 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) {
|
||||
#include "bot_commands/apply_potion.cpp"
|
||||
#include "bot_commands/attack.cpp"
|
||||
#include "bot_commands/behind_mob.cpp"
|
||||
#include "bot_commands/blocked_buffs.cpp"
|
||||
#include "bot_commands/bot.cpp"
|
||||
#include "bot_commands/bot_settings.cpp"
|
||||
#include "bot_commands/cast.cpp"
|
||||
|
||||
@@ -1669,6 +1669,8 @@ void bot_command_apply_poison(Client *c, const Seperator *sep);
|
||||
void bot_command_apply_potion(Client* c, const Seperator* sep);
|
||||
void bot_command_attack(Client *c, const Seperator *sep);
|
||||
void bot_command_behind_mob(Client* c, const Seperator* sep);
|
||||
void bot_command_blocked_buffs(Client* c, const Seperator* sep);
|
||||
void bot_command_blocked_pet_buffs(Client* c, const Seperator* sep);
|
||||
void bot_command_bot(Client *c, const Seperator *sep);
|
||||
void bot_command_bot_settings(Client* c, const Seperator* sep);
|
||||
void bot_command_cast(Client* c, const Seperator* sep);
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
#include "../bot_command.h"
|
||||
|
||||
void bot_command_blocked_buffs(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (!RuleB(Bots, AllowBotBlockedBuffs)) {
|
||||
c->Message(Chat::Yellow, "This command is disabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Allows you to set, view and wipe blocked buffs for the selected bots"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- You can 'set' spells to be blocked, 'remove' spells from the blocked list, 'list' the current blocked spells or 'wipe' the entire list."
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [add [ID] | remove [ID] | list | wipe] [actionable, default: target]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To add Courage (Spell ID #202) to the targeted bot's blocked list:",
|
||||
fmt::format(
|
||||
"{} add 202",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To view the targeted bot's blocked buff list:",
|
||||
fmt::format(
|
||||
"{} list",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To wipe all Warriors bots' blocked buff list:",
|
||||
fmt::format(
|
||||
"{} wipe byclass {}",
|
||||
sep->arg[0],
|
||||
Class::Warrior
|
||||
)
|
||||
};
|
||||
|
||||
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(
|
||||
"You can also control bot buffs ({}).",
|
||||
Saylink::Silent("^blockedbuffs help", "^blockedbuffs")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (RuleB(Bots, SendClassRaceOnHelp)) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool add = false;
|
||||
bool remove = false;
|
||||
bool list = false;
|
||||
bool wipe = false;
|
||||
uint16 spell_id;
|
||||
|
||||
//AA help
|
||||
if (!arg1.compare("add")) {
|
||||
if (!sep->IsNumber(2) || !IsValidSpell(atoi(sep->arg[2]))) {
|
||||
c->Message(Chat::Yellow, "You must enter a valid spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
add = true;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("remove")) {
|
||||
if (!sep->IsNumber(2) || !IsValidSpell(atoi(sep->arg[2]))) {
|
||||
c->Message(Chat::Yellow, "You must enter a valid spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
remove = true;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("list")) {
|
||||
list = true;
|
||||
}
|
||||
else if (!arg1.compare("wipe")) {
|
||||
wipe = 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 actionableArg = sep->arg[ab_arg];
|
||||
|
||||
if (actionableArg.empty()) {
|
||||
actionableArg = "target";
|
||||
}
|
||||
|
||||
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, actionableArg, sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
bool isSuccess = false;
|
||||
uint16 successCount = 0;
|
||||
Bot* firstFound = nullptr;
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter->IsInGroupOrRaid(c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!firstFound) {
|
||||
firstFound = bot_iter;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
bot_iter->SetBotBlockedBuff(spell_id, true);
|
||||
}
|
||||
else if (remove) {
|
||||
bot_iter->SetBotBlockedBuff(spell_id, false);
|
||||
}
|
||||
else if (list) {
|
||||
std::vector<BotBlockedBuffs_Struct> blockedBuffs = bot_iter->GetBotBlockedBuffs();
|
||||
bool found = false;
|
||||
|
||||
if (!blockedBuffs.empty()) {
|
||||
for (auto& blocked_buff : blockedBuffs) {
|
||||
if (blocked_buff.blocked == 1 && IsValidSpell(blocked_buff.spell_id)) {
|
||||
found = true;
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, '{} [#{}] is currently blocked.'",
|
||||
bot_iter->GetCleanName(),
|
||||
spells[blocked_buff.spell_id].name,
|
||||
blocked_buff.spell_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, 'I am not currently blocking any buffs.'",
|
||||
bot_iter->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (wipe) {
|
||||
bot_iter->ClearBotBlockedBuffs();
|
||||
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, I have wiped my blocked buffs list.'",
|
||||
bot_iter->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
isSuccess = true;
|
||||
++successCount;
|
||||
}
|
||||
|
||||
if (!isSuccess) {
|
||||
c->Message(Chat::Yellow, "No bots were selected.");
|
||||
}
|
||||
else {
|
||||
if (add || remove) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} {} {} blocking {} [#{}]",
|
||||
((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())),
|
||||
((successCount == 1 && firstFound) ? "is" : "of your bots"),
|
||||
(add ? "now" : "no longer"),
|
||||
spells[spell_id].name,
|
||||
spell_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bot_command_blocked_pet_buffs(Client* c, const Seperator* sep)
|
||||
{
|
||||
if (!RuleB(Bots, AllowBotBlockedBuffs)) {
|
||||
c->Message(Chat::Yellow, "This command is disabled.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||
std::vector<std::string> description =
|
||||
{
|
||||
"Allows you to set, view and wipe blocked pet buffs for the selected bots"
|
||||
};
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- You can 'set' spells to be blocked, 'remove' spells from the blocked list, 'list' the current blocked spells or 'wipe' the entire list.",
|
||||
"- This controls whether or not any pet the selected bot(s) own will prevent certain buffs from being cast."
|
||||
};
|
||||
|
||||
std::vector<std::string> example_format =
|
||||
{
|
||||
fmt::format(
|
||||
"{} [add [ID] | remove [ID] | list | wipe] [actionable, default: target]"
|
||||
, sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_one =
|
||||
{
|
||||
"To add Courage (Spell ID #202) to the targeted bot's blocked list:",
|
||||
fmt::format(
|
||||
"{} add 202",
|
||||
sep->arg[0],
|
||||
c->GetSpellTypeShortNameByID(BotSpellTypes::Nuke)
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_two =
|
||||
{
|
||||
"To view the targeted bot's blocked buff list:",
|
||||
fmt::format(
|
||||
"{} list",
|
||||
sep->arg[0]
|
||||
)
|
||||
};
|
||||
std::vector<std::string> examples_three =
|
||||
{
|
||||
"To wipe all Warriors bots' blocked buff list:",
|
||||
fmt::format(
|
||||
"{} wipe byclass {}",
|
||||
sep->arg[0],
|
||||
Class::Warrior
|
||||
)
|
||||
};
|
||||
|
||||
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(
|
||||
"You can also control pet buffs ({}).",
|
||||
Saylink::Silent("^blockedpetbuffs help", "^blockedpetbuffs")
|
||||
).c_str()
|
||||
);
|
||||
|
||||
if (RuleB(Bots, SendClassRaceOnHelp)) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"Use {} for information about race/class IDs.",
|
||||
Saylink::Silent("^classracelist")
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::string arg1 = sep->arg[1];
|
||||
std::string arg2 = sep->arg[2];
|
||||
int ab_arg = 2;
|
||||
bool add = false;
|
||||
bool remove = false;
|
||||
bool list = false;
|
||||
bool wipe = false;
|
||||
uint16 spell_id;
|
||||
|
||||
//AA help
|
||||
if (!arg1.compare("add")) {
|
||||
if (!sep->IsNumber(2) || !IsValidSpell(atoi(sep->arg[2]))) {
|
||||
c->Message(Chat::Yellow, "You must enter a valid spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
add = true;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("remove")) {
|
||||
if (!sep->IsNumber(2) || !IsValidSpell(atoi(sep->arg[2]))) {
|
||||
c->Message(Chat::Yellow, "You must enter a valid spell ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
remove = true;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
++ab_arg;
|
||||
}
|
||||
else if (!arg1.compare("list")) {
|
||||
list = true;
|
||||
}
|
||||
else if (!arg1.compare("wipe")) {
|
||||
wipe = 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 actionableArg = sep->arg[ab_arg];
|
||||
|
||||
if (actionableArg.empty()) {
|
||||
actionableArg = "target";
|
||||
}
|
||||
|
||||
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, actionableArg, sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
|
||||
return;
|
||||
}
|
||||
|
||||
sbl.remove(nullptr);
|
||||
|
||||
bool isSuccess = false;
|
||||
uint16 successCount = 0;
|
||||
Bot* firstFound = nullptr;
|
||||
|
||||
for (auto bot_iter : sbl) {
|
||||
if (!bot_iter->IsInGroupOrRaid(c)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!firstFound) {
|
||||
firstFound = bot_iter;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
bot_iter->SetBotBlockedPetBuff(spell_id, true);
|
||||
}
|
||||
else if (remove) {
|
||||
bot_iter->SetBotBlockedPetBuff(spell_id, false);
|
||||
}
|
||||
else if (list) {
|
||||
std::vector<BotBlockedBuffs_Struct> blockedBuffs = bot_iter->GetBotBlockedBuffs();
|
||||
bool found = false;
|
||||
|
||||
if (!blockedBuffs.empty()) {
|
||||
for (auto& blocked_buff : blockedBuffs) {
|
||||
if (blocked_buff.blocked_pet == 1 && IsValidSpell(blocked_buff.spell_id)) {
|
||||
found = true;
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, '{} [#{}] is currently blocked for my pet.'",
|
||||
bot_iter->GetCleanName(),
|
||||
spells[blocked_buff.spell_id].name,
|
||||
blocked_buff.spell_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, 'I am not currently blocking any pet buffs.'",
|
||||
bot_iter->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (wipe) {
|
||||
bot_iter->ClearBotBlockedBuffs();
|
||||
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} says, I have wiped my blocked buffs list.'",
|
||||
bot_iter->GetCleanName()
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
isSuccess = true;
|
||||
++successCount;
|
||||
}
|
||||
|
||||
if (!isSuccess) {
|
||||
c->Message(Chat::Yellow, "No bots were selected.");
|
||||
}
|
||||
else {
|
||||
if (add || remove) {
|
||||
c->Message(
|
||||
Chat::Yellow,
|
||||
fmt::format(
|
||||
"{} {} {} blocking {} [#{}] on their pet.",
|
||||
((successCount == 1 && firstFound) ? firstFound->GetCleanName() : (fmt::format("{}", successCount).c_str())),
|
||||
((successCount == 1 && firstFound) ? "is" : "of your bots"),
|
||||
(add ? "now" : "no longer"),
|
||||
spells[spell_id].name,
|
||||
spell_id
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ void bot_command_cast(Client* c, const Seperator* sep)
|
||||
|
||||
std::vector<std::string> notes =
|
||||
{
|
||||
"- This will interrupt any spell currently being cast by bots told to use the command.",
|
||||
"- 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",
|
||||
fmt::format(
|
||||
"- You can use {} aa # to cast any clickable AA or specifically {} harmtouch / {} layonhands"
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "../common/strings.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
#include "../common/repositories/bot_blocked_buffs_repository.h"
|
||||
#include "../common/repositories/bot_buffs_repository.h"
|
||||
#include "../common/repositories/bot_create_combinations_repository.h"
|
||||
#include "../common/repositories/bot_data_repository.h"
|
||||
@@ -2403,3 +2404,110 @@ bool BotDatabase::DeleteBotSettings(const uint32 bot_id)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::LoadBotBlockedBuffs(Bot* b)
|
||||
{
|
||||
if (!b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& l = BotBlockedBuffsRepository::GetWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`bot_id` = {}",
|
||||
b->GetBotID()
|
||||
)
|
||||
);
|
||||
|
||||
std::vector<BotBlockedBuffs_Struct> v;
|
||||
|
||||
BotBlockedBuffs_Struct t{ };
|
||||
|
||||
for (const auto& e : l) {
|
||||
t.spell_id = e.spell_id;
|
||||
t.blocked = e.blocked;
|
||||
t.blocked_pet = e.blocked_pet;
|
||||
|
||||
v.push_back(t);
|
||||
}
|
||||
|
||||
if (!v.empty()) {
|
||||
b->SetBotBlockedBuffs(v);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::SaveBotBlockedBuffs(Bot* b)
|
||||
{
|
||||
if (!b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DeleteBotBlockedBuffs(b->GetBotID())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<BotBlockedBuffs_Struct> v = b->GetBotBlockedBuffs();
|
||||
|
||||
if (v.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<BotBlockedBuffsRepository::BotBlockedBuffs> l;
|
||||
|
||||
if (!v.empty()) {
|
||||
for (auto& blocked_buff : v) {
|
||||
if (blocked_buff.blocked == 0 && blocked_buff.blocked_pet == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto e = BotBlockedBuffsRepository::BotBlockedBuffs{
|
||||
.bot_id = b->GetBotID(),
|
||||
.spell_id = blocked_buff.spell_id,
|
||||
.blocked = blocked_buff.blocked,
|
||||
.blocked_pet = blocked_buff.blocked_pet
|
||||
};
|
||||
|
||||
l.push_back(e);
|
||||
}
|
||||
|
||||
if (l.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BotBlockedBuffsRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`bot_id` = {}",
|
||||
b->GetBotID()
|
||||
)
|
||||
);
|
||||
|
||||
const int inserted = BotBlockedBuffsRepository::InsertMany(database, l);
|
||||
|
||||
if (!inserted) {
|
||||
DeleteBotBlockedBuffs(b->GetBotID());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BotDatabase::DeleteBotBlockedBuffs(const uint32 bot_id)
|
||||
{
|
||||
if (!bot_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BotBlockedBuffsRepository::DeleteWhere(
|
||||
database,
|
||||
fmt::format(
|
||||
"`bot_id` = {}",
|
||||
bot_id
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ public:
|
||||
bool SaveTimers(Bot* b);
|
||||
bool DeleteTimers(const uint32 bot_id);
|
||||
|
||||
bool LoadBotBlockedBuffs(Bot* b);
|
||||
bool SaveBotBlockedBuffs(Bot* b);
|
||||
bool DeleteBotBlockedBuffs(const uint32 bot_id);
|
||||
|
||||
/* Bot inventory functions */
|
||||
bool QueryInventoryCount(const uint32 bot_id, uint32& item_count);
|
||||
|
||||
@@ -97,4 +97,11 @@ struct BotSpellTypeOrder {
|
||||
uint16 priority;
|
||||
};
|
||||
|
||||
struct BotBlockedBuffs_Struct {
|
||||
uint32_t bot_id;
|
||||
uint32_t spell_id;
|
||||
uint8_t blocked;
|
||||
uint8_t blocked_pet;
|
||||
};
|
||||
|
||||
#endif // BOT_STRUCTS
|
||||
|
||||
+4
-1
@@ -4080,7 +4080,10 @@ bool Mob::SpellOnTarget(
|
||||
}
|
||||
|
||||
// now check if the spell is allowed to land
|
||||
if (RuleB(Spells, EnableBlockedBuffs)) {
|
||||
if (
|
||||
(!spelltar->IsBot() && RuleB(Spells, EnableBlockedBuffs)) ||
|
||||
(spelltar->IsBot() && RuleB(Bots, AllowBotBlockedBuffs))
|
||||
) {
|
||||
// We return true here since the caster's client should act like normal
|
||||
if (spelltar->IsBlockedBuff(spell_id)) {
|
||||
LogSpells(
|
||||
|
||||
Reference in New Issue
Block a user