TrinityCore
AuctionHouseBotSeller.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
19#include "AuctionHouseMgr.h"
20#include "DatabaseEnv.h"
21#include "DB2Stores.h"
22#include "GameTime.h"
23#include "Item.h"
24#include "Log.h"
25#include "Containers.h"
26#include "ObjectMgr.h"
27#include "Random.h"
28#include <sstream>
29
31{
32 // Define faction for our main data class.
33 for (uint8 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
35}
36
38{
39}
40
42{
43 std::unordered_set<uint32> npcItems;
44 std::unordered_set<uint32> lootItems;
45 std::unordered_set<uint32> includeItems;
46 std::unordered_set<uint32> excludeItems;
47
48 TC_LOG_DEBUG("ahbot", "AHBot seller filters:");
49
50 {
51 std::stringstream includeStream(sAuctionBotConfig->GetAHBotIncludes());
52 std::string temp;
53 while (std::getline(includeStream, temp, ','))
54 includeItems.insert(atoi(temp.c_str()));
55 }
56
57 {
58 std::stringstream excludeStream(sAuctionBotConfig->GetAHBotExcludes());
59 std::string temp;
60 while (std::getline(excludeStream, temp, ','))
61 excludeItems.insert(atol(temp.c_str()));
62 }
63
64 TC_LOG_DEBUG("ahbot", "Forced Inclusion {} items", includeItems.size());
65 TC_LOG_DEBUG("ahbot", "Forced Exclusion {} items", excludeItems.size());
66
67 TC_LOG_DEBUG("ahbot", "Loading npc vendor items for filter..");
68 CreatureTemplateContainer const& creatures = sObjectMgr->GetCreatureTemplates();
69 for (auto const& creatureTemplatePair : creatures)
70 if (VendorItemData const* data = sObjectMgr->GetNpcVendorItemList(creatureTemplatePair.first))
71 for (VendorItem const& vendorItem : data->m_items)
72 npcItems.insert(vendorItem.item);
73
74 TC_LOG_DEBUG("ahbot", "Npc vendor filter has {} items", npcItems.size());
75
76 TC_LOG_DEBUG("ahbot", "Loading loot items for filter..");
77 QueryResult result = WorldDatabase.PQuery(
78 "SELECT `item` FROM `creature_loot_template` WHERE `Reference` = 0 UNION "
79 "SELECT `item` FROM `disenchant_loot_template` WHERE `Reference` = 0 UNION "
80 "SELECT `item` FROM `fishing_loot_template` WHERE `Reference` = 0 UNION "
81 "SELECT `item` FROM `gameobject_loot_template` WHERE `Reference` = 0 UNION "
82 "SELECT `item` FROM `item_loot_template` WHERE `Reference` = 0 UNION "
83 "SELECT `item` FROM `milling_loot_template` WHERE `Reference` = 0 UNION "
84 "SELECT `item` FROM `pickpocketing_loot_template` WHERE `Reference` = 0 UNION "
85 "SELECT `item` FROM `prospecting_loot_template` WHERE `Reference` = 0 UNION "
86 "SELECT `item` FROM `reference_loot_template` WHERE `Reference` = 0 UNION "
87 "SELECT `item` FROM `skinning_loot_template` WHERE `Reference` = 0 UNION "
88 "SELECT `item` FROM `spell_loot_template` WHERE `Reference` = 0");
89
90 if (result)
91 {
92 do
93 {
94 Field* fields = result->Fetch();
95
96 uint32 entry = fields[0].GetUInt32();
97 if (!entry)
98 continue;
99
100 lootItems.insert(entry);
101 } while (result->NextRow());
102 }
103
104 TC_LOG_DEBUG("ahbot", "Loot filter has {} items", lootItems.size());
105 TC_LOG_DEBUG("ahbot", "Sorting and cleaning items for AHBot seller...");
106
107 uint32 itemsAdded = 0;
108
109 for (uint32 itemId = 0; itemId < sItemStore.GetNumRows(); ++itemId)
110 {
111 ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemId);
112 if (!prototype)
113 continue;
114
115 // skip items with too high quality (code can't properly work with its)
116 if (prototype->GetQuality() >= MAX_AUCTION_QUALITY)
117 continue;
118
119 // forced exclude filter
120 if (excludeItems.count(itemId))
121 continue;
122
123 // forced include filter
124 if (includeItems.count(itemId))
125 {
126 _itemPool[prototype->GetQuality()][prototype->GetClass()].push_back(itemId);
127 ++itemsAdded;
128 continue;
129 }
130
131 // bounding filters
132 switch (prototype->GetBonding())
133 {
134 case BIND_NONE:
136 continue;
137 break;
138 case BIND_ON_ACQUIRE:
140 continue;
141 break;
142 case BIND_ON_EQUIP:
144 continue;
145 break;
146 case BIND_ON_USE:
148 continue;
149 break;
150 case BIND_QUEST:
152 continue;
153 break;
154 default:
155 continue;
156 }
157
158 bool allowZero = false;
159 switch (prototype->GetClass())
160 {
162 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO); break;
164 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_ALLOW_ZERO); break;
166 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_WEAPON_ALLOW_ZERO); break;
167 case ITEM_CLASS_GEM:
168 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GEM_ALLOW_ZERO); break;
169 case ITEM_CLASS_ARMOR:
170 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_ARMOR_ALLOW_ZERO); break;
172 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_REAGENT_ALLOW_ZERO); break;
174 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_PROJECTILE_ALLOW_ZERO); break;
176 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_ALLOW_ZERO); break;
178 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_RECIPE_ALLOW_ZERO); break;
180 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUIVER_ALLOW_ZERO); break;
181 case ITEM_CLASS_QUEST:
182 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_QUEST_ALLOW_ZERO); break;
183 case ITEM_CLASS_KEY:
184 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_KEY_ALLOW_ZERO); break;
186 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_ALLOW_ZERO); break;
187 case ITEM_CLASS_GLYPH:
188 allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_ALLOW_ZERO); break;
189 default:
190 allowZero = false;
191 }
192
193 // Filter out items with no buy/sell price unless otherwise flagged in the config.
194 if (!allowZero)
195 {
197 {
198 if (prototype->GetSellPrice() == 0)
199 continue;
200 }
201 else
202 {
203 if (prototype->GetBuyPrice() == 0)
204 continue;
205 }
206 }
207
208 // vendor filter
210 if (npcItems.count(itemId))
211 continue;
212
213 // loot filter
215 if (lootItems.count(itemId))
216 continue;
217
218 // not vendor/loot filter
220 {
221 bool const isVendorItem = npcItems.count(itemId) > 0;
222 bool const isLootItem = lootItems.count(itemId) > 0;
223
224 if (!isLootItem && !isVendorItem)
225 continue;
226 }
227
228 // item class/subclass specific filters
229 switch (prototype->GetClass())
230 {
231 case ITEM_CLASS_ARMOR:
233 {
235 if (prototype->GetBaseItemLevel() < value)
236 continue;
238 if (prototype->GetBaseItemLevel() > value)
239 continue;
241 if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
242 continue;
244 if (prototype->GetBaseRequiredLevel() > static_cast<int32>(value))
245 continue;
247 if (prototype->GetRequiredSkillRank() < value)
248 continue;
250 if (prototype->GetRequiredSkillRank() > value)
251 continue;
252 break;
253 }
257 {
259 if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
260 continue;
262 if (prototype->GetBaseRequiredLevel() > static_cast<int32>(value))
263 continue;
265 if (prototype->GetRequiredSkillRank() < value)
266 continue;
268 if (prototype->GetRequiredSkillRank() > value)
269 continue;
270 break;
271 }
274 {
276 if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
277 continue;
279 if (prototype->GetBaseRequiredLevel() > static_cast<int32>(value))
280 continue;
282 if (prototype->GetRequiredSkillRank() < value)
283 continue;
285 if (prototype->GetRequiredSkillRank() > value)
286 continue;
287 }
288
289 if (prototype->HasFlag(ITEM_FLAG_HAS_LOOT))
290 {
291 // skip any not locked lootable items (mostly quest specific or reward cases)
292 if (!prototype->GetLockID())
293 continue;
294
296 continue;
297 }
298
299 break;
300 case ITEM_CLASS_GLYPH:
301 {
303 if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
304 continue;
306 if (prototype->GetBaseRequiredLevel() > static_cast<int32>(value))
307 continue;
309 if (prototype->GetBaseRequiredLevel() < static_cast<int32>(value))
310 continue;
312 if (prototype->GetBaseRequiredLevel() > static_cast<int32>(value))
313 continue;
314 break;
315 }
317 {
319 if (prototype->GetBaseItemLevel() < value)
320 continue;
322 if (prototype->GetBaseItemLevel() > value)
323 continue;
324 break;
325 }
328 {
330 if (prototype->GetBaseItemLevel() < value)
331 continue;
333 if (prototype->GetBaseItemLevel() > value)
334 continue;
335 break;
336 }
337 }
338
339 _itemPool[prototype->GetQuality()][prototype->GetClass()].push_back(itemId);
340 ++itemsAdded;
341 }
342
343 if (!itemsAdded)
344 {
345 TC_LOG_ERROR("ahbot", "AuctionHouseBot seller not have items, disabled.");
349 return false;
350 }
351
352 TC_LOG_DEBUG("ahbot", "AuctionHouseBot seller will use {} items to fill auction house (according your config choices)", itemsAdded);
353
354 LoadConfig();
355
356 if (sLog->ShouldLog("ahbot", LOG_LEVEL_DEBUG))
357 {
358 sLog->OutMessage("ahbot", LOG_LEVEL_DEBUG, "Items loaded \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
359 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
360 sLog->OutMessage("ahbot", LOG_LEVEL_DEBUG, "\t\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
361 (uint32)_itemPool[0][i].size(), (uint32)_itemPool[1][i].size(), (uint32)_itemPool[2][i].size(),
362 (uint32)_itemPool[3][i].size(), (uint32)_itemPool[4][i].size(), (uint32)_itemPool[5][i].size(),
363 (uint32)_itemPool[6][i].size());
364 }
365
366 TC_LOG_DEBUG("ahbot", "AHBot seller configuration data loaded and initialized");
367 return true;
368}
369
371{
372 for (uint8 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
373 if (sAuctionBotConfig->GetConfigItemAmountRatio(AuctionHouseType(i)))
375}
376
378{
379 uint32 ratio = sAuctionBotConfig->GetConfigItemAmountRatio(config.GetHouseType());
380
381 for (uint32 i = 0; i < MAX_AUCTION_QUALITY; ++i)
382 {
384 config.SetItemsAmountPerQuality(AuctionQuality(i), std::lroundf(amount * ratio / 100.f));
385 }
386
387 // Set Stack Quantities
403
404 // Set the best value to get nearest amount of items wanted
405 auto getPriorityForClass = [](uint32 itemClass) -> uint32
406 {
408 switch (itemClass)
409 {
416 case ITEM_CLASS_GEM:
417 index = CONFIG_AHBOT_CLASS_GEM_PRIORITY; break;
418 case ITEM_CLASS_ARMOR:
432 case ITEM_CLASS_QUEST:
434 case ITEM_CLASS_KEY:
435 index = CONFIG_AHBOT_CLASS_KEY_PRIORITY; break;
438 case ITEM_CLASS_GLYPH:
440 default:
441 return 0;
442 }
443
444 return sAuctionBotConfig->GetConfig(index);
445 };
446
447 std::vector<uint32> totalPrioPerQuality(MAX_AUCTION_QUALITY);
448 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
449 {
450 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
451 {
452 // skip empty pools
453 if (_itemPool[j][i].empty())
454 continue;
455
456 totalPrioPerQuality[j] += getPriorityForClass(i);
457 }
458 }
459
460 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
461 {
462 uint32 qualityAmount = config.GetItemsAmountPerQuality(AuctionQuality(j));
463 if (!totalPrioPerQuality[j])
464 continue;
465
466 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
467 {
468 uint32 classPrio = getPriorityForClass(i);
469 if (_itemPool[j][i].empty())
470 classPrio = 0;
471
472 uint32 weightedAmount = std::lroundf(classPrio / float(totalPrioPerQuality[j]) * qualityAmount);
473 config.SetItemsAmountPerClass(AuctionQuality(j), ItemClass(i), weightedAmount);
474 }
475 }
476
477 // do some assert checking, GetItemAmount must always return 0 if selected _itemPool is empty
478 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
479 {
480 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
481 {
482 if (_itemPool[j][i].empty())
484 }
485 }
486}
487
489{
490 LoadItemsQuantity(config);
491 uint32 ratio = sAuctionBotConfig->GetConfigPriceRatio(config.GetHouseType());
492
493 for (uint32 i = 0; i < MAX_AUCTION_QUALITY; ++i)
494 {
496 config.SetPriceRatioPerQuality(AuctionQuality(i), std::lroundf(amount * ratio / 100.f));
497 }
498
516
517 //load min and max auction times
520}
521
522// Set static of items on one AH faction.
523// Fill ItemInfos object with real content of AH.
525{
526 AllItemsArray itemsSaved;
527
528 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsById(sAuctionBotConfig->GetAuctionHouseId(config.GetHouseType()));
529 for (auto itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr)
530 {
531 AuctionPosting const* auctionEntry = &itr->second;
532 if (auctionEntry->Owner.IsEmpty() || sAuctionBotConfig->IsBotChar(auctionEntry->Owner)) // Add only ahbot items
533 ++itemsSaved[auctionEntry->Items[0]->GetQuality()][auctionEntry->Bucket->ItemClass];
534 }
535
536 uint32 count = 0;
537 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
538 {
539 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
540 {
541 config.SetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i, itemsSaved[j][i]);
542 count += config.GetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i);
543 }
544 }
545
546 TC_LOG_DEBUG("ahbot", "AHBot: Missed Item \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
547 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
548 {
549 TC_LOG_DEBUG("ahbot", "AHBot: \t\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
557 }
558 config.LastMissedItem = count;
559
560 return count;
561}
562
563// getRandomArray is used to make viable the possibility to add any of missed item in place of first one to last one.
565{
566 itemsToSellArray.clear();
567 bool found = false;
568
569 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
570 {
571 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
572 {
573 // if _itemPool for chosen is empty, MissedItemsPerClass will return 0 here (checked at startup)
574 if (config.GetMissedItemsPerClass(AuctionQuality(j), ItemClass(i)) > addedItem[j][i])
575 {
576 ItemToSell miss_item;
577 miss_item.Color = j;
578 miss_item.Itemclass = i;
579 itemsToSellArray.emplace_back(std::move(miss_item));
580 found = true;
581 }
582 }
583 }
584
585 return found;
586}
587
588// Set items price. All important value are passed by address.
589void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyout, uint32& bid, uint32 stackCount)
590{
591 uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->GetClass()));
592 uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->GetQuality()));
593 float priceRatio = (classRatio * qualityRatio) / 10000.0f;
594
595 float buyPrice = itemProto->GetBuyPrice();
596 float sellPrice = itemProto->GetSellPrice();
597
598 if (buyPrice == 0)
599 {
600 if (sellPrice > 0)
601 buyPrice = sellPrice * GetSellModifier(itemProto);
602 else
603 {
604 float divisor = ((itemProto->GetClass() == ITEM_CLASS_WEAPON || itemProto->GetClass() == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f);
605 float tempLevel = (itemProto->GetBaseItemLevel() == 0 ? 1.0f : itemProto->GetBaseItemLevel());
606 float tempQuality = (itemProto->GetQuality() == 0 ? 1.0f : itemProto->GetQuality());
607
608 buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor;
609 }
610 }
611
612 if (sellPrice == 0)
613 sellPrice = (buyPrice > 10 ? buyPrice / GetSellModifier(itemProto) : buyPrice);
614
616 buyPrice = sellPrice;
617
618 float basePriceFloat = buyPrice * stackCount / (itemProto->GetClass() == 6 ? 200.0f : static_cast<float>(itemProto->GetBuyCount()));
619 basePriceFloat *= priceRatio;
620
621 float range = basePriceFloat * 0.04f;
622
623 buyout = (static_cast<uint32>(frand(basePriceFloat - range, basePriceFloat + range) + 0.5f) / SILVER) * SILVER;
624 if (buyout == 0)
625 buyout = SILVER;
626
628 bid = (static_cast<uint32>(bidPercentage * buyout) / SILVER) * SILVER;
629 if (bid == 0)
630 bid = SILVER;
631}
632
633// Determines the stack size to use for the item
635{
636 if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->GetClass())) > urand(0, 99))
637 return urand(1, itemProto->GetMaxStackSize());
638 else
639 return 1;
640}
641
642// Determine the multiplier for the sell price of any weapon without a buy price.
644{
645 switch (prototype->GetClass())
646 {
648 case ITEM_CLASS_ARMOR:
651 return 5;
652 default:
653 return 4;
654 }
655}
656
657// Return the modifier by which the item's level and quality will be modified by to derive a relatively accurate price.
659{
660 switch (prototype->GetClass())
661 {
663 {
664 switch (prototype->GetSubClass())
665 {
667 return 100;
669 return 400;
671 return 15;
673 return 250;
675 return 125;
676 default:
677 return 300;
678 }
679 }
681 {
682 switch (prototype->GetSubClass())
683 {
689 return 1200;
695 return 1500;
697 return 350;
698 default:
699 return 1000;
700 }
701 }
702 case ITEM_CLASS_ARMOR:
703 {
704 switch (prototype->GetSubClass())
705 {
708 return 500;
710 return 600;
712 return 700;
715 return 800;
716 default:
717 return 400;
718 }
719 }
722 return 50;
724 {
725 switch (prototype->GetSubClass())
726 {
730 return 50;
732 return 250;
734 return 500;
738 return 300;
739 default:
740 return 100;
741 }
742 }
743 case ITEM_CLASS_QUEST: return 1000;
744 case ITEM_CLASS_KEY: return 3000;
745 default:
746 return 500;
747 }
748}
749
751{
752 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, std::max(al, 100000u));
753 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, std::max(ho, 100000u));
754 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, std::max(ne, 100000u));
755
756 for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
758}
759
761{
762 val = std::max(val, 10000u); // apply same upper limit as used for config load
763
764 switch (house)
765 {
768 default: sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, val); break;
769 }
770
772}
773
774void AuctionBotSeller::SetItemsAmount(std::array<uint32, MAX_AUCTION_QUALITY> const& amounts)
775{
783
784 for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
786}
787
789{
790 switch (quality)
791 {
793 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT, val); break;
799 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT, val); break;
804 default:
806 }
807
808 for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
810}
811
812// Add new auction to one of the factions.
813// Faction and setting associated is defined passed argument ( config )
815{
816 uint32 count = 0;
817 uint32 items = 0;
818
819 // If there is large amount of items missed we can use boost value to get fast filled AH
820 if (config.LastMissedItem > sAuctionBotConfig->GetItemPerCycleBoost())
821 {
822 items = sAuctionBotConfig->GetItemPerCycleBoost();
823 TC_LOG_DEBUG("ahbot", "AHBot: Boost value used to fill AH! (if this happens often adjust both ItemsPerCycle in worldserver.conf)");
824 }
825 else
826 items = sAuctionBotConfig->GetItemPerCycleNormal();
827
828 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsById(sAuctionBotConfig->GetAuctionHouseId(config.GetHouseType()));
829
830 ItemsToSellArray itemsToSell;
831 AllItemsArray allItems;
832 // Main loop
833 // getRandomArray will give what categories of items should be added (return true if there is at least 1 items missed)
834 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
835 while (GetItemsToSell(config, itemsToSell, allItems) && items > 0)
836 {
837 --items;
838
839 // Select random position from missed items table
841
842 // Set itemId with random item ID for selected categories and color, from _itemPool table
844 ++allItems[sellItem.Color][sellItem.Itemclass]; // Helper table to avoid rescan from DB in this loop. (has we add item in random orders)
845
846 if (!itemId)
847 {
848 TC_LOG_DEBUG("ahbot", "AHBot: Item entry 0 auction creating attempt.");
849 continue;
850 }
851
852 ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemId);
853 if (!prototype)
854 {
855 TC_LOG_DEBUG("ahbot", "AHBot: Unknown item {} auction creating attempt.", itemId);
856 continue;
857 }
858
859 uint32 stackCount = GetStackSizeForItem(prototype, config);
860
861 Item* item = Item::CreateItem(itemId, stackCount, ItemContext::NONE);
862 if (!item)
863 {
864 TC_LOG_ERROR("ahbot", "AHBot: Item::CreateItem() returned NULL for item {} (stack: {})", itemId, stackCount);
865 return;
866 }
867
868 // Update the just created item so that if it needs random properties it has them.
869 // Ex: Notched Shortsword of Stamina will only generate as a Notched Shortsword without this.
871
872 uint32 buyoutPrice;
873 uint32 bidPrice = 0;
874
875 // Price of items are set here
876 SetPricesOfItem(prototype, config, buyoutPrice, bidPrice, stackCount);
877
878 // Deposit time
879 uint32 etime = urand(1, 3);
880 switch (etime)
881 {
882 case 1:
883 etime = DAY / 2;
884 break;
885 case 3:
886 etime = 2 *DAY;
887 break;
888 case 2:
889 default:
890 etime = DAY;
891 break;
892 }
893
894 AuctionPosting auction;
895 auction.Id = sObjectMgr->GenerateAuctionID();
896 auction.Items.push_back(item);
897 auction.Owner = sAuctionBotConfig->GetRandChar();
898 if (!auction.IsCommodity())
899 auction.MinBid = bidPrice;
900
901 auction.BuyoutOrUnitPrice = buyoutPrice;
903 auction.EndTime = auction.StartTime + Hours(urand(config.GetMinTime(), config.GetMaxTime()));
904
905 auctionHouse->AddAuction(trans, std::move(auction));
906
907 ++count;
908 }
909 CharacterDatabase.CommitTransaction(trans);
910
911 TC_LOG_DEBUG("ahbot", "AHBot: Added {} items to auction", count);
912}
913
915{
916 if (sAuctionBotConfig->GetConfigItemAmountRatio(houseType) > 0)
917 {
918 TC_LOG_DEBUG("ahbot", "AHBot: {} selling ...", AuctionBotConfig::GetHouseTypeName(houseType));
919 if (SetStat(_houseConfig[houseType]))
920 AddNewAuctions(_houseConfig[houseType]);
921 return true;
922 }
923 else
924 return false;
925}
std::vector< ItemToSell > ItemsToSellArray
std::array< std::array< uint32, MAX_ITEM_CLASS >, MAX_ITEM_QUALITY > AllItemsArray
AuctionBotConfigUInt32Values
@ CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUEST
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GENERIC
@ CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL
@ CONFIG_AHBOT_CLASS_GLYPH_PRIORITY
@ CONFIG_AHBOT_CLASS_QUEST_PRIORITY
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_QUIVER
@ CONFIG_AHBOT_CLASS_PROJECTILE_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_GEM_PRIORITY
@ CONFIG_AHBOT_CLASS_QUIVER_PRIORITY
@ CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GEM
@ CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_MISC_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_PERMANENT_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK
@ CONFIG_AHBOT_CLASS_MISC_PRIORITY
@ CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK
@ CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_RECIPE_PRIORITY
@ CONFIG_AHBOT_CLASS_ARMOR_PRIORITY
@ CONFIG_AHBOT_CLASS_GLYPH_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_TRADEGOOD_PRIORITY
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_GLYPH
@ CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_REAGENT_PRIORITY
@ CONFIG_AHBOT_MAXTIME
@ CONFIG_AHBOT_ITEM_ORANGE_AMOUNT
@ CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_KEY_PRIORITY
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_MISC
@ CONFIG_AHBOT_ITEM_BLUE_AMOUNT
@ CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO
@ CONFIG_AHBOT_CLASS_QUEST_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL
@ CONFIG_AHBOT_CLASS_QUIVER_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_PROJECTILE_PRIORITY
@ CONFIG_AHBOT_CLASS_CONSUMABLE_PRIORITY
@ CONFIG_AHBOT_CLASS_GEM_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_MONEY_PRICE_RATIO
@ CONFIG_AHBOT_MINTIME
@ CONFIG_AHBOT_CLASS_CONTAINER_PRIORITY
@ CONFIG_AHBOT_CLASS_GENERIC_PRIORITY
@ CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_GENERIC_PRICE_RATIO
@ CONFIG_AHBOT_ITEM_GREEN_AMOUNT
@ CONFIG_AHBOT_CLASS_KEY_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_TRADEGOOD
@ CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_REAGENT
@ CONFIG_AHBOT_ITEM_WHITE_AMOUNT
@ CONFIG_AHBOT_ITEM_MIN_SKILL_RANK
@ CONFIG_AHBOT_CLASS_TRADEGOOD_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_WEAPON_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_ARMOR_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_WEAPON
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONTAINER
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_RECIPE
@ CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO
@ CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_ARMOR
@ CONFIG_AHBOT_ITEM_GRAY_AMOUNT
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_KEY
@ CONFIG_AHBOT_ITEM_MAX_SKILL_RANK
@ CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO
@ CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL
@ CONFIG_AHBOT_CLASS_REAGENT_PRICE_RATIO
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_CONSUMABLE
@ CONFIG_AHBOT_CLASS_RECIPE_PRICE_RATIO
@ CONFIG_AHBOT_ITEM_YELLOW_AMOUNT
@ CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL
@ CONFIG_AHBOT_ITEM_PURPLE_AMOUNT
@ CONFIG_AHBOT_CLASS_RANDOMSTACKRATIO_PROJECTILE
@ CONFIG_AHBOT_CLASS_WEAPON_PRIORITY
@ CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL
@ CONFIG_AHBOT_BIDPRICE_MIN
@ CONFIG_AHBOT_BIDPRICE_MAX
#define MAX_AUCTION_QUALITY
AuctionQuality
@ AUCTION_QUALITY_ORANGE
@ AUCTION_QUALITY_WHITE
@ AUCTION_QUALITY_PURPLE
@ AUCTION_QUALITY_BLUE
@ AUCTION_QUALITY_YELLOW
@ AUCTION_QUALITY_GREEN
@ AUCTION_QUALITY_GRAY
#define MAX_AUCTION_HOUSE_TYPE
AuctionHouseType
@ AUCTION_HOUSE_HORDE
@ AUCTION_HOUSE_ALLIANCE
#define sAuctionBotConfig
@ CONFIG_AHBOT_CLASS_QUIVER_ALLOW_ZERO
@ CONFIG_AHBOT_ITEMS_MISC
@ CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_TRADEGOOD_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_GEM_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_RECIPE_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_CONTAINER_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_KEY_ALLOW_ZERO
@ CONFIG_AHBOT_LOCKBOX_ENABLED
@ CONFIG_AHBOT_CLASS_REAGENT_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_PROJECTILE_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_QUEST_ALLOW_ZERO
@ CONFIG_AHBOT_CLASS_ARMOR_ALLOW_ZERO
@ CONFIG_AHBOT_BIND_QUEST
@ CONFIG_AHBOT_ITEMS_VENDOR
@ CONFIG_AHBOT_BIND_EQUIP
@ CONFIG_AHBOT_BIND_NO
@ CONFIG_AHBOT_CLASS_GLYPH_ALLOW_ZERO
@ CONFIG_AHBOT_BIND_PICKUP
@ CONFIG_AHBOT_CLASS_WEAPON_ALLOW_ZERO
@ CONFIG_AHBOT_ITEMS_LOOT
@ CONFIG_AHBOT_CLASS_MISC_ALLOW_ZERO
@ CONFIG_AHBOT_BIND_USE
@ CONFIG_AHBOT_BUYPRICE_SELLER
#define sAuctionMgr
@ DAY
Definition: Common.h:31
DB2Storage< ItemEntry > sItemStore("Item.db2", &ItemLoadInfo::Instance)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
std::chrono::hours Hours
Hours shorthand typedef.
Definition: Duration.h:38
#define ASSERT
Definition: Errors.h:68
ItemRandomBonusListId GenerateItemRandomBonusListId(uint32 item_id)
ItemClass
Definition: ItemTemplate.h:419
@ ITEM_CLASS_QUIVER
Definition: ItemTemplate.h:431
@ ITEM_CLASS_RECIPE
Definition: ItemTemplate.h:429
@ ITEM_CLASS_KEY
Definition: ItemTemplate.h:433
@ ITEM_CLASS_CONTAINER
Definition: ItemTemplate.h:421
@ ITEM_CLASS_TRADE_GOODS
Definition: ItemTemplate.h:427
@ ITEM_CLASS_REAGENT
Definition: ItemTemplate.h:425
@ ITEM_CLASS_MONEY
Definition: ItemTemplate.h:430
@ ITEM_CLASS_PERMANENT
Definition: ItemTemplate.h:434
@ ITEM_CLASS_GLYPH
Definition: ItemTemplate.h:436
@ ITEM_CLASS_PROJECTILE
Definition: ItemTemplate.h:426
@ ITEM_CLASS_GEM
Definition: ItemTemplate.h:423
@ ITEM_CLASS_ITEM_ENHANCEMENT
Definition: ItemTemplate.h:428
@ ITEM_CLASS_ARMOR
Definition: ItemTemplate.h:424
@ ITEM_CLASS_QUEST
Definition: ItemTemplate.h:432
@ ITEM_CLASS_MISCELLANEOUS
Definition: ItemTemplate.h:435
@ ITEM_CLASS_WEAPON
Definition: ItemTemplate.h:422
@ ITEM_CLASS_CONSUMABLE
Definition: ItemTemplate.h:420
@ ITEM_SUBCLASS_WEAPON_AXE2
Definition: ItemTemplate.h:481
@ ITEM_SUBCLASS_WEAPON_STAFF
Definition: ItemTemplate.h:490
@ ITEM_SUBCLASS_WEAPON_MACE
Definition: ItemTemplate.h:484
@ ITEM_SUBCLASS_WEAPON_MACE2
Definition: ItemTemplate.h:485
@ ITEM_SUBCLASS_WEAPON_DAGGER
Definition: ItemTemplate.h:495
@ ITEM_SUBCLASS_WEAPON_SWORD
Definition: ItemTemplate.h:487
@ ITEM_SUBCLASS_WEAPON_AXE
Definition: ItemTemplate.h:480
@ ITEM_SUBCLASS_WEAPON_FIST_WEAPON
Definition: ItemTemplate.h:493
@ ITEM_SUBCLASS_WEAPON_THROWN
Definition: ItemTemplate.h:496
@ ITEM_SUBCLASS_WEAPON_SWORD2
Definition: ItemTemplate.h:488
@ ITEM_SUBCLASS_WEAPON_POLEARM
Definition: ItemTemplate.h:486
@ ITEM_FLAG_HAS_LOOT
Definition: ItemTemplate.h:178
#define MAX_ITEM_CLASS
Definition: ItemTemplate.h:442
@ ITEM_SUBCLASS_ARMOR_MAIL
Definition: ItemTemplate.h:532
@ ITEM_SUBCLASS_ARMOR_CLOTH
Definition: ItemTemplate.h:530
@ ITEM_SUBCLASS_ARMOR_LEATHER
Definition: ItemTemplate.h:531
@ ITEM_SUBCLASS_ARMOR_SHIELD
Definition: ItemTemplate.h:535
@ ITEM_SUBCLASS_ARMOR_PLATE
Definition: ItemTemplate.h:533
@ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS
Definition: ItemTemplate.h:529
@ ITEM_SUBCLASS_PARTS
Definition: ItemTemplate.h:568
@ ITEM_SUBCLASS_ENCHANTING
Definition: ItemTemplate.h:579
@ ITEM_SUBCLASS_TRADE_GOODS
Definition: ItemTemplate.h:567
@ ITEM_SUBCLASS_EXPLOSIVES
Definition: ItemTemplate.h:569
@ ITEM_SUBCLASS_TRADE_GOODS_OTHER
Definition: ItemTemplate.h:578
@ ITEM_SUBCLASS_DEVICES
Definition: ItemTemplate.h:570
@ ITEM_SUBCLASS_MEAT
Definition: ItemTemplate.h:575
@ ITEM_SUBCLASS_ELEMENTAL
Definition: ItemTemplate.h:577
@ BIND_QUEST
Definition: ItemTemplate.h:120
@ BIND_ON_USE
Definition: ItemTemplate.h:119
@ BIND_ON_EQUIP
Definition: ItemTemplate.h:118
@ BIND_NONE
Definition: ItemTemplate.h:116
@ BIND_ON_ACQUIRE
Definition: ItemTemplate.h:117
@ ITEM_SUBCLASS_MISCELLANEOUS_MOUNT
Definition: ItemTemplate.h:678
@ ITEM_SUBCLASS_SCROLL
Definition: ItemTemplate.h:450
@ ITEM_SUBCLASS_FLASK
Definition: ItemTemplate.h:449
@ ITEM_SUBCLASS_CONSUMABLE
Definition: ItemTemplate.h:446
@ ITEM_SUBCLASS_BANDAGE
Definition: ItemTemplate.h:453
@ ITEM_SUBCLASS_ITEM_ENHANCEMENT
Definition: ItemTemplate.h:452
@ LOG_LEVEL_DEBUG
Definition: LogCommon.h:28
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define sLog
Definition: Log.h:130
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::unordered_map< uint32, CreatureTemplate > CreatureTemplateContainer
Definition: ObjectMgr.h:495
float frand(float min, float max)
Definition: Random.cpp:55
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
@ SILVER
static char const * GetHouseTypeName(AuctionHouseType houseType)
bool Initialize() override
void SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
SellerConfiguration _houseConfig[MAX_AUCTION_HOUSE_TYPE]
void LoadSellerValues(SellerConfiguration &config)
uint32 SetStat(SellerConfiguration &config)
void SetItemsAmount(std::array< uint32, MAX_AUCTION_QUALITY > const &amounts)
bool Update(AuctionHouseType houseType) override
ItemPool _itemPool[MAX_AUCTION_QUALITY][MAX_ITEM_CLASS]
void SetPricesOfItem(ItemTemplate const *itemProto, SellerConfiguration &config, uint32 &buyout, uint32 &bid, uint32 stackcnt)
void LoadItemsQuantity(SellerConfiguration &config)
static uint32 GetBuyModifier(ItemTemplate const *prototype)
void AddNewAuctions(SellerConfiguration &config)
uint32 GetStackSizeForItem(ItemTemplate const *itemProto, SellerConfiguration &config) const
static uint32 GetSellModifier(ItemTemplate const *itemProto)
void SetItemsRatioForHouse(AuctionHouseType house, uint32 val)
bool GetItemsToSell(SellerConfiguration &config, ItemsToSellArray &itemsToSellArray, AllItemsArray const &addedItem)
void SetItemsRatio(uint32 al, uint32 ho, uint32 ne)
std::map< uint32, AuctionPosting >::iterator GetAuctionsEnd()
void AddAuction(CharacterDatabaseTransaction trans, AuctionPosting auction)
std::map< uint32, AuctionPosting >::iterator GetAuctionsBegin()
Class used to access individual fields of database query result.
Definition: Field.h:90
uint32 GetUInt32() const
Definition: Field.cpp:62
Definition: Item.h:170
void SetItemRandomBonusList(ItemRandomBonusListId bonusListId)
Definition: Item.cpp:1158
static Item * CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const *player=nullptr, bool addDefaultBonuses=true)
Definition: Item.cpp:1625
bool IsEmpty() const
Definition: ObjectGuid.h:319
void SetMissedItemsPerClass(AuctionQuality quality, ItemClass itemClass, uint32 found)
void SetPriceRatioPerClass(ItemClass itemClass, uint32 value)
void SetMaxTime(uint32 value)
uint32 GetItemsAmountPerClass(AuctionQuality quality, ItemClass itemClass) const
void SetPriceRatioPerQuality(AuctionQuality quality, uint32 value)
uint32 GetRandomStackRatioPerClass(ItemClass itemClass) const
uint32 GetPriceRatioPerQuality(AuctionQuality quality) const
uint32 GetMissedItemsPerClass(AuctionQuality quality, ItemClass itemClass) const
void SetItemsAmountPerQuality(AuctionQuality quality, uint32 cnt)
uint32 GetPriceRatioPerClass(ItemClass itemClass) const
uint32 GetItemsAmountPerQuality(AuctionQuality quality) const
void SetMinTime(uint32 value)
void SetItemsAmountPerClass(AuctionQuality quality, ItemClass itemClass, uint32 amount)
AuctionHouseType GetHouseType() const
void SetRandomStackRatioPerClass(ItemClass itemClass, uint32 value)
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
bool IsCommodity() const
std::vector< Item * > Items
AuctionsBucketData * Bucket
ObjectGuid Owner
uint64 BuyoutOrUnitPrice
SystemTimePoint StartTime
SystemTimePoint EndTime
uint32 GetRequiredSkillRank() const
Definition: ItemTemplate.h:792
uint32 GetBaseItemLevel() const
Definition: ItemTemplate.h:789
uint32 GetQuality() const
Definition: ItemTemplate.h:779
uint32 GetBuyCount() const
Definition: ItemTemplate.h:783
uint32 GetMaxStackSize() const
Definition: ItemTemplate.h:847
uint32 GetBuyPrice() const
Definition: ItemTemplate.h:784
ItemBondingType GetBonding() const
Definition: ItemTemplate.h:806
int32 GetBaseRequiredLevel() const
Definition: ItemTemplate.h:790
bool HasFlag(ItemFlags flag) const
Definition: ItemTemplate.h:871
uint32 GetSubClass() const
Definition: ItemTemplate.h:778
uint32 GetSellPrice() const
Definition: ItemTemplate.h:785
uint32 GetLockID() const
Definition: ItemTemplate.h:810
uint32 GetClass() const
Definition: ItemTemplate.h:777
uint32 item
Definition: CreatureData.h:655