mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/Items: Fixed generating default bonuses based on context
This commit is contained in:
@@ -973,14 +973,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
|
||||
_itemLevelDeltaToBonusListContainer[itemBonusListLevelDelta->ItemLevelDelta] = itemBonusListLevelDelta->ID;
|
||||
|
||||
for (ItemBonusTreeNodeEntry const* bonusTreeNode : sItemBonusTreeNodeStore)
|
||||
{
|
||||
uint32 bonusTreeId = bonusTreeNode->ParentItemBonusTreeID;
|
||||
while (bonusTreeNode)
|
||||
{
|
||||
_itemBonusTrees[bonusTreeId].insert(bonusTreeNode);
|
||||
bonusTreeNode = sItemBonusTreeNodeStore.LookupEntry(bonusTreeNode->ChildItemBonusTreeID);
|
||||
}
|
||||
}
|
||||
_itemBonusTrees[bonusTreeNode->ParentItemBonusTreeID].insert(bonusTreeNode);
|
||||
|
||||
for (ItemChildEquipmentEntry const* itemChildEquipment : sItemChildEquipmentStore)
|
||||
{
|
||||
@@ -2035,26 +2028,21 @@ uint32 DB2Manager::GetItemBonusListForItemLevelDelta(int16 delta) const
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void VisitItemBonusTree(uint32 itemId, Visitor visitor)
|
||||
void VisitItemBonusTree(uint32 itemBonusTreeId, bool visitChildren, Visitor visitor)
|
||||
{
|
||||
auto itemIdRange = _itemToBonusTree.equal_range(itemId);
|
||||
if (itemIdRange.first == itemIdRange.second)
|
||||
auto treeItr = _itemBonusTrees.find(itemBonusTreeId);
|
||||
if (treeItr == _itemBonusTrees.end())
|
||||
return;
|
||||
|
||||
for (auto itemTreeItr = itemIdRange.first; itemTreeItr != itemIdRange.second; ++itemTreeItr)
|
||||
for (ItemBonusTreeNodeEntry const* bonusTreeNode : treeItr->second)
|
||||
{
|
||||
auto treeItr = _itemBonusTrees.find(itemTreeItr->second);
|
||||
if (treeItr == _itemBonusTrees.end())
|
||||
continue;
|
||||
|
||||
for (ItemBonusTreeNodeEntry const* bonusTreeNode : treeItr->second)
|
||||
{
|
||||
visitor(bonusTreeNode);
|
||||
}
|
||||
visitor(bonusTreeNode);
|
||||
if (visitChildren && bonusTreeNode->ChildItemBonusTreeID)
|
||||
VisitItemBonusTree(bonusTreeNode->ChildItemBonusTreeID, true, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<uint32> DB2Manager::GetItemBonusTree(uint32 itemId, ItemContext itemContext) const
|
||||
std::set<uint32> DB2Manager::GetDefaultItemBonusTree(uint32 itemId, ItemContext itemContext) const
|
||||
{
|
||||
std::set<uint32> bonusListIDs;
|
||||
|
||||
@@ -2062,98 +2050,121 @@ std::set<uint32> DB2Manager::GetItemBonusTree(uint32 itemId, ItemContext itemCon
|
||||
if (!proto)
|
||||
return bonusListIDs;
|
||||
|
||||
VisitItemBonusTree(itemId, [this, proto, itemContext, &bonusListIDs](ItemBonusTreeNodeEntry const* bonusTreeNode)
|
||||
{
|
||||
if (ItemContext(bonusTreeNode->ItemContext) != itemContext)
|
||||
return;
|
||||
auto itemIdRange = _itemToBonusTree.equal_range(itemId);
|
||||
if (itemIdRange.first == itemIdRange.second)
|
||||
return bonusListIDs;
|
||||
|
||||
if (bonusTreeNode->ChildItemBonusListID)
|
||||
uint16 itemLevelSelectorId = 0;
|
||||
for (auto itemTreeItr = itemIdRange.first; itemTreeItr != itemIdRange.second; ++itemTreeItr)
|
||||
{
|
||||
uint32 matchingNodes = 0;
|
||||
VisitItemBonusTree(itemTreeItr->second, false, [itemContext, &matchingNodes](ItemBonusTreeNodeEntry const* bonusTreeNode)
|
||||
{
|
||||
bonusListIDs.insert(bonusTreeNode->ChildItemBonusListID);
|
||||
}
|
||||
else if (bonusTreeNode->ChildItemLevelSelectorID)
|
||||
if (ItemContext(bonusTreeNode->ItemContext) == ItemContext::NONE || itemContext == ItemContext(bonusTreeNode->ItemContext))
|
||||
++matchingNodes;
|
||||
});
|
||||
|
||||
if (matchingNodes != 1)
|
||||
continue;
|
||||
|
||||
VisitItemBonusTree(itemTreeItr->second, true, [itemContext, &bonusListIDs, &itemLevelSelectorId](ItemBonusTreeNodeEntry const* bonusTreeNode)
|
||||
{
|
||||
ItemLevelSelectorEntry const* selector = sItemLevelSelectorStore.LookupEntry(bonusTreeNode->ChildItemLevelSelectorID);
|
||||
if (!selector)
|
||||
ItemContext requiredContext = ItemContext(bonusTreeNode->ItemContext) != ItemContext::Force_to_NONE ? ItemContext(bonusTreeNode->ItemContext) : ItemContext::NONE;
|
||||
if (ItemContext(bonusTreeNode->ItemContext) != ItemContext::NONE && itemContext != requiredContext)
|
||||
return;
|
||||
|
||||
int16 delta = int16(selector->MinItemLevel) - proto->ItemLevel;
|
||||
|
||||
if (uint32 bonus = GetItemBonusListForItemLevelDelta(delta))
|
||||
bonusListIDs.insert(bonus);
|
||||
|
||||
if (ItemLevelSelectorQualitySetEntry const* selectorQualitySet = sItemLevelSelectorQualitySetStore.LookupEntry(selector->ItemLevelSelectorQualitySetID))
|
||||
if (bonusTreeNode->ChildItemBonusListID)
|
||||
{
|
||||
auto itemSelectorQualities = _itemLevelQualitySelectorQualities.find(selector->ItemLevelSelectorQualitySetID);
|
||||
if (itemSelectorQualities != _itemLevelQualitySelectorQualities.end())
|
||||
{
|
||||
ItemQualities quality = ITEM_QUALITY_UNCOMMON;
|
||||
if (selector->MinItemLevel >= selectorQualitySet->IlvlEpic)
|
||||
quality = ITEM_QUALITY_EPIC;
|
||||
else if (selector->MinItemLevel >= selectorQualitySet->IlvlRare)
|
||||
quality = ITEM_QUALITY_RARE;
|
||||
|
||||
auto itemSelectorQuality = std::lower_bound(itemSelectorQualities->second.begin(), itemSelectorQualities->second.end(),
|
||||
quality, ItemLevelSelectorQualityEntryComparator{});
|
||||
|
||||
if (itemSelectorQuality != itemSelectorQualities->second.end())
|
||||
bonusListIDs.insert((*itemSelectorQuality)->QualityItemBonusListID);
|
||||
}
|
||||
bonusListIDs.insert(bonusTreeNode->ChildItemBonusListID);
|
||||
}
|
||||
|
||||
if (AzeriteUnlockMappingEntry const* azeriteUnlockMapping = Trinity::Containers::MapGetValuePtr(_azeriteUnlockMappings, std::make_pair(proto->ID, itemContext)))
|
||||
else if (bonusTreeNode->ChildItemLevelSelectorID)
|
||||
{
|
||||
switch (proto->InventoryType)
|
||||
{
|
||||
case INVTYPE_HEAD:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListHead);
|
||||
break;
|
||||
case INVTYPE_SHOULDERS:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListShoulders);
|
||||
break;
|
||||
case INVTYPE_CHEST:
|
||||
case INVTYPE_ROBE:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListChest);
|
||||
break;
|
||||
}
|
||||
itemLevelSelectorId = bonusTreeNode->ChildItemLevelSelectorID;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (ItemLevelSelectorEntry const* selector = sItemLevelSelectorStore.LookupEntry(itemLevelSelectorId))
|
||||
{
|
||||
int16 delta = int16(selector->MinItemLevel) - proto->ItemLevel;
|
||||
|
||||
if (uint32 bonus = GetItemBonusListForItemLevelDelta(delta))
|
||||
bonusListIDs.insert(bonus);
|
||||
|
||||
if (ItemLevelSelectorQualitySetEntry const* selectorQualitySet = sItemLevelSelectorQualitySetStore.LookupEntry(selector->ItemLevelSelectorQualitySetID))
|
||||
{
|
||||
auto itemSelectorQualities = _itemLevelQualitySelectorQualities.find(selector->ItemLevelSelectorQualitySetID);
|
||||
if (itemSelectorQualities != _itemLevelQualitySelectorQualities.end())
|
||||
{
|
||||
ItemQualities quality = ITEM_QUALITY_UNCOMMON;
|
||||
if (selector->MinItemLevel >= selectorQualitySet->IlvlEpic)
|
||||
quality = ITEM_QUALITY_EPIC;
|
||||
else if (selector->MinItemLevel >= selectorQualitySet->IlvlRare)
|
||||
quality = ITEM_QUALITY_RARE;
|
||||
|
||||
auto itemSelectorQuality = std::lower_bound(itemSelectorQualities->second.begin(), itemSelectorQualities->second.end(),
|
||||
quality, ItemLevelSelectorQualityEntryComparator{});
|
||||
|
||||
if (itemSelectorQuality != itemSelectorQualities->second.end())
|
||||
bonusListIDs.insert((*itemSelectorQuality)->QualityItemBonusListID);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (AzeriteUnlockMappingEntry const* azeriteUnlockMapping = Trinity::Containers::MapGetValuePtr(_azeriteUnlockMappings, std::make_pair(proto->ID, itemContext)))
|
||||
{
|
||||
switch (proto->InventoryType)
|
||||
{
|
||||
case INVTYPE_HEAD:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListHead);
|
||||
break;
|
||||
case INVTYPE_SHOULDERS:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListShoulders);
|
||||
break;
|
||||
case INVTYPE_CHEST:
|
||||
case INVTYPE_ROBE:
|
||||
bonusListIDs.insert(azeriteUnlockMapping->ItemBonusListChest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bonusListIDs;
|
||||
}
|
||||
|
||||
void LoadAzeriteEmpoweredItemUnlockMappings(std::unordered_map<int32, std::vector<AzeriteUnlockMappingEntry const*>> const& azeriteUnlockMappingsBySet, uint32 itemId)
|
||||
{
|
||||
ItemSparseEntry const* proto = sItemSparseStore.LookupEntry(itemId);
|
||||
if (!proto)
|
||||
auto itemIdRange = _itemToBonusTree.equal_range(itemId);
|
||||
if (itemIdRange.first == itemIdRange.second)
|
||||
return;
|
||||
|
||||
VisitItemBonusTree(itemId, [&azeriteUnlockMappingsBySet, proto](ItemBonusTreeNodeEntry const* bonusTreeNode)
|
||||
for (auto itemTreeItr = itemIdRange.first; itemTreeItr != itemIdRange.second; ++itemTreeItr)
|
||||
{
|
||||
if (!bonusTreeNode->ChildItemBonusListID && bonusTreeNode->ChildItemLevelSelectorID)
|
||||
VisitItemBonusTree(itemTreeItr->second, true, [&azeriteUnlockMappingsBySet, itemId](ItemBonusTreeNodeEntry const* bonusTreeNode)
|
||||
{
|
||||
ItemLevelSelectorEntry const* selector = sItemLevelSelectorStore.LookupEntry(bonusTreeNode->ChildItemLevelSelectorID);
|
||||
if (!selector)
|
||||
return;
|
||||
|
||||
if (std::vector<AzeriteUnlockMappingEntry const*> const* azeriteUnlockMappings = Trinity::Containers::MapGetValuePtr(azeriteUnlockMappingsBySet, selector->AzeriteUnlockMappingSet))
|
||||
if (!bonusTreeNode->ChildItemBonusListID && bonusTreeNode->ChildItemLevelSelectorID)
|
||||
{
|
||||
AzeriteUnlockMappingEntry const* selectedAzeriteUnlockMapping = nullptr;
|
||||
for (AzeriteUnlockMappingEntry const* azeriteUnlockMapping : *azeriteUnlockMappings)
|
||||
ItemLevelSelectorEntry const* selector = sItemLevelSelectorStore.LookupEntry(bonusTreeNode->ChildItemLevelSelectorID);
|
||||
if (!selector)
|
||||
return;
|
||||
|
||||
if (std::vector<AzeriteUnlockMappingEntry const*> const* azeriteUnlockMappings = Trinity::Containers::MapGetValuePtr(azeriteUnlockMappingsBySet, selector->AzeriteUnlockMappingSet))
|
||||
{
|
||||
if (azeriteUnlockMapping->ItemLevel > selector->MinItemLevel ||
|
||||
(selectedAzeriteUnlockMapping != nullptr && selectedAzeriteUnlockMapping->ItemLevel > azeriteUnlockMapping->ItemLevel))
|
||||
continue;
|
||||
AzeriteUnlockMappingEntry const* selectedAzeriteUnlockMapping = nullptr;
|
||||
for (AzeriteUnlockMappingEntry const* azeriteUnlockMapping : *azeriteUnlockMappings)
|
||||
{
|
||||
if (azeriteUnlockMapping->ItemLevel > selector->MinItemLevel ||
|
||||
(selectedAzeriteUnlockMapping != nullptr && selectedAzeriteUnlockMapping->ItemLevel > azeriteUnlockMapping->ItemLevel))
|
||||
continue;
|
||||
|
||||
selectedAzeriteUnlockMapping = azeriteUnlockMapping;
|
||||
selectedAzeriteUnlockMapping = azeriteUnlockMapping;
|
||||
}
|
||||
|
||||
if (selectedAzeriteUnlockMapping)
|
||||
_azeriteUnlockMappings[std::make_pair(itemId, ItemContext(bonusTreeNode->ItemContext))] = selectedAzeriteUnlockMapping;
|
||||
}
|
||||
|
||||
if (selectedAzeriteUnlockMapping)
|
||||
_azeriteUnlockMappings[std::make_pair(proto->ID, ItemContext(bonusTreeNode->ItemContext))] = selectedAzeriteUnlockMapping;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ItemChildEquipmentEntry const* DB2Manager::GetItemChildEquipment(uint32 itemId) const
|
||||
@@ -3053,7 +3064,7 @@ bool ChrClassesXPowerTypesEntryComparator::Compare(ChrClassesXPowerTypesEntry co
|
||||
|
||||
bool ItemLevelSelectorQualityEntryComparator::Compare(ItemLevelSelectorQualityEntry const* left, ItemLevelSelectorQualityEntry const* right)
|
||||
{
|
||||
return left->Quality > right->Quality;
|
||||
return left->Quality < right->Quality;
|
||||
}
|
||||
|
||||
bool DB2Manager::MountTypeXCapabilityEntryComparator::Compare(MountTypeXCapabilityEntry const* left, MountTypeXCapabilityEntry const* right)
|
||||
|
||||
@@ -303,7 +303,7 @@ public:
|
||||
std::vector<uint32> const* GetGlyphRequiredSpecs(uint32 glyphPropertiesId) const;
|
||||
ItemBonusList const* GetItemBonusList(uint32 bonusListId) const;
|
||||
uint32 GetItemBonusListForItemLevelDelta(int16 delta) const;
|
||||
std::set<uint32> GetItemBonusTree(uint32 itemId, ItemContext itemContext) const;
|
||||
std::set<uint32> GetDefaultItemBonusTree(uint32 itemId, ItemContext itemContext) const;
|
||||
ItemChildEquipmentEntry const* GetItemChildEquipment(uint32 itemId) const;
|
||||
ItemClassEntry const* GetItemClassByOldEnum(uint32 itemClass) const;
|
||||
bool HasItemCurrencyCost(uint32 itemId) const;
|
||||
|
||||
@@ -1081,6 +1081,7 @@ enum class ItemContext : uint8
|
||||
World_Quest_13 = 55,
|
||||
PVP_Ranked_Jackpot = 56,
|
||||
Tournament_Realm = 57,
|
||||
Relinquished = 58,
|
||||
};
|
||||
|
||||
enum ItemLimitCategoryMode
|
||||
|
||||
@@ -274,7 +274,7 @@ void Loot::AddItem(LootStoreItem const& item)
|
||||
generatedLoot.count = std::min(count, proto->GetMaxStackSize());
|
||||
if (_itemContext != ItemContext::NONE)
|
||||
{
|
||||
std::set<uint32> bonusListIDs = sDB2Manager.GetItemBonusTree(generatedLoot.itemid, _itemContext);
|
||||
std::set<uint32> bonusListIDs = sDB2Manager.GetDefaultItemBonusTree(generatedLoot.itemid, _itemContext);
|
||||
generatedLoot.BonusListIDs.insert(generatedLoot.BonusListIDs.end(), bonusListIDs.begin(), bonusListIDs.end());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user