Files
mod-playerbots/src/strategy/actions/DebugAction.cpp
Cryo81 07e4dec70d Warning fix + ilvl function fix (#1210)
* 1 variable order warning fixed
70 unused variable warning fixed

* Fixed GetEquipGearScore function

---------

Co-authored-by: Julien MAS <julien.mas81@gmail.com>
2025-04-20 14:26:42 +08:00

1054 lines
34 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
* and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "DebugAction.h"
#include "ChooseTravelTargetAction.h"
#include "MapMgr.h"
#include "Playerbots.h"
bool DebugAction::Execute(Event event)
{
Player* master = GetMaster();
if (!master)
return false;
std::string const text = event.getParam();
if (text == "scan")
{
sPlayerbotAIConfig->openLog("scan.csv", "w");
uint32 i = 0;
for (auto p : WorldPosition().getCreaturesNear())
{
WorldPosition pos(p->mapid, p->posX, p->posY, p->posZ, p->orientation);
uint32 areaId = 0;
uint32 zoneId = 0;
sMapMgr->GetZoneAndAreaId(PHASEMASK_NORMAL, zoneId, areaId, pos.getMapId(), pos.getX(), pos.getY(),
pos.getZ());
std::ostringstream out;
out << zoneId << "," << areaId << "," << (pos.getAreaName().empty() ? "none" : pos.getAreaName()) << ",";
pos.printWKT(out);
sPlayerbotAIConfig->log("scan.csv", out.str().c_str());
if (zoneId == 0 && areaId == 0)
{
sPlayerbotAIConfig->log("x", out.str().c_str());
}
else
{
sPlayerbotAIConfig->log("y", out.str().c_str());
}
i = zoneId;
}
return i == 0;
}
else if (text.find("printmap") != std::string::npos)
{
sTravelNodeMap->printMap();
sTravelNodeMap->printNodeStore();
return true;
}
else if (text.find("travel ") != std::string::npos)
{
WorldPosition botPos = WorldPosition(bot);
std::string const destination = text.substr(7);
TravelDestination* dest = ChooseTravelTargetAction::FindDestination(bot, destination);
if (dest)
{
std::vector<WorldPosition*> points = dest->nextPoint(&botPos, true);
if (points.empty())
return false;
std::vector<WorldPosition> beginPath, endPath;
TravelNodeRoute route = sTravelNodeMap->getRoute(botPos, *points.front(), beginPath, bot);
std::ostringstream out;
out << "Traveling to " << dest->getTitle() << ": ";
for (auto node : route.getNodes())
{
out << node->getName() << ", ";
}
botAI->TellMasterNoFacing(out.str());
return true;
}
else
{
botAI->TellMasterNoFacing("Destination " + destination + " not found.");
return true;
}
}
else if (text.find("quest ") != std::string::npos)
{
uint32 questId = stoi(text.substr(6));
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
if (!quest)
{
botAI->TellMasterNoFacing("Quest " + text.substr(6) + " not found.");
return false;
}
std::ostringstream out;
out << quest->GetTitle() << ": ";
QuestContainer* cont = sTravelMgr->quests[questId];
for (auto g : cont->questGivers)
{
out << g->getTitle() << " +" << cont->questGivers.size() << " ";
break;
}
for (auto g : cont->questTakers)
{
out << g->getTitle() << " +" << cont->questTakers.size() - 1;
break;
}
for (auto g : cont->questObjectives)
{
out << g->getTitle() << " +" << cont->questObjectives.size() - 1;
break;
}
botAI->TellMasterNoFacing(out);
return true;
}
else if (text.find("quest") != std::string::npos)
{
std::ostringstream out;
out << sTravelMgr->quests.size() << " quests ";
uint32 noT = 0, noG = 0, noO = 0;
for (auto q : sTravelMgr->quests)
{
if (q.second->questGivers.empty())
noG++;
if (q.second->questTakers.empty())
noT++;
if (q.second->questObjectives.empty())
noO++;
}
out << noG << "|" << noT << "|" << noO << " bad.";
botAI->TellMasterNoFacing(out);
return true;
}
else if (text.find("bquest") != std::string::npos)
{
std::ostringstream out;
out << "bad quests:";
// uint32 noT = 0, noG = 0, noO = 0; //not used, line marked for removal.
for (auto q : sTravelMgr->quests)
{
Quest const* quest = sObjectMgr->GetQuestTemplate(q.first);
if (!quest)
{
out << " " << q.first << " does not exists";
continue;
}
if (q.second->questGivers.empty() || q.second->questTakers.empty() || q.second->questObjectives.empty())
out << quest->GetTitle() << " ";
if (q.second->questGivers.empty())
out << " no G";
if (q.second->questTakers.empty())
out << " no T";
if (q.second->questObjectives.empty())
out << " no O";
}
botAI->TellMasterNoFacing(out);
}
else if (text.find("add node") != std::string::npos)
{
WorldPosition pos(bot);
std::string const name = "USER:" + text.substr(9);
/* TravelNode* startNode = */ sTravelNodeMap->addNode(pos, name, false, false); // startNode not used, but addNode as side effect, fragment marked for removal.
for (auto& endNode : sTravelNodeMap->getNodes(pos, 2000))
{
endNode->setLinked(false);
}
botAI->TellMasterNoFacing("Node " + name + " created.");
sTravelNodeMap->setHasToGen();
return true;
}
else if (text.find("rem node") != std::string::npos)
{
WorldPosition pos(bot);
TravelNode* startNode = sTravelNodeMap->getNode(pos, nullptr, 50);
if (!startNode)
return false;
if (startNode->isImportant())
{
botAI->TellMasterNoFacing("Node can not be removed.");
}
sTravelNodeMap->m_nMapMtx.lock();
sTravelNodeMap->removeNode(startNode);
botAI->TellMasterNoFacing("Node removed.");
sTravelNodeMap->m_nMapMtx.unlock();
sTravelNodeMap->setHasToGen();
return true;
}
else if (text.find("reset node") != std::string::npos)
{
for (auto& node : sTravelNodeMap->getNodes())
node->setLinked(false);
return true;
}
else if (text.find("reset path") != std::string::npos)
{
for (auto& node : sTravelNodeMap->getNodes())
for (auto& path : *node->getLinks())
node->removeLinkTo(path.first, true);
return true;
}
else if (text.find("gen node") != std::string::npos)
{
// Pathfinder
sTravelNodeMap->generateNodes();
return true;
}
else if (text.find("gen path") != std::string::npos)
{
sTravelNodeMap->generatePaths();
return true;
}
else if (text.find("crop path") != std::string::npos)
{
sTravelNodeMap->removeUselessPaths();
return true;
}
else if (text.find("save node") != std::string::npos)
{
sTravelNodeMap->printNodeStore();
sTravelNodeMap->saveNodeStore();
return true;
}
else if (text.find("load node") != std::string::npos)
{
std::thread t(
[]
{
sTravelNodeMap->removeNodes();
sTravelNodeMap->loadNodeStore();
});
t.detach();
return true;
}
else if (text.find("show node") != std::string::npos)
{
WorldPosition pos(bot);
std::vector<TravelNode*> nodes = sTravelNodeMap->getNodes(pos, 500);
for (auto& node : nodes)
{
for (auto& l : *node->getLinks())
{
Unit* start = nullptr;
GuidVector units;
// uint32 time = 60 * IN_MILLISECONDS; //not used, line marked for removal.
std::vector<WorldPosition> ppath = l.second->getPath();
for (auto p : ppath)
{
Creature* wpCreature =
bot->SummonCreature(1, p.getX(), p.getY(), p.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000.0f);
// addAura(246, wpCreature);
units.push_back(wpCreature->GetGUID());
if (!start)
start = wpCreature;
}
// FakeSpell(1064, bot, start, units.front(), units, {}, pos, pos);
}
}
return true;
}
else if (text.find("dspell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(7));
Unit* prev = bot;
for (float i = 0; i < 60; i++)
{
float ang = i / 60 * static_cast<float>(M_PI) * 4;
float dist = i / 60 * 30;
WorldPosition botPos(bot);
WorldPosition botPos1 = botPos;
botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
FakeSpell(spellEffect, wpCreature, wpCreature, prev->GetGUID(), {}, {}, botPos, botPos);
prev = wpCreature;
}
return true;
}
else if (text.find("vspell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(7));
// Unit* prev = bot; //not used, line marked for removal.
for (float i = 0; i < 60; i++)
{
float ang = i / 60 * static_cast<float>(M_PI) * 4;
float dist = i / 60 * 30;
WorldPosition botPos(bot);
WorldPosition botPos1 = botPos;
botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature)
{
WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 8 + 4); // visual effect on guid
data << wpCreature->GetGUID();
data << uint32(spellEffect); // index from SpellVisualKit.dbc
wpCreature->SendMessageToSet(&data, true);
}
}
return true;
}
else if (text.find("aspell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(7));
// Unit* prev = bot; //not used, line marked for removal.
for (float i = 0; i < 60; i++)
{
float ang = i / 60 * static_cast<float>(M_PI) * 4;
float dist = i / 60 * 30;
WorldPosition botPos(bot);
WorldPosition botPos1 = botPos;
botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 5000.0f + i * 100.0f);
wpCreature->SetObjectScale(0.5f);
if (wpCreature)
{
addAura(spellEffect, wpCreature);
}
}
return true;
}
else if (text.find("cspell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(7));
GuidVector units;
for (float i = 0; i < 60; i++)
{
float ang = i / 60 * static_cast<float>(M_PI) * 4;
float dist = i / 60 * 30;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + cos(ang) * dist);
botPos.setY(botPos.getY() + sin(ang) * dist);
botPos.setZ(botPos.getHeight() + 2);
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
units.push_back(wpCreature->GetGUID());
}
WorldPosition botPos(bot);
if (urand(0, 1))
FakeSpell(spellEffect, bot, bot, ObjectGuid::Empty, units, {}, botPos, botPos);
else
FakeSpell(spellEffect, bot, bot, units.front(), units, {}, botPos, botPos);
return true;
}
else if (text.find("fspell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(7));
{
WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 2 + 4));
data.Initialize(SMSG_SPELL_START);
data << bot->GetPackGUID();
data << bot->GetPackGUID();
data << uint32(spellEffect);
data << uint16(0);
data << uint32(0);
data << uint16(2);
data << master->GetGUID();
bot->SendMessageToSet(&data, true);
}
{
WorldPacket data(SMSG_SPELL_GO, 53); // guess size
data << bot->GetPackGUID();
data << bot->GetPackGUID();
data << uint32(spellEffect); // spellID
data << uint8(0) << uint8(1); // flags
data << uint8(1); // amount of targets
data << master->GetGUID();
data << uint8(0);
data << uint16(2);
data << master->GetGUID();
bot->SendMessageToSet(&data, true);
}
return true;
}
else if (text.find("spell ") != std::string::npos)
{
uint32 spellEffect = stoi(text.substr(6));
master->SendPlaySpellVisual(bot->GetGUID(), spellEffect);
return true;
}
else if (text.find("tspellmap") != std::string::npos)
{
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature)
{
std::ostringstream out;
out << "effect ";
out << effect;
const std::string& Cname = out.str();
wpCreature->Say(Cname.c_str(), LANG_UNIVERSAL, master);
}
}
}
return true;
}
else if (text.find("uspellmap") != std::string::npos)
{
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(effect, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
}
}
return true;
}
else if (text.find("dspellmap") != std::string::npos)
{
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
FakeSpell(effect, bot, nullptr, ObjectGuid::Empty, {}, {}, botPos, botPos, true);
}
}
return true;
}
else if (text.find("vspellmap") != std::string::npos)
{
std::vector<WorldPacket> datMap;
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature)
{
WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 8 + 4); // visual effect on guid
data << wpCreature->GetGUID();
data << uint32(effect);
; // index from SpellVisualKit.dbc
// wpCreature->SendMessageToSet(&data, true);
datMap.push_back(data);
// wpCreature->MonsterMoveWithSpeed(botPos.getX(), botPos.getY() + 80, botPos.getZ(), 8.0f, true,
// true);
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (auto dat : datMap)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
bot->SendMessageToSet(&dat, true);
}
for (auto dat : datMap)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
bot->SendMessageToSet(&dat, true);
}
return true;
}
else if (text.find("ispellmap") != std::string::npos)
{
std::vector<WorldPacket> datMap;
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature)
{
WorldPacket data(SMSG_PLAY_SPELL_IMPACT, 8 + 4); // visual effect on player
data << wpCreature->GetGUID();
data << uint32(effect); // index from SpellVisualKit.dbc
// wpCreature->SendMessageToSet(&data, true);
datMap.push_back(data);
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (auto dat : datMap)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
bot->SendMessageToSet(&dat, true);
}
for (auto dat : datMap)
{
std::this_thread::sleep_for(std::chrono::milliseconds(20));
bot->SendMessageToSet(&dat, true);
}
return true;
}
else if (text.find("cspellmap") != std::string::npos)
{
Creature* wpCreature = nullptr;
Creature* lCreature = nullptr;
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
wpCreature = bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(),
botPos.getY(), botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature && lCreature)
{
wpCreature->CastSpell(lCreature, effect, TRIGGERED_FULL_MASK);
}
lCreature = wpCreature;
}
}
return true;
}
else if (text.find("aspellmap") != std::string::npos)
{
Creature* wpCreature = nullptr;
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
if (wpCreature)
{
addAura(effect, wpCreature);
}
}
}
return true;
}
else if (text.find("gspellmap") != std::string::npos)
{
GuidVector all_targets; // = { bot->GetGUID(), master->GetGUID() };
// std::GuidVector all_dummies = { bot->GetGUID(), master->GetGUID() };
/*GuidVector a_targets = *context->GetValue<GuidVector >("all targets");
for (auto t : a_targets)
{
all_targets.push_back(t);
}
*/
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
all_targets.push_back(wpCreature->GetGUID());
}
}
all_targets.push_back(master->GetGUID());
all_targets.push_back(bot->GetGUID());
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (uint32 i = 0; i < 2; i++)
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
uint32 i = dx + dy * 10;
GuidVector hits, miss;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect);
if (spellInfo && spellInfo->Speed > 0)
for (auto tar : all_targets)
{
// hits.push_back(tar);
switch (urand(0, 10))
{
case 0:
hits.push_back(tar);
break;
case 1:
miss.push_back(tar);
break;
case 2:
case 3:
break;
}
}
Unit* realCaster = botAI->GetUnit(
all_targets[i]); // botAI->GetUnit(all_targets[urand(0, all_targets.size() - 1)]);
Unit* caster = botAI->GetUnit(
all_targets[i]); // botAI->GetUnit(all_targets[urand(0, all_targets.size() - 1)]);
Unit* target = botAI->GetUnit(all_targets[i + 1]);
if (!realCaster)
realCaster = bot;
if (!caster)
caster = bot;
if (!target)
target = master;
FakeSpell(effect, realCaster, caster, target->GetGUID(), hits, miss, WorldPosition(caster),
WorldPosition(target));
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
return true;
}
else if (text.find("mspellmap") != std::string::npos)
{
GuidVector all_targets;
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature = bot->SummonCreature(2334, botPos.getX(), botPos.getY(), botPos.getZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
all_targets.push_back(wpCreature->GetGUID());
}
}
all_targets.push_back(master->GetGUID());
all_targets.push_back(bot->GetGUID());
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (uint32 i = 0; i < 2; i++)
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 spellEffect = stoi(text.substr(10));
uint32 effect = dx + dy * 10 + spellEffect * 100;
uint32 i = dx + dy * 10;
GuidVector hits, miss;
// SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect); //not used, line marked for removal.
for (auto tar : all_targets)
{
// hits.push_back(tar);
switch (urand(0, 10))
{
case 0:
hits.push_back(tar);
break;
case 1:
miss.push_back(tar);
break;
case 2:
case 3:
break;
}
}
Unit* realCaster = botAI->GetUnit(
all_targets[i]); // botAI->GetUnit(all_targets[urand(0, all_targets.size() - 1)]);
Unit* caster = botAI->GetUnit(
all_targets[i]); // botAI->GetUnit(all_targets[urand(0, all_targets.size() - 1)]);
Unit* target = botAI->GetUnit(all_targets[i + 1]);
if (!realCaster)
realCaster = bot;
if (!caster)
caster = bot;
if (!target)
target = master;
master->SendPlaySpellVisual(caster->GetGUID(), 5036);
FakeSpell(effect, realCaster, caster, target->GetGUID(), hits, miss, WorldPosition(caster),
WorldPosition(target));
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
return true;
}
else if (text.find("soundmap") != std::string::npos)
{
uint32 soundEffects = stoi(text.substr(9));
for (int32 dx = 0; dx < 10; dx++)
{
for (int32 dy = 0; dy < 10; dy++)
{
uint32 effect = dx + dy * 10 + soundEffects * 100;
WorldPosition botPos(bot);
botPos.setX(botPos.getX() + (dx - 5) * 5);
botPos.setY(botPos.getY() + (dy - 5) * 5);
botPos.setZ(botPos.getHeight());
Creature* wpCreature =
bot->SummonCreature((dy == 0 && (dx == 0 || dx == 2)) ? 6 : 2, botPos.getX(), botPos.getY(),
botPos.getZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000.0f);
wpCreature->PlayDistanceSound(effect);
}
}
}
else if (text.find("sounds") != std::string::npos)
{
uint32 soundEffects = stoi(text.substr(6));
for (uint32 i = 0; i < 100; i++)
{
bot->PlayDistanceSound(i + soundEffects * 100);
bot->Say(std::to_string(i + soundEffects * 100), LANG_UNIVERSAL);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return true;
}
else if (text.find("dsound") != std::string::npos)
{
uint32 soundEffect = stoi(text.substr(7));
bot->PlayDirectSound(soundEffect);
return true;
}
else if (text.find("dsound") != std::string::npos)
{
uint32 soundEffect = stoi(text.substr(7));
bot->PlayDirectSound(soundEffect);
return true;
}
else if (text.find("sound") != std::string::npos)
{
uint32 soundEffect = stoi(text.substr(6));
bot->PlayDistanceSound(soundEffect);
return true;
}
std::string const response = botAI->HandleRemoteCommand(text);
botAI->TellMaster(response);
return true;
}
void DebugAction::FakeSpell(uint32 spellId, Unit* truecaster, Unit* caster, ObjectGuid target, GuidVector otherTargets,
GuidVector missTargets, WorldPosition source, WorldPosition dest, bool forceDest)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
{
uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
if (spellInfo->HasAttribute(SPELL_ATTR0_USES_RANGED_SLOT) ||
spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
castFlags |= CAST_FLAG_PROJECTILE;
WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 2 + 4));
data << truecaster->GetPackGUID(); // truecaster
if (caster)
data << caster->GetPackGUID(); // m_caster->GetPackGUID();
else
data << ObjectGuid::Empty;
data << uint32(spellId); // spellId
data << uint16(castFlags); // cast flags
data << uint32(1000.0f); // delay?
SpellCastTargets m_targets;
m_targets.Write(data);
// projectile info
if (castFlags & CAST_FLAG_PROJECTILE)
{
data << uint32(5996);
data << uint32(INVTYPE_AMMO);
}
if (caster)
caster->SendMessageToSet(&data, true);
else
truecaster->SendMessageToSet(&data, true);
}
{
SpellCastTargets m_targets;
if ((spellInfo && spellInfo->Targets & TARGET_FLAG_DEST_LOCATION) || forceDest)
m_targets.SetDst(dest);
if ((spellInfo && spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION) || forceDest)
m_targets.SetSrc(source.getX(), source.getY(), source.getZ());
if (!forceDest && target)
if (!spellInfo ||
!(spellInfo->Targets & TARGET_FLAG_DEST_LOCATION && spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION))
m_targets.SetUnitTarget(botAI->GetUnit(target));
uint32 castFlags = CAST_FLAG_UNKNOWN_9;
if (spellInfo->HasAttribute(SPELL_ATTR0_USES_RANGED_SLOT) ||
spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))
castFlags |= CAST_FLAG_PROJECTILE; // arrows/bullets visual
if (spellInfo->HasEffect(SPELL_EFFECT_ACTIVATE_RUNE))
castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
if (m_targets.HasTraj())
castFlags |= CAST_FLAG_ADJUST_MISSILE;
if (!spellInfo->StartRecoveryTime)
castFlags |= CAST_FLAG_NO_GCD;
WorldPacket data(SMSG_SPELL_GO, 53); // guess size
data << truecaster->GetPackGUID(); // truecaster
if (caster)
data << caster->GetPackGUID(); // m_caster->GetPackGUID();
else
data << ObjectGuid::Empty;
data << uint32(spellId); // spellId
data << uint16(castFlags); // cast flags
// WriteSpellGoTargets
uint32 hits = otherTargets.size() + (target ? 1 : 0);
data << uint8(hits); // Hits
if (target)
data << target;
// Hit targets here.
for (auto otherTarget : otherTargets)
data << otherTarget;
data << (uint8)missTargets.size(); // miss
for (auto missTarget : missTargets)
{
data << missTarget;
data << uint8(SPELL_MISS_RESIST); // Miss condition
data << uint8(SPELL_MISS_NONE); // Miss condition
}
m_targets.Write(data);
// projectile info
if (castFlags & CAST_FLAG_PROJECTILE)
{
data << uint32(5996);
data << uint32(INVTYPE_AMMO);
}
if (caster)
caster->SendMessageToSet(&data, true);
else
truecaster->SendMessageToSet(&data, true);
}
}
void DebugAction::addAura(uint32 spellId, Unit* target)
{
if (!target)
return;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
return;
if (!target->IsAlive() && !spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) &&
!spellInfo->HasAttribute(SPELL_ATTR2_ALLOW_DEAD_TARGET))
return;
target->AddAura(spellInfo, MAX_EFFECT_MASK, target);
}