Esempio n. 1
0
    void MovementInform(uint32 uiMoveType, uint32 uiPointId) override
    {
        if (uiMoveType != POINT_MOTION_TYPE || !m_pInstance)
            return;

        switch (uiPointId)
        {
            case POINT_ID_IN_AIR:
                // sort of a hack, it is unclear how this really work but the values are valid
                m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_FLY_ANIM);
                m_creature->SetLevitate(true);
                m_uiPhaseTimer = 1000;                          // Movement to Initial North Position is delayed
                return;
            case POINT_ID_LAND:
                // undo flying
                m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0);
                m_creature->SetLevitate(false);
                m_creature->HandleEmote(EMOTE_ONESHOT_LAND);
                m_uiPhaseTimer = 500;                           // Start PHASE_END shortly delayed
                return;
            case POINT_ID_LIFTOFF:
                m_uiPhaseTimer = 500;                           // Start Flying shortly delayed
                m_creature->HandleEmote(EMOTE_ONESHOT_LIFTOFF);
                break;
            case POINT_ID_INIT_NORTH:                           // Start PHASE_BREATH
                m_uiPhase = PHASE_BREATH;
                break;
        }

        if (Creature* pTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_ONYXIA_TRIGGER))
            m_creature->SetFacingToObject(pTrigger);
    }
Esempio n. 2
0
    void Aggro(Unit* /*pWho*/) override
    {
        DoScriptText(SAY_AGGRO, m_creature);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_ONYXIA, IN_PROGRESS);
    }
 void JustDied(Unit* /*pKiller*/) override
 {
     if (m_pInstance)
     {
         m_pInstance->SetData(TYPE_ONYXIA, DONE);
     }
 }
Esempio n. 4
0
    void JustReachedHome() override
    {
        // in case evade in phase 2, see comments for hack where phase 2 is set
        m_creature->SetLevitate(false);
        m_creature->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_ONYXIA, FAIL);
    }
Esempio n. 5
0
    void JustSummoned(Creature* pSummoned) override
    {
        if (!m_pInstance)
            return;

        if (Creature* pTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_ONYXIA_TRIGGER))
        {
            // Get some random point near the center
            float fX, fY, fZ;
            pSummoned->GetRandomPoint(pTrigger->GetPositionX(), pTrigger->GetPositionY(), pTrigger->GetPositionZ(), 20.0f, fX, fY, fZ);
            pSummoned->GetMotionMaster()->MovePoint(1, fX, fY, fZ);
        }
        else
            pSummoned->SetInCombatWithZone();

        if (pSummoned->GetEntry() == NPC_ONYXIA_WHELP)
            ++m_uiSummonCount;
    }
