diff --git a/src/strategy/raids/icecrown/RaidIccActions.cpp b/src/strategy/raids/icecrown/RaidIccActions.cpp index bead3a56..f0a0b436 100644 --- a/src/strategy/raids/icecrown/RaidIccActions.cpp +++ b/src/strategy/raids/icecrown/RaidIccActions.cpp @@ -37,7 +37,6 @@ bool IccLmTankPositionAction::Execute(Event event) if (!boss) return false; - bot->SetTarget(boss->GetGUID()); if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot)) { if (bot->GetExactDist2d(ICC_LM_TANK_POSITION) > 15.0f) @@ -45,9 +44,10 @@ bool IccLmTankPositionAction::Execute(Event event) ICC_LM_TANK_POSITION.GetPositionY(), ICC_LM_TANK_POSITION.GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); else - return Attack(boss); + return false; } - return Attack(boss); + + return false; } bool IccSpikeAction::Execute(Event event) @@ -60,48 +60,78 @@ bool IccSpikeAction::Execute(Event event) // Find the boss Unit* boss = AI_VALUE2(Unit*, "find target", "lord marrowgar"); - if (!boss) { return false; } + if (!boss) + return false; - Unit* currentTarget = AI_VALUE(Unit*, "current target"); - - GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + Aura* bossaura = botAI->GetAura("Bone Storm", boss); - Unit* spikeTarget = nullptr; - for (auto i = targets.begin(); i != targets.end(); ++i) + if (boss->isInFront(bot) && !botAI->IsTank(bot) && !bossaura) + return MoveTo(bot->GetMapId(), -390.6757f, 2230.5283f, 41.99232f, false, false, false, true, + MovementPriority::MOVEMENT_FORCED); + + if (!botAI->IsTank(bot)) + return false; + + GuidVector spikes = AI_VALUE(GuidVector, "possible targets no los"); + const uint32 spikeEntries[] = {36619, 38711, 38712}; // spikes id's + + Unit* priorityTarget = nullptr; + bool anySpikesExist = false; + + // First check for alive spikes + for (uint32 entry : spikeEntries) { - Unit* unit = botAI->GetUnit(*i); - if (unit && (unit->GetEntry() == 36619 || - unit->GetEntry() == 38711 || - unit->GetEntry() == 38712)) + for (const ObjectGuid& guid : spikes) { - spikeTarget = unit; - break; - } - } - - // Prioritize attacking a bone spike if found - if (spikeTarget) - { - if (currentTarget != spikeTarget) - { - if (Attack(spikeTarget)) + Unit* unit = botAI->GetUnit(guid); + if (unit && unit->GetEntry() == entry) // Check if spike exists { - return Attack(spikeTarget); + anySpikesExist = true; // At least one spike exists + + if (unit->IsAlive()) // Only consider alive ones for targeting + { + priorityTarget = unit; + break; + } } } - return Attack(spikeTarget); // Already attacking a spike + if (priorityTarget) + break; } - // No bone spikes found, attack boss if not already targeting - if (currentTarget != boss) + // Only fallback to boss if NO spikes exist at all (alive or dead) + if (!anySpikesExist && boss->IsAlive()) { - if (Attack(boss)) + priorityTarget = boss; + } + + // Update skull icon if needed + if (priorityTarget) + { + if (Group* group = bot->GetGroup()) { - return Attack(boss); + ObjectGuid currentSkull = group->GetTargetIcon(7); + Unit* currentSkullUnit = botAI->GetUnit(currentSkull); + + bool needsUpdate = false; + if (!currentSkullUnit || !currentSkullUnit->IsAlive()) + { + needsUpdate = true; + } + else if (currentSkullUnit != priorityTarget) + { + needsUpdate = true; + } + + if (needsUpdate) + { + group->SetTargetIcon(7, bot->GetGUID(), priorityTarget->GetGUID()); + } } } return false; + } //Lady @@ -118,10 +148,19 @@ bool IccDarkReckoningAction::Execute(Event event) bool IccRangedPositionLadyDeathwhisperAction::Execute(Event event) { + Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper"); + if (!boss) + return false; + + float currentDistance = bot->GetDistance2d(boss); + + if (currentDistance < 7.0f || currentDistance > 30.0f) + return false; + if (botAI->IsRanged(bot) || botAI->IsHeal(bot)) { - float radius = 5.0f; - float moveIncrement = 3.0f; + float radius = 3.0f; + float moveIncrement = 2.0f; bool isRanged = botAI->IsRanged(bot); GuidVector members = AI_VALUE(GuidVector, "group members"); @@ -155,7 +194,7 @@ bool IccAddsLadyDeathwhisperAction::Execute(Event event) if (!boss) return false; - if (botAI->IsTank(bot) && boss->GetHealthPct() < 98.0f) + if (botAI->IsTank(bot) && boss->GetHealthPct() < 95.0f) { if (bot->GetExactDist2d(ICC_LDW_TANK_POSTION) > 20.0f) return MoveTo(bot->GetMapId(), ICC_LDW_TANK_POSTION.GetPositionX(), @@ -163,69 +202,68 @@ bool IccAddsLadyDeathwhisperAction::Execute(Event event) false, false, false, MovementPriority::MOVEMENT_COMBAT); } - if (botAI->IsMainTank(bot) || botAI->IsHeal(bot)) + if (!botAI->IsTank(bot)) return false; Unit* currentTarget = AI_VALUE(Unit*, "current target"); - GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); - Unit* add = nullptr; - for (auto i = targets.begin(); i != targets.end(); ++i) - { - Unit* unit = botAI->GetUnit(*i); - if (unit && (unit->GetEntry() == 37949 || //cult adherent - unit->GetEntry() == 38394 || - unit->GetEntry() == 38625 || - unit->GetEntry() == 38626 || - unit->GetEntry() == 38010 || - unit->GetEntry() == 38397 || - unit->GetEntry() == 39000 || - unit->GetEntry() == 39001 || - unit->GetEntry() == 38136 || - unit->GetEntry() == 38396 || - unit->GetEntry() == 38632 || - unit->GetEntry() == 38633 || - unit->GetEntry() == 37890 || //cult fanatic - unit->GetEntry() == 38393 || - unit->GetEntry() == 38628 || - unit->GetEntry() == 38629 || - unit->GetEntry() == 38135 || - unit->GetEntry() == 38395 || - unit->GetEntry() == 38634 || - unit->GetEntry() == 38009 || - unit->GetEntry() == 38398 || - unit->GetEntry() == 38630 || - unit->GetEntry() == 38631)) - { - add = unit; - break; - } - } + const uint32 targetsEntries[] = {37949, 38394, 38625, 38626, 38010, 38397, 39000, 39001, 38136, 38396, 38632, 38633, 37890, 38393, 38628, 38629, 38135, 38395, 38634, 38009, 38398, 38630, 38631}; //fanatics and adherents - // Prioritize attacking an add if found - if (add) + Unit* priorityTarget = nullptr; + bool hasValidAdds = false; + + // First check for alive adds + for (uint32 entry : targetsEntries) { - if (currentTarget != add) + for (const ObjectGuid& guid : targets) { - if (Attack(add)) + Unit* unit = botAI->GetUnit(guid); + if (unit && unit->IsAlive() && unit->GetEntry() == entry) { - return Attack(add); + priorityTarget = unit; + hasValidAdds = true; + break; } } - return Attack(add); // Already attacking an add + if (priorityTarget) + break; } - // No adds found, attack boss if not already targeting - if (currentTarget != boss) + // Only fallback to boss if NO adds exist + if (!hasValidAdds && boss->IsAlive()) { - if (Attack(boss)) + priorityTarget = boss; + } + + // Update skull icon if needed + if (priorityTarget) + { + if (Group* group = bot->GetGroup()) { - return Attack(boss); + ObjectGuid currentSkull = group->GetTargetIcon(7); + Unit* currentSkullUnit = botAI->GetUnit(currentSkull); + + bool needsUpdate = false; + if (!currentSkullUnit || !currentSkullUnit->IsAlive()) + { + needsUpdate = true; // No valid skull target + } + else if (currentSkullUnit != priorityTarget) + { + needsUpdate = true; // Different target than desired + } + + if (needsUpdate) + { + group->SetTargetIcon(7, bot->GetGUID(), priorityTarget->GetGUID()); + } } } return false; + } bool IccShadeLadyDeathwhisperAction::Execute(Event event) @@ -479,128 +517,171 @@ bool IccDbsTankPositionAction::Execute(Event event) if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot)) { if (bot->GetExactDist2d(ICC_DBS_TANK_POSITION) > 5.0f) - return MoveTo(bot->GetMapId(), ICC_DBS_TANK_POSITION.GetPositionX(), - ICC_DBS_TANK_POSITION.GetPositionY(), ICC_DBS_TANK_POSITION.GetPositionZ(), false, - false, false, true, MovementPriority::MOVEMENT_NORMAL); + return MoveTo(bot->GetMapId(), ICC_DBS_TANK_POSITION.GetPositionX(), ICC_DBS_TANK_POSITION.GetPositionY(), + ICC_DBS_TANK_POSITION.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL); } - if (botAI->GetAura("Rune of Blood", bot)) + if (botAI->GetAura("Rune of Blood", bot) && botAI->IsTank(bot)) return true; if (botAI->IsRanged(bot) || botAI->IsHeal(bot)) { - // Get group and position in group - Group* group = bot->GetGroup(); - if (!group) - return false; + const float evasion = 12.0f; - // 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()) + // Get the nearest hostile NPCs + GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); + for (auto& npc : npcs) { - Player* member = itr->GetSource(); - if (!member || !member->IsAlive()) - continue; - - if ((botAI->IsRanged(member) || botAI->IsHeal(member)) && !botAI->IsTank(member)) + Unit* unit = botAI->GetUnit(npc); + if (unit && (unit->GetEntry() == 38508 || unit->GetEntry() == 38596 || unit->GetEntry() == 38597 || + unit->GetEntry() == 38598)) // blood beast { - if (member == bot) + // Only run away if the blood beast is targeting us + if (unit->GetVictim() == bot) { - rangedIndex = currentIndex; - break; + float currentDistance = bot->GetDistance2d(unit); + + // Move away from the blood beast if the bot is too close + if (currentDistance < evasion) + { + return MoveAway(unit, evasion - currentDistance); + } } - currentIndex++; } } - if (rangedIndex == -1) + // Get group and position in group + Group* group = bot->GetGroup(); + if (!group) + return false; + + // 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()) + { + Player* member = itr->GetSource(); + if (!member || !member->IsAlive()) + continue; + + if ((botAI->IsRanged(member) || botAI->IsHeal(member)) && !botAI->IsTank(member)) + { + if (member == bot) + { + rangedIndex = currentIndex; + break; + } + currentIndex++; + } + } + + if (rangedIndex == -1) + return false; + + // Fixed positions calculation + float tankToBossAngle = 3.14f; + const float minBossDistance = 11.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; + } - // 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; } - - return false; -} bool IccAddsDbsAction::Execute(Event event) { - if (botAI->IsHeal(bot)) - return false; Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); if (!boss) return false; - if (!botAI->GetAura("Rune of Blood", bot) && botAI->IsMainTank(bot)) + if (!botAI->IsMelee(bot)) return false; Unit* currentTarget = AI_VALUE(Unit*, "current target"); - - GuidVector targets = AI_VALUE(GuidVector, "possible targets"); - Unit* add = nullptr; - for (auto i = targets.begin(); i != targets.end(); ++i) - { - Unit* unit = botAI->GetUnit(*i); - if (unit && (unit->GetEntry() == 38508 || //blood beast - unit->GetEntry() == 38596 || - unit->GetEntry() == 38597 || - unit->GetEntry() == 38598)) - { - add = unit; - break; - } - } + GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); - // Prioritize attacking an add if found - if (add && !botAI->IsHeal(bot)) + const uint32 targetsEntries[] = {38508, 38596, 38597, 38598}; // adds + + Unit* priorityTarget = nullptr; + bool hasValidAdds = false; + + // First check for alive adds + for (uint32 entry : targetsEntries) { - if (currentTarget != add) + for (const ObjectGuid& guid : targets) { - if (Attack(add)) + Unit* unit = botAI->GetUnit(guid); + if (unit && unit->IsAlive() && unit->GetEntry() == entry) { - return Attack(add); + priorityTarget = unit; + hasValidAdds = true; + break; } } - return Attack(add); // Already attacking an add + if (priorityTarget) + break; } - // No adds found, attack boss if not already targeting - if (currentTarget != boss) + // Only fallback to boss if NO adds exist + if (!hasValidAdds && boss->IsAlive()) { - if (Attack(boss)) + priorityTarget = boss; + } + + // Update skull icon if needed + if (priorityTarget) + { + if (Group* group = bot->GetGroup()) { - return Attack(boss); + ObjectGuid currentSkull = group->GetTargetIcon(7); + Unit* currentSkullUnit = botAI->GetUnit(currentSkull); + + bool needsUpdate = false; + if (!currentSkullUnit || !currentSkullUnit->IsAlive()) + { + needsUpdate = true; // No valid skull target + } + else if (currentSkullUnit != priorityTarget) + { + needsUpdate = true; // Different target than desired + } + + if (needsUpdate) + { + group->SetTargetIcon(7, bot->GetGUID(), priorityTarget->GetGUID()); + } } } diff --git a/src/strategy/raids/icecrown/RaidIccActions.h b/src/strategy/raids/icecrown/RaidIccActions.h index b7267e18..bee1ab62 100644 --- a/src/strategy/raids/icecrown/RaidIccActions.h +++ b/src/strategy/raids/icecrown/RaidIccActions.h @@ -16,7 +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_LDW_TANK_POSTION = Position(-570.1f, 2211.2456f, 49.476616f); //-590.0f 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 7e500309..ab6fc226 100644 --- a/src/strategy/raids/icecrown/RaidIccMultipliers.cpp +++ b/src/strategy/raids/icecrown/RaidIccMultipliers.cpp @@ -74,33 +74,6 @@ float IccAddsDbsMultiplier::GetValue(Action* action) } } - if (botAI->IsDps(bot)) - { - GuidVector targets = AI_VALUE(GuidVector, "possible targets"); - bool hasAdds = false; - for (auto& guid : targets) - { - Unit* unit = botAI->GetUnit(guid); - if (unit && unit->IsAlive() && ( - unit->GetEntry() == 38508 || //blood beast - unit->GetEntry() == 38596 || - unit->GetEntry() == 38597 || - unit->GetEntry() == 38598)) - { - hasAdds = true; - break; - } - } - - if (hasAdds && !botAI->IsMainTank(bot)) - { - if (dynamic_cast(action)) - return 2.0f; - else if (dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action) || dynamic_cast(action)) - return 0.0f; - } - } return 1.0f; } diff --git a/src/strategy/raids/icecrown/RaidIccTriggers.cpp b/src/strategy/raids/icecrown/RaidIccTriggers.cpp index 0870d90e..d643cb1b 100644 --- a/src/strategy/raids/icecrown/RaidIccTriggers.cpp +++ b/src/strategy/raids/icecrown/RaidIccTriggers.cpp @@ -25,25 +25,7 @@ bool IccSpikeNearTrigger::IsActive() if (!boss) return false; - GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); - for (auto& npc : npcs) - { - Unit* unit = botAI->GetUnit(npc); - if (unit) - { - if (unit->GetEntry() == 36619 || unit->GetEntry() == 38711 || unit->GetEntry() == 38712 ) //spike ID - { - if (unit->GetDistance(bot) <= 20.0f) - { - return botAI->IsDps(bot); - } - - return botAI->IsRangedDps(bot); - } - } - } - - return false; + return true; } //Lady Deathwhisper @@ -144,7 +126,8 @@ bool IccGunshipTeleportAllyTrigger::IsActive() bool IccGunshipTeleportHordeTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "skybreaker sorcerer"); - if (!boss) { return false; } + if (!boss) + return false; return true; } @@ -153,7 +136,8 @@ bool IccGunshipTeleportHordeTrigger::IsActive() bool IccDbsTankPositionTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); - if (!boss) { return false; } + if (!boss) + return false; return true; } @@ -182,9 +166,10 @@ bool IccDbsMainTankRuneOfBloodTrigger::IsActive() bool IccAddsDbsTrigger::IsActive() { Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang"); - if (!boss) { return false; } + if (!boss) + return false; - return true; + return true; } //DOGS @@ -1012,4 +997,4 @@ bool IccLichKingAddsTrigger::IsActive() return false; return true; -} \ No newline at end of file +}