diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 138 |
1 files changed, 98 insertions, 40 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 215a82d169c..aad83013be1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -10976,58 +10976,81 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { 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]; - uint32 keyringCounts[KEYRING_SLOT_END - KEYRING_SLOT_START]; - uint32 currencyCounts[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START]; + // 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); - memset(keyringCounts, 0, sizeof(uint32) * (KEYRING_SLOT_END - KEYRING_SLOT_START)); - memset(currencyCounts, 0, sizeof(uint32) * (CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START)); + // counts + uint32 inventoryCounts[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START] = {}; + uint32 bagCounts[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE] = {}; + uint32 keyringCounts[KEYRING_SLOT_END - KEYRING_SLOT_START] = {}; + uint32 currencyCounts[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START] = {}; + // 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] = {}; + Item* keyringPointers[KEYRING_SLOT_END - KEYRING_SLOT_START] = {}; + Item* currencyPointers[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START] = {}; + + // filling inventory for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; 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 = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) { + // build items in key ring 'bag' item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (item2 && !item2->IsInTrade()) + { keyringCounts[i - KEYRING_SLOT_START] = item2->GetCount(); + keyringPointers[i - KEYRING_SLOT_START] = item2; + } } for (uint8 i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++) { + // build items in currency 'bag' item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (item2 && !item2->IsInTrade()) + { currencyCounts[i - CURRENCYTOKEN_SLOT_START] = item2->GetCount(); + currencyPointers[i - CURRENCYTOKEN_SLOT_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 @@ -11056,40 +11079,56 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit for (uint8 t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; ++t) { - item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t); - if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && keyringCounts[t-KEYRING_SLOT_START] + item->GetCount() <= pProto->GetMaxStackSize()) + item2 = keyringPointers[t-KEYRING_SLOT_START]; + if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && keyringCounts[t-KEYRING_SLOT_START] < pProto->GetMaxStackSize()) { - keyringCounts[t-KEYRING_SLOT_START] += item->GetCount(); - b_found = true; - break; + keyringCounts[t-KEYRING_SLOT_START] += remaining_count; + remaining_count = keyringCounts[t-KEYRING_SLOT_START] < pProto->GetMaxStackSize() ? 0 : keyringCounts[t-KEYRING_SLOT_START] - pProto->GetMaxStackSize(); + + b_found = remaining_count == 0; + + // if no pieces of the stack remain, then stop checking keyring + if (b_found) + break; } } + if (b_found) continue; for (int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) { - item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t); - if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && currencyCounts[t-CURRENCYTOKEN_SLOT_START] + item->GetCount() <= pProto->GetMaxStackSize()) + item2 = currencyPointers[t-CURRENCYTOKEN_SLOT_START]; + if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && currencyCounts[t-CURRENCYTOKEN_SLOT_START] < pProto->GetMaxStackSize()) { - currencyCounts[t-CURRENCYTOKEN_SLOT_START] += item->GetCount(); - b_found = true; - break; + currencyCounts[t-CURRENCYTOKEN_SLOT_START] += remaining_count; + remaining_count = currencyCounts[t-CURRENCYTOKEN_SLOT_START] < pProto->GetMaxStackSize() ? 0 : currencyCounts[t-CURRENCYTOKEN_SLOT_START] - pProto->GetMaxStackSize(); + + b_found = remaining_count == 0; + // if no pieces of the stack remain, then stop checking currency 'bag' + if (b_found) + break; } } + if (b_found) continue; for (int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++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; @@ -11097,21 +11136,28 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { 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; } @@ -11127,7 +11173,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { if (keyringCounts[t-KEYRING_SLOT_START] == 0) { - keyringCounts[t-KEYRING_SLOT_START] = 1; + keyringCounts[t-KEYRING_SLOT_START] = remaining_count; + keyringPointers[t-KEYRING_SLOT_START] = item; + b_found = true; break; } @@ -11143,7 +11191,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { if (currencyCounts[t-CURRENCYTOKEN_SLOT_START] == 0) { - currencyCounts[t-CURRENCYTOKEN_SLOT_START] = 1; + currencyCounts[t-CURRENCYTOKEN_SLOT_START] = remaining_count; + currencyPointers [t-CURRENCYTOKEN_SLOT_START] = item; + b_found = true; break; } @@ -11167,7 +11217,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { 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; } @@ -11175,6 +11227,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit } } } + if (b_found) continue; } @@ -11185,11 +11238,14 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { 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; @@ -11208,7 +11264,9 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit { 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; } @@ -11216,7 +11274,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit } } - // 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; } |