mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
@@ -54,6 +54,14 @@ public:
|
|||||||
creators["thorim gauntlet positioning action"] = &RaidUlduarActionContext::thorim_gauntlet_positioning_action;
|
creators["thorim gauntlet positioning action"] = &RaidUlduarActionContext::thorim_gauntlet_positioning_action;
|
||||||
creators["thorim phase 2 positioning action"] = &RaidUlduarActionContext::thorim_phase2_positioning_action;
|
creators["thorim phase 2 positioning action"] = &RaidUlduarActionContext::thorim_phase2_positioning_action;
|
||||||
creators["mimiron fire resistance action"] = &RaidUlduarActionContext::mimiron_fire_resistance_action;
|
creators["mimiron fire resistance action"] = &RaidUlduarActionContext::mimiron_fire_resistance_action;
|
||||||
|
creators["mimiron shock blast action"] = &RaidUlduarActionContext::mimiron_shock_blast_action;
|
||||||
|
creators["mimiron phase 1 positioning action"] = &RaidUlduarActionContext::mimiron_phase_1_positioning_action;
|
||||||
|
creators["mimiron p3wx2 laser barrage action"] = &RaidUlduarActionContext::mimiron_p3wx2_laser_barrage_action;
|
||||||
|
creators["mimiron rapid burst action"] = &RaidUlduarActionContext::mimiron_rapid_burst_action;
|
||||||
|
creators["mimiron aerial command unit action"] = &RaidUlduarActionContext::mimiron_aerial_command_unit_action;
|
||||||
|
creators["mimiron rocket strike action"] = &RaidUlduarActionContext::mimiron_rocket_strike_action;
|
||||||
|
creators["mimiron phase 4 mark dps action"] = &RaidUlduarActionContext::mimiron_phase_4_mark_dps_action;
|
||||||
|
creators["mimiron cheat action"] = &RaidUlduarActionContext::mimiron_cheat_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -95,6 +103,14 @@ private:
|
|||||||
static Action* thorim_gauntlet_positioning_action(PlayerbotAI* ai) { return new ThorimGauntletPositioningAction(ai); }
|
static Action* thorim_gauntlet_positioning_action(PlayerbotAI* ai) { return new ThorimGauntletPositioningAction(ai); }
|
||||||
static Action* thorim_phase2_positioning_action(PlayerbotAI* ai) { return new ThorimPhase2PositioningAction(ai); }
|
static Action* thorim_phase2_positioning_action(PlayerbotAI* ai) { return new ThorimPhase2PositioningAction(ai); }
|
||||||
static Action* mimiron_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "mimiron"); }
|
static Action* mimiron_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "mimiron"); }
|
||||||
|
static Action* mimiron_shock_blast_action(PlayerbotAI* ai) { return new MimironShockBlastAction(ai); }
|
||||||
|
static Action* mimiron_phase_1_positioning_action(PlayerbotAI* ai) { return new MimironPhase1PositioningAction(ai); }
|
||||||
|
static Action* mimiron_p3wx2_laser_barrage_action(PlayerbotAI* ai) { return new MimironP3Wx2LaserBarrageAction(ai); }
|
||||||
|
static Action* mimiron_rapid_burst_action(PlayerbotAI* ai) { return new MimironRapidBurstAction(ai); }
|
||||||
|
static Action* mimiron_aerial_command_unit_action(PlayerbotAI* ai) { return new MimironAerialCommandUnitAction(ai); }
|
||||||
|
static Action* mimiron_rocket_strike_action(PlayerbotAI* ai) { return new MimironRocketStrikeAction(ai); }
|
||||||
|
static Action* mimiron_phase_4_mark_dps_action(PlayerbotAI* ai) { return new MimironPhase4MarkDpsAction(ai); }
|
||||||
|
static Action* mimiron_cheat_action(PlayerbotAI* ai) { return new MimironCheatAction(ai); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "RaidUlduarActions.h"
|
#include "RaidUlduarActions.h"
|
||||||
|
|
||||||
|
#include <CombatStrategy.h>
|
||||||
#include <FollowMasterStrategy.h>
|
#include <FollowMasterStrategy.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -2171,9 +2172,8 @@ bool ThorimPhase2PositioningAction::Execute(Event event)
|
|||||||
targetPosition = ULDUAR_THORIM_PHASE2_RANGE3_SPOT;
|
targetPosition = ULDUAR_THORIM_PHASE2_RANGE3_SPOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveTo(bot->GetMapId(), targetPosition.GetPositionX(), targetPosition.GetPositionY(),
|
MoveTo(bot->GetMapId(), targetPosition.GetPositionX(), targetPosition.GetPositionY(), targetPosition.GetPositionZ(),
|
||||||
targetPosition.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT, true,
|
false, false, false, true, MovementPriority::MOVEMENT_COMBAT, true, backward);
|
||||||
backward);
|
|
||||||
|
|
||||||
if (bot->GetDistance(targetPosition) > 1.0f)
|
if (bot->GetDistance(targetPosition) > 1.0f)
|
||||||
return false;
|
return false;
|
||||||
@@ -2186,3 +2186,464 @@ bool ThorimPhase2PositioningAction::isUseful()
|
|||||||
ThorimPhase2PositioningTrigger thorimPhase2PositioningTrigger(botAI);
|
ThorimPhase2PositioningTrigger thorimPhase2PositioningTrigger(botAI);
|
||||||
return thorimPhase2PositioningTrigger.IsActive();
|
return thorimPhase2PositioningTrigger.IsActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MimironShockBlastAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
float radius = 20.0f;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leviathanMkII)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vx001 && !aerialCommandUnit)
|
||||||
|
{
|
||||||
|
float currentDistance = bot->GetDistance2d(leviathanMkII);
|
||||||
|
|
||||||
|
MoveAway(leviathanMkII, radius - currentDistance);
|
||||||
|
|
||||||
|
if (botAI->IsMelee(bot))
|
||||||
|
{
|
||||||
|
botAI->SetNextCheckDelay(100);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float init_angle = leviathanMkII->GetAngle(bot);
|
||||||
|
float distance = radius - bot->GetDistance2d(leviathanMkII);
|
||||||
|
for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8)
|
||||||
|
{
|
||||||
|
float angle = init_angle + delta;
|
||||||
|
float dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
|
float dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
|
float dz = bot->GetPositionZ();
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ(), dx, dy, dz))
|
||||||
|
{
|
||||||
|
bot->TeleportTo(target->GetMapId(), dx, dy, dz, target->GetOrientation());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironShockBlastAction::isUseful()
|
||||||
|
{
|
||||||
|
MimironShockBlastTrigger mimironShockBlastTrigger(botAI);
|
||||||
|
return mimironShockBlastTrigger.IsActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironPhase1PositioningAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(float, "disperse distance", 6.0f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironPhase1PositioningAction::isUseful()
|
||||||
|
{
|
||||||
|
MimironPhase1PositioningTrigger mimironPhase1PositioningTrigger(botAI);
|
||||||
|
return mimironPhase1PositioningTrigger.IsActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironP3Wx2LaserBarrageAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
auto master = botAI->GetMaster();
|
||||||
|
if (!master || !master->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot->GetDistance2d(master) > 15.0f)
|
||||||
|
{
|
||||||
|
return bot->TeleportTo(master->GetMapId(), master->GetPositionX(), master->GetPositionY(),
|
||||||
|
master->GetPositionZ(), master->GetOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
return MoveTo(master->GetMapId(), master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), false,
|
||||||
|
false, false, true, MovementPriority::MOVEMENT_COMBAT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRapidBurstAction::isUseful()
|
||||||
|
{
|
||||||
|
MimironRapidBurstTrigger mimironRapidBurstTrigger(botAI);
|
||||||
|
return mimironRapidBurstTrigger.IsActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRapidBurstAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Position targetPosition;
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 memberSpotNumber = 0;
|
||||||
|
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||||
|
{
|
||||||
|
Player* member = gref->GetSource();
|
||||||
|
if (!member)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bot->GetGUID() == member->GetGUID())
|
||||||
|
{
|
||||||
|
if (botAI->IsRanged(bot))
|
||||||
|
{
|
||||||
|
switch (memberSpotNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE1RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE2RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE3RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (botAI->IsMainTank(bot) && leviathanMkII)
|
||||||
|
{
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE4_TANK_SPOT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (memberSpotNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE1MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE2MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
targetPosition = ULDUAR_MIMIRON_PHASE2_SIDE3MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memberSpotNumber++;
|
||||||
|
|
||||||
|
if (memberSpotNumber == 3)
|
||||||
|
{
|
||||||
|
memberSpotNumber = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveTo(bot->GetMapId(), targetPosition.GetPositionX(), targetPosition.GetPositionY(), targetPosition.GetPositionZ(),
|
||||||
|
false, false, false, true, MovementPriority::MOVEMENT_FORCED, true, false);
|
||||||
|
|
||||||
|
if (AI_VALUE(float, "disperse distance") != 0.0f)
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(float, "disperse distance", 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TankFaceStrategy tankFaceStrategy(botAI);
|
||||||
|
if (botAI->HasStrategy(tankFaceStrategy.getName(), BotState::BOT_STATE_COMBAT))
|
||||||
|
{
|
||||||
|
botAI->ChangeStrategy(REMOVE_STRATEGY_CHAR + tankFaceStrategy.getName(), BotState::BOT_STATE_COMBAT);
|
||||||
|
}
|
||||||
|
if (botAI->HasStrategy(tankFaceStrategy.getName(), BotState::BOT_STATE_NON_COMBAT))
|
||||||
|
{
|
||||||
|
botAI->ChangeStrategy(REMOVE_STRATEGY_CHAR + tankFaceStrategy.getName(), BotState::BOT_STATE_NON_COMBAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bot->GetDistance(targetPosition) > 1.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironAerialCommandUnitAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* boss = nullptr;
|
||||||
|
Unit* bombBot = nullptr;
|
||||||
|
Unit* assaultBot = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
boss = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_BOMB_BOT)
|
||||||
|
{
|
||||||
|
bombBot = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_ASSAULT_BOT)
|
||||||
|
{
|
||||||
|
assaultBot = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMainTank(bot) || botAI->IsAssistTankOfIndex(bot, 0))
|
||||||
|
{
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bombBot)
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(crossIndex, bot->GetGUID(), bombBot->GetGUID());
|
||||||
|
}
|
||||||
|
else if (boss)
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(crossIndex, bot->GetGUID(), boss->GetGUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assaultBot)
|
||||||
|
{
|
||||||
|
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
|
||||||
|
Unit* skullUnit = botAI->GetUnit(skullTarget);
|
||||||
|
if (!skullTarget || !skullUnit || !skullUnit->IsAlive())
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(skullIndex, bot->GetGUID(), assaultBot->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AI_VALUE(float, "disperse distance") != 5.0f)
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(float, "disperse distance", 5.0f);
|
||||||
|
}
|
||||||
|
botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Set("cross");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRocketStrikeAction::isUseful()
|
||||||
|
{
|
||||||
|
MimironRocketStrikeTrigger mimironRocketStrikeTrigger(botAI);
|
||||||
|
return mimironRocketStrikeTrigger.IsActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRocketStrikeAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Creature* rocketStrikeN = bot->FindNearestCreature(NPC_ROCKET_STRIKE_N, 100.0f);
|
||||||
|
|
||||||
|
if (!rocketStrikeN)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vx001 && !aerialCommandUnit)
|
||||||
|
{
|
||||||
|
MoveAway(rocketStrikeN, 10.0f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float init_angle = rocketStrikeN->GetAngle(bot);
|
||||||
|
float distance = 10.0f - bot->GetDistance2d(rocketStrikeN);
|
||||||
|
for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8)
|
||||||
|
{
|
||||||
|
float angle = init_angle + delta;
|
||||||
|
float dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
|
float dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
|
float dz = bot->GetPositionZ();
|
||||||
|
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ(), dx, dy, dz))
|
||||||
|
{
|
||||||
|
bot->TeleportTo(target->GetMapId(), dx, dy, dz, target->GetOrientation());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironPhase4MarkDpsAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leviathanMkII || !vx001 || !aerialCommandUnit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMainTank(bot))
|
||||||
|
{
|
||||||
|
Unit* highestHealthUnit = nullptr;
|
||||||
|
uint32 highestHealth = 0;
|
||||||
|
if (leviathanMkII && leviathanMkII->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealth = leviathanMkII->GetHealth();
|
||||||
|
highestHealthUnit = leviathanMkII;
|
||||||
|
}
|
||||||
|
if (vx001 && vx001->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealth = vx001->GetHealth();
|
||||||
|
highestHealthUnit = vx001;
|
||||||
|
}
|
||||||
|
if (aerialCommandUnit && aerialCommandUnit->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealthUnit = aerialCommandUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
group->SetTargetIcon(skullIndex, bot->GetGUID(), highestHealthUnit->GetGUID());
|
||||||
|
if (highestHealthUnit == leviathanMkII)
|
||||||
|
{
|
||||||
|
if (AI_VALUE(std::string, "rti") == "skull")
|
||||||
|
{
|
||||||
|
botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Set("skull");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(crossIndex, bot->GetGUID(), leviathanMkII->GetGUID());
|
||||||
|
if (AI_VALUE(std::string, "rti") != "cross")
|
||||||
|
{
|
||||||
|
botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Set("cross");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
botAI->DoSpecificAction("attack rti target");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*if (AI_VALUE(float, "disperse distance") != 0.0f)
|
||||||
|
{
|
||||||
|
SET_AI_VALUE(float, "disperse distance", 0.0f);
|
||||||
|
}*/
|
||||||
|
botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Set("skull");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironCheatAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
|
||||||
|
for (const ObjectGuid& guid : targets)
|
||||||
|
{
|
||||||
|
Unit* unit = botAI->GetUnit(guid);
|
||||||
|
if (!unit || !unit->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (unit->GetEntry() == NPC_PROXIMITY_MINE)
|
||||||
|
{
|
||||||
|
unit->Kill(bot, unit);
|
||||||
|
}
|
||||||
|
else if (unit->GetEntry() == NPC_BOMB_BOT)
|
||||||
|
{
|
||||||
|
unit->Kill(bot, unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -278,4 +278,80 @@ public:
|
|||||||
bool isUseful() override;
|
bool isUseful() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MimironShockBlastAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironShockBlastAction(PlayerbotAI* ai) : MovementAction(ai, "mimiron shock blast action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironPhase1PositioningAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironPhase1PositioningAction(PlayerbotAI* ai) : MovementAction(ai, "mimiron phase 1 positioning action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironP3Wx2LaserBarrageAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironP3Wx2LaserBarrageAction(PlayerbotAI* ai, float distance = 24.0f, float delta_angle = M_PI / 8)
|
||||||
|
: MovementAction(ai, "mimiron p3wx2 laser barrage action")
|
||||||
|
{
|
||||||
|
this->distance = distance;
|
||||||
|
this->delta_angle = delta_angle;
|
||||||
|
}
|
||||||
|
virtual bool Execute(Event event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float distance, delta_angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironRapidBurstAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironRapidBurstAction(PlayerbotAI* ai) : MovementAction(ai, "mimiron rapid burst action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironAerialCommandUnitAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironAerialCommandUnitAction(PlayerbotAI* ai) : Action(ai, "mimiron aerial command unit action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironRocketStrikeAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironRocketStrikeAction(PlayerbotAI* ai) : MovementAction(ai, "mimiron rocket strike action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
bool isUseful() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironPhase4MarkDpsAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironPhase4MarkDpsAction(PlayerbotAI* ai) : Action(ai, "mimiron phase 4 mark dps action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironCheatAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironCheatAction(PlayerbotAI* ai) : Action(ai, "mimiron cheat action") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -190,9 +190,41 @@ void RaidUlduarStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
//
|
//
|
||||||
// Mimiron
|
// Mimiron
|
||||||
//
|
//
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron p3wx2 laser barrage trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron p3wx2 laser barrage action", ACTION_RAID + 2), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron shock blast trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron shock blast action", ACTION_RAID + 1), nullptr)));
|
||||||
|
|
||||||
triggers.push_back(new TriggerNode(
|
triggers.push_back(new TriggerNode(
|
||||||
"mimiron fire resistance trigger",
|
"mimiron fire resistance trigger",
|
||||||
NextAction::array(0, new NextAction("mimiron fire resistance action", ACTION_RAID), nullptr)));
|
NextAction::array(0, new NextAction("mimiron fire resistance action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron phase 1 positioning trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron phase 1 positioning action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron rapid burst trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron rapid burst action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron aerial command unit trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron aerial command unit action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron rocket strike trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron rocket strike action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron phase 4 mark dps trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron phase 4 mark dps action", ACTION_RAID), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(new TriggerNode(
|
||||||
|
"mimiron cheat trigger",
|
||||||
|
NextAction::array(0, new NextAction("mimiron cheat action", ACTION_RAID), nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaidUlduarStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
void RaidUlduarStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ public:
|
|||||||
creators["thorim fall from floor trigger"] = &RaidUlduarTriggerContext::thorim_fall_from_floor_trigger;
|
creators["thorim fall from floor trigger"] = &RaidUlduarTriggerContext::thorim_fall_from_floor_trigger;
|
||||||
creators["thorim phase 2 positioning trigger"] = &RaidUlduarTriggerContext::thorim_phase2_positioning_trigger;
|
creators["thorim phase 2 positioning trigger"] = &RaidUlduarTriggerContext::thorim_phase2_positioning_trigger;
|
||||||
creators["mimiron fire resistance trigger"] = &RaidUlduarTriggerContext::mimiron_fire_resistance_trigger;
|
creators["mimiron fire resistance trigger"] = &RaidUlduarTriggerContext::mimiron_fire_resistance_trigger;
|
||||||
|
creators["mimiron shock blast trigger"] = &RaidUlduarTriggerContext::mimiron_shock_blast_trigger;
|
||||||
|
creators["mimiron phase 1 positioning trigger"] = &RaidUlduarTriggerContext::mimiron_phase_1_positioning_trigger;
|
||||||
|
creators["mimiron p3wx2 laser barrage trigger"] = &RaidUlduarTriggerContext::mimiron_p3wx2_laser_barrage_trigger;
|
||||||
|
creators["mimiron rapid burst trigger"] = &RaidUlduarTriggerContext::mimiron_rapid_burst_trigger;
|
||||||
|
creators["mimiron aerial command unit trigger"] = &RaidUlduarTriggerContext::mimiron_aerial_command_unit_trigger;
|
||||||
|
creators["mimiron rocket strike trigger"] = &RaidUlduarTriggerContext::mimiron_rocket_strike_trigger;
|
||||||
|
creators["mimiron phase 4 mark dps trigger"] = &RaidUlduarTriggerContext::mimiron_phase_4_mark_dps_trigger;
|
||||||
|
creators["mimiron cheat trigger"] = &RaidUlduarTriggerContext::mimiron_cheat_trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -99,6 +107,14 @@ private:
|
|||||||
static Trigger* thorim_fall_from_floor_trigger(PlayerbotAI* ai) { return new ThorimFallFromFloorTrigger(ai); }
|
static Trigger* thorim_fall_from_floor_trigger(PlayerbotAI* ai) { return new ThorimFallFromFloorTrigger(ai); }
|
||||||
static Trigger* thorim_phase2_positioning_trigger(PlayerbotAI* ai) { return new ThorimPhase2PositioningTrigger(ai); }
|
static Trigger* thorim_phase2_positioning_trigger(PlayerbotAI* ai) { return new ThorimPhase2PositioningTrigger(ai); }
|
||||||
static Trigger* mimiron_fire_resistance_trigger(PlayerbotAI* ai) { return new BossFireResistanceTrigger(ai, "mimiron"); }
|
static Trigger* mimiron_fire_resistance_trigger(PlayerbotAI* ai) { return new BossFireResistanceTrigger(ai, "mimiron"); }
|
||||||
|
static Trigger* mimiron_shock_blast_trigger(PlayerbotAI* ai) { return new MimironShockBlastTrigger(ai); }
|
||||||
|
static Trigger* mimiron_phase_1_positioning_trigger(PlayerbotAI* ai) { return new MimironPhase1PositioningTrigger(ai); }
|
||||||
|
static Trigger* mimiron_p3wx2_laser_barrage_trigger(PlayerbotAI* ai) { return new MimironP3Wx2LaserBarrageTrigger(ai); }
|
||||||
|
static Trigger* mimiron_rapid_burst_trigger(PlayerbotAI* ai) { return new MimironRapidBurstTrigger(ai); }
|
||||||
|
static Trigger* mimiron_aerial_command_unit_trigger(PlayerbotAI* ai) { return new MimironAerialCommandUnitTrigger(ai); }
|
||||||
|
static Trigger* mimiron_rocket_strike_trigger(PlayerbotAI* ai) { return new MimironRocketStrikeTrigger(ai); }
|
||||||
|
static Trigger* mimiron_phase_4_mark_dps_trigger(PlayerbotAI* ai) { return new MimironPhase4MarkDpsTrigger(ai); }
|
||||||
|
static Trigger* mimiron_cheat_trigger(PlayerbotAI* ai) { return new MimironCheatTrigger(ai); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
#include "Trigger.h"
|
#include "Trigger.h"
|
||||||
#include "Vehicle.h"
|
#include "Vehicle.h"
|
||||||
|
#include <MovementActions.h>
|
||||||
|
|
||||||
const std::vector<uint32> availableVehicles = {NPC_VEHICLE_CHOPPER, NPC_SALVAGED_DEMOLISHER,
|
const std::vector<uint32> availableVehicles = {NPC_VEHICLE_CHOPPER, NPC_SALVAGED_DEMOLISHER,
|
||||||
NPC_SALVAGED_DEMOLISHER_TURRET, NPC_SALVAGED_SIEGE_ENGINE,
|
NPC_SALVAGED_DEMOLISHER_TURRET, NPC_SALVAGED_SIEGE_ENGINE,
|
||||||
@@ -1108,3 +1109,451 @@ bool ThorimPhase2PositioningTrigger::IsActive()
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MimironShockBlastTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* boss = AI_VALUE2(Unit*, "find target", "leviathan mk ii");
|
||||||
|
|
||||||
|
// Check boss and it is alive
|
||||||
|
if (!boss || !boss->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boss->HasUnitState(UNIT_STATE_CASTING) || !boss->FindCurrentSpellBySpellId(SPELL_SHOCK_BLAST))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMelee(bot))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return bot->GetDistance2d(boss) < 15.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironPhase1PositioningTrigger::IsActive()
|
||||||
|
{
|
||||||
|
if (!botAI->IsRanged(bot))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leviathanMkII || !leviathanMkII->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AI_VALUE(float, "disperse distance") != 6.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironP3Wx2LaserBarrageTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* boss = AI_VALUE2(Unit*, "find target", "vx-001");
|
||||||
|
|
||||||
|
// Check boss and it is alive
|
||||||
|
if (!boss || !boss->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCasting = boss->HasUnitState(UNIT_STATE_CASTING);
|
||||||
|
bool isP3WX2LaserBarrage = boss->FindCurrentSpellBySpellId(SPELL_SPINNING_UP) ||
|
||||||
|
boss->FindCurrentSpellBySpellId(SPELL_P3WX2_LASER_BARRAGE_1) ||
|
||||||
|
boss->FindCurrentSpellBySpellId(SPELL_P3WX2_LASER_BARRAGE_2) ||
|
||||||
|
boss->FindCurrentSpellBySpellId(SPELL_P3WX2_LASER_BARRAGE_AURA_1) ||
|
||||||
|
boss->FindCurrentSpellBySpellId(SPELL_P3WX2_LASER_BARRAGE_AURA_2) ||
|
||||||
|
boss->FindCurrentSpellBySpellId(SPELL_P3WX2_LASER_BARRAGE_3);
|
||||||
|
bool hasP3WX2LaserBarrageAura =
|
||||||
|
boss->HasAura(SPELL_P3WX2_LASER_BARRAGE_AURA_1) || boss->HasAura(SPELL_P3WX2_LASER_BARRAGE_AURA_2);
|
||||||
|
|
||||||
|
if ((!isCasting && !hasP3WX2LaserBarrageAura) || !isP3WX2LaserBarrage)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRapidBurstTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vx001 || !vx001->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leviathanMkII && leviathanMkII->HasUnitState(UNIT_STATE_CASTING) &&
|
||||||
|
leviathanMkII->FindCurrentSpellBySpellId(SPELL_SHOCK_BLAST))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMainTank(bot) && leviathanMkII && leviathanMkII->IsAlive() && leviathanMkII->GetVictim() != bot)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMelee(bot) && !botAI->IsMainTank(bot) && leviathanMkII && aerialCommandUnit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MimironP3Wx2LaserBarrageTrigger mimironP3Wx2LaserBarrageTrigger(botAI);
|
||||||
|
if (mimironP3Wx2LaserBarrageTrigger.IsActive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 memberSpotNumber = 0;
|
||||||
|
Position memberPosition;
|
||||||
|
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||||
|
{
|
||||||
|
Player* member = gref->GetSource();
|
||||||
|
if (!member)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bot->GetGUID() == member->GetGUID())
|
||||||
|
{
|
||||||
|
if (botAI->IsRanged(bot))
|
||||||
|
{
|
||||||
|
switch (memberSpotNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE1RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE2RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE3RANGE_SPOT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (botAI->IsMainTank(bot) && leviathanMkII)
|
||||||
|
{
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE4_TANK_SPOT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (memberSpotNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE1MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE2MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
memberPosition = ULDUAR_MIMIRON_PHASE2_SIDE3MELEE_SPOT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberSpotNumber++;
|
||||||
|
|
||||||
|
if (memberSpotNumber == 3)
|
||||||
|
{
|
||||||
|
memberSpotNumber = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
|
||||||
|
float nearestRocketStrikeDistance = std::numeric_limits<float>::max();
|
||||||
|
bool rocketStrikeDetected = false;
|
||||||
|
|
||||||
|
for (const ObjectGuid& guid : npcs)
|
||||||
|
{
|
||||||
|
Unit* unit = botAI->GetUnit(guid);
|
||||||
|
if (!unit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (unit->GetEntry() == NPC_ROCKET_STRIKE_N)
|
||||||
|
{
|
||||||
|
rocketStrikeDetected = true;
|
||||||
|
float distance = bot->GetDistance2d(memberPosition.GetPositionX(), memberPosition.GetPositionY());
|
||||||
|
if (distance < nearestRocketStrikeDistance)
|
||||||
|
{
|
||||||
|
nearestRocketStrikeDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bot->GetDistance(memberPosition) > 7.0f && !rocketStrikeDetected) ||
|
||||||
|
bot->GetDistance(memberPosition) > 20.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironAerialCommandUnitTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
//Unit* bombBot = nullptr;
|
||||||
|
Unit* assaultBot = nullptr;
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
//else if (target->GetEntry() == NPC_BOMB_BOT)
|
||||||
|
//{
|
||||||
|
// bombBot = target;
|
||||||
|
//}
|
||||||
|
else if (target->GetEntry() == NPC_ASSAULT_BOT)
|
||||||
|
{
|
||||||
|
assaultBot = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aerialCommandUnit || !aerialCommandUnit->IsAlive() || leviathanMkII || vx001)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!botAI->IsRanged(bot) && !botAI->IsMainTank(bot) && !botAI->IsAssistTankOfIndex(bot, 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMainTank(bot) || botAI->IsAssistTankOfIndex(bot, 0))
|
||||||
|
{
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
|
||||||
|
ObjectGuid crossTarget = group->GetTargetIcon(crossIndex);
|
||||||
|
|
||||||
|
//if (bombBot && bombBot->GetGUID() != crossTarget)
|
||||||
|
//{
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
if (!crossTarget || aerialCommandUnit->GetGUID() != crossTarget)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (assaultBot && (!skullTarget || assaultBot->GetGUID() != skullTarget))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rtiMark = AI_VALUE(std::string, "rti");
|
||||||
|
if (rtiMark != "cross")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironRocketStrikeTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* boss = AI_VALUE2(Unit*, "find target", "vx-001");
|
||||||
|
|
||||||
|
// Check boss and it is alive
|
||||||
|
if (!boss || !boss->IsAlive())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Creature* rocketStrikeN = bot->FindNearestCreature(NPC_ROCKET_STRIKE_N, 100.0f);
|
||||||
|
|
||||||
|
if (!rocketStrikeN)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bot->GetDistance2d(rocketStrikeN->GetPositionX(), rocketStrikeN->GetPositionY()) <= 10.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironPhase4MarkDpsTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Unit* leviathanMkII = nullptr;
|
||||||
|
Unit* vx001 = nullptr;
|
||||||
|
Unit* aerialCommandUnit = nullptr;
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
Unit* target = nullptr;
|
||||||
|
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||||
|
{
|
||||||
|
target = botAI->GetUnit(*i);
|
||||||
|
if (!target || !target->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (target->GetEntry() == NPC_LEVIATHAN_MKII)
|
||||||
|
{
|
||||||
|
leviathanMkII = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_VX001)
|
||||||
|
{
|
||||||
|
vx001 = target;
|
||||||
|
}
|
||||||
|
else if (target->GetEntry() == NPC_AERIAL_COMMAND_UNIT)
|
||||||
|
{
|
||||||
|
aerialCommandUnit = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leviathanMkII || !vx001 || !aerialCommandUnit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botAI->IsMainTank(bot))
|
||||||
|
{
|
||||||
|
Unit* highestHealthUnit = nullptr;
|
||||||
|
uint32 highestHealth = 0;
|
||||||
|
|
||||||
|
if (leviathanMkII && leviathanMkII->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealth = leviathanMkII->GetHealth();
|
||||||
|
highestHealthUnit = leviathanMkII;
|
||||||
|
}
|
||||||
|
if (vx001 && vx001->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealth = vx001->GetHealth();
|
||||||
|
highestHealthUnit = vx001;
|
||||||
|
}
|
||||||
|
if (aerialCommandUnit && aerialCommandUnit->GetHealth() > highestHealth)
|
||||||
|
{
|
||||||
|
highestHealthUnit = aerialCommandUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
|
||||||
|
if (!skullTarget)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestHealthUnit->GetGUID() != skullTarget;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AI_VALUE(std::string, "rti") != "skull";
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MimironCheatTrigger::IsActive()
|
||||||
|
{
|
||||||
|
if (!botAI->IsMainTank(bot))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
|
||||||
|
for (const ObjectGuid& guid : targets)
|
||||||
|
{
|
||||||
|
Unit* unit = botAI->GetUnit(guid);
|
||||||
|
if (!unit || !unit->IsAlive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (unit->GetEntry() == NPC_PROXIMITY_MINE)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (unit->GetEntry() == NPC_BOMB_BOT)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,6 +62,22 @@ enum UlduarIDs
|
|||||||
NPC_IRON_HONOR_GUARD = 32875,
|
NPC_IRON_HONOR_GUARD = 32875,
|
||||||
SPELL_UNBALANCING_STRIKE = 62130,
|
SPELL_UNBALANCING_STRIKE = 62130,
|
||||||
|
|
||||||
|
//Mimiron
|
||||||
|
NPC_LEVIATHAN_MKII = 33432,
|
||||||
|
NPC_VX001 = 33651,
|
||||||
|
NPC_AERIAL_COMMAND_UNIT = 33670,
|
||||||
|
NPC_BOMB_BOT = 33836,
|
||||||
|
NPC_ROCKET_STRIKE_N = 34047,
|
||||||
|
NPC_ASSAULT_BOT = 34057,
|
||||||
|
NPC_PROXIMITY_MINE = 34362,
|
||||||
|
SPELL_P3WX2_LASER_BARRAGE_1 = 63293,
|
||||||
|
SPELL_P3WX2_LASER_BARRAGE_2 = 63297,
|
||||||
|
SPELL_SPINNING_UP = 63414,
|
||||||
|
SPELL_SHOCK_BLAST = 63631,
|
||||||
|
SPELL_P3WX2_LASER_BARRAGE_3 = 64042,
|
||||||
|
SPELL_P3WX2_LASER_BARRAGE_AURA_1 = 63274,
|
||||||
|
SPELL_P3WX2_LASER_BARRAGE_AURA_2 = 63300,
|
||||||
|
|
||||||
// Buffs
|
// Buffs
|
||||||
SPELL_FROST_TRAP = 13809
|
SPELL_FROST_TRAP = 13809
|
||||||
};
|
};
|
||||||
@@ -94,6 +110,13 @@ const Position ULDUAR_THORIM_PHASE2_TANK_SPOT = Position(2134.8572f, -287.0291f,
|
|||||||
const Position ULDUAR_THORIM_PHASE2_RANGE1_SPOT = Position(2112.8752f, -267.69305f, 419.52814f);
|
const Position ULDUAR_THORIM_PHASE2_RANGE1_SPOT = Position(2112.8752f, -267.69305f, 419.52814f);
|
||||||
const Position ULDUAR_THORIM_PHASE2_RANGE2_SPOT = Position(2129.09f, -277.142f, 419.67462f);
|
const Position ULDUAR_THORIM_PHASE2_RANGE2_SPOT = Position(2129.09f, -277.142f, 419.67462f);
|
||||||
const Position ULDUAR_THORIM_PHASE2_RANGE3_SPOT = Position(2156.798f, -267.57434f, 419.52722f);
|
const Position ULDUAR_THORIM_PHASE2_RANGE3_SPOT = Position(2156.798f, -267.57434f, 419.52722f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE1RANGE_SPOT = Position(2753.708f, 2583.9617f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE1MELEE_SPOT = Position(2746.9792f, 2573.6716f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE2RANGE_SPOT = Position(2727.7224f, 2569.527f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE2MELEE_SPOT = Position(2739.4746f, 2569.4106f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE3RANGE_SPOT = Position(2754.1294f, 2553.9954f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE2_SIDE3MELEE_SPOT = Position(2746.8513f, 2565.4263f, 364.31357f);
|
||||||
|
const Position ULDUAR_MIMIRON_PHASE4_TANK_SPOT = Position(2744.5754f, 2570.8657f, 364.3138f);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flame Levi
|
// Flame Levi
|
||||||
@@ -336,4 +359,63 @@ public:
|
|||||||
bool IsActive() override;
|
bool IsActive() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mimiron
|
||||||
|
//
|
||||||
|
class MimironShockBlastTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironShockBlastTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron shock blast trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironPhase1PositioningTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironPhase1PositioningTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron phase 1 positioning trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironP3Wx2LaserBarrageTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironP3Wx2LaserBarrageTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron p3wx2 laser barrage trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironRapidBurstTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironRapidBurstTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron rapid burst trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironAerialCommandUnitTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironAerialCommandUnitTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron aerial command unit trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironRocketStrikeTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironRocketStrikeTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron rocket strike trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironPhase4MarkDpsTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironPhase4MarkDpsTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron phase 4 mark dps trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MimironCheatTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MimironCheatTrigger(PlayerbotAI* ai) : Trigger(ai, "mimiron cheat trigger") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ void NearestNpcsValue::FindUnits(std::list<Unit*>& targets)
|
|||||||
Cell::VisitAllObjects(bot, searcher, range);
|
Cell::VisitAllObjects(bot, searcher, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NearestNpcsValue::AcceptUnit(Unit* unit) { return !unit->IsHostileTo(bot) && !unit->IsPlayer(); }
|
bool NearestNpcsValue::AcceptUnit(Unit* unit) { return !unit->IsPlayer(); }
|
||||||
|
|
||||||
void NearestHostileNpcsValue::FindUnits(std::list<Unit*>& targets)
|
void NearestHostileNpcsValue::FindUnits(std::list<Unit*>& targets)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user