diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index ec0e9bf0..84fd4a48 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -4220,12 +4220,12 @@ Item* PlayerbotAI::FindStoneFor(Item* weapon) const return stone; } -static const uint32 uPriorizedWizardOilIds[5] = +static const std::vector uPriorizedWizardOilIds = { MINOR_WIZARD_OIL, LESSER_WIZARD_OIL, BRILLIANT_WIZARD_OIL, WIZARD_OIL, SUPERIOR_WIZARD_OIL }; -static const uint32 uPriorizedManaOilIds[4] = +static const std::vector uPriorizedManaOilIds = { MINOR_MANA_OIL, LESSER_MANA_OIL, BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, }; @@ -4236,26 +4236,26 @@ Item* PlayerbotAI::FindOilFor(Item* weapon) const ItemTemplate const* pProto = weapon->GetTemplate(); if (pProto && (pProto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || pProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || pProto->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)) { - for (uint8 i = 0; i < std::size(uPriorizedWizardOilIds); ++i) + for (const auto& id : uPriorizedWizardOilIds) { - oil = FindConsumable(uPriorizedWizardOilIds[i]); + oil = FindConsumable(uPriorizedWizardOilIds[id]); if (!oil) - oil = FindConsumable(uPriorizedManaOilIds[i]); + oil = FindConsumable(uPriorizedManaOilIds[id]); if (oil) - return oil; + return oil; } } else if (pProto && (pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE || pProto->SubClass == ITEM_SUBCLASS_WEAPON_MACE2)) { - for (uint8 i = 0; i < std::size(uPriorizedManaOilIds); ++i) + for (const auto& id : uPriorizedManaOilIds) { - oil = FindConsumable(uPriorizedManaOilIds[i]); + oil = FindConsumable(uPriorizedManaOilIds[id]); if (!oil) - oil = FindConsumable(uPriorizedWizardOilIds[i]); + oil = FindConsumable(uPriorizedWizardOilIds[id]); if (oil) - return oil; + return oil; } } @@ -4741,3 +4741,11 @@ uint8 PlayerbotAI::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool sw // no free position return NULL_SLOT; } +bool PlayerbotAI::IsSafe(Player* player) +{ + return player && player->GetMapId() == bot->GetMapId() && player->GetInstanceId() == bot->GetInstanceId() && !player->IsBeingTeleported(); +} +bool PlayerbotAI::IsSafe(WorldObject* obj) +{ + return obj && obj->GetMapId() == bot->GetMapId() && obj->GetInstanceId() == bot->GetInstanceId() && (!obj->IsPlayer() || !((Player*)obj)->IsBeingTeleported()); +} diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 79eea13e..cad89fd2 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -433,6 +433,11 @@ class PlayerbotAI : public PlayerbotAIBase bool AllowActive(ActivityType activityType); bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false); + //Check if player is safe to use. + bool IsSafe(Player* player); + bool IsSafe(WorldObject* obj); + + bool HasCheat(BotCheatMask mask) { return ((uint32)mask & (uint32)cheatMask) != 0 || ((uint32)mask & (uint32)sPlayerbotAIConfig->botCheatMask) != 0; } BotCheatMask GetCheat() { return cheatMask; } void SetCheat(BotCheatMask mask) { cheatMask = mask; } diff --git a/src/TravelMgr.cpp b/src/TravelMgr.cpp index 14e288e3..9e96fdde 100644 --- a/src/TravelMgr.cpp +++ b/src/TravelMgr.cpp @@ -1096,27 +1096,10 @@ bool QuestRelationTravelDestination::isActive(Player* bot) if (AI_VALUE(uint8, "free quest log slots") < 5) return false; - if (!AI_VALUE2(bool, "group or", "following party,near leader,can accept quest npc::" + std::to_string(entry))) //Noone has yellow exclamation mark. + //None has yellow exclamation mark. + if (!AI_VALUE2(bool, "group or", "following party,near leader,can accept quest npc::" + std::to_string(entry))) if (!AI_VALUE2(bool, "group or", "following party,near leader,can accept quest low level npc::" + std::to_string(entry) + "need quest objective::" + std::to_string(questId))) //Noone can do this quest for a usefull reward. return false; - - // higher chance bot will do rewarding quest (better gear etc) - if (dialogStatus != DIALOG_STATUS_AVAILABLE) - { - if (dialogStatus != DIALOG_STATUS_LOW_LEVEL_AVAILABLE) - { - bool hasGoodReward = false; - for (uint8 i = 0; i < questTemplate->GetRewChoiceItemsCount(); ++i) - { - ItemUsage usage = AI_VALUE2_LAZY(ItemUsage, "item usage", questTemplate->RewardChoiceItemId[i]); - if (usage == ITEM_USAGE_EQUIP || usage == ITEM_USAGE_REPLACE) - { - hasGoodReward = true; - break; - } - } - } - } } else { @@ -1275,7 +1258,8 @@ std::string const RpgTravelDestination::getTitle() { std::ostringstream out; - out << "rpg npc "; + if(entry > 0) + out << "rpg npc "; out << " " << ChatHelper::FormatWorldEntry(entry); diff --git a/src/strategy/actions/AcceptQuestAction.cpp b/src/strategy/actions/AcceptQuestAction.cpp index 5f3c0171..dd00ccad 100644 --- a/src/strategy/actions/AcceptQuestAction.cpp +++ b/src/strategy/actions/AcceptQuestAction.cpp @@ -15,7 +15,7 @@ bool AcceptAllQuestsAction::ProcessQuest(Quest const* quest, Object* questGiver) if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) { - LOG_INFO("playerbots", "Quest [ {} ] accepted", quest->GetTitle()); + LOG_INFO("playerbots", "{} => Quest [ {} ] accepted", bot->GetName(), quest->GetTitle()); bot->Say("Quest [ " + text_quest + " ] accepted", LANG_UNIVERSAL); } diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index e7caf4e2..795c7aab 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -8,6 +8,7 @@ #include "AddLootAction.h" #include "AttackAction.h" #include "AutoLearnSpellAction.h" +#include "ShareQuestAction.h" #include "BattleGroundTactics.h" #include "BattleGroundJoinAction.h" #include "BuyAction.h" @@ -152,6 +153,7 @@ class ActionContext : public NamedObjectContext creators["war stomp"] = &ActionContext::war_stomp; creators["auto talents"] = &ActionContext::auto_talents; creators["auto learn spell"] = &ActionContext::auto_learn_spell; + creators["auto share quest"] = &ActionContext::auto_share_quest; creators["auto teleport for level"] = &ActionContext::auto_teleport_for_level; creators["auto upgrade equip"] = &ActionContext::auto_upgrade_equip; creators["xp gain"] = &ActionContext::xp_gain; @@ -321,6 +323,7 @@ class ActionContext : public NamedObjectContext static Action* war_stomp(PlayerbotAI* botAI) { return new CastWarStompAction(botAI); } static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); } static Action* auto_learn_spell(PlayerbotAI* botAI) { return new AutoLearnSpellAction(botAI); } + static Action* auto_share_quest(PlayerbotAI* ai) { return new AutoShareQuestAction(ai); } static Action* auto_teleport_for_level(PlayerbotAI* botAI) { return new AutoTeleportForLevelAction(botAI); } static Action* auto_upgrade_equip(PlayerbotAI* botAI) { return new AutoUpgradeEquipAction(botAI); } static Action* xp_gain(PlayerbotAI* botAI) { return new XpGainAction(botAI); } diff --git a/src/strategy/actions/ChatActionContext.h b/src/strategy/actions/ChatActionContext.h index 8fb48c64..8476389d 100644 --- a/src/strategy/actions/ChatActionContext.h +++ b/src/strategy/actions/ChatActionContext.h @@ -171,7 +171,7 @@ class ChatActionContext : public NamedObjectContext creators["naxx chat shortcut"] = &ChatActionContext::naxx_chat_shortcut; creators["bwl chat shortcut"] = &ChatActionContext::bwl_chat_shortcut; creators["tell expected dps"] = &ChatActionContext::tell_expected_dps; - + creators["join"] = &ChatActionContext::join; } private: @@ -268,6 +268,7 @@ class ChatActionContext : public NamedObjectContext static Action* naxx_chat_shortcut(PlayerbotAI* ai) { return new NaxxChatShortcutAction(ai); } static Action* bwl_chat_shortcut(PlayerbotAI* ai) { return new BwlChatShortcutAction(ai); } static Action* tell_expected_dps(PlayerbotAI* ai) { return new TellExpectedDpsAction(ai); } + static Action* join(PlayerbotAI* ai) { return new JoinGroupAction(ai); } }; #endif diff --git a/src/strategy/actions/ChooseRpgTargetAction.cpp b/src/strategy/actions/ChooseRpgTargetAction.cpp index 8054dd9e..08f4f3b5 100644 --- a/src/strategy/actions/ChooseRpgTargetAction.cpp +++ b/src/strategy/actions/ChooseRpgTargetAction.cpp @@ -129,11 +129,18 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP) bool ChooseRpgTargetAction::Execute(Event event) { TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target"); - - uint32 num = 0; + Player* master = botAI->GetMaster(); + GuidPosition masterRpgTarget; + if (master && master != bot && GET_PLAYERBOT_AI(master) && master->GetMapId() == bot->GetMapId() && !master->IsBeingTeleported()) + { + Player* player = botAI->GetMaster(); + GuidPosition masterRpgTarget = PAI_VALUE(GuidPosition, "rpg target"); + } + else + master = nullptr; std::unordered_map targets; - + uint32 num = 0; GuidVector possibleTargets = AI_VALUE(GuidVector, "possible rpg targets"); GuidVector possibleObjects = AI_VALUE(GuidVector, "nearest game objects no los"); GuidVector possiblePlayers = AI_VALUE(GuidVector, "nearest friendly players"); @@ -216,10 +223,15 @@ bool ChooseRpgTargetAction::Execute(Event event) for (auto it = begin(targets); it != end(targets);) { - if (it->second == 0 || (hasGoodRelevance && it->second <= 1.0)) - { + //Remove empty targets. + if (it->second == 0) + it = targets.erase(it); + //Remove useless targets if there's any good ones + else if (hasGoodRelevance && it->second <= 1.0) + it = targets.erase(it); + //Remove useless targets if it's not masters target. + else if (!hasGoodRelevance && master && (!masterRpgTarget || it->first != masterRpgTarget)) it = targets.erase(it); - } else ++it; } diff --git a/src/strategy/actions/ChooseTravelTargetAction.cpp b/src/strategy/actions/ChooseTravelTargetAction.cpp index e27b9d62..54f5b05c 100644 --- a/src/strategy/actions/ChooseTravelTargetAction.cpp +++ b/src/strategy/actions/ChooseTravelTargetAction.cpp @@ -44,11 +44,11 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge foundTarget = SetGroupTarget(newTarget); //Join groups members //Empty bags/repair - if (!foundTarget && urand(1, 100) > 10) //90% chance + if (!foundTarget && urand(1, 100) > 10 && bot->GetLevel() > 5) //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)) + 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 } @@ -132,11 +132,13 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge //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 { diff --git a/src/strategy/actions/DropQuestAction.cpp b/src/strategy/actions/DropQuestAction.cpp index c659fec6..d595cccb 100644 --- a/src/strategy/actions/DropQuestAction.cpp +++ b/src/strategy/actions/DropQuestAction.cpp @@ -48,7 +48,7 @@ bool DropQuestAction::Execute(Event event) { const Quest* pQuest = sObjectMgr->GetQuestTemplate(entry); const std::string text_quest = ChatHelper::FormatQuest(pQuest); - LOG_INFO("playerbots", "Quest [ {} ] removed", pQuest->GetTitle()); + LOG_INFO("playerbots", "{} => Quest [ {} ] removed", bot->GetName(), pQuest->GetTitle()); bot->Say("Quest [ " + text_quest + " ] removed", LANG_UNIVERSAL); } @@ -103,7 +103,19 @@ bool CleanQuestLogAction::Execute(Event event) void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isGreen, bool hasProgress, bool isComplete) { + std::vector slots; for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + slots.push_back(slot); + + if (wantNum < 100) + { + std::random_device rd; + std::mt19937 g(rd()); + + std::shuffle(slots.begin(), slots.end(), g); + } + + for (uint8 slot : slots) { uint32 questId = bot->GetQuestSlotQuestId(slot); if (!questId) @@ -153,6 +165,12 @@ void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isG numQuest--; + if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT)) + { + const std::string text_quest = ChatHelper::FormatQuest(quest); + LOG_INFO("playerbots", "{} => Quest [ {} ] removed", bot->GetName(), quest->GetTitle()); + bot->Say("Quest [ " + text_quest + " ] removed", LANG_UNIVERSAL); + } botAI->TellMaster("Quest removed" + chat->FormatQuest(quest)); } } diff --git a/src/strategy/actions/InviteToGroupAction.cpp b/src/strategy/actions/InviteToGroupAction.cpp index 58094fc6..0967a823 100644 --- a/src/strategy/actions/InviteToGroupAction.cpp +++ b/src/strategy/actions/InviteToGroupAction.cpp @@ -22,9 +22,16 @@ bool InviteToGroupAction::Invite(Player* player) if (!player || !player->IsInWorld()) return false; + if (bot == player) + return false; + if (!GET_PLAYERBOT_AI(player) && !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_INVITE, true, player)) return false; + if (Group* group = player->GetGroup()) + if (!group->isRaidGroup() && group->GetMembersCount() > 4) + group->ConvertToRaid(); + WorldPacket p; uint32 roles_mask = 0; p << player->GetName(); @@ -46,6 +53,9 @@ bool InviteNearbyToGroupAction::Execute(Event event) if (player->GetGroup()) continue; + if (player == bot) + continue; + if (botAI) { if (botAI->GetGrouperType() == GrouperType::SOLO && !botAI->HasRealPlayerMaster()) // Do not invite solo players. @@ -165,3 +175,18 @@ bool InviteGuildToGroupAction::isUseful() { return bot->GetGuildId() && InviteNearbyToGroupAction::isUseful(); }; + +bool JoinGroupAction::Execute(Event event) +{ + Player* master = event.getOwner(); + Group* group = master->GetGroup(); + + if (group && (group->IsFull() || bot->GetGroup() == group)) + return false; + + if (bot->GetGroup()) + if (!botAI->DoSpecificAction("leave", event, true)) + return false; + + return Invite(bot); +} \ No newline at end of file diff --git a/src/strategy/actions/InviteToGroupAction.h b/src/strategy/actions/InviteToGroupAction.h index 8b8fa7f7..5bc138ed 100644 --- a/src/strategy/actions/InviteToGroupAction.h +++ b/src/strategy/actions/InviteToGroupAction.h @@ -20,6 +20,14 @@ class InviteToGroupAction : public Action virtual bool Invite(Player* player); }; +class JoinGroupAction : public InviteToGroupAction +{ +public: + JoinGroupAction(PlayerbotAI* ai, std::string name = "join") : InviteToGroupAction(ai, name) {} + bool Execute(Event event) override; + bool isUseful() override { return !bot->IsBeingTeleported(); } +}; + class InviteNearbyToGroupAction : public InviteToGroupAction { public: diff --git a/src/strategy/actions/LeaveGroupAction.cpp b/src/strategy/actions/LeaveGroupAction.cpp index 433d45e7..33f85b51 100644 --- a/src/strategy/actions/LeaveGroupAction.cpp +++ b/src/strategy/actions/LeaveGroupAction.cpp @@ -97,14 +97,12 @@ bool LeaveGroupAction::Leave(Player* player) bool LeaveFarAwayAction::Execute(Event event) { - return Leave(nullptr); + // allow bot to leave party when they want + return Leave(botAI->GetGroupMaster()); } bool LeaveFarAwayAction::isUseful() { - if (!sPlayerbotAIConfig->randomBotGroupNearby) - return false; - if (bot->InBattleground()) return false; diff --git a/src/strategy/actions/QuestAction.cpp b/src/strategy/actions/QuestAction.cpp index 978654e6..cd28687b 100644 --- a/src/strategy/actions/QuestAction.cpp +++ b/src/strategy/actions/QuestAction.cpp @@ -135,7 +135,7 @@ bool QuestAction::CompleteQuest(Player* player, uint32 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()); + LOG_INFO("playerbots", "{} => Quest [ {} ] completed", bot->GetName(), pQuest->GetTitle()); bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); } botAI->TellMasterNoFacing("Quest completed " + text_quest); @@ -244,6 +244,9 @@ bool QuestUpdateCompleteAction::Execute(Event event) WorldPacket p(event.getPacket()); p.rpos(0); + if (p.empty()) + return false; + uint32 entry, questId, available, required; ObjectGuid guid; p >> questId >> entry >> available >> required >> guid; @@ -254,7 +257,7 @@ bool QuestUpdateCompleteAction::Execute(Event event) 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()); + LOG_INFO("playerbots", "{} => Quest [ {} ] completed", bot->GetName(), qInfo->GetTitle()); bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); } botAI->TellMasterNoFacing("Quest completed " + text_quest); diff --git a/src/strategy/actions/ShareQuestAction.cpp b/src/strategy/actions/ShareQuestAction.cpp index 8ab7c8ba..22e68c1a 100644 --- a/src/strategy/actions/ShareQuestAction.cpp +++ b/src/strategy/actions/ShareQuestAction.cpp @@ -37,3 +37,74 @@ bool ShareQuestAction::Execute(Event event) return false; } + +bool AutoShareQuestAction::Execute(Event event) +{ + Player* requester = event.getOwner() ? event.getOwner() : GetMaster(); + bool shared = false; + + for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + { + uint32 logQuest = bot->GetQuestSlotQuestId(slot); + Quest const* quest = sObjectMgr->GetQuestTemplate(logQuest); + + if (!quest) + continue; + + bool partyNeedsQuest = false; + + for (GroupReference* itr = bot->GetGroup()->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player* player = itr->GetSource(); + + if (!player || player == bot || !player->IsInWorld() || !botAI->IsSafe(player)) // skip self + continue; + + if (bot->GetDistance(player) > 10) + continue; + + if (!player->SatisfyQuestStatus(quest, false)) + continue; + + if (player->GetQuestStatus(logQuest) == QUEST_STATUS_COMPLETE) + continue; + + if (!player->CanTakeQuest(quest, false)) + continue; + + if (!player->SatisfyQuestLog(false)) + continue; + + if (player->GetDivider()) + continue; + + if (auto ai = GET_PLAYERBOT_AI(player)) + { + if (PAI_VALUE(uint8, "free quest log slots") < 15 || !urand(0,5)) + { + WorldPacket packet(CMSG_PUSHQUESTTOPARTY, 20); + packet << logQuest; + ai->HandleMasterIncomingPacket(packet); + } + } + else + partyNeedsQuest = true; + } + + if (!partyNeedsQuest) + continue; + + WorldPacket p; + p << logQuest; + bot->GetSession()->HandlePushQuestToParty(p); + botAI->TellMaster("Quest shared"); + shared = true; + } + + return shared; +} + +bool AutoShareQuestAction::isUseful() +{ + return bot->GetGroup() && !botAI->HasActivePlayerMaster(); +} \ No newline at end of file diff --git a/src/strategy/actions/ShareQuestAction.h b/src/strategy/actions/ShareQuestAction.h index dc646787..86c185b1 100644 --- a/src/strategy/actions/ShareQuestAction.h +++ b/src/strategy/actions/ShareQuestAction.h @@ -12,9 +12,18 @@ class PlayerbotAI; class ShareQuestAction : public Action { public: - ShareQuestAction(PlayerbotAI* botAI) : Action(botAI, "share quest") { } + ShareQuestAction(PlayerbotAI* botAI, std::string name = "share quest") : Action(botAI, name) { } bool Execute(Event event) override; }; +class AutoShareQuestAction : public ShareQuestAction +{ +public: + AutoShareQuestAction(PlayerbotAI* ai) : ShareQuestAction(botAI, "auto share quest") {} + bool Execute(Event event) override; + + bool isUseful() override; +}; + #endif diff --git a/src/strategy/actions/TalkToQuestGiverAction.cpp b/src/strategy/actions/TalkToQuestGiverAction.cpp index 402161b0..329c0f9b 100644 --- a/src/strategy/actions/TalkToQuestGiverAction.cpp +++ b/src/strategy/actions/TalkToQuestGiverAction.cpp @@ -87,7 +87,7 @@ bool TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver, { const Quest* pQuest = sObjectMgr->GetQuestTemplate(questID); const std::string text_quest = ChatHelper::FormatQuest(pQuest); - LOG_INFO("playerbots", "Quest [ {} ] completed", pQuest->GetTitle()); + LOG_INFO("playerbots", "{} => Quest [ {} ] completed", bot->GetName(), pQuest->GetTitle()); bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL); } diff --git a/src/strategy/generic/MaintenanceStrategy.cpp b/src/strategy/generic/MaintenanceStrategy.cpp index db1a9e13..01ad78ef 100644 --- a/src/strategy/generic/MaintenanceStrategy.cpp +++ b/src/strategy/generic/MaintenanceStrategy.cpp @@ -20,5 +20,6 @@ void MaintenanceStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("move stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr))); // triggers.push_back(new TriggerNode("move long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f), new NextAction("repop", 0.8f), nullptr))); triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("use random quest item", 0.9f), nullptr))); + triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("auto share quest", 0.9f), NULL))); } diff --git a/src/strategy/triggers/RpgTriggers.cpp b/src/strategy/triggers/RpgTriggers.cpp index eee38718..2f00affd 100644 --- a/src/strategy/triggers/RpgTriggers.cpp +++ b/src/strategy/triggers/RpgTriggers.cpp @@ -305,6 +305,10 @@ bool RpgQueueBGTrigger::IsActive() if (!guidP.IsCreature()) return false; + + // if bot is not leader disallow tag bg + if (bot->GetGroup() && !bot->GetGroup()->IsLeader(bot->GetGUID())) + return false; if (AI_VALUE(BattlegroundTypeId, "rpg bg type") == BATTLEGROUND_TYPE_NONE) return false; diff --git a/src/strategy/values/GrindTargetValue.cpp b/src/strategy/values/GrindTargetValue.cpp index 55051d4d..313f7cf0 100644 --- a/src/strategy/values/GrindTargetValue.cpp +++ b/src/strategy/values/GrindTargetValue.cpp @@ -6,6 +6,7 @@ #include "Playerbots.h" #include "ReputationMgr.h" #include "SharedDefines.h" +#include "ServerFacade.h" Unit* GrindTargetValue::Calculate() { @@ -80,6 +81,15 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount) //if (!bot->InBattleground() && master && master->GetDistance(unit) >= sPlayerbotAIConfig->grindDistance && !sRandomPlayerbotMgr->IsRandomBot(bot)) //continue; + // Bots in bot-groups no have a more limited range to look for grind target + if (!bot->InBattleground() && master && botAI->HasStrategy("follow", BotState::BOT_STATE_NON_COMBAT) + && sServerFacade->GetDistance2d(master, unit) > sPlayerbotAIConfig->lootDistance) + { + if (botAI->HasStrategy("debug grind", BotState::BOT_STATE_NON_COMBAT)) + botAI->TellMaster(chat->FormatWorldobject(unit) + " ignored (far from master)."); + continue; + } + if (!bot->InBattleground() && (int)unit->GetLevel() - (int)bot->GetLevel() > 4 && !unit->GetGUID().IsPlayer()) continue;