diff options
Diffstat (limited to 'src')
8 files changed, 2190 insertions, 2510 deletions
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index f7d921875f9..72623c68ace 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -98,618 +98,562 @@ enum FathomlordKarathress  #define MAX_ADVISORS 3  //Fathom-Lord Karathress AI -class boss_fathomlord_karathress : public CreatureScript +struct boss_fathomlord_karathress : public BossAI  { -public: -    boss_fathomlord_karathress() : CreatureScript("boss_fathomlord_karathress") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_fathomlord_karathress(Creature* creature) : BossAI(creature, BOSS_FATHOM_LORD_KARATHRESS)      { -        return GetSerpentshrineCavernAI<boss_fathomlord_karathressAI>(creature); +        Initialize();      } -    struct boss_fathomlord_karathressAI : public ScriptedAI +    void Initialize()      { -        boss_fathomlord_karathressAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } - -        void Initialize() -        { -            CataclysmicBolt_Timer = 10000; -            Enrage_Timer = 600000;                              //10 minutes -            SearNova_Timer = 20000 + rand32() % 40000; // 20 - 60 seconds - -            BlessingOfTides = false; -        } - -        InstanceScript* instance; +        CataclysmicBolt_Timer = 10000; +        Enrage_Timer = 600000;                              //10 minutes +        SearNova_Timer = 20000 + rand32() % 40000; // 20 - 60 seconds -        uint32 CataclysmicBolt_Timer; -        uint32 Enrage_Timer; -        uint32 SearNova_Timer; +        BlessingOfTides = false; +    } -        bool BlessingOfTides; +    uint32 CataclysmicBolt_Timer; +    uint32 Enrage_Timer; +    uint32 SearNova_Timer; -        ObjectGuid Advisors[MAX_ADVISORS]; +    bool BlessingOfTides; -        void Reset() override -        { -            Initialize(); +    ObjectGuid Advisors[MAX_ADVISORS]; -            ObjectGuid RAdvisors[MAX_ADVISORS]; -            RAdvisors[0] = instance->GetGuidData(DATA_SHARKKIS); -            RAdvisors[1] = instance->GetGuidData(DATA_TIDALVESS); -            RAdvisors[2] = instance->GetGuidData(DATA_CARIBDIS); -            // Respawn of the 3 Advisors -            for (uint8 i = 0; i < MAX_ADVISORS; ++i) +    void Reset() override +    { +        Initialize(); + +        ObjectGuid RAdvisors[MAX_ADVISORS]; +        RAdvisors[0] = instance->GetGuidData(DATA_SHARKKIS); +        RAdvisors[1] = instance->GetGuidData(DATA_TIDALVESS); +        RAdvisors[2] = instance->GetGuidData(DATA_CARIBDIS); +        // Respawn of the 3 Advisors +        for (uint8 i = 0; i < MAX_ADVISORS; ++i) +            if (!RAdvisors[i].IsEmpty())              { -                if (!RAdvisors[i].IsEmpty()) +                Creature* advisor = ObjectAccessor::GetCreature(*me, RAdvisors[i]); +                if (advisor && !advisor->IsAlive())                  { -                    Creature* advisor = ObjectAccessor::GetCreature(*me, RAdvisors[i]); -                    if (advisor && !advisor->IsAlive()) -                    { -                        advisor->Respawn(); -                        advisor->AI()->EnterEvadeMode(); -                        advisor->GetMotionMaster()->MoveTargetedHome(); -                    } +                    advisor->Respawn(); +                    advisor->AI()->EnterEvadeMode(); +                    advisor->GetMotionMaster()->MoveTargetedHome();                  }              } -            instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); -        } +        _Reset(); +    } -        void EventSharkkisDeath() -        { -            Talk(SAY_GAIN_ABILITY1); -            DoCast(me, SPELL_POWER_OF_SHARKKIS); -        } +    void EventSharkkisDeath() +    { +        Talk(SAY_GAIN_ABILITY1); +        DoCast(me, SPELL_POWER_OF_SHARKKIS); +    } -        void EventTidalvessDeath() -        { -            Talk(SAY_GAIN_ABILITY2); -            DoCast(me, SPELL_POWER_OF_TIDALVESS); -        } +    void EventTidalvessDeath() +    { +        Talk(SAY_GAIN_ABILITY2); +        DoCast(me, SPELL_POWER_OF_TIDALVESS); +    } -        void EventCaribdisDeath() -        { -            Talk(SAY_GAIN_ABILITY3); -            DoCast(me, SPELL_POWER_OF_CARIBDIS); -        } +    void EventCaribdisDeath() +    { +        Talk(SAY_GAIN_ABILITY3); +        DoCast(me, SPELL_POWER_OF_CARIBDIS); +    } -        void GetAdvisors() -        { -            Advisors[0] = instance->GetGuidData(DATA_SHARKKIS); -            Advisors[1] = instance->GetGuidData(DATA_TIDALVESS); -            Advisors[2] = instance->GetGuidData(DATA_CARIBDIS); -        } +    void GetAdvisors() +    { +        Advisors[0] = instance->GetGuidData(DATA_SHARKKIS); +        Advisors[1] = instance->GetGuidData(DATA_TIDALVESS); +        Advisors[2] = instance->GetGuidData(DATA_CARIBDIS); +    } -        void StartEvent(Unit* who) -        { -            GetAdvisors(); +    void StartEvent(Unit* who) +    { +        GetAdvisors(); -            Talk(SAY_AGGRO); -            DoZoneInCombat(); +        Talk(SAY_AGGRO); -            instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); -            instance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); -        } +        instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); +    } -        void KilledUnit(Unit* /*victim*/) override -        { -            Talk(SAY_SLAY); -        } +    void KilledUnit(Unit* /*victim*/) override +    { +        Talk(SAY_SLAY); +    } -        void JustDied(Unit* /*killer*/) override -        { -            Talk(SAY_DEATH); +    void JustDied(Unit* /*killer*/) override +    { +        Talk(SAY_DEATH); -            instance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); +        instance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); -            //support for quest 10944 -            me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 1h); -        } +        //support for quest 10944 +        me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 1h); +    } -        void JustEngagedWith(Unit* who) override -        { -            StartEvent(who); -        } +    void JustEngagedWith(Unit* who) override +    { +        _JustEngagedWith(who); +        StartEvent(who); +    } -        void UpdateAI(uint32 diff) override +    void UpdateAI(uint32 diff) override +    { +        //Only if not incombat check if the event is started +        if (!me->IsInCombat() && instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == IN_PROGRESS)          { -            //Only if not incombat check if the event is started -            if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) +            if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER)))              { -                if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) -                { -                    AttackStart(target); -                    GetAdvisors(); -                } +                AttackStart(target); +                GetAdvisors();              } +        } -            //Return since we have no target -            if (!UpdateVictim()) -                return; +        //Return since we have no target +        if (!UpdateVictim()) +            return; -            //someone evaded! -            if (!instance->GetData(DATA_KARATHRESSEVENT)) -            { -                EnterEvadeMode(); -                return; -            } +        //someone evaded! +        if (instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == NOT_STARTED) +        { +            EnterEvadeMode(); +            return; +        } -            //CataclysmicBolt_Timer -            if (CataclysmicBolt_Timer <= diff) -            { -                //select a random unit other than the main tank -                Unit* target = SelectTarget(SelectTargetMethod::Random, 1); +        //CataclysmicBolt_Timer +        if (CataclysmicBolt_Timer <= diff) +        { +            //select a random unit other than the main tank +            Unit* target = SelectTarget(SelectTargetMethod::Random, 1); -                //if there aren't other units, cast on the tank -                if (!target) -                    target = me->GetVictim(); +            //if there aren't other units, cast on the tank +            if (!target) +                target = me->GetVictim(); -                if (target) -                    DoCast(target, SPELL_CATACLYSMIC_BOLT); -                CataclysmicBolt_Timer = 10000; -            } else CataclysmicBolt_Timer -= diff; +            if (target) +                DoCast(target, SPELL_CATACLYSMIC_BOLT); +            CataclysmicBolt_Timer = 10000; +        } else CataclysmicBolt_Timer -= diff; -            //SearNova_Timer -            if (SearNova_Timer <= diff) -            { -                DoCastVictim(SPELL_SEAR_NOVA); -                SearNova_Timer = 20000 + rand32() % 40000; -            } else SearNova_Timer -= diff; +        //SearNova_Timer +        if (SearNova_Timer <= diff) +        { +            DoCastVictim(SPELL_SEAR_NOVA); +            SearNova_Timer = 20000 + rand32() % 40000; +        } else SearNova_Timer -= diff; -            //Enrage_Timer -            if (Enrage_Timer <= diff) -            { -                DoCast(me, SPELL_ENRAGE); -                Enrage_Timer = 90000; -            } else Enrage_Timer -= diff; +        //Enrage_Timer +        if (Enrage_Timer <= diff) +        { +            DoCast(me, SPELL_ENRAGE); +            Enrage_Timer = 90000; +        } else Enrage_Timer -= diff; -            //Blessing of Tides Trigger -            if (!HealthAbovePct(75) && !BlessingOfTides) -            { -                BlessingOfTides = true; -                bool continueTriggering = false; -                for (uint8 i = 0; i < MAX_ADVISORS; ++i) +        //Blessing of Tides Trigger +        if (!HealthAbovePct(75) && !BlessingOfTides) +        { +            BlessingOfTides = true; +            bool continueTriggering = false; +            for (uint8 i = 0; i < MAX_ADVISORS; ++i) +                if (!Advisors[i].IsEmpty())                  { -                    if (!Advisors[i].IsEmpty()) +                    Creature* advisor = ObjectAccessor::GetCreature(*me, Advisors[i]); +                    if (advisor && advisor->IsAlive())                      { -                        Creature* advisor = ObjectAccessor::GetCreature(*me, Advisors[i]); -                        if (advisor && advisor->IsAlive()) -                        { -                            continueTriggering = true; -                            break; -                        } +                        continueTriggering = true; +                        break;                      }                  } - -                if (continueTriggering) -                { -                    DoCast(me, SPELL_BLESSING_OF_THE_TIDES); -                    Talk(SAY_GAIN_BLESSING); -                } +            if (continueTriggering) +            { +                DoCast(me, SPELL_BLESSING_OF_THE_TIDES); +                Talk(SAY_GAIN_BLESSING);              } - -            DoMeleeAttackIfReady();          } -    }; +        DoMeleeAttackIfReady(); +    }  };  //Fathom-Guard Sharkkis AI -class boss_fathomguard_sharkkis : public CreatureScript +struct boss_fathomguard_sharkkis : public ScriptedAI  { -public: -    boss_fathomguard_sharkkis() : CreatureScript("boss_fathomguard_sharkkis") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_fathomguard_sharkkis(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<boss_fathomguard_sharkkisAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript();      } -    struct boss_fathomguard_sharkkisAI : public ScriptedAI +    void Initialize()      { -        boss_fathomguard_sharkkisAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } +        LeechingThrow_Timer = 20000; +        TheBeastWithin_Timer = 30000; +        Multishot_Timer = 15000; +        Pet_Timer = 10000; -        void Initialize() -        { -            LeechingThrow_Timer = 20000; -            TheBeastWithin_Timer = 30000; -            Multishot_Timer = 15000; -            Pet_Timer = 10000; +        pet = false; +    } -            pet = false; -        } +    InstanceScript* instance; -        InstanceScript* instance; +    uint32 LeechingThrow_Timer; +    uint32 TheBeastWithin_Timer; +    uint32 Multishot_Timer; +    uint32 Pet_Timer; -        uint32 LeechingThrow_Timer; -        uint32 TheBeastWithin_Timer; -        uint32 Multishot_Timer; -        uint32 Pet_Timer; +    bool pet; -        bool pet; +    ObjectGuid SummonedPet; -        ObjectGuid SummonedPet; +    void Reset() override +    { +        Initialize(); -        void Reset() override -        { -            Initialize(); +        Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); +        if (Pet && Pet->IsAlive()) +            Pet->KillSelf(); -            Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); -            if (Pet && Pet->IsAlive()) -                Pet->KillSelf(); +        SummonedPet.Clear(); -            SummonedPet.Clear(); +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, NOT_STARTED); +    } -            instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); -        } +    void JustDied(Unit* /*killer*/) override +    { +        if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) +            ENSURE_AI(boss_fathomlord_karathress, Karathress->AI())->EventSharkkisDeath(); +    } + +    void JustEngagedWith(Unit* who) override +    { +        instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, IN_PROGRESS); +    } -        void JustDied(Unit* /*killer*/) override +    void UpdateAI(uint32 diff) override +    { +        //Only if not incombat check if the event is started +        if (!me->IsInCombat() && instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == IN_PROGRESS)          { -            if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) -                ENSURE_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); +            if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) +                AttackStart(target);          } -        void JustEngagedWith(Unit* who) override +        //Return since we have no target +        if (!UpdateVictim()) +            return; + +        //someone evaded! +        if (instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == NOT_STARTED)          { -            instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); -            instance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); +            EnterEvadeMode(); +            return;          } -        void UpdateAI(uint32 diff) override +        //LeechingThrow_Timer +        if (LeechingThrow_Timer <= diff)          { -            //Only if not incombat check if the event is started -            if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) -            { -                if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) -                    AttackStart(target); -            } +            DoCastVictim(SPELL_LEECHING_THROW); +            LeechingThrow_Timer = 20000; +        } else LeechingThrow_Timer -= diff; -            //Return since we have no target -            if (!UpdateVictim()) -                return; +        //Multishot_Timer +        if (Multishot_Timer <= diff) +        { +            DoCastVictim(SPELL_MULTISHOT); +            Multishot_Timer = 20000; +        } else Multishot_Timer -= diff; -            //someone evaded! -            if (!instance->GetData(DATA_KARATHRESSEVENT)) -            { -                EnterEvadeMode(); -                return; -            } +        //TheBeastWithin_Timer +        if (TheBeastWithin_Timer <= diff) +        { +            DoCast(me, SPELL_THE_BEAST_WITHIN); -            //LeechingThrow_Timer -            if (LeechingThrow_Timer <= diff) -            { -                DoCastVictim(SPELL_LEECHING_THROW); -                LeechingThrow_Timer = 20000; -            } else LeechingThrow_Timer -= diff; +            Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); +            if (Pet && Pet->IsAlive()) +                Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); -            //Multishot_Timer -            if (Multishot_Timer <= diff) -            { -                DoCastVictim(SPELL_MULTISHOT); -                Multishot_Timer = 20000; -            } else Multishot_Timer -= diff; +            TheBeastWithin_Timer = 30000; +        } else TheBeastWithin_Timer -= diff; -            //TheBeastWithin_Timer -            if (TheBeastWithin_Timer <= diff) +        //Pet_Timer +        if (Pet_Timer < diff && pet == false) +        { +            pet = true; +            //uint32 spell_id; +            uint32 pet_id; +            if (!urand(0, 1))              { -                DoCast(me, SPELL_THE_BEAST_WITHIN); - -                Creature* Pet = ObjectAccessor::GetCreature(*me, SummonedPet); -                if (Pet && Pet->IsAlive()) -                    Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); - -                TheBeastWithin_Timer = 30000; -            } else TheBeastWithin_Timer -= diff; - -            //Pet_Timer -            if (Pet_Timer < diff && pet == false) +                //spell_id = SPELL_SUMMON_FATHOM_LURKER; +                pet_id = CREATURE_FATHOM_LURKER; +            } +            else              { -                pet = true; -                //uint32 spell_id; -                uint32 pet_id; -                if (!urand(0, 1)) -                { -                    //spell_id = SPELL_SUMMON_FATHOM_LURKER; -                    pet_id = CREATURE_FATHOM_LURKER; -                } -                else -                { -                    //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; -                    pet_id = CREATURE_FATHOM_SPOREBAT; -                } -                //DoCast(me, spell_id, true); -                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; +                pet_id = CREATURE_FATHOM_SPOREBAT; +            } +            //DoCast(me, spell_id, true); +            if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +            { +                if (Creature* Pet = DoSpawnCreature(pet_id, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s))                  { -                    if (Creature* Pet = DoSpawnCreature(pet_id, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15s)) -                    { -                        Pet->AI()->AttackStart(target); -                        SummonedPet = Pet->GetGUID(); -                    } +                    Pet->AI()->AttackStart(target); +                    SummonedPet = Pet->GetGUID();                  } -            } else Pet_Timer -= diff; - -            DoMeleeAttackIfReady(); -        } -    }; +            } +        } else Pet_Timer -= diff; +        DoMeleeAttackIfReady(); +    }  };  //Fathom-Guard Tidalvess AI -class boss_fathomguard_tidalvess : public CreatureScript +struct boss_fathomguard_tidalvess : public ScriptedAI  { -public: -    boss_fathomguard_tidalvess() : CreatureScript("boss_fathomguard_tidalvess") { } +    boss_fathomguard_tidalvess(Creature* creature) : ScriptedAI(creature) +    { +        Initialize(); +        instance = creature->GetInstanceScript(); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void Initialize()      { -        return GetSerpentshrineCavernAI<boss_fathomguard_tidalvessAI>(creature); +        FrostShock_Timer = 25000; +        Spitfire_Timer = 60000; +        PoisonCleansing_Timer = 30000; +        Earthbind_Timer = 45000;      } -    struct boss_fathomguard_tidalvessAI : public ScriptedAI +    InstanceScript* instance; + +    uint32 FrostShock_Timer; +    uint32 Spitfire_Timer; +    uint32 PoisonCleansing_Timer; +    uint32 Earthbind_Timer; + +    void Reset() override      { -        boss_fathomguard_tidalvessAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } +        Initialize(); -        void Initialize() -        { -            FrostShock_Timer = 25000; -            Spitfire_Timer = 60000; -            PoisonCleansing_Timer = 30000; -            Earthbind_Timer = 45000; -        } +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, NOT_STARTED); +    } -        InstanceScript* instance; +    void JustDied(Unit* /*killer*/) override +    { +        if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) +            ENSURE_AI(boss_fathomlord_karathress, Karathress->AI())->EventTidalvessDeath(); +    } -        uint32 FrostShock_Timer; -        uint32 Spitfire_Timer; -        uint32 PoisonCleansing_Timer; -        uint32 Earthbind_Timer; +    void JustEngagedWith(Unit* who) override +    { +        instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, IN_PROGRESS); +        DoCast(me, SPELL_WINDFURY_WEAPON); +    } -        void Reset() override +    void UpdateAI(uint32 diff) override +    { +        //Only if not incombat check if the event is started +        if (!me->IsInCombat() && instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == IN_PROGRESS)          { -            Initialize(); - -            instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); +            if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) +                AttackStart(target);          } -        void JustDied(Unit* /*killer*/) override +        //Return since we have no target +        if (!UpdateVictim()) +            return; + +        //someone evaded! +        if (instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == NOT_STARTED)          { -            if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) -                ENSURE_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); +            EnterEvadeMode(); +            return;          } -        void JustEngagedWith(Unit* who) override +        if (!me->HasAura(SPELL_WINDFURY_WEAPON))          { -            instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); -            instance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS);              DoCast(me, SPELL_WINDFURY_WEAPON);          } -        void UpdateAI(uint32 diff) override +        //FrostShock_Timer +        if (FrostShock_Timer <= diff)          { -            //Only if not incombat check if the event is started -            if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) -            { -                if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) -                    AttackStart(target); -            } - -            //Return since we have no target -            if (!UpdateVictim()) -                return; - -            //someone evaded! -            if (!instance->GetData(DATA_KARATHRESSEVENT)) -            { -                EnterEvadeMode(); -                return; -            } - -            if (!me->HasAura(SPELL_WINDFURY_WEAPON)) -            { -                DoCast(me, SPELL_WINDFURY_WEAPON); -            } - -            //FrostShock_Timer -            if (FrostShock_Timer <= diff) -            { -                DoCastVictim(SPELL_FROST_SHOCK); -                FrostShock_Timer = 25000 + rand32() % 5000; -            } else FrostShock_Timer -= diff; - -            //Spitfire_Timer -            if (Spitfire_Timer <= diff) -            { -                DoCast(me, SPELL_SPITFIRE_TOTEM); -                if (Unit* SpitfireTotem = me->FindNearestCreature(CREATURE_SPITFIRE_TOTEM, 100.0f)) -                    SpitfireTotem->ToCreature()->AI()->AttackStart(me->GetVictim()); +            DoCastVictim(SPELL_FROST_SHOCK); +            FrostShock_Timer = 25000 + rand32() % 5000; +        } else FrostShock_Timer -= diff; -                Spitfire_Timer = 60000; -            } -            else -                Spitfire_Timer -= diff; +        //Spitfire_Timer +        if (Spitfire_Timer <= diff) +        { +            DoCast(me, SPELL_SPITFIRE_TOTEM); +            if (Unit* SpitfireTotem = me->FindNearestCreature(CREATURE_SPITFIRE_TOTEM, 100.0f)) +                SpitfireTotem->ToCreature()->AI()->AttackStart(me->GetVictim()); -            //PoisonCleansing_Timer -            if (PoisonCleansing_Timer <= diff) -            { -                DoCast(me, SPELL_POISON_CLEANSING_TOTEM); -                PoisonCleansing_Timer = 30000; -            } -            else -                PoisonCleansing_Timer -= diff; +            Spitfire_Timer = 60000; +        } +        else +            Spitfire_Timer -= diff; -            //Earthbind_Timer -            if (Earthbind_Timer <= diff) -            { -                DoCast(me, SPELL_EARTHBIND_TOTEM); -                Earthbind_Timer = 45000; -            } -            else -                Earthbind_Timer -= diff; +        //PoisonCleansing_Timer +        if (PoisonCleansing_Timer <= diff) +        { +            DoCast(me, SPELL_POISON_CLEANSING_TOTEM); +            PoisonCleansing_Timer = 30000; +        } +        else +            PoisonCleansing_Timer -= diff; -            DoMeleeAttackIfReady(); +        //Earthbind_Timer +        if (Earthbind_Timer <= diff) +        { +            DoCast(me, SPELL_EARTHBIND_TOTEM); +            Earthbind_Timer = 45000;          } -    }; +        else +            Earthbind_Timer -= diff; +        DoMeleeAttackIfReady(); +    }  };  //Fathom-Guard Caribdis AI -class boss_fathomguard_caribdis : public CreatureScript +struct boss_fathomguard_caribdis : public ScriptedAI  { -public: -    boss_fathomguard_caribdis() : CreatureScript("boss_fathomguard_caribdis") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_fathomguard_caribdis(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<boss_fathomguard_caribdisAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript();      } -    struct boss_fathomguard_caribdisAI : public ScriptedAI +    void Initialize()      { -        boss_fathomguard_caribdisAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } +        WaterBoltVolley_Timer = 35000; +        TidalSurge_Timer = 15000 + rand32() % 5000; +        Heal_Timer = 55000; +        Cyclone_Timer = 30000 + rand32() % 10000; +    } -        void Initialize() -        { -            WaterBoltVolley_Timer = 35000; -            TidalSurge_Timer = 15000 + rand32() % 5000; -            Heal_Timer = 55000; -            Cyclone_Timer = 30000 + rand32() % 10000; -        } +    InstanceScript* instance; -        InstanceScript* instance; +    uint32 WaterBoltVolley_Timer; +    uint32 TidalSurge_Timer; +    uint32 Heal_Timer; +    uint32 Cyclone_Timer; -        uint32 WaterBoltVolley_Timer; -        uint32 TidalSurge_Timer; -        uint32 Heal_Timer; -        uint32 Cyclone_Timer; +    void Reset() override +    { +        Initialize(); -        void Reset() override -        { -            Initialize(); +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, NOT_STARTED); +    } -            instance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); -        } +    void JustDied(Unit* /*killer*/) override +    { +        if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) +            ENSURE_AI(boss_fathomlord_karathress, Karathress->AI())->EventCaribdisDeath(); +    } + +    void JustEngagedWith(Unit* who) override +    { +        instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); +        instance->SetBossState(BOSS_FATHOM_LORD_KARATHRESS, IN_PROGRESS); +    } -        void JustDied(Unit* /*killer*/) override +    void UpdateAI(uint32 diff) override +    { +        //Only if not incombat check if the event is started +        if (!me->IsInCombat() && instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == IN_PROGRESS)          { -            if (Creature* Karathress = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KARATHRESS))) -                ENSURE_AI(boss_fathomlord_karathress::boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); +            if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) +                AttackStart(target);          } -        void JustEngagedWith(Unit* who) override +        //Return since we have no target +        if (!UpdateVictim()) +            return; + +        //someone evaded! +        if (instance->GetBossState(BOSS_FATHOM_LORD_KARATHRESS) == NOT_STARTED)          { -            instance->SetGuidData(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); -            instance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); +            EnterEvadeMode(); +            return;          } -        void UpdateAI(uint32 diff) override +        //WaterBoltVolley_Timer +        if (WaterBoltVolley_Timer <= diff)          { -            //Only if not incombat check if the event is started -            if (!me->IsInCombat() && instance->GetData(DATA_KARATHRESSEVENT)) -            { -                if (Unit* target = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESSEVENT_STARTER))) -                    AttackStart(target); -            } - -            //Return since we have no target -            if (!UpdateVictim()) -                return; +            DoCastVictim(SPELL_WATER_BOLT_VOLLEY); +            WaterBoltVolley_Timer = 30000; +        } else WaterBoltVolley_Timer -= diff; -            //someone evaded! -            if (!instance->GetData(DATA_KARATHRESSEVENT)) -            { -                EnterEvadeMode(); -                return; -            } - -            //WaterBoltVolley_Timer -            if (WaterBoltVolley_Timer <= diff) -            { -                DoCastVictim(SPELL_WATER_BOLT_VOLLEY); -                WaterBoltVolley_Timer = 30000; -            } else WaterBoltVolley_Timer -= diff; +        //TidalSurge_Timer +        if (TidalSurge_Timer <= diff) +        { +            DoCastSelf(SPELL_TIDAL_SURGE); +            TidalSurge_Timer = 15000 + rand32() % 5000; +        } else TidalSurge_Timer -= diff; -            //TidalSurge_Timer -            if (TidalSurge_Timer <= diff) -            { -                DoCastSelf(SPELL_TIDAL_SURGE); -                TidalSurge_Timer = 15000 + rand32() % 5000; -            } else TidalSurge_Timer -= diff; +        //Cyclone_Timer +        if (Cyclone_Timer <= diff) +        { +            //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work +            Cyclone_Timer = 30000 + rand32() % 10000; -            //Cyclone_Timer -            if (Cyclone_Timer <= diff) +            if (Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 5), TEMPSUMMON_TIMED_DESPAWN, 15s))              { -                //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work -                Cyclone_Timer = 30000 + rand32() % 10000; - -                if (Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 5), TEMPSUMMON_TIMED_DESPAWN, 15s)) -                { -                    Cyclone->SetObjectScale(3.0f); -                    Cyclone->SetFaction(me->GetFaction()); -                    Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); -                    if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                        Cyclone->AI()->AttackStart(target); -                } +                Cyclone->SetObjectScale(3.0f); +                Cyclone->SetFaction(me->GetFaction()); +                Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); +                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                    Cyclone->AI()->AttackStart(target);              } -            else -                Cyclone_Timer -= diff; - -            //Heal_Timer -            if (Heal_Timer <= diff) -            { -                // It can be cast on any of the mobs -                Unit* unit = nullptr; +        } +        else +            Cyclone_Timer -= diff; -                while (unit == nullptr || !unit->IsAlive()) -                    unit = selectAdvisorUnit(); +        //Heal_Timer +        if (Heal_Timer <= diff) +        { +            // It can be cast on any of the mobs +            Unit* unit = nullptr; -                DoCast(unit, SPELL_HEAL); -                Heal_Timer = 60000; -            } -            else -                Heal_Timer -= diff; +            while (unit == nullptr || !unit->IsAlive()) +                unit = selectAdvisorUnit(); -            DoMeleeAttackIfReady(); +            DoCast(unit, SPELL_HEAL); +            Heal_Timer = 60000;          } +        else +            Heal_Timer -= diff; -        Unit* selectAdvisorUnit() +        DoMeleeAttackIfReady(); +    } + +    Unit* selectAdvisorUnit() +    { +        Unit* unit = nullptr; +        switch (rand32() % 4)          { -            Unit* unit = nullptr; -            switch (rand32() % 4) -            { -            case 0: -                unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESS)); -                break; -            case 1: -                unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_SHARKKIS)); -                break; -            case 2: -                unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_TIDALVESS)); -                break; -            case 3: -                unit = me; -                break; -            } -            return unit; +        case 0: +            unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_KARATHRESS)); +            break; +        case 1: +            unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_SHARKKIS)); +            break; +        case 2: +            unit = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_TIDALVESS)); +            break; +        case 3: +            unit = me; +            break;          } -    }; +        return unit; +    }  };  // 38358 - Tidal Surge @@ -735,9 +679,9 @@ class spell_fathomlord_karathress_tidal_surge : public SpellScript  void AddSC_boss_fathomlord_karathress()  { -    new boss_fathomlord_karathress(); -    new boss_fathomguard_sharkkis(); -    new boss_fathomguard_tidalvess(); -    new boss_fathomguard_caribdis(); +    RegisterSerpentshrineCavernCreatureAI(boss_fathomlord_karathress); +    RegisterSerpentshrineCavernCreatureAI(boss_fathomguard_sharkkis); +    RegisterSerpentshrineCavernCreatureAI(boss_fathomguard_tidalvess); +    RegisterSerpentshrineCavernCreatureAI(boss_fathomguard_caribdis);      RegisterSpellScript(spell_fathomlord_karathress_tidal_surge);  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp index 19fb7ef0cdd..f22d7fe791a 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp @@ -80,329 +80,304 @@ enum HydrossTheUnstable  #define SPAWN_X_DIFF4               12.577011f  #define SPAWN_Y_DIFF4               4.72702f -class boss_hydross_the_unstable : public CreatureScript +struct boss_hydross_the_unstable : public BossAI  { -public: -    boss_hydross_the_unstable() : CreatureScript("boss_hydross_the_unstable") { } +    boss_hydross_the_unstable(Creature* creature) : BossAI(creature, BOSS_HYDROSS_THE_UNSTABLE) +    { +        Initialize(); +    } + +    void Initialize() +    { +        beams[0].Clear(); +        beams[1].Clear(); +        PosCheck_Timer = 2500; +        MarkOfHydross_Timer = 15000; +        MarkOfCorruption_Timer = 15000; +        WaterTomb_Timer = 7000; +        VileSludge_Timer = 7000; +        MarkOfHydross_Count = 0; +        MarkOfCorruption_Count = 0; +        EnrageTimer = 600000; + +        CorruptedForm = false; +        beam = false; +    } -    CreatureAI* GetAI(Creature* creature) const override +    ObjectGuid beams[2]; +    uint32 PosCheck_Timer; +    uint32 MarkOfHydross_Timer; +    uint32 MarkOfCorruption_Timer; +    uint32 WaterTomb_Timer; +    uint32 VileSludge_Timer; +    uint32 MarkOfHydross_Count; +    uint32 MarkOfCorruption_Count; +    uint32 EnrageTimer; +    bool CorruptedForm; +    bool beam; + +    void Reset() override      { -        return GetSerpentshrineCavernAI<boss_hydross_the_unstableAI>(creature); +        DeSummonBeams(); +        Initialize(); + +        me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); +        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); +        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + +        me->SetDisplayId(MODEL_CLEAN); + +        _Reset();      } -    struct boss_hydross_the_unstableAI : public ScriptedAI +    void SummonBeams()      { -        boss_hydross_the_unstableAI(Creature* creature) : ScriptedAI(creature), Summons(me) +        Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -258.333f, -356.34f, 22.0499f, 5.90835f, TEMPSUMMON_CORPSE_DESPAWN); +        if (beamer)          { -            Initialize(); -            instance = creature->GetInstanceScript(); +            beamer->CastSpell(me, SPELL_BLUE_BEAM, true); +            beamer->SetDisplayId(11686);  //invisible +            beams[0] = beamer->GetGUID();          } - -        void Initialize() +        beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -219.918f, -371.308f, 22.0042f, 2.73072f, TEMPSUMMON_CORPSE_DESPAWN); +        if (beamer)          { -            beams[0].Clear(); -            beams[1].Clear(); -            PosCheck_Timer = 2500; -            MarkOfHydross_Timer = 15000; -            MarkOfCorruption_Timer = 15000; -            WaterTomb_Timer = 7000; -            VileSludge_Timer = 7000; -            MarkOfHydross_Count = 0; -            MarkOfCorruption_Count = 0; -            EnrageTimer = 600000; - -            CorruptedForm = false; -            beam = false; +            beamer->CastSpell(me, SPELL_BLUE_BEAM, true); +            beamer->SetDisplayId(11686);  //invisible +            beams[1] = beamer->GetGUID();          } +    } -        InstanceScript* instance; - -        ObjectGuid beams[2]; -        uint32 PosCheck_Timer; -        uint32 MarkOfHydross_Timer; -        uint32 MarkOfCorruption_Timer; -        uint32 WaterTomb_Timer; -        uint32 VileSludge_Timer; -        uint32 MarkOfHydross_Count; -        uint32 MarkOfCorruption_Count; -        uint32 EnrageTimer; -        bool CorruptedForm; -        bool beam; -        SummonList Summons; - -        void Reset() override +    void DeSummonBeams() +    { +        for (uint8 i = 0; i < 2; ++i)          { -            DeSummonBeams(); -            Initialize(); +            if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i])) +                mob->DespawnOrUnsummon(); +        } +    } -            me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); -            me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); -            me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); +    void JustEngagedWith(Unit* who) override +    { +        Talk(SAY_AGGRO); -            me->SetDisplayId(MODEL_CLEAN); +        _JustEngagedWith(who); +    } -            instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); -            Summons.DespawnAll(); -        } +    void KilledUnit(Unit* /*victim*/) override +    { +        Talk(CorruptedForm ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY); +    } -        void SummonBeams() -        { -            Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -258.333f, -356.34f, 22.0499f, 5.90835f, TEMPSUMMON_CORPSE_DESPAWN); -            if (beamer) -            { -                beamer->CastSpell(me, SPELL_BLUE_BEAM, true); -                beamer->SetDisplayId(11686);  //invisible -                beams[0] = beamer->GetGUID(); -            } -            beamer = me->SummonCreature(ENTRY_BEAM_DUMMY, -219.918f, -371.308f, 22.0042f, 2.73072f, TEMPSUMMON_CORPSE_DESPAWN); -            if (beamer) -            { -                beamer->CastSpell(me, SPELL_BLUE_BEAM, true); -                beamer->SetDisplayId(11686);  //invisible -                beams[1] = beamer->GetGUID(); -            } -        } -        void DeSummonBeams() -        { -            for (uint8 i = 0; i < 2; ++i) -            { -                if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i])) -                { -                    mob->DespawnOrUnsummon(); -                } -            } -        } -        void JustEngagedWith(Unit* /*who*/) override -        { -            Talk(SAY_AGGRO); +    void JustSummoned(Creature* summoned) override +    { +        if (summoned->GetEntry() == ENTRY_PURE_SPAWN) +            summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true); -            instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); -        } +        if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) +            summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true); -        void KilledUnit(Unit* /*victim*/) override -        { -            Talk(CorruptedForm ? SAY_CORRUPT_SLAY : SAY_CLEAN_SLAY); -        } +        BossAI::JustSummoned(summoned); +    } -        void JustSummoned(Creature* summoned) override -        { -            if (summoned->GetEntry() == ENTRY_PURE_SPAWN) -            { -                summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true); -                Summons.Summon(summoned); -            } -            if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) -            { -                summoned->CastSpell(summoned, SPELL_ELEMENTAL_SPAWNIN, true); -                Summons.Summon(summoned); -            } -        } +    void JustDied(Unit* /*killer*/) override +    { +        Talk(CorruptedForm ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH); -        void SummonedCreatureDespawn(Creature* summon) override -        { -            Summons.Despawn(summon); -        } +        _JustDied(); +    } -        void JustDied(Unit* /*killer*/) override +    void UpdateAI(uint32 diff) override +    { +        if (!beam)          { -            Talk(CorruptedForm ? SAY_CORRUPT_DEATH : SAY_CLEAN_DEATH); - -            instance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); -            Summons.DespawnAll(); +            SummonBeams(); +            beam = true;          } +        //Return since we have no target +        if (!UpdateVictim()) +            return; -        void UpdateAI(uint32 diff) override +        // corrupted form +        if (CorruptedForm)          { -            if (!beam) -            { -                SummonBeams(); -                beam = true; -            } -            //Return since we have no target -            if (!UpdateVictim()) -                return; - -            // corrupted form -            if (CorruptedForm) +            //MarkOfCorruption_Timer +            if (MarkOfCorruption_Timer <= diff)              { -                //MarkOfCorruption_Timer -                if (MarkOfCorruption_Timer <= diff) +                if (MarkOfCorruption_Count <= 5)                  { -                    if (MarkOfCorruption_Count <= 5) -                    { -                        uint32 mark_spell = 0; +                    uint32 mark_spell = 0; -                        switch (MarkOfCorruption_Count) -                        { -                            case 0: -                                mark_spell = SPELL_MARK_OF_CORRUPTION1; -                                break; +                    switch (MarkOfCorruption_Count) +                    { +                        case 0: +                            mark_spell = SPELL_MARK_OF_CORRUPTION1; +                            break; -                            case 1: -                                mark_spell = SPELL_MARK_OF_CORRUPTION2; -                                break; +                        case 1: +                            mark_spell = SPELL_MARK_OF_CORRUPTION2; +                            break; -                            case 2: -                                mark_spell = SPELL_MARK_OF_CORRUPTION3; -                                break; +                        case 2: +                            mark_spell = SPELL_MARK_OF_CORRUPTION3; +                            break; -                            case 3: -                                mark_spell = SPELL_MARK_OF_CORRUPTION4; -                                break; +                        case 3: +                            mark_spell = SPELL_MARK_OF_CORRUPTION4; +                            break; -                            case 4: -                                mark_spell = SPELL_MARK_OF_CORRUPTION5; -                                break; +                        case 4: +                            mark_spell = SPELL_MARK_OF_CORRUPTION5; +                            break; -                            case 5: -                                mark_spell = SPELL_MARK_OF_CORRUPTION6; -                                break; -                        } +                        case 5: +                            mark_spell = SPELL_MARK_OF_CORRUPTION6; +                            break; +                    } -                        DoCastVictim(mark_spell); +                    DoCastVictim(mark_spell); -                        if (MarkOfCorruption_Count < 5) -                            ++MarkOfCorruption_Count; -                    } +                    if (MarkOfCorruption_Count < 5) +                        ++MarkOfCorruption_Count; +                } -                    MarkOfCorruption_Timer = 15000; -                } else MarkOfCorruption_Timer -= diff; +                MarkOfCorruption_Timer = 15000; +            } else MarkOfCorruption_Timer -= diff; -                //VileSludge_Timer -                if (VileSludge_Timer <= diff) -                { -                    if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                        DoCast(target, SPELL_VILE_SLUDGE); +            //VileSludge_Timer +            if (VileSludge_Timer <= diff) +            { +                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                    DoCast(target, SPELL_VILE_SLUDGE); -                    VileSludge_Timer = 15000; -                } else VileSludge_Timer -= diff; +                VileSludge_Timer = 15000; +            } else VileSludge_Timer -= diff; -                //PosCheck_Timer -                if (PosCheck_Timer <= diff) +            //PosCheck_Timer +            if (PosCheck_Timer <= diff) +            { +                if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS))                  { -                    if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) -                    { -                        // switch to clean form -                        me->SetDisplayId(MODEL_CLEAN); -                        CorruptedForm = false; -                        MarkOfHydross_Count = 0; - -                        Talk(SAY_SWITCH_TO_CLEAN); -                        ResetThreatList(); -                        SummonBeams(); - -                        // spawn 4 adds -                        DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); - -                        me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); -                        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); -                        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); -                    } +                    // switch to clean form +                    me->SetDisplayId(MODEL_CLEAN); +                    CorruptedForm = false; +                    MarkOfHydross_Count = 0; + +                    Talk(SAY_SWITCH_TO_CLEAN); +                    ResetThreatList(); +                    SummonBeams(); + +                    // spawn 4 adds +                    DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); + +                    me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); +                    me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); +                    me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); +                } -                    PosCheck_Timer = 2500; -                } else PosCheck_Timer -=diff; -            } -            // clean form -            else +                PosCheck_Timer = 2500; +            } else PosCheck_Timer -=diff; +        } +        // clean form +        else +        { +            //MarkOfHydross_Timer +            if (MarkOfHydross_Timer <= diff)              { -                //MarkOfHydross_Timer -                if (MarkOfHydross_Timer <= diff) +                if (MarkOfHydross_Count <= 5)                  { -                    if (MarkOfHydross_Count <= 5) -                    { -                        uint32 mark_spell = 0; - -                        switch (MarkOfHydross_Count) -                        { -                            case 0: -                                mark_spell = SPELL_MARK_OF_HYDROSS1; -                                break; - -                            case 1: -                                mark_spell = SPELL_MARK_OF_HYDROSS2; -                                break; +                    uint32 mark_spell = 0; -                            case 2: -                                mark_spell = SPELL_MARK_OF_HYDROSS3; -                                break; +                    switch (MarkOfHydross_Count) +                    { +                        case 0: +                            mark_spell = SPELL_MARK_OF_HYDROSS1; +                            break; -                            case 3: -                                mark_spell = SPELL_MARK_OF_HYDROSS4; -                                break; +                        case 1: +                            mark_spell = SPELL_MARK_OF_HYDROSS2; +                            break; -                            case 4: -                                mark_spell = SPELL_MARK_OF_HYDROSS5; -                                break; +                        case 2: +                            mark_spell = SPELL_MARK_OF_HYDROSS3; +                            break; -                            case 5: -                                mark_spell = SPELL_MARK_OF_HYDROSS6; -                                break; -                        } +                        case 3: +                            mark_spell = SPELL_MARK_OF_HYDROSS4; +                            break; -                        DoCastVictim(mark_spell); +                        case 4: +                            mark_spell = SPELL_MARK_OF_HYDROSS5; +                            break; -                        if (MarkOfHydross_Count < 5) -                            ++MarkOfHydross_Count; +                        case 5: +                            mark_spell = SPELL_MARK_OF_HYDROSS6; +                            break;                      } -                    MarkOfHydross_Timer = 15000; -                } else MarkOfHydross_Timer -= diff; +                    DoCastVictim(mark_spell); -                //WaterTomb_Timer -                if (WaterTomb_Timer <= diff) -                { -                    Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true); -                    if (target) -                        DoCast(target, SPELL_WATER_TOMB); +                    if (MarkOfHydross_Count < 5) +                        ++MarkOfHydross_Count; +                } -                    WaterTomb_Timer = 7000; -                } else WaterTomb_Timer -= diff; +                MarkOfHydross_Timer = 15000; +            } else MarkOfHydross_Timer -= diff; -                //PosCheck_Timer -                if (PosCheck_Timer <= diff) -                { -                    if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) -                    { -                        // switch to corrupted form -                        me->SetDisplayId(MODEL_CORRUPT); -                        MarkOfCorruption_Count = 0; -                        CorruptedForm = true; - -                        Talk(SAY_SWITCH_TO_CORRUPT); -                        ResetThreatList(); -                        DeSummonBeams(); - -                        // spawn 4 adds -                        DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); -                        DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); - -                        me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); -                        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); -                        me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); -                    } +            //WaterTomb_Timer +            if (WaterTomb_Timer <= diff) +            { +                Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true); +                if (target) +                    DoCast(target, SPELL_WATER_TOMB); -                    PosCheck_Timer = 2500; -                } else PosCheck_Timer -=diff; -            } +                WaterTomb_Timer = 7000; +            } else WaterTomb_Timer -= diff; -            //EnrageTimer -            if (EnrageTimer <= diff) +            //PosCheck_Timer +            if (PosCheck_Timer <= diff)              { -                DoCast(me, SPELL_ENRAGE); -                EnrageTimer = 60000; -            } else EnrageTimer -= diff; +                if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) +                { +                    // switch to corrupted form +                    me->SetDisplayId(MODEL_CORRUPT); +                    MarkOfCorruption_Count = 0; +                    CorruptedForm = true; + +                    Talk(SAY_SWITCH_TO_CORRUPT); +                    ResetThreatList(); +                    DeSummonBeams(); + +                    // spawn 4 adds +                    DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); +                    DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0s); + +                    me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); +                    me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); +                    me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); +                } -            DoMeleeAttackIfReady(); +                PosCheck_Timer = 2500; +            } else PosCheck_Timer -=diff;          } -    }; + +        //EnrageTimer +        if (EnrageTimer <= diff) +        { +            DoCast(me, SPELL_ENRAGE); +            EnrageTimer = 60000; +        } else EnrageTimer -= diff; + +        DoMeleeAttackIfReady(); +    }  };  void AddSC_boss_hydross_the_unstable()  { -    new boss_hydross_the_unstable(); +    RegisterSerpentshrineCavernCreatureAI(boss_hydross_the_unstable);  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index cccd2184da3..6cec120340f 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -131,745 +131,684 @@ float ShieldGeneratorChannelPos[4][4] =      {49.3126f, -943.398f, 42.5501f, 2.40174f}  }; -class boss_lady_vashj : public CreatureScript +struct boss_lady_vashj : public BossAI  { -public: -    boss_lady_vashj() : CreatureScript("boss_lady_vashj") { } +    boss_lady_vashj(Creature* creature) : BossAI(creature, BOSS_LADY_VASHJ) +    { +        Initialize(); +        instance = creature->GetInstanceScript(); +        Intro = false; +        JustCreated = true; +        CanAttack = false; +        creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // set it only once on Creature create (no need do intro if wiped) +    } -    CreatureAI* GetAI(Creature* creature) const override +    void Initialize()      { -        return GetSerpentshrineCavernAI<boss_lady_vashjAI>(creature); +        AggroTimer = 19000; +        ShockBlastTimer = 1 + rand32() % 60000; +        EntangleTimer = 30000; +        StaticChargeTimer = 10000 + rand32() % 15000; +        ForkedLightningTimer = 2000; +        CheckTimer = 15000; +        EnchantedElementalTimer = 5000; +        TaintedElementalTimer = 50000; +        CoilfangEliteTimer = 45000 + rand32() % 5000; +        CoilfangStriderTimer = 60000 + rand32() % 10000; +        SummonSporebatTimer = 10000; +        SummonSporebatStaticTimer = 30000; +        EnchantedElementalPos = 0; +        Phase = 0; + +        Entangle = false;      } -    struct boss_lady_vashjAI : public ScriptedAI +    InstanceScript* instance; + +    ObjectGuid ShieldGeneratorChannel[4]; + +    uint32 AggroTimer; +    uint32 ShockBlastTimer; +    uint32 EntangleTimer; +    uint32 StaticChargeTimer; +    uint32 ForkedLightningTimer; +    uint32 CheckTimer; +    uint32 EnchantedElementalTimer; +    uint32 TaintedElementalTimer; +    uint32 CoilfangEliteTimer; +    uint32 CoilfangStriderTimer; +    uint32 SummonSporebatTimer; +    uint32 SummonSporebatStaticTimer; +    uint8 EnchantedElementalPos; +    uint8 Phase; + +    bool Entangle; +    bool Intro; +    bool CanAttack; +    bool JustCreated; + +    void Reset() override      { -        boss_lady_vashjAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -            Intro = false; -            JustCreated = true; -            CanAttack = false; -            creature->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // set it only once on Creature create (no need do intro if wiped) -        } +        Initialize(); -        void Initialize() +        if (JustCreated)          { -            AggroTimer = 19000; -            ShockBlastTimer = 1 + rand32() % 60000; -            EntangleTimer = 30000; -            StaticChargeTimer = 10000 + rand32() % 15000; -            ForkedLightningTimer = 2000; -            CheckTimer = 15000; -            EnchantedElementalTimer = 5000; -            TaintedElementalTimer = 50000; -            CoilfangEliteTimer = 45000 + rand32() % 5000; -            CoilfangStriderTimer = 60000 + rand32() % 10000; -            SummonSporebatTimer = 10000; -            SummonSporebatStaticTimer = 30000; -            EnchantedElementalPos = 0; -            Phase = 0; - -            Entangle = false; -        } +            CanAttack = false; +            JustCreated = false; +        } else CanAttack = true; -        InstanceScript* instance; - -        ObjectGuid ShieldGeneratorChannel[4]; - -        uint32 AggroTimer; -        uint32 ShockBlastTimer; -        uint32 EntangleTimer; -        uint32 StaticChargeTimer; -        uint32 ForkedLightningTimer; -        uint32 CheckTimer; -        uint32 EnchantedElementalTimer; -        uint32 TaintedElementalTimer; -        uint32 CoilfangEliteTimer; -        uint32 CoilfangStriderTimer; -        uint32 SummonSporebatTimer; -        uint32 SummonSporebatStaticTimer; -        uint8 EnchantedElementalPos; -        uint8 Phase; - -        bool Entangle; -        bool Intro; -        bool CanAttack; -        bool JustCreated; - -        void Reset() override +        for (uint8 i = 0; i < 4; ++i)          { -            Initialize(); - -            if (JustCreated) -            { -                CanAttack = false; -                JustCreated = false; -            } else CanAttack = true; - -            for (uint8 i = 0; i < 4; ++i) +            if (!ShieldGeneratorChannel[i].IsEmpty())              { -                if (!ShieldGeneratorChannel[i].IsEmpty()) +                if (Unit* remo = ObjectAccessor::GetUnit(*me, ShieldGeneratorChannel[i]))                  { -                    if (Unit* remo = ObjectAccessor::GetUnit(*me, ShieldGeneratorChannel[i])) -                    { -                        remo->setDeathState(JUST_DIED); -                        ShieldGeneratorChannel[i].Clear(); -                    } +                    remo->setDeathState(JUST_DIED); +                    ShieldGeneratorChannel[i].Clear();                  }              } +        } -            instance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); +        _Reset(); -            me->SetCorpseDelay(1000*60*60); -        } +        me->SetCorpseDelay(1000*60*60); +    } -        // Called when a tainted elemental dies -        void EventTaintedElementalDeath() -        { -            // the next will spawn 50 seconds after the previous one's death -            if (TaintedElementalTimer > 50000) -                TaintedElementalTimer = 50000; -        } -        void KilledUnit(Unit* /*victim*/) override -        { -            Talk(SAY_SLAY); -        } +    // Called when a tainted elemental dies +    void EventTaintedElementalDeath() +    { +        // the next will spawn 50 seconds after the previous one's death +        if (TaintedElementalTimer > 50000) +            TaintedElementalTimer = 50000; +    } +    void KilledUnit(Unit* /*victim*/) override +    { +        Talk(SAY_SLAY); +    } -        void JustDied(Unit* /*killer*/) override -        { -            Talk(SAY_DEATH); +    void JustDied(Unit* /*killer*/) override +    { +        Talk(SAY_DEATH); -            instance->SetData(DATA_LADYVASHJEVENT, DONE); -        } +        _JustDied(); +    } -        void StartEvent() -        { -            Talk(SAY_AGGRO); +    void StartEvent(Unit* who) +    { +        Talk(SAY_AGGRO); -            Phase = 1; +        Phase = 1; -            instance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); -        } +        _JustEngagedWith(who); +    } -        void JustEngagedWith(Unit* who) override -        { -            // remove old tainted cores to prevent cheating in phase 2 -            Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); -            for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) -                if (Player* player = itr->GetSource()) -                    player->DestroyItemCount(31088, 1, true); -            StartEvent(); // this is JustEngagedWith(), so were are 100% in combat, start the event - -            if (Phase != 2) -                AttackStart(who); -        } +    void JustEngagedWith(Unit* who) override +    { +        // remove old tainted cores to prevent cheating in phase 2 +        Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); +        for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) +            if (Player* player = itr->GetSource()) +                player->DestroyItemCount(31088, 1, true); +        StartEvent(who); // this is JustEngagedWith(), so were are 100% in combat, start the event -        void MoveInLineOfSight(Unit* who) override +        if (Phase != 2) +            AttackStart(who); +    } + +    void MoveInLineOfSight(Unit* who) override +    { +        if (!Intro)          { -            if (!Intro) -            { -                Intro = true; -                Talk(SAY_INTRO); -            } -            if (!CanAttack) -                return; -            if (!who || me->GetVictim()) -                return; +            Intro = true; +            Talk(SAY_INTRO); +        } +        if (!CanAttack) +            return; +        if (!who || me->GetVictim()) +            return; -            if (me->CanCreatureAttack(who)) +        if (me->CanCreatureAttack(who)) +        { +            float attackRadius = me->GetAttackDistance(who); +            if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who))              { -                float attackRadius = me->GetAttackDistance(who); -                if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) -                { -                    if (!me->IsInCombat()) // AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking -                        StartEvent(); +                if (!me->IsInCombat()) // AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking +                    StartEvent(who); -                    if (Phase != 2) -                        AttackStart(who); -                } +                if (Phase != 2) +                    AttackStart(who);              }          } +    } -        void CastShootOrMultishot() +    void CastShootOrMultishot() +    { +        switch (urand(0, 1))          { -            switch (urand(0, 1)) -            { -                case 0: -                    // Shoot -                    // Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. -                    DoCastVictim(SPELL_SHOOT); -                    break; -                case 1: -                    // Multishot -                    // Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. -                    DoCastVictim(SPELL_MULTI_SHOT); -                    break; -            } -            if (rand32() % 3) -            { -                Talk(SAY_BOWSHOT); -            } +            case 0: +                // Shoot +                // Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. +                DoCastVictim(SPELL_SHOOT); +                break; +            case 1: +                // Multishot +                // Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. +                DoCastVictim(SPELL_MULTI_SHOT); +                break; +        } +        if (rand32() % 3) +        { +            Talk(SAY_BOWSHOT);          } +    } -        void UpdateAI(uint32 diff) override +    void UpdateAI(uint32 diff) override +    { +        if (!CanAttack && Intro)          { -            if (!CanAttack && Intro) +            if (AggroTimer <= diff)              { -                if (AggroTimer <= diff) -                { -                    CanAttack = true; -                    me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); -                    AggroTimer=19000; -                } -                else -                { -                    AggroTimer -= diff; -                    return; -                } +                CanAttack = true; +                me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); +                AggroTimer=19000;              } -            // to prevent abuses during phase 2 -            if (Phase == 2 && !me->GetVictim() && me->IsInCombat()) +            else              { -                EnterEvadeMode(); +                AggroTimer -= diff;                  return;              } -            // Return since we have no target -            if (!UpdateVictim()) -                return; +        } +        // to prevent abuses during phase 2 +        if (Phase == 2 && !me->GetVictim() && me->IsInCombat()) +        { +            EnterEvadeMode(); +            return; +        } +        // Return since we have no target +        if (!UpdateVictim()) +            return; -            if (Phase == 1 || Phase == 3) +        if (Phase == 1 || Phase == 3) +        { +            // ShockBlastTimer +            if (ShockBlastTimer <= diff)              { -                // ShockBlastTimer -                if (ShockBlastTimer <= diff) -                { -                    // Shock Burst -                    // Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. -                    DoCastVictim(SPELL_SHOCK_BLAST); +                // Shock Burst +                // Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. +                DoCastVictim(SPELL_SHOCK_BLAST); -                    ShockBlastTimer = 1000 + rand32() % 14000;       // random cooldown -                } else ShockBlastTimer -= diff; +                ShockBlastTimer = 1000 + rand32() % 14000;       // random cooldown +            } else ShockBlastTimer -= diff; -                // StaticChargeTimer -                if (StaticChargeTimer <= diff) -                { -                    // Static Charge -                    // Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. -                    Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200, true); -                    if (target && !target->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) -                        DoCast(target, SPELL_STATIC_CHARGE_TRIGGER); // cast Static Charge every 2 seconds for 20 seconds +            // StaticChargeTimer +            if (StaticChargeTimer <= diff) +            { +                // Static Charge +                // Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. +                Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200, true); +                if (target && !target->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) +                    DoCast(target, SPELL_STATIC_CHARGE_TRIGGER); // cast Static Charge every 2 seconds for 20 seconds -                    StaticChargeTimer = 10000 + rand32() % 20000; -                } else StaticChargeTimer -= diff; +                StaticChargeTimer = 10000 + rand32() % 20000; +            } else StaticChargeTimer -= diff; -                // EntangleTimer -                if (EntangleTimer <= diff) +            // EntangleTimer +            if (EntangleTimer <= diff) +            { +                if (!Entangle)                  { -                    if (!Entangle) -                    { -                        // Entangle -                        // Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. -                        DoCastVictim(SPELL_ENTANGLE); -                        Entangle = true; -                        EntangleTimer = 10000; -                    } -                    else -                    { -                        CastShootOrMultishot(); -                        Entangle = false; -                        EntangleTimer = 20000 + rand32() % 5000; -                    } -                } else EntangleTimer -= diff; +                    // Entangle +                    // Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. +                    DoCastVictim(SPELL_ENTANGLE); +                    Entangle = true; +                    EntangleTimer = 10000; +                } +                else +                { +                    CastShootOrMultishot(); +                    Entangle = false; +                    EntangleTimer = 20000 + rand32() % 5000; +                } +            } else EntangleTimer -= diff; -                // Phase 1 -                if (Phase == 1) +            // Phase 1 +            if (Phase == 1) +            { +                // Start phase 2 +                if (HealthBelowPct(70))                  { -                    // Start phase 2 -                    if (HealthBelowPct(70)) -                    { -                        // Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. -                        Phase = 2; +                    // Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. +                    Phase = 2; -                        me->GetMotionMaster()->Clear(); -                        DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); +                    me->GetMotionMaster()->Clear(); +                    DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); -                        for (uint8 i = 0; i < 4; ++i) -                            if (Creature* creature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0],  ShieldGeneratorChannelPos[i][1],  ShieldGeneratorChannelPos[i][2],  ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN)) -                                ShieldGeneratorChannel[i] = creature->GetGUID(); +                    for (uint8 i = 0; i < 4; ++i) +                        if (Creature* creature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0],  ShieldGeneratorChannelPos[i][1],  ShieldGeneratorChannelPos[i][2],  ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN)) +                            ShieldGeneratorChannel[i] = creature->GetGUID(); -                        Talk(SAY_PHASE2); -                    } +                    Talk(SAY_PHASE2);                  } -                // Phase 3 -                else +            } +            // Phase 3 +            else +            { +                // SummonSporebatTimer +                if (SummonSporebatTimer <= diff)                  { -                    // SummonSporebatTimer -                    if (SummonSporebatTimer <= diff) -                    { -                        if (Creature* sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN)) -                            if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                                sporebat->AI()->AttackStart(target); +                    if (Creature* sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN)) +                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                            sporebat->AI()->AttackStart(target); -                        // summon sporebats faster and faster -                        if (SummonSporebatStaticTimer > 1000) -                            SummonSporebatStaticTimer -= 1000; +                    // summon sporebats faster and faster +                    if (SummonSporebatStaticTimer > 1000) +                        SummonSporebatStaticTimer -= 1000; -                        SummonSporebatTimer = SummonSporebatStaticTimer; +                    SummonSporebatTimer = SummonSporebatStaticTimer; -                        if (SummonSporebatTimer < 5000) -                            SummonSporebatTimer = 5000; +                    if (SummonSporebatTimer < 5000) +                        SummonSporebatTimer = 5000; -                    } else SummonSporebatTimer -= diff; -                } +                } else SummonSporebatTimer -= diff; +            } -                // Melee attack -                DoMeleeAttackIfReady(); +            // Melee attack +            DoMeleeAttackIfReady(); -                // CheckTimer - used to check if somebody is in melee range -                if (CheckTimer <= diff) +            // CheckTimer - used to check if somebody is in melee range +            if (CheckTimer <= diff) +            { +                bool inMeleeRange = false; +                for (auto* ref : me->GetThreatManager().GetUnsortedThreatList())                  { -                    bool inMeleeRange = false; -                    for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) +                    Unit* target = ref->GetVictim(); +                    if (target->IsWithinMeleeRange(me)) // if in melee range                      { -                        Unit* target = ref->GetVictim(); -                        if (target->IsWithinMeleeRange(me)) // if in melee range -                        { -                            inMeleeRange = true; -                            break; -                        } +                        inMeleeRange = true; +                        break;                      } +                } -                    // if nobody is in melee range -                    if (!inMeleeRange) -                        CastShootOrMultishot(); +                // if nobody is in melee range +                if (!inMeleeRange) +                    CastShootOrMultishot(); -                    CheckTimer = 5000; -                } else CheckTimer -= diff; -            } -            // Phase 2 -            else +                CheckTimer = 5000; +            } else CheckTimer -= diff; +        } +        // Phase 2 +        else +        { +            // ForkedLightningTimer +            if (ForkedLightningTimer <= diff)              { -                // ForkedLightningTimer -                if (ForkedLightningTimer <= diff) -                { -                    // Forked Lightning -                    // Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. -                    Unit* target = SelectTarget(SelectTargetMethod::Random, 0); +                // Forked Lightning +                // Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. +                Unit* target = SelectTarget(SelectTargetMethod::Random, 0); -                    if (!target) -                        target = me->GetVictim(); +                if (!target) +                    target = me->GetVictim(); -                    DoCast(target, SPELL_FORKED_LIGHTNING); +                DoCast(target, SPELL_FORKED_LIGHTNING); -                    ForkedLightningTimer = 2000 + rand32() % 6000; -                } else ForkedLightningTimer -= diff; +                ForkedLightningTimer = 2000 + rand32() % 6000; +            } else ForkedLightningTimer -= diff; -                // EnchantedElementalTimer -                if (EnchantedElementalTimer <= diff) -                { -                    me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElementalPos][0], ElementPos[EnchantedElementalPos][1], ElementPos[EnchantedElementalPos][2], ElementPos[EnchantedElementalPos][3], TEMPSUMMON_CORPSE_DESPAWN); +            // EnchantedElementalTimer +            if (EnchantedElementalTimer <= diff) +            { +                me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElementalPos][0], ElementPos[EnchantedElementalPos][1], ElementPos[EnchantedElementalPos][2], ElementPos[EnchantedElementalPos][3], TEMPSUMMON_CORPSE_DESPAWN); -                    if (EnchantedElementalPos == 7) -                        EnchantedElementalPos = 0; -                    else -                        ++EnchantedElementalPos; +                if (EnchantedElementalPos == 7) +                    EnchantedElementalPos = 0; +                else +                    ++EnchantedElementalPos; -                    EnchantedElementalTimer = 10000 + rand32() % 5000; -                } else EnchantedElementalTimer -= diff; +                EnchantedElementalTimer = 10000 + rand32() % 5000; +            } else EnchantedElementalTimer -= diff; -                // TaintedElementalTimer -                if (TaintedElementalTimer <= diff) -                { -                    uint32 pos = rand32() % 8; -                    me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN); +            // TaintedElementalTimer +            if (TaintedElementalTimer <= diff) +            { +                uint32 pos = rand32() % 8; +                me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN); -                    TaintedElementalTimer = 120000; -                } else TaintedElementalTimer -= diff; +                TaintedElementalTimer = 120000; +            } else TaintedElementalTimer -= diff; -                // CoilfangEliteTimer -                if (CoilfangEliteTimer <= diff) +            // CoilfangEliteTimer +            if (CoilfangEliteTimer <= diff) +            { +                uint32 pos = rand32() % 3; +                Creature* coilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s); +                if (coilfangElite)                  { -                    uint32 pos = rand32() % 3; -                    Creature* coilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s); -                    if (coilfangElite) -                    { -                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                            coilfangElite->AI()->AttackStart(target); -                        else if (me->GetVictim()) -                            coilfangElite->AI()->AttackStart(me->GetVictim()); -                    } -                    CoilfangEliteTimer = 45000 + rand32() % 5000; -                } else CoilfangEliteTimer -= diff; +                    if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                        coilfangElite->AI()->AttackStart(target); +                    else if (me->GetVictim()) +                        coilfangElite->AI()->AttackStart(me->GetVictim()); +                } +                CoilfangEliteTimer = 45000 + rand32() % 5000; +            } else CoilfangEliteTimer -= diff; -                // CoilfangStriderTimer -                if (CoilfangStriderTimer <= diff) +            // CoilfangStriderTimer +            if (CoilfangStriderTimer <= diff) +            { +                uint32 pos = rand32() % 3; +                if (Creature* CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s))                  { -                    uint32 pos = rand32() % 3; -                    if (Creature* CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s)) -                    { -                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                            CoilfangStrider->AI()->AttackStart(target); -                        else if (me->GetVictim()) -                            CoilfangStrider->AI()->AttackStart(me->GetVictim()); -                    } -                    CoilfangStriderTimer = 60000 + rand32() % 10000; -                } else CoilfangStriderTimer -= diff; +                    if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                        CoilfangStrider->AI()->AttackStart(target); +                    else if (me->GetVictim()) +                        CoilfangStrider->AI()->AttackStart(me->GetVictim()); +                } +                CoilfangStriderTimer = 60000 + rand32() % 10000; +            } else CoilfangStriderTimer -= diff; -                // CheckTimer -                if (CheckTimer <= diff) +            // CheckTimer +            if (CheckTimer <= diff) +            { +                // Start Phase 3 +                if (instance->GetData(DATA_CANSTARTPHASE3))                  { -                    // Start Phase 3 -                    if (instance->GetData(DATA_CANSTARTPHASE3)) -                    { -                        // set life 50% -                        me->SetHealth(me->CountPctFromMaxHealth(50)); +                    // set life 50% +                    me->SetHealth(me->CountPctFromMaxHealth(50)); -                        me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); +                    me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); -                        Talk(SAY_PHASE3); +                    Talk(SAY_PHASE3); -                        Phase = 3; +                    Phase = 3; -                        // return to the tank -                        me->GetMotionMaster()->MoveChase(me->GetVictim()); -                    } -                    CheckTimer = 1000; -                } else CheckTimer -= diff; -            } +                    // return to the tank +                    me->GetMotionMaster()->MoveChase(me->GetVictim()); +                } +                CheckTimer = 1000; +            } else CheckTimer -= diff;          } -    }; - +    }  };  // Enchanted Elemental  // If one of them reaches Vashj he will increase her damage done by 5%. -class npc_enchanted_elemental : public CreatureScript +struct npc_enchanted_elemental : public ScriptedAI  { -public: -    npc_enchanted_elemental() : CreatureScript("npc_enchanted_elemental") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_enchanted_elemental(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_enchanted_elementalAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript();      } -    struct npc_enchanted_elementalAI : public ScriptedAI +    void Initialize()      { -        npc_enchanted_elementalAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } +        Move = 0; +        Phase = 1; -        void Initialize() -        { -            Move = 0; -            Phase = 1; +        X = ElementWPPos[0][0]; +        Y = ElementWPPos[0][1]; +        Z = ElementWPPos[0][2]; +    } -            X = ElementWPPos[0][0]; -            Y = ElementWPPos[0][1]; -            Z = ElementWPPos[0][2]; -        } +    InstanceScript* instance; +    uint32 Move; +    uint32 Phase; +    float X, Y, Z; -        InstanceScript* instance; -        uint32 Move; -        uint32 Phase; -        float X, Y, Z; +    ObjectGuid VashjGUID; -        ObjectGuid VashjGUID; +    void Reset() override +    { +        me->SetSpeedRate(MOVE_WALK, 0.6f); // walk +        me->SetSpeedRate(MOVE_RUN, 0.6f); // run +        Initialize(); -        void Reset() override +        //search for nearest waypoint (up on stairs) +        for (uint32 i = 1; i < 8; ++i)          { -            me->SetSpeedRate(MOVE_WALK, 0.6f); // walk -            me->SetSpeedRate(MOVE_RUN, 0.6f); // run -            Initialize(); - -            //search for nearest waypoint (up on stairs) -            for (uint32 i = 1; i < 8; ++i) +            if (me->GetDistance(ElementWPPos[i][0], ElementWPPos[i][1], ElementWPPos[i][2]) < me->GetDistance(X, Y, Z))              { -                if (me->GetDistance(ElementWPPos[i][0], ElementWPPos[i][1], ElementWPPos[i][2]) < me->GetDistance(X, Y, Z)) -                { -                    X = ElementWPPos[i][0]; -                    Y = ElementWPPos[i][1]; -                    Z = ElementWPPos[i][2]; -                } +                X = ElementWPPos[i][0]; +                Y = ElementWPPos[i][1]; +                Z = ElementWPPos[i][2];              } - -            VashjGUID = instance->GetGuidData(DATA_LADYVASHJ);          } -        void JustEngagedWith(Unit* /*who*/) override { } +        VashjGUID = instance->GetGuidData(DATA_LADYVASHJ); +    } -        void MoveInLineOfSight(Unit* /*who*/) override { } +    void JustEngagedWith(Unit* /*who*/) override { } -        void UpdateAI(uint32 diff) override -        { -            if (!VashjGUID) -                return; +    void MoveInLineOfSight(Unit* /*who*/) override { } -            if (Move <= diff) -            { -                me->SetWalk(true); -                if (Phase == 1) -                    me->GetMotionMaster()->MovePoint(0, X, Y, Z); -                if (Phase == 1 && me->IsWithinDist3d(X, Y, Z, 0.1f)) -                    Phase = 2; -                if (Phase == 2) -                { -                    me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); -                    Phase = 3; -                } -                if (Phase == 3) -                { -                    me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); -                    if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) -                        DoCast(me, SPELL_SURGE); -                } -                if (Creature* vashj = ObjectAccessor::GetCreature(*me, VashjGUID)) -                    if (!vashj->IsInCombat() || ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, vashj->AI())->Phase != 2 || vashj->isDead()) -                        me->KillSelf(); -                Move = 1000; -            } else Move -= diff; -        } -    }; +    void UpdateAI(uint32 diff) override +    { +        if (!VashjGUID) +            return; +        if (Move <= diff) +        { +            me->SetWalk(true); +            if (Phase == 1) +                me->GetMotionMaster()->MovePoint(0, X, Y, Z); +            if (Phase == 1 && me->IsWithinDist3d(X, Y, Z, 0.1f)) +                Phase = 2; +            if (Phase == 2) +            { +                me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); +                Phase = 3; +            } +            if (Phase == 3) +            { +                me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); +                if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) +                    DoCast(me, SPELL_SURGE); +            } +            if (Creature* vashj = ObjectAccessor::GetCreature(*me, VashjGUID)) +                if (!vashj->IsInCombat() || ENSURE_AI(boss_lady_vashj, vashj->AI())->Phase != 2 || vashj->isDead()) +                    me->KillSelf(); +            Move = 1000; +        } else Move -= diff; +    }  };  // Tainted Elemental  // This mob has 7, 900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3, 000 nature damage and placing a posion doing 2, 000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental -class npc_tainted_elemental : public CreatureScript +struct npc_tainted_elemental : public ScriptedAI  { -public: -    npc_tainted_elemental() : CreatureScript("npc_tainted_elemental") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_tainted_elemental(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_tainted_elementalAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript();      } -    struct npc_tainted_elementalAI : public ScriptedAI +    void Initialize()      { -        npc_tainted_elementalAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } - -        void Initialize() -        { -            PoisonBoltTimer = 5000 + rand32() % 5000; -            DespawnTimer = 30000; -        } +        PoisonBoltTimer = 5000 + rand32() % 5000; +        DespawnTimer = 30000; +    } -        InstanceScript* instance; +    InstanceScript* instance; -        uint32 PoisonBoltTimer; -        uint32 DespawnTimer; +    uint32 PoisonBoltTimer; +    uint32 DespawnTimer; -        void Reset() override -        { -            Initialize(); -        } +    void Reset() override +    { +        Initialize(); +    } -        void JustDied(Unit* /*killer*/) override -        { -            if (Creature* vashj = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_LADYVASHJ))) -                ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, vashj->AI())->EventTaintedElementalDeath(); -        } +    void JustDied(Unit* /*killer*/) override +    { +        if (Creature* vashj = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_LADYVASHJ))) +            ENSURE_AI(boss_lady_vashj, vashj->AI())->EventTaintedElementalDeath(); +    } -        void JustEngagedWith(Unit* who) override -        { -            AddThreat(who, 0.1f); -        } +    void JustEngagedWith(Unit* who) override +    { +        AddThreat(who, 0.1f); +    } -        void UpdateAI(uint32 diff) override +    void UpdateAI(uint32 diff) override +    { +        // PoisonBoltTimer +        if (PoisonBoltTimer <= diff)          { -            // PoisonBoltTimer -            if (PoisonBoltTimer <= diff) -            { -                Unit* target = SelectTarget(SelectTargetMethod::Random, 0); - -                if (target && target->IsWithinDistInMap(me, 30)) -                    DoCast(target, SPELL_POISON_BOLT); +            Unit* target = SelectTarget(SelectTargetMethod::Random, 0); -                PoisonBoltTimer = 5000 + rand32() % 5000; -            } else PoisonBoltTimer -= diff; +            if (target && target->IsWithinDistInMap(me, 30)) +                DoCast(target, SPELL_POISON_BOLT); -            // DespawnTimer -            if (DespawnTimer <= diff) -            { -                // call Unsummon() -                me->setDeathState(DEAD); +            PoisonBoltTimer = 5000 + rand32() % 5000; +        } else PoisonBoltTimer -= diff; -                // to prevent crashes -                DespawnTimer = 1000; -            } else DespawnTimer -= diff; -        } -    }; +        // DespawnTimer +        if (DespawnTimer <= diff) +        { +            // call Unsummon() +            me->setDeathState(DEAD); +            // to prevent crashes +            DespawnTimer = 1000; +        } else DespawnTimer -= diff; +    }  };  //Toxic Sporebat  //Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. -class npc_toxic_sporebat : public CreatureScript +struct npc_toxic_sporebat : public ScriptedAI  { -public: -    npc_toxic_sporebat() : CreatureScript("npc_toxic_sporebat") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_toxic_sporebat(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_toxic_sporebatAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript(); +        EnterEvadeMode();      } -    struct npc_toxic_sporebatAI : public ScriptedAI +    void Initialize()      { -        npc_toxic_sporebatAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -            EnterEvadeMode(); -        } +        MovementTimer = 0; +        ToxicSporeTimer = 5000; +        BoltTimer = 5500; +        CheckTimer = 1000; +    } -        void Initialize() -        { -            MovementTimer = 0; -            ToxicSporeTimer = 5000; -            BoltTimer = 5500; -            CheckTimer = 1000; -        } +    InstanceScript* instance; -        InstanceScript* instance; +    uint32 MovementTimer; +    uint32 ToxicSporeTimer; +    uint32 BoltTimer; +    uint32 CheckTimer; -        uint32 MovementTimer; -        uint32 ToxicSporeTimer; -        uint32 BoltTimer; -        uint32 CheckTimer; +    void Reset() override +    { +        me->SetDisableGravity(true); +        me->SetFaction(FACTION_MONSTER); +        Initialize(); +    } -        void Reset() override -        { -            me->SetDisableGravity(true); -            me->SetFaction(FACTION_MONSTER); -            Initialize(); -        } +    void MoveInLineOfSight(Unit* /*who*/) override +    { +    } -        void MoveInLineOfSight(Unit* /*who*/) override +    void MovementInform(uint32 type, uint32 id) override +    { +        if (type != POINT_MOTION_TYPE) +            return; -        { -        } +        if (id == 1) +            MovementTimer = 0; +    } -        void MovementInform(uint32 type, uint32 id) override +    void UpdateAI(uint32 diff) override +    { +        // Random movement +        if (MovementTimer <= diff)          { -            if (type != POINT_MOTION_TYPE) -                return; - -            if (id == 1) -                MovementTimer = 0; -        } +            uint32 rndpos = rand32() % 8; +            me->GetMotionMaster()->MovePoint(1, SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); +            MovementTimer = 6000; +        } else MovementTimer -= diff; -        void UpdateAI(uint32 diff) override +        // toxic spores +        if (BoltTimer <= diff)          { -            // Random movement -            if (MovementTimer <= diff) -            { -                uint32 rndpos = rand32() % 8; -                me->GetMotionMaster()->MovePoint(1, SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); -                MovementTimer = 6000; -            } else MovementTimer -= diff; - -            // toxic spores -            if (BoltTimer <= diff) +            if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))              { -                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                if (Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30s))                  { -                    if (Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30s)) -                    { -                        trig->SetFaction(FACTION_MONSTER); -                        trig->CastSpell(trig, SPELL_TOXIC_SPORES, true); -                    } +                    trig->SetFaction(FACTION_MONSTER); +                    trig->CastSpell(trig, SPELL_TOXIC_SPORES, true);                  } -                BoltTimer = 10000 + rand32() % 5000;              } -            else BoltTimer -= diff; +            BoltTimer = 10000 + rand32() % 5000; +        } +        else BoltTimer -= diff; -            // CheckTimer -            if (CheckTimer <= diff) +        // CheckTimer +        if (CheckTimer <= diff) +        { +            // check if vashj is death +            Unit* Vashj = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LADYVASHJ)); +            if (!Vashj || !Vashj->IsAlive() || ENSURE_AI(boss_lady_vashj, Vashj->ToCreature()->AI())->Phase != 3)              { -                // check if vashj is death -                Unit* Vashj = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LADYVASHJ)); -                if (!Vashj || !Vashj->IsAlive() || ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, Vashj->ToCreature()->AI())->Phase != 3) -                { -                    // remove -                    me->SetFaction(FACTION_FRIENDLY); -                    me->DespawnOrUnsummon(); -                    return; -                } - -                CheckTimer = 1000; +                // remove +                me->SetFaction(FACTION_FRIENDLY); +                me->DespawnOrUnsummon(); +                return;              } -            else -                CheckTimer -= diff; -        } -    }; +            CheckTimer = 1000; +        } +        else +            CheckTimer -= diff; +    }  }; -class npc_shield_generator_channel : public CreatureScript +struct npc_shield_generator_channel : public ScriptedAI  { -public: -    npc_shield_generator_channel() : CreatureScript("npc_shield_generator_channel") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_shield_generator_channel(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_shield_generator_channelAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript();      } -    struct npc_shield_generator_channelAI : public ScriptedAI +    void Initialize()      { -        npc_shield_generator_channelAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -        } - -        void Initialize() -        { -            CheckTimer = 0; -            Cast = false; -        } +        CheckTimer = 0; +        Cast = false; +    } -        InstanceScript* instance; -        uint32 CheckTimer; -        bool Cast; +    InstanceScript* instance; +    uint32 CheckTimer; +    bool Cast; -        void Reset() override -        { -            Initialize(); -            me->SetDisplayId(11686); // invisible -        } +    void Reset() override +    { +        Initialize(); +        me->SetDisplayId(11686); // invisible +    } -        void MoveInLineOfSight(Unit* /*who*/) override { } +    void MoveInLineOfSight(Unit* /*who*/) override { } -        void UpdateAI(uint32 diff) override +    void UpdateAI(uint32 diff) override +    { +        if (CheckTimer <= diff)          { -            if (CheckTimer <= diff) -            { -                Unit* vashj = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LADYVASHJ)); +            Unit* vashj = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LADYVASHJ)); -                if (vashj && vashj->IsAlive()) +            if (vashj && vashj->IsAlive()) +            { +                // start visual channel +                if (!Cast || !vashj->HasAura(SPELL_MAGIC_BARRIER))                  { -                    // start visual channel -                    if (!Cast || !vashj->HasAura(SPELL_MAGIC_BARRIER)) -                    { -                        DoCast(vashj, SPELL_MAGIC_BARRIER, true); -                        Cast = true; -                    } +                    DoCast(vashj, SPELL_MAGIC_BARRIER, true); +                    Cast = true;                  } -                CheckTimer = 1000; -            } else CheckTimer -= diff; -        } -    }; - +            } +            CheckTimer = 1000; +        } else CheckTimer -= diff; +    }  };  class item_tainted_core : public ItemScript @@ -884,7 +823,7 @@ public:              return true;          Creature* vashj = ObjectAccessor::GetCreature((*player), instance->GetGuidData(DATA_LADYVASHJ)); -        if (vashj && (ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, vashj->AI())->Phase == 2)) +        if (vashj && (ENSURE_AI(boss_lady_vashj, vashj->AI())->Phase == 2))          {              if (GameObject* gObj = targets.GetGOTarget())              { @@ -916,7 +855,7 @@ public:                      return true;                  // get and remove channel -                if (Unit* channel = ObjectAccessor::GetCreature(*vashj, ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, vashj->AI())->ShieldGeneratorChannel[channelIdentifier])) +                if (Unit* channel = ObjectAccessor::GetCreature(*vashj, ENSURE_AI(boss_lady_vashj, vashj->AI())->ShieldGeneratorChannel[channelIdentifier]))                      channel->setDeathState(JUST_DIED); // call Unsummon()                  instance->SetData(identifier, 1); @@ -941,10 +880,10 @@ public:  void AddSC_boss_lady_vashj()  { -    new boss_lady_vashj(); -    new npc_enchanted_elemental(); -    new npc_tainted_elemental(); -    new npc_toxic_sporebat(); -    new npc_shield_generator_channel(); +    RegisterSerpentshrineCavernCreatureAI(boss_lady_vashj); +    RegisterSerpentshrineCavernCreatureAI(npc_enchanted_elemental); +    RegisterSerpentshrineCavernCreatureAI(npc_tainted_elemental); +    RegisterSerpentshrineCavernCreatureAI(npc_toxic_sporebat); +    RegisterSerpentshrineCavernCreatureAI(npc_shield_generator_channel);      new item_tainted_core();  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index 7293fc9f6ee..10bdf3bc631 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -73,746 +73,698 @@ enum LeotherasTheBlind      SAY_DEATH               = 7  }; -class npc_inner_demon : public CreatureScript +struct npc_inner_demon : public ScriptedAI  { -public: -    npc_inner_demon() : CreatureScript("npc_inner_demon") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_inner_demon(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_inner_demonAI>(creature); +        Initialize();      } -    struct npc_inner_demonAI : public ScriptedAI +    void Initialize()      { -        npc_inner_demonAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -        } +        ShadowBolt_Timer = 10000; +        Link_Timer = 1000; +    } -        void Initialize() -        { -            ShadowBolt_Timer = 10000; -            Link_Timer = 1000; -        } +    uint32 ShadowBolt_Timer; -        uint32 ShadowBolt_Timer; +    uint32 Link_Timer; +    ObjectGuid victimGUID; -        uint32 Link_Timer; -        ObjectGuid victimGUID; +    void Reset() override +    { +        Initialize(); +    } -        void Reset() override -        { -            Initialize(); -        } +    void SetGUID(ObjectGuid const& guid, int32 id) override +    { +        if (id == INNER_DEMON_VICTIM) +            victimGUID = guid; +    } -        void SetGUID(ObjectGuid const& guid, int32 id) override -        { -            if (id == INNER_DEMON_VICTIM) -                victimGUID = guid; -        } +    ObjectGuid GetGUID(int32 id/* = 0 */) const override +    { +        if (id == INNER_DEMON_VICTIM) +            return victimGUID; +        return ObjectGuid::Empty; +    } -        ObjectGuid GetGUID(int32 id/* = 0 */) const override -        { -            if (id == INNER_DEMON_VICTIM) -                return victimGUID; -            return ObjectGuid::Empty; -        } +    void JustDied(Unit* /*killer*/) override +    { +        Unit* unit = ObjectAccessor::GetUnit(*me, victimGUID); +        if (unit && unit->HasAura(SPELL_INSIDIOUS_WHISPER)) +            unit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); +    } -        void JustDied(Unit* /*killer*/) override +    void DamageTaken(Unit* done_by, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override +    { +        if (!done_by || (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()))          { -            Unit* unit = ObjectAccessor::GetUnit(*me, victimGUID); -            if (unit && unit->HasAura(SPELL_INSIDIOUS_WHISPER)) -                unit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); +            damage = 0; +            ModifyThreatByPercent(done_by, -100);          } +    } -        void DamageTaken(Unit* done_by, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override -        { -            if (!done_by || (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID())) -            { -                damage = 0; -                ModifyThreatByPercent(done_by, -100); -            } -        } +    void JustEngagedWith(Unit* /*who*/) override +    { +        if (!victimGUID) +            return; +    } -        void JustEngagedWith(Unit* /*who*/) override -        { -            if (!victimGUID) -                return; -        } +    void UpdateAI(uint32 diff) override +    { +        //Return since we have no target +        if (!UpdateVictim() || !me->GetVictim()) +            return; -        void UpdateAI(uint32 diff) override +        if (me->EnsureVictim()->GetGUID() != victimGUID)          { -            //Return since we have no target -            if (!UpdateVictim() || !me->GetVictim()) -                return; - -            if (me->EnsureVictim()->GetGUID() != victimGUID) +            ModifyThreatByPercent(me->GetVictim(), -100); +            Unit* owner = ObjectAccessor::GetUnit(*me, victimGUID); +            if (owner && owner->IsAlive())              { -                ModifyThreatByPercent(me->GetVictim(), -100); -                Unit* owner = ObjectAccessor::GetUnit(*me, victimGUID); -                if (owner && owner->IsAlive()) -                { -                    AddThreat(owner, 999999); -                    AttackStart(owner); -                } else if (owner && owner->isDead()) -                { -                    me->KillSelf(); -                    return; -                } +                AddThreat(owner, 999999); +                AttackStart(owner); +            } else if (owner && owner->isDead()) +            { +                me->KillSelf(); +                return;              } +        } -            if (Link_Timer <= diff) -            { -                DoCastVictim(SPELL_SOUL_LINK, true); -                Link_Timer = 1000; -            } else Link_Timer -= diff; +        if (Link_Timer <= diff) +        { +            DoCastVictim(SPELL_SOUL_LINK, true); +            Link_Timer = 1000; +        } else Link_Timer -= diff; -            if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) -                DoCast(me, AURA_DEMONIC_ALIGNMENT, true); +        if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) +            DoCast(me, AURA_DEMONIC_ALIGNMENT, true); -            if (ShadowBolt_Timer <= diff) -            { -                DoCastVictim(SPELL_SHADOWBOLT, false); -                ShadowBolt_Timer = 10000; -            } else ShadowBolt_Timer -= diff; +        if (ShadowBolt_Timer <= diff) +        { +            DoCastVictim(SPELL_SHADOWBOLT, false); +            ShadowBolt_Timer = 10000; +        } else ShadowBolt_Timer -= diff; -           DoMeleeAttackIfReady(); -        } -    }; +       DoMeleeAttackIfReady(); +    }  };  //Original Leotheras the Blind AI -class boss_leotheras_the_blind : public CreatureScript +struct boss_leotheras_the_blind : public BossAI  { -public: -    boss_leotheras_the_blind() : CreatureScript("boss_leotheras_the_blind") { } +    boss_leotheras_the_blind(Creature* creature) : BossAI(creature, BOSS_LEOTHERAS_THE_BLIND) +    { +        Initialize(); +        creature->GetPosition(x, y, z); +    } -    CreatureAI* GetAI(Creature* creature) const override +    void Initialize()      { -        return GetSerpentshrineCavernAI<boss_leotheras_the_blindAI>(creature); +        BanishTimer = 1000; +        Whirlwind_Timer = 15000; +        ChaosBlast_Timer = 1000; +        SwitchToDemon_Timer = 45000; +        SwitchToHuman_Timer = 60000; +        Berserk_Timer = 600000; +        InnerDemons_Timer = 30000; + +        DealDamage = true; +        DemonForm = false; +        IsFinalForm = false; +        NeedThreatReset = false; +        EnrageUsed = false; +        for (ObjectGuid& guid : InnderDemon) +            guid.Clear(); +        InnerDemon_Count = 0;      } -    struct boss_leotheras_the_blindAI : public ScriptedAI +    uint32 Whirlwind_Timer; +    uint32 ChaosBlast_Timer; +    uint32 SwitchToDemon_Timer; +    uint32 SwitchToHuman_Timer; +    uint32 Berserk_Timer; +    uint32 InnerDemons_Timer; +    uint32 BanishTimer; + +    bool DealDamage; +    bool NeedThreatReset; +    bool DemonForm; +    bool IsFinalForm; +    bool EnrageUsed; +    float x, y, z; + +    ObjectGuid InnderDemon[5]; +    uint32 InnerDemon_Count; +    ObjectGuid Demon; +    ObjectGuid SpellBinderGUID[3]; + +    void Reset() override      { -        boss_leotheras_the_blindAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            creature->GetPosition(x, y, z); -            instance = creature->GetInstanceScript(); -        } +        CheckChannelers(); +        Initialize(); +        me->SetCanDualWield(true); +        me->SetSpeedRate(MOVE_RUN, 2.0f); +        me->SetDisplayId(MODEL_NIGHTELF); +        me->SetVirtualItem(0, 0); +        me->SetVirtualItem(1, 0); +        DoCast(me, SPELL_DUAL_WIELD, true); +        me->SetCorpseDelay(1000*60*60); +        _Reset(); +    } -        void Initialize() +    void CheckChannelers(/*bool DoEvade = true*/) +    { +        for (uint8 i = 0; i < 3; ++i)          { -            BanishTimer = 1000; -            Whirlwind_Timer = 15000; -            ChaosBlast_Timer = 1000; -            SwitchToDemon_Timer = 45000; -            SwitchToHuman_Timer = 60000; -            Berserk_Timer = 600000; -            InnerDemons_Timer = 30000; - -            DealDamage = true; -            DemonForm = false; -            IsFinalForm = false; -            NeedThreatReset = false; -            EnrageUsed = false; -            for (ObjectGuid& guid : InnderDemon) -                guid.Clear(); -            InnerDemon_Count = 0; -        } +            if (Creature* add = ObjectAccessor::GetCreature(*me, SpellBinderGUID[i])) +                add->DisappearAndDie(); -        InstanceScript* instance; - -        uint32 Whirlwind_Timer; -        uint32 ChaosBlast_Timer; -        uint32 SwitchToDemon_Timer; -        uint32 SwitchToHuman_Timer; -        uint32 Berserk_Timer; -        uint32 InnerDemons_Timer; -        uint32 BanishTimer; - -        bool DealDamage; -        bool NeedThreatReset; -        bool DemonForm; -        bool IsFinalForm; -        bool EnrageUsed; -        float x, y, z; - -        ObjectGuid InnderDemon[5]; -        uint32 InnerDemon_Count; -        ObjectGuid Demon; -        ObjectGuid SpellBinderGUID[3]; - -        void Reset() override -        { -            CheckChannelers(); -            Initialize(); -            me->SetCanDualWield(true); -            me->SetSpeedRate(MOVE_RUN, 2.0f); -            me->SetDisplayId(MODEL_NIGHTELF); -            me->SetVirtualItem(0, 0); -            me->SetVirtualItem(1, 0); -            DoCast(me, SPELL_DUAL_WIELD, true); -            me->SetCorpseDelay(1000*60*60); -            instance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); +            float nx = x; +            float ny = y; +            float o = 2.4f; +            if (i == 0) {nx += 10; ny -= 5; o=2.5f;} +            if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} +            if (i == 2) {nx -= 3; ny += 9; o=5.0f;} +            Creature* binder = me->SummonCreature(NPC_SPELLBINDER, nx, ny, z, o, TEMPSUMMON_DEAD_DESPAWN); +            if (binder) +                SpellBinderGUID[i] = binder->GetGUID();          } +    } +    void MoveInLineOfSight(Unit* who) override -        void CheckChannelers(/*bool DoEvade = true*/) -        { -            for (uint8 i = 0; i < 3; ++i) -            { -                if (Creature* add = ObjectAccessor::GetCreature(*me, SpellBinderGUID[i])) -                    add->DisappearAndDie(); - -                float nx = x; -                float ny = y; -                float o = 2.4f; -                if (i == 0) {nx += 10; ny -= 5; o=2.5f;} -                if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} -                if (i == 2) {nx -= 3; ny += 9; o=5.0f;} -                Creature* binder = me->SummonCreature(NPC_SPELLBINDER, nx, ny, z, o, TEMPSUMMON_DEAD_DESPAWN); -                if (binder) -                    SpellBinderGUID[i] = binder->GetGUID(); -            } -        } -        void MoveInLineOfSight(Unit* who) override +    { +        if (me->HasAura(AURA_BANISH)) +            return; +        if (!me->GetVictim() && me->CanCreatureAttack(who))          { -            if (me->HasAura(AURA_BANISH)) +            if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)                  return; -            if (!me->GetVictim() && me->CanCreatureAttack(who)) +            float attackRadius = me->GetAttackDistance(who); +            if (me->IsWithinDistInMap(who, attackRadius))              { -                if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) -                    return; - -                float attackRadius = me->GetAttackDistance(who); -                if (me->IsWithinDistInMap(who, attackRadius)) +                // Check first that object is in an angle in front of this one before LoS check +                if (me->HasInArc(float(M_PI) / 2.0f, who) && me->IsWithinLOSInMap(who))                  { -                    // Check first that object is in an angle in front of this one before LoS check -                    if (me->HasInArc(float(M_PI) / 2.0f, who) && me->IsWithinLOSInMap(who)) -                    { -                        AttackStart(who); -                    } +                    AttackStart(who);                  }              }          } +    } -        void StartEvent() +    void StartEvent() +    { +        Talk(SAY_AGGRO); +        instance->SetBossState(BOSS_LEOTHERAS_THE_BLIND, IN_PROGRESS); +    } + +    void CheckBanish() +    { +        uint8 AliveChannelers = 0; +        for (uint8 i = 0; i < 3; ++i)          { -            Talk(SAY_AGGRO); -            instance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); +            Unit* add = ObjectAccessor::GetUnit(*me, SpellBinderGUID[i]); +            if (add && add->IsAlive()) +                ++AliveChannelers;          } -        void CheckBanish() +        // channelers == 0 remove banish aura +        if (AliveChannelers == 0 && me->HasAura(AURA_BANISH))          { -            uint8 AliveChannelers = 0; -            for (uint8 i = 0; i < 3; ++i) -            { -                Unit* add = ObjectAccessor::GetUnit(*me, SpellBinderGUID[i]); -                if (add && add->IsAlive()) -                    ++AliveChannelers; -            } +            // removing banish aura +            me->RemoveAurasDueToSpell(AURA_BANISH); -            // channelers == 0 remove banish aura -            if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) -            { -                // removing banish aura -                me->RemoveAurasDueToSpell(AURA_BANISH); +            // Leotheras is getting immune again +            me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); -                // Leotheras is getting immune again -                me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); - -                // changing model to bloodelf -                me->SetDisplayId(MODEL_NIGHTELF); +            // changing model to bloodelf +            me->SetDisplayId(MODEL_NIGHTELF); -                // and reseting equipment -                me->LoadEquipment(); +            // and reseting equipment +            me->LoadEquipment(); -                if (!instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER).IsEmpty()) -                { -                    if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))) -                        AddThreat(victim, 1); -                    StartEvent(); -                } -            } -            else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) +            if (!instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER).IsEmpty())              { -                // channelers != 0 apply banish aura -                // removing Leotheras banish immune to apply AURA_BANISH -                me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); -                DoCast(me, AURA_BANISH); +                if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))) +                    AddThreat(victim, 1); +                StartEvent(); +            } +        } +        else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) +        { +            // channelers != 0 apply banish aura +            // removing Leotheras banish immune to apply AURA_BANISH +            me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); +            DoCast(me, AURA_BANISH); -                // changing model -                me->SetDisplayId(MODEL_DEMON); +            // changing model +            me->SetDisplayId(MODEL_DEMON); -                // and removing weapons -                me->SetVirtualItem(0, 0); -                me->SetVirtualItem(1, 0); -            } +            // and removing weapons +            me->SetVirtualItem(0, 0); +            me->SetVirtualItem(1, 0);          } +    } -        //Despawn all Inner Demon summoned -        void DespawnDemon() +    //Despawn all Inner Demon summoned +    void DespawnDemon() +    { +        for (uint8 i=0; i<5; ++i)          { -            for (uint8 i = 0; i < 5; ++i) +            if (!InnderDemon[i].IsEmpty())              { -                if (!InnderDemon[i].IsEmpty()) -                { -                    //delete creature -                    Creature* creature = ObjectAccessor::GetCreature((*me), InnderDemon[i]); -                    if (creature && creature->IsAlive()) -                        creature->DespawnOrUnsummon(); +                //delete creature +                Creature* creature = ObjectAccessor::GetCreature((*me), InnderDemon[i]); +                if (creature && creature->IsAlive()) +                    creature->DespawnOrUnsummon(); -                    InnderDemon[i].Clear(); -                } +                InnderDemon[i].Clear();              } - -            InnerDemon_Count = 0;          } -        void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core +        InnerDemon_Count = 0; +    } + +    void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core +    { +        for (uint8 i = 0; i < 5; ++i)          { -            for (uint8 i = 0; i < 5; ++i) +            if (!InnderDemon[i].IsEmpty())              { -                if (!InnderDemon[i].IsEmpty()) +                Creature* unit = ObjectAccessor::GetCreature((*me), InnderDemon[i]); +                if (unit && unit->IsAlive())                  { -                    Creature* unit = ObjectAccessor::GetCreature((*me), InnderDemon[i]); -                    if (unit && unit->IsAlive()) +                    Unit* unit_target = ObjectAccessor::GetUnit(*unit, unit->AI()->GetGUID(INNER_DEMON_VICTIM)); +                    if (unit_target && unit_target->IsAlive())                      { -                        Unit* unit_target = ObjectAccessor::GetUnit(*unit, unit->AI()->GetGUID(INNER_DEMON_VICTIM)); -                        if (unit_target && unit_target->IsAlive()) -                        { -                            unit->CastSpell(unit_target, SPELL_CONSUMING_MADNESS, true); -                            ModifyThreatByPercent(unit_target, -100); -                        } +                        unit->CastSpell(unit_target, SPELL_CONSUMING_MADNESS, true); +                        ModifyThreatByPercent(unit_target, -100);                      }                  }              }          } +    } -        void KilledUnit(Unit* victim) override -        { -            if (victim->GetTypeId() != TYPEID_PLAYER) -                return; +    void KilledUnit(Unit* victim) override +    { +        if (victim->GetTypeId() != TYPEID_PLAYER) +            return; -            Talk(DemonForm ? SAY_DEMON_SLAY : SAY_NIGHTELF_SLAY); -        } +        Talk(DemonForm ? SAY_DEMON_SLAY : SAY_NIGHTELF_SLAY); +    } + +    void JustDied(Unit* /*killer*/) override +    { +        Talk(SAY_DEATH); -        void JustDied(Unit* /*killer*/) override +        //despawn copy +        if (!Demon.IsEmpty())          { -            Talk(SAY_DEATH); +            if (Creature* pDemon = ObjectAccessor::GetCreature(*me, Demon)) +                pDemon->DespawnOrUnsummon(); +        } +        _JustDied(); +    } -            //despawn copy -            if (!Demon.IsEmpty()) -                if (Creature* pDemon = ObjectAccessor::GetCreature(*me, Demon)) -                    pDemon->DespawnOrUnsummon(); +    void JustEngagedWith(Unit* /*who*/) override +    { +        if (me->HasAura(AURA_BANISH)) +        return; -            instance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); -        } +        me->LoadEquipment(); +    } -        void JustEngagedWith(Unit* /*who*/) override +    void UpdateAI(uint32 diff) override +    { +        //Return since we have no target +        if (me->HasAura(AURA_BANISH) || !UpdateVictim())          { -            if (me->HasAura(AURA_BANISH)) +            if (BanishTimer <= diff) +            { +                CheckBanish();//no need to check every update tick +                BanishTimer = 1000; +            } else BanishTimer -= diff;              return; - -            me->LoadEquipment();          } - -        void UpdateAI(uint32 diff) override +        if (me->HasAura(SPELL_WHIRLWIND))          { -            //Return since we have no target -            if (me->HasAura(AURA_BANISH) || !UpdateVictim()) +            if (Whirlwind_Timer <= diff)              { -                if (BanishTimer <= diff) +                Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 0); +                if (newTarget)                  { -                    CheckBanish();//no need to check every update tick -                    BanishTimer = 1000; -                } else BanishTimer -= diff; -                return; -            } -            if (me->HasAura(SPELL_WHIRLWIND)) +                    ResetThreatList(); +                    me->GetMotionMaster()->Clear(); +                    me->GetMotionMaster()->MovePoint(0, newTarget->GetPositionX(), newTarget->GetPositionY(), newTarget->GetPositionZ()); +                } +                Whirlwind_Timer = 2000; +            } else Whirlwind_Timer -= diff; +        } + +        // reseting after changing forms and after ending whirlwind +        if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) +        { +            // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) +            if (DemonForm) +                InnerDemons_Timer = 30000; +            else +                Whirlwind_Timer =  15000; + +            NeedThreatReset = false; +            ResetThreatList(); +            me->GetMotionMaster()->Clear(); +            me->GetMotionMaster()->MoveChase(me->GetVictim()); +        } + +        //Enrage_Timer (10 min) +        if (Berserk_Timer < diff && !EnrageUsed) +        { +            me->InterruptNonMeleeSpells(false); +            DoCast(me, SPELL_BERSERK); +            EnrageUsed = true; +        } else Berserk_Timer -= diff; + +        if (!DemonForm) +        { +            //Whirldind Timer +            if (!me->HasAura(SPELL_WHIRLWIND))              {                  if (Whirlwind_Timer <= diff)                  { -                    Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 0); -                    if (newTarget) -                    { -                        ResetThreatList(); -                        me->GetMotionMaster()->Clear(); -                        me->GetMotionMaster()->MovePoint(0, newTarget->GetPositionX(), newTarget->GetPositionY(), newTarget->GetPositionZ()); -                    } +                    DoCast(me, SPELL_WHIRLWIND); +                    // while whirlwinding this variable is used to countdown target's change                      Whirlwind_Timer = 2000; +                    NeedThreatReset = true;                  } else Whirlwind_Timer -= diff;              } +            //Switch_Timer -            // reseting after changing forms and after ending whirlwind -            if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) +            if (!IsFinalForm)              { -                // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) -                if (DemonForm) -                    InnerDemons_Timer = 30000; -                else -                    Whirlwind_Timer =  15000; - -                NeedThreatReset = false; -                ResetThreatList(); -                me->GetMotionMaster()->Clear(); -                me->GetMotionMaster()->MoveChase(me->GetVictim()); +                if (SwitchToDemon_Timer <= diff) +                { +                    //switch to demon form +                    me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); +                    me->SetDisplayId(MODEL_DEMON); +                    Talk(SAY_SWITCH_TO_DEMON); +                    me->SetVirtualItem(0, 0); +                    me->SetVirtualItem(1, 0); +                    DemonForm = true; +                    NeedThreatReset = true; +                    SwitchToDemon_Timer = 45000; +                } else SwitchToDemon_Timer -= diff;              } - -            //Enrage_Timer (10 min) -            if (Berserk_Timer < diff && !EnrageUsed) -            { -                me->InterruptNonMeleeSpells(false); -                DoCast(me, SPELL_BERSERK); -                EnrageUsed = true; -            } else Berserk_Timer -= diff; - -            if (!DemonForm) +            DoMeleeAttackIfReady(); +        } +        else +        { +            //ChaosBlast_Timer +            if (!me->GetVictim()) +                return; +            if (me->IsWithinDist(me->GetVictim(), 30)) +                me->StopMoving(); +            if (ChaosBlast_Timer <= diff)              { -                //Whirldind Timer -                if (!me->HasAura(SPELL_WHIRLWIND)) -                { -                    if (Whirlwind_Timer <= diff) -                    { -                        DoCast(me, SPELL_WHIRLWIND); -                        // while whirlwinding this variable is used to countdown target's change -                        Whirlwind_Timer = 2000; -                        NeedThreatReset = true; -                    } else Whirlwind_Timer -= diff; -                } -                //Switch_Timer - -                if (!IsFinalForm) +                // will cast only when in range of spell +                if (me->IsWithinDist(me->GetVictim(), 30))                  { -                    if (SwitchToDemon_Timer <= diff) -                    { -                        //switch to demon form -                        me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); -                        me->SetDisplayId(MODEL_DEMON); -                        Talk(SAY_SWITCH_TO_DEMON); -                        me->SetVirtualItem(0, 0); -                        me->SetVirtualItem(1, 0); -                        DemonForm = true; -                        NeedThreatReset = true; -                        SwitchToDemon_Timer = 45000; -                    } else SwitchToDemon_Timer -= diff; +                    //DoCastVictim(SPELL_CHAOS_BLAST, true); +                    me->CastSpell(me->GetVictim(), SPELL_CHAOS_BLAST, CastSpellExtraArgs().SetOriginalCaster(me->GetGUID()).AddSpellBP0(100));                  } -                DoMeleeAttackIfReady(); -            } -            else +                ChaosBlast_Timer = 3000; +            } else ChaosBlast_Timer -= diff; +            //Summon Inner Demon +            if (InnerDemons_Timer <= diff)              { -                //ChaosBlast_Timer -                if (!me->GetVictim()) -                    return; -                if (me->IsWithinDist(me->GetVictim(), 30)) -                    me->StopMoving(); -                if (ChaosBlast_Timer <= diff) +                ThreatManager const& mgr = me->GetThreatManager(); +                std::list<Unit*> TargetList; +                Unit* currentVictim = mgr.GetLastVictim(); +                for (ThreatReference const* ref : mgr.GetSortedThreatList())                  { -                    // will cast only when in range of spell -                    if (me->IsWithinDist(me->GetVictim(), 30)) -                    { -                        //DoCastVictim(SPELL_CHAOS_BLAST, true); -                        me->CastSpell(me->GetVictim(), SPELL_CHAOS_BLAST, CastSpellExtraArgs().SetOriginalCaster(me->GetGUID()).AddSpellBP0(100)); -                    } -                    ChaosBlast_Timer = 3000; -                } else ChaosBlast_Timer -= diff; -                //Summon Inner Demon -                if (InnerDemons_Timer <= diff) +                    if (Player* tempTarget = ref->GetVictim()->ToPlayer()) +                        if (tempTarget != currentVictim && TargetList.size()<5) +                            TargetList.push_back(tempTarget); +                } +                //SpellInfo* spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); +                for (auto itr = TargetList.begin(), end = TargetList.end(); itr != end; ++itr)                  { -                    ThreatManager const& mgr = me->GetThreatManager(); -                    std::list<Unit*> TargetList; -                    Unit* currentVictim = mgr.GetLastVictim(); -                    for (ThreatReference const* ref : mgr.GetSortedThreatList()) +                    if ((*itr) && (*itr)->IsAlive())                      { -                        if (Player* tempTarget = ref->GetVictim()->ToPlayer()) -                            if (tempTarget != currentVictim && TargetList.size()<5) -                                TargetList.push_back(tempTarget); -                    } -                    //SpellInfo* spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); -                    for (auto itr = TargetList.begin(), end = TargetList.end(); itr != end; ++itr) -                    { -                        if ((*itr) && (*itr)->IsAlive()) +                        Creature* demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s); +                        if (demon)                          { -                            Creature* demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s); -                            if (demon) -                            { -                                demon->AI()->AttackStart((*itr)); -                                demon->AI()->SetGUID((*itr)->GetGUID(), INNER_DEMON_VICTIM); +                            demon->AI()->AttackStart((*itr)); +                            demon->AI()->SetGUID((*itr)->GetGUID(), INNER_DEMON_VICTIM); -                                (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); +                            (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); -                                if (InnerDemon_Count > 4) -                                    InnerDemon_Count = 0; +                            if (InnerDemon_Count > 4) +                                InnerDemon_Count = 0; -                                //Safe storing of creatures -                                InnderDemon[InnerDemon_Count] = demon->GetGUID(); +                            //Safe storing of creatures +                            InnderDemon[InnerDemon_Count] = demon->GetGUID(); -                                //Update demon count -                                ++InnerDemon_Count; -                            } +                            //Update demon count +                            ++InnerDemon_Count;                          }                      } -                    Talk(SAY_INNER_DEMONS); - -                    InnerDemons_Timer = 999999; -                } else InnerDemons_Timer -= diff; - -                //Switch_Timer -                if (SwitchToHuman_Timer <= diff) -                { -                    //switch to nightelf form -                    me->SetDisplayId(MODEL_NIGHTELF); -                    me->LoadEquipment(); - -                    CastConsumingMadness(); -                    DespawnDemon(); - -                    DemonForm = false; -                    NeedThreatReset = true; +                } +                Talk(SAY_INNER_DEMONS); -                    SwitchToHuman_Timer = 60000; -                } else SwitchToHuman_Timer -= diff; -            } +                InnerDemons_Timer = 999999; +            } else InnerDemons_Timer -= diff; -            if (!IsFinalForm && HealthBelowPct(15)) +            //Switch_Timer +            if (SwitchToHuman_Timer <= diff)              { -                //at this point he divides himself in two parts +                //switch to nightelf form +                me->SetDisplayId(MODEL_NIGHTELF); +                me->LoadEquipment(); +                  CastConsumingMadness();                  DespawnDemon(); -                if (Creature* Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6s)) -                { -                    Demon = Copy->GetGUID(); -                    if (me->GetVictim()) -                        Copy->AI()->AttackStart(me->GetVictim()); -                } -                //set nightelf final form -                IsFinalForm = true; +                  DemonForm = false; +                NeedThreatReset = true; -                Talk(SAY_FINAL_FORM); -                me->SetDisplayId(MODEL_NIGHTELF); -                me->LoadEquipment(); +                SwitchToHuman_Timer = 60000; +            } else SwitchToHuman_Timer -= diff; +        } + +        if (!IsFinalForm && HealthBelowPct(15)) +        { +            //at this point he divides himself in two parts +            CastConsumingMadness(); +            DespawnDemon(); +            if (Creature* Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6s)) +            { +                Demon = Copy->GetGUID(); +                if (me->GetVictim()) +                    Copy->AI()->AttackStart(me->GetVictim());              } +            //set nightelf final form +            IsFinalForm = true; +            DemonForm = false; + +            Talk(SAY_FINAL_FORM); +            me->SetDisplayId(MODEL_NIGHTELF); +            me->LoadEquipment();          } -    }; +    }  };  //Leotheras the Blind Demon Form AI -class boss_leotheras_the_blind_demonform : public CreatureScript +struct boss_leotheras_the_blind_demonform : public ScriptedAI  { -public: -    boss_leotheras_the_blind_demonform() : CreatureScript("boss_leotheras_the_blind_demonform") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_leotheras_the_blind_demonform(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<boss_leotheras_the_blind_demonformAI>(creature); +        Initialize();      } -    struct boss_leotheras_the_blind_demonformAI : public ScriptedAI +    void Initialize()      { -        boss_leotheras_the_blind_demonformAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -        } +        ChaosBlast_Timer = 1000; +        DealDamage = true; +    } -        void Initialize() -        { -            ChaosBlast_Timer = 1000; -            DealDamage = true; -        } +    uint32 ChaosBlast_Timer; +    bool DealDamage; -        uint32 ChaosBlast_Timer; -        bool DealDamage; +    void Reset() override +    { +        Initialize(); +    } -        void Reset() override -        { -            Initialize(); -        } +    void StartEvent() +    { +        Talk(SAY_FREE); +    } -        void StartEvent() -        { -            Talk(SAY_FREE); -        } +    void KilledUnit(Unit* victim) override +    { +        if (victim->GetTypeId() != TYPEID_PLAYER) +            return; -        void KilledUnit(Unit* victim) override -        { -            if (victim->GetTypeId() != TYPEID_PLAYER) -                return; +        Talk(SAY_DEMON_SLAY); +    } -            Talk(SAY_DEMON_SLAY); -        } +    void JustDied(Unit* /*killer*/) override +    { +        //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) +        DoCast(me, 8149, true); +    } -        void JustDied(Unit* /*killer*/) override -        { -            //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) -            DoCast(me, 8149, true); -        } +    void JustEngagedWith(Unit* /*who*/) override +    { +        StartEvent(); +    } -        void JustEngagedWith(Unit* /*who*/) override -        { -            StartEvent(); -        } +    void UpdateAI(uint32 diff) override +    { +        //Return since we have no target +        if (!UpdateVictim()) +            return; +        //ChaosBlast_Timer +        if (me->IsWithinDist(me->GetVictim(), 30)) +            me->StopMoving(); -        void UpdateAI(uint32 diff) override -        { -            //Return since we have no target -            if (!UpdateVictim()) -                return; -            //ChaosBlast_Timer +        if (ChaosBlast_Timer <= diff) +         { +            // will cast only when in range od spell              if (me->IsWithinDist(me->GetVictim(), 30)) -                me->StopMoving(); - -            if (ChaosBlast_Timer <= diff) -             { -                // will cast only when in range od spell -                if (me->IsWithinDist(me->GetVictim(), 30)) -                { -                    //DoCastVictim(SPELL_CHAOS_BLAST, true); -                    me->CastSpell(me->GetVictim(), SPELL_CHAOS_BLAST, CastSpellExtraArgs().SetOriginalCaster(me->GetGUID()).AddSpellBP0(100)); -                    ChaosBlast_Timer = 3000; -                } -             } else ChaosBlast_Timer -= diff; +            { +                //DoCastVictim(SPELL_CHAOS_BLAST, true); +                me->CastSpell(me->GetVictim(), SPELL_CHAOS_BLAST, CastSpellExtraArgs().SetOriginalCaster(me->GetGUID()).AddSpellBP0(100)); +                ChaosBlast_Timer = 3000; +            } +         } else ChaosBlast_Timer -= diff; -            //Do NOT deal any melee damage to the target. -        } -    }; +        //Do NOT deal any melee damage to the target. +    }  }; -class npc_greyheart_spellbinder : public CreatureScript +struct npc_greyheart_spellbinder : public ScriptedAI  { -public: -    npc_greyheart_spellbinder() : CreatureScript("npc_greyheart_spellbinder") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_greyheart_spellbinder(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_greyheart_spellbinderAI>(creature); +        Initialize(); +        instance = creature->GetInstanceScript(); +        AddedBanish = false;      } -    struct npc_greyheart_spellbinderAI : public ScriptedAI +    void Initialize()      { -        npc_greyheart_spellbinderAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -            AddedBanish = false; -        } +        Mindblast_Timer = urand(3000, 8000); +        Earthshock_Timer = urand(5000, 10000); +    } -        void Initialize() -        { -            Mindblast_Timer = urand(3000, 8000); -            Earthshock_Timer = urand(5000, 10000); -        } +    InstanceScript* instance; + +    ObjectGuid leotherasGUID; -        InstanceScript* instance; +    uint32 Mindblast_Timer; +    uint32 Earthshock_Timer; -        ObjectGuid leotherasGUID; +    bool AddedBanish; -        uint32 Mindblast_Timer; -        uint32 Earthshock_Timer; +    void Reset() override +    { +        Initialize(); -        bool AddedBanish; +        instance->SetGuidData(DATA_LEOTHERAS_EVENT_STARTER, ObjectGuid::Empty); +        Creature* leotheras = ObjectAccessor::GetCreature(*me, leotherasGUID); +        if (leotheras && leotheras->IsAlive()) +            ENSURE_AI(boss_leotheras_the_blind, leotheras->AI())->CheckChannelers(/*false*/); +    } -        void Reset() override -        { -            Initialize(); +    void JustEngagedWith(Unit* who) override +    { +        me->InterruptNonMeleeSpells(false); +        instance->SetGuidData(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); +    } -            instance->SetGuidData(DATA_LEOTHERAS_EVENT_STARTER, ObjectGuid::Empty); -            Creature* leotheras = ObjectAccessor::GetCreature(*me, leotherasGUID); -            if (leotheras && leotheras->IsAlive()) -                ENSURE_AI(boss_leotheras_the_blind::boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); -        } +    void JustAppeared() override +    { +        AddedBanish = false; +        Reset(); +    } -        void JustEngagedWith(Unit* who) override +    void CastChanneling() +    { +        if (!me->IsInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))          { -            me->InterruptNonMeleeSpells(false); -            instance->SetGuidData(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); +            if (!leotherasGUID.IsEmpty()) +            { +                Creature* leotheras = ObjectAccessor::GetCreature(*me, leotherasGUID); +                if (leotheras && leotheras->IsAlive()) +                    DoCast(leotheras, BANISH_BEAM); +            }          } +    } + +    void UpdateAI(uint32 diff) override +    { +        if (!leotherasGUID) +            leotherasGUID = instance->GetGuidData(DATA_LEOTHERAS); -        void JustAppeared() override +        if (!me->IsInCombat() && !instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER).IsEmpty())          { -            AddedBanish = false; -            Reset(); +            if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))) +                AttackStart(victim);          } -        void CastChanneling() +        if (!UpdateVictim())          { -            if (!me->IsInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) -            { -                if (!leotherasGUID.IsEmpty()) -                { -                    Creature* leotheras = ObjectAccessor::GetCreature(*me, leotherasGUID); -                    if (leotheras && leotheras->IsAlive()) -                        DoCast(leotheras, BANISH_BEAM); -                } -            } +            CastChanneling(); +            return;          } -        void UpdateAI(uint32 diff) override +        if (!instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))          { -            if (!leotherasGUID) -                leotherasGUID = instance->GetGuidData(DATA_LEOTHERAS); - -            if (!me->IsInCombat() && !instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER).IsEmpty()) -            { -                if (Unit* victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER))) -                    AttackStart(victim); -            } - -            if (!UpdateVictim()) -            { -                CastChanneling(); -                return; -            } - -            if (!instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER)) -            { -                EnterEvadeMode(); -                return; -            } +            EnterEvadeMode(); +            return; +        } -            if (Mindblast_Timer <= diff) -            { -                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                    DoCast(target, SPELL_MINDBLAST); +        if (Mindblast_Timer <= diff) +        { +            if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                DoCast(target, SPELL_MINDBLAST); -                Mindblast_Timer = urand(10000, 15000); -            } else Mindblast_Timer -= diff; +            Mindblast_Timer = urand(10000, 15000); +        } else Mindblast_Timer -= diff; -            if (Earthshock_Timer <= diff) +        if (Earthshock_Timer <= diff) +        { +            Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); +            for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)              { -                Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); -                for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) +                if (Player* i_pl = itr->GetSource())                  { -                    if (Player* i_pl = itr->GetSource()) -                    { -                        bool isCasting = false; -                        for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) -                            if (i_pl->GetCurrentSpell(i)) -                                isCasting = true; +                    bool isCasting = false; +                    for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) +                        if (i_pl->GetCurrentSpell(i)) +                            isCasting = true; -                        if (isCasting) -                        { -                            DoCast(i_pl, SPELL_EARTHSHOCK); -                            break; -                        } +                    if (isCasting) +                    { +                        DoCast(i_pl, SPELL_EARTHSHOCK); +                        break;                      }                  } -                Earthshock_Timer = urand(8000, 15000); -            } else Earthshock_Timer -= diff; -            DoMeleeAttackIfReady(); -        } - -        void JustDied(Unit* /*killer*/) override { } -    }; +            } +            Earthshock_Timer = urand(8000, 15000); +        } else Earthshock_Timer -= diff; +        DoMeleeAttackIfReady(); +    }  };  void AddSC_boss_leotheras_the_blind()  { -    new boss_leotheras_the_blind(); -    new boss_leotheras_the_blind_demonform(); -    new npc_greyheart_spellbinder(); -    new npc_inner_demon(); +    RegisterSerpentshrineCavernCreatureAI(boss_leotheras_the_blind); +    RegisterSerpentshrineCavernCreatureAI(boss_leotheras_the_blind_demonform); +    RegisterSerpentshrineCavernCreatureAI(npc_greyheart_spellbinder); +    RegisterSerpentshrineCavernCreatureAI(npc_inner_demon);  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index 5afdb989f40..a3e16887b68 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -79,408 +79,360 @@ float AddPos[9][3] =      {42.471519f, -445.115295f, -19.769423f}  }; -class boss_the_lurker_below : public CreatureScript +struct boss_the_lurker_below : public BossAI  { -public: -    boss_the_lurker_below() : CreatureScript("boss_the_lurker_below") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_the_lurker_below(Creature* creature) : BossAI(creature, BOSS_THE_LURKER_BELOW)      { -        return GetSerpentshrineCavernAI<boss_the_lurker_belowAI>(creature); +        Initialize(); +        SetCombatMovement(false);      } -    struct boss_the_lurker_belowAI : public ScriptedAI +    void Initialize()      { -        boss_the_lurker_belowAI(Creature* creature) : ScriptedAI(creature), Summons(me) -        { -            Initialize(); -            SetCombatMovement(false); -            instance = creature->GetInstanceScript(); -        } +        SpoutAnimTimer = 1000; +        RotTimer = 0; +        WaterboltTimer = 15000; // give time to get in range when fight starts +        SpoutTimer = 45000; +        WhirlTimer = 18000; // after avery spout +        PhaseTimer = 120000; +        GeyserTimer = rand32() % 5000 + 15000; +        CheckTimer = 15000; // give time to get in range when fight starts +        WaitTimer = 60000; // never reached +        WaitTimer2 = 60000; // never reached + +        Submerged = true; // will be false at combat start +        Spawned = false; +        InRange = false; +        CanStartEvent = false; +    } -        void Initialize() -        { -            SpoutAnimTimer = 1000; -            RotTimer = 0; -            WaterboltTimer = 15000; // give time to get in range when fight starts -            SpoutTimer = 45000; -            WhirlTimer = 18000; // after avery spout -            PhaseTimer = 120000; -            GeyserTimer = rand32() % 5000 + 15000; -            CheckTimer = 15000; // give time to get in range when fight starts -            WaitTimer = 60000; // never reached -            WaitTimer2 = 60000; // never reached - -            Submerged = true; // will be false at combat start -            Spawned = false; -            InRange = false; -            CanStartEvent = false; -        } +    bool Spawned; +    bool Submerged; +    bool InRange; +    bool CanStartEvent; +    uint32 RotTimer; +    uint32 SpoutAnimTimer; +    uint32 WaterboltTimer; +    uint32 SpoutTimer; +    uint32 WhirlTimer; +    uint32 PhaseTimer; +    uint32 GeyserTimer; +    uint32 CheckTimer; +    uint32 WaitTimer; +    uint32 WaitTimer2; + +    bool CheckCanStart()//check if players fished +    { +        if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) +            return false; +        return true; +    } -        InstanceScript* instance; -        SummonList Summons; - -        bool Spawned; -        bool Submerged; -        bool InRange; -        bool CanStartEvent; -        uint32 RotTimer; -        uint32 SpoutAnimTimer; -        uint32 WaterboltTimer; -        uint32 SpoutTimer; -        uint32 WhirlTimer; -        uint32 PhaseTimer; -        uint32 GeyserTimer; -        uint32 CheckTimer; -        uint32 WaitTimer; -        uint32 WaitTimer2; - -        bool CheckCanStart()//check if players fished -        { -            if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) -                return false; -            return true; -        } +    void Reset() override +    { +        me->SetSwim(true); +        me->SetDisableGravity(true); +        Initialize(); + +        _Reset(); +        instance->SetData(DATA_STRANGE_POOL, NOT_STARTED); +        DoCast(me, SPELL_SUBMERGE); // submerge anim +        me->SetVisible(false); // we start invis under water, submerged +        me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); +        me->SetImmuneToPC(true); +    } -        void Reset() override -        { -            me->SetSwim(true); -            me->SetDisableGravity(true); -            Initialize(); - -            Summons.DespawnAll(); - -            instance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); -            instance->SetData(DATA_STRANGE_POOL, NOT_STARTED); -            DoCast(me, SPELL_SUBMERGE); // submerge anim -            me->SetVisible(false); // we start invis under water, submerged -            me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); -            me->SetImmuneToPC(true); -        } +    void JustDied(Unit* /*killer*/) override +    { +        _JustDied(); +        instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS); +    } -        void JustDied(Unit* /*killer*/) override +    void MoveInLineOfSight(Unit* who) override +    { +        if (!CanStartEvent) // boss is invisible, don't attack +            return; +        if (!me->GetVictim() && who->IsValidAttackTarget(me))          { -            instance->SetData(DATA_THELURKERBELOWEVENT, DONE); -            instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS); - -            Summons.DespawnAll(); +            float attackRadius = me->GetAttackDistance(who); +            if (me->IsWithinDistInMap(who, attackRadius)) +                AttackStart(who);          } +    } -        void JustEngagedWith(Unit* /*who*/) override -        { -            instance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); -        } +    void MovementInform(uint32 type, uint32 /*id*/) override +    { +        if (type == ROTATE_MOTION_TYPE) +            me->SetReactState(REACT_AGGRESSIVE); +    } -        void MoveInLineOfSight(Unit* who) override +    void UpdateAI(uint32 diff) override +    { +        if (!CanStartEvent) // boss is invisible, don't attack          { -            if (!CanStartEvent) // boss is invisible, don't attack -                return; -            if (!me->GetVictim() && who->IsValidAttackTarget(me)) +            if (CheckCanStart())              { -                float attackRadius = me->GetAttackDistance(who); -                if (me->IsWithinDistInMap(who, attackRadius)) -                    AttackStart(who); +                if (Submerged) +                { +                    me->SetVisible(true); +                    Submerged = false; +                    WaitTimer2 = 500; +                } +                else if (WaitTimer2 <= diff) // wait 500ms before emerge anim +                { +                    me->RemoveAllAuras(); +                    me->SetEmoteState(EMOTE_ONESHOT_NONE); +                    DoCast(me, SPELL_EMERGE, false); +                    WaitTimer2 = 60000; // never reached +                    WaitTimer = 3000; +                } +                else +                    WaitTimer2 -= diff; + +                if (WaitTimer <= diff) // wait 3secs for emerge anim, then attack +                { +                    WaitTimer = 3000; +                    CanStartEvent = true; // fresh fished from pool +                    me->SetImmuneToPC(false); +                    me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); +                } +                else +                    WaitTimer -= diff;              } +            return;          } -        void MovementInform(uint32 type, uint32 /*id*/) override +        if (!me->IsThreatened()) // check if should evade          { -            if (type == ROTATE_MOTION_TYPE) -                me->SetReactState(REACT_AGGRESSIVE); +            if (me->IsEngaged()) +                EnterEvadeMode(); +            return;          } - -        void UpdateAI(uint32 diff) override +        if (!Submerged)          { -            if (!CanStartEvent) // boss is invisible, don't attack +            if (PhaseTimer <= diff)              { -                if (CheckCanStart()) -                { -                    if (Submerged) -                    { -                        me->SetVisible(true); -                        Submerged = false; -                        WaitTimer2 = 500; -                    } -                    else if (WaitTimer2 <= diff) // wait 500ms before emerge anim -                    { -                        me->RemoveAllAuras(); -                        me->SetEmoteState(EMOTE_ONESHOT_NONE); -                        DoCast(me, SPELL_EMERGE, false); -                        WaitTimer2 = 60000; // never reached -                        WaitTimer = 3000; -                    } -                    else -                        WaitTimer2 -= diff; +                me->InterruptNonMeleeSpells(false); +                DoCast(me, SPELL_SUBMERGE); +                PhaseTimer = 60000; // 60secs submerged +                Submerged = true; +            } +            else +                PhaseTimer -= diff; -                    if (WaitTimer <= diff) // wait 3secs for emerge anim, then attack -                    { -                        WaitTimer = 3000; -                        CanStartEvent = true; // fresh fished from pool -                        me->SetImmuneToPC(false); -                        me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); -                    } -                    else -                        WaitTimer -= diff; -                } +            if (SpoutTimer <= diff) +            { +                Talk(EMOTE_SPOUT); +                me->SetReactState(REACT_PASSIVE); +                me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); +                SpoutTimer = 45000; +                WhirlTimer = 20000; // whirl directly after spout +                RotTimer = 20000;                  return;              } +            else +                SpoutTimer -= diff; -            if (!me->IsThreatened()) // check if should evade +            // Whirl directly after a Spout and at random times +            if (WhirlTimer <= diff)              { -                if (me->IsEngaged()) -                    EnterEvadeMode(); -                return; +                WhirlTimer = 18000; +                DoCast(me, SPELL_WHIRL);              } -            if (!Submerged) +            else +                WhirlTimer -= diff; + +            if (CheckTimer <= diff) // check if there are players in melee range              { -                if (PhaseTimer <= diff) +                InRange = false; +                Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); +                if (!PlayerList.isEmpty())                  { -                    me->InterruptNonMeleeSpells(false); -                    DoCast(me, SPELL_SUBMERGE); -                    PhaseTimer = 60000; // 60secs submerged -                    Submerged = true; +                    for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) +                    { +                        if (me->IsWithinMeleeRange(i->GetSource())) +                            InRange = true; +                    }                  } -                else -                    PhaseTimer -= diff; +                CheckTimer = 2000; +            } +            else +                CheckTimer -= diff; -                if (SpoutTimer <= diff) +            if (RotTimer) +            { +                instance->instance->DoOnPlayers([&](Player* player)                  { -                    Talk(EMOTE_SPOUT); -                    me->SetReactState(REACT_PASSIVE); -                    me->GetMotionMaster()->MoveRotate(0, 20000, urand(0, 1) ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); -                    SpoutTimer = 45000; -                    WhirlTimer = 20000; // whirl directly after spout -                    RotTimer = 20000; -                    return; -                } -                else -                    SpoutTimer -= diff; +                    if (player->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, player) && me->IsWithinDist(player, SPOUT_DIST) && !player->IsInWater()) +                        DoCast(player, SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water +                }); -                // Whirl directly after a Spout and at random times -                if (WhirlTimer <= diff) +                if (SpoutAnimTimer <= diff)                  { -                    WhirlTimer = 18000; -                    DoCast(me, SPELL_WHIRL); -                } -                else -                    WhirlTimer -= diff; +                    DoCast(me, SPELL_SPOUT_ANIM, true); +                    SpoutAnimTimer = 1000; +                } else SpoutAnimTimer -= diff; -                if (CheckTimer <= diff) // check if there are players in melee range +                if (RotTimer <= diff)                  { -                    InRange = false; -                    Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); -                    if (!PlayerList.isEmpty()) -                    { -                        for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) -                        { -                            if (me->IsWithinMeleeRange(i->GetSource())) -                                InRange = true; -                        } -                    } -                    CheckTimer = 2000; +                    RotTimer = 0;                  }                  else -                    CheckTimer -= diff; - -                if (RotTimer) -                { -                    instance->instance->DoOnPlayers([this, diff](Player* player) -                    { -                        if (player->IsAlive() && me->HasInArc(diff / 20000.f * float(M_PI) * 2.f, player) && me->IsWithinDist(player, SPOUT_DIST) && !player->IsInWater()) -                            DoCast(player, SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water -                    }); - -                    if (SpoutAnimTimer <= diff) -                    { -                        DoCast(me, SPELL_SPOUT_ANIM, true); -                        SpoutAnimTimer = 1000; -                    } else SpoutAnimTimer -= diff; +                    RotTimer -= diff; +                return; +            } -                    if (RotTimer <= diff) -                    { -                        RotTimer = 0; -                    } -                    else -                        RotTimer -= diff; -                    return; -                } +            if (GeyserTimer <= diff) +            { +                Unit* target = SelectTarget(SelectTargetMethod::Random, 1); +                if (!target && me->GetVictim()) +                    target = me->GetVictim(); +                if (target) +                    DoCast(target, SPELL_GEYSER, true); +                GeyserTimer = rand32() % 5000 + 15000; +            } +            else +                GeyserTimer -= diff; -                if (GeyserTimer <= diff) +            if (!InRange) // if on players in melee range cast Waterbolt +            { +                if (WaterboltTimer <= diff)                  { -                    Unit* target = SelectTarget(SelectTargetMethod::Random, 1); +                    Unit* target = SelectTarget(SelectTargetMethod::Random, 0);                      if (!target && me->GetVictim())                          target = me->GetVictim();                      if (target) -                        DoCast(target, SPELL_GEYSER, true); -                    GeyserTimer = rand32() % 5000 + 15000; +                        DoCast(target, SPELL_WATERBOLT, true); +                    WaterboltTimer = 3000;                  }                  else -                    GeyserTimer -= diff; - -                if (!InRange) // if on players in melee range cast Waterbolt -                { -                    if (WaterboltTimer <= diff) -                    { -                        Unit* target = SelectTarget(SelectTargetMethod::Random, 0); -                        if (!target && me->GetVictim()) -                            target = me->GetVictim(); -                        if (target) -                            DoCast(target, SPELL_WATERBOLT, true); -                        WaterboltTimer = 3000; -                    } -                    else -                        WaterboltTimer -= diff; -                } +                    WaterboltTimer -= diff; +            } -                if (!UpdateVictim()) -                    return; +            if (!UpdateVictim()) +                return; -                DoMeleeAttackIfReady(); +            DoMeleeAttackIfReady(); -            } -            else // submerged +        } +        else // submerged +        { +            if (PhaseTimer <= diff)              { -                if (PhaseTimer <= diff) -                { -                    Submerged = false; -                    me->InterruptNonMeleeSpells(false); // shouldn't be any -                    me->RemoveAllAuras(); -                    me->SetImmuneToPC(false); -                    me->SetEmoteState(EMOTE_ONESHOT_NONE); -                    DoCast(me, SPELL_EMERGE, true); -                    Spawned = false; -                    SpoutTimer = 3000; // directly cast Spout after emerging! -                    PhaseTimer = 120000; -                    return; -                } -                else -                    PhaseTimer -= diff; +                Submerged = false; +                me->InterruptNonMeleeSpells(false); // shouldn't be any +                me->RemoveAllAuras(); +                me->SetImmuneToPC(false); +                me->SetEmoteState(EMOTE_ONESHOT_NONE); +                DoCast(me, SPELL_EMERGE, true); +                Spawned = false; +                SpoutTimer = 3000; // directly cast Spout after emerging! +                PhaseTimer = 120000; +                return; +            } +            else +                PhaseTimer -= diff; -                if (!me->IsThreatened()) // check if should evade -                { -                    EnterEvadeMode(); -                    return; -                } +            if (!me->IsThreatened()) // check if should evade +            { +                EnterEvadeMode(); +                return; +            } -                if (!me->IsInCombat()) -                    DoZoneInCombat(); +            if (!me->IsInCombat()) +                DoZoneInCombat(); -                if (!Spawned) -                { -                    me->ReplaceAllUnitFlags(UNIT_FLAG_IMMUNE_TO_PC); -                    // spawn adds -                    for (uint8 i = 0; i < 9; ++i) -                        if (Creature* summoned = me->SummonCreature(i < 6 ? NPC_COILFANG_AMBUSHER : NPC_COILFANG_GUARDIAN, AddPos[i][0], AddPos[i][1], AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN)) -                            Summons.Summon(summoned); -                    Spawned = true; -                } +            if (!Spawned) +            { +                me->ReplaceAllUnitFlags(UNIT_FLAG_IMMUNE_TO_PC); +                // spawn adds +                for (uint8 i = 0; i < 9; ++i) +                    me->SummonCreature(i < 6 ? NPC_COILFANG_AMBUSHER : NPC_COILFANG_GUARDIAN, AddPos[i][0], AddPos[i][1], AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN); +                Spawned = true;              }          } -     }; -}; +    } + }; -class npc_coilfang_ambusher : public CreatureScript +struct npc_coilfang_ambusher : public ScriptedAI  { -public: -    npc_coilfang_ambusher() : CreatureScript("npc_coilfang_ambusher") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_coilfang_ambusher(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_coilfang_ambusherAI>(creature); +        Initialize(); +        SetCombatMovement(false);      } -    struct npc_coilfang_ambusherAI : public ScriptedAI +    void Initialize()      { -        npc_coilfang_ambusherAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            SetCombatMovement(false); -        } - -        void Initialize() -        { -            MultiShotTimer = 10000; -            ShootBowTimer = 4000; -        } +        MultiShotTimer = 10000; +        ShootBowTimer = 4000; +    } -        uint32 MultiShotTimer; -        uint32 ShootBowTimer; +    uint32 MultiShotTimer; +    uint32 ShootBowTimer; -        void Reset() override -        { -            Initialize(); -        } +    void Reset() override +    { +        Initialize(); +    } -        void MoveInLineOfSight(Unit* who) override +    void MoveInLineOfSight(Unit* who) override -        { -            if (!who || me->GetVictim()) -                return; +    { +        if (!who || me->GetVictim()) +            return; -            if (who->isInAccessiblePlaceFor(me) && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 45)) -                AttackStart(who); -        } +        if (who->isInAccessiblePlaceFor(me) && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 45)) +            AttackStart(who); +    } -        void UpdateAI(uint32 diff) override +    void UpdateAI(uint32 diff) override +    { +        if (MultiShotTimer <= diff)          { -            if (MultiShotTimer <= diff) -            { -                if (me->GetVictim()) -                    DoCastVictim(SPELL_SPREAD_SHOT, true); +            if (me->GetVictim()) +                DoCastVictim(SPELL_SPREAD_SHOT, true); -                MultiShotTimer = 10000 + rand32() % 10000; -                ShootBowTimer += 1500; // add global cooldown -            } else MultiShotTimer -= diff; - -            if (ShootBowTimer <= diff) -            { -                if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                    me->CastSpell(target, SPELL_SHOOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(1100)); -                ShootBowTimer = 4000 + rand32() % 5000; -                MultiShotTimer += 1500; // add global cooldown -            } else ShootBowTimer -= diff; -        } -    }; +            MultiShotTimer = 10000 + rand32() % 10000; +            ShootBowTimer += 1500; // add global cooldown +        } else MultiShotTimer -= diff; +        if (ShootBowTimer <= diff) +        { +            if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                me->CastSpell(target, SPELL_SHOOT, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(1100)); +            ShootBowTimer = 4000 + rand32() % 5000; +            MultiShotTimer += 1500; // add global cooldown +        } else ShootBowTimer -= diff; +    }  }; -class go_strange_pool : public GameObjectScript +struct go_strange_pool : public GameObjectAI  { -    public: -        go_strange_pool() : GameObjectScript("go_strange_pool") { } - -        struct go_strange_poolAI : public GameObjectAI -        { -            go_strange_poolAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { } +    go_strange_pool(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { } -            InstanceScript* instance; +    InstanceScript* instance; -            bool OnGossipHello(Player* player) override +    bool OnGossipHello(Player* player) override +    { +        // 25% +        if (!urand(0, 3)) +        { +            if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED)              { -                // 25% -                if (!urand(0, 3)) -                { -                    if (instance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) -                    { -                        me->CastSpell(player, 54587); -                        instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS); -                    } -                    return true; -                } - -                return false; +                me->CastSpell(player, 54587); +                instance->SetData(DATA_STRANGE_POOL, IN_PROGRESS);              } -        }; - -        GameObjectAI* GetAI(GameObject* go) const override -        { -            return GetSerpentshrineCavernAI<go_strange_poolAI>(go); +            return true;          } + +        return false; +    }  };  void AddSC_boss_the_lurker_below()  { -    new boss_the_lurker_below(); -    new npc_coilfang_ambusher(); -    new go_strange_pool(); +    RegisterSerpentshrineCavernCreatureAI(boss_the_lurker_below); +    RegisterSerpentshrineCavernCreatureAI(npc_coilfang_ambusher); +    RegisterSerpentshrineCavernGameObjectAI(go_strange_pool);  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp index a752c81adaa..f3273232950 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp @@ -86,286 +86,253 @@ float MurlocCords[10][4] =  };  //Morogrim Tidewalker AI -class boss_morogrim_tidewalker : public CreatureScript +struct boss_morogrim_tidewalker : public BossAI  { -public: -    boss_morogrim_tidewalker() : CreatureScript("boss_morogrim_tidewalker") { } - -    CreatureAI* GetAI(Creature* creature) const override +    boss_morogrim_tidewalker(Creature* creature) : BossAI(creature, BOSS_MOROGRIM_TIDEWALKER)      { -        return GetSerpentshrineCavernAI<boss_morogrim_tidewalkerAI>(creature); +        Initialize(); +        Playercount = 0; +        counter = 0;      } -    struct boss_morogrim_tidewalkerAI : public ScriptedAI +    void Initialize()      { -        boss_morogrim_tidewalkerAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -            instance = creature->GetInstanceScript(); -            Playercount = 0; -            counter = 0; -        } +        TidalWave_Timer = 10000; +        WateryGrave_Timer = 30000; +        Earthquake_Timer = 40000; +        WateryGlobules_Timer = 0; +        globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; +        globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; +        globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; +        globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; + +        Earthquake = false; +        Phase2 = false; +    } -        void Initialize() -        { -            TidalWave_Timer = 10000; -            WateryGrave_Timer = 30000; -            Earthquake_Timer = 40000; -            WateryGlobules_Timer = 0; -            globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; -            globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; -            globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; -            globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; - -            Earthquake = false; -            Phase2 = false; -        } +    uint32 TidalWave_Timer; +    uint32 WateryGrave_Timer; +    uint32 Earthquake_Timer; +    uint32 WateryGlobules_Timer; +    uint32 globulespell[4]; +    int8 Playercount; +    int8 counter; -        InstanceScript* instance; +    bool Earthquake; +    bool Phase2; -        uint32 TidalWave_Timer; -        uint32 WateryGrave_Timer; -        uint32 Earthquake_Timer; -        uint32 WateryGlobules_Timer; -        uint32 globulespell[4]; -        int8 Playercount; -        int8 counter; +    void Reset() override +    { +        Initialize(); -        bool Earthquake; -        bool Phase2; +        _Reset(); +    } -        void Reset() override -        { -            Initialize(); +    void KilledUnit(Unit* /*victim*/) override +    { +        Talk(SAY_SLAY); +    } -            instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); -        } +    void JustDied(Unit* /*killer*/) override +    { +        Talk(SAY_DEATH); -        void StartEvent() -        { -            Talk(SAY_AGGRO); +        _JustDied(); +    } -            instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); -        } +    void JustEngagedWith(Unit* who) override +    { +        Playercount = me->GetMap()->GetPlayers().getSize(); +        Talk(SAY_AGGRO); +        _JustEngagedWith(who); +    } -        void KilledUnit(Unit* /*victim*/) override +    void ApplyWateryGrave(Unit* player, uint8 i) +    { +        switch (i)          { -            Talk(SAY_SLAY); -        } - -        void JustDied(Unit* /*killer*/) override -        { -            Talk(SAY_DEATH); - -            instance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); +        case 0: player->CastSpell(player, SPELL_WATERY_GRAVE_1, true); break; +        case 1: player->CastSpell(player, SPELL_WATERY_GRAVE_2, true); break; +        case 2: player->CastSpell(player, SPELL_WATERY_GRAVE_3, true); break; +        case 3: player->CastSpell(player, SPELL_WATERY_GRAVE_4, true); break;          } +    } -        void JustEngagedWith(Unit* /*who*/) override -        { -            Playercount = me->GetMap()->GetPlayers().getSize(); -            StartEvent(); -        } +    void UpdateAI(uint32 diff) override +    { +        //Return since we have no target +        if (!UpdateVictim()) +            return; -        void ApplyWateryGrave(Unit* player, uint8 i) +        //Earthquake_Timer +        if (Earthquake_Timer <= diff)          { -            switch (i) +            if (!Earthquake)              { -            case 0: player->CastSpell(player, SPELL_WATERY_GRAVE_1, true); break; -            case 1: player->CastSpell(player, SPELL_WATERY_GRAVE_2, true); break; -            case 2: player->CastSpell(player, SPELL_WATERY_GRAVE_3, true); break; -            case 3: player->CastSpell(player, SPELL_WATERY_GRAVE_4, true); break; +                DoCastVictim(SPELL_EARTHQUAKE); +                Earthquake = true; +                Earthquake_Timer = 10000;              } -        } - -        void UpdateAI(uint32 diff) override -        { -            //Return since we have no target -            if (!UpdateVictim()) -                return; - -            //Earthquake_Timer -            if (Earthquake_Timer <= diff) +            else              { -                if (!Earthquake) -                { -                    DoCastVictim(SPELL_EARTHQUAKE); -                    Earthquake = true; -                    Earthquake_Timer = 10000; -                } -                else -                { -                    Talk(SAY_SUMMON); +                Talk(SAY_SUMMON); -                    for (uint8 i = 0; i < 10; ++i) -                    { -                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) -                            if (Creature* Murloc = me->SummonCreature(NPC_TIDEWALKER_LURKER, MurlocCords[i][0], MurlocCords[i][1], MurlocCords[i][2], MurlocCords[i][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10s)) -                                Murloc->AI()->AttackStart(target); -                    } -                    Talk(EMOTE_EARTHQUAKE); -                    Earthquake = false; -                    Earthquake_Timer = 40000 + rand32() % 5000; +                for (uint8 i = 0; i < 10; ++i) +                { +                    if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) +                        if (Creature* Murloc = me->SummonCreature(NPC_TIDEWALKER_LURKER, MurlocCords[i][0], MurlocCords[i][1], MurlocCords[i][2], MurlocCords[i][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10s)) +                            Murloc->AI()->AttackStart(target);                  } -            } else Earthquake_Timer -= diff; +                Talk(EMOTE_EARTHQUAKE); +                Earthquake = false; +                Earthquake_Timer = 40000 + rand32() % 5000; +            } +        } else Earthquake_Timer -= diff; -            //TidalWave_Timer -            if (TidalWave_Timer <= diff) -            { -                DoCastVictim(SPELL_TIDAL_WAVE); -                TidalWave_Timer = 20000; -            } else TidalWave_Timer -= diff; +        //TidalWave_Timer +        if (TidalWave_Timer <= diff) +        { +            DoCastVictim(SPELL_TIDAL_WAVE); +            TidalWave_Timer = 20000; +        } else TidalWave_Timer -= diff; -            if (!Phase2) +        if (!Phase2) +        { +            //WateryGrave_Timer +            if (WateryGrave_Timer <= diff)              { -                //WateryGrave_Timer -                if (WateryGrave_Timer <= diff) +                //Teleport 4 players under the waterfalls +                GuidSet targets; +                GuidSet::const_iterator itr = targets.begin(); +                for (uint8 i = 0; i < 4; ++i)                  { -                    //Teleport 4 players under the waterfalls -                    GuidSet targets; -                    GuidSet::const_iterator itr = targets.begin(); -                    for (uint8 i = 0; i < 4; ++i) +                    counter = 0; +                    Unit* target; +                    do                      { -                        counter = 0; -                        Unit* target; -                        do -                        { -                            target = SelectTarget(SelectTargetMethod::Random, 1, 50, true);    //target players only -                            if (counter < Playercount) -                                break; -                            if (target) -                                itr = targets.find(target->GetGUID()); -                            ++counter; -                        } while (itr != targets.end()); - +                        target = SelectTarget(SelectTargetMethod::Random, 1, 50, true);    //target players only +                        if (counter < Playercount) +                            break;                          if (target) -                        { -                            targets.insert(target->GetGUID()); -                            ApplyWateryGrave(target, i); -                        } +                            itr = targets.find(target->GetGUID()); +                        ++counter; +                    } while (itr != targets.end()); + +                    if (target) +                    { +                        targets.insert(target->GetGUID()); +                        ApplyWateryGrave(target, i);                      } +                } -                    Talk(SAY_SUMMON_BUBL); +                Talk(SAY_SUMMON_BUBL); -                    Talk(EMOTE_WATERY_GRAVE); -                    WateryGrave_Timer = 30000; -                } else WateryGrave_Timer -= diff; +                Talk(EMOTE_WATERY_GRAVE); +                WateryGrave_Timer = 30000; +            } else WateryGrave_Timer -= diff; -                //Start Phase2 -                if (HealthBelowPct(25)) -                    Phase2 = true; -            } -            else +            //Start Phase2 +            if (HealthBelowPct(25)) +                Phase2 = true; +        } +        else +        { +            //WateryGlobules_Timer +            if (WateryGlobules_Timer <= diff)              { -                //WateryGlobules_Timer -                if (WateryGlobules_Timer <= diff) +                GuidSet globules; +                GuidSet::const_iterator itr = globules.begin(); +                for (uint8 g = 0; g < 4; g++)  //one unit can't cast more than one spell per update, so some players have to cast for us XD                  { -                    GuidSet globules; -                    GuidSet::const_iterator itr = globules.begin(); -                    for (uint8 g = 0; g < 4; g++)  //one unit can't cast more than one spell per update, so some players have to cast for us XD +                    counter = 0; +                    Unit* pGlobuleTarget; +                    do                      { -                        counter = 0; -                        Unit* pGlobuleTarget; -                        do -                        { -                            pGlobuleTarget = SelectTarget(SelectTargetMethod::Random, 0, 50, true); -                            if (pGlobuleTarget) -                                itr = globules.find(pGlobuleTarget->GetGUID()); -                            if (counter > Playercount) -                                break; -                            ++counter; -                        } while (itr != globules.end()); - +                        pGlobuleTarget = SelectTarget(SelectTargetMethod::Random, 0, 50, true);                          if (pGlobuleTarget) -                        { -                            globules.insert(pGlobuleTarget->GetGUID()); -                            pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); -                        } -                    } -                    Talk(EMOTE_WATERY_GLOBULES); -                    WateryGlobules_Timer = 25000; -                } else WateryGlobules_Timer -= diff; -            } +                            itr = globules.find(pGlobuleTarget->GetGUID()); +                        if (counter > Playercount) +                            break; +                        ++counter; +                    } while (itr != globules.end()); -            DoMeleeAttackIfReady(); +                    if (pGlobuleTarget) +                    { +                        globules.insert(pGlobuleTarget->GetGUID()); +                        pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); +                    } +                } +                Talk(EMOTE_WATERY_GLOBULES); +                WateryGlobules_Timer = 25000; +            } else WateryGlobules_Timer -= diff;          } -    }; +        DoMeleeAttackIfReady(); +    }  }; -class npc_water_globule : public CreatureScript +struct npc_water_globule : public ScriptedAI  { -public: -    npc_water_globule() : CreatureScript("npc_water_globule") { } - -    CreatureAI* GetAI(Creature* creature) const override +    npc_water_globule(Creature* creature) : ScriptedAI(creature)      { -        return GetSerpentshrineCavernAI<npc_water_globuleAI>(creature); +        Initialize();      } -    struct npc_water_globuleAI : public ScriptedAI +    void Initialize()      { -        npc_water_globuleAI(Creature* creature) : ScriptedAI(creature) -        { -            Initialize(); -        } +        Check_Timer = 1000; +    } -        void Initialize() -        { -            Check_Timer = 1000; -        } +    uint32 Check_Timer; -        uint32 Check_Timer; +    void Reset() override +    { +        Initialize(); -        void Reset() override -        { -            Initialize(); +        me->SetFaction(FACTION_MONSTER); +    } -            me->SetFaction(FACTION_MONSTER); -        } +    void JustEngagedWith(Unit* /*who*/) override { } -        void JustEngagedWith(Unit* /*who*/) override { } +    void MoveInLineOfSight(Unit* who) override -        void MoveInLineOfSight(Unit* who) override +    { +        if (!who || me->GetVictim()) +            return; +        if (me->CanCreatureAttack(who))          { -            if (!who || me->GetVictim()) -                return; - -            if (me->CanCreatureAttack(who)) -            { -                //no attack radius check - it attacks the first target that moves in his los -                //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); -                AttackStart(who); -            } +            //no attack radius check - it attacks the first target that moves in his los +            //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); +            AttackStart(who);          } +    } -        void UpdateAI(uint32 diff) override -        { -            //Return since we have no target -            if (!UpdateVictim()) -                return; +    void UpdateAI(uint32 diff) override +    { +        //Return since we have no target +        if (!UpdateVictim()) +            return; -            if (Check_Timer <= diff) +        if (Check_Timer <= diff) +        { +            if (me->IsWithinDistInMap(me->GetVictim(), 5))              { -                if (me->IsWithinDistInMap(me->GetVictim(), 5)) -                { -                    DoCastVictim(SPELL_GLOBULE_EXPLOSION); - -                    //despawn -                    me->DespawnOrUnsummon(); -                    return; -                } -                Check_Timer = 500; -            } else Check_Timer -= diff; +                DoCastVictim(SPELL_GLOBULE_EXPLOSION); -            //do NOT deal any melee damage to the target. -        } -    }; +                //despawn +                me->DespawnOrUnsummon(); +                return; +            } +            Check_Timer = 500; +        } else Check_Timer -= diff; +        //do NOT deal any melee damage to the target. +    }  };  void AddSC_boss_morogrim_tidewalker()  { -    new boss_morogrim_tidewalker(); -    new npc_water_globule(); +    RegisterSerpentshrineCavernCreatureAI(boss_morogrim_tidewalker); +    RegisterSerpentshrineCavernCreatureAI(npc_water_globule);  } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp index ab2586716e2..ebde8fa0ccc 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp @@ -97,7 +97,7 @@ class instance_serpent_shrine : public InstanceMapScript              instance_serpentshrine_cavern_InstanceMapScript(InstanceMap* map) : InstanceScript(map)              {                  SetHeaders(DataHeader); -                memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); +                SetBossNumber(MAX_ENCOUNTER);                  StrangePool = 0;                  Water = WATERSTATE_FRENZY; @@ -113,15 +113,6 @@ class instance_serpent_shrine : public InstanceMapScript                  TrashCount = 0;              } -            bool IsEncounterInProgress() const override -            { -                for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) -                    if (m_auiEncounter[i] == IN_PROGRESS) -                        return true; - -                return false; -            } -              void Update(uint32 diff) override              {                  //Water checks @@ -299,32 +290,6 @@ class instance_serpent_shrine : public InstanceMapScript                      case DATA_WATER:                          Water = data;                          break; -                    case DATA_HYDROSSTHEUNSTABLEEVENT: -                        m_auiEncounter[0] = data; -                        break; -                    case DATA_LEOTHERASTHEBLINDEVENT: -                        m_auiEncounter[1] = data; -                        break; -                    case DATA_THELURKERBELOWEVENT: -                        m_auiEncounter[2] = data; -                        break; -                    case DATA_KARATHRESSEVENT: -                        m_auiEncounter[3] = data; -                        break; -                    case DATA_MOROGRIMTIDEWALKEREVENT: -                        m_auiEncounter[4] = data; -                        break; -                        //Lady Vashj -                    case DATA_LADYVASHJEVENT: -                        if (data == NOT_STARTED) -                        { -                            ShieldGeneratorDeactivated[0] = false; -                            ShieldGeneratorDeactivated[1] = false; -                            ShieldGeneratorDeactivated[2] = false; -                            ShieldGeneratorDeactivated[3] = false; -                        } -                        m_auiEncounter[5] = data; -                        break;                      case DATA_SHIELDGENERATOR1:                          ShieldGeneratorDeactivated[0] = data != 0;                          break; @@ -340,28 +305,28 @@ class instance_serpent_shrine : public InstanceMapScript                      default:                          break;                  } +            } + +            bool SetBossState(uint32 id, EncounterState state) override +            { +                if (!InstanceScript::SetBossState(id, state)) +                    return false; + +                if (id == BOSS_LADY_VASHJ && state == NOT_STARTED) +                { +                    ShieldGeneratorDeactivated[0] = false; +                    ShieldGeneratorDeactivated[1] = false; +                    ShieldGeneratorDeactivated[2] = false; +                    ShieldGeneratorDeactivated[3] = false; +                } -                if (data == DONE) -                    SaveToDB(); +                return true;              }              uint32 GetData(uint32 type) const override              {                  switch (type)                  { -                    case DATA_HYDROSSTHEUNSTABLEEVENT: -                        return m_auiEncounter[0]; -                    case DATA_LEOTHERASTHEBLINDEVENT: -                        return m_auiEncounter[1]; -                    case DATA_THELURKERBELOWEVENT: -                        return m_auiEncounter[2]; -                    case DATA_KARATHRESSEVENT: -                        return m_auiEncounter[3]; -                    case DATA_MOROGRIMTIDEWALKEREVENT: -                        return m_auiEncounter[4]; -                        //Lady Vashj -                    case DATA_LADYVASHJEVENT: -                        return m_auiEncounter[5];                      case DATA_SHIELDGENERATOR1:                          return ShieldGeneratorDeactivated[0];                      case DATA_SHIELDGENERATOR2: @@ -385,34 +350,14 @@ class instance_serpent_shrine : public InstanceMapScript                  return 0;              } -            std::string GetSaveData() override +            void WriteSaveDataMore(std::ostringstream& stream) override              { -                OUT_SAVE_INST_DATA; -                std::ostringstream stream; -                stream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' -                    << m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' << m_auiEncounter[5] << ' ' << TrashCount; -                OUT_SAVE_INST_DATA_COMPLETE; -                return stream.str(); +                stream << TrashCount;              } -            void Load(char const* in) override +            void ReadSaveDataMore(std::istringstream& stream) override              { -                if (!in) -                { -                    OUT_LOAD_INST_DATA_FAIL; -                    return; -                } - -                OUT_LOAD_INST_DATA(in); -                std::istringstream stream(in); -                stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] -                    >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; - -                for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) -                    if (m_auiEncounter[i] == IN_PROGRESS)                // Do not load an encounter as "In Progress" - reset it instead. -                        m_auiEncounter[i] = NOT_STARTED; - -                OUT_LOAD_INST_DATA_COMPLETE; +                stream >> TrashCount;              }          private: @@ -436,7 +381,6 @@ class instance_serpent_shrine : public InstanceMapScript              uint32 TrashCount;              bool ShieldGeneratorDeactivated[4]; -            uint32 m_auiEncounter[MAX_ENCOUNTER];              bool DoSpawnFrenzy;          }; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h index b7ad1f73512..2228a36d8c8 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h @@ -30,33 +30,37 @@ enum SSWaterEventState      WATERSTATE_SCALDING = 2  }; +enum SSBosses +{ +    BOSS_HYDROSS_THE_UNSTABLE   = 0, +    BOSS_THE_LURKER_BELOW       = 1, +    BOSS_LEOTHERAS_THE_BLIND    = 2, +    BOSS_FATHOM_LORD_KARATHRESS = 3, +    BOSS_MOROGRIM_TIDEWALKER    = 4, +    BOSS_LADY_VASHJ             = 5 +}; +  enum SSDataTypes  {      DATA_CANSTARTPHASE3             = 1,      DATA_CARIBDIS                   = 2, -    DATA_HYDROSSTHEUNSTABLEEVENT    = 3, -    DATA_KARATHRESS                 = 4, -    DATA_KARATHRESSEVENT            = 5, -    DATA_KARATHRESSEVENT_STARTER    = 6, -    DATA_LADYVASHJ                  = 7, -    DATA_LADYVASHJEVENT             = 8, -    DATA_LEOTHERASTHEBLINDEVENT     = 9, -    DATA_MOROGRIMTIDEWALKEREVENT    = 10, -    DATA_SHARKKIS                   = 11, -    DATA_SHIELDGENERATOR1           = 12, -    DATA_SHIELDGENERATOR2           = 13, -    DATA_SHIELDGENERATOR3           = 14, -    DATA_SHIELDGENERATOR4           = 15, -    DATA_THELURKERBELOW             = 16, -    DATA_THELURKERBELOWEVENT        = 17, -    DATA_TIDALVESS                  = 18, -    DATA_FATHOMLORDKARATHRESSEVENT  = 19, -    DATA_LEOTHERAS                  = 20, -    DATA_LEOTHERAS_EVENT_STARTER    = 21, -    DATA_CONTROL_CONSOLE            = 22, -    DATA_STRANGE_POOL               = 23, -    DATA_WATER                      = 24, -    DATA_TRASH                      = 25, +    DATA_KARATHRESS                 = 3, +    DATA_KARATHRESSEVENT_STARTER    = 4, +    DATA_LADYVASHJ                  = 5, +    DATA_SHARKKIS                   = 6, +    DATA_SHIELDGENERATOR1           = 7, +    DATA_SHIELDGENERATOR2           = 8, +    DATA_SHIELDGENERATOR3           = 9, +    DATA_SHIELDGENERATOR4           = 10, +    DATA_THELURKERBELOW             = 11, +    DATA_TIDALVESS                  = 12, +    DATA_FATHOMLORDKARATHRESSEVENT  = 13, +    DATA_LEOTHERAS                  = 14, +    DATA_LEOTHERAS_EVENT_STARTER    = 15, +    DATA_CONTROL_CONSOLE            = 16, +    DATA_STRANGE_POOL               = 17, +    DATA_WATER                      = 18, +    DATA_TRASH                      = 19,  };  template <class AI, class T> @@ -65,4 +69,7 @@ inline AI* GetSerpentshrineCavernAI(T* obj)      return GetInstanceAI<AI>(obj, SSCScriptName);  } +#define RegisterSerpentshrineCavernCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetSerpentshrineCavernAI) +#define RegisterSerpentshrineCavernGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetSerpentshrineCavernAI) +  #endif  | 
