diff --git a/src/strategy/raids/karazhan/RaidKarazhanActions.cpp b/src/strategy/raids/karazhan/RaidKarazhanActions.cpp index 24335251..eb23d72c 100644 --- a/src/strategy/raids/karazhan/RaidKarazhanActions.cpp +++ b/src/strategy/raids/karazhan/RaidKarazhanActions.cpp @@ -18,7 +18,7 @@ namespace bool KarazhanAttumenTheHuntsmanStackBehindAction::Execute(Event event) { RaidKarazhanHelpers karazhanHelper(botAI); - Unit* boss = karazhanHelper.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN); + Unit* boss = karazhanHelper.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); float distance = 5.0f; float orientation = boss->GetOrientation() + M_PI; @@ -34,12 +34,9 @@ bool KarazhanAttumenTheHuntsmanStackBehindAction::Execute(Event event) bool KarazhanAttumenTheHuntsmanStackBehindAction::isUseful() { RaidKarazhanHelpers karazhanHelper(botAI); - Unit* boss = karazhanHelper.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN); + Unit* boss = karazhanHelper.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); - if (boss && botAI->IsTank(bot) && botAI->HasAggro(boss) && boss->GetVictim() == bot) - return false; - - return boss != nullptr; + return boss && !(botAI->IsTank(bot) && botAI->HasAggro(boss) && boss->GetVictim() == bot); } bool KarazhanMoroesMarkTargetAction::Execute(Event event) @@ -70,7 +67,9 @@ bool KarazhanMaidenOfVirtuePositionBossAction::Execute(Event event) { Player* member = itr->GetSource(); if (!member || !member->IsAlive() || !botAI->IsHeal(member) || !member->HasAura(SPELL_REPENTANCE)) + { continue; + } healer = member; break; } @@ -82,9 +81,10 @@ bool KarazhanMaidenOfVirtuePositionBossAction::Execute(Event event) float targetX = healer->GetPositionX() + cos(angle) * 6.0f; float targetY = healer->GetPositionY() + sin(angle) * 6.0f; float targetZ = healer->GetPositionZ(); - - return MoveTo(bot->GetMapId(), targetX, targetY, targetZ, false, false, false, true, - MovementPriority::MOVEMENT_COMBAT); + { + return MoveTo(bot->GetMapId(), targetX, targetY, targetZ, false, false, false, true, + MovementPriority::MOVEMENT_COMBAT); + } } const float maxDistance = 3.0f; @@ -96,9 +96,10 @@ bool KarazhanMaidenOfVirtuePositionBossAction::Execute(Event event) float dY = KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION.GetPositionY() - boss->GetPositionY(); float mX = KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION.GetPositionX() + (dX / distanceToBossPosition) * maxDistance; float mY = KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION.GetPositionY() + (dY / distanceToBossPosition) * maxDistance; - - return MoveTo(bot->GetMapId(), mX, mY, - bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, false); + { + return MoveTo(bot->GetMapId(), mX, mY, + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, false); + } } return false; } @@ -121,8 +122,10 @@ bool KarazhanMaidenOfVirtuePositionRangedAction::Execute(Event event) { Unit* member = botAI->GetUnit(memberGuid); - if (!member || !botAI->IsRanged(member->ToPlayer())) + if (!member || !botAI->IsRanged(member->ToPlayer())) + { continue; + } if (member == bot) break; @@ -137,12 +140,12 @@ bool KarazhanMaidenOfVirtuePositionRangedAction::Execute(Event event) float distance = bot->GetExactDist2d(KARAZHAN_MAIDEN_OF_VIRTUE_RANGED_POSITION[index]); const float maxDistance = 2.0f; - if (distance > maxDistance) + { return MoveTo(bot->GetMapId(), KARAZHAN_MAIDEN_OF_VIRTUE_RANGED_POSITION[index].GetPositionX(), KARAZHAN_MAIDEN_OF_VIRTUE_RANGED_POSITION[index].GetPositionY(), bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, false); - + } return false; } @@ -173,11 +176,9 @@ bool KarazhanBigBadWolfPositionBossAction::Execute(Event event) { return false; } - return MoveTo(bot->GetMapId(), mX, mY, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, false); } - return false; } @@ -200,7 +201,6 @@ bool KarazhanBigBadWolfRunAwayAction::Execute(Event event) currentIndex = (currentIndex + 1) % 4; target = KARAZHAN_BIG_BAD_WOLF_RUN_POSITION[currentIndex]; } - return MoveTo(bot->GetMapId(), target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_FORCED); } @@ -220,11 +220,17 @@ bool KarazhanRomuloAndJulianneMarkTargetAction::Execute(Event event) const int maxPctDifference = 10; if (julianne->GetHealthPct() + maxPctDifference < romulo->GetHealthPct() || julianne->GetHealthPct() < 1.0f) + { target = romulo; + } else if (romulo->GetHealthPct() + maxPctDifference < julianne->GetHealthPct() || romulo->GetHealthPct() < 1.0f) + { target = julianne; + } if (!target) + { return false; + } RaidKarazhanHelpers karazhanHelper(botAI); karazhanHelper.MarkTargetWithSkull(target); @@ -252,25 +258,33 @@ bool KarazhanWizardOfOzScorchStrawmanAction::Execute(Event event) { Unit* strawman = AI_VALUE2(Unit*, "find target", "strawman"); if (!strawman || !strawman->IsAlive()) + { return false; + } Group* group = bot->GetGroup(); if (!group) + { return false; + } for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->GetSource(); if (!member || !member->IsAlive()) + { continue; - + } if (member->getClass() != CLASS_MAGE) + { continue; - + } + PlayerbotAI* mageAI = sPlayerbotsMgr->GetPlayerbotAI(member); if (!mageAI) + { continue; - + } if (mageAI->CanCastSpell("scorch", strawman)) { mageAI->CastSpell("scorch", strawman); @@ -283,7 +297,9 @@ bool KarazhanTheCuratorMarkTargetAction::Execute(Event event) { Unit* target = AI_VALUE2(Unit*, "find target", "astral flare"); if (!target || !target->IsAlive()) + { return false; + } RaidKarazhanHelpers karazhanHelper(botAI); karazhanHelper.MarkTargetWithSkull(target); @@ -294,7 +310,6 @@ bool KarazhanTheCuratorMarkTargetAction::Execute(Event event) bool KarazhanTheCuratorPositionBossAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "the curator"); - const float maxDistance = 3.0f; const float distanceToBossPosition = boss->GetExactDist2d(KARAZHAN_THE_CURATOR_BOSS_POSITION); @@ -302,13 +317,13 @@ bool KarazhanTheCuratorPositionBossAction::Execute(Event event) { float dX = KARAZHAN_THE_CURATOR_BOSS_POSITION.GetPositionX() - boss->GetPositionX(); float dY = KARAZHAN_THE_CURATOR_BOSS_POSITION.GetPositionY() - boss->GetPositionY(); - float mX = KARAZHAN_THE_CURATOR_BOSS_POSITION.GetPositionX() + (dX / distanceToBossPosition) * maxDistance; float mY = KARAZHAN_THE_CURATOR_BOSS_POSITION.GetPositionY() + (dY / distanceToBossPosition) * maxDistance; - - return MoveTo(bot->GetMapId(), mX, mY, - bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, - false); + { + return MoveTo(bot->GetMapId(), mX, mY, + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT, true, + false); + } } return false; } @@ -327,8 +342,9 @@ bool KarazhanTheCuratorSpreadRangedAction::Execute(Event event) Unit* nearestPlayer = karazhanHelper.GetNearestPlayerInRadius(minDistance); if (nearestPlayer) + { return FleePosition(nearestPlayer->GetPosition(), minDistance); - + } return false; } @@ -343,11 +359,12 @@ bool KarazhanTerestianIllhoofMarkTargetAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "terestian illhoof"); if (!boss) + { return false; + } RaidKarazhanHelpers karazhanHelper(botAI); Unit* target = karazhanHelper.GetFirstAliveUnitByEntry(NPC_DEMON_CHAINS); - if (!target || !target->IsAlive()) { target = karazhanHelper.GetFirstAliveUnitByEntry(NPC_KILREK); @@ -357,7 +374,7 @@ bool KarazhanTerestianIllhoofMarkTargetAction::Execute(Event event) } } karazhanHelper.MarkTargetWithSkull(target); - + return false; } @@ -374,17 +391,15 @@ bool KarazhanShadeOfAranArcaneExplosionRunAwayAction::Execute(Event event) { return MoveAway(boss, safeDistance - distance); } - return false; } bool KarazhanShadeOfAranArcaneExplosionRunAwayAction::isUseful() { Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); - if (!boss || !boss->IsAlive()) - return false; - return boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION); + return boss && boss->IsAlive() && boss->HasUnitState(UNIT_STATE_CASTING) && + boss->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION); } bool KarazhanShadeOfAranFlameWreathStopMovementAction::Execute(Event event) @@ -395,8 +410,9 @@ bool KarazhanShadeOfAranFlameWreathStopMovementAction::Execute(Event event) AI_VALUE(LastMovement&, "last movement").Set(nullptr); bot->GetMotionMaster()->Clear(); if (bot->isMoving()) + { bot->StopMoving(); - + } return true; } return false; @@ -407,8 +423,9 @@ bool KarazhanShadeOfAranMarkConjuredElementalAction::Execute(Event event) RaidKarazhanHelpers karazhanHelper(botAI); Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!boss || !boss->IsAlive()) + { return false; - + } Unit* target = karazhanHelper.GetFirstAliveUnitByEntry(NPC_CONJURED_ELEMENTAL); if (!target || !target->IsAlive() || target->HasAura(SPELL_WARLOCK_BANISH)) { @@ -430,23 +447,23 @@ bool KarazhanShadeOfAranSpreadRangedAction::Execute(Event event) float dX = bot->GetPositionX() - boss->GetPositionX(); float dY = bot->GetPositionY() - boss->GetPositionY(); float length = std::sqrt(dX * dX + dY * dY); - dX /= length; dY /= length; - float tX = boss->GetPositionX() + dX * maxBossDistance; float tY = boss->GetPositionY() + dY * maxBossDistance; - - return MoveTo(bot->GetMapId(), tX, tY, bot->GetPositionZ(), false, false, false, true, - MovementPriority::MOVEMENT_COMBAT); + { + return MoveTo(bot->GetMapId(), tX, tY, bot->GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_COMBAT); + } } const float minDistance = 5.0f; RaidKarazhanHelpers karazhanHelper(botAI); Unit* nearestPlayer = karazhanHelper.GetNearestPlayerInRadius(minDistance); if (nearestPlayer) + { return FleePosition(nearestPlayer->GetPosition(), minDistance); - + } return false; } @@ -454,7 +471,9 @@ bool KarazhanShadeOfAranSpreadRangedAction::isUseful() { Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!boss || !boss->IsAlive()) + { return false; + } RaidKarazhanHelpers karazhanHelper(botAI); @@ -471,19 +490,27 @@ bool KarazhanNetherspiteBlockRedBeamAction::Execute(Event event) Group* group = bot->GetGroup(); if (!group) + { return false; + } Player* eligibleTank = nullptr; for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* member = itr->GetSource(); if (!member || !member->IsAlive()) + { continue; + } PlayerbotAI* memberAI = sPlayerbotsMgr->GetPlayerbotAI(member); if (!memberAI || !memberAI->IsTank(member)) + { continue; + } if (member->HasAura(SPELL_NETHER_EXHAUSTION_RED)) + { continue; + } eligibleTank = member; break; } @@ -522,8 +549,9 @@ bool KarazhanNetherspiteBlockRedBeamAction::Execute(Event event) float dy = py - by; float length = sqrt(dx*dx + dy*dy); if (length == 0.0f) + { return false; - + } dx /= length; dy /= length; float perpDx = -dy; @@ -549,8 +577,9 @@ bool KarazhanNetherspiteBlockRedBeamAction::isUseful() bool bossIsBanished = boss && boss->HasAura(SPELL_NETHERSPITE_BANISHED); if (!boss || !redPortal) + { return false; - + } if (lastBossBanishState[botGuid] != bossIsBanished) { if (!bossIsBanished) @@ -560,10 +589,10 @@ bool KarazhanNetherspiteBlockRedBeamAction::isUseful() } lastBossBanishState[botGuid] = bossIsBanished; } - if (bossIsBanished) + { return false; - + } return true; } @@ -606,7 +635,9 @@ bool KarazhanNetherspiteBlockBlueBeamAction::Execute(Event event) float dy = py - by; float length = sqrt(dx*dx + dy*dy); if (length == 0.0f) + { return false; + } dx /= length; dy /= length; @@ -630,8 +661,9 @@ bool KarazhanNetherspiteBlockBlueBeamAction::Execute(Event event) } } if (!outsideAllVoidZones) + { continue; - + } float distToIdeal = fabs(dist - 18.0f); if (!found || distToIdeal < bestDist) { @@ -698,8 +730,9 @@ bool KarazhanNetherspiteBlockGreenBeamAction::Execute(Event event) float dy = py - by; float length = sqrt(dx*dx + dy*dy); if (length == 0.0f) + { return false; - + } dx /= length; dy /= length; float bestDist = 150.0f; @@ -722,8 +755,9 @@ bool KarazhanNetherspiteBlockGreenBeamAction::Execute(Event event) } } if (!outsideAllVoidZones) + { continue; - + } float distToIdeal = fabs(dist - 18.0f); if (!found || distToIdeal < bestDist) { @@ -771,27 +805,30 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) break; } } + struct BeamAvoid { Unit* portal; float minDist, maxDist; }; std::vector beams; Unit* redPortal = bot->FindNearestCreature(NPC_RED_PORTAL, 150.0f); Unit* bluePortal = bot->FindNearestCreature(NPC_BLUE_PORTAL, 150.0f); Unit* greenPortal = bot->FindNearestCreature(NPC_GREEN_PORTAL, 150.0f); - - if (redPortal) { + if (redPortal) + { float bx = boss->GetPositionX(), by = boss->GetPositionY(); float px = redPortal->GetPositionX(), py = redPortal->GetPositionY(); float dx = px - bx, dy = py - by; float length = sqrt(dx*dx + dy*dy); beams.push_back({redPortal, 0.0f, length}); } - if (bluePortal) { + if (bluePortal) + { float bx = boss->GetPositionX(), by = boss->GetPositionY(); float px = bluePortal->GetPositionX(), py = bluePortal->GetPositionY(); float dx = px - bx, dy = py - by; float length = sqrt(dx*dx + dy*dy); beams.push_back({bluePortal, 0.0f, length}); } - if (greenPortal) { + if (greenPortal) + { float bx = boss->GetPositionX(), by = boss->GetPositionY(); float px = greenPortal->GetPositionX(), py = greenPortal->GetPositionY(); float dx = px - bx, dy = py - by; @@ -806,8 +843,10 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) float px = beam.portal->GetPositionX(), py = beam.portal->GetPositionY(); float dx = px - bx, dy = py - by; float length = sqrt(dx*dx + dy*dy); - if (length == 0.0f) continue; - + if (length == 0.0f) + {continue; + continue; + } dx /= length; dy /= length; float botdx = bot->GetPositionX() - bx, botdy = bot->GetPositionY() - by; float t = (botdx * dx + botdy * dy); @@ -821,7 +860,9 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) } if (!nearVoidZone && !nearBeam) + { return false; + } const float minMoveDist = 3.0f, maxSearchDist = 20.0f, stepAngle = M_PI/18.0f, stepDist = 0.5f; float bossZ = boss->GetPositionZ(); @@ -836,8 +877,9 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) float cy = bot->GetPositionY() + sin(angle) * dist; float cz = bossZ; if (std::any_of(voidZones.begin(), voidZones.end(), [&](Unit* vz){ return Position(cx, cy, cz).GetExactDist2d(vz) < 4.0f; })) + { continue; - + } bool tooCloseToBeam = false; for (const auto& beam : beams) { @@ -845,7 +887,10 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) float px = beam.portal->GetPositionX(), py = beam.portal->GetPositionY(); float dx = px - bx, dy = py - by; float length = sqrt(dx*dx + dy*dy); - if (length == 0.0f) continue; + if (length == 0.0f) + { + continue; + } dx /= length; dy /= length; float botdx = cx - bx, botdy = cy - by; float t = (botdx * dx + botdy * dy); @@ -857,11 +902,15 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) break; } } - if (tooCloseToBeam) continue; - + if (tooCloseToBeam) + { + continue; + } float moveDist = sqrt(pow(cx - bot->GetPositionX(), 2) + pow(cy - bot->GetPositionY(), 2)); - if (moveDist < minMoveDist) continue; - + if (moveDist < minMoveDist) + { + continue; + } if (!found || moveDist < bestDist) { bestCandidate = Position(cx, cy, cz); @@ -873,9 +922,10 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::Execute(Event event) if (found && karazhanHelper.IsSafePosition(bestCandidate.GetPositionX(), bestCandidate.GetPositionY(), bestCandidate.GetPositionZ(), voidZones, 4.0f)) - + { return MoveTo(bot->GetMapId(), bestCandidate.GetPositionX(), bestCandidate.GetPositionY(), bestCandidate.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT); + } return false; } @@ -883,13 +933,15 @@ bool KarazhanNetherspiteAvoidBeamAndVoidZoneAction::isUseful() { Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite"); if (!boss || boss->HasAura(SPELL_NETHERSPITE_BANISHED)) + { return false; - + } RaidKarazhanHelpers karazhanHelper(botAI); auto [redBlocker, greenBlocker, blueBlocker] = karazhanHelper.GetCurrentBeamBlockers(); if (bot == redBlocker || bot == blueBlocker || bot == greenBlocker) + { return false; - + } return true; } @@ -901,7 +953,9 @@ bool KarazhanNetherspiteBanishPhaseAvoidVoidZoneAction::Execute(Event event) for (Unit* vz : voidZones) { if (vz->GetEntry() == NPC_VOID_ZONE && bot->GetExactDist2d(vz) < 4.0f) + { return FleePosition(vz->GetPosition(), 4.0f); + } } return false; } @@ -910,19 +964,21 @@ bool KarazhanNetherspiteBanishPhaseAvoidVoidZoneAction::isUseful() { Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite"); if (!boss || !boss->HasAura(SPELL_NETHERSPITE_BANISHED)) + { return false; - + } RaidKarazhanHelpers karazhanHelper(botAI); std::vector voidZones = karazhanHelper.GetAllVoidZones(); for (Unit* vz : voidZones) { - if (bot->GetExactDist2d(vz) < 4.0f) + if (bot->GetExactDist2d(vz) < 4.0f) + { return true; + } } return false; } -// For Enfeebled bots to avoid Shadow Nova and all non-tank bots to avoid infernals bool KarazhanPrinceMalchezaarNonTankAvoidHazardAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar"); @@ -957,8 +1013,10 @@ bool KarazhanPrinceMalchezaarNonTankAvoidHazardAction::Execute(Event event) float y = bossY + dy * dist; float destZ = bossZ; if (!bot->IsWithinLOS(x, y, destZ)) + { continue; - bool pathSafe = karazhanHelper.IsStraightPathSafe(Position(bx, by, bz), Position(x, y, destZ), + } + bool pathSafe = karazhanHelper.IsStraightPathSafe(Position(bx, by, bz), Position(x, y, destZ), infernals, safeInfernalDistance, stepSize); float moveDist = sqrt(pow(x - bx, 2) + pow(y - by, 2)); if (pathSafe && moveDist < bestMoveDist) @@ -1011,8 +1069,10 @@ bool KarazhanPrinceMalchezaarNonTankAvoidHazardAction::Execute(Event event) float y = bossY + dy * dist; float destZ = bossZ; if (!bot->IsWithinLOS(x, y, destZ)) + { continue; - bool pathSafe = karazhanHelper.IsStraightPathSafe(Position(bx, by, bz), Position(x, y, destZ), + } + bool pathSafe = karazhanHelper.IsStraightPathSafe(Position(bx, by, bz), Position(x, y, destZ), infernals, safeInfernalDistance, stepSize); float moveDist = sqrt(pow(x - bx, 2) + pow(y - by, 2)); if (pathSafe && moveDist < bestMoveDist) @@ -1029,7 +1089,9 @@ bool KarazhanPrinceMalchezaarNonTankAvoidHazardAction::Execute(Event event) Position arcPoint = karazhanHelper.CalculateArcPoint(Position(bx, by, bz), Position(x, y, destZ), Position(bossX, bossY, bossZ)); if (!bot->IsWithinLOS(arcPoint.GetPositionX(), arcPoint.GetPositionY(), arcPoint.GetPositionZ())) + { continue; + } bool arcSafe = true; for (Unit* infernal : infernals) { @@ -1075,7 +1137,6 @@ bool KarazhanPrinceMalchezaarNonTankAvoidHazardAction::isUseful() return boss && !(botAI->IsTank(bot) && botAI->HasAggro(boss) && boss->GetVictim() == bot); } -// For tank to avoid infernals (with buffer distance) bool KarazhanPrinceMalchezaarTankAvoidHazardAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar"); @@ -1117,7 +1178,9 @@ bool KarazhanPrinceMalchezaarTankAvoidHazardAction::Execute(Event event) float y = by + dy * dist; float z = bz; if (!bot->IsWithinLOS(x, y, z)) + { continue; + } bool safe = karazhanHelper.IsStraightPathSafe(Position(bx, by, bz), Position(x, y, z), infernals, safeInfernalDistance, stepSize); float moveDist = sqrt(pow(x - bx, 2) + pow(y - by, 2)); @@ -1134,8 +1197,14 @@ bool KarazhanPrinceMalchezaarTankAvoidHazardAction::Execute(Event event) { Position arcPoint = karazhanHelper.CalculateArcPoint(Position(bx, by, bz), Position(x, y, z), Position(bx, by, bz)); - if (!bot->IsWithinLOS(arcPoint.GetPositionX(), arcPoint.GetPositionY(), arcPoint.GetPositionZ())) + float arcX = arcPoint.GetPositionX(); + float arcY = arcPoint.GetPositionY(); + float arcZ = arcPoint.GetPositionZ(); + float arcDestX = arcX, arcDestY = arcY, arcDestZ = arcZ; + if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bx, by, bz, arcDestX, arcDestY, arcDestZ)) + { continue; + } bool arcSafe = true; for (Unit* infernal : infernals) { @@ -1164,6 +1233,7 @@ bool KarazhanPrinceMalchezaarTankAvoidHazardAction::Execute(Event event) { bot->AttackStop(); bot->InterruptNonMeleeSpells(false); + return MoveTo(bot->GetMapId(), bestDestX, bestDestY, bestDestZ, false, false, false, true, MovementPriority::MOVEMENT_COMBAT); } diff --git a/src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp b/src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp index 81479e7e..939e73b9 100644 --- a/src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp +++ b/src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp @@ -35,7 +35,9 @@ const Position KARAZHAN_THE_CURATOR_BOSS_POSITION = Position(-11139.463f, -1884. void RaidKarazhanHelpers::MarkTargetWithSkull(Unit* target) { if (!target) + { return; + } if (Group* group = bot->GetGroup()) { @@ -43,15 +45,21 @@ void RaidKarazhanHelpers::MarkTargetWithSkull(Unit* target) ObjectGuid skullGuid = group->GetTargetIcon(skullIconId); if (skullGuid != target->GetGUID()) + { group->SetTargetIcon(skullIconId, bot->GetGUID(), target->GetGUID()); + } } } Unit* RaidKarazhanHelpers::GetFirstAliveUnit(const std::vector& units) { for (Unit* unit : units) + { if (unit && unit->IsAlive()) + { return unit; + } + } return nullptr; } @@ -65,8 +73,11 @@ Unit* RaidKarazhanHelpers::GetFirstAliveUnitByEntry(uint32 entry) Unit* unit = botAI->GetUnit(npcGuid); if (unit && unit->IsAlive() && unit->GetEntry() == entry) + { return unit; + } } + return nullptr; } @@ -79,10 +90,14 @@ Unit* RaidKarazhanHelpers::GetNearestPlayerInRadius(float radius) Player* member = itr->GetSource(); if (!member || !member->IsAlive() || member == bot) + { continue; + } if (bot->GetExactDist2d(member) < radius) + { return member; + } } } return nullptr; @@ -92,12 +107,13 @@ bool RaidKarazhanHelpers::IsFlameWreathActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!boss) + { return false; + } Spell* currentSpell = boss->GetCurrentSpell(CURRENT_GENERIC_SPELL); if (currentSpell && currentSpell->m_spellInfo && currentSpell->m_spellInfo->Id == SPELL_FLAME_WREATH) { - bot->Yell("I will not move when Flame Wreath is cast or the raid blows up.", LANG_UNIVERSAL); return true; } @@ -107,9 +123,13 @@ bool RaidKarazhanHelpers::IsFlameWreathActive() { Player* member = itr->GetSource(); if (!member || !member->IsAlive()) + { continue; + } if (member->HasAura(SPELL_AURA_FLAME_WREATH)) + { return true; + } } } return false; @@ -125,7 +145,9 @@ std::vector RaidKarazhanHelpers::GetBlueBlockers() { Player* member = itr->GetSource(); if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member)) + { continue; + } bool isDps = botAI->IsDps(member); bool isWarrior = member->getClass() == CLASS_WARRIOR; @@ -155,7 +177,9 @@ std::vector RaidKarazhanHelpers::GetGreenBlockers() { Player* member = itr->GetSource(); if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member)) + { continue; + } bool hasExhaustion = member->HasAura(SPELL_NETHER_EXHAUSTION_GREEN); Aura* greenBuff = member->GetAura(SPELL_GREEN_BEAM_DEBUFF); @@ -188,7 +212,9 @@ Position RaidKarazhanHelpers::GetPositionOnBeam(Unit* boss, Unit* portal, float float length = sqrt(dx*dx + dy*dy); if (length == 0.0f) + { return Position(bx, by, bz); + } dx /= length; dy /= length; @@ -213,26 +239,37 @@ std::tuple RaidKarazhanHelpers::GetCurrentBeamBlocker { Player* member = itr->GetSource(); if (!member || !member->IsAlive()) + { continue; - PlayerbotAI* memberAI = sPlayerbotsMgr->GetPlayerbotAI(member); - if (!memberAI || !memberAI->IsTank(member)) + } + if (!botAI->IsTank(member)) + { continue; + } if (member->HasAura(SPELL_NETHER_EXHAUSTION_RED)) + { continue; + } redBlockers.push_back(member); } } if (!redBlockers.empty()) + { redBlocker = redBlockers.front(); + } std::vector greenBlockers = GetGreenBlockers(); if (!greenBlockers.empty()) + { greenBlocker = greenBlockers.front(); + } std::vector blueBlockers = GetBlueBlockers(); if (!blueBlockers.empty()) + { blueBlocker = blueBlockers.front(); + } return std::make_tuple(redBlocker, greenBlocker, blueBlocker); } @@ -246,7 +283,9 @@ std::vector RaidKarazhanHelpers::GetAllVoidZones() { Unit* unit = botAI->GetUnit(npcGuid); if (!unit || unit->GetEntry() != NPC_VOID_ZONE) + { continue; + } float dist = bot->GetExactDist2d(unit); if (dist < radius) @@ -265,7 +304,9 @@ bool RaidKarazhanHelpers::IsSafePosition(float x, float y, float z, float dist = std::sqrt(std::pow(x - hazard->GetPositionX(), 2) + std::pow(y - hazard->GetPositionY(), 2)); if (dist < hazardRadius) + { return false; + } } return true; } @@ -280,7 +321,9 @@ std::vector RaidKarazhanHelpers::GetSpawnedInfernals() const Unit* unit = botAI->GetUnit(npcGuid); if (unit && unit->GetEntry() == NPC_NETHERSPITE_INFERNAL) + { infernals.push_back(unit); + } } return infernals; } @@ -295,7 +338,10 @@ bool RaidKarazhanHelpers::IsStraightPathSafe(const Position& start, const Positi float tz = target.GetPositionZ(); float totalDist = std::sqrt(std::pow(tx - sx, 2) + std::pow(ty - sy, 2)); if (totalDist == 0.0f) + { return true; + } + for (float checkDist = 0.0f; checkDist <= totalDist; checkDist += stepSize) { float t = checkDist / totalDist; @@ -306,56 +352,54 @@ bool RaidKarazhanHelpers::IsStraightPathSafe(const Position& start, const Positi { float hazardDist = std::sqrt(std::pow(checkX - hazard->GetPositionX(), 2) + std::pow(checkY - hazard->GetPositionY(), 2)); if (hazardDist < hazardRadius) + { return false; + } } } + return true; } Position RaidKarazhanHelpers::CalculateArcPoint(const Position& current, const Position& target, const Position& center) { float arcFraction = 0.25f; - // Calculate vectors from center to current position and target float currentX = current.GetPositionX() - center.GetPositionX(); float currentY = current.GetPositionY() - center.GetPositionY(); float targetX = target.GetPositionX() - center.GetPositionX(); float targetY = target.GetPositionY() - center.GetPositionY(); - // Calculate distances float currentDist = std::sqrt(currentX * currentX + currentY * currentY); float targetDist = std::sqrt(targetX * targetX + targetY * targetY); if (currentDist == 0.0f || targetDist == 0.0f) + { return current; + } - // Normalize vectors currentX /= currentDist; currentY /= currentDist; targetX /= targetDist; targetY /= targetDist; - // Calculate dot product to find the angle between vectors float dotProduct = currentX * targetX + currentY * targetY; - dotProduct = std::max(-1.0f, std::min(1.0f, dotProduct)); // Clamp to [-1, 1] + dotProduct = std::max(-1.0f, std::min(1.0f, dotProduct)); float angle = std::acos(dotProduct); - // Determine rotation direction (clockwise or counterclockwise) float crossProduct = currentX * targetY - currentY * targetX; - float stepAngle = angle * arcFraction; // Move arcFraction along the arc + float stepAngle = angle * arcFraction; if (crossProduct < 0) - stepAngle = -stepAngle; // Clockwise + { + stepAngle = -stepAngle; + } - // Calculate rotation matrix components float cos_a = std::cos(stepAngle); float sin_a = std::sin(stepAngle); - // Rotate current vector float rotatedX = currentX * cos_a - currentY * sin_a; float rotatedY = currentX * sin_a + currentY * cos_a; - // Smoothing: blend current and target radius float desiredDist = currentDist * 0.9f + targetDist * 0.1f; - // Calculate the new position return Position(center.GetPositionX() + rotatedX * desiredDist, center.GetPositionY() + rotatedY * desiredDist, current.GetPositionZ()); diff --git a/src/strategy/raids/karazhan/RaidKarazhanHelpers.h b/src/strategy/raids/karazhan/RaidKarazhanHelpers.h index 42db6580..2746b09d 100644 --- a/src/strategy/raids/karazhan/RaidKarazhanHelpers.h +++ b/src/strategy/raids/karazhan/RaidKarazhanHelpers.h @@ -8,49 +8,49 @@ enum KarazhanSpells { // Maiden of Virtue - SPELL_REPENTANCE = 29511, + SPELL_REPENTANCE = 29511, // Opera Event - SPELL_LITTLE_RED_RIDING_HOOD = 30756, + SPELL_LITTLE_RED_RIDING_HOOD = 30756, // Shade of Aran - SPELL_FLAME_WREATH = 30004, - SPELL_AURA_FLAME_WREATH = 29946, - SPELL_ARCANE_EXPLOSION = 29973, - SPELL_WARLOCK_BANISH = 18647, // Rank 2 + SPELL_FLAME_WREATH = 30004, + SPELL_AURA_FLAME_WREATH = 29946, + SPELL_ARCANE_EXPLOSION = 29973, + SPELL_WARLOCK_BANISH = 18647, // Rank 2 // Netherspite - SPELL_GREEN_BEAM_DEBUFF = 30422, - SPELL_BLUE_BEAM_DEBUFF = 30423, - SPELL_NETHER_EXHAUSTION_RED = 38637, - SPELL_NETHER_EXHAUSTION_GREEN = 38638, - SPELL_NETHER_EXHAUSTION_BLUE = 38639, - SPELL_NETHERSPITE_BANISHED = 39833, + SPELL_GREEN_BEAM_DEBUFF = 30422, + SPELL_BLUE_BEAM_DEBUFF = 30423, + SPELL_NETHER_EXHAUSTION_RED = 38637, + SPELL_NETHER_EXHAUSTION_GREEN = 38638, + SPELL_NETHER_EXHAUSTION_BLUE = 38639, + SPELL_NETHERSPITE_BANISHED = 39833, // Prince Malchezaar - SPELL_ENFEEBLE = 30843, + SPELL_ENFEEBLE = 30843, }; enum KarazhanNpcs { // Attumen the Huntsman - NPC_ATTUMEN_THE_HUNTSMAN = 16152, // Mounted ID + NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152, // Terestian Illhoof - NPC_KILREK = 17229, - NPC_DEMON_CHAINS = 17248, + NPC_KILREK = 17229, + NPC_DEMON_CHAINS = 17248, // Shade of Aran - NPC_CONJURED_ELEMENTAL = 17167, + NPC_CONJURED_ELEMENTAL = 17167, // Netherspite - NPC_VOID_ZONE = 16697, - NPC_RED_PORTAL = 17369, - NPC_BLUE_PORTAL = 17368, - NPC_GREEN_PORTAL = 17367, + NPC_VOID_ZONE = 16697, + NPC_RED_PORTAL = 17369, + NPC_BLUE_PORTAL = 17368, + NPC_GREEN_PORTAL = 17367, // Prince Malchezaar - NPC_NETHERSPITE_INFERNAL = 17646, + NPC_NETHERSPITE_INFERNAL = 17646, }; extern const Position KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION; diff --git a/src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp b/src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp index a1b25ee5..f5306f8b 100644 --- a/src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp +++ b/src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp @@ -19,13 +19,17 @@ float KarazhanBigBadWolfMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "the big bad wolf"); if (!boss) + { return 1.0f; + } if (bot->HasAura(SPELL_LITTLE_RED_RIDING_HOOD)) { if ((dynamic_cast(action) && !dynamic_cast(action)) || (dynamic_cast(action))) - return 0.0f; + { + return 0.0f; + } } return 1.0f; } @@ -34,18 +38,24 @@ float KarazhanShadeOfAranMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); if (!boss) + { return 1.0f; + } if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION)) { if (IsChargeAction(action)) + { return 0.0f; + } if (dynamic_cast(action)) { const float safeDistance = 20.0f; if (bot->GetDistance2d(boss) >= safeDistance) + { return 0.0f; + } } } @@ -67,7 +77,9 @@ float KarazhanShadeOfAranMultiplier::GetValue(Action* action) if (flameWreathActive) { if (dynamic_cast(action) || IsChargeAction(action)) + { return 0.0f; + } } return 1.0f; } @@ -76,7 +88,9 @@ float KarazhanNetherspiteBlueAndGreenBeamMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite"); if (!boss || !boss->IsAlive()) + { return 1.0f; + } RaidKarazhanHelpers karazhanHelper(botAI); auto [redBlocker /*unused*/, greenBlocker, blueBlocker] = karazhanHelper.GetCurrentBeamBlockers(); @@ -88,18 +102,25 @@ float KarazhanNetherspiteBlueAndGreenBeamMultiplier::GetValue(Action* action) bool inBeam = false; for (Unit* portal : {bluePortal, greenPortal}) { - if (!portal) continue; + if (!portal) + { + continue; + } float bx = boss->GetPositionX(), by = boss->GetPositionY(); float px = portal->GetPositionX(), py = portal->GetPositionY(); float dx = px - bx, dy = py - by; float length = sqrt(dx*dx + dy*dy); - if (length == 0.0f) continue; + if (length == 0.0f) + { + continue; + } dx /= length; dy /= length; float botdx = bot->GetPositionX() - bx, botdy = bot->GetPositionY() - by; float t = (botdx * dx + botdy * dy); float beamX = bx + dx * t, beamY = by + dy * t; float distToBeam = sqrt(pow(bot->GetPositionX() - beamX, 2) + pow(bot->GetPositionY() - beamY, 2)); - if (distToBeam < 5.0f && t > 0.0f && t < length) { + if (distToBeam < 5.0f && t > 0.0f && t < length) + { inBeam = true; break; } @@ -118,7 +139,9 @@ float KarazhanNetherspiteBlueAndGreenBeamMultiplier::GetValue(Action* action) if (!inVoidZone) { if (dynamic_cast(action) || IsChargeAction(action)) + { return 0.0f; + } } } } @@ -129,7 +152,9 @@ float KarazhanNetherspiteRedBeamMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite"); if (!boss || !boss->IsAlive()) + { return 1.0f; + } RaidKarazhanHelpers karazhanHelper(botAI); auto [redBlocker, greenBlocker /*unused*/, blueBlocker /*unused*/] = karazhanHelper.GetCurrentBeamBlockers(); @@ -177,7 +202,9 @@ float KarazhanNetherspiteRedBeamMultiplier::GetValue(Action* action) if (distToTarget < positionTolerance) { if (dynamic_cast(action) || IsChargeAction(action)) + { return 0.0f; + } } } } @@ -187,13 +214,14 @@ float KarazhanNetherspiteRedBeamMultiplier::GetValue(Action* action) float KarazhanPrinceMalchezaarMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar"); - if (!boss) - return 1.0f; - if (boss && bot->HasAura(SPELL_ENFEEBLE)) + if (boss && botAI->IsMelee(bot) && bot->HasAura(SPELL_ENFEEBLE)) { - if (IsChargeAction(action)) - return 0.0f; + if (dynamic_cast(action)) + { + return 1.0f; + } + return 0.0f; } return 1.0f; } diff --git a/src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp b/src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp index 55aa175e..f70ae70f 100644 --- a/src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp +++ b/src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp @@ -6,8 +6,9 @@ bool KarazhanAttumenTheHuntsmanTrigger::IsActive() { RaidKarazhanHelpers helpers(botAI); - Unit* boss = helpers.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN); - return boss != nullptr; + Unit* boss = helpers.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED); + + return boss && boss->IsAlive(); } bool KarazhanMoroesTrigger::IsActive() @@ -20,36 +21,27 @@ bool KarazhanMoroesTrigger::IsActive() Unit* robin = AI_VALUE2(Unit*, "find target", "lord robin daris"); Unit* crispin = AI_VALUE2(Unit*, "find target", "lord crispin ference"); - if ((!moroes || !moroes->IsAlive()) && - (!dorothea || !dorothea->IsAlive()) && - (!catriona || !catriona->IsAlive()) && - (!keira || !keira->IsAlive()) && - (!rafe || !rafe->IsAlive()) && - (!robin || !robin->IsAlive()) && - (!crispin || !crispin->IsAlive())) - return false; - - return true; + return ((moroes && moroes->IsAlive()) || + (dorothea && dorothea->IsAlive()) || + (catriona && catriona->IsAlive()) || + (keira && keira->IsAlive()) || + (rafe && rafe->IsAlive()) || + (robin && robin->IsAlive()) || + (crispin && crispin->IsAlive())); } bool KarazhanMaidenOfVirtueTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "maiden of virtue"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanBigBadWolfTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "the big bad wolf"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanRomuloAndJulianneTrigger::IsActive() @@ -57,10 +49,7 @@ bool KarazhanRomuloAndJulianneTrigger::IsActive() Unit* julianne = AI_VALUE2(Unit*, "find target", "julianne"); Unit* romulo = AI_VALUE2(Unit*, "find target", "romulo"); - if (!julianne || !julianne->IsAlive() || !romulo || !romulo->IsAlive()) - return false; - - return true; + return julianne && julianne->IsAlive() && romulo && romulo->IsAlive(); } bool KarazhanWizardOfOzTrigger::IsActive() @@ -72,63 +61,45 @@ bool KarazhanWizardOfOzTrigger::IsActive() Unit* tinhead = AI_VALUE2(Unit*, "find target", "tinhead"); Unit* crone = AI_VALUE2(Unit*, "find target", "the crone"); - if (( !dorothee || !dorothee->IsAlive() ) && - ( !tito || !tito->IsAlive() ) && - ( !roar || !roar->IsAlive() ) && - ( !strawman || !strawman->IsAlive() ) && - ( !tinhead || !tinhead->IsAlive() ) && - ( !crone || !crone->IsAlive() )) - return false; - - return true; + return ((dorothee && dorothee->IsAlive()) || + (tito && tito->IsAlive()) || + (roar && roar->IsAlive()) || + (strawman && strawman->IsAlive()) || + (tinhead && tinhead->IsAlive()) || + (crone && crone->IsAlive())); } bool KarazhanTheCuratorTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "the curator"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanTerestianIllhoofTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "terestian illhoof"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanShadeOfAranTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran"); - if (!boss) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanNetherspiteTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); } bool KarazhanPrinceMalchezaarTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar"); - if (!boss || !boss->IsAlive()) - return false; - - return true; + return boss && boss->IsAlive(); }