Chat refactor quests and generic + suggest

This commit is contained in:
antony
2024-08-01 14:13:00 +02:00
parent 79d0f3fd28
commit 142f2ad212
19 changed files with 1855 additions and 304 deletions

View File

@@ -6,7 +6,7 @@
#include "Event.h"
#include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "GuildMgr.h"
#include "BroadcastHelper.h"
bool AutoLearnSpellAction::Execute(Event event)
{
@@ -30,18 +30,12 @@ bool AutoLearnSpellAction::Execute(Event event)
void AutoLearnSpellAction::LearnSpells(std::ostringstream* out)
{
BroadcastHelper::BroadcastLevelup(botAI, bot);
if (sPlayerbotAIConfig->autoLearnTrainerSpells)
LearnTrainerSpells(out);
if (sPlayerbotAIConfig->autoLearnQuestSpells)
LearnQuestSpells(out);
if (sPlayerbotAIConfig->randomBotGuildTalk)
{
std::map<std::string, std::string> args;
args["%my_level"] = std::to_string(bot->GetLevel());
botAI->SayToGuild(BOT_TEXT2("broadcast_levelup_generic", args));
}
}
void AutoLearnSpellAction::LearnTrainerSpells(std::ostringstream* out)

View File

@@ -7,6 +7,7 @@
#include "GuildPackets.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include "BroadcastHelper.h"
Player* GuidManageAction::GetPlayer(Event event)
{
@@ -167,6 +168,7 @@ bool GuildManageNearbyAction::Execute(Event event)
{
if (!urand(0, 10))
{
BroadcastHelper::BroadcastGuildMemberPromotion(botAI, bot, player);
botAI->DoSpecificAction("guild promote", Event("guild management", guid), true);
continue;

View File

@@ -7,6 +7,7 @@
#include "GuildMgr.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include "BroadcastHelper.h"
bool InviteToGroupAction::Execute(Event event)
{
@@ -76,6 +77,26 @@ bool InviteNearbyToGroupAction::Execute(Event event)
if (sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->sightDistance)
continue;
Group* group = bot->GetGroup();
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
if (!botAI->HasActivePlayerMaster())
{
if (guild && bot->GetGuildId() == player->GetGuildId())
{
BroadcastHelper::BroadcastGuildGroupOrRaidInvite(botAI, bot, player, group);
}
else
{
std::map<std::string, std::string> placeholders;
placeholders["%player"] = player->GetName();
if (group && group->isRaidGroup())
bot->Say(BOT_TEXT2("join_raid", placeholders), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH));
else
bot->Say(BOT_TEXT2("join_group", placeholders), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH));
}
}
return Invite(player);
}
@@ -125,6 +146,8 @@ std::vector<Player*> InviteGuildToGroupAction::getGuildMembers()
bool InviteGuildToGroupAction::Execute(Event event)
{
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
for (auto& member : getGuildMembers())
{
Player* player = member;
@@ -165,6 +188,8 @@ bool InviteGuildToGroupAction::Execute(Event event)
if (!botAI && sServerFacade->GetDistance2d(bot, player) > sPlayerbotAIConfig->sightDistance)
continue;
Group* group = bot->GetGroup();
BroadcastHelper::BroadcastGuildGroupOrRaidInvite(botAI, bot, player, group);
return Invite(player);
}

View File

@@ -13,6 +13,7 @@
#include "Playerbots.h"
#include "ServerFacade.h"
#include "GuildMgr.h"
#include "BroadcastHelper.h"
bool LootAction::Execute(Event event)
{
@@ -417,19 +418,7 @@ bool StoreLootAction::Execute(Event event)
if (proto->Quality >= ITEM_QUALITY_RARE && !urand(0, 1) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT))
botAI->PlayEmote(TEXT_EMOTE_CHEER);
if (sPlayerbotAIConfig->randomBotGuildTalk && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE)
{
std::map<std::string, std::string> args;
args["%item"] = chat->FormatItem(proto);
botAI->SayToGuild(BOT_TEXT2("loot_command", args));
}
// std::ostringstream out;
// out << "Looting " << chat->FormatItem(proto);
// botAI->TellMasterNoFacing(out.str());
//ItemUsage usage = AI_VALUE2(ItemUsage, "item usage", proto->ItemId);
//LOG_ERROR("playerbots", "Bot {} is looting {} {} for usage {}.", bot->GetName().c_str(), itemcount, proto->Name1.c_str(), usage);
BroadcastHelper::BroadcastLootingItem(botAI, bot, proto);
}
AI_VALUE(LootObjectStack*, "available loot")->Remove(guid);

View File

@@ -10,64 +10,6 @@
bool QueryItemUsageAction::Execute(Event event)
{
if (!GetMaster() && !sPlayerbotAIConfig->randomBotSayWithoutMaster)
return false;
if (!sPlayerbotAIConfig->sayWhenCollectingItems)
return false;
WorldPacket& data = event.getPacket();
if (!data.empty())
{
data.rpos(0);
ObjectGuid guid;
data >> guid;
if (guid != bot->GetGUID())
return false;
uint32 received;
uint32 created;
uint32 isShowChatMessage;
uint32 notUsed;
uint32 itemId;
uint32 suffixFactor;
uint32 itemRandomPropertyId;
uint32 count;
uint32 invCount;
uint8 bagSlot;
data >> received; // 0=looted, 1=from npc
data >> created; // 0=received, 1=created
data >> isShowChatMessage; // IsShowChatMessage
data >> bagSlot; // item slot, but when added to stack: 0xFFFFFFFF
data >> notUsed;
data >> itemId;
data >> suffixFactor;
data >> itemRandomPropertyId;
data >> count;
// data >> invCount; // [-ZERO] count of items in inventory
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
if (!item)
return false;
bot->Say(QueryItem(item, count, GetCount(item)), LANG_UNIVERSAL);
return true;
}
std::string const text = event.getParam();
ItemIds items = chat->parseItems(text);
for (uint32 itemId : items)
{
ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId);
if (!item)
continue;
botAI->TellMaster(QueryItem(item, 0, GetCount(item)));
}
return true;
}

View File

@@ -8,6 +8,7 @@
#include "Playerbots.h"
#include "ReputationMgr.h"
#include "ServerFacade.h"
#include "BroadcastHelper.h"
bool QuestAction::Execute(Event event)
{
@@ -226,6 +227,7 @@ bool QuestAction::AcceptQuest(Quest const* quest, ObjectGuid questGiver)
if (bot->GetQuestStatus(questId) != QUEST_STATUS_NONE && bot->GetQuestStatus(questId) != QUEST_STATUS_REWARDED)
{
BroadcastHelper::BroadcastQuestAccepted(botAI, bot, quest);
out << "Accepted " << chat->FormatQuest(quest);
botAI->TellMaster(out);
return true;
@@ -253,13 +255,17 @@ bool QuestUpdateCompleteAction::Execute(Event event)
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId);
if (qInfo)
{
const std::string text_quest = ChatHelper::FormatQuest(qInfo);
std::map<std::string, std::string> placeholders;
const auto format = ChatHelper::FormatQuest(qInfo);
placeholders["%quest_link"] = format;
if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_COMBAT))
{
LOG_INFO("playerbots", "{} => Quest [ {} ] completed", bot->GetName(), qInfo->GetTitle());
bot->Say("Quest [ " + text_quest + " ] completed", LANG_UNIVERSAL);
bot->Say("Quest [ " + format + " ] completed", LANG_UNIVERSAL);
}
botAI->TellMasterNoFacing("Quest completed " + text_quest);
botAI->TellMasterNoFacing("Quest completed " + format);
BroadcastHelper::BroadcastQuestUpdateComplete(botAI, bot, qInfo);
}
return true;
@@ -276,9 +282,38 @@ bool QuestUpdateAddKillAction::Execute(Event event)
uint32 entry, questId, available, required;
p >> questId >> entry >> available >> required;
std::stringstream ss;
ss << "Update progression kill questid {" << std::to_string(questId) << "} {" << std::to_string(available) << "} / {" << std::to_string(required) << "}";
botAI->TellMasterNoFacing(ss.str());
const Quest* qInfo = sObjectMgr->GetQuestTemplate(questId);
if (qInfo && (entry & 0x80000000))
{
entry &= 0x7FFFFFFF;
const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry);
if (info)
BroadcastHelper::BroadcastQuestUpdateAddKill(botAI, bot, qInfo, available, required, info->name);
}
else if (qInfo)
{
CreatureTemplate const* info = sObjectMgr->GetCreatureTemplate(entry);
if (info)
{
BroadcastHelper::BroadcastQuestUpdateAddKill(botAI, bot, qInfo, available, required, info->Name);
}
}
else
{
std::map<std::string, std::string> placeholders;
placeholders["%quest_id"] = questId;
placeholders["%available"] = available;
placeholders["%required"] = required;
if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_COMBAT) || botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT))
{
LOG_INFO("playerbots", "{} => {}", bot->GetName(), BOT_TEXT2("%available/%required for questId: %quest_id", placeholders));
botAI->Say(BOT_TEXT2("%available/%required for questId: %quest_id", placeholders));
}
botAI->TellMasterNoFacing(BOT_TEXT2("%available/%required for questId: %quest_id", placeholders));
}
return false;
}
@@ -292,11 +327,29 @@ bool QuestUpdateAddItemAction::Execute(Event event)
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
auto const* itemPrototype = sObjectMgr->GetItemTemplate(itemId);
if (itemPrototype)
{
std::map<std::string, std::string> placeholders;
placeholders["%item_link"] = botAI->GetChatHelper()->FormatItem(itemPrototype);
uint32 availableItemsCount = botAI->GetInventoryItemsCountWithId(itemId);
placeholders["%quest_obj_available"] = std::to_string(availableItemsCount);
std::stringstream ss;
ss << "Update progression itemid {" << std::to_string(itemId) << "} count: {" << std::to_string(count) << "}";
botAI->TellMasterNoFacing(ss.str());
for (const auto& pair : botAI->GetCurrentQuestsRequiringItemId(itemId))
{
placeholders["%quest_link"] = chat->FormatQuest(pair.first);
uint32 requiredItemsCount = pair.second;
placeholders["%quest_obj_required"] = std::to_string(requiredItemsCount);
if (botAI->HasStrategy("debug quest", BotState::BOT_STATE_COMBAT) || botAI->HasStrategy("debug quest", BotState::BOT_STATE_NON_COMBAT))
{
const auto text = BOT_TEXT2("%quest_link - %item_link %quest_obj_available/%quest_obj_required", placeholders);
botAI->Say(text);
LOG_INFO("playerbots", "{} => {}", bot->GetName(), text);
}
BroadcastHelper::BroadcastQuestUpdateAddItem(botAI, bot, pair.first, availableItemsCount, requiredItemsCount, itemPrototype);
}
}
return false;
}
@@ -320,7 +373,10 @@ bool QuestUpdateFailedTimerAction::Execute(Event event)
if (qInfo)
{
botAI->TellMaster("Failed timer for " + botAI->GetChatHelper()->FormatQuest(qInfo) +", abandoning");
std::map<std::string, std::string> placeholders;
placeholders["%quest_link"] = botAI->GetChatHelper()->FormatQuest(qInfo);
botAI->TellMaster(BOT_TEXT2("Failed timer for %quest_link, abandoning", placeholders));
BroadcastHelper::BroadcastQuestUpdateFailedTimer(botAI, bot, qInfo);
}
else
{

View File

@@ -122,7 +122,7 @@ bool SayAction::isUseful()
return (time(nullptr) - lastSaid) > 30;
}
void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name)
void ChatReplyAction::ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name)
{
ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand
std::string respondsText = "";
@@ -165,7 +165,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32
}
//toxic links
if (msg.starts_with("gnomes")
if (msg.starts_with(sPlayerbotAIConfig->toxicLinksPrefix)
&& (GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg).size() > 0 || GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllQuestIds(msg).size() > 0))
{
HandleToxicLinksReply(bot, chatChannelSource, msg, name);
@@ -179,10 +179,11 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32
return;
}
SendGeneralResponse(bot, chatChannelSource, GenerateReplyMessage(bot, msg, guid1, name), name);
auto messageRepy = GenerateReplyMessage(bot, msg, guid1, name);
SendGeneralResponse(bot, chatChannelSource, messageRepy, name);
}
bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name)
bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
{
std::map<std::string, std::string> placeholders;
const auto thunderfury = sObjectMgr->GetItemTemplate(19019);
@@ -208,17 +209,164 @@ bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chat
return true;
}
bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name)
bool ChatReplyAction::HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
{
//quests
std::vector<uint32> incompleteQuests;
for (uint16 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
{
uint32 questId = bot->GetQuestSlotQuestId(slot);
if (!questId)
continue;
QuestStatus status = bot->GetQuestStatus(questId);
if (status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_NONE)
incompleteQuests.push_back(questId);
}
//items
std::vector<Item*> botItems = GET_PLAYERBOT_AI(bot)->GetInventoryAndEquippedItems();
std::map<std::string, std::string> placeholders;
placeholders["%random_inventory_item_link"] = botItems.size() > 0 ? GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatItem(botItems[rand() % botItems.size()]->GetTemplate()) : BOT_TEXT1("string_empty_link");
placeholders["%prefix"] = sPlayerbotAIConfig->toxicLinksPrefix;
if (incompleteQuests.size() > 0)
{
Quest const* quest = sObjectMgr->GetQuestTemplate(incompleteQuests[rand() % incompleteQuests.size()]);
placeholders["%random_taken_quest_or_item_link"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatQuest(quest);
}
else
{
placeholders["%random_taken_quest_or_item_link"] = placeholders["%random_inventory_item_link"];
}
placeholders["%my_role"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass());
AreaTableEntry const* current_area = GET_PLAYERBOT_AI(bot)->GetCurrentArea();
AreaTableEntry const* current_zone = GET_PLAYERBOT_AI(bot)->GetCurrentZone();
placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area");
placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area");
placeholders["%my_class"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass());
placeholders["%my_race"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatRace(bot->getRace());
placeholders["%my_level"] = std::to_string(bot->GetLevel());
switch (chatChannelSource)
{
case ChatChannelSource::SRC_WORLD:
{
GET_PLAYERBOT_AI(bot)->SayToWorld(BOT_TEXT2("suggest_toxic_links", placeholders));
break;
}
case ChatChannelSource::SRC_GENERAL:
{
GET_PLAYERBOT_AI(bot)->SayToChannel(BOT_TEXT2("suggest_toxic_links", placeholders), ChatChannelId::GENERAL);
break;
}
case ChatChannelSource::SRC_GUILD:
{
GET_PLAYERBOT_AI(bot)->SayToGuild(BOT_TEXT2("suggest_toxic_links", placeholders));
break;
}
}
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 60));
return true;
}
bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name)
bool ChatReplyAction::HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
{
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 60));
auto messageItemIds = GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllItemIds(msg);
if (messageItemIds.empty())
{
return false;
}
std::set<uint32> matchingItemIds;
for (auto messageItemId : messageItemIds)
{
if (GET_PLAYERBOT_AI(bot)->HasItemInInventory(messageItemId))
{
matchingItemIds.insert(messageItemId);
}
}
if (!matchingItemIds.empty())
{
std::map<std::string, std::string> placeholders;
placeholders["%other_name"] = name;
AreaTableEntry const* current_area = GET_PLAYERBOT_AI(bot)->GetCurrentArea();
AreaTableEntry const* current_zone = GET_PLAYERBOT_AI(bot)->GetCurrentZone();
placeholders["%area_name"] = current_area ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_area) : BOT_TEXT1("string_unknown_area");
placeholders["%zone_name"] = current_zone ? GET_PLAYERBOT_AI(bot)->GetLocalizedAreaName(current_zone) : BOT_TEXT1("string_unknown_area");
placeholders["%my_class"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->getClass());
placeholders["%my_race"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatRace(bot->getRace());
placeholders["%my_level"] = std::to_string(bot->GetLevel());
placeholders["%my_role"] = GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatClass(bot->GetSpec());
placeholders["%formatted_item_links"] = "";
for (auto matchingItemId : matchingItemIds)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(matchingItemId);
placeholders["%formatted_item_links"] += GET_PLAYERBOT_AI(bot)->GetChatHelper()->FormatItem(proto, GET_PLAYERBOT_AI(bot)->GetInventoryItemsCountWithId(matchingItemId));
placeholders["%formatted_item_links"] += " ";
}
switch (chatChannelSource)
{
case ChatChannelSource::SRC_WORLD:
{
//may reply to the same channel or whisper
if (urand(0, 1))
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders);
GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage);
}
else
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders);
GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name);
}
break;
}
case ChatChannelSource::SRC_GENERAL:
{
//may reply to the same channel or whisper
if (urand(0, 1))
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders);
GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL);
}
else
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders);
GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name);
}
break;
}
case ChatChannelSource::SRC_TRADE:
{
//may reply to the same channel or whisper
if (urand(0, 1))
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_channel", placeholders);
GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::TRADE);
}
else
{
std::string responseMessage = BOT_TEXT2("response_wtb_items_whisper", placeholders);
GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name);
}
break;
}
}
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 60));
}
return true;
}
bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name)
bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name)
{
auto messageQuestIds = GET_PLAYERBOT_AI(bot)->GetChatHelper()->ExtractAllQuestIds(msg);
@@ -303,7 +451,7 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh
return true;
}
bool ChatReplyAction::SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string responseMessage, std::string name)
bool ChatReplyAction::SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string& responseMessage, std::string& name)
{
// send responds
switch (chatChannelSource)
@@ -341,13 +489,11 @@ bool ChatReplyAction::SendGeneralResponse(Player* bot, ChatChannelSource chatCha
case ChatChannelSource::SRC_LOOKING_FOR_GROUP:
{
//do not reply to the chat
//may whisper
break;
}
case ChatChannelSource::SRC_GUILD_RECRUITMENT:
{
//do not reply to the chat
//may whisper
break;
}
case ChatChannelSource::SRC_WHISPER:
@@ -378,7 +524,7 @@ bool ChatReplyAction::SendGeneralResponse(Player* bot, ChatChannelSource chatCha
return true;
}
std::string ChatReplyAction::GenerateReplyMessage(Player* bot, std::string incomingMessage, uint32 guid1, std::string name)
std::string ChatReplyAction::GenerateReplyMessage(Player* bot, std::string& incomingMessage, uint32& guid1, std::string& name)
{
ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand

View File

@@ -32,12 +32,12 @@ public:
virtual bool Execute(Event event) { return true; }
bool isUseful() { return true; }
static void ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name);
static bool HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name);
static bool HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name);
static bool HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name);
static bool HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name);
static bool SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string responseMessage, std::string name);
static std::string GenerateReplyMessage(Player* bot, std::string incomingMessage, uint32 guid1, std::string name);
static void ChatReplyDo(Player* bot, uint32& type, uint32& guid1, uint32& guid2, std::string& msg, std::string& chanName, std::string& name);
static bool HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
static bool HandleToxicLinksReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
static bool HandleWTBItemsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
static bool HandleLFGQuestsReply(Player* bot, ChatChannelSource chatChannelSource, std::string& msg, std::string& name);
static bool SendGeneralResponse(Player* bot, ChatChannelSource chatChannelSource, std::string& responseMessage, std::string& name);
static std::string GenerateReplyMessage(Player* bot, std::string& incomingMessage, uint32& guid1, std::string& name);
};
#endif

