diff --git a/Source/Framework/Constants/ItemConst.cs b/Source/Framework/Constants/ItemConst.cs index c23adef85..c167dae83 100644 --- a/Source/Framework/Constants/ItemConst.cs +++ b/Source/Framework/Constants/ItemConst.cs @@ -464,8 +464,11 @@ namespace Framework.Constants OverrideName = 31, // Itemnamedescription Id ItemBonusListGroup = 34, ItemLimitCategory = 35, + PvpItemLevelIncrement = 36, ItemConversion = 37, ItemHistorySlot = 38, + PvpItemLevelBase = 43, + BondingWithPriority = 47, } public enum ItemCollectionType : byte diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index 533aabeb9..7eefef47d 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -1215,7 +1215,12 @@ namespace Game.Entities if (gemProto == null) return false; - return gemProto.GetItemLimitCategory() == limitCategory; + BonusData gemBonus = new(gemProto); + + foreach (ushort bonusListID in gemData.BonusListIDs) + gemBonus.AddBonusList(bonusListID); + + return gemBonus.LimitCategory == limitCategory; }); } @@ -1846,7 +1851,13 @@ namespace Game.Entities uint itemLevelBeforeUpgrades = itemLevel; if (pvpBonus) + { + if (bonusData.PvpItemLevel != 0) + itemLevel = bonusData.PvpItemLevel; + + itemLevel += (uint)bonusData.PvpItemLevelBonus; itemLevel += Global.DB2Mgr.GetPvpItemLevelBonus(itemTemplate.GetId()); + } if (itemTemplate.GetInventoryType() != InventoryType.NonEquip) { @@ -2726,6 +2737,7 @@ namespace Game.Entities public void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; } public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; } + public uint GetItemLimitCategory() { return _bonusData.LimitCategory; } public override Loot GetLootForPlayer(Player player) { return loot; } @@ -2937,6 +2949,8 @@ namespace Game.Entities for (int i = EffectCount; i < Effects.Length; ++i) Effects[i] = null; + LimitCategory = proto.GetItemLimitCategory(); + CanDisenchant = !proto.HasFlag(ItemFlags.NoDisenchant); CanScrap = proto.HasFlag(ItemFlags4.Scrapable); @@ -2946,7 +2960,8 @@ namespace Game.Entities _state.ScalingStatDistributionPriority = int.MaxValue; _state.AzeriteTierUnlockSetPriority = int.MaxValue; _state.RequiredLevelCurvePriority = int.MaxValue; - _state.HasQualityBonus = false; + _state.PvpItemLevelPriority = int.MaxValue; + _state.BondingPriority = int.MaxValue; } public BonusData(ItemInstance itemInstance) : this(Global.ObjectMgr.GetItemTemplate(itemInstance.ItemID)) @@ -3080,6 +3095,30 @@ namespace Game.Entities ContentTuningId = (uint)values[1]; } break; + case ItemBonusType.ItemLimitCategory: + if (!_state.HasItemLimitCategory) + { + LimitCategory = (uint)values[0]; + _state.HasItemLimitCategory = true; + } + break; + case ItemBonusType.PvpItemLevelIncrement: + PvpItemLevelBonus += (short)values[0]; + break; + case ItemBonusType.PvpItemLevelBase: + if (values[1] < _state.PvpItemLevelPriority) + { + PvpItemLevel = (ushort)values[0]; + _state.PvpItemLevelPriority = values[1]; + } + break; + case ItemBonusType.BondingWithPriority: + if (values[1] < _state.BondingPriority) + { + Bonding = (ItemBondingType)values[0]; + _state.BondingPriority = values[1]; + } + break; } } @@ -3104,8 +3143,11 @@ namespace Game.Entities public uint AzeriteTierUnlockSetId; public uint Suffix; public uint RequiredLevelCurve; + public ushort PvpItemLevel; + public short PvpItemLevelBonus; public ItemEffectRecord[] Effects = new ItemEffectRecord[13]; public int EffectCount; + public uint LimitCategory; public bool CanDisenchant; public bool CanScrap; public bool HasFixedLevel; @@ -3119,7 +3161,10 @@ namespace Game.Entities public int ScalingStatDistributionPriority; public int AzeriteTierUnlockSetPriority; public int RequiredLevelCurvePriority; + public int PvpItemLevelPriority; + public int BondingPriority; public bool HasQualityBonus; + public bool HasItemLimitCategory; } } diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index e15523784..0bd7c22c0 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -1268,8 +1268,10 @@ namespace Game.Entities if (pItem != null && pItem.m_lootGenerated) return InventoryResult.LootGone; + uint limitCategory = pItem != null ? pItem.GetItemLimitCategory() : pProto.GetItemLimitCategory(); + // no maximum - if ((pProto.GetMaxCount() <= 0 && pProto.GetItemLimitCategory() == 0) || pProto.GetMaxCount() == 2147483647) + if ((pProto.GetMaxCount() <= 0 && limitCategory == 0) || pProto.GetMaxCount() == 2147483647) return InventoryResult.Ok; if (pProto.GetMaxCount() > 0) @@ -1283,9 +1285,9 @@ namespace Game.Entities } // check unique-equipped limit - if (pProto.GetItemLimitCategory() != 0) + if (limitCategory != 0) { - ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(pProto.GetItemLimitCategory()); + ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(limitCategory); if (limitEntry == null) { no_space_count = count; @@ -1295,7 +1297,7 @@ namespace Game.Entities if (limitEntry.Flags == 0) { byte limitQuantity = GetItemLimitCategoryQuantity(limitEntry); - uint curcount = GetItemCountWithLimitCategory(pProto.GetItemLimitCategory(), pItem); + uint curcount = GetItemCountWithLimitCategory(limitCategory, pItem); if (curcount + count > limitQuantity) { no_space_count = count + curcount - limitQuantity; @@ -1730,8 +1732,14 @@ namespace Game.Entities case InventoryResult.ItemMaxLimitCategorySocketedExceededIs: case InventoryResult.ItemMaxLimitCategoryEquippedExceededIs: { - ItemTemplate proto = item1 != null ? item1.GetTemplate() : Global.ObjectMgr.GetItemTemplate(itemId); - failure.LimitCategory = (int)(proto != null ? proto.GetItemLimitCategory() : 0u); + if (item1 != null) + failure.LimitCategory = (int)item1.GetItemLimitCategory(); + else + { + ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemId); + if (proto != null) + failure.LimitCategory = (int)proto.GetItemLimitCategory(); + } break; } default: @@ -2776,12 +2784,8 @@ namespace Game.Entities ForEachItem(ItemSearchLocation.Everywhere, item => { if (item != skipItem) - { - ItemTemplate pProto = item.GetTemplate(); - if (pProto != null) - if (pProto.GetItemLimitCategory() == limitCategory) - count += item.GetCount(); - } + if (item.GetItemLimitCategory() == limitCategory) + count += item.GetCount(); return true; }); @@ -5055,7 +5059,7 @@ namespace Game.Entities ItemTemplate pProto = pItem.GetTemplate(); // proto based limitations - InventoryResult res = CanEquipUniqueItem(pProto, eslot, limit_count); + InventoryResult res = CanEquipUniqueItem(pProto, pItem.GetBonus(), eslot, limit_count); if (res != InventoryResult.Ok) return res; @@ -5066,17 +5070,22 @@ namespace Game.Entities if (pGem == null) continue; - // include for check equip another gems with same limit category for not equipped item (and then not counted) - uint gem_limit_count = (uint)(!pItem.IsEquipped() && pGem.GetItemLimitCategory() != 0 ? pItem.GetGemCountWithLimitCategory(pGem.GetItemLimitCategory()) : 1); + BonusData gemBonus = new(pGem); - InventoryResult ress = CanEquipUniqueItem(pGem, eslot, gem_limit_count); + foreach (ushort bonusListID in gemData.BonusListIDs) + gemBonus.AddBonusList(bonusListID); + + // include for check equip another gems with same limit category for not equipped item (and then not counted) + uint gem_limit_count = (uint)(!pItem.IsEquipped() && gemBonus.LimitCategory != 0 ? pItem.GetGemCountWithLimitCategory(gemBonus.LimitCategory) : 1); + + InventoryResult ress = CanEquipUniqueItem(pGem, gemBonus, eslot, gem_limit_count); if (ress != InventoryResult.Ok) return ress; } return InventoryResult.Ok; } - public InventoryResult CanEquipUniqueItem(ItemTemplate itemProto, byte except_slot = ItemConst.NullSlot, uint limit_count = 1) + public InventoryResult CanEquipUniqueItem(ItemTemplate itemProto, BonusData itemBonus, byte except_slot = ItemConst.NullSlot, uint limit_count = 1) { // check unique-equipped on item if (itemProto.HasFlag(ItemFlags.UniqueEquippable)) @@ -5087,9 +5096,9 @@ namespace Game.Entities } // check unique-equipped limit - if (itemProto.GetItemLimitCategory() != 0) + if (itemBonus.LimitCategory != 0) { - ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(itemProto.GetItemLimitCategory()); + ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(itemBonus.LimitCategory); if (limitEntry == null) return InventoryResult.NotEquippable; @@ -5100,9 +5109,9 @@ namespace Game.Entities return InventoryResult.ItemMaxLimitCategoryEquippedExceededIs; // there is an equip limit on this item - if (HasItemWithLimitCategoryEquipped(itemProto.GetItemLimitCategory(), limitQuantity - limit_count + 1, except_slot)) + if (HasItemWithLimitCategoryEquipped(itemBonus.LimitCategory, limitQuantity - limit_count + 1, except_slot)) return InventoryResult.ItemMaxLimitCategoryEquippedExceededIs; - else if (HasGemWithLimitCategoryEquipped(itemProto.GetItemLimitCategory(), limitQuantity - limit_count + 1, except_slot)) + else if (HasGemWithLimitCategoryEquipped(itemBonus.LimitCategory, limitQuantity - limit_count + 1, except_slot)) return InventoryResult.ItemMaxCountEquippedSocketed; } @@ -5403,7 +5412,7 @@ namespace Game.Entities if (pItem.GetSlot() == except_slot) return true; - if (pItem.GetTemplate().GetItemLimitCategory() != limitCategory) + if (pItem.GetItemLimitCategory() != limitCategory) return true; tempcount += pItem.GetCount(); diff --git a/Source/Game/Handlers/ItemHandler.cs b/Source/Game/Handlers/ItemHandler.cs index bb39b33c7..ffba642c6 100644 --- a/Source/Game/Handlers/ItemHandler.cs +++ b/Source/Game/Handlers/ItemHandler.cs @@ -886,9 +886,9 @@ namespace Game // unique limit type item int limit_newcount = 0; - if (iGemProto.GetItemLimitCategory() != 0) + if (gems[i].GetItemLimitCategory() != 0) { - ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(iGemProto.GetItemLimitCategory()); + ItemLimitCategoryRecord limitEntry = CliDB.ItemLimitCategoryStorage.LookupByKey(gems[i].GetItemLimitCategory()); if (limitEntry != null) { // NOTE: limitEntry.mode is not checked because if item has limit then it is applied in equip case @@ -897,7 +897,7 @@ namespace Game if (gems[j] != null) { // new gem - if (iGemProto.GetItemLimitCategory() == gems[j].GetTemplate().GetItemLimitCategory()) + if (gems[i].GetItemLimitCategory() == gems[j].GetTemplate().GetItemLimitCategory()) ++limit_newcount; } else if (oldGemData[j] != null) @@ -905,8 +905,15 @@ namespace Game // existing gem ItemTemplate jProto = Global.ObjectMgr.GetItemTemplate(oldGemData[j].ItemId); if (jProto != null) - if (iGemProto.GetItemLimitCategory() == jProto.GetItemLimitCategory()) + { + BonusData oldGemBonus = new(jProto); + + foreach (ushort bonusListID in oldGemData[j].BonusListIDs) + oldGemBonus.AddBonusList(bonusListID); + + if (gems[i].GetItemLimitCategory() == oldGemBonus.LimitCategory) ++limit_newcount; + } } }