Esempio n. 6
0
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Whelps summoning timer, outside encounter phase switch because the summoning spans across several sub-parts of phase 2
        if (m_uiSummonWhelpsTimer)
        {
            if (m_uiSummonWhelpsTimer < uiDiff)
            {
                SummonWhelps();
                // no update of timer: handled in SummonWhelps()
            }
            else
            {
                m_uiSummonWhelpsTimer -= uiDiff;
                if (m_uiSummonWhelpsTimer == 0)         // check needed for the rare but possible case where (m_uiSummonWhelpsTimer - uiDiff == 0)
                    SummonWhelps();
            }
        }

        switch (m_uiPhase)
        {
            case PHASE_END:
                if (m_uiBellowingRoarTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR) == CAST_OK)
                        m_uiBellowingRoarTimer = urand(15000, 45000);
                }
                else
                    m_uiBellowingRoarTimer -= uiDiff;
            // no break, phase 3 will use same abilities as in 1
            case PHASE_START:
            {
                if (m_uiFlameBreathTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FLAMEBREATH) == CAST_OK)
                        m_uiFlameBreathTimer = urand(10000, 20000);
                }
                else
                    m_uiFlameBreathTimer -= uiDiff;

                if (m_uiTailSweepTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_TAILSWEEP) == CAST_OK)
                        m_uiTailSweepTimer = urand(15000, 20000);
                }
                else
                    m_uiTailSweepTimer -= uiDiff;

                if (m_uiCleaveTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
                        m_uiCleaveTimer = urand(2000, 5000);
                }
                else
                    m_uiCleaveTimer -= uiDiff;

                if (m_uiWingBuffetTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_WINGBUFFET) == CAST_OK)
                        m_uiWingBuffetTimer = urand(15000, 30000);
                }
                else
                    m_uiWingBuffetTimer -= uiDiff;

                if (m_uiCheckInLairTimer < uiDiff)
                {
                    if (m_pInstance)
                    {
                        Creature* pOnyTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_ONYXIA_TRIGGER);
                        if (pOnyTrigger && !m_creature->IsWithinDistInMap(pOnyTrigger, 90.0f, false))
                        {
                            if (!m_bHasYelledLured)
                            {
                                m_bHasYelledLured = true;
                                DoScriptText(SAY_KITE, m_creature);
                            }
                            DoCastSpellIfCan(m_creature, SPELL_BREATH_ENTRANCE);
                        }
                        else
                            m_bHasYelledLured = false;
                    }
                    m_uiCheckInLairTimer = 3000;
                }
                else
                    m_uiCheckInLairTimer -= uiDiff;

                if (m_uiPhase == PHASE_START && m_creature->GetHealthPercent() < 65.0f)
                {
                    m_uiPhase = PHASE_TO_LIFTOFF;
                    DoScriptText(SAY_PHASE_2_TRANS, m_creature);
                    SetCombatMovement(false);
                    m_creature->GetMotionMaster()->MoveIdle();
                    m_creature->SetTarget(nullptr);

                    float fGroundZ = m_creature->GetMap()->GetHeight(aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, aMoveData[POINT_ID_SOUTH].fZ);
                    m_creature->GetMotionMaster()->MovePoint(POINT_ID_LIFTOFF, aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, fGroundZ);
                    return;
                }

                DoMeleeAttackIfReady();
                break;
            }
            case PHASE_BREATH:
            {
                if (m_creature->GetHealthPercent() < 40.0f)
                {
                    m_uiPhase = PHASE_BREATH_POST;
                    DoScriptText(SAY_PHASE_3_TRANS, m_creature);
                    m_uiSummonWhelpsTimer = 0;              // End of Onyxian Whelps summoning

                    float fGroundZ = m_creature->GetMap()->GetHeight(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
                    m_creature->GetMotionMaster()->MoveFlyOrLand(POINT_ID_LAND, m_creature->GetPositionX(), m_creature->GetPositionY(), fGroundZ, false);
                    return;
                }

                if (m_uiMovementTimer < uiDiff)
                {
                    // 3 possible actions
                    switch (urand(0, 2))
                    {
                        case 0:                             // breath
                            DoScriptText(EMOTE_BREATH, m_creature);
                            DoCastSpellIfCan(m_creature, aMoveData[m_uiMovePoint].uiSpellId, CAST_INTERRUPT_PREVIOUS);
                            m_uiMovePoint += NUM_MOVE_POINT / 2;
                            m_uiMovePoint %= NUM_MOVE_POINT;
                            m_uiMovementTimer = 25000;
                            return;
                        case 1:                             // a point on the left side
                        {
                            // C++ is stupid, so add -1 with +7
                            m_uiMovePoint += NUM_MOVE_POINT - 1;
                            m_uiMovePoint %= NUM_MOVE_POINT;
                            break;
                        }
                        case 2:                             // a point on the right side
                            ++m_uiMovePoint %= NUM_MOVE_POINT;
                            break;
                    }

                    m_uiMovementTimer = urand(15000, 25000);
                    m_creature->GetMotionMaster()->MovePoint(m_uiMovePoint, aMoveData[m_uiMovePoint].fX, aMoveData[m_uiMovePoint].fY, aMoveData[m_uiMovePoint].fZ);
                }
                else
                    m_uiMovementTimer -= uiDiff;

                if (m_uiFireballTimer < uiDiff)
                {
                    if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                    {
                        if (DoCastSpellIfCan(pTarget, SPELL_FIREBALL) == CAST_OK)
                            m_uiFireballTimer = urand(3000, 5000);
                    }
                }
                else
                    m_uiFireballTimer -= uiDiff;            // engulfingflames is supposed to be activated by a fireball but haven't come by

                break;
            }
            default:                                        // Phase-switching phases
                if (!m_uiPhaseTimer)
                    break;
                if (m_uiPhaseTimer <= uiDiff)
                {
                    switch (m_uiPhase)
                    {
                        case PHASE_TO_LIFTOFF:
                            m_uiPhase = PHASE_BREATH_PRE;
                            // Initial Onyxian Whelps spawn
                            m_uiSummonWhelpsTimer = 3000;
                            if (m_pInstance)
                                m_pInstance->SetData(TYPE_ONYXIA, DATA_LIFTOFF);
                            m_creature->GetMotionMaster()->MoveFlyOrLand(POINT_ID_IN_AIR, aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, aMoveData[POINT_ID_SOUTH].fZ, true);
                            break;
                        case PHASE_BREATH_PRE:
                            m_creature->GetMotionMaster()->MovePoint(POINT_ID_INIT_NORTH, aMoveData[POINT_ID_NORTH].fX, aMoveData[POINT_ID_NORTH].fY, aMoveData[POINT_ID_NORTH].fZ);
                            break;
                        case PHASE_BREATH_POST:
                            m_uiPhase = PHASE_END;
                            m_creature->SetTarget(m_creature->getVictim());
                            SetCombatMovement(true, true);
                            DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR);
                            break;
                    }
                    m_uiPhaseTimer = 0;
                }
                else
                    m_uiPhaseTimer -= uiDiff;
                break;
        }
    }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
        {
            return;
        }

        switch (m_uiPhase)
        {
            case PHASE_END:                                 // Here is room for additional summoned whelps and Erruption
                if (m_uiBellowingRoarTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR) == CAST_OK)
                    {
                        m_uiBellowingRoarTimer = 30000;
                    }
                }
                else
                {
                    m_uiBellowingRoarTimer -= uiDiff;
                }
                // no break, phase 3 will use same abilities as in 1
            case PHASE_START:
            {
                if (m_uiFlameBreathTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FLAMEBREATH) == CAST_OK)
                    {
                        m_uiFlameBreathTimer = urand(10000, 20000);
                    }
                }
                else
                {
                    m_uiFlameBreathTimer -= uiDiff;
                }

                if (m_uiTailSweepTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_TAILSWEEP) == CAST_OK)
                    {
                        m_uiTailSweepTimer = urand(15000, 20000);
                    }
                }
                else
                {
                    m_uiTailSweepTimer -= uiDiff;
                }

                if (m_uiCleaveTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
                    {
                        m_uiCleaveTimer = urand(2000, 5000);
                    }
                }
                else
                {
                    m_uiCleaveTimer -= uiDiff;
                }

                if (m_uiWingBuffetTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_WINGBUFFET) == CAST_OK)
                    {
                        m_uiWingBuffetTimer = urand(15000, 30000);
                    }
                }
                else
                {
                    m_uiWingBuffetTimer -= uiDiff;
                }

                if (m_uiCheckInLairTimer < uiDiff)
                {
                    if (m_pInstance)
                    {
                        Creature* pOnyTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_ONYXIA_TRIGGER);
                        if (pOnyTrigger && !m_creature->IsWithinDistInMap(pOnyTrigger, 90.0f, false))
                        {
                            DoCastSpellIfCan(m_creature, SPELL_BREATH_ENTRANCE);
                        }
                    }
                    m_uiCheckInLairTimer = 3000;
                }
                else
                {
                    m_uiCheckInLairTimer -= uiDiff;
                }

                if (m_uiPhase == PHASE_START && m_creature->GetHealthPercent() < 65.0f)
                {
                    m_uiPhase = PHASE_TO_LIFTOFF;
                    DoScriptText(SAY_PHASE_2_TRANS, m_creature);
                    SetCombatMovement(false);
                    m_creature->GetMotionMaster()->MoveIdle();
                    m_creature->SetTargetGuid(ObjectGuid());

                    float fGroundZ = m_creature->GetMap()->GetHeight(aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, aMoveData[POINT_ID_SOUTH].fZ);
                    m_creature->GetMotionMaster()->MovePoint(POINT_ID_LIFTOFF, aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, fGroundZ);
                    return;
                }

                DoMeleeAttackIfReady();
                break;
            }
            case PHASE_BREATH:
            {
                if (m_creature->GetHealthPercent() < 40.0f)
                {
                    m_uiPhase = PHASE_BREATH_POST;
                    DoScriptText(SAY_PHASE_3_TRANS, m_creature);

                    float fGroundZ = m_creature->GetMap()->GetHeight(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
                    m_creature->GetMotionMaster()->MoveFlyOrLand(POINT_ID_LAND, m_creature->GetPositionX(), m_creature->GetPositionY(), fGroundZ, false);
                    return;
                }

                if (m_uiMovementTimer < uiDiff)
                {
                    // 3 possible actions
                    switch (urand(0, 2))
                    {
                        case 0:                             // breath
                            DoScriptText(EMOTE_BREATH, m_creature);
                            DoCastSpellIfCan(m_creature, aMoveData[m_uiMovePoint].uiSpellId, CAST_INTERRUPT_PREVIOUS);
                            m_uiMovePoint += NUM_MOVE_POINT / 2;
                            m_uiMovePoint %= NUM_MOVE_POINT;
                            m_uiMovementTimer = 25000;
                            return;
                        case 1:                             // a point on the left side
                        {
                            // C++ is stupid, so add -1 with +7
                            m_uiMovePoint += NUM_MOVE_POINT - 1;
                            m_uiMovePoint %= NUM_MOVE_POINT;
                            break;
                        }
                        case 2:                             // a point on the right side
                            ++m_uiMovePoint %= NUM_MOVE_POINT;
                            break;
                    }

                    m_uiMovementTimer = urand(15000, 25000);
                    m_creature->GetMotionMaster()->MovePoint(m_uiMovePoint, aMoveData[m_uiMovePoint].fX, aMoveData[m_uiMovePoint].fY, aMoveData[m_uiMovePoint].fZ);
                }
                else
                {
                    m_uiMovementTimer -= uiDiff;
                }

                if (m_uiFireballTimer < uiDiff)
                {
                    if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                    {
                        if (DoCastSpellIfCan(pTarget, SPELL_FIREBALL) == CAST_OK)
                        {
                            m_uiFireballTimer = urand(3000, 5000);
                        }
                    }
                }
                else
                {
                    m_uiFireballTimer -= uiDiff;    // engulfingflames is supposed to be activated by a fireball but haven't come by
                }

                if (m_bIsSummoningWhelps)
                {
                    if (DidSummonWhelps(uiDiff))
                    {
                        m_bIsSummoningWhelps = false;
                        m_uiSummonCount = 0;
                        m_uiSummonWhelpsTimer = 80000;      // 90s - 10s for summoning
                    }
                }
                else
                {
                    if (m_uiSummonWhelpsTimer < uiDiff)
                    {
                        m_bIsSummoningWhelps = true;
                    }
                    else
                    {
                        m_uiSummonWhelpsTimer -= uiDiff;
                    }
                }

                break;
            }
            case PHASE_BREATH_PRE:                          // Summon first rounds of whelps
                DidSummonWhelps(uiDiff);
                // no break here
            default:                                        // Phase-switching phases
                if (!m_uiPhaseTimer)
                {
                    break;
                }
                if (m_uiPhaseTimer <= uiDiff)
                {
                    switch (m_uiPhase)
                    {
                        case PHASE_TO_LIFTOFF:
                            m_uiPhase = PHASE_BREATH_PRE;
                            if (m_pInstance)
                            {
                                m_pInstance->SetData(TYPE_ONYXIA, DATA_LIFTOFF);
                            }
                            m_creature->GetMotionMaster()->MoveFlyOrLand(POINT_ID_IN_AIR, aMoveData[POINT_ID_SOUTH].fX, aMoveData[POINT_ID_SOUTH].fY, aMoveData[POINT_ID_SOUTH].fZ, true);
                            break;
                        case PHASE_BREATH_PRE:
                            m_creature->GetMotionMaster()->MovePoint(POINT_ID_INIT_NORTH, aMoveData[POINT_ID_NORTH].fX, aMoveData[POINT_ID_NORTH].fY, aMoveData[POINT_ID_NORTH].fZ);
                            break;
                        case PHASE_BREATH_POST:
                            m_uiPhase = PHASE_END;
                            m_creature->SetTargetGuid(m_creature->getVictim()->GetObjectGuid());
                            SetCombatMovement(true, true);
                            DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR);
                            break;
                    }
                    m_uiPhaseTimer = 0;
                }
                else
                {
                    m_uiPhaseTimer -= uiDiff;
                }
                break;
        }
    }