diff --git a/changelog.txt b/changelog.txt index 0d8f82041..ad9699fb4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,11 +1,16 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== xx/xx/2014 == +== 03/31/2014 == Uleat: Fix for unconscious skillups. Uleat: Fix for crash issue with nullptr reference in recent Client::SummonItem() work. Uleat: Added rule for GM Status check code in Client::SummonItem(). Note: Rule default is set to 250..but, implementation is on hold until load item code handles the database 'minstatus' field. +Uleat: Added RuleB(Bots, BotLevelsWithOwner). Bots will auto-update as their owner levels/de-levels. Appearance packets are sent to show the 'leveling effect' as well as updating client entities. + +Optional Bot SQL: utils/sql/git/bot/optional/2014_03_31_BotLevelsWithOwnerRule.sql +Note: This sql is required to activate the optional behavior. + == 03/27/2014 == Kayen: SE_Gate will now use have a fail chance as defined by its base value in the spell data. Kayen: SE_Succor will now have a baseline fail chance of (2%). Rule added to adjust this as needed. diff --git a/common/ruletypes.h b/common/ruletypes.h index d275595fe..32775f316 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -448,6 +448,7 @@ RULE_BOOL ( Bots, BotSpellQuest, false ) // Anita Thrall's (Anita_Thrall.pl) Bot RULE_INT ( Bots, BotAAExpansion, 8 ) // Bots get AAs through this expansion RULE_BOOL ( Bots, BotGroupXP, false ) // Determines whether client gets xp for bots outside their group. RULE_BOOL ( Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs. +RULE_BOOL ( Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) RULE_CATEGORY_END() #endif diff --git a/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql b/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql new file mode 100644 index 000000000..4700d9abf --- /dev/null +++ b/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql @@ -0,0 +1,4 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (2, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (4, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (10, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 347dd0bc6..1526beddc 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5284,6 +5284,28 @@ uint32 Bot::GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage) { return Result; } +void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { + // This essentially performs a '#bot update,' with appearance packets, based on the current methods. + // This should not be called outside of Client::SetEXP() due to it's lack of rule checks. + if(client) { + std::list blist = entity_list.GetBotsByBotOwnerCharacterID(client->CharacterID()); + + for(std::list::iterator biter = blist.begin(); biter != blist.end(); ++biter) { + Bot* bot = *biter; + if(bot && (bot->GetLevel() != client->GetLevel())) { + bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code + bot->CalcBotStats(false); + if(sendlvlapp) + bot->SendLevelAppearance(); + // modified from Client::SetLevel() + bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change + } + } + + blist.clear(); + } +} + std::string Bot::ClassIdToString(uint16 classId) { std::string Result; diff --git a/zone/bot.h b/zone/bot.h index b0ff52845..485d37377 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -352,6 +352,7 @@ public: static uint32 CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage); static uint32 AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage); static uint32 GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage); + static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp); //static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* errorMessage); static std::string ClassIdToString(uint16 classId); static std::string RaceIdToString(uint16 raceId); diff --git a/zone/command.cpp b/zone/command.cpp index 40e37045e..c55fa4542 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2638,19 +2638,35 @@ void command_makepet(Client *c, const Seperator *sep) void command_level(Client *c, const Seperator *sep) { uint16 level = atoi(sep->arg[1]); - if ((level <= 0) || ((level > RuleI(Character, MaxLevel)) && (c->Admin() < commandLevelAboveCap)) ) + + if ((level <= 0) || ((level > RuleI(Character, MaxLevel)) && (c->Admin() < commandLevelAboveCap))) { c->Message(0, "Error: #Level: Invalid Level"); - else if (c->Admin() < 100) + } + else if (c->Admin() < 100) { c->SetLevel(level, true); - else if (!c->GetTarget()) +#ifdef BOTS + if(RuleB(Bots, BotLevelsWithOwner)) + Bot::LevelBotWithClient(c, level, true); +#endif + } + else if (!c->GetTarget()) { c->Message(0, "Error: #Level: No target"); - else - if (!c->GetTarget()->IsNPC() && ((c->Admin() < commandLevelNPCAboveCap) && (level > RuleI(Character, MaxLevel)))) + } + else { + if (!c->GetTarget()->IsNPC() && ((c->Admin() < commandLevelNPCAboveCap) && (level > RuleI(Character, MaxLevel)))) { c->Message(0, "Error: #Level: Invalid Level"); - else + } + else { c->GetTarget()->SetLevel(level, true); - if(c->GetTarget() && c->GetTarget()->IsClient()) - c->GetTarget()->CastToClient()->SendLevelAppearance(); + if(c->GetTarget()->IsClient()) { + c->GetTarget()->CastToClient()->SendLevelAppearance(); +#ifdef BOTS + if(RuleB(Bots, BotLevelsWithOwner)) + Bot::LevelBotWithClient(c->GetTarget()->CastToClient(), level, true); +#endif + } + } + } } void command_spawn(Client *c, const Seperator *sep) diff --git a/zone/exp.cpp b/zone/exp.cpp index cbf7f5f6d..5e8eb49f8 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -326,7 +326,18 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } else Message(15, "Welcome to level %i!", check_level); + +#ifdef BOTS + uint8 myoldlevel = GetLevel(); +#endif + SetLevel(check_level); + +#ifdef BOTS + if(RuleB(Bots, BotLevelsWithOwner)) + // hack way of doing this..but, least invasive... (same criteria as gain level for sendlvlapp) + Bot::LevelBotWithClient(this, GetLevel(), (myoldlevel==check_level-1)); +#endif } //If were at max level then stop gaining experience if we make it to the cap