void UpdateAI(const uint32 uiDiff) override { if (m_uiMovementTimer) { if (m_uiMovementTimer <= uiDiff) { m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MovePoint(PHASE_GROUND, m_creature->GetPositionX(), m_creature->GetPositionY(), 50.083f, false); m_uiMovementTimer = 0; } else m_uiMovementTimer -= uiDiff; } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } switch (m_uiPhase) { case PHASE_GROUND: if (m_uiCleaveTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK) m_uiCleaveTimer = urand(2000, 5000); } else m_uiCleaveTimer -= uiDiff; if (m_uiCorrosionTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CORROSION) == CAST_OK) { DoScriptText(SAY_BREATH, m_creature); m_uiCorrosionTimer = 30000; } } else m_uiCorrosionTimer -= uiDiff; if (m_uiGasNovaTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_GAS_NOVA) == CAST_OK) m_uiGasNovaTimer = 23000; } else m_uiGasNovaTimer -= uiDiff; if (m_uiEncapsulateTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_ENCAPSULATE_CHANNEL) == CAST_OK) m_uiEncapsulateTimer = urand(30000, 40000); } } else m_uiEncapsulateTimer -= uiDiff; if (m_uiFlyPhaseTimer < uiDiff) { DoScriptText(SAY_TAKEOFF, m_creature); SetCombatMovement(false); m_creature->SetLevitate(true); m_creature->GetMotionMaster()->MoveIdle(); m_creature->GetMotionMaster()->MovePoint(PHASE_AIR, m_creature->GetPositionX(), m_creature->GetPositionY(), 50.083f, false); m_uiPhase = PHASE_TRANSITION; m_uiSubPhase = SUBPHASE_VAPOR; m_uiDemonicVaporTimer = 1000; m_uiDemonicVaporCount = 0; m_uiFlyPhaseTimer = 60000; } else m_uiFlyPhaseTimer -= uiDiff; DoMeleeAttackIfReady(); break; case PHASE_AIR: switch (m_uiSubPhase) { case SUBPHASE_VAPOR: if (m_uiDemonicVaporTimer < uiDiff) { // After the second Demonic Vapor trial, start the breath phase if (m_uiDemonicVaporCount == 2) { if (!m_pInstance) return; // select the side on which we want to fly m_bIsLeftSide = urand(0, 1) ? true : false; m_uiCorruptionCount = 0; m_uiSubPhase = SUBPHASE_BREATH_PREPARE; if (Creature* pTrigger = m_pInstance->GetSingleCreatureFromStorage(m_bIsLeftSide ? NPC_FLIGHT_TRIGGER_LEFT : NPC_FLIGHT_TRIGGER_RIGHT)) m_creature->GetMotionMaster()->MovePoint(SUBPHASE_VAPOR, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), false); } else { if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_VAPOR) == CAST_OK) { ++m_uiDemonicVaporCount; m_uiDemonicVaporTimer = 11000; } } } else m_uiDemonicVaporTimer -= uiDiff; break; case SUBPHASE_BREATH_PREPARE: if (m_uiCorruptionTimer) { if (m_uiCorruptionTimer <= uiDiff) { if (!m_pInstance) return; // Fly to trigger on the same side - choose a random index for the trigger m_uiCorruptionIndex = urand(0, 2); if (Creature* pTrigger = m_creature->GetMap()->GetCreature(m_pInstance->SelectFelmystFlightTrigger(m_bIsLeftSide, m_uiCorruptionIndex))) m_creature->GetMotionMaster()->MovePoint(SUBPHASE_BREATH_PREPARE, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), false); m_uiSubPhase = SUBPHASE_BREATH_MOVE; m_uiCorruptionTimer = 0; } else m_uiCorruptionTimer -= uiDiff; } break; case SUBPHASE_BREATH_MOVE: // nothing here; this is handled in MovementInform break; } break; case PHASE_TRANSITION: // nothing here; wait for transition to finish break; } }
void MovementInform(uint32 uiMoveType, uint32 uiPointId) override { if (uiMoveType != POINT_MOTION_TYPE) return; switch (uiPointId) { case PHASE_GROUND: m_creature->SetWalk(false); // ToDo: start WP movement here. Currently disabled because of some MMaps issues // m_creature->GetMotionMaster()->MoveWaypoint(); break; case PHASE_AIR: // switch from ground transition to flight phase m_uiPhase = PHASE_AIR; break; case SUBPHASE_VAPOR: // After the third breath land and resume phase 1 if (m_uiCorruptionCount == 3) { m_uiPhase = PHASE_TRANSITION; float fGroundZ = m_creature->GetMap()->GetHeight(m_creature->GetPhaseMask(), m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); m_creature->GetMotionMaster()->MovePoint(PHASE_TRANSITION, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), fGroundZ, false); return; } // prepare to move to flight trigger ++m_uiCorruptionCount; m_uiCorruptionTimer = 5000; m_uiSubPhase = SUBPHASE_BREATH_PREPARE; break; case SUBPHASE_BREATH_PREPARE: // move across the arena if (!m_pInstance) return; // Fly to the other side, casting the breath. Keep the same trigger index if (Creature* pTrigger = m_creature->GetMap()->GetCreature(m_pInstance->SelectFelmystFlightTrigger(!m_bIsLeftSide, m_uiCorruptionIndex))) { DoScriptText(EMOTE_DEEP_BREATH, m_creature); DoCastSpellIfCan(m_creature, SPELL_SPEED_BURST, CAST_TRIGGERED); DoCastSpellIfCan(m_creature, SPELL_FOG_CORRUPTION, CAST_TRIGGERED); m_creature->GetMotionMaster()->MovePoint(SUBPHASE_BREATH_MOVE, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), false); } break; case SUBPHASE_BREATH_MOVE: if (!m_pInstance) return; // remove speed aura m_creature->RemoveAurasDueToSpell(SPELL_SPEED_BURST); // Get to the flight trigger on the same side of the arena if (Creature* pTrigger = m_pInstance->GetSingleCreatureFromStorage(!m_bIsLeftSide ? NPC_FLIGHT_TRIGGER_LEFT : NPC_FLIGHT_TRIGGER_RIGHT)) m_creature->GetMotionMaster()->MovePoint(SUBPHASE_VAPOR, pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), false); // switch sides m_bIsLeftSide = !m_bIsLeftSide; break; case PHASE_TRANSITION: // switch back to ground combat from flight transition m_uiPhase = PHASE_GROUND; SetCombatMovement(true); m_creature->SetLevitate(false); DoStartMovement(m_creature->getVictim()); break; } }