[7228] Implement empty bag swap with equipped non-empty bag with items exchange.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>

More early checks and proper swap bank bags in patch.
Correct error messages in fail case.
This commit is contained in:
nugu100 2009-02-04 23:36:01 +03:00 committed by VladimirMangos
parent fdd8176d74
commit 160777848a
2 changed files with 212 additions and 147 deletions

View file

@ -10050,31 +10050,19 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
// in specific slot // in specific slot
if( bag != NULL_BAG && slot != NULL_SLOT ) if( bag != NULL_BAG && slot != NULL_SLOT )
{
if( pProto->InventoryType == INVTYPE_BAG )
{
Bag *pBag = (Bag*)pItem;
if( pBag )
{ {
if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END )
{ {
if (!pItem->IsBag())
return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
Bag *pBag = (Bag*)pItem;
if( !HasBankBagSlot( slot ) ) if( !HasBankBagSlot( slot ) )
return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK ) if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK )
return cantuse; return cantuse;
} }
else
{
if( !pBag->IsEmpty() )
return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG;
}
}
}
else
{
if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END )
return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
}
res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem);
if(res!=EQUIP_ERR_OK) if(res!=EQUIP_ERR_OK)
@ -11230,6 +11218,8 @@ void Player::SwapItem( uint16 src, uint16 dst )
return; return;
} }
// SRC checks
if(pSrcItem->m_lootGenerated) // prevent swap looting item if(pSrcItem->m_lootGenerated) // prevent swap looting item
{ {
//best error message found for attempting to swap while looting //best error message found for attempting to swap while looting
@ -11240,8 +11230,8 @@ void Player::SwapItem( uint16 src, uint16 dst )
// check unequip potability for equipped items and bank bags // check unequip potability for equipped items and bank bags
if(IsEquipmentPos ( src ) || IsBagPos ( src )) if(IsEquipmentPos ( src ) || IsBagPos ( src ))
{ {
// bags can be swapped with empty bag slots // bags can be swapped with empty bag slots, or with empty bag (items move possibility checked later)
uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst )); uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst ) || pDstItem && pDstItem->IsBag() && ((Bag*)pDstItem)->IsEmpty());
if(msg != EQUIP_ERR_OK) if(msg != EQUIP_ERR_OK)
{ {
SendEquipError( msg, pSrcItem, pDstItem ); SendEquipError( msg, pSrcItem, pDstItem );
@ -11256,6 +11246,34 @@ void Player::SwapItem( uint16 src, uint16 dst )
return; return;
} }
// DST checks
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 ))
{
// bags can be swapped with empty bag slots, or with empty bag (items move possibility checked later)
uint8 msg = CanUnequipItem( dst, !IsBagPos ( dst ) || IsBagPos ( src ) || pSrcItem->IsBag() && ((Bag*)pSrcItem)->IsEmpty());
if(msg != EQUIP_ERR_OK)
{
SendEquipError( msg, pSrcItem, pDstItem );
return;
}
}
}
// NOW this is or item move (swap with empty), or swap with another item (including bags in bag possitions)
// or swap empty bag with another empty or not empty bag (with items exchange)
// Move case
if( !pDstItem ) if( !pDstItem )
{ {
if( IsInventoryPos( dst ) ) if( IsInventoryPos( dst ) )
@ -11298,29 +11316,12 @@ void Player::SwapItem( uint16 src, uint16 dst )
EquipItem( dest, pSrcItem, true); EquipItem( dest, pSrcItem, true);
AutoUnequipOffhandIfNeed(); AutoUnequipOffhandIfNeed();
} }
}
else // 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 ))
{
// bags can be swapped with empty bag slots
uint8 msg = CanUnequipItem( dst, !IsBagPos ( dst ) || IsBagPos ( src ) );
if(msg != EQUIP_ERR_OK)
{
SendEquipError( msg, pSrcItem, pDstItem );
return; return;
} }
}
// attempt merge to / fill target item // attempt merge to / fill target item
if(!pSrcItem->IsBag() && !pDstItem->IsBag())
{ {
uint8 msg; uint8 msg;
ItemPosCountVec sDest; ItemPosCountVec sDest;
@ -11410,6 +11411,71 @@ void Player::SwapItem( uint16 src, uint16 dst )
return; return;
} }
// Check bag swap with item exchange (one from empty in not bag possition (equipped (not possible in fact) or store)
if(pSrcItem->IsBag() && pDstItem->IsBag())
{
Bag* emptyBag = NULL;
Bag* fullBag = NULL;
if(((Bag*)pSrcItem)->IsEmpty() && !IsBagPos(src))
{
emptyBag = (Bag*)pSrcItem;
fullBag = (Bag*)pDstItem;
}
else if(((Bag*)pDstItem)->IsEmpty() && !IsBagPos(dst))
{
emptyBag = (Bag*)pDstItem;
fullBag = (Bag*)pSrcItem;
}
// bag swap (with items exchange) case
if(emptyBag && fullBag)
{
ItemPrototype const* emotyProto = emptyBag->GetProto();
uint32 count = 0;
for(int i=0; i < fullBag->GetBagSize(); ++i)
{
Item *bagItem = fullBag->GetItemByPos(i);
if (!bagItem)
continue;
ItemPrototype const* bagItemProto = bagItem->GetProto();
if (!bagItemProto || !ItemCanGoIntoBag(bagItemProto, emotyProto))
{
// one from items not go to empry target bag
SendEquipError( EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem );
return;
}
++count;
}
if (count > emptyBag->GetBagSize())
{
// too small targeted bag
SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem );
return;
}
// Items swap
count = 0; // will pos in new bag
for(int i=0; i< fullBag->GetBagSize(); ++i)
{
Item *bagItem = fullBag->GetItemByPos(i);
if (!bagItem)
continue;
fullBag->RemoveItem(i, true);
emptyBag->StoreItem(count, bagItem, true);
bagItem->SetState(ITEM_CHANGED, this);
++count;
}
}
}
// now do moves, remove... // now do moves, remove...
RemoveItem(dstbag, dstslot, false); RemoveItem(dstbag, dstslot, false);
RemoveItem(srcbag, srcslot, false); RemoveItem(srcbag, srcslot, false);
@ -11432,7 +11498,6 @@ void Player::SwapItem( uint16 src, uint16 dst )
AutoUnequipOffhandIfNeed(); AutoUnequipOffhandIfNeed();
} }
}
void Player::AddItemToBuyBackSlot( Item *pItem ) void Player::AddItemToBuyBackSlot( Item *pItem )
{ {

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7227" #define REVISION_NR "7228"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__