From caece3435199ce6cdae2e7a2766c174f7afb33b1 Mon Sep 17 00:00:00 2001 From: Tecc Date: Mon, 24 Aug 2026 14:27:09 +0000 Subject: [PATCH] fix(seller): stop price override items from bypassing every filter InitializeBins() is where the bind, class, level, quality, disabled item and whitelist filters are applied, and it feeds the per-quality bins. The price override map is loaded separately by LoadPriceOverrides() with no filtering at all, and GetItemsToSell() builds its two priority blocks straight from that map. Sell() then only checks the per-item count cap, that a prototype exists and that the quality is in range - so any item holding a row in mod_auctionhousebot_priceOverride got listed no matter what the filters said. That is how bind on pickup gear (Twin Blades of Azzinoth) reached the auction house while AuctionHouseBot.Bind_When_Picked_Up was 0, and it also meant rows added to mod_auctionhousebot_disabled_items had no effect on any item that had a price override. InitializeBins() now records every item that passed its tests in SellableItems, and the two priority blocks skip anything that is not in it. A price override is a price, not a permission to sell. The bin-sourced blocks were always filtered and are unchanged. --- src/AuctionHouseBot.cpp | 14 ++++++++++++++ src/AuctionHouseBotConfig.cpp | 15 +++++++++++++++ src/AuctionHouseBotConfig.h | 5 +++++ 3 files changed, 34 insertions(+) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 22a6ef8..138bdb7 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -1334,6 +1334,15 @@ std::vector AuctionHouseBot::GetItemsToSell(AHBConfig* config, ObjectGui for (const auto& [itemID, _] : config->itemPriceOverrides) { + // A price override row is a price, not a permission to sell: the item still + // has to have passed the filters in InitializeBins(). Without this, anything + // with an override slipped past the bind, class, level, disabled item and + // whitelist filters - which is how BoP gear reached the auction house. + if (!config->IsSellableItem(itemID)) + { + continue; + } + if (missingStacks(itemID) == 0) { continue; @@ -1359,6 +1368,11 @@ std::vector AuctionHouseBot::GetItemsToSell(AHBConfig* config, ObjectGui std::vector itemsWithOverrides; for (const auto& [itemID, _] : config->itemPriceOverrides) { + if (!config->IsSellableItem(itemID)) + { + continue; + } + itemsWithOverrides.push_back(itemID); } std::shuffle(itemsWithOverrides.begin(), itemsWithOverrides.end(), std::mt19937(std::random_device()())); diff --git a/src/AuctionHouseBotConfig.cpp b/src/AuctionHouseBotConfig.cpp index 954998c..38bdf81 100644 --- a/src/AuctionHouseBotConfig.cpp +++ b/src/AuctionHouseBotConfig.cpp @@ -377,6 +377,12 @@ AHBConfig::AHBConfig(uint32 ahid, AHBConfig* conf) { YellowItemsBin.insert(id); } + + SellableItems.clear(); + for (uint32 id: conf->SellableItems) + { + SellableItems.insert(id); + } } AHBConfig::~AHBConfig() @@ -600,6 +606,8 @@ void AHBConfig::Reset() OrangeItemsBin.clear(); YellowItemsBin.clear(); + SellableItems.clear(); + itemsCount.clear(); itemsSum.clear(); itemsPrice.clear(); @@ -3362,6 +3370,8 @@ void AHBConfig::InitializeBins() // Now that the items passed all the tests, organize it by quality // + SellableItems.insert(itr->second.ItemId); + if (itr->second.Class == ITEM_CLASS_TRADE_GOODS) { switch (itr->second.Quality) @@ -3623,6 +3633,11 @@ void AHBConfig::LoadCountOverrides() LOG_INFO("module", "AHBConfig: Loaded {} count overrides from mod_auctionhousebot_countOverride", itemCountOverrides.size()); } +bool AHBConfig::IsSellableItem(uint32 itemId) const +{ + return SellableItems.find(itemId) != SellableItems.end(); +} + uint32 AHBConfig::GetCountOverrideForItem(uint32 itemId) const { auto it = itemCountOverrides.find(itemId); diff --git a/src/AuctionHouseBotConfig.h b/src/AuctionHouseBotConfig.h index 0222d1a..428d777 100644 --- a/src/AuctionHouseBotConfig.h +++ b/src/AuctionHouseBotConfig.h @@ -285,6 +285,10 @@ class AHBConfig std::set OrangeItemsBin; std::set YellowItemsBin; + // Every item that passed the filters in InitializeBins(), i.e. the union of + // all the bins above. Lets the price override path reuse the filter verdict. + std::set SellableItems; + // Vectors for items std::vector GreyItemsVec; std::vector WhiteItemsVec; @@ -398,6 +402,7 @@ class AHBConfig uint64 GetItemPrice(uint32 id); void LoadPriceOverrides(); + bool IsSellableItem(uint32 itemId) const; void LoadCountOverrides(); void LoadBotGUIDs();