#include "RaidMagtheridonHelpers.h" #include "Creature.h" #include "GameObject.h" #include "Map.h" #include "ObjectGuid.h" #include "Playerbots.h" namespace MagtheridonHelpers { const Position WAITING_FOR_MAGTHERIDON_POSITION = { 1.359f, 2.048f, -0.406f, 3.135f }; const Position MAGTHERIDON_TANK_POSITION = { 22.827f, 2.105f, -0.406f, 3.135f }; const Position NW_CHANNELER_TANK_POSITION = { -11.764f, 30.818f, -0.411f, 0.0f }; const Position NE_CHANNELER_TANK_POSITION = { -12.490f, -26.211f, -0.411f, 0.0f }; const Position RANGED_SPREAD_POSITION = { -14.890f, 1.995f, -0.406f, 0.0f }; const Position HEALER_SPREAD_POSITION = { -2.265f, 1.874f, -0.404f, 0.0f }; // Identify channelers by their database GUIDs Creature* GetChanneler(Player* bot, uint32 dbGuid) { Map* map = bot->GetMap(); if (!map) return nullptr; auto it = map->GetCreatureBySpawnIdStore().find(dbGuid); if (it == map->GetCreatureBySpawnIdStore().end()) return nullptr; Creature* channeler = it->second; if (!channeler->IsAlive()) return nullptr; return channeler; } const std::vector MANTICRON_CUBE_DB_GUIDS = { 43157, 43158, 43159, 43160, 43161 }; // Get the positions of all Manticron Cubes by their database GUIDs std::vector GetAllCubeInfosByDbGuids(Map* map, const std::vector& cubeDbGuids) { std::vector cubes; if (!map) return cubes; for (uint32 dbGuid : cubeDbGuids) { auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(dbGuid); if (bounds.first == bounds.second) continue; GameObject* go = bounds.first->second; if (!go) continue; CubeInfo info; info.guid = go->GetGUID(); info.x = go->GetPositionX(); info.y = go->GetPositionY(); info.z = go->GetPositionZ(); cubes.push_back(info); } return cubes; } std::unordered_map botToCubeAssignment; void AssignBotsToCubesByGuidAndCoords(Group* group, const std::vector& cubes, PlayerbotAI* botAI) { botToCubeAssignment.clear(); if (!group) return; size_t cubeIndex = 0; std::vector candidates; // Assign ranged DPS (excluding Warlocks) to cubes first for (GroupReference* ref = group->GetFirstMember(); ref && cubeIndex < cubes.size(); ref = ref->next()) { Player* member = ref->GetSource(); if (!member || !member->IsAlive() || !botAI->IsRangedDps(member, true) || member->getClass() == CLASS_WARLOCK || !GET_PLAYERBOT_AI(member)) continue; candidates.push_back(member); if (candidates.size() >= cubes.size()) break; } // If there are still cubes left, assign any other non-tank bots if (candidates.size() < cubes.size()) { for (GroupReference* ref = group->GetFirstMember(); ref && candidates.size() < cubes.size(); ref = ref->next()) { Player* member = ref->GetSource(); if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member) || botAI->IsTank(member)) continue; if (std::find(candidates.begin(), candidates.end(), member) == candidates.end()) candidates.push_back(member); } } for (Player* member : candidates) { if (cubeIndex >= cubes.size()) break; if (!member || !member->IsAlive()) continue; botToCubeAssignment[member->GetGUID()] = cubes[cubeIndex++]; } } std::unordered_map lastBlastNovaState; std::unordered_map blastNovaTimer; std::unordered_map spreadWaitTimer; std::unordered_map dpsWaitTimer; bool IsSafeFromMagtheridonHazards(PlayerbotAI* botAI, Player* bot, float x, float y, float z) { // Debris std::vector debrisHazards; const GuidVector npcs = botAI->GetAiObjectContext()->GetValue("nearest npcs")->Get(); for (auto const& npcGuid : npcs) { Unit* unit = botAI->GetUnit(npcGuid); if (!unit || unit->GetEntry() != NPC_TARGET_TRIGGER) continue; debrisHazards.push_back(unit); } for (Unit* hazard : debrisHazards) { float dist = std::sqrt(std::pow(x - hazard->GetPositionX(), 2) + std::pow(y - hazard->GetPositionY(), 2)); if (dist < 9.0f) return false; } // Conflagration GuidVector gos = *botAI->GetAiObjectContext()->GetValue("nearest game objects"); for (auto const& goGuid : gos) { GameObject* go = botAI->GetGameObject(goGuid); if (!go || go->GetEntry() != GO_BLAZE) continue; float dist = std::sqrt(std::pow(x - go->GetPositionX(), 2) + std::pow(y - go->GetPositionY(), 2)); if (dist < 5.0f) return false; } return true; } }