Revert "Dungeon code cleanup"

This reverts commit d0a9e98801.
This commit is contained in:
Bobblybook
2024-10-20 15:58:14 +11:00
parent d0a9e98801
commit 3f7f306124
16 changed files with 151 additions and 106 deletions

View File

@@ -12,12 +12,12 @@ bool ShatterSpreadAction::Execute(Event event)
GuidVector members = AI_VALUE(GuidVector, "group members"); GuidVector members = AI_VALUE(GuidVector, "group members");
for (auto& member : members) for (auto& member : members)
{ {
Unit* unit = botAI->GetUnit(member); if (bot->GetGUID() == member)
if (!unit || bot->GetGUID() == member)
{ {
continue; continue;
} }
if (!closestMember || bot->GetExactDist2d(unit) < bot->GetExactDist2d(closestMember)) if (!closestMember ||
bot->GetExactDist2d(botAI->GetUnit(member)) < bot->GetExactDist2d(closestMember))
{ {
closestMember = botAI->GetUnit(member); closestMember = botAI->GetUnit(member);
} }

View File

@@ -26,5 +26,4 @@ void WotlkDungeonHoSStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
void WotlkDungeonHoSStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers) void WotlkDungeonHoSStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
{ {
multipliers.push_back(new KrystallusMultiplier(botAI)); multipliers.push_back(new KrystallusMultiplier(botAI));
multipliers.push_back(new SjonnirMultiplier(botAI));
} }

View File

@@ -33,12 +33,11 @@ bool MoveFromWhirlwindAction::Execute(Event event)
default: default:
break; break;
} }
float bossDistance = bot->GetExactDist2d(boss->GetPosition()); if (!boss || bot->GetExactDist2d(boss->GetPosition()) > targetDist)
if (!boss || bossDistance > targetDist)
{ {
return false; return false;
} }
return MoveAway(boss, targetDist - bossDistance); return MoveAway(boss, targetDist - bot->GetExactDist2d(boss->GetPosition()));
} }
bool FirebombSpreadAction::Execute(Event event) bool FirebombSpreadAction::Execute(Event event)
@@ -51,16 +50,13 @@ bool FirebombSpreadAction::Execute(Event event)
GuidVector members = AI_VALUE(GuidVector, "group members"); GuidVector members = AI_VALUE(GuidVector, "group members");
for (auto& member : members) for (auto& member : members)
{ {
Unit* unit = botAI->GetUnit(member); if (bot->GetGUID() == member)
if (!unit || bot->GetGUID() == member)
{ {
continue; continue;
} }
if (bot->GetExactDist2d(botAI->GetUnit(member)) < targetDist)
if (bot->GetExactDist2d(unit) < targetDist)
{ {
float bossDistance = bot->GetExactDist2d(boss->GetPosition()); return MoveAway(botAI->GetUnit(member), targetDist);
return MoveAway(unit, targetDist - bossDistance);
} }
} }
return false; return false;
@@ -74,22 +70,24 @@ bool TelestraSplitTargetAction::Execute(Event event)
for (auto& attacker : attackers) for (auto& attacker : attackers)
{ {
Unit* unit = botAI->GetUnit(attacker); Unit* npc = botAI->GetUnit(attacker);
if (!unit) { continue; } if (!npc)
{
switch (unit->GetEntry()) continue;
}
switch (npc->GetEntry())
{ {
// Focus arcane clone first // Focus arcane clone first
case NPC_ARCANE_MAGUS: case NPC_ARCANE_MAGUS:
splitTargets[0] = unit; splitTargets[0] = npc;
break; break;
// Then the frost clone // Then the frost clone
case NPC_FROST_MAGUS: case NPC_FROST_MAGUS:
splitTargets[1] = unit; splitTargets[1] = npc;
break; break;
// Fire clone last // Fire clone last
case NPC_FIRE_MAGUS: case NPC_FIRE_MAGUS:
splitTargets[2] = unit; splitTargets[2] = npc;
break; break;
} }
} }
@@ -141,15 +139,11 @@ bool ChaoticRiftTargetAction::Execute(Event event)
bool DodgeSpikesAction::isUseful() bool DodgeSpikesAction::isUseful()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper"); Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper");
if (!boss) { return false; }
return bot->GetExactDist2d(boss) > 0.5f; return bot->GetExactDist2d(boss) > 0.5f;
} }
bool DodgeSpikesAction::Execute(Event event) bool DodgeSpikesAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper"); Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper");
if (!boss) { return false; }
return Move(bot->GetAngle(boss), bot->GetExactDist2d(boss) - 0.3f); return Move(bot->GetAngle(boss), bot->GetExactDist2d(boss) - 0.3f);
} }

