mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-02 15:53:51 +00:00
feat: add auto-sell grey items on vendor open
When 'Auto Sell Greys' is enabled in Settings > Gameplay, all grey (ItemQuality::POOR) items in the backpack and extra bags are sold automatically when opening a vendor window. Items with no sell price are skipped. A system chat message reports the number of items sold and total gold received. The setting persists to ~/.wowee/settings.cfg under the key auto_sell_grey.
This commit is contained in:
parent
e62ae8b03e
commit
072f256af6
4 changed files with 75 additions and 1 deletions
|
|
@ -1394,6 +1394,8 @@ public:
|
||||||
const LootResponseData& getCurrentLoot() const { return currentLoot; }
|
const LootResponseData& getCurrentLoot() const { return currentLoot; }
|
||||||
void setAutoLoot(bool enabled) { autoLoot_ = enabled; }
|
void setAutoLoot(bool enabled) { autoLoot_ = enabled; }
|
||||||
bool isAutoLoot() const { return autoLoot_; }
|
bool isAutoLoot() const { return autoLoot_; }
|
||||||
|
void setAutoSellGrey(bool enabled) { autoSellGrey_ = enabled; }
|
||||||
|
bool isAutoSellGrey() const { return autoSellGrey_; }
|
||||||
|
|
||||||
// Master loot candidates (from SMSG_LOOT_MASTER_LIST)
|
// Master loot candidates (from SMSG_LOOT_MASTER_LIST)
|
||||||
const std::vector<uint64_t>& getMasterLootCandidates() const { return masterLootCandidates_; }
|
const std::vector<uint64_t>& getMasterLootCandidates() const { return masterLootCandidates_; }
|
||||||
|
|
@ -2879,6 +2881,7 @@ private:
|
||||||
// ---- Phase 5: Loot ----
|
// ---- Phase 5: Loot ----
|
||||||
bool lootWindowOpen = false;
|
bool lootWindowOpen = false;
|
||||||
bool autoLoot_ = false;
|
bool autoLoot_ = false;
|
||||||
|
bool autoSellGrey_ = false;
|
||||||
LootResponseData currentLoot;
|
LootResponseData currentLoot;
|
||||||
std::vector<uint64_t> masterLootCandidates_; // from SMSG_LOOT_MASTER_LIST
|
std::vector<uint64_t> masterLootCandidates_; // from SMSG_LOOT_MASTER_LIST
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ private:
|
||||||
bool pendingSeparateBags = true;
|
bool pendingSeparateBags = true;
|
||||||
bool pendingShowKeyring = true;
|
bool pendingShowKeyring = true;
|
||||||
bool pendingAutoLoot = false;
|
bool pendingAutoLoot = false;
|
||||||
|
bool pendingAutoSellGrey = false;
|
||||||
|
|
||||||
// Keybinding customization
|
// Keybinding customization
|
||||||
int pendingRebindAction = -1; // -1 = not rebinding, otherwise action index
|
int pendingRebindAction = -1; // -1 = not rebinding, otherwise action index
|
||||||
|
|
|
||||||
|
|
@ -21197,6 +21197,68 @@ void GameHandler::handleListInventory(network::Packet& packet) {
|
||||||
vendorWindowOpen = true;
|
vendorWindowOpen = true;
|
||||||
gossipWindowOpen = false; // Close gossip if vendor opens
|
gossipWindowOpen = false; // Close gossip if vendor opens
|
||||||
|
|
||||||
|
// Auto-sell grey items if enabled
|
||||||
|
if (autoSellGrey_ && currentVendorItems.vendorGuid != 0) {
|
||||||
|
uint32_t totalSellPrice = 0;
|
||||||
|
int itemsSold = 0;
|
||||||
|
|
||||||
|
// Helper lambda to attempt selling a poor-quality slot
|
||||||
|
auto tryAutoSell = [&](const ItemSlot& slot, uint64_t itemGuid) {
|
||||||
|
if (slot.empty()) return;
|
||||||
|
if (slot.item.quality != ItemQuality::POOR) return;
|
||||||
|
// Determine sell price (slot cache first, then item info fallback)
|
||||||
|
uint32_t sp = slot.item.sellPrice;
|
||||||
|
if (sp == 0) {
|
||||||
|
if (auto* info = getItemInfo(slot.item.itemId); info && info->valid)
|
||||||
|
sp = info->sellPrice;
|
||||||
|
}
|
||||||
|
if (sp == 0 || itemGuid == 0) return;
|
||||||
|
BuybackItem sold;
|
||||||
|
sold.itemGuid = itemGuid;
|
||||||
|
sold.item = slot.item;
|
||||||
|
sold.count = 1;
|
||||||
|
buybackItems_.push_front(sold);
|
||||||
|
if (buybackItems_.size() > 12) buybackItems_.pop_back();
|
||||||
|
pendingSellToBuyback_[itemGuid] = sold;
|
||||||
|
sellItem(currentVendorItems.vendorGuid, itemGuid, 1);
|
||||||
|
totalSellPrice += sp;
|
||||||
|
++itemsSold;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backpack slots
|
||||||
|
for (int i = 0; i < inventory.getBackpackSize(); ++i) {
|
||||||
|
uint64_t guid = backpackSlotGuids_[i];
|
||||||
|
if (guid == 0) guid = resolveOnlineItemGuid(inventory.getBackpackSlot(i).item.itemId);
|
||||||
|
tryAutoSell(inventory.getBackpackSlot(i), guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra bag slots
|
||||||
|
for (int b = 0; b < inventory.NUM_BAG_SLOTS; ++b) {
|
||||||
|
uint64_t bagGuid = equipSlotGuids_[19 + b];
|
||||||
|
for (int s = 0; s < inventory.getBagSize(b); ++s) {
|
||||||
|
uint64_t guid = 0;
|
||||||
|
if (bagGuid != 0) {
|
||||||
|
auto it = containerContents_.find(bagGuid);
|
||||||
|
if (it != containerContents_.end() && s < static_cast<int>(it->second.numSlots))
|
||||||
|
guid = it->second.slotGuids[s];
|
||||||
|
}
|
||||||
|
if (guid == 0) guid = resolveOnlineItemGuid(inventory.getBagSlot(b, s).item.itemId);
|
||||||
|
tryAutoSell(inventory.getBagSlot(b, s), guid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemsSold > 0) {
|
||||||
|
uint32_t gold = totalSellPrice / 10000;
|
||||||
|
uint32_t silver = (totalSellPrice % 10000) / 100;
|
||||||
|
uint32_t copper = totalSellPrice % 100;
|
||||||
|
char buf[128];
|
||||||
|
std::snprintf(buf, sizeof(buf),
|
||||||
|
"|cffaaaaaaAuto-sold %d grey item%s for %ug %us %uc.|r",
|
||||||
|
itemsSold, itemsSold == 1 ? "" : "s", gold, silver, copper);
|
||||||
|
addSystemChatMessage(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Play vendor sound
|
// Play vendor sound
|
||||||
if (npcVendorCallback_ && currentVendorItems.vendorGuid != 0) {
|
if (npcVendorCallback_ && currentVendorItems.vendorGuid != 0) {
|
||||||
auto entity = entityManager.getEntity(currentVendorItems.vendorGuid);
|
auto entity = entityManager.getEntity(currentVendorItems.vendorGuid);
|
||||||
|
|
|
||||||
|
|
@ -592,8 +592,9 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply auto-loot setting to GameHandler every frame (cheap bool sync)
|
// Apply auto-loot / auto-sell settings to GameHandler every frame (cheap bool sync)
|
||||||
gameHandler.setAutoLoot(pendingAutoLoot);
|
gameHandler.setAutoLoot(pendingAutoLoot);
|
||||||
|
gameHandler.setAutoSellGrey(pendingAutoSellGrey);
|
||||||
|
|
||||||
// Zone entry detection — fire a toast when the renderer's zone name changes
|
// Zone entry detection — fire a toast when the renderer's zone name changes
|
||||||
if (auto* rend = core::Application::getInstance().getRenderer()) {
|
if (auto* rend = core::Application::getInstance().getRenderer()) {
|
||||||
|
|
@ -16328,6 +16329,11 @@ void GameScreen::renderSettingsWindow() {
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("Automatically pick up all items when looting");
|
ImGui::SetTooltip("Automatically pick up all items when looting");
|
||||||
|
if (ImGui::Checkbox("Auto Sell Greys", &pendingAutoSellGrey)) {
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
ImGui::SetTooltip("Automatically sell all grey (poor quality) items when opening a vendor");
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::Text("Bags");
|
ImGui::Text("Bags");
|
||||||
|
|
@ -18328,6 +18334,7 @@ void GameScreen::saveSettings() {
|
||||||
|
|
||||||
// Gameplay
|
// Gameplay
|
||||||
out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n";
|
out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n";
|
||||||
|
out << "auto_sell_grey=" << (pendingAutoSellGrey ? 1 : 0) << "\n";
|
||||||
out << "graphics_preset=" << static_cast<int>(currentGraphicsPreset) << "\n";
|
out << "graphics_preset=" << static_cast<int>(currentGraphicsPreset) << "\n";
|
||||||
out << "ground_clutter_density=" << pendingGroundClutterDensity << "\n";
|
out << "ground_clutter_density=" << pendingGroundClutterDensity << "\n";
|
||||||
out << "shadows=" << (pendingShadows ? 1 : 0) << "\n";
|
out << "shadows=" << (pendingShadows ? 1 : 0) << "\n";
|
||||||
|
|
@ -18469,6 +18476,7 @@ void GameScreen::loadSettings() {
|
||||||
else if (key == "activity_volume") pendingActivityVolume = std::clamp(std::stoi(val), 0, 100);
|
else if (key == "activity_volume") pendingActivityVolume = std::clamp(std::stoi(val), 0, 100);
|
||||||
// Gameplay
|
// Gameplay
|
||||||
else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0);
|
else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0);
|
||||||
|
else if (key == "auto_sell_grey") pendingAutoSellGrey = (std::stoi(val) != 0);
|
||||||
else if (key == "graphics_preset") {
|
else if (key == "graphics_preset") {
|
||||||
int presetVal = std::clamp(std::stoi(val), 0, 4);
|
int presetVal = std::clamp(std::stoi(val), 0, 4);
|
||||||
currentGraphicsPreset = static_cast<GraphicsPreset>(presetVal);
|
currentGraphicsPreset = static_cast<GraphicsPreset>(presetVal);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue