mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Bot should be more consistent at doing quest +several fixes
This commit is contained in:
@@ -558,7 +558,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
nonCombatEngine->addStrategies("nc", "food", "chat", "follow",
|
||||
"default", "quest", "loot", "gather", "duel", "buff", "mount", "emote", nullptr);
|
||||
}
|
||||
if (sPlayerbotAIConfig->autoSaveMana) {
|
||||
if (sPlayerbotAIConfig->autoSaveMana){
|
||||
nonCombatEngine->addStrategy("auto save mana");
|
||||
}
|
||||
if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
|
||||
@@ -588,7 +588,9 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
{
|
||||
// nonCombatEngine->addStrategy("travel");
|
||||
nonCombatEngine->addStrategy("rpg");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
nonCombatEngine->addStrategy("move random");
|
||||
}
|
||||
|
||||
|
||||
@@ -128,15 +128,12 @@ PlayerbotAI::PlayerbotAI(Player* bot) : PlayerbotAIBase(true), bot(bot), chatHel
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_LOOT_ROLL, "loot roll");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_GOSSIP_HELLO, "gossip hello");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUESTGIVER_HELLO, "gossip hello");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUESTGIVER_COMPLETE_QUEST, "complete quest");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUESTGIVER_ACCEPT_QUEST, "accept quest");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_ACTIVATETAXI, "activate taxi");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_ACTIVATETAXIEXPRESS, "activate taxi");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_TAXICLEARALLNODES, "taxi done");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_TAXICLEARNODE, "taxi done");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_GROUP_UNINVITE, "uninvite");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_GROUP_UNINVITE_GUID, "uninvite guid");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_PUSHQUESTTOPARTY, "quest share");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_LFG_TELEPORT, "lfg teleport");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_CAST_SPELL, "see spell");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_REPOP_REQUEST, "release spirit");
|
||||
@@ -153,7 +150,6 @@ PlayerbotAI::PlayerbotAI(Player* bot) : PlayerbotAIBase(true), bot(bot), chatHel
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_INVENTORY_CHANGE_FAILURE, "cannot equip");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_TRADE_STATUS, "trade status");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_LOOT_RESPONSE, "loot response");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_KILL, "quest objective completed");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_ITEM_PUSH_RESULT, "item push result");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_PARTY_COMMAND_RESULT, "party command");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_LEVELUP_INFO, "levelup");
|
||||
@@ -168,7 +164,6 @@ PlayerbotAI::PlayerbotAI(Player* bot) : PlayerbotAIBase(true), bot(bot), chatHel
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_EMOTE, "receive emote");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_LOOT_START_ROLL, "master loot roll");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_ARENA_TEAM_INVITE, "arena team invite");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUEST_CONFIRM_ACCEPT, "quest confirm accept");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_GROUP_DESTROYED, "group destroyed");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_GROUP_LIST, "group list");
|
||||
|
||||
@@ -176,7 +171,16 @@ PlayerbotAI::PlayerbotAI(Player* bot) : PlayerbotAIBase(true), bot(bot), chatHel
|
||||
masterOutgoingPacketHandlers.AddHandler(SMSG_PARTY_COMMAND_RESULT, "party command");
|
||||
masterOutgoingPacketHandlers.AddHandler(MSG_RAID_READY_CHECK, "ready check");
|
||||
masterOutgoingPacketHandlers.AddHandler(MSG_RAID_READY_CHECK_FINISHED, "ready check finished");
|
||||
masterOutgoingPacketHandlers.AddHandler(SMSG_QUESTGIVER_OFFER_REWARD, "questgiver quest details");
|
||||
|
||||
// quest packet
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUESTGIVER_COMPLETE_QUEST, "complete quest");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUESTGIVER_ACCEPT_QUEST, "accept quest");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_QUEST_CONFIRM_ACCEPT, "confirm quest");
|
||||
masterIncomingPacketHandlers.AddHandler(CMSG_PUSHQUESTTOPARTY, "quest share");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_COMPLETE, "quest update complete");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_KILL, "quest update add kill");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUESTUPDATE_ADD_ITEM, "quest update add item");
|
||||
botOutgoingPacketHandlers.AddHandler(SMSG_QUEST_CONFIRM_ACCEPT, "confirm quest");
|
||||
}
|
||||
|
||||
PlayerbotAI::~PlayerbotAI()
|
||||
|
||||
@@ -114,6 +114,16 @@ void WorldPosition::set(const WorldLocation& pos)
|
||||
WorldRelocate(pos);
|
||||
}
|
||||
|
||||
void WorldPosition::set(const WorldPosition& pos)
|
||||
{
|
||||
WorldRelocate(pos.m_mapId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
|
||||
}
|
||||
|
||||
void WorldPosition::set(const WorldObject* pos)
|
||||
{
|
||||
WorldRelocate(pos->GetMapId(), pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), pos->GetOrientation());
|
||||
}
|
||||
|
||||
void WorldPosition::setMapId(uint32 id)
|
||||
{
|
||||
m_mapId = id;
|
||||
@@ -1061,30 +1071,59 @@ std::string const QuestTravelDestination::getTitle()
|
||||
|
||||
bool QuestRelationTravelDestination::isActive(Player* bot)
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
AiObjectContext* context = botAI->GetAiObjectContext();
|
||||
|
||||
if (botAI && !botAI->HasStrategy("rpg quest", BOT_STATE_NON_COMBAT))
|
||||
return false;
|
||||
|
||||
if (relation == 0)
|
||||
{
|
||||
if (questTemplate->GetQuestLevel() >= bot->GetLevel() + 5)
|
||||
if ((int32)questTemplate->GetQuestLevel() >= (int32)bot->GetLevel() + (int32)5)
|
||||
return false;
|
||||
|
||||
//if (questTemplate->XPValue(bot) == 0)
|
||||
// return false;
|
||||
// skip for now this quest
|
||||
if (getPoints().front()->GetMapId() != bot->GetMapId())
|
||||
return false;
|
||||
|
||||
if (!bot->GetMap()->GetEntry()->IsWorldMap() || !bot->CanTakeQuest(questTemplate, false))
|
||||
return false;
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
AiObjectContext* context = botAI->GetAiObjectContext();
|
||||
|
||||
uint32 dialogStatus = sTravelMgr->getDialogStatus(bot, entry, questTemplate);
|
||||
|
||||
if (AI_VALUE(bool, "can fight equal"))
|
||||
{
|
||||
if (dialogStatus != DIALOG_STATUS_AVAILABLE)
|
||||
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.
|
||||
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
|
||||
{
|
||||
if (dialogStatus != DIALOG_STATUS_LOW_LEVEL_AVAILABLE)
|
||||
if (!AI_VALUE2(bool, "group or", "following party,near leader,can accept quest low level npc::" + std::to_string(entry))) //Noone can pick up this quest for money.
|
||||
return false;
|
||||
|
||||
if (AI_VALUE(uint8, "free quest log slots") < 10)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1094,25 +1133,14 @@ bool QuestRelationTravelDestination::isActive(Player* bot)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bot->IsActiveQuest(questId))
|
||||
if (!AI_VALUE2(bool, "group or", "following party,near leader,can turn in quest npc::" + std::to_string(entry)))
|
||||
return false;
|
||||
|
||||
if (!bot->CanRewardQuest(questTemplate, false))
|
||||
return false;
|
||||
|
||||
uint32 dialogStatus = sTravelMgr->getDialogStatus(bot, entry, questTemplate);
|
||||
|
||||
if (dialogStatus != DIALOG_STATUS_REWARD2 && dialogStatus != DIALOG_STATUS_REWARD && dialogStatus != DIALOG_STATUS_REWARD_REP)
|
||||
return false;
|
||||
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
AiObjectContext* context = botAI->GetAiObjectContext();
|
||||
|
||||
// Do not try to hand-in dungeon/elite quests in instances without a group.
|
||||
//Do not try to hand-in dungeon/elite quests in instances without a group.
|
||||
if ((questTemplate->GetType() == QUEST_TYPE_ELITE || questTemplate->GetType() == QUEST_TYPE_DUNGEON) && !AI_VALUE(bool, "can fight boss"))
|
||||
{
|
||||
WorldPosition pos(bot);
|
||||
if (!this->nearestPoint(const_cast<WorldPosition*>(&pos))->isOverworld())
|
||||
if (!this->nearestPoint(&pos)->isOverworld())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4006,7 +4034,45 @@ std::vector<TravelDestination*> TravelMgr::getQuestTravelDestinations(Player* bo
|
||||
|
||||
std::vector<TravelDestination*> retTravelLocations;
|
||||
|
||||
if (questId == -1)
|
||||
if (!questId)
|
||||
{
|
||||
for (auto& dest : questGivers)
|
||||
{
|
||||
if (!ignoreInactive && !dest->isActive(bot))
|
||||
continue;
|
||||
|
||||
if (maxDistance > 0 && dest->distanceTo(&botLocation) > maxDistance)
|
||||
continue;
|
||||
|
||||
retTravelLocations.push_back(dest);
|
||||
}
|
||||
for (auto& quest : quests)
|
||||
{
|
||||
for (auto& dest : quest.second->questTakers)
|
||||
{
|
||||
if (!ignoreInactive && !dest->isActive(bot))
|
||||
continue;
|
||||
|
||||
if (maxDistance > 0 && dest->distanceTo(&botLocation) > maxDistance)
|
||||
continue;
|
||||
|
||||
retTravelLocations.push_back(dest);
|
||||
}
|
||||
|
||||
if (!ignoreObjectives)
|
||||
for (auto& dest : quest.second->questObjectives)
|
||||
{
|
||||
if (!ignoreInactive && !dest->isActive(bot))
|
||||
continue;
|
||||
|
||||
if (maxDistance > 0 && dest->distanceTo(&botLocation) > maxDistance)
|
||||
continue;
|
||||
|
||||
retTravelLocations.push_back(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (questId == -1)
|
||||
{
|
||||
for (auto& dest : questGivers)
|
||||
{
|
||||
|
||||
@@ -95,6 +95,8 @@ class WorldPosition : public WorldLocation
|
||||
|
||||
//Setters
|
||||
void set(const WorldLocation& pos);
|
||||
void set(const WorldObject* wo);
|
||||
void set(const WorldPosition& pos);
|
||||
void setMapId(uint32 id);
|
||||
void setX(float x);
|
||||
void setY(float y);
|
||||
@@ -406,7 +408,6 @@ class GuidPosition : public ObjectGuid, public WorldPosition
|
||||
GuidPosition(WorldObject* wo);
|
||||
GuidPosition(CreatureData const& creData);
|
||||
GuidPosition(GameObjectData const& goData);
|
||||
|
||||
CreatureTemplate const* GetCreatureTemplate();
|
||||
GameObjectTemplate const* GetGameObjectTemplate();
|
||||
|
||||
|
||||
@@ -12,13 +12,30 @@ void Qualified::Qualify(int qual)
|
||||
qualifier = out.str();
|
||||
}
|
||||
|
||||
std::string const Qualified::MultiQualify(std::vector<std::string> qualifiers)
|
||||
std::string const Qualified::MultiQualify(std::vector<std::string> qualifiers, const std::string& separator, const std::string_view brackets)
|
||||
{
|
||||
std::ostringstream out;
|
||||
for (auto& qualifier : qualifiers)
|
||||
out << qualifier << (&qualifier != &qualifiers.back() ? " " : "");
|
||||
std::stringstream out;
|
||||
for (uint8 i = 0; i < qualifiers.size(); i++)
|
||||
{
|
||||
const std::string& qualifier = qualifiers[i];
|
||||
if (i == qualifiers.size() - 1)
|
||||
{
|
||||
out << qualifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << qualifier << separator;
|
||||
}
|
||||
}
|
||||
|
||||
return out.str();
|
||||
if (brackets.empty())
|
||||
{
|
||||
return out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
return brackets[0] + out.str() + brackets[1];
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> Qualified::getMultiQualifiers(std::string const qualifier1)
|
||||
|
||||
@@ -34,7 +34,7 @@ class Qualified
|
||||
|
||||
std::string const getQualifier() { return qualifier; }
|
||||
|
||||
static std::string const MultiQualify(std::vector<std::string> qualifiers);
|
||||
static std::string const MultiQualify(std::vector<std::string> qualifiers, const std::string& separator, const std::string_view brackets = "{}");
|
||||
static std::vector<std::string> getMultiQualifiers(std::string const qualifier1);
|
||||
static int32 getMultiQualifier(std::string const qualifier1, uint32 pos);
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ class StrategyContext : public NamedObjectContext<Strategy>
|
||||
creators["debug move"] = &StrategyContext::debug_move;
|
||||
creators["debug rpg"] = &StrategyContext::debug_rpg;
|
||||
creators["debug spell"] = &StrategyContext::debug_spell;
|
||||
creators["debug quest"] = &StrategyContext::debug_quest;
|
||||
creators["maintenance"] = &StrategyContext::maintenance;
|
||||
creators["group"] = &StrategyContext::group;
|
||||
creators["guild"] = &StrategyContext::guild;
|
||||
@@ -169,6 +170,7 @@ class StrategyContext : public NamedObjectContext<Strategy>
|
||||
static Strategy* debug_move(PlayerbotAI* botAI) { return new DebugMoveStrategy(botAI); }
|
||||
static Strategy* debug_rpg(PlayerbotAI* botAI) { return new DebugRpgStrategy(botAI); }
|
||||
static Strategy* debug_spell(PlayerbotAI* botAI) { return new DebugSpellStrategy(botAI); }
|
||||
static Strategy* debug_quest(PlayerbotAI* botAI) { return new DebugQuestStrategy(botAI); }
|
||||
static Strategy* maintenance(PlayerbotAI* botAI) { return new MaintenanceStrategy(botAI); }
|
||||
static Strategy* group(PlayerbotAI* botAI) { return new GroupStrategy(botAI); }
|
||||
static Strategy* guild (PlayerbotAI* botAI) { return new GuildStrategy(botAI); }
|
||||
@@ -228,6 +230,4 @@ class QuestStrategyContext : public NamedObjectContext<Strategy>
|
||||
static Strategy* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsStrategy(botAI); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,54 +6,62 @@
|
||||
#include "Event.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
void AcceptAllQuestsAction::ProcessQuest(Quest const* quest, Object* questGiver)
|
||||
bool AcceptAllQuestsAction::ProcessQuest(Quest const* quest, Object* questGiver)
|
||||
{
|
||||
AcceptQuest(quest, questGiver->GetGUID());
|
||||
if (!AcceptQuest(quest, questGiver->GetGUID())) return false;
|
||||
|
||||
auto text_quest = ChatHelper::FormatQuest(quest);
|
||||
bot->PlayDistanceSound(620);
|
||||
|
||||
if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||
{
|
||||
bot->Say("Quest [ " + text_quest + " ] accepted", LANG_UNIVERSAL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AcceptQuestAction::Execute(Event event)
|
||||
{
|
||||
Player* master = GetMaster();
|
||||
if (!master)
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
if (!requester)
|
||||
return false;
|
||||
|
||||
Player* bot = botAI->GetBot();
|
||||
ObjectGuid guid;
|
||||
uint64_t guid;
|
||||
uint32 quest = 0;
|
||||
|
||||
std::string const text = event.getParam();
|
||||
PlayerbotChatHandler ch(master);
|
||||
PlayerbotChatHandler ch(requester);
|
||||
quest = ch.extractQuestId(text);
|
||||
|
||||
bool hasAccept = false;
|
||||
|
||||
if (event.getPacket().empty())
|
||||
{
|
||||
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
|
||||
for (GuidVector::iterator i = npcs.begin(); i != npcs.end(); i++)
|
||||
for (auto i = npcs.begin(); i != npcs.end(); i++)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(*i);
|
||||
if (unit && quest && unit->hasQuest(quest))
|
||||
{
|
||||
guid = unit->GetGUID();
|
||||
guid = unit->GetGUID().GetRawValue();
|
||||
break;
|
||||
}
|
||||
|
||||
if (unit && text == "*" && bot->GetDistance(unit) <= INTERACTION_DISTANCE)
|
||||
QuestAction::ProcessQuests(unit);
|
||||
if (unit && text == "*" && sqrt(bot->GetDistance(unit)) <= INTERACTION_DISTANCE)
|
||||
hasAccept |= QuestAction::ProcessQuests(unit);
|
||||
}
|
||||
|
||||
GuidVector gos = AI_VALUE(GuidVector, "nearest game objects");
|
||||
for (GuidVector::iterator i = gos.begin(); i != gos.end(); i++)
|
||||
GuidVector gos = AI_VALUE(GuidVector, "nearest game objects no los");
|
||||
for (auto i = gos.begin(); i != gos.end(); i++)
|
||||
{
|
||||
GameObject* go = botAI->GetGameObject(*i);
|
||||
if (go && quest && go->hasQuest(quest))
|
||||
{
|
||||
guid = go->GetGUID();
|
||||
guid = go->GetGUID().GetRawValue();
|
||||
break;
|
||||
}
|
||||
|
||||
if (go && text == "*" && bot->GetDistance(go) <= INTERACTION_DISTANCE)
|
||||
QuestAction::ProcessQuests(go);
|
||||
if (go && text == "*" && sqrt(bot->GetDistance(go)) <= INTERACTION_DISTANCE)
|
||||
hasAccept |= QuestAction::ProcessQuests(go);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -70,7 +78,17 @@ bool AcceptQuestAction::Execute(Event event)
|
||||
if (!qInfo)
|
||||
return false;
|
||||
|
||||
return AcceptQuest(qInfo, guid);
|
||||
hasAccept |= AcceptQuest(qInfo, ObjectGuid(guid));
|
||||
|
||||
if (hasAccept)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "AcceptQuestAction {" << qInfo->GetTitle() << "} - {" << std::to_string(qInfo->GetQuestId()) << "}";
|
||||
LOG_INFO("playerbots", "{}", ss.str().c_str());
|
||||
botAI->TellMaster(ss.str());
|
||||
}
|
||||
|
||||
return hasAccept;
|
||||
}
|
||||
|
||||
bool AcceptQuestShareAction::Execute(Event event)
|
||||
@@ -112,7 +130,7 @@ bool AcceptQuestShareAction::Execute(Event event)
|
||||
bot->SetDivider(ObjectGuid::Empty);
|
||||
}
|
||||
|
||||
if (bot->CanAddQuest( qInfo, false))
|
||||
if (bot->CanAddQuest(qInfo, false))
|
||||
{
|
||||
bot->AddQuest(qInfo, master);
|
||||
|
||||
@@ -125,7 +143,7 @@ bool AcceptQuestShareAction::Execute(Event event)
|
||||
|
||||
if (qInfo->GetSrcSpell() > 0)
|
||||
{
|
||||
bot->CastSpell( bot, qInfo->GetSrcSpell(), true);
|
||||
bot->CastSpell(bot, qInfo->GetSrcSpell(), true);
|
||||
}
|
||||
|
||||
botAI->TellMaster("Quest accepted");
|
||||
@@ -134,3 +152,41 @@ bool AcceptQuestShareAction::Execute(Event event)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConfirmQuestAction::Execute(Event event)
|
||||
{
|
||||
Player* bot = botAI->GetBot();
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
|
||||
WorldPacket& p = event.getPacket();
|
||||
p.rpos(0);
|
||||
uint32 quest;
|
||||
p >> quest;
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest);
|
||||
|
||||
quest = qInfo->GetQuestId();
|
||||
if (!bot->CanTakeQuest(qInfo, false))
|
||||
{
|
||||
// can't take quest
|
||||
botAI->TellError("quest_cant_take");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->CanAddQuest(qInfo, false))
|
||||
{
|
||||
bot->AddQuest(qInfo, requester);
|
||||
|
||||
if (bot->CanCompleteQuest(quest))
|
||||
bot->CompleteQuest(quest);
|
||||
|
||||
if (qInfo->GetSrcSpell() > 0)
|
||||
{
|
||||
bot->CastSpell(bot, qInfo->GetSrcSpell(), true);
|
||||
}
|
||||
|
||||
botAI->TellMaster("quest_accept");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class AcceptAllQuestsAction : public QuestAction
|
||||
AcceptAllQuestsAction(PlayerbotAI* botAI, std::string const name = "accept all quests") : QuestAction(botAI, name) { }
|
||||
|
||||
protected:
|
||||
void ProcessQuest(Quest const* quest, Object* questGiver) override;
|
||||
bool ProcessQuest(Quest const* quest, Object* questGiver) override;
|
||||
};
|
||||
|
||||
class AcceptQuestAction : public AcceptAllQuestsAction
|
||||
@@ -34,4 +34,10 @@ class AcceptQuestShareAction : public Action
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class ConfirmQuestAction : public Action {
|
||||
public:
|
||||
ConfirmQuestAction(PlayerbotAI* ai) : Action(ai, "confirm quest") {}
|
||||
bool Execute(Event event);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,10 +30,10 @@ bool AutoLearnSpellAction::Execute(Event event)
|
||||
|
||||
void AutoLearnSpellAction::LearnSpells(std::ostringstream* out)
|
||||
{
|
||||
if (sPlayerbotAIConfig->autoLearnTrainerSpells && sRandomPlayerbotMgr->IsRandomBot(bot))// || (!botAI->GetMaster() && sRandomPlayerbotMgr->IsRandomBot(bot)))
|
||||
if (sPlayerbotAIConfig->autoLearnTrainerSpells)
|
||||
LearnTrainerSpells(out);
|
||||
|
||||
if (sPlayerbotAIConfig->autoLearnQuestSpells && sRandomPlayerbotMgr->IsRandomBot(bot))// || (!botAI->GetMaster() && sRandomPlayerbotMgr->IsRandomBot(bot)))
|
||||
if (sPlayerbotAIConfig->autoLearnQuestSpells)
|
||||
LearnQuestSpells(out);
|
||||
|
||||
if (sPlayerbotAIConfig->randomBotGuildTalk)
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "GuildCreateActions.h"
|
||||
#include "PossibleRpgTargetsValue.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RpgSubActions.h"
|
||||
#include "Util.h"
|
||||
#include "ServerFacade.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
@@ -50,42 +53,77 @@ float ChooseRpgTargetAction::getMaxRelevance(GuidPosition guidP)
|
||||
GuidPosition currentRpgTarget = AI_VALUE(GuidPosition, "rpg target");
|
||||
SET_AI_VALUE(GuidPosition, "rpg target", guidP);
|
||||
|
||||
Strategy* rpgStrategy = botAI->GetAiObjectContext()->GetStrategy("rpg");
|
||||
Strategy* rpgStrategy;
|
||||
|
||||
std::vector<TriggerNode*> triggerNodes;
|
||||
rpgStrategy->InitTriggers(triggerNodes);
|
||||
|
||||
float maxRelevance = 0.0f;
|
||||
|
||||
for (auto& triggerNode : triggerNodes)
|
||||
for (auto& strategy : botAI->GetAiObjectContext()->GetSupportedStrategies())
|
||||
{
|
||||
Trigger* trigger = context->GetTrigger(triggerNode->getName());
|
||||
if (trigger)
|
||||
if (strategy.find("rpg") == std::string::npos)
|
||||
continue;
|
||||
|
||||
if (!botAI->HasStrategy(strategy, BotState::BOT_STATE_NON_COMBAT))
|
||||
continue;
|
||||
|
||||
rpgStrategy = botAI->GetAiObjectContext()->GetStrategy(strategy);
|
||||
|
||||
rpgStrategy->InitTriggers(triggerNodes);
|
||||
|
||||
for (auto triggerNode : triggerNodes)
|
||||
{
|
||||
triggerNode->setTrigger(trigger);
|
||||
Trigger* trigger = context->GetTrigger(triggerNode->getName());
|
||||
|
||||
if (triggerNode->getFirstRelevance() < maxRelevance || triggerNode->getFirstRelevance() > 2.0f)
|
||||
continue;
|
||||
if (trigger)
|
||||
{
|
||||
triggerNode->setTrigger(trigger);
|
||||
|
||||
trigger = triggerNode->getTrigger();
|
||||
if (!trigger->IsActive())
|
||||
continue;
|
||||
if (triggerNode->getFirstRelevance() < maxRelevance || triggerNode->getFirstRelevance() > 2.0f)
|
||||
continue;
|
||||
|
||||
maxRelevance = triggerNode->getFirstRelevance();
|
||||
Trigger* trigger = triggerNode->getTrigger();
|
||||
|
||||
if (!trigger->IsActive())
|
||||
continue;
|
||||
|
||||
NextAction** nextActions = triggerNode->getHandlers();
|
||||
|
||||
bool isRpg = false;
|
||||
|
||||
for (int32 i = 0; i < NextAction::size(nextActions); i++)
|
||||
{
|
||||
NextAction* nextAction = nextActions[i];
|
||||
|
||||
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
|
||||
|
||||
if (dynamic_cast<RpgEnabled*>(action))
|
||||
isRpg = true;
|
||||
}
|
||||
NextAction::destroy(nextActions);
|
||||
|
||||
if (isRpg)
|
||||
{
|
||||
maxRelevance = triggerNode->getFirstRelevance();
|
||||
rgpActionReason[guidP] = triggerNode->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto trigger : triggerNodes)
|
||||
{
|
||||
delete trigger;
|
||||
}
|
||||
|
||||
triggerNodes.clear();
|
||||
}
|
||||
|
||||
SET_AI_VALUE(GuidPosition, "rpg target", currentRpgTarget);
|
||||
|
||||
for (std::vector<TriggerNode*>::iterator i = triggerNodes.begin(); i != triggerNodes.end(); i++)
|
||||
{
|
||||
TriggerNode* trigger = *i;
|
||||
delete trigger;
|
||||
}
|
||||
if (!maxRelevance)
|
||||
return 0.0;
|
||||
|
||||
triggerNodes.clear();
|
||||
|
||||
return (maxRelevance - 1.0) * 1000.0f;
|
||||
return floor((maxRelevance - 1.0) * 1000.0f);
|
||||
}
|
||||
|
||||
bool ChooseRpgTargetAction::Execute(Event event)
|
||||
@@ -117,7 +155,7 @@ bool ChooseRpgTargetAction::Execute(Event event)
|
||||
|
||||
if (urand(0, 9))
|
||||
{
|
||||
for (auto target : ignoreList)
|
||||
for (auto target : ignoreList)
|
||||
targets.erase(target);
|
||||
}
|
||||
|
||||
@@ -188,7 +226,7 @@ bool ChooseRpgTargetAction::Execute(Event event)
|
||||
|
||||
if (targets.empty())
|
||||
{
|
||||
LOG_DEBUG("playerbots", "{} can't choose RPG target: all {} are not available", bot->GetName().c_str(), possibleTargets.size());
|
||||
LOG_DEBUG("playerbots", "{} can't choose RPG target: all {} targets are not available", bot->GetName().c_str(), possibleTargets.size());
|
||||
RESET_AI_VALUE(GuidSet&, "ignore rpg target");
|
||||
RESET_AI_VALUE(GuidPosition, "rpg target");
|
||||
return false;
|
||||
@@ -241,17 +279,20 @@ bool ChooseRpgTargetAction::isUseful()
|
||||
if (!botAI->AllowActivity(RPG_ACTIVITY))
|
||||
return false;
|
||||
|
||||
if (AI_VALUE(GuidPosition, "rpg target"))
|
||||
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
|
||||
|
||||
if (guidP && guidP.distance(bot) < sPlayerbotAIConfig->reactDistance * 2)
|
||||
return false;
|
||||
|
||||
TravelTarget* travelTarget = AI_VALUE(TravelTarget*, "travel target");
|
||||
|
||||
if (travelTarget->isTraveling() && isFollowValid(bot, *travelTarget->getPosition()))
|
||||
return false;
|
||||
//if (travelTarget->isTraveling() && AI_VALUE2(bool, "can free move to", *travelTarget->getPosition()))
|
||||
//return false;
|
||||
|
||||
if (AI_VALUE(GuidVector, "possible rpg targets").empty())
|
||||
return false;
|
||||
|
||||
//Not stay, not guard, not combat, not trading and group ready.
|
||||
if (!AI_VALUE(bool, "can move around"))
|
||||
return false;
|
||||
|
||||
@@ -310,7 +351,7 @@ bool ChooseRpgTargetAction::isFollowValid(Player* bot, WorldPosition pos)
|
||||
return true;
|
||||
|
||||
if (distance < formation->GetMaxDistance())
|
||||
return true;
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class ChooseRpgTargetAction : public Action
|
||||
private:
|
||||
float getMaxRelevance(GuidPosition guidP);
|
||||
bool HasSameTarget(ObjectGuid guid, uint32 max, GuidVector const& nearGuids);
|
||||
|
||||
std::unordered_map <ObjectGuid, std::string> rgpActionReason;
|
||||
};
|
||||
|
||||
class ClearRpgTargetAction : public ChooseRpgTargetAction
|
||||
|
||||
@@ -9,16 +9,24 @@
|
||||
|
||||
bool ChooseTravelTargetAction::Execute(Event event)
|
||||
{
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
|
||||
//Get the current travel target. This target is no longer active.
|
||||
TravelTarget* oldTarget = context->GetValue<TravelTarget*>("travel target")->Get();
|
||||
|
||||
//Select a new target to travel to.
|
||||
TravelTarget newTarget = TravelTarget(botAI);
|
||||
getNewTarget(&newTarget, oldTarget);
|
||||
|
||||
if (!oldTarget) return false;
|
||||
|
||||
if (!oldTarget->isForced() || oldTarget->getStatus() == TravelStatus::TRAVEL_STATUS_EXPIRED)
|
||||
getNewTarget(&newTarget, oldTarget);
|
||||
else
|
||||
newTarget.copyTarget(oldTarget);
|
||||
|
||||
//If the new target is not active we failed.
|
||||
if (!newTarget.isActive())
|
||||
return false;
|
||||
if (!newTarget.isActive() && !newTarget.isForced())
|
||||
return false;
|
||||
|
||||
setNewTarget(&newTarget, oldTarget);
|
||||
|
||||
@@ -36,6 +44,11 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge
|
||||
|
||||
foundTarget = SetGroupTarget(newTarget); //Join groups members
|
||||
|
||||
//Do quests (start, do, end)
|
||||
if (!foundTarget && urand(1, 100) > 5) //95% chance
|
||||
{
|
||||
foundTarget = SetQuestTarget(newTarget, false); //Do any nearby
|
||||
}
|
||||
//Enpty bags/repair
|
||||
if (!foundTarget && urand(1, 100) > 10) //90% chance
|
||||
if (AI_VALUE2(bool, "group or", "should sell,can sell,following party,near leader") || AI_VALUE2(bool, "group or", "should repair,can repair,following party,near leader"))
|
||||
@@ -53,9 +66,11 @@ void ChooseTravelTargetAction::getNewTarget(TravelTarget* newTarget, TravelTarge
|
||||
|
||||
if (!foundTarget)
|
||||
foundTarget = SetQuestTarget(newTarget); //Do low level quests
|
||||
} else if (urand(1, 100) > 50) {
|
||||
}
|
||||
else if (urand(1, 100) > 50) {
|
||||
foundTarget = SetGrindTarget(newTarget); //Go grind mobs for money
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
foundTarget = SetNewQuestTarget(newTarget); //Find a low level quest to do
|
||||
}
|
||||
}
|
||||
@@ -703,7 +718,7 @@ bool ChooseTravelTargetAction::SetNullTarget(TravelTarget* target)
|
||||
std::vector<std::string> split(std::string const s, char delim);
|
||||
char* strstri(char const* haystack, char const* needle);
|
||||
|
||||
TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::string const name)
|
||||
TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::string const name, bool zones, bool npcs, bool quests, bool mobs, bool bosses)
|
||||
{
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
|
||||
|
||||
@@ -711,32 +726,54 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
||||
|
||||
std::vector<TravelDestination*> dests;
|
||||
|
||||
//Zones
|
||||
for (auto& d : sTravelMgr->getExploreTravelDestinations(bot, true, true))
|
||||
//Quests
|
||||
if (quests)
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
for (auto& d : sTravelMgr->getQuestTravelDestinations(bot, 0, true, true))
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
//Zones
|
||||
if (zones)
|
||||
{
|
||||
for (auto& d : sTravelMgr->getExploreTravelDestinations(bot, true, true))
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
//Npcs
|
||||
for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true))
|
||||
if (npcs)
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
for (auto& d : sTravelMgr->getRpgTravelDestinations(bot, true, true))
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
//Mobs
|
||||
for (auto& d : sTravelMgr->getGrindTravelDestinations(bot, true, true))
|
||||
if (mobs)
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
for (auto& d : sTravelMgr->getGrindTravelDestinations(bot, true, true, 5000.0f))
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
//Bosses
|
||||
for (auto& d : sTravelMgr->getBossTravelDestinations(bot, true, true))
|
||||
if (bosses)
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
for (auto& d : sTravelMgr->getBossTravelDestinations(bot, true, true))
|
||||
{
|
||||
if (strstri(d->getTitle().c_str(), name.c_str()))
|
||||
dests.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
WorldPosition botPos(bot);
|
||||
@@ -745,9 +782,9 @@ TravelDestination* ChooseTravelTargetAction::FindDestination(Player* bot, std::s
|
||||
return nullptr;
|
||||
|
||||
TravelDestination* dest = *std::min_element(dests.begin(), dests.end(), [botPos](TravelDestination* i, TravelDestination* j)
|
||||
{
|
||||
return i->distanceTo(const_cast<WorldPosition*>(&botPos)) < j->distanceTo(const_cast<WorldPosition*>(&botPos));
|
||||
});
|
||||
{
|
||||
return i->distanceTo(const_cast<WorldPosition*>(&botPos)) < j->distanceTo(const_cast<WorldPosition*>(&botPos));
|
||||
});
|
||||
|
||||
return dest;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ class ChooseTravelTargetAction : public MovementAction
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
|
||||
static TravelDestination* FindDestination(Player* bot, std::string const name);
|
||||
static TravelDestination* FindDestination(Player* bot, std::string const name, bool zones = true, bool npcs = true, bool quests = true, bool mobs = true, bool bosses = true);
|
||||
|
||||
protected:
|
||||
void getNewTarget(TravelTarget* newTarget, TravelTarget* oldTarget);
|
||||
|
||||
@@ -101,10 +101,8 @@ void CleanQuestLogAction::DropQuestType(uint8& numQuest, uint8 wantNum, bool isG
|
||||
if (!quest)
|
||||
continue;
|
||||
|
||||
if (quest->GetRequiredClasses() && (quest->GetRewSpellCast() || quest->GetRewSpell())) //Do not drop class specific quests that learn spells.
|
||||
continue;
|
||||
|
||||
if (quest->GetRequiredClasses() && (quest->GetRewSpellCast() || quest->GetRewSpell())) // Do not drop class specific quests that learn spells.
|
||||
// Do not drop class quest, may be not rewarding gold but important spells
|
||||
if (quest->GetRequiredClasses())
|
||||
continue;
|
||||
|
||||
if (wantNum == 100)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "MovementActions.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
class TravelDestination;
|
||||
class WorldPosition;
|
||||
|
||||
class GoAction : public MovementAction
|
||||
{
|
||||
|
||||
@@ -14,8 +14,10 @@ void QueryQuestAction::TellObjective(std::string const name, uint32 available, u
|
||||
|
||||
bool QueryQuestAction::Execute(Event event)
|
||||
{
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
Player* bot = botAI->GetBot();
|
||||
WorldPosition botPos(bot);
|
||||
WorldPosition* ptr_botpos = &botPos;
|
||||
std::string text = event.getParam();
|
||||
bool travel = false;
|
||||
|
||||
@@ -28,7 +30,22 @@ bool QueryQuestAction::Execute(Event event)
|
||||
PlayerbotChatHandler ch(bot);
|
||||
uint32 questId = ch.extractQuestId(text);
|
||||
if (!questId)
|
||||
return 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;
|
||||
|
||||
if (text.find(quest->GetTitle()) != std::string::npos)
|
||||
{
|
||||
questId = quest->GetQuestId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
|
||||
{
|
||||
@@ -55,10 +72,7 @@ bool QueryQuestAction::Execute(Event event)
|
||||
uint32 limit = 0;
|
||||
std::vector<TravelDestination*> allDestinations = sTravelMgr->getQuestTravelDestinations(bot, questId, true, true, -1);
|
||||
|
||||
std::sort(allDestinations.begin(), allDestinations.end(), [botPos](TravelDestination* i, TravelDestination* j)
|
||||
{
|
||||
return i->distanceTo(const_cast<WorldPosition*>(&botPos)) < j->distanceTo(const_cast<WorldPosition*>(&botPos));
|
||||
});
|
||||
std::sort(allDestinations.begin(), allDestinations.end(), [ptr_botpos](TravelDestination* i, TravelDestination* j) {return i->distanceTo(ptr_botpos) < j->distanceTo(ptr_botpos); });
|
||||
|
||||
for (auto dest : allDestinations)
|
||||
{
|
||||
@@ -71,24 +85,18 @@ bool QueryQuestAction::Execute(Event event)
|
||||
uint32 apoints = dest->getPoints().size();
|
||||
|
||||
|
||||
out << round(dest->distanceTo(const_cast<WorldPosition*>(&botPos)));
|
||||
out << " to " << dest->getTitle();
|
||||
out << " " << apoints;
|
||||
out << round(dest->distanceTo(&botPos));
|
||||
|
||||
out << " to " << dest->getTitle();
|
||||
|
||||
out << " " << apoints;
|
||||
if (apoints < tpoints)
|
||||
out << "/" << tpoints;
|
||||
|
||||
out << " points.";
|
||||
|
||||
if (!dest->isActive(bot))
|
||||
out << " not active";
|
||||
|
||||
if (dest->isFull(bot))
|
||||
out << " crowded";
|
||||
|
||||
if (dest->isFull(bot))
|
||||
out << " crowded";
|
||||
|
||||
botAI->TellMaster(out);
|
||||
|
||||
limit++;
|
||||
|
||||
@@ -7,27 +7,48 @@
|
||||
#include "ChatHelper.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ReputationMgr.h"
|
||||
#include "ServerFacade.h"
|
||||
|
||||
bool QuestAction::Execute(Event event)
|
||||
{
|
||||
ObjectGuid guid = event.getObject();
|
||||
|
||||
Player* master = GetMaster();
|
||||
if (!master)
|
||||
{
|
||||
if (!guid)
|
||||
guid = bot->GetTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!guid)
|
||||
guid = master->GetTarget();
|
||||
}
|
||||
|
||||
if (!guid)
|
||||
return false;
|
||||
{
|
||||
if (!master)
|
||||
{
|
||||
guid = bot->GetTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
guid = master->GetTarget();
|
||||
}
|
||||
}
|
||||
|
||||
return ProcessQuests(guid);
|
||||
if (guid)
|
||||
{
|
||||
return ProcessQuests(guid);
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
|
||||
for (const auto npc : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npc);
|
||||
if (unit && bot->GetDistance(unit) <= INTERACTION_DISTANCE)
|
||||
result |= ProcessQuests(unit);
|
||||
}
|
||||
std::list<ObjectGuid> gos = AI_VALUE(std::list<ObjectGuid>, "nearest game objects");
|
||||
for (const auto go : gos)
|
||||
{
|
||||
GameObject* gameobj = botAI->GetGameObject(go);
|
||||
if (gameobj && bot->GetDistance(gameobj) <= INTERACTION_DISTANCE)
|
||||
result |= ProcessQuests(gameobj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QuestAction::CompleteQuest(Player* player, uint32 entry)
|
||||
@@ -67,7 +88,15 @@ bool QuestAction::CompleteQuest(Player* player, uint32 entry)
|
||||
int32 creature = pQuest->RequiredNpcOrGo[i];
|
||||
uint32 creaturecount = pQuest->RequiredNpcOrGoCount[i];
|
||||
|
||||
if (creature > 0)
|
||||
// TODO check if we need a REQSPELL condition, this methods and sql entry dosent seem implemented ?
|
||||
/*if (uint32 spell_id = pQuest->GetReqSpell[i])
|
||||
{
|
||||
for (uint16 z = 0; z < creaturecount; ++z)
|
||||
{
|
||||
player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id);
|
||||
}
|
||||
}*/
|
||||
/*else*/ if (creature > 0)
|
||||
{
|
||||
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature))
|
||||
for (uint16 z = 0; z < creaturecount; ++z)
|
||||
@@ -127,6 +156,8 @@ bool QuestAction::ProcessQuests(WorldObject* questGiver)
|
||||
|
||||
if (bot->GetDistance(questGiver) > INTERACTION_DISTANCE && !sPlayerbotAIConfig->syncQuestWithPlayer)
|
||||
{
|
||||
//if (botAI->HasStrategy("debug", BotState::BOT_STATE_COMBAT) || botAI->HasStrategy("debug", BotState::BOT_STATE_NON_COMBAT))
|
||||
|
||||
botAI->TellError("Cannot talk to quest giver");
|
||||
return false;
|
||||
}
|
||||
@@ -160,16 +191,16 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
|
||||
|
||||
if (bot->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
|
||||
out << "Already completed";
|
||||
else if (! bot->CanTakeQuest(quest, false))
|
||||
else if (!bot->CanTakeQuest(quest, false))
|
||||
{
|
||||
if (! bot->SatisfyQuestStatus(quest, false))
|
||||
if (!bot->SatisfyQuestStatus(quest, false))
|
||||
out << "Already on";
|
||||
else
|
||||
out << "Can't take";
|
||||
}
|
||||
else if (! bot->SatisfyQuestLog(false))
|
||||
else if (!bot->SatisfyQuestLog(false))
|
||||
out << "Quest log is full";
|
||||
else if (! bot->CanAddQuest(quest, false))
|
||||
else if (!bot->CanAddQuest(quest, false))
|
||||
out << "Bags are full";
|
||||
else
|
||||
{
|
||||
@@ -179,7 +210,7 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
|
||||
p.rpos(0);
|
||||
bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p);
|
||||
|
||||
if (bot->GetQuestStatus(questId ) == QUEST_STATUS_NONE && sPlayerbotAIConfig->syncQuestWithPlayer)
|
||||
if (bot->GetQuestStatus(questId) == QUEST_STATUS_NONE && sPlayerbotAIConfig->syncQuestWithPlayer)
|
||||
{
|
||||
Object* pObject = ObjectAccessor::GetObjectByTypeMask(*bot, questGiver, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM);
|
||||
bot->AddQuest(quest, pObject);
|
||||
@@ -196,10 +227,11 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
|
||||
|
||||
out << " " << chat->FormatQuest(quest);
|
||||
botAI->TellMaster(out);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestObjectiveCompletedAction::Execute(Event event)
|
||||
bool QuestUpdateCompleteAction::Execute(Event event)
|
||||
{
|
||||
WorldPacket p(event.getPacket());
|
||||
p.rpos(0);
|
||||
@@ -208,17 +240,84 @@ bool QuestObjectiveCompletedAction::Execute(Event event)
|
||||
ObjectGuid guid;
|
||||
p >> questId >> entry >> available >> required >> guid;
|
||||
|
||||
if (entry & 0x80000000)
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (qInfo)
|
||||
{
|
||||
entry &= 0x7FFFFFFF;
|
||||
if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(entry))
|
||||
botAI->TellMaster(chat->FormatQuestObjective(info->name, available, required));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CreatureTemplate const* info = sObjectMgr->GetCreatureTemplate(entry))
|
||||
botAI->TellMaster(chat->FormatQuestObjective(info->Name, available, required));
|
||||
if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
|
||||
{
|
||||
bot->Say("Quest [ " + ChatHelper::FormatQuest(qInfo) + " ] completed", LANG_UNIVERSAL);
|
||||
}
|
||||
botAI->TellMasterNoFacing("Quest completed " + ChatHelper::FormatQuest(qInfo));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* For creature or gameobject
|
||||
*/
|
||||
bool QuestUpdateAddKillAction::Execute(Event event)
|
||||
{
|
||||
WorldPacket p(event.getPacket());
|
||||
p.rpos(0);
|
||||
|
||||
uint32 entry, questId, available, required;
|
||||
ObjectGuid guid;
|
||||
p >> questId >> entry >> available >> required >> guid;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Update progression kill questid {" << std::to_string(questId) << "} {" << std::to_string(available) << "} / {" << std::to_string(required) << "}";
|
||||
botAI->TellMasterNoFacing(ss.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestUpdateAddItemAction::Execute(Event event)
|
||||
{
|
||||
WorldPacket p(event.getPacket());
|
||||
p.rpos(0);
|
||||
|
||||
uint32 itemId, count;
|
||||
p >> itemId >> count;
|
||||
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
auto const* itemPrototype = sObjectMgr->GetItemTemplate(itemId);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Update progression itemid {" << std::to_string(itemId) << "} count: {" << std::to_string(count) << "}";
|
||||
botAI->TellMasterNoFacing(ss.str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestUpdateFailedAction::Execute(Event event)
|
||||
{
|
||||
//opcode SMSG_QUESTUPDATE_FAILED is never sent...(yet?)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuestUpdateFailedTimerAction::Execute(Event event)
|
||||
{
|
||||
WorldPacket p(event.getPacket());
|
||||
p.rpos(0);
|
||||
|
||||
uint32 questId;
|
||||
p >> questId;
|
||||
|
||||
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
|
||||
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId);
|
||||
|
||||
if (qInfo)
|
||||
{
|
||||
botAI->TellMaster("Failed timer for " + botAI->GetChatHelper()->FormatQuest(qInfo) +", abandoning");
|
||||
}
|
||||
else
|
||||
{
|
||||
botAI->TellMaster("Failed timer for " + std::to_string(questId));
|
||||
}
|
||||
|
||||
//drop quest
|
||||
bot->AbandonQuest(questId);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "Action.h"
|
||||
#include "Object.h"
|
||||
#include "QuestDef.h"
|
||||
|
||||
class ObjectGuid;
|
||||
class Quest;
|
||||
@@ -17,25 +18,52 @@ class Object;
|
||||
|
||||
class QuestAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) { }
|
||||
public:
|
||||
QuestAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) { }
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
bool CompleteQuest(Player* player, uint32 entry);
|
||||
virtual void ProcessQuest(Quest const* quest, Object* questGiver) = 0;
|
||||
bool AcceptQuest(Quest const* quest, ObjectGuid questGiver);
|
||||
bool ProcessQuests(ObjectGuid questGiver);
|
||||
bool ProcessQuests(WorldObject* questGiver);
|
||||
protected:
|
||||
bool CompleteQuest(Player* player, uint32 entry);
|
||||
virtual bool ProcessQuest(Quest const* quest, Object* questGiver) = 0;
|
||||
bool AcceptQuest(Quest const* quest, ObjectGuid questGiver);
|
||||
bool ProcessQuests(ObjectGuid questGiver);
|
||||
bool ProcessQuests(WorldObject* questGiver);
|
||||
};
|
||||
|
||||
class QuestObjectiveCompletedAction : public Action
|
||||
class QuestUpdateCompleteAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestObjectiveCompletedAction(PlayerbotAI* botAI) : Action(botAI, "quest objective completed") { }
|
||||
public:
|
||||
QuestUpdateCompleteAction(PlayerbotAI* ai) : Action(ai, "quest update complete") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
bool Execute(Event event) override;
|
||||
class QuestUpdateAddKillAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestUpdateAddKillAction(PlayerbotAI* ai) : Action(ai, "quest update add kill") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class QuestUpdateAddItemAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestUpdateAddItemAction(PlayerbotAI* ai) : Action(ai, "quest update add item") {}
|
||||
bool Execute(Event event) override;;
|
||||
};
|
||||
|
||||
class QuestUpdateFailedAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestUpdateFailedAction(PlayerbotAI* ai) : Action(ai, "quest update failed") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class QuestUpdateFailedTimerAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestUpdateFailedTimerAction(PlayerbotAI* ai) : Action(ai, "quest update failed timer") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "QuestConfirmAcceptAction.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
bool QuestConfirmAcceptAction::Execute(Event event)
|
||||
{
|
||||
WorldPacket packet(event.getPacket());
|
||||
uint32 questId;
|
||||
packet >> questId;
|
||||
|
||||
WorldPacket sendPacket(CMSG_QUEST_CONFIRM_ACCEPT);
|
||||
sendPacket << questId;
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (!quest || !bot->CanAddQuest(quest, true)) {
|
||||
return false;
|
||||
}
|
||||
std::ostringstream out;
|
||||
out << "Quest: " << chat->FormatQuest(quest) << " confirm accept";
|
||||
botAI->TellMaster(out);
|
||||
bot->GetSession()->HandleQuestConfirmAccept(sendPacket);
|
||||
return true;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_QUESTCONFIRMACCEPTACTION_H
|
||||
#define _PLAYERBOT_QUESTCONFIRMACCEPTACTION_H
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "QuestAction.h"
|
||||
#include "Player.h"
|
||||
|
||||
class ObjectGuid;
|
||||
class Quest;
|
||||
class Player;
|
||||
class PlayerbotAI;
|
||||
class WorldObject;
|
||||
|
||||
class QuestConfirmAcceptAction : public Action
|
||||
{
|
||||
public:
|
||||
QuestConfirmAcceptAction(PlayerbotAI* botAI) : Action(botAI, "quest confirm accept") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Formations.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "RpgSubActions.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
@@ -45,65 +46,109 @@ bool RpgAction::isUseful()
|
||||
|
||||
bool RpgAction::SetNextRpgAction()
|
||||
{
|
||||
Strategy* rpgStrategy = botAI->GetAiObjectContext()->GetStrategy("rpg");
|
||||
|
||||
Strategy* rpgStrategy;
|
||||
std::vector<Action*> actions;
|
||||
std::vector<uint32> relevances;
|
||||
std::vector<TriggerNode*> triggerNodes;
|
||||
rpgStrategy->InitTriggers(triggerNodes);
|
||||
|
||||
for (auto& triggerNode : triggerNodes)
|
||||
|
||||
for (auto& strategy : botAI->GetAiObjectContext()->GetSupportedStrategies())
|
||||
{
|
||||
Trigger* trigger = context->GetTrigger(triggerNode->getName());
|
||||
if (trigger)
|
||||
if (strategy.find("rpg") == std::string::npos)
|
||||
continue;
|
||||
|
||||
rpgStrategy = botAI->GetAiObjectContext()->GetStrategy(strategy);
|
||||
|
||||
rpgStrategy->InitTriggers(triggerNodes);
|
||||
|
||||
for (auto& triggerNode : triggerNodes)
|
||||
{
|
||||
triggerNode->setTrigger(trigger);
|
||||
Trigger* trigger = context->GetTrigger(triggerNode->getName());
|
||||
|
||||
NextAction** nextActions = triggerNode->getHandlers();
|
||||
|
||||
trigger = triggerNode->getTrigger();
|
||||
|
||||
bool isChecked = false;
|
||||
for (int32 i = 0; i < NextAction::size(nextActions); i++)
|
||||
if (trigger)
|
||||
{
|
||||
NextAction* nextAction = nextActions[i];
|
||||
|
||||
if (nextAction->getRelevance() > 2.0f)
|
||||
continue;
|
||||
triggerNode->setTrigger(trigger);
|
||||
|
||||
if (!isChecked && !trigger->IsActive())
|
||||
break;
|
||||
NextAction** nextActions = triggerNode->getHandlers();
|
||||
|
||||
isChecked = true;
|
||||
Trigger* trigger = triggerNode->getTrigger();
|
||||
|
||||
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
|
||||
bool isChecked = false;
|
||||
|
||||
if (!action->isPossible() || !action->isUseful())
|
||||
continue;
|
||||
for (int32 i = 0; i < NextAction::size(nextActions); i++)
|
||||
{
|
||||
NextAction* nextAction = nextActions[i];
|
||||
|
||||
actions.push_back(action);
|
||||
relevances.push_back((nextAction->getRelevance() - 1) * 1000);
|
||||
if (nextAction->getRelevance() > 2.0f)
|
||||
continue;
|
||||
|
||||
if (!isChecked && !trigger->IsActive())
|
||||
break;
|
||||
|
||||
isChecked = true;
|
||||
|
||||
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
|
||||
if (!dynamic_cast<RpgEnabled*>(action) || !action->isPossible() || !action->isUseful())
|
||||
continue;
|
||||
|
||||
actions.push_back(action);
|
||||
relevances.push_back((nextAction->getRelevance() - 1) * 1000);
|
||||
}
|
||||
NextAction::destroy(nextActions);
|
||||
}
|
||||
|
||||
NextAction::destroy(nextActions);
|
||||
}
|
||||
|
||||
for (const auto i : triggerNodes)
|
||||
{
|
||||
delete i;
|
||||
}
|
||||
triggerNodes.clear();
|
||||
}
|
||||
|
||||
if (actions.empty())
|
||||
return false;
|
||||
|
||||
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_NON_COMBAT))
|
||||
{
|
||||
std::vector<std::pair<Action*, uint32>> sortedActions;
|
||||
|
||||
for (int i = 0; i < actions.size(); i++)
|
||||
sortedActions.push_back(std::make_pair(actions[i], relevances[i]));
|
||||
|
||||
std::sort(sortedActions.begin(), sortedActions.end(), [](std::pair<Action*, uint32>i, std::pair<Action*, uint32> j) {return i.second > j.second; });
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "------" << chat->FormatWorldobject(AI_VALUE(GuidPosition, "rpg target").GetWorldObject()) << "------";
|
||||
bot->Say(ss.str(), LANG_UNIVERSAL);
|
||||
botAI->TellMasterNoFacing(ss.str());
|
||||
|
||||
for (auto action : sortedActions)
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
out << " " << action.first->getName() << " " << action.second;
|
||||
|
||||
botAI->TellMasterNoFacing(out);
|
||||
}
|
||||
}
|
||||
|
||||
std::mt19937 gen(time(0));
|
||||
|
||||
sTravelMgr->weighted_shuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen);
|
||||
|
||||
Action* action = actions.front();
|
||||
|
||||
for (std::vector<TriggerNode*>::iterator i = triggerNodes.begin(); i != triggerNodes.end(); i++)
|
||||
if ((botAI->HasStrategy("debug", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_NON_COMBAT)))
|
||||
{
|
||||
TriggerNode* trigger = *i;
|
||||
delete trigger;
|
||||
}
|
||||
std::ostringstream out;
|
||||
out << "do: ";
|
||||
out << chat->FormatWorldobject(AI_VALUE(GuidPosition, "rpg target").GetWorldObject());
|
||||
|
||||
triggerNodes.clear();
|
||||
out << " " << action->getName();
|
||||
|
||||
botAI->TellMasterNoFacing(out);
|
||||
}
|
||||
|
||||
SET_AI_VALUE(std::string, "next rpg action", action->getName());
|
||||
|
||||
|
||||
@@ -13,28 +13,28 @@ class Unit;
|
||||
|
||||
class RpgAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
RpgAction(PlayerbotAI* botAI, std::string const name = "rpg") : MovementAction(botAI, name) { }
|
||||
public:
|
||||
RpgAction(PlayerbotAI* botAI, std::string const name = "rpg") : MovementAction(botAI, name) { }
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
|
||||
protected:
|
||||
virtual bool SetNextRpgAction();
|
||||
protected:
|
||||
virtual bool SetNextRpgAction();
|
||||
|
||||
typedef void (RpgAction::*RpgElement)(ObjectGuid guid);
|
||||
typedef void (RpgAction::* RpgElement)(ObjectGuid guid);
|
||||
|
||||
bool AddIgnore(ObjectGuid guid);
|
||||
bool RemIgnore(ObjectGuid guid);
|
||||
bool HasIgnore(ObjectGuid guid);
|
||||
bool AddIgnore(ObjectGuid guid);
|
||||
bool RemIgnore(ObjectGuid guid);
|
||||
bool HasIgnore(ObjectGuid guid);
|
||||
};
|
||||
|
||||
class CRpgAction : public RpgAction
|
||||
{
|
||||
public:
|
||||
CRpgAction(PlayerbotAI* botAI) : RpgAction(botAI, "crpg") { }
|
||||
public:
|
||||
CRpgAction(PlayerbotAI* botAI) : RpgAction(botAI, "crpg") { }
|
||||
|
||||
bool isUseful() override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "QuestDef.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver)
|
||||
bool TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver)
|
||||
{
|
||||
bool isCompleted = false;
|
||||
std::ostringstream out;
|
||||
out << "Quest ";
|
||||
|
||||
@@ -26,7 +27,7 @@ void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver
|
||||
{
|
||||
QuestStatus masterStatus = master->GetQuestStatus(quest->GetQuestId());
|
||||
if (masterStatus == QUEST_STATUS_INCOMPLETE || masterStatus == QUEST_STATUS_FAILED)
|
||||
CompleteQuest(master, quest->GetQuestId());
|
||||
isCompleted |= CompleteQuest(master, quest->GetQuestId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,39 +35,42 @@ void TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver
|
||||
{
|
||||
if (master && master->GetQuestStatus(quest->GetQuestId()) == QUEST_STATUS_COMPLETE && (status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_FAILED))
|
||||
{
|
||||
CompleteQuest(bot, quest->GetQuestId());
|
||||
isCompleted |= CompleteQuest(bot, quest->GetQuestId());
|
||||
status = bot->GetQuestStatus(quest->GetQuestId());
|
||||
}
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case QUEST_STATUS_COMPLETE:
|
||||
TurnInQuest(quest, questGiver, out);
|
||||
break;
|
||||
case QUEST_STATUS_INCOMPLETE:
|
||||
out << "|cffff0000Incompleted|r";
|
||||
break;
|
||||
case QUEST_STATUS_NONE:
|
||||
out << "|cff00ff00Available|r";
|
||||
break;
|
||||
case QUEST_STATUS_FAILED:
|
||||
out << "|cffff0000Failed|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case QUEST_STATUS_COMPLETE:
|
||||
isCompleted |= TurnInQuest(quest, questGiver, out);
|
||||
break;
|
||||
case QUEST_STATUS_INCOMPLETE:
|
||||
out << "|cffff0000Incompleted|r";
|
||||
break;
|
||||
case QUEST_STATUS_NONE:
|
||||
AcceptQuest(quest, questGiver->GetGUID());
|
||||
out << "|cff00ff00Available|r";
|
||||
break;
|
||||
case QUEST_STATUS_FAILED:
|
||||
out << "|cffff0000Failed|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out << ": " << chat->FormatQuest(quest);
|
||||
botAI->TellMaster(out);
|
||||
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
void TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver, std::ostringstream& out)
|
||||
bool TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver, std::ostringstream& out)
|
||||
{
|
||||
uint32 questID = quest->GetQuestId();
|
||||
|
||||
if (bot->GetQuestRewardStatus(questID))
|
||||
return;
|
||||
return false;
|
||||
|
||||
bot->PlayDistanceSound(621);
|
||||
|
||||
@@ -78,6 +82,8 @@ void TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver,
|
||||
{
|
||||
RewardMultipleItem(quest, questGiver, out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TalkToQuestGiverAction::RewardNoItem(Quest const* quest, Object* questGiver, std::ostringstream& out)
|
||||
@@ -244,23 +250,23 @@ bool TurnInQueryQuestAction::Execute(Event event)
|
||||
out << "Quest ";
|
||||
switch (status)
|
||||
{
|
||||
case QUEST_STATUS_COMPLETE:
|
||||
TurnInQuest(quest, object, out);
|
||||
break;
|
||||
case QUEST_STATUS_INCOMPLETE:
|
||||
out << "|cffff0000Incompleted|r";
|
||||
break;
|
||||
case QUEST_STATUS_NONE:
|
||||
out << "|cff00ff00Available|r";
|
||||
break;
|
||||
case QUEST_STATUS_FAILED:
|
||||
out << "|cffff0000Failed|r";
|
||||
break;
|
||||
case QUEST_STATUS_REWARDED:
|
||||
out << "|cffff0000Rewarded|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case QUEST_STATUS_COMPLETE:
|
||||
TurnInQuest(quest, object, out);
|
||||
break;
|
||||
case QUEST_STATUS_INCOMPLETE:
|
||||
out << "|cffff0000Incompleted|r";
|
||||
break;
|
||||
case QUEST_STATUS_NONE:
|
||||
out << "|cff00ff00Available|r";
|
||||
break;
|
||||
case QUEST_STATUS_FAILED:
|
||||
out << "|cffff0000Failed|r";
|
||||
break;
|
||||
case QUEST_STATUS_REWARDED:
|
||||
out << "|cffff0000Rewarded|r";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out << ": " << chat->FormatQuest(quest);
|
||||
|
||||
@@ -13,25 +13,25 @@ class WorldObject;
|
||||
|
||||
class TalkToQuestGiverAction : public QuestAction
|
||||
{
|
||||
public:
|
||||
TalkToQuestGiverAction(PlayerbotAI* botAI, std::string name = "talk to quest giver") : QuestAction(botAI, name) { }
|
||||
public:
|
||||
TalkToQuestGiverAction(PlayerbotAI* botAI, std::string name = "talk to quest giver") : QuestAction(botAI, name) { }
|
||||
|
||||
protected:
|
||||
void ProcessQuest(Quest const* quest, Object* questGiver) override;
|
||||
void TurnInQuest(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
protected:
|
||||
bool ProcessQuest(Quest const* quest, Object* questGiver) override;
|
||||
bool TurnInQuest(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
|
||||
private:
|
||||
void RewardNoItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
void RewardSingleItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
std::set<uint32> BestRewards(Quest const* quest);
|
||||
void RewardMultipleItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
void AskToSelectReward(Quest const* quest, std::ostringstream& out, bool forEquip);
|
||||
private:
|
||||
void RewardNoItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
void RewardSingleItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
std::set<uint32> BestRewards(Quest const* quest);
|
||||
void RewardMultipleItem(Quest const* quest, Object* questGiver, std::ostringstream& out);
|
||||
void AskToSelectReward(Quest const* quest, std::ostringstream& out, bool forEquip);
|
||||
};
|
||||
|
||||
class TurnInQueryQuestAction : public TalkToQuestGiverAction
|
||||
{
|
||||
public:
|
||||
TurnInQueryQuestAction(PlayerbotAI* botAI) : TalkToQuestGiverAction(botAI, "turn in query quest") {}
|
||||
bool Execute(Event event) override;
|
||||
public:
|
||||
TurnInQueryQuestAction(PlayerbotAI* botAI) : TalkToQuestGiverAction(botAI, "turn in query quest") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -463,13 +463,10 @@ bool UseRandomQuestItem::Execute(Event event)
|
||||
ObjectGuid goTarget;
|
||||
|
||||
std::vector<Item*> questItems = AI_VALUE2(std::vector<Item*>, "inventory items", "quest");
|
||||
|
||||
Item* item = nullptr;
|
||||
uint32 delay = 0;
|
||||
|
||||
if (questItems.empty())
|
||||
return false;
|
||||
|
||||
Item* item = nullptr;
|
||||
for (uint8 i = 0; i < 5; i++)
|
||||
{
|
||||
auto itr = questItems.begin();
|
||||
@@ -477,7 +474,6 @@ bool UseRandomQuestItem::Execute(Event event)
|
||||
Item* questItem = *itr;
|
||||
|
||||
ItemTemplate const* proto = questItem->GetTemplate();
|
||||
|
||||
if (proto->StartQuest)
|
||||
{
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(proto->StartQuest);
|
||||
@@ -488,61 +484,14 @@ bool UseRandomQuestItem::Execute(Event event)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 spellId = proto->Spells[0].SpellId;
|
||||
if (spellId)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||
|
||||
GuidVector npcs = AI_VALUE(GuidVector, ("nearest npcs"));
|
||||
for (auto& npc : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npc);
|
||||
if (botAI->CanCastSpell(spellId, unit, false))
|
||||
{
|
||||
item = questItem;
|
||||
unitTarget = unit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GuidVector gos = AI_VALUE(GuidVector, ("nearest game objects"));
|
||||
for (auto& go : gos)
|
||||
{
|
||||
GameObject* gameObject = botAI->GetGameObject(go);
|
||||
GameObjectTemplate const* goInfo = gameObject->GetGOInfo();
|
||||
if (!goInfo->GetLockId())
|
||||
continue;
|
||||
|
||||
LockEntry const* lock = sLockStore.LookupEntry(goInfo->GetLockId());
|
||||
for (uint8 i = 0; i < MAX_LOCK_CASE; ++i)
|
||||
{
|
||||
if (!lock->Type[i])
|
||||
continue;
|
||||
if (lock->Type[i] != LOCK_KEY_ITEM)
|
||||
continue;
|
||||
|
||||
if (lock->Index[i] == proto->ItemId)
|
||||
{
|
||||
item = questItem;
|
||||
goTarget = go;
|
||||
unitTarget = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
if (!goTarget && !unitTarget)
|
||||
return false;
|
||||
|
||||
bool used = UseItem(item, goTarget, nullptr, unitTarget);
|
||||
|
||||
if (used)
|
||||
botAI->SetNextCheckDelay(delay);
|
||||
botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown);
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "QuestAction.h"
|
||||
#include "PassLeadershipToMasterAction.h"
|
||||
#include "PetitionSignAction.h"
|
||||
#include "QuestConfirmAcceptAction.h"
|
||||
#include "ReadyCheckAction.h"
|
||||
#include "RememberTaxiAction.h"
|
||||
#include "ReviveFromCorpseAction.h"
|
||||
@@ -37,116 +36,131 @@
|
||||
#include "TradeStatusAction.h"
|
||||
#include "UseMeetingStoneAction.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "QuestConfirmAcceptAction.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class WorldPacketActionContext : public NamedObjectContext<Action>
|
||||
{
|
||||
public:
|
||||
WorldPacketActionContext()
|
||||
{
|
||||
creators["accept invitation"] = &WorldPacketActionContext::accept_invitation;
|
||||
creators["give leader in dungeon"] = &WorldPacketActionContext::give_leader_in_dungeon;
|
||||
creators["leader"] = &WorldPacketActionContext::pass_leadership_to_master;
|
||||
creators["tell not enough money"] = &WorldPacketActionContext::tell_not_enough_money;
|
||||
creators["tell not enough reputation"] = &WorldPacketActionContext::tell_not_enough_reputation;
|
||||
creators["tell cannot equip"] = &WorldPacketActionContext::tell_cannot_equip;
|
||||
creators["talk to quest giver"] = &WorldPacketActionContext::turn_in_quest;
|
||||
creators["accept quest"] = &WorldPacketActionContext::accept_quest;
|
||||
creators["accept all quests"] = &WorldPacketActionContext::accept_all_quests;
|
||||
creators["accept quest share"] = &WorldPacketActionContext::accept_quest_share;
|
||||
creators["loot roll"] = &WorldPacketActionContext::loot_roll;
|
||||
creators["master loot roll"] = &WorldPacketActionContext::master_loot_roll;
|
||||
creators["revive from corpse"] = &WorldPacketActionContext::revive_from_corpse;
|
||||
creators["find corpse"] = &WorldPacketActionContext::find_corpse;
|
||||
creators["auto release"] = &WorldPacketActionContext::auto_release;
|
||||
creators["accept resurrect"] = &WorldPacketActionContext::accept_resurrect;
|
||||
creators["use meeting stone"] = &WorldPacketActionContext::use_meeting_stone;
|
||||
creators["area trigger"] = &WorldPacketActionContext::area_trigger;
|
||||
creators["reach area trigger"] = &WorldPacketActionContext::reach_area_trigger;
|
||||
creators["check mount state"] = &WorldPacketActionContext::check_mount_state;
|
||||
creators["remember taxi"] = &WorldPacketActionContext::remember_taxi;
|
||||
creators["accept trade"] = &WorldPacketActionContext::accept_trade;
|
||||
creators["store loot"] = &WorldPacketActionContext::store_loot;
|
||||
creators["quest objective completed"] = &WorldPacketActionContext::quest_objective_completed;
|
||||
creators["party command"] = &WorldPacketActionContext::party_command;
|
||||
creators["tell cast failed"] = &WorldPacketActionContext::tell_cast_failed;
|
||||
creators["accept duel"] = &WorldPacketActionContext::accept_duel;
|
||||
creators["ready check"] = &WorldPacketActionContext::ready_check;
|
||||
creators["ready check finished"] = &WorldPacketActionContext::ready_check_finished;
|
||||
creators["uninvite"] = &WorldPacketActionContext::uninvite;
|
||||
creators["security check"] = &WorldPacketActionContext::security_check;
|
||||
creators["guild accept"] = &WorldPacketActionContext::guild_accept;
|
||||
creators["inventory change failure"] = &WorldPacketActionContext::inventory_change_failure;
|
||||
creators["bg status check"] = &WorldPacketActionContext::bg_status_check;
|
||||
creators["bg strategy check"] = &WorldPacketActionContext::bg_strategy_check;
|
||||
creators["bg status"] = &WorldPacketActionContext::bg_status;
|
||||
creators["bg join"] = &WorldPacketActionContext::bg_join;
|
||||
creators["bg leave"] = &WorldPacketActionContext::bg_leave;
|
||||
creators["arena tactics"] = &WorldPacketActionContext::arena_tactics;
|
||||
creators["petition sign"] = &WorldPacketActionContext::petition_sign;
|
||||
creators["lfg join"] = &WorldPacketActionContext::lfg_join;
|
||||
creators["lfg accept"] = &WorldPacketActionContext::lfg_accept;
|
||||
creators["lfg role check"] = &WorldPacketActionContext::lfg_role_check;
|
||||
creators["lfg leave"] = &WorldPacketActionContext::lfg_leave;
|
||||
creators["lfg teleport"] = &WorldPacketActionContext::lfg_teleport;
|
||||
creators["see spell"] = &WorldPacketActionContext::see_spell;
|
||||
creators["arena team accept"] = &WorldPacketActionContext::arena_team_accept;
|
||||
creators["turn in query quest"] = &WorldPacketActionContext::turn_in_query_quest;
|
||||
creators["quest confirm accept"] = &WorldPacketActionContext::quest_confirm_accept;
|
||||
}
|
||||
public:
|
||||
WorldPacketActionContext()
|
||||
{
|
||||
creators["accept invitation"] = &WorldPacketActionContext::accept_invitation;
|
||||
creators["give leader in dungeon"] = &WorldPacketActionContext::give_leader_in_dungeon;
|
||||
creators["leader"] = &WorldPacketActionContext::pass_leadership_to_master;
|
||||
creators["tell not enough money"] = &WorldPacketActionContext::tell_not_enough_money;
|
||||
creators["tell not enough reputation"] = &WorldPacketActionContext::tell_not_enough_reputation;
|
||||
creators["tell cannot equip"] = &WorldPacketActionContext::tell_cannot_equip;
|
||||
creators["loot roll"] = &WorldPacketActionContext::loot_roll;
|
||||
creators["master loot roll"] = &WorldPacketActionContext::master_loot_roll;
|
||||
creators["revive from corpse"] = &WorldPacketActionContext::revive_from_corpse;
|
||||
creators["find corpse"] = &WorldPacketActionContext::find_corpse;
|
||||
creators["auto release"] = &WorldPacketActionContext::auto_release;
|
||||
creators["accept resurrect"] = &WorldPacketActionContext::accept_resurrect;
|
||||
creators["use meeting stone"] = &WorldPacketActionContext::use_meeting_stone;
|
||||
creators["area trigger"] = &WorldPacketActionContext::area_trigger;
|
||||
creators["reach area trigger"] = &WorldPacketActionContext::reach_area_trigger;
|
||||
creators["check mount state"] = &WorldPacketActionContext::check_mount_state;
|
||||
creators["remember taxi"] = &WorldPacketActionContext::remember_taxi;
|
||||
creators["accept trade"] = &WorldPacketActionContext::accept_trade;
|
||||
creators["store loot"] = &WorldPacketActionContext::store_loot;
|
||||
|
||||
private:
|
||||
static Action* inventory_change_failure(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); }
|
||||
static Action* guild_accept(PlayerbotAI* botAI) { return new GuildAcceptAction(botAI); }
|
||||
static Action* security_check(PlayerbotAI* botAI) { return new SecurityCheckAction(botAI); }
|
||||
static Action* uninvite(PlayerbotAI* botAI) { return new UninviteAction(botAI); }
|
||||
static Action* ready_check_finished(PlayerbotAI* botAI) { return new FinishReadyCheckAction(botAI); }
|
||||
static Action* ready_check(PlayerbotAI* botAI) { return new ReadyCheckAction(botAI); }
|
||||
static Action* accept_duel(PlayerbotAI* botAI) { return new AcceptDuelAction(botAI); }
|
||||
static Action* tell_cast_failed(PlayerbotAI* botAI) { return new TellCastFailedAction(botAI); }
|
||||
static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); }
|
||||
static Action* quest_objective_completed(PlayerbotAI* botAI) { return new QuestObjectiveCompletedAction(botAI); }
|
||||
static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(botAI); }
|
||||
static Action* accept_trade(PlayerbotAI* botAI) { return new TradeStatusAction(botAI); }
|
||||
static Action* remember_taxi(PlayerbotAI* botAI) { return new RememberTaxiAction(botAI); }
|
||||
static Action* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); }
|
||||
static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); }
|
||||
static Action* reach_area_trigger(PlayerbotAI* botAI) { return new ReachAreaTriggerAction(botAI); }
|
||||
static Action* use_meeting_stone(PlayerbotAI* botAI) { return new UseMeetingStoneAction(botAI); }
|
||||
static Action* accept_resurrect(PlayerbotAI* botAI) { return new AcceptResurrectAction(botAI); }
|
||||
static Action* find_corpse(PlayerbotAI* botAI) { return new FindCorpseAction(botAI); }
|
||||
static Action* auto_release(PlayerbotAI* botAI) { return new AutoReleaseSpiritAction(botAI); }
|
||||
static Action* revive_from_corpse(PlayerbotAI* botAI) { return new ReviveFromCorpseAction(botAI); }
|
||||
static Action* accept_invitation(PlayerbotAI* botAI) { return new AcceptInvitationAction(botAI); }
|
||||
static Action* give_leader_in_dungeon(PlayerbotAI* botAI) { return new GiveLeaderAction(botAI, "I don't know this dungeon, lead the way!"); }
|
||||
static Action* pass_leadership_to_master(PlayerbotAI* botAI) { return new PassLeadershipToMasterAction(botAI); }
|
||||
static Action* tell_not_enough_money(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough money"); }
|
||||
static Action* tell_not_enough_reputation(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough reputation"); }
|
||||
static Action* tell_cannot_equip(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); }
|
||||
static Action* turn_in_quest(PlayerbotAI* botAI) { return new TalkToQuestGiverAction(botAI); }
|
||||
static Action* accept_quest(PlayerbotAI* botAI) { return new AcceptQuestAction(botAI); }
|
||||
static Action* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsAction(botAI); }
|
||||
static Action* accept_quest_share(PlayerbotAI* botAI) { return new AcceptQuestShareAction(botAI); }
|
||||
static Action* loot_roll(PlayerbotAI* botAI) { return new LootRollAction(botAI); }
|
||||
static Action* master_loot_roll(PlayerbotAI* botAI) { return new MasterLootRollAction(botAI); }
|
||||
static Action* bg_join(PlayerbotAI* botAI) { return new BGJoinAction(botAI); }
|
||||
static Action* bg_leave(PlayerbotAI* botAI) { return new BGLeaveAction(botAI); }
|
||||
static Action* bg_status(PlayerbotAI* botAI) { return new BGStatusAction(botAI); }
|
||||
static Action* bg_status_check(PlayerbotAI* botAI) { return new BGStatusCheckAction(botAI); }
|
||||
static Action* bg_strategy_check(PlayerbotAI* botAI) { return new BGStrategyCheckAction(botAI); }
|
||||
static Action* arena_tactics(PlayerbotAI* botAI) { return new ArenaTactics(botAI); }
|
||||
static Action* petition_sign(PlayerbotAI* botAI) { return new PetitionSignAction(botAI); }
|
||||
static Action* lfg_teleport(PlayerbotAI* botAI) { return new LfgTeleportAction(botAI); }
|
||||
static Action* lfg_leave(PlayerbotAI* botAI) { return new LfgLeaveAction(botAI); }
|
||||
static Action* lfg_accept(PlayerbotAI* botAI) { return new LfgAcceptAction(botAI); }
|
||||
static Action* lfg_role_check(PlayerbotAI* botAI) { return new LfgRoleCheckAction(botAI); }
|
||||
static Action* lfg_join(PlayerbotAI* botAI) { return new LfgJoinAction(botAI); }
|
||||
static Action* see_spell(PlayerbotAI* botAI) { return new SeeSpellAction(botAI); }
|
||||
static Action* arena_team_accept(PlayerbotAI* botAI) { return new ArenaTeamAcceptAction(botAI); }
|
||||
static Action* turn_in_query_quest(PlayerbotAI* botAI) { return new TurnInQueryQuestAction(botAI); }
|
||||
static Action* quest_confirm_accept(PlayerbotAI* botAI) { return new QuestConfirmAcceptAction(botAI); }
|
||||
// quest
|
||||
creators["talk to quest giver"] = &WorldPacketActionContext::turn_in_quest;
|
||||
creators["accept quest"] = &WorldPacketActionContext::accept_quest;
|
||||
creators["confirm quest"] = &WorldPacketActionContext::confirm_quest;
|
||||
creators["accept all quests"] = &WorldPacketActionContext::accept_all_quests;
|
||||
creators["accept quest share"] = &WorldPacketActionContext::accept_quest_share;
|
||||
creators["quest update add kill"] = &WorldPacketActionContext::quest_update_add_kill;
|
||||
creators["quest update add item"] = &WorldPacketActionContext::quest_update_add_item;
|
||||
creators["quest update failed"] = &WorldPacketActionContext::quest_update_failed;
|
||||
creators["quest update failed timer"] = &WorldPacketActionContext::quest_update_failed_timer;
|
||||
creators["quest update complete"] = &WorldPacketActionContext::quest_update_complete;
|
||||
|
||||
creators["party command"] = &WorldPacketActionContext::party_command;
|
||||
creators["tell cast failed"] = &WorldPacketActionContext::tell_cast_failed;
|
||||
creators["accept duel"] = &WorldPacketActionContext::accept_duel;
|
||||
creators["ready check"] = &WorldPacketActionContext::ready_check;
|
||||
creators["ready check finished"] = &WorldPacketActionContext::ready_check_finished;
|
||||
creators["uninvite"] = &WorldPacketActionContext::uninvite;
|
||||
creators["security check"] = &WorldPacketActionContext::security_check;
|
||||
creators["guild accept"] = &WorldPacketActionContext::guild_accept;
|
||||
creators["inventory change failure"] = &WorldPacketActionContext::inventory_change_failure;
|
||||
creators["bg status check"] = &WorldPacketActionContext::bg_status_check;
|
||||
creators["bg strategy check"] = &WorldPacketActionContext::bg_strategy_check;
|
||||
creators["bg status"] = &WorldPacketActionContext::bg_status;
|
||||
creators["bg join"] = &WorldPacketActionContext::bg_join;
|
||||
creators["bg leave"] = &WorldPacketActionContext::bg_leave;
|
||||
creators["arena tactics"] = &WorldPacketActionContext::arena_tactics;
|
||||
creators["petition sign"] = &WorldPacketActionContext::petition_sign;
|
||||
creators["lfg join"] = &WorldPacketActionContext::lfg_join;
|
||||
creators["lfg accept"] = &WorldPacketActionContext::lfg_accept;
|
||||
creators["lfg role check"] = &WorldPacketActionContext::lfg_role_check;
|
||||
creators["lfg leave"] = &WorldPacketActionContext::lfg_leave;
|
||||
creators["lfg teleport"] = &WorldPacketActionContext::lfg_teleport;
|
||||
creators["see spell"] = &WorldPacketActionContext::see_spell;
|
||||
creators["arena team accept"] = &WorldPacketActionContext::arena_team_accept;
|
||||
}
|
||||
|
||||
private:
|
||||
static Action* inventory_change_failure(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); }
|
||||
static Action* guild_accept(PlayerbotAI* botAI) { return new GuildAcceptAction(botAI); }
|
||||
static Action* security_check(PlayerbotAI* botAI) { return new SecurityCheckAction(botAI); }
|
||||
static Action* uninvite(PlayerbotAI* botAI) { return new UninviteAction(botAI); }
|
||||
static Action* ready_check_finished(PlayerbotAI* botAI) { return new FinishReadyCheckAction(botAI); }
|
||||
static Action* ready_check(PlayerbotAI* botAI) { return new ReadyCheckAction(botAI); }
|
||||
static Action* accept_duel(PlayerbotAI* botAI) { return new AcceptDuelAction(botAI); }
|
||||
static Action* tell_cast_failed(PlayerbotAI* botAI) { return new TellCastFailedAction(botAI); }
|
||||
static Action* party_command(PlayerbotAI* botAI) { return new PartyCommandAction(botAI); }
|
||||
static Action* store_loot(PlayerbotAI* botAI) { return new StoreLootAction(botAI); }
|
||||
static Action* accept_trade(PlayerbotAI* botAI) { return new TradeStatusAction(botAI); }
|
||||
static Action* remember_taxi(PlayerbotAI* botAI) { return new RememberTaxiAction(botAI); }
|
||||
static Action* check_mount_state(PlayerbotAI* botAI) { return new CheckMountStateAction(botAI); }
|
||||
static Action* area_trigger(PlayerbotAI* botAI) { return new AreaTriggerAction(botAI); }
|
||||
static Action* reach_area_trigger(PlayerbotAI* botAI) { return new ReachAreaTriggerAction(botAI); }
|
||||
static Action* use_meeting_stone(PlayerbotAI* botAI) { return new UseMeetingStoneAction(botAI); }
|
||||
static Action* accept_resurrect(PlayerbotAI* botAI) { return new AcceptResurrectAction(botAI); }
|
||||
static Action* find_corpse(PlayerbotAI* botAI) { return new FindCorpseAction(botAI); }
|
||||
static Action* auto_release(PlayerbotAI* botAI) { return new AutoReleaseSpiritAction(botAI); }
|
||||
static Action* revive_from_corpse(PlayerbotAI* botAI) { return new ReviveFromCorpseAction(botAI); }
|
||||
static Action* accept_invitation(PlayerbotAI* botAI) { return new AcceptInvitationAction(botAI); }
|
||||
static Action* give_leader_in_dungeon(PlayerbotAI* botAI) { return new GiveLeaderAction(botAI, "I don't know this dungeon, lead the way!"); }
|
||||
static Action* pass_leadership_to_master(PlayerbotAI* botAI) { return new PassLeadershipToMasterAction(botAI); }
|
||||
static Action* tell_not_enough_money(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough money"); }
|
||||
static Action* tell_not_enough_reputation(PlayerbotAI* botAI) { return new TellMasterAction(botAI, "Not enough reputation"); }
|
||||
static Action* tell_cannot_equip(PlayerbotAI* botAI) { return new InventoryChangeFailureAction(botAI); }
|
||||
|
||||
// quest
|
||||
static Action* quest_update_add_kill(PlayerbotAI* ai) { return new QuestUpdateAddKillAction(ai); }
|
||||
static Action* quest_update_add_item(PlayerbotAI* ai) { return new QuestUpdateAddItemAction(ai); }
|
||||
static Action* quest_update_failed(PlayerbotAI* ai) { return new QuestUpdateFailedAction(ai); }
|
||||
static Action* quest_update_failed_timer(PlayerbotAI* ai) { return new QuestUpdateFailedTimerAction(ai); }
|
||||
static Action* quest_update_complete(PlayerbotAI* botAI) { return new QuestUpdateCompleteAction(botAI); }
|
||||
|
||||
static Action* turn_in_quest(PlayerbotAI* botAI) { return new TalkToQuestGiverAction(botAI); }
|
||||
static Action* accept_quest(PlayerbotAI* botAI) { return new AcceptQuestAction(botAI); }
|
||||
static Action* confirm_quest(PlayerbotAI* ai) { return new ConfirmQuestAction(ai); }
|
||||
static Action* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsAction(botAI); }
|
||||
static Action* accept_quest_share(PlayerbotAI* botAI) { return new AcceptQuestShareAction(botAI); }
|
||||
//static Action* turn_in_query_quest(PlayerbotAI* botAI) { return new TurnInQueryQuestAction(botAI); }
|
||||
//static Action* quest_confirm_accept(PlayerbotAI* botAI) { return new QuestConfirmAcceptAction(botAI); }
|
||||
|
||||
|
||||
static Action* loot_roll(PlayerbotAI* botAI) { return new LootRollAction(botAI); }
|
||||
static Action* master_loot_roll(PlayerbotAI* botAI) { return new MasterLootRollAction(botAI); }
|
||||
static Action* bg_join(PlayerbotAI* botAI) { return new BGJoinAction(botAI); }
|
||||
static Action* bg_leave(PlayerbotAI* botAI) { return new BGLeaveAction(botAI); }
|
||||
static Action* bg_status(PlayerbotAI* botAI) { return new BGStatusAction(botAI); }
|
||||
static Action* bg_status_check(PlayerbotAI* botAI) { return new BGStatusCheckAction(botAI); }
|
||||
static Action* bg_strategy_check(PlayerbotAI* botAI) { return new BGStrategyCheckAction(botAI); }
|
||||
static Action* arena_tactics(PlayerbotAI* botAI) { return new ArenaTactics(botAI); }
|
||||
static Action* petition_sign(PlayerbotAI* botAI) { return new PetitionSignAction(botAI); }
|
||||
static Action* lfg_teleport(PlayerbotAI* botAI) { return new LfgTeleportAction(botAI); }
|
||||
static Action* lfg_leave(PlayerbotAI* botAI) { return new LfgLeaveAction(botAI); }
|
||||
static Action* lfg_accept(PlayerbotAI* botAI) { return new LfgAcceptAction(botAI); }
|
||||
static Action* lfg_role_check(PlayerbotAI* botAI) { return new LfgRoleCheckAction(botAI); }
|
||||
static Action* lfg_join(PlayerbotAI* botAI) { return new LfgJoinAction(botAI); }
|
||||
static Action* see_spell(PlayerbotAI* botAI) { return new SeeSpellAction(botAI); }
|
||||
static Action* arena_team_accept(PlayerbotAI* botAI) { return new ArenaTeamAcceptAction(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,4 +43,13 @@ class DebugSpellStrategy : public Strategy
|
||||
std::string const getName() override { return "debug spell"; }
|
||||
};
|
||||
|
||||
class DebugQuestStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
DebugQuestStrategy(PlayerbotAI* botAI) : Strategy(botAI) { }
|
||||
|
||||
uint32 GetType() const override { return STRATEGY_TYPE_NONCOMBAT | STRATEGY_TYPE_COMBAT; }
|
||||
std::string const getName() override { return "debug quest"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,11 +14,11 @@ void MaintenanceStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("clean quest log", 6.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("use random recipe", 1.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("use random quest item", 10.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("disenchant random item", 1.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("enchant random item", 1.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("smart destroy item", 1.0f), nullptr)));
|
||||
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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ void WorldPacketHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
triggers.push_back(new TriggerNode("lfg proposal", NextAction::array(0, new NextAction("lfg accept", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("lfg proposal active", NextAction::array(0, new NextAction("lfg accept", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("arena team invite", NextAction::array(0, new NextAction("arena team accept", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("quest confirm accept", NextAction::array(0, new NextAction("quest confirm accept", relevance), nullptr)));
|
||||
//triggers.push_back(new TriggerNode("no non bot players around", NextAction::array(0, new NextAction("delay", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("bg status", NextAction::array(0, new NextAction("bg status", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("xpgain", NextAction::array(0, new NextAction("xp gain", relevance), nullptr)));
|
||||
@@ -43,20 +42,22 @@ void WorldPacketHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
new NextAction("auto upgrade equip", relevance),
|
||||
nullptr)));
|
||||
// triggers.push_back(new TriggerNode("group destroyed", NextAction::array(0, new NextAction("reset botAI", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("questgiver quest details", NextAction::array(0, new NextAction("turn in query quest", relevance), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("group list", NextAction::array(0, new NextAction("reset botAI", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("see spell", NextAction::array(0, new NextAction("see spell", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("release spirit", NextAction::array(0, new NextAction("release", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("revive from corpse", NextAction::array(0, new NextAction("revive from corpse", relevance), nullptr)));
|
||||
triggers.push_back(new TriggerNode("master loot roll", NextAction::array(0, new NextAction("master loot roll", relevance), nullptr)));
|
||||
|
||||
// quest ?
|
||||
//triggers.push_back(new TriggerNode("quest confirm", NextAction::array(0, new NextAction("quest confirm", relevance), nullptr)));
|
||||
//triggers.push_back(new TriggerNode("questgiver quest details", NextAction::array(0, new NextAction("turn in query quest", relevance), nullptr)));
|
||||
}
|
||||
|
||||
WorldPacketHandlerStrategy::WorldPacketHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)
|
||||
{
|
||||
supported.push_back("loot roll");
|
||||
supported.push_back("check mount state");
|
||||
supported.push_back("quest objective completed");
|
||||
supported.push_back("party command");
|
||||
supported.push_back("ready check");
|
||||
supported.push_back("uninvite");
|
||||
@@ -65,6 +66,14 @@ WorldPacketHandlerStrategy::WorldPacketHandlerStrategy(PlayerbotAI* botAI) : Pas
|
||||
supported.push_back("random bot update");
|
||||
supported.push_back("inventory change failure");
|
||||
supported.push_back("bg status");
|
||||
|
||||
// quests
|
||||
supported.push_back("quest update add kill");
|
||||
supported.push_back("quest update add item");
|
||||
supported.push_back("quest update failed");
|
||||
supported.push_back("quest update failed timer");
|
||||
supported.push_back("quest update complete");
|
||||
supported.push_back("confirm quest");
|
||||
}
|
||||
|
||||
void ReadyCheckStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -11,20 +11,20 @@ class PlayerbotAI;
|
||||
|
||||
class WorldPacketHandlerStrategy : public PassTroughStrategy
|
||||
{
|
||||
public:
|
||||
WorldPacketHandlerStrategy(PlayerbotAI* botAI);
|
||||
public:
|
||||
WorldPacketHandlerStrategy(PlayerbotAI* botAI);
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "default"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "default"; }
|
||||
};
|
||||
|
||||
class ReadyCheckStrategy : public PassTroughStrategy
|
||||
{
|
||||
public:
|
||||
ReadyCheckStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) { }
|
||||
public:
|
||||
ReadyCheckStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI) { }
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "ready check"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "ready check"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -114,6 +114,12 @@ bool RpgEndQuestTrigger::IsActive()
|
||||
if (AI_VALUE2(bool, "can turn in quest npc", guidP.GetEntry()))
|
||||
return true;
|
||||
|
||||
if (!AI_VALUE2(bool, "can accept quest low level npc", guidP.GetEntry()))
|
||||
return false;
|
||||
|
||||
if (guidP.GetEntry() == AI_VALUE(TravelTarget*, "travel target")->getEntry())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,112 +11,127 @@
|
||||
|
||||
class WorldPacketTriggerContext : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
WorldPacketTriggerContext()
|
||||
{
|
||||
creators["gossip hello"] = &WorldPacketTriggerContext::gossip_hello;
|
||||
creators["group invite"] = &WorldPacketTriggerContext::group_invite;
|
||||
creators["group set leader"] = &WorldPacketTriggerContext::group_set_leader;
|
||||
creators["not enough money"] = &WorldPacketTriggerContext::no_money;
|
||||
creators["not enough reputation"] = &WorldPacketTriggerContext::no_reputation;
|
||||
creators["cannot equip"] = &WorldPacketTriggerContext::cannot_equip;
|
||||
creators["use game object"] = &WorldPacketTriggerContext::use_game_object;
|
||||
creators["complete quest"] = &WorldPacketTriggerContext::complete_quest;
|
||||
creators["accept quest"] = &WorldPacketTriggerContext::accept_quest;
|
||||
creators["quest share"] = &WorldPacketTriggerContext::quest_share;
|
||||
creators["loot roll"] = &WorldPacketTriggerContext::loot_roll;
|
||||
creators["resurrect request"] = &WorldPacketTriggerContext::resurrect_request;
|
||||
creators["area trigger"] = &WorldPacketTriggerContext::area_trigger;
|
||||
creators["within area trigger"] = &WorldPacketTriggerContext::within_area_trigger;
|
||||
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
|
||||
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
|
||||
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
|
||||
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
|
||||
creators["out of react range"] = &WorldPacketTriggerContext::out_of_react_range;
|
||||
creators["quest objective completed"] = &WorldPacketTriggerContext::quest_objective_completed;
|
||||
creators["item push result"] = &WorldPacketTriggerContext::item_push_result;
|
||||
creators["party command"] = &WorldPacketTriggerContext::party_command;
|
||||
creators["taxi done"] = &WorldPacketTriggerContext::taxi_done;
|
||||
creators["cast failed"] = &WorldPacketTriggerContext::cast_failed;
|
||||
creators["duel requested"] = &WorldPacketTriggerContext::duel_requested;
|
||||
creators["ready check"] = &WorldPacketTriggerContext::ready_check;
|
||||
creators["ready check finished"] = &WorldPacketTriggerContext::ready_check_finished;
|
||||
creators["uninvite"] = &WorldPacketTriggerContext::uninvite;
|
||||
creators["uninvite guid"] = &WorldPacketTriggerContext::uninvite_guid;
|
||||
creators["lfg join"] = &WorldPacketTriggerContext::lfg_update;
|
||||
creators["lfg proposal"] = &WorldPacketTriggerContext::lfg_proposal;
|
||||
creators["lfg role check"] = &WorldPacketTriggerContext::lfg_role_check;
|
||||
creators["lfg leave"] = &WorldPacketTriggerContext::lfg_leave;
|
||||
creators["guild invite"] = &WorldPacketTriggerContext::guild_invite;
|
||||
creators["petition offer"] = &WorldPacketTriggerContext::petition_offer;
|
||||
creators["lfg teleport"] = &WorldPacketTriggerContext::lfg_teleport;
|
||||
creators["inventory change failure"] = &WorldPacketTriggerContext::inventory_change_failure;
|
||||
creators["bg status"] = &WorldPacketTriggerContext::bg_status;
|
||||
creators["levelup"] = &WorldPacketTriggerContext::levelup;
|
||||
creators["xpgain"] = &WorldPacketTriggerContext::xpgain;
|
||||
creators["see spell"] = &WorldPacketTriggerContext::seespell;
|
||||
creators["release spirit"] = &WorldPacketTriggerContext::release_spirit;
|
||||
creators["revive from corpse"] = &WorldPacketTriggerContext::revive_from_corpse;
|
||||
creators["receive emote"] = &WorldPacketTriggerContext::receive_emote;
|
||||
creators["receive text emote"] = &WorldPacketTriggerContext::receive_text_emote;
|
||||
creators["arena team invite"] = &WorldPacketTriggerContext::arena_team_invite;
|
||||
creators["quest confirm accept"] = &WorldPacketTriggerContext::quest_confirm_accept;
|
||||
creators["group destroyed"] = &WorldPacketTriggerContext::group_destroyed;
|
||||
creators["group list"] = &WorldPacketTriggerContext::group_list;
|
||||
creators["questgiver quest details"] = &WorldPacketTriggerContext::questgiver_quest_details;
|
||||
}
|
||||
public:
|
||||
WorldPacketTriggerContext()
|
||||
{
|
||||
creators["gossip hello"] = &WorldPacketTriggerContext::gossip_hello;
|
||||
creators["group invite"] = &WorldPacketTriggerContext::group_invite;
|
||||
creators["group set leader"] = &WorldPacketTriggerContext::group_set_leader;
|
||||
creators["not enough money"] = &WorldPacketTriggerContext::no_money;
|
||||
creators["not enough reputation"] = &WorldPacketTriggerContext::no_reputation;
|
||||
creators["cannot equip"] = &WorldPacketTriggerContext::cannot_equip;
|
||||
creators["use game object"] = &WorldPacketTriggerContext::use_game_object;
|
||||
creators["loot roll"] = &WorldPacketTriggerContext::loot_roll;
|
||||
creators["resurrect request"] = &WorldPacketTriggerContext::resurrect_request;
|
||||
creators["area trigger"] = &WorldPacketTriggerContext::area_trigger;
|
||||
creators["within area trigger"] = &WorldPacketTriggerContext::within_area_trigger;
|
||||
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
|
||||
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
|
||||
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
|
||||
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
|
||||
creators["out of react range"] = &WorldPacketTriggerContext::out_of_react_range;
|
||||
|
||||
private:
|
||||
static Trigger* inventory_change_failure(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "inventory change failure"); }
|
||||
static Trigger* guild_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "guild invite"); }
|
||||
static Trigger* lfg_teleport(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg teleport"); }
|
||||
static Trigger* lfg_leave(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg leave"); }
|
||||
static Trigger* lfg_proposal(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg proposal"); }
|
||||
static Trigger* lfg_role_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg role check"); }
|
||||
static Trigger* lfg_update(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg join"); }
|
||||
static Trigger* uninvite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite"); }
|
||||
static Trigger* uninvite_guid(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite guid"); }
|
||||
static Trigger* ready_check_finished(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check finished"); }
|
||||
static Trigger* ready_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check"); }
|
||||
static Trigger* duel_requested(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "duel requested"); }
|
||||
static Trigger* cast_failed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cast failed"); }
|
||||
static Trigger* taxi_done(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "taxi done"); }
|
||||
static Trigger* party_command(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "party command"); }
|
||||
static Trigger* item_push_result(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "item push result"); }
|
||||
static Trigger* quest_objective_completed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "quest objective completed"); }
|
||||
static Trigger* out_of_react_range(PlayerbotAI* botAI) { return new OutOfReactRangeTrigger(botAI); }
|
||||
static Trigger* loot_response(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot response"); }
|
||||
static Trigger* trade_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status"); }
|
||||
static Trigger* cannot_equip(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cannot equip"); }
|
||||
static Trigger* check_mount_state(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "check mount state"); }
|
||||
static Trigger* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }
|
||||
static Trigger* within_area_trigger(PlayerbotAI* botAI) { return new WithinAreaTrigger(botAI); }
|
||||
static Trigger* resurrect_request(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "resurrect request"); }
|
||||
static Trigger* gossip_hello(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "gossip hello"); }
|
||||
static Trigger* group_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group invite"); }
|
||||
static Trigger* group_set_leader(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group set leader"); }
|
||||
static Trigger* no_money(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough money"); }
|
||||
static Trigger* no_reputation(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough reputation"); }
|
||||
static Trigger* use_game_object(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "use game object"); }
|
||||
static Trigger* complete_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "complete quest"); }
|
||||
static Trigger* accept_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "accept quest"); }
|
||||
static Trigger* quest_share(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "quest share"); }
|
||||
static Trigger* loot_roll(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot roll"); }
|
||||
static Trigger* taxi(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "activate taxi"); }
|
||||
static Trigger* bg_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "bg status"); }
|
||||
static Trigger* levelup(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "levelup"); }
|
||||
static Trigger* xpgain(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "xpgain"); }
|
||||
static Trigger* petition_offer(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "petition offer"); }
|
||||
static Trigger* seespell(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "see spell"); }
|
||||
static Trigger* release_spirit(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "release spirit"); }
|
||||
static Trigger* revive_from_corpse(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "revive from corpse"); }
|
||||
static Trigger* receive_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive emote"); }
|
||||
static Trigger* receive_text_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive text emote"); }
|
||||
static Trigger* arena_team_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "arena team invite"); }
|
||||
static Trigger* quest_confirm_accept(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "quest confirm accept"); }
|
||||
static Trigger* group_destroyed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group destroyed"); }
|
||||
static Trigger* group_list(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group list"); }
|
||||
static Trigger* questgiver_quest_details(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "questgiver quest details"); }
|
||||
// quest
|
||||
creators["complete quest"] = &WorldPacketTriggerContext::complete_quest;
|
||||
creators["accept quest"] = &WorldPacketTriggerContext::accept_quest;
|
||||
creators["confirm quest"] = &WorldPacketTriggerContext::quest_confirm_accept;
|
||||
creators["quest share"] = &WorldPacketTriggerContext::quest_share;
|
||||
creators["quest update add kill"] = &WorldPacketTriggerContext::quest_update_add_kill;
|
||||
creators["quest update add item"] = &WorldPacketTriggerContext::quest_update_add_item;
|
||||
creators["quest update failed"] = &WorldPacketTriggerContext::quest_update_failed;
|
||||
creators["quest update failed timer"] = &WorldPacketTriggerContext::quest_update_failed_timer;
|
||||
creators["quest update complete"] = &WorldPacketTriggerContext::quest_update_complete;
|
||||
creators["questgiver quest details"] = &WorldPacketTriggerContext::questgiver_quest_details;
|
||||
|
||||
|
||||
creators["item push result"] = &WorldPacketTriggerContext::item_push_result;
|
||||
creators["party command"] = &WorldPacketTriggerContext::party_command;
|
||||
creators["taxi done"] = &WorldPacketTriggerContext::taxi_done;
|
||||
creators["cast failed"] = &WorldPacketTriggerContext::cast_failed;
|
||||
creators["duel requested"] = &WorldPacketTriggerContext::duel_requested;
|
||||
creators["ready check"] = &WorldPacketTriggerContext::ready_check;
|
||||
creators["ready check finished"] = &WorldPacketTriggerContext::ready_check_finished;
|
||||
creators["uninvite"] = &WorldPacketTriggerContext::uninvite;
|
||||
creators["uninvite guid"] = &WorldPacketTriggerContext::uninvite_guid;
|
||||
creators["lfg join"] = &WorldPacketTriggerContext::lfg_update;
|
||||
creators["lfg proposal"] = &WorldPacketTriggerContext::lfg_proposal;
|
||||
creators["lfg role check"] = &WorldPacketTriggerContext::lfg_role_check;
|
||||
creators["lfg leave"] = &WorldPacketTriggerContext::lfg_leave;
|
||||
creators["guild invite"] = &WorldPacketTriggerContext::guild_invite;
|
||||
creators["petition offer"] = &WorldPacketTriggerContext::petition_offer;
|
||||
creators["lfg teleport"] = &WorldPacketTriggerContext::lfg_teleport;
|
||||
creators["inventory change failure"] = &WorldPacketTriggerContext::inventory_change_failure;
|
||||
creators["bg status"] = &WorldPacketTriggerContext::bg_status;
|
||||
creators["levelup"] = &WorldPacketTriggerContext::levelup;
|
||||
creators["xpgain"] = &WorldPacketTriggerContext::xpgain;
|
||||
creators["see spell"] = &WorldPacketTriggerContext::seespell;
|
||||
creators["release spirit"] = &WorldPacketTriggerContext::release_spirit;
|
||||
creators["revive from corpse"] = &WorldPacketTriggerContext::revive_from_corpse;
|
||||
creators["receive emote"] = &WorldPacketTriggerContext::receive_emote;
|
||||
creators["receive text emote"] = &WorldPacketTriggerContext::receive_text_emote;
|
||||
creators["arena team invite"] = &WorldPacketTriggerContext::arena_team_invite;
|
||||
creators["group destroyed"] = &WorldPacketTriggerContext::group_destroyed;
|
||||
creators["group list"] = &WorldPacketTriggerContext::group_list;
|
||||
}
|
||||
|
||||
private:
|
||||
static Trigger* inventory_change_failure(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "inventory change failure"); }
|
||||
static Trigger* guild_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "guild invite"); }
|
||||
static Trigger* lfg_teleport(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg teleport"); }
|
||||
static Trigger* lfg_leave(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg leave"); }
|
||||
static Trigger* lfg_proposal(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg proposal"); }
|
||||
static Trigger* lfg_role_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg role check"); }
|
||||
static Trigger* lfg_update(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg join"); }
|
||||
static Trigger* uninvite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite"); }
|
||||
static Trigger* uninvite_guid(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite guid"); }
|
||||
static Trigger* ready_check_finished(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check finished"); }
|
||||
static Trigger* ready_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check"); }
|
||||
static Trigger* duel_requested(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "duel requested"); }
|
||||
static Trigger* cast_failed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cast failed"); }
|
||||
static Trigger* taxi_done(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "taxi done"); }
|
||||
static Trigger* party_command(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "party command"); }
|
||||
static Trigger* item_push_result(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "item push result"); }
|
||||
|
||||
// quest
|
||||
static Trigger* quest_update_add_kill(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest update add kill"); }
|
||||
static Trigger* quest_update_add_item(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest update add item"); }
|
||||
static Trigger* quest_update_failed(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest update failed"); }
|
||||
static Trigger* quest_update_failed_timer(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest update failed timer"); }
|
||||
static Trigger* quest_update_complete(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest update complete"); }
|
||||
static Trigger* complete_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "complete quest"); }
|
||||
static Trigger* accept_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "accept quest"); }
|
||||
static Trigger* quest_confirm_accept(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "confirm quest"); }
|
||||
static Trigger* quest_share(PlayerbotAI* ai) { return new WorldPacketTrigger(ai, "quest share"); }
|
||||
static Trigger* questgiver_quest_details(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "questgiver quest details"); }
|
||||
|
||||
static Trigger* out_of_react_range(PlayerbotAI* botAI) { return new OutOfReactRangeTrigger(botAI); }
|
||||
static Trigger* loot_response(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot response"); }
|
||||
static Trigger* trade_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status"); }
|
||||
static Trigger* cannot_equip(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cannot equip"); }
|
||||
static Trigger* check_mount_state(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "check mount state"); }
|
||||
static Trigger* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }
|
||||
static Trigger* within_area_trigger(PlayerbotAI* botAI) { return new WithinAreaTrigger(botAI); }
|
||||
static Trigger* resurrect_request(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "resurrect request"); }
|
||||
static Trigger* gossip_hello(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "gossip hello"); }
|
||||
static Trigger* group_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group invite"); }
|
||||
static Trigger* group_set_leader(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group set leader"); }
|
||||
static Trigger* no_money(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough money"); }
|
||||
static Trigger* no_reputation(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough reputation"); }
|
||||
static Trigger* use_game_object(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "use game object"); }
|
||||
static Trigger* loot_roll(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot roll"); }
|
||||
static Trigger* taxi(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "activate taxi"); }
|
||||
static Trigger* bg_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "bg status"); }
|
||||
static Trigger* levelup(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "levelup"); }
|
||||
static Trigger* xpgain(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "xpgain"); }
|
||||
static Trigger* petition_offer(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "petition offer"); }
|
||||
static Trigger* seespell(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "see spell"); }
|
||||
static Trigger* release_spirit(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "release spirit"); }
|
||||
static Trigger* revive_from_corpse(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "revive from corpse"); }
|
||||
static Trigger* receive_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive emote"); }
|
||||
static Trigger* receive_text_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive text emote"); }
|
||||
static Trigger* arena_team_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "arena team invite"); }
|
||||
static Trigger* group_destroyed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group destroyed"); }
|
||||
static Trigger* group_list(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group list"); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,9 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
Group* group = bot->GetGroup();
|
||||
Player* master = GetMaster();
|
||||
|
||||
if (master && (master == bot || master->GetMapId() != bot->GetMapId() || master->IsBeingTeleported() || !GET_PLAYERBOT_AI(master)))
|
||||
master = nullptr;
|
||||
|
||||
GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
|
||||
for (ObjectGuid const guid : attackers)
|
||||
{
|
||||
@@ -46,8 +49,7 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
|
||||
float distance = 0;
|
||||
Unit* result = nullptr;
|
||||
|
||||
// std::unordered_map<uint32, bool> needForQuestMap;
|
||||
std::unordered_map<uint32, bool> needForQuestMap;
|
||||
|
||||
for (ObjectGuid const guid : targets)
|
||||
{
|
||||
@@ -81,16 +83,18 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
if (!bot->InBattleground() && (int)unit->GetLevel() - (int)bot->GetLevel() > 4 && !unit->GetGUID().IsPlayer())
|
||||
continue;
|
||||
|
||||
// if (needForQuestMap.find(unit->GetEntry()) == needForQuestMap.end())
|
||||
// needForQuestMap[unit->GetEntry()] = needForQuest(unit);
|
||||
if (needForQuestMap.find(unit->GetEntry()) == needForQuestMap.end())
|
||||
needForQuestMap[unit->GetEntry()] = needForQuest(unit);
|
||||
|
||||
// if (!needForQuestMap[unit->GetEntry()])
|
||||
// if ((urand(0, 100) < 75 || (context->GetValue<TravelTarget*>("travel target")->Get()->isWorking() &&
|
||||
// context->GetValue<TravelTarget*>("travel target")->Get()->getDestination()->getName() != "GrindTravelDestination")))
|
||||
// continue;
|
||||
|
||||
//if (bot->InBattleground() && bot->GetDistance(unit) > 40.0f)
|
||||
//continue;
|
||||
if (!needForQuestMap[unit->GetEntry()])
|
||||
{
|
||||
Creature* creature = dynamic_cast<Creature*>(unit);
|
||||
if ((urand(0, 100) < 60 || (context->GetValue<TravelTarget*>("travel target")->Get()->isWorking() &&
|
||||
context->GetValue<TravelTarget*>("travel target")->Get()->getDestination()->getName() != "GrindTravelDestination")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
if (CreatureTemplate const* CreatureTemplate = creature->GetCreatureTemplate())
|
||||
|
||||
Reference in New Issue
Block a user