Looking4Group / L4G_Core

Looking4Group Core
http://looking4group.eu
GNU General Public License v2.0
37 stars 69 forks source link

Karazhan - Terestian Illhoof #458

Closed Xadras closed 8 years ago

Xadras commented 9 years ago

Originally reported by: robinsch (Bitbucket: robinsch, GitHub: robinsch)



#!diff
From 6ffbecd04caf8363313b9323073d52f8f49978ad Mon Sep 17 00:00:00 2001
From: robinsch
Date: Sat, 5 Sep 2015 02:39:53 +0200
Subject: [PATCH] Scripts/TerestianIllhoof: Updated encounter.

* Terestian spawn point corrected
* Kil'Rek spawn removed
* Kil'Rek will be summoned 5 seconds after engage
* Portals are now at their correct place
* Terestian now casts his summon portal visual
* Terestian now casts shadowbolt upon engage
* Imps will no longer spawn if more then 20 Imps are currently in the fight
* Kil'Rek now emotes on death (DBM will work now!)
* Terestian and Kil'Rek will now evade (Kil'Rek will despawn) when they get pulled out of their room.

---
 sql/updates/world/2015_09_05_world.sql             |  13 +
 src/server/game/Spells/SpellMgr.cpp                |   3 +
 .../Karazhan/boss_terestian_illhoof.cpp            | 317 ++++++++++++++-------
 3 files changed, 228 insertions(+), 105 deletions(-)
 create mode 100644 sql/updates/world/2015_09_05_world.sql

diff --git a/sql/updates/world/2015_09_05_world.sql b/sql/updates/world/2015_09_05_world.sql
new file mode 100644
index 0000000..2c4d524
--- /dev/null
+++ b/sql/updates/world/2015_09_05_world.sql
@@ -0,0 +1,13 @@
+-- Delete Kilrek
+DELETE FROM `creature` WHERE (`guid`='85371');
+-- Correct spawn position from Terestian Illhoof
+UPDATE `creature` SET `position_x`='-11241', `position_y`='-1704.54', `position_z`='179.237', `orientation`='0.708644' WHERE (`guid`='56322');
+
+-- Set correct XYZ entry for portals
+DELETE FROM `spell_target_position` WHERE `id` IN (30171, 30179);
+INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`) VALUES ('30171', '532', '-11249.6933', '-1704.61023');
+INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`) VALUES ('30179', '532', '-11242.116', '-1713.33325');
+
+-- Kilrek emote
+DELETE FROM `script_texts` WHERE (`entry`='-1532115');
+INSERT INTO `script_texts` (`entry`, `content_default`, `type`, `comment`) VALUES ('-1532115', 'shrieks in pain and points at his master.', '2', 'KILREK_EMOTE_DEATH');
\ No newline at end of file
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index f8ec3f9..4e7b538 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2774,6 +2774,9 @@ void SpellMgr::LoadSpellCustomAttr()
         case 32747: // Deadly Throw Interupt
             spellInfo->speed = 0.0f;
             break;
+        case 30171: // Fiendish Portal - Should be fixed in Spell::EffectSummonType to use data from spell_target_position
+            spellInfo->Effect[0] = 0;
+            break;
         default:
             break;
         }
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp
index eb2a84f..288103c 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp
@@ -19,8 +19,8 @@

 /* ScriptData
 SDName: Boss_Terestian_Illhoof
-SD%Complete: 95
-SDComment: Complete! Needs adjustments to use spell though.
+SD%Complete: 100
+SDComment:
 SDCategory: Karazhan
 EndScriptData */

@@ -45,6 +45,11 @@ enum TerestianIllhoof
     SAY_SUMMON2                 = -1532072
 };

+enum Kilrek
+{
+    EMOTE_DEATH                 = -1532115
+};
+
 enum Spells
 {
     SPELL_SUMMON_DEMONCHAINS    = 30120,                   // Summons demonic chains that maintain the ritual of sacrifice.
@@ -72,49 +77,17 @@ enum Creatues
     NPC_KILREK                  = 17229
 };