View File

@@ -11,8 +11,8 @@
#include "ChatHelper.h"
#include "Playerbots.h"
#include "PlayerbotTextMgr.h"
#include "GuildMgr.h"
#include "Config.h"
#include "BroadcastHelper.h"
#include <functional>
@@ -36,6 +36,8 @@ SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string con
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindReputation, this));
suggestions.push_back(std::bind(&SuggestWhatToDoAction::something, this));
suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindMaterials, this));
suggestions.push_back(std::bind(&SuggestWhatToDoAction::somethingToxic, this));
suggestions.push_back(std::bind(&SuggestWhatToDoAction::toxicLinks, this));
}
bool SuggestWhatToDoAction::isUseful()
@@ -85,15 +87,7 @@ void SuggestWhatToDoAction::specificQuest()
if (quests.empty())
return;
uint32 index = rand() % quests.size();
Quest const* quest = sObjectMgr->GetQuestTemplate(quests[index]);
std::map<std::string, std::string> placeholders;
placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot));
placeholders["%quest"] = chat->FormatQuest(quest);
spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : 0, !urand(0, 2), !urand(0, 3));
BroadcastHelper::BroadcastSuggestQuest(botAI, quests, bot);
}
void SuggestWhatToDoAction::grindMaterials()
@@ -187,123 +181,34 @@ void SuggestWhatToDoAction::grindReputation()
levels.push_back("exalted");
std::vector<std::string> allowedFactions;
for (const auto& i : factions)
for (auto it : factions)
{
if (bot->GetLevel() >= i.second)
allowedFactions.push_back(i.first);
if ((int)bot->GetLevel() >= it.second) allowedFactions.push_back(it.first);
}
if (allowedFactions.empty())
return;
std::map<std::string, std::string> placeholders;
placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot));
placeholders["%level"] = levels[urand(0, 2)];
if (allowedFactions.empty()) return;
std::ostringstream rnd;
rnd << urand(1, 5) << "K";
placeholders["%rndK"] = rnd.str();
std::ostringstream itemout;
// itemout << "|c004040b0" << allowedFactions[urand(0, allowedFactions.size() - 1)] << "|r";
itemout << allowedFactions[urand(0, allowedFactions.size() - 1)];
placeholders["%faction"] = itemout.str();
spam(BOT_TEXT2("suggest_faction", placeholders), eTalkType::General, true);
BroadcastHelper::BroadcastSuggestGrindReputation(botAI, levels, allowedFactions, bot);
}
void SuggestWhatToDoAction::something()
{
std::map<std::string, std::string> placeholders;
placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot));
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(bot->GetMap()->GetZoneId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()));
if (!zone) return;
std::ostringstream out;
// out << "|cffb04040" << entry->area_name[0] << "|r";
out << zone->area_name[_dbc_locale];
placeholders["%zone"] = out.str();
spam(BOT_TEXT2("suggest_something", placeholders), urand(0, 1) ? eTalkType::General : 0, !urand(0, 2), !urand(0, 3));
BroadcastHelper::BroadcastSuggestSomething(botAI, bot);
}
void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, bool guild)
void SuggestWhatToDoAction::somethingToxic()
{
if (msg.empty())
return;
BroadcastHelper::BroadcastSuggestSomethingToxic(botAI, bot);
}
std::vector<std::string> channelNames;
ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId());
if (!cMgr)
return;
void SuggestWhatToDoAction::toxicLinks()
{
BroadcastHelper::BroadcastSuggestToxicLinks(botAI, bot);
}
AreaTableEntry const* zone = sAreaTableStore.LookupEntry(bot->GetMap()->GetZoneId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()));
if (!zone) return;
/*AreaTableEntry const* area = sAreaTableStore.LookupEntry(bot->GetMap()->GetAreaId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()));
if (!area) return;*/
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
{
ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i);
if (!channel) continue;
// combine full channel name
char channelName[100];
Channel* chn = nullptr;
if (channel->ChannelID == 24 || (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], 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;
// skip local defense and universal defense
if (chn->GetChannelId() == 22 || chn->GetChannelId() == 23)
continue;
// no filter, pick several options
if (flags == CHANNEL_FLAG_NONE)
{
channelNames.push_back(chn->GetName());
}
else
{
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
}
if (!channelNames.empty())
{
std::string randomName = channelNames[urand(0, channelNames.size() - 1)];
if (Channel* chn = cMgr->GetChannel(randomName, bot))
{
chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
}
}
if (worldChat)
{
if (Channel* worldChannel = cMgr->GetChannel("World", bot))
worldChannel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
}
}
if (sPlayerbotAIConfig->randomBotGuildTalk)
{
botAI->SayToGuild(msg);
}
void SuggestWhatToDoAction::thunderfury()
{
BroadcastHelper::BroadcastSuggestThunderfury(botAI, bot);
}
class FindTradeItemsVisitor : public IterateItemsVisitor
@@ -394,22 +299,14 @@ bool SuggestDungeonAction::Execute(Event event)
}
std::vector<std::string> allowedInstances;
for (const auto& instance : instances)
for (auto it : instances)
{
if (bot->GetLevel() >= instance.second)
allowedInstances.push_back(instance.first);
if (bot->GetLevel() >= it.second) allowedInstances.push_back(it.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, 3));
BroadcastHelper::BroadcastSuggestInstance(botAI, allowedInstances, bot);
return true;
}
@@ -469,11 +366,6 @@ bool SuggestTradeAction::Execute(Event event)
if (!price)
return false;
std::map<std::string, std::string> placeholders;
placeholders["%item"] = chat->FormatItem(proto, count);
placeholders["%gold"] = chat->formatMoney(price);
spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : 0, !urand(0, 2), urand(0, 5));
BroadcastHelper::BroadcastSuggestSell(botAI, proto, count, price, bot);
return true;
}

