Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/game/Object/SpellMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ struct SpellModifier;
enum SpellCategories
{
SPELLCATEGORY_HEALTH_MANA_POTIONS = 4,
SPELLCATEGORY_FOOD = 11,
SPELLCATEGORY_DEVOUR_MAGIC = 12,
SPELLCATEGORY_DRINK = 59
};

/**
Expand Down
18 changes: 16 additions & 2 deletions src/modules/Bots/playerbot/PlayerbotAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ void PacketHandlingHelper::AddPacket(const WorldPacket& packet)
* Default constructor for PlayerbotAI.
*/
PlayerbotAI::PlayerbotAI() : PlayerbotAIBase(), bot(NULL), aiObjectContext(NULL),
currentEngine(NULL), chatHelper(this), chatFilter(this), accountId(0), security(NULL), master(NULL), currentState(BOT_STATE_NON_COMBAT)
currentEngine(NULL), chatHelper(this), chatFilter(this), accountId(0), security(NULL), master(NULL), currentState(BOT_STATE_NON_COMBAT),
m_eatingUntil(0), m_drinkingUntil(0)
{
for (int i = 0 ; i < BOT_STATE_MAX; i++)
{
Expand All @@ -90,7 +91,8 @@ PlayerbotAI::PlayerbotAI() : PlayerbotAIBase(), bot(NULL), aiObjectContext(NULL)
* @param bot The player bot.
*/
PlayerbotAI::PlayerbotAI(Player* bot) :
PlayerbotAIBase(), chatHelper(this), chatFilter(this), security(bot), master(NULL)
PlayerbotAIBase(), chatHelper(this), chatFilter(this), security(bot), master(NULL),
m_eatingUntil(0), m_drinkingUntil(0)
{
this->bot = bot;

Expand Down Expand Up @@ -184,6 +186,15 @@ void PlayerbotAI::UpdateAI(uint32 elapsed)
nextAICheckDelay = sPlayerbotAIConfig.maxWaitForMove;
}

if (m_drinkingUntil || m_eatingUntil)
{
if (bot->IsInCombat() || !bot->IsSitState())
{
m_drinkingUntil = 0;
m_eatingUntil = 0;
}
}

PlayerbotAIBase::UpdateAI(elapsed);
}

Expand Down Expand Up @@ -404,6 +415,9 @@ void PlayerbotAI::HandleBotOutgoingPacket(const WorldPacket& packet)
*/
void PlayerbotAI::SpellInterrupted(uint32 spellid)
{
if (!spellid)
return;

LastSpellCast& lastSpell = aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get();
if (lastSpell.id != spellid)
{
Expand Down
18 changes: 18 additions & 0 deletions src/modules/Bots/playerbot/PlayerbotAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,22 @@ class PlayerbotAI : public PlayerbotAIBase
static bool IsOpposing(uint8 race1, uint8 race2);
PlayerbotSecurity* GetSecurity() { return &security; }

bool IsEating() const
{
return m_eatingUntil && time(0) <= m_eatingUntil
&& bot->GetHealth() < bot->GetMaxHealth();
}
bool IsDrinking() const
{
if (!m_drinkingUntil) return false;
time_t now = time(0);
uint32 mana = bot->GetPower(POWER_MANA);
uint32 maxMana = bot->GetMaxPower(POWER_MANA);
return now <= m_drinkingUntil && mana < maxMana;
}
void SetEating() { m_eatingUntil = time(0) + 30; }
void SetDrinking() { m_drinkingUntil = time(0) + 30; }

protected:
Player* bot;
Player* master;
Expand All @@ -194,5 +210,7 @@ class PlayerbotAI : public PlayerbotAIBase
PacketHandlingHelper masterOutgoingPacketHandlers;
CompositeChatFilter chatFilter;
PlayerbotSecurity security;
time_t m_eatingUntil;
time_t m_drinkingUntil;
};

4 changes: 4 additions & 0 deletions src/modules/Bots/playerbot/PlayerbotAIConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ PlayerbotAIConfig::PlayerbotAIConfig()
lowHealth(0),
mediumHealth(0),
almostFullHealth(0),
hungryHealth(0),
lowMana(0),
mediumMana(0),
thirstyMana(0),
randomBotAutologin(false),
randomBotTeleportDistance(0),
randomGearLoweringChance(0.0f),
Expand Down Expand Up @@ -142,8 +144,10 @@ bool PlayerbotAIConfig::Initialize()
lowHealth = config.GetIntDefault("AiPlayerbot.LowHealth", 50);
mediumHealth = config.GetIntDefault("AiPlayerbot.MediumHealth", 70);
almostFullHealth = config.GetIntDefault("AiPlayerbot.AlmostFullHealth", 85);
hungryHealth = config.GetIntDefault("AiPlayerbot.HungryHealth", 65);
lowMana = config.GetIntDefault("AiPlayerbot.LowMana", 15);
mediumMana = config.GetIntDefault("AiPlayerbot.MediumMana", 40);
thirstyMana = config.GetIntDefault("AiPlayerbot.ThirstyMana", 65);

randomGearLoweringChance = config.GetFloatDefault("AiPlayerbot.RandomGearLoweringChance", 0.15f);
randomBotMaxLevelChance = config.GetFloatDefault("AiPlayerbot.RandomBotMaxLevelChance", 0.4f);
Expand Down
4 changes: 2 additions & 2 deletions src/modules/Bots/playerbot/PlayerbotAIConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class PlayerbotAIConfig
float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance,
fleeDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance;
bool whisperToZoneOnly;
uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth;
uint32 lowMana, mediumMana;
uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth, hungryHealth;
uint32 lowMana, mediumMana, thirstyMana;

bool randomBotAutologin; ///< Indicates if random bots should auto-login.
std::string randomBotMapsAsString; ///< Comma-separated string of random bot maps.
Expand Down
2 changes: 2 additions & 0 deletions src/modules/Bots/playerbot/aiplayerbot.conf.dist.in
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ AiPlayerbot.CommandPrefix = ~
#AiPlayerbot.LowHealth = 45
#AiPlayerbot.MediumHealth = 65
#AiPlayerbot.AlmostFullHealth = 85
#AiPlayerbot.HungryHealth = 65
#AiPlayerbot.LowMana = 15
#AiPlayerbot.MediumMana = 40
#AiPlayerbot.ThirstyMana = 65

# Enable random bot system
#AiPlayerbot.RandomBotAutologin = 1
Expand Down
34 changes: 34 additions & 0 deletions src/modules/Bots/playerbot/strategy/ItemVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,38 @@ namespace ai
public:
map<uint32, int> count;
};

class FindFoodVisitor : public FindUsableItemVisitor
{
public:
FindFoodVisitor(Player* bot, uint32 spellCategory) : FindUsableItemVisitor(bot)
{
this->spellCategory = spellCategory;
}

virtual bool Accept(const ItemPrototype* proto)
{
return proto->Class == ITEM_CLASS_CONSUMABLE &&
proto->Spells[0].SpellCategory == spellCategory;
}
private:
uint32 spellCategory;
};

class FindConjuredFoodVisitor : public FindUsableItemVisitor
{
public:
FindConjuredFoodVisitor(Player* bot, uint32 spellCategory) : FindUsableItemVisitor(bot)
{
this->spellCategory = spellCategory;
}

virtual bool Accept(const ItemPrototype* proto)
{
return proto->IsConjuredConsumable() &&
proto->Spells[0].SpellCategory == spellCategory;
}
private:
uint32 spellCategory;
};
}
88 changes: 75 additions & 13 deletions src/modules/Bots/playerbot/strategy/actions/InventoryAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,44 @@ class FindPotionVisitor : public FindUsableItemVisitor
uint32 effectId;
};

