Bot should be more consistent at doing quest +several fixes

This commit is contained in:
Atidot3
2024-07-30 14:45:52 +02:00
parent 30a25ba13f
commit 0008d84f71
34 changed files with 986 additions and 609 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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.
//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;
};

View File

@@ -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);

View File

@@ -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)

View File

@@ -8,6 +8,8 @@
#include "MovementActions.h"
class PlayerbotAI;
class TravelDestination;
class WorldPosition;
class GoAction : public MovementAction
{

View File

@@ -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++;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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());

View File

@@ -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

View File

@@ -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,26 +250,26 @@ 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);
botAI->TellMaster(out);
return true;
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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