mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[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:
parent
fdd8176d74
commit
160777848a
2 changed files with 212 additions and 147 deletions
|
|
@ -10051,29 +10051,17 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
|
|||
// in specific slot
|
||||
if( bag != NULL_BAG && slot != NULL_SLOT )
|
||||
{
|
||||
if( pProto->InventoryType == INVTYPE_BAG )
|
||||
if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END )
|
||||
{
|
||||
Bag *pBag = (Bag*)pItem;
|
||||
if( pBag )
|
||||
{
|
||||
if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END )
|
||||
{
|
||||
if( !HasBankBagSlot( slot ) )
|
||||
return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
|
||||
if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK )
|
||||
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 )
|
||||
if (!pItem->IsBag())
|
||||
return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT;
|
||||
|
||||
Bag *pBag = (Bag*)pItem;
|
||||
if( !HasBankBagSlot( slot ) )
|
||||
return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT;
|
||||
|
||||
if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK )
|
||||
return cantuse;
|
||||
}
|
||||
|
||||
res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem);
|
||||
|
|
@ -11230,6 +11218,8 @@ void Player::SwapItem( uint16 src, uint16 dst )
|
|||
return;
|
||||
}
|
||||
|
||||
// SRC checks
|
||||
|
||||
if(pSrcItem->m_lootGenerated) // prevent swap looting item
|
||||
{
|
||||
//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
|
||||
if(IsEquipmentPos ( src ) || IsBagPos ( src ))
|
||||
{
|
||||
// bags can be swapped with empty bag slots
|
||||
uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst ));
|
||||
// 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 ) || pDstItem && pDstItem->IsBag() && ((Bag*)pDstItem)->IsEmpty());
|
||||
if(msg != EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, pSrcItem, pDstItem );
|
||||
|
|
@ -11256,6 +11246,34 @@ void Player::SwapItem( uint16 src, uint16 dst )
|
|||
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( IsInventoryPos( dst ) )
|
||||
|
|
@ -11298,140 +11316,187 @@ void Player::SwapItem( uint16 src, uint16 dst )
|
|||
EquipItem( dest, pSrcItem, true);
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else // if (!pDstItem)
|
||||
|
||||
// attempt merge to / fill target item
|
||||
if(!pSrcItem->IsBag() && !pDstItem->IsBag())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// attempt merge to / fill target item
|
||||
{
|
||||
uint8 msg;
|
||||
ItemPosCountVec sDest;
|
||||
uint16 eDest;
|
||||
if( IsInventoryPos( dst ) )
|
||||
msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, false );
|
||||
else if( IsBankPos ( dst ) )
|
||||
msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, false );
|
||||
else if( IsEquipmentPos ( dst ) )
|
||||
msg = CanEquipItem( dstslot, eDest, pSrcItem, false );
|
||||
else
|
||||
return;
|
||||
|
||||
// can be merge/fill
|
||||
if(msg == EQUIP_ERR_OK)
|
||||
{
|
||||
if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->GetMaxStackSize())
|
||||
{
|
||||
RemoveItem(srcbag, srcslot, true);
|
||||
|
||||
if( IsInventoryPos( dst ) )
|
||||
StoreItem( sDest, pSrcItem, true);
|
||||
else if( IsBankPos ( dst ) )
|
||||
BankItem( sDest, pSrcItem, true);
|
||||
else if( IsEquipmentPos ( dst ) )
|
||||
{
|
||||
EquipItem( eDest, pSrcItem, true);
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->GetMaxStackSize());
|
||||
pDstItem->SetCount( pSrcItem->GetProto()->GetMaxStackSize());
|
||||
pSrcItem->SetState(ITEM_CHANGED, this);
|
||||
pDstItem->SetState(ITEM_CHANGED, this);
|
||||
if( IsInWorld() )
|
||||
{
|
||||
pSrcItem->SendUpdateToPlayer( this );
|
||||
pDstItem->SendUpdateToPlayer( this );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// impossible merge/fill, do real swap
|
||||
uint8 msg;
|
||||
|
||||
// check src->dest move possibility
|
||||
ItemPosCountVec sDest;
|
||||
uint16 eDest;
|
||||
if( IsInventoryPos( dst ) )
|
||||
msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, true );
|
||||
else if( IsBankPos( dst ) )
|
||||
msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, true );
|
||||
else if( IsEquipmentPos( dst ) )
|
||||
{
|
||||
msg = CanEquipItem( dstslot, eDest, pSrcItem, true );
|
||||
if( msg == EQUIP_ERR_OK )
|
||||
msg = CanUnequipItem( eDest, true );
|
||||
}
|
||||
msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, false );
|
||||
else if( IsBankPos ( dst ) )
|
||||
msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, false );
|
||||
else if( IsEquipmentPos ( dst ) )
|
||||
msg = CanEquipItem( dstslot, eDest, pSrcItem, false );
|
||||
else
|
||||
return;
|
||||
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
// can be merge/fill
|
||||
if(msg == EQUIP_ERR_OK)
|
||||
{
|
||||
SendEquipError( msg, pSrcItem, pDstItem );
|
||||
if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->GetMaxStackSize())
|
||||
{
|
||||
RemoveItem(srcbag, srcslot, true);
|
||||
|
||||
if( IsInventoryPos( dst ) )
|
||||
StoreItem( sDest, pSrcItem, true);
|
||||
else if( IsBankPos ( dst ) )
|
||||
BankItem( sDest, pSrcItem, true);
|
||||
else if( IsEquipmentPos ( dst ) )
|
||||
{
|
||||
EquipItem( eDest, pSrcItem, true);
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->GetMaxStackSize());
|
||||
pDstItem->SetCount( pSrcItem->GetProto()->GetMaxStackSize());
|
||||
pSrcItem->SetState(ITEM_CHANGED, this);
|
||||
pDstItem->SetState(ITEM_CHANGED, this);
|
||||
if( IsInWorld() )
|
||||
{
|
||||
pSrcItem->SendUpdateToPlayer( this );
|
||||
pDstItem->SendUpdateToPlayer( this );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// check dest->src move possibility
|
||||
ItemPosCountVec sDest2;
|
||||
uint16 eDest2;
|
||||
if( IsInventoryPos( src ) )
|
||||
msg = CanStoreItem( srcbag, srcslot, sDest2, pDstItem, true );
|
||||
else if( IsBankPos( src ) )
|
||||
msg = CanBankItem( srcbag, srcslot, sDest2, pDstItem, true );
|
||||
else if( IsEquipmentPos( src ) )
|
||||
{
|
||||
msg = CanEquipItem( srcslot, eDest2, pDstItem, true);
|
||||
if( msg == EQUIP_ERR_OK )
|
||||
msg = CanUnequipItem( eDest2, true);
|
||||
}
|
||||
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
{
|
||||
SendEquipError( msg, pDstItem, pSrcItem );
|
||||
return;
|
||||
}
|
||||
|
||||
// now do moves, remove...
|
||||
RemoveItem(dstbag, dstslot, false);
|
||||
RemoveItem(srcbag, srcslot, false);
|
||||
|
||||
// add to dest
|
||||
if( IsInventoryPos( dst ) )
|
||||
StoreItem(sDest, pSrcItem, true);
|
||||
else if( IsBankPos( dst ) )
|
||||
BankItem(sDest, pSrcItem, true);
|
||||
else if( IsEquipmentPos( dst ) )
|
||||
EquipItem(eDest, pSrcItem, true);
|
||||
|
||||
// add to src
|
||||
if( IsInventoryPos( src ) )
|
||||
StoreItem(sDest2, pDstItem, true);
|
||||
else if( IsBankPos( src ) )
|
||||
BankItem(sDest2, pDstItem, true);
|
||||
else if( IsEquipmentPos( src ) )
|
||||
EquipItem(eDest2, pDstItem, true);
|
||||
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
|
||||
// impossible merge/fill, do real swap
|
||||
uint8 msg;
|
||||
|
||||
// check src->dest move possibility
|
||||
ItemPosCountVec sDest;
|
||||
uint16 eDest;
|
||||
if( IsInventoryPos( dst ) )
|
||||
msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, true );
|
||||
else if( IsBankPos( dst ) )
|
||||
msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, true );
|
||||
else if( IsEquipmentPos( dst ) )
|
||||
{
|
||||
msg = CanEquipItem( dstslot, eDest, pSrcItem, true );
|
||||
if( msg == EQUIP_ERR_OK )
|
||||
msg = CanUnequipItem( eDest, true );
|
||||
}
|
||||
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
{
|
||||
SendEquipError( msg, pSrcItem, pDstItem );
|
||||
return;
|
||||
}
|
||||
|
||||
// check dest->src move possibility
|
||||
ItemPosCountVec sDest2;
|
||||
uint16 eDest2;
|
||||
if( IsInventoryPos( src ) )
|
||||
msg = CanStoreItem( srcbag, srcslot, sDest2, pDstItem, true );
|
||||
else if( IsBankPos( src ) )
|
||||
msg = CanBankItem( srcbag, srcslot, sDest2, pDstItem, true );
|
||||
else if( IsEquipmentPos( src ) )
|
||||
{
|
||||
msg = CanEquipItem( srcslot, eDest2, pDstItem, true);
|
||||
if( msg == EQUIP_ERR_OK )
|
||||
msg = CanUnequipItem( eDest2, true);
|
||||
}
|
||||
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
{
|
||||
SendEquipError( msg, pDstItem, pSrcItem );
|
||||
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...
|
||||
RemoveItem(dstbag, dstslot, false);
|
||||
RemoveItem(srcbag, srcslot, false);
|
||||
|
||||
// add to dest
|
||||
if( IsInventoryPos( dst ) )
|
||||
StoreItem(sDest, pSrcItem, true);
|
||||
else if( IsBankPos( dst ) )
|
||||
BankItem(sDest, pSrcItem, true);
|
||||
else if( IsEquipmentPos( dst ) )
|
||||
EquipItem(eDest, pSrcItem, true);
|
||||
|
||||
// add to src
|
||||
if( IsInventoryPos( src ) )
|
||||
StoreItem(sDest2, pDstItem, true);
|
||||
else if( IsBankPos( src ) )
|
||||
BankItem(sDest2, pDstItem, true);
|
||||
else if( IsEquipmentPos( src ) )
|
||||
EquipItem(eDest2, pDstItem, true);
|
||||
|
||||
AutoUnequipOffhandIfNeed();
|
||||
}
|
||||
|
||||
void Player::AddItemToBuyBackSlot( Item *pItem )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue