mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-13 00:58:33 +00:00
Fix Karazhan timers (#1926)
I'm not 100% sure but think that the current implementation of timers for Attumen, Netherspite, and Nightbane with the instance's map id as the key would result in the timers being shared across separate raids running the instance at the same time. I've refactored to use the instance id as the key for all shared timers so to the extent this was an issue, it shouldn't be anymore. I also made some minor tweaks to the tank positioning for BBW and Curator as I noticed there was some weirdness in the logic that I neglected to address with the refactor.
This commit is contained in:
@@ -44,7 +44,7 @@ bool AttumenTheHuntsmanMarkTargetAction::Execute(Event event)
|
||||
Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
if (attumenMounted)
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
MarkTargetWithStar(bot, attumenMounted);
|
||||
|
||||
SetRtiTarget(botAI, "star", attumenMounted);
|
||||
@@ -57,7 +57,7 @@ bool AttumenTheHuntsmanMarkTargetAction::Execute(Event event)
|
||||
}
|
||||
else if (Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight"))
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
MarkTargetWithStar(bot, midnight);
|
||||
|
||||
if (!botAI->IsAssistTankOfIndex(bot, 0))
|
||||
@@ -131,8 +131,10 @@ bool AttumenTheHuntsmanManageDpsTimerAction::Execute(Event event)
|
||||
if (!midnight)
|
||||
return false;
|
||||
|
||||
const uint32 instanceId = midnight->GetMap()->GetInstanceId();
|
||||
|
||||
if (midnight && midnight->GetHealth() == midnight->GetMaxHealth())
|
||||
attumenDpsWaitTimer.erase(KARAZHAN_MAP_ID);
|
||||
attumenDpsWaitTimer.erase(instanceId);
|
||||
|
||||
// Midnight is still present as a separate (invisible) unit after Attumen mounts
|
||||
// So this block can be reached
|
||||
@@ -143,7 +145,7 @@ bool AttumenTheHuntsmanManageDpsTimerAction::Execute(Event event)
|
||||
const time_t now = std::time(nullptr);
|
||||
|
||||
if (attumenMounted)
|
||||
attumenDpsWaitTimer.try_emplace(KARAZHAN_MAP_ID, now);
|
||||
attumenDpsWaitTimer.try_emplace(instanceId, now);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -178,7 +180,7 @@ bool MoroesMarkTargetAction::Execute(Event event)
|
||||
|
||||
if (target)
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
MarkTargetWithSkull(bot, target);
|
||||
|
||||
SetRtiTarget(botAI, "skull", target);
|
||||
@@ -297,19 +299,18 @@ bool BigBadWolfPositionBossAction::Execute(Event event)
|
||||
if (wolf->GetVictim() == bot)
|
||||
{
|
||||
const Position& position = BIG_BAD_WOLF_BOSS_POSITION;
|
||||
const float maxStep = 2.0f;
|
||||
float dist = wolf->GetExactDist2d(position);
|
||||
float distanceToPosition = wolf->GetExactDist2d(position);
|
||||
|
||||
if (dist > 0.0f && dist > maxStep)
|
||||
if (distanceToPosition > 2.0f)
|
||||
{
|
||||
float dX = position.GetPositionX() - wolf->GetPositionX();
|
||||
float dY = position.GetPositionY() - wolf->GetPositionY();
|
||||
float moveDist = std::min(maxStep, dist);
|
||||
float moveX = wolf->GetPositionX() + (dX / dist) * moveDist;
|
||||
float moveY = wolf->GetPositionY() + (dY / dist) * moveDist;
|
||||
float moveDist = std::min(5.0f, distanceToPosition);
|
||||
float moveX = wolf->GetPositionX() + (dX / distanceToPosition) * moveDist;
|
||||
float moveY = wolf->GetPositionY() + (dY / distanceToPosition) * moveDist;
|
||||
|
||||
return MoveTo(KARAZHAN_MAP_ID, moveX, moveY, position.GetPositionZ(), false, false, false, false,
|
||||
MovementPriority::MOVEMENT_COMBAT, true, false);
|
||||
MovementPriority::MOVEMENT_COMBAT, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +405,7 @@ bool TheCuratorMarkAstralFlareAction::Execute(Event event)
|
||||
if (!flare)
|
||||
return false;
|
||||
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
MarkTargetWithSkull(bot, flare);
|
||||
|
||||
SetRtiTarget(botAI, "skull", flare);
|
||||
@@ -429,17 +430,17 @@ bool TheCuratorPositionBossAction::Execute(Event event)
|
||||
if (curator->GetVictim() == bot)
|
||||
{
|
||||
const Position& position = THE_CURATOR_BOSS_POSITION;
|
||||
const float maxDistance = 3.0f;
|
||||
float distanceToBossPosition = curator->GetExactDist2d(position);
|
||||
float distanceToPosition = curator->GetExactDist2d(position);
|
||||
|
||||
if (distanceToBossPosition > maxDistance)
|
||||
if (distanceToPosition > 2.0f)
|
||||
{
|
||||
float dX = position.GetPositionX() - curator->GetPositionX();
|
||||
float dY = position.GetPositionY() - curator->GetPositionY();
|
||||
float mX = position.GetPositionX() + (dX / distanceToBossPosition) * maxDistance;
|
||||
float mY = position.GetPositionY() + (dY / distanceToBossPosition) * maxDistance;
|
||||
float moveDist = std::min(10.0f, distanceToPosition);
|
||||
float moveX = position.GetPositionX() + (dX / distanceToPosition) * moveDist;
|
||||
float moveY = position.GetPositionY() + (dY / distanceToPosition) * moveDist;
|
||||
|
||||
return MoveTo(KARAZHAN_MAP_ID, mX, mY, position.GetPositionZ(), false, false, false, false,
|
||||
return MoveTo(KARAZHAN_MAP_ID, moveX, moveY, position.GetPositionZ(), false, false, false, false,
|
||||
MovementPriority::MOVEMENT_COMBAT, true, false);
|
||||
}
|
||||
}
|
||||
@@ -997,6 +998,7 @@ bool NetherspiteManageTimersAndTrackersAction::Execute(Event event)
|
||||
if (!netherspite)
|
||||
return false;
|
||||
|
||||
const uint32 instanceId = netherspite->GetMap()->GetInstanceId();
|
||||
const ObjectGuid botGuid = bot->GetGUID();
|
||||
const time_t now = std::time(nullptr);
|
||||
|
||||
@@ -1005,8 +1007,8 @@ bool NetherspiteManageTimersAndTrackersAction::Execute(Event event)
|
||||
if (netherspite->GetHealth() == netherspite->GetMaxHealth() &&
|
||||
!netherspite->HasAura(SPELL_GREEN_BEAM_HEAL))
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.insert_or_assign(KARAZHAN_MAP_ID, now);
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.insert_or_assign(instanceId, now);
|
||||
|
||||
if (botAI->IsTank(bot) && !bot->HasAura(SPELL_RED_BEAM_DEBUFF))
|
||||
{
|
||||
@@ -1016,8 +1018,8 @@ bool NetherspiteManageTimersAndTrackersAction::Execute(Event event)
|
||||
}
|
||||
else if (netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.erase(KARAZHAN_MAP_ID);
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.erase(instanceId);
|
||||
|
||||
if (botAI->IsTank(bot))
|
||||
{
|
||||
@@ -1027,8 +1029,8 @@ bool NetherspiteManageTimersAndTrackersAction::Execute(Event event)
|
||||
}
|
||||
else if (!netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
{
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.try_emplace(KARAZHAN_MAP_ID, now);
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
netherspiteDpsWaitTimer.try_emplace(instanceId, now);
|
||||
|
||||
if (botAI->IsTank(bot) && bot->HasAura(SPELL_RED_BEAM_DEBUFF))
|
||||
{
|
||||
@@ -1443,6 +1445,7 @@ bool NightbaneManageTimersAndTrackersAction::Execute(Event event)
|
||||
if (!nightbane)
|
||||
return false;
|
||||
|
||||
const uint32 instanceId = nightbane->GetMap()->GetInstanceId();
|
||||
const ObjectGuid botGuid = bot->GetGUID();
|
||||
const time_t now = std::time(nullptr);
|
||||
|
||||
@@ -1455,18 +1458,18 @@ bool NightbaneManageTimersAndTrackersAction::Execute(Event event)
|
||||
if (botAI->IsRanged(bot))
|
||||
nightbaneRangedStep.erase(botGuid);
|
||||
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
nightbaneDpsWaitTimer.erase(KARAZHAN_MAP_ID);
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
nightbaneDpsWaitTimer.erase(instanceId);
|
||||
}
|
||||
// Erase flight phase timer and Rain of Bones tracker on ground phase and start DPS wait timer
|
||||
else if (nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z)
|
||||
{
|
||||
nightbaneRainOfBonesHit.erase(botGuid);
|
||||
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
{
|
||||
nightbaneFlightPhaseStartTimer.erase(KARAZHAN_MAP_ID);
|
||||
nightbaneDpsWaitTimer.try_emplace(KARAZHAN_MAP_ID, now);
|
||||
nightbaneFlightPhaseStartTimer.erase(instanceId);
|
||||
nightbaneDpsWaitTimer.try_emplace(instanceId, now);
|
||||
}
|
||||
}
|
||||
// Erase DPS wait timer and tank and ranged position tracking and start flight phase timer
|
||||
@@ -1479,10 +1482,10 @@ bool NightbaneManageTimersAndTrackersAction::Execute(Event event)
|
||||
if (botAI->IsRanged(bot))
|
||||
nightbaneRangedStep.erase(botGuid);
|
||||
|
||||
if (IsMapIDTimerManager(botAI, bot))
|
||||
if (IsInstanceTimerManager(botAI, bot))
|
||||
{
|
||||
nightbaneDpsWaitTimer.erase(KARAZHAN_MAP_ID);
|
||||
nightbaneFlightPhaseStartTimer.try_emplace(KARAZHAN_MAP_ID, now);
|
||||
nightbaneDpsWaitTimer.erase(instanceId);
|
||||
nightbaneFlightPhaseStartTimer.try_emplace(instanceId, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ namespace KarazhanHelpers
|
||||
}
|
||||
}
|
||||
|
||||
// Only one bot is needed to set/reset mapwide timers
|
||||
bool IsMapIDTimerManager(PlayerbotAI* botAI, Player* bot)
|
||||
// Only one bot is needed to set/reset instance-wide timers
|
||||
bool IsInstanceTimerManager(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace KarazhanHelpers
|
||||
void MarkTargetWithCircle(Player* bot, Unit* target);
|
||||
void MarkTargetWithMoon(Player* bot, Unit* target);
|
||||
void SetRtiTarget(PlayerbotAI* botAI, const std::string& rtiName, Unit* target);
|
||||
bool IsMapIDTimerManager(PlayerbotAI* botAI, Player* bot);
|
||||
bool IsInstanceTimerManager(PlayerbotAI* botAI, Player* bot);
|
||||
Unit* GetFirstAliveUnit(const std::vector<Unit*>& units);
|
||||
Unit* GetFirstAliveUnitByEntry(PlayerbotAI* botAI, uint32 entry);
|
||||
Unit* GetNearestPlayerInRadius(Player* bot, float radius);
|
||||
|
||||
@@ -61,10 +61,11 @@ float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action* action)
|
||||
if (!attumenMounted)
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = attumenMounted->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 8;
|
||||
|
||||
auto it = attumenDpsWaitTimer.find(KARAZHAN_MAP_ID);
|
||||
auto it = attumenDpsWaitTimer.find(instanceId);
|
||||
if (it == attumenDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
@@ -201,10 +202,11 @@ float NetherspiteWaitForDpsMultiplier::GetValue(Action* action)
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = netherspite->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 5;
|
||||
|
||||
auto it = netherspiteDpsWaitTimer.find(KARAZHAN_MAP_ID);
|
||||
auto it = netherspiteDpsWaitTimer.find(instanceId);
|
||||
if (it == netherspiteDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsTank(bot))
|
||||
@@ -299,10 +301,11 @@ float NightbaneWaitForDpsMultiplier::GetValue(Action* action)
|
||||
if (!nightbane || nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z)
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = nightbane->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 8;
|
||||
|
||||
auto it = nightbaneDpsWaitTimer.find(KARAZHAN_MAP_ID);
|
||||
auto it = nightbaneDpsWaitTimer.find(instanceId);
|
||||
if (it == nightbaneDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
|
||||
@@ -40,7 +40,7 @@ bool AttumenTheHuntsmanAttumenIsMountedTrigger::IsActive()
|
||||
|
||||
bool AttumenTheHuntsmanBossWipesAggroWhenMountingTrigger::IsActive()
|
||||
{
|
||||
if (!IsMapIDTimerManager(botAI, bot))
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight");
|
||||
@@ -110,7 +110,7 @@ bool BigBadWolfBossIsChasingLittleRedRidingHoodTrigger::IsActive()
|
||||
|
||||
bool RomuloAndJulianneBothBossesRevivedTrigger::IsActive()
|
||||
{
|
||||
if (!IsMapIDTimerManager(botAI, bot))
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* romulo = AI_VALUE2(Unit*, "find target", "romulo");
|
||||
@@ -126,7 +126,7 @@ bool RomuloAndJulianneBothBossesRevivedTrigger::IsActive()
|
||||
|
||||
bool WizardOfOzNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (!IsMapIDTimerManager(botAI, bot))
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* dorothee = AI_VALUE2(Unit*, "find target", "dorothee");
|
||||
@@ -178,7 +178,7 @@ bool TheCuratorBossAstralFlaresCastArcingSearTrigger::IsActive()
|
||||
|
||||
bool TerestianIllhoofNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (!IsMapIDTimerManager(botAI, bot))
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* illhoof = AI_VALUE2(Unit*, "find target", "terestian illhoof");
|
||||
@@ -202,7 +202,7 @@ bool ShadeOfAranFlameWreathIsActiveTrigger::IsActive()
|
||||
// Exclusion of Banish is so the player may Banish elementals if they wish
|
||||
bool ShadeOfAranConjuredElementalsSummonedTrigger::IsActive()
|
||||
{
|
||||
if (!IsMapIDTimerManager(botAI, bot))
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* elemental = AI_VALUE2(Unit*, "find target", "conjured elemental");
|
||||
@@ -279,7 +279,7 @@ bool NetherspiteBossIsBanishedTrigger::IsActive()
|
||||
|
||||
bool NetherspiteNeedToManageTimersAndTrackersTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsTank(bot) && !IsMapIDTimerManager(botAI, bot))
|
||||
if (!botAI->IsTank(bot) && !IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
@@ -370,11 +370,12 @@ bool NightbaneBossIsFlyingTrigger::IsActive()
|
||||
if (!nightbane || nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z)
|
||||
return false;
|
||||
|
||||
const uint32 instanceId = nightbane->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 flightPhaseDurationSeconds = 35;
|
||||
|
||||
return nightbaneFlightPhaseStartTimer.find(KARAZHAN_MAP_ID) != nightbaneFlightPhaseStartTimer.end() &&
|
||||
(now - nightbaneFlightPhaseStartTimer[KARAZHAN_MAP_ID] < flightPhaseDurationSeconds);
|
||||
return nightbaneFlightPhaseStartTimer.find(instanceId) != nightbaneFlightPhaseStartTimer.end() &&
|
||||
(now - nightbaneFlightPhaseStartTimer[instanceId] < flightPhaseDurationSeconds);
|
||||
}
|
||||
|
||||
bool NightbaneNeedToManageTimersAndTrackersTrigger::IsActive()
|
||||
|
||||
Reference in New Issue
Block a user