speed up InitEquipment

This commit is contained in:
Yunfan Li
2023-08-10 13:44:46 +08:00
parent 8fc864aa04
commit 3b85e3e4b9
4 changed files with 384 additions and 271 deletions

View File

@@ -6,9 +6,14 @@
#include "AccountMgr.h" #include "AccountMgr.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "ArenaTeamMgr.h" #include "ArenaTeamMgr.h"
#include "DBCStores.h"
#include "GuildMgr.h" #include "GuildMgr.h"
#include "ItemTemplate.h"
#include "Log.h"
#include "LootMgr.h"
#include "MapMgr.h" #include "MapMgr.h"
#include "PetDefines.h" #include "PetDefines.h"
#include "Player.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -961,7 +966,7 @@ bool PlayerbotFactory::CanEquipWeapon(ItemTemplate const* proto)
bool PlayerbotFactory::CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality) bool PlayerbotFactory::CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality)
{ {
if (proto->Duration & 0x80000000) if (proto->Duration != 0)
return false; return false;
if (proto->Quality != desiredQuality) if (proto->Quality != desiredQuality)
@@ -1017,141 +1022,153 @@ void Shuffle(std::vector<uint32>& items)
} }
} }
void PlayerbotFactory::InitEquipmentNew(bool incremental) // void PlayerbotFactory::InitEquipmentNew(bool incremental)
{ // {
if (incremental) // if (incremental)
{ // {
DestroyItemsVisitor visitor(bot); // DestroyItemsVisitor visitor(bot);
IterateItems(&visitor, (IterateItemsMask)(ITERATE_ITEMS_IN_BAGS | ITERATE_ITEMS_IN_BANK)); // IterateItems(&visitor, (IterateItemsMask)(ITERATE_ITEMS_IN_BAGS | ITERATE_ITEMS_IN_BANK));
} // }
else // else
{ // {
DestroyItemsVisitor visitor(bot); // DestroyItemsVisitor visitor(bot);
IterateItems(&visitor, ITERATE_ALL_ITEMS); // IterateItems(&visitor, ITERATE_ALL_ITEMS);
} // }
std::string const& specName = AiFactory::GetPlayerSpecName(bot); // std::string const& specName = AiFactory::GetPlayerSpecName(bot);
if (specName.empty()) // if (specName.empty())
return; // return;
// look for upgrades // // look for upgrades
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) // for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
{ // {
if (slot == EQUIPMENT_SLOT_TABARD && !bot->GetGuildId()) // if (slot == EQUIPMENT_SLOT_TABARD && !bot->GetGuildId())
continue; // continue;
bool isUpgrade = false; // bool isUpgrade = false;
bool found = false; // bool found = false;
bool noItem = false; // bool noItem = false;
uint32 quality = urand(ITEM_QUALITY_UNCOMMON, ITEM_QUALITY_EPIC); // uint32 quality = urand(ITEM_QUALITY_UNCOMMON, ITEM_QUALITY_EPIC);
uint32 attempts = 10; // uint32 attempts = 10;
if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && quality > ITEM_QUALITY_NORMAL) { // if (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && quality > ITEM_QUALITY_NORMAL) {
quality--; // quality--;
} // }
// current item; // // current item;
Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); // Item* oldItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
if (oldItem) // if (oldItem)
isUpgrade = true; // isUpgrade = true;
uint32 itemInSlot = isUpgrade ? oldItem->GetTemplate()->ItemId : 0; // uint32 itemInSlot = isUpgrade ? oldItem->GetTemplate()->ItemId : 0;
uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; // uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel;
if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) // if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); // maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
uint32 minLevel = sPlayerbotAIConfig->randomBotMinLevel; // uint32 minLevel = sPlayerbotAIConfig->randomBotMinLevel;
if (minLevel < sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)) // if (minLevel < sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL))
minLevel = sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL); // minLevel = sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL);
// test // // test
do // do
{ // {
if (isUpgrade) // if (isUpgrade)
{ // {
std::vector<uint32> ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, 0, itemInSlot); // std::vector<uint32> ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, 0, itemInSlot);
if (!ids.empty()) // if (!ids.empty())
Shuffle(ids); // Shuffle(ids);
for (uint32 index = 0; index < ids.size(); ++index) // for (uint32 index = 0; index < ids.size(); ++index)
{ // {
uint32 newItemId = ids[index]; // uint32 newItemId = ids[index];
if (incremental && !IsDesiredReplacement(oldItem)) // if (incremental && !IsDesiredReplacement(oldItem))
{ // {
continue; // continue;
} // }
uint16 dest; // uint16 dest;
if (!CanEquipUnseenItem(slot, dest, newItemId)) // if (!CanEquipUnseenItem(slot, dest, newItemId))
continue; // continue;
if (oldItem) // if (oldItem)
{ // {
bot->RemoveItem(INVENTORY_SLOT_BAG_0, slot, true); // bot->RemoveItem(INVENTORY_SLOT_BAG_0, slot, true);
oldItem->DestroyForPlayer(bot); // oldItem->DestroyForPlayer(bot);
} // }
Item* newItem = bot->EquipNewItem(dest, newItemId, true); // Item* newItem = bot->EquipNewItem(dest, newItemId, true);
if (newItem) // if (newItem)
{ // {
newItem->AddToWorld(); // newItem->AddToWorld();
newItem->AddToUpdateQueueOf(bot); // newItem->AddToUpdateQueueOf(bot);
bot->AutoUnequipOffhandIfNeed(); // bot->AutoUnequipOffhandIfNeed();
newItem->SetOwnerGUID(bot->GetGUID()); // newItem->SetOwnerGUID(bot->GetGUID());
EnchantItem(newItem); // EnchantItem(newItem);
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}, Old item: {}", // LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}, Old item: {}",
bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), newItemId, slot, itemInSlot); // bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), newItemId, slot, itemInSlot);
found = true; // found = true;
break; // break;
} // }
} // }
} // }
else // else
{ // {
std::vector<uint32> ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, quality, itemInSlot); // std::vector<uint32> ids = sRandomItemMgr->GetUpgradeList(bot, specName, slot, quality, itemInSlot);
if (!ids.empty()) // if (!ids.empty())
Shuffle(ids); // Shuffle(ids);
for (uint32 index = 0; index < ids.size(); ++index) // for (uint32 index = 0; index < ids.size(); ++index)
{ // {
uint32 newItemId = ids[index]; // uint32 newItemId = ids[index];
uint16 dest; // uint16 dest;
if (!CanEquipUnseenItem(slot, dest, newItemId)) // if (!CanEquipUnseenItem(slot, dest, newItemId))
continue; // continue;
Item* newItem = bot->EquipNewItem(dest, newItemId, true); // Item* newItem = bot->EquipNewItem(dest, newItemId, true);
if (newItem) // if (newItem)
{ // {
bot->AutoUnequipOffhandIfNeed(); // bot->AutoUnequipOffhandIfNeed();
newItem->SetOwnerGUID(bot->GetGUID()); // newItem->SetOwnerGUID(bot->GetGUID());
EnchantItem(newItem); // EnchantItem(newItem);
found = true; // found = true;
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}", // LOG_INFO("playerbots", "Bot {} {}:{} <{}>: Equip: {}, slot: {}",
bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), newItemId, slot); // bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), newItemId, slot);
break; // break;
} // }
} // }
} // }
quality--; // quality--;
} while (!found && quality != ITEM_QUALITY_POOR); // } while (!found && quality != ITEM_QUALITY_POOR);
if (!found) // if (!found)
{ // {
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: no item for slot {}", // LOG_INFO("playerbots", "Bot {} {}:{} <{}>: no item for slot {}",
bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), slot); // bot->GetGUID().ToString().c_str(), IsAlliance(bot->getRace()) ? "A" : "H", bot->getLevel(), bot->GetName(), slot);
continue; // continue;
} // }
} // }
} // }
void PlayerbotFactory::InitEquipment(bool incremental) void PlayerbotFactory::InitEquipment(bool incremental)
{ {
// todo(yunfan): to be refactored, too much time overhead // todo(yunfan): to be refactored, too much time overhead
// DestroyItemsVisitor visitor(bot);
// IterateItems(&visitor, ITERATE_ALL_ITEMS);
std::map<uint8, std::vector<uint32> > items; std::map<uint8, std::vector<uint32> > items;
int tab = AiFactory::GetPlayerSpecTab(bot); int tab = AiFactory::GetPlayerSpecTab(bot);
// todo(yunfan): make cache for this
uint32 blevel = bot->getLevel();
int32 delta = 2;
if (blevel < 15)
delta = 15;
else if (blevel < 40)
delta = 10;
else if (blevel < 60)
delta = 6;
else if (blevel < 70)
delta = 9;
else if (blevel < 80)
delta = 9;
else if (blevel == 80)
delta = 2;
for(uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) for(uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
{ {
if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY) if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY)
@@ -1163,46 +1180,44 @@ void PlayerbotFactory::InitEquipment(bool incremental)
} }
do do
{ {
ItemTemplateContainer const* itemTemplates = sObjectMgr->GetItemTemplateStore(); ItemTemplateContainer const* itemTemplate = sObjectMgr->GetItemTemplateStore();
for (ItemTemplateContainer::const_iterator i = itemTemplates->begin(); i != itemTemplates->end(); ++i) for (uint32 requiredLevel = bot->GetLevel(); requiredLevel > std::max((int32)bot->GetLevel() - delta, 0); requiredLevel--) {
{ for (InventoryType inventoryType : GetPossibleInventoryTypeListBySlot((EquipmentSlots)slot)) {
uint32 itemId = i->first; for (uint32 itemId : sRandomItemMgr->GetCachedEquipments(requiredLevel, inventoryType)) {
if (sRandomItemMgr->IsTestItem(itemId)) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
continue; if (!proto)
continue;
if (proto->Class != ITEM_CLASS_WEAPON &&
proto->Class != ITEM_CLASS_ARMOR)
continue;
if (!CanEquipItem(proto, desiredQuality))
continue;
if (proto->Class == ITEM_CLASS_ARMOR && (
slot == EQUIPMENT_SLOT_HEAD ||
slot == EQUIPMENT_SLOT_SHOULDERS ||
slot == EQUIPMENT_SLOT_CHEST ||
slot == EQUIPMENT_SLOT_WAIST ||
slot == EQUIPMENT_SLOT_LEGS ||
slot == EQUIPMENT_SLOT_FEET ||
slot == EQUIPMENT_SLOT_WRISTS ||
slot == EQUIPMENT_SLOT_HANDS) && !CanEquipArmor(proto))
continue;
if (proto->Class == ITEM_CLASS_WEAPON && !CanEquipWeapon(proto))
continue;
if (slot == EQUIPMENT_SLOT_OFFHAND && bot->getClass() == CLASS_ROGUE && proto->Class != ITEM_CLASS_WEAPON)
continue;
uint16 dest = 0;
if (CanEquipUnseenItem(slot, dest, itemId))
items[slot].push_back(itemId);
}
} }
ItemTemplate const* proto = &i->second; if (items[slot].size() >= 10) break;
if (!proto)
continue;
if (proto->Class != ITEM_CLASS_WEAPON &&
proto->Class != ITEM_CLASS_ARMOR &&
proto->Class != ITEM_CLASS_CONTAINER &&
proto->Class != ITEM_CLASS_PROJECTILE)
continue;
if (!CanEquipItem(proto, desiredQuality))
continue;
if (proto->Class == ITEM_CLASS_ARMOR && (
slot == EQUIPMENT_SLOT_HEAD ||
slot == EQUIPMENT_SLOT_SHOULDERS ||
slot == EQUIPMENT_SLOT_CHEST ||
slot == EQUIPMENT_SLOT_WAIST ||
slot == EQUIPMENT_SLOT_LEGS ||
slot == EQUIPMENT_SLOT_FEET ||
slot == EQUIPMENT_SLOT_WRISTS ||
slot == EQUIPMENT_SLOT_HANDS) && !CanEquipArmor(proto))
continue;
if (proto->Class == ITEM_CLASS_WEAPON && !CanEquipWeapon(proto))
continue;
if (slot == EQUIPMENT_SLOT_OFFHAND && bot->getClass() == CLASS_ROGUE && proto->Class != ITEM_CLASS_WEAPON)
continue;
uint16 dest = 0;
if (CanEquipUnseenItem(slot, dest, itemId))
items[slot].push_back(itemId);
} }
} while (items[slot].size() < 10 && desiredQuality-- > ITEM_QUALITY_NORMAL); } while (items[slot].size() < 10 && desiredQuality-- > ITEM_QUALITY_NORMAL);
} }
@@ -1245,9 +1260,7 @@ void PlayerbotFactory::InitEquipment(bool incremental)
} }
if (oldItem) if (oldItem)
{ {
// bot->RemoveItem(INVENTORY_SLOT_BAG_0, slot, true);
bot->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true); bot->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true);
// oldItem->DestroyForPlayer(bot, false);
} }
uint16 dest; uint16 dest;
if (!CanEquipUnseenItem(slot, dest, bestItemForSlot)) { if (!CanEquipUnseenItem(slot, dest, bestItemForSlot)) {
@@ -1271,10 +1284,13 @@ bool PlayerbotFactory::IsDesiredReplacement(Item* item)
ItemTemplate const* proto = item->GetTemplate(); ItemTemplate const* proto = item->GetTemplate();
uint32 requiredLevel = proto->RequiredLevel; uint32 requiredLevel = proto->RequiredLevel;
if (!requiredLevel) if (!requiredLevel) {
{ return true;
requiredLevel = sRandomItemMgr->GetMinLevelFromCache(proto->ItemId);
} }
// if (!requiredLevel)
// {
// requiredLevel = sRandomItemMgr->GetMinLevelFromCache(proto->ItemId);
// }
uint32 delta = 1 + (80 - bot->getLevel()) / 10; uint32 delta = 1 + (80 - bot->getLevel()) / 10;
return int32(bot->getLevel() - requiredLevel) > delta; return int32(bot->getLevel() - requiredLevel) > delta;
@@ -1295,110 +1311,110 @@ inline Item* StoreNewItemInInventorySlot(Player* player, uint32 newItemId, uint3
return nullptr; return nullptr;
} }
void PlayerbotFactory::InitSecondEquipmentSet() // void PlayerbotFactory::InitSecondEquipmentSet()
{ // {
if (bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || bot->getClass() == CLASS_PRIEST) // if (bot->getClass() == CLASS_MAGE || bot->getClass() == CLASS_WARLOCK || bot->getClass() == CLASS_PRIEST)
return; // return;
std::map<uint32, std::vector<uint32>> items; // std::map<uint32, std::vector<uint32>> items;
uint32 desiredQuality = itemQuality; // uint32 desiredQuality = itemQuality;
while (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL) // while (urand(0, 100) < 100 * sPlayerbotAIConfig->randomGearLoweringChance && desiredQuality > ITEM_QUALITY_NORMAL)
{ // {
desiredQuality--; // desiredQuality--;
} // }
ItemTemplateContainer const* itemTemplate = sObjectMgr->GetItemTemplateStore(); // ItemTemplateContainer const* itemTemplate = sObjectMgr->GetItemTemplateStore();
do // do
{ // {
for (auto const& itr : *itemTemplate) // for (auto const& itr : *itemTemplate)
{ // {
ItemTemplate const* proto = &itr.second; // ItemTemplate const* proto = &itr.second;
if (!proto) // if (!proto)
continue; // continue;
if (!CanEquipItem(proto, desiredQuality)) // if (!CanEquipItem(proto, desiredQuality))
continue; // continue;
if (proto->Class == ITEM_CLASS_WEAPON) // if (proto->Class == ITEM_CLASS_WEAPON)
{ // {
//if (!CanEquipWeapon(proto)) // //if (!CanEquipWeapon(proto))
// continue; // // continue;
if (sRandomItemMgr->HasStatWeight(proto->ItemId)) // if (sRandomItemMgr->HasStatWeight(proto->ItemId))
{ // {
if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId)) // if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId))
continue; // continue;
} // }
Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); // Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
if (existingItem) // if (existingItem)
{ // {
switch (existingItem->GetTemplate()->SubClass) // switch (existingItem->GetTemplate()->SubClass)
{ // {
case ITEM_SUBCLASS_WEAPON_AXE: // case ITEM_SUBCLASS_WEAPON_AXE:
case ITEM_SUBCLASS_WEAPON_DAGGER: // case ITEM_SUBCLASS_WEAPON_DAGGER:
case ITEM_SUBCLASS_WEAPON_FIST: // case ITEM_SUBCLASS_WEAPON_FIST:
case ITEM_SUBCLASS_WEAPON_MACE: // case ITEM_SUBCLASS_WEAPON_MACE:
case ITEM_SUBCLASS_WEAPON_SWORD: // case ITEM_SUBCLASS_WEAPON_SWORD:
if (proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || proto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER || proto->SubClass == ITEM_SUBCLASS_WEAPON_FIST || // if (proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE || proto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER || proto->SubClass == ITEM_SUBCLASS_WEAPON_FIST ||
proto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD) // proto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD)
continue; // continue;
break; // break;
default: // default:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && // if (proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD) // proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
continue; // continue;
break; // break;
} // }
} // }
} // }
else if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) // else if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)
{ // {
//if (!CanEquipArmor(proto)) // //if (!CanEquipArmor(proto))
// continue; // // continue;
if (sRandomItemMgr->HasStatWeight(proto->ItemId)) // if (sRandomItemMgr->HasStatWeight(proto->ItemId))
{ // {
if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId)) // if (!sRandomItemMgr->GetLiveStatWeight(bot, proto->ItemId))
continue; // continue;
} // }
if (Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) // if (Item* existingItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
if (existingItem->GetTemplate()->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD) // if (existingItem->GetTemplate()->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD)
continue; // continue;
} // }
else // else
continue; // continue;
items[proto->Class].push_back(itr.first); // items[proto->Class].push_back(itr.first);
} // }
} while (items[ITEM_CLASS_ARMOR].empty() && items[ITEM_CLASS_WEAPON].empty() && desiredQuality-- > ITEM_QUALITY_NORMAL); // } while (items[ITEM_CLASS_ARMOR].empty() && items[ITEM_CLASS_WEAPON].empty() && desiredQuality-- > ITEM_QUALITY_NORMAL);
for (std::map<uint32, std::vector<uint32>>::iterator i = items.begin(); i != items.end(); ++i) // for (std::map<uint32, std::vector<uint32>>::iterator i = items.begin(); i != items.end(); ++i)
{ // {
std::vector<uint32>& ids = i->second; // std::vector<uint32>& ids = i->second;
if (ids.empty()) // if (ids.empty())
{ // {
LOG_DEBUG("playerbots", "{}: no items to make second equipment set for slot {}", bot->GetName().c_str(), i->first); // LOG_DEBUG("playerbots", "{}: no items to make second equipment set for slot {}", bot->GetName().c_str(), i->first);
continue; // continue;
} // }
for (uint32 attempts = 0; attempts < 15; attempts++) // for (uint32 attempts = 0; attempts < 15; attempts++)
{ // {
uint32 index = urand(0, ids.size() - 1); // uint32 index = urand(0, ids.size() - 1);
uint32 newItemId = ids[index]; // uint32 newItemId = ids[index];
if (Item* newItem = StoreNewItemInInventorySlot(bot, newItemId, 1)) // if (Item* newItem = StoreNewItemInInventorySlot(bot, newItemId, 1))
{ // {
newItem->SetOwnerGUID(bot->GetGUID()); // newItem->SetOwnerGUID(bot->GetGUID());
EnchantItem(newItem); // EnchantItem(newItem);
newItem->AddToWorld(); // newItem->AddToWorld();
newItem->AddToUpdateQueueOf(bot); // newItem->AddToUpdateQueueOf(bot);
break; // break;
} // }
} // }
} // }
} // }
void PlayerbotFactory::InitBags() void PlayerbotFactory::InitBags()
{ {
@@ -1769,18 +1785,22 @@ void PlayerbotFactory::InitAvailableSpells()
{ {
bot->LearnDefaultSkills(); bot->LearnDefaultSkills();
CreatureTemplateContainer const* creatureTemplateContainer = sObjectMgr->GetCreatureTemplates(); if (trainerIdCache.empty()) {
for (CreatureTemplateContainer::const_iterator i = creatureTemplateContainer->begin(); i != creatureTemplateContainer->end(); ++i) CreatureTemplateContainer const* creatureTemplateContainer = sObjectMgr->GetCreatureTemplates();
{ for (CreatureTemplateContainer::const_iterator i = creatureTemplateContainer->begin(); i != creatureTemplateContainer->end(); ++i)
CreatureTemplate const& co = i->second; {
if (co.trainer_type != TRAINER_TYPE_TRADESKILLS && co.trainer_type != TRAINER_TYPE_CLASS) CreatureTemplate const& co = i->second;
continue; if (co.trainer_type != TRAINER_TYPE_TRADESKILLS && co.trainer_type != TRAINER_TYPE_CLASS)
continue;
if (co.trainer_type == TRAINER_TYPE_CLASS && co.trainer_class != bot->getClass()) if (co.trainer_type == TRAINER_TYPE_CLASS && co.trainer_class != bot->getClass())
continue; continue;
uint32 trainerId = co.Entry;
uint32 trainerId = co.Entry;
trainerIdCache.push_back(trainerId);
}
}
for (uint32 trainerId : trainerIdCache) {
TrainerSpellData const* trainer_spells = sObjectMgr->GetNpcTrainerSpells(trainerId); TrainerSpellData const* trainer_spells = sObjectMgr->GetNpcTrainerSpells(trainerId);
if (!trainer_spells) if (!trainer_spells)
trainer_spells = sObjectMgr->GetNpcTrainerSpells(trainerId); trainer_spells = sObjectMgr->GetNpcTrainerSpells(trainerId);
@@ -1788,7 +1808,7 @@ void PlayerbotFactory::InitAvailableSpells()
if (!trainer_spells) if (!trainer_spells)
continue; continue;
for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
{ {
TrainerSpell const* tSpell = &itr->second; TrainerSpell const* tSpell = &itr->second;
@@ -1825,7 +1845,6 @@ void PlayerbotFactory::InitAvailableSpells()
bot->learnSpell(tSpell->learnedSpell[0], false); bot->learnSpell(tSpell->learnedSpell[0], false);
} }
else { else {
LOG_INFO("playerbots", "!tSpell->learnedSpell[0] {}", tSpell->spell);
botAI->CastSpell(tSpell->spell, bot); botAI->CastSpell(tSpell->spell, bot);
} }
} }
@@ -2810,6 +2829,74 @@ void PlayerbotFactory::ApplyEnchantTemplate(uint8 spec)
botAI->EnchantItemT((*itr).SpellId, (*itr).SlotId); botAI->EnchantItemT((*itr).SpellId, (*itr).SlotId);
} }
std::vector<InventoryType> PlayerbotFactory::GetPossibleInventoryTypeListBySlot(EquipmentSlots slot) {
std::vector<InventoryType> ret;
switch (slot) {
case EQUIPMENT_SLOT_HEAD:
ret.push_back(INVTYPE_HEAD);
break;
case EQUIPMENT_SLOT_NECK:
ret.push_back(INVTYPE_NECK);
break;
case EQUIPMENT_SLOT_SHOULDERS:
ret.push_back(INVTYPE_SHOULDERS);
break;
case EQUIPMENT_SLOT_BODY:
ret.push_back(INVTYPE_BODY);
break;
case EQUIPMENT_SLOT_CHEST:
ret.push_back(INVTYPE_CHEST);
ret.push_back(INVTYPE_ROBE);
break;
case EQUIPMENT_SLOT_WAIST:
ret.push_back(INVTYPE_WAIST);
break;
case EQUIPMENT_SLOT_LEGS:
ret.push_back(INVTYPE_LEGS);
break;
case EQUIPMENT_SLOT_FEET:
ret.push_back(INVTYPE_FEET);
break;
case EQUIPMENT_SLOT_WRISTS:
ret.push_back(INVTYPE_WRISTS);
break;
case EQUIPMENT_SLOT_HANDS:
ret.push_back(INVTYPE_HANDS);
break;
case EQUIPMENT_SLOT_FINGER1:
case EQUIPMENT_SLOT_FINGER2:
ret.push_back(INVTYPE_FINGER);
break;
case EQUIPMENT_SLOT_TRINKET1:
case EQUIPMENT_SLOT_TRINKET2:
ret.push_back(INVTYPE_TRINKET);
break;
case EQUIPMENT_SLOT_BACK:
ret.push_back(INVTYPE_CLOAK);
break;
case EQUIPMENT_SLOT_MAINHAND:
ret.push_back(INVTYPE_WEAPON);
ret.push_back(INVTYPE_2HWEAPON);
ret.push_back(INVTYPE_WEAPONMAINHAND);
break;
case EQUIPMENT_SLOT_OFFHAND:
ret.push_back(INVTYPE_WEAPON);
ret.push_back(INVTYPE_2HWEAPON);
ret.push_back(INVTYPE_WEAPONOFFHAND);
ret.push_back(INVTYPE_SHIELD);
ret.push_back(INVTYPE_HOLDABLE);
break;
case EQUIPMENT_SLOT_RANGED:
ret.push_back(INVTYPE_RANGED);
ret.push_back(INVTYPE_RANGEDRIGHT);
ret.push_back(INVTYPE_RELIC);
break;
default:
break;
}
return ret;
}
void PlayerbotFactory::LoadEnchantContainer() void PlayerbotFactory::LoadEnchantContainer()
{ {
m_EnchantContainer.clear(); m_EnchantContainer.clear();
@@ -3022,4 +3109,4 @@ bool PlayerbotFactory::NotSameArmorType(uint32 item_subclass_armor, Player* bot)
return item_subclass_armor != ITEM_SUBCLASS_ARMOR_LEATHER; return item_subclass_armor != ITEM_SUBCLASS_ARMOR_LEATHER;
} }
return false; return false;
} }

