예제 #1
0
    bool HasPlayersInLeftSide()
    {
        Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers();

        if (lPlayers.isEmpty())
            return false;

        for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
        {
            if (Player* pPlayer = itr->getSource())
            {
                if (!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive())
                    return true;
            }
        }

        return false;
    }
예제 #2
0
    bool HasPlayersInLeftSide() const
    {
        Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers();

        if (lPlayers.isEmpty())
            return false;

        for (const auto& lPlayer : lPlayers)
        {
            if (Player* pPlayer = lPlayer.getSource())
            {
                if (!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive())
                    return true;
            }
        }

        return false;
    }
예제 #3
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        switch (m_uiPhase)
        {
            case PHASE_SPEECH:
                if (m_uiSpeechTimer < uiDiff)
                {
                    switch (m_uiSpeech)
                    {
                        case 1: DoScriptText(SAY_SPEECH_1, m_creature); m_uiSpeechTimer = 4 * IN_MILLISECONDS; break;
                        case 2: DoScriptText(SAY_SPEECH_2, m_creature); m_uiSpeechTimer = 6 * IN_MILLISECONDS; break;
                        case 3: DoScriptText(SAY_SPEECH_3, m_creature); m_uiSpeechTimer = 5 * IN_MILLISECONDS; break;
                        case 4: DoScriptText(SAY_SPEECH_4, m_creature); m_uiPhase = PHASE_BALCONY; break;
                    }
                    m_uiSpeech++;
                }
                else
                    m_uiSpeechTimer -= uiDiff;

                // No break here

            case PHASE_BALCONY:                            // Do summoning
                if (m_uiTraineeTimer < uiDiff)
                {
                    SummonAdds(true, NPC_UNREL_TRAINEE);
                    m_uiTraineeTimer = 20 * IN_MILLISECONDS;
                }
                else
                    m_uiTraineeTimer -= uiDiff;
                if (m_uiDeathKnightTimer < uiDiff)
                {
                    SummonAdds(true, NPC_UNREL_DEATH_KNIGHT);
                    m_uiDeathKnightTimer = 25 * IN_MILLISECONDS;
                }
                else
                    m_uiDeathKnightTimer -= uiDiff;
                if (m_uiRiderTimer < uiDiff)
                {
                    SummonAdds(true, NPC_UNREL_RIDER);
                    m_uiRiderTimer = 30 * IN_MILLISECONDS;
                }
                else
                    m_uiRiderTimer -= uiDiff;

                if (m_uiPhaseTimer < uiDiff)
                {
                    m_uiPhase = PHASE_STOP_SUMMONING;
                    m_uiPhaseTimer = 50 * IN_MILLISECONDS;
                }
                else
                    m_uiPhaseTimer -= uiDiff;

                break;

            case PHASE_STOP_SUMMONING:
                if (m_uiPhaseTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT, CAST_TRIGGERED) == CAST_OK)
                    {
                        m_uiPhase = m_pInstance ? PHASE_TELEPORTING : PHASE_STOP_TELEPORTING;

                        DoScriptText(SAY_TELEPORT, m_creature);
                        DoScriptText(EMOTE_TO_FRAY, m_creature);

                        // Remove Immunity
                        m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false);

                        DoResetThreat();
                        m_creature->SetInCombatWithZone();
                    }
                }
                else
                    m_uiPhaseTimer -= uiDiff;

                break;

            case PHASE_TELEPORTING:                         // Phase is only reached if m_pInstance is valid
                if (m_uiTeleportTimer < uiDiff)
                {
                    uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT;
                    if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK)
                    {
                        m_uiTeleportTimer = urand(30000, 45000); // Teleports between 30 seconds and 45 seconds.
                        m_uiShadowboltTimer = 2 * IN_MILLISECONDS;
                    }
                }
                else
                    m_uiTeleportTimer -= uiDiff;

                if (m_creature->GetHealthPercent() <= 30.0f)
                {
                    m_uiPhase = PHASE_STOP_TELEPORTING;
                    ProcessCentralDoor();
                    // as the doors now open, recheck whether mobs are standing around
                    m_uiControlZoneTimer = 1;
                }
                // no break here

            case PHASE_STOP_TELEPORTING:
                if (m_uiHarvestSoulTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature, SPELL_HARVESTSOUL) == CAST_OK)
                        m_uiHarvestSoulTimer = 15 * IN_MILLISECONDS;
                }
                else
                    m_uiHarvestSoulTimer -= uiDiff;

                if (m_uiShadowboltTimer)
                {
                    if (m_uiShadowboltTimer <= uiDiff)
                        m_uiShadowboltTimer = 2 * IN_MILLISECONDS;
                    else
                        m_uiShadowboltTimer -= uiDiff;
                }
                // Shadowbold cooldown finished, cast when ready
                else if (!m_creature->IsNonMeleeSpellCasted(true))
                {
                    // Select valid target
                    if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0))
                        DoCastSpellIfCan(pTarget, SPELL_SHADOWBOLT);
                }

                break;
        }

        // Control Check, if Death zone empty
        if (m_uiControlZoneTimer)
        {
            if (m_uiControlZoneTimer <= uiDiff)
            {
                m_uiControlZoneTimer = 0;

                if (m_pInstance && !HasPlayersInLeftSide())
                {
                    ProcessCentralDoor();
                    for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); itr++)
                    {
                        if (Creature* pCreature = m_pInstance->instance->GetCreature(*itr))
                        {
                            if (!pCreature->isInCombat())
                                pCreature->SetInCombatWithZone();
                        }
                    }
                }
            }
            else
                m_uiControlZoneTimer -= uiDiff;
        }
    }
