mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-18 22:19:54 -04:00
Core/Items: Calculating item level + organized iterating over items (#26276)
* Unified iterating player items into a single function Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
@@ -2644,7 +2644,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
}
|
||||
case CRITERIA_ADDITIONAL_CONDITION_AZERITE_ITEM_LEVEL: // 235
|
||||
{
|
||||
Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE);
|
||||
Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
|
||||
if (!heartOfAzeroth || heartOfAzeroth->ToAzeriteItem()->GetLevel() < reqValue)
|
||||
return false;
|
||||
break;
|
||||
@@ -2693,7 +2693,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
break;
|
||||
case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_LOWER: // 259
|
||||
{
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
|
||||
if (essence.AzeriteEssenceID == reqValue && essence.Rank < secondaryAsset)
|
||||
@@ -2702,7 +2702,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
}
|
||||
case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_EQUAL: // 260
|
||||
{
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
|
||||
if (essence.AzeriteEssenceID == reqValue && essence.Rank == secondaryAsset)
|
||||
@@ -2711,7 +2711,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
}
|
||||
case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_GREATER: // 261
|
||||
{
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
|
||||
if (essence.AzeriteEssenceID == reqValue && essence.Rank > secondaryAsset)
|
||||
@@ -2734,7 +2734,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
return false;
|
||||
break;
|
||||
case CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_LOWER: // 266
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
|
||||
for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
|
||||
@@ -2742,7 +2742,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
|
||||
return true;
|
||||
return false;
|
||||
case CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_GREATER: // 267
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
|
||||
for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
|
||||
|
||||
@@ -2087,7 +2087,7 @@ void GameObject::Use(Unit* user)
|
||||
}
|
||||
case 2: // Heart Forge
|
||||
{
|
||||
Item const* item = player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE);
|
||||
Item const* item = player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
|
||||
@@ -263,43 +263,6 @@ bool Bag::IsEmpty() const
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 Bag::GetItemCount(uint32 item, Item* eItem) const
|
||||
{
|
||||
Item* pItem;
|
||||
uint32 count = 0;
|
||||
for (uint32 i=0; i < GetBagSize(); ++i)
|
||||
{
|
||||
pItem = m_bagslot[i];
|
||||
if (pItem && pItem != eItem && pItem->GetEntry() == item)
|
||||
count += pItem->GetCount();
|
||||
}
|
||||
|
||||
if (eItem && eItem->GetTemplate()->GetGemProperties())
|
||||
{
|
||||
for (uint32 i=0; i < GetBagSize(); ++i)
|
||||
{
|
||||
pItem = m_bagslot[i];
|
||||
if (pItem && pItem != eItem && pItem->GetSocketColor(0))
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32 Bag::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (uint32 i = 0; i < GetBagSize(); ++i)
|
||||
if (Item* pItem = m_bagslot[i])
|
||||
if (pItem != skipItem)
|
||||
if (ItemTemplate const* pProto = pItem->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += m_bagslot[i]->GetCount();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8 Bag::GetSlotByItemGUID(ObjectGuid guid) const
|
||||
{
|
||||
for (uint32 i = 0; i < GetBagSize(); ++i)
|
||||
@@ -317,3 +280,13 @@ Item* Bag::GetItemByPos(uint8 slot) const
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 GetBagSize(Bag const* bag)
|
||||
{
|
||||
return bag->GetBagSize();
|
||||
}
|
||||
|
||||
Item* GetItemInBag(Bag const* bag, uint8 slot)
|
||||
{
|
||||
return bag->GetItemByPos(slot);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ class TC_GAME_API Bag : public Item
|
||||
void RemoveItem(uint8 slot, bool update);
|
||||
|
||||
Item* GetItemByPos(uint8 slot) const;
|
||||
uint32 GetItemCount(uint32 item, Item* eItem = nullptr) const;
|
||||
uint32 GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem = nullptr) const;
|
||||
|
||||
uint8 GetSlotByItemGUID(ObjectGuid guid) const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
@@ -6909,7 +6909,7 @@ void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bo
|
||||
if (id == CURRENCY_TYPE_AZERITE)
|
||||
{
|
||||
if (count > 0)
|
||||
if (Item* heartOfAzeroth = GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item* heartOfAzeroth = GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
heartOfAzeroth->ToAzeriteItem()->GiveXP(uint64(count));
|
||||
return;
|
||||
}
|
||||
@@ -8153,7 +8153,7 @@ void Player::ApplyAzeritePowers(Item* item, bool apply)
|
||||
}
|
||||
else if (AzeriteEmpoweredItem* azeriteEmpoweredItem = item->ToAzeriteEmpoweredItem())
|
||||
{
|
||||
if (!apply || GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_IN_EQUIPMENT))
|
||||
if (!apply || GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Equipment))
|
||||
for (int32 i = 0; i < MAX_AZERITE_EMPOWERED_TIER; ++i)
|
||||
if (AzeritePowerEntry const* azeritePower = sAzeritePowerStore.LookupEntry(azeriteEmpoweredItem->GetSelectedAzeritePower(i)))
|
||||
ApplyAzeritePower(azeriteEmpoweredItem, azeritePower, apply);
|
||||
@@ -9934,128 +9934,53 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
|
||||
|
||||
InventoryResult Player::CanUnequipItems(uint32 item, uint32 count) const
|
||||
{
|
||||
uint32 tempcount = 0;
|
||||
|
||||
InventoryResult res = EQUIP_ERR_OK;
|
||||
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == item)
|
||||
{
|
||||
InventoryResult ires = CanUnequipItem(INVENTORY_SLOT_BAG_0 << 8 | i, false);
|
||||
if (ires == EQUIP_ERR_OK)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
else
|
||||
res = ires;
|
||||
}
|
||||
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == item)
|
||||
uint32 tempcount = 0;
|
||||
bool result = ForEachItem(ItemSearchLocation::Equipment, [this, item, &res, &tempcount, count](Item* pItem)
|
||||
{
|
||||
if (pItem->GetEntry() == item)
|
||||
{
|
||||
InventoryResult ires = CanUnequipItem(pItem->GetPos(), false);
|
||||
if (ires == EQUIP_ERR_OK)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return EQUIP_ERR_OK;
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
else
|
||||
res = ires;
|
||||
}
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
|
||||
if (!result) // we stopped early due to a sucess
|
||||
return EQUIP_ERR_OK;
|
||||
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == item)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == item)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
if (Item* pItem = GetItemByPos(i, j))
|
||||
if (pItem->GetEntry() == item)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
|
||||
// not found req. item count and have unequippable items
|
||||
return res;
|
||||
return res; // return latest error if any
|
||||
}
|
||||
|
||||
uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; i++)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetEntry() == item)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
count += pBag->GetItemCount(item, skipItem);
|
||||
|
||||
if (skipItem && skipItem->GetTemplate()->GetGemProperties())
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetSocketColor(0))
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
bool countGems = skipItem && skipItem->GetTemplate()->GetGemProperties();
|
||||
|
||||
ItemSearchLocation location = ItemSearchLocation::Equipment | ItemSearchLocation::Inventory | ItemSearchLocation::ReagentBank;
|
||||
if (inBankAlso)
|
||||
location |= ItemSearchLocation::Bank;
|
||||
|
||||
uint32 count = 0;
|
||||
ForEachItem(location, [&count, item, skipItem, countGems](Item* pItem)
|
||||
{
|
||||
// checking every item from 39 to 74 (including bank bags)
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetEntry() == item)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
count += pBag->GetItemCount(item, skipItem);
|
||||
|
||||
if (skipItem && skipItem->GetTemplate()->GetGemProperties())
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetSocketColor(0))
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
}
|
||||
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetEntry() == item)
|
||||
if (pItem != skipItem)
|
||||
{
|
||||
if (pItem->GetEntry() == item)
|
||||
count += pItem->GetCount();
|
||||
|
||||
if (skipItem && skipItem->GetTemplate()->GetGemProperties())
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetSocketColor(0))
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
if (countGems)
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
}
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetEntry() == item)
|
||||
count += pItem->GetCount();
|
||||
|
||||
if (skipItem && skipItem->GetTemplate()->GetGemProperties())
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem && pItem->GetSocketColor(0))
|
||||
count += pItem->GetGemCountWithID(item);
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -10063,84 +9988,32 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
|
||||
uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem)
|
||||
if (ItemTemplate const* pProto = pItem->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem);
|
||||
|
||||
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem)
|
||||
if (ItemTemplate const* pProto = pItem->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for (int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem);
|
||||
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem)
|
||||
if (ItemTemplate const* pProto = pItem->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem != skipItem)
|
||||
if (ItemTemplate const* pProto = pItem->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += pItem->GetCount();
|
||||
ForEachItem(ItemSearchLocation::Everywhere, [&count, limitCategory, skipItem](Item* item)
|
||||
{
|
||||
if (item != skipItem)
|
||||
if (ItemTemplate const* pProto = item->GetTemplate())
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
count += item->GetCount();
|
||||
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
Item* Player::GetItemByGuid(ObjectGuid guid) const
|
||||
{
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
Item* result = nullptr;
|
||||
ForEachItem(ItemSearchLocation::Everywhere, [&result, guid](Item* item)
|
||||
{
|
||||
if (item->GetGUID() == guid)
|
||||
{
|
||||
result = item;
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
return nullptr;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
Item* Player::GetItemByPos(uint16 pos) const
|
||||
@@ -10231,18 +10104,17 @@ Item* Player::GetShield(bool useable) const
|
||||
|
||||
Item* Player::GetChildItemByGuid(ObjectGuid guid) const
|
||||
{
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetGUID() == guid)
|
||||
return pItem;
|
||||
|
||||
return nullptr;
|
||||
Item* result = nullptr;
|
||||
ForEachItem(ItemSearchLocation::Equipment | ItemSearchLocation::Inventory, [&result, guid](Item* item)
|
||||
{
|
||||
if (item->GetGUID() == guid)
|
||||
{
|
||||
result = item;
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
WeaponAttackType Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType)
|
||||
@@ -10400,181 +10272,84 @@ void Player::SetInventorySlotCount(uint8 slots)
|
||||
|
||||
bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
||||
{
|
||||
uint32 tempcount = 0;
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < inventoryEnd; i++)
|
||||
{
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
|
||||
{
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
{
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
||||
{
|
||||
Item* pItem = GetItemByPos(i, j);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ItemSearchLocation location = ItemSearchLocation::Equipment | ItemSearchLocation::Inventory | ItemSearchLocation::ReagentBank;
|
||||
if (inBankAlso)
|
||||
{
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; i++)
|
||||
{
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
|
||||
{
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
{
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
||||
{
|
||||
Item* pItem = GetItemByPos(i, j);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
location |= ItemSearchLocation::Bank;
|
||||
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; i++)
|
||||
uint32 currentCount = 0;
|
||||
return !ForEachItem(location, [item, count, ¤tCount](Item* pItem)
|
||||
{
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
if (pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
currentCount += pItem->GetCount();
|
||||
if (currentCount >= count)
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; i++)
|
||||
{
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
bool Player::HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_slot) const
|
||||
{
|
||||
uint32 tempcount = 0;
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
{
|
||||
if (i == except_slot)
|
||||
continue;
|
||||
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetEntry() == item)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
|
||||
if (pProto && pProto->GetGemProperties())
|
||||
bool includeGems = pProto && pProto->GetGemProperties();
|
||||
return !ForEachItem(ItemSearchLocation::Equipment, [item, &tempcount, count, except_slot, includeGems](Item* pItem)
|
||||
{
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
if (pItem->GetSlot() != except_slot)
|
||||
{
|
||||
if (i == except_slot)
|
||||
continue;
|
||||
if (pItem->GetEntry() == item)
|
||||
tempcount += pItem->GetCount();
|
||||
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (pItem && pItem->GetSocketColor(0))
|
||||
{
|
||||
if (includeGems)
|
||||
tempcount += pItem->GetGemCountWithID(item);
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if (tempcount >= count)
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
bool Player::HasItemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count, uint8 except_slot) const
|
||||
{
|
||||
uint32 tempcount = 0;
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
return !ForEachItem(ItemSearchLocation::Equipment, [&tempcount, limitCategory, count, except_slot](Item* pItem)
|
||||
{
|
||||
if (i == except_slot)
|
||||
continue;
|
||||
if (pItem->GetSlot() == except_slot)
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (!pItem)
|
||||
continue;
|
||||
if (pItem->GetTemplate()->GetItemLimitCategory() != limitCategory)
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
|
||||
ItemTemplate const* pProto = pItem->GetTemplate();
|
||||
if (!pProto)
|
||||
continue;
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
|
||||
if (pProto->GetItemLimitCategory() == limitCategory)
|
||||
{
|
||||
tempcount += pItem->GetCount();
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
bool Player::HasGemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count, uint8 except_slot) const
|
||||
{
|
||||
uint32 tempcount = 0;
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
return !ForEachItem(ItemSearchLocation::Equipment, [&tempcount, limitCategory, count, except_slot](Item* pItem)
|
||||
{
|
||||
if (i == except_slot)
|
||||
continue;
|
||||
|
||||
Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||
if (!pItem)
|
||||
continue;
|
||||
if (pItem->GetSlot() == except_slot)
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
|
||||
ItemTemplate const* pProto = pItem->GetTemplate();
|
||||
if (!pProto)
|
||||
continue;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
|
||||
if (pItem->GetSocketColor(0) || pItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT))
|
||||
{
|
||||
tempcount += pItem->GetGemCountWithLimitCategory(limitCategory);
|
||||
if (tempcount >= count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tempcount += pItem->GetGemCountWithLimitCategory(limitCategory);
|
||||
if (tempcount >= count)
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
|
||||
return false;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count /*= nullptr*/, uint32* offendingItemId /*= nullptr*/) const
|
||||
@@ -12232,6 +12007,8 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAverageItemLevelTotal();
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -12488,6 +12265,8 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
|
||||
UpdateCriteria(CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
|
||||
UpdateCriteria(CRITERIA_TYPE_EQUIP_EPIC_ITEM, slot, pItem->GetEntry());
|
||||
|
||||
UpdateAverageItemLevelEquipped();
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
@@ -12738,6 +12517,9 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
|
||||
pItem->SendUpdateToPlayer(this);
|
||||
|
||||
AutoUnequipChildItem(pItem);
|
||||
|
||||
if (bag == INVENTORY_SLOT_BAG_0)
|
||||
UpdateAverageItemLevelEquipped();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12875,6 +12657,10 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
|
||||
pItem->SetContainedIn(ObjectGuid::Empty);
|
||||
pItem->SetSlot(NULL_SLOT);
|
||||
pItem->SetState(ITEM_REMOVED, this);
|
||||
|
||||
UpdateAverageItemLevelTotal();
|
||||
if (bag == INVENTORY_SLOT_BAG_0)
|
||||
UpdateAverageItemLevelEquipped();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13186,100 +12972,36 @@ void Player::DestroyConjuredItems(bool update)
|
||||
DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
|
||||
}
|
||||
|
||||
Item* Player::GetItemByEntry(uint32 entry, ItemSearchLocation where /*= ITEM_SEARCH_DEFAULT*/) const
|
||||
Item* Player::GetItemByEntry(uint32 entry, ItemSearchLocation where /*= ItemSearchLocation::Default */) const
|
||||
{
|
||||
if (where & ITEM_SEARCH_IN_EQUIPMENT)
|
||||
Item* result = nullptr;
|
||||
ForEachItem(where, [&result, entry](Item* item)
|
||||
{
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
if (item->GetEntry() == entry)
|
||||
{
|
||||
result = item;
|
||||
return ItemSearchCallbackResult::Stop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (where & ITEM_SEARCH_IN_INVENTORY)
|
||||
{
|
||||
// in inventory
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
}
|
||||
|
||||
if (where & ITEM_SEARCH_IN_BANK)
|
||||
{
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
|
||||
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
}
|
||||
|
||||
if (where & ITEM_SEARCH_IN_REAGENT_BANK)
|
||||
{
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEntry() == entry)
|
||||
return pItem;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Item*> Player::GetItemListByEntry(uint32 entry, bool inBankAlso) const
|
||||
{
|
||||
std::vector<Item*> itemList = std::vector<Item*>();
|
||||
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < inventoryEnd; ++i)
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* bag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < bag->GetBagSize(); ++j)
|
||||
if (Item* item = bag->GetItemByPos(j))
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
|
||||
ItemSearchLocation location = ItemSearchLocation::Equipment | ItemSearchLocation::Inventory | ItemSearchLocation::ReagentBank;
|
||||
if (inBankAlso)
|
||||
location |= ItemSearchLocation::Bank;
|
||||
|
||||
std::vector<Item*> itemList = std::vector<Item*>();
|
||||
ForEachItem(location, [&itemList, entry](Item* item)
|
||||
{
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
}
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
if (item->GetEntry() == entry)
|
||||
itemList.push_back(item);
|
||||
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@@ -27855,7 +27577,7 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec)
|
||||
activeGlyphs.IsFullUpdate = true;
|
||||
SendDirectMessage(activeGlyphs.Write());
|
||||
|
||||
if (Item* item = GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item* item = GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
{
|
||||
if (AzeriteItem* azeriteItem = item->ToAzeriteItem())
|
||||
{
|
||||
@@ -28950,3 +28672,132 @@ uint8 Player::GetItemLimitCategoryQuantity(ItemLimitCategoryEntry const* limitEn
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool ForEachEquipmentSlot(InventoryType inventoryType, bool canDualWield, bool canTitanGrip, T callback)
|
||||
{
|
||||
switch (inventoryType)
|
||||
{
|
||||
case INVTYPE_HEAD: callback(EQUIPMENT_SLOT_HEAD); return true;
|
||||
case INVTYPE_NECK: callback(EQUIPMENT_SLOT_NECK); return true;
|
||||
case INVTYPE_SHOULDERS: callback(EQUIPMENT_SLOT_SHOULDERS); return true;
|
||||
case INVTYPE_BODY: callback(EQUIPMENT_SLOT_BODY); return true;
|
||||
case INVTYPE_ROBE:
|
||||
case INVTYPE_CHEST: callback(EQUIPMENT_SLOT_CHEST); return true;
|
||||
case INVTYPE_WAIST: callback(EQUIPMENT_SLOT_WAIST); return true;
|
||||
case INVTYPE_LEGS: callback(EQUIPMENT_SLOT_LEGS); return true;
|
||||
case INVTYPE_FEET: callback(EQUIPMENT_SLOT_FEET); return true;
|
||||
case INVTYPE_WRISTS: callback(EQUIPMENT_SLOT_WRISTS); return true;
|
||||
case INVTYPE_HANDS: callback(EQUIPMENT_SLOT_HANDS); return true;
|
||||
case INVTYPE_CLOAK: callback(EQUIPMENT_SLOT_BACK); return true;
|
||||
case INVTYPE_FINGER:
|
||||
callback(EQUIPMENT_SLOT_FINGER1);
|
||||
callback(EQUIPMENT_SLOT_FINGER2, true);
|
||||
return true;
|
||||
case INVTYPE_TRINKET:
|
||||
callback(EQUIPMENT_SLOT_TRINKET1);
|
||||
callback(EQUIPMENT_SLOT_TRINKET2, true);
|
||||
return true;
|
||||
case INVTYPE_WEAPON:
|
||||
callback(EQUIPMENT_SLOT_MAINHAND);
|
||||
if (canDualWield)
|
||||
callback(EQUIPMENT_SLOT_OFFHAND, true);
|
||||
return true;
|
||||
case INVTYPE_2HWEAPON:
|
||||
callback(EQUIPMENT_SLOT_MAINHAND);
|
||||
if (canDualWield && canTitanGrip)
|
||||
callback(EQUIPMENT_SLOT_OFFHAND, true);
|
||||
return true;
|
||||
case INVTYPE_RANGED:
|
||||
case INVTYPE_RANGEDRIGHT:
|
||||
case INVTYPE_WEAPONMAINHAND: callback(EQUIPMENT_SLOT_MAINHAND); return true;
|
||||
case INVTYPE_SHIELD:
|
||||
case INVTYPE_HOLDABLE:
|
||||
case INVTYPE_WEAPONOFFHAND: callback(EQUIPMENT_SLOT_OFFHAND); return true;
|
||||
|
||||
case INVTYPE_NON_EQUIP:
|
||||
case INVTYPE_BAG:
|
||||
case INVTYPE_TABARD:
|
||||
case INVTYPE_AMMO:
|
||||
case INVTYPE_THROWN:
|
||||
case INVTYPE_QUIVER:
|
||||
case INVTYPE_RELIC:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateAverageItemLevelTotal()
|
||||
{
|
||||
std::array<std::tuple<InventoryType, uint32, ObjectGuid>, EQUIPMENT_SLOT_END> bestItemLevels = { };
|
||||
bestItemLevels.fill({ INVTYPE_NON_EQUIP, 0, ObjectGuid::Empty });
|
||||
float sum = 0;
|
||||
|
||||
ForEachItem(ItemSearchLocation::Everywhere, [this, &bestItemLevels, &sum](Item* item)
|
||||
{
|
||||
ItemTemplate const* itemTemplate = item->GetTemplate();
|
||||
if (itemTemplate)
|
||||
{
|
||||
uint16 dest;
|
||||
if (item->IsEquipped())
|
||||
{
|
||||
uint32 itemLevel = item->GetItemLevel(this);
|
||||
InventoryType inventoryType = itemTemplate->GetInventoryType();
|
||||
std::tuple<InventoryType, uint32, ObjectGuid>& slotData = bestItemLevels[item->GetSlot()];
|
||||
if (itemLevel > std::get<1>(slotData))
|
||||
{
|
||||
sum += itemLevel - std::get<1>(slotData);
|
||||
slotData = { inventoryType, itemLevel, item->GetGUID() };
|
||||
}
|
||||
}
|
||||
else if (CanEquipItem(NULL_SLOT, dest, item, true, false) == EQUIP_ERR_OK)
|
||||
{
|
||||
uint32 itemLevel = item->GetItemLevel(this);
|
||||
InventoryType inventoryType = itemTemplate->GetInventoryType();
|
||||
ForEachEquipmentSlot(inventoryType, m_canDualWield, m_canTitanGrip, [&bestItemLevels, item, itemLevel, inventoryType, &sum](EquipmentSlots slot, bool checkDuplicateGuid = false)
|
||||
{
|
||||
if (checkDuplicateGuid)
|
||||
{
|
||||
for (std::tuple<InventoryType, uint32, ObjectGuid> const& slotData : bestItemLevels)
|
||||
if (std::get<2>(slotData) == item->GetGUID())
|
||||
return;
|
||||
}
|
||||
|
||||
std::tuple<InventoryType, uint32, ObjectGuid>& slotData = bestItemLevels[slot];
|
||||
if (itemLevel > std::get<1>(slotData))
|
||||
{
|
||||
sum += itemLevel - std::get<1>(slotData);
|
||||
slotData = { inventoryType, itemLevel, item->GetGUID() };
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return ItemSearchCallbackResult::Continue;
|
||||
});
|
||||
|
||||
// If main hand is a 2h weapon, count it twice
|
||||
std::tuple<InventoryType, uint32, ObjectGuid> const& mainHand = bestItemLevels[EQUIPMENT_SLOT_MAINHAND];
|
||||
if (!m_canTitanGrip && std::get<0>(mainHand) == INVTYPE_2HWEAPON)
|
||||
sum += std::get<1>(mainHand);
|
||||
|
||||
sum /= 16.0f;
|
||||
SetAverageItemLevelTotal(sum);
|
||||
}
|
||||
|
||||
void Player::UpdateAverageItemLevelEquipped()
|
||||
{
|
||||
float totalItemLevel = 0;
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
|
||||
{
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
{
|
||||
uint32 itemLevel = pItem->GetItemLevel(this);
|
||||
totalItemLevel += itemLevel;
|
||||
if (!m_canTitanGrip && i == EQUIPMENT_SLOT_MAINHAND && pItem->GetTemplate()->GetInventoryType() == INVTYPE_2HWEAPON) // 2h weapon counts twice
|
||||
totalItemLevel += itemLevel;
|
||||
}
|
||||
}
|
||||
|
||||
totalItemLevel /= 16.0;
|
||||
SetAverageItemLevelEquipped(totalItemLevel);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ namespace WorldPackets
|
||||
}
|
||||
}
|
||||
|
||||
TC_GAME_API uint32 GetBagSize(Bag const* bag);
|
||||
TC_GAME_API Item* GetItemInBag(Bag const* bag, uint8 slot);
|
||||
|
||||
typedef std::deque<Mail*> PlayerMails;
|
||||
|
||||
#define PLAYER_MAX_SKILLS 256
|
||||
@@ -675,15 +678,23 @@ struct ItemPosCount
|
||||
};
|
||||
typedef std::vector<ItemPosCount> ItemPosCountVec;
|
||||
|
||||
enum ItemSearchLocation
|
||||
enum class ItemSearchLocation
|
||||
{
|
||||
ITEM_SEARCH_IN_EQUIPMENT = 0x01,
|
||||
ITEM_SEARCH_IN_INVENTORY = 0x02,
|
||||
ITEM_SEARCH_IN_BANK = 0x04,
|
||||
ITEM_SEARCH_IN_REAGENT_BANK = 0x08,
|
||||
Equipment = 0x01,
|
||||
Inventory = 0x02,
|
||||
Bank = 0x04,
|
||||
ReagentBank = 0x08,
|
||||
|
||||
ITEM_SEARCH_DEFAULT = ITEM_SEARCH_IN_EQUIPMENT | ITEM_SEARCH_IN_INVENTORY,
|
||||
ITEM_SEARCH_EVERYWHERE = ITEM_SEARCH_IN_EQUIPMENT | ITEM_SEARCH_IN_INVENTORY | ITEM_SEARCH_IN_BANK | ITEM_SEARCH_IN_REAGENT_BANK
|
||||
Default = Equipment | Inventory,
|
||||
Everywhere = Equipment | Inventory | Bank | ReagentBank
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(ItemSearchLocation);
|
||||
|
||||
enum class ItemSearchCallbackResult
|
||||
{
|
||||
Stop,
|
||||
Continue
|
||||
};
|
||||
|
||||
enum TransferAbortReason
|
||||
@@ -1159,11 +1170,77 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
/*** STORAGE SYSTEM ***/
|
||||
/*********************************************************/
|
||||
|
||||
/**
|
||||
* @brief Iterate over each item in the player storage
|
||||
* @tparam T ItemSearchCallbackResult ItemCallback(Item* item)
|
||||
* @param location Locations of the items to iterate over
|
||||
* @param callback Callback called on each item. Will continue as long as it returns ItemSearchCallbackResult::Continue
|
||||
*/
|
||||
template <typename T>
|
||||
bool ForEachItem(ItemSearchLocation location, T callback) const
|
||||
{
|
||||
EnumFlag<ItemSearchLocation> flag = location;
|
||||
|
||||
if (flag.HasFlag(ItemSearchLocation::Equipment))
|
||||
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
|
||||
if (flag.HasFlag(ItemSearchLocation::Inventory))
|
||||
{
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
|
||||
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
|
||||
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < GetBagSize(pBag); ++j)
|
||||
if (Item* pItem = GetItemInBag(pBag, j))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flag.HasFlag(ItemSearchLocation::Bank))
|
||||
{
|
||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
|
||||
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < GetBagSize(pBag); ++j)
|
||||
if (Item* pItem = GetItemInBag(pBag, j))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flag.HasFlag(ItemSearchLocation::ReagentBank))
|
||||
for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (callback(pItem) == ItemSearchCallbackResult::Stop)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
void UpdateAverageItemLevelTotal();
|
||||
void UpdateAverageItemLevelEquipped();
|
||||
|
||||
uint8 FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const;
|
||||
uint32 GetItemCount(uint32 item, bool inBankAlso = false, Item* skipItem = nullptr) const;
|
||||
uint32 GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem = nullptr) const;
|
||||
Item* GetItemByGuid(ObjectGuid guid) const;
|
||||
Item* GetItemByEntry(uint32 entry, ItemSearchLocation where = ITEM_SEARCH_DEFAULT) const;
|
||||
Item* GetItemByEntry(uint32 entry, ItemSearchLocation where = ItemSearchLocation::Default) const;
|
||||
std::vector<Item*> GetItemListByEntry(uint32 entry, bool inBankAlso = false) const;
|
||||
Item* GetItemByPos(uint16 pos) const;
|
||||
Item* GetItemByPos(uint8 bag, uint8 slot) const;
|
||||
@@ -2471,6 +2548,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void RemovePlayerFlagEx(PlayerFlagsEx flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::PlayerFlagsEx), flags); }
|
||||
void SetPlayerFlagsEx(PlayerFlagsEx flags) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::PlayerFlagsEx), flags); }
|
||||
|
||||
void SetAverageItemLevelTotal(float newItemLevel) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::AvgItemLevel, 0), newItemLevel); }
|
||||
void SetAverageItemLevelEquipped(float newItemLevel) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::AvgItemLevel, 1), newItemLevel); }
|
||||
|
||||
uint32 GetCustomizationChoice(uint32 chrCustomizationOptionId) const
|
||||
{
|
||||
int32 choiceIndex = m_playerData->Customizations.FindIndexIf([chrCustomizationOptionId](UF::ChrCustomizationChoice choice)
|
||||
|
||||
@@ -28,7 +28,7 @@ void WorldSession::HandleAzeriteEssenceUnlockMilestone(WorldPackets::Azerite::Az
|
||||
if (!AzeriteItem::FindHeartForge(_player))
|
||||
return;
|
||||
|
||||
Item* item = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE);
|
||||
Item* item = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ void WorldSession::HandleAzeriteEssenceActivateEssence(WorldPackets::Azerite::Az
|
||||
{
|
||||
WorldPackets::Azerite::ActivateEssenceFailed activateEssenceResult;
|
||||
activateEssenceResult.AzeriteEssenceID = azeriteEssenceActivateEssence.AzeriteEssenceID;
|
||||
Item* item = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_IN_EQUIPMENT);
|
||||
Item* item = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Equipment);
|
||||
if (!item)
|
||||
{
|
||||
activateEssenceResult.Reason = AzeriteEssenceActivateResult::NotEquipped;
|
||||
@@ -200,7 +200,7 @@ void WorldSession::HandleAzeriteEmpoweredItemSelectPower(WorldPackets::Azerite::
|
||||
return;
|
||||
|
||||
uint32 azeriteLevel = 0;
|
||||
Item const* heartOfAzeroth = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE);
|
||||
Item const* heartOfAzeroth = _player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
|
||||
if (!heartOfAzeroth)
|
||||
return;
|
||||
|
||||
|
||||
@@ -1364,6 +1364,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
|
||||
if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
|
||||
pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
|
||||
pCurrChar->UpdateAverageItemLevelTotal();
|
||||
pCurrChar->UpdateAverageItemLevelEquipped();
|
||||
|
||||
m_playerLoading.Clear();
|
||||
|
||||
// Handle Login-Achievements (should be handled after loading)
|
||||
|
||||
@@ -65,7 +65,7 @@ void WorldSession::HandleInspectOpcode(WorldPackets::Inspect::Inspect& inspect)
|
||||
inspectResult.GuildData->AchievementPoints = guild->GetAchievementMgr().GetAchievementPoints();
|
||||
}
|
||||
|
||||
if (Item const* heartOfAzeroth = player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE))
|
||||
if (Item const* heartOfAzeroth = player->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
|
||||
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
|
||||
inspectResult.AzeriteLevel = azeriteItem->GetEffectiveLevel();
|
||||
|
||||
|
||||
@@ -5824,7 +5824,7 @@ void Spell::EffectLearnAzeriteEssencePower(SpellEffIndex /*effIndex*/)
|
||||
if (!playerTarget)
|
||||
return;
|
||||
|
||||
Item* heartOfAzeroth = playerTarget->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ITEM_SEARCH_EVERYWHERE);
|
||||
Item* heartOfAzeroth = playerTarget->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
|
||||
if (!heartOfAzeroth)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user