-struct mob_kilrekAI : public ScriptedAI
+enum Defines
 {
-    mob_kilrekAI(Creature *c) : ScriptedAI(c)
-    {
-        instance = c->GetInstanceScript();
-    }
-
-    ScriptedInstance* instance;
-
-    uint32 AmplifyTimer;
-
-    void Reset()
-    {
-        AmplifyTimer = 2000;
-    }
-
-    void JustDied(Unit* /*Killer*/)
-    {
-        Unit* Terestian = Unit::GetUnit((*me), instance->GetData64(DATA_TERESTIAN));
-        if (Terestian && Terestian->isAlive())
-            DoCast(Terestian, SPELL_BROKEN_PACT, true);
-    }
-
-    void UpdateAI(const uint32 diff)
-    {
-        // Return since we have no target
-        if (!UpdateVictim())
-            return;
-
-        if (AmplifyTimer <= diff)
-        {
-            me->InterruptNonMeleeSpells(false);
-            DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES);
-
-            AmplifyTimer = urand(10000, 20000);
-        }
-        else AmplifyTimer -= diff;
-
-        DoMeleeAttackIfReady();
-    }
+    MAX_COUNT_IMP               = 20,
+    MAX_COUNT_PORTALS           = 2
 };

-float KilrekLocation = {};
+float PortalLocations[2][2] =
+{
+    { -11252.0205, -1703.97009 },
+    { -11241.5742, -1717.40063 },
+};

 struct mob_demon_chainAI : public ScriptedAI
 {
@@ -173,63 +146,30 @@ struct mob_fiendish_portalAI : public PassiveAI
     }
 };

-struct mob_fiendish_impAI : public ScriptedAI
-{
-    mob_fiendish_impAI(Creature *c) : ScriptedAI(c)
-    {
-        Initialize();
-    }
-
-    void Initialize()
-    {
-        FireboltTimer = 2000;
-    }
-
-    uint32 FireboltTimer;
-
-    void Reset()
-    {
-        Initialize();
-
-        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
-    }
-
-    void EnterCombat(Unit * /*who*/) {}
-
-    void UpdateAI(const uint32 diff)
-    {
-        //Return since we have no target
-        if (!UpdateVictim())
-            return;
-
-        if (FireboltTimer <= diff)
-        {
-            DoCast(me->getVictim(), SPELL_FIREBOLT);
-            FireboltTimer = 2200;
-        }
-        else FireboltTimer -= diff;
-
-        DoMeleeAttackIfReady();
-    }
-};
-
 struct boss_terestianAI : public ScriptedAI
 {
     boss_terestianAI(Creature *c) : ScriptedAI(c)
     {
         instance = c->GetInstanceScript();
         Initialize();
+        me->GetPosition(&pos);
     }

     void Initialize()
     {
         PortalsCount = 0;
+        ImpCount = 0;
         SacrificeTimer = 30000;
-        ShadowboltTimer = 5000;
-        SummonTimer = 10000;
+        ShadowboltTimer = 100;
+        PortalTimer = 10000;
+        SummonPortalTimer = 0;
+        SummonImpTimer = 0;
+        SummonKilrekTimer = 5000;
         BerserkTimer = 600000;
+        CheckTimer = 3000;

         SummonedPortals = false;
+        KilrekSummoned = false;
         Berserk = false;
     }

@@ -237,13 +177,21 @@ struct boss_terestianAI : public ScriptedAI

     uint64 PortalGUID[2];
     uint8 PortalsCount;
+    uint8 ImpCount;

     uint32 SacrificeTimer;
     uint32 ShadowboltTimer;
-    uint32 SummonTimer;
+    uint32 PortalTimer;
+    uint32 SummonPortalTimer;
+    uint32 SummonImpTimer;
+    uint32 SummonKilrekTimer;
     uint32 BerserkTimer;
+    uint32 CheckTimer;
+
+    Position pos;

     bool SummonedPortals;
+    bool KilrekSummoned;
     bool Berserk;

     void Reset()
@@ -267,17 +215,17 @@ struct boss_terestianAI : public ScriptedAI
         instance->SetData(TYPE_TERESTIAN, NOT_STARTED);

         me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
+    }

