diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 77faf1300..908c8e253 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -833,6 +833,17 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const { ItemPrototype const* proto = GetProto(); + // Enchant spells only use Effect[0] (patch 3.3.2) + if (proto->IsVellum() && spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_ENCHANT_ITEM) + { + // EffectItemType[0] is the associated scroll itemID, if a scroll can be made + if (spellInfo->EffectItemType[EFFECT_INDEX_0] == 0) + return false; + // Other checks do not apply to vellum enchants, so return final result + return ((proto->SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT && spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON) || + (proto->SubClass == ITEM_SUBCLASS_ARMOR_ENCHANTMENT && spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR)); + } + if (spellInfo->EquippedItemClass != -1) // -1 == any item class { if(spellInfo->EquippedItemClass != int32(proto->Class)) diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index e31364ef9..229768b88 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -666,6 +666,10 @@ struct ItemPrototype bool IsPotion() const { return Class==ITEM_CLASS_CONSUMABLE && SubClass==ITEM_SUBCLASS_POTION; } bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_FLAG_CONJURED); } + bool IsVellum() const + { + return (Class == ITEM_CLASS_TRADE_GOODS && (1 << SubClass) & (1 << ITEM_SUBCLASS_ARMOR_ENCHANTMENT | 1 << ITEM_SUBCLASS_WEAPON_ENCHANTMENT)); + } }; // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 39e87fcf9..a26f5255c 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -5969,6 +5969,8 @@ SpellCastResult Spell::CheckItems() return SPELL_CAST_OK; Player* p_caster = (Player*)m_caster; + bool isScrollItem = false; + bool isVellumTarget = false; // cast item checks if(m_CastItem) @@ -5984,6 +5986,9 @@ SpellCastResult Spell::CheckItems() if(!proto) return SPELL_FAILED_ITEM_NOT_FOUND; + if (proto->Flags & ITEM_FLAG_ENCHANT_SCROLL) + isScrollItem = true; + for (int i = 0; i < 5; ++i) if (proto->Spells[i].SpellCharges) if(m_CastItem->GetSpellCharges(i) == 0) @@ -6052,9 +6057,15 @@ SpellCastResult Spell::CheckItems() return m_IsTriggeredSpell && !(m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM) ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_ITEM_GONE; + isVellumTarget = m_targets.getItemTarget()->GetProto()->IsVellum(); if(!m_targets.getItemTarget()->IsFitToSpellRequirements(m_spellInfo)) return m_IsTriggeredSpell && !(m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM) ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_EQUIPPED_ITEM_CLASS; + + // Do not enchant vellum with scroll + if (isVellumTarget && isScrollItem) + return m_IsTriggeredSpell && !(m_targets.m_targetMask & TARGET_FLAG_TRADE_ITEM) + ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_BAD_TARGETS; } // if not item target then required item must be equipped (for triggered case not report error) else @@ -6207,6 +6218,17 @@ SpellCastResult Spell::CheckItems() if( targetItem->GetProto()->ItemLevel < m_spellInfo->baseLevel ) return SPELL_FAILED_LOWLEVEL; + // Check if we can store a new scroll, enchanting vellum has implicit SPELL_EFFECT_CREATE_ITEM + if (isVellumTarget && m_spellInfo->EffectItemType[i]) + { + ItemPosCountVec dest; + uint8 msg = p_caster->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, m_spellInfo->EffectItemType[i], 1 ); + if (msg != EQUIP_ERR_OK) + { + p_caster->SendEquipError( msg, NULL, NULL ); + return SPELL_FAILED_DONT_REPORT; + } + } // Not allow enchant in trade slot for some enchant type if( targetItem->GetOwner() != m_caster ) { @@ -6216,6 +6238,9 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_ERROR; if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND) return SPELL_FAILED_NOT_TRADEABLE; + // cannot replace vellum with scroll in trade slot + if (isVellumTarget) + return SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW; } break; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 04825950d..65b761f74 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -5018,11 +5018,6 @@ void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx) if (!itemTarget) return; - Player* p_caster = (Player*)m_caster; - - // not grow at item use at item case - p_caster->UpdateCraftSkill(m_spellInfo->Id); - uint32 enchant_id = m_spellInfo->EffectMiscValue[eff_idx]; if (!enchant_id) return; @@ -5036,6 +5031,25 @@ void Spell::EffectEnchantItemPerm(SpellEffectIndex eff_idx) if (!item_owner) return; + Player* p_caster = (Player*)m_caster; + + // Enchanting a vellum requires special handling, as it creates a new item + // instead of modifying an existing one. + ItemPrototype const* targetProto = itemTarget->GetProto(); + if (targetProto->IsVellum() && m_spellInfo->EffectItemType[eff_idx]) + { + unitTarget = m_caster; + DoCreateItem(eff_idx,m_spellInfo->EffectItemType[eff_idx]); + // Vellum target case: Target becomes additional reagent, new scroll item created instead in Spell::EffectEnchantItemPerm() + // cannot already delete in TakeReagents() unfortunately + p_caster->DestroyItemCount(targetProto->ItemId, 1, true); + return; + } + + // Using enchant stored on scroll does not increase enchanting skill! (Already granted on scroll creation) + if (!(m_CastItem && m_CastItem->GetProto()->Flags & ITEM_FLAG_ENCHANT_SCROLL)) + p_caster->UpdateCraftSkill(m_spellInfo->Id); + if (item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) ) { sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6d68267ff..7a2de543a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11202" + #define REVISION_NR "11203" #endif // __REVISION_NR_H__