ICC BQL/VDW major update + minor fixes/improvements (#929)

LDW
Improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS
Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL
Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW
Boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid).
Druids will be assigned to raid healing if no druid present then some other random heal class.
Added rotations for druid healers if they end up healing the boss.
Raid healers will not use portals anymore.
Healers will come to the ground now after using portals (they were stuck in air)
This commit is contained in:
Noscopezz
2025-01-30 17:07:01 +01:00
committed by GitHub
parent d770e0a9a0
commit bdf8c6cc14
5 changed files with 441 additions and 83 deletions

View File

@@ -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:

View File

@@ -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);

View File

@@ -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<DpsAssistAction*>(action) ||
dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
dynamic_cast<CombatFormationMoveAction*>(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<IccBqlVampiricBiteAction*>(action))
return 5.0f; // Highest priority for bite action
else if (dynamic_cast<DpsAssistAction*>(action) ||
dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
dynamic_cast<CombatFormationMoveAction*>(action))
if (dynamic_cast<DpsAssistAction*>(action) ||
dynamic_cast<IccBqlTankPositionAction*>(action) ||
dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
dynamic_cast<CombatFormationMoveAction*>(action))
return 0.0f; // Disable all formation/movement actions
else
return 0.0f; // Disable all other actions
}
return 1.0f;

View File

@@ -114,7 +114,7 @@ void RaidIccStrategy::InitTriggers(std::vector<TriggerNode*>& 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",

View File

@@ -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<ObjectGuid> 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<ObjectGuid> 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;