-        if (Minion* Kilrek = me->GetFirstMinion())
+    void EnterEvadeMode()
+    {
+        if (Creature* Kilrek = Unit::GetUnit((*me), instance->GetData64(DATA_KILREK))->ToCreature())
         {
-            if (!Kilrek->isAlive())
-            {
-                Kilrek->UnSummon();
-                DoCast(me, SPELL_SUMMON_IMP, true);
-            }
+            if (Kilrek->isAlive())
+                Kilrek->ForcedDespawn();
         }
-        else
-            DoCast(me, SPELL_SUMMON_IMP, true);
+
+        ScriptedAI::EnterEvadeMode();
     }

     void EnterCombat(Unit* /*who*/)
@@ -328,6 +276,18 @@ struct boss_terestianAI : public ScriptedAI
         if (!UpdateVictim())
             return;

+        if (CheckTimer < diff)
+        {
+            if (!me->IsWithinDist3d(&pos, 35.0f))
+                EnterEvadeMode();
+            else
+                DoZoneInCombat();
+
+            CheckTimer = 3000;
+        }
+        else
+            CheckTimer -= diff;
+
         if (SacrificeTimer <= diff)
         {
             Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, GetSpellMaxRange(SPELL_SACRIFICE), true);
@@ -345,30 +305,78 @@ struct boss_terestianAI : public ScriptedAI
                 }
             }
         }
-        else SacrificeTimer -= diff;
+        else
+            SacrificeTimer -= diff;
+
+        if (SummonKilrekTimer && SummonKilrekTimer <= diff)
+        {
+            DoCast(me, SPELL_SUMMON_IMP, true);
+            SummonKilrekTimer = 0;
+        }
+        else
+            SummonKilrekTimer -= diff;

         if (ShadowboltTimer <= diff)
         {
             DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
             ShadowboltTimer = 10000;
         }
-        else ShadowboltTimer -= diff;
+        else
+            ShadowboltTimer -= diff;

-        if (SummonTimer <= diff)
+        if (!SummonedPortals)
         {
-            if (!PortalGUID[0])
-                DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false);
+            if (PortalTimer && PortalTimer <= diff)
+            {
+                DoScriptText(RAND(SAY_SUMMON1, SAY_SUMMON2), me);
+                DoCast(me, SPELL_FIENDISH_PORTAL, false); // Effect removed in SpellMgr.cpp
+                SummonPortalTimer = 2000;
+                PortalTimer = 0;
+            }
+            else
+                PortalTimer -= diff;

-            if (!PortalGUID[1])
-                DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false);
+            if (SummonPortalTimer && SummonPortalTimer <= diff)
+            {
+                /* Should be fixed in Spell::EffectSummonType to use data from spell_target_position
+                if (!PortalGUID[0])
+                DoCast(me, SPELL_FIENDISH_PORTAL, false);

+                if (!PortalGUID[1])
+                DoCast(me, SPELL_FIENDISH_PORTAL_1, false);
+                */
+
+                for (uint8 i = 0; i < MAX_COUNT_PORTALS; ++i)
+                {
+                    if (PortalsCount <= MAX_COUNT_PORTALS)
+                        me->SummonCreature(NPC_PORTAL, PortalLocations[i][0], PortalLocations[i][1], me->GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN);
+                }
+
+                SummonImpTimer = 5000; // CastingTime (Id 5) = 2.00 + 5000
+                SummonedPortals = true;
+            }
+            else
+                SummonPortalTimer -= diff;
+        }
+
+        if (SummonImpTimer && SummonImpTimer <= diff)
+        {
             if (PortalGUID[0] && PortalGUID[1])
             {
-                if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0, 1)]))
-                    pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false);
-                SummonTimer = 5000;
+                if (ImpCount < MAX_COUNT_IMP)
+                {
+                    if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0, 1)]))
+                    {
+                        pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false);
+                        ++ImpCount;
+                    }
+                }
+
+                SummonImpTimer = urand(2000, 7000);
             }
