From 5760e0a11f09615adddb50f062fd86817e2b4955 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Mon, 13 Nov 2023 20:00:50 -0600 Subject: [PATCH 1/6] Removed unused increment and decrement --- src/AuctionHouseBot.cpp | 79 ----------------------------------- src/AuctionHouseBot.h | 2 - src/AuctionHouseBotScript.cpp | 10 ----- 3 files changed, 91 deletions(-) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index b50f396..edad797 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -682,85 +682,6 @@ void AuctionHouseBot::InitializeConfiguration() ItemsPerCycle = sConfigMgr->GetOption("AuctionHouseBot.ItemsPerCycle", 200); } -void AuctionHouseBot::IncrementItemCounts(AuctionEntry* ah) -{ - // from auctionhousehandler.cpp, creates auction pointer & player pointer - - // get exact item information - Item *pItem = sAuctionMgr->GetAItem(ah->item_guid); - if (!pItem) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: Item {} doesn't exist, perhaps bought already?", ah->item_guid.ToString()); - return; - } - - // get item prototype - ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(ah->item_template); - - AHBConfig *config; - - AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(ah->GetHouseId()); - if (!ahEntry) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Neutral", ah->GetHouseId()); - config = &NeutralConfig; - } - else if (ahEntry->houseId == AUCTIONHOUSE_ALLIANCE) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Alliance", ah->GetHouseId()); - config = &AllianceConfig; - } - else if (ahEntry->houseId == AUCTIONHOUSE_HORDE) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Horde", ah->GetHouseId()); - config = &HordeConfig; - } - else - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Neutral", ah->GetHouseId()); - config = &NeutralConfig; - } -} - -void AuctionHouseBot::DecrementItemCounts(AuctionEntry* ah, uint32 itemEntry) -{ - // get item prototype - ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemEntry); - - AHBConfig *config; - - AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(ah->GetHouseId()); - if (!ahEntry) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Neutral", ah->GetHouseId()); - config = &NeutralConfig; - } - else if (ahEntry->houseId == AUCTIONHOUSE_ALLIANCE) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Alliance", ah->GetHouseId()); - config = &AllianceConfig; - } - else if (ahEntry->houseId == AUCTIONHOUSE_HORDE) - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Horde", ah->GetHouseId()); - config = &HordeConfig; - } - else - { - if (debug_Out) - LOG_ERROR("module", "AHBot: {} returned as House Faction. Neutral", ah->GetHouseId()); - config = &NeutralConfig; - } -} - void AuctionHouseBot::Commands(uint32 command, uint32 ahMapID, uint32 col, char* args) { AHBConfig *config = NULL; diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 193ade7..38c34d7 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -762,8 +762,6 @@ public: void Initialize(); void InitializeConfiguration(); void LoadValues(AHBConfig*); - void DecrementItemCounts(AuctionEntry* ah, uint32 itemEntry); - void IncrementItemCounts(AuctionEntry* ah); void Commands(uint32, uint32, uint32, char*); ObjectGuid::LowType GetAHBplayerGUID() { return AHBplayerGUID; }; }; diff --git a/src/AuctionHouseBotScript.cpp b/src/AuctionHouseBotScript.cpp index 19ef7c8..12be835 100644 --- a/src/AuctionHouseBotScript.cpp +++ b/src/AuctionHouseBotScript.cpp @@ -52,16 +52,6 @@ public: oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, ObjectGuid::Create(auctionbot->GetAHBplayerGUID()), newPrice, auction->GetAuctionOutBid(), auction->item_template); } - void OnAuctionAdd(AuctionHouseObject* /*ah*/, AuctionEntry* auction) override - { - auctionbot->IncrementItemCounts(auction); - } - - void OnAuctionRemove(AuctionHouseObject* /*ah*/, AuctionEntry* auction) override - { - auctionbot->DecrementItemCounts(auction, auction->item_template); - } - void OnBeforeAuctionHouseMgrUpdate() override { auctionbot->Update(); From 1f53fbf0af81b8c9599d7b794bb7aea6f789f032 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 08:12:48 -0600 Subject: [PATCH 2/6] Put back in regular bags --- conf/mod_ahbot.conf.dist | 2 +- src/AuctionHouseBot.cpp | 213 ++++++++++++++++++++------------------- src/AuctionHouseBot.h | 6 +- 3 files changed, 115 insertions(+), 106 deletions(-) diff --git a/conf/mod_ahbot.conf.dist b/conf/mod_ahbot.conf.dist index 701a890..9c6f25a 100644 --- a/conf/mod_ahbot.conf.dist +++ b/conf/mod_ahbot.conf.dist @@ -49,4 +49,4 @@ AuctionHouseBot.UseBuyPriceForSeller = 0 AuctionHouseBot.UseBuyPriceForBuyer = 0 AuctionHouseBot.Account = 0 AuctionHouseBot.GUID = 0 -AuctionHouseBot.ItemsPerCycle = 200 +AuctionHouseBot.ItemsPerCycle = 1000 diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index edad797..3e2255b 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -50,7 +50,7 @@ AuctionHouseBot::~AuctionHouseBot() { } -uint32 AuctionHouseBot::GetStackSizeForItem(ItemTemplate const* itemProto) const +uint32 AuctionHouseBot::getStackSizeForItem(ItemTemplate const* itemProto) const { // Determine the stack ratio based on class type if (itemProto == NULL) @@ -84,6 +84,114 @@ uint32 AuctionHouseBot::GetStackSizeForItem(ItemTemplate const* itemProto) const return 1; } +void AuctionHouseBot::populateItemCandidateList() +{ + // Clear old list + itemCandidates.clear(); + + // Fill list + ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); + for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) + { + // Skip any BOP items + if (itr->second.Bonding == BIND_WHEN_PICKED_UP) + continue; + + // Restrict quality to anything under 7 (artifact and below) or are 0 (poor) + if (itr->second.Quality == 0 || itr->second.Quality > 6) + continue; + + // Disabled items by Id + if (DisableItemStore.find(itr->second.ItemId) != DisableItemStore.end()) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (PTR/Beta/Unused Item)", itr->second.ItemId); + continue; + } + + // Disable conjured items + if (itr->second.IsConjuredConsumable()) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Conjured Consumable)", itr->second.ItemId); + continue; + } + + // Disable money + if (itr->second.Class == ITEM_CLASS_MONEY) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Money)", itr->second.ItemId); + continue; + } + + // Disable moneyloot + if (itr->second.MinMoneyLoot > 0) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (MoneyLoot)", itr->second.ItemId); + continue; + } + + // Disable items with duration + if (itr->second.Duration > 0) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Has a Duration)", itr->second.ItemId); + continue; + } + + // Disable items which are bind quest Items + if (itr->second.Bonding == BIND_QUEST_ITEM) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (BOP or BQI and Required Level is less than Item Level)", itr->second.ItemId); + continue; + } + + // Disable anything with the string literal of a testing or depricated item + if (itr->second.Name1.find("Test ") != std::string::npos || + itr->second.Name1.find("Unused") != std::string::npos || + itr->second.Name1.find("Deprecated") != std::string::npos || + itr->second.Name1.find(" Epic ") != std::string::npos || + itr->second.Name1.find("[PH]") != std::string::npos || + itr->second.Name1.find("[DEP]") != std::string::npos || + itr->second.Name1.find("TEST") != std::string::npos) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled item with a temp or unused item name", itr->second.ItemId); + continue; + } + + // Disable "other" consumables + if (itr->second.Class == ITEM_CLASS_CONSUMABLE && itr->second.SubClass == ITEM_SUBCLASS_CONSUMABLE_OTHER) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled consumber 'other' item", itr->second.ItemId); + continue; + } + + // Disable All Pets + if (itr->second.Class == ITEM_CLASS_MISC && itr->second.SubClass == ITEM_SUBCLASS_JUNK_PET) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); + continue; + } + + // Disable All MISC items (pets, mounts, etc) Use Subclass _JUNK_() for pets and mounts + if (itr->second.Class == ITEM_CLASS_MISC) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); + continue; + } + + // Store the item ID + itemCandidates.push_back(itr->second.ItemId); + } +} + void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) { if (!AHBSeller) @@ -234,7 +342,7 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) } // Set stack size - uint32 stackCount = GetStackSizeForItem(prototype); + uint32 stackCount = getStackSizeForItem(prototype); item->SetCount(stackCount); uint32 dep = sAuctionMgr->GetAuctionDeposit(ahEntry, etime, item, stackCount); @@ -559,106 +667,7 @@ void AuctionHouseBot::Initialize() if (AHBSeller) { // Build a list of items that can be pulled from for auction - ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); - for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) - { - // Skip any BOP items - if (itr->second.Bonding == BIND_WHEN_PICKED_UP) - continue; - - // Restrict quality to anything under 7 (artifact and below) or are 0 (poor) - if (itr->second.Quality == 0 || itr->second.Quality > 6) - continue; - - // Disabled items by Id - if (DisableItemStore.find(itr->second.ItemId) != DisableItemStore.end()) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (PTR/Beta/Unused Item)", itr->second.ItemId); - continue; - } - - // Disable conjured items - if (itr->second.IsConjuredConsumable()) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Conjured Consumable)", itr->second.ItemId); - continue; - } - - // Disable money - if (itr->second.Class == ITEM_CLASS_MONEY) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Money)", itr->second.ItemId); - continue; - } - - // Disable moneyloot - if (itr->second.MinMoneyLoot > 0) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (MoneyLoot)", itr->second.ItemId); - continue; - } - - // Disable items with duration - if (itr->second.Duration > 0) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Has a Duration)", itr->second.ItemId); - continue; - } - - // Disable items which are bind quest Items - if (itr->second.Bonding == BIND_QUEST_ITEM) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (BOP or BQI and Required Level is less than Item Level)", itr->second.ItemId); - continue; - } - - // Disable "other" consumables - if (itr->second.Class == ITEM_CLASS_CONSUMABLE && itr->second.SubClass == ITEM_SUBCLASS_CONSUMABLE_OTHER) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled consumber 'other' item", itr->second.ItemId); - continue; - } - - // Disable Junk items - if (itr->second.SubClass == ITEM_SUBCLASS_JUNK) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled 'junk' item", itr->second.ItemId); - continue; - } - - // Disable All Misc (Pets, Mounts, etc) - if (itr->second.Class == ITEM_CLASS_MISC) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); - continue; - } - - // Disable anything with the string literal of a testing or depricated item - if (itr->second.Name1.find("Test ") != std::string::npos || - itr->second.Name1.find("Unused") != std::string::npos || - itr->second.Name1.find("Deprecated") != std::string::npos || - itr->second.Name1.find(" Epic ") != std::string::npos || - itr->second.Name1.find("[PH]") != std::string::npos || - itr->second.Name1.find("[DEP]") != std::string::npos || - itr->second.Name1.find("TEST") != std::string::npos) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled item with a temp or unused item name", itr->second.ItemId); - continue; - } - - // Store the item ID - itemCandidates.push_back(itr->second.ItemId); - } + populateItemCandidateList(); LOG_INFO("module", "AuctionHouseBot:"); LOG_INFO("module", "{} disabled items", uint32(DisableItemStore.size())); diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 38c34d7..7d39b8e 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -732,8 +732,6 @@ private: std::set DisableItemStore; - //End Filters - AHBConfig AllianceConfig; AHBConfig HordeConfig; AHBConfig NeutralConfig; @@ -743,10 +741,12 @@ private: time_t _lastrun_n; inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; - uint32 GetStackSizeForItem(ItemTemplate const* itemProto) const; + uint32 getStackSizeForItem(ItemTemplate const* itemProto) const; + void populateItemCandidateList(); void addNewAuctions(Player *AHBplayer, AHBConfig *config); void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session); + // friend class ACE_Singleton; AuctionHouseBot(); From 6b60a7d6ba63a998864272ca07bf74aafadfa2bc Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 09:30:04 -0600 Subject: [PATCH 3/6] Recalculate Sell Item Price --- src/AuctionHouseBot.cpp | 80 ++++++++++++++++++++++++++--------------- src/AuctionHouseBot.h | 1 + 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 3e2255b..592102b 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -84,6 +84,55 @@ uint32 AuctionHouseBot::getStackSizeForItem(ItemTemplate const* itemProto) const return 1; } +void AuctionHouseBot::calculateSellItemPrice(Player* AHBplayer, Item* item, ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice) +{ + // Start with a buyout price related to the sell price + outBuyoutPrice = itemProto->SellPrice; + + // Multiply the price by the quality + outBuyoutPrice *= itemProto->Quality; + + // Set a minimum base buyoutPrice to 1 silver + if (outBuyoutPrice < 100) + { + // TODO: Move this to a config value + outBuyoutPrice = 100; + } + + // If a vendor sells this item, make the base price the same as the vendor price + // TODO:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + // Add a variance to the buyout price, minimum of 1% + uint64 sellVarianceBuyoutPriceTopPercent = 150; + uint64 sellVarianceBuyoutPriceBottomPercent = 75; + + // Constrain variance top so that it can't be lower than bottom, and minimum values are 1% + if (sellVarianceBuyoutPriceTopPercent == 0) + sellVarianceBuyoutPriceTopPercent = 1; + if (sellVarianceBuyoutPriceBottomPercent == 0) + sellVarianceBuyoutPriceBottomPercent = 1; + if (sellVarianceBuyoutPriceTopPercent < sellVarianceBuyoutPriceBottomPercent) + sellVarianceBuyoutPriceTopPercent = sellVarianceBuyoutPriceBottomPercent; + + // Apply variance to buyout price + outBuyoutPrice = urand(sellVarianceBuyoutPriceBottomPercent * outBuyoutPrice, sellVarianceBuyoutPriceTopPercent * outBuyoutPrice); + outBuyoutPrice /= 100; + + // Calculate a bid price based on a variance against buyout price, minimum of 1% + uint64 sellVarianceBidPriceTopPercent = 100; + uint64 sellVarianceBidPriceBottomPercent = 75; + if (sellVarianceBidPriceTopPercent == 0) + sellVarianceBidPriceTopPercent = 1; + if (sellVarianceBidPriceBottomPercent == 0) + sellVarianceBidPriceBottomPercent = 1; + if (sellVarianceBidPriceTopPercent < sellVarianceBidPriceBottomPercent) + sellVarianceBidPriceTopPercent = sellVarianceBidPriceBottomPercent; + + // Calculate the bid price + outBidPrice = urand(sellVarianceBidPriceBottomPercent * outBuyoutPrice, sellVarianceBidPriceTopPercent * outBuyoutPrice); + outBidPrice /= 100; +} + void AuctionHouseBot::populateItemCandidateList() { // Clear old list @@ -291,37 +340,10 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) if (randomPropertyId != 0) item->SetItemRandomProperties(randomPropertyId); + // Determine price uint64 buyoutPrice = 0; uint64 bidPrice = 0; - - if (SellMethod) - buyoutPrice = prototype->BuyPrice; - else - buyoutPrice = prototype->SellPrice; - - // Set a minimum buyoutPrice to 1 silver - if (buyoutPrice < 100) - { - // TODO: Move this to a config value - buyoutPrice = 100; - } - - // Set the price - if (prototype->Quality <= AHB_MAX_QUALITY) - { - buyoutPrice *= urand(config->GetMinPrice(prototype->Quality), config->GetMaxPrice(prototype->Quality)); - buyoutPrice /= 100; - bidPrice = buyoutPrice * urand(config->GetMinBidPrice(prototype->Quality), config->GetMaxBidPrice(prototype->Quality)); - bidPrice /= 100; - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) - LOG_ERROR("module", "AHBuyer: Quality {} not Supported", prototype->Quality); - item->RemoveFromUpdateQueueOf(AHBplayer); - continue; - } + calculateSellItemPrice(AHBplayer, item, prototype, bidPrice, buyoutPrice); // Define a duration uint32 etime = urand(1,3); diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 7d39b8e..0401369 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -742,6 +742,7 @@ private: inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; uint32 getStackSizeForItem(ItemTemplate const* itemProto) const; + void calculateSellItemPrice(Player* AHBplayer, Item* item, ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice); void populateItemCandidateList(); void addNewAuctions(Player *AHBplayer, AHBConfig *config); void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session); From 176c96f00e7514d97676cc7479bc81af34fe1ed7 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 09:52:16 -0600 Subject: [PATCH 4/6] Small cleanup --- src/AuctionHouseBot.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 592102b..0891278 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -60,7 +60,7 @@ uint32 AuctionHouseBot::getStackSizeForItem(ItemTemplate const* itemProto) const uint32 stackRatio = 0; switch (itemProto->Class) { - case ITEM_CLASS_CONSUMABLE: stackRatio = 5; break; + case ITEM_CLASS_CONSUMABLE: stackRatio = 75; break; case ITEM_CLASS_CONTAINER: stackRatio = 0; break; case ITEM_CLASS_WEAPON: stackRatio = 0; break; case ITEM_CLASS_GEM: stackRatio = 5; break; @@ -89,16 +89,16 @@ void AuctionHouseBot::calculateSellItemPrice(Player* AHBplayer, Item* item, Item // Start with a buyout price related to the sell price outBuyoutPrice = itemProto->SellPrice; - // Multiply the price by the quality - outBuyoutPrice *= itemProto->Quality; - // Set a minimum base buyoutPrice to 1 silver if (outBuyoutPrice < 100) { - // TODO: Move this to a config value + // TODO: Move to a config outBuyoutPrice = 100; } + // Multiply the price by the quality + outBuyoutPrice *= itemProto->Quality; + // If a vendor sells this item, make the base price the same as the vendor price // TODO:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -205,7 +205,8 @@ void AuctionHouseBot::populateItemCandidateList() itr->second.Name1.find(" Epic ") != std::string::npos || itr->second.Name1.find("[PH]") != std::string::npos || itr->second.Name1.find("[DEP]") != std::string::npos || - itr->second.Name1.find("TEST") != std::string::npos) + itr->second.Name1.find("TEST") != std::string::npos || + itr->second.Name1.find("OLD") != std::string::npos) { if (debug_Out_Filters) LOG_ERROR("module", "AuctionHouseBot: Item {} disabled item with a temp or unused item name", itr->second.ItemId); @@ -220,16 +221,16 @@ void AuctionHouseBot::populateItemCandidateList() continue; } - // Disable All Pets - if (itr->second.Class == ITEM_CLASS_MISC && itr->second.SubClass == ITEM_SUBCLASS_JUNK_PET) + // Disable All MISC items (pets, mounts, etc) Use Subclass _JUNK_() for pets and mounts + if (itr->second.Class == ITEM_CLASS_MISC) { if (debug_Out_Filters) LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); continue; } - // Disable All MISC items (pets, mounts, etc) Use Subclass _JUNK_() for pets and mounts - if (itr->second.Class == ITEM_CLASS_MISC) + // Disable all items that have neither a sell or a buy price + if (itr->second.SellPrice == 0 && itr->second.BuyPrice == 0) { if (debug_Out_Filters) LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); From 5b7f44b1d788ac7a0d0075aac6700342b7cabc84 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 10:03:50 -0600 Subject: [PATCH 5/6] Change buy bot to use same value calculation as sell bot --- src/AuctionHouseBot.cpp | 54 +++++++++-------------------------------- src/AuctionHouseBot.h | 2 +- 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 0891278..62be096 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -84,7 +84,7 @@ uint32 AuctionHouseBot::getStackSizeForItem(ItemTemplate const* itemProto) const return 1; } -void AuctionHouseBot::calculateSellItemPrice(Player* AHBplayer, Item* item, ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice) +void AuctionHouseBot::calculateItemValue(ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice) { // Start with a buyout price related to the sell price outBuyoutPrice = itemProto->SellPrice; @@ -344,7 +344,7 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) // Determine price uint64 buyoutPrice = 0; uint64 bidPrice = 0; - calculateSellItemPrice(AHBplayer, item, prototype, bidPrice, buyoutPrice); + calculateItemValue(prototype, bidPrice, buyoutPrice); // Define a duration uint32 etime = urand(1,3); @@ -464,61 +464,32 @@ void AuctionHouseBot::addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *con else currentprice = auction->startbid; - // Prepare portion from maximum bid + // Prepare portion from maximum bid per item double bidrate = static_cast(urand(1, 100)) / 100; - long double bidMax = 0; - - // check that bid has acceptable value and take bid based on vendorprice, stacksize and quality - if (BuyMethod) - { - if (prototype->Quality <= AHB_MAX_QUALITY) - { - if (currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) - bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) - LOG_ERROR("module", "AHBuyer: Quality {} not Supported", prototype->Quality); - continue; - } - } - else - { - if (prototype->Quality <= AHB_MAX_QUALITY) - { - if (currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) - bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) - LOG_ERROR("module", "AHBuyer: Quality {} not Supported", prototype->Quality); - continue; - } - } + uint64 discardBuyoutPrice = 0; + uint64 bidPriceMaxSingle = 0; + calculateItemValue(prototype, bidPriceMaxSingle, discardBuyoutPrice); + uint64 bitPriceMaxCurStack = bidPriceMaxSingle * pItem->GetCount(); // check some special items, and do recalculating to their prices switch (prototype->Class) { - // ammo + // ammo case 6: - bidMax = 0; + bitPriceMaxCurStack = 0; break; default: break; } - if (bidMax == 0) + if (bitPriceMaxCurStack == 0) { // quality check failed to get bidmax, let's get out of here continue; } // Calculate our bid - long double bidvalue = currentprice + ((bidMax - currentprice) * bidrate); + long double bidvalue = currentprice + ((bitPriceMaxCurStack - currentprice) * bidrate); // Convert to uint32 uint32 bidprice = static_cast(bidvalue); @@ -526,7 +497,6 @@ void AuctionHouseBot::addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *con if ((currentprice + auction->GetAuctionOutBid()) > bidprice) bidprice = currentprice + auction->GetAuctionOutBid(); - if (debug_Out) { LOG_INFO("module", "-------------------------------------------------"); @@ -540,7 +510,7 @@ void AuctionHouseBot::addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *con LOG_INFO("module", "AHBuyer: Deposit: {}", auction->deposit); LOG_INFO("module", "AHBuyer: Expire Time: {}", uint32(auction->expire_time)); LOG_INFO("module", "AHBuyer: Bid Rate: {}", bidrate); - LOG_INFO("module", "AHBuyer: Bid Max: {}", bidMax); + LOG_INFO("module", "AHBuyer: Bid Max: {}", bitPriceMaxCurStack); LOG_INFO("module", "AHBuyer: Bid Value: {}", bidvalue); LOG_INFO("module", "AHBuyer: Bid Price: {}", bidprice); LOG_INFO("module", "AHBuyer: Item GUID: {}", auction->item_guid.ToString()); diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 0401369..1fd852d 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -742,7 +742,7 @@ private: inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; uint32 getStackSizeForItem(ItemTemplate const* itemProto) const; - void calculateSellItemPrice(Player* AHBplayer, Item* item, ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice); + void calculateItemValue(ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice); void populateItemCandidateList(); void addNewAuctions(Player *AHBplayer, AHBConfig *config); void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session); From f7abdb74ccd448a1092fa814bad6d60c662dcf71 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 12:23:30 -0600 Subject: [PATCH 6/6] Added item class seed weights --- src/AuctionHouseBot.cpp | 113 ++++++++++++++++++++++++++++++++-------- src/AuctionHouseBot.h | 7 +++ 2 files changed, 99 insertions(+), 21 deletions(-) diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 62be096..abc8765 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -25,10 +25,8 @@ #include "WorldSession.h" #include "GameTime.h" #include "DatabaseEnv.h" -#include using namespace std; -vector itemCandidates; AuctionHouseBot::AuctionHouseBot() { @@ -60,14 +58,14 @@ uint32 AuctionHouseBot::getStackSizeForItem(ItemTemplate const* itemProto) const uint32 stackRatio = 0; switch (itemProto->Class) { - case ITEM_CLASS_CONSUMABLE: stackRatio = 75; break; + case ITEM_CLASS_CONSUMABLE: stackRatio = 50; break; case ITEM_CLASS_CONTAINER: stackRatio = 0; break; case ITEM_CLASS_WEAPON: stackRatio = 0; break; case ITEM_CLASS_GEM: stackRatio = 5; break; case ITEM_CLASS_REAGENT: stackRatio = 50; break; case ITEM_CLASS_ARMOR: stackRatio = 0; break; case ITEM_CLASS_PROJECTILE: stackRatio = 100; break; - case ITEM_CLASS_TRADE_GOODS: stackRatio = 25; break; + case ITEM_CLASS_TRADE_GOODS: stackRatio = 50; break; case ITEM_CLASS_GENERIC: stackRatio = 100; break; case ITEM_CLASS_RECIPE: stackRatio = 0; break; case ITEM_CLASS_QUIVER: stackRatio = 0; break; @@ -133,15 +131,82 @@ void AuctionHouseBot::calculateItemValue(ItemTemplate const* itemProto, uint64& outBidPrice /= 100; } +void AuctionHouseBot::populatetemClassSeedListForItemClass(uint32 itemClass, uint32 itemClassSeedWeight) +{ + for (uint32 i = 0; i < itemClassSeedWeight; ++i) + itemCandidateClassWeightedSeedList.push_back(itemClass); +} + +void AuctionHouseBot::populateItemClassSeedList() +{ + // Determine how many of what kinds of items to use based on a seeded weight list, 0 = none + + // TODO: Move these weight items to a config + uint32 itemClassWeightitemClassWeightConsumable = 6; + uint32 itemClassSeedWeightContainer = 4; + uint32 itemClassSeedWeightWeapon = 8; + uint32 itemClassSeedWeightGem = 3; + uint32 itemClassSeedWeightArmor = 8; + uint32 itemClassSeedWeightReagent = 1; + uint32 itemClassSeedWeightProjectile = 2; + uint32 itemClassSeedWeightTradeGoods = 10; + uint32 itemClassSeedWeightGeneric = 1; + uint32 itemClassSeedWeightRecipe = 6; + uint32 itemClassSeedWeightQuiver = 1; + uint32 itemClassSeedWeightQuest = 1; + uint32 itemClassSeedWeightKey = 1; + uint32 itemClassSeedWeightMisc = 0; + uint32 itemClassSeedWeightGlyph = 3; + + // Clear old list + itemCandidateClassWeightedSeedList.clear(); + + // Fill the list + populatetemClassSeedListForItemClass(ITEM_CLASS_CONSUMABLE, itemClassWeightitemClassWeightConsumable); + populatetemClassSeedListForItemClass(ITEM_CLASS_CONTAINER, itemClassSeedWeightContainer); + populatetemClassSeedListForItemClass(ITEM_CLASS_WEAPON, itemClassSeedWeightWeapon); + populatetemClassSeedListForItemClass(ITEM_CLASS_GEM, itemClassSeedWeightGem); + populatetemClassSeedListForItemClass(ITEM_CLASS_ARMOR, itemClassSeedWeightArmor); + populatetemClassSeedListForItemClass(ITEM_CLASS_REAGENT, itemClassSeedWeightReagent); + populatetemClassSeedListForItemClass(ITEM_CLASS_PROJECTILE, itemClassSeedWeightProjectile); + populatetemClassSeedListForItemClass(ITEM_CLASS_TRADE_GOODS, itemClassSeedWeightTradeGoods); + populatetemClassSeedListForItemClass(ITEM_CLASS_GENERIC, itemClassSeedWeightGeneric); + populatetemClassSeedListForItemClass(ITEM_CLASS_RECIPE, itemClassSeedWeightRecipe); + populatetemClassSeedListForItemClass(ITEM_CLASS_QUIVER, itemClassSeedWeightQuiver); + populatetemClassSeedListForItemClass(ITEM_CLASS_QUEST, itemClassSeedWeightQuest); + populatetemClassSeedListForItemClass(ITEM_CLASS_KEY, itemClassSeedWeightKey); + populatetemClassSeedListForItemClass(ITEM_CLASS_MISC, itemClassSeedWeightMisc); + populatetemClassSeedListForItemClass(ITEM_CLASS_GLYPH, itemClassSeedWeightGlyph); +} + void AuctionHouseBot::populateItemCandidateList() { - // Clear old list - itemCandidates.clear(); + // Clear old list and rebuild it + itemCandidatesByItemClass.clear(); + itemCandidatesByItemClass[ITEM_CLASS_CONSUMABLE] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_CONTAINER] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_WEAPON] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_GEM] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_ARMOR] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_REAGENT] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_PROJECTILE] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_TRADE_GOODS] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_GENERIC] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_RECIPE] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_QUIVER] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_QUEST] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_KEY] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_MISC] = vector(); + itemCandidatesByItemClass[ITEM_CLASS_GLYPH] = vector(); // Fill list ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { + // Skip any items not in the seed list + if (std::find(itemCandidateClassWeightedSeedList.begin(), itemCandidateClassWeightedSeedList.end(), itr->second.Class) == itemCandidateClassWeightedSeedList.end()) + continue; + // Skip any BOP items if (itr->second.Bonding == BIND_WHEN_PICKED_UP) continue; @@ -190,6 +255,14 @@ void AuctionHouseBot::populateItemCandidateList() continue; } + // Disable containers with zero slots + if (itr->second.Class == ITEM_CLASS_CONTAINER && itr->second.ContainerSlots == 0) + { + if (debug_Out_Filters) + LOG_ERROR("module", "AuctionHouseBot: Item {} disabled (Container with no slots)", itr->second.ItemId); + continue; + } + // Disable items which are bind quest Items if (itr->second.Bonding == BIND_QUEST_ITEM) { @@ -203,9 +276,11 @@ void AuctionHouseBot::populateItemCandidateList() itr->second.Name1.find("Unused") != std::string::npos || itr->second.Name1.find("Deprecated") != std::string::npos || itr->second.Name1.find(" Epic ") != std::string::npos || - itr->second.Name1.find("[PH]") != std::string::npos || - itr->second.Name1.find("[DEP]") != std::string::npos || + itr->second.Name1.find("]") != std::string::npos || + itr->second.Name1.find("[") != std::string::npos || itr->second.Name1.find("TEST") != std::string::npos || + itr->second.Name1.find("(") != std::string::npos || + itr->second.Name1.find(")") != std::string::npos || itr->second.Name1.find("OLD") != std::string::npos) { if (debug_Out_Filters) @@ -221,16 +296,8 @@ void AuctionHouseBot::populateItemCandidateList() continue; } - // Disable All MISC items (pets, mounts, etc) Use Subclass _JUNK_() for pets and mounts - if (itr->second.Class == ITEM_CLASS_MISC) - { - if (debug_Out_Filters) - LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); - continue; - } - - // Disable all items that have neither a sell or a buy price - if (itr->second.SellPrice == 0 && itr->second.BuyPrice == 0) + // Disable all items that have neither a sell or a buy price, with exception of item enhancements + if (itr->second.SellPrice == 0 && itr->second.BuyPrice == 0 && itr->second.Class != ITEM_CLASS_CONSUMABLE && itr->second.SubClass != ITEM_SUBCLASS_ITEM_ENHANCEMENT) { if (debug_Out_Filters) LOG_ERROR("module", "AuctionHouseBot: Item {} disabled misc item", itr->second.ItemId); @@ -238,7 +305,7 @@ void AuctionHouseBot::populateItemCandidateList() } // Store the item ID - itemCandidates.push_back(itr->second.ItemId); + itemCandidatesByItemClass[itr->second.Class].push_back(itr->second.ItemId); } } @@ -310,13 +377,16 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) LOG_ERROR("module", "AHSeller: {} count", cnt); // Pull a random item out of the candidate list - uint32 itemID = itemCandidates[urand(0, itemCandidates.size() - 1)]; + uint32 chosenItemClass = itemCandidateClassWeightedSeedList[urand(0, itemCandidateClassWeightedSeedList.size() - 1)]; + uint32 itemID = 0; + if (itemCandidatesByItemClass[chosenItemClass].size() != 0) + itemID = itemCandidatesByItemClass[chosenItemClass][urand(0, itemCandidatesByItemClass[chosenItemClass].size() - 1)]; // Prevent invalid IDs if (itemID == 0) { if (debug_Out) - LOG_ERROR("module", "AHSeller: Item::CreateItem() - ItemID is 0"); + LOG_ERROR("module", "AHSeller: Item::CreateItem() - ItemID is 0", chosenItemClass); continue; } @@ -660,6 +730,7 @@ void AuctionHouseBot::Initialize() if (AHBSeller) { // Build a list of items that can be pulled from for auction + populateItemClassSeedList(); populateItemCandidateList(); LOG_INFO("module", "AuctionHouseBot:"); diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 1fd852d..019ac36 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -23,6 +23,9 @@ #include "Common.h" #include "ObjectGuid.h" +#include +#include + struct AuctionEntry; class Player; class WorldSession; @@ -731,6 +734,8 @@ private: uint32 ItemsPerCycle; std::set DisableItemStore; + std::vector itemCandidateClassWeightedSeedList; + std::map> itemCandidatesByItemClass; AHBConfig AllianceConfig; AHBConfig HordeConfig; @@ -743,6 +748,8 @@ private: inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; uint32 getStackSizeForItem(ItemTemplate const* itemProto) const; void calculateItemValue(ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice); + void populatetemClassSeedListForItemClass(uint32 itemClass, uint32 itemClassSeedWeight); + void populateItemClassSeedList(); void populateItemCandidateList(); void addNewAuctions(Player *AHBplayer, AHBConfig *config); void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session);