diff --git a/changelog.txt b/changelog.txt index 138482aa8..4b717ed5b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/09/2018 == +Uleat: Added bot owner options + - usage: ^owneroption [option] (or aliased as: ^oo [option]) + - options are saved in the database and therefore, persistent + - Implemented option 'deathmarquee' + -- toggles client owner flag to show marquee message when a bot dies (default: disabled) + == 10/07/2018 == Uleat: Fixed a few bot issues.. - Fix for bot item trades not attuning diff --git a/common/version.h b/common/version.h index 849b3d9ac..4caca5b38 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9129 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9020 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021 #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 3496ce8d2..acdb20532 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -19,6 +19,7 @@ 9018|2018_02_02_Bot_Spells_Min_Max_HP.sql|SHOW COLUMNS FROM `bot_spells_entries` LIKE 'min_hp'|empty| 9019|2018_04_12_bots_stop_melee_level.sql|SHOW COLUMNS FROM `bot_data` LIKE 'stop_melee_level'|empty| 9020|2018_08_13_bots_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `bot_step` = 0|not_empty| +9021|2018_10_09_bots_owner_options.sql|SHOW TABLES LIKE 'bot_owner_options'|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/2018_10_09_bots_owner_options.sql b/utils/sql/git/bots/required/2018_10_09_bots_owner_options.sql new file mode 100644 index 000000000..ec1a7bebe --- /dev/null +++ b/utils/sql/git/bots/required/2018_10_09_bots_owner_options.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `bot_owner_options`; + +CREATE TABLE `bot_owner_options` ( + `owner_id` INT(11) UNSIGNED NOT NULL, + `death_marquee` SMALLINT(3) UNSIGNED NULL DEFAULT '0', + PRIMARY KEY (`owner_id`) +) +COLLATE='latin1_swedish_ci' +ENGINE=MyISAM; + +INSERT INTO `bot_command_settings`(`bot_command`, `access`, `aliases`) VALUES ('owneroption', '0', 'oo'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 2c8b143c6..f5b26c3e0 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4042,6 +4042,15 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::Sk return false; Save(); + + Mob *my_owner = GetBotOwner(); + if (my_owner && my_owner->IsClient() && my_owner->CastToClient()->GetBotOptionDeathMarquee()) { + if (killerMob) + my_owner->CastToClient()->SendMarqueeMessage(CC_Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain by %s", GetCleanName(), killerMob->GetCleanName())); + else + my_owner->CastToClient()->SendMarqueeMessage(CC_Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName())); + } + Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Client *give_exp_client = nullptr; if(give_exp && give_exp->IsClient()) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 17e7cf6ab..35aa156ed 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1399,6 +1399,7 @@ int bot_command_init(void) bot_command_add("lull", "Orders a bot to cast a pacification spell", 0, bot_command_lull) || bot_command_add("mesmerize", "Orders a bot to cast a mesmerization spell", 0, bot_command_mesmerize) || bot_command_add("movementspeed", "Orders a bot to cast a movement speed enhancement spell", 0, bot_command_movement_speed) || + bot_command_add("owneroption", "Sets options available to bot owners", 0, bot_command_owner_option) || bot_command_add("pet", "Lists the available bot pet [subcommands]", 0, bot_command_pet) || bot_command_add("petremove", "Orders a bot to remove its pet", 0, bot_subcommand_pet_remove) || bot_command_add("petsettype", "Orders a Magician bot to use a specified pet type", 0, bot_subcommand_pet_set_type) || @@ -3437,6 +3438,25 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) helper_no_available_bots(c, my_bot); } +void bot_command_owner_option(Client *c, const Seperator *sep) +{ + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [deathmarquee]", sep->arg[0]); + return; + } + + std::string owner_option = sep->arg[1]; + + if (!owner_option.compare("deathmarquee")) { + c->SetBotOptionDeathMarquee(!c->GetBotOptionDeathMarquee()); + c->Message(m_action, "Bot death marquee is now %s.", (c->GetBotOptionDeathMarquee() == true ? "enabled" : "disabled")); + botdb.SaveOwnerOptionDeathMarquee(c->CharacterID(), c->GetBotOptionDeathMarquee()); + } + else { + c->Message(m_fail, "Owner option '%s' is not recognized.", owner_option.c_str()); + } +} + void bot_command_pet(Client *c, const Seperator *sep) { /* VS2012 code - begin */ diff --git a/zone/bot_command.h b/zone/bot_command.h index f2c706cac..603852b38 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -575,6 +575,7 @@ void bot_command_levitation(Client *c, const Seperator *sep); void bot_command_lull(Client *c, const Seperator *sep); void bot_command_mesmerize(Client *c, const Seperator *sep); void bot_command_movement_speed(Client *c, const Seperator *sep); +void bot_command_owner_option(Client *c, const Seperator *sep); void bot_command_pet(Client *c, const Seperator *sep); void bot_command_pick_lock(Client *c, const Seperator *sep); void bot_command_pull(Client *c, const Seperator *sep); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 92d6fba98..17bc51487 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -25,6 +25,7 @@ #include "bot_database.h" #include "bot.h" +#include "client.h" BotDatabase botdb; @@ -2185,6 +2186,51 @@ bool BotDatabase::SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, return true; } +bool BotDatabase::LoadOwnerOptions(Client *owner) +{ + if (!owner || !owner->CharacterID()) + return false; + + query = StringFormat( + "SELECT `death_marquee` FROM `bot_owner_options`" + " WHERE `owner_id` = '%u'", + owner->CharacterID() + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) { + query = StringFormat("REPLACE INTO `bot_owner_options` (`owner_id`) VALUES ('%u')", owner->CharacterID()); + results = QueryDatabase(query); + + return false; + } + + auto row = results.begin(); + owner->SetBotOptionDeathMarquee((atoi(row[0]) != 0)); + + return true; +} + +bool BotDatabase::SaveOwnerOptionDeathMarquee(const uint32 owner_id, const bool flag) +{ + if (!owner_id) + return false; + + query = StringFormat( + "UPDATE `bot_owner_options`" + " SET `death_marquee` = '%u'" + " WHERE `owner_id` = '%u'", + (flag == true ? 1 : 0), + owner_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + /* Bot bot-group functions */ bool BotDatabase::QueryBotGroupExistence(const std::string& group_name, bool& extant_flag) diff --git a/zone/bot_database.h b/zone/bot_database.h index 2361c0cf1..2840c415c 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -32,6 +32,7 @@ class Bot; struct BotsAvailableList; +class Client; namespace EQEmu { @@ -145,6 +146,8 @@ public: bool SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, const uint8 sml_value); + bool LoadOwnerOptions(Client *owner); + bool SaveOwnerOptionDeathMarquee(const uint32 owner_id, const bool flag); /* Bot bot-group functions */ bool QueryBotGroupExistence(const std::string& botgroup_name, bool& extant_flag); diff --git a/zone/client.cpp b/zone/client.cpp index b251a72d4..18940d58a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -335,6 +335,10 @@ Client::Client(EQStreamInterface* ieqs) temp_pvp = false; is_client_moving = false; +#ifdef BOTS + bot_owner_options = DefaultBotOwnerOptions; +#endif + AI_Init(); } diff --git a/zone/client.h b/zone/client.h index 393ede129..023367e50 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1641,6 +1641,25 @@ private: void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, bool log, bool silent, bool &error, int depth); bool InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth); + +#ifdef BOTS + struct BotOwnerOptions { + bool death_marquee; + }; + + BotOwnerOptions bot_owner_options; + + const BotOwnerOptions DefaultBotOwnerOptions = { + false // death_marquee + }; + +public: + void SetBotOptionDeathMarquee(bool flag) { bot_owner_options.death_marquee = flag; } + + bool GetBotOptionDeathMarquee() const { return bot_owner_options.death_marquee; } + +private: +#endif }; #endif diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 97db51286..c6fd66894 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1599,6 +1599,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } #ifdef BOTS + botdb.LoadOwnerOptions(this); + // TODO: mod below function for loading spawned botgroups Bot::LoadAndSpawnAllZonedBots(this); #endif