Core/Items: Fix item spell selection for items that have multiple on-use effects

(cherry picked from commit 06dee8eabfa02879c5c22b4f083272b84d59d93f)
This commit is contained in:
Shauren
2026-06-28 20:42:44 +02:00
parent 2698482140
commit 6f40090a7b
2 changed files with 42 additions and 58 deletions
+41 -57
View File
@@ -8774,72 +8774,56 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
}
}
void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, ObjectGuid castCount, std::array<int32, 3> const& misc)
void Player::CastItemUseSpell(Item* item, uint32 spellId, SpellCastTargets const& targets, ObjectGuid castCount, std::array<int32, 3> const& misc)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: {}) has wrong spell id {}, ignoring", item->GetEntry(), spellId);
return;
}
ItemTemplate const* proto = item->GetTemplate();
bool isValidSpell = false;
if (!item->GetTemplate()->HasFlag(ITEM_FLAG_LEGACY))
{
// item spells cast at use
for (ItemEffectEntry const* effectData : item->GetEffects())
isValidSpell = std::ranges::any_of(item->GetEffects(), [spellId](ItemEffectEntry const* effectData)
{
// wrong triggering type
if (effectData->TriggerType != ITEM_SPELLTRIGGER_ON_USE)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: {}) has wrong spell id {}, ignoring", item->GetEntry(), effectData->SpellID);
continue;
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
WorldPackets::Spells::SpellPrepare spellPrepare;
spellPrepare.ClientCastID = castCount;
spellPrepare.ServerCastID = spell->m_castId;
SendDirectMessage(spellPrepare.Write());
spell->m_fromClient = true;
spell->m_CastItem = item;
std::ranges::copy(misc, std::ranges::begin(spell->m_misc.Raw.Data));
spell->prepare(targets);
return;
}
return effectData->SpellID == int32(spellId) && effectData->TriggerType == ITEM_SPELLTRIGGER_ON_USE;
});
}
// Item enchantments spells cast at use
for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot)
if (!isValidSpell)
{
uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot));
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!pEnchant)
continue;
for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s)
isValidSpell = [&]
{
if (pEnchant->Effect[s] != ITEM_ENCHANTMENT_TYPE_USE_SPELL)
continue;
for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot))))
for (uint8 enchantEffect = 0; enchantEffect < MAX_ITEM_ENCHANTMENT_EFFECTS; ++enchantEffect)
if (enchant->Effect[enchantEffect] == ITEM_ENCHANTMENT_TYPE_USE_SPELL && enchant->EffectArg[enchantEffect] == spellId)
return true;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s], DIFFICULTY_NONE);
if (!spellInfo)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Enchant {}, cast unknown spell {}", pEnchant->ID, pEnchant->EffectArg[s]);
continue;
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
WorldPackets::Spells::SpellPrepare spellPrepare;
spellPrepare.ClientCastID = castCount;
spellPrepare.ServerCastID = spell->m_castId;
SendDirectMessage(spellPrepare.Write());
spell->m_fromClient = true;
spell->m_CastItem = item;
std::ranges::copy(misc, std::ranges::begin(spell->m_misc.Raw.Data));
spell->prepare(targets);
return;
}
return false;
}();
}
if (!isValidSpell)
{
TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Tried to cast Spell {} not found on Item {}, ignoring", spellId, proto->GetId());
return;
}
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
WorldPackets::Spells::SpellPrepare spellPrepare;
spellPrepare.ClientCastID = castCount;
spellPrepare.ServerCastID = spell->m_castId;
SendDirectMessage(spellPrepare.Write());
spell->m_fromClient = true;
spell->m_CastItem = item;
std::ranges::copy(misc, std::ranges::begin(spell->m_misc.Raw.Data));
spell->prepare(targets);
}
void Player::ApplyItemLootedSpell(Item* item, bool apply)
@@ -31751,7 +31735,7 @@ bool Player::ProcessItemCast(SpellCastRequest& castRequest, SpellCastTargets con
if (!sScriptMgr->OnItemUse(this, item, targets, castRequest.CastRequest.CastID))
{
// no script or script not process request by self
CastItemUseSpell(item, targets, castRequest.CastRequest.CastID, castRequest.CastRequest.Misc);
CastItemUseSpell(item, castRequest.CastRequest.SpellID, targets, castRequest.CastRequest.CastID, castRequest.CastRequest.Misc);
}
return true;
+1 -1
View File
@@ -2554,7 +2554,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void CastItemCombatSpell(DamageInfo const& damageInfo);
void CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemTemplate const* proto);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, ObjectGuid castCount, std::array<int32, 3> const& misc);
void CastItemUseSpell(Item* item, uint32 spellId, SpellCastTargets const& targets, ObjectGuid castCount, std::array<int32, 3> const& misc);
void ApplyItemLootedSpell(Item* item, bool apply);
void ApplyItemLootedSpell(ItemTemplate const* itemTemplate);