mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-17 10:45:43 +00:00
Big update.
This commit is contained in:
184
src/strategy/actions/BuyAction.cpp
Normal file
184
src/strategy/actions/BuyAction.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "BuyAction.h"
|
||||
#include "BudgetValues.h"
|
||||
#include "Event.h"
|
||||
#include "ItemVisitors.h"
|
||||
#include "ItemCountValue.h"
|
||||
#include "ItemUsageValue.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
bool BuyAction::Execute(Event event)
|
||||
{
|
||||
bool buyUseful = false;
|
||||
ItemIds itemIds;
|
||||
std::string const link = event.getParam();
|
||||
|
||||
if (link == "vendor")
|
||||
buyUseful = true;
|
||||
else
|
||||
{
|
||||
itemIds = chat->parseItems(link);
|
||||
}
|
||||
|
||||
GuidVector vendors = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
|
||||
|
||||
bool vendored = false;
|
||||
bool result = false;
|
||||
for (GuidVector::iterator i = vendors.begin(); i != vendors.end(); ++i)
|
||||
{
|
||||
ObjectGuid vendorguid = *i;
|
||||
Creature* pCreature = bot->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);
|
||||
if (!pCreature)
|
||||
continue;
|
||||
|
||||
vendored = true;
|
||||
|
||||
if (buyUseful)
|
||||
{
|
||||
// Items are evaluated from high-level to low level.
|
||||
// For each item the bot checks again if an item is usefull.
|
||||
// Bot will buy until no usefull items are left.
|
||||
|
||||
VendorItemData const* tItems = pCreature->GetVendorItems();
|
||||
if (!tItems)
|
||||
continue;
|
||||
|
||||
VendorItemList m_items_sorted = tItems->m_items;
|
||||
|
||||
m_items_sorted.erase(std::remove_if(m_items_sorted.begin(), m_items_sorted.end(), [](VendorItem* i)
|
||||
{
|
||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(i->item);
|
||||
return !proto;
|
||||
}), m_items_sorted.end());
|
||||
|
||||
if (m_items_sorted.empty())
|
||||
continue;
|
||||
|
||||
std::sort(m_items_sorted.begin(), m_items_sorted.end(), [](VendorItem* i, VendorItem* j) { return sObjectMgr->GetItemTemplate(i->item)->ItemLevel > sObjectMgr->GetItemTemplate(j->item)->ItemLevel; });
|
||||
|
||||
for (auto& tItem : m_items_sorted)
|
||||
{
|
||||
for (uint32 i = 0; i < 10; i++) // Buy 10 times or until no longer usefull/possible
|
||||
{
|
||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", tItem->item);
|
||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(tItem->item);
|
||||
|
||||
uint32 price = proto->BuyPrice;
|
||||
|
||||
// reputation discount
|
||||
price = uint32(floor(price * bot->GetReputationPriceDiscount(pCreature)));
|
||||
|
||||
NeedMoneyFor needMoneyFor = NeedMoneyFor::none;
|
||||
|
||||
switch (usage)
|
||||
{
|
||||
case ITEM_USAGE_REPLACE:
|
||||
case ITEM_USAGE_EQUIP:
|
||||
needMoneyFor = NeedMoneyFor::gear;
|
||||
break;
|
||||
case ITEM_USAGE_AMMO:
|
||||
needMoneyFor = NeedMoneyFor::ammo;
|
||||
break;
|
||||
case ITEM_USAGE_QUEST:
|
||||
needMoneyFor = NeedMoneyFor::anything;
|
||||
break;
|
||||
case ITEM_USAGE_USE:
|
||||
needMoneyFor = NeedMoneyFor::consumables;
|
||||
break;
|
||||
case ITEM_USAGE_SKILL:
|
||||
needMoneyFor = NeedMoneyFor::tradeskill;
|
||||
break;
|
||||
}
|
||||
|
||||
if (needMoneyFor == NeedMoneyFor::none)
|
||||
break;
|
||||
|
||||
if (AI_VALUE2(uint32, "free money for", uint32(needMoneyFor)) < price)
|
||||
break;
|
||||
|
||||
if (!BuyItem(tItems, vendorguid, proto))
|
||||
break;
|
||||
|
||||
if (usage == ITEM_USAGE_REPLACE || usage == ITEM_USAGE_EQUIP) // Equip upgrades and stop buying this time.
|
||||
{
|
||||
botAI->DoSpecificAction("equip upgrades");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itemIds.empty())
|
||||
return false;
|
||||
|
||||
for (ItemIds::iterator i = itemIds.begin(); i != itemIds.end(); i++)
|
||||
{
|
||||
uint32 itemId = *i;
|
||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
|
||||
if (!proto)
|
||||
continue;
|
||||
|
||||
result |= BuyItem(pCreature->GetVendorItems(), vendorguid, proto);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Nobody sells " << ChatHelper::FormatItem(proto) << " nearby";
|
||||
botAI->TellMaster(out.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vendored)
|
||||
{
|
||||
botAI->TellError("There are no vendors nearby");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuyAction::BuyItem(VendorItemData const* tItems, ObjectGuid vendorguid, ItemTemplate const* proto)
|
||||
{
|
||||
uint32 oldCount = AI_VALUE2(uint32, "item count", proto->Name1);
|
||||
|
||||
if (!tItems)
|
||||
return false;
|
||||
|
||||
uint32 itemId = proto->ItemId;
|
||||
for (uint32 slot = 0; slot < tItems->GetItemCount(); slot++)
|
||||
{
|
||||
if (tItems->GetItem(slot)->item == itemId)
|
||||
{
|
||||
uint32 botMoney = bot->GetMoney();
|
||||
if (botAI->HasCheat(BotCheatMask::gold))
|
||||
{
|
||||
bot->SetMoney(10000000);
|
||||
}
|
||||
|
||||
bot->BuyItemFromVendorSlot(vendorguid, slot, itemId, 1, NULL_BAG, NULL_SLOT);
|
||||
|
||||
if (botAI->HasCheat(BotCheatMask::gold))
|
||||
{
|
||||
bot->SetMoney(botMoney);
|
||||
}
|
||||
|
||||
if (oldCount < AI_VALUE2(uint32, "item count", proto->Name1)) // BuyItem Always returns false (unless unique) so we have to check the item counts.
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Buying " << ChatHelper::FormatItem(proto);
|
||||
botAI->TellMaster(out.str());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user