TrinityCore
Loading...
Searching...
No Matches
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 "Containers.h"
21#include "DatabaseEnv.h"
22#include "DBCStores.h"
23#include "GameTime.h"
24#include "Item.h"
25#include "Log.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
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(atoi(temp.c_str()));
62 }
63
64 TC_LOG_DEBUG("ahbot", "Forced Inclusion {} items", (uint32)includeItems.size());
65 TC_LOG_DEBUG("ahbot", "Forced Exclusion {} items", (uint32)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", (uint32)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", (uint32)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->Quality >= 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->Quality][prototype->Class].push_back(itemId);
127 ++itemsAdded;
128 continue;
129 }
130
131 // bounding filters
132 switch (prototype->Bonding)
133 {
134 case NO_BIND:
136 continue;
137 break;
140 continue;
141 break;
144 continue;
145 break;
146 case BIND_WHEN_USE:
148 continue;
149 break;
150 case BIND_QUEST_ITEM:
152 continue;
153 break;
154 default:
155 continue;
156 }
157
158 bool allowZero = false;
159 switch (prototype->Class)
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->SellPrice == 0)
199 continue;
200 }
201 else
202 {
203 if (prototype->BuyPrice == 0)
204 continue;
205 }
206 }
207
208 // vendor filter
210 {
211 if (npcItems.count(itemId))
212 continue;
213 }
214
215 // loot filter
217 {
218 if (lootItems.count(itemId))
219 continue;
220 }
221
222 // not vendor/loot filter
224 {
225 bool const isVendorItem = npcItems.count(itemId) > 0;
226 bool const isLootItem = lootItems.count(itemId) > 0;
227
228 if (!isLootItem && !isVendorItem)
229 continue;
230 }
231
232 // item class/subclass specific filters
233 switch (prototype->Class)
234 {
235 case ITEM_CLASS_ARMOR:
237 {
239 if (prototype->ItemLevel < value)
240 continue;
242 if (prototype->ItemLevel > value)
243 continue;
245 if (prototype->RequiredLevel < value)
246 continue;
248 if (prototype->RequiredLevel > value)
249 continue;
251 if (prototype->RequiredSkillRank < value)
252 continue;
254 if (prototype->RequiredSkillRank > value)
255 continue;
256 break;
257 }
261 {
263 if (prototype->RequiredLevel < value)
264 continue;
266 if (prototype->RequiredLevel > value)
267 continue;
269 if (prototype->RequiredSkillRank < value)
270 continue;
272 if (prototype->RequiredSkillRank > value)
273 continue;
274 break;
275 }
277 if (prototype->SubClass == ITEM_SUBCLASS_JUNK_MOUNT)
278 {
280 if (prototype->RequiredLevel < value)
281 continue;
283 if (prototype->RequiredLevel > value)
284 continue;
286 if (prototype->RequiredSkillRank < value)
287 continue;
289 if (prototype->RequiredSkillRank > value)
290 continue;
291 }
292
293 if (prototype->HasFlag(ITEM_FLAG_HAS_LOOT))
294 {
295 // skip any not locked lootable items (mostly quest specific or reward cases)
296 if (!prototype->LockID)
297 continue;
298
300 continue;
301 }
302
303 break;
304 case ITEM_CLASS_GLYPH:
305 {
307 if (prototype->RequiredLevel < value)
308 continue;
310 if (prototype->RequiredLevel > value)
311 continue;
313 if (prototype->RequiredLevel < value)
314 continue;
316 if (prototype->RequiredLevel > value)
317 continue;
318 break;
319 }
321 {
323 if (prototype->ItemLevel < value)
324 continue;
326 if (prototype->ItemLevel > value)
327 continue;
328 break;
329 }
332 {
334 if (prototype->ItemLevel < value)
335 continue;
337 if (prototype->ItemLevel > value)
338 continue;
339 break;
340 }
341 }
342
343 _itemPool[prototype->Quality][prototype->Class].push_back(itemId);
344 ++itemsAdded;
345 }
346
347 if (!itemsAdded)
348 {
349 TC_LOG_ERROR("ahbot", "AuctionHouseBot seller not have items, disabled.");
353 return false;
354 }
355
356 TC_LOG_DEBUG("ahbot", "AuctionHouseBot seller will use {} items to fill auction house (according your config choices)", itemsAdded);
357
358 LoadConfig();
359
360 TC_LOG_DEBUG("ahbot", "Items loaded \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
361 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
362 TC_LOG_DEBUG("ahbot", "\t\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
363 (uint32)_itemPool[0][i].size(), (uint32)_itemPool[1][i].size(), (uint32)_itemPool[2][i].size(),
364 (uint32)_itemPool[3][i].size(), (uint32)_itemPool[4][i].size(), (uint32)_itemPool[5][i].size(),
365 (uint32)_itemPool[6][i].size());
366
367 TC_LOG_DEBUG("ahbot", "AHBot seller configuration data loaded and initialized");
368 return true;
369}
370
372{
373 for (uint8 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
374 if (sAuctionBotConfig->GetConfigItemAmountRatio(AuctionHouseType(i)))
376}
377
379{
380 uint32 ratio = sAuctionBotConfig->GetConfigItemAmountRatio(config.GetHouseType());
381
382 for (uint32 i = 0; i < MAX_AUCTION_QUALITY; ++i)
383 {
385 config.SetItemsAmountPerQuality(AuctionQuality(i), std::lroundf(amount * ratio / 100.f));
386 }
387
388 // Set Stack Quantities
404
405 // Set the best value to get nearest amount of items wanted
406 auto getPriorityForClass = [](uint32 itemClass) -> uint32
407 {
409 switch (itemClass)
410 {
417 case ITEM_CLASS_GEM:
418 index = CONFIG_AHBOT_CLASS_GEM_PRIORITY; break;
419 case ITEM_CLASS_ARMOR:
433 case ITEM_CLASS_QUEST:
435 case ITEM_CLASS_KEY:
436 index = CONFIG_AHBOT_CLASS_KEY_PRIORITY; break;
439 case ITEM_CLASS_GLYPH:
441 default:
442 return 0;
443 }
444
445 return sAuctionBotConfig->GetConfig(index);
446 };
447
448 std::vector<uint32> totalPrioPerQuality(MAX_AUCTION_QUALITY);
449 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
450 {
451 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
452 {
453 // skip empty pools
454 if (_itemPool[j][i].empty())
455 continue;
456
457 totalPrioPerQuality[j] += getPriorityForClass(i);
458 }
459 }
460
461 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
462 {
463 uint32 qualityAmount = config.GetItemsAmountPerQuality(AuctionQuality(j));
464 if (!totalPrioPerQuality[j])
465 continue;
466
467 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
468 {
469 uint32 classPrio = getPriorityForClass(i);
470 if (_itemPool[j][i].empty())
471 classPrio = 0;
472
473 uint32 weightedAmount = std::lroundf(classPrio / float(totalPrioPerQuality[j]) * qualityAmount);
474 config.SetItemsAmountPerClass(AuctionQuality(j), ItemClass(i), weightedAmount);
475 }
476 }
477
478 // do some assert checking, GetItemAmount must always return 0 if selected _itemPool is empty
479 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
480 {
481 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
482 {
483 if (_itemPool[j][i].empty())
485 }
486 }
487}
488
490{
491 LoadItemsQuantity(config);
492 uint32 ratio = sAuctionBotConfig->GetConfigPriceRatio(config.GetHouseType());
493
494 for (uint32 i = 0; i < MAX_AUCTION_QUALITY; ++i)
495 {
497 config.SetPriceRatioPerQuality(AuctionQuality(i), std::lroundf(amount * ratio / 100.f));
498 }
499
517
518 //load min and max auction times
521}
522
523// Set static of items on one AH faction.
524// Fill ItemInfos object with real content of AH.
526{
527 AllItemsArray itemsSaved(MAX_AUCTION_QUALITY, std::vector<uint32>(MAX_ITEM_CLASS));
528
529 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
530 for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr)
531 {
532 AuctionEntry* auctionEntry = itr->second;
533 Item* item = sAuctionMgr->GetAItem(auctionEntry->itemGUIDLow);
534 if (item)
535 {
536 ItemTemplate const* prototype = item->GetTemplate();
537 if (prototype)
538 if (!auctionEntry->owner || sAuctionBotConfig->IsBotChar(auctionEntry->owner)) // Add only ahbot items
539 ++itemsSaved[prototype->Quality][prototype->Class];
540 }
541 }
542
543 uint32 count = 0;
544 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
545 {
546 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
547 {
548 config.SetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i, itemsSaved[j][i]);
549 count += config.GetMissedItemsPerClass((AuctionQuality)j, (ItemClass)i);
550 }
551 }
552
553 TC_LOG_DEBUG("ahbot", "AHBot: Missed Item \tGray\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
554 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
555 {
556 TC_LOG_DEBUG("ahbot", "AHBot: \t\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
564 }
565 config.LastMissedItem = count;
566
567 return count;
568}
569
570// getRandomArray is used to make viable the possibility to add any of missed item in place of first one to last one.
572{
573 itemsToSellArray.clear();
574 bool found = false;
575
576 for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
577 {
578 for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
579 {
580 // if _itemPool for chosen is empty, MissedItemsPerClass will return 0 here (checked at startup)
581 if (config.GetMissedItemsPerClass(AuctionQuality(j), ItemClass(i)) > addedItem[j][i])
582 {
583 ItemToSell miss_item;
584 miss_item.Color = j;
585 miss_item.Itemclass = i;
586 itemsToSellArray.emplace_back(std::move(miss_item));
587 found = true;
588 }
589 }
590 }
591
592 return found;
593}
594
595// Set items price. All important value are passed by address.
596void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackCount)
597{
598 uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class));
599 uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality));
600 float priceRatio = (classRatio * qualityRatio) / 10000.0f;
601
602 float buyPrice = itemProto->BuyPrice;
603 float sellPrice = itemProto->SellPrice;
604
605 if (buyPrice == 0)
606 {
607 if (sellPrice > 0)
608 buyPrice = sellPrice * GetSellModifier(itemProto);
609 else
610 {
611 float divisor = ((itemProto->Class == ITEM_CLASS_WEAPON || itemProto->Class == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f);
612 float tempLevel = (itemProto->ItemLevel == 0 ? 1.0f : itemProto->ItemLevel);
613 float tempQuality = (itemProto->Quality == 0 ? 1.0f : itemProto->Quality);
614
615 buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor;
616 }
617 }
618
619 if (sellPrice == 0)
620 sellPrice = (buyPrice > 10 ? buyPrice / GetSellModifier(itemProto) : buyPrice);
621
623 buyPrice = sellPrice;
624
625 float basePriceFloat = buyPrice * stackCount / (itemProto->Class == 6 ? 200.0f : static_cast<float>(itemProto->BuyCount));
626 basePriceFloat *= priceRatio;
627
628 float range = basePriceFloat * 0.04f;
629
630 buyp = static_cast<uint32>(frand(basePriceFloat - range, basePriceFloat + range) + 0.5f);
631 if (buyp == 0)
632 buyp = 1;
633
635 bidp = static_cast<uint32>(bidPercentage * buyp);
636 if (bidp == 0)
637 bidp = 1;
638}
639
640// Determines the stack size to use for the item
642{
643 if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->Class)) > urand(0, 99))
644 return urand(1, itemProto->GetMaxStackSize());
645 else
646 return 1;
647}
648
649// Determine the multiplier for the sell price of any weapon without a buy price.
651{
652 switch (prototype->Class)
653 {
655 case ITEM_CLASS_ARMOR:
658 return 5;
659 default:
660 return 4;
661 }
662}
663
664// Return the modifier by which the item's level and quality will be modified by to derive a relatively accurate price.
666{
667 switch (prototype->Class)
668 {
670 {
671 switch (prototype->SubClass)
672 {
674 return 100;
676 return 400;
678 return 15;
680 return 250;
682 return 125;
683 default:
684 return 300;
685 }
686 }
688 {
689 switch (prototype->SubClass)
690 {
696 return 1200;
702 return 1500;
704 return 350;
705 default:
706 return 1000;
707 }
708 }
709 case ITEM_CLASS_ARMOR:
710 {
711 switch (prototype->SubClass)
712 {
715 return 500;
717 return 600;
719 return 700;
722 return 800;
723 default:
724 return 400;
725 }
726 }
729 return 50;
731 {
732 switch (prototype->SubClass)
733 {
737 return 50;
739 return 250;
741 return 500;
745 return 300;
746 default:
747 return 100;
748 }
749 }
750 case ITEM_CLASS_QUEST: return 1000;
751 case ITEM_CLASS_KEY: return 3000;
752 default:
753 return 500;
754 }
755}
756
758{
759 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, std::max(al, 100000u));
760 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_HORDE_ITEM_AMOUNT_RATIO, std::max(ho, 100000u));
761 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, std::max(ne, 100000u));
762
763 for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
765}
766
768{
769 val = std::max(val, 10000u); // apply same upper limit as used for config load
770
771 switch (house)
772 {
775 default: sAuctionBotConfig->SetConfig(CONFIG_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, val); break;
776 }
777
779}
780
794
796{
797 switch (quality)
798 {
800 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_GRAY_AMOUNT, val); break;
806 sAuctionBotConfig->SetConfig(CONFIG_AHBOT_ITEM_BLUE_AMOUNT, val); break;
811 default:
813 }
814
815 for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
817}
818
819// Add new auction to one of the factions.
820// Faction and setting associated is defined passed argument ( config )
822{
823 uint32 count = 0;
824 uint32 items = 0;
825
826 // If there is large amount of items missed we can use boost value to get fast filled AH
827 if (config.LastMissedItem > sAuctionBotConfig->GetItemPerCycleBoost())
828 {
829 items = sAuctionBotConfig->GetItemPerCycleBoost();
830 TC_LOG_DEBUG("ahbot", "AHBot: Boost value used to fill AH! (if this happens often adjust both ItemsPerCycle in worldserver.conf)");
831 }
832 else
833 items = sAuctionBotConfig->GetItemPerCycleNormal();
834
835 uint32 houseid = 0;
836 switch (config.GetHouseType())
837 {
839 houseid = AUCTIONHOUSE_ALLIANCE;
840 break;
842 houseid = AUCTIONHOUSE_HORDE;
843 break;
844 default:
845 houseid = AUCTIONHOUSE_NEUTRAL;
846 break;
847 }
848
849 AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(houseid);
850
851 AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType());
852
853 ItemsToSellArray itemsToSell;
854 AllItemsArray allItems(MAX_AUCTION_QUALITY, std::vector<uint32>(MAX_ITEM_CLASS));
855 // Main loop
856 // getRandomArray will give what categories of items should be added (return true if there is at least 1 items missed)
857 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
858 while (GetItemsToSell(config, itemsToSell, allItems) && items > 0)
859 {
860 --items;
861
862 // Select random position from missed items table
864
865 // Set itemId with random item ID for selected categories and color, from _itemPool table
867 ++allItems[sellItem.Color][sellItem.Itemclass]; // Helper table to avoid rescan from DB in this loop. (has we add item in random orders)
868
869 if (!itemId)
870 {
871 TC_LOG_DEBUG("ahbot", "AHBot: Item entry 0 auction creating attempt.");
872 continue;
873 }
874
875 ItemTemplate const* prototype = sObjectMgr->GetItemTemplate(itemId);
876 if (!prototype)
877 {
878 TC_LOG_DEBUG("ahbot", "AHBot: Unknown item {} auction creating attempt.", itemId);
879 continue;
880 }
881
882 uint32 stackCount = GetStackSizeForItem(prototype, config);
883
884 Item* item = Item::CreateItem(itemId, stackCount);
885 if (!item)
886 {
887 TC_LOG_ERROR("ahbot", "AHBot: Item::CreateItem() returned NULL for item {} (stack: {})", itemId, stackCount);
888 return;
889 }
890
891 // Update the just created item so that if it needs random properties it has them.
892 // Ex: Notched Shortsword of Stamina will only generate as a Notched Shortsword without this.
893 if (int32 randomPropertyId = GenerateItemRandomPropertyId(itemId))
894 item->SetItemRandomProperties(randomPropertyId);
895
896 uint32 buyoutPrice;
897 uint32 bidPrice = 0;
898
899 // Price of items are set here
900 SetPricesOfItem(prototype, config, buyoutPrice, bidPrice, stackCount);
901
902 // Deposit time
903 uint32 etime = urand(1, 3);
904 switch (etime)
905 {
906 case 1:
907 etime = DAY / 2;
908 break;
909 case 3:
910 etime = 2 *DAY;
911 break;
912 case 2:
913 default:
914 etime = DAY;
915 break;
916 }
917
918 AuctionEntry* auctionEntry = new AuctionEntry();
919 auctionEntry->Id = sObjectMgr->GenerateAuctionID();
920 auctionEntry->owner = sAuctionBotConfig->GetRandChar();
921 auctionEntry->itemGUIDLow = item->GetGUID().GetCounter();
922 auctionEntry->itemEntry = item->GetEntry();
923 auctionEntry->startbid = bidPrice;
924 auctionEntry->buyout = buyoutPrice;
925 auctionEntry->houseId = houseid;
926 auctionEntry->bidder = 0;
927 auctionEntry->bid = 0;
928 auctionEntry->deposit = sAuctionMgr->GetAuctionDeposit(ahEntry, etime, item, stackCount);
929 auctionEntry->auctionHouseEntry = ahEntry;
930 auctionEntry->expire_time = GameTime::GetGameTime() + urand(config.GetMinTime(), config.GetMaxTime()) * HOUR;
931 auctionEntry->Flags = AUCTION_ENTRY_FLAG_NONE;
932
933 item->SaveToDB(trans);
934 sAuctionMgr->AddAItem(item);
935 auctionHouse->AddAuction(auctionEntry);
936 auctionEntry->SaveToDB(trans);
937
938 auctionHouse->AddAuction(auctionEntry);
939
940 ++count;
941 }
942 CharacterDatabase.CommitTransaction(trans);
943
944 TC_LOG_DEBUG("ahbot", "AHBot: Added {} items to auction", count);
945}
946
948{
949 if (sAuctionBotConfig->GetConfigItemAmountRatio(houseType) > 0)
950 {
951 TC_LOG_DEBUG("ahbot", "AHBot: {} selling ...", AuctionBotConfig::GetHouseTypeName(houseType));
952 if (SetStat(_houseConfig[houseType]))
953 AddNewAuctions(_houseConfig[houseType]);
954 return true;
955 }
956 else
957 return false;
958}
std::vector< std::vector< uint32 > > AllItemsArray
std::vector< ItemToSell > ItemsToSellArray
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
@ AUCTION_ENTRY_FLAG_NONE
@ AUCTIONHOUSE_HORDE
@ AUCTIONHOUSE_ALLIANCE
@ AUCTIONHOUSE_NEUTRAL
#define sAuctionMgr
@ HOUR
Definition Common.h:30
@ DAY
Definition Common.h:31
DBCStorage< ItemEntry > sItemStore(Itemfmt)
DBCStorage< AuctionHouseEntry > sAuctionHouseStore(AuctionHouseEntryfmt)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
#define ASSERT
Definition Errors.h:68
int32 GenerateItemRandomPropertyId(uint32 item_id)
ItemClass
@ ITEM_CLASS_QUIVER
@ ITEM_CLASS_GENERIC
@ ITEM_CLASS_RECIPE
@ ITEM_CLASS_KEY
@ ITEM_CLASS_CONTAINER
@ ITEM_CLASS_TRADE_GOODS
@ ITEM_CLASS_REAGENT
@ ITEM_CLASS_MONEY
@ ITEM_CLASS_PERMANENT
@ ITEM_CLASS_GLYPH
@ ITEM_CLASS_PROJECTILE
@ ITEM_CLASS_GEM
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_QUEST
@ ITEM_CLASS_MISCELLANEOUS
@ ITEM_CLASS_WEAPON
@ ITEM_CLASS_CONSUMABLE
@ ITEM_SUBCLASS_WEAPON_AXE2
@ ITEM_SUBCLASS_WEAPON_STAFF
@ ITEM_SUBCLASS_WEAPON_MACE
@ ITEM_SUBCLASS_WEAPON_MACE2
@ ITEM_SUBCLASS_WEAPON_DAGGER
@ ITEM_SUBCLASS_WEAPON_SWORD
@ ITEM_SUBCLASS_WEAPON_AXE
@ ITEM_SUBCLASS_WEAPON_FIST_WEAPON
@ ITEM_SUBCLASS_WEAPON_THROWN
@ ITEM_SUBCLASS_WEAPON_SWORD2
@ ITEM_SUBCLASS_WEAPON_POLEARM
@ ITEM_FLAG_HAS_LOOT
#define MAX_ITEM_CLASS
@ ITEM_SUBCLASS_ARMOR_MAIL
@ ITEM_SUBCLASS_ARMOR_CLOTH
@ ITEM_SUBCLASS_ARMOR_LEATHER
@ ITEM_SUBCLASS_ARMOR_SHIELD
@ ITEM_SUBCLASS_ARMOR_PLATE
@ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS
@ ITEM_SUBCLASS_PARTS
@ ITEM_SUBCLASS_ENCHANTING
@ ITEM_SUBCLASS_TRADE_GOODS
@ ITEM_SUBCLASS_EXPLOSIVES
@ ITEM_SUBCLASS_TRADE_GOODS_OTHER
@ ITEM_SUBCLASS_DEVICES
@ ITEM_SUBCLASS_MEAT
@ ITEM_SUBCLASS_ELEMENTAL
@ BIND_WHEN_EQUIPED
@ BIND_WHEN_USE
@ NO_BIND
@ BIND_QUEST_ITEM
@ BIND_WHEN_PICKED_UP
@ ITEM_SUBCLASS_JUNK_MOUNT
@ ITEM_SUBCLASS_SCROLL
@ ITEM_SUBCLASS_FLASK
@ ITEM_SUBCLASS_CONSUMABLE
@ ITEM_SUBCLASS_BANDAGE
@ ITEM_SUBCLASS_ITEM_ENHANCEMENT
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define sObjectMgr
Definition ObjectMgr.h:1721
std::unordered_map< uint32, CreatureTemplate > CreatureTemplateContainer
Definition ObjectMgr.h:535
float frand(float min, float max)
Definition Random.cpp:55
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
static char const * GetHouseTypeName(AuctionHouseType houseType)
void SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
void SetPricesOfItem(ItemTemplate const *itemProto, SellerConfiguration &config, uint32 &buyp, uint32 &bidp, uint32 stackcnt)
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 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)
AuctionEntryMap::iterator GetAuctionsEnd()
void AddAuction(AuctionEntry *auction)
AuctionEntryMap::iterator GetAuctionsBegin()
Class used to access individual fields of database query result.
Definition Field.h:92
uint32 GetUInt32() const
Definition Field.cpp:61
Definition Item.h:62
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:323
static Item * CreateItem(uint32 itemEntry, uint32 count, Player const *player=nullptr)
Definition Item.cpp:1044
void SetItemRandomProperties(int32 randomPropId)
Definition Item.cpp:592
ItemTemplate const * GetTemplate() const
Definition Item.cpp:535
LowType GetCounter() const
Definition ObjectGuid.h:156
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
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)
time_t GetGameTime()
Definition GameTime.cpp:42
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
ObjectGuid::LowType bidder
AuctionHouseEntry const * auctionHouseEntry
void SaveToDB(CharacterDatabaseTransaction trans) const
ObjectGuid::LowType owner
ObjectGuid::LowType itemGUIDLow
AuctionEntryFlag Flags
uint32 RequiredSkillRank
uint32 GetMaxStackSize() const
uint32 RequiredLevel
bool HasFlag(ItemFlags flag) const