mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Dungeon botAI bugfixes
- Utgarde Keep (Keleseth): Bots continue combat correctly after killing a frost tomb - Utgarde Keep (Dalronn & Skarvald): Bots continue combat correctly after killing Dalronn - Utgarde Keep (Ingvar): Tank correctly avoids Dark Smash in second phase - Oculus (Drake combat): Bots more consistently attack the drakes in the air when flying around - Halls of Lightning (Bjarngrim): Bots no longer acquire priority targets until in combat
This commit is contained in:
@@ -8,11 +8,11 @@ bool BjarngrimTargetAction::Execute(Event event)
|
|||||||
|
|
||||||
// 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
|
||||||
GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
|
GuidVector npcs = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
|
||||||
for (auto i = targets.begin(); i != targets.end(); ++i)
|
for (auto& npc : npcs)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(*i);
|
Unit* unit = botAI->GetUnit(npc);
|
||||||
if (unit && unit->GetEntry() == NPC_STORMFORGED_LIEUTENANT)
|
if (unit && unit->GetEntry() == NPC_STORMFORGED_LIEUTENANT)
|
||||||
{
|
{
|
||||||
target = unit;
|
target = unit;
|
||||||
|
|||||||
@@ -5,16 +5,17 @@
|
|||||||
|
|
||||||
bool StormforgedLieutenantTrigger::IsActive()
|
bool StormforgedLieutenantTrigger::IsActive()
|
||||||
{
|
{
|
||||||
if (botAI->IsTank(bot) || botAI->IsHeal(bot)) { return false; }
|
if (!botAI->IsDps(bot)) { return false; }
|
||||||
|
|
||||||
// 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
|
||||||
GuidVector targets = AI_VALUE(GuidVector, "possible targets no los");
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
|
|
||||||
for (auto i = targets.begin(); i != targets.end(); ++i)
|
for (auto& target : targets)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(*i);
|
Unit* unit = botAI->GetUnit(target);
|
||||||
if (unit && unit->GetEntry() == NPC_STORMFORGED_LIEUTENANT)
|
if (unit && unit->IsInCombat() &&
|
||||||
|
unit->GetEntry() == NPC_STORMFORGED_LIEUTENANT)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,18 +161,17 @@ bool DrakeAttackAction::Execute(Event event)
|
|||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
GuidVector attackers = AI_VALUE(GuidVector, "attackers");
|
GuidVector npcs = AI_VALUE(GuidVector, "possible targets");
|
||||||
for (auto& attacker : attackers)
|
for (auto& npc : npcs)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(attacker);
|
Unit* unit = botAI->GetUnit(npc);
|
||||||
if (!unit) { continue; }
|
if (!unit || !unit->IsInCombat()) { continue; }
|
||||||
|
|
||||||
SET_AI_VALUE(Unit*, "current target", unit);
|
|
||||||
target = unit;
|
target = unit;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Check this again to see if a target was assigned
|
||||||
if (!target) { return false; }
|
if (!target) { return false; }
|
||||||
|
|
||||||
switch (vehicleBase->GetEntry())
|
switch (vehicleBase->GetEntry())
|
||||||
|
|||||||
@@ -49,18 +49,8 @@ bool GroupFlyingTrigger::IsActive()
|
|||||||
|
|
||||||
bool DrakeCombatTrigger::IsActive()
|
bool DrakeCombatTrigger::IsActive()
|
||||||
{
|
{
|
||||||
Unit* vehicleBase = bot->GetVehicleBase();
|
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||||
if (!vehicleBase) { return false; }
|
return !targets.empty();
|
||||||
|
|
||||||
GuidVector attackers = AI_VALUE(GuidVector, "attackers");
|
|
||||||
for (auto& attacker : attackers)
|
|
||||||
{
|
|
||||||
Unit* target = botAI->GetUnit(attacker);
|
|
||||||
if (!target) { continue; }
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VarosCloudstriderTrigger::IsActive()
|
bool VarosCloudstriderTrigger::IsActive()
|
||||||
@@ -76,7 +66,7 @@ bool UromArcaneExplosionTrigger::IsActive()
|
|||||||
Unit* boss = AI_VALUE2(Unit*, "find target", "mage-lord urom");
|
Unit* boss = AI_VALUE2(Unit*, "find target", "mage-lord urom");
|
||||||
if (!boss) { return false; }
|
if (!boss) { return false; }
|
||||||
|
|
||||||
return boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION);
|
return bool(boss->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UromTimeBombTrigger::IsActive()
|
bool UromTimeBombTrigger::IsActive()
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ bool AttackFrostTombAction::Execute(Event event)
|
|||||||
// 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");
|
||||||
|
|
||||||
for (auto i = targets.begin(); i != targets.end(); ++i)
|
for (auto& target : targets)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(*i);
|
Unit* unit = botAI->GetUnit(target);
|
||||||
if (unit && unit->GetEntry() == NPC_FROST_TOMB)
|
if (unit && unit->GetEntry() == NPC_FROST_TOMB)
|
||||||
{
|
{
|
||||||
frostTomb = unit;
|
frostTomb = unit;
|
||||||
|
|||||||
@@ -9,20 +9,30 @@ 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; }
|
||||||
|
|
||||||
|
// Suppress auto-targeting behaviour only when a tomb is up
|
||||||
if (dynamic_cast<DpsAssistAction*>(action))
|
if (dynamic_cast<DpsAssistAction*>(action))
|
||||||
|
{
|
||||||
|
GuidVector members = AI_VALUE(GuidVector, "group members");
|
||||||
|
for (auto& member : members)
|
||||||
|
{
|
||||||
|
Unit* unit = botAI->GetUnit(member);
|
||||||
|
if (unit && unit->HasAura(SPELL_FROST_TOMB))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Only need to deal with Dalronn here. If he's dead, just fall back to normal dps strat
|
||||||
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))
|
// Only suppress DpsAssistAction if Dalronn is alive
|
||||||
|
if (dalronn->isTargetableForAttack() && dynamic_cast<DpsAssistAction*>(action))
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class WotlkDungeonUKTriggerContext : public NamedObjectContext<Trigger>
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
static Trigger* keleseth_frost_tomb(PlayerbotAI* ai) { return new KelesethFrostTombTrigger(ai); }
|
static Trigger* keleseth_frost_tomb(PlayerbotAI* ai) { return new KelesethFrostTombTrigger(ai); }
|
||||||
static Trigger* dalronn_priority_target(PlayerbotAI* ai) { return new DalronnNontankTrigger(ai); }
|
static Trigger* dalronn_priority_target(PlayerbotAI* ai) { return new DalronnDpsTrigger(ai); }
|
||||||
static Trigger* ingvar_staggering_roar(PlayerbotAI* ai) { return new IngvarStaggeringRoarTrigger(ai); }
|
static Trigger* ingvar_staggering_roar(PlayerbotAI* ai) { return new IngvarStaggeringRoarTrigger(ai); }
|
||||||
static Trigger* ingvar_dreadful_roar(PlayerbotAI* ai) { return new IngvarDreadfulRoarTrigger(ai); }
|
static Trigger* ingvar_dreadful_roar(PlayerbotAI* ai) { return new IngvarDreadfulRoarTrigger(ai); }
|
||||||
static Trigger* ingvar_smash_tank(PlayerbotAI* ai) { return new IngvarSmashTankTrigger(ai); }
|
static Trigger* ingvar_smash_tank(PlayerbotAI* ai) { return new IngvarSmashTankTrigger(ai); }
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ bool KelesethFrostTombTrigger::IsActive()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DalronnNontankTrigger::IsActive()
|
bool DalronnDpsTrigger::IsActive()
|
||||||
{
|
{
|
||||||
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 || !boss->isTargetableForAttack()) { return false; }
|
||||||
|
|
||||||
|
// This doesn't cause issues with healers currently and they will continue to heal even when included here
|
||||||
return !botAI->IsTank(bot);
|
return !botAI->IsTank(bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,13 +31,10 @@ 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->FindCurrentSpellBySpellId(SPELL_STAGGERING_ROAR))
|
if (boss->FindCurrentSpellBySpellId(SPELL_STAGGERING_ROAR))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +43,7 @@ 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) { return false; }
|
||||||
|
|
||||||
if (boss->HasUnitState(UNIT_STATE_CASTING) &&
|
if (boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
|
||||||
boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -58,14 +55,11 @@ 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->FindCurrentSpellBySpellId(SPELL_SMASH) ||
|
if (boss->FindCurrentSpellBySpellId(SPELL_SMASH) ||
|
||||||
boss->FindCurrentSpellBySpellId(SPELL_DARK_SMASH))
|
boss->FindCurrentSpellBySpellId(SPELL_DARK_SMASH))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ enum UtgardeKeepIDs
|
|||||||
SPELL_DREADFUL_ROAR_H = 59734,
|
SPELL_DREADFUL_ROAR_H = 59734,
|
||||||
SPELL_WOE_STRIKE_N = 42730,
|
SPELL_WOE_STRIKE_N = 42730,
|
||||||
SPELL_WOE_STRIKE_H = 59735,
|
SPELL_WOE_STRIKE_H = 59735,
|
||||||
SPELL_DARK_SMASH = 42723,
|
SPELL_DARK_SMASH_N = 42723,
|
||||||
|
SPELL_DARK_SMASH_H = 59709,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPELL_STAGGERING_ROAR DUNGEON_MODE(bot, SPELL_STAGGERING_ROAR_N, SPELL_STAGGERING_ROAR_H)
|
#define SPELL_STAGGERING_ROAR DUNGEON_MODE(bot, SPELL_STAGGERING_ROAR_N, SPELL_STAGGERING_ROAR_H)
|
||||||
#define SPELL_DREADFUL_ROAR DUNGEON_MODE(bot, SPELL_DREADFUL_ROAR_N, SPELL_DREADFUL_ROAR_H)
|
#define SPELL_DREADFUL_ROAR DUNGEON_MODE(bot, SPELL_DREADFUL_ROAR_N, SPELL_DREADFUL_ROAR_H)
|
||||||
#define SPELL_SMASH DUNGEON_MODE(bot, SPELL_SMASH_N, SPELL_SMASH_H)
|
#define SPELL_SMASH DUNGEON_MODE(bot, SPELL_SMASH_N, SPELL_SMASH_H)
|
||||||
|
#define SPELL_DARK_SMASH DUNGEON_MODE(bot, SPELL_DARK_SMASH_N, SPELL_DARK_SMASH_H)
|
||||||
|
|
||||||
class KelesethFrostTombTrigger : public Trigger
|
class KelesethFrostTombTrigger : public Trigger
|
||||||
{
|
{
|
||||||
@@ -35,10 +37,10 @@ public:
|
|||||||
bool IsActive() override;
|
bool IsActive() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DalronnNontankTrigger : public Trigger
|
class DalronnDpsTrigger : public Trigger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DalronnNontankTrigger(PlayerbotAI* ai) : Trigger(ai, "dalronn non-tank") {}
|
DalronnDpsTrigger(PlayerbotAI* ai) : Trigger(ai, "dalronn dps") {}
|
||||||
bool IsActive() override;
|
bool IsActive() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user