From a9973cf8cbb7dbb806c29047967471919be779a2 Mon Sep 17 00:00:00 2001 From: zeb <37308742+zeb139@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:54:59 -0400 Subject: [PATCH] Exposed additional config, added .conf.dist readme --- conf/mod_ahbot.conf.dist | 37 +++++++++++--- src/AuctionHouseBot.cpp | 91 +++++++++++++++++++++++++++-------- src/AuctionHouseBot.h | 7 ++- src/AuctionHouseBotScript.cpp | 4 +- 4 files changed, 110 insertions(+), 29 deletions(-) diff --git a/conf/mod_ahbot.conf.dist b/conf/mod_ahbot.conf.dist index cba14ba..79d447a 100644 --- a/conf/mod_ahbot.conf.dist +++ b/conf/mod_ahbot.conf.dist @@ -46,11 +46,6 @@ # acore_characters.item_instance database table to grow over time. # Default: false (disabled) # -# AuctionHouseBot.Seller.UseDBDropRates.Enabled -# Enable/Disable the Seller using items' in-game drop rates from enemies -# and gameobjects to determine probability of listing the items on the AH. -# Default: false (disabled) -# # AuctionHouseBot.GUIDs # These are the character GUIDS (from characters->characters table) that # will be used to create auctions and otherwise interact with auctions. @@ -81,12 +76,42 @@ AuctionHouseBot.MinutesBetweenBuyCycle = 1 AuctionHouseBot.MinutesBetweenSellCycle = 1 AuctionHouseBot.EnableSeller = false AuctionHouseBot.ReturnExpiredAuctionItemsToBot = false -AuctionHouseBot.Seller.UseDBDropRates.Enabled = false AuctionHouseBot.GUIDs = 0 AuctionHouseBot.ItemsPerCycle = 150 AuctionHouseBot.ListingExpireTimeInSecondsMin = 900 AuctionHouseBot.ListingExpireTimeInSecondsMax = 86400 +############################################################################### +# AuctionHouseBot.AdvancedListingRules.UseDropRates.Enabled +# Enable/Disable the Seller using items' in-game drop rates from Enemies +# and GameObjects to determine the probability of listing them on the AH. +# Attempts to simulate "live" AHs by making very powerful items appear less often. +# This setting respects ListProportion config. It can also result in more duplicate +# items appearing on the AH due to higher-drop-rate items being selected more often. +# Crafted items may also appear more often since their drop rate is effectively 100%. +# Default: false (disabled) +# +# AuctionHouseBot.AdvancedListingRules.UseDropRates.MinQuality +# The minimum quality that should be included by AdvancedListingRules.UseDropRates. +# Value should be the integer corresponding to the desired minimum rarity. +# Examples: Setting to 3 will apply to Rare, Epic, Legendary, and Heirloom. +# Setting to 1 will apply to Common, Uncommon, Rare, Epic, Legendary, and Heirloom. +# (0) Poor, (1) Common, (2) Uncommon, (3) Rare, (4) Epic, (5) Legendary, (6) Heirloom +# Default: 3 +# +# AuctionHouseBot.Seller.AdvancedListingRules.UseDropRates. +# Toggle AdvancedListingRules.UseDropRates behavior for individual category. +# Only applied if AdvancedListingRules.UseDropRates.Enabled is true. +# Default: true (enabled) +############################################################################### + +AuctionHouseBot.AdvancedListingRules.UseDropRates.Enabled = false +AuctionHouseBot.AdvancedListingRules.UseDropRates.MinQuality = 2 + +AuctionHouseBot.AdvancedListingRules.UseDropRates.Weapon = true +AuctionHouseBot.AdvancedListingRules.UseDropRates.Armor = true +AuctionHouseBot.AdvancedListingRules.UseDropRates.Recipe = true + ############################################################################### # AuctionHouseBot.MaxBuyoutPriceInCopper # Maximum amount that a buyout on a listing can be in copper. Prevents diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 26f597b..20a3441 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -157,7 +157,10 @@ AuctionHouseBot::AuctionHouseBot() : ListedItemIDRestrictedEnabled(false), ListedItemIDMin(0), ListedItemIDMax(200000), - SellerUseDBDropRates(false), + AdvancedListingRuleUseDropRatesEnabled(false), + AdvancedListingRuleUseDropRatesWeaponEnabled(true), + AdvancedListingRuleUseDropRatesArmorEnabled(true), + AdvancedListingRuleUseDropRatesRecipeEnabled(true), LastBuyCycleCount(0), LastSellCycleCount(0), ActiveListMultipleItemID(0), @@ -1014,7 +1017,7 @@ void AuctionHouseBot::AddNewAuctions(std::vector AHBPlayers, FactionSpe } // If current item is crafted, ineligible, or quest reward, ignore drop rates and continue to list it - if (SellerUseDBDropRates && + if (AdvancedListingRuleUseDropRatesEnabled && IsItemEligibleForDBDropRates(prototype) && !IsItemCrafted(itemID) && !IsItemQuestReward(itemID)) @@ -1117,6 +1120,28 @@ void AuctionHouseBot::AddNewAuctions(std::vector AHBPlayers, FactionSpe LOG_INFO("module", "AHSeller: Added {} items", itemsGenerated); } +std::string AuctionHouseBot::GetAdvancedListingRuleUseDropRatesEnabledCategoriesString() +{ + std::vector enabledCategories; + + if (AdvancedListingRuleUseDropRatesWeaponEnabled) + enabledCategories.push_back(ITEM_CLASS_WEAPON); + if (AdvancedListingRuleUseDropRatesArmorEnabled) + enabledCategories.push_back(ITEM_CLASS_ARMOR); + if (AdvancedListingRuleUseDropRatesRecipeEnabled) + enabledCategories.push_back(ITEM_CLASS_RECIPE); + + std::ostringstream oss; + for (size_t i = 0; i < enabledCategories.size(); ++i) + { + if (i > 0) + oss << ","; + oss << enabledCategories[i]; + } + + return oss.str(); +} + void AuctionHouseBot::PopulateItemDropChances() { // Search creature loot templates, referenced loot_loot_template, group_loot tables, and object_loot tables for items' drop rates @@ -1127,7 +1152,7 @@ void AuctionHouseBot::PopulateItemDropChances() FROM creature_template ct JOIN creature_loot_template clt ON clt.Entry = ct.lootid JOIN item_template it ON it.entry = clt.Item - WHERE clt.Reference = 0 AND clt.GroupId = 0 AND it.class IN (2,4,9) AND it.quality > 2 + WHERE clt.Reference = 0 AND clt.GroupId = 0 AND it.class IN ({}) AND it.quality >= {} )SQL"; std::string referenceDropString = R"SQL( @@ -1164,7 +1189,7 @@ void AuctionHouseBot::PopulateItemDropChances() END AS reference_chance FROM all_references ar JOIN item_template it ON it.entry = ar.itemID - WHERE it.class IN (2,4,9) AND it.quality > 2 + WHERE it.class IN ({}) AND it.quality >= {} )SQL"; // This will lookup items in referenced_loot_template whose Reference entry is not associated with a creature_loot_template @@ -1192,8 +1217,8 @@ void AuctionHouseBot::PopulateItemDropChances() (1.0 / rd.groupCount) * COALESCE(NULLIF(rd.referenceChance, 0), 1) AS reference_chance FROM reference_data rd JOIN item_template it ON it.entry = rd.itemID - WHERE it.class IN (2, 4, 9) - AND it.quality > 2 + WHERE it.class IN ({}) + AND it.quality >= {} )SQL"; std::string groupDropString = R"SQL( @@ -1213,7 +1238,7 @@ void AuctionHouseBot::PopulateItemDropChances() SELECT group_tables.*, COUNT(*) OVER (PARTITION BY loot_entry, group_id) AS item_count FROM group_tables ) compute_item_count - WHERE itemClass IN (2,4,9) AND itemQuality > 2 + WHERE itemClass IN ({}) AND itemQuality >= {} )SQL"; std::string objectsDropString = R"SQL( @@ -1222,24 +1247,33 @@ void AuctionHouseBot::PopulateItemDropChances() 0 AS reference_chance FROM item_loot_template ilt JOIN item_template it ON it.entry = ilt.Item - WHERE it.class IN (2,4,9) AND it.quality > 2 AND chance != 0 + WHERE it.class IN ({}) AND it.quality >= {} AND chance != 0 UNION ALL SELECT it.entry AS itemID, golt.Chance AS direct_chance, 0 AS reference_chance FROM gameobject_loot_template golt JOIN item_template it ON it.entry = golt.Item - WHERE it.class IN (2,4,9) AND it.quality > 2 AND chance != 0 + WHERE it.class IN ({}) AND it.quality >= {} AND chance != 0 )SQL"; - QueryResult directResult = WorldDatabase.Query(directDropString); - QueryResult referenceResult = WorldDatabase.Query(referenceDropString); - QueryResult danglingReferenceResult = WorldDatabase.Query(danglingReferenceDropString); - QueryResult groupResult = WorldDatabase.Query(groupDropString); - QueryResult objectsDropResult = WorldDatabase.Query(objectsDropString); + std::string enabledCategories = GetAdvancedListingRuleUseDropRatesEnabledCategoriesString(); + if (enabledCategories.empty()) + { + LOG_ERROR("module", "AuctionHouseBot: No categories are enabled for AuctionHouseBot.Seller.AdvancedListingRules.UseDropRates"); + return; + } + + QueryResult directResult = WorldDatabase.Query(directDropString, enabledCategories, AdvancedListingRuleUseDropRatesMinQuality); + QueryResult referenceResult = WorldDatabase.Query(referenceDropString, enabledCategories, AdvancedListingRuleUseDropRatesMinQuality); + QueryResult danglingReferenceResult = WorldDatabase.Query(danglingReferenceDropString, enabledCategories, AdvancedListingRuleUseDropRatesMinQuality); + QueryResult groupResult = WorldDatabase.Query(groupDropString, enabledCategories, AdvancedListingRuleUseDropRatesMinQuality); + QueryResult objectsDropResult = WorldDatabase.Query(objectsDropString, + enabledCategories, AdvancedListingRuleUseDropRatesMinQuality, + enabledCategories, AdvancedListingRuleUseDropRatesMinQuality); if (!directResult || !referenceResult || !danglingReferenceResult || !groupResult || !objectsDropResult) { - LOG_ERROR("module", "AuctionHouseBot: PopulateItemDropChances() failed!"); + LOG_ERROR("module", "AuctionHouseBot: PopulateItemDropChances() failed to query items' drop rates."); return; } @@ -1688,7 +1722,11 @@ void AuctionHouseBot::InitializeConfiguration() SetCyclesBetweenBuyOrSell(); ReturnExpiredAuctionItemsToBot = sConfigMgr->GetOption("AuctionHouseBot.ReturnExpiredAuctionItemsToBot", false); ItemsPerCycle = sConfigMgr->GetOption("AuctionHouseBot.ItemsPerCycle", 75); - SellerUseDBDropRates = sConfigMgr->GetOption("AuctionHouseBot.Seller.UseDBDropRates.Enabled", false); + AdvancedListingRuleUseDropRatesEnabled = sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Enabled", false); + AdvancedListingRuleUseDropRatesWeaponEnabled = sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Weapon", true); + AdvancedListingRuleUseDropRatesArmorEnabled = sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Armor", true); + AdvancedListingRuleUseDropRatesRecipeEnabled = sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Recipe", true); + AdvancedListingRuleUseDropRatesMinQuality = sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.MinQuality", 3); MaxBuyoutPriceInCopper = sConfigMgr->GetOption("AuctionHouseBot.MaxBuyoutPriceInCopper", 1000000000); BuyoutVariationReducePercent = sConfigMgr->GetOption("AuctionHouseBot.BuyoutVariationReducePercent", 0.15f); BuyoutVariationAddPercent = sConfigMgr->GetOption("AuctionHouseBot.BuyoutVariationAddPercent", 0.25f); @@ -2311,8 +2349,21 @@ bool AuctionHouseBot::IsItemCrafted(uint32 itemID) bool AuctionHouseBot::IsItemEligibleForDBDropRates(ItemTemplate const* proto) { - return (proto->Quality >= ITEM_QUALITY_RARE && - (proto->Class == ITEM_CLASS_WEAPON || - proto->Class == ITEM_CLASS_ARMOR || - proto->Class == ITEM_CLASS_RECIPE)); + if (!AdvancedListingRuleUseDropRatesEnabled) + return false; + + if (!proto || proto->Quality < AdvancedListingRuleUseDropRatesMinQuality) + return false; + + switch (proto->Class) + { + case ITEM_CLASS_WEAPON: + return AdvancedListingRuleUseDropRatesWeaponEnabled; + case ITEM_CLASS_ARMOR: + return AdvancedListingRuleUseDropRatesArmorEnabled; + case ITEM_CLASS_RECIPE: + return AdvancedListingRuleUseDropRatesRecipeEnabled; + default: + return false; + } } diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index 228a63a..d72ebf9 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -280,7 +280,11 @@ private: bool PreventOverpayingForVendorItems; std::unordered_map CachedItemDropRates; std::vector ItemTiersByClassAndQuality[17][7][11]; // [Classes][Qualities][Tiers] - bool SellerUseDBDropRates; + bool AdvancedListingRuleUseDropRatesEnabled; + bool AdvancedListingRuleUseDropRatesWeaponEnabled; + bool AdvancedListingRuleUseDropRatesArmorEnabled; + bool AdvancedListingRuleUseDropRatesRecipeEnabled; + int AdvancedListingRuleUseDropRatesMinQuality; std::unordered_set QuestRewardItemIDs; FactionSpecificAuctionHouseConfig AllianceConfig; @@ -319,6 +323,7 @@ public: uint32 GetStackSizeForItem(ItemTemplate const* itemProto) const; void CalculateItemValue(ItemTemplate const* itemProto, uint64& outBidPrice, uint64& outBuyoutPrice); void PopulateItemDropChances(); + std::string GetAdvancedListingRuleUseDropRatesEnabledCategoriesString(); void PopulateQuestRewardItemIDs(); bool IsItemQuestReward(uint32 itemID); bool IsItemCrafted(uint32 itemID); diff --git a/src/AuctionHouseBotScript.cpp b/src/AuctionHouseBotScript.cpp index 71dd96e..fcfbb97 100644 --- a/src/AuctionHouseBotScript.cpp +++ b/src/AuctionHouseBotScript.cpp @@ -26,7 +26,7 @@ public: LOG_INFO("server.loading", "AuctionHouseBot: (Re)populating item candidate lists ..."); auctionbot->PopulateItemCandidatesAndProportions(); - if (sConfigMgr->GetOption("AuctionHouseBot.Seller.UseDBDropRates.Enabled", true)) + if (sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Enabled", true)) { auctionbot->PopulateQuestRewardItemIDs(); auctionbot->PopulateItemDropChances(); @@ -38,7 +38,7 @@ public: { LOG_INFO("server.loading", "AuctionHouseBot: (Re)populating item candidate lists ..."); auctionbot->PopulateItemCandidatesAndProportions(); - if (sConfigMgr->GetOption("AuctionHouseBot.Seller.UseDBDropRates.Enabled", true)) + if (sConfigMgr->GetOption("AuctionHouseBot.AdvancedListingRules.UseDropRates.Enabled", true)) { auctionbot->PopulateQuestRewardItemIDs(); auctionbot->PopulateItemDropChances();