mangos/src/game/AuctionHouseBot/AuctionHouseBot.cpp
2020-01-07 22:35:20 +00:00

1944 lines
87 KiB
C++

/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2020 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "AuctionHouseBot.h"
#include "ProgressBar.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "AuctionHouseMgr.h"
#include "SystemConfig.h"
#include "SQLStorages.h"
#include "World.h"
/** \addtogroup auctionbot
* @{
* \file
*/
#include "Policies/Singleton.h"
struct BuyerAuctionEval
{
BuyerAuctionEval() : AuctionId(0), LastChecked(0), LastExist(0) {}
uint32 AuctionId;
time_t LastChecked;
time_t LastExist;
};
struct BuyerItemInfo
{
BuyerItemInfo() : ItemCount(0), BuyPrice(0), BidPrice(0), MinBuyPrice(0), MinBidPrice(0) {}
uint32 ItemCount;
double BuyPrice;
double BidPrice;
uint32 MinBuyPrice;
uint32 MinBidPrice;
};
typedef std::map<uint32, BuyerItemInfo > BuyerItemInfoMap;
typedef std::map<uint32, BuyerAuctionEval > CheckEntryMap;
struct AHB_Buyer_Config
{
public:
AHB_Buyer_Config() : m_houseType(AUCTION_HOUSE_NEUTRAL) {}
void Initialize(AuctionHouseType houseType)
{
m_houseType = houseType;
}
AuctionHouseType GetHouseType() const { return m_houseType; }
public:
BuyerItemInfoMap SameItemInfo;
CheckEntryMap CheckedEntry;
uint32 FactionChance;
bool BuyerEnabled;
uint32 BuyerPriceRatio;
private:
AuctionHouseType m_houseType;
};
struct RandomArrayEntry
{
uint32 color;
uint32 itemclass;
};
typedef std::vector<RandomArrayEntry> RandomArray;
struct SellerItemClassInfo
{
SellerItemClassInfo() : AmountOfItems(0), MissItems(0), Quantity(0) {}
uint32 AmountOfItems;
uint32 MissItems;
uint32 Quantity;
};
struct SellerItemInfo
{
SellerItemInfo() : AmountOfItems(0), MissItems(0), PriceRatio(0) {}
uint32 AmountOfItems;
uint32 MissItems;
uint32 PriceRatio;
SellerItemClassInfo ItemClassInfos[MAX_ITEM_CLASS];
};
class AHB_Seller_Config
{
public:
AHB_Seller_Config() : m_houseType(AUCTION_HOUSE_NEUTRAL)
{
}
~AHB_Seller_Config() {}
void Initialize(AuctionHouseType houseType)
{
m_houseType = houseType;
}
AuctionHouseType GetHouseType() const { return m_houseType; }
uint32 LastMissedItem;
void SetMinTime(uint32 value)
{
m_minTime = value;
}
uint32 GetMinTime() const
{
if (m_minTime < 1)
{ return 1; }
else if ((m_maxTime) && (m_minTime > m_maxTime))
{ return m_maxTime; }
else
{ return m_minTime; }
}
void SetMaxTime(uint32 value) { m_maxTime = value; }
uint32 GetMaxTime() const { return m_maxTime; }
// Data access classified by item class and item quality //
void SetItemsAmountPerClass(AuctionQuality quality, ItemClass itemclass, uint32 amount) { m_ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems = amount * m_ItemInfo[quality].ItemClassInfos[itemclass].Quantity; }
uint32 GetItemsAmountPerClass(AuctionQuality quality, ItemClass itemclass) const { return m_ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems; }
void SetItemsQuantityPerClass(AuctionQuality quality, ItemClass itemclass, uint32 qty) { m_ItemInfo[quality].ItemClassInfos[itemclass].Quantity = qty; }
uint32 GetItemsQuantityPerClass(AuctionQuality quality, ItemClass itemclass) const { return m_ItemInfo[quality].ItemClassInfos[itemclass].Quantity; }
void SetMissedItemsPerClass(AuctionQuality quality, ItemClass itemclass, uint32 found)
{
if (m_ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems > found)
{ m_ItemInfo[quality].ItemClassInfos[itemclass].MissItems = m_ItemInfo[quality].ItemClassInfos[itemclass].AmountOfItems - found; }
else
{ m_ItemInfo[quality].ItemClassInfos[itemclass].MissItems = 0; }
}
uint32 GetMissedItemsPerClass(AuctionQuality quality, ItemClass itemclass) const { return m_ItemInfo[quality].ItemClassInfos[itemclass].MissItems; }
// Data for every quality of item //
void SetItemsAmountPerQuality(AuctionQuality quality, uint32 cnt) { m_ItemInfo[quality].AmountOfItems = cnt; }
uint32 GetItemsAmountPerQuality(AuctionQuality quality) const { return m_ItemInfo[quality].AmountOfItems; }
void SetPriceRatioPerQuality(AuctionQuality quality, uint32 value) { m_ItemInfo[quality].PriceRatio = value; }
uint32 GetPriceRatioPerQuality(AuctionQuality quality) const { return m_ItemInfo[quality].PriceRatio; }
private:
AuctionHouseType m_houseType;
uint32 m_minTime;
uint32 m_maxTime;
SellerItemInfo m_ItemInfo[MAX_AUCTION_QUALITY];
};
/**
* This class handle all Buyer method
* (holder of AuctionBotConfig for each auction house type)
* (Taken from comments in file)
* \todo Perhaps a better description of the class?
*/
class AuctionBotBuyer : public AuctionBotAgent
{
public:
AuctionBotBuyer();
~AuctionBotBuyer();
bool Initialize() override;
/**
* Updates the specified house type. Will buy items if there are any that match certain
* criteria.
* @param houseType Type of the house.
* @return true if the update was successful, false otherwise
*/
bool Update(AuctionHouseType houseType) override;
void LoadConfig();
/**
* Adds the new auction buyer bot bid.
* @param config The config.
*/
void addNewAuctionBuyerBotBid(AHB_Buyer_Config& config);
private:
uint32 m_CheckInterval;
AHB_Buyer_Config m_HouseConfig[MAX_AUCTION_HOUSE_TYPE];
/**
* Loads the buyer values.
* @param config The config.
*/
void LoadBuyerValues(AHB_Buyer_Config& config);
/**
* Determines whether [is buyable entry] [the specified buyout price].
*
* @param buyoutPrice The buyout price.
* @param InGame_BuyPrice The in game_ buy price.
* @param MaxBuyablePrice The max buyable price.
* @param MinBuyPrice The min buy price.
* @param MaxChance The max chance.
* @param ChanceRatio The chance ratio.
* @return true if the entry is buyable, false otherwise
*/
bool IsBuyableEntry(uint32 buyoutPrice, double InGame_BuyPrice, double MaxBuyablePrice, uint32 MinBuyPrice, uint32 MaxChance, uint32 ChanceRatio);
/**
* Determines whether [is bidable entry] [the specified bid price].
*
* @param bidPrice The bid price.
* @param InGame_BuyPrice The in game_ buy price.
* @param MaxBidablePrice The max bidable price.
* @param MinBidPrice The min bid price.
* @param MaxChance The max chance.
* @param ChanceRatio The chance ratio.
* @return true if the bot can bid on this entry, false otherwise
*/
bool IsBidableEntry(uint32 bidPrice, double InGame_BuyPrice, double MaxBidablePrice, uint32 MinBidPrice, uint32 MaxChance, uint32 ChanceRatio);
/**
* Places the bid to entry.
*
* @param auction The auction.
* @param bidPrice The bid price.
*/
void PlaceBidToEntry(AuctionEntry* auction, uint32 bidPrice);
/**
* Buys the entry.
*
* @param auction The auction.
*/
void BuyEntry(AuctionEntry* auction);
/**
* Prepares the list of entry.
*
* @param config The config.
*/
void PrepareListOfEntry(AHB_Buyer_Config& config);
/**
* Gets the buyable entry.
*
* @param config The config.
* <returns></returns
*/
uint32 GetBuyableEntry(AHB_Buyer_Config& config);
};
/**
* This class handle all Selling method
* (holder of AHB_Seller_Config data for each auction house type)
* (Taken from comments in file)
* \todo Maybe improve the description of this class
*/
class AuctionBotSeller : public AuctionBotAgent
{
public:
typedef std::vector<uint32> ItemPool;
/**
* Initializes a new instance of the \ref AuctionBotSeller class.
*/
AuctionBotSeller();
/**
* Finalizes an instance of the \ref AuctionBotSeller class.
*/
~AuctionBotSeller();
/**
* Initializes this instance.
*/
bool Initialize() override;
/**
* Updates the specified house type by possibly putting up new items for
* sale if there's a need for it.
* @param houseType Type of the house.
*/
bool Update(AuctionHouseType houseType) override;
/**
* Add new auction to one of the factions.
* Faction and setting associated is passed with the config
* @param config The config to use for adding the auctions
*/
void addNewAuctions(AHB_Seller_Config& config);
/**
* Sets the items ratio. This should be a value betweeen 0 and 10000 which
* probably represents 0-100%
* @param al The alliance item amount/ratio
* @param ho The horde item amount/ratio
* @param ne The neutral item amount/ratio
*/
void SetItemsRatio(uint32 al, uint32 ho, uint32 ne);
/**
* Sets the items ratio for a specific house. Works as \ref AuctionBotSeller::SetItemsRatio
* but only changes the value for one house instead.
* @param house The house to change the ratio for
* @param val The new ratio
*/
void SetItemsRatioForHouse(AuctionHouseType house, uint32 val);
/**
* Changes how many items of each item quality should be available.
* @param vals Array of size \ref MAX_AUCTION_QUALITY telling the amount of each item to be available on the AH.
* @see AuctionQuality
*/
void SetItemsAmount(uint32(&vals) [MAX_AUCTION_QUALITY]);
/**
* Changes how many items of a certain quality should be available. Works as
* \ref AuctionBotSeller::SetItemsAmount but for one of the qualities instead
* of all.
* @param quality The quality to change
* @param val How many of this item quality that should be available on AH
*/
void SetItemsAmountForQuality(AuctionQuality quality, uint32 val);
/**
* Loads the config.
*/
void LoadConfig();
private:
AHB_Seller_Config m_HouseConfig[MAX_AUCTION_HOUSE_TYPE];
ItemPool m_ItemPool[MAX_AUCTION_QUALITY][MAX_ITEM_CLASS];
/**
* Loads the seller values
* @param config The config.
*/
void LoadSellerValues(AHB_Seller_Config& config);
/**
* Set static of items on one AH faction.
* Fill ItemInfos object with real content of AH.
*
* @param config The config.
* @return
*/
uint32 SetStat(AHB_Seller_Config& config);
/**
* getRandomArray is used to make available the possibility to
* add any of missed item in place of first one to last one.
*
* @param config The config.
* @param ra The ra.
* @param addedItem The added item.
*/
bool getRandomArray(AHB_Seller_Config& config, RandomArray& ra, const std::vector<std::vector<uint32> >& addedItem);
/**
* Set items price. All important value are passed by address.
*
* @param itemProto The item proto.
* @param config The config.
* @param buyp The buyp.
* @param bidp The bidp.
* @param stackcnt The stackcnt.
* @param itemQuality The item quality.
*/
void SetPricesOfItem(AHB_Seller_Config& config, uint32& buyp, uint32& bidp, uint32 stackcnt, ItemQualities itemQuality);
/**
* Loads the items quantity.
*
* @param config The config.
*/
void LoadItemsQuantity(AHB_Seller_Config& config);
};
INSTANTIATE_SINGLETON_1(AuctionHouseBot);
INSTANTIATE_SINGLETON_1(AuctionBotConfig);
//== AuctionBotConfig functions ============================
AuctionBotConfig::AuctionBotConfig() : m_configFileName(AUCTIONHOUSEBOT_CONFIG_LOCATION),
m_configUint32Values(), m_configBoolValues()
{
}
bool AuctionBotConfig::Initialize()
{
if (!m_AhBotCfg.SetSource(m_configFileName.c_str()))
{
sLog.outString("AHBOT is Disabled. Unable to open configuration file %s. ", m_configFileName.c_str());
setConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, 0);
setConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO, 0);
setConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, 0);
return false;
}
else
{ sLog.outString("AHBot using configuration file %s", m_configFileName.c_str()); }
GetConfigFromFile();
if (!getConfig(CONFIG_BOOL_AHBOT_BUYER_ENABLED) && !getConfig(CONFIG_BOOL_AHBOT_SELLER_ENABLED))
{
sLog.outString("AHBOT is Disabled. (If you want to use it please set config in 'ahbot.conf')");
return false;
}
if ((getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) == 0) && (getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO) == 0) && (getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO) == 0) &&
!getConfig(CONFIG_BOOL_AHBOT_BUYER_ALLIANCE_ENABLED) && !getConfig(CONFIG_BOOL_AHBOT_BUYER_HORDE_ENABLED) && !getConfig(CONFIG_BOOL_AHBOT_BUYER_NEUTRAL_ENABLED))
{
sLog.outString("All feature of AuctionHouseBot are disabled! (If you want to use it please set config in 'ahbot.conf')");
return false;
}
if ((getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO) == 0) && (getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO) == 0) && (getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO) == 0))
{ sLog.outString("AuctionHouseBot SELLER is disabled! (If you want to use it please set config in 'ahbot.conf')"); }
if (!getConfig(CONFIG_BOOL_AHBOT_BUYER_ALLIANCE_ENABLED) && !getConfig(CONFIG_BOOL_AHBOT_BUYER_HORDE_ENABLED) && !getConfig(CONFIG_BOOL_AHBOT_BUYER_NEUTRAL_ENABLED))
{ sLog.outString("AuctionHouseBot BUYER is disabled! (If you want to use it please set config in 'ahbot.conf')"); }
m_ItemsPerCycleBoost = getConfig(CONFIG_UINT32_AHBOT_ITEMS_PER_CYCLE_BOOST);
m_ItemsPerCycleNormal = getConfig(CONFIG_UINT32_AHBOT_ITEMS_PER_CYCLE_NORMAL);
return true;
}
void AuctionBotConfig::SetAHBotId(const std::string& BotCharName)
{
m_BotId = 0;
if (!BotCharName.empty())
{
m_BotId = sObjectMgr.GetPlayerGuidByName(BotCharName.c_str()).GetCounter();
if (!m_BotId)
{ sLog.outError("AHBot uses an invalid character name `%s`", BotCharName.c_str()); }
}
}
void AuctionBotConfig::setConfig(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue)
{
setConfig(index, m_AhBotCfg.GetIntDefault(fieldname, defvalue));
if (int32(getConfig(index)) < 0)
{
sLog.outError("AHBot: %s (%i) can't be negative. Using %u instead.", fieldname, int32(getConfig(index)), defvalue);
setConfig(index, defvalue);
}
}
void AuctionBotConfig::setConfigMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 maxvalue)
{
setConfig(index, m_AhBotCfg.GetIntDefault(fieldname, defvalue));
if (getConfig(index) > maxvalue)
{
sLog.outError("AHBot: %s (%u) must be in range 0...%u. Using %u instead.", fieldname, getConfig(index), maxvalue, maxvalue);
setConfig(index, maxvalue);
}
}
void AuctionBotConfig::setConfigMinMax(AuctionBotConfigUInt32Values index, char const* fieldname, uint32 defvalue, uint32 minvalue, uint32 maxvalue)
{
setConfig(index, m_AhBotCfg.GetIntDefault(fieldname, defvalue));
if (getConfig(index) > maxvalue)
{
sLog.outError("AHBot: %s (%u) must be in range %u...%u. Using %u instead.", fieldname, getConfig(index), minvalue, maxvalue, maxvalue);
setConfig(index, maxvalue);
}
if (getConfig(index) < minvalue)
{
sLog.outError("AHBot: %s (%u) must be in range %u...%u. Using %u instead.", fieldname, getConfig(index), minvalue, maxvalue, minvalue);
setConfig(index, minvalue);
}
}
void AuctionBotConfig::setConfig(AuctionBotConfigBoolValues index, char const* fieldname, bool defvalue)
{
setConfig(index, m_AhBotCfg.GetBoolDefault(fieldname, defvalue));
}
// Get AuctionHousebot configuration file
void AuctionBotConfig::GetConfigFromFile()
{
// Check config file version
if (m_AhBotCfg.GetIntDefault("ConfVersion", 0) != AHBOT_CONFIG_VERSION)
{ sLog.outError("AHBot: Configuration file version doesn't match expected version. Some config variables may be wrong or missing."); }
setConfigMax(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO , "AuctionHouseBot.Alliance.Items.Amount.Ratio" , 100, 10000);
setConfigMax(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO , "AuctionHouseBot.Horde.Items.Amount.Ratio" , 100, 10000);
setConfigMax(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO , "AuctionHouseBot.Neutral.Items.Amount.Ratio" , 100, 10000);
SetAHBotIncludes(m_AhBotCfg.GetStringDefault("AuctionHouseBot.forceIncludeItems", ""));
SetAHBotExcludes(m_AhBotCfg.GetStringDefault("AuctionHouseBot.forceExcludeItems", ""));
SetAHBotId(m_AhBotCfg.GetStringDefault("AuctionHouseBot.CharacterName", ""));
setConfig(CONFIG_BOOL_AHBOT_BUYER_ALLIANCE_ENABLED , "AuctionHouseBot.Buyer.Alliance.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_BUYER_HORDE_ENABLED , "AuctionHouseBot.Buyer.Horde.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_BUYER_NEUTRAL_ENABLED , "AuctionHouseBot.Buyer.Neutral.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_ITEMS_VENDOR , "AuctionHouseBot.Items.Vendor" , false);
setConfig(CONFIG_BOOL_AHBOT_ITEMS_LOOT , "AuctionHouseBot.Items.Loot" , true);
setConfig(CONFIG_BOOL_AHBOT_ITEMS_MISC , "AuctionHouseBot.Items.Misc" , false);
setConfig(CONFIG_BOOL_AHBOT_BIND_NO , "AuctionHouseBot.Bind.No" , true);
setConfig(CONFIG_BOOL_AHBOT_BIND_PICKUP , "AuctionHouseBot.Bind.Pickup" , false);
setConfig(CONFIG_BOOL_AHBOT_BIND_EQUIP , "AuctionHouseBot.Bind.Equip" , true);
setConfig(CONFIG_BOOL_AHBOT_BIND_USE , "AuctionHouseBot.Bind.Use" , true);
setConfig(CONFIG_BOOL_AHBOT_BIND_QUEST , "AuctionHouseBot.Bind.Quest" , false);
setConfig(CONFIG_BOOL_AHBOT_LOCKBOX_ENABLED , "AuctionHouseBot.LockBox.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_BUYPRICE_SELLER , "AuctionHouseBot.BuyPrice.Seller" , true);
setConfig(CONFIG_UINT32_AHBOT_ITEMS_PER_CYCLE_BOOST , "AuctionHouseBot.ItemsPerCycle.Boost" , 75);
setConfig(CONFIG_UINT32_AHBOT_ITEMS_PER_CYCLE_NORMAL , "AuctionHouseBot.ItemsPerCycle.Normal" , 20);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_ITEM_LEVEL , "AuctionHouseBot.Items.ItemLevel.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_ITEM_LEVEL , "AuctionHouseBot.Items.ItemLevel.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_REQ_LEVEL , "AuctionHouseBot.Items.ReqLevel.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_REQ_LEVEL , "AuctionHouseBot.Items.ReqLevel.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_SKILL_RANK , "AuctionHouseBot.Items.ReqSkill.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_SKILL_RANK , "AuctionHouseBot.Items.ReqSkill.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_GREY_AMOUNT , "AuctionHouseBot.Items.Amount.Grey" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_WHITE_AMOUNT , "AuctionHouseBot.Items.Amount.White" , 2000);
setConfig(CONFIG_UINT32_AHBOT_ITEM_GREEN_AMOUNT , "AuctionHouseBot.Items.Amount.Green" , 2500);
setConfig(CONFIG_UINT32_AHBOT_ITEM_BLUE_AMOUNT , "AuctionHouseBot.Items.Amount.Blue" , 1500);
setConfig(CONFIG_UINT32_AHBOT_ITEM_PURPLE_AMOUNT , "AuctionHouseBot.Items.Amount.Purple" , 500);
setConfig(CONFIG_UINT32_AHBOT_ITEM_ORANGE_AMOUNT , "AuctionHouseBot.Items.Amount.Orange" , 0);
setConfig(CONFIG_UINT32_AHBOT_ITEM_YELLOW_AMOUNT , "AuctionHouseBot.Items.Amount.Yellow" , 0);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT , "AuctionHouseBot.Class.Consumable" , 6, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT , "AuctionHouseBot.Class.Container" , 4, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT , "AuctionHouseBot.Class.Weapon" , 8, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT , "AuctionHouseBot.Class.Armor" , 8, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_REAGENT_AMOUNT , "AuctionHouseBot.Class.Reagent" , 1, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT , "AuctionHouseBot.Class.Projectile" , 2, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT , "AuctionHouseBot.Class.TradeGood" , 10, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT , "AuctionHouseBot.Class.Recipe" , 6, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_QUIVER_AMOUNT , "AuctionHouseBot.Class.Quiver" , 1, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT , "AuctionHouseBot.Class.Quest" , 1, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_KEY_AMOUNT , "AuctionHouseBot.Class.Key" , 1, 10);
setConfigMax(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT , "AuctionHouseBot.Class.Misc" , 5, 10);
setConfig(CONFIG_UINT32_AHBOT_ALLIANCE_PRICE_RATIO , "AuctionHouseBot.Alliance.Price.Ratio" , 200);
setConfig(CONFIG_UINT32_AHBOT_HORDE_PRICE_RATIO , "AuctionHouseBot.Horde.Price.Ratio" , 200);
setConfig(CONFIG_UINT32_AHBOT_NEUTRAL_PRICE_RATIO , "AuctionHouseBot.Neutral.Price.Ratio" , 200);
setConfig(CONFIG_UINT32_AHBOT_MINTIME , "AuctionHouseBot.MinTime" , 1);
setConfig(CONFIG_UINT32_AHBOT_MAXTIME , "AuctionHouseBot.MaxTime" , 72);
setConfigMinMax(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_ALLIANCE, "AuctionHouseBot.Buyer.Alliance.Chance.Ratio", 3, 1, 100);
setConfigMinMax(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_HORDE , "AuctionHouseBot.Buyer.Horde.Chance.Ratio" , 3, 1, 100);
setConfigMinMax(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_NEUTRAL , "AuctionHouseBot.Buyer.Neutral.Chance.Ratio" , 3, 1, 100);
setConfigMinMax(CONFIG_UINT32_AHBOT_BUYER_RECHECK_INTERVAL , "AuctionHouseBot.Buyer.Recheck.Interval" , 20, 1, DAY / MINUTE);
setConfig(CONFIG_BOOL_AHBOT_DEBUG_SELLER , "AuctionHouseBot.DEBUG.Seller" , false);
setConfig(CONFIG_BOOL_AHBOT_DEBUG_BUYER , "AuctionHouseBot.DEBUG.Buyer" , false);
setConfig(CONFIG_BOOL_AHBOT_SELLER_ENABLED , "AuctionHouseBot.Seller.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_BUYER_ENABLED , "AuctionHouseBot.Buyer.Enabled" , false);
setConfig(CONFIG_BOOL_AHBOT_BUYPRICE_BUYER , "AuctionHouseBot.Buyer.BuyPrice" , false);
setConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL , "AuctionHouseBot.Class.Misc.Mount.ReqLevel.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL , "AuctionHouseBot.Class.Misc.Mount.ReqLevel.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK , "AuctionHouseBot.Class.Misc.Mount.ReqSkill.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK , "AuctionHouseBot.Class.Misc.Mount.ReqSkill.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL , "AuctionHouseBot.Class.TradeGood.ItemLevel.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL , "AuctionHouseBot.Class.TradeGood.ItemLevel.Max" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL , "AuctionHouseBot.Class.Container.ItemLevel.Min" , 0);
setConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL , "AuctionHouseBot.Class.Container.ItemLevel.Max" , 0);
}
bool AuctionBotConfig::Reload()
{
if (m_AhBotCfg.Reload())
{
GetConfigFromFile();
return true;
}
return false;
}
char const* AuctionBotConfig::GetItemClassName(ItemClass itemclass)
{
ItemClassEntry const* itemClassEntry = sItemClassStore.LookupEntry(itemclass);
return itemClassEntry ? itemClassEntry->name[sWorld.GetDefaultDbcLocale()] : "";
}
char const* AuctionBotConfig::GetHouseTypeName(AuctionHouseType houseType)
{
char const* names[MAX_AUCTION_HOUSE_TYPE] = { "Alliance", "Horde", "Neutral" };
return names[houseType];
}
uint32 AuctionBotConfig::getConfigItemAmountRatio(AuctionHouseType houseType) const
{
switch (houseType)
{
case AUCTION_HOUSE_ALLIANCE: return getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO);
case AUCTION_HOUSE_HORDE: return getConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO);
default: return getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO);
}
}
bool AuctionBotConfig::getConfigBuyerEnabled(AuctionHouseType houseType) const
{
switch (houseType)
{
case AUCTION_HOUSE_ALLIANCE: return getConfig(CONFIG_BOOL_AHBOT_BUYER_ALLIANCE_ENABLED);
case AUCTION_HOUSE_HORDE: return getConfig(CONFIG_BOOL_AHBOT_BUYER_HORDE_ENABLED);
default: return getConfig(CONFIG_BOOL_AHBOT_BUYER_NEUTRAL_ENABLED);
}
}
uint32 AuctionBotConfig::getConfigItemQualityAmount(AuctionQuality quality) const
{
switch (quality)
{
case AUCTION_QUALITY_GREY: return getConfig(CONFIG_UINT32_AHBOT_ITEM_GREY_AMOUNT);
case AUCTION_QUALITY_WHITE: return getConfig(CONFIG_UINT32_AHBOT_ITEM_WHITE_AMOUNT);
case AUCTION_QUALITY_GREEN: return getConfig(CONFIG_UINT32_AHBOT_ITEM_GREEN_AMOUNT);
case AUCTION_QUALITY_BLUE: return getConfig(CONFIG_UINT32_AHBOT_ITEM_BLUE_AMOUNT);
case AUCTION_QUALITY_PURPLE: return getConfig(CONFIG_UINT32_AHBOT_ITEM_PURPLE_AMOUNT);
case AUCTION_QUALITY_ORANGE: return getConfig(CONFIG_UINT32_AHBOT_ITEM_ORANGE_AMOUNT);
default: return getConfig(CONFIG_UINT32_AHBOT_ITEM_YELLOW_AMOUNT);
}
}
//== AuctionBotBuyer functions =============================
AuctionBotBuyer::AuctionBotBuyer()
{
// Define faction for our main data class.
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{ m_HouseConfig[i].Initialize(AuctionHouseType(i)); }
}
AuctionBotBuyer::~AuctionBotBuyer()
{
}
bool AuctionBotBuyer::Initialize()
{
LoadConfig();
bool active_house = false;
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{
if (m_HouseConfig[i].BuyerEnabled)
{
active_house = true;
break;
}
}
if (!active_house)
{ return false; }
// load Check interval
m_CheckInterval = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_BUYER_RECHECK_INTERVAL) * MINUTE;
DETAIL_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot buyer interval between 2 check = %u", m_CheckInterval);
sLog.SetLogFilter(LOG_FILTER_AHBOT_BUYER, !sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_DEBUG_BUYER));
return true;
}
void AuctionBotBuyer::LoadBuyerValues(AHB_Buyer_Config& config)
{
uint32 FactionChance;
switch (config.GetHouseType())
{
case AUCTION_HOUSE_ALLIANCE:
config.BuyerPriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_PRICE_RATIO) + 50;
FactionChance = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_ALLIANCE);
break;
case AUCTION_HOUSE_HORDE:
config.BuyerPriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_PRICE_RATIO) + 50;
FactionChance = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_HORDE);
break;
default:
config.BuyerPriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_PRICE_RATIO) + 50;
FactionChance = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_BUYER_CHANCE_RATIO_NEUTRAL);
break;
}
config.FactionChance = 5000 * FactionChance;
}
void AuctionBotBuyer::LoadConfig()
{
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{
m_HouseConfig[i].BuyerEnabled = sAuctionBotConfig.getConfigBuyerEnabled(AuctionHouseType(i));
if (m_HouseConfig[i].BuyerEnabled)
{ LoadBuyerValues(m_HouseConfig[i]); }
}
}
uint32 AuctionBotBuyer::GetBuyableEntry(AHB_Buyer_Config& config)
{
config.SameItemInfo.clear();
uint32 count = 0;
time_t Now = time(NULL);
AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(config.GetHouseType())->GetAuctionsBounds();
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
AuctionEntry* Aentry = itr->second;
Item* item = sAuctionMgr.GetAItem(Aentry->itemGuidLow);
if (item)
{
ItemPrototype const* prototype = item->GetProto();
if (prototype)
{
BuyerItemInfo& buyerItem = config.SameItemInfo[item->GetEntry()]; // Structure constructor will make sure Element are correctly initialised if entry is created here.
++buyerItem.ItemCount;
buyerItem.BuyPrice = buyerItem.BuyPrice + (Aentry->buyout / item->GetCount());
buyerItem.BidPrice = buyerItem.BidPrice + (Aentry->startbid / item->GetCount());
if (Aentry->buyout != 0)
{
if (Aentry->buyout / item->GetCount() < buyerItem.MinBuyPrice)
{ buyerItem.MinBuyPrice = Aentry->buyout / item->GetCount(); }
else if (buyerItem.MinBuyPrice == 0)
{ buyerItem.MinBuyPrice = Aentry->buyout / item->GetCount(); }
}
if (Aentry->startbid / item->GetCount() < buyerItem.MinBidPrice)
{ buyerItem.MinBidPrice = Aentry->startbid / item->GetCount(); }
else if (buyerItem.MinBidPrice == 0)
{ buyerItem.MinBidPrice = Aentry->startbid / item->GetCount(); }
if (Aentry->owner == sAuctionBotConfig.GetAHBotId())
{
if ((Aentry->bid != 0) && Aentry->bidder) // Add bided by player
{
config.CheckedEntry[Aentry->Id].LastExist = Now;
config.CheckedEntry[Aentry->Id].AuctionId = Aentry->Id;
++count;
}
}
else
{
if (Aentry->bid != 0)
{
if (Aentry->bidder)
{
config.CheckedEntry[Aentry->Id].LastExist = Now;
config.CheckedEntry[Aentry->Id].AuctionId = Aentry->Id;
++count;
}
}
else
{
config.CheckedEntry[Aentry->Id].LastExist = Now;
config.CheckedEntry[Aentry->Id].AuctionId = Aentry->Id;
++count;
}
}
}
}
}
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: %u items added to buyable vector for AH type: %u", count, config.GetHouseType());
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: SameItemInfo size = " SIZEFMTD, config.SameItemInfo.size());
return count;
}
void AuctionBotBuyer::PrepareListOfEntry(AHB_Buyer_Config& config)
{
time_t Now = time(NULL) - 5;
for (CheckEntryMap::iterator itr = config.CheckedEntry.begin(); itr != config.CheckedEntry.end();)
{
if (itr->second.LastExist < (Now - 5))
{ config.CheckedEntry.erase(itr++); }
else
{ ++itr; }
}
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: CheckedEntry size = " SIZEFMTD, config.CheckedEntry.size());
}
bool AuctionBotBuyer::IsBuyableEntry(uint32 buyoutPrice, double InGame_BuyPrice, double MaxBuyablePrice, uint32 MinBuyPrice, uint32 MaxChance, uint32 ChanceRatio)
{
uint32 Chance = 0;
if (buyoutPrice <= MinBuyPrice)
{
if (buyoutPrice <= MaxBuyablePrice)
{ Chance = MaxChance; }
else
{
if ((buyoutPrice > 0) && (MaxBuyablePrice > 0))
{
double ratio = buyoutPrice / MaxBuyablePrice;
if (ratio < 10)
{ Chance = MaxChance - (ratio * (MaxChance / 10)); }
else { Chance = 1; }
}
}
}
else if (buyoutPrice <= InGame_BuyPrice)
{
if (buyoutPrice <= MaxBuyablePrice)
{ Chance = MaxChance / 5; }
else
{
if ((buyoutPrice > 0) && (MaxBuyablePrice > 0))
{
double ratio = buyoutPrice / MaxBuyablePrice;
if (ratio < 10)
{ Chance = (MaxChance / 5) - (ratio * (MaxChance / 50)); }
else { Chance = 1; }
}
}
}
else if (buyoutPrice <= MaxBuyablePrice)
{ Chance = MaxChance / 10; }
else
{
if ((buyoutPrice > 0) && (MaxBuyablePrice > 0))
{
double ratio = buyoutPrice / MaxBuyablePrice;
if (ratio < 10)
{ Chance = (MaxChance / 5) - (ratio * (MaxChance / 50)); }
else { Chance = 0; }
}
else { Chance = 0; }
}
uint32 RandNum = urand(1, ChanceRatio);
if (RandNum <= Chance)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: WIN BUY! Chance = %u, num = %u.", Chance, RandNum);
return true;
}
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot:LOOSE BUY! Chance = %u, num = %u.", Chance, RandNum);
return false;
}
bool AuctionBotBuyer::IsBidableEntry(uint32 bidPrice, double InGame_BuyPrice, double MaxBidablePrice, uint32 MinBidPrice, uint32 MaxChance, uint32 ChanceRatio)
{
uint32 Chance = 0;
if (bidPrice <= MinBidPrice)
{
if ((InGame_BuyPrice != 0) && (bidPrice < (InGame_BuyPrice - (InGame_BuyPrice / 30))))
{ Chance = MaxChance; }
else
{
if (bidPrice < MaxBidablePrice)
{
double ratio = MaxBidablePrice / bidPrice;
if (ratio < 3)
{ Chance = ((MaxChance / 500) * ratio); }
else
{ Chance = (MaxChance / 500); }
}
}
}
else if (bidPrice < (InGame_BuyPrice - (InGame_BuyPrice / 30)))
{ Chance = (MaxChance / 10); }
else
{
if (bidPrice < MaxBidablePrice)
{
double ratio = MaxBidablePrice / bidPrice;
if (ratio < 4)
{ Chance = ((MaxChance / 1000) * ratio); }
else
{ Chance = (MaxChance / 1000); }
}
}
uint32 RandNum = urand(1, ChanceRatio);
if (RandNum <= Chance)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: WIN BID! Chance = %u, num = %u.", Chance, RandNum);
return true;
}
else
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: LOOSE BID! Chance = %u, num = %u.", Chance, RandNum);
return false;
}
}
void AuctionBotBuyer::PlaceBidToEntry(AuctionEntry* auction, uint32 bidPrice)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Bid placed to entry %u, %.2fg", auction->Id, float(bidPrice) / 10000.0f);
auction->UpdateBid(bidPrice);
}
void AuctionBotBuyer::BuyEntry(AuctionEntry* auction)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Entry %u bought at %.2fg", auction->Id, float(auction->buyout) / 10000.0f);
auction->UpdateBid(auction->buyout);
}
void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config)
{
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(config.GetHouseType());
PrepareListOfEntry(config);
time_t Now = time(NULL);
uint32 BuyCycles;
if (config.CheckedEntry.size() > sAuctionBotConfig.GetItemPerCycleBoost())
{
BuyCycles = sAuctionBotConfig.GetItemPerCycleBoost();
BASIC_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Boost value used for Buyer! (if this happens often adjust both ItemsPerCycle in ahbot.conf)");
}
else
{ BuyCycles = sAuctionBotConfig.GetItemPerCycleNormal(); }
for (CheckEntryMap::iterator itr = config.CheckedEntry.begin(); itr != config.CheckedEntry.end();)
{
BuyerAuctionEval& auctionEval = itr->second;
AuctionEntry* auction = auctionHouse->GetAuction(auctionEval.AuctionId);
if (!auction) // is auction not active now
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Entry %u on ah %u doesn't exists, perhaps bought already?",
auctionEval.AuctionId, auction->GetHouseId());
config.CheckedEntry.erase(itr++);
continue;
}
if ((auctionEval.LastChecked != 0) && ((Now - auctionEval.LastChecked) <= m_CheckInterval))
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: In time interval wait for entry %u!", auction->Id);
++itr;
continue;
}
if (BuyCycles == 0)
{ break; }
uint32 MaxChance = 5000;
Item* item = sAuctionMgr.GetAItem(auction->itemGuidLow);
if (!item) // auction item not accessible, possible auction in payment pending mode
{
config.CheckedEntry.erase(itr++);
continue;
}
ItemPrototype const* prototype = item->GetProto();
uint32 BasePrice = sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BUYPRICE_BUYER) ? prototype->BuyPrice : prototype->SellPrice;
BasePrice *= item->GetCount();
double MaxBuyablePrice = (BasePrice * config.BuyerPriceRatio) / 100;
BuyerItemInfoMap::iterator sameitem_itr = config.SameItemInfo.find(item->GetEntry());
uint32 buyoutPrice = auction->buyout / item->GetCount();
uint32 bidPrice;
uint32 bidPriceByItem;
if (auction->bid >= auction->startbid)
{
bidPrice = auction->GetAuctionOutBid();
bidPriceByItem = auction->bid / item->GetCount();
}
else
{
bidPrice = auction->startbid;
bidPriceByItem = auction->startbid / item->GetCount();
}
double InGame_BuyPrice;
double InGame_BidPrice;
uint32 minBidPrice;
uint32 minBuyPrice;
if (sameitem_itr == config.SameItemInfo.end())
{
InGame_BuyPrice = 0;
InGame_BidPrice = 0;
minBidPrice = 0;
minBuyPrice = 0;
}
else
{
const BuyerItemInfo& sameBuyerItem = sameitem_itr->second;
if (sameBuyerItem.ItemCount == 1)
{
MaxBuyablePrice = MaxBuyablePrice * 5;
} // if only one item exist can be buyed if the price is high too.
InGame_BuyPrice = sameBuyerItem.BuyPrice / sameBuyerItem.ItemCount;
InGame_BidPrice = sameBuyerItem.BidPrice / sameBuyerItem.ItemCount;
minBidPrice = sameBuyerItem.MinBidPrice;
minBuyPrice = sameBuyerItem.MinBuyPrice;
}
double MaxBidablePrice = MaxBuyablePrice - (MaxBuyablePrice / 30); // Max Bidable price defined to 70% of max buyable price
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Auction added with data:");
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: MaxPrice of Entry %u is %.1fg.", auctionEval.AuctionId, MaxBuyablePrice / 10000);
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: GamePrice buy=%.1fg, bid=%.1fg.", InGame_BuyPrice / 10000, InGame_BidPrice / 10000);
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Minimal price see in AH Buy=%ug, Bid=%ug.",
minBuyPrice / 10000, minBidPrice / 10000);
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Actual Entry price, Buy=%ug, Bid=%ug.", buyoutPrice / 10000, bidPrice / 10000);
if (auction->owner == sAuctionBotConfig.GetAHBotId()) // Original auction owner
{
MaxChance = MaxChance / 5; // if Owner is AHBot this mean player placed bid on this auction. We divide by 5 chance for AhBuyer to place bid on it. (This make more challenge than ignore entry)
}
if (auction->buyout != 0) // Is the item directly buyable?
{
if (IsBuyableEntry(buyoutPrice, InGame_BuyPrice, MaxBuyablePrice, minBuyPrice, MaxChance, config.FactionChance))
{
if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance / 2, config.FactionChance))
if (urand(0, 5) == 0) { PlaceBidToEntry(auction, bidPrice); }
else { BuyEntry(auction); }
else
{ BuyEntry(auction); }
}
else
{
if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance / 2, config.FactionChance))
{ PlaceBidToEntry(auction, bidPrice); }
}
}
else // buyout = 0 mean only bid are possible
if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance, config.FactionChance))
{ PlaceBidToEntry(auction, bidPrice); }
auctionEval.LastChecked = Now;
--BuyCycles;
++itr;
}
}
bool AuctionBotBuyer::Update(AuctionHouseType houseType)
{
if (sAuctionBotConfig.getConfigBuyerEnabled(houseType))
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: %s buying ...", AuctionBotConfig::GetHouseTypeName(houseType));
if (GetBuyableEntry(m_HouseConfig[houseType]) > 0)
{ addNewAuctionBuyerBotBid(m_HouseConfig[houseType]); }
return true;
}
else { return false; }
}
//== AuctionBotSeller functions ============================
AuctionBotSeller::AuctionBotSeller()
{
// Define faction for our main data class.
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{ m_HouseConfig[i].Initialize(AuctionHouseType(i)); }
}
AuctionBotSeller::~AuctionBotSeller()
{
}
bool AuctionBotSeller::Initialize()
{
std::vector<uint32> npcItems;
std::vector<uint32> lootItems;
std::vector<uint32> includeItems;
std::vector<uint32> excludeItems;
sLog.outString("AHBot seller filters:");
sLog.outString();
{
std::stringstream includeStream(sAuctionBotConfig.GetAHBotIncludes());
std::string temp;
while (getline(includeStream, temp, ','))
{ includeItems.push_back(atoi(temp.c_str())); }
}
{
std::stringstream excludeStream(sAuctionBotConfig.GetAHBotExcludes());
std::string temp;
while (getline(excludeStream, temp, ','))
{ excludeItems.push_back(atoi(temp.c_str())); }
}
sLog.outString("Forced Inclusion " SIZEFMTD " items", includeItems.size());
sLog.outString("Forced Exclusion " SIZEFMTD " items", excludeItems.size());
sLog.outString();
sLog.outString("Loading npc vendor items for filter..");
if (QueryResult* result = WorldDatabase.Query("SELECT DISTINCT item FROM npc_vendor"))
{
BarGoLink bar(result->GetRowCount());
do
{
bar.step();
Field* fields = result->Fetch();
npcItems.push_back(fields[0].GetUInt32());
}
while (result->NextRow());
delete result;
}
else
{
BarGoLink bar(1);
bar.step();
}
sLog.outString("Npc vendor filter has " SIZEFMTD " items", npcItems.size());
sLog.outString();
sLog.outString("Loading loot items for filter..");
if (QueryResult* result = WorldDatabase.PQuery(
"SELECT item FROM creature_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 pickpocketing_loot_template UNION "
"SELECT item FROM skinning_loot_template"))
{
BarGoLink bar(result->GetRowCount());
do
{
bar.step();
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
if (!entry)
{ continue; }
lootItems.push_back(fields[0].GetUInt32());
}
while (result->NextRow());
delete result;
}
else
{
BarGoLink bar(1);
bar.step();
}
sLog.outString("Loot filter has " SIZEFMTD " items", lootItems.size());
sLog.outString();
sLog.outString("Sorting and cleaning items for AHBot seller...");
uint32 itemsAdded = 0;
BarGoLink bar(sItemStorage.GetMaxEntry());
for (uint32 itemID = 0; itemID < sItemStorage.GetMaxEntry(); ++itemID)
{
ItemPrototype const* prototype = sObjectMgr.GetItemPrototype(itemID);
bar.step();
if (!prototype)
{ continue; }
// skip items with too high quality (code can't propertly work with its)
if (prototype->Quality >= MAX_AUCTION_QUALITY)
{ continue; }
// forced exclude filter
bool isExcludeItem = false;
for (size_t i = 0; (i < excludeItems.size() && (!isExcludeItem)); ++i)
if (itemID == excludeItems[i])
{ isExcludeItem = true; }
if (isExcludeItem)
{ continue; }
// forced include filter
bool isForcedIncludeItem = false;
for (size_t i = 0; (i < includeItems.size() && (!isForcedIncludeItem)); ++i)
if (itemID == includeItems[i])
{ isForcedIncludeItem = true; }
if (isForcedIncludeItem)
{
m_ItemPool[prototype->Quality][prototype->Class].push_back(itemID);
++itemsAdded;
continue;
}
// bounding filters
switch (prototype->Bonding)
{
case NO_BIND:
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BIND_NO))
{ continue; }
break;
case BIND_WHEN_PICKED_UP:
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BIND_PICKUP))
{ continue; }
break;
case BIND_WHEN_EQUIPPED:
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BIND_EQUIP))
{ continue; }
break;
case BIND_WHEN_USE:
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BIND_USE))
{ continue; }
break;
case BIND_QUEST_ITEM:
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BIND_QUEST))
{ continue; }
break;
default:
continue;
}
// no price filter
if (sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BUYPRICE_SELLER))
{
if (prototype->BuyPrice == 0)
{ continue; }
}
else
{
if (prototype->SellPrice == 0)
{ continue; }
}
// vendor filter
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_ITEMS_VENDOR))
{
bool IsVendorItem = false;
for (size_t i = 0; (i < npcItems.size()) && (!IsVendorItem); ++i)
if (itemID == npcItems[i])
{ IsVendorItem = true; }
if (IsVendorItem)
{ continue; }
}
// loot filter
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_ITEMS_LOOT))
{
bool isLootItem = false;
for (size_t i = 0; (i < lootItems.size()) && (!isLootItem); ++i)
if (itemID == lootItems[i])
{ isLootItem = true; }
if (isLootItem)
{ continue; }
}
// not vendor/loot filter
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_ITEMS_MISC))
{
bool IsVendorItem = false;
bool isLootItem = false;
for (size_t i = 0; (i < npcItems.size()) && (!IsVendorItem); ++i)
if (itemID == npcItems[i])
{ IsVendorItem = true; }
for (size_t i = 0; (i < lootItems.size()) && (!isLootItem); ++i)
if (itemID == lootItems[i])
{ isLootItem = true; }
if ((!isLootItem) && (!IsVendorItem))
{ continue; }
}
// item class/subclass specific filters
switch (prototype->Class)
{
case ITEM_CLASS_ARMOR:
case ITEM_CLASS_WEAPON:
{
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_ITEM_LEVEL))
{
if (prototype->ItemLevel < value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_ITEM_LEVEL))
{
if (prototype->ItemLevel > value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_REQ_LEVEL))
{
if (prototype->RequiredLevel < value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_REQ_LEVEL))
{
if (prototype->RequiredLevel > value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_SKILL_RANK))
{
if (prototype->RequiredSkillRank < value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_SKILL_RANK))
{
if (prototype->RequiredSkillRank > value)
{ continue; }
}
break;
}
case ITEM_CLASS_RECIPE:
case ITEM_CLASS_CONSUMABLE:
case ITEM_CLASS_PROJECTILE:
{
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_REQ_LEVEL))
{
if (prototype->RequiredLevel < value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_REQ_LEVEL))
{
if (prototype->RequiredLevel > value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MIN_SKILL_RANK))
{
if (prototype->RequiredSkillRank < value)
{ continue; }
}
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_MAX_SKILL_RANK))
{
if (prototype->RequiredSkillRank > value)
{ continue; }
}
break;
}
case ITEM_CLASS_MISC:
if (prototype->Flags & ITEM_FLAG_LOOTABLE)
{
// skip any not locked lootable items (mostly quest specific or reward cases)
if (!prototype->LockID)
{ continue; }
if (!sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_LOCKBOX_ENABLED))
{ continue; }
}
break;
case ITEM_CLASS_TRADE_GOODS:
{
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL))
if (prototype->ItemLevel < value)
{ continue; }
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL))
if (prototype->ItemLevel > value)
{ continue; }
break;
}
case ITEM_CLASS_CONTAINER:
case ITEM_CLASS_QUIVER:
{
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL))
if (prototype->ItemLevel < value)
{ continue; }
if (uint32 value = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL))
if (prototype->ItemLevel > value)
{ continue; }
break;
}
default:
continue;
}
m_ItemPool[prototype->Quality][prototype->Class].push_back(itemID);
++itemsAdded;
}
if (!itemsAdded)
{
sLog.outError("AuctionHouseBot seller not have items, disabled.");
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, 0);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO, 0);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, 0);
return false;
}
sLog.outString("AuctionHouseBot seller will use %u items to fill auction house (according your config choices)", itemsAdded);
LoadConfig();
sLog.outString("Items loaded \tGrey\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
sLog.outString("%-18s\t" SIZEFMTD "\t" SIZEFMTD "\t" SIZEFMTD "\t" SIZEFMTD "\t" SIZEFMTD "\t" SIZEFMTD "\t" SIZEFMTD,
sAuctionBotConfig.GetItemClassName(ItemClass(i)),
m_ItemPool[0][i].size(), m_ItemPool[1][i].size(), m_ItemPool[2][i].size(),
m_ItemPool[3][i].size(), m_ItemPool[4][i].size(), m_ItemPool[5][i].size(),
m_ItemPool[6][i].size());
sLog.outString();
sLog.outString("AHBot seller configuration data loaded and initilized");
sLog.SetLogFilter(LOG_FILTER_AHBOT_SELLER, !sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_DEBUG_SELLER));
return true;
}
void AuctionBotSeller::LoadConfig()
{
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
if (sAuctionBotConfig.getConfigItemAmountRatio(AuctionHouseType(i)))
{ LoadSellerValues(m_HouseConfig[i]); }
}
void AuctionBotSeller::LoadItemsQuantity(AHB_Seller_Config& config)
{
uint32 ratio = sAuctionBotConfig.getConfigItemAmountRatio(config.GetHouseType());
config.SetItemsAmountPerQuality(AUCTION_QUALITY_GREY, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_GREY_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_WHITE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_WHITE_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_GREEN, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_GREEN_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_BLUE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_BLUE_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_PURPLE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_PURPLE_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_ORANGE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_ORANGE_AMOUNT) * ratio / 100);
config.SetItemsAmountPerQuality(AUCTION_QUALITY_YELLOW, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ITEM_YELLOW_AMOUNT) * ratio / 100);
// Set quantity wanted but only on possible item color
// This avoid any no-exist class-color items selection by random items create function
// ============================================================================================
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_CONSUMABLE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_CONTAINER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_PROJECTILE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_RECIPE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_QUIVER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_QUEST, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_KEY, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREY, ITEM_CLASS_MISC, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_CONTAINER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_REAGENT, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_REAGENT_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_RECIPE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_QUIVER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUIVER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_QUEST, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_KEY, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_KEY_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_WHITE, ITEM_CLASS_MISC, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_CONTAINER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_PROJECTILE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_RECIPE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_QUIVER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUIVER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_QUEST, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_KEY, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_KEY_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_GREEN, ITEM_CLASS_MISC, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_CONTAINER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_RECIPE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_QUIVER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUIVER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_QUEST, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_KEY, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_BLUE, ITEM_CLASS_MISC, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_CONSUMABLE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_CONTAINER, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_PROJECTILE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_RECIPE, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_QUIVER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_QUEST, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_KEY, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_PURPLE, ITEM_CLASS_MISC, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_CONSUMABLE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_CONTAINER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_PROJECTILE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_TRADE_GOODS, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_RECIPE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_QUIVER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_QUEST, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_KEY, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_ORANGE, ITEM_CLASS_MISC, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_CONSUMABLE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_CONTAINER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_WEAPON, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_ARMOR, sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT));
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_REAGENT, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_PROJECTILE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_TRADE_GOODS, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_RECIPE, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_QUIVER, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_QUEST, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_KEY, 0);
config.SetItemsQuantityPerClass(AUCTION_QUALITY_YELLOW, ITEM_CLASS_MISC, 0);
// ============================================================================================
// Set the best value to get nearest amount of items wanted
for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
{
uint32 indice = config.GetItemsAmountPerQuality(AuctionQuality(j)) /
(sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONSUMABLE_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_CONTAINER_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_WEAPON_AMOUNT) +
sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_GEM_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_ARMOR_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_REAGENT_AMOUNT) +
sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_PROJECTILE_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_TRADEGOOD_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_GENERIC_AMOUNT) +
sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_RECIPE_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUIVER_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_QUEST_AMOUNT) +
sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_KEY_AMOUNT) + sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_CLASS_MISC_AMOUNT));
for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
{ config.SetItemsAmountPerClass(AuctionQuality(j), ItemClass(i), indice); }
}
}
void AuctionBotSeller::LoadSellerValues(AHB_Seller_Config& config)
{
LoadItemsQuantity(config);
uint32 PriceRatio;
switch (config.GetHouseType())
{
case AUCTION_HOUSE_ALLIANCE:
PriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_ALLIANCE_PRICE_RATIO);
break;
case AUCTION_HOUSE_HORDE:
PriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_HORDE_PRICE_RATIO);
break;
default:
PriceRatio = sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_NEUTRAL_PRICE_RATIO);
break;
}
config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREY, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio);
config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio);
// load min and max auction times
config.SetMinTime(sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_MINTIME));
config.SetMaxTime(sAuctionBotConfig.getConfig(CONFIG_UINT32_AHBOT_MAXTIME));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: minTime = %u", config.GetMinTime());
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: maxTime = %u", config.GetMaxTime());
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: For AH type %u", config.GetHouseType());
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: GreyItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_GREY));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: WhiteItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_WHITE));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: GreenItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_GREEN));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: BlueItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_BLUE));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: PurpleItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_PURPLE));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: OrangeItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_ORANGE));
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: YellowItems = %u", config.GetItemsAmountPerQuality(AUCTION_QUALITY_YELLOW));
}
// Set static of items on one AH faction.
// Fill ItemInfos object with real content of AH.
uint32 AuctionBotSeller::SetStat(AHB_Seller_Config& config)
{
std::vector<std::vector<uint32> > ItemsInAH(MAX_AUCTION_QUALITY, std::vector< uint32 > (MAX_ITEM_CLASS));
AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(config.GetHouseType())->GetAuctionsBounds();
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
AuctionEntry* Aentry = itr->second;
Item* item = sAuctionMgr.GetAItem(Aentry->itemGuidLow);
if (item)
{
ItemPrototype const* prototype = item->GetProto();
if (prototype)
{
if (Aentry->owner == sAuctionBotConfig.GetAHBotId()) // Add only ahbot items
{
++ItemsInAH[prototype->Quality][prototype->Class];
}
}
}
}
uint32 count = 0;
for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
{
for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
{
config.SetMissedItemsPerClass((AuctionQuality) j, (ItemClass) i, ItemsInAH[j][i]);
count += config.GetMissedItemsPerClass((AuctionQuality) j, (ItemClass) i);
}
}
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: Missed Item \tGrey\tWhite\tGreen\tBlue\tPurple\tOrange\tYellow");
for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: %-18s\t%u\t%u\t%u\t%u\t%u\t%u\t%u",
sAuctionBotConfig.GetItemClassName(ItemClass(i)),
config.GetMissedItemsPerClass(AUCTION_QUALITY_GREY, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_WHITE, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_GREEN, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_BLUE, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_PURPLE, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_ORANGE, (ItemClass) i),
config.GetMissedItemsPerClass(AUCTION_QUALITY_YELLOW, (ItemClass) i));
}
config.LastMissedItem = count;
return count;
}
// getRandomArray is used to make available the possibility to add any of missed item in place of first one to last one.
bool AuctionBotSeller::getRandomArray(AHB_Seller_Config& config, RandomArray& ra, const std::vector<std::vector<uint32> >& addedItem)
{
ra.clear();
bool Ok = false;
for (uint32 j = 0; j < MAX_AUCTION_QUALITY; ++j)
{
for (uint32 i = 0; i < MAX_ITEM_CLASS; ++i)
{
if ((config.GetMissedItemsPerClass(AuctionQuality(j), ItemClass(i)) > addedItem[j][i]) && !m_ItemPool[j][i].empty())
{
RandomArrayEntry miss_item;
miss_item.color = j;
miss_item.itemclass = i;
ra.push_back(miss_item);
Ok = true;
}
}
}
return Ok;
}
// Set items price. All important value are passed by address.
void AuctionBotSeller::SetPricesOfItem(AHB_Seller_Config& config, uint32& buyp, uint32& bidp, uint32 stackcnt, ItemQualities itemQuality)
{
double temp_buyp = buyp * stackcnt *
(itemQuality < MAX_AUCTION_QUALITY ? config.GetPriceRatioPerQuality(AuctionQuality(itemQuality)) : 1) ;
double randrange = temp_buyp * 0.4;
buyp = (urand(temp_buyp - randrange, temp_buyp + randrange) / 100) + 1;
double urandrange = buyp * 40;
double temp_bidp = buyp * 50;
bidp = (urand(temp_bidp - urandrange, temp_bidp + urandrange) / 100) + 1;
}
void AuctionBotSeller::SetItemsRatio(uint32 al, uint32 ho, uint32 ne)
{
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, al < 10000 ? al : 10000);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO, ho < 10000 ? ho : 10000);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, ne < 10000 ? ne : 10000);
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{ LoadItemsQuantity(m_HouseConfig[i]); }
}
void AuctionBotSeller::SetItemsRatioForHouse(AuctionHouseType house, uint32 val)
{
if (val > 10000) // apply same upper limit as used for config load
{ val = 10000; }
switch (house)
{
case AUCTION_HOUSE_ALLIANCE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ALLIANCE_ITEM_AMOUNT_RATIO, val); break;
case AUCTION_HOUSE_HORDE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_HORDE_ITEM_AMOUNT_RATIO, val); break;
default: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_NEUTRAL_ITEM_AMOUNT_RATIO, val); break;
}
LoadItemsQuantity(m_HouseConfig[house]);
}
void AuctionBotSeller::SetItemsAmount(uint32(&vals) [MAX_AUCTION_QUALITY])
{
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_GREY_AMOUNT, vals[AUCTION_QUALITY_GREY]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_WHITE_AMOUNT, vals[AUCTION_QUALITY_WHITE]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_GREEN_AMOUNT, vals[AUCTION_QUALITY_GREEN]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_BLUE_AMOUNT, vals[AUCTION_QUALITY_BLUE]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_PURPLE_AMOUNT, vals[AUCTION_QUALITY_PURPLE]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_ORANGE_AMOUNT, vals[AUCTION_QUALITY_ORANGE]);
sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_YELLOW_AMOUNT, vals[AUCTION_QUALITY_YELLOW]);
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{ LoadItemsQuantity(m_HouseConfig[i]); }
}
void AuctionBotSeller::SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
{
switch (quality)
{
case AUCTION_QUALITY_GREY: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_GREY_AMOUNT, val); break;
case AUCTION_QUALITY_WHITE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_WHITE_AMOUNT, val); break;
case AUCTION_QUALITY_GREEN: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_GREEN_AMOUNT, val); break;
case AUCTION_QUALITY_BLUE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_BLUE_AMOUNT, val); break;
case AUCTION_QUALITY_PURPLE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_PURPLE_AMOUNT, val); break;
case AUCTION_QUALITY_ORANGE: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_ORANGE_AMOUNT, val); break;
default: sAuctionBotConfig.setConfig(CONFIG_UINT32_AHBOT_ITEM_YELLOW_AMOUNT, val); break;
}
for (int i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{ LoadItemsQuantity(m_HouseConfig[i]); }
}
// Add new auction to one of the factions.
// Faction and setting assossiated is defined passed argument ( config )
void AuctionBotSeller::addNewAuctions(AHB_Seller_Config& config)
{
uint32 items;
// If there is large amount of items missed we can use boost value to get fast filled AH
if (config.LastMissedItem > sAuctionBotConfig.GetItemPerCycleBoost())
{
items = sAuctionBotConfig.GetItemPerCycleBoost();
BASIC_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Boost value used to fill AH! (if this happens often adjust both ItemsPerCycle in ahbot.conf)");
}
else { items = sAuctionBotConfig.GetItemPerCycleNormal(); }
uint32 houseid;
switch (config.GetHouseType())
{
case AUCTION_HOUSE_ALLIANCE: houseid = 1; break;
case AUCTION_HOUSE_HORDE: houseid = 6; break;
default: houseid = 7; break;
}
AuctionHouseEntry const* ahEntry = sAuctionHouseStore.LookupEntry(houseid);
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(config.GetHouseType());
RandomArray randArray;
std::vector<std::vector<uint32> > ItemsAdded(MAX_AUCTION_QUALITY, std::vector<uint32> (MAX_ITEM_CLASS));
// Main loop
// getRandomArray will give what categories of items should be added (return true if there is at least 1 items missed)
while (getRandomArray(config, randArray, ItemsAdded) && (items > 0))
{
--items;
// Select random position from missed items table
uint32 pos = (urand(0, randArray.size() - 1));
// Set itemID with random item ID for selected categories and color, from m_ItemPool table
uint32 itemID = m_ItemPool[randArray[pos].color][randArray[pos].itemclass][urand(0, m_ItemPool[randArray[pos].color][randArray[pos].itemclass].size() - 1)];
++ ItemsAdded[randArray[pos].color][randArray[pos].itemclass]; // Helper table to avoid rescan from DB in this loop. (has we add item in random orders)
if (!itemID)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: Item entry 0 auction creating attempt.");
continue;
}
ItemPrototype const* prototype = sObjectMgr.GetItemPrototype(itemID);
if (!prototype)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: Unknown item %u auction creating attempt.", itemID);
continue;
}
uint32 stackCount = urand(1, prototype->GetMaxStackSize());
Item* item = Item::CreateItem(itemID, stackCount);
if (!item)
{
sLog.outError("AHBot: Item::CreateItem() returned NULL for item %u (stack: %u)", itemID, stackCount);
return;
}
uint32 buyoutPrice;
uint32 bidPrice = 0;
// Not sure if i will keep the next test
if (sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BUYPRICE_SELLER))
{ buyoutPrice = prototype->BuyPrice * item->GetCount(); }
else
{ buyoutPrice = prototype->SellPrice * item->GetCount(); }
// Price of items are set here
SetPricesOfItem(config, buyoutPrice, bidPrice, stackCount, ItemQualities(prototype->Quality));
auctionHouse->AddAuctionByGuid(ahEntry, item, urand(config.GetMinTime(), config.GetMaxTime()) * HOUR, bidPrice, buyoutPrice, sAuctionBotConfig.GetAHBotId());
}
}
bool AuctionBotSeller::Update(AuctionHouseType houseType)
{
if (sAuctionBotConfig.getConfigItemAmountRatio(houseType) > 0)
{
DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_SELLER, "AHBot: %s selling ...", AuctionBotConfig::GetHouseTypeName(houseType));
if (SetStat(m_HouseConfig[houseType]))
{ addNewAuctions(m_HouseConfig[houseType]); }
return true;
}
else
{ return false; }
}
//== AuctionHouseBot functions =============================
AuctionHouseBot::AuctionHouseBot() : m_Buyer(NULL), m_Seller(NULL), m_OperationSelector(0)
{
}
AuctionHouseBot::~AuctionHouseBot()
{
delete m_Buyer;
delete m_Seller;
}
void AuctionHouseBot::InitializeAgents()
{
if (sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_SELLER_ENABLED))
{
delete m_Seller;
m_Seller = new AuctionBotSeller();
if (!m_Seller->Initialize())
{
delete m_Seller;
m_Seller = NULL;
}
}
if (sAuctionBotConfig.getConfig(CONFIG_BOOL_AHBOT_BUYER_ENABLED))
{
delete m_Buyer;
m_Buyer = new AuctionBotBuyer();
if (!m_Buyer->Initialize())
{
delete m_Buyer;
m_Buyer = NULL;
}
}
}
void AuctionHouseBot::Initialize()
{
if (sAuctionBotConfig.Initialize())
{
InitializeAgents();
}
}
void AuctionHouseBot::SetItemsRatio(uint32 al, uint32 ho, uint32 ne)
{
if (AuctionBotSeller* seller = dynamic_cast<AuctionBotSeller*>(m_Seller))
{ seller->SetItemsRatio(al, ho, ne); }
}
void AuctionHouseBot::SetItemsRatioForHouse(AuctionHouseType house, uint32 val)
{
if (AuctionBotSeller* seller = dynamic_cast<AuctionBotSeller*>(m_Seller))
{ seller->SetItemsRatioForHouse(house, val); }
}
void AuctionHouseBot::SetItemsAmount(uint32(&vals) [MAX_AUCTION_QUALITY])
{
if (AuctionBotSeller* seller = dynamic_cast<AuctionBotSeller*>(m_Seller))
{ seller->SetItemsAmount(vals); }
}
void AuctionHouseBot::SetItemsAmountForQuality(AuctionQuality quality, uint32 val)
{
if (AuctionBotSeller* seller = dynamic_cast<AuctionBotSeller*>(m_Seller))
{ seller->SetItemsAmountForQuality(quality, val); }
}
bool AuctionHouseBot::ReloadAllConfig()
{
if (!sAuctionBotConfig.Reload())
{
sLog.outError("AHBot: Error while trying to reload config from file!");
return false;
}
InitializeAgents();
return true;
}
void AuctionHouseBot::PrepareStatusInfos(AuctionHouseBotStatusInfo& statusInfo)
{
for (uint32 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{
statusInfo[i].ItemsCount = 0;
for (int j = 0; j < MAX_AUCTION_QUALITY; ++j)
{ statusInfo[i].QualityInfo[j] = 0; }
AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(AuctionHouseType(i))->GetAuctionsBounds();
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
AuctionEntry* Aentry = itr->second;
if (Item* item = sAuctionMgr.GetAItem(Aentry->itemGuidLow))
{
ItemPrototype const* prototype = item->GetProto();
if (Aentry->owner == sAuctionBotConfig.GetAHBotId()) // Add only ahbot items
{
if (prototype->Quality < MAX_AUCTION_QUALITY)
{ ++statusInfo[i].QualityInfo[prototype->Quality]; }
++statusInfo[i].ItemsCount;
}
}
}
}
}
void AuctionHouseBot::Rebuild(bool all)
{
for (uint32 i = 0; i < MAX_AUCTION_HOUSE_TYPE; ++i)
{
AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(AuctionHouseType(i))->GetAuctionsBounds();
for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
AuctionEntry* entry = itr->second;
if (entry->owner == sAuctionBotConfig.GetAHBotId()) // ahbot auction
if (all || entry->bid == 0) // expire auction now if no bid or forced
entry->expireTime = sWorld.GetGameTime();
}
}
}
void AuctionHouseBot::Update()
{
// nothing do...
if (!m_Buyer && !m_Seller)
{ return; }
// scan all possible update cases until first success
for (uint32 count = 0; count < 2 * MAX_AUCTION_HOUSE_TYPE; ++count)
{
bool successStep = false;
if (m_OperationSelector < MAX_AUCTION_HOUSE_TYPE)
{
if (m_Seller)
{ successStep = m_Seller->Update(AuctionHouseType(m_OperationSelector)); }
}
else
{
if (m_Buyer)
{ successStep = m_Buyer->Update(AuctionHouseType(m_OperationSelector - MAX_AUCTION_HOUSE_TYPE)); }
}
++m_OperationSelector;
if (m_OperationSelector >= 2 * MAX_AUCTION_HOUSE_TYPE)
{ m_OperationSelector = 0; }
// one success update per call
if (successStep)
{ break; }
}
}
/** @} */