diff --git a/src/game/MailHandler.cpp b/src/game/MailHandler.cpp index c7c8db657..84ada5d04 100644 --- a/src/game/MailHandler.cpp +++ b/src/game/MailHandler.cpp @@ -493,8 +493,8 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data ) Item *it = pl->GetMItem(itemId); ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, it, false ); - if( msg == EQUIP_ERR_OK ) + InventoryResult msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, it, false ); + if (msg == EQUIP_ERR_OK) { m->RemoveItem(itemId); m->removedItems.push_back(itemId); @@ -771,8 +771,8 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data ) DETAIL_LOG("HandleMailCreateTextItem mailid=%u", mailId); ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, bodyItem, false ); - if( msg == EQUIP_ERR_OK ) + InventoryResult msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, bodyItem, false ); + if (msg == EQUIP_ERR_OK) { m->checked = m->checked | MAIL_CHECK_MASK_COPIED; m->state = MAIL_STATE_CHANGED; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ca9ff4451..c6d67cfd0 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -822,33 +822,33 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 // bags and main-hand weapon must equipped at this moment // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) // or ammo not equipped in special bag - for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) { - if(Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) { uint16 eDest; // equip offhand weapon/shield if it attempt equipped before main-hand weapon - uint8 msg = CanEquipItem( NULL_SLOT, eDest, pItem, false ); - if( msg == EQUIP_ERR_OK ) + InventoryResult msg = CanEquipItem(NULL_SLOT, eDest, pItem, false); + if (msg == EQUIP_ERR_OK) { - RemoveItem(INVENTORY_SLOT_BAG_0, i,true); - EquipItem( eDest, pItem, true); + RemoveItem(INVENTORY_SLOT_BAG_0, i, true); + EquipItem(eDest, pItem, true); } // move other items to more appropriate slots (ammo not equipped in special bag) else { ItemPosCountVec sDest; - msg = CanStoreItem( NULL_BAG, NULL_SLOT, sDest, pItem, false ); - if( msg == EQUIP_ERR_OK ) + msg = CanStoreItem(NULL_BAG, NULL_SLOT, sDest, pItem, false); + if (msg == EQUIP_ERR_OK) { RemoveItem(INVENTORY_SLOT_BAG_0, i,true); pItem = StoreItem( sDest, pItem, true); } // if this is ammo then use it - msg = CanUseAmmo( pItem->GetEntry() ); - if( msg == EQUIP_ERR_OK ) - SetAmmo( pItem->GetEntry() ); + msg = CanUseAmmo(pItem->GetEntry()); + if (msg == EQUIP_ERR_OK) + SetAmmo(pItem->GetEntry()); } } } @@ -10496,7 +10496,7 @@ InventoryResult Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, return EQUIP_ERR_ITEM_NOT_FOUND; } -InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading ) const +InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool direct_action ) const { dest = 0; if (pItem) @@ -10518,7 +10518,7 @@ InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, boo return res; // check this only in game - if (not_loading) + if (direct_action) { // May be here should be more stronger checks; STUNNED checked // ROOT, CONFUSED, DISTRACTED, FLEEING this needs to be checked. @@ -10530,7 +10530,7 @@ InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, boo // - in-progress arenas if (!pProto->CanChangeEquipStateInCombat()) { - if( isInCombat() ) + if (isInCombat()) return EQUIP_ERR_NOT_IN_COMBAT; if (BattleGround* bg = GetBattleGround()) @@ -10558,7 +10558,7 @@ InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, boo if (eslot == NULL_SLOT) return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; - InventoryResult msg = CanUseItem(pItem , not_loading); + InventoryResult msg = CanUseItem(pItem , direct_action); if (msg != EQUIP_ERR_OK) return msg; if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot)) @@ -10571,7 +10571,7 @@ InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, boo // check unique-equipped special item classes if (pProto->Class == ITEM_CLASS_QUIVER) { - for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) { @@ -10624,7 +10624,7 @@ InventoryResult Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, boo // offhand item must can be stored in inventory for offhand item and it also must be unequipped Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); ItemPosCountVec off_dest; - if (offItem && (!not_loading || + if (offItem && (!direct_action || CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK )) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; @@ -10865,13 +10865,13 @@ InventoryResult Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &des return EQUIP_ERR_BANK_FULL; } -InventoryResult Player::CanUseItem( Item *pItem, bool not_loading ) const +InventoryResult Player::CanUseItem(Item *pItem, bool direct_action) const { if (pItem) { DEBUG_LOG( "STORAGE: CanUseItem item = %u", pItem->GetEntry()); - if (!isAlive() && not_loading) + if (!isAlive() && direct_action) return EQUIP_ERR_YOU_ARE_DEAD; //if (isStunned()) @@ -21631,6 +21631,70 @@ void Player::AutoStoreLoot(Loot& loot, bool broadcast, uint8 bag, uint8 slot) } } +Item* Player::ConvertItem(Item* item, uint32 newItemId) +{ + uint16 pos = item->GetPos(); + + Item *pNewItem = Item::CreateItem(newItemId, 1, this); + if (!pNewItem) + return NULL; + + // copy enchantments + for (uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j) + { + if (item->GetEnchantmentId(EnchantmentSlot(j))) + pNewItem->SetEnchantment(EnchantmentSlot(j), item->GetEnchantmentId(EnchantmentSlot(j)), + item->GetEnchantmentDuration(EnchantmentSlot(j)), item->GetEnchantmentCharges(EnchantmentSlot(j))); + } + + // copy durability + if (item->GetUInt32Value(ITEM_FIELD_DURABILITY) < item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) + { + double loosePercent = 1 - item->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); + DurabilityLoss(pNewItem, loosePercent); + } + + if (IsInventoryPos(pos)) + { + ItemPosCountVec dest; + InventoryResult msg = CanStoreItem(item->GetBagSlot(), item->GetSlot(), dest, pNewItem, true); + // ignore cast/combat time restriction + if (msg == EQUIP_ERR_OK) + { + DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + return StoreItem( dest, pNewItem, true); + } + } + else if (IsBankPos(pos)) + { + ItemPosCountVec dest; + InventoryResult msg = CanBankItem(item->GetBagSlot(), item->GetSlot(), dest, pNewItem, true); + // ignore cast/combat time restriction + if (msg == EQUIP_ERR_OK) + { + DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + return BankItem(dest, pNewItem, true); + } + } + else if (IsEquipmentPos (pos)) + { + uint16 dest; + InventoryResult msg = CanEquipItem(item->GetSlot(), dest, pNewItem, true, false); + // ignore cast/combat time restriction + if (msg == EQUIP_ERR_OK) + { + DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + pNewItem = EquipItem(dest, pNewItem, true); + AutoUnequipOffhandIfNeed(); + return pNewItem; + } + } + + // fail + delete pNewItem; + return NULL; +} + uint32 Player::CalculateTalentsPoints() const { uint32 base_level = getClass() == CLASS_DEATH_KNIGHT ? 55 : 9; diff --git a/src/game/Player.h b/src/game/Player.h index 78340f9c0..280aadb7d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1218,18 +1218,18 @@ class MANGOS_DLL_SPEC Player : public Unit return _CanStoreItem( bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL ); } - InventoryResult CanStoreItems( Item **pItem,int count) const; - InventoryResult CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const; - InventoryResult CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading = true ) const; + InventoryResult CanStoreItems(Item **pItem,int count) const; + InventoryResult CanEquipNewItem(uint8 slot, uint16 &dest, uint32 item, bool swap) const; + InventoryResult CanEquipItem(uint8 slot, uint16 &dest, Item *pItem, bool swap, bool direct_action = true) const; InventoryResult CanEquipUniqueItem( Item * pItem, uint8 except_slot = NULL_SLOT, uint32 limit_count = 1 ) const; InventoryResult CanEquipUniqueItem( ItemPrototype const* itemProto, uint8 except_slot = NULL_SLOT, uint32 limit_count = 1 ) const; InventoryResult CanUnequipItems( uint32 item, uint32 count ) const; InventoryResult CanUnequipItem( uint16 src, bool swap ) const; InventoryResult CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, Item *pItem, bool swap, bool not_loading = true ) const; - InventoryResult CanUseItem( Item *pItem, bool not_loading = true ) const; - bool HasItemTotemCategory( uint32 TotemCategory ) const; - InventoryResult CanUseItem( ItemPrototype const *pItem ) const; + InventoryResult CanUseItem(Item *pItem, bool direct_action = true) const; + bool HasItemTotemCategory(uint32 TotemCategory) const; + InventoryResult CanUseItem(ItemPrototype const *pItem) const; InventoryResult CanUseAmmo( uint32 item ) const; Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 ); Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update ); @@ -1242,6 +1242,8 @@ class MANGOS_DLL_SPEC Player : public Unit void AutoStoreLoot(uint32 loot_id, LootStore const& store, bool broadcast = false, uint8 bag = NULL_BAG, uint8 slot = NULL_SLOT); void AutoStoreLoot(Loot& loot, bool broadcast = false, uint8 bag = NULL_BAG, uint8 slot = NULL_SLOT); + Item* ConvertItem(Item* item, uint32 newItemId); + InventoryResult _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const; InventoryResult _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 84e2c0092..2bb2148f2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4478,73 +4478,12 @@ void Spell::EffectSummonChangeItem(SpellEffectIndex eff_idx) if (!newitemid) return; - uint16 pos = m_CastItem->GetPos(); + Item* oldItem = m_CastItem; - Item *pNewItem = Item::CreateItem( newitemid, 1, player); - if (!pNewItem) - return; + // prevent crash at access and unexpected charges counting with item update queue corrupt + ClearCastItem(); - for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j) - { - if (m_CastItem->GetEnchantmentId(EnchantmentSlot(j))) - pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j))); - } - - if (m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) - { - double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); - player->DurabilityLoss(pNewItem, loosePercent); - } - - if (player->IsInventoryPos(pos)) - { - ItemPosCountVec dest; - uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); - if (msg == EQUIP_ERR_OK) - { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); - - // prevent crash at access and unexpected charges counting with item update queue corrupt - ClearCastItem(); - - player->StoreItem( dest, pNewItem, true); - return; - } - } - else if (player->IsBankPos (pos)) - { - ItemPosCountVec dest; - uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); - if (msg == EQUIP_ERR_OK) - { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); - - // prevent crash at access and unexpected charges counting with item update queue corrupt - ClearCastItem(); - - player->BankItem( dest, pNewItem, true); - return; - } - } - else if (player->IsEquipmentPos (pos)) - { - uint16 dest; - uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true ); - if (msg == EQUIP_ERR_OK) - { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); - - // prevent crash at access and unexpected charges counting with item update queue corrupt - ClearCastItem(); - - player->EquipItem( dest, pNewItem, true); - player->AutoUnequipOffhandIfNeed(); - return; - } - } - - // fail - delete pNewItem; + player->ConvertItem(oldItem, newitemid); } void Spell::EffectProficiency(SpellEffectIndex /*eff_idx*/) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 888c43aa8..a71cf7de7 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3695,42 +3695,42 @@ bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skip // Maybe later some special spells will be excluded too. // generic spells are casted when they are not finished and not delayed - if ( m_currentSpells[CURRENT_GENERIC_SPELL] && + if (m_currentSpells[CURRENT_GENERIC_SPELL] && (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && - (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) ) - return(true); + (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED)) + return true; // channeled spells may be delayed, but they are still considered casted - else if ( !skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] && - (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) ) - return(true); + else if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] && + (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)) + return true; // autorepeat spells may be finished or delayed, but they are still considered casted - else if ( !skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL] ) - return(true); + else if (!skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL]) + return true; - return(false); + return false; } void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id) { // generic spells are interrupted if they are not finished or delayed - if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id)) + if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id == spell_id)) InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed); // autorepeat spells are interrupted if they are not finished or delayed - if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id)) + if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == spell_id)) InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed); // channeled spells are interrupted if they are not finished, even if they are delayed - if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id)) + if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id == spell_id)) InterruptSpell(CURRENT_CHANNELED_SPELL,true); } Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const { for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i) - if(m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id==spell_id) + if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id == spell_id) return m_currentSpells[i]; return NULL; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 305d4341e..74bdbb348 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 "11644" + #define REVISION_NR "11645" #endif // __REVISION_NR_H__