void MovementInform(uint32 uiMoveType, uint32 uiPointId) override
    {
        if (uiMoveType != POINT_MOTION_TYPE)
            return;

        if (uiPointId == POINT_ID_EVADE)
        {
            m_creature->SetFacingTo(fIntroPosition[3]);

            if (m_pInstance)
                m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, FAIL);
        }
        else if (uiPointId == POINT_ID_INTRO)
        {
            if (m_pInstance)
                m_pInstance->DoUseDoorOrButton(GO_SAURFANG_DOOR);

            // Note: this should be done only after the intro event is finished
            // ToDo: move this to the proper place after the intro will be implemented
            // Also the faction needs to be checked if it should be handled in database
            m_creature->setFaction(FACTION_ID_UNDEAD);
            m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PASSIVE);
            m_creature->SetInCombatWithZone();
        }
    }
 void JustReachedHome() override
 {
     if (m_pInstance)
     {
         m_pInstance->SetData(TYPE_LADY_DEATHWHISPER, FAIL);
         m_pInstance->SetSpecialAchievementCriteria(ACHIEVE_FULL_HOUSE, false);
     }
 }
 void JustReachedHome() override
 {
     if (m_pInstance)
     {
         m_pInstance->SetData(TYPE_MARROWGAR, FAIL);
         m_pInstance->SetSpecialAchievementCriteria(ACHIEVE_BONED, false);
     }
 }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_pInstance)
            return;

        if (m_pInstance->GetData(TYPE_PLAGUE_WING_ENTRANCE) != IN_PROGRESS)
            return;

        // random summon creatures
        if (m_uiSummonTimer)
        {
            if (m_uiSummonTimer <= uiDiff)
            {
                float fX, fY, fZ;
                uint8 uiMaxInsects = urand(MAX_INSECT_PER_ROUND * 0.5, MAX_INSECT_PER_ROUND);
                for (uint8 i = 0; i < uiMaxInsects; ++i)
                {
                    m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 15.0f, fX, fY, fZ);
                    m_creature->SummonCreature(NPC_FLESH_EATING_INSECT, fX, fY, fZ + 20.0f, 0, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, 5 * MINUTE * IN_MILLISECONDS);
                }
                m_uiSummonTimer = urand(2000, 5000);
            }
            else
                m_uiSummonTimer -= uiDiff;
        }

        // event can last max 5 min
        if (m_uiEventTimer)
        {
            if (m_uiEventTimer <= uiDiff)
            {
                bool bEventFailed = true;

                // check withing all players in map if any are still alive and in LoS
                Map::PlayerList const& pAllPlayers = m_pInstance->instance->GetPlayers();

                if (!pAllPlayers.isEmpty())
                {
                    for (Map::PlayerList::const_iterator itr = pAllPlayers.begin(); itr != pAllPlayers.end(); ++itr)
                    {
                        if (Player* pPlayer = itr->getSource())
                        {
                            if (pPlayer->isAlive() && pPlayer->IsWithinLOSInMap(m_creature))
                                bEventFailed = false;
                        }
                    }
                }

                // set event as done if there are still players around
                m_pInstance->SetData(TYPE_PLAGUE_WING_ENTRANCE, bEventFailed ? FAIL : DONE);
                m_uiSummonTimer = 0;
                m_uiEventTimer = 0;
            }
            else
                m_uiEventTimer -= uiDiff;
        }
    }
    void JustReachedHome() override
    {
        DoCastSpellIfCan(m_creature, SPELL_OOZE_FLOOD_REMOVE, CAST_TRIGGERED);

        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_ROTFACE, FAIL);

            // reset putricide
            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
                pPutricide->AI()->EnterEvadeMode();
        }
    }
    void Aggro(Unit* /*pWho*/) override
    {
        DoScriptText(SAY_AGGRO, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_SHROUD_OF_SORROW, CAST_TRIGGERED);

        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_QUEEN_LANATHEL, IN_PROGRESS);

            if (m_pInstance->IsHeroicDifficulty())
                DoCastSpellIfCan(m_creature, SPELL_PRESENCE_OF_DARKFALLEN, CAST_TRIGGERED);
        }
    }
    void Aggro(Unit* /*pWho*/) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_LADY_DEATHWHISPER, IN_PROGRESS);
            m_pInstance->SetSpecialAchievementCriteria(ACHIEVE_FULL_HOUSE, true);
        }

        // make sure that the event will not continue in the fight
        m_bIsEventFinished = true;

        DoScriptText(SAY_AGGRO, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_MANA_BARRIER, CAST_TRIGGERED);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        DoCastSpellIfCan(m_creature, SPELL_OOZE_FLOOD_REMOVE, CAST_TRIGGERED);

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

            // reset putricide
            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
                pPutricide->AI()->EnterEvadeMode();
        }

        DoScriptText(SAY_DEATH, m_creature);
    }
    void JustReachedHome() override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_SINDRAGOSA, FAIL);

        m_creature->GetMotionMaster()->MovePoint(SINDRAGOSA_POINT_AIR_EAST, SindragosaPosition[8][0], SindragosaPosition[8][1], SindragosaPosition[8][2], false);
    }
    void UpdateAI(const uint32 uiDiff) override
    {
        if (!m_bHasImpaled)
        {
            if (m_creature->IsTemporarySummon())
            {
                TemporarySummon* pTemporary = (TemporarySummon*)m_creature;

                // Impale player
                if (Player* pSummoner = m_creature->GetMap()->GetPlayer(pTemporary->GetSummonerGuid()))
                    DoCastSpellIfCan(pSummoner, SPELL_IMPALED);
            }

            m_bHasImpaled = true;
        }

        // achievement check
        if (m_bBonedFailed)
            return;

        if (m_uiImpaledTimer > 8000)
        {
            m_bBonedFailed = true;

            if (m_pInstance)
                m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_BONED, false);
        }

        m_uiImpaledTimer += uiDiff;
    }
    void Aggro(Unit* /*pWho*/) override
    {
        DoScriptText(SAY_AGGRO, m_creature);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_MARROWGAR, IN_PROGRESS);
    }
    void JustReachedHome() override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_FESTERGUT, FAIL);

            // reset gas stalker and putricide
            if (Creature* pStalker = m_pInstance->GetSingleCreatureFromStorage(NPC_GAS_STALKER))
                pStalker->RemoveAllAurasOnEvade();

            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
                pPutricide->AI()->EnterEvadeMode();
        }

        DoCastSpellIfCan(m_creature, SPELL_REMOVE_INOCULENT, CAST_TRIGGERED);
    }
    void JustReachedHome() override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_ROTFACE, FAIL);

        DoCastSpellIfCan(m_creature, SPELL_OOZE_FLOOD_REMOVE, CAST_TRIGGERED);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_ROTFACE, DONE);

        DoScriptText(SAY_DEATH, m_creature);
    }
    void JustReachedHome() override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_FESTERGUT, FAIL);

        DoCastSpellIfCan(m_creature, SPELL_REMOVE_INOCULENT, CAST_TRIGGERED);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        DoScriptText(SAY_DEATH, m_creature);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_MARROWGAR, DONE);
    }
    void Aggro(Unit* /*pWho*/) override
    {
        DoScriptText(SAY_AGGRO, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_BLOOD_POWER, CAST_TRIGGERED);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, IN_PROGRESS);
    }
    void Aggro(Unit* /*pWho*/) override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS);

        DoScriptText(SAY_AGGRO, m_creature);
        m_uiPhase = PHASE_ONE;
    }
    void JustReachedHome() override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, FAIL);

        DoCastSpellIfCan(m_creature, SPELL_REMOVE_MARKS, CAST_TRIGGERED);
        m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_FESTERGUT, DONE);

        DoScriptText(SAY_DEATH, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_REMOVE_INOCULENT, CAST_TRIGGERED);
    }
    void Aggro(Unit* /*pWho*/) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, IN_PROGRESS);
            m_pInstance->SetSpecialAchievementCriteria(ACHIEVE_IVE_GONE_AND_MADE_A_MESS, true);
            m_iMarkOfFallenCount = 0;
        }

        DoScriptText(SAY_AGGRO, m_creature);

        SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED);

        DoCastSpellIfCan(m_creature, SPELL_BLOOD_POWER, CAST_TRIGGERED);
        DoCastSpellIfCan(m_creature, SPELL_RUNE_OF_BLOOD, CAST_TRIGGERED);
        DoCastSpellIfCan(m_creature, SPELL_MARK_OF_FALLEN_CHAMPION, CAST_TRIGGERED);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        DoScriptText(SAY_DEATH, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_REMOVE_MARKS, CAST_TRIGGERED);

        if (m_pInstance)
            m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, DONE);
    }
    void Aggro(Unit* /*pWho*/) override
    {
        DoScriptText(SAY_AGGRO, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_GASTRIC_BLOAT, CAST_TRIGGERED);

        // set encounter in progress and get professor to the balcony
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_FESTERGUT, IN_PROGRESS);

            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
            {
                pPutricide->SetWalk(false);
                pPutricide->GetMotionMaster()->MovePoint(101, afBalconyLocation[0], afBalconyLocation[1], afBalconyLocation[2]);
            }
        }
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_FESTERGUT, DONE);

            // reset gas stalker and putricide
            if (Creature* pStalker = m_pInstance->GetSingleCreatureFromStorage(NPC_GAS_STALKER))
                pStalker->RemoveAllAurasOnEvade();

            // ToDo: research if there is any event/yell happening on boss death
            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
                pPutricide->AI()->EnterEvadeMode();
        }

        DoScriptText(SAY_DEATH, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_REMOVE_INOCULENT, CAST_TRIGGERED);
    }
    void Aggro(Unit* /*pWho*/) override
    {
        if (!m_pInstance)
            return;

        m_creature->SetInCombatWithZone();
        m_pInstance->SetData(TYPE_MARROWGAR, IN_PROGRESS);
        DoScriptText(SAY_AGGRO, m_creature);
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_LICH_KING, DONE);

        DoScriptText(SAY_OUTRO_14, m_creature);

        // TODO: finish event, after around 8 seconds play cinematic
    }
    void ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker, uint32 uiMiscValue) override
    {
        if (eventType == AI_EVENT_CUSTOM_A)
        {
            // prepare explosion; Rotface yells and achiev is failed
            if (DoCastSpellIfCan(m_creature, SPELL_UNSTABLE_EXPLOSION) == CAST_OK)
            {
                if (m_pInstance)
                {
                    if (Creature* pRotface = m_pInstance->GetSingleCreatureFromStorage(NPC_ROTFACE))
                        DoScriptText(SAY_OOZE_EXPLODE, pRotface);

                    m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_DANCES_OOZES, false);
                }

                m_uiUnstableExplosionTimer = 5000;
            }
        }
    }
    void Aggro(Unit* /*pWho*/) override
    {
        if (m_pInstance)
            m_pInstance->SetData(TYPE_ROTFACE, IN_PROGRESS);

        DoScriptText(SAY_AGGRO, m_creature);

        DoCastSpellIfCan(m_creature, SPELL_MUTATED_INFECTION_1, CAST_TRIGGERED);
        DoCastSpellIfCan(m_creature, SPELL_OOZE_FLOOD_PERIODIC, CAST_TRIGGERED);
    }
    void JustSummoned(Creature* pSummoned) override
    {
        if (pSummoned->GetEntry() == NPC_MALLEABLE_OOZE_STALKER)
        {
            if (!m_pInstance)
                return;

            if (Creature* pPutricide = m_pInstance->GetSingleCreatureFromStorage(NPC_PROFESSOR_PUTRICIDE))
                pPutricide->CastSpell(pSummoned, SPELL_MALLEABLE_GOO, true);
        }
    }
    void JustDied(Unit* /*pKiller*/) override
    {
        if (m_pInstance)
        {
            m_pInstance->SetData(TYPE_DEATHBRINGER_SAURFANG, DONE);
            if (m_iMarkOfFallenCount > (m_bIs25Man ? 5: 3))
                m_pInstance->SetSpecialAchievementCriteria(ACHIEVE_IVE_GONE_AND_MADE_A_MESS, false);
        }

        m_creature->CastSpell(m_creature, SPELL_ACHIEVEMENT_CREDIT, false);

        DoScriptText(SAY_DEATH, m_creature);
        DoCastSpellIfCan(m_creature, SPELL_REMOVE_MARKS, CAST_TRIGGERED);

        if (Creature* pTmp = m_creature->GetMap()->GetCreature(m_guidEventNpcGuid))
        {
            if (npc_highlord_saurfang_iccAI* pTmpAI = dynamic_cast<npc_highlord_saurfang_iccAI*>(pTmp->AI()))
                pTmpAI->DoContinueEvent();
        }
    }