View File

@@ -7,6 +7,22 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "NexusTriggers.h" #include "NexusTriggers.h"
#define ANGLE_45_DEG (static_cast<float>(M_PI) / 4.f)
#define ANGLE_90_DEG M_PI_2
#define ANGLE_120_DEG (2.f * static_cast<float>(M_PI) / 3.f)
// Slice of the circle that we want melee dps to attack from.
// Measured from boss orientation, on one side.
// Even though the breath cone is not the full 180 degrees,
// avoid melee dps from the front due to parry potential.
// Bots should learn good dps etiquette :)
#define DRAGON_MELEE_MIN_ANGLE ANGLE_90_DEG
// This leaves a danger zone of 60 degrees at the tail end on both sides.
// This is a total of 120 degrees tail arc that bots will avoid -
// number just happens to be the same in this case, but this is always measured from the front.
#define DRAGON_MELEE_MAX_ANGLE ANGLE_120_DEG
class MoveFromWhirlwindAction : public MovementAction class MoveFromWhirlwindAction : public MovementAction
{ {
public: public:

View File

@@ -77,8 +77,10 @@ float AnomalusMultiplier::GetValue(Action* action)
float OrmorokMultiplier::GetValue(Action* action) float OrmorokMultiplier::GetValue(Action* action)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper"); Unit* boss = AI_VALUE2(Unit*, "find target", "ormorok the tree-shaper");
if (!boss) { return 1.0f; } if (!boss)
{
return 1.0f;
}
// These are used for auto ranged repositioning, need to suppress so ranged dps don't ping-pong // These are used for auto ranged repositioning, need to suppress so ranged dps don't ping-pong
if (dynamic_cast<FleeAction*>(action)) if (dynamic_cast<FleeAction*>(action))
{ {

View File

@@ -39,4 +39,13 @@ class OrmorokMultiplier : public Multiplier
virtual float GetValue(Action* action); virtual float GetValue(Action* action);
}; };
class KeristraszaMultiplier : public Multiplier
{
public:
KeristraszaMultiplier(PlayerbotAI* ai) : Multiplier(ai, "keristrasza") {}
public:
virtual float GetValue(Action* action);
};
#endif #endif

View File

@@ -50,4 +50,5 @@ void WotlkDungeonNexStrategy::InitMultipliers(std::vector<Multiplier*> &multipli
multipliers.push_back(new TelestraMultiplier(botAI)); multipliers.push_back(new TelestraMultiplier(botAI));
multipliers.push_back(new AnomalusMultiplier(botAI)); multipliers.push_back(new AnomalusMultiplier(botAI));
multipliers.push_back(new OrmorokMultiplier(botAI)); multipliers.push_back(new OrmorokMultiplier(botAI));
// multipliers.push_back(new KeristraszaMultiplier(botAI));
} }

View File

@@ -42,22 +42,22 @@ bool AvoidShadowCrashAction::Execute(Event event)
{ {
// Could check all enemy units in range as it's possible to pull multiple of these mobs. // Could check all enemy units in range as it's possible to pull multiple of these mobs.
// They should really be killed 1 by 1, multipulls are messy so we just handle singles for now // They should really be killed 1 by 1, multipulls are messy so we just handle singles for now
Unit* unit = AI_VALUE2(Unit*, "find target", "forgotten one"); Unit* npc = AI_VALUE2(Unit*, "find target", "forgotten one");
Unit* victim = nullptr; Unit* victim = nullptr;
float radius = 10.0f; float radius = 10.0f;
float targetDist = radius + 2.0f; float targetDist = radius + 2.0f;
if (!unit) { return false; } if (!npc) { return false; }
// Actively move if targeted by a shadow crash. // Actively move if targeted by a shadow crash.
// Spell check not needed, they don't have any other non-instant casts // Spell check not needed, they don't have any other non-instant casts
if (unit->HasUnitState(UNIT_STATE_CASTING)) // && unit->FindCurrentSpellBySpellId(SPELL_SHADOW_CRASH)) if (npc->HasUnitState(UNIT_STATE_CASTING)) // && npc->FindCurrentSpellBySpellId(SPELL_SHADOW_CRASH))
{ {
// This doesn't seem to avoid casts very well, perhaps because this isn't checked while allies are casting. // This doesn't seem to avoid casts very well, perhaps because this isn't checked while allies are casting.
// TODO: Revisit if this is an issue in heroics, otherwise ignore shadow crashes for the most part. // TODO: Revisit if this is an issue in heroics, otherwise ignore shadow crashes for the most part.
victim = botAI->GetUnit(unit->GetTarget()); victim = botAI->GetUnit(npc->GetTarget());
if (victim && bot->GetExactDist2d(victim) < radius) if (victim && bot->GetExactDist2d(victim) < radius)
{ {
return MoveAway(victim, targetDist - bot->GetExactDist2d(victim->GetPosition())); return MoveAway(victim, targetDist - bot->GetExactDist2d(victim));
} }
} }

View File

@@ -9,10 +9,9 @@
float ElderNadoxMultiplier::GetValue(Action* action) float ElderNadoxMultiplier::GetValue(Action* action)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "elder nadox"); Unit* boss = AI_VALUE2(Unit*, "find target", "elder nadox");
if (!boss) { return 1.0f; }
Unit* guardian = AI_VALUE2(Unit*, "find target", "ahn'kahar guardian"); Unit* guardian = AI_VALUE2(Unit*, "find target", "ahn'kahar guardian");
if (guardian)
if (boss && guardian)
{ {
if (dynamic_cast<DpsAssistAction*>(action)) if (dynamic_cast<DpsAssistAction*>(action))
{ {
@@ -25,7 +24,7 @@ float ElderNadoxMultiplier::GetValue(Action* action)
float JedogaShadowseekerMultiplier::GetValue(Action* action) float JedogaShadowseekerMultiplier::GetValue(Action* action)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "jedoga shadowseeker"); Unit* boss = AI_VALUE2(Unit*, "find target", "jedoga shadowseeker");
if (!boss) { return 1.0f; } // Unit* volunteer = AI_VALUE2(Unit*, "find target", "twilight volunteer");
Unit* volunteer = nullptr; Unit* volunteer = nullptr;
// Target is not findable from threat table using AI_VALUE2(), // Target is not findable from threat table using AI_VALUE2(),
@@ -42,7 +41,7 @@ float JedogaShadowseekerMultiplier::GetValue(Action* action)
} }
} }
if (volunteer) if (boss && volunteer)
{ {
if (dynamic_cast<DpsAssistAction*>(action)) if (dynamic_cast<DpsAssistAction*>(action))
{ {
@@ -54,10 +53,9 @@ float JedogaShadowseekerMultiplier::GetValue(Action* action)
float ForgottenOneMultiplier::GetValue(Action* action) float ForgottenOneMultiplier::GetValue(Action* action)
{ {
Unit* unit = AI_VALUE2(Unit*, "find target", "forgotten one"); Unit* npc = AI_VALUE2(Unit*, "find target", "forgotten one");
if (!unit) { return 1.0f; }
if (bot->isMoving()) if (npc && bot->isMoving())
{ {
if (dynamic_cast<MovementAction*>(action)) if (dynamic_cast<MovementAction*>(action))
{ {

View File

@@ -17,9 +17,9 @@ bool NadoxGuardianTrigger::IsActive()
bool JedogaVolunteerTrigger::IsActive() bool JedogaVolunteerTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "jedoga shadowseeker"); Unit* boss = AI_VALUE2(Unit*, "find target", "jedoga shadowseeker");
if (!boss) { return false; } // Unit* volunteer = AI_VALUE2(Unit*, "find target", "twilight volunteer");
Unit* volunteer = nullptr;
// Volunteer is not findable from threat table using AI_VALUE2(), // Target is not findable from threat table using AI_VALUE2(),
// therefore need to search manually for the unit name // therefore need to search manually for the unit name
GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
@@ -28,16 +28,16 @@ bool JedogaVolunteerTrigger::IsActive()
Unit* unit = botAI->GetUnit(*i); Unit* unit = botAI->GetUnit(*i);
if (unit && unit->GetEntry() == NPC_TWILIGHT_VOLUNTEER) if (unit && unit->GetEntry() == NPC_TWILIGHT_VOLUNTEER)
{ {
return true; volunteer = unit;
break;
} }
} }
return false;
return boss && volunteer;
} }
bool ShadowCrashTrigger::IsActive() bool ShadowCrashTrigger::IsActive()
{ {
Unit* unit = AI_VALUE2(Unit*, "find target", "forgotten one"); if (botAI->IsMelee(bot)) { return false; }
if (!unit) { return false; } return !botAI->IsMelee(bot) && AI_VALUE2(Unit*, "find target", "forgotten one");
return !botAI->IsMelee(bot);
} }

View File

@@ -14,7 +14,7 @@ bool AttackFrostTombAction::Execute(Event event)
for (auto i = targets.begin(); i != targets.end(); ++i) for (auto i = targets.begin(); i != targets.end(); ++i)
{ {
Unit* unit = botAI->GetUnit(*i); Unit* unit = botAI->GetUnit(*i);
if (unit && unit->GetEntry() == NPC_FROST_TOMB) if (unit && unit->GetName() == "Frost Tomb")
{ {
frostTomb = unit; frostTomb = unit;
break; break;
@@ -31,9 +31,7 @@ bool AttackFrostTombAction::Execute(Event event)
bool AttackDalronnAction::Execute(Event event) bool AttackDalronnAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller"); Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!boss) { return false; } if (!boss || AI_VALUE(Unit*, "current target") == boss)
if (AI_VALUE(Unit*, "current target") == boss)
{ {
return false; return false;
} }
@@ -44,7 +42,10 @@ bool IngvarStopCastingAction::Execute(Event event)
{ {
// Doesn't work, this action gets queued behind the current spell instead of interrupting it // Doesn't work, this action gets queued behind the current spell instead of interrupting it
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss) { return false; } if (!boss)
{
return false;
}
int32 my_spell_id = AI_VALUE(uint32, "active spell"); int32 my_spell_id = AI_VALUE(uint32, "active spell");
if (!my_spell_id || my_spell_id == 0) if (!my_spell_id || my_spell_id == 0)
@@ -53,7 +54,10 @@ bool IngvarStopCastingAction::Execute(Event event)
} }
Spell* spell = bot->FindCurrentSpellBySpellId(my_spell_id); Spell* spell = bot->FindCurrentSpellBySpellId(my_spell_id);
if (!spell) { return false; } if (!spell)
{
return false;
}
// bot->Yell("cancelling spell="+std::to_string(my_spell_id), LANG_UNIVERSAL); // bot->Yell("cancelling spell="+std::to_string(my_spell_id), LANG_UNIVERSAL);
bot->InterruptSpell(spell->GetCurrentContainer(), false, true, true); bot->InterruptSpell(spell->GetCurrentContainer(), false, true, true);
@@ -67,7 +71,10 @@ bool IngvarDodgeSmashAction::isUseful() { return !AI_VALUE2(bool, "behind", "cur
bool IngvarDodgeSmashAction::Execute(Event event) bool IngvarDodgeSmashAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss) { return false; } if (!boss)
{
return false;
}
float distance = bot->GetExactDist2d(boss->GetPosition()); float distance = bot->GetExactDist2d(boss->GetPosition());
// Extra units to move into the boss, instead of being just 1 pixel past his midpoint. // Extra units to move into the boss, instead of being just 1 pixel past his midpoint.
@@ -81,7 +88,10 @@ bool IngvarSmashReturnAction::isUseful() { return AI_VALUE2(bool, "behind", "cur
bool IngvarSmashReturnAction::Execute(Event event) bool IngvarSmashReturnAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss) { return false; } if (!boss)
{
return false;
}
float distance = bot->GetExactDist2d(boss->GetPosition()); float distance = bot->GetExactDist2d(boss->GetPosition());
return Move(bot->GetAngle(boss), distance + bot->GetMeleeReach()); return Move(bot->GetAngle(boss), distance + bot->GetMeleeReach());

View File

@@ -7,8 +7,10 @@
float PrinceKelesethMultiplier::GetValue(Action* action) float PrinceKelesethMultiplier::GetValue(Action* action)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth"); Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
if (!boss) { return 1.0f; } if (!boss)
{
return 1.0f;
}
if (dynamic_cast<DpsAssistAction*>(action)) if (dynamic_cast<DpsAssistAction*>(action))
{ {
return 0.0f; return 0.0f;
@@ -18,9 +20,13 @@ float PrinceKelesethMultiplier::GetValue(Action* action)
float SkarvaldAndDalronnMultiplier::GetValue(Action* action) float SkarvaldAndDalronnMultiplier::GetValue(Action* action)
{ {
// Only need to deal with Dalronn here. If he's dead, just fall back to normal dps strat // Unit* skarvald = AI_VALUE2(Unit*, "find target", "skarvald the constructor");
Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller"); Unit* dalronn = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!boss) { return 1.0f; }
if (!dalronn)
{
return 1.0f;
}
if (dynamic_cast<DpsAssistAction*>(action)) if (dynamic_cast<DpsAssistAction*>(action))
{ {
@@ -33,7 +39,10 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
bool isTank = botAI->IsTank(bot); bool isTank = botAI->IsTank(bot);
if (!boss) { return 1.0f; } if (!boss)
{
return 1.0f;
}
// Prevent movement actions overriding current movement, we're probably dodging a slam // Prevent movement actions overriding current movement, we're probably dodging a slam
if (isTank && bot->isMoving() && dynamic_cast<MovementAction*>(action)) if (isTank && bot->isMoving() && dynamic_cast<MovementAction*>(action))
@@ -51,7 +60,10 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
{ {
uint32 spellId = AI_VALUE2(uint32, "spell id", action->getName()); uint32 spellId = AI_VALUE2(uint32, "spell id", action->getName());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo) { return 1.0f; } if (!spellInfo)
{
return 1.0f;
}
uint32 castTime = spellInfo->CalcCastTime(bot); uint32 castTime = spellInfo->CalcCastTime(bot);
if (castTime != 0) if (castTime != 0)
@@ -61,8 +73,10 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
} }
} }
// Done with non-tank logic // Done with non-tank logic
if (!isTank) { return 1.0f; } if (!isTank)
{
return 1.0f;
}
// TANK ONLY // TANK ONLY
if (boss->FindCurrentSpellBySpellId(SPELL_SMASH) || if (boss->FindCurrentSpellBySpellId(SPELL_SMASH) ||
boss->FindCurrentSpellBySpellId(SPELL_DARK_SMASH)) boss->FindCurrentSpellBySpellId(SPELL_DARK_SMASH))

View File

@@ -9,7 +9,7 @@ bool KelesethFrostTombTrigger::IsActive()
for (auto& member : members) for (auto& member : members)
{ {
Unit* unit = botAI->GetUnit(member); Unit* unit = botAI->GetUnit(member);
if (unit && unit->HasAura(SPELL_FROST_TOMB)) if (unit && unit->HasAura(DEBUFF_FROST_TOMB))
{ {
return true; return true;
} }
@@ -19,17 +19,21 @@ bool KelesethFrostTombTrigger::IsActive()
bool DalronnNontankTrigger::IsActive() bool DalronnNontankTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller"); Unit* dalronn = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!boss) { return false; } if (!dalronn)
{
return false;
}
return !botAI->IsTank(bot); return !botAI->IsTank(bot);
} }
bool IngvarStaggeringRoarTrigger::IsActive() bool IngvarStaggeringRoarTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss) { return false; } if (!boss)
{
return false;
}
if (boss->HasUnitState(UNIT_STATE_CASTING)) if (boss->HasUnitState(UNIT_STATE_CASTING))
{ {
if (boss->FindCurrentSpellBySpellId(SPELL_STAGGERING_ROAR)) if (boss->FindCurrentSpellBySpellId(SPELL_STAGGERING_ROAR))
@@ -43,12 +47,16 @@ bool IngvarStaggeringRoarTrigger::IsActive()
bool IngvarDreadfulRoarTrigger::IsActive() bool IngvarDreadfulRoarTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss) { return false; } if (!boss)
if (boss->HasUnitState(UNIT_STATE_CASTING) &&
boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
{ {
return true; return false;
}
if (boss->HasUnitState(UNIT_STATE_CASTING))
{
if (boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
{
return true;
}
} }
return false; return false;
} }
@@ -56,7 +64,10 @@ bool IngvarDreadfulRoarTrigger::IsActive()
bool IngvarSmashTankTrigger::IsActive() bool IngvarSmashTankTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss || !botAI->IsTank(bot)) { return false; } if (!boss || !botAI->IsTank(bot))
{
return false;
}
if (boss->HasUnitState(UNIT_STATE_CASTING)) if (boss->HasUnitState(UNIT_STATE_CASTING))
{ {
@@ -75,15 +86,20 @@ bool IngvarSmashTankReturnTrigger::IsActive()
// if (!boss || !botAI->IsTank(bot) || boss->HasUnitState(UNIT_STATE_CASTING)) // if (!boss || !botAI->IsTank(bot) || boss->HasUnitState(UNIT_STATE_CASTING))
// Ignore casting state as Ingvar will sometimes chain-cast a roar after a smash.. // Ignore casting state as Ingvar will sometimes chain-cast a roar after a smash..
// We don't want this to prevent our tank from repositioning properly. // We don't want this to prevent our tank from repositioning properly.
if (!boss || !botAI->IsTank(bot)) { return false; } if (!boss || !botAI->IsTank(bot))
{
return false;
}
return true; return true;
} }
bool NotBehindIngvarTrigger::IsActive() bool NotBehindIngvarTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer"); Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss || botAI->IsTank(bot)) { return false; } if (!boss || botAI->IsTank(bot))
{
return false;
}
return AI_VALUE2(bool, "behind", "current target"); return AI_VALUE2(bool, "behind", "current target");
} }

View File

@@ -7,8 +7,6 @@ bool AttackErekemAction::Execute(Event event)
{ {
// Focus boss first, adds after // Focus boss first, adds after
Unit* boss = AI_VALUE2(Unit*, "find target", "erekem"); Unit* boss = AI_VALUE2(Unit*, "find target", "erekem");
if (!boss) { return false; }
if (AI_VALUE(Unit*, "current target") != boss) if (AI_VALUE(Unit*, "current target") != boss)
{ {
return Attack(boss); return Attack(boss);
@@ -21,8 +19,6 @@ bool AttackIchorGlobuleAction::Execute(Event event)
Unit* boss = AI_VALUE2(Unit*, "find target", "ichoron"); Unit* boss = AI_VALUE2(Unit*, "find target", "ichoron");
if (!boss) { return false; } if (!boss) { return false; }
Unit* currentTarget = AI_VALUE(Unit*, "current target");
// Tank prioritise boss if it's up // Tank prioritise boss if it's up
if (botAI->IsTank(bot) && !boss->HasAura(SPELL_DRAINED)) if (botAI->IsTank(bot) && !boss->HasAura(SPELL_DRAINED))
{ {
@@ -42,6 +38,7 @@ bool AttackIchorGlobuleAction::Execute(Event event)
Unit* unit = botAI->GetUnit(*i); Unit* unit = botAI->GetUnit(*i);
if (unit && unit->GetEntry() == NPC_ICHOR_GLOBULE) if (unit && unit->GetEntry() == NPC_ICHOR_GLOBULE)
{ {
Unit* currentTarget = AI_VALUE(Unit*, "current target");
// Check IDs here, NOT Unit* pointers: // Check IDs here, NOT Unit* pointers:
// Don't keep swapping between sentries. // Don't keep swapping between sentries.
// If we're already attacking one, don't retarget another // If we're already attacking one, don't retarget another
@@ -53,7 +50,7 @@ bool AttackIchorGlobuleAction::Execute(Event event)
} }
} }
// No ichor globules left alive, fall back to targeting boss // No ichor globules left alive, fall back to targeting boss
if (currentTarget != boss) if (AI_VALUE(Unit*, "current target") != boss)
{ {
return Attack(boss); return Attack(boss);
} }
@@ -65,8 +62,6 @@ bool AttackVoidSentryAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator"); Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator");
if (!boss) { return false; } if (!boss) { return false; }
Unit* currentTarget = AI_VALUE(Unit*, "current target");
// Target is not findable from threat table using AI_VALUE2(), // Target is not findable from threat table using AI_VALUE2(),
// therefore need to search manually for the unit name // therefore need to search manually for the unit name
@@ -78,6 +73,7 @@ bool AttackVoidSentryAction::Execute(Event event)
Unit* unit = botAI->GetUnit(*i); Unit* unit = botAI->GetUnit(*i);
if (unit && unit->GetEntry() == NPC_VOID_SENTRY) if (unit && unit->GetEntry() == NPC_VOID_SENTRY)
{ {
Unit* currentTarget = AI_VALUE(Unit*, "current target");
// Check IDs here, NOT Unit* pointers: // Check IDs here, NOT Unit* pointers:
// Don't keep swapping between sentries. // Don't keep swapping between sentries.
// If we're already attacking one, don't retarget another // If we're already attacking one, don't retarget another
@@ -89,7 +85,7 @@ bool AttackVoidSentryAction::Execute(Event event)
} }
} }
// No void sentries left alive, fall back to targeting boss // No void sentries left alive, fall back to targeting boss
if (currentTarget != boss) if (AI_VALUE(Unit*, "current target") != boss)
{ {
return Attack(boss); return Attack(boss);
} }

View File

@@ -8,6 +8,8 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "VioletHoldTriggers.h" #include "VioletHoldTriggers.h"
// const Position NOVOS_PARTY_POSITION = Position(-378.852f, -760.349f, 28.587f);
class AttackErekemAction : public AttackAction class AttackErekemAction : public AttackAction
{ {
public: public:

View File

@@ -6,42 +6,30 @@
bool ErekemTargetTrigger::IsActive() bool ErekemTargetTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "erekem"); return AI_VALUE2(Unit*, "find target", "erekem") && botAI->IsDps(bot);
if (!boss) { return false; }
return botAI->IsDps(bot);
} }
bool IchoronTargetTrigger::IsActive() bool IchoronTargetTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "ichoron"); return AI_VALUE2(Unit*, "find target", "ichoron") && !botAI->IsHeal(bot);
if (!boss) { return false; }
return !botAI->IsHeal(bot);
} }
bool VoidShiftTrigger::IsActive() bool VoidShiftTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator"); Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator");
if (!boss) { return false; } return boss && bot->HasAura(SPELL_VOID_SHIFTED) && !botAI->IsHeal(bot);
return bot->HasAura(SPELL_VOID_SHIFTED) && !botAI->IsHeal(bot);
} }
bool ShroudOfDarknessTrigger::IsActive() bool ShroudOfDarknessTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator"); Unit* boss = AI_VALUE2(Unit*, "find target", "zuramat the obliterator");
if (!boss) { return false; } return boss && boss->HasAura(SPELL_SHROUD_OF_DARKNESS);
return boss->HasAura(SPELL_SHROUD_OF_DARKNESS);
} }
bool CyanigosaPositioningTrigger::IsActive() bool CyanigosaPositioningTrigger::IsActive()
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "cyanigosa"); Unit* boss = AI_VALUE2(Unit*, "find target", "cyanigosa");
if (!boss) { return false; }
// Include healers here for now, otherwise they stand in things // Include healers here for now, otherwise they stand in things
return !botAI->IsTank(bot) && !botAI->IsRangedDps(bot); return boss && !botAI->IsTank(bot) && !botAI->IsRangedDps(bot);
// return botAI->IsMelee(bot) && !botAI->IsTank(bot); // return boss && botAI->IsMelee(bot) && !botAI->IsTank(bot);
} }