aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp84
1 files changed, 60 insertions, 24 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 94367e1a6e4..b472ca3a795 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -11237,41 +11237,57 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
{
Item* item2;
- // fill space table
- uint32 inventoryCounts[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START];
- uint32 bagCounts[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE];
+ // fill space tables, creating a mock-up of the player's inventory
- memset(inventoryCounts, 0, sizeof(uint32) * (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
- memset(bagCounts, 0, sizeof(uint32) * (INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START) * MAX_BAG_SIZE);
+ // counts
+ uint32 inventoryCounts[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START] = {};
+ uint32 bagCounts[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE] = {};
+
+ // Item pointers
+ Item* inventoryPointers[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START] = {};
+ Item* bagPointers[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE] = {};
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
+
+ // filling inventory
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < inventoryEnd; i++)
{
+ // build items in stock backpack
item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
if (item2 && !item2->IsInTrade())
+ {
inventoryCounts[i - INVENTORY_SLOT_ITEM_START] = item2->GetCount();
+ inventoryPointers[i - INVENTORY_SLOT_ITEM_START] = item2;
+ }
}
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
+ // build item counts in equippable bags
item2 = GetItemByPos(i, j);
if (item2 && !item2->IsInTrade())
+ {
bagCounts[i - INVENTORY_SLOT_BAG_START][j] = item2->GetCount();
+ bagPointers[i - INVENTORY_SLOT_BAG_START][j] = item2;
+ }
}
- // check free space for all items
+ // check free space for all items that we wish to add
for (int k = 0; k < count; ++k)
{
+ // Incoming item
Item* item = items[k];
// no item
if (!item)
continue;
+ uint32_t remaining_count = item->GetCount();
+
TC_LOG_DEBUG("entities.player.items", "Player::CanStoreItems: Player '%s' (%s), Index: %i ItemID: %u, Count: %u",
- GetName().c_str(), GetGUID().ToString().c_str(), k + 1, item->GetEntry(), item->GetCount());
+ GetName().c_str(), GetGUID().ToString().c_str(), k + 1, item->GetEntry(), remaining_count);
ItemTemplate const* pProto = item->GetTemplate();
// strange item
@@ -11300,14 +11316,19 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
for (int t = INVENTORY_SLOT_ITEM_START; t < inventoryEnd; ++t)
{
- item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inventoryCounts[t-INVENTORY_SLOT_ITEM_START] + item->GetCount() <= pProto->GetMaxStackSize())
+ item2 = inventoryPointers[t-INVENTORY_SLOT_ITEM_START];
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inventoryCounts[t-INVENTORY_SLOT_ITEM_START] < pProto->GetMaxStackSize())
{
- inventoryCounts[t-INVENTORY_SLOT_ITEM_START] += item->GetCount();
- b_found = true;
- break;
+ inventoryCounts[t-INVENTORY_SLOT_ITEM_START] += remaining_count;
+ remaining_count = inventoryCounts[t-INVENTORY_SLOT_ITEM_START] < pProto->GetMaxStackSize() ? 0 : inventoryCounts[t-INVENTORY_SLOT_ITEM_START] - pProto->GetMaxStackSize();
+
+ b_found = remaining_count == 0;
+ // if no pieces of the stack remain, then stop checking stock bag
+ if (b_found)
+ break;
}
}
+
if (b_found)
continue;
@@ -11315,21 +11336,28 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
{
if (Bag* bag = GetBagByPos(t))
{
- if (ItemCanGoIntoBag(item->GetTemplate(), bag->GetTemplate()))
+ if (!ItemCanGoIntoBag(item->GetTemplate(), bag->GetTemplate()))
+ continue;
+
+ for (uint32 j = 0; j < bag->GetBagSize(); j++)
{
- for (uint32 j = 0; j < bag->GetBagSize(); j++)
+ item2 = bagPointers[t-INVENTORY_SLOT_BAG_START][j];
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && bagCounts[t-INVENTORY_SLOT_BAG_START][j] < pProto->GetMaxStackSize())
{
- item2 = GetItemByPos(t, j);
- if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && bagCounts[t-INVENTORY_SLOT_BAG_START][j] + item->GetCount() <= pProto->GetMaxStackSize())
- {
- bagCounts[t-INVENTORY_SLOT_BAG_START][j] += item->GetCount();
- b_found = true;
+ // add count to stack so that later items in the list do not double-book
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] += remaining_count;
+ remaining_count = bagCounts[t-INVENTORY_SLOT_BAG_START][j] < pProto->GetMaxStackSize() ? 0 : bagCounts[t-INVENTORY_SLOT_BAG_START][j] - pProto->GetMaxStackSize();
+
+ b_found = remaining_count == 0;
+
+ // if no pieces of the stack remain, then stop checking equippable bags
+ if (b_found)
break;
- }
}
}
}
}
+
if (b_found)
continue;
}
@@ -11353,7 +11381,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
{
if (bagCounts[t-INVENTORY_SLOT_BAG_START][j] == 0)
{
- bagCounts[t-INVENTORY_SLOT_BAG_START][j] = 1;
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] = remaining_count;
+ bagPointers[t-INVENTORY_SLOT_BAG_START][j] = item;
+
b_found = true;
break;
}
@@ -11361,6 +11391,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
}
}
}
+
if (b_found)
continue;
}
@@ -11371,11 +11402,14 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
{
if (inventoryCounts[t-INVENTORY_SLOT_ITEM_START] == 0)
{
- inventoryCounts[t-INVENTORY_SLOT_ITEM_START] = 1;
+ inventoryCounts[t-INVENTORY_SLOT_ITEM_START] = remaining_count;
+ inventoryPointers[t-INVENTORY_SLOT_ITEM_START] = item;
+
b_found = true;
break;
}
}
+
if (b_found)
continue;
@@ -11394,7 +11428,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
{
if (bagCounts[t - INVENTORY_SLOT_BAG_START][j] == 0)
{
- bagCounts[t - INVENTORY_SLOT_BAG_START][j] = 1;
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] = remaining_count;
+ bagPointers[t-INVENTORY_SLOT_BAG_START][j] = item;
+
b_found = true;
break;
}
@@ -11402,7 +11438,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offending
}
}
- // no free slot found?
+ // if no free slot found for all pieces of the item, then return an error
if (!b_found)
return EQUIP_ERR_BAG_FULL;
}