mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Suggest dungeon implementation + log action unknown to help debug
This commit is contained in:
@@ -636,7 +636,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
|||||||
// Battleground switch
|
// Battleground switch
|
||||||
if (player->InBattleground() && player->GetBattleground())
|
if (player->InBattleground() && player->GetBattleground())
|
||||||
{
|
{
|
||||||
nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", nullptr);
|
nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", "emote", nullptr);
|
||||||
nonCombatEngine->removeStrategy("custom::say");
|
nonCombatEngine->removeStrategy("custom::say");
|
||||||
nonCombatEngine->removeStrategy("travel");
|
nonCombatEngine->removeStrategy("travel");
|
||||||
nonCombatEngine->removeStrategy("rpg");
|
nonCombatEngine->removeStrategy("rpg");
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
|
|||||||
|
|
||||||
uint32 botAccountId = holder.GetAccountId();
|
uint32 botAccountId = holder.GetAccountId();
|
||||||
|
|
||||||
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, 0, false, false, 0, true);
|
// At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this allows channels to work as intended)
|
||||||
|
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), sWorld->GetDefaultDbcLocale(), 0, false, false, 0, true);
|
||||||
|
|
||||||
botSession->HandlePlayerLoginFromDB(holder); // will delete lqh
|
botSession->HandlePlayerLoginFromDB(holder); // will delete lqh
|
||||||
|
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
|||||||
|
|
||||||
if (!action)
|
if (!action)
|
||||||
{
|
{
|
||||||
|
LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(), botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel());
|
||||||
LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
|
LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
|
||||||
}
|
}
|
||||||
else if (action->isUseful())
|
else if (action->isUseful())
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ class ActionContext : public NamedObjectContext<Action>
|
|||||||
creators["talk"] = &ActionContext::talk;
|
creators["talk"] = &ActionContext::talk;
|
||||||
creators["suggest what to do"] = &ActionContext::suggest_what_to_do;
|
creators["suggest what to do"] = &ActionContext::suggest_what_to_do;
|
||||||
creators["suggest trade"] = &ActionContext::suggest_trade;
|
creators["suggest trade"] = &ActionContext::suggest_trade;
|
||||||
|
creators["suggest dungeon"] = &ActionContext::suggest_dungeon;
|
||||||
creators["return"] = &ActionContext::_return;
|
creators["return"] = &ActionContext::_return;
|
||||||
creators["move to loot"] = &ActionContext::move_to_loot;
|
creators["move to loot"] = &ActionContext::move_to_loot;
|
||||||
creators["open loot"] = &ActionContext::open_loot;
|
creators["open loot"] = &ActionContext::open_loot;
|
||||||
@@ -280,6 +281,7 @@ class ActionContext : public NamedObjectContext<Action>
|
|||||||
static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); }
|
static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); }
|
||||||
static Action* suggest_what_to_do(PlayerbotAI* botAI) { return new SuggestWhatToDoAction(botAI); }
|
static Action* suggest_what_to_do(PlayerbotAI* botAI) { return new SuggestWhatToDoAction(botAI); }
|
||||||
static Action* suggest_trade(PlayerbotAI* botAI) { return new SuggestTradeAction(botAI); }
|
static Action* suggest_trade(PlayerbotAI* botAI) { return new SuggestTradeAction(botAI); }
|
||||||
|
static Action* suggest_dungeon(PlayerbotAI* botAI) { return new SuggestDungeonAction(botAI); }
|
||||||
static Action* attack_anything(PlayerbotAI* botAI) { return new AttackAnythingAction(botAI); }
|
static Action* attack_anything(PlayerbotAI* botAI) { return new AttackAnythingAction(botAI); }
|
||||||
static Action* attack_least_hp_target(PlayerbotAI* botAI) { return new AttackLeastHpTargetAction(botAI); }
|
static Action* attack_least_hp_target(PlayerbotAI* botAI) { return new AttackLeastHpTargetAction(botAI); }
|
||||||
static Action* attack_enemy_player(PlayerbotAI* botAI) { return new AttackEnemyPlayerAction(botAI); }
|
static Action* attack_enemy_player(PlayerbotAI* botAI) { return new AttackEnemyPlayerAction(botAI); }
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SuggestWhatToDoAction.h"
|
#include "SuggestWhatToDoAction.h"
|
||||||
|
#include "ServerFacade.h"
|
||||||
#include "ChannelMgr.h"
|
#include "ChannelMgr.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "ItemVisitors.h"
|
#include "ItemVisitors.h"
|
||||||
@@ -24,7 +25,7 @@ enum eTalkType
|
|||||||
LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL
|
LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, uint8> SuggestWhatToDoAction::instances;
|
std::map<std::string, uint8> SuggestDungeonAction::instances;
|
||||||
std::map<std::string, uint8> SuggestWhatToDoAction::factions;
|
std::map<std::string, uint8> SuggestWhatToDoAction::factions;
|
||||||
|
|
||||||
SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string const name)
|
SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string const name)
|
||||||
@@ -34,7 +35,6 @@ SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string con
|
|||||||
suggestions.push_back(std::bind(&SuggestWhatToDoAction::specificQuest, this));
|
suggestions.push_back(std::bind(&SuggestWhatToDoAction::specificQuest, this));
|
||||||
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindReputation, this));
|
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindReputation, this));
|
||||||
suggestions.push_back(std::bind(&SuggestWhatToDoAction::something, this));
|
suggestions.push_back(std::bind(&SuggestWhatToDoAction::something, this));
|
||||||
suggestions.push_back(std::bind(&SuggestWhatToDoAction::instance, this));
|
|
||||||
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindMaterials, this));
|
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindMaterials, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,73 +61,6 @@ bool SuggestWhatToDoAction::Execute(Event event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuggestWhatToDoAction::instance()
|
|
||||||
{
|
|
||||||
if (instances.empty())
|
|
||||||
{
|
|
||||||
instances["Ragefire Chasm"] = 15;
|
|
||||||
instances["Deadmines"] = 18;
|
|
||||||
instances["Wailing Caverns"] = 18;
|
|
||||||
instances["Shadowfang Keep"] = 25;
|
|
||||||
instances["Blackfathom Deeps"] = 20;
|
|
||||||
instances["Stockade"] = 20;
|
|
||||||
instances["Gnomeregan"] = 35;
|
|
||||||
instances["Razorfen Kraul"] = 35;
|
|
||||||
instances["Maraudon"] = 50;
|
|
||||||
instances["Scarlet Monestery"] = 40;
|
|
||||||
instances["Uldaman"] = 45;
|
|
||||||
instances["Dire Maul"] = 58;
|
|
||||||
instances["Scholomance"] = 59;
|
|
||||||
instances["Razorfen Downs"] = 40;
|
|
||||||
instances["Strathholme"] = 59;
|
|
||||||
instances["Zul'Farrak"] = 45;
|
|
||||||
instances["Blackrock Depths"] = 55;
|
|
||||||
instances["Temple of Atal'Hakkar"] = 55;
|
|
||||||
instances["Lower Blackrock Spire"] = 57;
|
|
||||||
|
|
||||||
instances["Hellfire Citidel"] = 65;
|
|
||||||
instances["Coilfang Reservoir"] = 65;
|
|
||||||
instances["Auchindoun"] = 65;
|
|
||||||
instances["Cavens of Time"] = 68;
|
|
||||||
instances["Tempest Keep"] = 69;
|
|
||||||
instances["Magister's Terrace"] = 70;
|
|
||||||
|
|
||||||
instances["Utgarde Keep"] = 75;
|
|
||||||
instances["The Nexus"] = 75;
|
|
||||||
instances["Ahn'kahet: The Old Kingdom"] = 75;
|
|
||||||
instances["Azjol-Nerub"] = 75;
|
|
||||||
instances["Drak'Tharon Keep"] = 75;
|
|
||||||
instances["Violet Hold"] = 80;
|
|
||||||
instances["Gundrak"] = 77;
|
|
||||||
instances["Halls of Stone"] = 77;
|
|
||||||
instances["Halls of Lightning"] = 77;
|
|
||||||
instances["Oculus"] = 77;
|
|
||||||
instances["Utgarde Pinnacle"] = 77;
|
|
||||||
instances["Trial of the Champion"] = 80;
|
|
||||||
instances["Forge of Souls"] = 80;
|
|
||||||
instances["Pit of Saron"] = 80;
|
|
||||||
instances["Halls of Reflection"] = 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> allowedInstances;
|
|
||||||
for (const auto& instance : instances)
|
|
||||||
{
|
|
||||||
if (bot->GetLevel() >= instance.second)
|
|
||||||
allowedInstances.push_back(instance.first);
|
|
||||||
}
|
|
||||||
if (allowedInstances.empty()) return;
|
|
||||||
|
|
||||||
std::map<std::string, std::string> placeholders;
|
|
||||||
placeholders["%role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot));
|
|
||||||
|
|
||||||
std::ostringstream itemout;
|
|
||||||
//itemout << "|c00b000b0" << allowedInstances[urand(0, allowedInstances.size() - 1)] << "|r";
|
|
||||||
itemout << allowedInstances[urand(0, allowedInstances.size() - 1)];
|
|
||||||
placeholders["%instance"] = itemout.str();
|
|
||||||
|
|
||||||
spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint32> SuggestWhatToDoAction::GetIncompletedQuests()
|
std::vector<uint32> SuggestWhatToDoAction::GetIncompletedQuests()
|
||||||
{
|
{
|
||||||
std::vector<uint32> result;
|
std::vector<uint32> result;
|
||||||
@@ -310,48 +243,46 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b
|
|||||||
ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i);
|
ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i);
|
||||||
if (!channel) continue;
|
if (!channel) continue;
|
||||||
|
|
||||||
for (AreaTableEntry const* current_zone : sAreaTableStore)
|
AreaTableEntry const* current_zone = GetAreaEntryByAreaID(bot->GetAreaId());
|
||||||
|
if (!current_zone)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// combine full channel name
|
||||||
|
char channelName[100];
|
||||||
|
Channel* chn = nullptr;
|
||||||
|
if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0)
|
||||||
{
|
{
|
||||||
if (!current_zone)
|
std::string chanName = channel->pattern[_dbc_locale];
|
||||||
continue;
|
chn = cMgr->GetChannel(chanName, bot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]);
|
||||||
|
chn = cMgr->GetChannel(channelName, bot);
|
||||||
|
}
|
||||||
|
if (!chn)
|
||||||
|
continue;
|
||||||
|
// skip world chat here
|
||||||
|
if (chn->GetName() == "World")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (flags != 0 && chn->GetFlags() != flags)
|
||||||
|
continue;
|
||||||
|
|
||||||
// combine full channel name
|
// skip local defense
|
||||||
char channelName[100];
|
if (chn->GetChannelId() == 22)
|
||||||
Channel* chn = nullptr;
|
continue;
|
||||||
if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0)
|
|
||||||
{
|
|
||||||
std::string chanName = channel->pattern[_dbc_locale];
|
|
||||||
chn = cMgr->GetChannel(chanName, bot);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]);
|
|
||||||
chn = cMgr->GetChannel(channelName, bot);
|
|
||||||
}
|
|
||||||
if (!chn)
|
|
||||||
continue;
|
|
||||||
// skip world chat here
|
|
||||||
if (chn->GetName() == "World")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (flags != 0 && chn->GetFlags() != flags)
|
// no filter, pick several options
|
||||||
continue;
|
if (flags == CHANNEL_FLAG_NONE)
|
||||||
|
{
|
||||||
// skip local defense
|
channelNames.push_back(chn->GetName());
|
||||||
//if (chn->GetFlags() == 0x18)
|
}
|
||||||
// continue;
|
else
|
||||||
|
{
|
||||||
// no filter, pick several options
|
if (!bot->IsInChannel(chn))
|
||||||
if (flags == CHANNEL_FLAG_NONE)
|
chn->JoinChannel(bot, "");
|
||||||
{
|
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
||||||
channelNames.push_back(chn->GetName());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
|
||||||
LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!channelNames.empty())
|
if (!channelNames.empty())
|
||||||
@@ -359,8 +290,10 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b
|
|||||||
std::string randomName = channelNames[urand(0, channelNames.size() - 1)];
|
std::string randomName = channelNames[urand(0, channelNames.size() - 1)];
|
||||||
if (Channel* chn = cMgr->GetChannel(randomName, bot))
|
if (Channel* chn = cMgr->GetChannel(randomName, bot))
|
||||||
{
|
{
|
||||||
|
if (!bot->IsInChannel(chn))
|
||||||
|
chn->JoinChannel(bot, "");
|
||||||
|
|
||||||
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
||||||
LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,6 +343,78 @@ class FindTradeItemsVisitor : public IterateItemsVisitor
|
|||||||
uint32 quality;
|
uint32 quality;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest dungeon")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SuggestDungeonAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
if (instances.empty())
|
||||||
|
{
|
||||||
|
instances["Ragefire Chasm"] = 15;
|
||||||
|
instances["Deadmines"] = 18;
|
||||||
|
instances["Wailing Caverns"] = 18;
|
||||||
|
instances["Shadowfang Keep"] = 25;
|
||||||
|
instances["Blackfathom Deeps"] = 20;
|
||||||
|
instances["Stockade"] = 20;
|
||||||
|
instances["Gnomeregan"] = 35;
|
||||||
|
instances["Razorfen Kraul"] = 35;
|
||||||
|
instances["Maraudon"] = 50;
|
||||||
|
instances["Scarlet Monestery"] = 40;
|
||||||
|
instances["Uldaman"] = 45;
|
||||||
|
instances["Dire Maul"] = 58;
|
||||||
|
instances["Scholomance"] = 59;
|
||||||
|
instances["Razorfen Downs"] = 40;
|
||||||
|
instances["Strathholme"] = 59;
|
||||||
|
instances["Zul'Farrak"] = 45;
|
||||||
|
instances["Blackrock Depths"] = 55;
|
||||||
|
instances["Temple of Atal'Hakkar"] = 55;
|
||||||
|
instances["Lower Blackrock Spire"] = 57;
|
||||||
|
|
||||||
|
instances["Hellfire Citidel"] = 65;
|
||||||
|
instances["Coilfang Reservoir"] = 65;
|
||||||
|
instances["Auchindoun"] = 65;
|
||||||
|
instances["Cavens of Time"] = 68;
|
||||||
|
instances["Tempest Keep"] = 69;
|
||||||
|
instances["Magister's Terrace"] = 70;
|
||||||
|
|
||||||
|
instances["Utgarde Keep"] = 75;
|
||||||
|
instances["The Nexus"] = 75;
|
||||||
|
instances["Ahn'kahet: The Old Kingdom"] = 75;
|
||||||
|
instances["Azjol-Nerub"] = 75;
|
||||||
|
instances["Drak'Tharon Keep"] = 75;
|
||||||
|
instances["Violet Hold"] = 80;
|
||||||
|
instances["Gundrak"] = 77;
|
||||||
|
instances["Halls of Stone"] = 77;
|
||||||
|
instances["Halls of Lightning"] = 77;
|
||||||
|
instances["Oculus"] = 77;
|
||||||
|
instances["Utgarde Pinnacle"] = 77;
|
||||||
|
instances["Trial of the Champion"] = 80;
|
||||||
|
instances["Forge of Souls"] = 80;
|
||||||
|
instances["Pit of Saron"] = 80;
|
||||||
|
instances["Halls of Reflection"] = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> allowedInstances;
|
||||||
|
for (const auto& instance : instances)
|
||||||
|
{
|
||||||
|
if (bot->GetLevel() >= instance.second)
|
||||||
|
allowedInstances.push_back(instance.first);
|
||||||
|
}
|
||||||
|
if (allowedInstances.empty()) return false;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> placeholders;
|
||||||
|
placeholders["%role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot));
|
||||||
|
|
||||||
|
std::ostringstream itemout;
|
||||||
|
//itemout << "|c00b000b0" << allowedInstances[urand(0, allowedInstances.size() - 1)] << "|r";
|
||||||
|
itemout << allowedInstances[urand(0, allowedInstances.size() - 1)];
|
||||||
|
placeholders["%instance"] = itemout.str();
|
||||||
|
|
||||||
|
spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade")
|
SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ class SuggestWhatToDoAction : public InventoryAction
|
|||||||
std::vector<uint32> GetIncompletedQuests();
|
std::vector<uint32> GetIncompletedQuests();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::map<std::string, uint8> instances;
|
|
||||||
static std::map<std::string, uint8> factions;
|
static std::map<std::string, uint8> factions;
|
||||||
const int32_t _dbc_locale;
|
const int32_t _dbc_locale;
|
||||||
};
|
};
|
||||||
@@ -44,4 +43,15 @@ class SuggestTradeAction : public SuggestWhatToDoAction
|
|||||||
bool isUseful() override { return true; }
|
bool isUseful() override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SuggestDungeonAction : public SuggestWhatToDoAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SuggestDungeonAction(PlayerbotAI* botAI);
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override { return true; }
|
||||||
|
private:
|
||||||
|
static std::map<std::string, uint8> instances;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user