Rewrite bot texts

This commit is contained in:
郑佩茹
2022-09-26 17:20:59 -06:00
parent 660fd2a0c1
commit b2821d7f3a
18 changed files with 1163 additions and 320 deletions

View File

@@ -5,125 +5,26 @@
#include "SayAction.h"
#include "Event.h"
#include "Playerbots.h"
std::map<std::string, std::vector<std::string>> SayAction::stringTable;
std::map<std::string, uint32> SayAction::probabilityTable;
#include "PlayerbotTextMgr.h"
#include "ChannelMgr.h"
#include "GuildMgr.h"
#include <regex>
SayAction::SayAction(PlayerbotAI* botAI) : Action(botAI, "say"), Qualified()
{
}
void replaceAll(std::string& str, std::string const from, std::string const to)
{
if (from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
bool SayAction::Execute(Event event)
{
if (stringTable.empty())
{
if (PreparedQueryResult result = PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_SPEECH)))
{
do
{
Field* fields = result->Fetch();
std::string const name = fields[0].Get<std::string>();
std::string text = fields[1].Get<std::string>();
std::string const type = fields[2].Get<std::string>();
if (type == "yell")
text = "/y " + text;
if (!text.empty() && text != "")
stringTable[name].push_back(std::move(text));
}
while (result->NextRow());
}
}
if (probabilityTable.empty())
{
if (PreparedQueryResult result = PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_SPEECH_PROBABILITY)))
{
do
{
Field* fields = result->Fetch();
std::string const name = fields[0].Get<std::string>();
uint32 probability = fields[1].Get<uint32>();
probabilityTable[name] = probability;
}
while (result->NextRow());
}
}
std::vector<std::string>& strings = stringTable[qualifier];
if (strings.empty())
return false;
time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier);
uint32 nextTime = time(nullptr) + urand(1, 30);
botAI->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime);
if (Group* group = bot->GetGroup())
{
std::vector<Player*> members;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (PlayerbotAI* memberAi = GET_PLAYERBOT_AI(member))
members.push_back(member);
}
uint32 count = members.size();
if (count > 1)
{
for (uint32 i = 0; i < count * 5; i++)
{
uint32 i1 = urand(0, count - 1);
uint32 i2 = urand(0, count - 1);
Player* item = members[i1];
members[i1] = members[i2];
members[i2] = item;
}
}
uint32 index = 0;
for (Player* player : members)
{
PlayerbotAI* memberAi = GET_PLAYERBOT_AI(player);
memberAi->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime + (20 * ++index) + urand(1, 15));
}
}
uint32 probability = probabilityTable[qualifier];
if (!probability)
probability = 100;
if (urand(0, 100) >= probability)
return false;
uint32 idx = urand(0, strings.size() - 1);
std::string text = strings[idx];
std::string text = "";
std::map<std::string, std::string> placeholders;
Unit* target = AI_VALUE(Unit*, "tank target");
if (!target)
target = AI_VALUE(Unit*, "current target");
if (target)
replaceAll(text, "<target>", target->GetName());
replaceAll(text, "<randomfaction>", IsAlliance(bot->getRace()) ? "Alliance" : "Horde");
// set replace strings
if (target) placeholders["<target>"] = target->GetName();
placeholders["<randomfaction>"] = IsAlliance(bot->getRace()) ? "Alliance" : "Horde";
if (qualifier == "low ammo" || qualifier == "no ammo")
{
if (Item* const pItem = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED))
@@ -131,11 +32,11 @@ bool SayAction::Execute(Event event)
switch (pItem->GetTemplate()->SubClass)
{
case ITEM_SUBCLASS_WEAPON_GUN:
replaceAll(text, "<ammo>", "bullets");
placeholders["<ammo>"] = "bullets";
break;
case ITEM_SUBCLASS_WEAPON_BOW:
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
replaceAll(text, "<ammo>", "arrows");
placeholders["<ammo>"] = "arrows";
break;
}
}
@@ -144,9 +45,53 @@ bool SayAction::Execute(Event event)
if (bot->GetMap())
{
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(bot->GetAreaId()))
replaceAll(text, "<subzone>", area->area_name[0]);
placeholders["<subzone>"] = area->area_name[0];
}
// set delay before next say
time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier);
uint32 nextTime = time(nullptr) + urand(1, 30);
botAI->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime);
Group* group = bot->GetGroup();
if (group)
{
std::vector<Player*> members;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
PlayerbotAI* memberAi = GET_PLAYERBOT_AI(member);
if (memberAi) members.push_back(member);
}
uint32 count = members.size();
if (count > 1)
{
for (uint32 i = 0; i < count * 5; i++)
{
int i1 = urand(0, count - 1);
int i2 = urand(0, count - 1);
Player* item = members[i1];
members[i1] = members[i2];
members[i2] = item;
}
}
int index = 0;
for (auto & member : members)
{
PlayerbotAI* memberAi = GET_PLAYERBOT_AI(member);
if (memberAi)
memberAi->GetAiObjectContext()->GetValue<time_t>("last said", qualifier)->Set(nextTime + (20 * ++index) + urand(1, 15));
}
}
// load text based on chance
if (!sPlayerbotTextMgr->GetBotText(qualifier, text, placeholders))
return false;
if (text.find("/y ") == 0)
bot->Yell(text.substr(3), (bot->GetTeamId() == TEAM_ALLIANCE ? LANG_COMMON : LANG_ORCISH));
else
@@ -163,3 +108,540 @@ bool SayAction::isUseful()
time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier);
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)
{
ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand
std::string respondsText = "";
// Chat Logic
int32 verb_pos = -1;
int32 verb_type = -1;
int32 is_quest = 0;
bool found = false;
std::stringstream text(msg);
std::string segment;
std::vector<std::string> word;
while (std::getline(text, segment, ' '))
{
word.push_back(segment);
}
for (uint32 i = 0; i < 15; i++)
{
if (word.size() < i)
word.push_back("");
}
if (msg.find("?") != std::string::npos)
is_quest = 1;
if (word[0].find("what") != std::string::npos)
is_quest = 2;
else if (word[0].find("who") != std::string::npos)
is_quest = 3;
else if (word[0] == "when")
is_quest = 4;
else if (word[0] == "where")
is_quest = 5;
else if (word[0] == "why")
is_quest = 6;
// Responds
for (uint32 i = 0; i < 8; i++)
{
// // blame gm with chat tag
// if (Player* plr = sObjectMgr->GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid1)))
// {
// if (plr->isGMChat())
// {
// replyType = REPLY_ADMIN_ABUSE;
// found = true;
// break;
// }
// }
//
if (word[i] == "hi" || word[i] == "hey" || word[i] == "hello" || word[i] == "wazzup")
{
replyType = REPLY_HELLO;
found = true;
break;
}
if (verb_type < 4)
{
if (word[i] == "am" || word[i] == "are" || word[i] == "is")
{
verb_pos = i;
verb_type = 2; // present
}
else if (word[i] == "will")
{
verb_pos = i;
verb_type = 3; // future
}
else if (word[i] == "was" || word[i] == "were")
{
verb_pos = i;
verb_type = 1; // past
}
else if (word[i] == "shut" || word[i] == "noob")
{
if (msg.find(bot->GetName()) == std::string::npos)
{
continue; // not react
uint32 rnd = urand(0, 2);
std::string msg = "";
if (rnd == 0)
msg = "sorry %s, ill shut up now";
if (rnd == 1)
msg = "ok ok %s";
if (rnd == 2)
msg = "fine, i wont talk to you anymore %s";
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
else
{
replyType = REPLY_GRUDGE;
found = true;
break;
}
}
}
}
if (verb_type < 4 && is_quest && !found)
{
switch (is_quest)
{
case 2:
{
uint32 rnd = urand(0, 3);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "i dont know what";
break;
case 1:
msg = "i dont know %s";
break;
case 2:
msg = "who cares";
break;
case 3:
msg = "afraid that was before i was around or paying attention";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 3:
{
uint32 rnd = urand(0, 4);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "nobody";
break;
case 1:
msg = "we all do";
break;
case 2:
msg = "perhaps its you, %s";
break;
case 3:
msg = "dunno %s";
break;
case 4:
msg = "is it me?";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 4:
{
uint32 rnd = urand(0, 6);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "soon perhaps %s";
break;
case 1:
msg = "probably later";
break;
case 2:
msg = "never";
break;
case 3:
msg = "what do i look like, a psychic?";
break;
case 4:
msg = "a few minutes, maybe an hour ... years?";
break;
case 5:
msg = "when? good question %s";
break;
case 6:
msg = "dunno %s";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 5:
{
uint32 rnd = urand(0, 6);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "really want me to answer that?";
break;
case 1:
msg = "on the map?";
break;
case 2:
msg = "who cares";
break;
case 3:
msg = "afk?";
break;
case 4:
msg = "none of your buisiness where";
break;
case 5:
msg = "yeah, where?";
break;
case 6:
msg = "dunno %s";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 6:
{
uint32 rnd = urand(0, 6);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "dunno %s";
break;
case 1:
msg = "why? just because %s";
break;
case 2:
msg = "why is the sky blue?";
break;
case 3:
msg = "dont ask me %s, im just a bot";
break;
case 4:
msg = "your asking the wrong person";
break;
case 5:
msg = "who knows?";
break;
case 6:
msg = "dunno %s";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
default:
{
switch (verb_type)
{
case 1:
{
uint32 rnd = urand(0, 3);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "its true, " + word[verb_pos + 1] + " " + word[verb_pos] + " " + word[verb_pos + 2] + " " + word[verb_pos + 3] + " " + word[verb_pos + 4] + " " + word[verb_pos + 4];
break;
case 1:
msg = "ya %s but thats in the past";
break;
case 2:
msg = "nah, but " + word[verb_pos + 1] + " will " + word[verb_pos + 3] + " again though %s";
break;
case 3:
msg = "afraid that was before i was around or paying attention";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 2:
{
uint32 rnd = urand(0, 6);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "its true, " + word[verb_pos + 1] + " " + word[verb_pos] + " " + word[verb_pos + 2] + " " + word[verb_pos + 3] + " " + word[verb_pos + 4] + " " + word[verb_pos + 5];
break;
case 1:
msg = "ya %s thats true";
break;
case 2:
msg = "maybe " + word[verb_pos + 1] + " " + word[verb_pos] + " " + word[verb_pos + 2] + " " + word[verb_pos + 3] + " " + word[verb_pos + 4] + " " + word[verb_pos + 5];
break;
case 3:
msg = "dunno %s";
break;
case 4:
msg = "i dont think so %s";
break;
case 5:
msg = "yes";
break;
case 6:
msg = "no";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 3:
{
uint32 rnd = urand(0, 8);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "dunno %s";
break;
case 1:
msg = "beats me %s";
break;
case 2:
msg = "how should i know %s";
break;
case 3:
msg = "dont ask me %s, im just a bot";
break;
case 4:
msg = "your asking the wrong person";
break;
case 5:
msg = "what do i look like, a psychic?";
break;
case 6:
msg = "sure %s";
break;
case 7:
msg = "i dont think so %s";
break;
case 8:
msg = "maybe";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
}
}
}
}
else if (!found)
{
switch (verb_type)
{
case 1:
{
uint32 rnd = urand(0, 2);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "yeah %s, the key word being " + word[verb_pos] + " " + word[verb_pos + 1];
break;
case 1:
msg = "ya %s but thats in the past";
break;
case 2:
msg = word[verb_pos - 1] + " will " + word[verb_pos + 1] + " again though %s";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 2:
{
uint32 rnd = urand(0, 2);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "%s, what do you mean " + word[verb_pos + 1] + "?";
break;
case 1:
msg = "%s, what is a " + word[verb_pos + 1] + "?";
break;
case 2:
msg = "yeah i know " + word[verb_pos - 1] + " is a " + word[verb_pos + 1];
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
case 3:
{
uint32 rnd = urand(0, 1);
std::string msg = "";
switch (rnd)
{
case 0:
msg = "are you sure thats going to happen %s?";
break;
case 1:
msg = "%s, what will happen %s?";
break;
case 2:
msg = "are you saying " + word[verb_pos - 1] + " will " + word[verb_pos + 1] + " " + word[verb_pos + 2] + " %s?";
break;
}
msg = std::regex_replace(msg, std::regex("%s"), name);
respondsText = msg;
found = true;
break;
}
}
}
if (!found)
{
// Name Responds
if (msg.find(bot->GetName()) != std::string::npos)
{
replyType = REPLY_NAME;
found = true;
}
else // Does not understand
{
replyType = REPLY_NOT_UNDERSTAND;
found = true;
}
}
// send responds
//
if (found)
{
// load text if needed
if (respondsText.empty())
{
respondsText = BOT_TEXT2(replyType, name);
}
const char* c = respondsText.c_str();
if (strlen(c) > 255)
return;
if (chanName == "World")
{
if (ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()))
{
std::string worldChan = "World";
if (Channel* chn = cMgr->GetJoinChannel(worldChan.c_str(), 0))
if (bot->GetTeamId() == TEAM_ALLIANCE)
chn->Say(bot->GetGUID(), c, LANG_COMMON);
else
chn->Say(bot->GetGUID(), c, LANG_ORCISH);
}
}
else
{
if (type == CHAT_MSG_WHISPER)
{
ObjectGuid receiver = sCharacterCache->GetCharacterGuidByName(name);
if (!receiver.IsPlayer())
{
return;
}
if (bot->GetTeamId() == TEAM_ALLIANCE)
{
bot->Whisper(c, LANG_COMMON, ObjectAccessor::FindPlayer(receiver));
}
else
{
bot->Whisper(c, LANG_ORCISH, ObjectAccessor::FindPlayer(receiver));
}
}
if (type == CHAT_MSG_SAY)
{
if (bot->GetTeamId() == TEAM_ALLIANCE)
bot->Say(respondsText, LANG_COMMON);
else
bot->Say(respondsText, LANG_ORCISH);
}
if (type == CHAT_MSG_YELL)
{
if (bot->GetTeamId() == TEAM_ALLIANCE)
bot->Yell(respondsText, LANG_COMMON);
else
bot->Yell(respondsText, LANG_ORCISH);
}
if (type == CHAT_MSG_GUILD)
{
if (!bot->GetGuildId())
return;
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
if (!guild)
return;
guild->BroadcastToGuild(bot->GetSession(), false, respondsText, LANG_UNIVERSAL);
}
}
GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(nullptr) + urand(5, 25));
}
}