mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
feat(Core/Loot): Loot wild quest game objects
This commit is contained in:
parent
7318396256
commit
d35e0da5d9
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "LootAction.h"
|
#include "LootAction.h"
|
||||||
|
|
||||||
|
#include "Bag.h"
|
||||||
#include "ChatHelper.h"
|
#include "ChatHelper.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "GuildMgr.h"
|
#include "GuildMgr.h"
|
||||||
@ -139,8 +140,9 @@ bool OpenLootAction::DoLoot(LootObject& lootObject)
|
|||||||
if (go && (go->GetGoState() != GO_STATE_READY))
|
if (go && (go->GetGoState() != GO_STATE_READY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// This prevents dungeon chests like Tribunal Chest (Halls of Stone) from being ninja'd by the bots
|
// Block event-gated chests (Tribunal Chest, Gunship Armory) but allow
|
||||||
if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND))
|
// wild quest GOs (Moonpetal Lily etc.) when the bot is on the quest.
|
||||||
|
if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND) && !lootObject.isNeededQuestItem)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// This prevents raid chests like Gunship Armory (ICC) from being ninja'd by the bots
|
// This prevents raid chests like Gunship Armory (ICC) from being ninja'd by the bots
|
||||||
|
|||||||
@ -45,7 +45,8 @@ void LootTargetList::shrink(time_t fromTime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LootObject::LootObject(Player* bot, ObjectGuid guid) : guid(), skillId(SKILL_NONE), reqSkillValue(0), reqItem(0)
|
LootObject::LootObject(Player* bot, ObjectGuid guid)
|
||||||
|
: guid(), skillId(SKILL_NONE), reqSkillValue(0), reqItem(0), isNeededQuestItem(false)
|
||||||
{
|
{
|
||||||
Refresh(bot, guid);
|
Refresh(bot, guid);
|
||||||
}
|
}
|
||||||
@ -55,6 +56,7 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
|
|||||||
skillId = SKILL_NONE;
|
skillId = SKILL_NONE;
|
||||||
reqSkillValue = 0;
|
reqSkillValue = 0;
|
||||||
reqItem = 0;
|
reqItem = 0;
|
||||||
|
isNeededQuestItem = false;
|
||||||
guid.Clear();
|
guid.Clear();
|
||||||
|
|
||||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||||
@ -101,6 +103,7 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
|
|||||||
if (IsNeededForQuest(bot, itemId))
|
if (IsNeededForQuest(bot, itemId))
|
||||||
{
|
{
|
||||||
this->guid = lootGUID;
|
this->guid = lootGUID;
|
||||||
|
this->isNeededQuestItem = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +138,21 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
|
|||||||
if (!proto)
|
if (!proto)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Moonpetal Lily, Hyacinth Mushroom etc. expose quest
|
||||||
|
// drops here (not in gameobject_questitem). Flag it so
|
||||||
|
// the INTERACT_COND gate lets the bot through.
|
||||||
|
if (IsNeededForQuest(bot, itemId))
|
||||||
|
{
|
||||||
|
this->guid = lootGUID;
|
||||||
|
this->isNeededQuestItem = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (proto->Class != ITEM_CLASS_QUEST)
|
if (proto->Class != ITEM_CLASS_QUEST)
|
||||||
{
|
{
|
||||||
onlyHasQuestItems = false;
|
onlyHasQuestItems = false;
|
||||||
break;
|
// keep scanning — a later item may be needed
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this item references another loot table, process it
|
// If this item references another loot table, process it
|
||||||
@ -157,11 +171,15 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
|
|||||||
if (!refProto)
|
if (!refProto)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (refProto->Class != ITEM_CLASS_QUEST)
|
if (IsNeededForQuest(bot, refItemId))
|
||||||
{
|
{
|
||||||
onlyHasQuestItems = false;
|
this->guid = lootGUID;
|
||||||
break;
|
this->isNeededQuestItem = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (refProto->Class != ITEM_CLASS_QUEST)
|
||||||
|
onlyHasQuestItems = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,6 +288,7 @@ LootObject::LootObject(LootObject const& other)
|
|||||||
skillId = other.skillId;
|
skillId = other.skillId;
|
||||||
reqSkillValue = other.reqSkillValue;
|
reqSkillValue = other.reqSkillValue;
|
||||||
reqItem = other.reqItem;
|
reqItem = other.reqItem;
|
||||||
|
isNeededQuestItem = other.isNeededQuestItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LootObject::IsLootPossible(Player* bot)
|
bool LootObject::IsLootPossible(Player* bot)
|
||||||
@ -299,10 +318,13 @@ bool LootObject::IsLootPossible(Player* bot)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent bot from running to chests that are unlootable (e.g. Gunship Armory before completing the event) or on
|
// Block event-gated chests (Gunship Armory pre-event) and unspawned
|
||||||
// respawn time
|
// GOs. INTERACT_COND alone is allowed when the GO holds a quest
|
||||||
|
// item we need — ConditionMgr already gates on quest state.
|
||||||
GameObject* go = botAI->GetGameObject(guid);
|
GameObject* go = botAI->GetGameObject(guid);
|
||||||
if (go && (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE) || !go->isSpawned()))
|
if (go && (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE) || !go->isSpawned()))
|
||||||
|
return false;
|
||||||
|
if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND) && !isNeededQuestItem)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (skillId == SKILL_NONE)
|
if (skillId == SKILL_NONE)
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public:
|
|||||||
class LootObject
|
class LootObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LootObject() : skillId(0), reqSkillValue(0), reqItem(0) {}
|
LootObject() : skillId(0), reqSkillValue(0), reqItem(0), isNeededQuestItem(false) {}
|
||||||
LootObject(Player* bot, ObjectGuid guid);
|
LootObject(Player* bot, ObjectGuid guid);
|
||||||
LootObject(LootObject const& other);
|
LootObject(LootObject const& other);
|
||||||
LootObject& operator=(LootObject const& other) = default;
|
LootObject& operator=(LootObject const& other) = default;
|
||||||
@ -40,6 +40,9 @@ public:
|
|||||||
uint32 skillId;
|
uint32 skillId;
|
||||||
uint32 reqSkillValue;
|
uint32 reqSkillValue;
|
||||||
uint32 reqItem;
|
uint32 reqItem;
|
||||||
|
// GO holds a quest item we still need; lets us bypass the
|
||||||
|
// INTERACT_COND blanket reject in the loot path
|
||||||
|
bool isNeededQuestItem;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool IsNeededForQuest(Player* bot, uint32 itemId);
|
static bool IsNeededForQuest(Player* bot, uint32 itemId);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user