Files
mod-playerbots/src/strategy/raids/eyeofeternity/RaidEoEActions.cpp
Bobblybook c6a0b012e8 EoE cleanup
2024-12-16 17:47:44 +11:00

392 lines
11 KiB
C++

#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);
}
}