diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..5610d2b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,72 @@ +name: Bug report +description: Create a bug report to help us improve. +title: "Bug: " +body: + - type: textarea + id: current + attributes: + label: Current Behaviour + description: | + Description of the problem or issue here. + Include entries of affected creatures / items / quests / spells etc. + If this is a crash, post the crashlog (upload to https://gist.github.com/) and include the link here. + Never upload files! Use GIST for text and YouTube for videos! + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behaviour + description: | + Tell us what should happen instead. + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce the problem + description: | + What does someone else need to do to encounter the same bug? + placeholder: | + 1. Step 1 + 2. Step 2 + 3. Step 3 + validations: + required: true + - type: textarea + id: extra + attributes: + label: Extra Notes + description: | + Do you have any extra notes that can help solve the issue that does not fit any other field? + placeholder: | + None + validations: + required: false + - type: textarea + id: commit + attributes: + label: AC rev. hash/commit + description: | + Copy the result of the `.server debug` command (if you need to run it from the client get a prat addon) + validations: + required: true + - type: input + id: os + attributes: + label: Operating system + description: | + The Operating System the Server is running on. + i.e. Windows 11 x64, Debian 10 x64, macOS 12, Ubuntu 20.04 + validations: + required: true + - type: textarea + id: custom + attributes: + label: Custom changes or Modules + description: | + List which custom changes or modules you have applied, i.e. Eluna module, etc. + placeholder: | + None + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..58f79dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,33 @@ +name: Feature request +description: Suggest an idea for this project +title: "Feature: " +body: + - type: markdown + attributes: + value: | + Thank you for taking your time to fill out a feature request. Remember to fill out all fields including the title above. + An issue that is not properly filled out will be closed. + - type: textarea + id: description + attributes: + label: Describe your feature request or suggestion in detail + description: | + A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + id: solution + attributes: + label: Describe a possible solution to your feature or suggestion in detail + description: | + A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + - type: textarea + id: additional + attributes: + label: Additional context + description: | + Add any other context or screenshots about the feature request here. + validations: + required: false diff --git a/.github/workflows/core-build.yml b/.github/workflows/core-build.yml index f0f3cb0..921c9eb 100644 --- a/.github/workflows/core-build.yml +++ b/.github/workflows/core-build.yml @@ -1,45 +1,12 @@ name: core-build on: push: + branches: + - 'master' pull_request: jobs: build: - strategy: - fail-fast: false - matrix: - compiler: [clang] - runs-on: ubuntu-20.04 - name: ${{ matrix.compiler }} - env: - COMPILER: ${{ matrix.compiler }} - steps: - - uses: actions/checkout@v2 - with: - repository: 'azerothcore/azerothcore-wotlk' - ref: 'master' - submodules: 'recursive' - - uses: actions/checkout@v2 - with: - submodules: 'recursive' - path: 'modules/mod-ah-bot' - - name: Cache - uses: actions/cache@v1.1.2 - with: - path: /home/runner/.ccache - key: ccache:${{ matrix.compiler }}:${{ github.ref }}:${{ github.sha }} - restore-keys: | - ccache:${{ matrix.compiler }}:${{ github.ref }} - ccache:${{ matrix.compiler }} - - name: Configure OS - run: source ./apps/ci/ci-install.sh - env: - CONTINUOUS_INTEGRATION: true - - name: Import db - run: source ./apps/ci/ci-import-db.sh - - name: Build - run: source ./apps/ci/ci-compile.sh - - name: Dry run - run: source ./apps/ci/ci-worldserver-dry-run.sh - - name: Check startup errors - run: source ./apps/ci/ci-error-check.sh \ No newline at end of file + uses: azerothcore/reusable-workflows/.github/workflows/core_build_modules.yml@main + with: + module_repo: ${{ github.event.repository.name }} diff --git a/README.md b/README.md index db90434..810b8e7 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,3 @@ Notes: - Ayase: ported the bot to AzerothCore - Other contributors (check the contributors list) - diff --git a/conf/conf.sh.dist b/conf/conf.sh.dist deleted file mode 100644 index 937a7bc..0000000 --- a/conf/conf.sh.dist +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -# -# CUSTOM -# - -DB_WORLD_CUSTOM_PATHS+=( - $MOD_AH_BOT_ROOT"/sql/world/base/" -) diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-auth/base/.gitkeep b/data/sql/db-auth/base/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-auth/updates/.gitkeep b/data/sql/db-auth/updates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-characters/base/.gitkeep b/data/sql/db-characters/base/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-characters/updates/.gitkeep b/data/sql/db-characters/updates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/sql/db-world/base/.gitkeep b/data/sql/db-world/base/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sql/world/base/mod_auctionhousebot.sql b/data/sql/db-world/base/mod_auctionhousebot.sql similarity index 100% rename from sql/world/base/mod_auctionhousebot.sql rename to data/sql/db-world/base/mod_auctionhousebot.sql diff --git a/data/sql/db-world/updates/.gitkeep b/data/sql/db-world/updates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/include.sh b/include.sh index 038ece6..e69de29 100644 --- a/include.sh +++ b/include.sh @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -MOD_AH_BOT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/" && pwd )" - -source $MOD_AH_BOT_ROOT"/conf/conf.sh.dist" - -if [ -f $MOD_AH_BOT_ROOT"/conf/conf.sh" ]; then - source $MOD_AH_BOT_ROOT"/conf/conf.sh" -fi diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..21c9245 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,25 @@ + + +## Changes Proposed: +- +- + +## Issues Addressed: + +- Closes + +## SOURCE: + + +## Tests Performed: + +- +- + + +## How to Test the Changes: + + +1. +2. +3. diff --git a/src/AuctionHouseBot.cpp b/src/AuctionHouseBot.cpp index 53cebe5..dd80109 100644 --- a/src/AuctionHouseBot.cpp +++ b/src/AuctionHouseBot.cpp @@ -18,6 +18,11 @@ #include "ObjectMgr.h" #include "AuctionHouseMgr.h" #include "AuctionHouseBot.h" +#include "ItemIndex.h" + +#include +#include + #include "Config.h" #include "Player.h" #include "WorldSession.h" @@ -29,25 +34,6 @@ AuctionHouseBot::AuctionHouseBot() { - DisableItemsBelowLevel = 0; - DisableItemsAboveLevel = 0; - DisableTGsBelowLevel = 0; - DisableTGsAboveLevel = 0; - DisableItemsBelowGUID = 0; - DisableItemsAboveGUID = 0; - DisableTGsBelowGUID = 0; - DisableTGsAboveGUID = 0; - DisableItemsBelowReqLevel = 0; - DisableItemsAboveReqLevel = 0; - DisableTGsBelowReqLevel = 0; - DisableTGsAboveReqLevel = 0; - DisableItemsBelowReqSkillRank = 0; - DisableItemsAboveReqSkillRank = 0; - DisableTGsBelowReqSkillRank = 0; - DisableTGsAboveReqSkillRank = 0; - - //End Filters - _lastUpdateAlliance = GameTime::GetGameTime(); _lastUpdateHorde = GameTime::GetGameTime(); _lastUpdateNeutral = GameTime::GetGameTime(); @@ -120,6 +106,8 @@ void AuctionHouseBot::AddNewAuctions(Player* AHBplayer, AHBConfig* config) LOG_DEBUG("module.ahbot", "AHSeller: {} items", items); + auto const itemIndex = sAHIndex; + // only insert a few at a time, so as not to peg the processor for (uint32 cnt = 1; cnt <= items; cnt++) { @@ -135,7 +123,7 @@ void AuctionHouseBot::AddNewAuctions(Player* AHBplayer, AHBConfig* config) uint32 choice = urand(0, 13); itemColor = choice; - auto const& itemsBin = _itemsBin[choice]; + auto const& itemsBin = itemIndex->GetItemBin(choice); if (!itemsBin.empty() && itemsCount[choice] < percents[choice]) itemID = Acore::Containers::SelectRandomContainerElement(itemsBin); @@ -227,7 +215,7 @@ void AuctionHouseBot::AddNewAuctions(Player* AHBplayer, AHBConfig* config) AuctionEntry* auctionEntry = new AuctionEntry(); auctionEntry->Id = sObjectMgr->GenerateAuctionID(); auctionEntry->houseId = config->GetAuctionHouseID(); - auctionEntry->item_guid = item->GetGUID(); + auctionEntry->item_guid = item->GetGUID(); auctionEntry->item_template = item->GetEntry(); auctionEntry->itemCount = item->GetCount(); auctionEntry->owner = AHBplayer->GetGUID(); @@ -267,7 +255,7 @@ void AuctionHouseBot::AddNewAuctionBuyerBotBid(std::shared_ptr player, s WithCallback(std::bind(&AuctionHouseBot::AddNewAuctionBuyerBotBidCallback, this, player, session, sharedConfig, std::placeholders::_1))); } -void AuctionHouseBot::AddNewAuctionBuyerBotBidCallback(std::shared_ptr player, std::shared_ptr session, std::shared_ptr config, QueryResult result) +void AuctionHouseBot::AddNewAuctionBuyerBotBidCallback(std::shared_ptr player, std::shared_ptr /*session*/, std::shared_ptr config, QueryResult result) { if (!result || !result->GetRowCount()) return; @@ -512,19 +500,10 @@ void AuctionHouseBot::Update() void AuctionHouseBot::Initialize() { - DisableItemStore.clear(); - QueryResult result = WorldDatabase.Query("SELECT item FROM mod_auctionhousebot_disabled_items"); - - if (result) - { - do - { - Field* fields = result->Fetch(); - DisableItemStore.emplace(fields[0].Get()); - } while (result->NextRow()); - } + if (AHBSeller) + if (!sAHIndex->InitializeItemsToSell()) + AHBSeller = false; - // End Filters if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) { LoadValues(&AllianceConfig); @@ -547,479 +526,7 @@ void AuctionHouseBot::Initialize() } } - if (AHBSeller) - { - std::string npcQuery = "SELECT distinct item FROM npc_vendor"; - QueryResult results = WorldDatabase.Query(npcQuery); - if (results) - { - do - { - Field* fields = results->Fetch(); - npcItems.push_back(fields[0].Get()); - - } while (results->NextRow()); - } - else - LOG_ERROR("module.ahbot", "AuctionHouseBot: \"{}\" failed", npcQuery); - - std::string lootQuery = "SELECT item FROM creature_loot_template UNION " - "SELECT item FROM reference_loot_template UNION " - "SELECT item FROM disenchant_loot_template UNION " - "SELECT item FROM fishing_loot_template UNION " - "SELECT item FROM gameobject_loot_template UNION " - "SELECT item FROM item_loot_template UNION " - "SELECT item FROM milling_loot_template UNION " - "SELECT item FROM pickpocketing_loot_template UNION " - "SELECT item FROM prospecting_loot_template UNION " - "SELECT item FROM skinning_loot_template"; - - results = WorldDatabase.Query(lootQuery); - if (results) - { - do - { - Field* fields = results->Fetch(); - lootItems.push_back(fields[0].Get()); - - } while (results->NextRow()); - } - else - LOG_ERROR("module.ahbot", "AuctionHouseBot: \"{}\" failed", lootQuery); - - for (auto const& [itemID, itemTemplate] : *sObjectMgr->GetItemTemplateStore()) - { - switch (itemTemplate.Bonding) - { - case NO_BIND: - if (!No_Bind) - continue; - break; - case BIND_WHEN_PICKED_UP: - if (!Bind_When_Picked_Up) - continue; - break; - case BIND_WHEN_EQUIPED: - if (!Bind_When_Equipped) - continue; - break; - case BIND_WHEN_USE: - if (!Bind_When_Use) - continue; - break; - case BIND_QUEST_ITEM: - if (!Bind_Quest_Item) - continue; - break; - default: - continue; - break; - } - - if (SellMethod) - { - if (!itemTemplate.BuyPrice) - continue; - } - else - { - if (!itemTemplate.SellPrice) - continue; - } - - if (itemTemplate.Quality > ITEM_QUALITY_ARTIFACT) - continue; - - if (!Vendor_Items && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isVendorItem = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) - { - if (itemTemplate.ItemId == npcItems[i]) - isVendorItem = true; - } - - if (isVendorItem) - continue; - } - - if (!Vendor_TGs && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isVendorTG = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) - { - if (itemTemplate.ItemId == npcItems[i]) - isVendorTG = true; - } - - if (isVendorTG) - continue; - } - - if (!Loot_Items && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isLootItem = false; - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) - { - if (itemTemplate.ItemId == lootItems[i]) - isLootItem = true; - } - - if (isLootItem) - continue; - } - - if (!Loot_TGs && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isLootTG = false; - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) - { - if (itemTemplate.ItemId == lootItems[i]) - isLootTG = true; - } - - if (isLootTG) - continue; - } - - if (Other_Items && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isVendorItem = false; - bool isLootItem = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) - { - if (itemTemplate.ItemId == npcItems[i]) - isVendorItem = true; - } - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) - { - if (itemTemplate.ItemId == lootItems[i]) - isLootItem = true; - } - - if (!isLootItem && !isVendorItem) - continue; - } - - if (Other_TGs && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) - { - bool isVendorTG = false; - bool isLootTG = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) - { - if (itemTemplate.ItemId == npcItems[i]) - isVendorTG = true; - } - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) - { - if (itemTemplate.ItemId == lootItems[i]) - isLootTG = true; - } - - if (!isLootTG && !isVendorTG) - continue; - } - - // Disable items by Id - if (DisableItemStore.find(itemTemplate.ItemId) != DisableItemStore.end()) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (PTR/Beta/Unused Item)", itemTemplate.ItemId); - continue; - } - - // Disable permanent enchants items - if (DisablePermEnchant && itemTemplate.Class == ITEM_CLASS_PERMANENT) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Permanent Enchant Item)", itemTemplate.ItemId); - continue; - } - - // Disable conjured items - if (DisableConjured && itemTemplate.IsConjuredConsumable()) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Conjured Consumable)", itemTemplate.ItemId); - continue; - } - - // Disable gems - if (DisableGems && itemTemplate.Class == ITEM_CLASS_GEM) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Gem)", itemTemplate.ItemId); - continue; - } - - // Disable money - if (DisableMoney && itemTemplate.Class == ITEM_CLASS_MONEY) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Money)", itemTemplate.ItemId); - continue; - } - - // Disable moneyloot - if (DisableMoneyLoot && itemTemplate.MinMoneyLoot) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (MoneyLoot)", itemTemplate.ItemId); - continue; - } - - // Disable lootable items - if (DisableLootable && itemTemplate.Flags & 4) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Lootable Item)", itemTemplate.ItemId); - continue; - } - - // Disable Keys - if (DisableKeys && itemTemplate.Class == ITEM_CLASS_KEY) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Quest Item)", itemTemplate.ItemId); - continue; - } - - // Disable items with duration - if (DisableDuration && itemTemplate.Duration) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Has a Duration)", itemTemplate.ItemId); - continue; - } - - // Disable items which are BOP or Quest Items and have a required level lower than the item level - if (DisableBOP_Or_Quest_NoReqLevel && ((itemTemplate.Bonding == BIND_WHEN_PICKED_UP || itemTemplate.Bonding == BIND_QUEST_ITEM) && (itemTemplate.RequiredLevel < itemTemplate.ItemLevel))) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (BOP or BQI and Required Level is less than Item Level)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Warrior - if (DisableWarriorItems && itemTemplate.AllowableClass == 1) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Warrior Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Paladin - if (DisablePaladinItems && itemTemplate.AllowableClass == 2) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Paladin Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Hunter - if (DisableHunterItems && itemTemplate.AllowableClass == 4) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Hunter Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Rogue - if (DisableRogueItems && itemTemplate.AllowableClass == 8) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Rogue Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Priest - if (DisablePriestItems && itemTemplate.AllowableClass == 16) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Priest Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for DK - if (DisableDKItems && itemTemplate.AllowableClass == 32) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (DK Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Shaman - if (DisableShamanItems && itemTemplate.AllowableClass == 64) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Shaman Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Mage - if (DisableMageItems && itemTemplate.AllowableClass == 128) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Mage Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Warlock - if (DisableWarlockItems && itemTemplate.AllowableClass == 256) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Warlock Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Unused Class - if (DisableUnusedClassItems && itemTemplate.AllowableClass == 512) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Unused Item)", itemTemplate.ItemId); - continue; - } - - // Disable items specifically for Druid - if (DisableDruidItems && itemTemplate.AllowableClass == 1024) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Druid Item)", itemTemplate.ItemId); - continue; - } - - // Disable Items below level X - if (DisableItemsBelowLevel && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemLevel < DisableItemsBelowLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Items above level X - if (DisableItemsAboveLevel && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemLevel > DisableItemsAboveLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Trade Goods below level X - if (DisableTGsBelowLevel && itemTemplate.Class == ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemLevel < DisableTGsBelowLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Trade Goods above level X - if (DisableTGsAboveLevel && itemTemplate.Class == ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemLevel > DisableTGsAboveLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Items below GUID X - if (DisableItemsBelowGUID && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemId < DisableItemsBelowGUID) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Items above GUID X - if (DisableItemsAboveGUID && itemTemplate.Class != ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemId > DisableItemsAboveGUID) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Trade Goods below GUID X - if (DisableTGsBelowGUID && itemTemplate.Class == ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemId < DisableTGsBelowGUID) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Trade Goods above GUID X - if (DisableTGsAboveGUID && itemTemplate.Class == ITEM_CLASS_TRADE_GOODS && itemTemplate.ItemId > DisableTGsAboveGUID) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); - continue; - } - - // Disable Items for level lower than X - if (DisableItemsBelowReqLevel && itemTemplate.RequiredLevel < DisableItemsBelowReqLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); - continue; - } - - // Disable Items for level higher than X - if (DisableItemsAboveReqLevel && itemTemplate.RequiredLevel > DisableItemsAboveReqLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); - continue; - } - - // Disable Trade Goods for level lower than X - if (DisableTGsBelowReqLevel && itemTemplate.RequiredLevel < DisableTGsBelowReqLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); - continue; - } - - // Disable Trade Goods for level higher than X - if (DisableTGsAboveReqLevel && itemTemplate.RequiredLevel > DisableTGsAboveReqLevel) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); - continue; - } - - // Disable Items that require skill lower than X - if (DisableItemsBelowReqSkillRank && itemTemplate.RequiredSkillRank < DisableItemsBelowReqSkillRank) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); - continue; - } - - // Disable Items that require skill higher than X - if (DisableItemsAboveReqSkillRank && itemTemplate.RequiredSkillRank > DisableItemsAboveReqSkillRank) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); - continue; - } - - // Disable Trade Goods that require skill lower than X - if (DisableTGsBelowReqSkillRank && itemTemplate.RequiredSkillRank < DisableTGsBelowReqSkillRank) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); - continue; - } - - // Disable Trade Goods that require skill higher than X - if (DisableTGsAboveReqSkillRank && itemTemplate.RequiredSkillRank > DisableTGsAboveReqSkillRank) - { - LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); - continue; - } - - uint32 itemQualityIndexStart = itemTemplate.Class == ITEM_CLASS_TRADE_GOODS ? 0 : AHB_DEFAULT_QUALITY_SIZE; - _itemsBin[itemQualityIndexStart + itemTemplate.Quality].emplace_back(itemTemplate.ItemId); - } - - std::size_t totalItems = 0; - for (auto const& itr : _itemsBin) - totalItems += itr.size(); - - if (!totalItems) - { - LOG_ERROR("module.ahbot", "AuctionHouseBot: No items"); - AHBSeller = 0; - } - - LOG_INFO("module.ahbot", "AuctionHouseBot:"); - LOG_INFO("module.ahbot", "{} disabled items", DisableItemStore.size()); - LOG_INFO("module.ahbot", "Loaded {} grey trade goods", _itemsBin[ITEM_QUALITY_POOR].size()); - LOG_INFO("module.ahbot", "Loaded {} white trade goods", _itemsBin[ITEM_QUALITY_NORMAL].size()); - LOG_INFO("module.ahbot", "Loaded {} green trade goods", _itemsBin[ITEM_QUALITY_UNCOMMON].size()); - LOG_INFO("module.ahbot", "Loaded {} blue trade goods", _itemsBin[ITEM_QUALITY_RARE].size()); - LOG_INFO("module.ahbot", "Loaded {} purple trade goods", _itemsBin[ITEM_QUALITY_EPIC].size()); - LOG_INFO("module.ahbot", "Loaded {} orange trade goods", _itemsBin[ITEM_QUALITY_LEGENDARY].size()); - LOG_INFO("module.ahbot", "Loaded {} yellow trade goods", _itemsBin[ITEM_QUALITY_ARTIFACT].size()); - LOG_INFO("module.ahbot", "Loaded {} grey items", _itemsBin[AHB_ITEM_QUALITY_POOR].size()); - LOG_INFO("module.ahbot", "Loaded {} white items", _itemsBin[AHB_ITEM_QUALITY_NORMAL].size()); - LOG_INFO("module.ahbot", "Loaded {} green items", _itemsBin[AHB_ITEM_QUALITY_UNCOMMON].size()); - LOG_INFO("module.ahbot", "Loaded {} blue items", _itemsBin[AHB_ITEM_QUALITY_RARE].size()); - LOG_INFO("module.ahbot", "Loaded {} purple items", _itemsBin[AHB_ITEM_QUALITY_EPIC].size()); - LOG_INFO("module.ahbot", "Loaded {} orange items", _itemsBin[AHB_ITEM_QUALITY_LEGENDARY].size()); - LOG_INFO("module.ahbot", "Loaded {} yellow items", _itemsBin[AHB_ITEM_QUALITY_ARTIFACT].size()); - } - - LOG_INFO("module", "AuctionHouseBot and AuctionHouseBuyer have been loaded."); + LOG_INFO("module", "AuctionHouseBot has been loaded."); } void AuctionHouseBot::InitializeConfiguration() @@ -1032,60 +539,6 @@ void AuctionHouseBot::InitializeConfiguration() AHBplayerAccount = sConfigMgr->GetOption("AuctionHouseBot.Account", 0); AHBplayerGUID = sConfigMgr->GetOption("AuctionHouseBot.GUID", 0); ItemsPerCycle = sConfigMgr->GetOption("AuctionHouseBot.ItemsPerCycle", 200); - - // Begin Filters - - Vendor_Items = sConfigMgr->GetOption("AuctionHouseBot.VendorItems", false); - Loot_Items = sConfigMgr->GetOption("AuctionHouseBot.LootItems", true); - Other_Items = sConfigMgr->GetOption("AuctionHouseBot.OtherItems", false); - Vendor_TGs = sConfigMgr->GetOption("AuctionHouseBot.VendorTradeGoods", false); - Loot_TGs = sConfigMgr->GetOption("AuctionHouseBot.LootTradeGoods", true); - Other_TGs = sConfigMgr->GetOption("AuctionHouseBot.OtherTradeGoods", false); - - No_Bind = sConfigMgr->GetOption("AuctionHouseBot.No_Bind", true); - Bind_When_Picked_Up = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Picked_Up", false); - Bind_When_Equipped = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Equipped", true); - Bind_When_Use = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Use", true); - Bind_Quest_Item = sConfigMgr->GetOption("AuctionHouseBot.Bind_Quest_Item", false); - - DisablePermEnchant = sConfigMgr->GetOption("AuctionHouseBot.DisablePermEnchant", false); - DisableConjured = sConfigMgr->GetOption("AuctionHouseBot.DisableConjured", false); - DisableGems = sConfigMgr->GetOption("AuctionHouseBot.DisableGems", false); - DisableMoney = sConfigMgr->GetOption("AuctionHouseBot.DisableMoney", false); - DisableMoneyLoot = sConfigMgr->GetOption("AuctionHouseBot.DisableMoneyLoot", false); - DisableLootable = sConfigMgr->GetOption("AuctionHouseBot.DisableLootable", false); - DisableKeys = sConfigMgr->GetOption("AuctionHouseBot.DisableKeys", false); - DisableDuration = sConfigMgr->GetOption("AuctionHouseBot.DisableDuration", false); - DisableBOP_Or_Quest_NoReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableBOP_Or_Quest_NoReqLevel", false); - - DisableWarriorItems = sConfigMgr->GetOption("AuctionHouseBot.DisableWarriorItems", false); - DisablePaladinItems = sConfigMgr->GetOption("AuctionHouseBot.DisablePaladinItems", false); - DisableHunterItems = sConfigMgr->GetOption("AuctionHouseBot.DisableHunterItems", false); - DisableRogueItems = sConfigMgr->GetOption("AuctionHouseBot.DisableRogueItems", false); - DisablePriestItems = sConfigMgr->GetOption("AuctionHouseBot.DisablePriestItems", false); - DisableDKItems = sConfigMgr->GetOption("AuctionHouseBot.DisableDKItems", false); - DisableShamanItems = sConfigMgr->GetOption("AuctionHouseBot.DisableShamanItems", false); - DisableMageItems = sConfigMgr->GetOption("AuctionHouseBot.DisableMageItems", false); - DisableWarlockItems = sConfigMgr->GetOption("AuctionHouseBot.DisableWarlockItems", false); - DisableUnusedClassItems = sConfigMgr->GetOption("AuctionHouseBot.DisableUnusedClassItems", false); - DisableDruidItems = sConfigMgr->GetOption("AuctionHouseBot.DisableDruidItems", false); - - DisableItemsBelowLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowLevel", 0); - DisableItemsAboveLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveLevel", 0); - DisableTGsBelowLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowLevel", 0); - DisableTGsAboveLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveLevel", 0); - DisableItemsBelowGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowGUID", 0); - DisableItemsAboveGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveGUID", 0); - DisableTGsBelowGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowGUID", 0); - DisableTGsAboveGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveGUID", 0); - DisableItemsBelowReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowReqLevel", 0); - DisableItemsAboveReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveReqLevel", 0); - DisableTGsBelowReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowReqLevel", 0); - DisableTGsAboveReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveReqLevel", 0); - DisableItemsBelowReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowReqSkillRank", 0); - DisableItemsAboveReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveReqSkillRank", 0); - DisableTGsBelowReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowReqSkillRank", 0); - DisableTGsAboveReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveReqSkillRank", 0); } void AuctionHouseBot::IncrementItemCounts(AuctionEntry* ah) diff --git a/src/AuctionHouseBot.h b/src/AuctionHouseBot.h index aec8c37..19c10dd 100644 --- a/src/AuctionHouseBot.h +++ b/src/AuctionHouseBot.h @@ -1,5 +1,3 @@ -/* - * Copyright (C) 2008-2010 Trinity /* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * @@ -58,58 +56,6 @@ class AuctionHouseBot ObjectGuid::LowType AHBplayerGUID; uint32 ItemsPerCycle; - bool Vendor_Items{ false }; - bool Loot_Items{ false }; - bool Other_Items{ false }; - bool Vendor_TGs{ false }; - bool Loot_TGs{ false }; - bool Other_TGs{ false }; - - bool No_Bind{ false }; - bool Bind_When_Picked_Up{ false }; - bool Bind_When_Equipped{ false }; - bool Bind_When_Use{ false }; - bool Bind_Quest_Item{ false }; - - bool DisablePermEnchant{ false }; - bool DisableConjured{ false }; - bool DisableGems{ false }; - bool DisableMoney{ false }; - bool DisableMoneyLoot{ false }; - bool DisableLootable{ false };; - bool DisableKeys{ false }; - bool DisableDuration{ false }; - bool DisableBOP_Or_Quest_NoReqLevel{ false }; - - bool DisableWarriorItems{ false }; - bool DisablePaladinItems{ false }; - bool DisableHunterItems{ false }; - bool DisableRogueItems{ false }; - bool DisablePriestItems{ false }; - bool DisableDKItems{ false }; - bool DisableShamanItems{ false }; - bool DisableMageItems{ false }; - bool DisableWarlockItems{ false }; - bool DisableUnusedClassItems{ false }; - bool DisableDruidItems{ false }; - - uint32 DisableItemsBelowLevel{ 0 }; - uint32 DisableItemsAboveLevel{ 0 }; - uint32 DisableTGsBelowLevel{ 0 }; - uint32 DisableTGsAboveLevel{ 0 }; - uint32 DisableItemsBelowGUID{ 0 }; - uint32 DisableItemsAboveGUID{ 0 }; - uint32 DisableTGsBelowGUID{ 0 }; - uint32 DisableTGsAboveGUID{ 0 }; - uint32 DisableItemsBelowReqLevel{ 0 }; - uint32 DisableItemsAboveReqLevel{ 0 }; - uint32 DisableTGsBelowReqLevel{ 0 }; - uint32 DisableTGsAboveReqLevel{ 0 }; - uint32 DisableItemsBelowReqSkillRank{ 0 }; - uint32 DisableItemsAboveReqSkillRank{ 0 }; - uint32 DisableTGsBelowReqSkillRank{ 0 }; - uint32 DisableTGsAboveReqSkillRank{ 0 }; - std::unordered_set DisableItemStore{}; AHBConfig AllianceConfig; @@ -120,10 +66,6 @@ class AuctionHouseBot Seconds _lastUpdateHorde{ 0s }; Seconds _lastUpdateNeutral{ 0s }; - std::array, AHB_MAX_QUALITY> _itemsBin{}; - std::vector npcItems{}; - std::vector lootItems{}; - inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; void AddNewAuctions(Player* AHBplayer, AHBConfig* config); void AddNewAuctionBuyerBotBid(std::shared_ptr player, std::shared_ptr session, AHBConfig* config); diff --git a/src/AuctionHouseBotConfig.cpp b/src/AuctionHouseBotConfig.cpp index 2c231c2..8cfcda8 100644 --- a/src/AuctionHouseBotConfig.cpp +++ b/src/AuctionHouseBotConfig.cpp @@ -20,6 +20,8 @@ #include "ItemTemplate.h" #include +#include "Log.h" + AHBConfig::AHBConfig(uint32 ahid) { _auctionHouseID = ahid; @@ -61,25 +63,16 @@ void AHBConfig::SetPercentages(std::array& percentages) } else if (totalPercent != 100) { - _itemsPercent[ITEM_QUALITY_POOR] = 0; - _itemsPercent[ITEM_QUALITY_NORMAL] = 27; - _itemsPercent[ITEM_QUALITY_UNCOMMON] = 12; - _itemsPercent[ITEM_QUALITY_RARE] = 10; - _itemsPercent[ITEM_QUALITY_EPIC] = 1; - _itemsPercent[ITEM_QUALITY_LEGENDARY] = 0; - _itemsPercent[ITEM_QUALITY_ARTIFACT] = 0; - - _itemsPercent[AHB_ITEM_QUALITY_POOR] = 0; - _itemsPercent[AHB_ITEM_QUALITY_NORMAL] = 10; - _itemsPercent[AHB_ITEM_QUALITY_UNCOMMON] = 30; - _itemsPercent[AHB_ITEM_QUALITY_RARE] = 8; - _itemsPercent[AHB_ITEM_QUALITY_EPIC] = 2; - _itemsPercent[AHB_ITEM_QUALITY_LEGENDARY] = 0; - _itemsPercent[AHB_ITEM_QUALITY_ARTIFACT] = 0; + // re-normalize all percentages + const float fixMultiplier = 100.f / static_cast(totalPercent); + + for (auto& it : percentages) + it *= fixMultiplier; + + LOG_WARN("module.ahbot", "AHConfig: Percentages don't add up to 100 (was {}), they have been auto-normalized.", totalPercent); } - for (size_t i = 0; i < percentages.size(); i++) - _itemsPercent[i] = percentages[i]; + std::copy_n(percentages.begin(), AHB_MAX_QUALITY, _itemsPercent.begin()); CalculatePercents(); } diff --git a/src/AuctionHouseBotConfig.h b/src/AuctionHouseBotConfig.h index 49acbba..ea66ece 100644 --- a/src/AuctionHouseBotConfig.h +++ b/src/AuctionHouseBotConfig.h @@ -15,8 +15,12 @@ * with this program. If not, see . */ +#ifndef AUCTION_HOUSE_BOT_CONFIG_H +#define AUCTION_HOUSE_BOT_CONFIG_H + #include "Define.h" #include "Duration.h" +#include "SharedDefines.h" #include enum AHItemQualities @@ -167,3 +171,5 @@ class AHBConfig std::array _maxPrice{}; std::array _itemsCount{}; }; + +#endif // AUCTION_HOUSE_BOT_CONFIG_H diff --git a/src/ItemIndex.cpp b/src/ItemIndex.cpp new file mode 100644 index 0000000..fb0a307 --- /dev/null +++ b/src/ItemIndex.cpp @@ -0,0 +1,576 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ItemIndex.h" + +#include + +#include "Config.h" +#include "WorldSession.h" +#include "DatabaseEnv.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "SmartEnum.h" + +AuctionHouseIndex* AuctionHouseIndex::instance() +{ + static AuctionHouseIndex instance; + return &instance; +} + +struct ItemFilter +{ + bool SellMethod{ false }; + + bool Vendor_Items{ false }; + bool Loot_Items{ false }; + bool Other_Items{ false }; + bool Vendor_TGs{ false }; + bool Loot_TGs{ false }; + bool Other_TGs{ false }; + + bool No_Bind{ false }; + bool Bind_When_Picked_Up{ false }; + bool Bind_When_Equipped{ false }; + bool Bind_When_Use{ false }; + bool Bind_Quest_Item{ false }; + + bool DisablePermEnchant{ false }; + bool DisableConjured{ false }; + bool DisableGems{ false }; + bool DisableMoney{ false }; + bool DisableMoneyLoot{ false }; + bool DisableLootable{ false };; + bool DisableKeys{ false }; + bool DisableDuration{ false }; + bool DisableBOP_Or_Quest_NoReqLevel{ false }; + + std::bitset<32> DisableClassItemsMask; + + uint32 DisableItemsBelowLevel{ 0 }; + uint32 DisableItemsAboveLevel{ 0 }; + uint32 DisableTGsBelowLevel{ 0 }; + uint32 DisableTGsAboveLevel{ 0 }; + uint32 DisableItemsBelowGUID{ 0 }; + uint32 DisableItemsAboveGUID{ 0 }; + uint32 DisableTGsBelowGUID{ 0 }; + uint32 DisableTGsAboveGUID{ 0 }; + uint32 DisableItemsBelowReqLevel{ 0 }; + uint32 DisableItemsAboveReqLevel{ 0 }; + uint32 DisableTGsBelowReqLevel{ 0 }; + uint32 DisableTGsAboveReqLevel{ 0 }; + uint32 DisableItemsBelowReqSkillRank{ 0 }; + uint32 DisableItemsAboveReqSkillRank{ 0 }; + uint32 DisableTGsBelowReqSkillRank{ 0 }; + uint32 DisableTGsAboveReqSkillRank{ 0 }; + + std::unordered_set disabledItems{}; + std::unordered_set npcItems{}; + std::unordered_set lootItems{}; + + ItemFilter() + { + QueryResult results = WorldDatabase.Query("SELECT item FROM mod_auctionhousebot_disabled_items"); + + if (results) + { + do + { + const Field* fields = results->Fetch(); + disabledItems.emplace(fields[0].Get()); + } while (results->NextRow()); + } + + std::string npcQuery = "SELECT distinct item FROM npc_vendor"; + results = WorldDatabase.Query(npcQuery); + if (results) + { + do + { + const Field* fields = results->Fetch(); + npcItems.emplace(fields[0].Get()); + } while (results->NextRow()); + } + else + LOG_ERROR("module.ahbot", "AuctionHouseBot: \"{}\" failed", npcQuery); + + std::string lootQuery = "SELECT item FROM creature_loot_template UNION " + "SELECT item FROM reference_loot_template UNION " + "SELECT item FROM disenchant_loot_template UNION " + "SELECT item FROM fishing_loot_template UNION " + "SELECT item FROM gameobject_loot_template UNION " + "SELECT item FROM item_loot_template UNION " + "SELECT item FROM milling_loot_template UNION " + "SELECT item FROM pickpocketing_loot_template UNION " + "SELECT item FROM prospecting_loot_template UNION " + "SELECT item FROM skinning_loot_template"; + + results = WorldDatabase.Query(lootQuery); + if (results) + { + do + { + const Field* fields = results->Fetch(); + lootItems.emplace(fields[0].Get()); + } while (results->NextRow()); + } + else + LOG_ERROR("module.ahbot", "AuctionHouseBot: \"{}\" failed", lootQuery); + + + + SellMethod = sConfigMgr->GetOption("AuctionHouseBot.UseBuyPriceForSeller", false); + + // Begin Filters + + Vendor_Items = sConfigMgr->GetOption("AuctionHouseBot.VendorItems", false); + Loot_Items = sConfigMgr->GetOption("AuctionHouseBot.LootItems", true); + Other_Items = sConfigMgr->GetOption("AuctionHouseBot.OtherItems", false); + Vendor_TGs = sConfigMgr->GetOption("AuctionHouseBot.VendorTradeGoods", false); + Loot_TGs = sConfigMgr->GetOption("AuctionHouseBot.LootTradeGoods", true); + Other_TGs = sConfigMgr->GetOption("AuctionHouseBot.OtherTradeGoods", false); + + No_Bind = sConfigMgr->GetOption("AuctionHouseBot.No_Bind", true); + Bind_When_Picked_Up = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Picked_Up", false); + Bind_When_Equipped = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Equipped", true); + Bind_When_Use = sConfigMgr->GetOption("AuctionHouseBot.Bind_When_Use", true); + Bind_Quest_Item = sConfigMgr->GetOption("AuctionHouseBot.Bind_Quest_Item", false); + + DisablePermEnchant = sConfigMgr->GetOption("AuctionHouseBot.DisablePermEnchant", false); + DisableConjured = sConfigMgr->GetOption("AuctionHouseBot.DisableConjured", false); + DisableGems = sConfigMgr->GetOption("AuctionHouseBot.DisableGems", false); + DisableMoney = sConfigMgr->GetOption("AuctionHouseBot.DisableMoney", false); + DisableMoneyLoot = sConfigMgr->GetOption("AuctionHouseBot.DisableMoneyLoot", false); + DisableLootable = sConfigMgr->GetOption("AuctionHouseBot.DisableLootable", false); + DisableKeys = sConfigMgr->GetOption("AuctionHouseBot.DisableKeys", false); + DisableDuration = sConfigMgr->GetOption("AuctionHouseBot.DisableDuration", false); + DisableBOP_Or_Quest_NoReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableBOP_Or_Quest_NoReqLevel", false); + + // Classes are 1 based index, to get their flag bit we need zero based, so -1 + DisableClassItemsMask.set(Classes::CLASS_WARRIOR - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableWarriorItems", false)); + DisableClassItemsMask.set(Classes::CLASS_PALADIN - 1, sConfigMgr->GetOption("AuctionHouseBot.DisablePaladinItems", false)); + DisableClassItemsMask.set(Classes::CLASS_HUNTER - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableHunterItems", false)); + DisableClassItemsMask.set(Classes::CLASS_ROGUE - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableRogueItems", false)); + DisableClassItemsMask.set(Classes::CLASS_PRIEST - 1, sConfigMgr->GetOption("AuctionHouseBot.DisablePriestItems", false)); + DisableClassItemsMask.set(Classes::CLASS_DEATH_KNIGHT - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableDKItems", false)); + DisableClassItemsMask.set(Classes::CLASS_SHAMAN - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableShamanItems", false)); + DisableClassItemsMask.set(Classes::CLASS_MAGE - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableMageItems", false)); + DisableClassItemsMask.set(Classes::CLASS_WARLOCK - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableWarlockItems", false)); + DisableClassItemsMask.set(10 - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableUnusedClassItems", false)); + DisableClassItemsMask.set(Classes::CLASS_DRUID - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableDruidItems", false)); + DisableClassItemsMask.set(Classes::CLASS_WARRIOR - 1, sConfigMgr->GetOption("AuctionHouseBot.DisableWarriorItems", false)); + + DisableItemsBelowLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowLevel", 0); + DisableItemsAboveLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveLevel", 0); + DisableTGsBelowLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowLevel", 0); + DisableTGsAboveLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveLevel", 0); + DisableItemsBelowGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowGUID", 0); + DisableItemsAboveGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveGUID", 0); + DisableTGsBelowGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowGUID", 0); + DisableTGsAboveGUID = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveGUID", 0); + DisableItemsBelowReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowReqLevel", 0); + DisableItemsAboveReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveReqLevel", 0); + DisableTGsBelowReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowReqLevel", 0); + DisableTGsAboveReqLevel = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveReqLevel", 0); + DisableItemsBelowReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsBelowReqSkillRank", 0); + DisableItemsAboveReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableItemsAboveReqSkillRank", 0); + DisableTGsBelowReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsBelowReqSkillRank", 0); + DisableTGsAboveReqSkillRank = sConfigMgr->GetOption("AuctionHouseBot.DisableTGsAboveReqSkillRank", 0); + } + + bool IsAccepted(const ItemTemplate& itemTemplate) const + { + switch (itemTemplate.Bonding) + { + case NO_BIND: + if (!No_Bind) + return false; + break; + case BIND_WHEN_PICKED_UP: + if (!Bind_When_Picked_Up) + return false; + break; + case BIND_WHEN_EQUIPED: + if (!Bind_When_Equipped) + return false; + break; + case BIND_WHEN_USE: + if (!Bind_When_Use) + return false; + break; + case BIND_QUEST_ITEM: + if (!Bind_Quest_Item) + return false; + break; + default: + return false; + } + + if (SellMethod) + { + if (!itemTemplate.BuyPrice) + return false; + } + else + { + if (!itemTemplate.SellPrice) + return false; + } + + if (itemTemplate.Quality > ITEM_QUALITY_ARTIFACT) + return false; + + auto isVendorItem = [this](const ItemTemplate& itemTemplate) + { + return npcItems.contains(itemTemplate.ItemId); + }; + + auto isLootItem = [this](const ItemTemplate& itemTemplate) + { + return lootItems.contains(itemTemplate.ItemId); + }; + + if (itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) + { + // Item checks + + if (!Vendor_Items) + { + if (isVendorItem(itemTemplate)) + return false; + } + + if (!Loot_Items) + { + if (isLootItem(itemTemplate)) + return false; + } + + if (!Other_Items) + { + if (!isLootItem(itemTemplate) && !isVendorItem(itemTemplate)) + return false; + } + } + else if (itemTemplate.Class == ITEM_CLASS_TRADE_GOODS) + { + // Tradegood checks + + if (!Vendor_TGs) + { + if (isVendorItem(itemTemplate)) + return false; + } + + if (!Loot_TGs) + { + if (isLootItem(itemTemplate)) + return false; + } + + if (!Other_TGs) + { + if (!isLootItem(itemTemplate) && !isVendorItem(itemTemplate)) + return false; + } + } + + + // Disable items by Id + if (disabledItems.contains(itemTemplate.ItemId)) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (PTR/Beta/Unused Item)", itemTemplate.ItemId); + return false; + } + + // Disable permanent enchants items + if (DisablePermEnchant && itemTemplate.Class == ITEM_CLASS_PERMANENT) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Permanent Enchant Item)", itemTemplate.ItemId); + return false; + } + + // Disable conjured items + if (DisableConjured && itemTemplate.IsConjuredConsumable()) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Conjured Consumable)", itemTemplate.ItemId); + return false; + } + + // Disable gems + if (DisableGems && itemTemplate.Class == ITEM_CLASS_GEM) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Gem)", itemTemplate.ItemId); + return false; + } + + // Disable money + if (DisableMoney && itemTemplate.Class == ITEM_CLASS_MONEY) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Money)", itemTemplate.ItemId); + return false; + } + + // Disable moneyloot + if (DisableMoneyLoot && itemTemplate.MinMoneyLoot) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (MoneyLoot)", itemTemplate.ItemId); + return false; + } + + // Disable lootable items + if (DisableLootable && itemTemplate.Flags & 4) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Lootable Item)", itemTemplate.ItemId); + return false; + } + + // Disable Keys + if (DisableKeys && itemTemplate.Class == ITEM_CLASS_KEY) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Quest Item)", itemTemplate.ItemId); + return false; + } + + // Disable items with duration + if (DisableDuration && itemTemplate.Duration) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Has a Duration)", itemTemplate.ItemId); + return false; + } + + // Disable items which are BOP or Quest Items and have a required level lower than the item level + if (DisableBOP_Or_Quest_NoReqLevel && ((itemTemplate.Bonding == BIND_WHEN_PICKED_UP || itemTemplate.Bonding == BIND_QUEST_ITEM) && (itemTemplate.RequiredLevel < itemTemplate.ItemLevel))) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (BOP or BQI and Required Level is less than Item Level)", itemTemplate.ItemId); + return false; + } + + + // We have disabled some class-specific items, lets see if this is one of them + if (DisableClassItemsMask.any()) + { + const std::bitset<32> allowableClass(itemTemplate.AllowableClass); + + // If this item is specific for just one class (as opposed to multiple classes), then check if its a class that we have disabled + if (allowableClass.count() == 1) + { + if ((DisableClassItemsMask & allowableClass).any()) + { + // slightly ugly, find index of first bit that is set, to find out which class this is + + Classes itemAllowClass = Classes::CLASS_NONE; + for (uint8 classBit = 0; classBit < MAX_CLASSES; ++classBit) + if (allowableClass.test(classBit)) + itemAllowClass = static_cast(classBit + 1); // Zero based index back to 1 based + + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled ({} Item)", itemTemplate.ItemId, Acore::Impl::EnumUtilsImpl::EnumUtils::ToString(itemAllowClass).Title); + return false; + } + } + } + + if (itemTemplate.Class != ITEM_CLASS_TRADE_GOODS) + { + // Item filters + + // Disable Items below level X + if (DisableItemsBelowLevel && itemTemplate.ItemLevel < DisableItemsBelowLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Items above level X + if (DisableItemsAboveLevel && itemTemplate.ItemLevel > DisableItemsAboveLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Items below GUID X + if (DisableItemsBelowGUID && itemTemplate.ItemId < DisableItemsBelowGUID) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Items above GUID X + if (DisableItemsAboveGUID && itemTemplate.ItemId > DisableItemsAboveGUID) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Item Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + } + else + { + // TradeGood filters + + // Disable Trade Goods below level X + if (DisableTGsBelowLevel && itemTemplate.ItemLevel < DisableTGsBelowLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Trade Goods above level X + if (DisableTGsAboveLevel && itemTemplate.ItemLevel > DisableTGsAboveLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Trade Goods below GUID X + if (DisableTGsBelowGUID && itemTemplate.ItemId < DisableTGsBelowGUID) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + + // Disable Trade Goods above GUID X + if (DisableTGsAboveGUID && itemTemplate.ItemId > DisableTGsAboveGUID) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (Trade Good Level = {})", itemTemplate.ItemId, itemTemplate.ItemLevel); + return false; + } + } + + // Disable Items for level lower than X + if (DisableItemsBelowReqLevel && itemTemplate.RequiredLevel < DisableItemsBelowReqLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); + return false; + } + + // Disable Items for level higher than X + if (DisableItemsAboveReqLevel && itemTemplate.RequiredLevel > DisableItemsAboveReqLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); + return false; + } + + // Disable Trade Goods for level lower than X + if (DisableTGsBelowReqLevel && itemTemplate.RequiredLevel < DisableTGsBelowReqLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); + return false; + } + + // Disable Trade Goods for level higher than X + if (DisableTGsAboveReqLevel && itemTemplate.RequiredLevel > DisableTGsAboveReqLevel) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Trade Good {} disabled (RequiredLevel = {})", itemTemplate.ItemId, itemTemplate.RequiredLevel); + return false; + } + + // Disable Items that require skill lower than X + if (DisableItemsBelowReqSkillRank && itemTemplate.RequiredSkillRank < DisableItemsBelowReqSkillRank) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); + return false; + } + + // Disable Items that require skill higher than X + if (DisableItemsAboveReqSkillRank && itemTemplate.RequiredSkillRank > DisableItemsAboveReqSkillRank) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); + return false; + } + + // Disable Trade Goods that require skill lower than X + if (DisableTGsBelowReqSkillRank && itemTemplate.RequiredSkillRank < DisableTGsBelowReqSkillRank) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); + return false; + } + + // Disable Trade Goods that require skill higher than X + if (DisableTGsAboveReqSkillRank && itemTemplate.RequiredSkillRank > DisableTGsAboveReqSkillRank) + { + LOG_DEBUG("module.ahbot.filters", "AuctionHouseBot: Item {} disabled (RequiredSkillRank = {})", itemTemplate.ItemId, itemTemplate.RequiredSkillRank); + return false; + } + + return true; + } +}; + + + +bool AuctionHouseIndex::InitializeItemsToSell() +{ + const ItemFilter filter; + + + for (auto const& [itemID, itemTemplate] : *sObjectMgr->GetItemTemplateStore()) + { + WPAssert(itemTemplate.ItemId, "ItemID cannot be zero"); + + if (!filter.IsAccepted(itemTemplate)) + continue; + + const uint32 itemQualityIndexStart = itemTemplate.Class == ITEM_CLASS_TRADE_GOODS ? 0 : AHB_DEFAULT_QUALITY_SIZE; + _itemsBin[itemQualityIndexStart + itemTemplate.Quality].emplace_back(itemTemplate.ItemId); + } + + std::size_t totalItems = std::accumulate(_itemsBin.begin(), _itemsBin.end(), 0u, [](const std::size_t c, const std::vector& v) {return c + v.size(); }); + + if (!totalItems) + { + LOG_ERROR("module.ahbot", "AuctionHouseBot: No items"); + return false; + } + + LOG_INFO("module.ahbot", "AuctionHouseBot:"); + LOG_INFO("module.ahbot", "{} disabled items", filter.disabledItems.size()); + LOG_INFO("module.ahbot", "Loaded {} grey trade goods", _itemsBin[ITEM_QUALITY_POOR].size()); + LOG_INFO("module.ahbot", "Loaded {} white trade goods", _itemsBin[ITEM_QUALITY_NORMAL].size()); + LOG_INFO("module.ahbot", "Loaded {} green trade goods", _itemsBin[ITEM_QUALITY_UNCOMMON].size()); + LOG_INFO("module.ahbot", "Loaded {} blue trade goods", _itemsBin[ITEM_QUALITY_RARE].size()); + LOG_INFO("module.ahbot", "Loaded {} purple trade goods", _itemsBin[ITEM_QUALITY_EPIC].size()); + LOG_INFO("module.ahbot", "Loaded {} orange trade goods", _itemsBin[ITEM_QUALITY_LEGENDARY].size()); + LOG_INFO("module.ahbot", "Loaded {} yellow trade goods", _itemsBin[ITEM_QUALITY_ARTIFACT].size()); + LOG_INFO("module.ahbot", "Loaded {} grey items", _itemsBin[AHB_ITEM_QUALITY_POOR].size()); + LOG_INFO("module.ahbot", "Loaded {} white items", _itemsBin[AHB_ITEM_QUALITY_NORMAL].size()); + LOG_INFO("module.ahbot", "Loaded {} green items", _itemsBin[AHB_ITEM_QUALITY_UNCOMMON].size()); + LOG_INFO("module.ahbot", "Loaded {} blue items", _itemsBin[AHB_ITEM_QUALITY_RARE].size()); + LOG_INFO("module.ahbot", "Loaded {} purple items", _itemsBin[AHB_ITEM_QUALITY_EPIC].size()); + LOG_INFO("module.ahbot", "Loaded {} orange items", _itemsBin[AHB_ITEM_QUALITY_LEGENDARY].size()); + LOG_INFO("module.ahbot", "Loaded {} yellow items", _itemsBin[AHB_ITEM_QUALITY_ARTIFACT].size()); + + return true; + /* + AuctionHouseBot: + 5957 disabled items + loaded 5 grey trade goods + loaded 471 white trade goods + loaded 58 green trade goods + loaded 26 blue trade goods + loaded 3 purple trade goods + loaded 1 orange trade goods + loaded 0 yellow trade goods + loaded 1633 grey items + loaded 2771 white items + loaded 5520 green items + loaded 1645 blue items + loaded 809 purple items + loaded 0 orange items + loaded 1 yellow items + */ + +} + diff --git a/src/ItemIndex.h b/src/ItemIndex.h new file mode 100644 index 0000000..e61f57b --- /dev/null +++ b/src/ItemIndex.h @@ -0,0 +1,53 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef ITEM_INDEX_H +#define ITEM_INDEX_H + +#include "ObjectGuid.h" +#include "ItemTemplate.h" +#include "AuctionHouseBotConfig.h" +#include "DatabaseEnvFwd.h" +#include +#include + +class AuctionHouseIndex +{ +public: + AuctionHouseIndex() = default; + ~AuctionHouseIndex() = default; + + static AuctionHouseIndex* instance(); + + bool InitializeItemsToSell(); + + const std::vector& GetItemBin(uint32 quality) const + { + return _itemsBin[quality]; + } + +private: + + + std::array, AHB_MAX_QUALITY> _itemsBin{}; + +}; + + +#define sAHIndex AuctionHouseIndex::instance() + +#endif