-        } else SummonTimer -= diff;
+        }
+        else
+            SummonImpTimer -= diff;

         if (!Berserk)
         {
@@ -376,8 +384,107 @@ struct boss_terestianAI : public ScriptedAI
             {
                 DoCast(me, SPELL_BERSERK);
                 Berserk = true;
-            } else BerserkTimer -= diff;
+            }
+            else
+                BerserkTimer -= diff;
+        }
+
+        DoMeleeAttackIfReady();
+    }
+};
+
+struct mob_fiendish_impAI : public ScriptedAI
+{
+    mob_fiendish_impAI(Creature *c) : ScriptedAI(c)
+    {
+        instance = c->GetInstanceScript();
+        Initialize();
+    }
+
+    ScriptedInstance *instance;
+
+    void Initialize()
+    {
+        FireboltTimer = 2000;
+    }
+
+    uint32 FireboltTimer;
+
+    void Reset()
+    {
+        Initialize();
+
+        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
+    }
+
+    void JustDied(Unit * /*killer*/)
+    {
+        Creature* Terestian = Unit::GetUnit((*me), instance->GetData64(DATA_TERESTIAN))->ToCreature();
+        if (Terestian && Terestian->isAlive())
+            CAST_AI(boss_terestianAI, Terestian->AI())->ImpCount--;
+    }
+
+    void EnterCombat(Unit * /*who*/) {}
+
+    void UpdateAI(const uint32 diff)
+    {
+        //Return since we have no target
+        if (!UpdateVictim())
+            return;
+
+        if (FireboltTimer <= diff)
+        {
+            DoCast(me->getVictim(), SPELL_FIREBOLT);
+            FireboltTimer = 2200;
         }
+        else FireboltTimer -= diff;
+
+        DoMeleeAttackIfReady();
+    }
+};
+
+struct mob_kilrekAI : public ScriptedAI
+{
+    mob_kilrekAI(Creature *c) : ScriptedAI(c)
+    {
+        instance = c->GetInstanceScript();
+    }
+
+    ScriptedInstance* instance;
+
+    uint32 AmplifyTimer;
+
+    void Reset()
+    {
+        AmplifyTimer = 2000;
+    }
+
+    void JustDied(Unit* /*Killer*/)
+    {
+        Creature* Terestian = Unit::GetUnit((*me), instance->GetData64(DATA_TERESTIAN))->ToCreature();
+        if (Terestian && Terestian->isAlive())
+        {
+            DoScriptText(EMOTE_DEATH, me);
+            CAST_AI(boss_terestianAI, Terestian->AI())->SummonKilrekTimer = 45000;
+            DoCast(Terestian, SPELL_BROKEN_PACT, true);
+            me->ForcedDespawn(15000);
+        }
+    }
+
+    void UpdateAI(const uint32 diff)
+    {
+        // Return since we have no target
+        if (!UpdateVictim())
+            return;
+
+        if (AmplifyTimer <= diff)
+        {
+            me->InterruptNonMeleeSpells(false);
+            DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES);
+
+            AmplifyTimer = urand(10000, 20000);
+        }
+        else AmplifyTimer -= diff;

         DoMeleeAttackIfReady();
     }

Xadras commented 8 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


Removing component: NPC (automated comment)

Xadras commented 9 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


das dürfte dann den freeze erklären, hatte sql mäßig nur das von oben eingespielt

Xadras commented 9 years ago

Original comment by robinsch (Bitbucket: robinsch, GitHub: robinsch):


Kannst auch bool KilrekSummoned entfernen, wird nicht benutzt.

Hast du auch das Script zum Portal assigned? mob_fiendish_portal

Benutzt für aura remove: RemoveAuraDueToSpellByCancel

Xadras commented 9 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


