mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
[Bots] Add Bot-specific Spell Settings. (#2553)
* [Bots] Add Bot-specific Spell Settings. # Notes - Allows players to set `priority`, `min_level`, `max_level`, `min_hp`, `max_hp`, and `is_enabled` settings per spell based on targeted bot. - Lets players disable spells they don't want their bots casting or change the criteria they cast them at if they want. * Update botspellsai.cpp * Update 2022_11_19_bot_spell_settings.sql * Typo. * Update botspellsai.cpp * Cleanup and add Reload Methods to Perl/Lua.
This commit is contained in:
parent
f6c5560e9c
commit
2d364e2fd1
@ -403,6 +403,7 @@ namespace DatabaseSchema {
|
|||||||
"bot_pet_inventories",
|
"bot_pet_inventories",
|
||||||
"bot_pets",
|
"bot_pets",
|
||||||
"bot_spell_casting_chances",
|
"bot_spell_casting_chances",
|
||||||
|
"bot_spell_settings",
|
||||||
"bot_spells_entries",
|
"bot_spells_entries",
|
||||||
"bot_stances",
|
"bot_stances",
|
||||||
"bot_timers",
|
"bot_timers",
|
||||||
|
|||||||
403
common/repositories/base/base_bot_spell_settings_repository.h
Normal file
403
common/repositories/base/base_bot_spell_settings_repository.h
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
/**
|
||||||
|
* 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://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
|
#define EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../../database.h"
|
||||||
|
#include "../../strings.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
class BaseBotSpellSettingsRepository {
|
||||||
|
public:
|
||||||
|
struct BotSpellSettings {
|
||||||
|
uint32_t id;
|
||||||
|
int32_t bot_id;
|
||||||
|
int16_t spell_id;
|
||||||
|
int16_t priority;
|
||||||
|
uint16_t min_level;
|
||||||
|
uint16_t max_level;
|
||||||
|
int16_t min_hp;
|
||||||
|
int16_t max_hp;
|
||||||
|
uint8_t is_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::string PrimaryKey()
|
||||||
|
{
|
||||||
|
return std::string("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> Columns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"bot_id",
|
||||||
|
"spell_id",
|
||||||
|
"priority",
|
||||||
|
"min_level",
|
||||||
|
"max_level",
|
||||||
|
"min_hp",
|
||||||
|
"max_hp",
|
||||||
|
"is_enabled",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SelectColumns()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
"id",
|
||||||
|
"bot_id",
|
||||||
|
"spell_id",
|
||||||
|
"priority",
|
||||||
|
"min_level",
|
||||||
|
"max_level",
|
||||||
|
"min_hp",
|
||||||
|
"max_hp",
|
||||||
|
"is_enabled",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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_spell_settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseSelect()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"SELECT {} FROM {}",
|
||||||
|
SelectColumnsRaw(),
|
||||||
|
TableName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BaseInsert()
|
||||||
|
{
|
||||||
|
return fmt::format(
|
||||||
|
"INSERT INTO {} ({}) ",
|
||||||
|
TableName(),
|
||||||
|
ColumnsRaw()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BotSpellSettings NewEntity()
|
||||||
|
{
|
||||||
|
BotSpellSettings e{};
|
||||||
|
|
||||||
|
e.id = 0;
|
||||||
|
e.bot_id = 0;
|
||||||
|
e.spell_id = 0;
|
||||||
|
e.priority = 0;
|
||||||
|
e.min_level = 0;
|
||||||
|
e.max_level = 255;
|
||||||
|
e.min_hp = 0;
|
||||||
|
e.max_hp = 0;
|
||||||
|
e.is_enabled = 1;
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BotSpellSettings GetBotSpellSettings(
|
||||||
|
const std::vector<BotSpellSettings> &bot_spell_settingss,
|
||||||
|
int bot_spell_settings_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (auto &bot_spell_settings : bot_spell_settingss) {
|
||||||
|
if (bot_spell_settings.id == bot_spell_settings_id) {
|
||||||
|
return bot_spell_settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static BotSpellSettings FindOne(
|
||||||
|
Database& db,
|
||||||
|
int bot_spell_settings_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} WHERE id = {} LIMIT 1",
|
||||||
|
BaseSelect(),
|
||||||
|
bot_spell_settings_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
auto row = results.begin();
|
||||||
|
if (results.RowCount() == 1) {
|
||||||
|
BotSpellSettings e{};
|
||||||
|
|
||||||
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
|
e.bot_id = static_cast<int32_t>(atoi(row[1]));
|
||||||
|
e.spell_id = static_cast<int16_t>(atoi(row[2]));
|
||||||
|
e.priority = static_cast<int16_t>(atoi(row[3]));
|
||||||
|
e.min_level = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
|
||||||
|
e.max_level = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
|
||||||
|
e.min_hp = static_cast<int16_t>(atoi(row[6]));
|
||||||
|
e.max_hp = static_cast<int16_t>(atoi(row[7]));
|
||||||
|
e.is_enabled = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int DeleteOne(
|
||||||
|
Database& db,
|
||||||
|
int bot_spell_settings_id
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
PrimaryKey(),
|
||||||
|
bot_spell_settings_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int UpdateOne(
|
||||||
|
Database& db,
|
||||||
|
const BotSpellSettings &e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[0] + " = " + std::to_string(e.id));
|
||||||
|
v.push_back(columns[1] + " = " + std::to_string(e.bot_id));
|
||||||
|
v.push_back(columns[2] + " = " + std::to_string(e.spell_id));
|
||||||
|
v.push_back(columns[3] + " = " + std::to_string(e.priority));
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.min_level));
|
||||||
|
v.push_back(columns[5] + " = " + std::to_string(e.max_level));
|
||||||
|
v.push_back(columns[6] + " = " + std::to_string(e.min_hp));
|
||||||
|
v.push_back(columns[7] + " = " + std::to_string(e.max_hp));
|
||||||
|
v.push_back(columns[8] + " = " + std::to_string(e.is_enabled));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE {} = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
PrimaryKey(),
|
||||||
|
e.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? results.RowsAffected() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BotSpellSettings InsertOne(
|
||||||
|
Database& db,
|
||||||
|
BotSpellSettings e
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
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.priority));
|
||||||
|
v.push_back(std::to_string(e.min_level));
|
||||||
|
v.push_back(std::to_string(e.max_level));
|
||||||
|
v.push_back(std::to_string(e.min_hp));
|
||||||
|
v.push_back(std::to_string(e.max_hp));
|
||||||
|
v.push_back(std::to_string(e.is_enabled));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{} VALUES ({})",
|
||||||
|
BaseInsert(),
|
||||||
|
Strings::Implode(",", v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.Success()) {
|
||||||
|
e.id = results.LastInsertedID();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = NewEntity();
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int InsertMany(
|
||||||
|
Database& db,
|
||||||
|
const std::vector<BotSpellSettings> &entries
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::vector<std::string> insert_chunks;
|
||||||
|
|
||||||
|
for (auto &e: entries) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
v.push_back(std::to_string(e.id));
|
||||||
|
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.priority));
|
||||||
|
v.push_back(std::to_string(e.min_level));
|
||||||
|
v.push_back(std::to_string(e.max_level));
|
||||||
|
v.push_back(std::to_string(e.min_hp));
|
||||||
|
v.push_back(std::to_string(e.max_hp));
|
||||||
|
v.push_back(std::to_string(e.is_enabled));
|
||||||
|
|
||||||
|
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<BotSpellSettings> All(Database& db)
|
||||||
|
{
|
||||||
|
std::vector<BotSpellSettings> all_entries;
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"{}",
|
||||||
|
BaseSelect()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
all_entries.reserve(results.RowCount());
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
BotSpellSettings e{};
|
||||||
|
|
||||||
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
|
e.bot_id = static_cast<int32_t>(atoi(row[1]));
|
||||||
|
e.spell_id = static_cast<int16_t>(atoi(row[2]));
|
||||||
|
e.priority = static_cast<int16_t>(atoi(row[3]));
|
||||||
|
e.min_level = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
|
||||||
|
e.max_level = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
|
||||||
|
e.min_hp = static_cast<int16_t>(atoi(row[6]));
|
||||||
|
e.max_hp = static_cast<int16_t>(atoi(row[7]));
|
||||||
|
e.is_enabled = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
|
||||||
|
|
||||||
|
all_entries.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<BotSpellSettings> GetWhere(Database& db, const std::string &where_filter)
|
||||||
|
{
|
||||||
|
std::vector<BotSpellSettings> 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) {
|
||||||
|
BotSpellSettings e{};
|
||||||
|
|
||||||
|
e.id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||||
|
e.bot_id = static_cast<int32_t>(atoi(row[1]));
|
||||||
|
e.spell_id = static_cast<int16_t>(atoi(row[2]));
|
||||||
|
e.priority = static_cast<int16_t>(atoi(row[3]));
|
||||||
|
e.min_level = static_cast<uint16_t>(strtoul(row[4], nullptr, 10));
|
||||||
|
e.max_level = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
|
||||||
|
e.min_hp = static_cast<int16_t>(atoi(row[6]));
|
||||||
|
e.max_hp = static_cast<int16_t>(atoi(row[7]));
|
||||||
|
e.is_enabled = static_cast<uint8_t>(strtoul(row[8], nullptr, 10));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
77
common/repositories/bot_spell_settings_repository.h
Normal file
77
common/repositories/bot_spell_settings_repository.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#ifndef EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
|
#define EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "../database.h"
|
||||||
|
#include "../strings.h"
|
||||||
|
#include "base/base_bot_spell_settings_repository.h"
|
||||||
|
|
||||||
|
class BotSpellSettingsRepository: public BaseBotSpellSettingsRepository {
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* BotSpellSettingsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||||
|
* BotSpellSettingsRepository::GetWhereNeverExpires()
|
||||||
|
* BotSpellSettingsRepository::GetWhereXAndY()
|
||||||
|
* BotSpellSettingsRepository::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
|
||||||
|
|
||||||
|
static bool UpdateSpellSetting(
|
||||||
|
Database& db,
|
||||||
|
const BotSpellSettings &e
|
||||||
|
) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
auto columns = Columns();
|
||||||
|
|
||||||
|
v.push_back(columns[3] + " = " + std::to_string(e.priority));
|
||||||
|
v.push_back(columns[4] + " = " + std::to_string(e.min_level));
|
||||||
|
v.push_back(columns[5] + " = " + std::to_string(e.max_level));
|
||||||
|
v.push_back(columns[6] + " = " + std::to_string(e.min_hp));
|
||||||
|
v.push_back(columns[7] + " = " + std::to_string(e.max_hp));
|
||||||
|
v.push_back(columns[8] + " = " + std::to_string(e.is_enabled));
|
||||||
|
|
||||||
|
auto results = db.QueryDatabase(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE {} SET {} WHERE `bot_id` = {} AND `spell_id` = {}",
|
||||||
|
TableName(),
|
||||||
|
Strings::Implode(", ", v),
|
||||||
|
e.bot_id,
|
||||||
|
e.spell_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (results.Success() ? true : false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H
|
||||||
@ -37,7 +37,7 @@
|
|||||||
#define CURRENT_BINARY_DATABASE_VERSION 9212
|
#define CURRENT_BINARY_DATABASE_VERSION 9212
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9032
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9033
|
||||||
#else
|
#else
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
9030|2022_10_27_bot_data_buckets.sql|SHOW COLUMNS FROM `bot_spells_entries` LIKE 'bucket_name'|empty|
|
9030|2022_10_27_bot_data_buckets.sql|SHOW COLUMNS FROM `bot_spells_entries` LIKE 'bucket_name'|empty|
|
||||||
9031|2022_11_13_bot_spells_entries.sql|SELECT * FROM db_version WHERE bots_version >= 9031|empty|
|
9031|2022_11_13_bot_spells_entries.sql|SELECT * FROM db_version WHERE bots_version >= 9031|empty|
|
||||||
9032|2022_11_07_bot_expansion_bitmask.sql|SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'|empty|
|
9032|2022_11_07_bot_expansion_bitmask.sql|SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'|empty|
|
||||||
|
9033|2022_11_19_bot_spell_settings.sql|SHOW TABLES LIKE 'bot_spell_settings'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE `bot_spell_settings` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`bot_id` int(11) NOT NULL DEFAULT 0,
|
||||||
|
`spell_id` smallint(5) NOT NULL DEFAULT 0,
|
||||||
|
`priority` smallint(5) NOT NULL DEFAULT 0,
|
||||||
|
`min_level` smallint(5) unsigned NOT NULL DEFAULT 0,
|
||||||
|
`max_level` smallint(5) unsigned NOT NULL DEFAULT 255,
|
||||||
|
`min_hp` smallint(5) NOT NULL DEFAULT 0,
|
||||||
|
`max_hp` smallint(5) NOT NULL DEFAULT 0,
|
||||||
|
`is_enabled` tinyint(1) unsigned NOT NULL DEFAULT 1,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
316
zone/bot.cpp
316
zone/bot.cpp
@ -25,6 +25,7 @@
|
|||||||
#include "lua_parser.h"
|
#include "lua_parser.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
#include "../common/say_link.h"
|
#include "../common/say_link.h"
|
||||||
|
#include "../common/repositories/bot_spell_settings_repository.h"
|
||||||
|
|
||||||
extern volatile bool is_zone_loaded;
|
extern volatile bool is_zone_loaded;
|
||||||
|
|
||||||
@ -407,6 +408,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
|||||||
|
|
||||||
GetBotOwnerDataBuckets();
|
GetBotOwnerDataBuckets();
|
||||||
GetBotDataBuckets();
|
GetBotDataBuckets();
|
||||||
|
LoadBotSpellSettings();
|
||||||
AI_AddBotSpells(GetBotSpellID());
|
AI_AddBotSpells(GetBotSpellID());
|
||||||
|
|
||||||
CalcBotStats(false);
|
CalcBotStats(false);
|
||||||
@ -10538,18 +10540,24 @@ bool Bot::GetBotOwnerDataBuckets()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = fmt::format(
|
const auto query = fmt::format(
|
||||||
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
|
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
|
||||||
Strings::Escape(bot_owner->GetBucketKey())
|
Strings::Escape(bot_owner->GetBucketKey())
|
||||||
);
|
);
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
|
|
||||||
if (!results.Success() || !results.RowCount()) {
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bot_owner_data_buckets.clear();
|
||||||
|
|
||||||
|
if (!results.RowCount()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto row : results) {
|
for (auto row : results) {
|
||||||
bot_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
|
bot_owner_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -10557,16 +10565,22 @@ bool Bot::GetBotOwnerDataBuckets()
|
|||||||
|
|
||||||
bool Bot::GetBotDataBuckets()
|
bool Bot::GetBotDataBuckets()
|
||||||
{
|
{
|
||||||
auto query = fmt::format(
|
const auto query = fmt::format(
|
||||||
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
|
"SELECT `key`, `value` FROM data_buckets WHERE `key` LIKE '{}-%'",
|
||||||
Strings::Escape(GetBucketKey())
|
Strings::Escape(GetBucketKey())
|
||||||
);
|
);
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
|
|
||||||
if (!results.Success() || !results.RowCount()) {
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bot_data_buckets.clear();
|
||||||
|
|
||||||
|
if (!results.RowCount()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto row : results) {
|
for (auto row : results) {
|
||||||
bot_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
|
bot_data_buckets.insert(std::pair<std::string,std::string>(row[0], row[1]));
|
||||||
}
|
}
|
||||||
@ -10591,7 +10605,7 @@ bool Bot::CheckDataBucket(std::string bucket_name, std::string bucket_value, uin
|
|||||||
bucket_name
|
bucket_name
|
||||||
);
|
);
|
||||||
|
|
||||||
player_value = bot_data_buckets[full_name];
|
player_value = bot_owner_data_buckets[full_name];
|
||||||
if (player_value.empty()) {
|
if (player_value.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -10635,6 +10649,292 @@ void Bot::SetExpansionBitmask(int expansion_bitmask, bool save)
|
|||||||
LoadAAs();
|
LoadAAs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Bot::AddBotSpellSetting(uint16 spell_id, BotSpellSetting* bs)
|
||||||
|
{
|
||||||
|
if (!IsValidSpell(spell_id) || !bs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto obs = GetBotSpellSetting(spell_id);
|
||||||
|
if (obs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s = BotSpellSettingsRepository::NewEntity();
|
||||||
|
|
||||||
|
s.spell_id = spell_id;
|
||||||
|
s.bot_id = GetBotID();
|
||||||
|
|
||||||
|
s.priority = bs->priority;
|
||||||
|
s.min_level = bs->min_level;
|
||||||
|
s.max_level = bs->max_level;
|
||||||
|
s.min_hp = bs->min_hp;
|
||||||
|
s.max_hp = bs->max_hp;
|
||||||
|
s.is_enabled = bs->is_enabled;
|
||||||
|
|
||||||
|
const auto& nbs = BotSpellSettingsRepository::InsertOne(content_db, s);
|
||||||
|
if (!nbs.id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBotSpellSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::DeleteBotSpellSetting(uint16 spell_id)
|
||||||
|
{
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bs = GetBotSpellSetting(spell_id);
|
||||||
|
if (!bs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BotSpellSettingsRepository::DeleteWhere(
|
||||||
|
content_db,
|
||||||
|
fmt::format(
|
||||||
|
"bot_id = {} AND spell_id = {}",
|
||||||
|
GetBotID(),
|
||||||
|
spell_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
LoadBotSpellSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BotSpellSetting* Bot::GetBotSpellSetting(uint16 spell_id)
|
||||||
|
{
|
||||||
|
if (!IsValidSpell(spell_id) || !bot_spell_settings.count(spell_id)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto b = bot_spell_settings.find(spell_id);
|
||||||
|
if (b != bot_spell_settings.end()) {
|
||||||
|
return &b->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bot::ListBotSpells()
|
||||||
|
{
|
||||||
|
auto bot_owner = GetBotOwner();
|
||||||
|
if (!bot_owner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AIBot_spells.empty()) {
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} has no AI Spells.",
|
||||||
|
GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spell_count = 0;
|
||||||
|
auto spell_number = 1;
|
||||||
|
|
||||||
|
for (const auto& s : AIBot_spells) {
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell {} | Spell: {} ({})",
|
||||||
|
spell_number,
|
||||||
|
spells[s.spellid].name,
|
||||||
|
s.spellid
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell {} | Priority: {} Health: {}",
|
||||||
|
spell_number,
|
||||||
|
s.priority,
|
||||||
|
GetHPString(s.min_hp, s.max_hp)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
spell_count++;
|
||||||
|
spell_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} has {} AI Spell{}.",
|
||||||
|
GetCleanName(),
|
||||||
|
spell_count,
|
||||||
|
spell_count != 1 ? "s" :""
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bot::ListBotSpellSettings()
|
||||||
|
{
|
||||||
|
auto bot_owner = GetBotOwner();
|
||||||
|
if (!bot_owner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bot_spell_settings.size()) {
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} does not have any spell settings.",
|
||||||
|
GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto setting_count = 0;
|
||||||
|
auto setting_number = 1;
|
||||||
|
|
||||||
|
for (const auto& bs : bot_spell_settings) {
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Setting {} | Spell: {} ({}) Enabled: {}",
|
||||||
|
setting_number,
|
||||||
|
spells[bs.first].name,
|
||||||
|
bs.first,
|
||||||
|
bs.second.is_enabled ? "Yes" : "No"
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Setting {} | Priority: {} Levels: {} Health: {}",
|
||||||
|
setting_number,
|
||||||
|
bs.second.priority,
|
||||||
|
GetLevelString(bs.second.min_level, bs.second.max_level),
|
||||||
|
GetHPString(bs.second.min_hp, bs.second.max_hp)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
setting_count++;
|
||||||
|
setting_number++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bot_owner->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} has {} spell setting{}.",
|
||||||
|
GetCleanName(),
|
||||||
|
setting_count,
|
||||||
|
setting_count != 1 ? "s" : ""
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bot::LoadBotSpellSettings()
|
||||||
|
{
|
||||||
|
bot_spell_settings.clear();
|
||||||
|
|
||||||
|
auto s = BotSpellSettingsRepository::GetWhere(content_db, fmt::format("bot_id = {}", GetBotID()));
|
||||||
|
if (s.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : s) {
|
||||||
|
BotSpellSetting b;
|
||||||
|
|
||||||
|
b.priority = e.priority;
|
||||||
|
b.min_level = e.min_level;
|
||||||
|
b.max_level = e.max_level;
|
||||||
|
b.min_hp = e.min_hp;
|
||||||
|
b.max_hp = e.max_hp;
|
||||||
|
b.is_enabled = e.is_enabled;
|
||||||
|
|
||||||
|
bot_spell_settings[e.spell_id] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs)
|
||||||
|
{
|
||||||
|
if (!IsValidSpell(spell_id) || !bs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s = BotSpellSettingsRepository::NewEntity();
|
||||||
|
|
||||||
|
s.spell_id = spell_id;
|
||||||
|
s.bot_id = GetBotID();
|
||||||
|
s.priority = bs->priority;
|
||||||
|
s.min_level = bs->min_level;
|
||||||
|
s.max_level = bs->max_level;
|
||||||
|
s.min_hp = bs->min_hp;
|
||||||
|
s.max_hp = bs->max_hp;
|
||||||
|
s.is_enabled = bs->is_enabled;
|
||||||
|
|
||||||
|
auto obs = GetBotSpellSetting(spell_id);
|
||||||
|
if (!obs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BotSpellSettingsRepository::UpdateSpellSetting(content_db, s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadBotSpellSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Bot::GetLevelString(uint8 min_level, uint8 max_level)
|
||||||
|
{
|
||||||
|
std::string level_string = "Any";
|
||||||
|
if (min_level && max_level) {
|
||||||
|
level_string = fmt::format(
|
||||||
|
"{} to {}",
|
||||||
|
min_level,
|
||||||
|
max_level
|
||||||
|
);
|
||||||
|
} else if (min_level && !max_level) {
|
||||||
|
level_string = fmt::format(
|
||||||
|
"{}+",
|
||||||
|
min_level
|
||||||
|
);
|
||||||
|
} else if (!min_level && max_level) {
|
||||||
|
level_string = fmt::format(
|
||||||
|
"1 to {}",
|
||||||
|
max_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return level_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Bot::GetHPString(int8 min_hp, int8 max_hp)
|
||||||
|
{
|
||||||
|
std::string hp_string = "Any";
|
||||||
|
if (min_hp && max_hp) {
|
||||||
|
hp_string = fmt::format(
|
||||||
|
"{}%% to {}%%",
|
||||||
|
min_hp,
|
||||||
|
max_hp
|
||||||
|
);
|
||||||
|
} else if (min_hp && !max_hp) {
|
||||||
|
hp_string = fmt::format(
|
||||||
|
"{}%% to 100%%",
|
||||||
|
min_hp
|
||||||
|
);
|
||||||
|
} else if (!min_hp && max_hp) {
|
||||||
|
hp_string = fmt::format(
|
||||||
|
"1%% to {}%%",
|
||||||
|
max_hp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hp_string;
|
||||||
|
}
|
||||||
|
|
||||||
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };
|
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
zone/bot.h
18
zone/bot.h
@ -307,7 +307,7 @@ public:
|
|||||||
void DoEnduranceRegen(); //This Regenerates endurance
|
void DoEnduranceRegen(); //This Regenerates endurance
|
||||||
void DoEnduranceUpkeep(); //does the endurance upkeep
|
void DoEnduranceUpkeep(); //does the endurance upkeep
|
||||||
|
|
||||||
bool AI_AddBotSpells(uint32 iDBSpellsID);
|
bool AI_AddBotSpells(uint32 bot_spell_id);
|
||||||
void AddSpellToBotList(
|
void AddSpellToBotList(
|
||||||
int16 iPriority,
|
int16 iPriority,
|
||||||
uint16 iSpellID,
|
uint16 iSpellID,
|
||||||
@ -470,6 +470,7 @@ public:
|
|||||||
//static void UpdateRaidCastingRoles(const Raid* raid, bool disband = false);
|
//static void UpdateRaidCastingRoles(const Raid* raid, bool disband = false);
|
||||||
|
|
||||||
bool IsBotCaster() { return IsCasterClass(GetClass()); }
|
bool IsBotCaster() { return IsCasterClass(GetClass()); }
|
||||||
|
bool IsBotHybrid() { return IsHybridClass(GetClass()); }
|
||||||
bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); }
|
bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); }
|
||||||
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
|
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
|
||||||
bool IsBotSpellFighter() { return IsSpellFighterClass(GetClass()); }
|
bool IsBotSpellFighter() { return IsSpellFighterClass(GetClass()); }
|
||||||
@ -596,6 +597,18 @@ public:
|
|||||||
int GetExpansionBitmask();
|
int GetExpansionBitmask();
|
||||||
void SetExpansionBitmask(int expansion_bitmask, bool save = true);
|
void SetExpansionBitmask(int expansion_bitmask, bool save = true);
|
||||||
|
|
||||||
|
void ListBotSpells();
|
||||||
|
|
||||||
|
std::string GetLevelString(uint8 min_level, uint8 max_level);
|
||||||
|
std::string GetHPString(int8 min_hp, int8 max_hp);
|
||||||
|
|
||||||
|
bool AddBotSpellSetting(uint16 spell_id, BotSpellSetting* bs);
|
||||||
|
bool DeleteBotSpellSetting(uint16 spell_id);
|
||||||
|
BotSpellSetting* GetBotSpellSetting(uint16 spell_id);
|
||||||
|
void ListBotSpellSettings();
|
||||||
|
void LoadBotSpellSettings();
|
||||||
|
bool UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs);
|
||||||
|
|
||||||
static void SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id);
|
static void SpawnBotGroupByName(Client* c, std::string botgroup_name, uint32 leader_id);
|
||||||
|
|
||||||
std::string CreateSayLink(Client* botOwner, const char* message, const char* name);
|
std::string CreateSayLink(Client* botOwner, const char* message, const char* name);
|
||||||
@ -762,6 +775,9 @@ private:
|
|||||||
|
|
||||||
BotCastingRoles m_CastingRoles;
|
BotCastingRoles m_CastingRoles;
|
||||||
std::map<std::string,std::string> bot_data_buckets;
|
std::map<std::string,std::string> bot_data_buckets;
|
||||||
|
std::map<std::string,std::string> bot_owner_data_buckets;
|
||||||
|
|
||||||
|
std::map<uint16, BotSpellSetting> bot_spell_settings;
|
||||||
|
|
||||||
std::shared_ptr<HealRotation> m_member_of_heal_rotation;
|
std::shared_ptr<HealRotation> m_member_of_heal_rotation;
|
||||||
|
|
||||||
|
|||||||
@ -1416,6 +1416,12 @@ int bot_command_init(void)
|
|||||||
bot_command_add("rune", "Orders a bot to cast a rune of protection", AccountStatus::Player, bot_command_rune) ||
|
bot_command_add("rune", "Orders a bot to cast a rune of protection", AccountStatus::Player, bot_command_rune) ||
|
||||||
bot_command_add("sendhome", "Orders a bot to open a magical doorway home", AccountStatus::Player, bot_command_send_home) ||
|
bot_command_add("sendhome", "Orders a bot to open a magical doorway home", AccountStatus::Player, bot_command_send_home) ||
|
||||||
bot_command_add("size", "Orders a bot to change a player's size", AccountStatus::Player, bot_command_size) ||
|
bot_command_add("size", "Orders a bot to change a player's size", AccountStatus::Player, bot_command_size) ||
|
||||||
|
bot_command_add("spelllist", "Lists a Caster of Hybrid bot's spells", AccountStatus::Player, bot_command_spell_list) ||
|
||||||
|
bot_command_add("spellsettingsadd", "Add a bot spell setting for a Caster or Hybrid bot", AccountStatus::Player, bot_command_spell_settings_add) ||
|
||||||
|
bot_command_add("spellsettingsdelete", "Delete a bot spell setting from a Caster or Hybrid bot", AccountStatus::Player, bot_command_spell_settings_delete) ||
|
||||||
|
bot_command_add("spellsettingslist", "Lists a Caster or Hybrid bot's spell settings", AccountStatus::Player, bot_command_spell_settings_list) ||
|
||||||
|
bot_command_add("spellsettingstoggle", "Toggle a bot spell for a Caster or Hybrid bot", AccountStatus::Player, bot_command_spell_settings_toggle) ||
|
||||||
|
bot_command_add("spellsettingsupdate", "Update a bot spell setting for a Caster or Hybrid bot", AccountStatus::Player, bot_command_spell_settings_update) ||
|
||||||
bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) ||
|
bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) ||
|
||||||
bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) ||
|
bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) ||
|
||||||
bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) ||
|
bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) ||
|
||||||
@ -10086,7 +10092,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
|||||||
if (local_entry->single != single_flag) {
|
if (local_entry->single != single_flag) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = fmt::format(
|
msg = fmt::format(
|
||||||
"{}circle {}{}",
|
"{}circle {}{}",
|
||||||
std::to_string(BOT_COMMAND_CHAR),
|
std::to_string(BOT_COMMAND_CHAR),
|
||||||
@ -10122,7 +10128,7 @@ void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_b
|
|||||||
if (local_entry->single != single_flag) {
|
if (local_entry->single != single_flag) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = fmt::format(
|
msg = fmt::format(
|
||||||
"{}portal {}{}",
|
"{}portal {}{}",
|
||||||
std::to_string(BOT_COMMAND_CHAR),
|
std::to_string(BOT_COMMAND_CHAR),
|
||||||
@ -10226,4 +10232,514 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_list(Client* c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_list", sep->arg[0], "spelllist")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Priority] [Min Level] [Max Level] [Min HP] [Max HP]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->ListBotSpells();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_settings_add(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_settings_add", sep->arg[0], "spellsettingsadd")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Priority] [Min Level] [Max Level] [Min HP] [Max HP]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arguments = sep->argnum;
|
||||||
|
if (
|
||||||
|
arguments < 6 ||
|
||||||
|
!sep->IsNumber(1) ||
|
||||||
|
!sep->IsNumber(2) ||
|
||||||
|
!sep->IsNumber(3) ||
|
||||||
|
!sep->IsNumber(4) ||
|
||||||
|
!sep->IsNumber(5) ||
|
||||||
|
!sep->IsNumber(6)
|
||||||
|
) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Priority] [Min Level] [Max Level] [Min HP] [Max HP]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spell_id = static_cast<uint16>(std::stoul(sep->arg[1]));
|
||||||
|
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell ID {} is invalid or could not be found.",
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_bot->GetBotSpellSetting(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"{} already has a spell setting for {} ({}), trying using {} instead.",
|
||||||
|
my_bot->GetCleanName(),
|
||||||
|
spells[spell_id].name,
|
||||||
|
spell_id,
|
||||||
|
Saylink::Silent("^spellsettingsupdate")
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto priority = static_cast<int16>(std::stoi(sep->arg[2]));
|
||||||
|
auto min_level = static_cast<uint8>(std::stoul(sep->arg[3]));
|
||||||
|
auto max_level = static_cast<uint8>(std::stoul(sep->arg[4]));
|
||||||
|
auto min_hp = static_cast<int8>(EQ::Clamp(std::stoi(sep->arg[5]), -1, 99));
|
||||||
|
auto max_hp = static_cast<int8>(EQ::Clamp(std::stoi(sep->arg[6]), -1, 100));
|
||||||
|
|
||||||
|
BotSpellSetting bs;
|
||||||
|
|
||||||
|
bs.priority = priority;
|
||||||
|
bs.min_level = min_level;
|
||||||
|
bs.max_level = max_level;
|
||||||
|
bs.min_hp = min_hp;
|
||||||
|
bs.max_hp = max_hp;
|
||||||
|
|
||||||
|
if (!my_bot->UpdateBotSpellSetting(spell_id, &bs)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Failed to add spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->AI_AddBotSpells(my_bot->GetBotSpellID());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Successfully added spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell Setting Added | Spell: {} ({}) ",
|
||||||
|
spells[spell_id].name,
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell Setting Added | Priority: {} Levels: {} Health: {}",
|
||||||
|
priority,
|
||||||
|
my_bot->GetLevelString(min_level, max_level),
|
||||||
|
my_bot->GetHPString(min_hp, max_hp)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_settings_delete(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_settings_delete", sep->arg[0], "spellsettingsdelete")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arguments = sep->argnum;
|
||||||
|
if (
|
||||||
|
arguments < 1 ||
|
||||||
|
!sep->IsNumber(1)
|
||||||
|
) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spell_id = static_cast<uint16>(std::stoul(sep->arg[1]));
|
||||||
|
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell ID {} is invalid or could not be found.",
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!my_bot->DeleteBotSpellSetting(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Failed to delete spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->AI_AddBotSpells(my_bot->GetBotSpellID());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Successfully deleted spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell Setting Deleted | Spell: {} ({})",
|
||||||
|
spells[spell_id].name,
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_settings_list(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_settings_list", sep->arg[0], "spellsettingslist")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {}",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->ListBotSpellSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_settings_toggle(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_settings_toggle", sep->arg[0], "spellsettingstoggle")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Toggle]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arguments = sep->argnum;
|
||||||
|
if (
|
||||||
|
arguments < 2 ||
|
||||||
|
!sep->IsNumber(1)
|
||||||
|
) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Toggle]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spell_id = static_cast<uint16>(std::stoul(sep->arg[1]));
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell ID {} is invalid or could not be found.",
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool toggle = (
|
||||||
|
sep->IsNumber(2) ?
|
||||||
|
(std::stoi(sep->arg[2]) ? true : false) :
|
||||||
|
atobool(sep->arg[2])
|
||||||
|
);
|
||||||
|
|
||||||
|
auto obs = my_bot->GetBotSpellSetting(spell_id);
|
||||||
|
if (!obs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BotSpellSetting bs;
|
||||||
|
|
||||||
|
bs.priority = obs->priority;
|
||||||
|
bs.min_level = obs->min_level;
|
||||||
|
bs.max_level = obs->max_level;
|
||||||
|
bs.min_hp = obs->min_hp;
|
||||||
|
bs.max_hp = obs->max_hp;
|
||||||
|
bs.is_enabled = toggle;
|
||||||
|
|
||||||
|
if (!my_bot->UpdateBotSpellSetting(spell_id, &bs)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Failed to {}able spell for {}.",
|
||||||
|
toggle ? "en" : "dis",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->AI_AddBotSpells(my_bot->GetBotSpellID());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Successfully {}abled spell for {}.",
|
||||||
|
toggle ? "en" : "dis",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell {}abled | Spell: {} ({})",
|
||||||
|
toggle ? "En" : "Dis",
|
||||||
|
spells[spell_id].name,
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bot_command_spell_settings_update(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
if (helper_command_alias_fail(c, "bot_command_spell_settings_update", sep->arg[0], "spellsettingsupdate")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Priority] [Min Level] [Max Level] [Min HP] [Max HP]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
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 (!my_bot->IsBotCaster() && !my_bot->IsBotHybrid()) {
|
||||||
|
c->Message(Chat::White, "You must target a Caster or Hybrid bot to use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arguments = sep->argnum;
|
||||||
|
if (
|
||||||
|
arguments < 6 ||
|
||||||
|
!sep->IsNumber(1) ||
|
||||||
|
!sep->IsNumber(2) ||
|
||||||
|
!sep->IsNumber(3) ||
|
||||||
|
!sep->IsNumber(4) ||
|
||||||
|
!sep->IsNumber(5) ||
|
||||||
|
!sep->IsNumber(6)
|
||||||
|
) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Usage: {} [Spell ID] [Priority] [Min Level] [Max Level] [Min HP] [Max HP]",
|
||||||
|
sep->arg[0]
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spell_id = static_cast<uint16>(std::stoul(sep->arg[1]));
|
||||||
|
|
||||||
|
if (!IsValidSpell(spell_id)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell ID {} is invalid or could not be found.",
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto priority = static_cast<int16>(std::stoi(sep->arg[2]));
|
||||||
|
auto min_level = static_cast<uint8>(std::stoul(sep->arg[3]));
|
||||||
|
auto max_level = static_cast<uint8>(std::stoul(sep->arg[4]));
|
||||||
|
auto min_hp = static_cast<int8>(EQ::Clamp(std::stoi(sep->arg[5]), -1, 99));
|
||||||
|
auto max_hp = static_cast<int8>(EQ::Clamp(std::stoi(sep->arg[6]), -1, 100));
|
||||||
|
|
||||||
|
BotSpellSetting bs;
|
||||||
|
|
||||||
|
bs.priority = priority;
|
||||||
|
bs.min_level = min_level;
|
||||||
|
bs.max_level = max_level;
|
||||||
|
bs.min_hp = min_hp;
|
||||||
|
bs.max_hp = max_hp;
|
||||||
|
|
||||||
|
if (!my_bot->UpdateBotSpellSetting(spell_id, &bs)) {
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Failed to update spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bot->AI_AddBotSpells(my_bot->GetBotSpellID());
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Successfully updated spell setting for {}.",
|
||||||
|
my_bot->GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell Setting Updated | Spell: {} ({})",
|
||||||
|
spells[spell_id].name,
|
||||||
|
spell_id
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
c->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Spell Setting Updated | Priority: {} Levels: {} Health: {}",
|
||||||
|
priority,
|
||||||
|
my_bot->GetLevelString(min_level, max_level),
|
||||||
|
my_bot->GetHPString(min_hp, max_hp)
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BOTS
|
#endif // BOTS
|
||||||
|
|||||||
@ -526,7 +526,6 @@ typedef std::map<BCEnum::SpType, std::map<uint8, std::string>> bcst_required_bot
|
|||||||
typedef std::map<uint8, uint8> bcst_levels;
|
typedef std::map<uint8, uint8> bcst_levels;
|
||||||
typedef std::map<BCEnum::SpType, bcst_levels> bcst_levels_map;
|
typedef std::map<BCEnum::SpType, bcst_levels> bcst_levels_map;
|
||||||
|
|
||||||
|
|
||||||
#define BOT_COMMAND_CHAR '^'
|
#define BOT_COMMAND_CHAR '^'
|
||||||
|
|
||||||
typedef void (*BotCmdFuncPtr)(Client *,const Seperator *);
|
typedef void (*BotCmdFuncPtr)(Client *,const Seperator *);
|
||||||
@ -540,8 +539,7 @@ typedef struct {
|
|||||||
extern int (*bot_command_dispatch)(Client *,char const*);
|
extern int (*bot_command_dispatch)(Client *,char const*);
|
||||||
extern int bot_command_count; // number of bot commands loaded
|
extern int bot_command_count; // number of bot commands loaded
|
||||||
|
|
||||||
|
// Bot Command System:
|
||||||
// the bot command system:
|
|
||||||
int bot_command_init(void);
|
int bot_command_init(void);
|
||||||
void bot_command_deinit(void);
|
void bot_command_deinit(void);
|
||||||
int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function);
|
int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function);
|
||||||
@ -549,8 +547,7 @@ int bot_command_not_avail(Client *c, const char *message);
|
|||||||
int bot_command_real_dispatch(Client *c, char const *message);
|
int bot_command_real_dispatch(Client *c, char const *message);
|
||||||
void bot_command_log_command(Client *c, const char *message);
|
void bot_command_log_command(Client *c, const char *message);
|
||||||
|
|
||||||
|
// Bot Commands
|
||||||
// bot commands
|
|
||||||
void bot_command_actionable(Client *c, const Seperator *sep);
|
void bot_command_actionable(Client *c, const Seperator *sep);
|
||||||
void bot_command_aggressive(Client *c, const Seperator *sep);
|
void bot_command_aggressive(Client *c, const Seperator *sep);
|
||||||
void bot_command_apply_poison(Client *c, const Seperator *sep);
|
void bot_command_apply_poison(Client *c, const Seperator *sep);
|
||||||
@ -589,6 +586,12 @@ void bot_command_resurrect(Client *c, const Seperator *sep);
|
|||||||
void bot_command_rune(Client *c, const Seperator *sep);
|
void bot_command_rune(Client *c, const Seperator *sep);
|
||||||
void bot_command_send_home(Client *c, const Seperator *sep);
|
void bot_command_send_home(Client *c, const Seperator *sep);
|
||||||
void bot_command_size(Client *c, const Seperator *sep);
|
void bot_command_size(Client *c, const Seperator *sep);
|
||||||
|
void bot_command_spell_list(Client* c, const Seperator *sep);
|
||||||
|
void bot_command_spell_settings_add(Client* c, const Seperator *sep);
|
||||||
|
void bot_command_spell_settings_delete(Client* c, const Seperator *sep);
|
||||||
|
void bot_command_spell_settings_list(Client* c, const Seperator *sep);
|
||||||
|
void bot_command_spell_settings_toggle(Client* c, const Seperator *sep);
|
||||||
|
void bot_command_spell_settings_update(Client* c, const Seperator *sep);
|
||||||
void bot_command_summon_corpse(Client *c, const Seperator *sep);
|
void bot_command_summon_corpse(Client *c, const Seperator *sep);
|
||||||
void bot_command_suspend(Client *c, const Seperator *sep);
|
void bot_command_suspend(Client *c, const Seperator *sep);
|
||||||
void bot_command_taunt(Client *c, const Seperator *sep);
|
void bot_command_taunt(Client *c, const Seperator *sep);
|
||||||
@ -596,8 +599,7 @@ void bot_command_track(Client *c, const Seperator *sep);
|
|||||||
void bot_command_view_combos(Client *c, const Seperator *sep);
|
void bot_command_view_combos(Client *c, const Seperator *sep);
|
||||||
void bot_command_water_breathing(Client *c, const Seperator *sep);
|
void bot_command_water_breathing(Client *c, const Seperator *sep);
|
||||||
|
|
||||||
|
// Bot Subcommands
|
||||||
// bot subcommands
|
|
||||||
void bot_subcommand_bot_appearance(Client *c, const Seperator *sep);
|
void bot_subcommand_bot_appearance(Client *c, const Seperator *sep);
|
||||||
void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep);
|
void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep);
|
||||||
void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep);
|
void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep);
|
||||||
|
|||||||
@ -79,6 +79,15 @@ struct BotAA {
|
|||||||
uint8 total_levels;
|
uint8 total_levels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BotSpellSetting {
|
||||||
|
int16 priority;
|
||||||
|
uint8 min_level;
|
||||||
|
uint8 max_level;
|
||||||
|
int8 min_hp;
|
||||||
|
int8 max_hp;
|
||||||
|
bool is_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BOTS
|
#endif // BOTS
|
||||||
|
|
||||||
#endif // BOT_STRUCTS
|
#endif // BOT_STRUCTS
|
||||||
|
|||||||
@ -21,6 +21,8 @@
|
|||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
#include "../common/data_verification.h"
|
#include "../common/data_verification.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
|
#include "../common/repositories/bot_spells_entries_repository.h"
|
||||||
|
#include "../common/repositories/npc_spells_repository.h"
|
||||||
|
|
||||||
#if EQDEBUG >= 12
|
#if EQDEBUG >= 12
|
||||||
#define BotAI_DEBUG_Spells 25
|
#define BotAI_DEBUG_Spells 25
|
||||||
@ -2877,16 +2879,16 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType)
|
|||||||
return database.botdb.GetSpellCastingChance(spell_type_index, class_index, stance_index, type_index);
|
return database.botdb.GetSpellCastingChance(spell_type_index, class_index, stance_index, type_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::AI_AddBotSpells(uint32 iDBSpellsID) {
|
bool Bot::AI_AddBotSpells(uint32 bot_spell_id) {
|
||||||
// ok, this function should load the list, and the parent list then shove them into the struct and sort
|
// ok, this function should load the list, and the parent list then shove them into the struct and sort
|
||||||
npc_spells_id = iDBSpellsID;
|
npc_spells_id = bot_spell_id;
|
||||||
AIBot_spells.clear();
|
AIBot_spells.clear();
|
||||||
if (!iDBSpellsID) {
|
if (!bot_spell_id) {
|
||||||
AIautocastspell_timer->Disable();
|
AIautocastspell_timer->Disable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* spell_list = content_db.GetBotSpells(iDBSpellsID);
|
auto* spell_list = content_db.GetBotSpells(bot_spell_id);
|
||||||
if (!spell_list) {
|
if (!spell_list) {
|
||||||
AIautocastspell_timer->Disable();
|
AIautocastspell_timer->Disable();
|
||||||
return false;
|
return false;
|
||||||
@ -2897,7 +2899,7 @@ bool Bot::AI_AddBotSpells(uint32 iDBSpellsID) {
|
|||||||
auto debug_msg = fmt::format(
|
auto debug_msg = fmt::format(
|
||||||
"Loading NPCSpells onto {}: dbspellsid={}, level={}",
|
"Loading NPCSpells onto {}: dbspellsid={}, level={}",
|
||||||
GetName(),
|
GetName(),
|
||||||
iDBSpellsID,
|
bot_spell_id,
|
||||||
GetLevel()
|
GetLevel()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2993,7 +2995,50 @@ bool Bot::AI_AddBotSpells(uint32 iDBSpellsID) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddSpellToBotList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust, e.min_hp, e.max_hp, e.bucket_name, e.bucket_value, e.bucket_comparison);
|
|
||||||
|
const auto& bs = GetBotSpellSetting(e.spellid);
|
||||||
|
if (bs) {
|
||||||
|
if (!bs->is_enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->min_level > 0 && GetLevel() < bs->min_level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->max_level > 0 && GetLevel() > bs->max_level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSpellToBotList(
|
||||||
|
bs->priority,
|
||||||
|
e.spellid,
|
||||||
|
e.type,
|
||||||
|
e.manacost,
|
||||||
|
e.recast_delay,
|
||||||
|
e.resist_adjust,
|
||||||
|
bs->min_hp,
|
||||||
|
bs->max_hp,
|
||||||
|
e.bucket_name,
|
||||||
|
e.bucket_value,
|
||||||
|
e.bucket_comparison
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSpellToBotList(
|
||||||
|
e.priority,
|
||||||
|
e.spellid,
|
||||||
|
e.type,
|
||||||
|
e.manacost,
|
||||||
|
e.recast_delay,
|
||||||
|
e.resist_adjust,
|
||||||
|
e.min_hp,
|
||||||
|
e.max_hp,
|
||||||
|
e.bucket_name,
|
||||||
|
e.bucket_value,
|
||||||
|
e.bucket_comparison
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3049,7 +3094,50 @@ bool Bot::AI_AddBotSpells(uint32 iDBSpellsID) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddSpellToBotList(e.priority, e.spellid, e.type, e.manacost, e.recast_delay, e.resist_adjust, e.min_hp, e.max_hp, e.bucket_name, e.bucket_value, e.bucket_comparison);
|
|
||||||
|
const auto& bs = GetBotSpellSetting(e.spellid);
|
||||||
|
if (bs) {
|
||||||
|
if (!bs->is_enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->min_level > 0 && GetLevel() < bs->min_level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->max_level > 0 && GetLevel() > bs->max_level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSpellToBotList(
|
||||||
|
bs->priority,
|
||||||
|
e.spellid,
|
||||||
|
e.type,
|
||||||
|
e.manacost,
|
||||||
|
e.recast_delay,
|
||||||
|
e.resist_adjust,
|
||||||
|
bs->min_hp,
|
||||||
|
bs->max_hp,
|
||||||
|
e.bucket_name,
|
||||||
|
e.bucket_value,
|
||||||
|
e.bucket_comparison
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSpellToBotList(
|
||||||
|
e.priority,
|
||||||
|
e.spellid,
|
||||||
|
e.type,
|
||||||
|
e.manacost,
|
||||||
|
e.recast_delay,
|
||||||
|
e.resist_adjust,
|
||||||
|
e.min_hp,
|
||||||
|
e.max_hp,
|
||||||
|
e.bucket_name,
|
||||||
|
e.bucket_value,
|
||||||
|
e.bucket_comparison
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3108,108 +3196,91 @@ bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 iSpellID) {
|
|||||||
return it != spell_list->entries.end();
|
return it != spell_list->entries.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
DBbotspells_Struct *ZoneDatabase::GetBotSpells(uint32 iDBSpellsID)
|
DBbotspells_Struct* ZoneDatabase::GetBotSpells(uint32 bot_spell_id)
|
||||||
{
|
{
|
||||||
if (!iDBSpellsID) {
|
if (!bot_spell_id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = Bot_Spells_Cache.find(iDBSpellsID);
|
auto c = bot_spells_cache.find(bot_spell_id);
|
||||||
|
if (c != bot_spells_cache.end()) { // it's in the cache, easy =)
|
||||||
if (it != Bot_Spells_Cache.end()) { // it's in the cache, easy =)
|
return &c->second;
|
||||||
return &it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Bot_Spells_LoadTried.count(iDBSpellsID)) { // no reason to ask the DB again if we have failed once already
|
if (!bot_spells_loadtried.count(bot_spell_id)) { // no reason to ask the DB again if we have failed once already
|
||||||
Bot_Spells_LoadTried.insert(iDBSpellsID);
|
bot_spells_loadtried.insert(bot_spell_id);
|
||||||
|
|
||||||
auto query = fmt::format(
|
auto n = NpcSpellsRepository::FindOne(content_db, bot_spell_id);
|
||||||
"SELECT id, parent_list, attack_proc, proc_chance, "
|
if (!n.id) {
|
||||||
"range_proc, rproc_chance, defensive_proc, dproc_chance, "
|
|
||||||
"fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, "
|
|
||||||
"engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, "
|
|
||||||
"pursue_no_sp_recast_min, pursue_no_sp_recast_max, "
|
|
||||||
"pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, "
|
|
||||||
"idle_b_chance FROM npc_spells WHERE id = {}",
|
|
||||||
iDBSpellsID
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success() || !results.RowCount()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
DBbotspells_Struct spell_set;
|
DBbotspells_Struct spell_set;
|
||||||
|
|
||||||
spell_set.parent_list = std::stoul(row[1]);
|
spell_set.parent_list = n.parent_list;
|
||||||
spell_set.attack_proc = static_cast<uint16>(std::stoul(row[2]));
|
spell_set.attack_proc = n.attack_proc;
|
||||||
spell_set.proc_chance = static_cast<uint8>(std::stoul(row[3]));
|
spell_set.proc_chance = n.proc_chance;
|
||||||
spell_set.range_proc = static_cast<uint16>(std::stoul(row[4]));
|
spell_set.range_proc = n.range_proc;
|
||||||
spell_set.rproc_chance = static_cast<int16>(std::stoi(row[5]));
|
spell_set.rproc_chance = n.rproc_chance;
|
||||||
spell_set.defensive_proc = static_cast<uint16>(std::stoul(row[6]));
|
spell_set.defensive_proc = n.defensive_proc;
|
||||||
spell_set.dproc_chance = static_cast<int16>(std::stoi(row[7]));
|
spell_set.dproc_chance = n.dproc_chance;
|
||||||
spell_set.fail_recast = std::stoul(row[8]);
|
spell_set.fail_recast = n.fail_recast;
|
||||||
spell_set.engaged_no_sp_recast_min = std::stoul(row[9]);
|
spell_set.engaged_no_sp_recast_min = n.engaged_no_sp_recast_min;
|
||||||
spell_set.engaged_no_sp_recast_max = std::stoul(row[10]);
|
spell_set.engaged_no_sp_recast_max = n.engaged_no_sp_recast_max;
|
||||||
spell_set.engaged_beneficial_self_chance = static_cast<uint8>(std::stoul(row[11]));
|
spell_set.engaged_beneficial_self_chance = n.engaged_b_self_chance;
|
||||||
spell_set.engaged_beneficial_other_chance = static_cast<uint8>(std::stoul(row[12]));
|
spell_set.engaged_beneficial_other_chance = n.engaged_b_other_chance;
|
||||||
spell_set.engaged_detrimental_chance = static_cast<uint8>(std::stoul(row[13]));
|
spell_set.engaged_detrimental_chance = n.engaged_d_chance;
|
||||||
spell_set.pursue_no_sp_recast_min = std::stoul(row[14]);
|
spell_set.pursue_no_sp_recast_min = n.pursue_no_sp_recast_min;
|
||||||
spell_set.pursue_no_sp_recast_max = std::stoul(row[15]);
|
spell_set.pursue_no_sp_recast_max = n.pursue_no_sp_recast_max;
|
||||||
spell_set.pursue_detrimental_chance = static_cast<uint8>(std::stoul(row[16]));
|
spell_set.pursue_detrimental_chance = n.pursue_d_chance;
|
||||||
spell_set.idle_no_sp_recast_min = std::stoul(row[17]);
|
spell_set.idle_no_sp_recast_min = n.idle_no_sp_recast_min;
|
||||||
spell_set.idle_no_sp_recast_max = std::stoul(row[18]);
|
spell_set.idle_no_sp_recast_max = n.idle_no_sp_recast_max;
|
||||||
spell_set.idle_beneficial_chance = static_cast<uint8>(std::stoul(row[19]));
|
spell_set.idle_beneficial_chance = n.idle_b_chance;
|
||||||
|
|
||||||
// pulling fixed values from an auto-increment field is dangerous...
|
auto bse = BotSpellsEntriesRepository::GetWhere(
|
||||||
query = fmt::format(
|
content_db,
|
||||||
"SELECT spellid, type, minlevel, maxlevel, "
|
fmt::format(
|
||||||
"manacost, recast_delay, priority, min_hp, max_hp, resist_adjust, "
|
"npc_spells_id = {}",
|
||||||
"bucket_name, bucket_value, bucket_comparison "
|
bot_spell_id
|
||||||
"FROM bot_spells_entries "
|
)
|
||||||
"WHERE npc_spells_id = {} ORDER BY minlevel",
|
|
||||||
iDBSpellsID
|
|
||||||
);
|
);
|
||||||
results = QueryDatabase(query);
|
if (bse.empty()) {
|
||||||
if (!results.Success() || !results.RowCount()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto row : results) {
|
for (const auto& e : bse) {
|
||||||
DBbotspells_entries_Struct entry;
|
DBbotspells_entries_Struct entry;
|
||||||
auto spell_id = std::stoi(row[0]);
|
entry.spellid = e.spellid;
|
||||||
entry.spellid = spell_id;
|
entry.type = e.type;
|
||||||
entry.type = std::stoul(row[1]);
|
entry.minlevel = e.minlevel;
|
||||||
entry.minlevel = static_cast<uint8>(std::stoul(row[2]));
|
entry.maxlevel = e.maxlevel;
|
||||||
entry.maxlevel = static_cast<uint8>(std::stoul(row[3]));
|
entry.manacost = e.manacost;
|
||||||
entry.manacost = static_cast<int16>(std::stoi(row[4]));
|
entry.recast_delay = e.recast_delay;
|
||||||
entry.recast_delay = std::stoi(row[5]);
|
entry.priority = e.priority;
|
||||||
entry.priority = static_cast<int16>(std::stoi(row[6]));
|
entry.min_hp = e.min_hp;
|
||||||
entry.min_hp = static_cast<int8>(std::stoi(row[7]));
|
entry.max_hp = e.max_hp;
|
||||||
entry.max_hp = static_cast<int8>(std::stoi(row[8]));
|
entry.resist_adjust = e.resist_adjust;
|
||||||
entry.resist_adjust = static_cast<int16>(std::stoi(row[9]));
|
entry.bucket_name = e.bucket_name;
|
||||||
entry.bucket_name = row[10];
|
entry.bucket_value = e.bucket_value;
|
||||||
entry.bucket_value = row[11];
|
entry.bucket_comparison = e.bucket_comparison;
|
||||||
entry.bucket_comparison = static_cast<uint8>(std::stoul(row[12]));
|
|
||||||
|
|
||||||
// some spell types don't make much since to be priority 0, so fix that
|
// some spell types don't make much since to be priority 0, so fix that
|
||||||
if (!(entry.type & SPELL_TYPES_INNATE) && entry.priority == 0) {
|
if (!(entry.type & SPELL_TYPES_INNATE) && entry.priority == 0) {
|
||||||
entry.priority = 1;
|
entry.priority = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row[9]) {
|
if (e.resist_adjust) {
|
||||||
entry.resist_adjust = static_cast<int16>(std::stoi(row[9]));
|
entry.resist_adjust = e.resist_adjust;
|
||||||
} else if (IsValidSpell(spell_id)) {
|
} else if (IsValidSpell(e.spellid)) {
|
||||||
entry.resist_adjust = spells[spell_id].resist_difficulty;
|
entry.resist_adjust = spells[e.spellid].resist_difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
spell_set.entries.push_back(entry);
|
spell_set.entries.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot_Spells_Cache.insert(std::make_pair(iDBSpellsID, spell_set));
|
bot_spells_cache.insert(std::make_pair(bot_spell_id, spell_set));
|
||||||
|
|
||||||
return &Bot_Spells_Cache[iDBSpellsID];
|
return &bot_spells_cache[bot_spell_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@ -109,6 +109,26 @@ void Lua_Bot::SetExpansionBitmask(int expansion_bitmask, bool save) {
|
|||||||
self->SetExpansionBitmask(expansion_bitmask, save);
|
self->SetExpansionBitmask(expansion_bitmask, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Lua_Bot::ReloadBotDataBuckets() {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->GetBotDataBuckets();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Bot::ReloadBotOwnerDataBuckets() {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->GetBotOwnerDataBuckets();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Bot::ReloadBotSpells() {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->AI_AddBotSpells(self->GetBotSpellID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Bot::ReloadBotSpellSettings() {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->LoadBotSpellSettings();
|
||||||
|
}
|
||||||
|
|
||||||
bool Lua_Bot::HasBotSpellEntry(uint16 spellid) {
|
bool Lua_Bot::HasBotSpellEntry(uint16 spellid) {
|
||||||
Lua_Safe_Call_Bool();
|
Lua_Safe_Call_Bool();
|
||||||
return self->HasBotSpellEntry(spellid);
|
return self->HasBotSpellEntry(spellid);
|
||||||
@ -117,27 +137,31 @@ bool Lua_Bot::HasBotSpellEntry(uint16 spellid) {
|
|||||||
luabind::scope lua_register_bot() {
|
luabind::scope lua_register_bot() {
|
||||||
return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
|
return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32, uint32, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32, uint32, uint32, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("AddBotItem", (void(Lua_Bot::*)(uint16, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32, uint32)) & Lua_Bot::AddBotItem)
|
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
|
||||||
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32)) & Lua_Bot::CountBotItem)
|
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem)
|
||||||
.def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16)) & Lua_Bot::GetBotItem)
|
.def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem)
|
||||||
.def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16)) & Lua_Bot::GetBotItemIDBySlot)
|
.def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot)
|
||||||
.def("GetExpansionBitmask", (int(Lua_Bot::*)(void)) & Lua_Bot::GetExpansionBitmask)
|
.def("GetExpansionBitmask", (int(Lua_Bot::*)(void))&Lua_Bot::GetExpansionBitmask)
|
||||||
.def("GetOwner", (Lua_Mob(Lua_Bot::*)(void)) & Lua_Bot::GetOwner)
|
.def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner)
|
||||||
.def("HasBotItem", (bool(Lua_Bot::*)(uint32)) & Lua_Bot::HasBotItem)
|
.def("HasBotItem", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
|
||||||
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
|
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
|
||||||
.def("OwnerMessage", (void(Lua_Bot::*)(std::string)) & Lua_Bot::OwnerMessage)
|
.def("OwnerMessage", (void(Lua_Bot::*)(std::string))&Lua_Bot::OwnerMessage)
|
||||||
.def("RemoveBotItem", (void(Lua_Bot::*)(uint32)) & Lua_Bot::RemoveBotItem)
|
.def("ReloadBotDataBuckets", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotDataBuckets)
|
||||||
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int)) & Lua_Bot::SetExpansionBitmask)
|
.def("ReloadBotOwnerDataBuckets", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotOwnerDataBuckets)
|
||||||
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int, bool)) & Lua_Bot::SetExpansionBitmask)
|
.def("ReloadBotSpells", (bool(Lua_Bot::*)(void))&Lua_Bot::ReloadBotSpells)
|
||||||
.def("SignalBot", (void(Lua_Bot::*)(int)) & Lua_Bot::SignalBot);
|
.def("ReloadBotSpellSettings", (void(Lua_Bot::*)(void))&Lua_Bot::ReloadBotSpellSettings)
|
||||||
|
.def("RemoveBotItem", (void(Lua_Bot::*)(uint32))&Lua_Bot::RemoveBotItem)
|
||||||
|
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask)
|
||||||
|
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask)
|
||||||
|
.def("SignalBot", (void(Lua_Bot::*)(int))&Lua_Bot::SignalBot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -43,6 +43,10 @@ public:
|
|||||||
Lua_Mob GetOwner();
|
Lua_Mob GetOwner();
|
||||||
bool HasBotItem(uint32 item_id);
|
bool HasBotItem(uint32 item_id);
|
||||||
void OwnerMessage(std::string message);
|
void OwnerMessage(std::string message);
|
||||||
|
bool ReloadBotDataBuckets();
|
||||||
|
bool ReloadBotOwnerDataBuckets();
|
||||||
|
bool ReloadBotSpells();
|
||||||
|
void ReloadBotSpellSettings();
|
||||||
void RemoveBotItem(uint32 item_id);
|
void RemoveBotItem(uint32 item_id);
|
||||||
void SetExpansionBitmask(int expansion_bitmask);
|
void SetExpansionBitmask(int expansion_bitmask);
|
||||||
void SetExpansionBitmask(int expansion_bitmask, bool save);
|
void SetExpansionBitmask(int expansion_bitmask, bool save);
|
||||||
|
|||||||
@ -106,6 +106,26 @@ void Perl_Bot_SetExpansionBitmask(Bot* self, int expansion_bitmask, bool save)
|
|||||||
self->SetExpansionBitmask(expansion_bitmask, save);
|
self->SetExpansionBitmask(expansion_bitmask, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Perl_Bot_ReloadBotDataBuckets(Bot* self)
|
||||||
|
{
|
||||||
|
return self->GetBotDataBuckets();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Perl_Bot_ReloadBotOwnerDataBuckets(Bot* self)
|
||||||
|
{
|
||||||
|
return self->GetBotOwnerDataBuckets();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Perl_Bot_ReloadBotSpells(Bot* self)
|
||||||
|
{
|
||||||
|
return self->AI_AddBotSpells(self->GetBotSpellID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Perl_Bot_ReloadBotSpellSettings(Bot* self)
|
||||||
|
{
|
||||||
|
self->LoadBotSpellSettings();
|
||||||
|
}
|
||||||
|
|
||||||
bool Perl_Bot_HasBotSpellEntry(Bot* self, uint16 spellid)
|
bool Perl_Bot_HasBotSpellEntry(Bot* self, uint16 spellid)
|
||||||
{
|
{
|
||||||
return self->HasBotSpellEntry(spellid);
|
return self->HasBotSpellEntry(spellid);
|
||||||
@ -134,6 +154,10 @@ void perl_register_bot()
|
|||||||
package.add("HasBotItem", &Perl_Bot_HasBotItem);
|
package.add("HasBotItem", &Perl_Bot_HasBotItem);
|
||||||
package.add("HasBotSpellEntry", &Perl_Bot_HasBotSpellEntry);
|
package.add("HasBotSpellEntry", &Perl_Bot_HasBotSpellEntry);
|
||||||
package.add("OwnerMessage", &Perl_Bot_OwnerMessage);
|
package.add("OwnerMessage", &Perl_Bot_OwnerMessage);
|
||||||
|
package.add("ReloadBotDataBuckets", &Perl_Bot_ReloadBotDataBuckets);
|
||||||
|
package.add("ReloadBotOwnerDataBuckets", &Perl_Bot_ReloadBotOwnerDataBuckets);
|
||||||
|
package.add("ReloadBotSpells", &Perl_Bot_ReloadBotSpells);
|
||||||
|
package.add("ReloadBotSpellSettings", &Perl_Bot_ReloadBotSpellSettings);
|
||||||
package.add("RemoveBotItem", &Perl_Bot_RemoveBotItem);
|
package.add("RemoveBotItem", &Perl_Bot_RemoveBotItem);
|
||||||
package.add("SetExpansionBitmask", (void(*)(Bot*, int))&Perl_Bot_SetExpansionBitmask);
|
package.add("SetExpansionBitmask", (void(*)(Bot*, int))&Perl_Bot_SetExpansionBitmask);
|
||||||
package.add("SetExpansionBitmask", (void(*)(Bot*, int, bool))&Perl_Bot_SetExpansionBitmask);
|
package.add("SetExpansionBitmask", (void(*)(Bot*, int, bool))&Perl_Bot_SetExpansionBitmask);
|
||||||
|
|||||||
@ -533,8 +533,8 @@ public:
|
|||||||
const NPCType* LoadNPCTypesData(uint32 id, bool bulk_load = false);
|
const NPCType* LoadNPCTypesData(uint32 id, bool bulk_load = false);
|
||||||
|
|
||||||
/*Bots */
|
/*Bots */
|
||||||
DBbotspells_Struct* GetBotSpells(uint32 iDBSpellsID);
|
DBbotspells_Struct* GetBotSpells(uint32 bot_spell_id);
|
||||||
void ClearBotSpells() { Bot_Spells_Cache.clear(); Bot_Spells_LoadTried.clear(); }
|
void ClearBotSpells() { bot_spells_cache.clear(); bot_spells_loadtried.clear(); }
|
||||||
|
|
||||||
/* Mercs */
|
/* Mercs */
|
||||||
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
|
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
|
||||||
@ -637,8 +637,9 @@ protected:
|
|||||||
std::unordered_set<uint32> npc_spells_loadtried;
|
std::unordered_set<uint32> npc_spells_loadtried;
|
||||||
DBnpcspellseffects_Struct** npc_spellseffects_cache;
|
DBnpcspellseffects_Struct** npc_spellseffects_cache;
|
||||||
bool* npc_spellseffects_loadtried;
|
bool* npc_spellseffects_loadtried;
|
||||||
std::unordered_map<uint32, DBbotspells_Struct> Bot_Spells_Cache;
|
std::unordered_map<uint32, DBbotspells_Struct> bot_spells_cache;
|
||||||
std::unordered_set<uint32> Bot_Spells_LoadTried;
|
std::unordered_set<uint32> bot_spells_loadtried;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ZoneDatabase database;
|
extern ZoneDatabase database;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user