mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-12-01 21:12:50 +08:00
Prelim EoE completion
This commit is contained in:
@@ -21,8 +21,8 @@ class WotlkDungeonOccActionContext : public NamedObjectContext<Action>
|
||||
static Action* avoid_unstable_sphere(PlayerbotAI* ai) { return new AvoidUnstableSphereAction(ai); }
|
||||
static Action* mount_drake(PlayerbotAI* ai) { return new MountDrakeAction(ai); }
|
||||
static Action* dismount_drake(PlayerbotAI* ai) { return new DismountDrakeAction(ai); }
|
||||
static Action* fly_drake(PlayerbotAI* ai) { return new FlyDrakeAction(ai); }
|
||||
static Action* drake_attack(PlayerbotAI* ai) { return new DrakeAttackAction(ai); }
|
||||
static Action* fly_drake(PlayerbotAI* ai) { return new OccFlyDrakeAction(ai); }
|
||||
static Action* drake_attack(PlayerbotAI* ai) { return new OccDrakeAttackAction(ai); }
|
||||
static Action* avoid_arcane_explosion(PlayerbotAI* ai) { return new AvoidArcaneExplosionAction(ai); }
|
||||
static Action* time_bomb_spread(PlayerbotAI* ai) { return new TimeBombSpreadAction(ai); }
|
||||
};
|
||||
|
||||
@@ -111,7 +111,7 @@ bool DismountDrakeAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FlyDrakeAction::Execute(Event event)
|
||||
bool OccFlyDrakeAction::Execute(Event event)
|
||||
{
|
||||
Player* master = botAI->GetMaster();
|
||||
if (!master) { return false; }
|
||||
@@ -152,7 +152,7 @@ bool FlyDrakeAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrakeAttackAction::Execute(Event event)
|
||||
bool OccDrakeAttackAction::Execute(Event event)
|
||||
{
|
||||
vehicleBase = bot->GetVehicleBase();
|
||||
if (!vehicleBase) { return false; }
|
||||
@@ -188,7 +188,7 @@ bool DrakeAttackAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrakeAttackAction::CastDrakeSpellAction(Unit* target, uint32 spellId, uint32 cooldown)
|
||||
bool OccDrakeAttackAction::CastDrakeSpellAction(Unit* target, uint32 spellId, uint32 cooldown)
|
||||
{
|
||||
if (botAI->CanCastVehicleSpell(spellId, target))
|
||||
if (botAI->CastVehicleSpell(spellId, target))
|
||||
@@ -199,7 +199,7 @@ bool DrakeAttackAction::CastDrakeSpellAction(Unit* target, uint32 spellId, uint3
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrakeAttackAction::AmberDrakeAction(Unit* target)
|
||||
bool OccDrakeAttackAction::AmberDrakeAction(Unit* target)
|
||||
{
|
||||
Aura* shockCharges = target->GetAura(SPELL_SHOCK_CHARGE, vehicleBase->GetGUID());
|
||||
if (shockCharges && shockCharges->GetStackAmount() > 8)
|
||||
@@ -225,7 +225,7 @@ bool DrakeAttackAction::AmberDrakeAction(Unit* target)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrakeAttackAction::EmeraldDrakeAction(Unit* target)
|
||||
bool OccDrakeAttackAction::EmeraldDrakeAction(Unit* target)
|
||||
{
|
||||
Aura* poisonStacks = target->GetAura(SPELL_LEECHING_POISON, vehicleBase->GetGUID());
|
||||
if (!poisonStacks || (poisonStacks->GetStackAmount() < 3 ||
|
||||
@@ -286,7 +286,7 @@ bool DrakeAttackAction::EmeraldDrakeAction(Unit* target)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrakeAttackAction::RubyDrakeAction(Unit* target)
|
||||
bool OccDrakeAttackAction::RubyDrakeAction(Unit* target)
|
||||
{
|
||||
Aura* evasiveCharges = vehicleBase->GetAura(SPELL_EVASIVE_CHARGES);
|
||||
Aura* evasiveManeuvers = vehicleBase->GetAura(SPELL_EVASIVE_MANEUVERS);
|
||||
|
||||
@@ -38,17 +38,17 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class FlyDrakeAction : public MovementAction
|
||||
class OccFlyDrakeAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
FlyDrakeAction(PlayerbotAI* ai) : MovementAction(ai, "fly drake") {}
|
||||
OccFlyDrakeAction(PlayerbotAI* ai) : MovementAction(ai, "occ fly drake") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class DrakeAttackAction : public Action
|
||||
class OccDrakeAttackAction : public Action
|
||||
{
|
||||
public:
|
||||
DrakeAttackAction(PlayerbotAI* botAI) : Action(botAI, "drake attack") {}
|
||||
OccDrakeAttackAction(PlayerbotAI* botAI) : Action(botAI, "occ drake attack") {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
protected:
|
||||
@@ -57,7 +57,6 @@ protected:
|
||||
bool AmberDrakeAction(Unit* target);
|
||||
bool EmeraldDrakeAction(Unit* target);
|
||||
bool RubyDrakeAction(Unit* target);
|
||||
|
||||
};
|
||||
|
||||
class AvoidArcaneExplosionAction : public MovementAction
|
||||
|
||||
@@ -26,12 +26,12 @@ float MountingDrakeMultiplier::GetValue(Action* action)
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float FlyingMultiplier::GetValue(Action* action)
|
||||
float OccFlyingMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (bot->GetMapId() != OCULUS_MAP_ID || !bot->GetVehicleBase()) { return 1.0f; }
|
||||
|
||||
// Suppresses FollowAction as well as some attack-based movements
|
||||
if (dynamic_cast<MovementAction*>(action) && !dynamic_cast<FlyDrakeAction*>(action))
|
||||
if (dynamic_cast<MovementAction*>(action) && !dynamic_cast<OccFlyDrakeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ float EregosMultiplier::GetValue(Action* action)
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "ley-guardian eregos");
|
||||
if (!boss) { return 1.0f; }
|
||||
|
||||
if (boss->HasAura(SPELL_PLANAR_SHIFT && dynamic_cast<DrakeAttackAction*>(action)))
|
||||
if (boss->HasAura(SPELL_PLANAR_SHIFT && dynamic_cast<OccDrakeAttackAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ class MountingDrakeMultiplier : public Multiplier
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class FlyingMultiplier : public Multiplier
|
||||
class OccFlyingMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
FlyingMultiplier(PlayerbotAI* ai) : Multiplier(ai, "flying drake") {}
|
||||
OccFlyingMultiplier(PlayerbotAI* ai) : Multiplier(ai, "occ flying drake") {}
|
||||
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
|
||||
@@ -36,7 +36,7 @@ void WotlkDungeonOccStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
|
||||
void WotlkDungeonOccStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
|
||||
{
|
||||
multipliers.push_back(new MountingDrakeMultiplier(botAI));
|
||||
multipliers.push_back(new FlyingMultiplier(botAI));
|
||||
multipliers.push_back(new OccFlyingMultiplier(botAI));
|
||||
multipliers.push_back(new UromMultiplier(botAI));
|
||||
multipliers.push_back(new EregosMultiplier(botAI));
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "RaidBwlStrategy.h"
|
||||
#include "RaidNaxxStrategy.h"
|
||||
#include "RaidOsStrategy.h"
|
||||
#include "RaidEoEStrategy.h"
|
||||
#include "RaidMcStrategy.h"
|
||||
#include "RaidAq20Strategy.h"
|
||||
#include "RaidIccStrategy.h"
|
||||
@@ -23,6 +24,7 @@ public:
|
||||
creators["aq20"] = &RaidStrategyContext::aq20;
|
||||
creators["naxx"] = &RaidStrategyContext::naxx;
|
||||
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
|
||||
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
|
||||
creators["uld"] = &RaidStrategyContext::uld;
|
||||
creators["icc"] = &RaidStrategyContext::icc;
|
||||
}
|
||||
@@ -33,6 +35,7 @@ private:
|
||||
static Strategy* aq20(PlayerbotAI* botAI) { return new RaidAq20Strategy(botAI); }
|
||||
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
||||
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
|
||||
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
|
||||
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
|
||||
static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); }
|
||||
};
|
||||
|
||||
@@ -10,21 +10,21 @@ class RaidEoEActionContext : public NamedObjectContext<Action>
|
||||
public:
|
||||
RaidEoEActionContext()
|
||||
{
|
||||
// creators["sartharion tank position"] = &RaidOsActionContext::tank_position;
|
||||
// creators["avoid twilight fissure"] = &RaidOsActionContext::avoid_twilight_fissure;
|
||||
// creators["avoid flame tsunami"] = &RaidOsActionContext::avoid_flame_tsunami;
|
||||
// creators["sartharion attack priority"] = &RaidOsActionContext::attack_priority;
|
||||
// creators["enter twilight portal"] = &RaidOsActionContext::enter_twilight_portal;
|
||||
// creators["exit twilight portal"] = &RaidOsActionContext::exit_twilight_portal;
|
||||
creators["malygos position"] = &RaidEoEActionContext::position;
|
||||
creators["malygos target"] = &RaidEoEActionContext::target;
|
||||
// creators["pull power spark"] = &RaidEoEActionContext::pull_power_spark;
|
||||
// creators["kill power spark"] = &RaidEoEActionContext::kill_power_spark;
|
||||
creators["fly drake"] = &RaidEoEActionContext::fly_drake;
|
||||
creators["drake attack"] = &RaidEoEActionContext::drake_attack;
|
||||
}
|
||||
|
||||
private:
|
||||
// static Action* tank_position(PlayerbotAI* ai) { return new SartharionTankPositionAction(ai); }
|
||||
// static Action* avoid_twilight_fissure(PlayerbotAI* ai) { return new AvoidTwilightFissureAction(ai); }
|
||||
// static Action* avoid_flame_tsunami(PlayerbotAI* ai) { return new AvoidFlameTsunamiAction(ai); }
|
||||
// static Action* attack_priority(PlayerbotAI* ai) { return new SartharionAttackPriorityAction(ai); }
|
||||
// static Action* enter_twilight_portal(PlayerbotAI* ai) { return new EnterTwilightPortalAction(ai); }
|
||||
// static Action* exit_twilight_portal(PlayerbotAI* ai) { return new ExitTwilightPortalAction(ai); }
|
||||
static Action* position(PlayerbotAI* ai) { return new MalygosPositionAction(ai); }
|
||||
static Action* target(PlayerbotAI* ai) { return new MalygosTargetAction(ai); }
|
||||
// static Action* pull_power_spark(PlayerbotAI* ai) { return new PullPowerSparkAction(ai); }
|
||||
// static Action* kill_power_spark(PlayerbotAI* ai) { return new KillPowerSparkAction(ai); }
|
||||
static Action* fly_drake(PlayerbotAI* ai) { return new EoEFlyDrakeAction(ai); }
|
||||
static Action* drake_attack(PlayerbotAI* ai) { return new EoEDrakeAttackAction(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,244 +3,388 @@
|
||||
|
||||
#include "Playerbots.h"
|
||||
|
||||
// bool SartharionTankPositionAction::Execute(Event event)
|
||||
|
||||
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; }
|
||||
|
||||
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* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
// Unit* spark = nullptr;
|
||||
|
||||
// // Unit* shadron = AI_VALUE2(Unit*, "find target", "shadron");
|
||||
// // Unit* tenebron = AI_VALUE2(Unit*, "find target", "tenebron");
|
||||
// // Unit* vesperon = AI_VALUE2(Unit*, "find target", "vesperon");
|
||||
// Unit* shadron = nullptr;
|
||||
// Unit* tenebron = nullptr;
|
||||
// Unit* vesperon = nullptr;
|
||||
|
||||
// // Detect incoming drakes before they are on aggro table
|
||||
// GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
|
||||
// for (auto& target : targets)
|
||||
// {
|
||||
// Unit* unit = botAI->GetUnit(target);
|
||||
// if (!unit) { continue; }
|
||||
|
||||
// switch (unit->GetEntry())
|
||||
// if (unit && unit->GetEntry() == NPC_POWER_SPARK)
|
||||
// {
|
||||
// case NPC_SHADRON:
|
||||
// shadron = unit;
|
||||
// continue;
|
||||
// case NPC_TENEBRON:
|
||||
// tenebron = unit;
|
||||
// continue;
|
||||
// case NPC_VESPERON:
|
||||
// vesperon = unit;
|
||||
// continue;
|
||||
// default:
|
||||
// continue;
|
||||
// spark = unit;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Position currentPos = bot->GetPosition();
|
||||
// // Adjustable, this is the acceptable distance to stack point that will be accepted as "safe"
|
||||
// float looseDistance = 12.0f;
|
||||
// if (!spark) { return false; }
|
||||
|
||||
// if (botAI->IsMainTank(bot))
|
||||
// if (spark->GetDistance2d(MALYGOS_STACK_POSITION.first, MALYGOS_STACK_POSITION.second) > 3.0f)
|
||||
// {
|
||||
// if (bot->GetExactDist2d(SARTHARION_MAINTANK_POSITION.first, SARTHARION_MAINTANK_POSITION.second) > looseDistance)
|
||||
// {
|
||||
// return MoveTo(OS_MAP_ID, SARTHARION_MAINTANK_POSITION.first, SARTHARION_MAINTANK_POSITION.second, currentPos.GetPositionZ(),
|
||||
// false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
|
||||
// }
|
||||
// }
|
||||
// // Offtank grab drakes
|
||||
// else if (shadron || tenebron || vesperon)
|
||||
// {
|
||||
// float triggerDistance = 100.0f;
|
||||
// // Prioritise threat before positioning
|
||||
// if (tenebron && bot->GetExactDist2d(tenebron) < triggerDistance &&
|
||||
// tenebron->GetTarget() != bot->GetGUID() && AI_VALUE(Unit*, "current target") != tenebron)
|
||||
// {
|
||||
// return Attack(tenebron);
|
||||
// }
|
||||
// if (shadron && bot->GetExactDist2d(shadron) < triggerDistance &&
|
||||
// shadron->GetTarget() != bot->GetGUID() && AI_VALUE(Unit*, "current target") != shadron)
|
||||
// {
|
||||
// return Attack(shadron);
|
||||
// }
|
||||
// if (vesperon && bot->GetExactDist2d(vesperon) < triggerDistance &&
|
||||
// vesperon->GetTarget() != bot->GetGUID() && AI_VALUE(Unit*, "current target") != vesperon)
|
||||
// {
|
||||
// return Attack(vesperon);
|
||||
// }
|
||||
|
||||
// bool drakeInCombat = (tenebron && bot->GetExactDist2d(tenebron) < triggerDistance) ||
|
||||
// (shadron && bot->GetExactDist2d(shadron) < triggerDistance) ||
|
||||
// (vesperon && bot->GetExactDist2d(vesperon) < triggerDistance);
|
||||
// // Offtank has threat on drakes, check positioning
|
||||
// if (drakeInCombat && bot->GetExactDist2d(SARTHARION_OFFTANK_POSITION.first, SARTHARION_OFFTANK_POSITION.second) > looseDistance)
|
||||
// {
|
||||
// return MoveTo(OS_MAP_ID, SARTHARION_OFFTANK_POSITION.first, SARTHARION_OFFTANK_POSITION.second, currentPos.GetPositionZ(),
|
||||
// false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool AvoidTwilightFissureAction::Execute(Event event)
|
||||
// {
|
||||
// const float radius = 5.0f;
|
||||
|
||||
// GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
|
||||
// for (auto& npc : npcs)
|
||||
// {
|
||||
// Unit* unit = botAI->GetUnit(npc);
|
||||
// if (unit && unit->GetEntry() == NPC_TWILIGHT_FISSURE)
|
||||
// {
|
||||
// float currentDistance = bot->GetDistance2d(unit);
|
||||
// if (currentDistance < radius)
|
||||
// {
|
||||
// return MoveAway(unit, radius - currentDistance);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool AvoidFlameTsunamiAction::Execute(Event event)
|
||||
// {
|
||||
// // Adjustable, this is the acceptable distance to stack point that will be accepted as "safe"
|
||||
// float looseDistance = 4.0f;
|
||||
|
||||
// GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
|
||||
// for (auto& npc : npcs)
|
||||
// {
|
||||
// Unit* unit = botAI->GetUnit(npc);
|
||||
// if (unit && unit->GetEntry() == NPC_FLAME_TSUNAMI)
|
||||
// {
|
||||
// Position currentPos = bot->GetPosition();
|
||||
|
||||
// // I think these are centrepoints for the wave segments. Either way they uniquely identify the wave
|
||||
// // direction as they have different coords for the left and right waves
|
||||
// // int casting is not a mistake, need to avoid FP errors somehow.
|
||||
// // I always saw these accurate to around 6 decimal places, but if there are issues,
|
||||
// // can switch this to abs comparison of floats which would technically be more robust.
|
||||
// int posY = (int) unit->GetPositionY();
|
||||
// if (posY == 505 || posY == 555) // RIGHT WAVE
|
||||
// {
|
||||
// bool wavePassed = currentPos.GetPositionX() > unit->GetPositionX();
|
||||
// if (wavePassed)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (bot->GetExactDist2d(currentPos.GetPositionX(), TSUNAMI_RIGHT_SAFE_ALL) > looseDistance)
|
||||
// {
|
||||
// return MoveTo(OS_MAP_ID, currentPos.GetPositionX(), TSUNAMI_RIGHT_SAFE_ALL, currentPos.GetPositionZ(),
|
||||
// false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
|
||||
// }
|
||||
// }
|
||||
// else // LEFT WAVE
|
||||
// {
|
||||
// bool wavePassed = currentPos.GetPositionX() < unit->GetPositionX();
|
||||
// if (wavePassed)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (botAI->IsMelee(bot))
|
||||
// {
|
||||
// if (bot->GetExactDist2d(currentPos.GetPositionX(), TSUNAMI_LEFT_SAFE_MELEE) > looseDistance)
|
||||
// {
|
||||
// return MoveTo(OS_MAP_ID, currentPos.GetPositionX(), TSUNAMI_LEFT_SAFE_MELEE, currentPos.GetPositionZ(),
|
||||
// false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
|
||||
// }
|
||||
// }
|
||||
// else // Ranged/healers
|
||||
// {
|
||||
// if (bot->GetExactDist2d(currentPos.GetPositionX(), TSUNAMI_LEFT_SAFE_RANGED) > looseDistance)
|
||||
// {
|
||||
// return MoveTo(OS_MAP_ID, currentPos.GetPositionX(), TSUNAMI_LEFT_SAFE_RANGED, currentPos.GetPositionZ(),
|
||||
// false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool SartharionAttackPriorityAction::Execute(Event event)
|
||||
// {
|
||||
// Unit* sartharion = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// Unit* shadron = AI_VALUE2(Unit*, "find target", "shadron");
|
||||
// Unit* tenebron = AI_VALUE2(Unit*, "find target", "tenebron");
|
||||
// Unit* vesperon = AI_VALUE2(Unit*, "find target", "vesperon");
|
||||
// Unit* acolyte = AI_VALUE2(Unit*, "find target", "acolyte of shadron");
|
||||
|
||||
// Unit* target = nullptr;
|
||||
|
||||
// if (acolyte)
|
||||
// {
|
||||
// target = acolyte;
|
||||
// }
|
||||
// else if (vesperon)
|
||||
// {
|
||||
// target = vesperon;
|
||||
// }
|
||||
// else if (tenebron)
|
||||
// {
|
||||
// target = tenebron;
|
||||
// }
|
||||
// else if (shadron)
|
||||
// {
|
||||
// target = shadron;
|
||||
// }
|
||||
// else if (sartharion)
|
||||
// {
|
||||
// target = sartharion;
|
||||
// }
|
||||
|
||||
// if (target && AI_VALUE(Unit*, "current target") != target)
|
||||
// {
|
||||
// return Attack(target);
|
||||
// bot->Yell("GRIPPING SPARK", LANG_UNIVERSAL);
|
||||
// return botAI->CastSpell("death grip", spark);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool EnterTwilightPortalAction::Execute(Event event)
|
||||
// bool PullPowerSparkAction::isPossible()
|
||||
// {
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss || !boss->HasAura(SPELL_GIFT_OF_TWILIGHT_FIRE)) { return false; }
|
||||
// Unit* spark = nullptr;
|
||||
|
||||
// GameObject* portal = bot->FindNearestGameObject(GO_TWILIGHT_PORTAL, 100.0f);
|
||||
// if (!portal) { return false; }
|
||||
|
||||
// if (!portal->IsAtInteractDistance(bot))
|
||||
// GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
|
||||
// for (auto& target : targets)
|
||||
// {
|
||||
// return MoveTo(portal, fmaxf(portal->GetInteractionDistance() - 1.0f, 0.0f));
|
||||
// Unit* unit = botAI->GetUnit(target);
|
||||
// if (unit && unit->GetEntry() == NPC_POWER_SPARK)
|
||||
// {
|
||||
// spark = unit;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Go through portal
|
||||
// WorldPacket data1(CMSG_GAMEOBJ_USE);
|
||||
// data1 << portal->GetGUID();
|
||||
// bot->GetSession()->HandleGameObjectUseOpcode(data1);
|
||||
|
||||
// return true;
|
||||
// return botAI->CanCastSpell(spell, spark);
|
||||
// }
|
||||
|
||||
// bool ExitTwilightPortalAction::Execute(Event event)
|
||||
// bool PullPowerSparkAction::isUseful()
|
||||
// {
|
||||
// GameObject* portal = bot->FindNearestGameObject(GO_NORMAL_PORTAL, 100.0f);
|
||||
// if (!portal) { return false; }
|
||||
// Unit* spark = nullptr;
|
||||
|
||||
// if (!portal->IsAtInteractDistance(bot))
|
||||
// GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
|
||||
// for (auto& target : targets)
|
||||
// {
|
||||
// return MoveTo(portal, fmaxf(portal->GetInteractionDistance() - 1.0f, 0.0f));
|
||||
// Unit* unit = botAI->GetUnit(target);
|
||||
// if (unit && unit->GetEntry() == NPC_POWER_SPARK)
|
||||
// {
|
||||
// spark = unit;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Go through portal
|
||||
// WorldPacket data1(CMSG_GAMEOBJ_USE);
|
||||
// data1 << portal->GetGUID();
|
||||
// bot->GetSession()->HandleGameObjectUseOpcode(data1);
|
||||
// if (!spark)
|
||||
// return false;
|
||||
|
||||
// return true;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,62 +3,67 @@
|
||||
|
||||
#include "MovementActions.h"
|
||||
#include "AttackAction.h"
|
||||
#include "GenericSpellActions.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
// const float TSUNAMI_LEFT_SAFE_MELEE = 552.0f;
|
||||
// const float TSUNAMI_LEFT_SAFE_RANGED = 504.0f;
|
||||
// const float TSUNAMI_RIGHT_SAFE_ALL = 529.0f;
|
||||
// const std::pair<float, float> SARTHARION_MAINTANK_POSITION = {3258.5f, 532.5f};
|
||||
// const std::pair<float, float> SARTHARION_OFFTANK_POSITION = {3230.0f, 526.0f};
|
||||
// const std::pair<float, float> SARTHARION_RANGED_POSITION = {3248.0f, 507.0f};
|
||||
const std::pair<float, float> MALYGOS_MAINTANK_POSITION = {757.0f, 1337.0f};
|
||||
const std::pair<float, float> MALYGOS_STACK_POSITION = {755.0f, 1301.0f};
|
||||
|
||||
// class SartharionTankPositionAction : public AttackAction
|
||||
// {
|
||||
// public:
|
||||
// SartharionTankPositionAction(PlayerbotAI* botAI, std::string const name = "sartharion tank position")
|
||||
// : AttackAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class MalygosPositionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
MalygosPositionAction(PlayerbotAI* botAI, std::string const name = "malygos position")
|
||||
: MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
// class AvoidTwilightFissureAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// AvoidTwilightFissureAction(PlayerbotAI* botAI, std::string const name = "avoid twilight fissure")
|
||||
// : MovementAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class MalygosTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
MalygosTargetAction(PlayerbotAI* botAI, std::string const name = "malygos target")
|
||||
: AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
// class AvoidFlameTsunamiAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// AvoidFlameTsunamiAction(PlayerbotAI* botAI, std::string const name = "avoid flame tsunami")
|
||||
// : MovementAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class PullPowerSparkAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
PullPowerSparkAction(PlayerbotAI* botAI, std::string const name = "pull power spark")
|
||||
: CastSpellAction(botAI, "death grip") {}
|
||||
bool Execute(Event event) override;
|
||||
bool isPossible() override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
// class SartharionAttackPriorityAction : public AttackAction
|
||||
// {
|
||||
// public:
|
||||
// SartharionAttackPriorityAction(PlayerbotAI* botAI, std::string const name = "sartharion attack priority")
|
||||
// : AttackAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class KillPowerSparkAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
KillPowerSparkAction(PlayerbotAI* botAI, std::string const name = "kill power spark")
|
||||
: AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
// class EnterTwilightPortalAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// EnterTwilightPortalAction(PlayerbotAI* botAI, std::string const name = "enter twilight portal")
|
||||
// : MovementAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class EoEFlyDrakeAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
EoEFlyDrakeAction(PlayerbotAI* ai) : MovementAction(ai, "eoe fly drake") {}
|
||||
bool Execute(Event event) override;
|
||||
bool isPossible() override;
|
||||
};
|
||||
|
||||
// class ExitTwilightPortalAction : public MovementAction
|
||||
// {
|
||||
// public:
|
||||
// ExitTwilightPortalAction(PlayerbotAI* botAI, std::string const name = "exit twilight portal")
|
||||
// : MovementAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
// };
|
||||
class EoEDrakeAttackAction : public Action
|
||||
{
|
||||
public:
|
||||
EoEDrakeAttackAction(PlayerbotAI* botAI) : Action(botAI, "eoe drake attack") {}
|
||||
bool Execute(Event event) override;
|
||||
bool isPossible() override;
|
||||
|
||||
protected:
|
||||
Unit* vehicleBase;
|
||||
bool CastDrakeSpellAction(Unit* target, uint32 spellId, uint32 cooldown);
|
||||
bool DrakeDpsAction(Unit* target);
|
||||
bool DrakeHealAction();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,3 +47,68 @@
|
||||
// }
|
||||
// return 1.0f;
|
||||
// }
|
||||
|
||||
float MalygosMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "malygos");
|
||||
|
||||
uint8 phase = MalygosTrigger::getPhase(bot, boss);
|
||||
if (phase == 0) { return 1.0f; }
|
||||
|
||||
if (phase == 1)
|
||||
{
|
||||
if (dynamic_cast<FollowAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (botAI->IsDps(bot) && dynamic_cast<DpsAssistAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (botAI->IsRangedDps(bot) && dynamic_cast<DropTargetAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (!botAI->IsMainTank(bot) && dynamic_cast<TankAssistAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// if (dynamic_cast<MovementAction*>(action) && !dynamic_cast<MalygosPositionAction*>(action))
|
||||
// {
|
||||
// return 0.0f;
|
||||
// }
|
||||
}
|
||||
else if (phase == 2)
|
||||
{
|
||||
if (botAI->IsDps(bot) && dynamic_cast<DpsAssistAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<FleeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<TankAssistAction*>(action))
|
||||
{
|
||||
Unit* target = action->GetTarget();
|
||||
if (target && target->GetEntry() == NPC_SCION_OF_ETERNITY)
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
else if (phase == 3)
|
||||
{
|
||||
// Suppresses FollowAction as well as some attack-based movements
|
||||
if (dynamic_cast<MovementAction*>(action) && !dynamic_cast<EoEFlyDrakeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
#include "Multiplier.h"
|
||||
|
||||
// class SartharionMultiplier : public Multiplier
|
||||
// {
|
||||
// public:
|
||||
// SartharionMultiplier(PlayerbotAI* ai) : Multiplier(ai, "sartharion") {}
|
||||
class MalygosMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
MalygosMultiplier(PlayerbotAI* ai) : Multiplier(ai, "malygos") {}
|
||||
|
||||
// public:
|
||||
// virtual float GetValue(Action* action);
|
||||
// };
|
||||
public:
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,29 +4,22 @@
|
||||
|
||||
void RaidEoEStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("sartharion tank",
|
||||
// NextAction::array(0, new NextAction("sartharion tank position", ACTION_MOVE), nullptr)));
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("twilight fissure",
|
||||
// NextAction::array(0, new NextAction("avoid twilight fissure", ACTION_RAID + 2), nullptr)));
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("flame tsunami",
|
||||
// NextAction::array(0, new NextAction("avoid flame tsunami", ACTION_RAID + 1), nullptr)));
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("sartharion dps",
|
||||
// NextAction::array(0, new NextAction("sartharion attack priority", ACTION_RAID), nullptr)));
|
||||
// // Flank dragon positioning
|
||||
// triggers.push_back(new TriggerNode("sartharion melee positioning",
|
||||
// NextAction::array(0, new NextAction("rear flank", ACTION_MOVE + 4), nullptr)));
|
||||
|
||||
// triggers.push_back(new TriggerNode("twilight portal enter",
|
||||
// NextAction::array(0, new NextAction("enter twilight portal", ACTION_RAID + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("twilight portal exit",
|
||||
// NextAction::array(0, new NextAction("exit twilight portal", ACTION_RAID + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("malygos",
|
||||
NextAction::array(0, new NextAction("malygos position", ACTION_MOVE), nullptr)));
|
||||
triggers.push_back(new TriggerNode("malygos",
|
||||
NextAction::array(0, new NextAction("malygos target", ACTION_RAID + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("power spark",
|
||||
// NextAction::array(0, new NextAction("pull power spark", ACTION_RAID + 2), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("power spark",
|
||||
// NextAction::array(0, new NextAction("kill power spark", ACTION_RAID + 3), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("group flying",
|
||||
NextAction::array(0, new NextAction("fly drake", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("drake combat",
|
||||
NextAction::array(0, new NextAction("drake attack", ACTION_NORMAL + 5), nullptr)));
|
||||
}
|
||||
|
||||
void RaidEoEStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
|
||||
{
|
||||
// multipliers.push_back(new SartharionMultiplier(botAI));
|
||||
multipliers.push_back(new MalygosMultiplier(botAI));
|
||||
}
|
||||
|
||||
@@ -10,23 +10,13 @@ class RaidEoETriggerContext : public NamedObjectContext<Trigger>
|
||||
public:
|
||||
RaidEoETriggerContext()
|
||||
{
|
||||
// creators["sartharion tank"] = &RaidOsTriggerContext::sartharion_tank;
|
||||
// creators["flame tsunami"] = &RaidOsTriggerContext::flame_tsunami;
|
||||
// creators["twilight fissure"] = &RaidOsTriggerContext::twilight_fissure;
|
||||
// creators["sartharion dps"] = &RaidOsTriggerContext::sartharion_dps;
|
||||
// creators["sartharion melee positioning"] = &RaidOsTriggerContext::sartharion_melee;
|
||||
// creators["twilight portal enter"] = &RaidOsTriggerContext::twilight_portal_enter;
|
||||
// creators["twilight portal exit"] = &RaidOsTriggerContext::twilight_portal_exit;
|
||||
creators["malygos"] = &RaidEoETriggerContext::malygos;
|
||||
creators["power spark"] = &RaidEoETriggerContext::power_spark;
|
||||
}
|
||||
|
||||
private:
|
||||
// static Trigger* sartharion_tank(PlayerbotAI* ai) { return new SartharionTankTrigger(ai); }
|
||||
// static Trigger* flame_tsunami(PlayerbotAI* ai) { return new FlameTsunamiTrigger(ai); }
|
||||
// static Trigger* twilight_fissure(PlayerbotAI* ai) { return new TwilightFissureTrigger(ai); }
|
||||
// static Trigger* sartharion_dps(PlayerbotAI* ai) { return new SartharionDpsTrigger(ai); }
|
||||
// static Trigger* sartharion_melee(PlayerbotAI* ai) { return new SartharionMeleePositioningTrigger(ai); }
|
||||
// static Trigger* twilight_portal_enter(PlayerbotAI* ai) { return new TwilightPortalEnterTrigger(ai); }
|
||||
// static Trigger* twilight_portal_exit(PlayerbotAI* ai) { return new TwilightPortalExitTrigger(ai); }
|
||||
static Trigger* power_spark(PlayerbotAI* ai) { return new PowerSparkTrigger(ai); }
|
||||
static Trigger* malygos(PlayerbotAI* ai) { return new MalygosTrigger(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,127 +2,52 @@
|
||||
|
||||
#include "SharedDefines.h"
|
||||
|
||||
// bool SartharionTankTrigger::IsActive()
|
||||
// {
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
uint8 MalygosTrigger::getPhase(Player* bot, Unit* boss)
|
||||
{
|
||||
uint8 phase = 0;
|
||||
Unit* vehicle = bot->GetVehicleBase();
|
||||
if (bot->GetMapId() != EOE_MAP_ID) { return phase; }
|
||||
|
||||
if (vehicle && vehicle->GetEntry() == NPC_WYRMREST_SKYTALON)
|
||||
{
|
||||
phase = 3;
|
||||
}
|
||||
else if (boss && boss->HealthAbovePct(50))
|
||||
{
|
||||
phase = 1;
|
||||
}
|
||||
else if (boss)
|
||||
{
|
||||
phase = 2;
|
||||
}
|
||||
|
||||
return phase;
|
||||
}
|
||||
|
||||
bool MalygosTrigger::IsActive()
|
||||
{
|
||||
return bool(AI_VALUE2(Unit*, "find target", "malygos"));
|
||||
}
|
||||
|
||||
bool PowerSparkTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "malygos");
|
||||
if (!boss) { return false; }
|
||||
|
||||
if (bot->getClass() != CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// return botAI->IsTank(bot);
|
||||
// }
|
||||
|
||||
// bool FlameTsunamiTrigger::IsActive()
|
||||
// {
|
||||
// if (botAI->IsTank(bot)) { return false; }
|
||||
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
|
||||
|
||||
// GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
|
||||
// for (auto& npc : npcs)
|
||||
// {
|
||||
// Unit* unit = botAI->GetUnit(npc);
|
||||
// if (unit)
|
||||
// {
|
||||
// if (unit->GetEntry() == NPC_FLAME_TSUNAMI)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool TwilightFissureTrigger::IsActive()
|
||||
// {
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
|
||||
|
||||
// GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
|
||||
// for (auto& npc : npcs)
|
||||
// {
|
||||
// Unit* unit = botAI->GetUnit(npc);
|
||||
// if (unit)
|
||||
// {
|
||||
// if (unit->GetEntry() == NPC_TWILIGHT_FISSURE)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// bool SartharionDpsTrigger::IsActive()
|
||||
// {
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
|
||||
// return botAI->IsDps(bot);
|
||||
// }
|
||||
|
||||
// bool SartharionMeleePositioningTrigger::IsActive()
|
||||
// {
|
||||
// if (!botAI->IsMelee(bot) || !botAI->IsDps(bot)) { return false; }
|
||||
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
|
||||
// Unit* shadron = AI_VALUE2(Unit*, "find target", "shadron");
|
||||
// Unit* tenebron = AI_VALUE2(Unit*, "find target", "tenebron");
|
||||
// Unit* vesperon = AI_VALUE2(Unit*, "find target", "vesperon");
|
||||
|
||||
// return !(shadron || tenebron || vesperon);
|
||||
// }
|
||||
|
||||
// bool TwilightPortalEnterTrigger::IsActive()
|
||||
// {
|
||||
// if (botAI->IsMainTank(bot) || botAI->IsHealAssistantOfIndex(bot, 0)) { return false; }
|
||||
|
||||
// // In 25-man, take two healers in. Otherwise just take one
|
||||
// // if (bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
|
||||
// // {
|
||||
// // if (botAI->IsHealAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 1))
|
||||
// // {
|
||||
// // return false;
|
||||
// // }
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // if (botAI->IsHealAssistantOfIndex(bot, 0))
|
||||
// // {
|
||||
// // return false;
|
||||
// // }
|
||||
// // }
|
||||
|
||||
|
||||
// // Don't enter portal until drakes are dead
|
||||
// if (bot->HasAura(SPELL_POWER_OF_SHADRON) ||
|
||||
// bot->HasAura(SPELL_POWER_OF_TENEBRON) ||
|
||||
// bot->HasAura(SPELL_POWER_OF_VESPERON))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// Unit* boss = AI_VALUE2(Unit*, "find target", "sartharion");
|
||||
// if (!boss) { return false; }
|
||||
|
||||
// // GuidVector objects = AI_VALUE(GuidVector, "nearest game objects no los");
|
||||
// // for (auto& object : objects)
|
||||
// // {
|
||||
// // GameObject* go = botAI->GetGameObject(object);
|
||||
// // if (go && go->GetEntry() == GO_TWILIGHT_PORTAL)
|
||||
// // {
|
||||
// // return true;
|
||||
// // }
|
||||
// // }
|
||||
// return bool(bot->FindNearestGameObject(GO_TWILIGHT_PORTAL, 100.0f));
|
||||
// }
|
||||
|
||||
// bool TwilightPortalExitTrigger::IsActive()
|
||||
// {
|
||||
// return bot->HasAura(SPELL_TWILIGHT_SHIFT) && !AI_VALUE2(Unit*, "find target", "acolyte of shadron");
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,114 +7,52 @@
|
||||
|
||||
enum EyeOfEternityIDs
|
||||
{
|
||||
// // Bosses
|
||||
// NPC_SARTHARION = 28860,
|
||||
// NPC_SHADRON = 30451,
|
||||
// NPC_TENEBRON = 30452,
|
||||
// NPC_VESPERON = 30449,
|
||||
NPC_MALYGOS = 28859,
|
||||
NPC_POWER_SPARK = 30084,
|
||||
NPC_NEXUS_LORD = 30245,
|
||||
NPC_SCION_OF_ETERNITY = 30249,
|
||||
NPC_WYRMREST_SKYTALON = 30161,
|
||||
|
||||
SPELL_POWER_SPARK_VISUAL = 55845,
|
||||
SPELL_POWER_SPARK_GROUND_BUFF = 55852,
|
||||
SPELL_POWER_SPARK_MALYGOS_BUFF = 56152,
|
||||
|
||||
// // Mini-boss shared
|
||||
// SPELL_SHADOW_BREATH = 57570,
|
||||
// SPELL_SHADOW_FISSURE = 57579,
|
||||
// SPELL_SUMMON_TWILIGHT_WHELP = 58035,
|
||||
// SPELL_GIFT_OF_TWILIGHT_SHADOW = 57835,
|
||||
// SPELL_TWILIGHT_TORMENT_VESPERON = 57935,
|
||||
SPELL_TELEPORT_VISUAL = 52096,
|
||||
|
||||
// // Sartharion
|
||||
// SPELL_SARTHARION_CLEAVE = 56909,
|
||||
// SPELL_SARTHARION_FLAME_BREATH = 56908,
|
||||
// SPELL_SARTHARION_TAIL_LASH = 56910,
|
||||
// SPELL_CYCLONE_AURA_PERIODIC = 57598,
|
||||
// SPELL_LAVA_STRIKE_DUMMY = 57578,
|
||||
// SPELL_LAVA_STRIKE_DUMMY_TRIGGER = 57697,
|
||||
// SPELL_LAVA_STRIKE_SUMMON = 57572,
|
||||
// SPELL_SARTHARION_PYROBUFFET = 56916,
|
||||
// SPELL_SARTHARION_BERSERK = 61632,
|
||||
// SPELL_SARTHARION_TWILIGHT_REVENGE = 60639,
|
||||
SPELL_SCION_ARCANE_BARRAGE = 56397,
|
||||
SPELL_ARCANE_SHOCK_N = 57058,
|
||||
SPELL_ARCANE_SHOCK_H = 60073,
|
||||
SPELL_HASTE = 57060,
|
||||
|
||||
// // Sartharion with drakes
|
||||
// SPELL_WILL_OF_SARTHARION = 61254,
|
||||
// SPELL_POWER_OF_TENEBRON = 61248,
|
||||
// SPELL_POWER_OF_VESPERON = 61251,
|
||||
// SPELL_POWER_OF_SHADRON = 58105,
|
||||
// SPELL_GIFT_OF_TWILIGHT_FIRE = 58766,
|
||||
SPELL_ALEXSTRASZA_GIFT = 61028,
|
||||
|
||||
// // Visuals
|
||||
// SPELL_EGG_MARKER_VISUAL = 58547,
|
||||
// SPELL_FLAME_TSUNAMI_VISUAL = 57494,
|
||||
|
||||
// // Misc
|
||||
// SPELL_FADE_ARMOR = 60708,
|
||||
// SPELL_FLAME_TSUNAMI_DAMAGE_AURA = 57492,
|
||||
// SPELL_FLAME_TSUNAMI_LEAP = 60241,
|
||||
// SPELL_SARTHARION_PYROBUFFET_TRIGGER = 57557,
|
||||
|
||||
// NPC_TWILIGHT_EGG = 30882,
|
||||
// NPC_TWILIGHT_WHELP = 30890,
|
||||
// NPC_DISCIPLE_OF_SHADRON = 30688,
|
||||
// NPC_DISCIPLE_OF_VESPERON = 30858,
|
||||
// NPC_ACOLYTE_OF_SHADRON = 31218,
|
||||
// NPC_ACOLYTE_OF_VESPERON = 31219,
|
||||
|
||||
// // Sartharion fight
|
||||
// NPC_LAVA_BLAZE = 30643,
|
||||
// NPC_FLAME_TSUNAMI = 30616,
|
||||
// NPC_SAFE_AREA_TRIGGER = 30494,
|
||||
// NPC_TWILIGHT_FISSURE = 30641,
|
||||
// GO_TWILIGHT_PORTAL = 193988,
|
||||
// GO_NORMAL_PORTAL = 193989,
|
||||
// SPELL_TWILIGHT_SHIFT = 57874,
|
||||
// Drake Abilities:
|
||||
// DPS
|
||||
SPELL_FLAME_SPIKE = 56091,
|
||||
SPELL_ENGULF_IN_FLAMES = 56092,
|
||||
// Healing
|
||||
SPELL_REVIVIFY = 57090,
|
||||
SPELL_LIFE_BURST = 57143,
|
||||
// Utility
|
||||
SPELL_FLAME_SHIELD = 57108,
|
||||
SPELL_BLAZING_SPEED = 57092,
|
||||
};
|
||||
|
||||
const uint32 EOE_MAP_ID = 615;
|
||||
const uint32 EOE_MAP_ID = 616;
|
||||
|
||||
// class SartharionTankTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// SartharionTankTrigger(PlayerbotAI* botAI) : Trigger(botAI, "sartharion tank") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
class MalygosTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
MalygosTrigger(PlayerbotAI* botAI) : Trigger(botAI, "malygos") {}
|
||||
bool IsActive() override;
|
||||
uint8 static getPhase(Player* bot, Unit* boss);
|
||||
};
|
||||
|
||||
// class FlameTsunamiTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// FlameTsunamiTrigger(PlayerbotAI* botAI) : Trigger(botAI, "flame tsunami") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
|
||||
// class TwilightFissureTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// TwilightFissureTrigger(PlayerbotAI* botAI) : Trigger(botAI, "twilight fissure") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
|
||||
// class SartharionDpsTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// SartharionDpsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "sartharion dps") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
|
||||
// class SartharionMeleePositioningTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// SartharionMeleePositioningTrigger(PlayerbotAI* botAI) : Trigger(botAI, "sartharion melee positioning") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
|
||||
// class TwilightPortalEnterTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// TwilightPortalEnterTrigger(PlayerbotAI* botAI) : Trigger(botAI, "twilight portal enter") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
|
||||
// class TwilightPortalExitTrigger : public Trigger
|
||||
// {
|
||||
// public:
|
||||
// TwilightPortalExitTrigger(PlayerbotAI* botAI) : Trigger(botAI, "twilight portal exit") {}
|
||||
// bool IsActive() override;
|
||||
// };
|
||||
class PowerSparkTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
PowerSparkTrigger(PlayerbotAI* botAI) : Trigger(botAI, "power spark") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user