diff --git a/src/game/Item.cpp b/src/game/Item.cpp index 8afad4a07..10eef36eb 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -709,6 +709,9 @@ bool Item::IsEquipped() const bool Item::CanBeTraded(bool mail) const { + if (m_lootGenerated) + return false; + if ((!mail || !IsBoundAccountWide()) && IsSoulBound()) return false; @@ -1017,6 +1020,23 @@ void Item::BuildUpdateData(UpdateDataMapType& update_players) ClearUpdateMask(false); } +uint8 Item::CanBeMergedPartlyWith( ItemPrototype const* proto ) const +{ + // check item type + if (GetEntry() != proto->ItemId) + return EQUIP_ERR_ITEM_CANT_STACK; + + // check free space (full stacks can't be target of merge + if (GetCount() >= proto->GetMaxStackSize()) + return EQUIP_ERR_ITEM_CANT_STACK; + + // not allow merge looting currently items + if (m_lootGenerated) + return EQUIP_ERR_ALREADY_LOOTED; + + return EQUIP_ERR_OK; +} + bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const { if(pUnitTarget->GetTypeId() != TYPEID_UNIT) diff --git a/src/game/Item.h b/src/game/Item.h index 52fc9693d..409f8cee9 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -264,6 +264,7 @@ class MANGOS_DLL_SPEC Item : public Object uint32 GetMaxStackCount() const { return GetProto()->GetMaxStackSize(); } uint8 GetGemCountWithID(uint32 GemID) const; uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const; + uint8 CanBeMergedPartlyWith(ItemPrototype const* proto) const; uint8 GetSlot() const {return m_slot;} Bag *GetContainer() { return m_container; } diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 7887859f5..800b78a97 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -150,13 +150,6 @@ void WorldSession::HandleAutoEquipItemOpcode( WorldPacket & recv_data ) if( !pSrcItem ) return; // only at cheat - if(pSrcItem->m_lootGenerated) // prevent swap looting item - { - //best error message found for attempting to swap while looting - _player->SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL ); - return; - } - uint16 dest; uint8 msg = _player->CanEquipItem( NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag() ); if( msg != EQUIP_ERR_OK ) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d0665376d..c6a746ce4 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9033,13 +9033,10 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV // non empty slot, check item type else { - // check item type - if (pItem2->GetEntry() != pProto->ItemId) - return EQUIP_ERR_ITEM_CANT_STACK; - - // check free space - if (pItem2->GetCount() >= pProto->GetMaxStackSize()) - return EQUIP_ERR_ITEM_CANT_STACK; + // can be merged at least partly + uint8 res = pItem2->CanBeMergedPartlyWith(pProto); + if (res != EQUIP_ERR_OK) + return res; // free stack space or infinity need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); @@ -9095,40 +9092,30 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy if ((pItem2 != NULL) != merge) continue; + uint32 need_space = pProto->GetMaxStackSize(); + if (pItem2) { - if (pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize()) - { - uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); - if(need_space > count) - need_space = count; + // can be merged at least partly + uint8 res = pItem2->CanBeMergedPartlyWith(pProto); + if (res != EQUIP_ERR_OK) + continue; - ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space); - if (!newPosition.isContainedIn(dest)) - { - dest.push_back(newPosition); - count -= need_space; - - if (count==0) - return EQUIP_ERR_OK; - } - } + // descrease at current stacksize + need_space -= pItem2->GetCount(); } - else + + if (need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space); + if (!newPosition.isContainedIn(dest)) { - uint32 need_space = pProto->GetMaxStackSize(); - if (need_space > count) - need_space = count; + dest.push_back(newPosition); + count -= need_space; - ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space); - if (!newPosition.isContainedIn(dest)) - { - dest.push_back(newPosition); - count -= need_space; - - if (count==0) - return EQUIP_ERR_OK; - } + if (count==0) + return EQUIP_ERR_OK; } } return EQUIP_ERR_OK; @@ -9152,39 +9139,30 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, if ((pItem2 != NULL) != merge) continue; + uint32 need_space = pProto->GetMaxStackSize(); + if (pItem2) { - if (pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize()) - { - uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); - if (need_space > count) - need_space = count; - ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); - if (!newPosition.isContainedIn(dest)) - { - dest.push_back(newPosition); - count -= need_space; + // can be merged at least partly + uint8 res = pItem2->CanBeMergedPartlyWith(pProto); + if (res != EQUIP_ERR_OK) + continue; - if (count==0) - return EQUIP_ERR_OK; - } - } + // descrease at current stacksize + need_space -= pItem2->GetCount(); } - else + + if (need_space > count) + need_space = count; + + ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); + if (!newPosition.isContainedIn(dest)) { - uint32 need_space = pProto->GetMaxStackSize(); - if (need_space > count) - need_space = count; + dest.push_back(newPosition); + count -= need_space; - ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); - if (!newPosition.isContainedIn(dest)) - { - dest.push_back(newPosition); - count -= need_space; - - if (count==0) - return EQUIP_ERR_OK; - } + if (count==0) + return EQUIP_ERR_OK; } } return EQUIP_ERR_OK; @@ -9202,11 +9180,22 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED :EQUIP_ERR_ITEM_NOT_FOUND; } - if (pItem && pItem->IsBindedNotWith(this)) + if (pItem) { - if (no_space_count) - *no_space_count = count; - return EQUIP_ERR_DONT_OWN_THAT_ITEM; + // item used + if(pItem->m_lootGenerated) + { + if (no_space_count) + *no_space_count = count; + return EQUIP_ERR_ALREADY_LOOTED; + } + + if (pItem->IsBindedNotWith(this)) + { + if (no_space_count) + *no_space_count = count; + return EQUIP_ERR_DONT_OWN_THAT_ITEM; + } } // check count of items (skip for auto move for same player from bank) @@ -9684,6 +9673,10 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if( !pProto ) return EQUIP_ERR_ITEM_NOT_FOUND; + // item used + if(pItem->m_lootGenerated) + return EQUIP_ERR_ALREADY_LOOTED; + // item it 'bind' if(pItem->IsBindedNotWith(this)) return EQUIP_ERR_DONT_OWN_THAT_ITEM; @@ -9704,7 +9697,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; ++t) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) + if( pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount(); b_found = true; @@ -9716,7 +9709,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) + if( pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount(); b_found = true; @@ -9728,7 +9721,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++t) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) + if( pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_slot_items[t-INVENTORY_SLOT_ITEM_START] += pItem->GetCount(); b_found = true; @@ -9745,7 +9738,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(uint32 j = 0; j < pBag->GetBagSize(); ++j) { pItem2 = GetItemByPos( t, j ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->GetMaxStackSize()) + if( pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); b_found = true; @@ -9887,6 +9880,10 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo ItemPrototype const *pProto = pItem->GetProto(); if( pProto ) { + // item used + if(pItem->m_lootGenerated) + return EQUIP_ERR_ALREADY_LOOTED; + if(pItem->IsBindedNotWith(this)) return EQUIP_ERR_DONT_OWN_THAT_ITEM; @@ -10030,6 +10027,10 @@ uint8 Player::CanUnequipItem( uint16 pos, bool swap ) const if( !pProto ) return EQUIP_ERR_ITEM_NOT_FOUND; + // item used + if(pItem->m_lootGenerated) + return EQUIP_ERR_ALREADY_LOOTED; + // do not allow unequipping gear except weapons, offhands, projectiles, relics in // - combat // - in-progress arenas @@ -10054,9 +10055,6 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p if (!pItem) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; - if (pItem->m_lootGenerated) - return EQUIP_ERR_ITEM_LOCKED; - uint32 count = pItem->GetCount(); sLog.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount()); @@ -10064,6 +10062,10 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p if (!pProto) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; + // item used + if(pItem->m_lootGenerated) + return EQUIP_ERR_ALREADY_LOOTED; + if (pItem->IsBindedNotWith(this)) return EQUIP_ERR_DONT_OWN_THAT_ITEM; @@ -11149,6 +11151,13 @@ void Player::SplitItem( uint16 src, uint16 dst, uint32 count ) return; } + if(pSrcItem->m_lootGenerated) // prevent split looting item (item + { + //best error message found for attempting to split while looting + SendEquipError( EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL ); + return; + } + // not let split all items (can be only at cheating) if(pSrcItem->GetCount() == count) { @@ -11163,13 +11172,6 @@ void Player::SplitItem( uint16 src, uint16 dst, uint32 count ) return; } - if(pSrcItem->m_lootGenerated) // prevent split looting item (item - { - //best error message found for attempting to split while looting - SendEquipError( EQUIP_ERR_COULDNT_SPLIT_ITEMS, pSrcItem, NULL ); - return; - } - sLog.outDebug( "STORAGE: SplitItem bag = %u, slot = %u, item = %u, count = %u", dstbag, dstslot, pSrcItem->GetEntry(), count); Item *pNewItem = pSrcItem->CloneItem( count, this ); if( !pNewItem ) @@ -11265,13 +11267,6 @@ void Player::SwapItem( uint16 src, uint16 dst ) // SRC checks - if (pSrcItem->m_lootGenerated) // prevent swap looting item - { - //best error message found for attempting to swap while looting - SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL ); - return; - } - // check unequip potability for equipped items and bank bags if (IsEquipmentPos(src) || IsBagPos(src)) { @@ -11302,13 +11297,6 @@ void Player::SwapItem( uint16 src, uint16 dst ) if (pDstItem) { - if(pDstItem->m_lootGenerated) // prevent swap looting item - { - //best error message found for attempting to swap while looting - SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL ); - return; - } - // check unequip potability for equipped items and bank bags if(IsEquipmentPos ( dst ) || IsBagPos ( dst )) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 61b76bbb6..9b83207f2 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 "9226" + #define REVISION_NR "9227" #endif // __REVISION_NR_H__