diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h index 657f156ea..d91e5ec04 100644 --- a/common/repositories/base/base_bot_data_repository.h +++ b/common/repositories/base/base_bot_data_repository.h @@ -68,6 +68,7 @@ public: uint8_t stop_melee_level; int32_t expansion_bitmask; uint8_t enforce_spell_settings; + uint8_t archery_setting; }; static std::string PrimaryKey() @@ -127,6 +128,7 @@ public: "stop_melee_level", "expansion_bitmask", "enforce_spell_settings", + "archery_setting", }; } @@ -182,6 +184,7 @@ public: "stop_melee_level", "expansion_bitmask", "enforce_spell_settings", + "archery_setting", }; } @@ -271,6 +274,7 @@ public: e.stop_melee_level = 255; e.expansion_bitmask = -1; e.enforce_spell_settings = 0; + e.archery_setting = 0; return e; } @@ -355,6 +359,7 @@ public: e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); return e; } @@ -436,6 +441,7 @@ public: v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level)); v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask)); v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings)); + v.push_back(columns[49] + " = " + std::to_string(e.archery_setting)); auto results = db.QueryDatabase( fmt::format( @@ -506,6 +512,7 @@ public: v.push_back(std::to_string(e.stop_melee_level)); v.push_back(std::to_string(e.expansion_bitmask)); v.push_back(std::to_string(e.enforce_spell_settings)); + v.push_back(std::to_string(e.archery_setting)); auto results = db.QueryDatabase( fmt::format( @@ -584,6 +591,7 @@ public: v.push_back(std::to_string(e.stop_melee_level)); v.push_back(std::to_string(e.expansion_bitmask)); v.push_back(std::to_string(e.enforce_spell_settings)); + v.push_back(std::to_string(e.archery_setting)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -666,6 +674,7 @@ public: e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); all_entries.push_back(e); } @@ -739,6 +748,7 @@ public: e.stop_melee_level = static_cast(strtoul(row[46], nullptr, 10)); e.expansion_bitmask = static_cast(atoi(row[47])); e.enforce_spell_settings = static_cast(strtoul(row[48], nullptr, 10)); + e.archery_setting = static_cast(strtoul(row[49], nullptr, 10)); all_entries.push_back(e); } diff --git a/common/version.h b/common/version.h index 2fd8ea0bf..f043aa1ab 100644 --- a/common/version.h +++ b/common/version.h @@ -37,7 +37,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9212 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9034 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9035 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 3554ccce2..a63ecad68 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -33,6 +33,7 @@ 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| 9034|2022_12_02_bot_spell_settings.sql|SHOW COLUMNS FROM `bot_data` LIKE 'enforce_spell_settings'|empty| +9035|2022_12_04_bot_archery.sql|SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2022_12_04_bot_archery.sql b/utils/sql/git/bots/required/2022_12_04_bot_archery.sql new file mode 100644 index 000000000..ae05f4132 --- /dev/null +++ b/utils/sql/git/bots/required/2022_12_04_bot_archery.sql @@ -0,0 +1,2 @@ +ALTER TABLE `bot_data` +ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`; \ No newline at end of file diff --git a/zone/bot.cpp b/zone/bot.cpp index 7612f3156..50dc62e00 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -72,7 +72,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm SetBotID(0); SetBotSpellID(0); SetSpawnStatus(false); - SetBotArcher(false); SetBotCharmer(false); SetPetChooser(false); SetRangerAutoWeaponSelect(false); @@ -167,7 +166,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetBotID(botID); SetBotSpellID(botSpellsID); SetSpawnStatus(false); - SetBotArcher(false); SetBotCharmer(false); SetPetChooser(false); SetRangerAutoWeaponSelect(false); @@ -3164,12 +3162,12 @@ void Bot::AI_Process() if (atArcheryRange && !IsBotArcher()) { - SetBotArcher(true); + SetBotArcherySetting(true); changeWeapons = true; } else if (!atArcheryRange && IsBotArcher()) { - SetBotArcher(false); + SetBotArcherySetting(false); changeWeapons = true; } @@ -10867,6 +10865,24 @@ std::string Bot::GetHPString(int8 min_hp, int8 max_hp) return hp_string; } +void Bot::SetBotArcherySetting(bool bot_archer_setting, bool save) +{ + m_bot_archery_setting = bot_archer_setting; + if (save) { + if (!database.botdb.SaveBotArcherSetting(GetBotID(), bot_archer_setting)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) { + GetBotOwner()->CastToClient()->Message( + Chat::White, + fmt::format( + "Failed to save archery settings for {}.", + GetCleanName() + ).c_str() + ); + } + } + } +} + uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 }; #endif diff --git a/zone/bot.h b/zone/bot.h index be44e5c87..fd6a3f3d9 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -468,7 +468,7 @@ public: virtual bool GetSpawnStatus() { return _spawnStatus; } uint8 GetPetChooserID() { return _petChooserID; } bool IsPetChooser() { return _petChooser; } - bool IsBotArcher() { return _botArcher; } + bool IsBotArcher() { return m_bot_archery_setting; } bool IsBotCharmer() { return _botCharmer; } virtual bool IsBot() const { return true; } bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; } @@ -586,7 +586,7 @@ public: void SetBotSpellID(uint32 newSpellID); virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; } void SetPetChooserID(uint8 id) { _petChooserID = id; } - void SetBotArcher(bool a) { _botArcher = a; } + void SetBotArcherySetting(bool bot_archer_setting, bool save = false); void SetBotCharmer(bool c) { _botCharmer = c; } void SetPetChooser(bool p) { _petChooser = p; } void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; } @@ -753,7 +753,7 @@ private: bool _spawnStatus; Mob* _botOwner; bool _botOrderAttack; - bool _botArcher; + bool m_bot_archery_setting; bool _botCharmer; bool _petChooser; uint8 _petChooserID; diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 6e32e46bb..fcea1446c 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -6942,8 +6942,9 @@ void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep) { - if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) + if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) { return; + } if (helper_is_help_or_usage(sep->arg[1])) { c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); return; @@ -6966,21 +6967,26 @@ void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep) } std::list sbl; - if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) { return; + } for (auto bot_iter : sbl) { - if (!bot_iter) + if (!bot_iter) { continue; + } - if (toggle_archer) - bot_iter->SetBotArcher(!bot_iter->IsBotArcher()); - else - bot_iter->SetBotArcher(archer_state); + if (toggle_archer) { + bot_iter->SetBotArcherySetting(!bot_iter->IsBotArcher(), true); + } + else { + bot_iter->SetBotArcherySetting(archer_state, true); + } bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher()); - if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) + if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) { bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher()); + } } } @@ -9368,11 +9374,9 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) c->PushItemOnCursor(*inst, true); if ( slot_id == EQ::invslot::slotRange || - slot_id == EQ::invslot::slotAmmo || - slot_id == EQ::invslot::slotPrimary || - slot_id == EQ::invslot::slotSecondary + slot_id == EQ::invslot::slotAmmo ) { - my_bot->SetBotArcher(false); + my_bot->SetBotArcherySetting(false, true); } my_bot->RemoveBotItemBySlot(slot_id, &error_message); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index b2ab960b9..7e9a4614d 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -410,7 +410,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) " `follow_distance`," // 26 " `stop_melee_level`," // 27 " `expansion_bitmask`," // 28 - " `enforce_spell_settings`" // 29 + " `enforce_spell_settings`," // 29 + " `archery_setting`" // 30 " FROM `bot_data`" " WHERE `bot_id` = {}" " LIMIT 1", @@ -511,6 +512,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) loaded_bot->SetExpansionBitmask(eb, false); loaded_bot->SetBotEnforceSpellSetting((std::stoi(row[29]) > 0 ? true : false)); + + loaded_bot->SetBotArcherySetting((std::stoi(row[30]) > 0 ? true : false)); } return true; @@ -3302,6 +3305,27 @@ bool BotDatabase::SaveEnforceSpellSetting(const uint32 bot_id, const bool enforc return true; } +bool BotDatabase::SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting) +{ + if (!bot_id) { + return false; + } + + query = fmt::format( + "UPDATE `bot_data`" + "SET `archery_setting` = {} " + "WHERE `bot_id` = {}", + (bot_archer_setting ? 1 : 0), + bot_id + ); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + return true; +} + /* fail::Bot functions */ const char* BotDatabase::fail::LoadBotsList() { return "Failed to bots list"; } const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner ID"; } diff --git a/zone/bot_database.h b/zone/bot_database.h index 2f4828a46..923811211 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -144,6 +144,8 @@ public: bool SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, const uint8 sml_value); + bool SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting); + bool LoadOwnerOptions(Client *owner); bool SaveOwnerOption(const uint32 owner_id, size_t type, const bool flag); bool SaveOwnerOption(const uint32 owner_id, const std::pair type, const std::pair flag);