Core/Items: Fixed generating default bonuses based on context

This commit is contained in:
Shauren
2020-06-07 12:38:38 +02:00
parent afcb8ff8e9
commit e5a6552abc
4 changed files with 103 additions and 91 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -1081,6 +1081,7 @@ enum class ItemContext : uint8
World_Quest_13 = 55,
PVP_Ranked_Jackpot = 56,
Tournament_Realm = 57,
Relinquished = 58,
};
enum ItemLimitCategoryMode

View File

@@ -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());
}