View File

@@ -24,8 +24,10 @@ class SuggestWhatToDoAction : public InventoryAction
void grindReputation();
void grindMaterials();
void something();
void spam(std::string msg, uint8 flags = 0, bool worldChat = false, bool guild = false);
void toxicLinks();
void somethingToxic();
void thunderfury();
std::vector<uint32> GetIncompletedQuests();
private:

View File

@@ -10,6 +10,7 @@
#include "Playerbots.h"
#include "QuestDef.h"
#include "WorldPacket.h"
#include "BroadcastHelper.h"
bool TalkToQuestGiverAction::ProcessQuest(Quest const* quest, Object* questGiver)
{
@@ -96,14 +97,19 @@ bool TalkToQuestGiverAction::TurnInQuest(Quest const* quest, Object* questGiver,
void TalkToQuestGiverAction::RewardNoItem(Quest const* quest, Object* questGiver, std::ostringstream& out)
{
std::map<std::string, std::string> args;
args["%quest"] = chat->FormatQuest(quest);
if (bot->CanRewardQuest(quest, false))
{
out << BOT_TEXT2("quest_status_completed", args);
BroadcastHelper::BroadcastQuestTurnedIn(botAI, bot, quest);
bot->RewardQuest(quest, 0, questGiver, false);
out << "Completed";
}
else
{
out << "|cffff0000Unable to turn in|r";
out << BOT_TEXT2("quest_status_unable_to_complete", args);
}
}
@@ -111,15 +117,19 @@ void TalkToQuestGiverAction::RewardSingleItem(Quest const* quest, Object* questG
{
int index = 0;
ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[index]);
std::map<std::string, std::string> args;
args["%quest"] = chat->FormatQuest(quest);
args["%item"] = chat->FormatItem(item);
if (bot->CanRewardQuest(quest, index, false))
{
out << BOT_TEXT2("quest_status_complete_single_reward", args);
BroadcastHelper::BroadcastQuestTurnedIn(botAI, bot, quest);
bot->RewardQuest(quest, index, questGiver, true);
out << "Rewarded " << chat->FormatItem(item);
}
else
{
out << "|cffff0000Unable to turn in:|r, reward: " << chat->FormatItem(item);
out << BOT_TEXT2("quest_status_unable_to_complete", args);
}
}

View File

@@ -6,7 +6,7 @@
#include "Event.h"
#include "PlayerbotAIConfig.h"
#include "Playerbots.h"
#include "GuildMgr.h"
#include "BroadcastHelper.h"
bool XpGainAction::Execute(Event event)
{
@@ -33,19 +33,10 @@ bool XpGainAction::Execute(Event event)
p >> groupBonus; // 8 group bonus
}
if (sPlayerbotAIConfig->randomBotGuildTalk && bot->GetGuildId() && urand(0, 10))
Creature* creature = botAI->GetCreature(guid);
if (creature && !creature->GetMap()->IsDungeon())
{
Creature* creature = botAI->GetCreature(guid);
if (creature && (creature->isElite() || creature->isWorldBoss() || creature->GetLevel() > 61 || creature->GetLevel() > bot->GetLevel() + 4))
{
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
if (guild)
{
std::map<std::string, std::string> args;
args["%victim_name"] = creature->GetName();
botAI->SayToGuild(BOT_TEXT2("broadcast_killed_rare", args));
}
}
BroadcastHelper::BroadcastKill(botAI, bot, creature);
}
Unit* victim = nullptr;