mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-10 02:31:03 +00:00
Implement blocked_buffs and blocked_pet_buffs
This commit is contained in:
@@ -1178,6 +1178,25 @@ WHERE NOT EXISTS
|
||||
(SELECT *
|
||||
FROM spells_new
|
||||
WHERE bot_spells_entries.spell_id = spells_new.id);
|
||||
)"
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9052,
|
||||
.description = "2024_12_15_bot_blocked_buffs.sql",
|
||||
.check = "SHOW TABLES LIKE 'bot_blocked_buffs'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
CREATE TABLE `bot_blocked_buffs` (
|
||||
`bot_id` INT(11) UNSIGNED NOT NULL,
|
||||
`spell_id` INT(11) UNSIGNED NOT NULL,
|
||||
`blocked` TINYINT(4) UNSIGNED NULL DEFAULT '0',
|
||||
`blocked_pet` TINYINT(4) UNSIGNED NULL DEFAULT '0',
|
||||
PRIMARY KEY (`bot_id`, `spell_id`) USING BTREE
|
||||
)
|
||||
COLLATE='latin1_swedish_ci'
|
||||
ENGINE=InnoDB
|
||||
;
|
||||
)"
|
||||
}
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
/**
|
||||
* DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://docs.eqemu.io/developer/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
#define EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../strings.h"
|
||||
#include <ctime>
|
||||
|
||||
class BaseBotBlockedBuffsRepository {
|
||||
public:
|
||||
struct BotBlockedBuffs {
|
||||
uint32_t bot_id;
|
||||
uint32_t spell_id;
|
||||
uint8_t blocked;
|
||||
uint8_t blocked_pet;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("bot_id");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"bot_id",
|
||||
"spell_id",
|
||||
"blocked",
|
||||
"blocked_pet",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> SelectColumns()
|
||||
{
|
||||
return {
|
||||
"bot_id",
|
||||
"spell_id",
|
||||
"blocked",
|
||||
"blocked_pet",
|
||||
};
|
||||
}
|
||||
|
||||
static std::string ColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", Columns()));
|
||||
}
|
||||
|
||||
static std::string SelectColumnsRaw()
|
||||
{
|
||||
return std::string(Strings::Implode(", ", SelectColumns()));
|
||||
}
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("bot_blocked_buffs");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
{
|
||||
return fmt::format(
|
||||
"SELECT {} FROM {}",
|
||||
SelectColumnsRaw(),
|
||||
TableName()
|
||||
);
|
||||
}
|
||||
|
||||
static std::string BaseInsert()
|
||||
{
|
||||
return fmt::format(
|
||||
"INSERT INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static BotBlockedBuffs NewEntity()
|
||||
{
|
||||
BotBlockedBuffs e{};
|
||||
|
||||
e.bot_id = 0;
|
||||
e.spell_id = 0;
|
||||
e.blocked = 0;
|
||||
e.blocked_pet = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static BotBlockedBuffs GetBotBlockedBuffs(
|
||||
const std::vector<BotBlockedBuffs> &bot_blocked_buffss,
|
||||
int bot_blocked_buffs_id
|
||||
)
|
||||
{
|
||||
for (auto &bot_blocked_buffs : bot_blocked_buffss) {
|
||||
if (bot_blocked_buffs.bot_id == bot_blocked_buffs_id) {
|
||||
return bot_blocked_buffs;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static BotBlockedBuffs FindOne(
|
||||
Database& db,
|
||||
int bot_blocked_buffs_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {} = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
PrimaryKey(),
|
||||
bot_blocked_buffs_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
BotBlockedBuffs e{};
|
||||
|
||||
e.bot_id = row[0] ? static_cast<uint32_t>(atoi(row[0])) : 0;
|
||||
e.spell_id = row[1] ? static_cast<uint32_t>(atoi(row[1])) : 0;
|
||||
e.blocked = row[2] ? static_cast<uint8_t>(atoi(row[2])) : 0;
|
||||
e.blocked_pet = row[3] ? static_cast<uint8_t>(atoi(row[3])) : 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int bot_blocked_buffs_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
bot_blocked_buffs_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
const BotBlockedBuffs &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
|
||||
v.push_back(columns[1] + " = " + std::to_string(e.spell_id));
|
||||
v.push_back(columns[2] + " = " + std::to_string(e.blocked));
|
||||
v.push_back(columns[3] + " = " + std::to_string(e.blocked_pet));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"UPDATE {} SET {} WHERE {} = {}",
|
||||
TableName(),
|
||||
Strings::Implode(", ", v),
|
||||
PrimaryKey(),
|
||||
e.bot_id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static BotBlockedBuffs InsertOne(
|
||||
Database& db,
|
||||
BotBlockedBuffs e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.blocked));
|
||||
v.push_back(std::to_string(e.blocked_pet));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
e.bot_id = results.LastInsertedID();
|
||||
return e;
|
||||
}
|
||||
|
||||
e = NewEntity();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
const std::vector<BotBlockedBuffs> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.blocked));
|
||||
v.push_back(std::to_string(e.blocked_pet));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<BotBlockedBuffs> All(Database& db)
|
||||
{
|
||||
std::vector<BotBlockedBuffs> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{}",
|
||||
BaseSelect()
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotBlockedBuffs e{};
|
||||
|
||||
e.bot_id = row[0] ? static_cast<uint32_t>(atoi(row[0])) : 0;
|
||||
e.spell_id = row[1] ? static_cast<uint32_t>(atoi(row[1])) : 0;
|
||||
e.blocked = row[2] ? static_cast<uint8_t>(atoi(row[2])) : 0;
|
||||
e.blocked_pet = row[3] ? static_cast<uint8_t>(atoi(row[3])) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<BotBlockedBuffs> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<BotBlockedBuffs> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE {}",
|
||||
BaseSelect(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
BotBlockedBuffs e{};
|
||||
|
||||
e.bot_id = row[0] ? static_cast<uint32_t>(atoi(row[0])) : 0;
|
||||
e.spell_id = row[1] ? static_cast<uint32_t>(atoi(row[1])) : 0;
|
||||
e.blocked = row[2] ? static_cast<uint8_t>(atoi(row[2])) : 0;
|
||||
e.blocked_pet = row[3] ? static_cast<uint8_t>(atoi(row[3])) : 0;
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"DELETE FROM {} WHERE {}",
|
||||
TableName(),
|
||||
where_filter
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int Truncate(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"TRUNCATE TABLE {}",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int64 GetMaxId(Database& db)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COALESCE(MAX({}), 0) FROM {}",
|
||||
PrimaryKey(),
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static int64 Count(Database& db, const std::string &where_filter = "")
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT COUNT(*) FROM {} {}",
|
||||
TableName(),
|
||||
(where_filter.empty() ? "" : "WHERE " + where_filter)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
|
||||
}
|
||||
|
||||
static std::string BaseReplace()
|
||||
{
|
||||
return fmt::format(
|
||||
"REPLACE INTO {} ({}) ",
|
||||
TableName(),
|
||||
ColumnsRaw()
|
||||
);
|
||||
}
|
||||
|
||||
static int ReplaceOne(
|
||||
Database& db,
|
||||
const BotBlockedBuffs &e
|
||||
)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.blocked));
|
||||
v.push_back(std::to_string(e.blocked_pet));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES ({})",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", v)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int ReplaceMany(
|
||||
Database& db,
|
||||
const std::vector<BotBlockedBuffs> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> v;
|
||||
|
||||
v.push_back(std::to_string(e.bot_id));
|
||||
v.push_back(std::to_string(e.spell_id));
|
||||
v.push_back(std::to_string(e.blocked));
|
||||
v.push_back(std::to_string(e.blocked_pet));
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseReplace(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
#define EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../strings.h"
|
||||
#include "base/base_bot_blocked_buffs_repository.h"
|
||||
|
||||
class BotBlockedBuffsRepository: public BaseBotBlockedBuffsRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* BotBlockedBuffsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* BotBlockedBuffsRepository::GetWhereNeverExpires()
|
||||
* BotBlockedBuffsRepository::GetWhereXAndY()
|
||||
* BotBlockedBuffsRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H
|
||||
@@ -891,6 +891,7 @@ RULE_BOOL(Bots, AllowCommandedLull, true, "If enabled bots can be commanded to l
|
||||
RULE_INT(Bots, CampTimer, 25, "Number of seconds after /camp has begun before bots camp out.")
|
||||
RULE_BOOL(Bots, SendClassRaceOnHelp, true, "If enabled a reminder of how to check class/race IDs will be sent when using compatible commands.")
|
||||
RULE_BOOL(Bots, AllowCrossGroupRaidAssist, true, "If enabled bots will autodefend group or raid members set as main assist.")
|
||||
RULE_BOOL(Bots, AllowBotBlockedBuffs, true, "If enabled, you can create blocked buffs for each bot and for their pets.")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Chat)
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9286
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9051 //TODO bot rewrite
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9052 //TODO bot rewrite
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+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