#include "RaidEoEActions.h" #include "RaidEoETriggers.h" #include "Playerbots.h" bool MalygosPositionAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); if (!boss) { return false; } uint8 phase = MalygosTrigger::getPhase(bot, boss); float distance = 5.0f; if (phase == 1) { Unit* spark = nullptr; GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); for (auto& target : targets) { Unit* unit = botAI->GetUnit(target); if (unit && unit->GetEntry() == NPC_POWER_SPARK) { spark = unit; break; } } // Position tank if (botAI->IsMainTank(bot)) { if (bot->GetDistance2d(MALYGOS_MAINTANK_POSITION.first, MALYGOS_MAINTANK_POSITION.second) > distance) { return MoveTo(EOE_MAP_ID, MALYGOS_MAINTANK_POSITION.first, MALYGOS_MAINTANK_POSITION.second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } return false; } // Position DK for spark pull // else if (spark && bot->IsClass(CLASS_DEATH_KNIGHT)) // { // if (bot->GetDistance2d(MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second) > distance) // { // bot->Yell("SPARK SPAWNED, MOVING TO STACK", LANG_UNIVERSAL); // return MoveTo(EOE_MAP_ID, MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second, bot->GetPositionZ(), // false, false, false, false, MovementPriority::MOVEMENT_COMBAT); // } // return false; // } else if (spark) { return false; } else if (!bot->IsClass(CLASS_HUNTER)) { if (bot->GetDistance2d(MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second) > (distance * 3.0f)) { return MoveTo(EOE_MAP_ID, MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } return false; } } return false; } bool MalygosTargetAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); if (!boss) { return false; } uint8 phase = MalygosTrigger::getPhase(bot, boss); if (phase == 1) { if (botAI->IsHeal(bot)) { return false; } // Init this as boss by default, if no better target is found just fall back to Malygos Unit* newTarget = boss; // Unit* spark = nullptr; // GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); // for (auto& target : targets) // { // Unit* unit = botAI->GetUnit(target); // if (unit && unit->GetEntry() == NPC_POWER_SPARK) // { // spark = unit; // break; // } // } // if (spark && botAI->IsRangedDps(bot)) // { // newTarget = spark; // } Unit* currentTarget = AI_VALUE(Unit*, "current target"); if (!currentTarget || currentTarget->GetEntry() != newTarget->GetEntry()) { return Attack(newTarget); } } else if (phase == 2) { if (botAI->IsHeal(bot)) { return false; } Unit* newTarget = nullptr; Unit* nexusLord = nullptr; Unit* scionOfEternity = nullptr; GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); for (auto& target : targets) { Unit* unit = botAI->GetUnit(target); if (!unit) { continue; } if (unit->GetEntry() == NPC_NEXUS_LORD) { nexusLord = unit; } else if (unit->GetEntry() == NPC_SCION_OF_ETERNITY) { scionOfEternity = unit; } } if (botAI->IsRangedDps(bot) && scionOfEternity) { newTarget = scionOfEternity; } else { newTarget = nexusLord; } if (!newTarget) { return false; } Unit* currentTarget = AI_VALUE(Unit*, "current target"); if (!currentTarget || currentTarget->GetEntry() != newTarget->GetEntry()) { return Attack(newTarget); } } // else if (phase == 3) // {} return false; } // bool PullPowerSparkAction::Execute(Event event) // { // Unit* spark = nullptr; // GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); // for (auto& target : targets) // { // Unit* unit = botAI->GetUnit(target); // if (unit && unit->GetEntry() == NPC_POWER_SPARK) // { // spark = unit; // break; // } // } // if (!spark) { return false; } // if (spark->GetDistance2d(MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second) > 3.0f) // { // bot->Yell("GRIPPING SPARK", LANG_UNIVERSAL); // return botAI->CastSpell("death grip", spark); // } // return false; // } // bool PullPowerSparkAction::isPossible() // { // Unit* spark = nullptr; // GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); // for (auto& target : targets) // { // Unit* unit = botAI->GetUnit(target); // if (unit && unit->GetEntry() == NPC_POWER_SPARK) // { // spark = unit; // break; // } // } // return botAI->CanCastSpell(spell, spark); // } // bool PullPowerSparkAction::isUseful() // { // Unit* spark = nullptr; // GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); // for (auto& target : targets) // { // Unit* unit = botAI->GetUnit(target); // if (unit && unit->GetEntry() == NPC_POWER_SPARK) // { // spark = unit; // break; // } // } // if (!spark) // return false; // if (!spark->IsInWorld() || spark->GetMapId() != bot->GetMapId()) // return false; // return bot->GetDistance2d(MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second) < 3.0f; // } // bool KillPowerSparkAction::Execute(Event event) // { // return false; // } bool EoEFlyDrakeAction::isPossible() { Unit* vehicleBase = bot->GetVehicleBase(); return (vehicleBase && vehicleBase->GetEntry() == NPC_WYRMREST_SKYTALON); } bool EoEFlyDrakeAction::Execute(Event event) { Player* master = botAI->GetMaster(); if (!master) { return false; } Unit* masterVehicle = master->GetVehicleBase(); Unit* vehicleBase = bot->GetVehicleBase(); if (!vehicleBase || !masterVehicle) { return false; } MotionMaster* mm = vehicleBase->GetMotionMaster(); Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); if (boss && false) { // Handle as boss encounter instead of formation flight mm->Clear(false); float distance = vehicleBase->GetExactDist(boss); float range = 55.0f; // Drake range is 60yd if (distance > range) { mm->MoveForwards(boss, range - distance); vehicleBase->SendMovementFlagUpdate(); return true; } vehicleBase->SetFacingToObject(boss); mm->MoveIdle(); vehicleBase->SendMovementFlagUpdate(); return false; } if (vehicleBase->GetExactDist(masterVehicle) > 5.0f) { uint8 numPlayers; bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL ? numPlayers = 25 : numPlayers = 10; // 3/4 of a circle, with frontal cone 90 deg unobstructed float angle = botAI->GetGroupSlotIndex(bot) * (2*M_PI - M_PI_2)/numPlayers + M_PI_2; // float angle = M_PI; vehicleBase->SetCanFly(true); mm->MoveFollow(masterVehicle, 3.0f, angle); vehicleBase->SendMovementFlagUpdate(); return true; } return false; } bool EoEDrakeAttackAction::isPossible() { Unit* vehicleBase = bot->GetVehicleBase(); return (vehicleBase && vehicleBase->GetEntry() == NPC_WYRMREST_SKYTALON); } bool EoEDrakeAttackAction::Execute(Event event) { vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) { return false; } // Unit* target = AI_VALUE(Unit*, "current target"); Unit* boss = AI_VALUE2(Unit*, "find target", "malygos"); // if (!boss) { return false; } if (!boss) { GuidVector npcs = AI_VALUE(GuidVector, "possible targets"); for (auto& npc : npcs) { Unit* unit = botAI->GetUnit(npc); if (!unit || unit->GetEntry() != NPC_MALYGOS) { continue; } boss = unit; break; } } // Check this again to see if a target was assigned if (!boss) { return false; } if (botAI->IsHeal(bot)) { return DrakeHealAction(); } else { return DrakeDpsAction(boss); } return false; } bool EoEDrakeAttackAction::CastDrakeSpellAction(Unit* target, uint32 spellId, uint32 cooldown) { if (botAI->CanCastVehicleSpell(spellId, target)) if (botAI->CastVehicleSpell(spellId, target)) { vehicleBase->AddSpellCooldown(spellId, 0, cooldown); return true; } return false; } bool EoEDrakeAttackAction::DrakeDpsAction(Unit* target) { Unit* vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) { return false; } Vehicle* veh = bot->GetVehicle(); uint8 comboPoints = vehicleBase->GetComboPoints(target); if (comboPoints >= 2) { return CastDrakeSpellAction(target, SPELL_ENGULF_IN_FLAMES, 0); } else { return CastDrakeSpellAction(target, SPELL_FLAME_SPIKE, 0); } } bool EoEDrakeAttackAction::DrakeHealAction() { Unit* vehicleBase = bot->GetVehicleBase(); if (!vehicleBase) { return false; } Unit* target = vehicleBase->GetComboTarget(); if (!target) { // Unit* newTarget = nullptr; Unit* newTarget = vehicleBase; GuidVector members = AI_VALUE(GuidVector, "group members"); for (auto& member : members) { Unit* unit = botAI->GetUnit(member); if (!unit) { continue; } Unit* drake = unit->GetVehicleBase(); if (!drake || drake->IsFullHealth()) { continue; } if (!newTarget || drake->GetHealthPct() < newTarget->GetHealthPct() - 5.0f) { newTarget = drake; } } target = newTarget; } uint8 comboPoints = vehicleBase->GetComboPoints(target); if (comboPoints >= 5) { return CastDrakeSpellAction(target, SPELL_LIFE_BURST, 0); } else { // "Revivify" may be bugged server-side: // "botAI->CanCastVehicleSpell()" returns SPELL_FAILED_BAD_TARGETS when targeting drakes. // Forcing the cast attempt seems to succeed, not sure what's going on here. // return CastDrakeSpellAction(target, SPELL_REVIVIFY, 0); return botAI->CastVehicleSpell(SPELL_REVIVIFY, target); } }