예제 #4
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        switch(m_uiPhase)
        {
        case PHASE_SPEECH:
        {
            if (m_uiSpeechTimer < uiDiff)
            {
                m_uiSpeechTimer = 5000;
                ++m_uiSpeechCount;

                switch(m_uiSpeechCount)
                {
                case 1:
                    DoScriptText(SAY_SPEECH_2, m_creature);
                    break;
                case 2:
                    DoScriptText(SAY_SPEECH_3, m_creature);
                    break;
                case 3:
                    DoScriptText(SAY_SPEECH_4, m_creature);
                    break;
                case 4:
                    m_uiPhase = PHASE_BALCONY;
                    break;
                }
            }
            else
                m_uiSpeechTimer -= uiDiff;

            break;
        }
        case PHASE_BALCONY:
        {
            if (m_uiSummonTimer < uiDiff)
            {
                if (m_uiSummonCount >= MAX_WAVES)
                {
                    DoScriptText(SAY_TELEPORT, m_creature);
                    DoScriptText(EMOTE_TO_FRAY, m_creature);
                    DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT);
                    m_uiPhase = PHASE_GROUND;
                    return;
                }

                // npc, npc, npc, timer
                static uint32 const auiSummonData[MAX_WAVES][4] =
                {
                    {NPC_UNREL_TRAINEE, 0, 0, 20000},
                    {NPC_UNREL_TRAINEE, 0, 0, 20000},
                    {NPC_UNREL_TRAINEE, 0, 0, 10000},
                    {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000},
                    {NPC_UNREL_TRAINEE, 0, 0, 15000},
                    {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000},
                    {NPC_UNREL_TRAINEE, 0, 0, 15000},
                    {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 0, 10000},
                    {NPC_UNREL_RIDER, 0, 0, 10000},
                    {NPC_UNREL_TRAINEE, 0, 0, 5000},
                    {NPC_UNREL_DEATH_KNIGHT, 0, 0, 15000},
                    {NPC_UNREL_TRAINEE, NPC_UNREL_RIDER, 0, 10000},
                    {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_DEATH_KNIGHT, 0, 10000},
                    {NPC_UNREL_TRAINEE, 0, 0, 10000},
                    {NPC_UNREL_RIDER, 0, 0, 5000},
                    {NPC_UNREL_DEATH_KNIGHT, 0, 0, 5000},
                    {NPC_UNREL_TRAINEE, 0, 0, 20000},
                    {NPC_UNREL_RIDER, NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 15000},
                    {NPC_UNREL_TRAINEE, 0, 0, 30000},
                };

                SummonAdds(true, auiSummonData[m_uiSummonCount][0]);

                if (auiSummonData[m_uiSummonCount][1])
                    SummonAdds(true, auiSummonData[m_uiSummonCount][1]);

                if (auiSummonData[m_uiSummonCount][2])
                    SummonAdds(true, auiSummonData[m_uiSummonCount][2]);

                m_uiSummonTimer = auiSummonData[m_uiSummonCount][3];

                ++m_uiSummonCount;
            }
            else
                m_uiSummonTimer -= uiDiff;

            break;
        }
        case PHASE_GROUND:
        case PHASE_END:
        {
            if (m_uiPhase == PHASE_GROUND)
            {
                if (m_creature->GetHealthPercent() < 30.0f)
                {
                    if (m_pInstance->IsInRightSideGothArea(m_creature))
                    {
                        DoScriptText(EMOTE_GATE, m_creature);
                        m_pInstance->SetData(TYPE_GOTHIK, SPECIAL);
                        m_uiPhase = PHASE_END;
                        m_uiShadowboltTimer = 2000;
                        return;
                    }
                }

                if (m_uiTeleportTimer < uiDiff)
                {
                    uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT;

                    if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK)
                    {
                        DoResetThreat();
                        m_uiTeleportTimer = 15000;
                        m_uiShadowboltTimer = 2000;
                        return;
                    }
                }
                else
                    m_uiTeleportTimer -= uiDiff;
            }

            if (m_uiShadowboltTimer < uiDiff)
            {
                if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ?  SPELL_SHADOWBOLT: SPELL_SHADOWBOLT_H) == CAST_OK)
                    m_uiShadowboltTimer = 1500;
            }
            else
                m_uiShadowboltTimer -= uiDiff;

            DoMeleeAttackIfReady();                     // possibly no melee at all
            break;
        }
        }
    }