void Aggro(Unit* pWho) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_KRICK, IN_PROGRESS);

            // Say aggro and also put Krick in combat
            if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
            {
                DoScriptText(SAY_AGGRO, pKrick);
                pKrick->AI()->AttackStart(pWho);
            }
        }
    }
    void JustDied(Unit* pKiller) override
    {
        DoScriptText(SAY_DEATH, m_creature, pKiller);

        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_GARFROST, DONE);

            // Summon Ironskull or Victus for outro
            m_creature->SummonCreature(m_pInstance->GetPlayerTeam() == HORDE ? NPC_IRONSKULL_PART1 : NPC_VICTUS_PART1,
                                       afOutroNpcSpawnLoc[0], afOutroNpcSpawnLoc[1], afOutroNpcSpawnLoc[2], afOutroNpcSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);

            // ToDo: handle the other npcs movement
        }
    }
    void Aggro(Unit* pWho) override
    {
        DoScriptText(SAY_AGGRO, m_creature, pWho);
        DoCastSpellIfCan(m_creature, SPELL_PERMAFROST);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_GARFROST, IN_PROGRESS);
    }
 void KilledUnit(Unit* /*pVictim*/)
 {
     if (m_pInstance)
     {
         if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
             DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, pKrick);
     }
 }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_KRICK, DONE);

            if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
            {
                DoScriptText(SAY_OUTRO_1, pKrick);
                pKrick->AI()->EnterEvadeMode();

                // Summon Jaina or Sylvanas for epilogue
                pKrick->SummonCreature(m_pInstance->GetPlayerTeam() == HORDE ? NPC_SYLVANAS_PART1 : NPC_JAINA_PART1,
                                       afOutroNpcSpawnLoc[0], afOutroNpcSpawnLoc[1], afOutroNpcSpawnLoc[2], afOutroNpcSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
            }

            if (Creature* pTyrannus = m_pInstance->GetSingleCreatureFromStorage(NPC_TYRANNUS_INTRO))
                pTyrannus->NearTeleportTo(afTyrannusTeleLoc[0], afTyrannusTeleLoc[1], afTyrannusTeleLoc[2], afTyrannusTeleLoc[3]);
        }
    }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // This needs to be checked only on heroic
        if (!m_bIsRegularMode && m_uiCheckPermafrostTimer)
        {
            if (m_uiCheckPermafrostTimer <= uiDiff)
            {
                ThreatList playerList = m_creature->getThreatManager().getThreatList();
                for (ThreatList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
                {
                    if (Player* pTarget = m_creature->GetMap()->GetPlayer((*itr)->getUnitGuid()))
                    {
                        Aura* pAuraIntenseCold = pTarget->GetAura(SPELL_PERMAFROST_AURA_H, EFFECT_INDEX_2);

                        if (pAuraIntenseCold)
                        {
                            if (pAuraIntenseCold->GetStackAmount() > MAX_PERMAFROST_STACK)
                            {
                                if (m_pInstance)
                                    m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_DOESNT_GO_ELEVEN, false);

                                m_uiCheckPermafrostTimer = 0;
                                return;
                            }
                        }
                    }
                }
                m_uiCheckPermafrostTimer = 1000;
            }
            else
                m_uiCheckPermafrostTimer -= uiDiff;
        }

        // Do nothing more while moving
        if (m_uiPhase == PHASE_MOVEMENT)
            return;

        // Casted in every phase
        if (m_uiThrowSaroniteTimer < uiDiff)
        {
            // TODO - only target players?
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (DoCastSpellIfCan(pTarget, SPELL_THROW_SARONITE) == CAST_OK)
                {
                    DoScriptText(EMOTE_THROW_SARONITE, m_creature, pTarget);
                    m_uiThrowSaroniteTimer = 16000;
                }
            }
        }
        else
            m_uiThrowSaroniteTimer -= uiDiff;

        switch (m_uiPhase)
        {
            case PHASE_NO_ENCHANTMENT:
            {
                if (m_creature->GetHealthPercent() < 66.0f)
                {
                    DoCastSpellIfCan(m_creature, SPELL_THUNDERING_STOMP, CAST_INTERRUPT_PREVIOUS);
                    SetCombatMovement(false);

                    m_creature->GetMotionMaster()->MoveJump(aGarfrostMoveLocs[0][0], aGarfrostMoveLocs[0][1], aGarfrostMoveLocs[0][2], 3 * m_creature->GetSpeed(MOVE_RUN), 10.0f, PHASE_BLADE_ENCHANTMENT);
                    m_uiPhase = PHASE_MOVEMENT;

                    // Stop further action
                    return;
                }
                break;
            }
            case PHASE_BLADE_ENCHANTMENT:
            {
                if (m_creature->GetHealthPercent() < 33.0f)
                {
                    DoCastSpellIfCan(m_creature, SPELL_THUNDERING_STOMP, CAST_INTERRUPT_PREVIOUS);
                    SetCombatMovement(false);

                    m_creature->GetMotionMaster()->MoveJump(aGarfrostMoveLocs[1][0], aGarfrostMoveLocs[1][1], aGarfrostMoveLocs[1][2], 3 * m_creature->GetSpeed(MOVE_RUN), 10.0f, PHASE_MACE_ENCHANTMENT);
                    m_uiPhase = PHASE_MOVEMENT;

                    // Stop further action
                    return;
                }

                if (m_uiChillingWaveTimer < uiDiff)
                {
                    if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CHILLING_WAVE) == CAST_OK)
                        m_uiChillingWaveTimer = 14000;
                }
                else
                    m_uiChillingWaveTimer -= uiDiff;

                break;
            }
            case PHASE_MACE_ENCHANTMENT:
            {
                if (m_uiDeepFreezeTimer < uiDiff)
                {
                    if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
                    {
                        if (DoCastSpellIfCan(pTarget, SPELL_DEEP_FREEZE) == CAST_OK)
                        {
                            DoScriptText(EMOTE_DEEP_FREEZE, m_creature, pTarget);
                            m_uiDeepFreezeTimer = 20000;
                        }
                    }
                }
                else
                    m_uiDeepFreezeTimer -= uiDiff;

                break;
            }
        }

        DoMeleeAttackIfReady();
    }
 void JustReachedHome() override
 {
     if (m_pInstance)
         m_pInstance->SetData(TYPE_GARFROST, FAIL);
 }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_pInstance)
            return;

        // He needs to be mounted manually, not by vehicle_accessories
        if (m_uiMountTimer)
        {
            if (m_uiMountTimer <= uiDiff)
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                    pKrick->CastSpell(m_creature, SPELL_RIDE_VEHICLE_HARDCODED, TRIGGERED_OLD_TRIGGERED);

                m_uiMountTimer = 0;
            }
            else
                m_uiMountTimer -= uiDiff;
        }

        if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
            return;

        // Cooldown timer - we need to block all Krick spell during some events
        if (m_uiCooldownTimer)
        {
            if (m_uiCooldownTimer <= uiDiff)
                m_uiCooldownTimer = 0;
            else
                m_uiCooldownTimer -= uiDiff;

            return;
        }

        if (m_uiPoisonNovaTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_POISON_NOVA) == CAST_OK)
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                {
                    DoScriptText(SAY_ORDER_BLOW, pKrick);
                    DoScriptText(EMOTE_ICK_POISON, pKrick);
                }

                m_uiCooldownTimer = 5000;
                m_uiPoisonNovaTimer = urand(20000, 25000);
            }
        }
        else
            m_uiPoisonNovaTimer -= uiDiff;

        if (m_uiPursueTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_PURSUIT) == CAST_OK)
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                {
                    switch (urand(0, 2))
                    {
                        case 0: DoScriptText(SAY_TARGET_1, pKrick); break;
                        case 1: DoScriptText(SAY_TARGET_2, pKrick); break;
                        case 2: DoScriptText(SAY_TARGET_3, pKrick); break;
                    }
                }

                m_uiCooldownTimer = 17000;
                m_uiPursueTimer = urand(50000, 70000);
            }
        }
        else
            m_uiPursueTimer -= uiDiff;

        if (m_uiMightKickTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTY_KICK) == CAST_OK)
                m_uiMightKickTimer = 10000;
        }
        else
            m_uiMightKickTimer -= uiDiff;

        if (m_uiToxicWasteTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                    pKrick->CastSpell(pTarget, SPELL_TOXIC_WASTE, TRIGGERED_OLD_TRIGGERED);

                m_uiToxicWasteTimer = urand(3000, 5000);
            }
        }
        else
            m_uiToxicWasteTimer -= uiDiff;

        if (m_uiShadowboltTimer < uiDiff)
        {
            if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                    pKrick->CastSpell(pTarget, SPELL_SHADOW_BOLT, TRIGGERED_OLD_TRIGGERED);

                m_uiShadowboltTimer = urand(4000, 8000);
            }
        }
        else
            m_uiShadowboltTimer -= uiDiff;

        if (m_uiExplosivBarrageTimer < uiDiff)
        {
            if (DoCastSpellIfCan(m_creature, SPELL_EXPLOSIVE_BARRAGE_ICK) == CAST_OK)
            {
                if (Creature* pKrick = m_pInstance->GetSingleCreatureFromStorage(NPC_KRICK))
                {
                    pKrick->CastSpell(pKrick, SPELL_EXPLOSIVE_BARRAGE_KRICK, TRIGGERED_OLD_TRIGGERED);

                    DoScriptText(SAY_ORDER_STOP, pKrick);
                    DoScriptText(EMOTE_KRICK_MINES, pKrick);
                }

                m_uiCooldownTimer = 20000;
                m_uiExplosivBarrageTimer = urand(25000, 30000);
            }
        }
        else
            m_uiExplosivBarrageTimer -= uiDiff;

        DoMeleeAttackIfReady();
    }
 void JustReachedHome() override
 {
     if (m_pInstance)
         m_pInstance->SetData(TYPE_KRICK, FAIL);
 }