Script/DB: Some improvements for Terestian - resolves #462

Xadras commented 9 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


Lag am

#!c++

CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp();

Hab das auskommentiert und dafür ne schleife die 20 mal durchgeht reingehackt, nicht schön aber selten, danach keine Probleme mehr

Und halt beim summon von kilrek:

#!c++

me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);

reingepackt, sonst hat sichhuf immer 25% mehr dmg auch wenn man den ned wieder killt

Xadras commented 9 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


Okay das soweit gefixt.. nun noch den Broken pact fixen, der verschwindet nicht wieder sobald kilrek wieder erscheint ^^

Xadras commented 9 years ago

Original comment by robinsch (Bitbucket: robinsch, GitHub: robinsch):


Kann ich so nicht confirmen, code sieht sauber aus und crasht auch nicht.

Xadras commented 9 years ago

Original comment by Xadras (Bitbucket: Xadras, GitHub: Xadras):


Bei nem wipe bzw. wenn aufeinmal keiner mehr da ist, freezed es den server

Grund ist hier:

#!c++

for (uint8 i = 0; i < 2; ++i)
        {
            if (PortalGUID[i])
            {
                if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i]))
                {
                    CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
                    pPortal->ForcedDespawn();
                }

                PortalGUID[i] = 0;
            }
        }
Xadras commented 9 years ago

Original comment by robinsch (Bitbucket: robinsch, GitHub: robinsch):


Hier das ganze CPP Script, falls der Diff stört. SQL und SpellMgr.cpp changes nicht vergessen.

#!c++

/* * Copyright (C) 2010-2012 Project SkyFire <http://www.projectskyfire.org/>
* Copyright (C) 2010-2012 Oregon <http://www.oregoncore.com/>
* Copyright (C) 2006-2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
*
* 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/>.
*/

/* ScriptData
SDName: Boss_Terestian_Illhoof
SD%Complete: 100
SDComment:
SDCategory: Karazhan
EndScriptData */

#include "ScriptPCH.h"
#include "karazhan.h"

enum TerestianIllhoof
{
    // SAY_SLAY
    SAY_SLAY1 = -1532065,
    SAY_SLAY2 = -1532066,

    SAY_DEATH = -1532067,
    SAY_AGGRO = -1532068,

    // SAY_SACRIFICE
    SAY_SACRIFICE1 = -1532069,
    SAY_SACRIFICE2 = -1532070,

    // SAY_SUMMON
    SAY_SUMMON1 = -1532071,
    SAY_SUMMON2 = -1532072
};

enum Kilrek
{
    EMOTE_DEATH = -1532115
};

enum Spells
{
    SPELL_SUMMON_DEMONCHAINS = 30120,                   // Summons demonic chains that maintain the ritual of sacrifice.
    SPELL_DEMON_CHAINS = 30206,                   // Instant - Visual Effect
    SPELL_ENRAGE = 23537,                   // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min.
    SPELL_SHADOW_BOLT = 30055,                   // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage.
    SPELL_SACRIFICE = 30115,                   // Teleports and adds the debuff
    SPELL_BERSERK = 32965,                   // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley.
    SPELL_SUMMON_FIENDISIMP = 30184,                   // Summons a Fiendish Imp.
    SPELL_SUMMON_IMP = 30066,                   // Summons Kil'rek

    SPELL_FIENDISH_PORTAL = 30171,                   // Opens portal and summons Fiendish Portal, 2 sec cast
    SPELL_FIENDISH_PORTAL_1 = 30179,                   // Opens portal and summons Fiendish Portal, instant cast

    SPELL_FIREBOLT = 30050,                   // Blasts a target for 150 Fire damage.
    SPELL_BROKEN_PACT = 30065,                   // All damage taken increased by 25%.
    SPELL_AMPLIFY_FLAMES = 30053,                   // Increases the Fire damage taken by an enemy by 500 for 25 sec.
};

enum Creatues
{
    NPC_DEMONCHAINS = 17248,
    NPC_FIENDISHIMP = 17267,
    NPC_PORTAL = 17265,
    NPC_KILREK = 17229
};

