void ReceiveAIEvent(AIEventType eventType, Creature* /*pSender*/, Unit* /*pInvoker*/, uint32 /*uiMiscValue*/) override { // inform about the harpoon repair event if (eventType == AI_EVENT_CUSTOM_A) { DoMoveEngineersToHarpoon(); m_uiRepairHarpoonTimer = 20000; } // inform about a harpoon being shot if (eventType == AI_EVENT_CUSTOM_B) { ++m_uiHarpoonsUsed; // start grounded phase if (m_uiHarpoonsUsed == m_uiMaxHarpoons) { // use upgraded speed rate for FlyOrLand. This isn't supported by DB but it's confirmed to happen on retail uint32 uiSpeedRate = m_creature->GetSpeedRate(MOVE_RUN); m_creature->SetWalk(false); m_creature->SetSpeedRate(MOVE_RUN, SPEED_RATE_RAZORSCALE); m_creature->GetMotionMaster()->MoveFlyOrLand(1, afRazorscaleGroundPos[0], afRazorscaleGroundPos[1], afRazorscaleGroundPos[2], false); m_creature->SetSpeedRate(MOVE_RUN, uiSpeedRate); m_uiPhase = PHASE_TRANSITION; m_uiShackleTimer = 5000; // move the trappers around m_pInstance->SetData(TYPE_DO_TRAPPERS_MOVE, 0); } } }
void ReceiveAIEvent(AIEventType eventType, Unit* /*pSender*/, Unit* pInvoker, uint32 /*uiMiscValue*/) override { // inform about the harpoon repair event if (eventType == AI_EVENT_CUSTOM_A) { DoMoveEngineersToHarpoon(); m_uiRepairHarpoonTimer = 20000; } // inform about a harpoon being shot if (eventType == AI_EVENT_CUSTOM_B) { ++m_uiHarpoonsUsed; // start grounded phase if (m_uiHarpoonsUsed == m_uiMaxHarpoons) { // use upgraded speed rate for FlyOrLand. This isn't supported by DB but it's confirmed to happen on retail uint32 uiSpeedRate = m_creature->GetSpeedRate(MOVE_RUN); m_creature->SetWalk(false); m_creature->SetSpeedRate(MOVE_RUN, SPEED_RATE_RAZORSCALE); m_creature->GetMotionMaster()->MoveFlyOrLand(1, afRazorscaleGroundPos[0], afRazorscaleGroundPos[1], afRazorscaleGroundPos[2], false); m_creature->SetSpeedRate(MOVE_RUN, uiSpeedRate); m_uiPhase = PHASE_TRANSITION; m_uiShackleTimer = 5000; // move the trappers around float fX, fY, fZ; uint8 uiIndex = 5; if (m_pInstance) { if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_RAZORSCALE_CONTROLLER)) { for (GuidList::const_iterator itr = m_lTrappersGuids.begin(); itr != m_lTrappersGuids.end(); ++itr) { if (Creature* pTrapper = m_creature->GetMap()->GetCreature(*itr)) { pController->GetNearPoint(pController, fX, fY, fZ, 0, 50.0f, M_PI_F / 4 * uiIndex); pTrapper->SetWalk(false); uiSpeedRate = pTrapper->GetSpeedRate(MOVE_RUN); pTrapper->SetSpeedRate(MOVE_RUN, SPEED_RATE_HELPERS); pTrapper->GetMotionMaster()->MovePoint(1, fX, fY, fZ); pTrapper->SetSpeedRate(MOVE_RUN, uiSpeedRate); ++uiIndex; } } } // yell that Razor is grounded if (Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_EXPEDITION_COMMANDER)) DoScriptText(SAY_GROUNDED, pCommander); } } } }
void UpdateAI(const uint32 uiDiff) override { if (!SelectCustomHostileTarget()) 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_AIR: 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 = 2000; } } else m_uiFireballTimer -= uiDiff; if (m_uiDevouringFlameTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_DEVOURING_FLAME) == CAST_OK) m_uiDevouringFlameTimer = 10000; } } else m_uiDevouringFlameTimer -= uiDiff; // harpoon is repaired; move to next one, or to home position if all are completed if (m_uiRepairHarpoonTimer) { if (m_uiRepairHarpoonTimer <= uiDiff) { // handle fire extinguish after a grounded phase if (!m_pInstance->GetData(TYPE_DATA_CURRENT_HARPOON)) { // extinguish fires if (m_pInstance) { if (Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_EXPEDITION_COMMANDER)) { if (Creature* pEngineer = GetClosestCreatureWithEntry(pCommander, NPC_EXPEDITION_ENGINEER, 15.0f)) DoScriptText(SAY_EXTINGUISH_FIRE, pEngineer); } } // move engineers to the first harpoon again DoMoveEngineersToHarpoon(); m_uiRepairHarpoonTimer = 20000; } else { DoScriptText(EMOTE_HARPOON_READY, m_creature); // despawn the current broken harpoon and spawn the repaired one if (GameObject* pHarpoon = m_creature->GetMap()->GetGameObject(ObjectGuid(m_pInstance->GetData64(DATA64_BROKEN_HARPOON)))) { pHarpoon->SetRespawnTime(HOUR); pHarpoon->SetLootState(GO_JUST_DEACTIVATED); DoRepairHarpoon(pHarpoon); } // if all harpoons have been repaired stop if (uint8(m_pInstance->GetData(TYPE_DATA_CURRENT_HARPOON)) == m_uiMaxHarpoons) { m_pInstance->SetData(TYPE_DO_HARPOONS_OK, 0); m_uiRepairHarpoonTimer = 0; } // move to next harpoon else { DoMoveEngineersToHarpoon(); m_uiRepairHarpoonTimer = 20000; } } } else m_uiRepairHarpoonTimer -= uiDiff; } // spawn Mole Machines with dwarfes if (m_uiDwarfSpawnTimer < uiDiff) { DoSpawnMoleMachines(); m_uiDwarfSpawnTimer = 40000; } else m_uiDwarfSpawnTimer -= uiDiff; break; case PHASE_TRANSITION: if (m_uiShackleTimer < uiDiff) { // cast trap visual m_pInstance->SetData(TYPE_DO_TRAPPERS_CAST, SPELL_SHACKLE); // stun Razorscale if (DoCastSpellIfCan(m_creature, SPELL_STUN) == CAST_OK) { m_creature->SetLevitate(false); m_creature->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_FLY_ANIM); m_uiPhase = PHASE_GROUNDED; m_uiGroundedTimer = 30000; m_uiGroundedStep = 0; m_uiShackleTimer = 5000; } } else m_uiShackleTimer -= uiDiff; break; case PHASE_GROUNDED: if (m_uiGroundedTimer < uiDiff) { switch (m_uiGroundedStep) { case 0: m_creature->RemoveAurasDueToSpell(SPELL_STUN); if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H) == CAST_OK) { DoScriptText(EMOTE_BREATH, m_creature); m_uiGroundedTimer = 2500; } break; case 1: if (DoCastSpellIfCan(m_creature, SPELL_WING_BUFFET) == CAST_OK) m_uiGroundedTimer = 1500; break; case 2: if (DoCastSpellIfCan(m_creature, SPELL_FIREBOLT) == CAST_OK) m_uiGroundedTimer = 2000; break; case 3: // if fully grounded then go to ground phase if (m_bIsGrounded) { SetCombatMovement(true); DoResetThreat(); DoStartMovement(m_creature->getVictim()); m_uiPhase = PHASE_ONLY_GROUND; } // resume air phase else { m_creature->SetLevitate(true); m_creature->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_FLY_ANIM); float fX, fY, fZ; m_creature->GetRespawnCoord(fX, fY, fZ); // use upgraded speed rate for FlyOrLand. This isn't supported by DB but it's confirmed to happen on retail uint32 uiSpeedRate = m_creature->GetSpeedRate(MOVE_RUN); m_creature->SetSpeedRate(MOVE_RUN, SPEED_RATE_RAZORSCALE); m_creature->GetMotionMaster()->MoveFlyOrLand(1, fX, fY, fZ, true); m_creature->SetSpeedRate(MOVE_RUN, uiSpeedRate); // reset timers m_uiPhase = PHASE_AIR; m_pInstance->SetData(TYPE_DATA_CURRENT_HARPOON, 0); m_uiHarpoonsUsed = 0; m_uiRepairHarpoonTimer = 20000; m_uiFireballTimer = 5000; m_uiDevouringFlameTimer = 10000; ++m_uiFlyPhaseCount; // set achiev criteria as failed if (m_uiFlyPhaseCount >= 2 && m_pInstance) m_pInstance->SetData(TYPE_ACHIEV_QUICK_SHAVE, uint32(false)); } // make the Trappers evade or move to home position m_pInstance->SetData(TYPE_DO_TRAPPERS_EVADE, 0); break; } ++m_uiGroundedStep; } else m_uiGroundedTimer -= uiDiff; // make boss land at 50% hp if (!m_bIsGrounded && m_creature->GetHealthPercent() < 50.0f) { DoScriptText(EMOTE_GROUNDED, m_creature); m_creature->RemoveAurasDueToSpell(SPELL_STUN); m_uiGroundedStep = 1; m_uiGroundedTimer = 0; m_bIsGrounded = true; } break; case PHASE_ONLY_GROUND: if (m_uiDevouringFlameTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { if (DoCastSpellIfCan(pTarget, SPELL_DEVOURING_FLAME) == CAST_OK) m_uiDevouringFlameTimer = 10000; } } else m_uiDevouringFlameTimer -= uiDiff; if (m_uiFuseArmorTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FUSE_ARMOR) == CAST_OK) m_uiFuseArmorTimer = 13000; } else m_uiFuseArmorTimer -= uiDiff; if (m_uiFlameBuffetTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_BUFFET : SPELL_FLAME_BUFFET_H) == CAST_OK) m_uiFlameBuffetTimer = 10000; } else m_uiFlameBuffetTimer -= uiDiff; if (m_uiFlameBreathTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H) == CAST_OK) { DoScriptText(EMOTE_BREATH, m_creature); m_uiFlameBreathTimer = 15000; } } else m_uiFlameBreathTimer -= uiDiff; DoMeleeAttackIfReady(); break; } }