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

@@ -27,6 +27,7 @@
#include "UpdateTime.h"
#include "Vehicle.h"
#include "GuildMgr.h"
#include "SayAction.h"
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems);
std::vector<std::string> split(std::string const s, char delim);
@@ -295,6 +296,27 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal
chatCommands.push(*i);
}
// chat replies
std::list<ChatQueuedReply> delayedResponses;
while (!chatReplies.empty())
{
ChatQueuedReply holder = chatReplies.front();
time_t checkTime = holder.m_time;
if (checkTime && time(0) < checkTime)
{
delayedResponses.push_back(holder);
chatReplies.pop();
continue;
}
ChatReplyAction::ChatReplyDo(bot, holder.m_type, holder.m_guid1, holder.m_guid2, holder.m_msg, holder.m_chanName, holder.m_name);
chatReplies.pop();
}
for (std::list<ChatQueuedReply>::iterator i = delayedResponses.begin(); i != delayedResponses.end(); ++i)
{
chatReplies.push(*i);
}
// logout if logout timer is ready or if instant logout is possible
if (bot->GetSession()->isLogingOut())
{
@@ -464,6 +486,9 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro
if (type == CHAT_MSG_ADDON)
return;
if (type == CHAT_MSG_SYSTEM)
return;
if (text.find(sPlayerbotAIConfig->commandSeparator) != std::string::npos)
{
std::vector<std::string> commands;
@@ -593,6 +618,9 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro
void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
{
if (packet.empty())
return;
switch (packet.GetOpcode())
{
case SMSG_SPELL_FAILURE:
@@ -631,13 +659,75 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
uint32 emoteId;
p.rpos(0);
p >> emoteId >> source;
if (!source.IsPlayer())
return;
else
if (source.IsPlayer())
botOutgoingPacketHandlers.AddPacket(packet);
return;
}
case SMSG_MESSAGECHAT: // do not react to self or if not ready to reply
{
if (!AllowActivity())
return;
WorldPacket p(packet);
if (!p.empty() && (p.GetOpcode() == SMSG_MESSAGECHAT || p.GetOpcode() == SMSG_GM_MESSAGECHAT))
{
p.rpos(0);
uint8 msgtype, chatTag;
uint32 lang, textLen, nameLen, unused;
ObjectGuid guid1, guid2;
std::string name, chanName, message;
p >> msgtype >> lang;
p >> guid1 >> unused;
if (guid1.IsEmpty() || p.size() > p.DEFAULT_SIZE)
return;
switch (msgtype)
{
case CHAT_MSG_CHANNEL:
p >> chanName;
[[fallthrough]];
case CHAT_MSG_SAY:
case CHAT_MSG_PARTY:
case CHAT_MSG_YELL:
case CHAT_MSG_WHISPER:
case CHAT_MSG_GUILD:
p >> guid2;
p >> textLen >> message >> chatTag;
if (guid1 != bot->GetGUID()) // do not reply to self
{
// try to always reply to real player
time_t lastChat = GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Get();
bool isPaused = time(0) < lastChat;
bool shouldReply = false;
bool isRandomBot = false;
sCharacterCache->GetCharacterNameByGuid(guid1, name);
uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid1);
isRandomBot = sPlayerbotAIConfig->IsInRandomAccountList(accountId);
bool isMentioned = message.find(bot->GetName()) != std::string::npos;
// random bot speaks, chat CD
if (isRandomBot && isPaused)
return;
// BG: react only if mentioned or if not channel and real player spoke
if (bot->InBattleground() && bot->GetBattleground() && !(isMentioned || (msgtype != CHAT_MSG_CHANNEL && !isRandomBot)))
return;
if ((isRandomBot && !isPaused && (!urand(0, 20) || (!urand(0, 10) && message.find(bot->GetName()) != std::string::npos))) || (!isRandomBot && (isMentioned || msgtype != CHAT_MSG_CHANNEL || !urand(0, 4))))
{
QueueChatResponse(msgtype, guid1, ObjectGuid(), message, chanName, name);
GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 25));
return;
}
}
break;
default:
break;
}
}
return;
}
case SMSG_MOVE_KNOCK_BACK: // handle knockbacks
{
// Peiru: Disable Knockback handling for now until spline crash can be resolved
@@ -1357,7 +1447,7 @@ bool PlayerbotAI::TellMasterNoFacing(std::string const text, PlayerbotSecurityLe
bool PlayerbotAI::TellError(std::string const text, PlayerbotSecurityLevel securityLevel)
{
Player* master = GetMaster();
if (!IsTellAllowed(securityLevel) || GET_PLAYERBOT_AI(master))
if (!IsTellAllowed(securityLevel) || !master || GET_PLAYERBOT_AI(master))
return false;
if (PlayerbotMgr* mgr = GET_PLAYERBOT_MGR(master))
@@ -1736,9 +1826,9 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
if (pet && pet->HasSpell(spellId))
{
bool autocast = false;
for(AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
for(unsigned int & m_autospell : pet->m_autospells)
{
if (*i == spellId)
if (m_autospell == spellId)
{
autocast = true;
break;
@@ -1893,9 +1983,9 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
if (pet && pet->HasSpell(spellId))
{
bool autocast = false;
for (AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
for (unsigned int & m_autospell : pet->m_autospells)
{
if (*i == spellId)
if (m_autospell == spellId)
{
autocast = true;
break;
@@ -3526,4 +3616,9 @@ bool PlayerbotAI::IsInRealGuild()
return false;
return !(sPlayerbotAIConfig->IsInRandomAccountList(leaderAccount));
}
void PlayerbotAI::QueueChatResponse(uint8 msgtype, ObjectGuid guid1, ObjectGuid guid2, std::string message, std::string chanName, std::string name)
{
chatReplies.push(ChatQueuedReply(msgtype, guid1.GetCounter(), guid2.GetCounter(), message, chanName, name, time(0) + urand(inCombat ? 10 : 5, inCombat ? 25 : 15)));
}