aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlan Deutscher <adeutscher@gmail.com>2020-04-16 11:21:01 -0700
committerShauren <shauren.trinity@gmail.com>2022-01-01 16:29:06 +0100
commit68e1dc8adb84a3df5241358be591400db39e4d62 (patch)
treed1d6ce8c44bb167bd1adf8308f2d9d85251ae41f /src
parentd6931f392e4a5d11c7eeb8c415b5757a4381f03b (diff)
Core/Players: Improve trade exchange calculations (#24435)
* Add some comments to Player::CanStoreItems to help me wrap my head around how the method works. * Experimental fix for incoming trade-stack problem. * Only add to stacks that aren't already full. * Use remaining_count instead of static 1. * Remove debug logging from exploration. * More uses of remaining_count for consistency. * Correct space count check * Correct overflow problem. * Remove redundant check, handled in existing for statement. * Store Item pointers in order to be able to merge in multiple incoming stacks. * Build fix - was continually working locally, but failing in CI. * Break build in order to keep PR focused on Player.cpp changes. * Adjust phrasing of how arrays are initialized. * Fix phrasing of comments to avoid sounding like a ToDo item * In the spirit of b649273d5f, rephrase an old comment to be a statement rather than a question. (cherry picked from commit e11a13c755fcc7912d54bd4732795e1d992aab0c)
Diffstat (limited to 'src')
-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;
}