diff --git a/Source/Framework/Constants/ItemConst.cs b/Source/Framework/Constants/ItemConst.cs index 12ced5bb4..61ec259a7 100644 --- a/Source/Framework/Constants/ItemConst.cs +++ b/Source/Framework/Constants/ItemConst.cs @@ -283,14 +283,19 @@ namespace Framework.Constants OK = 3 } - public enum EnchantmentSlotMask : ushort + [Flags] + public enum SpellItemEnchantmentFlags : ushort { - CanSouldBound = 0x01, - Unk1 = 0x02, - Unk2 = 0x04, - Unk3 = 0x08, - Collectable = 0x100, - HideIfNotCollected = 0x200, + Soulbound = 0x01, + DoNotLog = 0x02, + MainhandOnly = 0x04, + AllowEnteringArena = 0x08, + DoNotSaveToDB = 0x10, + ScaleAsAGem = 0x20, + DisableInChallengeModes = 0x40, + DisableInProvingGrounds = 0x80, + AllowTransmog = 0x100, + HideUntilCollected = 0x200, } public enum ItemModifier diff --git a/Source/Game/DataStorage/Structs/S_Records.cs b/Source/Game/DataStorage/Structs/S_Records.cs index fd7b10650..0ee94c504 100644 --- a/Source/Game/DataStorage/Structs/S_Records.cs +++ b/Source/Game/DataStorage/Structs/S_Records.cs @@ -347,7 +347,7 @@ namespace Game.DataStorage public uint TransmogCost; public ushort[] EffectPointsMin = new ushort[ItemConst.MaxItemEnchantmentEffects]; public ushort ItemVisual; - public EnchantmentSlotMask Flags; + public ushort Flags; public ushort RequiredSkillID; public ushort RequiredSkillRank; public ushort ItemLevel; @@ -358,6 +358,8 @@ namespace Game.DataStorage public byte ConditionID; public byte MinLevel; public byte MaxLevel; + + public SpellItemEnchantmentFlags GetFlags() { return (SpellItemEnchantmentFlags)Flags; } } public sealed class SpellItemEnchantmentConditionRecord diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index b705b4ea9..c32773035 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -168,7 +168,13 @@ namespace Game.Entities ss.Clear(); for (EnchantmentSlot slot = 0; slot < EnchantmentSlot.Max; ++slot) - ss.AppendFormat("{0} {1} {2} ", GetEnchantmentId(slot), GetEnchantmentDuration(slot), GetEnchantmentCharges(slot)); + { + var enchantment = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(slot)); + if (enchantment != null && !enchantment.GetFlags().HasFlag(SpellItemEnchantmentFlags.DoNotSaveToDB)) + ss.Append($"{GetEnchantmentId(slot)} {GetEnchantmentDuration(slot)} {GetEnchantmentCharges(slot)} "); + else + ss.Append("0 0 0 "); + } stmt.AddValue(++index, ss.ToString()); stmt.AddValue(++index, m_randomBonusListId); @@ -892,7 +898,7 @@ namespace Game.Entities { var enchantEntry = CliDB.SpellItemEnchantmentStorage.LookupByKey(enchant_id); if (enchantEntry != null) - if (enchantEntry.Flags.HasAnyFlag(EnchantmentSlotMask.CanSouldBound)) + if (enchantEntry.GetFlags().HasFlag(SpellItemEnchantmentFlags.Soulbound)) return true; } } @@ -960,12 +966,13 @@ namespace Game.Entities Player owner = GetOwner(); if (slot < EnchantmentSlot.MaxInspected) { - uint oldEnchant = GetEnchantmentId(slot); - if (oldEnchant != 0) - owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant, (uint)slot); + var oldEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(slot)); + if (oldEnchant != null && !oldEnchant.GetFlags().HasFlag(SpellItemEnchantmentFlags.DoNotLog)) + owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant.Id, (uint)slot); - if (id != 0) - owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot); + var newEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(id); + if (newEnchant != null && !newEnchant.GetFlags().HasFlag(SpellItemEnchantmentFlags.DoNotLog)) + owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot); } ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner); diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index a2af5ba78..26170b849 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -1919,9 +1919,19 @@ namespace Game.Entities // remove item dependent auras and casts (only weapon and armor slots) if (slot < EquipmentSlot.End) { - // remove held enchantments, update expertise + // update expertise if (slot == EquipmentSlot.MainHand) + { + // clear main hand only enchantments + for (EnchantmentSlot enchantSlot = 0; enchantSlot < EnchantmentSlot.Max; ++enchantSlot) + { + var enchantment = CliDB.SpellItemEnchantmentStorage.LookupByKey(pItem.GetEnchantmentId(enchantSlot)); + if (enchantment != null && enchantment.GetFlags().HasFlag(SpellItemEnchantmentFlags.MainhandOnly)) + pItem.ClearEnchantment(enchantSlot); + } + UpdateExpertise(WeaponAttackType.BaseAttack); + } else if (slot == EquipmentSlot.OffHand) UpdateExpertise(WeaponAttackType.OffAttack); // update armor penetration - passive auras may need it diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index f98115bdb..cbb0a1456 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -959,9 +959,8 @@ namespace Game.Entities for (byte i = InventorySlots.ItemStart; i < inventoryEnd; ++i) { Item pItem = GetItemByPos(InventorySlots.Bag0, i); - if (pItem) - if (pItem.GetEnchantmentId(slot) != 0) - pItem.ClearEnchantment(slot); + if (pItem && !Global.SpellMgr.IsArenaAllowedEnchancment(pItem.GetEnchantmentId(slot))) + pItem.ClearEnchantment(slot); } // in inventory bags @@ -973,9 +972,8 @@ namespace Game.Entities for (byte j = 0; j < pBag.GetBagSize(); j++) { Item pItem = pBag.GetItemByPos(j); - if (pItem) - if (pItem.GetEnchantmentId(slot) != 0) - pItem.ClearEnchantment(slot); + if (pItem && !Global.SpellMgr.IsArenaAllowedEnchancment(pItem.GetEnchantmentId(slot))) + pItem.ClearEnchantment(slot); } } } diff --git a/Source/Game/Handlers/CharacterHandler.cs b/Source/Game/Handlers/CharacterHandler.cs index 9dac19594..7c1010544 100644 --- a/Source/Game/Handlers/CharacterHandler.cs +++ b/Source/Game/Handlers/CharacterHandler.cs @@ -1587,7 +1587,7 @@ namespace Game if (illusion == null) return false; - if (illusion.ItemVisual == 0 || !illusion.Flags.HasAnyFlag(EnchantmentSlotMask.Collectable)) + if (illusion.ItemVisual == 0 || !illusion.GetFlags().HasFlag(SpellItemEnchantmentFlags.AllowTransmog)) return false; PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogUseConditionID); diff --git a/Source/Game/Handlers/TransmogrificationHandler.cs b/Source/Game/Handlers/TransmogrificationHandler.cs index b25eed126..fe09c312f 100644 --- a/Source/Game/Handlers/TransmogrificationHandler.cs +++ b/Source/Game/Handlers/TransmogrificationHandler.cs @@ -143,7 +143,7 @@ namespace Game return; } - if (illusion.ItemVisual == 0 || !illusion.Flags.HasAnyFlag(EnchantmentSlotMask.Collectable)) + if (illusion.ItemVisual == 0 || !illusion.GetFlags().HasFlag(SpellItemEnchantmentFlags.AllowTransmog)) { Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID); return; diff --git a/Source/Game/Server/WorldManager.cs b/Source/Game/Server/WorldManager.cs index aed764836..8d46b9f85 100644 --- a/Source/Game/Server/WorldManager.cs +++ b/Source/Game/Server/WorldManager.cs @@ -748,9 +748,6 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loading Spell target coordinates..."); Global.SpellMgr.LoadSpellTargetPositions(); - Log.outInfo(LogFilter.ServerLoading, "Loading enchant custom attributes..."); - Global.SpellMgr.LoadEnchantCustomAttr(); - Log.outInfo(LogFilter.ServerLoading, "Loading linked spells..."); Global.SpellMgr.LoadSpellLinked(); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 1ed3e586d..00c542efc 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -6351,7 +6351,7 @@ namespace Game.Spells { if (enchantEntry == null) return SpellCastResult.Error; - if (enchantEntry.Flags.HasAnyFlag(EnchantmentSlotMask.CanSouldBound)) + if (enchantEntry.GetFlags().HasFlag(SpellItemEnchantmentFlags.Soulbound)) return SpellCastResult.NotTradeable; } break; @@ -6365,10 +6365,10 @@ namespace Game.Spells if (item.GetOwner() != player) { int enchant_id = spellEffectInfo.MiscValue; - var pEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(enchant_id); - if (pEnchant == null) + var enchantEntry = CliDB.SpellItemEnchantmentStorage.LookupByKey(enchant_id); + if (enchantEntry == null) return SpellCastResult.Error; - if (pEnchant.Flags.HasAnyFlag(EnchantmentSlotMask.CanSouldBound)) + if (enchantEntry.GetFlags().HasFlag(SpellItemEnchantmentFlags.Soulbound)) return SpellCastResult.NotTradeable; } diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index 736df018b..a50378c16 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -578,7 +578,11 @@ namespace Game.Entities public bool IsArenaAllowedEnchancment(uint ench_id) { - return mEnchantCustomAttr.LookupByKey((int)ench_id); + var enchantment = CliDB.SpellItemEnchantmentStorage.LookupByKey(ench_id); + if (enchantment != null) + return enchantment.GetFlags().HasFlag(SpellItemEnchantmentFlags.AllowEnteringArena); + + return false; } public List GetSpellLinked(int spell_id) @@ -1685,36 +1689,6 @@ namespace Game.Entities Log.outInfo(LogFilter.ServerLoading, "Loaded {0} spell pet auras in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } - // Fill custom data about enchancments - public void LoadEnchantCustomAttr() - { - uint oldMSTime = Time.GetMSTime(); - - uint count = 0; - foreach (var spellInfo in mSpellInfoMap.Values) - { - // @todo find a better check - if (!spellInfo.HasAttribute(SpellAttr2.PreserveEnchantInArena) || !spellInfo.HasAttribute(SpellAttr0.NotShapeshift)) - continue; - - foreach (var spellEffectInfo in spellInfo.GetEffects()) - { - if (spellEffectInfo.Effect == SpellEffectName.EnchantItemTemporary) - { - int enchId = spellEffectInfo.MiscValue; - var ench = CliDB.SpellItemEnchantmentStorage.LookupByKey((uint)enchId); - if (ench == null) - continue; - mEnchantCustomAttr[enchId] = true; - ++count; - break; - } - } - } - - Log.outInfo(LogFilter.ServerLoading, "Loaded {0} custom enchant attributes in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); - } - public void LoadSpellEnchantProcData() { uint oldMSTime = Time.GetMSTime(); @@ -4777,7 +4751,6 @@ namespace Game.Entities Dictionary mSpellPetAuraMap = new(); MultiMap mSpellLinkedMap = new(); Dictionary mSpellEnchantProcEventMap = new(); - Dictionary mEnchantCustomAttr = new(); MultiMap mSpellAreaMap = new(); MultiMap mSpellAreaForQuestMap = new(); MultiMap mSpellAreaForQuestEndMap = new();