View File

@@ -6,9 +6,9 @@
#define _PLAYERBOT_PLAYERBOTFACTORY_H #define _PLAYERBOT_PLAYERBOTFACTORY_H
#include "InventoryAction.h" #include "InventoryAction.h"
#include "Player.h"
class Item; class Item;
class Player;
struct ItemTemplate; struct ItemTemplate;
@@ -123,8 +123,8 @@ class PlayerbotFactory : public InventoryAction
private: private:
void Prepare(); void Prepare();
void InitSecondEquipmentSet(); // void InitSecondEquipmentSet();
void InitEquipmentNew(bool incremental); // void InitEquipmentNew(bool incremental);
bool CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality); bool CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality);
bool CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item); bool CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item);
void InitTradeSkills(); void InitTradeSkills();
@@ -166,15 +166,15 @@ class PlayerbotFactory : public InventoryAction
void LoadEnchantContainer(); void LoadEnchantContainer();
void ApplyEnchantTemplate(); void ApplyEnchantTemplate();
void ApplyEnchantTemplate(uint8 spec); void ApplyEnchantTemplate(uint8 spec);
std::vector<InventoryType> GetPossibleInventoryTypeListBySlot(EquipmentSlots slot);
static bool IsShieldTank(Player* bot); static bool IsShieldTank(Player* bot);
static bool NotSameArmorType(uint32 item_subclass_armor, Player* bot); static bool NotSameArmorType(uint32 item_subclass_armor, Player* bot);
EnchantContainer::const_iterator GetEnchantContainerBegin() { return m_EnchantContainer.begin(); } EnchantContainer::const_iterator GetEnchantContainerBegin() { return m_EnchantContainer.begin(); }
EnchantContainer::const_iterator GetEnchantContainerEnd() { return m_EnchantContainer.end(); } EnchantContainer::const_iterator GetEnchantContainerEnd() { return m_EnchantContainer.end(); }
uint32 level; uint32 level;
uint32 itemQuality; uint32 itemQuality;
static std::list<uint32> specialQuestIds; static std::list<uint32> specialQuestIds;
std::vector<uint32> trainerIdCache;
protected: protected:
EnchantContainer m_EnchantContainer; EnchantContainer m_EnchantContainer;
}; };

