diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index 9786e0530..3b1a28aab 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -188,6 +188,15 @@ Item* Bag::GetItemByEntry( uint32 item ) const return NULL; } +Item* Bag::GetItemByLimitedCategory(uint32 limitedCategory) const +{ + for(uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i] && m_bagslot[i]->GetProto()->ItemLimitCategory == limitedCategory) + return m_bagslot[i]; + + return NULL; +} + uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const { Item *pItem; diff --git a/src/game/Bag.h b/src/game/Bag.h index 4306d628c..ac57858ef 100644 --- a/src/game/Bag.h +++ b/src/game/Bag.h @@ -43,6 +43,7 @@ class Bag : public Item Item* GetItemByPos( uint8 slot ) const; Item* GetItemByEntry( uint32 item ) const; + Item* GetItemByLimitedCategory(uint32 limitedCategory) const; uint32 GetItemCount( uint32 item, Item* eItem = NULL ) const; uint32 GetItemCountWithLimitCategory(uint32 limitCategory) const; diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index a6112d537..4ba2be5da 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -329,6 +329,12 @@ enum ItemLimitCategoryMode ITEM_LIMIT_CATEGORY_MODE_EQUIP = 1, // limit applied to amount equipped items (including used gems) }; +// some used in code cases +enum ItemLimitCategory +{ + ITEM_LIMIT_CATEGORY_MANA_GEM = 4, +}; + enum TotemCategoryType { TOTEM_CATEGORY_TYPE_KNIFE = 1, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index fc8e2dd87..096375817 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -8642,6 +8642,26 @@ Item* Player::GetItemByEntry( uint32 item ) const return NULL; } +Item* Player::GetItemByLimitedCategory(uint32 limitedCategory) const +{ + for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) + if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + if (pItem->GetProto()->ItemLimitCategory == limitedCategory) + return pItem; + + for(int i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) + if (Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + if (pItem->GetProto()->ItemLimitCategory == limitedCategory) + return pItem; + + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + if (Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i)) + if (Item* itemPtr = pBag->GetItemByLimitedCategory(limitedCategory)) + return itemPtr; + + return NULL; +} + Item* Player::GetItemByGuid( uint64 guid ) const { for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) @@ -15523,7 +15543,7 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff) } // "Conjured items disappear if you are logged out for more than 15 minutes" - if ((timediff > 15*60) && (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED))) + if (timediff > 15*MINUTE && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED)) { CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); item->FSetState(ITEM_REMOVED); @@ -15591,7 +15611,13 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff) // item's state may have changed after stored if (success) + { item->SetState(ITEM_UNCHANGED, this); + + // recharged mana gem + if (timediff > 15*MINUTE && proto->ItemLimitCategory ==ITEM_LIMIT_CATEGORY_MANA_GEM) + item->RestoreCharges(); + } else { sLog.outError("Player::_LoadInventory: Player %s has item (GUID: %u Entry: %u) can't be loaded to inventory (Bag GUID: %u Slot: %u) by some reason, will send by mail.", GetName(),item_guid, item_id, bag_guid, slot); diff --git a/src/game/Player.h b/src/game/Player.h index 23e1a8bcf..f4b5cec74 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1151,6 +1151,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 GetItemCountWithLimitCategory(uint32 limitCategory) const; Item* GetItemByGuid( uint64 guid ) const; Item* GetItemByEntry(uint32 item) const; // only for special cases + Item* GetItemByLimitedCategory(uint32 limitedCategory) const; Item* GetItemByPos( uint16 pos ) const; Item* GetItemByPos( uint8 bag, uint8 slot ) const; Item* GetWeaponForAttack(WeaponAttackType attackType) const { return GetWeaponForAttack(attackType,false,false); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 95f5dd427..9c6f63a30 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -5614,16 +5614,22 @@ SpellCastResult Spell::CheckItems() { if (!m_IsTriggeredSpell && m_spellInfo->EffectItemType[i]) { - // Conjure Mana Gem + // Conjure Mana Gem (skip same or low level ranks for later recharge) if (i == EFFECT_INDEX_0 && m_spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_DUMMY) { - if (Item* item = p_caster->GetItemByEntry(m_spellInfo->EffectItemType[i])) + if (ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(m_spellInfo->EffectItemType[i])) { - if (item->HasMaxCharges()) - return SPELL_FAILED_ITEM_AT_MAX_CHARGES; + if (Item* item = p_caster->GetItemByLimitedCategory(itemProto->ItemLimitCategory)) + { + if (item->GetProto()->ItemLevel <= itemProto->ItemLevel) + { + if (item->HasMaxCharges()) + return SPELL_FAILED_ITEM_AT_MAX_CHARGES; - // will recharge in next effect - continue; + // will recharge in next effect + continue; + } + } } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index fe136bdea..45592684a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1656,6 +1656,14 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) // Conjure Mana Gem if (eff_idx == EFFECT_INDEX_1 && m_spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_CREATE_ITEM) { + if (m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + // checked in create item check, avoid unexpected + if (Item* item = ((Player*)m_caster)->GetItemByLimitedCategory(ITEM_LIMIT_CATEGORY_MANA_GEM)) + if (item->HasMaxCharges()) + return; + unitTarget->CastSpell( unitTarget, m_spellInfo->CalculateSimpleValue(eff_idx), true, m_CastItem); return; } @@ -7455,6 +7463,19 @@ void Spell::EffectRestoreItemCharges( SpellEffectIndex eff_idx ) Player* player = (Player*)unitTarget; - if (Item* item = player->GetItemByEntry(m_spellInfo->EffectItemType[eff_idx])) - item->RestoreCharges(); + ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(m_spellInfo->EffectItemType[eff_idx]); + if (!itemProto) + return; + + // In case item from limited category recharge any from category, is this valid checked early in spell checks + Item* item; + if (itemProto->ItemLimitCategory) + item = player->GetItemByLimitedCategory(itemProto->ItemLimitCategory); + else + item = player->GetItemByEntry(m_spellInfo->EffectItemType[eff_idx]); + + if (!item) + return; + + item->RestoreCharges(); } \ No newline at end of file diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9246e42a7..f16e8f9cc 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 "9507" + #define REVISION_NR "9508" #endif // __REVISION_NR_H__