aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrazom62 <none@none>2010-05-31 19:10:26 +0200
committerTrazom62 <none@none>2010-05-31 19:10:26 +0200
commit15847b2f2f8be359f7d152a9f088c4a4052e9622 (patch)
tree7ebe081787b9a60cabd2f66c58578d58b93ec104
parent1a636d3af87ff1390925c407f93e49bb687027b6 (diff)
Fix exploit with swaping already looted items.
Patch by Vladimir from idea of Zhenya. Fixes issue #702. --HG-- branch : trunk
-rw-r--r--src/game/Item.cpp20
-rw-r--r--src/game/Item.h1
-rw-r--r--src/game/ItemHandler.cpp7
-rw-r--r--src/game/Player.cpp167
4 files changed, 104 insertions, 91 deletions
diff --git a/src/game/Item.cpp b/src/game/Item.cpp
index cbb27666033..4cfd9484f9f 100644
--- a/src/game/Item.cpp
+++ b/src/game/Item.cpp
@@ -705,6 +705,9 @@ bool Item::IsEquipped() const
bool Item::CanBeTraded(bool mail) const
{
+ if (m_lootGenerated)
+ return false;
+
if ((!mail || !IsBoundAccountWide()) && IsSoulBound())
return false;
@@ -766,6 +769,23 @@ bool Item::IsBoundByEnchant() const
return false;
}
+uint8 Item::CanBeMergedPartlyWith(ItemPrototype const* proto) const
+{
+ // not allow merge looting currently items
+ if (m_lootGenerated)
+ return EQUIP_ERR_ALREADY_LOOTED;
+
+ // 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;
+
+ return EQUIP_ERR_OK;
+}
+
bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
{
ItemPrototype const* proto = GetProto();
diff --git a/src/game/Item.h b/src/game/Item.h
index b4112b3d132..1bddd344ed4 100644
--- a/src/game/Item.h
+++ b/src/game/Item.h
@@ -265,6 +265,7 @@ class 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 5e70910f774..53aede43492 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -153,13 +153,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 0864266fb81..5e74fc99e3e 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -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;
-
- ItemPosCount newPosition = ItemPosCount((bag << 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
- {
- uint32 need_space = pProto->GetMaxStackSize();
- if (need_space > count)
- need_space = count;
- ItemPosCount newPosition = ItemPosCount((bag << 8) | j, need_space);
- if (!newPosition.isContainedIn(dest))
- {
- dest.push_back(newPosition);
- count -= need_space;
+ if (need_space > count)
+ need_space = count;
- if (count == 0)
- return EQUIP_ERR_OK;
- }
+ 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;
}
}
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
- {
- uint32 need_space = pProto->GetMaxStackSize();
- 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;
+ if (need_space > count)
+ need_space = count;
- if (count == 0)
- return EQUIP_ERR_OK;
- }
+ 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;
}
}
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)