diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 84 |
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; } |
