From df7664070ddd65dbbebe7b8701f92485dd93fa09 Mon Sep 17 00:00:00 2001 From: trickerer Date: Tue, 26 Nov 2024 09:35:22 +0700 Subject: [PATCH] NPCBots: Implement Blizzlike money sharing --- src/server/game/AI/NpcBots/bot_ai.cpp | 25 +++++++++- src/server/game/AI/NpcBots/botmgr.cpp | 13 ++++++ src/server/game/AI/NpcBots/botmgr.h | 2 + src/server/game/Handlers/LootHandler.cpp | 48 ++++++++++++++++++++ src/server/worldserver/worldserver.conf.dist | 11 +++++ 5 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/server/game/AI/NpcBots/bot_ai.cpp b/src/server/game/AI/NpcBots/bot_ai.cpp index 936874410f6d5..dd692c122aaf6 100644 --- a/src/server/game/AI/NpcBots/bot_ai.cpp +++ b/src/server/game/AI/NpcBots/bot_ai.cpp @@ -12091,7 +12091,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) { @@ -12100,7 +12121,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 67753a2184343..6d8442354ed89 100644 --- a/src/server/game/AI/NpcBots/botmgr.cpp +++ b/src/server/game/AI/NpcBots/botmgr.cpp @@ -86,6 +86,8 @@ bool _enableNpcBots; bool _logToDB; bool _xpReductionBlizzlikeEnable; bool _xpReductionBlizzlikeGroupOnly; +bool _moneyLootShareEnable; +bool _moneyLootShareGroupOnly; bool _enableNpcBotsDungeons; bool _enableNpcBotsRaids; bool _enableNpcBotsBGs; @@ -335,6 +337,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); @@ -1117,6 +1121,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 f5ea93d1251ac..e3ffc6b961aa9 100644 --- a/src/server/game/AI/NpcBots/botmgr.h +++ b/src/server/game/AI/NpcBots/botmgr.h @@ -243,6 +243,8 @@ class TC_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 590e62774b564..4bade8244b147 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -31,6 +31,10 @@ #include "Player.h" #include "WorldPacket.h" +//npcbot +#include "botmgr.h" +//end npcbot + void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); @@ -165,6 +169,50 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) if (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(); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 49d1471026647..7a729b477d17b 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -4231,6 +4231,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