class FindFoodVisitor : public FindUsableItemVisitor
class FindManaGemVisitor : public FindUsableItemVisitor
{
public:
FindFoodVisitor(Player* bot, uint32 spellCategory) : FindUsableItemVisitor(bot)
{
this->spellCategory = spellCategory;
}
FindManaGemVisitor(Player* bot) : FindUsableItemVisitor(bot) {}

virtual bool Accept(const ItemPrototype* proto)
{
return proto->Class == ITEM_CLASS_CONSUMABLE &&
proto->SubClass == ITEM_SUBCLASS_FOOD &&
proto->Spells[0].SpellCategory == spellCategory;
}
if (proto->Class == ITEM_CLASS_CONSUMABLE &&
(proto->Flags & ITEM_FLAG_CONJURED) &&
proto->SubClass != ITEM_SUBCLASS_POTION)
{
for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; j++)
{
if (!proto->Spells[j].SpellId)
{
continue;
}

private:
uint32 spellCategory;
const SpellEntry* const spellInfo = sSpellStore.LookupEntry(proto->Spells[j].SpellId);
if (!spellInfo)
{
continue;
}

for (int i = 0; i < 3; i++)
{
if (spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
{
return true;
}
}
}
}
return false;
}
};


void InventoryAction::IterateItems(IterateItemsVisitor* visitor, IterateItemsMask mask)
{
if (mask & ITERATE_ITEMS_IN_BAGS)
Expand Down Expand Up @@ -148,6 +167,28 @@ bool compare_items_by_level(const Item* item1, const Item* item2)
return compare_items(item1->GetProto(), item2->GetProto());
}


