mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 08:03:50 +00:00
feat: add Sort Bags button to backpack window
Adds Inventory::sortBags() which collects all items from the backpack and equip bags, sorts them client-side by quality descending → item ID ascending → stack count descending, then writes them back. A "Sort Bags" SmallButton is rendered in the backpack footer with a tooltip explaining the sort order. The sort is purely local (no server packets) since the WoW protocol has no sort-bags opcode; it provides an instant, session-persistent visual reorder.
This commit is contained in:
parent
3e3bbf915e
commit
d99fe8de0f
3 changed files with 66 additions and 10 deletions
|
|
@ -125,6 +125,10 @@ public:
|
||||||
int findFreeBackpackSlot() const;
|
int findFreeBackpackSlot() const;
|
||||||
bool addItem(const ItemDef& item);
|
bool addItem(const ItemDef& item);
|
||||||
|
|
||||||
|
// Sort all bag slots (backpack + equip bags) by quality desc → itemId asc → stackCount desc.
|
||||||
|
// Purely client-side: reorders the local inventory struct without server interaction.
|
||||||
|
void sortBags();
|
||||||
|
|
||||||
// Test data
|
// Test data
|
||||||
void populateTestItems();
|
void populateTestItems();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "game/inventory.hpp"
|
#include "game/inventory.hpp"
|
||||||
#include "core/logger.hpp"
|
#include "core/logger.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace wowee {
|
namespace wowee {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
@ -185,6 +186,44 @@ bool Inventory::addItem(const ItemDef& item) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inventory::sortBags() {
|
||||||
|
// Collect all items from backpack and equip bags into a flat list.
|
||||||
|
std::vector<ItemDef> items;
|
||||||
|
items.reserve(BACKPACK_SLOTS + NUM_BAG_SLOTS * MAX_BAG_SIZE);
|
||||||
|
|
||||||
|
for (int i = 0; i < BACKPACK_SLOTS; ++i) {
|
||||||
|
if (!backpack[i].empty())
|
||||||
|
items.push_back(backpack[i].item);
|
||||||
|
}
|
||||||
|
for (int b = 0; b < NUM_BAG_SLOTS; ++b) {
|
||||||
|
for (int s = 0; s < bags[b].size; ++s) {
|
||||||
|
if (!bags[b].slots[s].empty())
|
||||||
|
items.push_back(bags[b].slots[s].item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort: quality descending → itemId ascending → stackCount descending.
|
||||||
|
std::stable_sort(items.begin(), items.end(), [](const ItemDef& a, const ItemDef& b) {
|
||||||
|
if (a.quality != b.quality)
|
||||||
|
return static_cast<int>(a.quality) > static_cast<int>(b.quality);
|
||||||
|
if (a.itemId != b.itemId)
|
||||||
|
return a.itemId < b.itemId;
|
||||||
|
return a.stackCount > b.stackCount;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write sorted items back, filling backpack first then equip bags.
|
||||||
|
int idx = 0;
|
||||||
|
int n = static_cast<int>(items.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < BACKPACK_SLOTS; ++i)
|
||||||
|
backpack[i].item = (idx < n) ? items[idx++] : ItemDef{};
|
||||||
|
|
||||||
|
for (int b = 0; b < NUM_BAG_SLOTS; ++b) {
|
||||||
|
for (int s = 0; s < bags[b].size; ++s)
|
||||||
|
bags[b].slots[s].item = (idx < n) ? items[idx++] : ItemDef{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Inventory::populateTestItems() {
|
void Inventory::populateTestItems() {
|
||||||
// Equipment
|
// Equipment
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1019,7 +1019,7 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen,
|
||||||
float contentH = rows * (slotSize + 4.0f) + 10.0f;
|
float contentH = rows * (slotSize + 4.0f) + 10.0f;
|
||||||
if (bagIndex < 0) {
|
if (bagIndex < 0) {
|
||||||
int keyringRows = (inventory.getKeyringSize() + columns - 1) / columns;
|
int keyringRows = (inventory.getKeyringSize() + columns - 1) / columns;
|
||||||
contentH += 25.0f; // money display for backpack
|
contentH += 36.0f; // separator + sort button + money display
|
||||||
contentH += 30.0f + keyringRows * (slotSize + 4.0f); // keyring header + slots
|
contentH += 30.0f + keyringRows * (slotSize + 4.0f); // keyring header + slots
|
||||||
}
|
}
|
||||||
float gridW = columns * (slotSize + 4.0f) + 30.0f;
|
float gridW = columns * (slotSize + 4.0f) + 30.0f;
|
||||||
|
|
@ -1094,9 +1094,21 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Money display at bottom of backpack
|
// Footer for backpack: sort button + money display
|
||||||
if (bagIndex < 0 && moneyCopper > 0) {
|
if (bagIndex < 0) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Sort Bags button — client-side reorder by quality/type
|
||||||
|
if (ImGui::SmallButton("Sort Bags")) {
|
||||||
|
inventory.sortBags();
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Sort all bag slots by quality (highest first),\nthen by item ID, then by stack size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moneyCopper > 0) {
|
||||||
|
ImGui::SameLine();
|
||||||
uint64_t gold = moneyCopper / 10000;
|
uint64_t gold = moneyCopper / 10000;
|
||||||
uint64_t silver = (moneyCopper / 100) % 100;
|
uint64_t silver = (moneyCopper / 100) % 100;
|
||||||
uint64_t copper = moneyCopper % 100;
|
uint64_t copper = moneyCopper % 100;
|
||||||
|
|
@ -1105,6 +1117,7 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen,
|
||||||
static_cast<unsigned long long>(silver),
|
static_cast<unsigned long long>(silver),
|
||||||
static_cast<unsigned long long>(copper));
|
static_cast<unsigned long long>(copper));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue