void UpdateAI(const uint32 uiDiff) override { if (m_creature->GetMapId() != MAP_ID_BWL) return; DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Only do this if we haven't spawned nef yet if (m_uiSpawnedAdds < MAX_DRAKE_SUMMONS) { // Shadowbolt Timer if (m_uiShadowBoltTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SHADOWBOLT) == CAST_OK) m_uiShadowBoltTimer = urand(2000, 4000); } } else m_uiShadowBoltTimer -= uiDiff; // Fear Timer if (m_uiFearTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { if (DoCastSpellIfCan(pTarget, SPELL_FEAR) == CAST_OK) m_uiFearTimer = urand(10000, 20000); } } else m_uiFearTimer -= uiDiff; // Shadowbolt Volley if (m_uiShadowboltVolleyTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SHADOWBOLT_VOLLEY) == CAST_OK) m_uiShadowboltVolleyTimer = urand(19000, 28000); } else m_uiShadowboltVolleyTimer -= uiDiff; // Silence if (m_uiSilenceTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SILENCE) == CAST_OK) m_uiSilenceTimer = urand(14000, 23000); } } else m_uiSilenceTimer -= uiDiff; // Shadow Command if (m_uiShadowCommandTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { if (DoCastSpellIfCan(pTarget, SPELL_SHADOW_COMMAND) == CAST_OK) m_uiShadowCommandTimer = urand(24000, 30000); } } else m_uiShadowCommandTimer -= uiDiff; // ShadowBlink if (m_uiShadowBlinkTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SHADOWBLINK) == CAST_OK) m_uiShadowBlinkTimer = urand(30000, 40000); } else m_uiShadowBlinkTimer -= uiDiff; // Add spawning mechanism if (m_uiAddSpawnTimer < uiDiff) { // Spawn 2 random types of creatures at the 2 locations uint32 uiCreatureId = 0; // 1 in 3 chance it will be a chromatic uiCreatureId = urand(0, 2) ? m_uiDrakeTypeOne : uint32(NPC_CHROMATIC_DRAKANOID); m_creature->SummonCreature(uiCreatureId, aNefarianLocs[0].m_fX, aNefarianLocs[0].m_fY, aNefarianLocs[0].m_fZ, 5.000f, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 30000); // 1 in 3 chance it will be a chromatic uiCreatureId = urand(0, 2) ? m_uiDrakeTypeTwo : uint32(NPC_CHROMATIC_DRAKANOID); m_creature->SummonCreature(uiCreatureId, aNefarianLocs[1].m_fX, aNefarianLocs[1].m_fY, aNefarianLocs[1].m_fZ, 5.000, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 30000); // Begin phase 2 by spawning Nefarian if (m_uiSpawnedAdds >= MAX_DRAKE_SUMMONS) { // Inturrupt any spell casting m_creature->InterruptNonMeleeSpells(false); // Make super invis if (m_creature->GetVisibility() != VISIBILITY_OFF) m_creature->SetVisibility(VISIBILITY_OFF); // Spawn Nefarian // Summon as active, to be able to work proper! m_creature->SummonCreature(NPC_NEFARIAN, aNefarianLocs[2].m_fX, aNefarianLocs[2].m_fY, aNefarianLocs[2].m_fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0, true); } m_uiAddSpawnTimer = 4000; } else m_uiAddSpawnTimer -= uiDiff; } }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; switch (m_uiPhase) { // arena phase abilities case PHASE_ARENA: if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK_1) == CAST_OK) { DoCastSpellIfCan(m_creature, SPELL_SUMMON_LIGHTNING_ORB, CAST_TRIGGERED); DoScriptText(SAY_ARENA_WIPE, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } if (m_uiArenaDwarfTimer < uiDiff) { DoSpawnArenaDwarf(); m_uiArenaDwarfTimer = 10000; } else m_uiArenaDwarfTimer -= uiDiff; if (m_uiChargeOrbTimer < uiDiff) { // this spell has AoE target, but we need to be very specific with the selected targets if (Creature* pTarget = m_creature->GetMap()->GetCreature(SelectRandomOrbGuid())) { if (DoCastSpellIfCan(pTarget, SPELL_CHARGE_ORB) == CAST_OK) m_uiChargeOrbTimer = 20000; } } else m_uiChargeOrbTimer -= uiDiff; if (m_uiStormHammerTimer < uiDiff) { if (Unit* pTarget = GetRandomArenaPlayer()) { if (DoCastSpellIfCan(pTarget, SPELL_STORMHAMMER) == CAST_OK) m_uiStormHammerTimer = 15000; } } else m_uiStormHammerTimer -= uiDiff; break; // solo phase abilities case PHASE_SOLO: if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK_2) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } if (m_uiAttackTimer) { if (m_uiAttackTimer <= uiDiff) { // Add some small delay to combat movement because Jump triggers before it's actually finished DoResetThreat(); SetCombatMovement(true); DoStartMovement(m_creature->getVictim()); m_uiAttackTimer = 0; } else m_uiAttackTimer -= uiDiff; } if (m_uiChargeOrbTimer < uiDiff) { // this spell requires very specific targets if (Creature* pTarget = m_creature->GetMap()->GetCreature(SelectRandomOrbGuid())) { pTarget->CastSpell(pTarget, SPELL_LIGHTNING_ORG_CHARGED, true); // charge the lower orb as well if (Unit* pOrb = GetClosestCreatureWithEntry(pTarget, NPC_THUNDER_ORB, 25.0f, true, false, true)) pTarget->CastSpell(pOrb, SPELL_LIGHTNING_PILLAR, true); m_uiChargeOrbTimer = 20000; } } else m_uiChargeOrbTimer -= uiDiff; if (m_uiChainLightningTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H) == CAST_OK) m_uiChainLightningTimer = urand(10000, 15000); } } else m_uiChainLightningTimer -= uiDiff; if (m_uiUnbalancingStrikeTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_UNBALANCING_STRIKE) == CAST_OK) m_uiUnbalancingStrikeTimer = 25000; } else m_uiUnbalancingStrikeTimer -= uiDiff; DoMeleeAttackIfReady(); break; // transition phase; nothing here, wait for transition to finish case PHASE_TRANSITION: break; } }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) m_uiBerserkTimer = 0; } else m_uiBerserkTimer -= uiDiff; } switch (m_uiPhase) { case PHASE_FLOOR: /* ToDo: Enable this when the spells are properly supported in core if (m_uiVortexTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_VORTEX) == CAST_OK) { DoScriptText(SAY_VORTEX, m_creature); m_uiVortexTimer = 60000; } } else m_uiVortexTimer -= uiDiff; */ if (m_uiArcaneBreathTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_ARCANE_BREATH : SPELL_ARCANE_BREATH_H) == CAST_OK) m_uiArcaneBreathTimer = urand(13000, 16000); } else m_uiArcaneBreathTimer -= uiDiff; if (m_uiPowerSparkTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_SPARK) == CAST_OK) { DoScriptText(SAY_EMOTE_SPARK, m_creature); m_uiPowerSparkTimer = 30000; } } else m_uiPowerSparkTimer -= uiDiff; if (m_creature->GetHealthPercent() < 50.0f) { SetCombatMovement(false); m_creature->SetLevitate(true); m_creature->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); // Move idle first, so we can avoid evading, because of the waypoint movement m_creature->GetMotionMaster()->MoveIdle(); m_creature->GetMotionMaster()->MovePoint(0, aCenterMovePos[0], aCenterMovePos[1], aCenterMovePos[2] + 30.0f); StartNextDialogueText(SAY_END_PHASE_1); m_uiPhase = PHASE_TRANSITION_1; } DoMeleeAttackIfReady(); break; case PHASE_DISCS: if (m_uiOverloadTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_ARCANE_BOMB) == CAST_OK) { if (!urand(0, 3)) DoScriptText(SAY_SHELL, m_creature); m_uiOverloadTimer = urand(16000, 19000); } } else m_uiOverloadTimer -= uiDiff; // Note: the boss should move in certain points before he does the breath ability if (m_uiArcanePulseTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SURGE_OF_POWER_PULSE) == CAST_OK) { DoScriptText(SAY_DEEP_BREATH, m_creature); DoScriptText(SAY_EMOTE_BREATH, m_creature); m_uiArcanePulseTimer = 60000; } } else m_uiArcanePulseTimer -= uiDiff; if (m_uiArcaneStormTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_ARCANE_STORM : SPELL_ARCANE_STORM_H) == CAST_OK) m_uiArcaneStormTimer = urand(15000, 17000); } else m_uiArcaneStormTimer -= uiDiff; break; case PHASE_DRAGONS: if (m_uiStaticFieldTimer < uiDiff) { // Cast Static Field spell on a number of targets, based on difficulty for (uint8 i = 0; i < m_uiMaxStaticFieldTargets; ++i) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_STATIC_FIELD_SUMMON, CAST_TRIGGERED) == CAST_OK) { switch (urand(0, 2)) { case 0: DoScriptText(SAY_SPELL_1, m_creature); break; case 1: DoScriptText(SAY_SPELL_2, m_creature); break; case 2: DoScriptText(SAY_SPELL_3, m_creature); break; } m_uiStaticFieldTimer = urand(10000, 17000); } } } } else m_uiStaticFieldTimer -= uiDiff; if (m_uiSurgeOfPowerTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_SURGE_OF_POWER) == CAST_OK) { if (!urand(0, 3)) DoScriptText(SAY_SURGE, m_creature); m_uiSurgeOfPowerTimer = urand(5000, 15000); } } } else m_uiSurgeOfPowerTimer -= uiDiff; break; case PHASE_TRANSITION_1: case PHASE_TRANSITION_2: // Nothing here - wait for transition to finish break; } }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Don't use spells during the epilogue if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) return; if (m_bIsFirstPhase) { // *Heroic mode only: if (!m_bIsRegularMode) { if (m_uiShockBarrierTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_SHOCK_BARRIER) == CAST_OK) { m_uiPyroblastTimer = 1000; m_uiShockBarrierTimer = 60000; } } else m_uiShockBarrierTimer -= uiDiff; if (m_uiPyroblastTimer) { if (m_uiPyroblastTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_PYROBLAST) == CAST_OK) m_uiPyroblastTimer = 0; } else m_uiPyroblastTimer -= uiDiff; } } if (m_uiFireballTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H) == CAST_OK) m_uiFireballTimer = urand(2000, 4000); } } else m_uiFireballTimer -= uiDiff; if (m_uiPhoenixTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_PHOENIX) == CAST_OK) { DoScriptText(SAY_PHOENIX, m_creature); m_uiPhoenixTimer = 45000; } } else m_uiPhoenixTimer -= uiDiff; if (m_uiFlameStrikeTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_FLAME_STRIKE) == CAST_OK) { DoScriptText(SAY_FLAMESTRIKE, m_creature); m_uiFlameStrikeTimer = urand(15000, 25000); } } } else m_uiFlameStrikeTimer -= uiDiff; // Below 50% if (m_creature->GetHealthPercent() < 50.0f) { if (DoCastSpellIfCan(m_creature, SPELL_TELEPORT_CENTER, CAST_INTERRUPT_PREVIOUS) == CAST_OK) { SetCombatMovement(false); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MoveIdle(); m_bIsFirstPhase = false; } } DoMeleeAttackIfReady(); } else { if (m_uiGravityLapseTimer < uiDiff) { switch (m_uiGravityLapseStage) { case 0: // Cast Gravity Lapse on Players if (DoCastSpellIfCan(m_creature, SPELL_GRAVITY_LAPSE) == CAST_OK) { if (m_bFirstGravityLapse) { DoScriptText(SAY_GRAVITY_LAPSE, m_creature); m_bFirstGravityLapse = false; } else DoScriptText(SAY_RECAST_GRAVITY, m_creature); m_uiGravityLapseTimer = 2000; m_uiGravityIndex = 0; ++m_uiGravityLapseStage; } break; case 1: // Summon spheres and apply the Gravity Lapse visual - upon visual expire, the gravity lapse is removed if (DoCastSpellIfCan(m_creature, SPELL_GRAVITY_LAPSE_VISUAL) == CAST_OK) { for (uint8 i = 0; i < MAX_ARCANE_SPHERES; ++i) DoCastSpellIfCan(m_creature, SPELL_ARCANE_SPHERE_SUMMON, CAST_TRIGGERED); m_uiGravityLapseTimer = 30000; ++m_uiGravityLapseStage; } break; case 2: // Cast Power Feedback and stay stunned for 10 secs - also break the statues if they are not broken if (DoCastSpellIfCan(m_creature, SPELL_POWER_FEEDBACK) == CAST_OK) { DoScriptText(SAY_TIRED, m_creature); RemoveGravityLapse(); m_uiGravityLapseTimer = 10000; m_uiGravityLapseStage = 0; } break; } } else m_uiGravityLapseTimer -= uiDiff; } }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { // it's unclear wether it casts Berserk or Ascend to Heavens if (DoCastSpellIfCan(m_creature, SPELL_ASCEND_HEAVENS, CAST_INTERRUPT_PREVIOUS) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } if (m_uiQuantumStrikeTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_QUANTUM_STRIKE : SPELL_QUANTUM_STRIKE_H) == CAST_OK) m_uiQuantumStrikeTimer = 4000; } else m_uiQuantumStrikeTimer -= uiDiff; if (m_uiBigBangTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_BIG_BANG : SPELL_BIG_BANG_H) == CAST_OK) m_uiBigBangTimer = 90000; } else m_uiBigBangTimer -= uiDiff; if (m_uiCosmicSmashTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_COSMIC_SMASH_SUMMON : SPELL_COSMIC_SMASH_SUMMON_H) == CAST_OK) m_uiCosmicSmashTimer = urand(40000, 50000); } else m_uiCosmicSmashTimer -= uiDiff; if (m_uiPhasePunchTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_PHASE_PUNCH) == CAST_OK) m_uiPhasePunchTimer = 15000; } else m_uiPhasePunchTimer -= uiDiff; // summons are happening only above 20% hp if (!m_bIsLowHealth) { if (m_uiCollapsingStarTimer < uiDiff) { // spawn as many stars as it's needed to a max of 4 uint8 uiMaxStars = MAX_BLACK_HOLES - m_uiActiveStars; if (uiMaxStars) { for (uint8 i = 0; i < uiMaxStars; ++i) DoSpawnCollapsingStar(); DoScriptText(SAY_SUMMON_STAR, m_creature); m_uiCollapsingStarTimer = 60000; } else m_uiCollapsingStarTimer = 10000; } else m_uiCollapsingStarTimer -= uiDiff; if (m_uiConstellationTimer < uiDiff) { // activate as many constelations as it's needed to a max of 3 uint8 uiMaxConstellations = MAX_ACTIVE_CONSTELATIONS - m_uiActiveConstelations; if (uiMaxConstellations) { m_uiConstellationTimer = 50000; for (uint8 i = 0; i < uiMaxConstellations; ++i) ActivateRandomConstellation(); } else m_uiConstellationTimer = 10000; } else m_uiConstellationTimer -= uiDiff; } // switch to second phase if (!m_bIsLowHealth && m_creature->GetHealthPercent() < 20.0f) { DoScriptText(SAY_PHASE_2, m_creature); m_bIsLowHealth = true; // despawn all remaining blackholes and collapsing stars for (GuidList::const_iterator itr = m_lSummonedGuids.begin(); itr != m_lSummonedGuids.end(); ++itr) { if (Creature* pBlackHole = m_creature->GetMap()->GetCreature(*itr)) pBlackHole->ForcedDespawn(); } // spawn new worm holes for (uint8 i = 0; i < MAX_WORM_HOLES; ++i) m_creature->SummonCreature(NPC_WORM_HOLE, afWormHoles[i][0], afWormHoles[i][1], afWormHoles[i][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0); } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { switch (m_uiPhase) { case PHASE_CHANNEL: if (m_uiSummonDefenderTimer < uiDiff) { DoSummonAshtongue(SPELL_SUMMON_DEFENDER); m_uiSummonDefenderTimer = 15000; } else m_uiSummonDefenderTimer -= uiDiff; if (m_lSorcerersGUIDList.size() <= m_uiChannelersDead) { if (m_uiSummonSorcererTimer < uiDiff) { DoSummonAshtongue(SPELL_SUMMON_SORCERER); m_uiSummonSorcererTimer = urand(20000, 30000); } else m_uiSummonSorcererTimer -= uiDiff; } if (m_uiSummonPackTimer < uiDiff) { DoSummonAshtongue(); m_uiSummonPackTimer = 35000; } else m_uiSummonPackTimer -= uiDiff; break; case PHASE_COMBAT: if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bHasYelledOnce && m_creature->GetHealthPercent() < 15.0f) { DoScriptText(SAY_LOW_HEALTH, m_creature); m_bHasYelledOnce = true; } if (m_uiDestructivePoisonTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_DESTRUCTIVE_POISON) == CAST_OK) m_uiDestructivePoisonTimer = 15000; } else m_uiDestructivePoisonTimer -= uiDiff; if (m_uiLightningBoltTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CHAIN_LIGHTNING) == CAST_OK) m_uiLightningBoltTimer = 10000; } else m_uiLightningBoltTimer -= uiDiff; DoMeleeAttackIfReady(); break; case PHASE_EPILOGUE: DialogueUpdate(uiDiff); break; } }
void UpdateAI(const uint32 uiDiff) { DialogueUpdate(uiDiff); }
void UpdateEscortAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (m_uiOutroTimer) { if (m_uiOutroTimer <= uiDiff) { switch (m_uiOutroPhase) { case 0: DoScriptText(SAY_REMULOS_OUTRO_1, m_creature); m_uiOutroTimer = 3000; break; case 1: // Despawn Remulos after the outro is finished - he will respawn automatically at his home position after a few min DoScriptText(SAY_REMULOS_OUTRO_2, m_creature); m_creature->SetRespawnDelay(1 * MINUTE); m_creature->ForcedDespawn(3000); m_uiOutroTimer = 0; break; } ++m_uiOutroPhase; } else m_uiOutroTimer -= uiDiff; } // during the battle if (m_uiShadesummonTimer) { if (m_uiShadesummonTimer <= uiDiff) { // do this yell only first time if (m_bIsFirstWave) { // summon 3 shades inside the house for (uint8 i = 0; i < MAX_SHADOWS; ++i) m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, aShadowsLocations[i].m_fX, aShadowsLocations[i].m_fY, aShadowsLocations[i].m_fZ, 0, TEMPSPAWN_DEAD_DESPAWN, 0); if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid)) DoScriptText(SAY_ERANIKUS_ATTACK_1, pEranikus); ++m_uiSummonCount; SetEscortPaused(false); m_bIsFirstWave = false; } // Summon 3 shades per turn until the maximum summon turns are reached float fX, fY, fZ; // Randomize the summon point uint8 uiSummonPoint = roll_chance_i(70) ? uint32(MAX_SHADOWS) : urand(MAX_SHADOWS + 1, MAX_SHADOWS + 2); if (m_uiSummonCount < MAX_SUMMON_TURNS) { for (uint8 i = 0; i < MAX_SHADOWS; ++i) { m_creature->GetRandomPoint(aShadowsLocations[uiSummonPoint].m_fX, aShadowsLocations[uiSummonPoint].m_fY, aShadowsLocations[uiSummonPoint].m_fZ, 10.0f, fX, fY, fZ); m_creature->SummonCreature(NPC_NIGHTMARE_PHANTASM, fX, fY, fZ, 0.0f, TEMPSPAWN_DEAD_DESPAWN, 0); } ++m_uiSummonCount; } // If all the shades were summoned then set Eranikus in combat // We don't count the dead shades, because the boss is usually set in combat before all shades are dead if (m_uiSummonCount == MAX_SUMMON_TURNS) { m_uiShadesummonTimer = 0; if (Creature* pEranikus = m_creature->GetMap()->GetCreature(m_eranikusGuid)) { pEranikus->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0); pEranikus->SetLevitate(false); pEranikus->GetMotionMaster()->MovePoint(POINT_ID_ERANIKUS_COMBAT, aEranikusLocations[2].m_fX, aEranikusLocations[2].m_fY, aEranikusLocations[2].m_fZ); } } else m_uiShadesummonTimer = urand(20000, 30000); } else m_uiShadesummonTimer -= uiDiff; } // Combat spells if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiHealTimer < uiDiff) { if (Unit* pTarget = DoSelectLowestHpFriendly(DEFAULT_VISIBILITY_DISTANCE)) { switch (urand(0, 2)) { case 0: DoCastSpellIfCan(pTarget, SPELL_HEALING_TOUCH); break; case 1: DoCastSpellIfCan(pTarget, SPELL_REJUVENATION); break; case 2: DoCastSpellIfCan(pTarget, SPELL_REGROWTH); break; } } m_uiHealTimer = 10000; } else m_uiHealTimer -= uiDiff; if (m_uiStarfireTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_STARFIRE) == CAST_OK) m_uiStarfireTimer = 20000; } } else m_uiStarfireTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bHasLowHp && m_creature->GetHealthPercent() < 20.0f) { DoScriptText(SAY_LOWHP, m_creature); m_bHasLowHp = true; } if (m_uiPyroblastTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_PYROBLAST) == CAST_OK) { m_uiPyroblastTimer = 40000; DoScriptText(SAY_PYRO, m_creature); } } else m_uiPyroblastTimer -= uiDiff; if (m_uiFireballTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIREBALL) == CAST_OK) m_uiFireballTimer = 4000; } else m_uiFireballTimer -= uiDiff; if (m_uiFrostBoltTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROSTBOLT) == CAST_OK) m_uiFrostBoltTimer = urand(4000, 6000); } else m_uiFrostBoltTimer -= uiDiff; if (m_uiConeColtTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_CONE_OF_COLD) == CAST_OK) m_uiConeColtTimer = urand(7000, 12000); } else m_uiConeColtTimer -= uiDiff; if (m_uiFireBlastTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIRE_BLAST) == CAST_OK) m_uiFireBlastTimer = urand(5000, 16000); } else m_uiFireBlastTimer -= uiDiff; if (m_uiArcaneMissileTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ARCANE_MISSILES) == CAST_OK) m_uiArcaneMissileTimer = urand(5000, 8000); } else m_uiArcaneMissileTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiFelfireShockTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FELFIRE_SHOCK : SPELL_FELFIRE_SHOCK_H) == CAST_OK) m_uiFelfireShockTimer = urand(35000, 45000); } else m_uiFelfireShockTimer -= uiDiff; if (m_uiKnockAwayTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_KNOCK_AWAY) == CAST_OK) { m_uiKnockAwayTimer = urand(30000, 35000); m_uiFelfireLineupTimer = 2000; } } else m_uiKnockAwayTimer -= uiDiff; // Prepare the boss for charging if (m_uiFelfireLineupTimer) { if (m_uiFelfireLineupTimer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_CHARGE_TARGETING) == CAST_OK) { // ToDo: the Wrath-Scryer's Felfire npcs should be summoned at this point and aligned to the chosen target! m_creature->CastSpell(m_creature, SPELL_FELFIRE_LINE_UP, TRIGGERED_OLD_TRIGGERED); DoScriptText(urand(0, 1) ? SAY_CHARGE_1 : SAY_CHARGE_2, m_creature, pTarget); m_uiChargeTimer = 2500; m_uiFelfireLineupTimer = 0; } } } else m_uiFelfireLineupTimer -= uiDiff; } // Charge the target if (m_uiChargeTimer) { if (m_uiChargeTimer <= uiDiff) { m_creature->RemoveAurasDueToSpell(SPELL_KNOCK_AWAY); SetCombatMovement(false); // prevents interrupting charge // Note: this spell will also light up the Wrath-Scryer's Felfire npcs if (DoCastSpellIfCan(m_creature, SPELL_CHARGE) == CAST_OK) m_uiChargeTimer = 0; } else m_uiChargeTimer -= uiDiff; } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) { return; } DialogueUpdate(uiDiff); switch (m_uiPhase) { case PHASE_TRANSITION: // Transition phase is handled in the dialogue helper; however we don't want the spell timers to be decreased so we use a specific phase break; case PHASE_SACRIFICE: // Final phase - use the same spells // no break; case PHASE_ARMAGEDDON: // In the last phase he uses Armageddon continuously if (m_uiArmageddonTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_ARMAGEDDON) == CAST_OK) { m_uiArmageddonTimer = m_uiPhase == PHASE_SACRIFICE ? 20000 : 30000; } } else { m_uiArmageddonTimer -= uiDiff; } // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_ARMAGEDDON && m_creature->GetHealthPercent() < 25.0f) { StartNextDialogueText(PHASE_SACRIFICE); } // no break - use the spells from the phases below; case PHASE_DARKNESS: // In the last phase he uses this spell more often if (m_uiDarknessOfSoulsTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_DARKNESS_OF_SOULS) == CAST_OK) { m_uiDarknessOfSoulsTimer = m_uiPhase == PHASE_SACRIFICE ? 30000 : 45000; } } else { m_uiDarknessOfSoulsTimer -= uiDiff; } if (m_uiFlameDartTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FLAME_DART) == CAST_OK) { m_uiFlameDartTimer = urand(25000, 30000); } } else { m_uiFlameDartTimer -= uiDiff; } // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_DARKNESS && m_creature->GetHealthPercent() < 55.0f) { StartNextDialogueText(PHASE_ARMAGEDDON); } // no break - use the spells from the phase below; case PHASE_INFERNO: if (m_uiKalecSummonTimer) { if (m_uiKalecSummonTimer <= uiDiff) { m_creature->SummonCreature(NPC_KALECGOS, aKalegSpawnLoc[0], aKalegSpawnLoc[1], aKalegSpawnLoc[2], aKalegSpawnLoc[3], TEMPSUMMON_CORPSE_DESPAWN, 0); m_uiKalecSummonTimer = 0; } else { m_uiKalecSummonTimer -= uiDiff; } } if (m_uiLegionLightingTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_LEGION_LIGHTING) == CAST_OK) { m_uiLegionLightingTimer = urand(10000, 15000); } } } else { m_uiLegionLightingTimer -= uiDiff; } if (m_uiFireBloomTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FIRE_BLOOM) == CAST_OK) { m_uiFireBloomTimer = 20000; } } else { m_uiFireBloomTimer -= uiDiff; } if (m_uiSoulFlyTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SOUL_FLY) == CAST_OK) { m_uiSoulFlyTimer = urand(3000, 10000); } } else { m_uiSoulFlyTimer -= uiDiff; } // Only spawn a Shadow orb when necessary if (m_uiShieldOrbCount < m_uiMaxShieldOrbs) { if (m_uiShieldOrbTimer < uiDiff) { // Get some random coords for the Orb float fX, fY, fZ; m_creature->GetNearPoint2D(fX, fY, 25.0f, frand(0, 2 * M_PI_F)); fZ = frand(35.0f, 45.0f); m_creature->SummonCreature(NPC_SHIELD_ORB, fX, fY, fZ, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); ++m_uiShieldOrbCount; m_uiShieldOrbTimer = 30000; } else { m_uiShieldOrbTimer -= uiDiff; } } // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_INFERNO && m_creature->GetHealthPercent() < 85.0f) { StartNextDialogueText(PHASE_DARKNESS); } DoMeleeAttackIfReady(); break; } }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; DialogueUpdate(uiDiff); switch (m_uiPhase) { case PHASE_TRANSITION: // Transition phase is handled in the dialogue helper; however we don't want the spell timers to be decreased so we use a specific phase break; case PHASE_SACRIFICE: // Final phase - use the same spells // no break; case PHASE_ARMAGEDDON: // In the last phase he uses Armageddon continuously if (m_uiArmageddonTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_ARMAGEDDON) == CAST_OK) m_uiArmageddonTimer = m_uiPhase == PHASE_SACRIFICE ? 20000 : 30000; } else m_uiArmageddonTimer -= uiDiff; // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_ARMAGEDDON && m_creature->GetHealthPercent() < 25.0f) StartNextDialogueText(PHASE_SACRIFICE); // no break - use the spells from the phases below; case PHASE_DARKNESS: // In the last phase he uses this spell more often /* ToDo: Uncomment this spell when the Blue Dragonfight Orbs are implemented if (m_uiDarknessOfSoulsTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_DARKNESS_OF_SOULS) == CAST_OK) m_uiDarknessOfSoulsTimer = m_uiPhase == PHASE_SACRIFICE ? 30000 : 45000; } else m_uiDarknessOfSoulsTimer -= uiDiff; */ if (m_uiFlameDartTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FLAME_DART) == CAST_OK) m_uiFlameDartTimer = urand(25000, 30000); } else m_uiFlameDartTimer -= uiDiff; // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_DARKNESS && m_creature->GetHealthPercent() < 55.0f) StartNextDialogueText(PHASE_ARMAGEDDON); // no break - use the spells from the phase below; case PHASE_INFERNO: if (m_uiKalecSummonTimer) { if (m_uiKalecSummonTimer <= uiDiff) { m_creature->SummonCreature(NPC_KALECGOS, m_creature->GetPositionX(), m_creature->GetPositionY(), 85.0f, 3.80f, TEMPSUMMON_CORPSE_DESPAWN, 0); m_uiKalecSummonTimer = 0; } else m_uiKalecSummonTimer -= uiDiff; } if (m_uiLegionLightingTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_LEGION_LIGHTING) == CAST_OK) m_uiLegionLightingTimer = urand(10000, 15000); } } else m_uiLegionLightingTimer -= uiDiff; if (m_uiFireBloomTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_FIRE_BLOOM) == CAST_OK) m_uiFireBloomTimer = 20000; } else m_uiFireBloomTimer -= uiDiff; if (m_uiSoulFlyTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SOUL_FLY) == CAST_OK) m_uiSoulFlyTimer = urand(3000, 10000); } else m_uiSoulFlyTimer -= uiDiff; // Go to next phase and start transition dialogue if (m_uiPhase == PHASE_INFERNO && m_creature->GetHealthPercent() < 85.0f) StartNextDialogueText(PHASE_DARKNESS); DoMeleeAttackIfReady(); break; } }
void Update(uint32 uiDiff) { DialogueUpdate(uiDiff); }