mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
ItemUsageValue: Handle items that create required items (#1091)
* Updated IsItemUsefulForQuest to handle items that create required quest items * Debug output * Removed unneeded botAI-> * Debug output in Calculate * -> not . * Comprehensive debug output for quest usage * Corrected logic for lootable items when sync quest is enabled * #include "LootObjectStack.h" * Corrected call to IsItem * Removed debug statements * Reimplement ItemCount >= RequiredItemCount * Modified CanLoot to loot all items when loot source is an item in their bags * Set loot target when sending Open packet
This commit is contained in:
@@ -4,6 +4,9 @@
|
|||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
|
#include "LootObjectStack.h"
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
|
||||||
bool OpenItemAction::Execute(Event event)
|
bool OpenItemAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
bool foundOpenable = false;
|
bool foundOpenable = false;
|
||||||
@@ -27,6 +30,11 @@ void OpenItemAction::OpenItem(Item* item, uint8 bag, uint8 slot)
|
|||||||
packet << bag << slot;
|
packet << bag << slot;
|
||||||
bot->GetSession()->HandleOpenItemOpcode(packet);
|
bot->GetSession()->HandleOpenItemOpcode(packet);
|
||||||
|
|
||||||
|
// Store the item GUID as the loot target
|
||||||
|
LootObject lootObject;
|
||||||
|
lootObject.guid = item->GetGUID();
|
||||||
|
botAI->GetAiObjectContext()->GetValue<LootObject>("loot target")->Set(lootObject);
|
||||||
|
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "Opened item: " << item->GetTemplate()->Name1;
|
out << "Opened item: " << item->GetTemplate()->Name1;
|
||||||
botAI->TellMaster(out.str());
|
botAI->TellMaster(out.str());
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "AiFactory.h"
|
#include "AiFactory.h"
|
||||||
#include "ChatHelper.h"
|
#include "ChatHelper.h"
|
||||||
#include "GuildTaskMgr.h"
|
#include "GuildTaskMgr.h"
|
||||||
|
#include "LootObjectStack.h"
|
||||||
#include "PlayerbotAIConfig.h"
|
#include "PlayerbotAIConfig.h"
|
||||||
#include "PlayerbotFactory.h"
|
#include "PlayerbotFactory.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
@@ -112,11 +113,37 @@ ItemUsage ItemUsageValue::Calculate()
|
|||||||
return ITEM_USAGE_DISENCHANT;
|
return ITEM_USAGE_DISENCHANT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// While sync is on, do not loot quest items that are also Useful for master. Master
|
Player* master = botAI->GetMaster();
|
||||||
if (!botAI->GetMaster() || !sPlayerbotAIConfig->syncQuestWithPlayer ||
|
bool isSelfBot = (master == bot);
|
||||||
!IsItemUsefulForQuest(botAI->GetMaster(), proto))
|
bool botNeedsItemForQuest = IsItemUsefulForQuest(bot, proto);
|
||||||
if (IsItemUsefulForQuest(bot, proto))
|
bool masterNeedsItemForQuest = master && sPlayerbotAIConfig->syncQuestWithPlayer && IsItemUsefulForQuest(master, proto);
|
||||||
|
|
||||||
|
// Identify the source of loot
|
||||||
|
LootObject lootObject = AI_VALUE(LootObject, "loot target");
|
||||||
|
|
||||||
|
// Get GUID of loot source
|
||||||
|
ObjectGuid lootGuid = lootObject.guid;
|
||||||
|
|
||||||
|
// Check if loot source is an item
|
||||||
|
bool isLootFromItem = lootGuid.IsItem();
|
||||||
|
|
||||||
|
// If the loot is from an item in the bot’s bags, ignore syncQuestWithPlayer
|
||||||
|
if (isLootFromItem && botNeedsItemForQuest)
|
||||||
|
{
|
||||||
return ITEM_USAGE_QUEST;
|
return ITEM_USAGE_QUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the bot is NOT acting alone and the master needs this quest item, defer to the master
|
||||||
|
if (!isSelfBot && masterNeedsItemForQuest)
|
||||||
|
{
|
||||||
|
return ITEM_USAGE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the bot itself needs the item for a quest, allow looting
|
||||||
|
if (botNeedsItemForQuest)
|
||||||
|
{
|
||||||
|
return ITEM_USAGE_QUEST;
|
||||||
|
}
|
||||||
|
|
||||||
if (proto->Class == ITEM_CLASS_PROJECTILE && bot->CanUseItem(proto) == EQUIP_ERR_OK)
|
if (proto->Class == ITEM_CLASS_PROJECTILE && bot->CanUseItem(proto) == EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
@@ -464,6 +491,10 @@ uint32 ItemUsageValue::GetSmallestBagSize()
|
|||||||
|
|
||||||
bool ItemUsageValue::IsItemUsefulForQuest(Player* player, ItemTemplate const* proto)
|
bool ItemUsageValue::IsItemUsefulForQuest(Player* player, ItemTemplate const* proto)
|
||||||
{
|
{
|
||||||
|
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
||||||
|
if (!botAI)
|
||||||
|
return false;
|
||||||
|
|
||||||
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
||||||
{
|
{
|
||||||
uint32 entry = player->GetQuestSlotQuestId(slot);
|
uint32 entry = player->GetQuestSlotQuestId(slot);
|
||||||
@@ -471,20 +502,52 @@ bool ItemUsageValue::IsItemUsefulForQuest(Player* player, ItemTemplate const* pr
|
|||||||
if (!quest)
|
if (!quest)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Check if the item itself is needed for the quest
|
||||||
for (uint8 i = 0; i < 4; i++)
|
for (uint8 i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (quest->RequiredItemId[i] != proto->ItemId)
|
if (quest->RequiredItemId[i] == proto->ItemId)
|
||||||
|
{
|
||||||
|
if (AI_VALUE2(uint32, "item count", proto->Name1) >= quest->RequiredItemCount[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GET_PLAYERBOT_AI(player) &&
|
return true; // Item is directly required for a quest
|
||||||
AI_VALUE2(uint32, "item count", proto->Name1) >= quest->RequiredItemCount[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Check if the item has spells that create a required quest item
|
||||||
|
for (uint8 i = 0; i < MAX_ITEM_SPELLS; i++)
|
||||||
|
{
|
||||||
|
uint32 spellId = proto->Spells[i].SpellId;
|
||||||
|
if (!spellId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||||
|
if (!spellInfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (uint8 effectIndex = 0; effectIndex < MAX_SPELL_EFFECTS; effectIndex++)
|
||||||
|
{
|
||||||
|
if (spellInfo->Effects[effectIndex].Effect == SPELL_EFFECT_CREATE_ITEM)
|
||||||
|
{
|
||||||
|
uint32 createdItemId = spellInfo->Effects[effectIndex].ItemType;
|
||||||
|
|
||||||
|
// Check if the created item is required for a quest
|
||||||
|
for (uint8 j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
if (quest->RequiredItemId[j] == createdItemId)
|
||||||
|
{
|
||||||
|
if (AI_VALUE2(uint32, "item count", createdItemId) >= quest->RequiredItemCount[j])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return true; // Item is useful because it creates a required quest item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Item is not useful for any active quests
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemUsageValue::IsItemNeededForSkill(ItemTemplate const* proto)
|
bool ItemUsageValue::IsItemNeededForSkill(ItemTemplate const* proto)
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ class NormalLootStrategy : public LootStrategy
|
|||||||
public:
|
public:
|
||||||
bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) override
|
bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) override
|
||||||
{
|
{
|
||||||
|
// Identify the source of loot, loot it if the source is an item in the bots inventory
|
||||||
|
LootObject lootObject = AI_VALUE(LootObject, "loot target");
|
||||||
|
ObjectGuid lootGuid = lootObject.guid;
|
||||||
|
if (lootGuid.IsItem())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, continue with the normal loot logic
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << proto->ItemId;
|
out << proto->ItemId;
|
||||||
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str());
|
ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", out.str());
|
||||||
|
|||||||
Reference in New Issue
Block a user