diff --git a/src/strategy/raids/icecrown/RaidIccActions.cpp b/src/strategy/raids/icecrown/RaidIccActions.cpp index 5a7d824c..f3a14dc9 100644 --- a/src/strategy/raids/icecrown/RaidIccActions.cpp +++ b/src/strategy/raids/icecrown/RaidIccActions.cpp @@ -138,7 +138,7 @@ bool IccRangedPositionLadyDeathwhisperAction::Execute(Event event) if (dist < radius) { float moveDistance = std::min(moveIncrement, radius - dist + 1.0f); - return FleePosition(unit->GetPosition(), moveDistance); + return FleePosition(unit->GetPosition(), moveDistance, 250U); // return MoveAway(unit, moveDistance); } } @@ -151,13 +151,20 @@ bool IccRangedPositionLadyDeathwhisperAction::Execute(Event event) bool IccAddsLadyDeathwhisperAction::Execute(Event event) { - if (botAI->IsMainTank(bot) || botAI->IsHeal(bot)) - { - return false; - } - // Find the boss Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); - if (!boss) { return false; } + if (!boss) + return false; + + if (botAI->IsTank(bot) && boss->GetHealthPct() < 98.0f) + { + if (bot->GetExactDist2d(ICC_LDW_TANK_POSTION) > 20.0f) + return MoveTo(bot->GetMapId(), ICC_LDW_TANK_POSTION.GetPositionX(), + ICC_LDW_TANK_POSTION.GetPositionY(), ICC_LDW_TANK_POSTION.GetPositionZ(), false, + false, false, false, MovementPriority::MOVEMENT_COMBAT); + } + + if (botAI->IsMainTank(bot) || botAI->IsHeal(bot)) + return false; Unit* currentTarget = AI_VALUE(Unit*, "current target"); @@ -418,7 +425,7 @@ bool IccGunshipTeleportAllyAction::Execute(Event event) if (bot->GetTarget() != boss->GetGUID()) return false; - if (bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_ALLY) > 15.0f) + if (!botAI->IsAssistTank(bot) && bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_ALLY) > 15.0f) return bot->TeleportTo(bot->GetMapId(), ICC_GUNSHIP_TELEPORT_ALLY.GetPositionX(), ICC_GUNSHIP_TELEPORT_ALLY.GetPositionY(), ICC_GUNSHIP_TELEPORT_ALLY.GetPositionZ(), bot->GetOrientation()); @@ -446,7 +453,7 @@ bool IccGunshipTeleportHordeAction::Execute(Event event) if (bot->GetTarget() != boss->GetGUID()) return false; - if (bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_HORDE) > 15.0f) + if (!botAI->IsAssistTank(bot) && bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_HORDE) > 15.0f) return bot->TeleportTo(bot->GetMapId(), ICC_GUNSHIP_TELEPORT_HORDE.GetPositionX(), ICC_GUNSHIP_TELEPORT_HORDE.GetPositionY(), ICC_GUNSHIP_TELEPORT_HORDE.GetPositionZ(), bot->GetOrientation()); @@ -469,51 +476,84 @@ bool IccDbsTankPositionAction::Execute(Event event) false, false, true, MovementPriority::MOVEMENT_NORMAL); } - if (bot->HasAura(71042) || bot->HasAura(72408)) + if (botAI->GetAura("Rune of Blood", bot)) return true; if (botAI->IsRanged(bot) || botAI->IsHeal(bot)) { - float radius = 9.0f; - float moveIncrement = 3.0f; - bool isRanged = botAI->IsRanged(bot); + // Get group and position in group + Group* group = bot->GetGroup(); + if (!group) + return false; - GuidVector members = AI_VALUE(GuidVector, "group members"); - if (isRanged) - { - // Ranged: spread from other members - for (auto& member : members) + // Find this bot's position among ranged/healers in the group + int rangedIndex = -1; + int currentIndex = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { - Unit* unit = botAI->GetUnit(member); - if (!unit || !unit->IsAlive() || unit == bot || botAI->IsTank(bot) || botAI->IsMelee(bot)) + Player* member = itr->GetSource(); + if (!member || !member->IsAlive()) continue; - float dist = bot->GetExactDist2d(unit); - if (dist < radius) + if ((botAI->IsRanged(member) || botAI->IsHeal(member)) && !botAI->IsTank(member)) { - float moveDistance = std::min(moveIncrement, radius - dist + 1.0f); - return FleePosition(unit->GetPosition(), moveDistance); - // return MoveAway(unit, moveDistance); + if (member == bot) + { + rangedIndex = currentIndex; + break; + } + currentIndex++; } } - } - return false; // Everyone is in position + if (rangedIndex == -1) + return false; + + // Fixed positions calculation + float tankToBossAngle = 3.14f; + const float minBossDistance = 15.0f; + const float spreadDistance = 10.0f; + + // Calculate position in a fixed grid (3 rows x 5 columns) + int row = rangedIndex / 5; + int col = rangedIndex % 5; + + // Calculate base position + float xOffset = (col - 2) * spreadDistance; // Center around tank position + float yOffset = minBossDistance + (row * spreadDistance); // Each row further back + + // Add zigzag offset for odd rows + if (row % 2 == 1) + xOffset += spreadDistance / 2; + + // Rotate position based on tank-to-boss angle + float finalX = ICC_DBS_TANK_POSITION.GetPositionX() + (cos(tankToBossAngle) * yOffset - sin(tankToBossAngle) * xOffset); + float finalY = ICC_DBS_TANK_POSITION.GetPositionY() + (sin(tankToBossAngle) * yOffset + cos(tankToBossAngle) * xOffset); + float finalZ = ICC_DBS_TANK_POSITION.GetPositionZ(); + + // Update Z coordinate + bot->UpdateAllowedPositionZ(finalX, finalY, finalZ); + + // Move if not in position + if (bot->GetExactDist2d(finalX, finalY) > 3.0f) + return MoveTo(bot->GetMapId(), finalX, finalY, finalZ, + false, false, false, true, MovementPriority::MOVEMENT_COMBAT); } + return false; } bool IccAddsDbsAction::Execute(Event event) { if (botAI->IsHeal(bot)) - { return false; - } - // Find the boss - Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); - if (!boss) { return false; } - if (!(bot->HasAura(71042) || bot->HasAura(72408)) && botAI->IsMainTank(bot)) //rune of blood aura + Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); + if (!boss) + return false; + + if (!botAI->GetAura("Rune of Blood", bot) && botAI->IsMainTank(bot)) return false; Unit* currentTarget = AI_VALUE(Unit*, "current target"); @@ -558,6 +598,7 @@ bool IccAddsDbsAction::Execute(Event event) return false; } + //FESTERGUT bool IccFestergutTankPositionAction::Execute(Event event) { @@ -574,50 +615,116 @@ bool IccFestergutTankPositionAction::Execute(Event event) false, false, true, MovementPriority::MOVEMENT_NORMAL); } - float radius = 10.0f; GuidVector members = AI_VALUE(GuidVector, "group members"); - - // First check if any group members have spores bool sporesPresent = false; for (auto& member : members) { Unit* unit = botAI->GetUnit(member); - if (unit && unit->HasAura(69279)) // gas spore + if (!unit) + continue; + + if (unit->HasAura(69279)) { sporesPresent = true; break; } } - // Only spread out if no spores are active if (!sporesPresent && (botAI->IsRanged(bot) || botAI->IsHeal(bot))) { - // Find closest player (including melee) - Unit* closestPlayer = nullptr; - float minDist = radius; + Group* group = bot->GetGroup(); + if (!group) + return false; + + // Separate counters for healers and ranged DPS + int healerIndex = -1; + int rangedDpsIndex = -1; + int currentHealerIndex = 0; + int currentRangedDpsIndex = 0; - for (auto& member : members) + // First pass: count total healers and ranged + int totalHealers = 0; + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { - Unit* unit = botAI->GetUnit(member); - if (!unit || unit == bot) + Player* member = itr->GetSource(); + if (!member || !member->IsAlive() || botAI->IsTank(member)) continue; - - float dist = bot->GetExactDist2d(unit); - if (dist < minDist) - { - minDist = dist; - closestPlayer = unit; - } + + if (botAI->IsHeal(member)) + totalHealers++; } - if (closestPlayer) + // Second pass: assign positions + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { - // Move away from closest player, but maintain roughly max range from boss - float distToCenter = bot->GetExactDist2d(ICC_FESTERGUT_TANK_POSITION); - float moveDistance = (distToCenter > 25.0f) ? 2.0f : 3.0f; // Move less if already far from center - return FleePosition(closestPlayer->GetPosition(), moveDistance); - // return MoveAway(closestPlayer, moveDistance); + Player* member = itr->GetSource(); + if (!member || !member->IsAlive() || botAI->IsTank(member)) + continue; + + if (member == bot) + { + if (botAI->IsHeal(bot)) + healerIndex = currentHealerIndex; + else if (botAI->IsRanged(bot)) + rangedDpsIndex = currentRangedDpsIndex; + break; + } + + if (botAI->IsHeal(member)) + currentHealerIndex++; + else if (botAI->IsRanged(member)) + currentRangedDpsIndex++; + } + + int positionIndex; + if (healerIndex != -1) + { + // Healers get positions in first two rows + int healersPerRow = (totalHealers + 1) / 2; // Round up + positionIndex = healerIndex; + // Ensure healer is in first two rows + if (positionIndex >= healersPerRow) + { + positionIndex = positionIndex - healersPerRow + 5; // Move to second row + } } + else if (rangedDpsIndex != -1) + { + // Ranged DPS start from where healers end + positionIndex = totalHealers + rangedDpsIndex; + } + else + return false; + + // Fixed positions calculation + float tankToBossAngle = 4.58f; + const float minBossDistance = 20.0f; + const float spreadDistance = 10.0f; + + // Calculate position in a fixed grid (3 rows x 5 columns) + int row = positionIndex / 5; + int col = positionIndex % 5; + + // Calculate base position + float xOffset = (col - 2) * spreadDistance; // Center around tank position + float yOffset = minBossDistance + (row * spreadDistance); // Each row further back + + // Add zigzag offset for odd rows + if (row % 2 == 1) + xOffset += spreadDistance / 2; + + // Rotate position based on tank-to-boss angle + float finalX = ICC_FESTERGUT_TANK_POSITION.GetPositionX() + (cos(tankToBossAngle) * yOffset - sin(tankToBossAngle) * xOffset); + float finalY = ICC_FESTERGUT_TANK_POSITION.GetPositionY() + (sin(tankToBossAngle) * yOffset + cos(tankToBossAngle) * xOffset); + float finalZ = ICC_FESTERGUT_TANK_POSITION.GetPositionZ(); + + // Update Z coordinate + bot->UpdateAllowedPositionZ(finalX, finalY, finalZ); + + // Move if not in position + if (bot->GetExactDist2d(finalX, finalY) > 3.0f) + return MoveTo(bot->GetMapId(), finalX, finalY, finalZ, + false, false, false, true, MovementPriority::MOVEMENT_COMBAT); } return false; } @@ -888,7 +995,7 @@ bool IccRotfaceGroupPositionAction::Execute(Event event) bool IccRotfaceMoveAwayFromExplosionAction::Execute(Event event) { if (botAI->IsMainTank(bot) || bot->HasAura(71215)) - { return false; } + return false; // Stop current actions first bot->AttackStop(); @@ -1671,55 +1778,151 @@ bool IccBpcKineticBombAction::Execute(Event event) bool IccBqlTankPositionAction::Execute(Event event) { Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel"); + Aura* aura = botAI->GetAura("Frenzied Bloodthirst", bot); + Aura* aura2 = botAI->GetAura("Swarming Shadows", bot); // If tank is not at position, move there - if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot)) + if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot) && !(aura || aura2)) { - if (bot->GetExactDist2d(ICC_BQL_TANK_POSITION) > 20.0f) - return MoveTo(bot->GetMapId(), ICC_BQL_TANK_POSITION.GetPositionX(), - ICC_BQL_TANK_POSITION.GetPositionY(), ICC_BQL_TANK_POSITION.GetPositionZ(), - false, true, false, true, MovementPriority::MOVEMENT_COMBAT); + if (bot->GetExactDist2d(ICC_BQL_TANK_POSITION) > 10.0f) + return MoveTo(bot->GetMapId(), ICC_BQL_TANK_POSITION.GetPositionX(), + ICC_BQL_TANK_POSITION.GetPositionY(), ICC_BQL_TANK_POSITION.GetPositionZ(), + false, false, false, true, MovementPriority::MOVEMENT_FORCED); } + // If assist tank and no blood mirror, move to extact postion of main tank + if (botAI->IsAssistTank(bot) && !botAI->GetAura("Blood Mirror", bot) && !(aura || aura2)) + { + Unit* mainTank = AI_VALUE(Unit*, "main tank"); + if (!mainTank) + return false; + + return MoveTo(bot->GetMapId(), mainTank->GetPositionX(), mainTank->GetPositionY(), mainTank->GetPositionZ(), + false, false, false, true, MovementPriority::MOVEMENT_FORCED); + } + float radius = 8.0f; float moveIncrement = 3.0f; bool isRanged = botAI->IsRanged(bot); bool isMelee = botAI->IsMelee(bot); - Aura* aura = botAI->GetAura("Frenzied Bloodthirst", bot); + + //if bot has Swarming Shadows, move to the wall + if (aura2) + { + // Get current position and map + float currentX = bot->GetPositionX(); + float currentY = bot->GetPositionY(); + float currentZ = bot->GetPositionZ(); + Map* map = bot->GetMap(); + + float bestDist = 100.0f; + float bestX = currentX; + float bestY = currentY; + bool foundWall = false; + + // Check only east (0) and west (π) directions for walls + float angles[2] = {M_PI_2, -M_PI_2}; // East = π/2, West = -π/2 + for (float angle : angles) + { + float dx = cos(angle); + float dy = sin(angle); + + // Binary search to find the wall + float minDist = 5.0f; + float maxDist = 100.0f; + float wallDist = maxDist; + + for (int i = 0; i < 8; i++) + { + float testDist = (minDist + maxDist) / 2; + float testX = currentX + dx * testDist; + float testY = currentY + dy * testDist; + float testZ = currentZ; + + bool heightFound = map->GetHeight(testX, testY, testZ); + if (!heightFound) + testZ = currentZ; + + bool hasLos = map->isInLineOfSight(currentX, currentY, currentZ + 2.0f, + testX, testY, testZ + 2.0f, + bot->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::Nothing); + + if (hasLos) + { + minDist = testDist; + } + else + { + maxDist = testDist; + wallDist = testDist; + foundWall = true; + } + } + + if (foundWall && wallDist < bestDist) + { + bestDist = wallDist; + bestX = currentX + dx * (wallDist - 2.0f); // Stay 2 yards from wall + bestY = currentY + dy * (wallDist - 2.0f); + } + } + + // Only move if we're too far from the wall + if (foundWall && bestDist > 10.0f) + { + // Verify we still have the aura before moving + if (!botAI->GetAura("Swarming Shadows", bot)) + return false; + + return MoveTo(bot->GetMapId(), bestX, bestY, bot->GetPositionZ(), + false, false, false, true, MovementPriority::MOVEMENT_FORCED); + } + } GuidVector members = AI_VALUE(GuidVector, "group members"); - if (isRanged && !aura) //frenzied bloodthrist + + if (isRanged && !aura && !aura2) //frenzied bloodthrist { // Ranged: spread from other ranged for (auto& member : members) { Unit* unit = botAI->GetUnit(member); - if (!unit || !unit->IsAlive() || unit == bot || botAI->GetAura("Frenzied Bloodthirst", unit)) + if (!unit || !unit->IsAlive() || unit == bot || botAI->GetAura("Frenzied Bloodthirst", unit) || botAI->GetAura("Uncontrollable Frenzy", unit)) continue; float dist = bot->GetExactDist2d(unit); if (dist < radius) { float moveDistance = std::min(moveIncrement, radius - dist + 1.0f); - return MoveAway(unit, moveDistance); + return FleePosition(unit->GetPosition(), moveDistance, 250U); + //return MoveAway(unit, moveDistance); } } } - if (isMelee && !aura && boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)) // melee also spread + if (isMelee && !aura && !aura2 && ((boss->GetPositionZ() - bot->GetPositionZ()) > 5.0f)) // melee also spread { // Melee: spread from other melee for (auto& member : members) { Unit* unit = botAI->GetUnit(member); - if (!unit || !unit->IsAlive() || unit == bot || botAI->GetAura("Frenzied Bloodthirst", unit)) + if (!unit || !unit->IsAlive() || unit == bot || botAI->GetAura("Frenzied Bloodthirst", unit) || botAI->GetAura("Uncontrollable Frenzy", unit)) continue; float dist = bot->GetExactDist2d(unit); if (dist < radius) { - float moveDistance = std::min(moveIncrement, radius - dist + 1.0f); - return MoveAway(unit, moveDistance); + // Calculate direction away from nearby player + float dx = bot->GetPositionX() - unit->GetPositionX(); + float dy = bot->GetPositionY() - unit->GetPositionY(); + float angle = atan2(dy, dx); + + // Move 8 yards away from the player + float newX = unit->GetPositionX() + cos(angle) * 8.0f; + float newY = unit->GetPositionY() + sin(angle) * 8.0f; + + return MoveTo(bot->GetMapId(), newX, newY, bot->GetPositionZ(), + false, false, false, true, MovementPriority::MOVEMENT_FORCED); } } } @@ -1907,7 +2110,9 @@ bool IccBqlVampiricBiteAction::Execute(Event event) } // Double check target is still alive - if (!target->IsAlive()) + if (!target->IsAlive() || (botAI->GetAura("Frenzied Bloodthirst", target) + || botAI->GetAura("Essence of the Blood Queen", target) + || botAI->GetAura("Uncontrollable Frenzy", target))) { return false; } @@ -1917,7 +2122,10 @@ bool IccBqlVampiricBiteAction::Execute(Event event) float y = target->GetPositionY(); float z = target->GetPositionZ(); - if (bot->IsWithinLOS(x, y, z) && bot->GetExactDist2d(target) > BITE_RANGE) + if (bot->IsWithinLOS(x, y, z) && bot->GetExactDist2d(target) > BITE_RANGE + && !(botAI->GetAura("Frenzied Bloodthirst", target) + || botAI->GetAura("Essence of the Blood Queen", target) + || botAI->GetAura("Uncontrollable Frenzy", target))) { return MoveTo(target->GetMapId(), x, y, z, false, false, false, true, MovementPriority::MOVEMENT_FORCED); } @@ -1926,7 +2134,9 @@ bool IccBqlVampiricBiteAction::Execute(Event event) if (bot->IsWithinLOS(x, y, z) && bot->GetExactDist2d(target) <= BITE_RANGE) { // Final alive check before casting - if (!target->IsAlive()) + if (!target->IsAlive() || (botAI->GetAura("Frenzied Bloodthirst", target) + || botAI->GetAura("Essence of the Blood Queen", target) + || botAI->GetAura("Uncontrollable Frenzy", target))) { return false; } @@ -2047,10 +2257,33 @@ bool IccValithriaHealAction::Execute(Event event) bot->SetSpeed(MOVE_FLIGHT, 1.0f, true); } // Find Valithria + + if (bot->GetPositionZ() > 367.961f) + return bot->TeleportTo(bot->GetMapId(), bot->GetPositionX(), + bot->GetPositionY(), 365.0f, bot->GetOrientation()); + if (Creature* valithria = bot->FindNearestCreature(36789, 100.0f)) { switch (bot->getClass()) { + case CLASS_DRUID: + { + // Check for Rejuvenation (48441) + if (!valithria->HasAura(48441)) + return botAI->CastSpell(48441, valithria); + + // Check for Regrowth (48443) + if (!valithria->HasAura(48443)) + return botAI->CastSpell(48443, valithria); + + // Check for Lifebloom stacks (48451) + Aura* lifebloom = valithria->GetAura(48451); + if (!lifebloom || lifebloom->GetStackAmount() < 3) + return botAI->CastSpell(48451, valithria); + + // If all HoTs are up with full stacks, cast Wild Growth (53251) + return botAI->CastSpell(53251, valithria); + } case CLASS_SHAMAN: return valithria->HasAura(61301) ? botAI->CastSpell(49273, valithria) : botAI->CastSpell(61301, valithria); // Cast Healing Wave if Riptide is up, otherwise cast Riptide case CLASS_PRIEST: diff --git a/src/strategy/raids/icecrown/RaidIccActions.h b/src/strategy/raids/icecrown/RaidIccActions.h index c1347acf..66bd93b9 100644 --- a/src/strategy/raids/icecrown/RaidIccActions.h +++ b/src/strategy/raids/icecrown/RaidIccActions.h @@ -16,6 +16,7 @@ const Position ICC_LM_TANK_POSITION = Position(-391.0f, 2259.0f, 42.0f); const Position ICC_DARK_RECKONING_SAFE_POSITION = Position(-523.33386f, 2211.2031f, 62.823116f); +const Position ICC_LDW_TANK_POSTION = Position(-589.9879f, 2211.2456f, 49.476616f); const Position ICC_ROTTING_FROST_GIANT_TANK_POSITION = Position(-265.90125f, 2209.0605f, 199.97006f); const Position ICC_GUNSHIP_TELEPORT_ALLY = Position (-370.04645f, 1993.3536f, 466.65656f); const Position ICC_GUNSHIP_TELEPORT_ALLY2 = Position (-392.66208f, 2064.893f, 466.5672f, 5.058196f); diff --git a/src/strategy/raids/icecrown/RaidIccMultipliers.cpp b/src/strategy/raids/icecrown/RaidIccMultipliers.cpp index da27c079..6c645381 100644 --- a/src/strategy/raids/icecrown/RaidIccMultipliers.cpp +++ b/src/strategy/raids/icecrown/RaidIccMultipliers.cpp @@ -407,17 +407,29 @@ float IccBqlVampiricBiteMultiplier::GetValue(Action* action) if (!boss) return 1.0f; - if (bot->HasAura(70877) || bot->HasAura(71474)) // If bot has frenzied bloodthirst + Aura* aura = botAI->GetAura("Frenzied Bloodthirst", bot); + + if (botAI->IsMelee(bot) && ((boss->GetPositionZ() - bot->GetPositionZ()) > 5.0f) && !aura) + { + if (dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action)) + return 0.0f; + } + + // If bot has frenzied bloodthirst, allow highest priority for bite action + if (aura) // If bot has frenzied bloodthirst { if (dynamic_cast(action)) return 5.0f; // Highest priority for bite action - else if (dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action) || - dynamic_cast(action)) + + if (dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action)) return 0.0f; // Disable all formation/movement actions - else - return 0.0f; // Disable all other actions } return 1.0f; diff --git a/src/strategy/raids/icecrown/RaidIccStrategy.cpp b/src/strategy/raids/icecrown/RaidIccStrategy.cpp index 2e8338c7..f554d021 100644 --- a/src/strategy/raids/icecrown/RaidIccStrategy.cpp +++ b/src/strategy/raids/icecrown/RaidIccStrategy.cpp @@ -114,7 +114,7 @@ void RaidIccStrategy::InitTriggers(std::vector& triggers) NextAction::array(0, new NextAction("icc bql pact of darkfallen", ACTION_RAID +1), nullptr))); triggers.push_back(new TriggerNode("icc bql vampiric bite", - NextAction::array(0, new NextAction("icc bql vampiric bite", ACTION_RAID + 2), nullptr))); + NextAction::array(0, new NextAction("icc bql vampiric bite", ACTION_EMERGENCY + 5), nullptr))); //VDW triggers.push_back(new TriggerNode("icc valkyre spear", diff --git a/src/strategy/raids/icecrown/RaidIccTriggers.cpp b/src/strategy/raids/icecrown/RaidIccTriggers.cpp index e0525b9b..46bfb031 100644 --- a/src/strategy/raids/icecrown/RaidIccTriggers.cpp +++ b/src/strategy/raids/icecrown/RaidIccTriggers.cpp @@ -68,7 +68,8 @@ bool IccRangedPositionLadyDeathwhisperTrigger::IsActive() bool IccAddsLadyDeathwhisperTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); - if (!boss) { return false; } + if (!boss) + return false; return true; } @@ -587,6 +588,61 @@ bool IccValithriaPortalTrigger::IsActive() if (!botAI->IsHeal(bot) || bot->HasAura(70766)) return false; + Group* group = bot->GetGroup(); + if (!group) + return false; + + // Count healers and collect their GUIDs + std::vector healerGuids; + int healerCount = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player* member = itr->GetSource(); + if (!member || !member->IsAlive()) + continue; + + if (botAI->IsHeal(member)) + { + healerCount++; + healerGuids.push_back(member->GetGUID()); + } + } + + // Sort GUIDs to ensure consistent ordering + std::sort(healerGuids.begin(), healerGuids.end()); + + // Find position of current bot's GUID in the sorted list + auto botGuidPos = std::find(healerGuids.begin(), healerGuids.end(), bot->GetGUID()); + if (botGuidPos == healerGuids.end()) + return false; + + int healerIndex = std::distance(healerGuids.begin(), botGuidPos); + + // Determine if this healer should focus on raid + bool shouldHealRaid = false; + + if (healerCount > 3) + { + // If more than 3 healers, 2 should heal raid + if (bot->getClass() == CLASS_DRUID) + shouldHealRaid = true; // Druids prioritize raid healing + else + shouldHealRaid = (healerIndex >= (healerCount - 2)); // Last 2 healers (by GUID) heal raid if no druid + } + else + { + // If 3 or fewer healers, 1 should heal raid + if (bot->getClass() == CLASS_DRUID) + shouldHealRaid = true; // Druids prioritize raid healing + else + shouldHealRaid = (healerIndex == (healerCount - 1)); // Last healer (by GUID) heals raid if no druid + } + + // Raid healers should not use portals + if (shouldHealRaid) + return false; + // Find the nearest portal creature Creature* portal = bot->FindNearestCreature(37945, 100.0f); // Only check within 10 yards Creature* portal2 = bot->FindNearestCreature(38430, 100.0f); // Only check within 10 yards @@ -604,6 +660,62 @@ bool IccValithriaHealTrigger::IsActive() if (!botAI->IsHeal(bot) || bot->HasAura(70766)) return false; + Group* group = bot->GetGroup(); + if (!group) + return false; + + // Count healers and collect their GUIDs + std::vector healerGuids; + int healerCount = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + { + Player* member = itr->GetSource(); + if (!member || !member->IsAlive()) + continue; + + if (botAI->IsHeal(member)) + { + healerCount++; + healerGuids.push_back(member->GetGUID()); + } + } + + // Sort GUIDs to ensure consistent ordering + std::sort(healerGuids.begin(), healerGuids.end()); + + // Find position of current bot's GUID in the sorted list + auto botGuidPos = std::find(healerGuids.begin(), healerGuids.end(), bot->GetGUID()); + if (botGuidPos == healerGuids.end()) + return false; + + int healerIndex = std::distance(healerGuids.begin(), botGuidPos); + + // Determine if this healer should focus on raid + bool shouldHealRaid = false; + + if (healerCount > 3) + { + // If more than 3 healers, 2 should heal raid + if (bot->getClass() == CLASS_DRUID) + shouldHealRaid = true; // Druids prioritize raid healing + else + shouldHealRaid = (healerIndex >= (healerCount - 2)); // Last 2 healers (by GUID) heal raid if no druid + } + else + { + // If 3 or fewer healers, 1 should heal raid + if (bot->getClass() == CLASS_DRUID) + shouldHealRaid = true; // Druids prioritize raid healing + else + shouldHealRaid = (healerIndex == (healerCount - 1)); // Last healer (by GUID) heals raid if no druid + } + + // If assigned to raid healing, return false to not heal Valithria + if (shouldHealRaid) + return false; + + // For Valithria healers, check portal logic // If no portal is found within 100 yards, we should heal if (!bot->FindNearestCreature(37945, 100.0f) && !bot->FindNearestCreature(38430, 100.0f)) return true;