mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 23:49:25 +02:00
# Pull Request
Removed unused variables and fixed styling issues.
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific
configuration)
- Expected behavior and how to verify it
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
This was filtered from the code provided by SmashingQuasar. Eliminated
variables were confirmed to be not used, but unclear at times if that is
due to mistakes in writing.
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
341 lines
9.5 KiB
C++
341 lines
9.5 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#include "MailAction.h"
|
|
|
|
#include "ChatHelper.h"
|
|
#include "Event.h"
|
|
#include "Mail.h"
|
|
#include "Playerbots.h"
|
|
|
|
std::map<std::string, MailProcessor*> MailAction::processors;
|
|
|
|
class TellMailProcessor : public MailProcessor
|
|
{
|
|
public:
|
|
bool Before(PlayerbotAI* botAI) override
|
|
{
|
|
botAI->TellMaster("=== Mailbox ===");
|
|
tells.clear();
|
|
return true;
|
|
}
|
|
|
|
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
|
{
|
|
Player* bot = botAI->GetBot();
|
|
time_t cur_time = time(nullptr);
|
|
uint32 days = (cur_time - mail->deliver_time) / 3600 / 24;
|
|
|
|
std::ostringstream out;
|
|
out << "#" << (index + 1) << " ";
|
|
if (!mail->money && !mail->HasItems())
|
|
out << "|cffffffff" << mail->subject;
|
|
|
|
if (mail->money)
|
|
{
|
|
out << "|cffffff00" << ChatHelper::formatMoney(mail->money);
|
|
if (!mail->subject.empty())
|
|
out << " |cffa0a0a0(" << mail->subject << ")";
|
|
}
|
|
|
|
if (mail->HasItems())
|
|
{
|
|
for (MailItemInfoVec::iterator i = mail->items.begin(); i != mail->items.end(); ++i)
|
|
{
|
|
Item* item = bot->GetMItem(i->item_guid);
|
|
uint32 count = item ? item->GetCount() : 1;
|
|
|
|
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(i->item_template))
|
|
{
|
|
out << ChatHelper::FormatItem(proto, count);
|
|
if (!mail->subject.empty())
|
|
out << " |cffa0a0a0(" << mail->subject << ")";
|
|
}
|
|
}
|
|
}
|
|
|
|
out << ", |cff00ff00" << days << " day(s)";
|
|
tells.push_front(out.str());
|
|
return true;
|
|
}
|
|
|
|
bool After(PlayerbotAI* botAI) override
|
|
{
|
|
for (std::list<std::string>::iterator i = tells.begin(); i != tells.end(); ++i)
|
|
botAI->TellMaster(*i);
|
|
|
|
return true;
|
|
}
|
|
|
|
static TellMailProcessor instance;
|
|
|
|
private:
|
|
std::list<std::string> tells;
|
|
};
|
|
|
|
class TakeMailProcessor : public MailProcessor
|
|
{
|
|
public:
|
|
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
|
{
|
|
Player* bot = botAI->GetBot();
|
|
if (!CheckBagSpace(bot))
|
|
{
|
|
botAI->TellError("Not enough bag space");
|
|
return false;
|
|
}
|
|
|
|
ObjectGuid mailbox = FindMailbox(botAI);
|
|
if (mail->money)
|
|
{
|
|
std::ostringstream out;
|
|
out << mail->subject << ", |cffffff00" << ChatHelper::formatMoney(mail->money) << "|cff00ff00 processed";
|
|
botAI->TellMaster(out.str());
|
|
|
|
WorldPacket packet;
|
|
packet << mailbox;
|
|
packet << mail->messageID;
|
|
bot->GetSession()->HandleMailTakeMoney(packet);
|
|
RemoveMail(bot, mail->messageID, mailbox);
|
|
}
|
|
else if (!mail->items.empty())
|
|
{
|
|
std::vector<uint32> guids;
|
|
for (MailItemInfoVec::iterator i = mail->items.begin(); i != mail->items.end(); ++i)
|
|
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(i->item_template))
|
|
guids.push_back(i->item_guid);
|
|
|
|
for (std::vector<uint32>::iterator i = guids.begin(); i != guids.end(); ++i)
|
|
{
|
|
WorldPacket packet;
|
|
packet << mailbox;
|
|
packet << mail->messageID;
|
|
packet << *i;
|
|
|
|
Item* item = bot->GetMItem(*i);
|
|
|
|
std::ostringstream out;
|
|
out << mail->subject << ", " << ChatHelper::FormatItem(item->GetTemplate()) << "|cff00ff00 processed";
|
|
|
|
bot->GetSession()->HandleMailTakeItem(packet);
|
|
botAI->TellMaster(out.str());
|
|
}
|
|
|
|
RemoveMail(bot, mail->messageID, mailbox);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static TakeMailProcessor instance;
|
|
|
|
private:
|
|
bool CheckBagSpace(Player* bot)
|
|
{
|
|
uint32 totalused = 0;
|
|
for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++)
|
|
if (bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
|
++totalused;
|
|
|
|
uint32 totalfree = 16 - totalused;
|
|
for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
|
|
{
|
|
if (Bag const* pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag))
|
|
{
|
|
ItemTemplate const* pBagProto = pBag->GetTemplate();
|
|
if (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER)
|
|
totalfree += pBag->GetFreeSlots();
|
|
}
|
|
}
|
|
|
|
return totalfree >= 2;
|
|
}
|
|
};
|
|
|
|
class DeleteMailProcessor : public MailProcessor
|
|
{
|
|
public:
|
|
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
|
{
|
|
std::ostringstream out;
|
|
out << "|cffffffff" << mail->subject << "|cffff0000 deleted";
|
|
RemoveMail(botAI->GetBot(), mail->messageID, FindMailbox(botAI));
|
|
botAI->TellMaster(out.str());
|
|
return true;
|
|
}
|
|
|
|
static DeleteMailProcessor instance;
|
|
};
|
|
|
|
class ReadMailProcessor : public MailProcessor
|
|
{
|
|
public:
|
|
bool Process(uint32 index, Mail* mail, PlayerbotAI* botAI) override
|
|
{
|
|
std::ostringstream out, body;
|
|
out << "|cffffffff" << mail->subject;
|
|
botAI->TellMaster(out.str());
|
|
|
|
return true;
|
|
}
|
|
|
|
static ReadMailProcessor instance;
|
|
};
|
|
|
|
TellMailProcessor TellMailProcessor::instance;
|
|
TakeMailProcessor TakeMailProcessor::instance;
|
|
DeleteMailProcessor DeleteMailProcessor::instance;
|
|
ReadMailProcessor ReadMailProcessor::instance;
|
|
|
|
std::map<uint32, Mail*> filterList(std::vector<Mail*> src, std::string const filter)
|
|
{
|
|
std::map<uint32, Mail*> result;
|
|
if (filter.empty() || filter == "*")
|
|
{
|
|
uint32 idx = 0;
|
|
for (std::vector<Mail*>::iterator i = src.begin(); i != src.end(); ++i)
|
|
result[idx++] = *i;
|
|
|
|
return result;
|
|
}
|
|
|
|
if (filter.find("-") != std::string::npos)
|
|
{
|
|
std::vector<std::string> ss = split(filter, '-');
|
|
uint32 from = 0;
|
|
uint32 to = src.size() - 1;
|
|
|
|
if (!ss[0].empty())
|
|
from = atoi(ss[0].c_str()) - 1;
|
|
|
|
if (ss.size() > 1 && !ss[1].empty())
|
|
to = atoi(ss[1].c_str()) - 1;
|
|
|
|
if (from < 0)
|
|
from = 0;
|
|
|
|
if (from > src.size() - 1)
|
|
from = src.size() - 1;
|
|
|
|
if (to < 0)
|
|
to = 0;
|
|
|
|
if (to > src.size() - 1)
|
|
to = src.size() - 1;
|
|
|
|
for (uint32 i = from; i <= to; ++i)
|
|
result[i] = src[i];
|
|
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::string> ss = split(filter, ',');
|
|
for (std::vector<std::string>::iterator i = ss.begin(); i != ss.end(); ++i)
|
|
{
|
|
uint32 idx = atoi(i->c_str()) - 1;
|
|
|
|
if (idx < 0)
|
|
idx = 0;
|
|
|
|
if (idx > src.size() - 1)
|
|
idx = src.size() - 1;
|
|
|
|
result[idx] = src[idx];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool MailAction::Execute(Event event)
|
|
{
|
|
Player* master = GetMaster();
|
|
if (!master)
|
|
return false;
|
|
|
|
if (!MailProcessor::FindMailbox(botAI))
|
|
{
|
|
botAI->TellError("There is no mailbox nearby");
|
|
return false;
|
|
}
|
|
|
|
if (processors.empty())
|
|
{
|
|
processors["?"] = &TellMailProcessor::instance;
|
|
processors["take"] = &TakeMailProcessor::instance;
|
|
processors["delete"] = &DeleteMailProcessor::instance;
|
|
processors["read"] = &ReadMailProcessor::instance;
|
|
}
|
|
|
|
std::string const text = event.getParam();
|
|
if (text.empty())
|
|
{
|
|
botAI->TellMaster(
|
|
"whisper 'mail ?' to query mailbox, 'mail take/delete/read filter' to take/delete/read mails by filter");
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> ss = split(text, ' ');
|
|
std::string const action = ss[0];
|
|
std::string const filter = ss.size() > 1 ? ss[1] : "";
|
|
|
|
MailProcessor* processor = processors[action];
|
|
if (!processor)
|
|
{
|
|
std::ostringstream out;
|
|
out << action << ": I don't know how to do that";
|
|
botAI->TellMaster(out.str());
|
|
return false;
|
|
}
|
|
|
|
if (!processor->Before(botAI))
|
|
return false;
|
|
|
|
std::vector<Mail*> mailList;
|
|
time_t cur_time = time(nullptr);
|
|
for (PlayerMails::const_iterator itr = bot->GetMails().begin(); itr != bot->GetMails().end(); ++itr)
|
|
{
|
|
if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
|
|
continue;
|
|
|
|
Mail* mail = *itr;
|
|
mailList.push_back(mail);
|
|
}
|
|
|
|
std::map<uint32, Mail*> filtered = filterList(mailList, filter);
|
|
for (std::map<uint32, Mail*>::iterator i = filtered.begin(); i != filtered.end(); ++i)
|
|
{
|
|
if (!processor->Process(i->first, i->second, botAI))
|
|
break;
|
|
}
|
|
|
|
return processor->After(botAI);
|
|
}
|
|
|
|
void MailProcessor::RemoveMail(Player* bot, uint32 id, ObjectGuid mailbox)
|
|
{
|
|
WorldPacket packet;
|
|
packet << mailbox;
|
|
packet << id;
|
|
packet << (uint32)0; // mailTemplateId
|
|
bot->GetSession()->HandleMailDelete(packet);
|
|
}
|
|
|
|
ObjectGuid MailProcessor::FindMailbox(PlayerbotAI* botAI)
|
|
{
|
|
GuidVector gos = *botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest game objects");
|
|
ObjectGuid mailbox;
|
|
for (ObjectGuid const guid : gos)
|
|
{
|
|
if (GameObject* go = botAI->GetGameObject(guid))
|
|
if (go->GetGoType() == GAMEOBJECT_TYPE_MAILBOX)
|
|
{
|
|
mailbox = go->GetGUID();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return mailbox;
|
|
}
|