diff --git a/src/server/game/AI/NpcBots/bot_ai.cpp b/src/server/game/AI/NpcBots/bot_ai.cpp index 463d6c26032d2d..775b2edbbd1eb7 100644 --- a/src/server/game/AI/NpcBots/bot_ai.cpp +++ b/src/server/game/AI/NpcBots/bot_ai.cpp @@ -9112,7 +9112,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 if (slot <= BOT_SLOT_RANGED && einfo->ItemEntry[slot] == item->GetEntry()) msg << " |cffe6cc80|h[!" << LocalizedNpcText(player, BOT_TEXT_VISUALONLY) << "!]|h|r"; - msg << " GS: " << uint32(CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot, item->GetTemplate())); + msg << " GS: " << uint32(CalculateItemGearScore(item->GetTemplate(), me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot)); BotWhisper(msg.str(), player); @@ -9199,7 +9199,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 if (visual_only) str << " |cffe6cc80|h[!" << LocalizedNpcText(player, BOT_TEXT_VISUALONLY) << "!]|h|r"; - str << " GS: " << uint32(CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot, item->GetTemplate())); + str << " GS: " << uint32(CalculateItemGearScore(item->GetTemplate(), me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot)); AddGossipItemFor(player, GOSSIP_ICON_CHAT, str.str(), GOSSIP_SENDER_EQUIPMENT_INFO, action); @@ -9264,7 +9264,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 { std::ostringstream name; _AddItemLink(player, item, name); - name << " GS: " << uint32(CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot, item->GetTemplate())); + name << " GS: " << uint32(CalculateItemGearScore(item->GetTemplate(), me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot)); if (BotMgr::SendEquipListItems()) BotWhisper(name.str(), player); AddGossipItemFor(player, GOSSIP_ICON_CHAT, name.str(), GOSSIP_SENDER_EQUIP + slot, GOSSIP_ACTION_INFO_DEF + item->GetGUID().GetCounter()); @@ -9288,7 +9288,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 { std::ostringstream name; _AddItemLink(player, item, name); - name << " GS: " << uint32(CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot, item->GetTemplate())); + name << " GS: " << uint32(CalculateItemGearScore(item->GetTemplate(), me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot)); if (BotMgr::SendEquipListItems()) BotWhisper(name.str(), player); AddGossipItemFor(player, GOSSIP_ICON_CHAT, name.str(), GOSSIP_SENDER_EQUIP + slot, GOSSIP_ACTION_INFO_DEF + item->GetGUID().GetCounter()); @@ -9883,7 +9883,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 else if (GetBotClass() == BOT_CLASS_WARRIOR && _canEquip(proto, BOT_SLOT_MAINHAND, true)) slot = BOT_SLOT_MAINHAND; - name << " GS: " << uint32(CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot, proto)); + name << " GS: " << uint32(CalculateItemGearScore(proto, me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), slot)); AddGossipItemFor(player, GOSSIP_ICON_CHAT, name.str(), GOSSIP_SENDER_EQUIPMENT_BANK_WITHDRAW_ITEM, GOSSIP_ACTION_INFO_DEF + item->GetGUID().GetCounter()); } @@ -10092,7 +10092,7 @@ bool bot_ai::OnGossipSelect(Player* player, Creature* creature/* == me*/, uint32 if (item) { _AddItemLink(player, item, ss); - float item_gs = CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), i, proto); + float item_gs = CalculateItemGearScore(proto, me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), i); gs_total += item_gs; ss << " GS: " << uint32(item_gs); } @@ -14355,7 +14355,7 @@ float bot_ai::_getItemGearStatScore(ItemTemplate const* iproto, uint8 forslot, I for (uint8 i = 0; i != MAX_BOT_ITEM_MOD; ++i) itemScore += istats[i] * _getStatScore(i); - float itemGearScore = CalculateItemGearScore(me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), forslot, iproto); + float itemGearScore = CalculateItemGearScore(iproto, me->GetEntry(), me->GetLevel(), GetBotClass(), GetSpec(), forslot); itemScore += itemGearScore; //BOT_LOG_ERROR("scripts", "_getItemGearScore total score %.3f", itemScore); diff --git a/src/server/game/AI/NpcBots/botdatamgr.cpp b/src/server/game/AI/NpcBots/botdatamgr.cpp index 6e8c7c343fae5a..cadd0a8518e9f9 100644 --- a/src/server/game/AI/NpcBots/botdatamgr.cpp +++ b/src/server/game/AI/NpcBots/botdatamgr.cpp @@ -2,6 +2,7 @@ #include "BattlegroundQueue.h" #include "bot_ai.h" #include "botdatamgr.h" +#include "botgearscore.h" #include "botlog.h" #include "botmgr.h" #include "botspell.h" @@ -78,7 +79,32 @@ bool BotBankItemCompare::operator()(Item const* item1, Item const* item2) const { ItemTemplate const* proto1 = item1->GetTemplate(); ItemTemplate const* proto2 = item2->GetTemplate(); - return proto1->Name1 < proto2->Name1; + + if (proto1->Class == proto2->Class) + { + if (proto1->SubClass == proto2->SubClass) + { + if (proto1->InventoryType == proto2->InventoryType) + { + if (proto1->Quality == proto2->Quality) + { + float gs1 = CalculateItemGearScoreRaw(proto1); + float gs2 = CalculateItemGearScoreRaw(proto1); + if (gs1 == gs2) + { + if (proto1->Name1 == proto2->Name1) + return item1->GetGUID().GetCounter() < item2->GetGUID().GetCounter(); + return proto1->Name1 < proto2->Name1; + } + return gs1 < gs2; + } + return proto1->Quality > proto2->Quality; + } + return proto1->InventoryType < proto2->InventoryType; + } + return proto1->SubClass < proto2->SubClass; + } + return proto1->Class < proto2->Class; } class BotBattlegroundEnterEvent : public BasicEvent diff --git a/src/server/game/AI/NpcBots/botgearscore.cpp b/src/server/game/AI/NpcBots/botgearscore.cpp index 9fe3a3d0edc272..b3415cb76096c8 100644 --- a/src/server/game/AI/NpcBots/botgearscore.cpp +++ b/src/server/game/AI/NpcBots/botgearscore.cpp @@ -55,11 +55,11 @@ constexpr std::pair ItemLevelFactors[2][5] = { } }; -void CalculateRawItemScore(ItemTemplate const* proto, float& score) +float CalculateItemGearScoreRaw(ItemTemplate const* proto) { auto smcit = ItemSlotMods.find(proto->InventoryType); if (smcit == ItemSlotMods.cend()) - return; + return 0.0f; uint32 quality = proto->Quality; float itemlvl = proto->ItemLevel; @@ -83,33 +83,38 @@ void CalculateRawItemScore(ItemTemplate const* proto, float& score) } if (!(quality >= ITEM_QUALITY_UNCOMMON && quality <= ITEM_QUALITY_EPIC)) - return; + return 0.0f; auto const& p = ItemLevelFactors[size_t(itemlvl <= 120.0f)][quality]; - score = floor(((itemlvl - p.first) / p.second) * slotmod * qscale * GS_scale); + return floor(((itemlvl - p.first) / p.second) * slotmod * qscale * GS_scale); } -float CalculateItemGearScore(uint32 botentry, uint8 botlevel, uint8 botclass, uint8 botspec, uint8 slot, ItemTemplate const* proto) +float CalculateItemGearScore(ItemTemplate const* proto, uint32 botentry/* = 0*/, uint8 botlevel/* = 0*/, uint8 botclass/* = 0*/, uint8 botspec/* = 0*/, uint8 slot/* = 18*/) { - ASSERT(slot < BOT_INVENTORY_SIZE, "Invalid bot equip slot %u!", uint32(slot)); - EquipmentInfo const* einfo = BotDataMgr::GetBotEquipmentInfo(botentry); - ASSERT(einfo, "Trying to CalculateItemGearScore for bot %u with no equip info!", botentry); + EquipmentInfo const* einfo = nullptr; + if (botentry) + { + ASSERT(slot < BOT_INVENTORY_SIZE, "Invalid bot equip slot %u!", uint32(slot)); + einfo = BotDataMgr::GetBotEquipmentInfo(botentry); + ASSERT(einfo, "Trying to CalculateItemGearScore for bot %u with no equip info!", botentry); + } float itemscore = 0.0f; - if (slot > BOT_SLOT_RANGED || einfo->ItemEntry[slot] != proto->ItemId) + if (slot > BOT_SLOT_RANGED || !einfo || einfo->ItemEntry[slot] != proto->ItemId) { - CalculateRawItemScore(proto, itemscore); + itemscore = CalculateItemGearScoreRaw(proto); - if (slot == BOT_SLOT_MAINHAND || slot == BOT_SLOT_OFFHAND) + if (botspec == BOT_SPEC_WARRIOR_FURY && botlevel >= 60 && proto->InventoryType == INVTYPE_2HWEAPON) + itemscore *= 0.5f; + else if (botclass == BOT_CLASS_HUNTER) { - if (botspec == BOT_SPEC_WARRIOR_FURY && botlevel >= 60 && proto->InventoryType == INVTYPE_2HWEAPON) - itemscore *= 0.5f; - else if (botclass == BOT_CLASS_HUNTER) + if (proto->InventoryType == INVTYPE_WEAPON || proto->InventoryType == INVTYPE_WEAPONMAINHAND || + proto->InventoryType == INVTYPE_WEAPONOFFHAND || proto->InventoryType == INVTYPE_THROWN) itemscore *= 0.3164f; + else if (proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_RANGEDRIGHT) + itemscore *= 5.3224f; } - else if (slot == BOT_SLOT_RANGED && botclass == BOT_CLASS_HUNTER) - itemscore *= 5.3224f; } return std::max(itemscore, 0.0f); @@ -124,7 +129,7 @@ std::pair CalculateBotGearScore(uint32 botentry, uint8 botlevel, u { if (Item const* item = items[i]) { - float itemscore = CalculateItemGearScore(botentry, botlevel, botclass, botspec, i, item->GetTemplate()); + float itemscore = CalculateItemGearScore(item->GetTemplate(), botentry, botlevel, botclass, botspec, i); if (itemscore > 0.0f) { ++items_count; diff --git a/src/server/game/AI/NpcBots/botgearscore.h b/src/server/game/AI/NpcBots/botgearscore.h index cb96c9ca2d74f9..bc4056839c205b 100644 --- a/src/server/game/AI/NpcBots/botgearscore.h +++ b/src/server/game/AI/NpcBots/botgearscore.h @@ -10,7 +10,8 @@ class Item; struct ItemTemplate; -float CalculateItemGearScore(uint32 botentry, uint8 botlevel, uint8 botclass, uint8 botspec, uint8 slot, ItemTemplate const* proto); +float CalculateItemGearScoreRaw(ItemTemplate const* proto); +float CalculateItemGearScore(ItemTemplate const* proto, uint32 botentry = 0, uint8 botlevel = 0, uint8 botclass = 0, uint8 botspec = 0, uint8 slot = BOT_INVENTORY_SIZE); std::pair CalculateBotGearScore(uint32 botentry, uint8 botlevel, uint8 botclass, uint8 botspec, Item const* const items[BOT_INVENTORY_SIZE]); #endif