Item* InventoryAction::FindPlayerItem(Player *bot, FindItemVisitor *visitor)
{
for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i)
{
if (Item* pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
visitor->Visit(pItem);
}
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
{
if (Bag* pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
{
for (uint32 j = 0; j < pBag->GetBagSize(); ++j)
{
if (Item* pItem = pBag->GetItemByPos(j))
visitor->Visit(pItem);
}
}
}
return visitor->GetResult().empty() ? NULL : visitor->GetResult().front();
}

void InventoryAction::TellItems(map<uint32, int> itemMap)
{
list<ItemPrototype const*> items;
Expand Down Expand Up @@ -232,14 +273,28 @@ list<Item*> InventoryAction::parseItems(string text)

if (text == "food")
{
FindFoodVisitor visitor(bot, 11);
FindFoodVisitor visitor(bot, SPELLCATEGORY_FOOD);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}

if (text == "drink")
{
FindFoodVisitor visitor(bot, 59);
FindFoodVisitor visitor(bot, SPELLCATEGORY_DRINK);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}

if (text == "conjured food")
{
FindConjuredFoodVisitor visitor(bot, SPELLCATEGORY_FOOD);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}

if (text == "conjured drink")
{
FindConjuredFoodVisitor visitor(bot, SPELLCATEGORY_DRINK);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}
Expand All @@ -258,6 +313,13 @@ list<Item*> InventoryAction::parseItems(string text)
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}

if (text == "mana gem")
{
FindManaGemVisitor visitor(bot);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
}

FindUsableNamedItemVisitor visitor(bot, text);
IterateItems(&visitor, ITERATE_ITEMS_IN_BAGS);
found.insert(visitor.GetResult().begin(), visitor.GetResult().end());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ai
class InventoryAction : public Action {
public:
InventoryAction(PlayerbotAI* ai, string name) : Action(ai, name) {}
static Item* FindPlayerItem(Player* player, FindItemVisitor* visitor);

protected:
void IterateItems(IterateItemsVisitor* visitor, IterateItemsMask mask = ITERATE_ITEMS_IN_BAGS);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "botpch.h"
//#include "../../playerbot.h"
//#include "NonCombatActions.h"
#include "../../playerbot.h"
#include "NonCombatActions.h"

using namespace ai;

34 changes: 30 additions & 4 deletions src/modules/Bots/playerbot/strategy/actions/NonCombatActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,25 @@ namespace ai
return false;
}

return UseItemAction::Execute(event);
if (ai->IsDrinking())
return true;

bool result = UseItemAction::Execute(event);
if (result)
ai->SetDrinking();
return result;
}

virtual bool isPossible()
{
return ai->IsDrinking() || UseItemAction::isPossible();
}

virtual bool isUseful()
{
return UseItemAction::isUseful() && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.lowMana;
if (ai->IsDrinking())
return true;
return UseItemAction::isUseful() && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig.thirstyMana;
}
};

Expand All @@ -39,12 +52,25 @@ namespace ai
return false;
}

return UseItemAction::Execute(event);
if (ai->IsEating())
return true;

bool result = UseItemAction::Execute(event);
if (result)
ai->SetEating();
return result;
}

virtual bool isPossible()
{
return ai->IsEating() || UseItemAction::isPossible();
}

virtual bool isUseful()
{
return UseItemAction::isUseful() && AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig.lowHealth;
if (ai->IsEating())
return true;
return UseItemAction::isUseful() && AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig.hungryHealth;
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "botpch.h"
#include "../../playerbot.h"
#include "TradeStatusAction.h"
#include "UseItemAction.h"

#include "../ItemVisitors.h"
#include "../../PlayerbotAIConfig.h"
Expand Down
11 changes: 0 additions & 11 deletions src/modules/Bots/playerbot/strategy/actions/UseItemAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,6 @@ bool UseItemAction::UseItem(Item* item, ObjectGuid goGuid, Item* itemTarget)
return false;
}

if (item->GetProto()->Class == ITEM_CLASS_CONSUMABLE && item->GetProto()->SubClass == ITEM_SUBCLASS_FOOD)
{
if (bot->IsInCombat())
{
return false;
}

ai->InterruptSpell();
ai->SetNextCheckDelay(30000);
}

ai->TellMasterNoFacing(out.str());
bot->GetSession()->QueuePacket(packet);
return true;
Expand Down
Loading