View File

@@ -154,6 +154,7 @@ void RandomItemMgr::Init()
{ {
BuildItemInfoCache(); BuildItemInfoCache();
// BuildEquipCache(); // BuildEquipCache();
BuildEquipCacheNew();
BuildAmmoCache(); BuildAmmoCache();
BuildPotionCache(); BuildPotionCache();
BuildFoodCache(); BuildFoodCache();
@@ -441,6 +442,11 @@ bool RandomItemMgr::CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank)
return sp || ap || tank; return sp || ap || tank;
} }
std::vector<uint32> RandomItemMgr::GetCachedEquipments(uint32 requiredLevel, uint32 inventoryType)
{
return equipCacheNew[requiredLevel][inventoryType];
}
bool RandomItemMgr::ShouldEquipArmorForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto) bool RandomItemMgr::ShouldEquipArmorForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto)
{ {
if (proto->InventoryType == INVTYPE_TABARD) if (proto->InventoryType == INVTYPE_TABARD)
@@ -2139,6 +2145,23 @@ void RandomItemMgr::BuildEquipCache()
} }
} }
void RandomItemMgr::BuildEquipCacheNew()
{
LOG_INFO("playerbots", "Loading equipments cache...");
ItemTemplateContainer const* itemTemplates = sObjectMgr->GetItemTemplateStore();
for (auto const& itr : *itemTemplates)
{
ItemTemplate const* proto = &itr.second;
if (!proto)
continue;
uint32 itemId = proto->ItemId;
if (IsTestItem(itemId)) {
continue;
}
equipCacheNew[proto->RequiredLevel][proto->InventoryType].push_back(itemId);
}
}
RandomItemList RandomItemMgr::Query(uint32 level, uint8 clazz, uint8 slot, uint32 quality) RandomItemList RandomItemMgr::Query(uint32 level, uint8 clazz, uint8 slot, uint32 quality)
{ {
// return equipCache[key]; // return equipCache[key];

View File

@@ -166,10 +166,12 @@ class RandomItemMgr
std::vector<uint32> GetQuestIdsForItem(uint32 itemId); std::vector<uint32> GetQuestIdsForItem(uint32 itemId);
static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId); static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId);
bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); } bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); }
std::vector<uint32> GetCachedEquipments(uint32 requiredLevel, uint32 inventoryType);
private: private:
void BuildRandomItemCache(); void BuildRandomItemCache();
void BuildEquipCache(); void BuildEquipCache();
void BuildEquipCacheNew();
void BuildItemInfoCache(); void BuildItemInfoCache();
void BuildAmmoCache(); void BuildAmmoCache();
void BuildFoodCache(); void BuildFoodCache();
@@ -180,7 +182,6 @@ class RandomItemMgr
bool CanEquipItemNew(ItemTemplate const* proto); bool CanEquipItemNew(ItemTemplate const* proto);
void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank); void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank);
bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank); bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank);
private: private:
std::map<uint32, RandomItemCache> randomItemCache; std::map<uint32, RandomItemCache> randomItemCache;
std::map<RandomItemType, RandomItemPredicate*> predicates; std::map<RandomItemType, RandomItemPredicate*> predicates;
@@ -197,6 +198,8 @@ class RandomItemMgr
std::map<uint32, ItemInfoEntry> itemInfoCache; std::map<uint32, ItemInfoEntry> itemInfoCache;
std::set<uint32> itemForTest; std::set<uint32> itemForTest;
static std::set<uint32> itemCache; static std::set<uint32> itemCache;
// equipCacheNew[RequiredLevel][InventoryType]
std::map<uint32, std::map<uint32, std::vector<uint32>>> equipCacheNew;
}; };
#define sRandomItemMgr RandomItemMgr::instance() #define sRandomItemMgr RandomItemMgr::instance()