enum Defines
{
    MAX_COUNT_IMP = 20,
    MAX_COUNT_PORTALS = 2
};

float PortalLocations[2][2] =
{
    { -11252.0205, -1703.97009 },
    { -11241.5742, -1717.40063 },
};

struct mob_demon_chainAI : public ScriptedAI
{
    mob_demon_chainAI(Creature *c) : ScriptedAI(c)
    {
        Initialize();
    }

    void Initialize()
    {
        SacrificeGUID = 0;
    }

    uint64 SacrificeGUID;

    void Reset()
    {
        Initialize();
    }

    void EnterCombat(Unit* /*who*/) {}
    void AttackStart(Unit* /*who*/) {}
    void MoveInLineOfSight(Unit* /*who*/) {}

    void JustDied(Unit * /*killer*/)
    {
        if (SacrificeGUID)
        {
            Unit* Sacrifice = Unit::GetUnit((*me), SacrificeGUID);
            if (Sacrifice)
                Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
        }
    }
};

struct mob_fiendish_portalAI : public PassiveAI
{
    mob_fiendish_portalAI(Creature *c) : PassiveAI(c), summons(me){}

    SummonList summons;

    void Reset()
    {
        DespawnAllImp();
    }

    void JustSummoned(Creature* summon)
    {
        summons.Summon(summon);
        DoZoneInCombat(summon);
    }

    void DespawnAllImp()
    {
        summons.DespawnAll();
    }
};

struct boss_terestianAI : public ScriptedAI
{
    boss_terestianAI(Creature *c) : ScriptedAI(c)
    {
        instance = c->GetInstanceScript();
        Initialize();
        me->GetPosition(&pos);
    }

    void Initialize()
    {
        PortalsCount = 0;
        ImpCount = 0;
        SacrificeTimer = 30000;
        ShadowboltTimer = 100;
        PortalTimer = 10000;
        SummonPortalTimer = 0;
        SummonImpTimer = 0;
        SummonKilrekTimer = 5000;
        BerserkTimer = 600000;
        CheckTimer = 3000;

        SummonedPortals = false;
        KilrekSummoned = false;
        Berserk = false;
    }

    ScriptedInstance *instance;

    uint64 PortalGUID[2];
    uint8 PortalsCount;
    uint8 ImpCount;

    uint32 SacrificeTimer;
    uint32 ShadowboltTimer;
    uint32 PortalTimer;
    uint32 SummonPortalTimer;
    uint32 SummonImpTimer;
    uint32 SummonKilrekTimer;
    uint32 BerserkTimer;
    uint32 CheckTimer;

    Position pos;

    bool SummonedPortals;
    bool KilrekSummoned;
    bool Berserk;

    void Reset()
    {
        for (uint8 i = 0; i < 2; ++i)
        {
            if (PortalGUID[i])
            {
                if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i]))
                {
                    CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp();
                    pPortal->ForcedDespawn();
                }

