Core/Items: Implemented new item bonus types: limit category and pvp item level

Port From (https://github.com/TrinityCore/TrinityCore/commit/8fff15ba7c63bc12fa00664bfe067bbc9586d3f2)
This commit is contained in:
Hondacrx
2025-12-08 16:09:02 -05:00
parent b962dc7a48
commit f01f61c464
4 changed files with 92 additions and 28 deletions
+3
View File
@@ -464,8 +464,11 @@ namespace Framework.Constants
OverrideName = 31, // Itemnamedescription Id OverrideName = 31, // Itemnamedescription Id
ItemBonusListGroup = 34, ItemBonusListGroup = 34,
ItemLimitCategory = 35, ItemLimitCategory = 35,
PvpItemLevelIncrement = 36,
ItemConversion = 37, ItemConversion = 37,
ItemHistorySlot = 38, ItemHistorySlot = 38,
PvpItemLevelBase = 43,
BondingWithPriority = 47,
} }
public enum ItemCollectionType : byte public enum ItemCollectionType : byte
+47 -2
View File
@@ -1215,7 +1215,12 @@ namespace Game.Entities
if (gemProto == null) if (gemProto == null)
return false; 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; uint itemLevelBeforeUpgrades = itemLevel;
if (pvpBonus) if (pvpBonus)
{
if (bonusData.PvpItemLevel != 0)
itemLevel = bonusData.PvpItemLevel;
itemLevel += (uint)bonusData.PvpItemLevelBonus;
itemLevel += Global.DB2Mgr.GetPvpItemLevelBonus(itemTemplate.GetId()); itemLevel += Global.DB2Mgr.GetPvpItemLevelBonus(itemTemplate.GetId());
}
if (itemTemplate.GetInventoryType() != InventoryType.NonEquip) if (itemTemplate.GetInventoryType() != InventoryType.NonEquip)
{ {
@@ -2726,6 +2737,7 @@ namespace Game.Entities
public void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; } public void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; }
public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; } public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; }
public uint GetItemLimitCategory() { return _bonusData.LimitCategory; }
public override Loot GetLootForPlayer(Player player) { return loot; } public override Loot GetLootForPlayer(Player player) { return loot; }
@@ -2937,6 +2949,8 @@ namespace Game.Entities
for (int i = EffectCount; i < Effects.Length; ++i) for (int i = EffectCount; i < Effects.Length; ++i)
Effects[i] = null; Effects[i] = null;
LimitCategory = proto.GetItemLimitCategory();
CanDisenchant = !proto.HasFlag(ItemFlags.NoDisenchant); CanDisenchant = !proto.HasFlag(ItemFlags.NoDisenchant);
CanScrap = proto.HasFlag(ItemFlags4.Scrapable); CanScrap = proto.HasFlag(ItemFlags4.Scrapable);
@@ -2946,7 +2960,8 @@ namespace Game.Entities
_state.ScalingStatDistributionPriority = int.MaxValue; _state.ScalingStatDistributionPriority = int.MaxValue;
_state.AzeriteTierUnlockSetPriority = int.MaxValue; _state.AzeriteTierUnlockSetPriority = int.MaxValue;
_state.RequiredLevelCurvePriority = 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)) public BonusData(ItemInstance itemInstance) : this(Global.ObjectMgr.GetItemTemplate(itemInstance.ItemID))
@@ -3080,6 +3095,30 @@ namespace Game.Entities
ContentTuningId = (uint)values[1]; ContentTuningId = (uint)values[1];
} }
break; 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 AzeriteTierUnlockSetId;
public uint Suffix; public uint Suffix;
public uint RequiredLevelCurve; public uint RequiredLevelCurve;
public ushort PvpItemLevel;
public short PvpItemLevelBonus;
public ItemEffectRecord[] Effects = new ItemEffectRecord[13]; public ItemEffectRecord[] Effects = new ItemEffectRecord[13];
public int EffectCount; public int EffectCount;
public uint LimitCategory;
public bool CanDisenchant; public bool CanDisenchant;
public bool CanScrap; public bool CanScrap;
public bool HasFixedLevel; public bool HasFixedLevel;
@@ -3119,7 +3161,10 @@ namespace Game.Entities
public int ScalingStatDistributionPriority; public int ScalingStatDistributionPriority;
public int AzeriteTierUnlockSetPriority; public int AzeriteTierUnlockSetPriority;
public int RequiredLevelCurvePriority; public int RequiredLevelCurvePriority;
public int PvpItemLevelPriority;
public int BondingPriority;
public bool HasQualityBonus; public bool HasQualityBonus;
public bool HasItemLimitCategory;
} }
} }
+30 -21
View File
@@ -1268,8 +1268,10 @@ namespace Game.Entities
if (pItem != null && pItem.m_lootGenerated) if (pItem != null && pItem.m_lootGenerated)
return InventoryResult.LootGone; return InventoryResult.LootGone;
uint limitCategory = pItem != null ? pItem.GetItemLimitCategory() : pProto.GetItemLimitCategory();
// no maximum // no maximum
if ((pProto.GetMaxCount() <= 0 && pProto.GetItemLimitCategory() == 0) || pProto.GetMaxCount() == 2147483647) if ((pProto.GetMaxCount() <= 0 && limitCategory == 0) || pProto.GetMaxCount() == 2147483647)
return InventoryResult.Ok; return InventoryResult.Ok;
if (pProto.GetMaxCount() > 0) if (pProto.GetMaxCount() > 0)
@@ -1283,9 +1285,9 @@ namespace Game.Entities
} }
// check unique-equipped limit // 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) if (limitEntry == null)
{ {
no_space_count = count; no_space_count = count;
@@ -1295,7 +1297,7 @@ namespace Game.Entities
if (limitEntry.Flags == 0) if (limitEntry.Flags == 0)
{ {
byte limitQuantity = GetItemLimitCategoryQuantity(limitEntry); byte limitQuantity = GetItemLimitCategoryQuantity(limitEntry);
uint curcount = GetItemCountWithLimitCategory(pProto.GetItemLimitCategory(), pItem); uint curcount = GetItemCountWithLimitCategory(limitCategory, pItem);
if (curcount + count > limitQuantity) if (curcount + count > limitQuantity)
{ {
no_space_count = count + curcount - limitQuantity; no_space_count = count + curcount - limitQuantity;
@@ -1730,8 +1732,14 @@ namespace Game.Entities
case InventoryResult.ItemMaxLimitCategorySocketedExceededIs: case InventoryResult.ItemMaxLimitCategorySocketedExceededIs:
case InventoryResult.ItemMaxLimitCategoryEquippedExceededIs: case InventoryResult.ItemMaxLimitCategoryEquippedExceededIs:
{ {
ItemTemplate proto = item1 != null ? item1.GetTemplate() : Global.ObjectMgr.GetItemTemplate(itemId); if (item1 != null)
failure.LimitCategory = (int)(proto != null ? proto.GetItemLimitCategory() : 0u); failure.LimitCategory = (int)item1.GetItemLimitCategory();
else
{
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemId);
if (proto != null)
failure.LimitCategory = (int)proto.GetItemLimitCategory();
}
break; break;
} }
default: default:
@@ -2776,12 +2784,8 @@ namespace Game.Entities
ForEachItem(ItemSearchLocation.Everywhere, item => ForEachItem(ItemSearchLocation.Everywhere, item =>
{ {
if (item != skipItem) if (item != skipItem)
{ if (item.GetItemLimitCategory() == limitCategory)
ItemTemplate pProto = item.GetTemplate();
if (pProto != null)
if (pProto.GetItemLimitCategory() == limitCategory)
count += item.GetCount(); count += item.GetCount();
}
return true; return true;
}); });
@@ -5055,7 +5059,7 @@ namespace Game.Entities
ItemTemplate pProto = pItem.GetTemplate(); ItemTemplate pProto = pItem.GetTemplate();
// proto based limitations // proto based limitations
InventoryResult res = CanEquipUniqueItem(pProto, eslot, limit_count); InventoryResult res = CanEquipUniqueItem(pProto, pItem.GetBonus(), eslot, limit_count);
if (res != InventoryResult.Ok) if (res != InventoryResult.Ok)
return res; return res;
@@ -5066,17 +5070,22 @@ namespace Game.Entities
if (pGem == null) if (pGem == null)
continue; continue;
// include for check equip another gems with same limit category for not equipped item (and then not counted) BonusData gemBonus = new(pGem);
uint gem_limit_count = (uint)(!pItem.IsEquipped() && pGem.GetItemLimitCategory() != 0 ? pItem.GetGemCountWithLimitCategory(pGem.GetItemLimitCategory()) : 1);
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) if (ress != InventoryResult.Ok)
return ress; return ress;
} }
return InventoryResult.Ok; 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 // check unique-equipped on item
if (itemProto.HasFlag(ItemFlags.UniqueEquippable)) if (itemProto.HasFlag(ItemFlags.UniqueEquippable))
@@ -5087,9 +5096,9 @@ namespace Game.Entities
} }
// check unique-equipped limit // 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) if (limitEntry == null)
return InventoryResult.NotEquippable; return InventoryResult.NotEquippable;
@@ -5100,9 +5109,9 @@ namespace Game.Entities
return InventoryResult.ItemMaxLimitCategoryEquippedExceededIs; return InventoryResult.ItemMaxLimitCategoryEquippedExceededIs;
// there is an equip limit on this item // 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; 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; return InventoryResult.ItemMaxCountEquippedSocketed;
} }
@@ -5403,7 +5412,7 @@ namespace Game.Entities
if (pItem.GetSlot() == except_slot) if (pItem.GetSlot() == except_slot)
return true; return true;
if (pItem.GetTemplate().GetItemLimitCategory() != limitCategory) if (pItem.GetItemLimitCategory() != limitCategory)
return true; return true;
tempcount += pItem.GetCount(); tempcount += pItem.GetCount();
+11 -4
View File
@@ -886,9 +886,9 @@ namespace Game
// unique limit type item // unique limit type item
int limit_newcount = 0; 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) if (limitEntry != null)
{ {
// NOTE: limitEntry.mode is not checked because if item has limit then it is applied in equip case // 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) if (gems[j] != null)
{ {
// new gem // new gem
if (iGemProto.GetItemLimitCategory() == gems[j].GetTemplate().GetItemLimitCategory()) if (gems[i].GetItemLimitCategory() == gems[j].GetTemplate().GetItemLimitCategory())
++limit_newcount; ++limit_newcount;
} }
else if (oldGemData[j] != null) else if (oldGemData[j] != null)
@@ -905,10 +905,17 @@ namespace Game
// existing gem // existing gem
ItemTemplate jProto = Global.ObjectMgr.GetItemTemplate(oldGemData[j].ItemId); ItemTemplate jProto = Global.ObjectMgr.GetItemTemplate(oldGemData[j].ItemId);
if (jProto != null) 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; ++limit_newcount;
} }
} }
}
if (limit_newcount > 0 && limit_newcount > _player.GetItemLimitCategoryQuantity(limitEntry)) if (limit_newcount > 0 && limit_newcount > _player.GetItemLimitCategoryQuantity(limitEntry))
{ {