Fix exploit with swaping already looted items.
Patch by Vladimir from idea of Zhenya. Fixes issue #702. --HG-- branch : trunk
This commit is contained in:
+83
-84
@@ -9892,13 +9892,10 @@ uint8 Player::_CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVe
|
||||
// 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();
|
||||
@@ -9953,40 +9950,30 @@ uint8 Player::_CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, ItemPrototyp
|
||||
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;
|
||||
@@ -10010,39 +9997,30 @@ uint8 Player::_CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 slot_end, I
|
||||
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;
|
||||
@@ -10060,11 +10038,22 @@ uint8 Player::_CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32
|
||||
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)
|
||||
@@ -10542,6 +10531,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;
|
||||
@@ -10561,8 +10554,8 @@ 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())
|
||||
pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t );
|
||||
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;
|
||||
@@ -10574,7 +10567,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;
|
||||
@@ -10586,7 +10579,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;
|
||||
@@ -10603,7 +10596,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;
|
||||
@@ -10745,6 +10738,10 @@ uint8 Player::CanEquipItem(uint8 slot, uint16 &dest, Item *pItem, bool swap, boo
|
||||
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;
|
||||
|
||||
@@ -10888,6 +10885,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
|
||||
@@ -10912,12 +10913,6 @@ uint8 Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pI
|
||||
if (!pItem)
|
||||
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
|
||||
|
||||
if (pItem->m_lootGenerated)
|
||||
{
|
||||
GetSession()->DoLootRelease(GetLootGUID());
|
||||
return EQUIP_ERR_OK;
|
||||
}
|
||||
|
||||
uint32 count = pItem->GetCount();
|
||||
|
||||
sLog.outDebug("STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount());
|
||||
@@ -10925,6 +10920,10 @@ uint8 Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pI
|
||||
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;
|
||||
|
||||
@@ -12061,6 +12060,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)
|
||||
{
|
||||
@@ -12075,13 +12081,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)
|
||||
|
||||
Reference in New Issue
Block a user