                PortalGUID[i] = 0;
            }
        }

        Initialize();

        instance->SetData(TYPE_TERESTIAN, NOT_STARTED);

        me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
    }

    void EnterEvadeMode()
    {
        if (Creature* Kilrek = Unit::GetUnit((*me), instance->GetData64(DATA_KILREK))->ToCreature())
        {
            if (Kilrek->isAlive())
                Kilrek->ForcedDespawn();
        }

        ScriptedAI::EnterEvadeMode();
    }

    void EnterCombat(Unit* /*who*/)
    {
        DoScriptText(SAY_AGGRO, me);
    }

    void JustSummoned(Creature* pSummoned)
    {
        if (pSummoned->GetEntry() == NPC_PORTAL)
        {
            PortalGUID[PortalsCount] = pSummoned->GetGUID();
            ++PortalsCount;

            if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1)
            {
                DoScriptText(RAND(SAY_SUMMON1, SAY_SUMMON2), me);
                SummonedPortals = true;
            }
        }
    }

    void KilledUnit(Unit * /*victim*/)
    {
        DoScriptText(RAND(SAY_SLAY1, SAY_SLAY2), me);
    }

    void JustDied(Unit * /*killer*/)
    {
        for (uint8 i = 0; i < 2; ++i)
        {
            if (PortalGUID[i])
            {
                if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i]))
                    pPortal->ForcedDespawn();

                PortalGUID[i] = 0;
            }
        }

        DoScriptText(SAY_DEATH, me);

        instance->SetData(TYPE_TERESTIAN, DONE);
    }

    void UpdateAI(const uint32 diff)
    {
        if (!UpdateVictim())
            return;

        if (CheckTimer < diff)
        {
            if (!me->IsWithinDist3d(&pos, 35.0f))
                EnterEvadeMode();
            else
                DoZoneInCombat();

            CheckTimer = 3000;
        }
        else
            CheckTimer -= diff;

        if (SacrificeTimer <= diff)
        {
            Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, GetSpellMaxRange(SPELL_SACRIFICE), true);
            if (pTarget && pTarget->isAlive())
            {
                DoCast(pTarget, SPELL_SACRIFICE, true);
                DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true);

                if (Creature* Chains = me->FindNearestCreature(NPC_DEMONCHAINS, 100))
                {
                    CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID();
                    Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true);
                    DoScriptText(RAND(SAY_SACRIFICE1, SAY_SACRIFICE2), me);
                    SacrificeTimer = 30000;
                }
            }
        }
        else
            SacrificeTimer -= diff;

        if (SummonKilrekTimer && SummonKilrekTimer <= diff)
        {
            DoCast(me, SPELL_SUMMON_IMP, true);
            SummonKilrekTimer = 0;
        }
        else
            SummonKilrekTimer -= diff;

        if (ShadowboltTimer <= diff)
        {
            DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT);
            ShadowboltTimer = 10000;
        }
        else
            ShadowboltTimer -= diff;

        if (!SummonedPortals)
        {
            if (PortalTimer && PortalTimer <= diff)
            {
                DoScriptText(RAND(SAY_SUMMON1, SAY_SUMMON2), me);
                DoCast(me, SPELL_FIENDISH_PORTAL, false); // Effect removed in SpellMgr.cpp
                SummonPortalTimer = 2000;
                PortalTimer = 0;
            }
            else
                PortalTimer -= diff;

            if (SummonPortalTimer && SummonPortalTimer <= diff)
            {
                /* Should be fixed in Spell::EffectSummonType to use data from spell_target_position
                if (!PortalGUID[0])
                DoCast(me, SPELL_FIENDISH_PORTAL, false);

                if (!PortalGUID[1])
                DoCast(me, SPELL_FIENDISH_PORTAL_1, false);
                */

                for (uint8 i = 0; i < MAX_COUNT_PORTALS; ++i)
                {
                    if (PortalsCount <= MAX_COUNT_PORTALS)
                        me->SummonCreature(NPC_PORTAL, PortalLocations[i][0], PortalLocations[i][1], me->GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN);
                }

                SummonImpTimer = 5000; // CastingTime (Id 5) = 2.00 + 5000
                SummonedPortals = true;
            }
            else
                SummonPortalTimer -= diff;
        }

        if (SummonImpTimer && SummonImpTimer <= diff)
        {
            if (PortalGUID[0] && PortalGUID[1])
            {
                if (ImpCount < MAX_COUNT_IMP)
                {
                    if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0, 1)]))
                    {
                        pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false);
                        ++ImpCount;
                    }
                }

                SummonImpTimer = urand(2000, 7000);
            }
        }
        else
            SummonImpTimer -= diff;

        if (!Berserk)
        {
            if (BerserkTimer <= diff)
            {
                DoCast(me, SPELL_BERSERK);
                Berserk = true;
            }
            else
                BerserkTimer -= diff;
        }

        DoMeleeAttackIfReady();
    }
};

