diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 69ad02ca1ce57a..5ec0da05fc92b0 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -4527,6 +4527,17 @@ NpcBot.XpReduction.StartingNumber = 2 NpcBot.XpReduction.Blizzlike.Enable = 1 NpcBot.XpReduction.Blizzlike.GroupOnly = 0 +# +# NpcBot.MoneyShare.Enable +# NpcBot.MoneyShare.GroupOnly +# Description: Share money loot with bots, effectively reducing money amount players receive. +# Example: Group of 5, 3 bots, looting 100 copper, players receive 20 copper each. +# Default: 0 - (NpcBot.MoneyShare.Enable) +# 0 - (NpcBot.MoneyShare.GroupOnly) + +NpcBot.MoneyShare.Enable = 0 +NpcBot.MoneyShare.GroupOnly = 0 + # # NpcBot.MountLevel.60 # NpcBot.MountLevel.100 diff --git a/src/server/game/AI/NpcBots/bot_ai.cpp b/src/server/game/AI/NpcBots/bot_ai.cpp index 539a9bfdd05c3f..59fcd205c80c7a 100644 --- a/src/server/game/AI/NpcBots/bot_ai.cpp +++ b/src/server/game/AI/NpcBots/bot_ai.cpp @@ -12104,7 +12104,28 @@ void bot_ai::_autoLootCreatureGold(Creature* creature) const players.push_back(p); } - uint32 goldPerPlayer = uint32(loot->gold / uint32(players.size())); + uint32 bots_count = 0; + if (BotMgr::GetNpcBotMoneyShareEnabled()) + { + for (GroupReference const* itr = gr->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player const* member = itr->GetSource(); + if (!member || !member->IsInMap(creature) || !member->HaveBot()) + continue; + + BotMap const* botMap = member->GetBotMgr()->GetBotMap(); + for (auto const& kv : *botMap) + { + Creature const* bot = kv.second; + if (bot && bot->IsAlive() && bot->IsInMap(creature) && (gr->IsMember(kv.first) || !BotMgr::GetNpcBotMoneyShareGroupOnly()) && + (member->GetMap()->IsDungeon() || creature->GetDistance(bot) <= sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE))) + ++bots_count; + } + } + } + + uint32 sharers_count = uint32(players.size()) + bots_count; + uint32 goldPerPlayer = uint32(loot->gold / sharers_count); for (std::vector::const_iterator i = players.begin(); i != players.end(); ++i) { @@ -12113,7 +12134,7 @@ void bot_ai::_autoLootCreatureGold(Creature* creature) const WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); - data << uint8(players.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." + data << uint8(sharers_count <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." (*i)->SendDirectMessage(&data); } } diff --git a/src/server/game/AI/NpcBots/botmgr.cpp b/src/server/game/AI/NpcBots/botmgr.cpp index 3d64b0a322b840..c29efd0c07ad34 100644 --- a/src/server/game/AI/NpcBots/botmgr.cpp +++ b/src/server/game/AI/NpcBots/botmgr.cpp @@ -87,6 +87,8 @@ bool _enableNpcBots; bool _logToDB; bool _xpReductionBlizzlikeEnable; bool _xpReductionBlizzlikeGroupOnly; +bool _moneyLootShareEnable; +bool _moneyLootShareGroupOnly; bool _enableNpcBotsDungeons; bool _enableNpcBotsRaids; bool _enableNpcBotsBGs; @@ -336,6 +338,8 @@ void BotMgr::LoadConfig(bool reload) _xpReductionStartingNumber = sConfigMgr->GetIntDefault("NpcBot.XpReduction.StartingNumber", 2); _xpReductionBlizzlikeEnable = sConfigMgr->GetBoolDefault("NpcBot.XpReduction.Blizzlike.Enable", true); _xpReductionBlizzlikeGroupOnly = sConfigMgr->GetBoolDefault("NpcBot.XpReduction.Blizzlike.GroupOnly", false); + _moneyLootShareEnable = sConfigMgr->GetBoolDefault("NpcBot.MoneyShare.Enable", false); + _moneyLootShareGroupOnly = sConfigMgr->GetBoolDefault("NpcBot.MoneyShare.GroupOnly", false); _mountLevel60 = sConfigMgr->GetIntDefault("NpcBot.MountLevel.60", 20); _mountLevel100 = sConfigMgr->GetIntDefault("NpcBot.MountLevel.100", 40); _healTargetIconFlags = sConfigMgr->GetIntDefault("NpcBot.HealTargetIconMask", 0); @@ -1118,6 +1122,15 @@ bool BotMgr::GetNpcBotXpReductionBlizzlikeGroupOnly() return _xpReductionBlizzlikeGroupOnly; } +bool BotMgr::GetNpcBotMoneyShareEnabled() +{ + return _moneyLootShareEnable; +} +bool BotMgr::GetNpcBotMoneyShareGroupOnly() +{ + return _moneyLootShareGroupOnly; +} + uint8 BotMgr::GetNpcBotMountLevel60() { return _mountLevel60; diff --git a/src/server/game/AI/NpcBots/botmgr.h b/src/server/game/AI/NpcBots/botmgr.h index cea84220eea9d9..496f5cb449a20b 100644 --- a/src/server/game/AI/NpcBots/botmgr.h +++ b/src/server/game/AI/NpcBots/botmgr.h @@ -244,6 +244,8 @@ class AC_GAME_API BotMgr static uint8 GetNpcBotXpReductionStartingNumber(); static bool GetNpcBotXpReductionBlizzlikeEnabled(); static bool GetNpcBotXpReductionBlizzlikeGroupOnly(); + static bool GetNpcBotMoneyShareEnabled(); + static bool GetNpcBotMoneyShareGroupOnly(); static uint8 GetNpcBotMountLevel60(); static uint8 GetNpcBotMountLevel100(); static int32 GetBotInfoPacketsLimit(); diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index cd644bef952d25..0311ec270c8d26 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -30,6 +30,10 @@ #include "WorldPacket.h" #include "WorldSession.h" +//npcbot +#include "botmgr.h" +//end npcbot + void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) { LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); @@ -181,6 +185,50 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) { sScriptMgr->OnBeforeLootMoney(player, loot); loot->NotifyMoneyRemoved(); + //npcbot + if (shareMoney && player->GetGroup() && BotMgr::GetNpcBotMoneyShareEnabled()) + { + Group* group = player->GetGroup(); + std::vector playersNear; + uint32 bots_count = 0; + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player* member = itr->GetSource(); + if (!member) + continue; + + if (player->IsAtGroupRewardDistance(member)) + playersNear.push_back(member); + + if (!member->HaveBot()) + continue; + + BotMap const* botMap = member->GetBotMgr()->GetBotMap(); + for (auto const& kv : *botMap) + { + Creature const* bot = kv.second; + if (bot && bot->IsAlive() && bot->IsInMap(player) && (group->IsMember(kv.first) || !BotMgr::GetNpcBotMoneyShareGroupOnly()) && + (member->GetMap()->IsDungeon() || player->GetDistance(bot) <= sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE))) + ++bots_count; + } + } + + uint32 sharers_count = uint32(playersNear.size()) + bots_count; + uint32 goldPerPlayer = uint32(loot->gold / sharers_count); + + for (std::vector::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) + { + (*i)->ModifyMoney(goldPerPlayer); + (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); + + WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); + data << uint32(goldPerPlayer); + data << uint8(sharers_count <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." + (*i)->SendDirectMessage(&data); + } + } + else + //end npcbot if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup();