void instance_blackrock_depths::Update(uint32 uiDiff)
{
    if (m_uiDwarfFightTimer)
    {
        if (m_uiDwarfFightTimer <= uiDiff)
        {
            if (m_uiDwarfRound < MAX_DWARFS)
            {
                DoCallNextDwarf();
                m_uiDwarfFightTimer = 30000;
            }
            else
                m_uiDwarfFightTimer = 0;
        }
        else
            m_uiDwarfFightTimer -= uiDiff;
    }

    if (m_uiDagranTimer)
    {
        if (m_uiDagranTimer <= uiDiff)
            m_uiDagranTimer = 0;
        else
            m_uiDagranTimer -= uiDiff;
    }

    // Every second some of the patrons will do one random emote if they are not hostile (i.e. Plugger event is not done/in progress)
    if (m_uiPatronEmoteTimer)
    {
        if (m_uiPatronEmoteTimer <= uiDiff)
        {
            HandleBarPatrons(PATRON_EMOTE);
            m_uiPatronEmoteTimer = 1000;
        }
        else
            m_uiPatronEmoteTimer -= uiDiff;
    }

    if (m_uiPatrolTimer)
    {
        if (m_uiPatrolTimer <= uiDiff)
        {
            switch(GetData(TYPE_BAR))
            {
                case IN_PROGRESS:
                    HandleBarPatrol(1);
                    break;
                case SPECIAL:
                    HandleBarPatrol(2);
                    break;
                default:
                    break;
            }
        }
        else
            m_uiPatrolTimer -= uiDiff;
    }
}
void instance_blackrock_depths::OnCreatureDeath(Creature* pCreature)
{
    switch (pCreature->GetEntry())
    {
        case NPC_WARBRINGER_CONST:
        case NPC_WATCHER_DOOMGRIP:
            if (GetData(TYPE_VAULT) == IN_PROGRESS)
            {
                m_sVaultNpcGuids.erase(pCreature->GetObjectGuid());

                // If all event npcs dead then set event to done
                if (m_sVaultNpcGuids.empty())
                {
                    SetData(TYPE_VAULT, DONE);
                }
            }
            break;
        case NPC_OGRABISI:
        case NPC_SHILL:
        case NPC_CREST:
        case NPC_JAZ:
            if (GetData(TYPE_QUEST_JAIL_BREAK) == IN_PROGRESS)
            {
                SetData(TYPE_QUEST_JAIL_BREAK, SPECIAL);
            }
            break;
            // Handle Tomb of the Seven dwarf death event
        case NPC_HATEREL:
        case NPC_ANGERREL:
        case NPC_VILEREL:
        case NPC_GLOOMREL:
        case NPC_SEETHREL:
        case NPC_DOPEREL:
            // Only handle the event when event is in progress
            if (GetData(TYPE_TOMB_OF_SEVEN) != IN_PROGRESS)
            {
                return;
            }
            // Call the next dwarf only if it's the last one which joined the fight
            if (pCreature->GetEntry() == aTombDwarfes[m_uiDwarfRound - 1])
            {
                DoCallNextDwarf();
            }
            break;
        case NPC_DOOMREL:
            SetData(TYPE_TOMB_OF_SEVEN, DONE);
            break;
        case NPC_MAGMUS:
            SetData(TYPE_IRON_HALL, DONE);
            break;
    }
}
void instance_blackrock_depths::Update(uint32 uiDiff)
{
    if (m_uiDwarfFightTimer)
    {
        if (m_uiDwarfFightTimer <= uiDiff)
        {
            if (m_uiDwarfRound < MAX_DWARFS)
            {
                DoCallNextDwarf();
                m_uiDwarfFightTimer = 30000;
            }
            else
                m_uiDwarfFightTimer = 0;
        }
        else
            m_uiDwarfFightTimer -= uiDiff;
    }
}
void instance_blackrock_depths::SetData(uint32 uiType, uint32 uiData)
{
    switch (uiType)
    {
        case TYPE_RING_OF_LAW:
            // If finished the arena event after theldren fight
            if (uiData == DONE && m_auiEncounter[0] == SPECIAL)
            {
                DoRespawnGameObject(GO_ARENA_SPOILS, HOUR);
            }
            m_auiEncounter[0] = uiData;
            break;
        case TYPE_VAULT:
            if (uiData == SPECIAL)
            {
                ++m_uiCofferDoorsOpened;

                if (m_uiCofferDoorsOpened == MAX_RELIC_DOORS)
                {
                    SetData(TYPE_VAULT, IN_PROGRESS);

                    Creature* pConstruct = NULL;

                    // Activate vault constructs
                    for (GuidSet::const_iterator itr = m_sVaultNpcGuids.begin(); itr != m_sVaultNpcGuids.end(); ++itr)
                    {
                        pConstruct = instance->GetCreature(*itr);
                        if (pConstruct)
                        {
                            pConstruct->RemoveAurasDueToSpell(SPELL_STONED);
                        }
                    }

                    if (!pConstruct)
                    {
                        return;
                    }

                    // Summon doomgrip
                    pConstruct->SummonCreature(NPC_WATCHER_DOOMGRIP, aVaultPositions[0], aVaultPositions[1], aVaultPositions[2], aVaultPositions[3], TEMPSUMMON_DEAD_DESPAWN, 0);
                }
                // No need to store in this case
                return;
            }
            if (uiData == DONE)
            {
                DoUseDoorOrButton(GO_SECRET_DOOR);
            }
            m_auiEncounter[1] = uiData;
            break;
        case TYPE_BAR:
            if (uiData == SPECIAL)
            {
                ++m_uiBarAleCount;
            }
            else
            {
                m_auiEncounter[2] = uiData;
            }
            break;
        case TYPE_TOMB_OF_SEVEN:
            // Don't set the same data twice
            if (uiData == m_auiEncounter[3])
            {
                break;
            }
            // Combat door
            DoUseDoorOrButton(GO_TOMB_ENTER);
            // Start the event
            if (uiData == IN_PROGRESS)
            {
                DoCallNextDwarf();
            }
            if (uiData == FAIL)
            {
                // Reset dwarfes
                for (uint8 i = 0; i < MAX_DWARFS; ++i)
                {
                    if (Creature* pDwarf = GetSingleCreatureFromStorage(aTombDwarfes[i]))
                    {
                        if (!pDwarf->IsAlive())
                        {
                            pDwarf->Respawn();
                        }
                    }
                }

                m_uiDwarfRound = 0;
                m_uiDwarfFightTimer = 0;
            }
            if (uiData == DONE)
            {
                DoRespawnGameObject(GO_CHEST_SEVEN, HOUR);
                DoUseDoorOrButton(GO_TOMB_EXIT);
            }
            m_auiEncounter[3] = uiData;
            break;
        case TYPE_LYCEUM:
            if (uiData == DONE)
            {
                DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                DoUseDoorOrButton(GO_GOLEM_ROOM_S);
            }
            m_auiEncounter[4] = uiData;
            break;
        case TYPE_IRON_HALL:
            switch (uiData)
            {
                case IN_PROGRESS:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    break;
                case FAIL:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    break;
                case DONE:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    DoUseDoorOrButton(GO_THRONE_ROOM);
                    break;
            }
            m_auiEncounter[5] = uiData;
            break;
        case TYPE_QUEST_JAIL_BREAK:
            m_auiEncounter[6] = uiData;
            return;
    }

    if (uiData == DONE)
    {
        OUT_SAVE_INST_DATA;

        std::ostringstream saveStream;
        saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
                   << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6];

        m_strInstData = saveStream.str();

        SaveToDB();
        OUT_SAVE_INST_DATA_COMPLETE;
    }
}
void instance_blackrock_depths::OnCreatureDeath(Creature* pCreature)
{
    switch (pCreature->GetEntry())
    {
        case NPC_WARBRINGER_CONST:
        case NPC_WATCHER_DOOMGRIP:
            if (GetData(TYPE_VAULT) == IN_PROGRESS)
            {
                m_sVaultNpcGuids.erase(pCreature->GetObjectGuid());

                // If all event npcs dead then set event to done
                if (m_sVaultNpcGuids.empty())
                    SetData(TYPE_VAULT, DONE);
            }
            break;
        case NPC_OGRABISI:
        case NPC_SHILL:
        case NPC_CREST:
        case NPC_JAZ:
            if (GetData(TYPE_QUEST_JAIL_BREAK) == IN_PROGRESS)
                SetData(TYPE_QUEST_JAIL_BREAK, SPECIAL);
            break;
            // Handle Tomb of the Seven dwarf death event
        case NPC_HATEREL:
        case NPC_ANGERREL:
        case NPC_VILEREL:
        case NPC_GLOOMREL:
        case NPC_SEETHREL:
        case NPC_DOPEREL:
            // Only handle the event when event is in progress
            if (GetData(TYPE_TOMB_OF_SEVEN) != IN_PROGRESS)
                return;
            // Call the next dwarf only if it's the last one which joined the fight
            if (pCreature->GetEntry() == aTombDwarfes[m_uiDwarfRound - 1])
                DoCallNextDwarf();
            break;
        case NPC_DOOMREL:
            SetData(TYPE_TOMB_OF_SEVEN, DONE);
            break;
        case NPC_MAGMUS:
            SetData(TYPE_IRON_HALL, DONE);
            break;
        case NPC_HURLEY_BLACKBREATH:
            SetData(TYPE_HURLEY, DONE);
            break;
        case NPC_RIBBLY_SCREWSPIGGOT:
            // Do nothing if the patrol was already spawned or is about to:
            // Plugger has made the bar hostile
            if (GetData(TYPE_BAR) == IN_PROGRESS || GetData(TYPE_PLUGGER) == IN_PROGRESS || GetData(TYPE_BAR) == DONE || GetData(TYPE_PLUGGER) == DONE)
                return;
            else
                SetData(TYPE_BAR, IN_PROGRESS);
            break;
        case NPC_SHADOWFORGE_SENATOR:
            // Emperor Dagran Thaurissan performs a random yell upon the death
            // of Shadowforge Senators in the Throne Room
            if (Creature* pDagran = GetSingleCreatureFromStorage(NPC_EMPEROR))
            {
                uint32 uiTextId;

                if (!pDagran->isAlive())
                    return;

                if (m_uiDagranTimer > 0)
                    return;

                switch (urand(0, 3))
                {
                    case 0: uiTextId = YELL_SENATOR_1; break;
                    case 1: uiTextId = YELL_SENATOR_2; break;
                    case 2: uiTextId = YELL_SENATOR_3; break;
                    case 3: uiTextId = YELL_SENATOR_4; break;
                }
                DoScriptText(uiTextId, pDagran);
                m_uiDagranTimer = 30000;    // set a timer of 30 sec to avoid Emperor Thaurissan to spam yells in case many senators are killed in a short amount of time
            }
            break;
    }
}
void instance_blackrock_depths::SetData(uint32 uiType, uint32 uiData)
{
    switch (uiType)
    {
        case TYPE_RING_OF_LAW:
            // If finished the arena event after theldren fight
            if (uiData == DONE && m_auiEncounter[0] == SPECIAL)
                DoRespawnGameObject(GO_ARENA_SPOILS, HOUR);
            else if (uiData == DONE)
            {
                for (GuidSet::const_iterator itr = m_sArenaCrowdNpcGuids.begin(); itr != m_sArenaCrowdNpcGuids.end(); ++itr)
                {
                    if (Creature* pSpectator = instance->GetCreature(*itr))
                        pSpectator->SetFactionTemporary(FACTION_ARENA_NEUTRAL, TEMPFACTION_RESTORE_RESPAWN);
                }
            }
            m_auiEncounter[0] = uiData;
            break;
        case TYPE_VAULT:
            if (uiData == SPECIAL)
            {
                ++m_uiCofferDoorsOpened;

                if (m_uiCofferDoorsOpened == MAX_RELIC_DOORS)
                {
                    SetData(TYPE_VAULT, IN_PROGRESS);

                    Creature* pConstruct = NULL;

                    // Activate vault constructs
                    for (GuidSet::const_iterator itr = m_sVaultNpcGuids.begin(); itr != m_sVaultNpcGuids.end(); ++itr)
                    {
                        pConstruct = instance->GetCreature(*itr);
                        if (pConstruct)
                            pConstruct->RemoveAurasDueToSpell(SPELL_STONED);
                    }

                    if (!pConstruct)
                        return;

                    // Summon doomgrip
                    pConstruct->SummonCreature(NPC_WATCHER_DOOMGRIP, aVaultPositions[0], aVaultPositions[1], aVaultPositions[2], aVaultPositions[3], TEMPSPAWN_DEAD_DESPAWN, 0);
                }
                // No need to store in this case
                return;
            }
            if (uiData == DONE)
            {
                DoUseDoorOrButton(GO_SECRET_DOOR);
                DoToggleGameObjectFlags(GO_SECRET_SAFE, GO_FLAG_NO_INTERACT, false);
            }
            m_auiEncounter[1] = uiData;
            break;
        case TYPE_ROCKNOT:
            if (uiData == SPECIAL)
                ++m_uiBarAleCount;
            else
            {
                if (uiData == DONE)
                {
                    HandleBarPatrons(PATRON_PISSED);
                    SetBarDoorIsOpen();
                }
                m_auiEncounter[2] = uiData;
            }
            break;
        case TYPE_TOMB_OF_SEVEN:
            // Don't set the same data twice
            if (uiData == m_auiEncounter[3])
                break;
            // Combat door
            DoUseDoorOrButton(GO_TOMB_ENTER);
            // Start the event
            if (uiData == IN_PROGRESS)
                DoCallNextDwarf();
            if (uiData == FAIL)
            {
                // Reset dwarfes
                for (uint8 i = 0; i < MAX_DWARFS; ++i)
                {
                    if (Creature* pDwarf = GetSingleCreatureFromStorage(aTombDwarfes[i]))
                    {
                        if (!pDwarf->isAlive())
                            pDwarf->Respawn();
                    }
                }

                m_uiDwarfRound = 0;
                m_uiDwarfFightTimer = 0;
            }
            if (uiData == DONE)
            {
                DoRespawnGameObject(GO_CHEST_SEVEN, HOUR);
                DoUseDoorOrButton(GO_TOMB_EXIT);
            }
            m_auiEncounter[3] = uiData;
            break;
        case TYPE_LYCEUM:
            if (uiData == DONE)
            {
                DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                DoUseDoorOrButton(GO_GOLEM_ROOM_S);
            }
            m_auiEncounter[4] = uiData;
            break;
        case TYPE_IRON_HALL:
            switch (uiData)
            {
                case IN_PROGRESS:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    break;
                case FAIL:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    break;
                case DONE:
                    DoUseDoorOrButton(GO_GOLEM_ROOM_N);
                    DoUseDoorOrButton(GO_GOLEM_ROOM_S);
                    DoUseDoorOrButton(GO_THRONE_ROOM);
                    break;
            }
            m_auiEncounter[5] = uiData;
            break;
        case TYPE_QUEST_JAIL_BREAK:
            m_auiEncounter[6] = uiData;
            return;
        case TYPE_FLAMELASH:
            for (int i = 0; i < MAX_DWARF_RUNES; ++i)
                DoUseDoorOrButton(GO_DWARFRUNE_A01 + i);
            return;
        case TYPE_HURLEY:
            if (uiData == SPECIAL)
            {
                ++m_uiBrokenKegs;

                if (m_uiBrokenKegs == 3)
                {
                    if (Creature* pPlugger = GetSingleCreatureFromStorage(NPC_PLUGGER_SPAZZRING))
                    {
                        // Summon Hurley Blackbreath
                        Creature* pHurley = pPlugger->SummonCreature(NPC_HURLEY_BLACKBREATH, aHurleyPositions[0], aHurleyPositions[1], aHurleyPositions[2], aHurleyPositions[3], TEMPSPAWN_DEAD_DESPAWN, 0);

                        if (!pHurley)
                            return;

                        // Summon cronies around Hurley
                        for (uint8 i = 0; i < MAX_CRONIES; ++i)
                        {
                            float fX, fY, fZ;
                            pPlugger->GetRandomPoint(aHurleyPositions[0], aHurleyPositions[1], aHurleyPositions[2], 2.0f, fX, fY, fZ);
                            if (Creature* pSummoned = pPlugger->SummonCreature(NPC_BLACKBREATH_CRONY, fX, fY, fZ, aHurleyPositions[3], TEMPSPAWN_DEAD_DESPAWN, 0))
                            {
                                pSummoned->SetWalk(false);
                                // The cronies should not engage anyone until their boss does so
                                // the linking is done by DB
                                pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
                                // The movement toward the kegs is handled by Hurley EscortAI
                                // and we want the cronies to follow him there
                                pSummoned->GetMotionMaster()->MoveFollow(pHurley, 1.0f, 0);
                            }
                        }
                        SetData(TYPE_HURLEY, IN_PROGRESS);
                    }
                }
            }
            else
                m_auiEncounter[8] = uiData;
            break;
        case TYPE_BRIDGE:
            m_auiEncounter[9] = uiData;
            return;
        case TYPE_BAR:
            if (uiData == IN_PROGRESS)
                HandleBarPatrol(0);
            m_auiEncounter[10] = uiData;
            break;
        case TYPE_PLUGGER:
            if (uiData == SPECIAL)
            {
                if (Creature* pPlugger = GetSingleCreatureFromStorage(NPC_PLUGGER_SPAZZRING))
                {
                    ++m_uiStolenAles;
                    if (m_uiStolenAles == 3)
                        uiData = IN_PROGRESS;
                }
            }
            m_auiEncounter[11] = uiData;
            break;
        case TYPE_NAGMARA:
            m_auiEncounter[12] = uiData;
            break;
    }

    if (uiData == DONE)
    {
        OUT_SAVE_INST_DATA;

        std::ostringstream saveStream;
        saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
                   << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " "
                   << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " "
                   << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " "
                   << m_auiEncounter[12];

        m_strInstData = saveStream.str();

        SaveToDB();
        OUT_SAVE_INST_DATA_COMPLETE;
    }
}