Reapply "Dungeon code cleanup"

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

View File

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

View File

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

View File

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

View File

@@ -7,22 +7,6 @@
#include "Playerbots.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
{
public:

View File

@@ -77,10 +77,8 @@ float AnomalusMultiplier::GetValue(Action* action)
float OrmorokMultiplier::GetValue(Action* action)
{
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
if (dynamic_cast<FleeAction*>(action))
{

View File

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

View File

@@ -50,5 +50,4 @@ void WotlkDungeonNexStrategy::InitMultipliers(std::vector<Multiplier*> &multipli
multipliers.push_back(new TelestraMultiplier(botAI));
multipliers.push_back(new AnomalusMultiplier(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.
// They should really be killed 1 by 1, multipulls are messy so we just handle singles for now
Unit* npc = AI_VALUE2(Unit*, "find target", "forgotten one");
Unit* unit = AI_VALUE2(Unit*, "find target", "forgotten one");
Unit* victim = nullptr;
float radius = 10.0f;
float targetDist = radius + 2.0f;
if (!npc) { return false; }
if (!unit) { return false; }
// Actively move if targeted by a shadow crash.
// Spell check not needed, they don't have any other non-instant casts
if (npc->HasUnitState(UNIT_STATE_CASTING)) // && npc->FindCurrentSpellBySpellId(SPELL_SHADOW_CRASH))
if (unit->HasUnitState(UNIT_STATE_CASTING)) // && unit->FindCurrentSpellBySpellId(SPELL_SHADOW_CRASH))
{
// 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.
victim = botAI->GetUnit(npc->GetTarget());
victim = botAI->GetUnit(unit->GetTarget());
if (victim && bot->GetExactDist2d(victim) < radius)
{
return MoveAway(victim, targetDist - bot->GetExactDist2d(victim));
return MoveAway(victim, targetDist - bot->GetExactDist2d(victim->GetPosition()));
}
}

View File

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

View File

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

View File

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

View File

@@ -7,10 +7,8 @@
float PrinceKelesethMultiplier::GetValue(Action* action)
{
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
if (!boss)
{
return 1.0f;
}
if (!boss) { return 1.0f; }
if (dynamic_cast<DpsAssistAction*>(action))
{
return 0.0f;
@@ -20,13 +18,9 @@ float PrinceKelesethMultiplier::GetValue(Action* action)
float SkarvaldAndDalronnMultiplier::GetValue(Action* action)
{
// Unit* skarvald = AI_VALUE2(Unit*, "find target", "skarvald the constructor");
Unit* dalronn = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!dalronn)
{
return 1.0f;
}
// 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");
if (!boss) { return 1.0f; }
if (dynamic_cast<DpsAssistAction*>(action))
{
@@ -39,10 +33,7 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
{
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
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
if (isTank && bot->isMoving() && dynamic_cast<MovementAction*>(action))
@@ -60,10 +51,7 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
{
uint32 spellId = AI_VALUE2(uint32, "spell id", action->getName());
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
return 1.0f;
}
if (!spellInfo) { return 1.0f; }
uint32 castTime = spellInfo->CalcCastTime(bot);
if (castTime != 0)
@@ -73,10 +61,8 @@ float IngvarThePlundererMultiplier::GetValue(Action* action)
}
}
// Done with non-tank logic
if (!isTank)
{
return 1.0f;
}
if (!isTank) { return 1.0f; }
// TANK ONLY
if (boss->FindCurrentSpellBySpellId(SPELL_SMASH) ||
boss->FindCurrentSpellBySpellId(SPELL_DARK_SMASH))

View File

@@ -9,7 +9,7 @@ bool KelesethFrostTombTrigger::IsActive()
for (auto& member : members)
{
Unit* unit = botAI->GetUnit(member);
if (unit && unit->HasAura(DEBUFF_FROST_TOMB))
if (unit && unit->HasAura(SPELL_FROST_TOMB))
{
return true;
}
@@ -19,21 +19,17 @@ bool KelesethFrostTombTrigger::IsActive()
bool DalronnNontankTrigger::IsActive()
{
Unit* dalronn = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!dalronn)
{
return false;
}
Unit* boss = AI_VALUE2(Unit*, "find target", "dalronn the controller");
if (!boss) { return false; }
return !botAI->IsTank(bot);
}
bool IngvarStaggeringRoarTrigger::IsActive()
{
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))
@@ -47,16 +43,12 @@ bool IngvarStaggeringRoarTrigger::IsActive()
bool IngvarDreadfulRoarTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "ingvar the plunderer");
if (!boss)
if (!boss) { return false; }
if (boss->HasUnitState(UNIT_STATE_CASTING) &&
boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
{
return false;
}
if (boss->HasUnitState(UNIT_STATE_CASTING))
{
if (boss->FindCurrentSpellBySpellId(SPELL_DREADFUL_ROAR))
{
return true;
}
return true;
}
return false;
}
@@ -64,10 +56,7 @@ bool IngvarDreadfulRoarTrigger::IsActive()
bool IngvarSmashTankTrigger::IsActive()
{
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))
{
@@ -86,20 +75,15 @@ bool IngvarSmashTankReturnTrigger::IsActive()
// if (!boss || !botAI->IsTank(bot) || boss->HasUnitState(UNIT_STATE_CASTING))
// 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.
if (!boss || !botAI->IsTank(bot))
{
return false;
}
if (!boss || !botAI->IsTank(bot)) { return false; }
return true;
}
bool NotBehindIngvarTrigger::IsActive()
{
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");
}

View File

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

View File

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

View File

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