struct mob_fiendish_impAI : public ScriptedAI
{
    mob_fiendish_impAI(Creature *c) : ScriptedAI(c)
    {
        instance = c->GetInstanceScript();
        Initialize();
    }

    ScriptedInstance *instance;

    void Initialize()
    {
        FireboltTimer = 2000;
    }

    uint32 FireboltTimer;

    void Reset()
    {
        Initialize();

        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
    }

    void JustDied(Unit * /*killer*/)
    {
        Creature* Terestian = Unit::GetUnit((*me), instance->GetData64(DATA_TERESTIAN))->ToCreature();
        if (Terestian && Terestian->isAlive())
            CAST_AI(boss_terestianAI, Terestian->AI())->ImpCount--;
    }

    void EnterCombat(Unit * /*who*/) {}

    void UpdateAI(const uint32 diff)
    {
        //Return since we have no target
        if (!UpdateVictim())
            return;

        if (FireboltTimer <= diff)
        {
            DoCast(me->getVictim(), SPELL_FIREBOLT);
            FireboltTimer = 2200;
        }
        else FireboltTimer -= diff;

        DoMeleeAttackIfReady();
    }
};

struct mob_kilrekAI : public ScriptedAI
{
    mob_kilrekAI(Creature *c) : ScriptedAI(c)
    {
        instance = c->GetInstanceScript();
    }

    ScriptedInstance* instance;

    uint32 AmplifyTimer;

    void Reset()
    {
        AmplifyTimer = 2000;
    }

    void JustDied(Unit* /*Killer*/)
    {
        Creature* Terestian = Unit::GetUnit((*me), instance->GetData64(DATA_TERESTIAN))->ToCreature();
        if (Terestian && Terestian->isAlive())
        {
            DoScriptText(EMOTE_DEATH, me);
            CAST_AI(boss_terestianAI, Terestian->AI())->SummonKilrekTimer = 45000;
            DoCast(Terestian, SPELL_BROKEN_PACT, true);
            me->ForcedDespawn(15000);
        }
    }

    void UpdateAI(const uint32 diff)
    {
        // Return since we have no target
        if (!UpdateVictim())
            return;

        if (AmplifyTimer <= diff)
        {
            me->InterruptNonMeleeSpells(false);
            DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES);

            AmplifyTimer = urand(10000, 20000);
        }
        else AmplifyTimer -= diff;

        DoMeleeAttackIfReady();
    }
};

CreatureAI* GetAI_mob_kilrek(Creature* creature)
{
    return new mob_kilrekAI(creature);
}

CreatureAI* GetAI_mob_fiendish_imp(Creature* creature)
{
    return new mob_fiendish_impAI(creature);
}

CreatureAI* GetAI_mob_fiendish_portal(Creature* creature)
{
    return new mob_fiendish_portalAI(creature);
}

CreatureAI* GetAI_boss_terestian_illhoof(Creature* creature)
{
    return new boss_terestianAI(creature);
}

CreatureAI* GetAI_mob_demon_chain(Creature* creature)
{
    return new mob_demon_chainAI(creature);
}

void AddSC_boss_terestian_illhoof()
{
    Script *newscript;
    newscript = new Script;
    newscript->Name = "boss_terestian_illhoof";
    newscript->GetAI = &GetAI_boss_terestian_illhoof;
    newscript->RegisterSelf();

    newscript = new Script;
    newscript->Name = "mob_fiendish_imp";
    newscript->GetAI = &GetAI_mob_fiendish_imp;
    newscript->RegisterSelf();

    newscript = new Script;
    newscript->Name = "mob_fiendish_portal";
    newscript->GetAI = &GetAI_mob_fiendish_portal;
    newscript->RegisterSelf();

    newscript = new Script;
    newscript->Name = "mob_kilrek";
    newscript->GetAI = &GetAI_mob_kilrek;
    newscript->RegisterSelf();

    newscript = new Script;
    newscript->Name = "mob_demon_chain";
    newscript->GetAI = &GetAI_mob_demon_chain;
    newscript->RegisterSelf();
}