コード例 #1
0
ファイル: boss_onyxia.cpp プロジェクト: adan830/QuaDCore
    void UpdateAI(const uint32 diff)
    {
        if(!UpdateVictim())
            return;

        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 60) && (Phase == 1))
        {
            Phase = 2;
            m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
            m_creature->SetHover(true);
            m_creature->GetMotionMaster()->Clear(false);
            m_creature->GetMotionMaster()->MoveIdle();
            DoScriptText(SAY_PHASE_2_TRANS, m_creature);
        }

        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 40) && (Phase == 2))
        {
            Phase = 3;
            m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
            m_creature->SetHover(false);
            m_creature->GetMotionMaster()->MovePoint(0, -10.6155, -219.357, -87.7344);
            DoStartMovement(m_creature->getVictim());
            m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
            DoScriptText(SAY_PHASE_3_TRANS, m_creature);
        }

        if(Phase == 1 || Phase == 3)
        {
            if(FlameBreathTimer < diff)
            {
                DoCast(m_creature->getVictim(), SPELL_FLAMEBREATH);
                FlameBreathTimer = 15000;
            }else FlameBreathTimer -= diff;

            if(TailSweepTimer < diff)
            {
                Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
                if(target && !m_creature->HasInArc(M_PI, target))
                    DoCast(target, SPELL_TAILSWEEP);

                TailSweepTimer = 10000;
            }else TailSweepTimer -= diff;

            if(CleaveTimer < diff)
            {
                DoCast(m_creature->getVictim(), SPELL_CLEAVE);
                CleaveTimer = 10000;
            }else CleaveTimer -= diff;

            if(WingBuffetTimer < diff)
            {
                DoCast(m_creature->getVictim(), SPELL_WINGBUFFET);
                WingBuffetTimer = 7000 + ((rand()%8)*1000);
            }else WingBuffetTimer -= diff;

            if(KnockAwayTimer < diff)
            {
                if(rand() <= 30)
                {
                    DoCast(m_creature->getVictim(), SPELL_KNOCK_AWAY);
                }
                KnockAwayTimer = 15000;
            }else KnockAwayTimer -= diff;

            if(Phase == 3)
            {
                if(BellowingRoarTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_BELLOWINGROAR);

                    BellowingRoarTimer = 30000;
                }else BellowingRoarTimer -= diff;

                if(SummonWhelpsTimer < diff)
                {
                    SummonWhelps(Phase);

                    SummonWhelpsTimer = 45000;
                }else SummonWhelpsTimer -= diff;
            }

            DoMeleeAttackIfReady();
        }

        if(Phase == 2)
        {
            if(InitialSpawn)
            {
                InitialSpawn = false;

                for(uint32 i = 0; i < 10; ++i)
                {
                    uint32 random = rand()%4;
                    Creature* Whelp = m_creature->SummonCreature(CREATURE_WHELP, SpawnLocations[random][0], SpawnLocations[random][1], SpawnLocations[random][2], 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
                    if(Whelp)
                        Whelp->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0));
                }
            }

            if(EngulfingFlamesTimer < diff)
            {
                DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_ENGULFINGFLAMES);
                m_creature->HandleEmoteCommand(ANIM_FLY);

                EngulfingFlamesTimer = 10000;
            }
            else EngulfingFlamesTimer -= diff;

            if(FireballTimer < diff)
            {
                DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);

                FireballTimer = 18000;
            }
            else FireballTimer -= diff;

            if(MovementTimer < diff)
            {
                if(rand()%100 < 30)
                {
                    DoScriptText(EMOTE_BREATH, m_creature);
                    DoCast(m_creature->getVictim(), SPELL_DEEPBREATH);
                }
                else ChangePosition();

                MovementTimer = 25000;
            }else MovementTimer -= diff;

            if(SummonWhelpsTimer < diff)
            {
                SummonWhelps(Phase);

                SummonWhelpsTimer = 45000;
            }
            else SummonWhelpsTimer -= diff;
        }
    }
コード例 #2
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;
        }
    }