diff --git a/src/strategy/actions/ChooseTravelTargetAction.cpp b/src/strategy/actions/ChooseTravelTargetAction.cpp index 9b700a85..7846df53 100644 --- a/src/strategy/actions/ChooseTravelTargetAction.cpp +++ b/src/strategy/actions/ChooseTravelTargetAction.cpp @@ -41,63 +41,129 @@ bool ChooseTravelTargetAction::Execute(Event event) void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarget* oldTarget) { bool foundTarget = false; - foundTarget = SetGroupTarget(newTarget); //Join groups members + //Empty bags/repair + if (!foundTarget && urand(1, 100) > 10) //90% chance + { + if (AI_VALUE2(bool, "group or", "should sell,can sell,following party,near leader") || + AI_VALUE2(bool, "group or", "should repair,can repair,following party,near leader") || + (AI_VALUE2(bool, "group or", "should sell,can ah sell,following party,near leader") && bot->GetLevel() > 5)) + { + foundTarget = SetRpgTarget(newTarget); //Go to town to sell items or repair + } + } + + //Rpg in city + if (!foundTarget && urand(1, 100) > 90 && bot->GetLevel() > 5) //10% chance + { + foundTarget = SetNpcFlagTarget(newTarget, { UNIT_NPC_FLAG_BANKER,UNIT_NPC_FLAG_BATTLEMASTER,UNIT_NPC_FLAG_AUCTIONEER }); + } + + // PvP activities + bool pvpActivate = false; + if (pvpActivate && !foundTarget && urand(0, 4) && bot->GetLevel() > 50) + { + WorldPosition pos = WorldPosition(bot); + WorldPosition* botPos = &pos; + TravelTarget* target = context->GetValue("travel target")->Get(); + + TravelDestination* dest = ChooseTravelTargetAction::FindDestination(bot, "Tarren Mill"); + if (dest) + { + std::vector points = dest->nextPoint(botPos, true); + if (!points.empty()) + { + target->setTarget(dest, points.front()); + target->setForced(true); + + std::ostringstream out; out << "Traveling to " << dest->getTitle(); + botAI->TellMasterNoFacing(out.str()); + foundTarget = true; + } + } + } + + //Grind for money + if (!foundTarget && AI_VALUE(bool, "should get money")) + { + //Empty mail for money + //if (AI_VALUE(bool, "can get mail")) + //{ + // foundTarget = SetGOTypeTarget(requester, newTarget, GAMEOBJECT_TYPE_MAILBOX, "", false); //Find a mailbox + //} + + if (!foundTarget) + { + if (urand(1, 100) > 50) //50% Focus on active quests for money. + { + if (urand(1, 100) > 50) //50% Focus on active quests for money. + { + foundTarget = SetQuestTarget(newTarget, false, true, true); //Turn in quests for money. + } + + if (!foundTarget) + { + foundTarget = SetQuestTarget(newTarget, true, false, false); //Find new (low) level quests + } + } + else + { + foundTarget = SetGrindTarget(newTarget); //Go grind mobs for money + } + } + } + + + //Continue current target. + if (!foundTarget && urand(1, 100) > 10) //90% chance + { + foundTarget = SetCurrentTarget(newTarget, oldTarget); //Extend current target. + } + + //Get mail + //if (!foundTarget && urand(1, 100) > 70) //30% chance + //{ + // if (AI_VALUE(bool, "can get mail")) + // { + // foundTarget = SetGOTypeTarget(requester, newTarget, GAMEOBJECT_TYPE_MAILBOX, "", false); //Find a mailbox + // } + //} + + //Dungeon in group. + if (!foundTarget && urand(1, 100) > 50) //50% chance + if (AI_VALUE(bool, "can fight boss")) + { + foundTarget = SetBossTarget( newTarget); //Go fight a (dungeon boss) + } + //Do quests (start, do, end) if (!foundTarget && urand(1, 100) > 5) //95% chance { - foundTarget = SetQuestTarget(newTarget, false); //Do any nearby - } - //Enpty bags/repair - if (!foundTarget && urand(1, 100) > 10) //90% chance - if (AI_VALUE2(bool, "group or", "should sell,can sell,following party,near leader") || AI_VALUE2(bool, "group or", "should repair,can repair,following party,near leader")) - foundTarget = SetRpgTarget(newTarget); //Go to town to sell items or repair - - //Rpg in city - if (!foundTarget && urand(1, 100) > 90) //10% chance - foundTarget = SetNpcFlagTarget(newTarget, { UNIT_NPC_FLAG_BANKER,UNIT_NPC_FLAG_BATTLEMASTER,UNIT_NPC_FLAG_AUCTIONEER }); - - //Grind for money - if (!foundTarget && AI_VALUE(bool, "should get money")) { - if (urand(1, 100) > 66) - { - foundTarget = SetQuestTarget(newTarget, true); //Turn in quests for money. - - if (!foundTarget) - foundTarget = SetQuestTarget(newTarget); //Do low level quests - } - else if (urand(1, 100) > 50) { - foundTarget = SetGrindTarget(newTarget); //Go grind mobs for money - } - else { - foundTarget = SetNewQuestTarget(newTarget); //Find a low level quest to do - } + foundTarget = SetQuestTarget(newTarget, true, true, true); //Do any nearby } - //Continue - if (!foundTarget && urand(1, 100) > 10) //90% chance - foundTarget = SetCurrentTarget(newTarget, oldTarget); //Extend current target. - - //Dungeon in group - if (!foundTarget && urand(1, 100) > 50) //50% chance - if (AI_VALUE(bool, "can fight boss")) - foundTarget = SetBossTarget(newTarget); //Go fight a (dungeon boss) - - if (!foundTarget && urand(1, 100) > 5) //95% chance - foundTarget = SetQuestTarget(newTarget); //Do a target of an active quest. - - if (!foundTarget && urand(1, 100) > 5) - foundTarget = SetNewQuestTarget(newTarget); //Find a new quest to do. - - if (!foundTarget && botAI->HasStrategy("explore", BOT_STATE_NON_COMBAT)) //Explore a unexplored sub-zone. + //Explore a nearby unexplored area. + if (!foundTarget && botAI->HasStrategy("explore", BotState::BOT_STATE_NON_COMBAT) && urand(1, 100) > 90) //10% chance Explore a unexplored sub-zone. + { foundTarget = SetExploreTarget(newTarget); + } - // if (!foundTarget) - //foundTarget = SetRpgTarget(target); + //Just hang with an npc + if (!foundTarget && urand(1, 100) > 50) //50% chance + { + foundTarget = SetRpgTarget(newTarget); + if (foundTarget) + newTarget->setForced(true); + } if (!foundTarget) - SetNullTarget(newTarget); //Idle a bit. + { + foundTarget = SetGrindTarget(newTarget); + } + + if (!foundTarget) + SetNullTarget(newTarget); //Idle a bit. } void ChooseTravelTargetAction::setNewTarget(TravelTarget* newTarget, TravelTarget* oldTarget) @@ -396,44 +462,56 @@ bool ChooseTravelTargetAction::SetCurrentTarget(TravelTarget* target, TravelTarg return target->isActive(); } -bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCompleted) +bool ChooseTravelTargetAction::SetQuestTarget(TravelTarget* target, bool onlyCompleted, bool newQuests, bool activeQuests, bool completedQuests) { std::vector activeDestinations; std::vector activePoints; - - QuestStatusMap& questMap = bot->getQuestStatusMap(); - WorldPosition botLocation(bot); + bool onlyClassQuest = !urand(0, 10); - //Find destinations related to the active quests. - for (auto& quest : questMap) + if (newQuests) { - if (bot->IsQuestRewarded(quest.first)) - continue; - - uint32 questId = quest.first; - QuestStatusData* questStatus = &quest.second; - - if (onlyCompleted && sObjectMgr->GetQuestTemplate(questId) && !bot->CanRewardQuest(sObjectMgr->GetQuestTemplate(questId), false)) - continue; - - std::vector questDestinations = sTravelMgr->getQuestTravelDestinations(bot, questId, botAI->HasRealPlayerMaster(), false, 5000); - std::vector questPoints; - - for (auto& questDestination : questDestinations) - { - std::vector destinationPoints = questDestination->getPoints(); - if (!destinationPoints.empty()) - questPoints.insert(questPoints.end(), destinationPoints.begin(), destinationPoints.end()); - } - - if (getBestDestination(&questDestinations, &questPoints)) - { - activeDestinations.push_back(questDestinations.front()); - activePoints.push_back(questPoints.front()); - } - + activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10); //Prefer new quests near the player at lower levels. } + if (activeQuests || completedQuests) + { + QuestStatusMap& questMap = bot->getQuestStatusMap(); + //Find destinations related to the active quests. + for (auto& quest : questMap) + { + if (bot->IsQuestRewarded(quest.first)) + continue; + + uint32 questId = quest.first; + QuestStatusData* questStatus = &quest.second; + const auto questTemplate = sObjectMgr->GetQuestTemplate(questId); + + if (!activeQuests && !bot->CanRewardQuest(questTemplate, false)) + continue; + + if (!completedQuests && bot->CanRewardQuest(questTemplate, false)) + continue; + + //Find quest takers or objectives + std::vector questDestinations = sTravelMgr->getQuestTravelDestinations(bot, questId, true, false, 0); + + if (onlyClassQuest && activeDestinations.size() && questDestinations.size()) //Only do class quests if we have any. + { + if (activeDestinations.front()->GetQuestTemplate()->GetRequiredClasses() && !questTemplate->GetRequiredClasses()) + continue; + + if (!activeDestinations.front()->GetQuestTemplate()->GetRequiredClasses() && questTemplate->GetRequiredClasses()) + activeDestinations.clear(); + } + + activeDestinations.insert(activeDestinations.end(), questDestinations.begin(), questDestinations.end()); + } + } + if (newQuests && activeDestinations.empty()) + activeDestinations = sTravelMgr->getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away. + + if (botAI->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) + botAI->TellMasterNoFacing(std::to_string(activeDestinations.size()) + " quest destinations found."); if (!getBestDestination(&activeDestinations, &activePoints)) return false; diff --git a/src/strategy/actions/ChooseTravelTargetAction.h b/src/strategy/actions/ChooseTravelTargetAction.h index a17630ed..f4350092 100644 --- a/src/strategy/actions/ChooseTravelTargetAction.h +++ b/src/strategy/actions/ChooseTravelTargetAction.h @@ -30,10 +30,9 @@ class ChooseTravelTargetAction : public MovementAction void ReportTravelTarget(TravelTarget* newTarget, TravelTarget* oldTarget); bool getBestDestination(std::vector* activeDestinations, std::vector* activePoints); - bool SetGroupTarget(TravelTarget* target); bool SetCurrentTarget(TravelTarget* target, TravelTarget* oldTarget); - bool SetQuestTarget(TravelTarget* target, bool onlyCompleted = false); + bool SetQuestTarget(TravelTarget* target, bool onlyCompleted = false, bool newQuests = true, bool activeQuests = true, bool completedQuests = true); bool SetNewQuestTarget(TravelTarget* target); bool SetRpgTarget(TravelTarget* target); bool SetGrindTarget(TravelTarget* target); diff --git a/src/strategy/actions/DropQuestAction.cpp b/src/strategy/actions/DropQuestAction.cpp index 100163a9..c659fec6 100644 --- a/src/strategy/actions/DropQuestAction.cpp +++ b/src/strategy/actions/DropQuestAction.cpp @@ -47,8 +47,9 @@ bool DropQuestAction::Execute(Event event) if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) { const Quest* pQuest = sObjectMgr->GetQuestTemplate(entry); - LOG_INFO("playerbots", "Quest [ {} ] dropped", pQuest->GetTitle()); - bot->Say("Quest [ " + ChatHelper::FormatQuest(pQuest) + " ] dropped", LANG_UNIVERSAL); + const std::string text_quest = ChatHelper::FormatQuest(pQuest); + LOG_INFO("playerbots", "Quest [ {} ] removed", pQuest->GetTitle()); + bot->Say("Quest [ " + text_quest + " ] removed", LANG_UNIVERSAL); } botAI->TellMaster("Quest removed"); @@ -57,7 +58,8 @@ bool DropQuestAction::Execute(Event event) bool CleanQuestLogAction::Execute(Event event) { - std::string const link = event.getParam(); + Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); + std::string link = event.getParam(); if (botAI->HasActivePlayerMaster()) return false; @@ -66,13 +68,16 @@ bool CleanQuestLogAction::Execute(Event event) DropQuestType(totalQuests); //Count the total quests if (MAX_QUEST_LOG_SIZE - totalQuests > 6) - return true; - - if (AI_VALUE(bool, "can fight equal")) // Only drop gray quests when able to fight proper lvl quests. { - DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6); // Drop gray/red quests. - DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6, false, true); // Drop gray/red quests with progress. - DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6, false, true, true); // Drop gray/red completed quests. + DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE, true, true); //Drop failed quests + return true; + } + + if (AI_VALUE(bool, "can fight equal")) //Only drop gray quests when able to fight proper lvl quests. + { + DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6); //Drop gray/red quests. + DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6, false, true); //Drop gray/red quests with progress. + DropQuestType(totalQuests, MAX_QUEST_LOG_SIZE - 6, false, true, true); //Drop gray/red completed quests. } if (MAX_QUEST_LOG_SIZE - totalQuests > 4) @@ -128,13 +133,13 @@ void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isG continue; } - if (HasProgress(bot, quest) && !hasProgress) + if (HasProgress(bot, quest) && !hasProgress && bot->GetQuestStatus(questId) != QUEST_STATUS_FAILED) continue; if (bot->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE && !isComplete) continue; - if (numQuest <= wantNum && bot->GetQuestStatus(questId) != QUEST_STATUS_FAILED) // Always drop failed quests + if (numQuest <= wantNum && bot->GetQuestStatus(questId) != QUEST_STATUS_FAILED) continue; //Drop quest. diff --git a/src/strategy/actions/QuestAction.cpp b/src/strategy/actions/QuestAction.cpp index 676844f8..978654e6 100644 --- a/src/strategy/actions/QuestAction.cpp +++ b/src/strategy/actions/QuestAction.cpp @@ -132,14 +132,16 @@ bool QuestAction::CompleteQuest(Player* player, uint32 entry) player->ModifyMoney(-ReqOrRewMoney); } - player->CompleteQuest(entry); + const std::string text_quest = ChatHelper::FormatQuest(pQuest); if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) { LOG_INFO("playerbots", "Quest [ {} ] completed", pQuest->GetTitle()); - bot->Say("Quest [ " + ChatHelper::FormatQuest(pQuest) + " ] completed", LANG_UNIVERSAL); + bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); } + botAI->TellMasterNoFacing("Quest completed " + text_quest); + + player->CompleteQuest(entry); - botAI->TellMasterNoFacing("Quest completed " + ChatHelper::FormatQuest(pQuest)); return true; } @@ -249,12 +251,13 @@ bool QuestUpdateCompleteAction::Execute(Event event) Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId); if (qInfo) { + const std::string text_quest = ChatHelper::FormatQuest(qInfo); if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) { LOG_INFO("playerbots", "Quest [ {} ] completed", qInfo->GetTitle()); - bot->Say("Quest [ " + ChatHelper::FormatQuest(qInfo) + " ] completed", LANG_UNIVERSAL); + bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); } - botAI->TellMasterNoFacing("Quest completed " + ChatHelper::FormatQuest(qInfo)); + botAI->TellMasterNoFacing("Quest completed " + text_quest); } return true; diff --git a/src/strategy/actions/TalkToQuestGiverAction.cpp b/src/strategy/actions/TalkToQuestGiverAction.cpp index 000aad98..997959be 100644 --- a/src/strategy/actions/TalkToQuestGiverAction.cpp +++ b/src/strategy/actions/TalkToQuestGiverAction.cpp @@ -49,7 +49,7 @@ bool TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver out << "|cffff0000Incompleted|r"; break; case QUEST_STATUS_NONE: - AcceptQuest(quest, questGiver->GetGUID()); + //AcceptQuest(quest, questGiver->GetGUID()); out << "|cff00ff00Available|r"; break; case QUEST_STATUS_FAILED: @@ -83,6 +83,14 @@ bool TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver, RewardMultipleItem(quest, questGiver, out); } + if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) + { + const Quest* pQuest = sObjectMgr->GetQuestTemplate(questID); + const std::string text_quest = ChatHelper::FormatQuest(pQuest); + LOG_INFO("playerbots", "Quest [ {} ] completed", pQuest->GetTitle()); + bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); + } + return true; } @@ -257,6 +265,7 @@ bool TurnInQueryQuestAction::Execute(Event event) out << "|cffff0000Incompleted|r"; break; case QUEST_STATUS_NONE: + //AcceptQuest(quest, object->GetGUID()); out << "|cff00ff00Available|r"; break; case QUEST_STATUS_FAILED: