From f7abdb74ccd448a1092fa814bad6d60c662dcf71 Mon Sep 17 00:00:00 2001 From: NathanHandley Date: Tue, 14 Nov 2023 12:23:30 -0600 Subject: [PATCH] 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);