mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Gunship fix (#846)
* ICC PP WIP WIP * added mutated plague for PP * BPC added (kinetic and boss targeting need to be done by player) OT collects dark nucles, bots spread on vortex and other stuff they do ok on their own. Tested only on 10NM, should work on 25NM * Tank pos. correction * BQL, ranged spread, link, flame, bite, tanking tested 10NM to do (better fire spread, hc tacti, melee spread when in air) * LDW improved improved shadow logic, ranged spread for easier shadow handling * dbs update, fixed teleporting Bots should only go and teleport to the mage that is actually below zero now * DBS ranged fix Ranged should spread more quickly and freak out less * Festergut && DBS fixed ranged spread (both) fixed spore logic (fester) * Rotface fix Improved big ooze tanking (static pos, todo kiting) ooze explosion spread mechanic fix ooze pool fix Player needs to mark rotface with skull icon, oterwise bots try to attack oozes * BQL fixed for 25nm todo: better melee logic in air phase, better melee flame spread * VDW, Sister Svalna, Sindy update Sister Svalna, bots can pickup spears and throw at svalna when she has shield up VDW added healer strats to use portal and heal boss (atm druids are for raid healing only, so use druide + any other healer, ideally player should be healer) todo (focus on supressers, add healer rotations, atm they use quickest spell they can) Sindragosa Added tank boss manipulation (boss orientation and position) bots detect (buffet, unchained magic and chilled to the bone and act accordingly) bots detect frost beacon move to safe spot and los frost bombs around them, while dpsing tombs (todo stop dps if only one tomb is left, if we have frost bombs around, not a big deal atm since in nm they dont one shot) Last phase bots los behind tomb to loose buffet, tanks swap when they have hi buffet count. Player should tell bots with skull rti if they should kill tomb or focus boss. todo (dynamic tomb los in last phase so that healers can see tank but also hide behind tomb to break los from boss) Removed some debug messages, improved LM spike action (nearest bots also try to help kill it) Improved Lady Deathwshiper shade action (only targeted bots will run away instead of every bot that is near it) dbs improved tank switch I recommend to use 3 healers (just to be safe) and 2 paladin tanks (warr seems to struggle with agro) in 10 man 25 man 6-7 healers (just to be safe) Since most of the bosses are about survival and not dps * LK Update (doable) LK added Improved tank switching for all bosses Fixed PP gas cloud kiting Malleable goo todo (dont know how to detect it since its not object or npc) just summon ranged bots to safe position to bypass BPC fixed OT sometimes not tanking kele kinectic bombs todo (for now player should take care of them) Sindragosa fixed rare case when she is in air phase but tombs went to last phase position LK Bots can handle necrotic Bots can handle adds Bots should focus valkyre that actually grabbed someone (if unlucky and player just use attack command and summon bots to you if they are far away from you) if they grab bots you can either summon to make them useless or let bots cc them and do it legit way. Defile should be watched by player and once it was cast just summon bots to you Vile spirits for some reason go to the ground and get nuked by bots aoe spells so there is not much to be done **Player needs to be alive the whole LK fight since you will have to watch out for frost spehers (sometimes bots ignore them), summon bots when defile is up and summon ranged bots if they get stuck near shambling or raging spirits since their aoe will wipe you) all in all LK is doable both 10 and 25nm, player needs to have knowledge of lk fight and needs to know how to use multibot addon and make macros for eg summoning or commanding groups of bots or individual bots) Dont forget frost/shadow/nature resist auras in whole ICC since it will help alot I have done whole icc 10 and 25 with 2 pala tanks, 2/5 heals and rest dps, if you use +1 or +2 heals it should be easier (since I was testing I did close to 0 dmg in fights same with heals) * fixed changes made by mistake fix * Malleable fix (simple spread mechanic) Malleable mechanic added (simple spread for now) Gas cloud fixed (Bots sometimes got stuck between puddle and kite location) * Defile Update Bots detect and avoid defile (they struggle to find a way back to the boss around it tho, use summon to help them) Melee bots should be able to stand behind/to the flank of shambling/spirits * GS fixed bots not returning to their ship for A and H Bots will return back to ship after killing mage * PP gas cloud kiting improved PP gas cloud kiting improved * BPC targeting fixed Bots will mark valid prince with skull RTI now * BQL added melee spread in air pahse BQL added melee spread * VDW healing rotation improved Healers will now use strong heals and hots * Fixed Necrotic Plague Fixed issue with Necrotic where it would get dispelled too soon, or would not get dispelled at all
This commit is contained in:
@@ -37,7 +37,7 @@ bool IccLmTankPositionAction::Execute(Event event)
|
||||
bot->SetTarget(boss->GetGUID());
|
||||
if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot))
|
||||
{
|
||||
if (bot->GetExactDist2d(ICC_LM_TANK_POSITION) > 5.0f)
|
||||
if (bot->GetExactDist2d(ICC_LM_TANK_POSITION) > 15.0f)
|
||||
return MoveTo(bot->GetMapId(), ICC_LM_TANK_POSITION.GetPositionX(),
|
||||
ICC_LM_TANK_POSITION.GetPositionY(), ICC_LM_TANK_POSITION.GetPositionZ(), false,
|
||||
false, false, true, MovementPriority::MOVEMENT_NORMAL);
|
||||
@@ -402,7 +402,11 @@ bool IccGunshipTeleportAllyAction::Execute(Event event)
|
||||
|
||||
// Only target the mage that is channeling Below Zero
|
||||
if (!(boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(69705)))
|
||||
return false;
|
||||
{
|
||||
if (bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_ALLY2) > 45.0f)
|
||||
return bot->TeleportTo(bot->GetMapId(), ICC_GUNSHIP_TELEPORT_ALLY2.GetPositionX(),
|
||||
ICC_GUNSHIP_TELEPORT_ALLY2.GetPositionY(), ICC_GUNSHIP_TELEPORT_ALLY2.GetPositionZ(), bot->GetOrientation());
|
||||
}
|
||||
|
||||
bot->SetTarget(boss->GetGUID());
|
||||
// Check if the bot is targeting a valid boss before teleporting
|
||||
@@ -424,7 +428,11 @@ bool IccGunshipTeleportHordeAction::Execute(Event event)
|
||||
|
||||
// Only target the sorcerer that is channeling Below Zero
|
||||
if (!(boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(69705)))
|
||||
return false;
|
||||
{
|
||||
if (bot->GetExactDist2d(ICC_GUNSHIP_TELEPORT_HORDE2) > 45.0f)
|
||||
return bot->TeleportTo(bot->GetMapId(), ICC_GUNSHIP_TELEPORT_HORDE2.GetPositionX(),
|
||||
ICC_GUNSHIP_TELEPORT_HORDE2.GetPositionY(), ICC_GUNSHIP_TELEPORT_HORDE2.GetPositionZ(), bot->GetOrientation());
|
||||
}
|
||||
|
||||
bot->SetTarget(boss->GetGUID());
|
||||
// Check if the bot is targeting a valid boss before teleporting
|
||||
@@ -991,6 +999,14 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
if (!gasCloud)
|
||||
return false;
|
||||
|
||||
static ObjectGuid lastGasCloudGuid;
|
||||
// If this is a new gas cloud, reset to position 2
|
||||
if (lastGasCloudGuid != gasCloud->GetGUID())
|
||||
{
|
||||
lastGasCloudGuid = gasCloud->GetGUID();
|
||||
lastKnownPosition = 0; // This will make it go to position 2
|
||||
}
|
||||
|
||||
// Check if this bot has Gaseous Bloat
|
||||
bool botHasAura = botAI->HasAura("Gaseous Bloat", bot);
|
||||
|
||||
@@ -1007,10 +1023,10 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
const Position* nextPos = nullptr;
|
||||
|
||||
// Determine current position
|
||||
if (dist1 < 5.0f) currentPosition = 1;
|
||||
else if (dist2 < 5.0f) currentPosition = 2;
|
||||
else if (dist3 < 5.0f) currentPosition = 3;
|
||||
else if (dist4 < 5.0f) currentPosition = 4;
|
||||
if (dist1 < 8.0f) currentPosition = 1;
|
||||
else if (dist2 < 8.0f) currentPosition = 2;
|
||||
else if (dist3 < 8.0f) currentPosition = 3;
|
||||
else if (dist4 < 8.0f) currentPosition = 4;
|
||||
|
||||
// If we're at a new position, update last known position
|
||||
if (currentPosition != 0 && currentPosition != lastKnownPosition)
|
||||
@@ -1018,8 +1034,8 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
lastKnownPosition = currentPosition;
|
||||
}
|
||||
|
||||
// If we haven't reached our last known position yet, don't start new movement
|
||||
if (lastKnownPosition != 0 && lastKnownPosition != currentPosition)
|
||||
// Only prevent movement if we're already moving and haven't reached the target yet
|
||||
if (lastKnownPosition != 0 && lastKnownPosition != currentPosition && AI_VALUE(bool, "moving"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1030,10 +1046,6 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
switch(currentPosition)
|
||||
{
|
||||
case 0: // Not at any position
|
||||
case 4: // At position 4, go to 1
|
||||
nextPos = &ICC_PUTRICIDE_GAS1_POSITION;
|
||||
lastKnownPosition = 1;
|
||||
break;
|
||||
case 1:
|
||||
nextPos = &ICC_PUTRICIDE_GAS2_POSITION;
|
||||
lastKnownPosition = 2;
|
||||
@@ -1046,16 +1058,34 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
nextPos = &ICC_PUTRICIDE_GAS4_POSITION;
|
||||
lastKnownPosition = 4;
|
||||
break;
|
||||
case 4:
|
||||
nextPos = &ICC_PUTRICIDE_GAS1_POSITION;
|
||||
lastKnownPosition = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextPos)
|
||||
{
|
||||
// Use PathGenerator to find a safe path to the target
|
||||
PathGenerator path(bot);
|
||||
path.CalculatePath(nextPos->GetPositionX(), nextPos->GetPositionY(), nextPos->GetPositionZ(), false);
|
||||
|
||||
if (path.GetPathType() == PATHFIND_NORMAL || path.GetPathType() == PATHFIND_INCOMPLETE)
|
||||
{
|
||||
return MoveTo(bot->GetMapId(), nextPos->GetPositionX(), nextPos->GetPositionY(), nextPos->GetPositionZ(),
|
||||
false, true, false, false, MovementPriority::MOVEMENT_FORCED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no valid path found, try to move directly (old behavior)
|
||||
return MoveTo(bot->GetMapId(), nextPos->GetPositionX(), nextPos->GetPositionY(), nextPos->GetPositionZ(),
|
||||
false, false, false, true, MovementPriority::MOVEMENT_FORCED);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// If bot doesn't have aura, check if anyone else does
|
||||
else
|
||||
{
|
||||
@@ -1083,13 +1113,13 @@ bool IccPutricideGasCloudAction::Execute(Event event)
|
||||
lastKnownPosition = 0;
|
||||
return Attack(gasCloud);
|
||||
}
|
||||
// If no one has aura yet, everyone stays at position 1
|
||||
// If no one has aura yet, everyone stays at position 2
|
||||
else if (!someoneHasAura)
|
||||
{
|
||||
lastKnownPosition = 0;
|
||||
return MoveTo(bot->GetMapId(), ICC_PUTRICIDE_GAS1_POSITION.GetPositionX(),
|
||||
ICC_PUTRICIDE_GAS1_POSITION.GetPositionY(),
|
||||
ICC_PUTRICIDE_GAS1_POSITION.GetPositionZ(),
|
||||
return MoveTo(bot->GetMapId(), ICC_PUTRICIDE_GAS2_POSITION.GetPositionX(),
|
||||
ICC_PUTRICIDE_GAS2_POSITION.GetPositionY(),
|
||||
ICC_PUTRICIDE_GAS2_POSITION.GetPositionZ(),
|
||||
false, false, false, true, MovementPriority::MOVEMENT_NORMAL);
|
||||
}
|
||||
}
|
||||
@@ -1190,9 +1220,8 @@ bool IccBpcNucleusAction::Execute(Event event)
|
||||
|
||||
bool IccBpcMainTankAction::Execute(Event event)
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
if (botAI->IsMainTank(bot))
|
||||
{
|
||||
// Move to MT position if we're not there
|
||||
if (bot->GetExactDist2d(ICC_BPC_MT_POSITION) > 20.0f)
|
||||
return MoveTo(bot->GetMapId(), ICC_BPC_MT_POSITION.GetPositionX(),
|
||||
@@ -1207,15 +1236,89 @@ bool IccBpcMainTankAction::Execute(Event event)
|
||||
if (currentTarget && (currentTarget == valanar || currentTarget == taldaram))
|
||||
return Attack(currentTarget);
|
||||
|
||||
// Pick a new prince
|
||||
if (valanar)
|
||||
// Pick a new prince that isn't targeting us
|
||||
if (valanar && (!valanar->GetVictim() || valanar->GetVictim() != bot))
|
||||
return Attack(valanar);
|
||||
if (taldaram)
|
||||
if (taldaram && (!taldaram->GetVictim() || taldaram->GetVictim() != bot))
|
||||
return Attack(taldaram);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!botAI->IsTank(bot))
|
||||
{
|
||||
Unit* currentTarget = AI_VALUE(Unit*, "current target");
|
||||
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
|
||||
|
||||
// First check if skull-marked target is a valid empowered prince
|
||||
Unit* skullTarget = nullptr;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
if (ObjectGuid skullGuid = group->GetTargetIcon(7)) // 7 = skull
|
||||
{
|
||||
skullTarget = botAI->GetUnit(skullGuid);
|
||||
if (skullTarget && skullTarget->IsAlive() && skullTarget->HasAura(71596) &&
|
||||
(skullTarget->GetEntry() == 37972 || // Keleseth
|
||||
skullTarget->GetEntry() == 37973 || // Taldaram
|
||||
skullTarget->GetEntry() == 37970)) // Valanar
|
||||
{
|
||||
return Attack(skullTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no valid skull target, search for empowered prince
|
||||
Unit* empoweredPrince = nullptr;
|
||||
for (auto i = targets.begin(); i != targets.end(); ++i)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(*i);
|
||||
if (!unit || !unit->IsAlive())
|
||||
continue;
|
||||
|
||||
if (unit->HasAura(71596))
|
||||
{
|
||||
if (unit->GetEntry() == 37972 || // Keleseth
|
||||
unit->GetEntry() == 37973 || // Taldaram
|
||||
unit->GetEntry() == 37970) // Valanar
|
||||
{
|
||||
empoweredPrince = unit;
|
||||
|
||||
// Mark empowered prince with skull if in group
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
group->SetTargetIcon(7, bot->GetGUID(), unit->GetGUID()); // 7 = skull
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attack empowered prince if found and current target doesn't have aura
|
||||
if (empoweredPrince)
|
||||
{
|
||||
// Only switch if current target doesn't have the aura
|
||||
if (!currentTarget || !currentTarget->HasAura(71596))
|
||||
{
|
||||
return Attack(empoweredPrince);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Attack(currentTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// Keep current prince target if no empowered prince found
|
||||
if (currentTarget && (currentTarget->GetEntry() == 37972 || // Keleseth
|
||||
currentTarget->GetEntry() == 37973 || // Taldaram
|
||||
currentTarget->GetEntry() == 37970)) // Valanar
|
||||
{
|
||||
return Attack(currentTarget);
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IccBpcEmpoweredVortexAction::Execute(Event event)
|
||||
{
|
||||
// Double check that we're not a tank
|
||||
@@ -1297,9 +1400,7 @@ bool IccBpcEmpoweredVortexAction::Execute(Event event)
|
||||
|
||||
bool IccBqlTankPositionAction::Execute(Event event)
|
||||
{
|
||||
// Only tanks should move to tank position
|
||||
if (!(botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot) || botAI->IsRanged(bot)))
|
||||
return false;
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel");
|
||||
|
||||
// If tank is not at position, move there
|
||||
if (botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot))
|
||||
@@ -1313,9 +1414,10 @@ bool IccBqlTankPositionAction::Execute(Event event)
|
||||
float radius = 8.0f;
|
||||
float moveIncrement = 3.0f;
|
||||
bool isRanged = botAI->IsRanged(bot);
|
||||
bool isMelee = botAI->IsMelee(bot);
|
||||
|
||||
GuidVector members = AI_VALUE(GuidVector, "group members");
|
||||
if (isRanged && !(bot->HasAura(70877) || bot->HasAura(71474)))
|
||||
if (isRanged && !(bot->HasAura(70877) || bot->HasAura(71474) && boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))) //frenzied bloodthrist
|
||||
{
|
||||
// Ranged: spread from other ranged
|
||||
for (auto& member : members)
|
||||
@@ -1332,7 +1434,23 @@ bool IccBqlTankPositionAction::Execute(Event event)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isMelee && boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)) // melee also spread
|
||||
{
|
||||
// Melee: spread from other melee
|
||||
for (auto& member : members)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(member);
|
||||
if (!unit || !unit->IsAlive() || unit == bot || unit->HasAura(70877) || unit->HasAura(71474))
|
||||
continue;
|
||||
|
||||
float dist = bot->GetExactDist2d(unit);
|
||||
if (dist < radius)
|
||||
{
|
||||
float moveDistance = std::min(moveIncrement, radius - dist + 1.0f);
|
||||
return MoveAway(unit, moveDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // Everyone is in position
|
||||
}
|
||||
|
||||
@@ -1619,11 +1737,11 @@ bool IccValithriaHealAction::Execute(Event event)
|
||||
switch (bot->getClass())
|
||||
{
|
||||
case CLASS_SHAMAN:
|
||||
return botAI->CastSpell(49276, valithria); // Lesser Healing Wave
|
||||
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:
|
||||
return botAI->CastSpell(48071, valithria); // Flash Heal
|
||||
return valithria->HasAura(48068) ? botAI->CastSpell(48063, valithria) : botAI->CastSpell(48068, valithria); // Cast Greater Heal if Renew is up, otherwise cast Renew
|
||||
case CLASS_PALADIN:
|
||||
return botAI->CastSpell(48782, valithria); // Holy Light
|
||||
return valithria->HasAura(53563) ? botAI->CastSpell(48782, valithria) : botAI->CastSpell(53563, valithria); // Cast Holy Light if Beacon is up, otherwise cast Beacon of Light
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ 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_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);
|
||||
const Position ICC_GUNSHIP_TELEPORT_HORDE = Position (-449.5343f, 2477.2024f, 470.17648f);
|
||||
const Position ICC_GUNSHIP_TELEPORT_HORDE2 = Position (-429.81586f, 2400.6804f, 471.56537f);
|
||||
const Position ICC_DBS_TANK_POSITION = Position(-494.26517f, 2211.549f, 541.11414f);
|
||||
const Position ICC_FESTERGUT_TANK_POSITION = Position(4269.1772f, 3144.7673f, 360.38577f);
|
||||
const Position ICC_FESTERGUT_RANGED_SPORE = Position(4261.143f, 3109.4146f, 360.38605f);
|
||||
|
||||
@@ -21,6 +21,15 @@
|
||||
#include "WarriorActions.h"
|
||||
#include "PlayerbotAI.h"
|
||||
|
||||
//LK global variables
|
||||
namespace {
|
||||
uint32 g_lastPlagueTime = 0;
|
||||
bool g_plagueAllowedToCure = false;
|
||||
std::map<ObjectGuid, uint32> g_plagueTimes;
|
||||
std::map<ObjectGuid, bool> g_allowCure;
|
||||
std::mutex g_plagueMutex; // Add mutex for thread safety
|
||||
}
|
||||
|
||||
float IccLadyDeathwhisperMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper");
|
||||
@@ -279,7 +288,7 @@ float IccAddsPutricideMultiplier::GetValue(Action* action)
|
||||
{
|
||||
if (dynamic_cast<IccPutricideVolatileOozeAction*>(action) || dynamic_cast<IccPutricideGasCloudAction*>(action))
|
||||
return 2.0f;
|
||||
else if (dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action))
|
||||
else if (dynamic_cast<DpsAssistAction*>(action) || dynamic_cast<TankAssistAction*>(action) || dynamic_cast<AvoidMalleableGooAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -542,56 +551,57 @@ float IccLichKingNecroticPlagueMultiplier::GetValue(Action* action)
|
||||
// Handle cure actions
|
||||
if (dynamic_cast<CurePartyMemberAction*>(action))
|
||||
{
|
||||
static std::map<ObjectGuid, uint32> plagueTimes;
|
||||
static std::map<ObjectGuid, bool> allowCure;
|
||||
Group* group = bot->GetGroup();
|
||||
if (!group)
|
||||
return 1.0f;
|
||||
|
||||
Unit* target = action->GetTarget();
|
||||
if (!target || !target->IsPlayer())
|
||||
return 0.0f;
|
||||
// Check if any bot in the group has plague
|
||||
bool anyBotHasPlague = false;
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
if (Player* member = ref->GetSource())
|
||||
{
|
||||
if (botAI->HasAura("Necrotic Plague", member))
|
||||
{
|
||||
anyBotHasPlague = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid targetGuid = target->GetGUID();
|
||||
uint32 currentTime = getMSTime();
|
||||
|
||||
// Check if target has plague
|
||||
bool hasPlague = target->HasAura(70338) || target->HasAura(73785) ||
|
||||
target->HasAura(73786) || target->HasAura(73787) ||
|
||||
target->HasAura(70337) || target->HasAura(73912) ||
|
||||
target->HasAura(73913) || target->HasAura(73914);
|
||||
|
||||
// If no plague, reset timers and block cure
|
||||
if (!hasPlague)
|
||||
// Reset state if no one has plague
|
||||
if (!anyBotHasPlague)
|
||||
{
|
||||
plagueTimes.erase(targetGuid);
|
||||
allowCure.erase(targetGuid);
|
||||
g_lastPlagueTime = 0;
|
||||
g_plagueAllowedToCure = false;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Start timer if this is a new plague
|
||||
if (g_lastPlagueTime == 0)
|
||||
{
|
||||
g_lastPlagueTime = currentTime;
|
||||
g_plagueAllowedToCure = false;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// If we haven't seen this plague yet, start the timer
|
||||
if (plagueTimes.find(targetGuid) == plagueTimes.end())
|
||||
{
|
||||
plagueTimes[targetGuid] = currentTime;
|
||||
allowCure[targetGuid] = false;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// If we've already allowed cure for this plague instance, keep allowing it
|
||||
if (allowCure[targetGuid])
|
||||
// Once we allow cure, keep allowing it until plague is gone
|
||||
if (g_plagueAllowedToCure)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Check if enough time has passed
|
||||
uint32 timeSincePlague = currentTime - plagueTimes[targetGuid];
|
||||
if (timeSincePlague >= 3000)
|
||||
// Check if enough time has passed (3,5 seconds)
|
||||
if (currentTime - g_lastPlagueTime >= 3500)
|
||||
{
|
||||
allowCure[targetGuid] = true;
|
||||
g_plagueAllowedToCure = true;
|
||||
return 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@@ -92,26 +92,26 @@ void RaidIccStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
//BPC
|
||||
triggers.push_back(new TriggerNode("icc bpc keleseth tank",
|
||||
NextAction::array(0, new NextAction("icc bpc keleseth tank", ACTION_EMERGENCY + 1), nullptr)));
|
||||
NextAction::array(0, new NextAction("icc bpc keleseth tank", ACTION_RAID + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("icc bpc nucleus",
|
||||
NextAction::array(0, new NextAction("icc bpc nucleus", ACTION_EMERGENCY + 3), nullptr)));
|
||||
NextAction::array(0, new NextAction("icc bpc nucleus", ACTION_RAID + 2), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("icc bpc main tank",
|
||||
NextAction::array(0, new NextAction("icc bpc main tank", ACTION_EMERGENCY + 2), nullptr)));
|
||||
NextAction::array(0, new NextAction("icc bpc main tank", ACTION_RAID + 4), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("icc bpc empowered vortex",
|
||||
NextAction::array(0, new NextAction("icc bpc empowered vortex", ACTION_INTERRUPT), nullptr)));
|
||||
NextAction::array(0, new NextAction("icc bpc empowered vortex", ACTION_RAID + 3), nullptr)));
|
||||
|
||||
//BQL
|
||||
triggers.push_back(new TriggerNode("icc bql tank position",
|
||||
NextAction::array(0, new NextAction("icc bql tank position", ACTION_RAID), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("icc bql pact of darkfallen",
|
||||
NextAction::array(0, new NextAction("icc bql pact of darkfallen", ACTION_EMERGENCY +1), nullptr)));
|
||||
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_EMERGENCY + 5), nullptr)));
|
||||
NextAction::array(0, new NextAction("icc bql vampiric bite", ACTION_RAID + 2), nullptr)));
|
||||
|
||||
//VDW
|
||||
triggers.push_back(new TriggerNode("icc valkyre spear",
|
||||
|
||||
@@ -370,6 +370,10 @@ bool IccPutricideMalleableGooTrigger::IsActive()
|
||||
//BPC
|
||||
bool IccBpcKelesethTankTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
|
||||
if (!boss)
|
||||
return false;
|
||||
|
||||
if (!botAI->IsAssistTank(bot))
|
||||
return false;
|
||||
|
||||
@@ -385,15 +389,15 @@ bool IccBpcKelesethTankTrigger::IsActive()
|
||||
}
|
||||
}
|
||||
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
|
||||
if (!boss || boss->GetEntry() != 37972) // Verify it's actually Keleseth
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IccBpcNucleusTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
|
||||
if (!boss)
|
||||
return false;
|
||||
|
||||
if (!botAI->IsAssistTank(bot))
|
||||
return false;
|
||||
|
||||
@@ -414,13 +418,11 @@ bool IccBpcNucleusTrigger::IsActive()
|
||||
|
||||
bool IccBpcMainTankTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* valanar = AI_VALUE2(Unit*, "find target", "prince valanar");
|
||||
Unit* taldaram = AI_VALUE2(Unit*, "find target", "prince taldaram");
|
||||
Unit* keleseth = AI_VALUE2(Unit*, "find target", "prince keleseth");
|
||||
|
||||
return valanar != nullptr || taldaram != nullptr;
|
||||
return valanar != nullptr || taldaram != nullptr || keleseth != nullptr;
|
||||
}
|
||||
|
||||
bool IccBpcEmpoweredVortexTrigger::IsActive()
|
||||
@@ -435,12 +437,10 @@ bool IccBpcEmpoweredVortexTrigger::IsActive()
|
||||
|
||||
// For ranged, spread whenever Valanar is empowered
|
||||
if (botAI->IsRanged(bot))
|
||||
return valanar->HasAura(70952); // Invocation of Blood
|
||||
return valanar->HasAura(71596); // Invocation of Blood
|
||||
|
||||
// For melee, only spread during vortex cast
|
||||
if (valanar->HasAura(70952) && // Invocation of Blood
|
||||
valanar->GetCurrentSpell(CURRENT_GENERIC_SPELL) &&
|
||||
valanar->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == 72039)
|
||||
if (valanar->HasAura(71596) && valanar->HasUnitState(UNIT_STATE_CASTING) && valanar->FindCurrentSpellBySpellId(72039))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -452,7 +452,7 @@ bool IccBpcEmpoweredVortexTrigger::IsActive()
|
||||
bool IccBqlTankPositionTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel");
|
||||
if (!boss || !(botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot) || botAI->IsRanged(bot)))
|
||||
if (!boss)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user