text: /*
   * Copyright (C) 2008 - 2012 TrinityCore <http://www.trinitycore.org/>
   *
   * Copyright (C) 2011 - 2012 ArkCORE <http://www.arkania.net/>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
   * Free Software Foundation; either version 2 of the License, or (at your
   * option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along
   * with this program. If not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "ScriptPCH.h"
  #include "culling_of_stratholme.h"
  #include "ScriptedEscortAI.h"
  
  enum Says
  {
      //First Act - Uther and Jaina Dialog
      SAY_PHASE101                                = -1595070,  //Arthas
      SAY_PHASE102                                = -1595071,  //Uther
      SAY_PHASE103                                = -1595072,  //Arthas
      SAY_PHASE104                                = -1595073,  //Arthas
      SAY_PHASE105                                = -1595074,  //Uther
      SAY_PHASE106                                = -1595075,  //Arthas
      SAY_PHASE107                                = -1595076,  //Uther
      SAY_PHASE108                                = -1595077,  //Arthas
      SAY_PHASE109                                = -1595078,  //Arthas
      SAY_PHASE110                                = -1595079,  //Uther
      SAY_PHASE111                                = -1595080,  //Arthas
      SAY_PHASE112                                = -1595081,  //Uther
      SAY_PHASE113                                = -1595082,  //Jaina
      SAY_PHASE114                                = -1595083,  //Arthas
      SAY_PHASE115                                = -1595084,  //Uther
      SAY_PHASE116                                = -1595085,  //Arthas
      SAY_PHASE117                                = -1595086,  //Jaina
      SAY_PHASE118                                = -1595087,  //Arthas
      //Second Act - City Streets
      SAY_PHASE201                                = -1595088,  //Arthas
      SAY_PHASE202                                = -1595089,  //Cityman
      SAY_PHASE203                                = -1595090,  //Arthas
      SAY_PHASE204                                = -1595091,  //Crazyman
      SAY_PHASE205                                = -1595092,  //Arthas
      SAY_PHASE206                                = -1595009,  //Malganis
      SAY_PHASE207                                = -1595010,  //Malganis
      SAY_PHASE208                                = -1595093,  //Arthas
      SAY_PHASE209                                = -1595094,  //Arthas
      SAY_PHASE210                                = -1595095,  //Arthas
      //Third Act - Town Hall
      SAY_PHASE301                               = -1595096,  //Arthas
      SAY_PHASE302                               = -1595097,  //Drakonian
      SAY_PHASE303                               = -1595098,  //Arthas
      SAY_PHASE304                               = -1595099,  //Arthas
      SAY_PHASE305                               = -1595100,  //Drakonian
      SAY_PHASE306                               = -1595101,  //Arthas
      SAY_PHASE307                               = -1595102,  //Arthas
      SAY_PHASE308                               = -1595103,  //Arthas
      SAY_PHASE309                               = -1595104,  //Arthas
      SAY_PHASE310                               = -1595105,  //Arthas
      SAY_PHASE311                               = -1595106,  //Arthas
      SAY_PHASE312                               = -1595107,  //Arthas
      SAY_PHASE313                               = -1595108,  //Arthas
      SAY_PHASE314                               = -1595000,  //Epoch
      SAY_PHASE315                               = -1595109,  //Arthas
      //Fourth Act - Fire Corridor
      SAY_PHASE401                               = -1595110,  //Arthas
      SAY_PHASE402                               = -1595111,  //Arthas
      SAY_PHASE403                               = -1595112,  //Arthas
      SAY_PHASE404                               = -1595113,  //Arthas
      SAY_PHASE405                               = -1595114,  //Arthas
      SAY_PHASE406                               = -1595115,  //Arthas
      SAY_PHASE407                               = -1595116,  //Arthas
      //Fifth Act - Mal'Ganis Fight
      SAY_PHASE501                               = -1595117,  //Arthas
      SAY_PHASE502                               = -1595118,  //Arthas
      SAY_PHASE503                               = -1595119,  //Arthas
      SAY_PHASE504                               = -1595120,  //Arthas
  };
  
  enum NPCs
  {
      NPC_INFINITE_ADVERSARY                     = 27742,
      NPC_INFINITE_HUNTER                        = 27743,
      NPC_INFINITE_AGENT                         = 27744,
      NPC_TIME_RIFT                              = 28409,
      NPC_ZOMBIE                                 = 27737,
      NPC_GHOUL                                  = 28249,
      NPC_NECROMANCER                            = 28200,
      NPC_STALKER                                = 28199,
      NPC_FIEND                                  = 27734,
      NPC_GOLEM                                  = 28201,
      NPC_EGHOUL                                 = 27729,
      NPC_CONSTRUCT                              = 27736,
  
      NPC_INVIS_TARGET                           = 20562,
  
      NPC_KNIGHT_ESCORT                          = 27745,
      NPC_PRIEST_ESCORT                          = 27747,
      NPC_CITY_MAN                               = 28167,
      NPC_CITY_MAN2                              = 28169,
      NPC_CITY_MAN3                              = 31126,
      NPC_CITY_MAN4                              = 31127,
  };
  
  enum Spells
  {
      SPELL_FEAR                                 = 39176,
      SPELL_ARTHAS_AURA                          = 52442,
      SPELL_EXORCISM_N                           = 52445,
      SPELL_EXORCISM_H                           = 58822,
      SPELL_HOLY_LIGHT                           = 52444,
      SPELL_ARCANE_DISRUPTION                    = 49590,
  };
  
  enum GossipMenuArthas
  {
     GOSSIP_MENU_ARTHAS_1                        = 100001,
     GOSSIP_MENU_ARTHAS_2                        = 100002,
     GOSSIP_MENU_ARTHAS_3                        = 100003,
     GOSSIP_MENU_ARTHAS_4                        = 100004,
     GOSSIP_MENU_ARTHAS_5                        = 100005
  };
  
  enum EncounterData
  {
      ENCOUNTER_WAVES_NUMBER                      = 8,
      ENCOUNTER_WAVES_MAX_SPAWNS                  = 5,
      ENCOUNTER_DRACONIAN_NUMBER                  = 4,
      ENCOUNTER_CHRONO_SPAWNS                     = 19
  };
  
  // Locations for necromancers and add to spawn
  float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]=
  {
      {
          {NPC_ZOMBIE, 2164.698975f, 1255.392944f, 135.040878f, 0.490202f},
          {NPC_ZOMBIE, 2183.501465f, 1263.079102f, 134.859055f, 3.169981f},
          {NPC_GHOUL, 2177.512939f, 1247.313843f, 135.846695f, 1.696574f},
          {NPC_GHOUL, 2171.991943f, 1246.615845f, 135.745026f, 1.696574f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_GHOUL, 2254.434326f, 1163.427612f, 138.055038f, 2.077358f},
          {NPC_GHOUL, 2254.703613f, 1158.867798f, 138.212234f, 2.345532f},
          {NPC_GHOUL, 2257.615723f, 1162.310913f, 138.091202f, 2.077358f},
          {NPC_NECROMANCER, 2258.258057f, 1157.250732f, 138.272873f, 2.387766f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_STALKER, 2348.120117f, 1202.302490f, 130.491104f, 4.698538f},
          {NPC_GHOUL, 2352.863525f, 1207.819092f, 130.424271f, 4.949865f},
          {NPC_GHOUL, 2343.593750f, 1207.915039f, 130.781311f, 4.321547f},
          {NPC_NECROMANCER, 2348.257324f, 1212.202515f, 130.670135f, 4.450352f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_STALKER, 2139.825195f, 1356.277100f, 132.199615f, 5.820131f},
          {NPC_GHOUL, 2137.073486f, 1362.464844f, 132.271637f, 5.820131f},
          {NPC_GHOUL, 2134.075684f, 1354.148071f, 131.885864f, 5.820131f},
          {NPC_NECROMANCER, 2133.302246f, 1358.907837f, 132.037689f, 5.820131f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_NECROMANCER, 2264.013428f, 1174.055908f, 138.093094f, 2.860481f},
          {NPC_GHOUL, 2264.207764f, 1170.892700f, 138.034973f, 2.860481f},
          {NPC_GHOUL, 2266.948975f, 1176.898926f, 137.976929f, 2.860481f},
          {NPC_STALKER, 2269.215576f, 1170.109253f, 137.742691f, 2.860481f},
          {NPC_FIEND, 2273.106689f, 1176.101074f, 137.880508f, 2.860481f}
      },
      {
          {NPC_GOLEM, 2349.701660f, 1188.436646f, 130.428864f, 3.908642f},
          {NPC_GHOUL, 2349.909180f, 1194.582642f, 130.417816f, 3.577001f},
          {NPC_EGHOUL, 2354.662598f, 1185.692017f, 130.552032f, 3.577001f},
          {NPC_EGHOUL, 2354.716797f, 1191.614380f, 130.539810f, 3.577001f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_CONSTRUCT, 2145.212891f, 1355.288086f, 132.288773f, 6.004838f},
          {NPC_NECROMANCER, 2137.078613f, 1357.612671f, 132.173340f, 6.004838f},
          {NPC_EGHOUL, 2139.402100f, 1352.541626f, 132.127518f, 5.812850f},
          {NPC_EGHOUL, 2142.408447f, 1360.760620f, 132.321564f, 5.812850f},
          {0, 0, 0, 0, 0}
      },
      {
          {NPC_GHOUL, 2172.686279f, 1259.618164f, 134.391754f, 1.865499f},
          {NPC_FIEND, 2177.649170f, 1256.061157f, 135.096512f, 1.849572f},
          {NPC_CONSTRUCT, 2170.782959f, 1253.594849f, 134.973022f, 1.849572f},
          {NPC_NECROMANCER, 2175.595703f, 1249.041992f, 135.603531f, 1.849572f},
          {0, 0, 0, 0, 0}
      }
  };
  
  // Locations for rifts to spawn and draconians to go
  float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]=
  {
      {NPC_TIME_RIFT, 2431.790039f, 1190.670044f, 148.076004f, 0.187923f},
      {NPC_INFINITE_ADVERSARY, 2433.857910f, 1185.612061f, 148.075974f, 4.566168f},
      {NPC_INFINITE_ADVERSARY, 2437.577881f, 1188.241089f, 148.075974f, 0.196999f},
      {NPC_INFINITE_AGENT, 2437.165527f, 1192.294922f, 148.075974f, 0.169247f},
      {NPC_INFINITE_HUNTER, 2434.989990f, 1197.679565f, 148.075974f, 0.715971f},
      {NPC_TIME_RIFT, 2403.954834f, 1178.815430f, 148.075943f, 4.966126f},
      {NPC_INFINITE_AGENT, 2403.676758f, 1171.495850f, 148.075607f, 4.902797f},
      {NPC_INFINITE_HUNTER, 2407.691162f, 1172.162720f, 148.075607f, 4.963010f},
      {NPC_TIME_RIFT, 2414.217041f, 1133.446167f, 148.076050f, 1.706972f},
      {NPC_INFINITE_ADVERSARY, 2416.024658f, 1139.456177f, 148.076431f, 1.752129f},
      {NPC_INFINITE_HUNTER, 2410.866699f, 1139.680542f, 148.076431f, 1.752129f},
      {NPC_TIME_RIFT, 2433.081543f, 1099.869751f, 148.076157f, 1.809509f},
      {NPC_INFINITE_ADVERSARY, 2426.947998f, 1107.471680f, 148.076019f, 1.877580f},
      {NPC_INFINITE_HUNTER, 2432.944580f, 1108.896362f, 148.208160f, 2.199241f},
      {NPC_TIME_RIFT, 2444.077637f, 1114.366089f, 148.076157f, 3.049565f},
      {NPC_INFINITE_ADVERSARY, 2438.190674f, 1118.368164f, 148.076172f, 3.139232f},
      {NPC_INFINITE_AGENT, 2435.861328f, 1113.402954f, 148.169327f, 2.390271f},
      {NPC_TIME_RIFT, 2463.131592f, 1115.391724f, 152.473129f, 3.409651f},
      {NPC_EPOCH, 2451.809326f, 1112.901245f, 149.220459f, 3.363617f}
  };
  
  #define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme."
  #define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready."
  #define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness."
  #define GOSSIP_ITEM_ARTHAS_3 "I'm ready."
  #define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!"
  #define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire."
  
  class npc_arthas : public CreatureScript
  {
  public:
      npc_arthas() : CreatureScript("npc_arthas") { }
  
      bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
      {
          player->PlayerTalkClass->ClearMenus();
          npc_arthasAI* pAI = CAST_AI(npc_arthas::npc_arthasAI, creature->AI());
  
          if (!pAI)
              return false;
  
          switch (action)
          {
              case GOSSIP_ACTION_INFO_DEF:
                  pAI->Start(true, true, player->GetGUID(), 0, false, false);
                  pAI->SetDespawnAtEnd(false);
                  pAI->bStepping = false;
                  pAI->uiStep = 1;
                  break;
              case GOSSIP_ACTION_INFO_DEF+1:
                  pAI->bStepping = true;
                  pAI->uiStep = 24;
                  break;
              case GOSSIP_ACTION_INFO_DEF+2:
                  pAI->SetHoldState(false);
                  pAI->bStepping = false;
                  pAI->uiStep = 61;
                  break;
              case GOSSIP_ACTION_INFO_DEF+3:
                  pAI->SetHoldState(false);
                  break;
              case GOSSIP_ACTION_INFO_DEF+4:
                  pAI->bStepping = true;
                  pAI->uiStep = 84;
                  break;
              case GOSSIP_ACTION_INFO_DEF+5:
                  pAI->bStepping = true;
                  pAI->uiStep = 85;
                  break;
          }
          player->CLOSE_GOSSIP_MENU();
          pAI->SetDespawnAtFar(true);
          creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
          return true;
      }
  
      bool OnGossipHello(Player* player, Creature* creature)
      {
          npc_arthasAI* pAI = CAST_AI(npc_arthas::npc_arthasAI, creature->AI());
  
          if (pAI && pAI->bStepping == false)
          {
              switch (pAI->uiGossipStep)
              {
                  case 0: //This one is a workaround since the very beggining of the script is wrong.
                  {
                      QuestStatus status = player->GetQuestStatus(13149);
                      if (status != QUEST_STATUS_COMPLETE && status != QUEST_STATUS_REWARDED)
                          return false;
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
                      player->SEND_GOSSIP_MENU(907, creature->GetGUID());
                      break;
                  }
                  case 1:
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
                      player->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, creature->GetGUID());
                      break;
                  case 2:
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
                      player->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, creature->GetGUID());
                      break;
                  case 3:
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
                      player->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, creature->GetGUID());
                      break;
                  case 4:
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
                      player->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, creature->GetGUID());
                      break;
                  case 5:
                      player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
                      player->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, creature->GetGUID());
                      break;
                  default:
                      return false;
              }
          }
          return true;
      }
  
      CreatureAI* GetAI(Creature* creature) const
      {
          return new npc_arthasAI(creature);
      }
  
      struct npc_arthasAI : public npc_escortAI
      {
          npc_arthasAI(Creature* creature) : npc_escortAI(creature)
          {
              instance = creature->GetInstanceScript();
              Reset();
          }
  
          InstanceScript* instance;
  
          bool bStepping;
          uint32 uiStep;
          uint32 uiPhaseTimer;
          uint32 uiGossipStep;
          uint32 uiPlayerFaction;
          uint32 uiBossEvent;
          uint32 uiWave;
  
          uint64 uiUtherGUID;
          uint64 uiJainaGUID;
          uint64 uiCitymenGUID[2];
          uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS];
          uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER];
          uint64 uiStalkerGUID;
  
          uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID
          uint64 uiEpochGUID;
          uint64 uiMalganisGUID;
          uint64 uiInfiniteGUID;
  
          uint32 uiExorcismTimer;
  
          void Reset()
          {
              uiUtherGUID = 0;
              uiJainaGUID = 0;
  
              for (uint8 i = 0; i < 2; ++i)
                  uiCitymenGUID[i] = 0;
  
              for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
                  uiWaveGUID[i] = 0;
  
              for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i)
                  uiInfiniteDraconianGUID[i] = 0;
  
              uiStalkerGUID = 0;
              uiBossGUID = 0;
              uiEpochGUID = 0;
              uiMalganisGUID = 0;
              uiInfiniteGUID = 0;
  
              if (instance) {
                  instance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED);
                  switch (instance->GetData(DATA_ARTHAS_EVENT))
                  {
                      case NOT_STARTED:
                          bStepping = true;
                          uiStep = 0;
                          me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                          uiBossEvent = DATA_MEATHOOK_EVENT;
                          uiGossipStep = 0;
                          break;
                  }
                  uiPhaseTimer = 1000;
                  uiExorcismTimer = 7300;
                  uiWave = 0;
              }
          }
  
          void EnterCombat(Unit* /*who*/)
          {
              DoCast(me, SPELL_ARTHAS_AURA);
          }
  
          void JustDied(Unit* /*killer*/)
          {
              if (instance)
                  instance->SetData(DATA_ARTHAS_EVENT, FAIL);
          }
  
          void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector)
          {
              me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0], RiftAndSpawnsLocations[timeRiftID][1], RiftAndSpawnsLocations[timeRiftID][2], RiftAndSpawnsLocations[timeRiftID][3], RiftAndSpawnsLocations[timeRiftID][4], TEMPSUMMON_TIMED_DESPAWN, 11000);
  
              for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i)
              {
                  if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break;
                  if (Creature* temp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0], RiftAndSpawnsLocations[timeRiftID][1], RiftAndSpawnsLocations[timeRiftID][2], RiftAndSpawnsLocations[timeRiftID][3], RiftAndSpawnsLocations[timeRiftID][4], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
                  {
                      guidVector[i-timeRiftID-1] = temp->GetGUID();
                      temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                      temp->SetReactState(REACT_PASSIVE);
                      temp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1], RiftAndSpawnsLocations[i][2], RiftAndSpawnsLocations[i][3]);
                      if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH)
                          uiEpochGUID = temp->GetGUID();
                  }
              }
          }
  
          void SpawnWaveGroup(uint32 waveID, uint64* guidVector)
          {
              for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
              {
                  if ((uint32)WavesLocations[waveID][i][0] == 0) break;
                  if (Creature* temp = me->SummonCreature((uint32)WavesLocations[waveID][i][0], WavesLocations[waveID][i][1], WavesLocations[waveID][i][2], WavesLocations[waveID][i][3], WavesLocations[waveID][i][4], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
                  {
                      guidVector[i] = temp->GetGUID();
                  }
              }
          }
  
          void SetHoldState(bool bOnHold)
          {
              SetEscortPaused(bOnHold);
          }
  
          void JumpToNextStep(uint32 uiTimer)
          {
              uiPhaseTimer = uiTimer;
              ++uiStep;
          }
  
          void WaypointReached(uint32 uiPointId)
          {
              switch (uiPointId)
              {
                  case 0:
                  case 1:
                  case 3:
                  case 9:
                  case 10:
                  case 11:
                  case 22:
                  case 23:
                  case 26:
                  case 55:
                  case 56:
                      SetHoldState(true);
                      bStepping = true;
                      break;
                  case 7:
                      if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN, 2091.977f, 1275.021f, 140.757f, 0.558f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
                          uiCitymenGUID[0] = pCityman0->GetGUID();
                      if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2, 2093.514f, 1275.842f, 140.408f, 3.801f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
                          uiCitymenGUID[1] = pCityman1->GetGUID();
                      break;
                  case 8:
                      uiGossipStep = 1;
                      me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                      SetHoldState(true);
                      break;
                  case 12:
                      SetRun(true);
                      DoScriptText(SAY_PHASE210, me);
                      if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3, 2398.14f, 1207.81f, 134.04f, 5.155249f, TEMPSUMMON_DEAD_DESPAWN, 180000))
                      {
                          uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID();
                          if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4, 2403.22f, 1205.54f, 134.04f, 3.311264f, TEMPSUMMON_DEAD_DESPAWN, 180000))
                          {
                              uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID();
  
                              if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN, 2400.82f, 1201.69f, 134.01f, 1.534082f, TEMPSUMMON_DEAD_DESPAWN, 180000))
                              {
                                  uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID();
                                  pDisguised0->SetTarget(uiInfiniteDraconianGUID[1]);
                                  pDisguised1->SetTarget(uiInfiniteDraconianGUID[0]);
                                  pDisguised2->SetTarget(uiInfiniteDraconianGUID[1]);
                              }
                          }
                      }
                      break;
                  case 20:
                      uiGossipStep = 2;
                      me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                      SetRun(false);
                      SetHoldState(true);
                      break;
                  case 21:
                      DoScriptText(SAY_PHASE301, me);
                      break;
                  case 25:
                      SetRun(false);
                      SpawnTimeRift(0, &uiInfiniteDraconianGUID[0]);
                      DoScriptText(SAY_PHASE307, me);
                      break;
                  case 29:
                      SetRun(false);
                      SpawnTimeRift(5, &uiInfiniteDraconianGUID[0]);
                      SpawnTimeRift(8, &uiInfiniteDraconianGUID[2]);
                      DoScriptText(SAY_PHASE309, me);
                      SetHoldState(true);
                      bStepping = true;
                      break;
                  case 31:
                      SetRun(false);
                      SpawnTimeRift(11, &uiInfiniteDraconianGUID[0]);
                      SpawnTimeRift(14, &uiInfiniteDraconianGUID[2]);
                      DoScriptText(SAY_PHASE311, me);
                      SetHoldState(true);
                      bStepping = true;
                      break;
                  case 32:
                      DoScriptText(SAY_PHASE401, me);
                      break;
                  case 34:
                      DoScriptText(SAY_PHASE402, me);
                      break;
                  case 35:
                      DoScriptText(SAY_PHASE403, me);
                      break;
                  case 36:
                      if (instance)
                          if (GameObject* pGate = instance->instance->GetGameObject(instance->GetData64(DATA_SHKAF_GATE)))
                              pGate->SetGoState(GO_STATE_ACTIVE);
                      break;
                  case 45:
                      SetRun(true);
                      SetDespawnAtFar(false);
                      uiGossipStep = 4;
                      me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                      SetHoldState(true);
                      break;
                  case 47:
                      SetRun(false);
                      DoScriptText(SAY_PHASE405, me);
                      break;
                  case 48:
                      SetRun(true);
                      DoScriptText(SAY_PHASE406, me);
                      break;
                  case 53:
                      DoScriptText(SAY_PHASE407, me);
                      break;
                  case 54:
                      uiGossipStep = 5;
                      me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                      SetHoldState(true);
                      break;
               }
          }
  
          void UpdateAI(const uint32 diff)
          {
              npc_escortAI::UpdateAI(diff);
  
              DoMeleeAttackIfReady();
  
              if (bStepping)
              {
                  if (uiPhaseTimer <= diff)
                  {
                      switch (uiStep)
                      {
                          //After reset
                          case 0:
                              if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f))
                                  uiJainaGUID = pJaina->GetGUID();
                              else if (Unit* pJaina = me->SummonCreature(NPC_JAINA, 1895.48f, 1292.66f, 143.706f, 0.023475f, TEMPSUMMON_DEAD_DESPAWN, 180000))
                                  uiJainaGUID = pJaina->GetGUID();
                              bStepping = false;
                              JumpToNextStep(0);
                              break;
                          //After waypoint 0
                          case 1:
                              me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                              if (Unit* pUther = me->SummonCreature(NPC_UTHER, 1794.357f, 1272.183f, 140.558f, 1.37f, TEMPSUMMON_DEAD_DESPAWN, 180000))
                              {
                                  uiUtherGUID = pUther->GetGUID();
                                  pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                  pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f);
                                  pUther->SetTarget(me->GetGUID());
                                  me->SetTarget(uiUtherGUID);
                              }
                              JumpToNextStep(17000);
                              break;
                          case 2:
                              DoScriptText(SAY_PHASE101, me);
                              JumpToNextStep(2000);
                              break;
                          case 3:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                              {
                                  DoScriptText(SAY_PHASE102, pUther);
                              }
                              JumpToNextStep(8000);
                              break;
                          case 4:
                              SetEscortPaused(false);
                              bStepping = false;
                              SetRun(false);
                              DoScriptText(SAY_PHASE103, me);
                              JumpToNextStep(0);
                              break;
                          //After waypoint 1
                          case 5:
                              if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID))
                                  pJaina->SetTarget(me->GetGUID());
                              DoScriptText(SAY_PHASE104, me);
                              JumpToNextStep(10000);
                              break;
                          case 6:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  DoScriptText(SAY_PHASE105, pUther);
                              JumpToNextStep(1000);
                              break;
                          case 7:
                              DoScriptText(SAY_PHASE106, me);
                              JumpToNextStep(4000);
                              break;
                          case 8:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  DoScriptText(SAY_PHASE107, pUther);
                              JumpToNextStep(6000);
                              break;
                          case 9:
                              DoScriptText(SAY_PHASE108, me);
                              JumpToNextStep(4000);
                              break;
                          case 10:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  DoScriptText(SAY_PHASE109, pUther);
                              JumpToNextStep(8000);
                              break;
                          case 11:
                              DoScriptText(SAY_PHASE110, me);
                              JumpToNextStep(4000);
                              break;
                          case 12:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  DoScriptText(SAY_PHASE111, pUther);
                              JumpToNextStep(4000);
                              break;
                          case 13:
                              DoScriptText(SAY_PHASE112, me);
                              JumpToNextStep(11000);
                              break;
                          case 14:
                              if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID))
                                  DoScriptText(SAY_PHASE113, pJaina);
                              JumpToNextStep(3000);
                              break;
                          case 15:
                              DoScriptText(SAY_PHASE114, me);
                              JumpToNextStep(9000);
                              break;
                          case 16:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  DoScriptText(SAY_PHASE115, pUther);
                              JumpToNextStep(4000);
                              break;
                          case 17:
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                              {
                                  pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                  pUther->GetMotionMaster()->MovePoint(0, 1794.357f, 1272.183f, 140.558f);
                              }
                              JumpToNextStep(1000);
                              break;
                          case 18:
                              if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID))
                              {
                                  me->SetTarget(uiJainaGUID);
                                  pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                  pJaina->GetMotionMaster()->MovePoint(0, 1794.357f, 1272.183f, 140.558f);
                              }
                              JumpToNextStep(1000);
                              break;
                          case 19:
                              DoScriptText(SAY_PHASE116, me);
                              JumpToNextStep(1000);
                              break;
                          case 20:
                              if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID))
                                  DoScriptText(SAY_PHASE117, pJaina);
                              JumpToNextStep(3000);
                              break;
                          case 21:
                              SetEscortPaused(false);
                              bStepping = false;
                              me->SetTarget(0);
                              JumpToNextStep(0);
                              break;
                          //After waypoint 3
                          case 22:
                              DoScriptText(SAY_PHASE118, me);
                              me->SetTarget(uiJainaGUID);
                              JumpToNextStep(10000);
                              break;
                          case 23:
                              SetEscortPaused(false);
                              bStepping = false;
                              SetRun(true);
  
                              if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID))
                                  pJaina->DisappearAndDie();
  
                              if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID))
                                  pUther->DisappearAndDie();
  
                              me->SetTarget(0);
                              JumpToNextStep(0);
                              break;
                          //After Gossip 1 (waypoint 8)
                          case 24:
                              if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2026.469f, 1287.088f, 143.596f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 14000))
                              {
                                  uiStalkerGUID = pStalker->GetGUID();
                                  me->SetTarget(uiStalkerGUID);
                              }
                              JumpToNextStep(1000);
                              break;
                          case 25:
                              DoScriptText(SAY_PHASE201, me);
                              JumpToNextStep(12000);
                              break;
                          case 26:
                              SetEscortPaused(false);
                              bStepping = false;
                              SetRun(false);
                              me->SetTarget(0);
                              JumpToNextStep(0);
                              break;
                          //After waypoint 9
                          case 27:
                              me->SetTarget(uiCitymenGUID[0]);
                              if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0]))
                              {
                                  pCityman->SetTarget(me->GetGUID());
                                  pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                  pCityman->GetMotionMaster()->MovePoint(0, 2088.625f, 1279.191f, 140.743f);
                              }
                              JumpToNextStep(2000);
                              break;
                          case 28:
                              if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0]))
                                  DoScriptText(SAY_PHASE202, pCityman);
                              JumpToNextStep(4000);
                              break;
                          case 29:
                              SetEscortPaused(false);
                              bStepping = false;
                              DoScriptText(SAY_PHASE203, me);
                              JumpToNextStep(0);
                              break;
                          //After waypoint 10
                          case 30:
                              me->HandleEmoteCommand(37);
                              JumpToNextStep(1000);
                              break;
                          case 31:
                              SetEscortPaused(false);
                              bStepping = false;
                              if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1]))
                              {
                                  DoScriptText(SAY_PHASE204, pCityman1);
                                  pCityman1->SetTarget(me->GetGUID());
                                  if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0]))
                                      pCityman0->Kill(pCityman0);
                                  me->SetTarget(uiCitymenGUID[1]);
                              }
                              JumpToNextStep(0);
                              break;
                          //After waypoint 11
                          case 32:
                              me->HandleEmoteCommand(37);
                              JumpToNextStep(1000);
                              break;
                          case 33:
                              if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1]))
                                  pCityman1->Kill(pCityman1);
                              JumpToNextStep(1000);
                              break;
                          case 34:
                              if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2081.447f, 1287.770f, 141.3241f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 10000))
                              {
                                  uiStalkerGUID = pStalker->GetGUID();
                                  me->SetTarget(uiStalkerGUID);
                              }
                              DoScriptText(SAY_PHASE205, me);
                              JumpToNextStep(3000);
                              break;
                          case 35:
                              if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET, 2117.349f, 1288.624f, 136.271f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 60000))
                              {
                                  uiStalkerGUID = pStalkerM->GetGUID();
                                  me->SetTarget(uiStalkerGUID);
                              }
                              JumpToNextStep(1000);
                              break;
                          case 36:
                              if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS, 2117.349f, 1288.624f, 136.271f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 60000))
                              {
                                  if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID))
                                      pMalganis->CastSpell(pStalkerM, 63793, false);
  
                                  uiMalganisGUID = pMalganis->GetGUID();
                                  DoScriptText(SAY_PHASE206, pMalganis);
                                  pMalganis->SetTarget(me->GetGUID());
                                  pMalganis->SetReactState(REACT_PASSIVE);
                              }
                              JumpToNextStep(11000);
                              break;
                          case 37:
                              if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID))
                              {
                                  if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f))
                                      pZombie->UpdateEntry(NPC_ZOMBIE, 0);
                                  else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f))
                                      pZombie->UpdateEntry(NPC_ZOMBIE, 0);
                                  else //There's no one else to transform
                                      uiStep++;
                              }
                              else
                                  uiStep++;
                              uiPhaseTimer = 500;
                              break;
                          case 38:
                              if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID))
                                  DoScriptText(SAY_PHASE207, pMalganis);
                              JumpToNextStep(17000);
                              break;
                          case 39:
                              if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID))
                                  pMalganis->SetVisible(false);
                              DoScriptText(SAY_PHASE208, me);
                              JumpToNextStep(7000);
                              break;
                          case 40:
                              if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2081.447f, 1287.770f, 141.3241f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 10000))
                              {
                                  uiStalkerGUID = pStalker->GetGUID();
                                  me->SetTarget(uiStalkerGUID);
                              }
                              DoScriptText(SAY_PHASE209, me);
  
                              uiBossEvent = DATA_MEATHOOK_EVENT;
                              if (instance)
                                  instance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS);
  
                              me->SetReactState(REACT_DEFENSIVE);
                              SetDespawnAtFar(false);
                              JumpToNextStep(5000);
                              break;
                          case 41: //Summon wave group
                          case 43:
                          case 45:
                          case 47:
                          case 51:
                          case 53:
                          case 55:
                          case 57:
                              if (instance->GetData(uiBossEvent) != DONE)
                              {
                                  SpawnWaveGroup(uiWave, uiWaveGUID);
                                  uiWave++;
                              }
                              JumpToNextStep(500);
                              break;
                          case 42: //Wait group to die
                          case 44:
                          case 46:
                          case 48:
                          case 52:
                          case 54:
                          case 56:
                          case 58:
                              if (instance->GetData(uiBossEvent) != DONE)
                              {
                                  uint32 mobCounter = 0;
                                  uint32 deadCounter = 0;
                                  for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
                                  {
                                      if (uiWaveGUID[i] == 0)
                                          break;
                                      ++mobCounter;
                                      Unit* temp = Unit::GetCreature(*me, uiWaveGUID[i]);
                                      if (!temp || temp->isDead())
                                          ++deadCounter;
                                  }
  
                                  if (mobCounter <= deadCounter) //If group is dead
                                      JumpToNextStep(1000);
                                  else
                                      uiPhaseTimer = 1000;
                              }
                              else
                                  JumpToNextStep(500);
                              break;
                          case 49: //Summon Boss
                          case 59:
                              if (instance->GetData(uiBossEvent) != DONE)
                              {
                                  uint32 uiBossID = 0;
                                  if (uiBossEvent == DATA_MEATHOOK_EVENT)
                                      uiBossID = NPC_MEATHOOK;
                                  else if (uiBossEvent == DATA_SALRAMM_EVENT)
                                      uiBossID = NPC_SALRAMM;
  
                                  if (Unit* pBoss = me->SummonCreature(uiBossID, 2232.19f, 1331.933f, 126.662f, 3.15f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
                                  {
                                      uiBossGUID = pBoss->GetGUID();
                                      pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
                                      pBoss->GetMotionMaster()->MovePoint(0, 2194.110f, 1332.00f, 130.00f);
                                  }
                              }
                              JumpToNextStep(30000);
                              break;
                          case 50: //Wait Boss death
                          case 60:
                              if (instance)
                              {
                                  if (instance->GetData(uiBossEvent) == DONE)
                                  {
                                      JumpToNextStep(1000);
                                      if (uiBossEvent == DATA_MEATHOOK_EVENT)
                                          uiBossEvent = DATA_SALRAMM_EVENT;
                                      else if (uiBossEvent == DATA_SALRAMM_EVENT)
                                      {
                                          SetHoldState(false);
                                          bStepping = false;
                                          uiBossEvent = DATA_EPOCH_EVENT;
                                      }
                                  }
                                  else if (instance->GetData(uiBossEvent) == FAIL)
                                      npc_escortAI::EnterEvadeMode();
                                  else
                                      uiPhaseTimer = 10000;
                              }
                              break;
                          //After Gossip 2 (waypoint 22)
                          case 61:
                              me->SetReactState(REACT_AGGRESSIVE);
                              if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0]))
                                  pDisguised0->SetTarget(me->GetGUID());
                              if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1]))
                                  pDisguised1->SetTarget(me->GetGUID());
                              if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2]))
                                  pDisguised2->SetTarget(me->GetGUID());
                              JumpToNextStep(1000);
                              break;
                          case 62:
                              if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0]))
                                  DoScriptText(SAY_PHASE302, pDisguised0);
                              JumpToNextStep(7000);
                              break;
                          case 63:
                              DoScriptText(SAY_PHASE303, me);
                              SetHoldState(false);
                              bStepping = false;
                              JumpToNextStep(0);
                              break;
                          //After waypoint 23
                          case 64:
                              me->HandleEmoteCommand(54);
                              JumpToNextStep(1000);
                              break;
                          case 65:
                              if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0]))
                                  pDisguised0->HandleEmoteCommand(11);
                              JumpToNextStep(1000);
                              break;
                          case 66:
                              DoScriptText(SAY_PHASE304, me);
                              JumpToNextStep(2000);
                              break;
                          case 67:
                              if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0]))
                                  DoScriptText(SAY_PHASE305, pDisguised0);
                              JumpToNextStep(1000);
                              break;
                          case 68:
                              if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2]))
                              {
                                  pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0);
                                  //Make them unattackable
                                  pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                                  pDisguised2->SetReactState(REACT_PASSIVE);
                              }
                              JumpToNextStep(2000);
                              break;
                          case 69:
                              if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1]))
                              {
                                  pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0);
                                  //Make them unattackable
                                  pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                                  pDisguised1->SetReactState(REACT_PASSIVE);
                              }
                              JumpToNextStep(2000);
                              break;
                          case 70:
                              if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0]))
                              {
                                  pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0);
                                  //Make them unattackable
                                  pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                                  pDisguised0->SetReactState(REACT_PASSIVE);
                              }
                              JumpToNextStep(2000);
                              break;
                          case 71:
                          //After waypoint 26, 29, 31
                          case 73:
                          case 75:
                          case 77:
                              //Make cratures attackable
                              for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i)
                                  if (Creature* temp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i]))
                                  {
                                      temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                                      temp->SetReactState(REACT_AGGRESSIVE);
                                  }
                              JumpToNextStep(5000);
                              break;
                          case 72:
                          case 74:
                          case 76:
                              if (me->isInCombat())
                                  uiPhaseTimer = 1000;
                              else
                              {
                                  if (uiStep == 72) DoScriptText(SAY_PHASE308, me);
                                  if (uiStep == 74) DoScriptText(SAY_PHASE308, me);
                                  if (uiStep == 76) DoScriptText(SAY_PHASE310, me);
                                  SetHoldState(false);
                                  bStepping = false;
                                  SetRun(true);
                                  JumpToNextStep(2000);
                              }
                              break;
                          case 78:
                              if (me->isInCombat())
                                  uiPhaseTimer = 1000;
                              else
                              {
                                  DoScriptText(SAY_PHASE312, me);
                                  JumpToNextStep(5000);
                              }
                              break;
                          case 79:
                              DoScriptText(SAY_PHASE313, me);
                              JumpToNextStep(1000);
                              break;
                          case 80:
                              if (instance)
                                  if (instance->GetData(DATA_EPOCH_EVENT) != DONE)
                                  {
                                      SpawnTimeRift(17, &uiEpochGUID);
                                      if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID))
                                          DoScriptText(SAY_PHASE314, pEpoch);
                                      me->SetTarget(uiEpochGUID);
                                  }
                              JumpToNextStep(18000);
                              break;
                          case 81:
                              if (instance)
                                  if (instance->GetData(DATA_EPOCH_EVENT) != DONE)
                                      DoScriptText(SAY_PHASE315, me);
                              JumpToNextStep(6000);
                              break;
                          case 82:
                              if (instance)
                                  if (instance->GetData(DATA_EPOCH_EVENT) != DONE)
                                  {
                                      if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID))
                                      {
                                          //Make Epoch attackable
                                          pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
                                          pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
                                          pEpoch->SetReactState(REACT_AGGRESSIVE);
                                      }
                                  }
                              JumpToNextStep(1000);
                              break;
                          case 83:
                              if (instance)
                              {
                                  if (instance->GetData(DATA_EPOCH_EVENT) == DONE)
                                  {
                                      uiGossipStep = 3;
                                      me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                                      bStepping = false;
                                      uiBossEvent = DATA_MAL_GANIS_EVENT;
                                      JumpToNextStep(15000);
                                  }
                                  else if (instance->GetData(DATA_EPOCH_EVENT) == FAIL)
                                      npc_escortAI::EnterEvadeMode();
                                  else
                                      uiPhaseTimer = 10000;
                              }
                              break;
                          //After Gossip 4
                          case 84:
                              DoScriptText(SAY_PHASE404, me);
                              SetHoldState(false);
                              bStepping = false;
                              break;
                          //After Gossip 5
                          case 85:
                              DoScriptText(SAY_PHASE501, me);
                              if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS, 2296.665f, 1502.362f, 128.362f, 4.961f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
                              {
                                  uiMalganisGUID = pMalganis->GetGUID();
                                  pMalganis->SetReactState(REACT_PASSIVE);
                              }
                              if (instance)
                                  if (GameObject* pGate = instance->instance->GetGameObject(instance->GetData64(DATA_MAL_GANIS_GATE_1)))
                                      pGate->SetGoState(GO_STATE_ACTIVE);
                              SetHoldState(false);
                              bStepping = false;
                              JumpToNextStep(0);
                              break;
                          //After waypoint 55
                          case 86:
                              DoScriptText(SAY_PHASE502, me);
                              JumpToNextStep(6000);
                              me->SetTarget(uiMalganisGUID);
                              break;
                          case 87:
                              if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID))
                              {
                                  pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_PASSIVE | UNIT_FLAG_UNK_15);
                                  pMalganis->SetReactState(REACT_AGGRESSIVE);
                              }
                              JumpToNextStep(1000);
                              break;
                          case 88:
                              if (instance)
                              {
                                  if (instance->GetData(DATA_MAL_GANIS_EVENT) == DONE)
                                  {
                                      SetHoldState(false);
                                      JumpToNextStep(1000);
                                  }
                                  else if (instance->GetData(DATA_MAL_GANIS_EVENT) == FAIL)
                                      npc_escortAI::EnterEvadeMode();
                                  else
                                      uiPhaseTimer = 10000;
                              }
                              break;
                          //After waypoint 56
                          case 89:
                              SetRun(true);
                              me->SetTarget(uiMalganisGUID);
                              DoScriptText(SAY_PHASE503, me);
                              JumpToNextStep(7000);
                              break;
                          case 90:
                              if (instance)
                              {
                                  instance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D
                                  me->SetTarget(instance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind
                              }
                              DoScriptText(SAY_PHASE504, me);
                              bStepping = false;
                              break;
                      }
                  } else uiPhaseTimer -= diff;
              }
  
              //Battling skills
              if (!me->getVictim())
                  return;
  
              if (uiExorcismTimer < diff)
              {
                  if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                      DoCast(target, SPELL_EXORCISM_N);
                  uiExorcismTimer = 7300;
              } else uiExorcismTimer -= diff;
  
              if (HealthBelowPct(40))
                  DoCast(me, SPELL_HOLY_LIGHT);
          }
      };
  };
  
  class npc_crate_helper : public CreatureScript
  {
      public:
          npc_crate_helper() : CreatureScript("npc_create_helper_cot") { }
  
          struct npc_crate_helperAI : public NullCreatureAI
          {
              npc_crate_helperAI(Creature* creature) : NullCreatureAI(creature)
              {
                  _marked = false;
              }
  
              void SpellHit(Unit* /*caster*/, SpellEntry const* spell)
              {
                  if (spell->Id == SPELL_ARCANE_DISRUPTION && !_marked)
                  {
                      _marked = true;
                      if (InstanceScript* instance = me->GetInstanceScript())
                          instance->SetData(DATA_CRATE_COUNT, instance->GetData(DATA_CRATE_COUNT) + 1);
                      if (GameObject* crate = me->FindNearestGameObject(GO_SUSPICIOUS_CRATE, 5.0f))
                      {
                          crate->SummonGameObject(GO_PLAGUED_CRATE, crate->GetPositionX(), crate->GetPositionY(), crate->GetPositionZ(), crate->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, DAY);
                          crate->Delete();
                      }
                  }
              }
  
          private:
              bool _marked;
          };
  
          CreatureAI* GetAI(Creature* creature) const
          {
              return new npc_crate_helperAI(creature);
          }
  };
  
  void AddSC_culling_of_stratholme()
  {
      new npc_arthas();
      new npc_crate_helper();
  }
  