mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 23:49:25 +02:00
fix(Core/RPG): Scope do-quest yield-to-grind to current objective only
This commit is contained in:
parent
8c027e3a70
commit
4e8e3e2afe
@ -331,8 +331,11 @@ bool NewRpgDoQuestAction::DoIncompleteQuest(NewRpgInfo::DoQuest& data)
|
|||||||
|
|
||||||
if (bot->GetDistance(data.pos) > 10.0f && !data.lastReachPOI)
|
if (bot->GetDistance(data.pos) > 10.0f && !data.lastReachPOI)
|
||||||
{
|
{
|
||||||
// yield to attack-anything if a quest mob is right next to us
|
// Yield to attack-anything ONLY if a mob needed by this exact
|
||||||
if (HasNearbyQuestMob(15.0f))
|
// quest+objective is right next to us. The broad variant (any
|
||||||
|
// quest in the log) yielded for every nearby mob and derailed
|
||||||
|
// turn-ins / cross-zone travel through other quests' clusters.
|
||||||
|
if (HasNearbyQuestMobForObjective(15.0f, data.questId, data.objectiveIdx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Note: previously yielded ~10%/tick when any hostile was
|
// Note: previously yielded ~10%/tick when any hostile was
|
||||||
|
|||||||
@ -1558,6 +1558,79 @@ bool NewRpgBaseAction::HasNearbyQuestMob(float range)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NewRpgBaseAction::HasNearbyQuestMobForObjective(float range, uint32 questId, int32 objectiveIdx)
|
||||||
|
{
|
||||||
|
if (!questId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||||
|
if (!quest)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Turn-in path: completed quest has no remaining mob objective.
|
||||||
|
if (bot->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QuestStatusData const& qs = bot->getQuestStatusMap().at(questId);
|
||||||
|
|
||||||
|
uint32 neededCreatureEntry = 0;
|
||||||
|
uint32 neededItemId = 0;
|
||||||
|
|
||||||
|
if (objectiveIdx >= 0 && objectiveIdx < QUEST_OBJECTIVES_COUNT)
|
||||||
|
{
|
||||||
|
int32 entry = quest->RequiredNpcOrGo[objectiveIdx];
|
||||||
|
if (entry > 0 &&
|
||||||
|
qs.CreatureOrGOCount[objectiveIdx] < quest->RequiredNpcOrGoCount[objectiveIdx])
|
||||||
|
{
|
||||||
|
neededCreatureEntry = uint32(entry);
|
||||||
|
}
|
||||||
|
// Item objective sometimes lives in the same slot range.
|
||||||
|
if (objectiveIdx < QUEST_ITEM_OBJECTIVES_COUNT &&
|
||||||
|
quest->RequiredItemId[objectiveIdx] &&
|
||||||
|
qs.ItemCount[objectiveIdx] < quest->RequiredItemCount[objectiveIdx])
|
||||||
|
{
|
||||||
|
neededItemId = quest->RequiredItemId[objectiveIdx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (objectiveIdx >= QUEST_OBJECTIVES_COUNT &&
|
||||||
|
objectiveIdx < QUEST_OBJECTIVES_COUNT + QUEST_ITEM_OBJECTIVES_COUNT)
|
||||||
|
{
|
||||||
|
int32 itemSlot = objectiveIdx - QUEST_OBJECTIVES_COUNT;
|
||||||
|
if (quest->RequiredItemId[itemSlot] &&
|
||||||
|
qs.ItemCount[itemSlot] < quest->RequiredItemCount[itemSlot])
|
||||||
|
{
|
||||||
|
neededItemId = quest->RequiredItemId[itemSlot];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!neededCreatureEntry && !neededItemId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
GuidVector possibleTargets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
for (ObjectGuid guid : possibleTargets)
|
||||||
|
{
|
||||||
|
Creature* c = botAI->GetCreature(guid);
|
||||||
|
if (!c || !c->IsInWorld() || !c->IsAlive())
|
||||||
|
continue;
|
||||||
|
if (!(c->GetPhaseMask() & bot->GetPhaseMask()))
|
||||||
|
continue;
|
||||||
|
if (bot->GetDistance(c) > range)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (neededCreatureEntry && c->GetEntry() == neededCreatureEntry)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (neededItemId)
|
||||||
|
{
|
||||||
|
CreatureTemplate const* tmpl = c->GetCreatureTemplate();
|
||||||
|
if (tmpl && tmpl->lootid &&
|
||||||
|
LootTemplates_Creature.HaveQuestLootForPlayer(tmpl->lootid, bot))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly, float distanceLimit)
|
ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly, float distanceLimit)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -68,6 +68,12 @@ protected:
|
|||||||
// travel so we yield to attack-anything instead of running past.
|
// travel so we yield to attack-anything instead of running past.
|
||||||
bool HasNearbyQuestMob(float range = 20.0f);
|
bool HasNearbyQuestMob(float range = 20.0f);
|
||||||
|
|
||||||
|
// Narrower variant: only yields for mobs needed by the SPECIFIC
|
||||||
|
// quest+objective the bot is currently working on. Without this,
|
||||||
|
// do-quest yields for any quest in the log, derailing turn-ins
|
||||||
|
// and cross-zone travel through other quests' mob clusters.
|
||||||
|
bool HasNearbyQuestMobForObjective(float range, uint32 questId, int32 objectiveIdx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool GetQuestPOIPosAndObjectiveIdx(uint32 questId, std::vector<POIInfo>& poiInfo, bool toComplete = false);
|
bool GetQuestPOIPosAndObjectiveIdx(uint32 questId, std::vector<POIInfo>& poiInfo, bool toComplete = false);
|
||||||
static WorldPosition SelectRandomGrindPos(Player* bot);
|
static WorldPosition SelectRandomGrindPos(Player* bot);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user