diff --git a/playerbot/PlayerbotAI.cpp b/playerbot/PlayerbotAI.cpp index dd52382f..36788b89 100644 --- a/playerbot/PlayerbotAI.cpp +++ b/playerbot/PlayerbotAI.cpp @@ -1191,7 +1191,7 @@ void PlayerbotAI::Reset(bool full) aiObjectContext->GetValue("last area trigger")->Get().Set(NULL); aiObjectContext->GetValue("last taxi")->Get().Set(NULL); - aiObjectContext->GetValue("travel target")->Get()->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(aiObjectContext->GetValue("travel target")->Get()); aiObjectContext->GetValue("travel target")->Get()->setStatus(TravelStatus::TRAVEL_STATUS_EXPIRED); aiObjectContext->GetValue("travel target")->Get()->setExpireIn(1000); diff --git a/playerbot/PlayerbotAIConfig.cpp b/playerbot/PlayerbotAIConfig.cpp index 10e79ff7..fea5f5f9 100644 --- a/playerbot/PlayerbotAIConfig.cpp +++ b/playerbot/PlayerbotAIConfig.cpp @@ -766,7 +766,7 @@ bool PlayerbotAIConfig::Initialize() targetPosRecalcDistance = config.GetFloatDefault("AiPlayerbot.TargetPosRecalcDistance", 0.1f), sLog.outString("Loading area levels."); - sTravelMgr.loadAreaLevels(); + sTravelMgr.LoadAreaLevels(); sLog.outString("Loading spellIds."); ChatHelper::PopulateSpellNameList(); ItemUsageValue::PopulateProfessionReagentIds(); diff --git a/playerbot/RandomPlayerbotMgr.cpp b/playerbot/RandomPlayerbotMgr.cpp index 756384c5..565b30e6 100644 --- a/playerbot/RandomPlayerbotMgr.cpp +++ b/playerbot/RandomPlayerbotMgr.cpp @@ -2105,7 +2105,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector tlocs.erase(std::remove_if(tlocs.begin(), tlocs.end(), [](const WorldPosition& l) {std::vector::iterator i = find(sPlayerbotAIConfig.randomBotMaps.begin(), sPlayerbotAIConfig.randomBotMaps.end(), l.getMapId()); return i == sPlayerbotAIConfig.randomBotMaps.end(); }), tlocs.end()); //Random shuffle based on distance. Closer distances are more likely (but not exclusively) to be at the begin of the list. - tlocs = sTravelMgr.getNextPoint(WorldPosition(bot), tlocs, 0); + tlocs = WorldPosition(bot).GetNextPoint(tlocs, 0); //5% + 0.1% per level chance node on different map in selection. //tlocs.erase(std::remove_if(tlocs.begin(), tlocs.end(), [bot](WorldLocation const& l) {return l.mapid != bot->GetMapId() && urand(1, 100) > 0.5 * bot->GetLevel(); }), tlocs.end()); @@ -3700,7 +3700,7 @@ void RandomPlayerbotMgr::RandomTeleportForRpg(Player* bot, bool activeOnly) AiObjectContext* context = bot->GetPlayerbotAI()->GetAiObjectContext(); TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); - travelTarget->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(travelTarget); travelTarget->setStatus(TravelStatus::TRAVEL_STATUS_COOLDOWN); travelTarget->setExpireIn(10 * MINUTE * IN_MILLISECONDS); } diff --git a/playerbot/TravelMgr.cpp b/playerbot/TravelMgr.cpp index f6a334d0..286a28b4 100644 --- a/playerbot/TravelMgr.cpp +++ b/playerbot/TravelMgr.cpp @@ -50,14 +50,14 @@ std::vector TravelDestination::SortedPoints(WorldPosition* pos) */ std::vector TravelDestination::NextPoint(const WorldPosition& pos) const { - return sTravelMgr.getNextPoint(pos, GetPoints()); + return pos.GetNextPoint(GetPoints()); } std::string QuestTravelDestination::GetTitle() const { return ChatHelper::formatQuest(GetQuestTemplate()); } -bool QuestRelationTravelDestination::IsActive(const Player* bot) const { +bool QuestRelationTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); if (!ai->HasStrategy("rpg quest", BotState::BOT_STATE_NON_COMBAT)) @@ -154,7 +154,7 @@ std::string QuestRelationTravelDestination::GetTitle() const { return out.str(); } -bool QuestObjectiveTravelDestination::IsActive(const Player* bot) const { +bool QuestObjectiveTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); @@ -242,9 +242,6 @@ bool QuestObjectiveTravelDestination::IsActive(const Player* bot) const { if (!AI_VALUE2(bool, "group or", "following party,near leader,need quest objective::" + Qualified::MultiQualify(qualifier,","))) //Noone needs the quest objective. return false; - if (!sTravelMgr.getObjectiveStatus(bot, GetQuestTemplate(), GetSubEntry())) - return false; - WorldPosition botPos(bot); if (!isVendor && GetEntry() > 0 && !IsOut(botPos)) @@ -283,7 +280,7 @@ std::string QuestObjectiveTravelDestination::GetTitle() const { return out.str(); } -bool RpgTravelDestination::IsActive(const Player* bot) const +bool RpgTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); @@ -339,7 +336,7 @@ bool RpgTravelDestination::IsActive(const Player* bot) const return false; //Once the target rpged with it is added to the ignore list. We can now move on. - std::set& ignoreList = bot->GetPlayerbotAI()->GetAiObjectContext()->GetValue&>("ignore rpg target")->Get(); + std::set& ignoreList = AI_VALUE(std::set&,"ignore rpg target"); for (auto& i : ignoreList) { @@ -379,7 +376,7 @@ std::string RpgTravelDestination::GetTitle() const return out.str(); } -bool ExploreTravelDestination::IsActive(const Player* bot) const +bool ExploreTravelDestination::IsActive(Player* bot) const { AreaTableEntry const* area = GetAreaEntryByAreaID(GetEntry()); @@ -396,7 +393,7 @@ bool ExploreTravelDestination::IsActive(const Player* bot) const return !(currFields & val); } -bool GrindTravelDestination::IsActive(const Player* bot) const +bool GrindTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); @@ -447,7 +444,7 @@ std::string GrindTravelDestination::GetTitle() const return out.str(); } -bool BossTravelDestination::IsActive(const Player* bot) const +bool BossTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); @@ -521,7 +518,7 @@ std::string BossTravelDestination::GetTitle() const return out.str(); } -bool GatherTravelDestination::IsActive(const Player* bot) const +bool GatherTravelDestination::IsActive(Player* bot) const { PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); @@ -590,6 +587,11 @@ std::string GatherTravelDestination::GetTitle() const { return out.str(); } +TravelTarget::TravelTarget(PlayerbotAI* ai) : AiObject(ai) +{ + sTravelMgr.SetNullTravelTarget(this); +} + void TravelTarget::setTarget(TravelDestination* tDestination1, WorldPosition* wPosition1, bool groupCopy1) { wPosition = wPosition1; tDestination = tDestination1; @@ -689,7 +691,7 @@ bool TravelTarget::isTraveling() { if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT) && !ai->HasStrategy("travel once", BotState::BOT_STATE_NON_COMBAT)) { - setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(this); return false; } @@ -710,7 +712,7 @@ bool TravelTarget::isWorking() { if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT) && !ai->HasStrategy("travel once", BotState::BOT_STATE_NON_COMBAT)) { - setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(this); return false; } @@ -767,16 +769,16 @@ TravelState TravelTarget::getTravelState() { void TravelMgr::Clear() { #ifdef MANGOS - sObjectAccessor.DoForAllPlayers([this](Player* plr) { TravelMgr::setNullTravelTarget(plr); }); + sObjectAccessor.DoForAllPlayers([this](Player* plr) { TravelMgr::SetNullTravelTarget(plr); }); #endif #ifdef CMANGOS #ifndef MANGOSBOT_ZERO - sObjectAccessor.ExecuteOnAllPlayers([this](Player* plr) { TravelMgr::setNullTravelTarget(plr); }); + sObjectAccessor.ExecuteOnAllPlayers([this](Player* plr) { TravelMgr::SetNullTravelTarget(plr); }); #else HashMapHolder::ReadGuard g(HashMapHolder::GetLock()); HashMapHolder::MapType& m = sObjectAccessor.GetPlayers(); for (HashMapHolder::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) - TravelMgr::setNullTravelTarget(itr->second); + TravelMgr::SetNullTravelTarget(itr->second); #endif #endif for (auto& [type, entryMap] : destinationMap) @@ -787,7 +789,7 @@ void TravelMgr::Clear() pointsMap.clear(); } -int32 TravelMgr::getAreaLevel(uint32 area_id) +int32 TravelMgr::GetAreaLevel(uint32 area_id) { auto lev = areaLevels.find(area_id); @@ -821,7 +823,7 @@ int32 TravelMgr::getAreaLevel(uint32 area_id) if (!subArea || subArea->zone != area->ID) continue; - int32 subLevel = getAreaLevel(subArea->ID); + int32 subLevel = GetAreaLevel(subArea->ID); if (!subLevel) continue; @@ -873,7 +875,7 @@ int32 TravelMgr::getAreaLevel(uint32 area_id) if (area->zone) { areaLevels[area_id] = 0; //Set a temporary value so it wont be counted. - level = getAreaLevel(area->zone); + level = GetAreaLevel(area->zone); areaLevels[area_id] = level; return areaLevels[area_id]; } @@ -883,7 +885,7 @@ int32 TravelMgr::getAreaLevel(uint32 area_id) return areaLevels[area_id]; } -void TravelMgr::loadAreaLevels() +void TravelMgr::LoadAreaLevels() { if (!areaLevels.empty()) return; @@ -923,7 +925,7 @@ void TravelMgr::loadAreaLevels() { if (std::find(loadedAreas.begin(), loadedAreas.end(), area->ID) == loadedAreas.end()) { - int32 level = sTravelMgr.getAreaLevel(area->ID); + int32 level = sTravelMgr.GetAreaLevel(area->ID); WorldDatabase.PExecute("INSERT INTO `ai_playerbot_zone_level` (`id`, `level`) VALUES ('%d', '%d')", area->ID, level); } @@ -935,93 +937,6 @@ void TravelMgr::loadAreaLevels() } } -void TravelMgr::logQuestError(uint32 errorNr, Quest* quest, uint32 objective, uint32 unitId, uint32 itemId) -{ - bool logQuestErrors = false; //For debugging. - - if (!logQuestErrors) - return; - - if (errorNr == 1) - { - std::string unitName = ""; - CreatureInfo const* cInfo = NULL; - GameObjectInfo const* gInfo = NULL; - - if (unitId > 0) - cInfo = ObjectMgr::GetCreatureTemplate(unitId); - else - gInfo = ObjectMgr::GetGameObjectInfo(unitId * -1); - - if (cInfo) - unitName = cInfo->Name; - else if (gInfo) - unitName = gInfo->name; - - sLog.outString("Quest %s [%d] has %s %s [%d] but none is found in the world.", quest->GetTitle().c_str(), quest->GetQuestId(), objective == 0 ? "quest giver" : "quest taker", unitName.c_str(), unitId); - } - else if (errorNr == 2) - { - std::string unitName = ""; - CreatureInfo const* cInfo = NULL; - GameObjectInfo const* gInfo = NULL; - - if (unitId > 0) - cInfo = ObjectMgr::GetCreatureTemplate(unitId); - else - gInfo = ObjectMgr::GetGameObjectInfo(unitId * -1); - - if (cInfo) - unitName = cInfo->Name; - else if (gInfo) - unitName = gInfo->name; - - sLog.outErrorDb("Quest %s [%d] needs %s [%d] for objective %d but none is found in the world.", quest->GetTitle().c_str(), quest->GetQuestId(), unitName.c_str(), unitId, objective); - } - else if (errorNr == 3) - { - sLog.outErrorDb("Quest %s [%d] needs itemId %d but no such item exists.", quest->GetTitle().c_str(), quest->GetQuestId(), itemId); - } - else if (errorNr == 4) - { - ItemPrototype const* proto = sObjectMgr.GetItemPrototype(itemId); - - std::string unitName = ""; - CreatureInfo const* cInfo = NULL; - GameObjectInfo const* gInfo = NULL; - - if (unitId > 0) - cInfo = ObjectMgr::GetCreatureTemplate(unitId); - else - gInfo = ObjectMgr::GetGameObjectInfo(unitId * -1); - - if (cInfo) - unitName = cInfo->Name; - else if (gInfo) - unitName = gInfo->name; - - sLog.outString("Quest %s [%d] needs %s [%d] for loot of item %s [%d] for objective %d but none is found in the world.", quest->GetTitle().c_str(), quest->GetQuestId(), unitName.c_str(), unitId, proto->Name1, itemId, objective); - } - else if (errorNr == 5) - { - ItemPrototype const* proto = sObjectMgr.GetItemPrototype(itemId); - - sLog.outString("Quest %s [%d] needs item %s [%d] for objective %d but none is found in the world.", quest->GetTitle().c_str(), quest->GetQuestId(), proto->Name1, itemId, objective); - } - else if (errorNr == 6) - { - sLog.outErrorDb("Quest %s [%d] has no quest giver.", quest->GetTitle().c_str(), quest->GetQuestId()); - } - else if (errorNr == 7) - { - sLog.outErrorDb("Quest %s [%d] has no quest taker.", quest->GetTitle().c_str(), quest->GetQuestId()); - } - else if (errorNr == 8) - { - sLog.outErrorDb("Quest %s [%d] has no quest viable quest objective.", quest->GetTitle().c_str(), quest->GetQuestId()); - } -} - void TravelMgr::SetMobAvoidArea() { sLog.outString("-Apply mob avoidance maps"); @@ -1209,7 +1124,7 @@ void TravelMgr::LoadQuestTravelTable() for (auto tLoc : locs) { - tLoc->AddPoint(&pointsMap.find(guidP.GetRawValue())->second); + tLoc->AddPoint(&pointsMap.at(guidP.GetRawValue())); } } } @@ -1264,7 +1179,7 @@ void TravelMgr::LoadQuestTravelTable() rLoc = AddDestination(u.entry); pointsMap.insert_or_assign(u.guid, point); - rLoc->AddPoint(&pointsMap.find(u.guid)->second); + rLoc->AddPoint(&pointsMap.at(u.guid)); break; } } @@ -1275,7 +1190,7 @@ void TravelMgr::LoadQuestTravelTable() point = GuidPosition(u.guid, WorldPosition(u.map, u.x, u.y, u.z, u.o)); pointsMap.insert_or_assign(u.guid, point); - gLoc->AddPoint(&pointsMap.find(u.guid)->second); + gLoc->AddPoint(&pointsMap.at(u.guid)); } if (cInfo->Rank == 3 || cInfo->Rank == 4 || (cInfo->Rank == 1 && !point.isOverworld() && u.c == 1)) @@ -1283,7 +1198,7 @@ void TravelMgr::LoadQuestTravelTable() bLoc = AddDestination(u.entry); pointsMap.insert_or_assign(u.guid, point); - bLoc->AddPoint(&pointsMap.find(u.guid)->second); + bLoc->AddPoint(&pointsMap.at(u.guid)); } if (cInfo->GetRequiredLootSkill() == SKILL_SKINNING) @@ -1291,7 +1206,7 @@ void TravelMgr::LoadQuestTravelTable() tLoc = AddDestination(u.entry); pointsMap.insert_or_assign(u.guid, point); - tLoc->AddPoint(&pointsMap.find(u.guid)->second); + tLoc->AddPoint(&pointsMap.at(u.guid)); } } else @@ -1319,7 +1234,7 @@ void TravelMgr::LoadQuestTravelTable() rLoc = AddDestination(entry); pointsMap.insert_or_assign(u.guid, point); - rLoc->AddPoint(&pointsMap.find(u.guid)->second); + rLoc->AddPoint(&pointsMap.at(u.guid)); break; } } @@ -1346,7 +1261,7 @@ void TravelMgr::LoadQuestTravelTable() tLoc = AddDestination(entry); pointsMap.insert_or_assign(u.guid, point); - tLoc->AddPoint(&pointsMap.find(u.guid)->second); + tLoc->AddPoint(&pointsMap.at(u.guid)); } } } @@ -1377,7 +1292,7 @@ void TravelMgr::LoadQuestTravelTable() pointsMap.insert_or_assign(guid, point); loc = AddDestination(area->ID); - loc->AddPoint(&pointsMap.find(guid)->second); + loc->AddPoint(&pointsMap.at(guid)); } //Analyse log files @@ -2066,7 +1981,7 @@ void TravelMgr::LoadQuestTravelTable() if (zoneLocs.find(name) == zoneLocs.end()) zoneLocs.insert_or_assign(name, Locs); - zoneLocs.find(name)->second.push_back(point); + zoneLocs.at(name).push_back(point); } for (auto& loc : zoneLocs) @@ -2133,621 +2048,10 @@ void TravelMgr::LoadQuestTravelTable() WorldPosition::unloadMapAndVMaps(mapId); } -#endif - - /* - bool printStrategyMap = false; - if (printStrategyMap && sPlayerbotAIConfig.hasLog("strategy.csv")) - { - static std::map classes; - static std::map > specs; - classes[CLASS_DRUID] = "druid"; - specs[CLASS_DRUID][0] = "balance"; - specs[CLASS_DRUID][1] = "feral combat"; - specs[CLASS_DRUID][2] = "restoration"; - - classes[CLASS_HUNTER] = "hunter"; - specs[CLASS_HUNTER][0] = "beast mastery"; - specs[CLASS_HUNTER][1] = "marksmanship"; - specs[CLASS_HUNTER][2] = "survival"; - - classes[CLASS_MAGE] = "mage"; - specs[CLASS_MAGE][0] = "arcane"; - specs[CLASS_MAGE][1] = "fire"; - specs[CLASS_MAGE][2] = "frost"; - - classes[CLASS_PALADIN] = "paladin"; - specs[CLASS_PALADIN][0] = "holy"; - specs[CLASS_PALADIN][1] = "protection"; - specs[CLASS_PALADIN][2] = "retribution"; - - classes[CLASS_PRIEST] = "priest"; - specs[CLASS_PRIEST][0] = "discipline"; - specs[CLASS_PRIEST][1] = "holy"; - specs[CLASS_PRIEST][2] = "shadow"; - - classes[CLASS_ROGUE] = "rogue"; - specs[CLASS_ROGUE][0] = "assasination"; - specs[CLASS_ROGUE][1] = "combat"; - specs[CLASS_ROGUE][2] = "subtlety"; - - classes[CLASS_SHAMAN] = "shaman"; - specs[CLASS_SHAMAN][0] = "elemental"; - specs[CLASS_SHAMAN][1] = "enhancement"; - specs[CLASS_SHAMAN][2] = "restoration"; - - classes[CLASS_WARLOCK] = "warlock"; - specs[CLASS_WARLOCK][0] = "affliction"; - specs[CLASS_WARLOCK][1] = "demonology"; - specs[CLASS_WARLOCK][2] = "destruction"; - - classes[CLASS_WARRIOR] = "warrior"; - specs[CLASS_WARRIOR][0] = "arms"; - specs[CLASS_WARRIOR][1] = "fury"; - specs[CLASS_WARRIOR][2] = "protection"; - -#ifdef MANGOSBOT_TWO - classes[CLASS_DEATH_KNIGHT] = "dk"; - specs[CLASS_DEATH_KNIGHT][0] = "blood"; - specs[CLASS_DEATH_KNIGHT][1] = "frost"; - specs[CLASS_DEATH_KNIGHT][2] = "unholy"; -#endif - - //Use randombot 0. - std::ostringstream cout; cout << sPlayerbotAIConfig.randomBotAccountPrefix << 0; - std::string accountName = cout.str(); - - auto results = LoginDatabase.PQuery("SELECT id FROM account where username = '%s'", accountName.c_str()); - if (results) - { - - Field* fields = results->Fetch(); - uint32 accountId = fields[0].GetUInt32(); - - WorldSession* session = new WorldSession(accountId, NULL, SEC_PLAYER, -#ifndef MANGOSBOT_ZERO - 2, 0, LOCALE_enUS, accountName.c_str(), 0, 0, false); -#else - 0, LOCALE_enUS, accountName.c_str(), 0); -#endif - - std::vector, uint32>> classSpecLevel; - - std::unordered_map, uint32>>> actions; - - std::ostringstream out; - - for (uint8 race = RACE_HUMAN; race < MAX_RACES; race++) - { - for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES; ++cls) - { -#ifdef MANGOSBOT_TWO - if (cls != 10) -#else - if (cls != 10 && cls != 6) -#endif - { - Player* player = new Player(session); - - if (player->Create(sObjectMgr.GeneratePlayerLowGuid(), "dummy", - race, //race - cls, //class - 1, //gender - 1, // skinColor, - 1, - 1, - 1, // hairColor, - 1, 0)) - { - - for (uint8 tab = 0; tab < 3; tab++) - { - TalentSpec newSpec; - if (tab == 0) - newSpec = TalentSpec(player, "1-0-0"); - else if (tab == 1) - newSpec = TalentSpec(player, "0-1-0"); - else - newSpec = TalentSpec(player, "0-0-1"); - - for (uint32 lvl = 1; lvl < MAX_LEVEL; lvl++) - { - player->SetLevel(lvl); - - std::ostringstream tout; - newSpec.ApplyTalents(player, &tout); - - PlayerbotAI* ai = new PlayerbotAI(player); - - ai->ResetStrategies(false); - - AiObjectContext* con = ai->GetAiObjectContext(); - - std::list tstrats; - std::set strategies, sstrats; - - tstrats = ai->GetStrategies(BotState::BOT_STATE_COMBAT); - sstrats = con->GetSupportedStrategies(); - if (!sstrats.empty()) - strategies.insert(tstrats.begin(), tstrats.end()); - - tstrats = ai->GetStrategies(BotState::BOT_STATE_NON_COMBAT); - if (!tstrats.empty()) - strategies.insert(tstrats.begin(), tstrats.end()); - - tstrats = ai->GetStrategies(BotState::BOT_STATE_DEAD); - if (!tstrats.empty()) - strategies.insert(tstrats.begin(), tstrats.end()); - - sstrats = con->GetSupportedStrategies(); - if(!sstrats.empty()) - strategies.insert(sstrats.begin(), sstrats.end()); - - for (auto& stratName : strategies) - { - Strategy* strat = con->GetStrategy(stratName); - - if (strat->getDefaultActions()) - for (int32 i = 0; i < NextAction::size(strat->getDefaultActions()); i++) - { - NextAction* nextAction = strat->getDefaultActions()[i]; - - std::ostringstream aout; - - aout << nextAction->getRelevance() << "," << nextAction->getName() << ",,S:" << stratName; - - if (actions.find(aout.str().c_str()) != actions.end()) - classSpecLevel = actions.find(aout.str().c_str())->second; - else - classSpecLevel.clear(); - - classSpecLevel.push_back(make_pair(make_pair(cls, tab), lvl)); - - actions.insert_or_assign(aout.str().c_str(), classSpecLevel); - } - - std::list triggers; - strat->InitTriggers(triggers); - for (auto& triggerNode : triggers) - { - //out << " TN:" << triggerNode->getName(); - - Trigger* trigger = con->GetTrigger(triggerNode->getName()); - - if (trigger) - { - - triggerNode->setTrigger(trigger); - - NextAction** nextActions = triggerNode->getHandlers(); - - for (int32 i = 0; i < NextAction::size(nextActions); i++) - { - NextAction* nextAction = nextActions[i]; - //out << " A:" << nextAction->getName() << "(" << nextAction->getRelevance() << ")"; - - std::ostringstream aout; - - aout << nextAction->getRelevance() << "," << nextAction->getName() << "," << triggerNode->getName() << "," << stratName; - - if (actions.find(aout.str().c_str()) != actions.end()) - classSpecLevel = actions.find(aout.str().c_str())->second; - else - classSpecLevel.clear(); - - classSpecLevel.push_back(make_pair(make_pair(cls, tab), lvl)); - - actions.insert_or_assign(aout.str().c_str(), classSpecLevel); - } - } - } - } - - delete ai; - } - } - } - delete player; - } - } - } - - std::vector< std::string> actionKeys; - - for (auto& action : actions) - actionKeys.push_back(action.first); - - std::sort(actionKeys.begin(), actionKeys.end(), [](std::string i, std::string j) - {stringstream is(i); std::stringstream js(j); float iref, jref; std::string iact, jact, itrig, jtrig, istrat, jstrat; - is >> iref >> iact >> itrig >> istrat; - js >> jref >> jact >> jtrig >> jstrat; - if (iref > jref) - return true; - if (iref == jref && istrat < jstrat) - return true; - if (iref == jref && !(istrat > jstrat) && iact < jact) - return true; - if (iref == jref && !(istrat > jstrat) && !(iact > jact) && itrig < jtrig) - return true; - return false; - }); - - sPlayerbotAIConfig.log("strategy.csv", "relevance, action, trigger, strategy, classes"); - - for (auto& actionkey : actionKeys) - { - if (actions.find(actionkey)->second.size() != (MAX_LEVEL - 1) * (MAX_CLASSES - 1)) - { - classSpecLevel = actions.find(actionkey)->second; - - std::vector,std::pair>> classs; - - for (auto cl : classSpecLevel) - { - uint32 minLevel = MAX_LEVEL; uint32 maxLevel = 0; - - uint32 cls = cl.first.first; - uint32 tb = cl.first.second; - - if (std::find_if(classs.begin(), classs.end(), [cls,tb](std::pair, std::pair> i){return i.first.first ==cls && i.first.second == tb;}) == classs.end()) - { - for (auto cll : classSpecLevel) - { - if (cll.first.first == cl.first.first && cll.first.second == cl.first.second) - { - minLevel = std::min(minLevel, cll.second); - maxLevel = std::max(maxLevel, cll.second); - } - } - - classs.push_back(make_pair(cl.first, make_pair(minLevel, maxLevel))); - } - } - - out << actionkey; - - if (classs.size() != 9 * 3) - { - out << ","; - - for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES; ++cls) - { - bool a[3] = { false,false,false }; - uint32 min[3] = { 0,0,0 }; - uint32 max[3] = { 0,0,0 }; - - if (std::find_if(classs.begin(), classs.end(), [cls](std::pair, std::pair> i) {return i.first.first == cls; }) == classs.end()) - continue; - - for (uint32 tb = 0; tb < 3; tb++) - { - auto tcl = std::find_if(classs.begin(), classs.end(), [cls, tb](std::pair, std::pair> i) {return i.first.first == cls && i.first.second == tb; }); - if (tcl == classs.end()) - continue; - - a[tb] = true; - min[tb] = tcl->second.first; - max[tb] = tcl->second.second; - } - - if (a[0] && a[1] && a[2] && min[0] == min[1] == min[2] && max[0] == max[1] == max[2]) - { - if (min[0] != 1 || max[0] != MAX_LEVEL - 1) - out << classes[cls] << "(" << min[0] << "-" << max[0] << ")"; - else - out << classes[cls]; - - if (cls != classs.back().first.first) - out << ";"; - } - else - { - for (uint32 tb = 0; tb < 3; tb++) - { - if (!a[tb]) - continue; - - if (min[tb] != 1 || max[tb] != MAX_LEVEL - 1) - out << specs[cls][tb] << " " << classes[cls] << "(" << min[tb] << "-" << max[tb] << ")"; - else - out << specs[cls][tb] << " " << classes[cls]; - - if (cls != classs.back().first.first || tb != classs.back().first.second) - out << ";"; - } - } - } - } - else - "all"; - - out << "\n"; - } - else - out << actionkey << "\n"; - } - - sPlayerbotAIConfig.log("strategy.csv", out.str().c_str()); - } - } - */ - - /* - sPlayerbotAIConfig.openLog(7, "w"); - - //Zone area map REMOVE! - uint32 k = 0; - for (auto& node : sTravelNodeMap.getNodes()) - { - WorldPosition* pos = node->getPosition(); - //map area - for (uint32 x = 0; x < 2000; x++) - { - for (uint32 y = 0; y < 2000; y++) - { - if (!pos->getMap()) - continue; - - float nx = pos->getX() + (x*5)-5000.0f; - float ny = pos->getY() + (y*5)-5000.0f; - float nz = pos->getZ() + 100.0f; - - //pos->getMap()->GetHitPosition(nx, ny, nz + 200.0f, nx, ny, nz, -0.5f); - - if (!pos->getMap()->GetHeightInRange(nx, ny, nz, 5000.0f)) // GetHeight can fail - continue; - - WorldPosition npos = WorldPosition(pos->getMapId(), nx, ny, nz, 0.0); - uint32 area = path.getArea(npos.getMapId(), npos.getX(), npos.getY(), npos.getZ()); - - std::ostringstream out; - out << std::fixed << area << "," << npos.getDisplayX() << "," << npos.getDisplayY(); - sPlayerbotAIConfig.log(7, out.str().c_str()); - } - } - k++; - - if (k > 0) - break; - } - - //Explore map output (REMOVE!) - - sPlayerbotAIConfig.openLog(5, "w"); - for (auto i : exploreLocs) - { - for (auto j : i.second->getPoints()) - { - std::ostringstream out; - std::string name = i.second->getTitle(); - name.erase(remove(name.begin(), name.end(), '\"'), name.end()); - out << std::fixed << std::setprecision(2) << name.c_str() << "," << i.first << "," << j->getDisplayX() << "," << j->getDisplayY() << "," << j->getX() << "," << j->getY() << "," << j->getZ(); - sPlayerbotAIConfig.log(5, out.str().c_str()); - } - } - - */ -} - -uint32 TravelMgr::getDialogStatus(const Player* pPlayer, int32 questgiver, Quest const* pQuest) -{ - uint32 dialogStatus = DIALOG_STATUS_NONE; - - QuestRelationsMapBounds rbounds; // QuestRelations (quest-giver) - QuestRelationsMapBounds irbounds; // InvolvedRelations (quest-finisher) - - uint32 questId = pQuest->GetQuestId(); - - if (questgiver > 0) - { - rbounds = sObjectMgr.GetCreatureQuestRelationsMapBounds(questgiver); - irbounds = sObjectMgr.GetCreatureQuestInvolvedRelationsMapBounds(questgiver); - } - else - { - rbounds = sObjectMgr.GetGOQuestRelationsMapBounds(questgiver * -1); - irbounds = sObjectMgr.GetGOQuestInvolvedRelationsMapBounds(questgiver * -1); - } - - // Check markings for quest-finisher - for (QuestRelationsMap::const_iterator itr = irbounds.first; itr != irbounds.second; ++itr) - { - if (itr->second != questId) - continue; - - uint32 dialogStatusNew = DIALOG_STATUS_NONE; - - if (!pQuest || !pQuest->IsActive()) - { - continue; - } - - QuestStatus status = pPlayer->GetQuestStatus(questId); - - if ((status == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(questId)) || - (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))) - { - if (pQuest->IsAutoComplete() && pQuest->IsRepeatable()) - { - dialogStatusNew = DIALOG_STATUS_REWARD_REP; - } - else - { - dialogStatusNew = DIALOG_STATUS_REWARD2; - } - } - else if (status == QUEST_STATUS_INCOMPLETE) - { - dialogStatusNew = DIALOG_STATUS_INCOMPLETE; - } - - if (dialogStatusNew > dialogStatus) - { - dialogStatus = dialogStatusNew; - } - } - - // check markings for quest-giver - for (QuestRelationsMap::const_iterator itr = rbounds.first; itr != rbounds.second; ++itr) - { - if (itr->second != questId) - continue; - - uint32 dialogStatusNew = DIALOG_STATUS_NONE; - - if (!pQuest || !pQuest->IsActive()) - { - continue; - } - - QuestStatus status = pPlayer->GetQuestStatus(questId); - - if (status == QUEST_STATUS_NONE) // For all other cases the mark is handled either at some place else, or with involved-relations already - { - if (pPlayer->CanSeeStartQuest(pQuest)) - { - if (pPlayer->SatisfyQuestLevel(pQuest, false)) - { - int32 lowLevelDiff = sWorld.getConfig(CONFIG_INT32_QUEST_LOW_LEVEL_HIDE_DIFF); - if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap().find(questId)->second.m_rewarded)) - { - dialogStatusNew = DIALOG_STATUS_REWARD_REP; - } - else if (lowLevelDiff < 0 || pPlayer->GetLevel() <= pPlayer->GetQuestLevelForPlayer(pQuest) + uint32(lowLevelDiff)) - { - dialogStatusNew = DIALOG_STATUS_AVAILABLE; - } - else - { -#ifndef MANGOSBOT_TWO - dialogStatusNew = DIALOG_STATUS_CHAT; -#else - dialogStatusNew = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; -#endif - } - } - else - { - dialogStatusNew = DIALOG_STATUS_UNAVAILABLE; - } - } - } - - if (dialogStatusNew > dialogStatus) - { - dialogStatus = dialogStatusNew; - } - } - - return dialogStatus; -} - -//Selects a random WorldPosition from a list. Use a distance weighted distribution. -std::vector TravelMgr::getNextPoint(const WorldPosition& center, std::vector points, uint32 amount) { - std::vector retVec; - - if (points.size() < 2) - { - retVec.push_back(points[0]); - return retVec; - } - - retVec = points; - - std::vector weights; - - std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [center](WorldPosition* point) { return 200000 / (1 + point->distance(center)); }); - - //If any weight is 0 add 1 to all weights. - for (auto& w : weights) - { - if (w > 0) - continue; - - std::for_each(weights.begin(), weights.end(), [](uint32& d) { d += 1; }); - break; - - } - - std::mt19937 gen(time(0)); - - weighted_shuffle(retVec.begin(), retVec.end(), weights.begin(), weights.end(), gen); - - return retVec; -} - -std::vector TravelMgr::getNextPoint(const WorldPosition& center, std::vector points, uint32 amount) { - std::vector retVec; - - if (points.size() < 2) - { - if (points.size() == 1) - retVec.push_back(points[0]); - return retVec; - } - - retVec = points; - - - std::vector weights; - - //List of weights based on distance (Gausian curve that starts at 100 and lower to 1 at 1000 distance) - //std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [center](WorldPosition point) { return 1 + 1000 * exp(-1 * pow(point.distance(center) / 400.0, 2)); }); - - //List of weights based on distance (Twice the distance = half the weight). Caps out at 200.0000 range. - std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [center](WorldPosition point) { return 200000/(1+point.distance(center)); }); - - //If any weight is 0 add 1 to all weights. - for (auto& w : weights) - { - if (w > 0) - continue; - - std::for_each(weights.begin(), weights.end(), [](uint32& d) { d += 1; }); - break; - - } - - std::mt19937 gen(time(0)); - - weighted_shuffle(retVec.begin(), retVec.end(), weights.begin(), weights.end(), gen); - - return retVec; +#endif } -QuestStatusData* TravelMgr::getQuestStatus(const Player* bot, uint32 questId) -{ - auto questStatusMap = bot->getQuestStatusMap(); - return &(questStatusMap.find(questId)->second); -} - -bool TravelMgr::getObjectiveStatus(const Player* bot, Quest const* pQuest, uint32 objective) -{ - uint32 questId = pQuest->GetQuestId(); - if (!bot->IsActiveQuest(questId)) - return false; - - if (bot->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE) - return false; - - QuestStatusData* questStatus = sTravelMgr.getQuestStatus(bot, questId); - - uint32 reqCount = pQuest->ReqItemCount[objective]; - uint32 hasCount = questStatus->m_itemcount[objective]; - - if (reqCount && hasCount < reqCount) - return true; - - reqCount = pQuest->ReqCreatureOrGOCount[objective]; - hasCount = questStatus->m_creatureOrGOcount[objective]; - - if (reqCount && hasCount < reqCount) - return true; - - return false; -} - -std::vector TravelMgr::getQuestTravelDestinations(Player* bot, int32 questId, bool ignoreFull, bool ignoreInactive, float maxDistance, bool ignoreObjectives) +std::vector TravelMgr::GetQuestTravelDestinations(Player* bot, int32 questId, bool ignoreFull, bool ignoreInactive, float maxDistance, bool ignoreObjectives) const { WorldPosition botLocation(bot); @@ -2755,7 +2059,7 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo if (!questId) { - for (auto& [questId, dests] : destinationMap[typeid(QuestRelationTravelDestination)]) + for (auto& [questId, dests] : destinationMap.at(typeid(QuestRelationTravelDestination))) { for (auto& dest : dests) { @@ -2769,7 +2073,7 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo } } if (!ignoreObjectives) - for (auto& [questId, dests] : destinationMap[typeid(QuestObjectiveTravelDestination)]) + for (auto& [questId, dests] : destinationMap.at(typeid(QuestObjectiveTravelDestination))) { for (auto& dest : dests) { @@ -2785,7 +2089,7 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo } else if (questId == -1) { - for (auto& [questId, dests] : destinationMap[typeid(QuestRelationTravelDestination)]) + for (auto& [questId, dests] : destinationMap.at(typeid(QuestRelationTravelDestination))) { for (auto& dest : dests) { @@ -2804,7 +2108,7 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo } else { - for (auto& dest : destinationMap[typeid(QuestRelationTravelDestination)][questId]) + for (auto& dest : destinationMap.at(typeid(QuestRelationTravelDestination)).at(questId)) { if (!ignoreInactive && !dest->IsActive(bot)) @@ -2817,7 +2121,7 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo } if (!ignoreObjectives) - for (auto& dest : destinationMap[typeid(QuestObjectiveTravelDestination)][questId]) + for (auto& dest : destinationMap.at(typeid(QuestObjectiveTravelDestination)).at(questId)) { if (!ignoreInactive && !dest->IsActive(bot)) continue; @@ -2831,13 +2135,13 @@ std::vector TravelMgr::getQuestTravelDestinations(Player* bo return retTravelLocations; } -std::vector TravelMgr::getRpgTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance) +std::vector TravelMgr::GetRpgTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance) const { WorldPosition botLocation(bot); std::vector retTravelLocations; - for (auto& [entry, dests] : destinationMap[typeid(RpgTravelDestination)]) + for (auto& [entry, dests] : destinationMap.at(typeid(RpgTravelDestination))) { for (auto& dest : dests) { @@ -2854,13 +2158,13 @@ std::vector TravelMgr::getRpgTravelDestinations(Player* bot, return retTravelLocations; } -std::vector TravelMgr::getExploreTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive) +std::vector TravelMgr::GetExploreTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive) const { WorldPosition botLocation(bot); std::vector retTravelLocations; - for (auto& [entry, dests] : destinationMap[typeid(ExploreTravelDestination)]) + for (auto& [entry, dests] : destinationMap.at(typeid(ExploreTravelDestination))) { for (auto& dest : dests) { @@ -2873,16 +2177,16 @@ std::vector TravelMgr::getExploreTravelDestinations(Player* return retTravelLocations; } -std::vector TravelMgr::getExploreLocs() +std::vector TravelMgr::GetExploreLocs() const { std::vector retDests; - for (auto& [entry, dests] : destinationMap[typeid(ExploreTravelDestination)]) + for (auto& [entry, dests] : destinationMap.at(typeid(ExploreTravelDestination))) retDests.insert(retDests.end(), dests.begin(), dests.end()); return retDests; } -std::vector TravelMgr::getGrindTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance, uint32 maxCheck) +std::vector TravelMgr::GetGrindTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance, uint32 maxCheck) const { WorldPosition botLocation(bot); @@ -2890,7 +2194,7 @@ std::vector TravelMgr::getGrindTravelDestinations(Player* bo uint32 checked = 0; - for (auto& [entry, dests] : destinationMap[typeid(GrindTravelDestination)]) + for (auto& [entry, dests] : destinationMap.at(typeid(GrindTravelDestination))) { for (auto& dest : dests) { @@ -2910,13 +2214,13 @@ std::vector TravelMgr::getGrindTravelDestinations(Player* bo return retTravelLocations; } -std::vector TravelMgr::getBossTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance) +std::vector TravelMgr::GetBossTravelDestinations(Player* bot, bool ignoreFull, bool ignoreInactive, float maxDistance) const { WorldPosition botLocation(bot); std::vector retTravelLocations; - for (auto& [entry, dests] : destinationMap[typeid(BossTravelDestination)]) + for (auto& [entry, dests] : destinationMap.at(typeid(BossTravelDestination))) { for (auto& dest : dests) { @@ -2933,7 +2237,13 @@ std::vector TravelMgr::getBossTravelDestinations(Player* bot return retTravelLocations; } -void TravelMgr::setNullTravelTarget(Player* player) +void TravelMgr::SetNullTravelTarget(TravelTarget* target) const +{ + if (target) + target->setTarget(nullTravelDestination, nullWorldPosition); +} + +void TravelMgr::SetNullTravelTarget(Player* player) const { if (!player) return; @@ -2943,11 +2253,10 @@ void TravelMgr::setNullTravelTarget(Player* player) TravelTarget* target = player->GetPlayerbotAI()->GetAiObjectContext()->GetValue("travel target")->Get(); - if (target) - target->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + SetNullTravelTarget(target); } -void TravelMgr::addMapTransfer(WorldPosition start, WorldPosition end, float portalDistance, bool makeShortcuts) +void TravelMgr::AddMapTransfer(WorldPosition start, WorldPosition end, float portalDistance, bool makeShortcuts) { uint32 sMap = start.getMapId(); uint32 eMap = end.getMapId(); @@ -2966,16 +2275,16 @@ void TravelMgr::addMapTransfer(WorldPosition start, WorldPosition end, float por { if (eMapt == sMap && sMapt != eMap) // [S1 >MT> E1 -> S2] >THIS> E2 { - float newDistToEnd = mapTransDistance(*mapTransfer.getPointFrom(), start) + portalDistance; - if (mapTransDistance(*mapTransfer.getPointFrom(), end) > newDistToEnd) - addMapTransfer(*mapTransfer.getPointFrom(), end, newDistToEnd, false); + float newDistToEnd = MapTransDistance(mapTransfer.GetPointFrom(), start) + portalDistance; + if (MapTransDistance(mapTransfer.GetPointFrom(), end) > newDistToEnd) + AddMapTransfer(mapTransfer.GetPointFrom(), end, newDistToEnd, false); } if (sMapt == eMap && eMapt != sMap) // S1 >THIS> [E1 -> S2 >MT> E2] { - float newDistToEnd = portalDistance + mapTransDistance(end, *mapTransfer.getPointTo()); - if (mapTransDistance(start, *mapTransfer.getPointTo()) > newDistToEnd) - addMapTransfer(start, *mapTransfer.getPointTo(), newDistToEnd, false); + float newDistToEnd = portalDistance + MapTransDistance(end, mapTransfer.GetPointTo()); + if (MapTransDistance(start, mapTransfer.GetPointTo()) > newDistToEnd) + AddMapTransfer(start, mapTransfer.GetPointTo(), newDistToEnd, false); } } } @@ -2984,23 +2293,23 @@ void TravelMgr::addMapTransfer(WorldPosition start, WorldPosition end, float por auto mapTransfers = mapTransfersMap.find(std::make_pair(start.getMapId(), end.getMapId())); if (mapTransfers == mapTransfersMap.end()) - mapTransfersMap.insert({ { sMap, eMap }, {mapTransfer(start, end, portalDistance)} }); + mapTransfersMap.insert({ { sMap, eMap }, {MapTransfer(start, end, portalDistance)} }); else - mapTransfers->second.push_back(mapTransfer(start, end, portalDistance)); + mapTransfers->second.push_back(MapTransfer(start, end, portalDistance)); }; -void TravelMgr::loadMapTransfers() +void TravelMgr::LoadMapTransfers() { for (auto& node : sTravelNodeMap.getNodes()) { - for (auto& link : *node->getLinks()) + for (auto& [node, path] : *node->getLinks()) { - addMapTransfer(*node->getPosition(), *link.first->getPosition(), link.second->getDistance()); + AddMapTransfer(*node->getPosition(), *node->getPosition(), path->getDistance()); } } } -float TravelMgr::mapTransDistance(WorldPosition start, WorldPosition end, bool toMap) +float TravelMgr::MapTransDistance(const WorldPosition& start, const WorldPosition& end, bool toMap) const { uint32 sMap = start.getMapId(); uint32 eMap = end.getMapId(); @@ -3017,9 +2326,10 @@ float TravelMgr::mapTransDistance(WorldPosition start, WorldPosition end, bool t for (auto& mapTrans : mapTransfers->second) { - if (toMap) end = *mapTrans.getPointTo(); + WorldPosition realEnd = end; + if (toMap) realEnd = mapTrans.GetPointTo(); - float dist = mapTrans.distance(start, end); + float dist = mapTrans.Distance(start, realEnd); if (dist < minDist) minDist = dist; @@ -3028,7 +2338,7 @@ float TravelMgr::mapTransDistance(WorldPosition start, WorldPosition end, bool t return minDist; } -float TravelMgr::fastMapTransDistance(WorldPosition start, WorldPosition end, bool toMap) +float TravelMgr::FastMapTransDistance(const WorldPosition& start, const WorldPosition& end, bool toMap) const { uint32 sMap = start.getMapId(); uint32 eMap = end.getMapId(); @@ -3045,79 +2355,14 @@ float TravelMgr::fastMapTransDistance(WorldPosition start, WorldPosition end, bo for (auto& mapTrans : mapTransfers->second) { - if (toMap) end = *mapTrans.getPointTo(); + WorldPosition realEnd = end; + if (toMap) realEnd = mapTrans.GetPointTo(); - float dist = mapTrans.fDist(start, end); + float dist = mapTrans.FDist(start, end); if (dist < minDist) minDist = dist; } return minDist; -} - -void TravelMgr::printGrid(uint32 mapId, int x, int y, std::string type) -{ - std::string fileName = "unload_grid.csv"; - - if (sPlayerbotAIConfig.hasLog(fileName)) - { - std::ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00, " << 0 << 0 << x << "," << y << ", " << type << ","; - WorldPosition::printWKT(WorldPosition::fromGridPair(GridPair(x, y), mapId), out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } -} - -void TravelMgr::printObj(WorldObject* obj, std::string type) -{ - std::string fileName = "unload_grid.csv"; - - if (sPlayerbotAIConfig.hasLog(fileName)) - { - WorldPosition p = WorldPosition(obj); - - Cell const& cell = obj->GetCurrentCell(); - - std::vector vcell, vgrid; - vcell = p.fromCellPair(p.getCellPair()); - vgrid = p.gridFromCellPair(p.getCellPair()); - - { - std::ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00, " << obj->GetObjectGuid().GetEntry() << "," << obj->GetObjectGuid().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; - - p.printWKT(vcell, out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - - { - std::ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00, " << obj->GetObjectGuid().GetEntry() << "," << obj->GetObjectGuid().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; - - p.printWKT(vgrid, out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - } - - fileName = "unload_obj.csv"; - - if (sPlayerbotAIConfig.hasLog(fileName)) - { - WorldPosition p = WorldPosition(obj); - - Cell const& cell = obj->GetCurrentCell(); - - { - std::ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00, " << obj->GetObjectGuid().GetEntry() << "," << obj->GetObjectGuid().GetCounter() << "," << cell.GridX() << "," << cell.GridY() << ", " << type << ","; - - p.printWKT({ p }, out, 0); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - } } \ No newline at end of file diff --git a/playerbot/TravelMgr.h b/playerbot/TravelMgr.h index 4ca9aedc..6a1d07f8 100644 --- a/playerbot/TravelMgr.h +++ b/playerbot/TravelMgr.h @@ -8,26 +8,27 @@ namespace ai { class GuidePosition; - class mapTransfer + class MapTransfer { public: - mapTransfer(WorldPosition pointFrom1, WorldPosition pointTo1, float portalLength1 = 0.1f) - : pointFrom(pointFrom1), pointTo(pointTo1), portalLength(portalLength1) { + MapTransfer(const WorldPosition& pointFrom, const WorldPosition& pointTo, float portalLength = 0.1f) + : pointFrom(pointFrom), pointTo(pointTo), portalLength(portalLength) { } + float Distance(const WorldPosition& start, const WorldPosition& end) const { return (isUseful(start, end) ? (start.distance(pointFrom) + portalLength + pointTo.distance(end)) : 200000); } - bool isFrom(WorldPosition point) { return point.getMapId() == pointFrom.getMapId(); } - bool isTo(WorldPosition point) { return point.getMapId() == pointTo.getMapId(); } + float FDist(const WorldPosition& start, const WorldPosition& end) const { return start.fDist(pointFrom) + portalLength + pointTo.fDist(end); } - WorldPosition* getPointFrom() { return &pointFrom; } - WorldPosition* getPointTo() { return &pointTo; } + WorldPosition GetPointFrom() const { return pointFrom; } + WorldPosition GetPointTo() const { return pointTo; } + private: + bool isFrom(const WorldPosition& point) const { return point.getMapId() == pointFrom.getMapId(); } + bool isTo(const WorldPosition& point) const { return point.getMapId() == pointTo.getMapId(); } - bool isUseful(WorldPosition point) { return isFrom(point) || isTo(point); } - float distance(WorldPosition point) { return isUseful(point) ? (isFrom(point) ? point.distance(pointFrom) : point.distance(pointTo)) : 200000; } + bool isUseful(const WorldPosition& point) const { return isFrom(point) || isTo(point); } + bool isUseful(const WorldPosition& start, const WorldPosition& end) const { return isFrom(start) && isTo(end); } + + float Distance(const WorldPosition& point) const { return isUseful(point) ? (isFrom(point) ? point.distance(pointFrom) : point.distance(pointTo)) : 200000; } - bool isUseful(WorldPosition start, WorldPosition end) { return isFrom(start) && isTo(end); } - float distance(WorldPosition start, WorldPosition end) { return (isUseful(start, end) ? (start.distance(pointFrom) + portalLength + pointTo.distance(end)) : 200000); } - float fDist(WorldPosition start, WorldPosition end) { return start.fDist(pointFrom) + portalLength + pointTo.fDist(end); } - private: WorldPosition pointFrom, pointTo; float portalLength = 0.1f; }; @@ -52,7 +53,7 @@ namespace ai bool HasPoint(const WorldPosition* pos) { return std::find(points.begin(), points.end(), pos) != points.end(); } std::vector GetPoints() const; - virtual bool IsActive(const Player* bot) const { return false; } + virtual bool IsActive(Player* bot) const { return false; } virtual int32 GetEntry() const { return 0; } virtual uint8 GetSubEntry() const { return 0; } WorldPosition* NearestPoint(const WorldPosition& pos) const; @@ -110,7 +111,7 @@ namespace ai public: QuestTravelDestination(uint32 questId, int32 entry, uint8 subEntry) : EntryTravelDestination(entry), questId(questId), subEntry(subEntry) { questTemplate = sObjectMgr.GetQuestTemplate(questId); }; - virtual bool IsActive(const Player* bot) const override { return bot->IsActiveQuest(questId); } + virtual bool IsActive(Player* bot) const override { return bot->IsActiveQuest(questId); } virtual std::string GetTitle() const override; @@ -118,7 +119,7 @@ namespace ai virtual uint32 GetQuestId() const { return questId; } protected: virtual Quest const* GetQuestTemplate() const { return questTemplate; } - virtual uint8 GetSubEntry() const { return subEntry; } + virtual uint8 GetSubEntry() const override { return subEntry; } private: uint32 questId; uint8 subEntry; @@ -131,7 +132,7 @@ namespace ai public: QuestRelationTravelDestination(uint32 questId, int32 entry, uint32 relation) : QuestTravelDestination(questId, entry, relation) {} - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -141,7 +142,7 @@ namespace ai public: QuestObjectiveTravelDestination(uint32 questId, int32 entry, uint32 objective) : QuestTravelDestination(questId, entry, objective) { SetExpireFast(); }; - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -151,7 +152,7 @@ namespace ai public: RpgTravelDestination(int32 entry) : EntryTravelDestination(entry) {} - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -161,7 +162,7 @@ namespace ai public: ExploreTravelDestination(int32 areaId) : EntryTravelDestination(areaId) { SetExpireFast(); SetCooldownShort(); title = sAreaStore.LookupEntry(areaId)->area_name[0]; } - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override { return title; } protected: std::string title = ""; @@ -173,7 +174,7 @@ namespace ai public: GrindTravelDestination(int32 entry) : EntryTravelDestination(entry) {} - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -183,7 +184,7 @@ namespace ai public: BossTravelDestination(int32 entry) : EntryTravelDestination(entry) { SetCooldownShort(); } - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -193,7 +194,7 @@ namespace ai public: GatherTravelDestination(int32 entry) : EntryTravelDestination(entry) {} - virtual bool IsActive(const Player* bot) const override; + virtual bool IsActive(Player* bot) const override; virtual std::string GetTitle() const override; }; @@ -232,7 +233,7 @@ namespace ai class TravelTarget : AiObject { public: - TravelTarget(PlayerbotAI* ai) : AiObject(ai) {}; + TravelTarget(PlayerbotAI* ai); TravelTarget(PlayerbotAI* ai, TravelDestination* tDestination1, WorldPosition* wPosition1) : AiObject(ai) { setTarget(tDestination1, wPosition1); } ~TravelTarget() = default; @@ -300,67 +301,33 @@ namespace ai { public: TravelMgr() {}; - void Clear(); - - void SetMobAvoidArea(); - void SetMobAvoidAreaMap(uint32 mapId); - void LoadQuestTravelTable(); + std::vector GetExploreLocs() const; + void SetMobAvoidArea(); - template - void weighted_shuffle - (D first, D last - , W first_weight, W last_weight - , URBG&& g) - { - while (first != last && first_weight != last_weight) - { - std::discrete_distribution dd(first_weight, last_weight); - auto i = dd(g); - - if (i) - { - std::swap(*first, *std::next(first, i)); - std::swap(*first_weight, *std::next(first_weight, i)); - } - ++first; - ++first_weight; - } - } - - std::vector getNextPoint(const WorldPosition& center, std::vector points, uint32 amount = 1); - std::vector getNextPoint(const WorldPosition& center, std::vector points, uint32 amount = 1); - QuestStatusData* getQuestStatus(const Player* bot, uint32 questId); - bool getObjectiveStatus(const Player* bot, Quest const* pQuest, uint32 objective); - uint32 getDialogStatus(const Player* pPlayer, int32 questgiver, Quest const* pQuest); - std::vector getQuestTravelDestinations(Player* bot, int32 questId = -1, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000, bool ignoreObjectives = false); - std::vector getRpgTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000); - std::vector getExploreTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false); - std::vector getGrindTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000, uint32 maxCheck = 50); - std::vector getBossTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 25000); - - - void setNullTravelTarget(Player* player); - - void addMapTransfer(WorldPosition start, WorldPosition end, float portalDistance = 0.1f, bool makeShortcuts = true); - void loadMapTransfers(); - float mapTransDistance(WorldPosition start, WorldPosition end, bool toMap = false); - float fastMapTransDistance(WorldPosition start, WorldPosition end, bool toMap = false); + std::vector GetQuestTravelDestinations(Player* bot, int32 questId = -1, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000, bool ignoreObjectives = false) const; + std::vector GetRpgTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000) const; + std::vector GetExploreTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false) const; + std::vector GetGrindTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000, uint32 maxCheck = 50) const; + std::vector GetBossTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 25000) const; - NullTravelDestination* nullTravelDestination = new NullTravelDestination(); - WorldPosition* nullWorldPosition = new WorldPosition(); + void SetNullTravelTarget(TravelTarget* target) const; - void addBadVmap(uint32 mapId, int x, int y) { badVmap.push_back(std::make_tuple(mapId, x, y)); } - void addBadMmap(uint32 mapId, int x, int y) { badMmap.push_back(std::make_tuple(mapId, x, y)); } - bool isBadVmap(uint32 mapId, int x, int y) { return std::find(badVmap.begin(), badVmap.end(), std::make_tuple(mapId, x, y)) != badVmap.end(); } - bool isBadMmap(uint32 mapId, int x, int y) { return std::find(badMmap.begin(), badMmap.end(), std::make_tuple(mapId, x, y)) != badMmap.end(); } + void LoadMapTransfers(); + float MapTransDistance(const WorldPosition& start, const WorldPosition& end, bool toMap = false) const; + float FastMapTransDistance(const WorldPosition& start, const WorldPosition& end, bool toMap = false) const; + void AddBadMmap(uint32 mapId, int x, int y) { badMmap.push_back(std::make_tuple(mapId, x, y)); } + bool IsBadMmap(uint32 mapId, int x, int y) const { return std::find(badMmap.begin(), badMmap.end(), std::make_tuple(mapId, x, y)) != badMmap.end(); } - void printGrid(uint32 mapId, int x, int y, std::string type); - void printObj(WorldObject* obj, std::string type); + int32 GetAreaLevel(uint32 area_id); + void LoadAreaLevels(); + private: + void Clear(); + void SetMobAvoidAreaMap(uint32 mapId); - int32 getAreaLevel(uint32 area_id); - void loadAreaLevels(); + void SetNullTravelTarget(Player* player) const; + void AddMapTransfer(WorldPosition start, WorldPosition end, float portalDistance = 0.1f, bool makeShortcuts = true); template T* AddDestination(int32 entry) { @@ -381,21 +348,16 @@ namespace ai return (T*)destinationMap[typeid(T)][questId].back(); } - - std::vector getExploreLocs(); - protected: - void logQuestError(uint32 errorNr, Quest* quest, uint32 objective = 0, uint32 unitId = 0, uint32 itemId = 0); - - std::vector avoidLoaded; - + NullTravelDestination* nullTravelDestination = new NullTravelDestination(); + WorldPosition* nullWorldPosition = new WorldPosition(); TypedDestinationMap destinationMap; std::unordered_map pointsMap; std::unordered_map areaLevels; - std::vector> badVmap, badMmap; + std::vector> badMmap; - std::unordered_map, std::vector, boost::hash>> mapTransfersMap; + std::unordered_map, std::vector, boost::hash>> mapTransfersMap; }; } diff --git a/playerbot/TravelNode.cpp b/playerbot/TravelNode.cpp index a497cc7a..e1e9c22e 100644 --- a/playerbot/TravelNode.cpp +++ b/playerbot/TravelNode.cpp @@ -2377,7 +2377,7 @@ void TravelNodeMap::generateTransportNodes() void TravelNodeMap::generateZoneMeanNodes() { //Zone means - for (auto& loc : sTravelMgr.getExploreLocs()) + for (auto& loc : sTravelMgr.GetExploreLocs()) { std::vector points; @@ -2905,7 +2905,7 @@ void TravelNodeMap::generateAll() calcMapOffset(); sLog.outString("-Generating maptransfers"); - sTravelMgr.loadMapTransfers(); + sTravelMgr.LoadMapTransfers(); if (hasToGen || hasToFullGen) { diff --git a/playerbot/WorldPosition.cpp b/playerbot/WorldPosition.cpp index 9e1f6881..be53e4cd 100644 --- a/playerbot/WorldPosition.cpp +++ b/playerbot/WorldPosition.cpp @@ -141,7 +141,7 @@ float WorldPosition::distance(const WorldPosition& to) const return relPoint(to).size(); //this -> mapTransfer | mapTransfer -> center - return sTravelMgr.mapTransDistance(*this, to); + return sTravelMgr.MapTransDistance(*this, to); }; float WorldPosition::fDist(const WorldPosition& to) const @@ -150,7 +150,7 @@ float WorldPosition::fDist(const WorldPosition& to) const return sqrt(sqDistance2d(to)); //this -> mapTransfer | mapTransfer -> center - return sTravelMgr.fastMapTransDistance(*this, to); + return sTravelMgr.FastMapTransDistance(*this, to); }; //When moving from this along list return last point that falls within range. @@ -257,6 +257,79 @@ std::vector> WorldPosition::distancePartition(const return partitions; } +std::vector WorldPosition::GetNextPoint(std::vector points, uint32 amount) const { + std::vector retVec; + + if (points.size() < 2) + { + retVec.push_back(points[0]); + return retVec; + } + + retVec = points; + + std::vector weights; + + std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [this](WorldPosition* point) { return 200000 / (1 + this->distance(*point)); }); + + //If any weight is 0 add 1 to all weights. + for (auto& w : weights) + { + if (w > 0) + continue; + + std::for_each(weights.begin(), weights.end(), [](uint32& d) { d += 1; }); + break; + + } + + std::mt19937 gen(time(0)); + + WeightedShuffle(retVec.begin(), retVec.end(), weights.begin(), weights.end(), gen); + + return retVec; +} + +std::vector WorldPosition::GetNextPoint(std::vector points, uint32 amount) const { + std::vector retVec; + + if (points.size() < 2) + { + if (points.size() == 1) + retVec.push_back(points[0]); + return retVec; + } + + retVec = points; + + + std::vector weights; + + //List of weights based on distance (Gausian curve that starts at 100 and lower to 1 at 1000 distance) + //std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [center](WorldPosition point) { return 1 + 1000 * exp(-1 * pow(point.distance(center) / 400.0, 2)); }); + + //List of weights based on distance (Twice the distance = half the weight). Caps out at 200.0000 range. + std::transform(retVec.begin(), retVec.end(), std::back_inserter(weights), [this](WorldPosition point) { return 200000 / (1 + this->distance(point)); }); + + //If any weight is 0 add 1 to all weights. + for (auto& w : weights) + { + if (w > 0) + continue; + + std::for_each(weights.begin(), weights.end(), [](uint32& d) { d += 1; }); + break; + + } + + std::mt19937 gen(time(0)); + + WeightedShuffle(retVec.begin(), retVec.end(), weights.begin(), weights.end(), gen); + + return retVec; +} + + bool WorldPosition::canFly() const { #ifdef MANGOSBOT_ZERO @@ -392,7 +465,7 @@ std::string WorldPosition::getAreaName(const bool fullName, const bool zoneName) int32 WorldPosition::getAreaLevel() const { if(getArea()) - return sTravelMgr.getAreaLevel(getArea()->ID); + return sTravelMgr.GetAreaLevel(getArea()->ID); return 0; } @@ -606,7 +679,7 @@ bool WorldPosition::loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y if (MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y)) return true; #endif - if (sTravelMgr.isBadMmap(mapId, x, y)) + if (sTravelMgr.IsBadMmap(mapId, x, y)) return false; bool isLoaded = false; @@ -630,13 +703,13 @@ bool WorldPosition::loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y #endif if(!isLoaded) - sTravelMgr.addBadMmap(mapId, x, y); + sTravelMgr.AddBadMmap(mapId, x, y); if (sPlayerbotAIConfig.hasLog(logName)) { std::ostringstream out; out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.isBadMmap(mapId, x, y) ? "0" : "1") << ","; + out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.IsBadMmap(mapId, x, y) ? "0" : "1") << ","; printWKT(frommGridPair(mGridPair(x, y), mapId), out, 1, true); sPlayerbotAIConfig.log(logName, out.str().c_str()); } diff --git a/playerbot/WorldPosition.h b/playerbot/WorldPosition.h index edfeac9c..c52fc325 100644 --- a/playerbot/WorldPosition.h +++ b/playerbot/WorldPosition.h @@ -26,6 +26,27 @@ namespace ai WP_CLOSEST = 3 }; + template + inline void WeightedShuffle + (D first, D last + , W first_weight, W last_weight + , URBG&& g) + { + while (first != last && first_weight != last_weight) + { + std::discrete_distribution dd(first_weight, last_weight); + auto i = dd(g); + + if (i) + { + std::swap(*first, *std::next(first, i)); + std::swap(*first_weight, *std::next(first_weight, i)); + } + ++first; + ++first_weight; + } + } + class GuidPosition; typedef std::pair mGridPair; @@ -164,6 +185,9 @@ namespace ai void distancePartition(const std::vector& distanceLimits, WorldPosition* to, std::vector>& partition) const; std::vector> distancePartition(const std::vector& distanceLimits, std::vector points) const; + std::vector GetNextPoint(std::vector points, uint32 amount = 1) const; + std::vector GetNextPoint(std::vector points, uint32 amount = 1) const; + //Map functions. Player independent. const MapEntry* getMapEntry() const { return sMapStore.LookupEntry(mapid); } uint32 getFirstInstanceId() const { for (auto& map : sMapMgr.Maps()) { if (map.second->GetId() == getMapId()) return map.second->GetInstanceId(); }; return 0; } diff --git a/playerbot/strategy/actions/ChooseRpgTargetAction.cpp b/playerbot/strategy/actions/ChooseRpgTargetAction.cpp index 4439cc41..8523429d 100644 --- a/playerbot/strategy/actions/ChooseRpgTargetAction.cpp +++ b/playerbot/strategy/actions/ChooseRpgTargetAction.cpp @@ -390,7 +390,7 @@ bool ChooseRpgTargetAction::Execute(Event& event) //We pick a random target from the list with targets having a higher relevance of being picked. std::mt19937 gen(time(0)); - sTravelMgr.weighted_shuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen); + WeightedShuffle(guidps.begin(), guidps.end(), relevances.begin(), relevances.end(), gen); GuidPosition guidP(guidps.front(),bot->GetMapId(), bot->GetInstanceId()); //If we can't find a target clear ignore list and try again later. diff --git a/playerbot/strategy/actions/ChooseTravelTargetAction.cpp b/playerbot/strategy/actions/ChooseTravelTargetAction.cpp index 1d4ed081..d7e1b156 100644 --- a/playerbot/strategy/actions/ChooseTravelTargetAction.cpp +++ b/playerbot/strategy/actions/ChooseTravelTargetAction.cpp @@ -711,7 +711,7 @@ bool ChooseTravelTargetAction::SetBestTarget(Player* requester, TravelTarget* ta if (travelPoints.empty()) return false; - travelPoints = sTravelMgr.getNextPoint(botLocation, travelPoints); //Pick a good point. + travelPoints = botLocation.GetNextPoint(travelPoints); //Pick a good point. //Pick the best destination and point (random shuffle). @@ -828,7 +828,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(Player* requester, TravelTarget* t if (newQuests) { auto pmo = sPerformanceMonitor.start(PERF_MON_VALUE, "getQuestTravelDestinations1", &context->performanceStack); - TravelDestinations = sTravelMgr.getQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10); //Prefer new quests near the player at lower levels. + TravelDestinations = sTravelMgr.GetQuestTravelDestinations(bot, -1, true, false, 400 + bot->GetLevel() * 10); //Prefer new quests near the player at lower levels. } if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) @@ -857,7 +857,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(Player* requester, TravelTarget* t //Find quest takers or objectives auto pmo = sPerformanceMonitor.start(PERF_MON_VALUE, "getQuestTravelDestinations2", &context->performanceStack); - std::vector questDestinations = sTravelMgr.getQuestTravelDestinations(bot, questId, true, false,0); + std::vector questDestinations = sTravelMgr.GetQuestTravelDestinations(bot, questId, true, false,0); pmo.reset(); if (onlyClassQuest && TravelDestinations.size() && questDestinations.size()) //Only do class quests if we have any. @@ -877,7 +877,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(Player* requester, TravelTarget* t if (newQuests && TravelDestinations.empty()) { auto pmo = sPerformanceMonitor.start(PERF_MON_VALUE, "getQuestTravelDestinations3", &context->performanceStack); - TravelDestinations = sTravelMgr.getQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away. + TravelDestinations = sTravelMgr.GetQuestTravelDestinations(bot, -1, true, false); //If we really don't find any new quests look futher away. } if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) @@ -889,7 +889,7 @@ bool ChooseTravelTargetAction::SetQuestTarget(Player* requester, TravelTarget* t bool ChooseTravelTargetAction::SetRpgTarget(Player* requester, TravelTarget* target) { //Find rpg npcs - std::vector TravelDestinations = sTravelMgr.getRpgTravelDestinations(bot, true, false); + std::vector TravelDestinations = sTravelMgr.GetRpgTravelDestinations(bot, true, false); if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) ai->TellPlayerNoFacing(requester, std::to_string(TravelDestinations.size()) + " rpg destinations found."); @@ -900,7 +900,7 @@ bool ChooseTravelTargetAction::SetRpgTarget(Player* requester, TravelTarget* tar bool ChooseTravelTargetAction::SetGrindTarget(Player* requester, TravelTarget* target) { //Find grind mobs. - std::vector TravelDestinations = sTravelMgr.getGrindTravelDestinations(bot, true, false, 600+bot->GetLevel()*400); + std::vector TravelDestinations = sTravelMgr.GetGrindTravelDestinations(bot, true, false, 600+bot->GetLevel()*400); if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) ai->TellPlayerNoFacing(requester, std::to_string(TravelDestinations.size()) + " grind destinations found."); @@ -911,7 +911,7 @@ bool ChooseTravelTargetAction::SetGrindTarget(Player* requester, TravelTarget* t bool ChooseTravelTargetAction::SetBossTarget(Player* requester, TravelTarget* target) { //Find boss mobs. - std::vector TravelDestinations = sTravelMgr.getBossTravelDestinations(bot, true); + std::vector TravelDestinations = sTravelMgr.GetBossTravelDestinations(bot, true); if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) ai->TellPlayerNoFacing(requester, std::to_string(TravelDestinations.size()) + " boss destinations found."); @@ -922,7 +922,7 @@ bool ChooseTravelTargetAction::SetBossTarget(Player* requester, TravelTarget* ta bool ChooseTravelTargetAction::SetExploreTarget(Player* requester, TravelTarget* target) { //Find exploration locations (middle of a sub-zone). - std::vector TravelDestinations = sTravelMgr.getExploreTravelDestinations(bot, true, false); + std::vector TravelDestinations = sTravelMgr.GetExploreTravelDestinations(bot, true, false); if (ai->HasStrategy("debug travel", BotState::BOT_STATE_NON_COMBAT)) ai->TellPlayerNoFacing(requester, std::to_string(TravelDestinations.size()) + " explore destinations found."); @@ -940,7 +940,7 @@ bool ChooseTravelTargetAction::SetNpcFlagTarget(Player* requester, TravelTarget* std::vector TravelDestinations; //Loop over all npcs. - for (auto& d : sTravelMgr.getRpgTravelDestinations(bot, true, true)) + for (auto& d : sTravelMgr.GetRpgTravelDestinations(bot, true, true)) { if (d->GetEntry() <= 0) continue; @@ -1038,7 +1038,7 @@ bool ChooseTravelTargetAction::SetGOTypeTarget(Player* requester, TravelTarget* std::vector TravelDestinations; //Loop over all npcs. - for (auto& d : sTravelMgr.getRpgTravelDestinations(bot, true, true)) + for (auto& d : sTravelMgr.GetRpgTravelDestinations(bot, true, true)) { if (d->GetEntry() >= 0) continue; @@ -1079,7 +1079,7 @@ bool ChooseTravelTargetAction::SetGOTypeTarget(Player* requester, TravelTarget* bool ChooseTravelTargetAction::SetNullTarget(TravelTarget* target) { - target->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(target); return true; } @@ -1099,7 +1099,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Quests if (quests) { - for (auto& d : sTravelMgr.getQuestTravelDestinations(bot, 0, true, true)) + for (auto& d : sTravelMgr.GetQuestTravelDestinations(bot, 0, true, true)) { if (strstri(d->GetTitle().c_str(), name.c_str())) dests.push_back(d); @@ -1109,7 +1109,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Zones if (zones) { - for (auto& d : sTravelMgr.getExploreTravelDestinations(bot, true, true)) + for (auto& d : sTravelMgr.GetExploreTravelDestinations(bot, true, true)) { if (strstri(d->GetTitle().c_str(), name.c_str())) dests.push_back(d); @@ -1119,7 +1119,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Npcs if (npcs) { - for (auto& d : sTravelMgr.getRpgTravelDestinations(bot, true, true)) + for (auto& d : sTravelMgr.GetRpgTravelDestinations(bot, true, true)) { if (strstri(d->GetTitle().c_str(), name.c_str())) dests.push_back(d); @@ -1129,7 +1129,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Mobs if (mobs) { - for (auto& d : sTravelMgr.getGrindTravelDestinations(bot, true, true, 5000.0f, 0)) + for (auto& d : sTravelMgr.GetGrindTravelDestinations(bot, true, true, 5000.0f, 0)) { if (strstri(d->GetTitle().c_str(), name.c_str())) dests.push_back(d); @@ -1139,7 +1139,7 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s //Bosses if (bosses) { - for (auto& d : sTravelMgr.getBossTravelDestinations(bot, true, true)) + for (auto& d : sTravelMgr.GetBossTravelDestinations(bot, true, true)) { if (strstri(d->GetTitle().c_str(), name.c_str())) dests.push_back(d); diff --git a/playerbot/strategy/actions/DebugAction.cpp b/playerbot/strategy/actions/DebugAction.cpp index fbd5190a..ac540d17 100644 --- a/playerbot/strategy/actions/DebugAction.cpp +++ b/playerbot/strategy/actions/DebugAction.cpp @@ -912,8 +912,8 @@ bool DebugAction::Execute(Event& event) if (guidP.getArea()->zone && GetAreaEntryByAreaID(guidP.getArea()->zone)) { out << " z:" << GetAreaEntryByAreaID(guidP.getArea()->zone)->area_name[0]; - if (sTravelMgr.getAreaLevel(guidP.getArea()->zone)) - out << " level: " << sTravelMgr.getAreaLevel(guidP.getArea()->zone); + if (sTravelMgr.GetAreaLevel(guidP.getArea()->zone)) + out << " level: " << sTravelMgr.GetAreaLevel(guidP.getArea()->zone); } out << "] "; diff --git a/playerbot/strategy/actions/GoAction.cpp b/playerbot/strategy/actions/GoAction.cpp index 77e200ed..afc3d7ba 100644 --- a/playerbot/strategy/actions/GoAction.cpp +++ b/playerbot/strategy/actions/GoAction.cpp @@ -285,7 +285,7 @@ bool GoAction::TravelTo(TravelDestination* dest, Player* requester) const } else { - target->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition); + sTravelMgr.SetNullTravelTarget(target); target->setForced(false); return false; } diff --git a/playerbot/strategy/actions/ListQuestsActions.cpp b/playerbot/strategy/actions/ListQuestsActions.cpp index 6a677089..f5172283 100644 --- a/playerbot/strategy/actions/ListQuestsActions.cpp +++ b/playerbot/strategy/actions/ListQuestsActions.cpp @@ -102,13 +102,13 @@ int ListQuestsAction::ListQuests(Player* requester, bool completed, bool silent, if (travelDetail == QUEST_TRAVEL_DETAIL_SUMMARY) { - std::vector allDestinations = sTravelMgr.getQuestTravelDestinations(bot, questId, true, true, -1); - std::vector availDestinations = sTravelMgr.getQuestTravelDestinations(bot, questId, ai->GetMaster(), false, -1); + std::vector allDestinations = sTravelMgr.GetQuestTravelDestinations(bot, questId, true, true, -1); + std::vector availDestinations = sTravelMgr.GetQuestTravelDestinations(bot, questId, ai->GetMaster(), false, -1); uint32 desTot = allDestinations.size(); uint32 desAvail = availDestinations.size(); - uint32 desFull = desAvail - sTravelMgr.getQuestTravelDestinations(bot, questId, false, false, -1).size(); - uint32 desRange = desAvail - sTravelMgr.getQuestTravelDestinations(bot, questId, false, false).size(); + uint32 desFull = desAvail - sTravelMgr.GetQuestTravelDestinations(bot, questId, false, false, -1).size(); + uint32 desRange = desAvail - sTravelMgr.GetQuestTravelDestinations(bot, questId, false, false).size(); uint32 tpoints = 0; uint32 apoints = 0; @@ -129,7 +129,7 @@ int ListQuestsAction::ListQuests(Player* requester, bool completed, bool silent, else if (travelDetail == QUEST_TRAVEL_DETAIL_FULL) { uint32 limit = 0; - std::vector allDestinations = sTravelMgr.getQuestTravelDestinations(bot, questId, true, true, -1); + std::vector allDestinations = sTravelMgr.GetQuestTravelDestinations(bot, questId, true, true, -1); std::sort(allDestinations.begin(), allDestinations.end(), [botPos](TravelDestination* i, TravelDestination* j) {return i->DistanceTo(botPos) < j->DistanceTo(botPos); }); diff --git a/playerbot/strategy/actions/MoveToTravelTargetAction.cpp b/playerbot/strategy/actions/MoveToTravelTargetAction.cpp index df98ef8a..7b848e96 100644 --- a/playerbot/strategy/actions/MoveToTravelTargetAction.cpp +++ b/playerbot/strategy/actions/MoveToTravelTargetAction.cpp @@ -265,7 +265,7 @@ bool MoveToTravelTargetAction::isUseful() WorldPosition travelPos(*AI_VALUE(TravelTarget*, "travel target")->getPosition()); - if (travelPos.isDungeon() && bot->GetGroup() && bot->GetGroup()->IsLeader(bot->GetObjectGuid()) && sTravelMgr.mapTransDistance(bot, travelPos, true) < sPlayerbotAIConfig.sightDistance && !AI_VALUE2(bool, "group and", "near leader")) + if (travelPos.isDungeon() && bot->GetGroup() && bot->GetGroup()->IsLeader(bot->GetObjectGuid()) && sTravelMgr.MapTransDistance(bot, travelPos, true) < sPlayerbotAIConfig.sightDistance && !AI_VALUE2(bool, "group and", "near leader")) return false; if (AI_VALUE(bool, "has available loot")) diff --git a/playerbot/strategy/actions/QueryQuestAction.cpp b/playerbot/strategy/actions/QueryQuestAction.cpp index 3cf77494..9fa1ae02 100644 --- a/playerbot/strategy/actions/QueryQuestAction.cpp +++ b/playerbot/strategy/actions/QueryQuestAction.cpp @@ -64,7 +64,7 @@ bool QueryQuestAction::Execute(Event& event) if (travel) { uint32 limit = 0; - std::vector allDestinations = sTravelMgr.getQuestTravelDestinations(bot, questId, true, true, -1); + std::vector allDestinations = sTravelMgr.GetQuestTravelDestinations(bot, questId, true, true, -1); std::sort(allDestinations.begin(), allDestinations.end(), [botPos](TravelDestination* i, TravelDestination* j) {return i->DistanceTo(botPos) < j->DistanceTo(botPos); }); diff --git a/playerbot/strategy/actions/ReleaseSpiritAction.h b/playerbot/strategy/actions/ReleaseSpiritAction.h index daba09c5..badddf6b 100644 --- a/playerbot/strategy/actions/ReleaseSpiritAction.h +++ b/playerbot/strategy/actions/ReleaseSpiritAction.h @@ -160,7 +160,7 @@ namespace ai ai->TellPlayer(requester, BOT_TEXT("hello"), PlayerbotSecurityLevel::PLAYERBOT_SECURITY_ALLOW_ALL, false); TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); - travelTarget->setTarget(sTravelMgr.nullTravelDestination, sTravelMgr.nullWorldPosition, true); + sTravelMgr.SetNullTravelTarget(travelTarget); travelTarget->setStatus(TravelStatus::TRAVEL_STATUS_EXPIRED); travelTarget->setExpireIn(1000); diff --git a/playerbot/strategy/actions/RpgAction.cpp b/playerbot/strategy/actions/RpgAction.cpp index fc10d1fe..e1d6c562 100644 --- a/playerbot/strategy/actions/RpgAction.cpp +++ b/playerbot/strategy/actions/RpgAction.cpp @@ -126,7 +126,7 @@ bool RpgAction::SetNextRpgAction() std::mt19937 gen(time(0)); - sTravelMgr.weighted_shuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen); + WeightedShuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen); Action* action = actions.front(); diff --git a/playerbot/strategy/values/GrindTargetValue.cpp b/playerbot/strategy/values/GrindTargetValue.cpp index 97adb3df..ca08e4b2 100644 --- a/playerbot/strategy/values/GrindTargetValue.cpp +++ b/playerbot/strategy/values/GrindTargetValue.cpp @@ -131,11 +131,8 @@ Unit* GrindTargetValue::FindTargetForGrinding(int assistCount) } float newdistance = sServerFacade.GetDistance2d(bot, unit); - - if (needForQuestMap.find(unit->GetEntry()) == needForQuestMap.end()) - needForQuestMap[unit->GetEntry()] = needForQuest(unit); - - if (!needForQuestMap[unit->GetEntry()]) + + if (unit->GetEntry() && !AI_VALUE2(bool, "need for quest", std::to_string(unit->GetEntry()))) { if (urand(0, 100) < 99 && AI_VALUE(TravelTarget*, "travel target")->isWorking() && typeid(AI_VALUE(TravelTarget*, "travel target")->getDestination()) != typeid(GrindTravelDestination)) { @@ -212,87 +209,6 @@ Unit* GrindTargetValue::FindTargetForGrinding(int assistCount) return result; } -bool GrindTargetValue::needForQuest(Unit* target) -{ - bool justCheck = (bot->GetObjectGuid() == target->GetObjectGuid()); - - QuestStatusMap& questMap = bot->getQuestStatusMap(); - for (auto& quest : questMap) - { - const Quest* questTemplate = sObjectMgr.GetQuestTemplate(quest.first); - if (!questTemplate) - continue; - - uint32 questId = questTemplate->GetQuestId(); - - if (!questId) - continue; - - QuestStatus status = bot->GetQuestStatus(questId); - - if ((status == QUEST_STATUS_COMPLETE && !bot->GetQuestRewardStatus(questId))) - { - if (!justCheck && !target->HasInvolvedQuest(questId)) - continue; - - return true; - } - else if (status == QUEST_STATUS_INCOMPLETE) - { - QuestStatusData* questStatus = sTravelMgr.getQuestStatus(bot, questId); - - if ((int32)questTemplate->GetQuestLevel() > (int32)bot->GetLevel()+5) - continue; - - for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) - { - int32 entry = questTemplate->ReqCreatureOrGOId[j]; - - if (entry && entry > 0) - { - int required = questTemplate->ReqCreatureOrGOCount[j]; - int available = questStatus->m_creatureOrGOcount[j]; - - if (required && available < required && (target->GetEntry() == entry || justCheck)) - return true; - } - - if (justCheck) - { - int32 itemId = questTemplate->ReqItemId[j]; - - if (itemId && itemId > 0) - { - int required = questTemplate->ReqItemCount[j]; - int available = questStatus->m_itemcount[j]; - - if (required && available < required) - return true; - } - } - } - - if (!justCheck) - { - CreatureInfo const* data = sObjectMgr.GetCreatureTemplate(target->GetEntry()); - - if (data) - { - uint32 lootId = data->LootId; - - if (lootId) - { - if (LootTemplates_Creature.HaveQuestLootForPlayer(lootId, bot)) - return true; - } - } - } - } - - } - return false; -} - int GrindTargetValue::GetTargetingPlayerCount( Unit* unit ) { Group* group = bot->GetGroup(); diff --git a/playerbot/strategy/values/GrindTargetValue.h b/playerbot/strategy/values/GrindTargetValue.h index 40390718..8729f436 100644 --- a/playerbot/strategy/values/GrindTargetValue.h +++ b/playerbot/strategy/values/GrindTargetValue.h @@ -16,7 +16,5 @@ namespace ai private: int GetTargetingPlayerCount(Unit* unit); Unit* FindTargetForGrinding(int assistCount); - - bool needForQuest(Unit* target); }; } diff --git a/playerbot/strategy/values/QuestValues.cpp b/playerbot/strategy/values/QuestValues.cpp index 507487d7..6f920834 100644 --- a/playerbot/strategy/values/QuestValues.cpp +++ b/playerbot/strategy/values/QuestValues.cpp @@ -334,6 +334,61 @@ std::list ActiveQuestObjectivesValue::Calculate() return retQuestObjectives; } +bool NeedForQuestValue::Calculate() +{ + int32 entry = stoi(getQualifier()); + + questGuidpMap questMap = GAI_VALUE(questGuidpMap, "quest guidp map"); + + std::list retQuestObjectives; + + QuestStatusMap& questStatusMap = bot->getQuestStatusMap(); + + for (auto& questStatus : questStatusMap) + { + uint32 questId = questStatus.first; + + Quest const* quest = sObjectMgr.GetQuestTemplate(questId); + + if (!quest || !quest->IsActive()) + { + continue; + } + + QuestStatusData statusData = questStatus.second; + + if (statusData.m_status != QUEST_STATUS_INCOMPLETE) + continue; + + for (uint32 objective = 0; objective < QUEST_OBJECTIVES_COUNT; objective++) + { + std::vector qualifier = { std::to_string(questId), std::to_string(objective) }; + + if (!AI_VALUE2(bool, "need quest objective", Qualified::MultiQualify(qualifier, ","))) + continue; + + auto q = questMap.find(questId); + + if (q == questMap.end()) + continue; + + auto qt = q->second.find((int)QuestRelationFlag(1 << objective)); + + if (qt == q->second.end()) + continue; + + for (auto& [objectiveEntry, guidPs] : qt->second) + { + if (entry == objectiveEntry) + return true; + + } + } + } + + return false; +} + uint8 FreeQuestLogSlotValue::Calculate() { uint8 numQuest = 0; diff --git a/playerbot/strategy/values/QuestValues.h b/playerbot/strategy/values/QuestValues.h index 0d1d7818..ae5ad985 100644 --- a/playerbot/strategy/values/QuestValues.h +++ b/playerbot/strategy/values/QuestValues.h @@ -121,6 +121,14 @@ namespace ai ActiveQuestObjectivesValue(PlayerbotAI* ai) : CalculatedValue(ai, "active quest objectives", 5) {} virtual std::list Calculate() override; }; + + //Check if a specific entry is a quest objective that the bot has to complete. + class NeedForQuestValue : public BoolCalculatedValue, Qualified + { + public: + NeedForQuestValue(PlayerbotAI* ai) : BoolCalculatedValue(ai, "need for quest", 5) {} + virtual bool Calculate() override; + }; //Free quest log slots class FreeQuestLogSlotValue : public Uint8CalculatedValue diff --git a/playerbot/strategy/values/ValueContext.h b/playerbot/strategy/values/ValueContext.h index f7902bf5..c2f4dd9e 100644 --- a/playerbot/strategy/values/ValueContext.h +++ b/playerbot/strategy/values/ValueContext.h @@ -313,6 +313,7 @@ namespace ai creators["can repeat quest npc"] = [](PlayerbotAI* ai) { return new CanRepeatQuestValue(ai); }; creators["need quest reward"] = [](PlayerbotAI* ai) { return new NeedQuestRewardValue(ai); }; creators["need quest objective"] = [](PlayerbotAI* ai) { return new NeedQuestObjectiveValue(ai); }; + creators["need for quest"] = [](PlayerbotAI* ai) { return new NeedForQuestValue(ai); }; creators["can use item on"] = [](PlayerbotAI* ai) { return new CanUseItemOn(ai); }; creators["quest reward"] = [](PlayerbotAI* ai) { return new QuestRewardValue(ai); }; creators["has nearby quest taker"] = [](PlayerbotAI* ai) { return new HasNearbyQuestTakerValue(ai); };