diff --git a/conf/mod_ahbot.conf.dist b/conf/mod_ahbot.conf.dist index caf5e93..4a59180 100644 --- a/conf/mod_ahbot.conf.dist +++ b/conf/mod_ahbot.conf.dist @@ -192,10 +192,28 @@ AuctionHouseBot.Buyer.BidAgainstPlayers = false # a proportion of 1 with all others being zero, then when an auction is listed # by a seller bot then 80% will be uncommon consumables and 20% will be normal # containers. This won't increase the total number of auctions. +# +# AuctionHouseBot.ListProportion.ListMultipliedItemIDs +# Comma separated list of items in the format of "itemID:ListMultplier" +# which causes any itemIDs to be listed "ListMultiplier" more times +# when that item is rolled. If the ItemsPerCycle limit is reached +# in a cycle, the remaining listing counts roll over to the next cycle. +# Each listing is subjected to independent stack and price calculations. +# Listings multplied this way do not have any influence over the +# list proportions. For example, if you make an item list 1000 times, +# this won't reduce the list proportion chances for the next item roll +# once all of the multiple listings are complete. ListMultiplier must +# be a whole number (no decimals). The multiple listings can be listed +# in other faction auction houses if ItemsPerCycle is met before the +# multiplier is expended. +# Example: "2589:4,4306:10" would cause linen cloth to be listed 4 times and +# silk cloth to be listed 5 times when randomly selected for being listed +# Default: Many Non-Epic quality unprocessed common trade goods like Linen Cloth +# and Peacebloom are in the config by default to over bias those at 10x rate ############################################################################### AuctionHouseBot.ListProportion.CategoryConsumable.QualityPoor = 0 -AuctionHouseBot.ListProportion.CategoryConsumable.QualityNormal = 3 +AuctionHouseBot.ListProportion.CategoryConsumable.QualityNormal = 8 AuctionHouseBot.ListProportion.CategoryConsumable.QualityUncommon = 2 AuctionHouseBot.ListProportion.CategoryConsumable.QualityRare = 1 AuctionHouseBot.ListProportion.CategoryConsumable.QualityEpic = 0 @@ -205,7 +223,7 @@ AuctionHouseBot.ListProportion.CategoryConsumable.QualityHeirloom = 0 AuctionHouseBot.ListProportion.CategoryContainer.QualityPoor = 1 AuctionHouseBot.ListProportion.CategoryContainer.QualityNormal = 4 -AuctionHouseBot.ListProportion.CategoryContainer.QualityUncommon = 3 +AuctionHouseBot.ListProportion.CategoryContainer.QualityUncommon = 2 AuctionHouseBot.ListProportion.CategoryContainer.QualityRare = 1 AuctionHouseBot.ListProportion.CategoryContainer.QualityEpic = 1 AuctionHouseBot.ListProportion.CategoryContainer.QualityLegendary = 0 @@ -249,20 +267,20 @@ AuctionHouseBot.ListProportion.CategoryReagent.QualityArtifact = 0 AuctionHouseBot.ListProportion.CategoryReagent.QualityHeirloom = 0 AuctionHouseBot.ListProportion.CategoryProjectile.QualityPoor = 0 -AuctionHouseBot.ListProportion.CategoryProjectile.QualityNormal = 5 -AuctionHouseBot.ListProportion.CategoryProjectile.QualityUncommon = 3 -AuctionHouseBot.ListProportion.CategoryProjectile.QualityRare = 2 +AuctionHouseBot.ListProportion.CategoryProjectile.QualityNormal = 2 +AuctionHouseBot.ListProportion.CategoryProjectile.QualityUncommon = 1 +AuctionHouseBot.ListProportion.CategoryProjectile.QualityRare = 1 AuctionHouseBot.ListProportion.CategoryProjectile.QualityEpic = 1 AuctionHouseBot.ListProportion.CategoryProjectile.QualityLegendary = 0 AuctionHouseBot.ListProportion.CategoryProjectile.QualityArtifact = 0 AuctionHouseBot.ListProportion.CategoryProjectile.QualityHeirloom = 0 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityPoor = 1 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityNormal = 40 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityUncommon = 12 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityRare = 8 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityEpic = 5 -AuctionHouseBot.ListProportion.CategoryTradeGood.QualityLegendary = 1 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityPoor = 0 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityNormal = 20 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityUncommon = 7 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityRare = 2 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityEpic = 1 +AuctionHouseBot.ListProportion.CategoryTradeGood.QualityLegendary = 0 AuctionHouseBot.ListProportion.CategoryTradeGood.QualityArtifact = 0 AuctionHouseBot.ListProportion.CategoryTradeGood.QualityHeirloom = 0 @@ -321,7 +339,7 @@ AuctionHouseBot.ListProportion.CategoryMisc.QualityArtifact = 0 AuctionHouseBot.ListProportion.CategoryMisc.QualityHeirloom = 0 AuctionHouseBot.ListProportion.CategoryGlyph.QualityPoor = 0 -AuctionHouseBot.ListProportion.CategoryGlyph.QualityNormal = 2 +AuctionHouseBot.ListProportion.CategoryGlyph.QualityNormal = 3 AuctionHouseBot.ListProportion.CategoryGlyph.QualityUncommon = 0 AuctionHouseBot.ListProportion.CategoryGlyph.QualityRare = 0 AuctionHouseBot.ListProportion.CategoryGlyph.QualityEpic = 0 @@ -329,6 +347,10 @@ AuctionHouseBot.ListProportion.CategoryGlyph.QualityLegendary = 0 AuctionHouseBot.ListProportion.CategoryGlyph.QualityArtifact = 0 AuctionHouseBot.ListProportion.CategoryGlyph.QualityHeirloom = 0 +# Default IDs here are listed in order of Cloth, Leather, Ore, Stone, Herbs, Enchanting, Uncut Gems +# Note: it was not required to be in this order, just stating that so you can find blocks to remove/edit +AuctionHouseBot.ListProportion.ListMultipliedItemIDs = 2589:10,2592:10,4306:10,4338:10,14047:10,21877:10,33470:10,2318:10,2319:10,4234:10,4304:10,8170:10,21887:10,33568:10,2770:10,2771:10,2772:10,2775:10,2776:10,3858:10,7911:10,10620:10,23424:10,23425:10,23426:10,23427:10,36909:10,36912:10,36910:10,2835:10,2836:10,2838:10,12365:10,7912:10,765:10,785:10,2447:10,2449:10,2450:10,2452:10,2453:10,3355:10,3356:10,3357:10,3358:10,3369:10,3818:10,3819:10,3820:10,3821:10,4625:10,8153:10,8831:10,8836:10,8838:10,8839:10,8845:10,8846:10,13463:10,13464:10,13465:10,13466:10,13467:10,13468:10,22785:10,22786:10,22787:10,22789:10,22790:10,22791:10,22792:10,22793:10,22794:10,22795:10,36901:10,36902:10,36903:10,36904:10,36905:10,36906:10,36907:10,36908:10,37921:10,10938:10,10939:10,10940:10,10978:10,10998:10,11082:10,11084:10,11128:10,11134:10,11135:10,11138:10,11139:10,11174:10,11175:10,11177:10,11178:10,14343:10,16202:10,16203:10,16204:10,22445:10,22446:10,22447:10,22448:10,22449:10,34052:10,34053:10,34054:10,34055:10,34056:10,774:10,818:10,1206:10,1210:10,1529:10,1705:10,3864:10,7909:10,7910:10,12361:10,12364:10,12799:10,12800:10,21929:10,23077:10,23079:10,23107:10,23112:10,23117:10,23436:10,23437:10,23438:10,23439:10,23440:10,23441:10,36917:10,36918:10,36919:10,36920:10,36921:10,36922:10,36923:10,36924:10,36925:10,36926:10,36927:10,36928:10,36929:10,36930:10,36931:10,36932:10,36933:10,36934:10 + ############################################################################### # AuctionHouseBot.PriceMinimumCenterBase.* # Category-level price minimums, in copper, before any multipliers come diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index bb05d19..90e4120 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -147,7 +147,9 @@ AuctionHouseBot::AuctionHouseBot() : ListedItemIDRestrictedEnabled(false), ListedItemIDMin(0), ListedItemIDMax(200000), - LastCycleCount(0) + LastCycleCount(0), + ActiveListMultipleItemID(0), + RemainingListMultipleCount(0) { AllianceConfig = FactionSpecificAuctionHouseConfig(2); HordeConfig = FactionSpecificAuctionHouseConfig(6); @@ -879,7 +881,27 @@ void AuctionHouseBot::AddNewAuctions(Player* AHBplayer, FactionSpecificAuctionHo uint32 itemsGenerated = 0; for (uint32 cnt = 1; cnt <= newItemsToListCount; cnt++) { - uint32 itemID = GetRandomItemIDForListing(); + // Either generate a new item ID to list, or grab from the remaining list + uint32 itemID; + if (ActiveListMultipleItemID != 0) + { + itemID = ActiveListMultipleItemID; + RemainingListMultipleCount--; + if (RemainingListMultipleCount <= 0) + ActiveListMultipleItemID = 0; + } + else + { + itemID = GetRandomItemIDForListing(); + if (itemID != 0 && ItemListProportionMultipliedItemIDs.find(itemID) != ItemListProportionMultipliedItemIDs.end() && + ItemListProportionMultipliedItemIDs[itemID] > 1) + { + ActiveListMultipleItemID = itemID; + RemainingListMultipleCount = ItemListProportionMultipliedItemIDs[itemID] - 1; + if (debug_Out) + LOG_INFO("module", "AHSeller: Is listing item ID {} which is configured for {} multiples from ListMultipliedItemIDs", itemID, ItemListProportionMultipliedItemIDs[itemID]); + } + } // Prevent invalid IDs if (itemID == 0) @@ -1274,6 +1296,26 @@ void AuctionHouseBot::InitializeConfiguration() RandomStackIncrementMisc = GetRandomStackIncrementValue("AuctionHouseBot.ListingStack.RandomStackIncrement.Misc", 1); RandomStackIncrementGlyph = GetRandomStackIncrementValue("AuctionHouseBot.ListingStack.RandomStackIncrement.Glyph", 1); + // List proportions + ItemListProportionNodesSeed.clear(); + for (int category = 0; category < MAX_ITEM_CLASS; category++) + { + for (int quality = 0; quality < MAX_ITEM_QUALITY; quality++) + { + if (category != ITEM_CLASS_MONEY && category != ITEM_CLASS_PERMANENT) + { + std::string key = std::string("AuctionHouseBot.ListProportion.Category") + GetCategoryName((ItemClass)category) + ".Quality" + GetQualityName((ItemQualities)quality); + ListProportionNode node; + node.ItemClassID = category; + node.ItemQualityID = quality; + node.Proportion = sConfigMgr->GetOption(key.c_str(), 0); + ItemListProportionNodesSeed.push_back(node); + } + } + } + ItemListProportionMultipliedItemIDs.clear(); + AddItemValuePairsToItemIDMap(ItemListProportionMultipliedItemIDs, sConfigMgr->GetOption("AuctionHouseBot.ListProportion.ListMultipliedItemIDs", "")); + // Price Multipliers PriceMultiplierCategoryConsumable = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.Category.Consumable", 1); PriceMultiplierCategoryContainer = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.Category.Container", 1); @@ -1313,28 +1355,15 @@ void AuctionHouseBot::InitializeConfiguration() PriceMultiplierQualityLegendary = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.Quality.Legendary", 3); PriceMultiplierQualityArtifact = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.Quality.Artifact", 3); PriceMultiplierQualityHeirloom = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.Quality.Heirloom", 3); - ItemListProportionNodesSeed.clear(); for (int category = 0; category < MAX_ITEM_CLASS; category++) { for (int quality = 0; quality < MAX_ITEM_QUALITY; quality++) { - // Price Multipliers std::string key = std::string("AuctionHouseBot.PriceMultiplier.Category") + GetCategoryName((ItemClass)category) + ".Quality" + GetQualityName((ItemQualities)quality); float multiplier = sConfigMgr->GetOption(key.c_str(), 1.0f); PriceMultiplierCategoryQuality[category][quality] = multiplier; - - // List Proportions - if (category != ITEM_CLASS_MONEY && category != ITEM_CLASS_PERMANENT) - { - key = std::string("AuctionHouseBot.ListProportion.Category") + GetCategoryName((ItemClass)category) + ".Quality" + GetQualityName((ItemQualities)quality); - ListProportionNode node; - node.ItemClassID = category; - node.ItemQualityID = quality; - node.Proportion = sConfigMgr->GetOption(key.c_str(), 0); - ItemListProportionNodesSeed.push_back(node); - } } } PriceMultiplierCategoryMountQualityPoor = sConfigMgr->GetOption("AuctionHouseBot.PriceMultiplier.CategoryMount.QualityPoor", 1.0); @@ -1377,7 +1406,7 @@ void AuctionHouseBot::InitializeConfiguration() PriceMinimumCenterBaseKey = sConfigMgr->GetOption("AuctionHouseBot.PriceMinimumCenterBase.Key", 1000); PriceMinimumCenterBaseMisc = sConfigMgr->GetOption("AuctionHouseBot.PriceMinimumCenterBase.Misc", 1000); PriceMinimumCenterBaseGlyph = sConfigMgr->GetOption("AuctionHouseBot.PriceMinimumCenterBase.Glyph", 1000); - AddPriceMinimumOverrides(sConfigMgr->GetOption("AuctionHouseBot.PriceMinimumCenterBase.OverrideItems", "")); + AddItemValuePairsToItemIDMap(PriceMinimumCenterBaseOverridesByItemID, sConfigMgr->GetOption("AuctionHouseBot.PriceMinimumCenterBase.OverrideItems", "")); // Item level Restrictions ListedItemLevelRestrictedEnabled = sConfigMgr->GetOption("AuctionHouseBot.ListedItemLevelRestrict.Enabled", false); @@ -1494,12 +1523,13 @@ void AuctionHouseBot::AddCharacters(std::string characterGUIDString) } while (queryResult->NextRow()); } -void AuctionHouseBot::AddPriceMinimumOverrides(std::string priceMinimimOverridesString) +template +void AuctionHouseBot::AddItemValuePairsToItemIDMap(std::unordered_map& workingValueToItemIDMap, std::string valueToItemIDMapString) { std::string delimitedValue; - std::stringstream priceMinimumStream; - priceMinimumStream.str(priceMinimimOverridesString); - while (std::getline(priceMinimumStream, delimitedValue, ',')) // Process each item ID in the string, delimited by the comma "," + std::stringstream valueToItemIDStream; + valueToItemIDStream.str(valueToItemIDMapString); + while (std::getline(valueToItemIDStream, delimitedValue, ',')) // Process each item ID in the string, delimited by the comma "," { std::string curBlock; std::stringstream itemPairStream(delimitedValue); @@ -1510,10 +1540,10 @@ void AuctionHouseBot::AddPriceMinimumOverrides(std::string priceMinimimOverrides { std::string itemIDString = curBlock.substr(0, curBlock.find(":")); auto itemId = atoi(itemIDString.c_str()); - std::string priceInCopper = curBlock.substr(curBlock.find(":") + 1); - auto copperPrice = atoi(priceInCopper.c_str()); - if (itemId > 0 && copperPrice > 0) - PriceMinimumCenterBaseOverridesByItemID.insert({itemId, copperPrice}); + std::string valueString = curBlock.substr(curBlock.find(":") + 1); + auto convertedValue = atoi(valueString.c_str()); + if (itemId > 0 && convertedValue > 0) + workingValueToItemIDMap.insert({ itemId, convertedValue }); } } } diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index f0e4eab..d187414 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -183,6 +183,7 @@ private: uint32 RandomStackIncrementGlyph; std::vector ItemListProportionNodesSeed; std::vector ItemListProportionNodesLookup; + std::unordered_map ItemListProportionMultipliedItemIDs; std::map>> ItemCandidatesByItemClassAndQuality; float PriceMultiplierCategoryConsumable; float PriceMultiplierCategoryContainer; @@ -270,7 +271,9 @@ private: FactionSpecificAuctionHouseConfig HordeConfig; FactionSpecificAuctionHouseConfig NeutralConfig; - int LastCycleCount; + int LastCycleCount; + int ActiveListMultipleItemID; + int RemainingListMultipleCount; AuctionHouseBot(); @@ -288,7 +291,6 @@ public: uint32 GetRandomStackValue(std::string configKeyString, uint32 defaultValue); uint32 GetRandomStackIncrementValue(std::string configKeyString, uint32 defaultValue); void AddCharacters(std::string characterGUIDString); - void AddPriceMinimumOverrides(std::string priceMinimimOverridesString); void AddItemIDsFromString(std::set& workingItemIDSet, std::string itemString, const char* parentOperationName); void AddToItemIDSet(std::set& workingItemIDSet, uint32 itemID, const char* parentOperationName); const char* GetQualityName(ItemQualities quality); @@ -302,6 +304,9 @@ public: void AddNewAuctions(Player* AHBplayer, FactionSpecificAuctionHouseConfig* config); void AddNewAuctionBuyerBotBid(Player* AHBplayer, FactionSpecificAuctionHouseConfig* config); void PopulateVendorItemsPrices(); + + template + void AddItemValuePairsToItemIDMap(std::unordered_map& workingValueToItemIDMap, std::string valueToItemIDMap); }; #define auctionbot AuctionHouseBot::instance()