From 2e2c87090dd7a62a200e2f83bd93e830ed428cef Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Sun, 10 Nov 2024 16:56:17 -0500 Subject: [PATCH] Core/Items: Implemented ITEM_BONUS_DISENCHANT_LOOT_ID Port From (https://github.com/TrinityCore/TrinityCore/commit/3238175a62750ea5127feb69ce86d0c3c05dfc52) --- Source/Game/Entities/Item/Item.cs | 46 +++++++++++++++++++++++++----- Source/Game/Loot/Loot.cs | 45 +++++++++++++++++++++++------ Source/Game/Loot/LootManager.cs | 12 ++++++++ Source/Game/Spells/Spell.cs | 8 +++--- Source/Game/Spells/SpellEffects.cs | 2 +- 5 files changed, 93 insertions(+), 20 deletions(-) diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index ee25cf35e..770acc118 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -1876,15 +1876,40 @@ namespace Game.Entities return 0f; } - public ItemDisenchantLootRecord GetDisenchantLoot(Player owner) + public uint? GetDisenchantLootId() { if (!_bonusData.CanDisenchant) return null; - return GetDisenchantLoot(GetTemplate(), (uint)GetQuality(), GetItemLevel(owner)); + if (_bonusData.DisenchantLootId != 0) + return _bonusData.DisenchantLootId; + + // ignore temporary item level scaling (pvp or timewalking) + uint itemLevel = GetItemLevel(GetTemplate(), _bonusData, (uint)_bonusData.RequiredLevel, GetModifier(ItemModifier.TimewalkerLevel), 0, 0, 0, false, 0); + + var disenchantLoot = GetBaseDisenchantLoot(GetTemplate(), (uint)GetQuality(), itemLevel); + if (disenchantLoot == null) + return null; + + return disenchantLoot.Id; } - public static ItemDisenchantLootRecord GetDisenchantLoot(ItemTemplate itemTemplate, uint quality, uint itemLevel) + public ushort? GetDisenchantSkillRequired() + { + if (!_bonusData.CanDisenchant) + return null; + + // ignore temporary item level scaling (pvp or timewalking) + uint itemLevel = GetItemLevel(GetTemplate(), _bonusData, (uint)_bonusData.RequiredLevel, GetModifier(ItemModifier.TimewalkerLevel), 0, 0, 0, false, 0); + + var disenchantLoot = GetBaseDisenchantLoot(GetTemplate(), (uint)GetQuality(), itemLevel); + if (disenchantLoot == null) + return null; + + return disenchantLoot.SkillRequired; + } + + public static ItemDisenchantLootRecord GetBaseDisenchantLoot(ItemTemplate itemTemplate, uint quality, uint itemLevel) { if (itemTemplate.HasFlag(ItemFlags.Conjured) || itemTemplate.HasFlag(ItemFlags.NoDisenchant) || itemTemplate.GetBonding() == ItemBondingType.Quest) return null; @@ -2833,13 +2858,11 @@ namespace Game.Entities ItemLevelBonus = 0; RequiredLevel = proto.GetBaseRequiredLevel(); for (uint i = 0; i < ItemConst.MaxStats; ++i) + { ItemStatType[i] = proto.GetStatModifierBonusStat(i); - - for (uint i = 0; i < ItemConst.MaxStats; ++i) StatPercentEditor[i] = proto.GetStatPercentEditor(i); - - for (uint i = 0; i < ItemConst.MaxStats; ++i) ItemStatSocketCostMultiplier[i] = proto.GetStatPercentageOfSocket(i); + } for (uint i = 0; i < ItemConst.MaxGemSockets; ++i) { @@ -2876,6 +2899,7 @@ namespace Game.Entities _state.SuffixPriority = int.MaxValue; _state.AppearanceModPriority = int.MaxValue; + _state.DisenchantLootPriority = int.MaxValue; _state.ScalingStatDistributionPriority = int.MaxValue; _state.AzeriteTierUnlockSetPriority = int.MaxValue; _state.RequiredLevelCurvePriority = int.MaxValue; @@ -2970,6 +2994,13 @@ namespace Game.Entities HasFixedLevel = type == ItemBonusType.ScalingStatDistributionFixed; } break; + case ItemBonusType.DisenchantLootId: + if (values[1] < _state.DisenchantLootPriority) + { + DisenchantLootId = (uint)values[0]; + _state.DisenchantLootPriority = values[1]; + } + break; case ItemBonusType.Bounding: Bonding = (ItemBondingType)values[0]; break; @@ -3041,6 +3072,7 @@ namespace Game.Entities { public int SuffixPriority; public int AppearanceModPriority; + public int DisenchantLootPriority; public int ScalingStatDistributionPriority; public int AzeriteTierUnlockSetPriority; public int RequiredLevelCurvePriority; diff --git a/Source/Game/Loot/Loot.cs b/Source/Game/Loot/Loot.cs index a851c2e8b..2b3006572 100644 --- a/Source/Game/Loot/Loot.cs +++ b/Source/Game/Loot/Loot.cs @@ -519,8 +519,8 @@ namespace Game.Loots m_voteMask = RollMask.AllMask; if (itemTemplate.HasFlag(ItemFlags2.CanOnlyRollGreed)) m_voteMask = m_voteMask & ~RollMask.Need; - var disenchant = GetItemDisenchantLoot(); - if (disenchant == null || disenchant.SkillRequired > enchantingSkill) + var disenchantSkillRequired = GetItemDisenchantSkillRequired(); + if (!disenchantSkillRequired.HasValue || disenchantSkillRequired > enchantingSkill) m_voteMask = m_voteMask & ~RollMask.Disenchant; if (playerCount > 1) // check if more than one player can loot this item @@ -643,7 +643,30 @@ namespace Game.Loots return notVoted == 0; } - ItemDisenchantLootRecord GetItemDisenchantLoot() + uint? GetItemDisenchantLootId() + { + ItemInstance itemInstance = new(m_lootItem); + + BonusData bonusData = new(itemInstance); + if (!bonusData.CanDisenchant) + return null; + + if (bonusData.DisenchantLootId != 0) + return bonusData.DisenchantLootId; + + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(m_lootItem.itemid); + + // ignore temporary item level scaling (pvp or timewalking) + uint itemLevel = Item.GetItemLevel(itemTemplate, bonusData, (uint)bonusData.RequiredLevel, 0, 0, 0, 0, false, 0); + + var disenchantLoot = Item.GetBaseDisenchantLoot(itemTemplate, (uint)bonusData.Quality, itemLevel); + if (disenchantLoot == null) + return null; + + return disenchantLoot.Id; + } + + ushort? GetItemDisenchantSkillRequired() { ItemInstance itemInstance = new(m_lootItem); @@ -652,8 +675,15 @@ namespace Game.Loots return null; ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(m_lootItem.itemid); - uint itemLevel = Item.GetItemLevel(itemTemplate, bonusData, 1, 0, 0, 0, 0, false, 0); - return Item.GetDisenchantLoot(itemTemplate, (uint)bonusData.Quality, itemLevel); + + // ignore temporary item level scaling (pvp or timewalking) + uint itemLevel = Item.GetItemLevel(itemTemplate, bonusData, (uint)bonusData.RequiredLevel, 0, 0, 0, 0, false, 0); + + var disenchantLoot = Item.GetBaseDisenchantLoot(itemTemplate, (uint)bonusData.Quality, itemLevel); + if (disenchantLoot == null) + return null; + + return disenchantLoot.SkillRequired; } // terminate the roll @@ -682,9 +712,8 @@ namespace Game.Loots if (winnerPair.Value.Vote == RollVote.Disenchant) { - var disenchant = GetItemDisenchantLoot(); Loot loot = new(m_map, m_loot.GetOwnerGUID(), LootType.Disenchanting, null); - loot.FillLoot(disenchant.Id, LootStorage.Disenchant, player, true, false, LootModes.Default, ItemContext.None); + loot.FillLoot(GetItemDisenchantLootId().GetValueOrDefault(), LootStorage.Disenchant, player, true, false, LootModes.Default, ItemContext.None); if (!loot.AutoStore(player, ItemConst.NullBag, ItemConst.NullSlot, true)) { for (uint i = 0; i < loot.items.Count; ++i) @@ -1141,7 +1170,7 @@ namespace Game.Loots } case LootItemType.Currency: { - LootCurrency lootCurrency = new(); + LootCurrency lootCurrency = new(); lootCurrency.CurrencyID = item.itemid; lootCurrency.Quantity = item.count; lootCurrency.LootListID = (byte)item.LootListId; diff --git a/Source/Game/Loot/LootManager.cs b/Source/Game/Loot/LootManager.cs index 93fe0331b..aa4fbe90b 100644 --- a/Source/Game/Loot/LootManager.cs +++ b/Source/Game/Loot/LootManager.cs @@ -146,6 +146,18 @@ namespace Game.Loots lootIdSetUsed.Add(lootid); } + foreach (var (_, itemBonus) in CliDB.ItemBonusStorage) + { + if (itemBonus.BonusType != ItemBonusType.DisenchantLootId) + continue; + + uint lootid = (uint)itemBonus.Value[0]; + if (!lootIdSet.Contains(lootid)) + Disenchant.ReportNonExistingId(lootid, 0); + else + lootIdSetUsed.Add(lootid); + } + foreach (var lootId in lootIdSetUsed) lootIdSet.Remove(lootId); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 9d9f08233..3fbfdeaee 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -7036,10 +7036,10 @@ namespace Game.Spells if (itemProto == null) return SpellCastResult.CantBeSalvaged; - ItemDisenchantLootRecord itemDisenchantLoot = item.GetDisenchantLoot(m_caster.ToPlayer()); - if (itemDisenchantLoot == null) + ushort? disenchantSkillRequired = item.GetDisenchantSkillRequired(); + if (!disenchantSkillRequired.HasValue) return SpellCastResult.CantBeSalvaged; - if (itemDisenchantLoot.SkillRequired > player.GetSkillValue(SkillType.Enchanting)) + if (disenchantSkillRequired > player.GetSkillValue(SkillType.Enchanting)) return SpellCastResult.CantBeSalvagedSkill; break; } @@ -9816,11 +9816,11 @@ namespace Game.Spells public class CastSpellExtraArgsInit { public TriggerCastFlags TriggerFlags; + public Difficulty CastDifficulty; public Item CastItem; public Spell TriggeringSpell; public AuraEffect TriggeringAura; public ObjectGuid OriginalCaster; - public Difficulty CastDifficulty; public ObjectGuid OriginalCastId; public int? OriginalCastItemLevel; public SpellValueOverride Value; diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 3a039ff32..5352fd98c 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -3106,7 +3106,7 @@ namespace Game.Spells if (m_CastItem == null) caster.UpdateCraftSkill(m_spellInfo); itemTarget.loot = new Loot(caster.GetMap(), itemTarget.GetGUID(), LootType.Disenchanting, null); - itemTarget.loot.FillLoot(itemTarget.GetDisenchantLoot(caster).Id, LootStorage.Disenchant, caster, true); + itemTarget.loot.FillLoot(itemTarget.GetDisenchantLootId().GetValueOrDefault(), LootStorage.Disenchant, caster, true); caster.SendLoot(itemTarget.loot); }