diff options
Diffstat (limited to 'src/server/scripts')
| -rw-r--r-- | src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp | 500 | 
1 files changed, 324 insertions, 176 deletions
diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index 7458e86592e..193f8c6cb4c 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -25,213 +25,336 @@  enum Spells  {      SPELL_EMERGE                                  = 54850, -    SPELL_MIGHTY_BLOW                             = 54719, +    SPELL_ELEMENTAL_SPAWN_EFEFCT                  = 54888, +    SPELL_MOJO_VOLLEY                             = 54849, +    SPELL_SURGE_VISUAL                            = 54827,      SPELL_MERGE                                   = 54878, +    SPELL_MIGHTY_BLOW                             = 54719,      SPELL_SURGE                                   = 54801,      SPELL_FREEZE_ANIM                             = 16245,      SPELL_MOJO_PUDDLE                             = 55627, -    H_SPELL_MOJO_PUDDLE                           = 58994,      SPELL_MOJO_WAVE                               = 55626, -    H_SPELL_MOJO_WAVE                             = 58993  }; -class boss_drakkari_colossus : public CreatureScript +enum ColossusEvents  { -public: -    boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { } +    EVENT_MIGHTY_BLOW   = 1, +}; -    CreatureAI* GetAI(Creature* pCreature) const -    { -        return new boss_drakkari_colossusAI (pCreature); -    } +enum ColossusActions +{ +    ACTION_SUMMON_ELEMENTAL     = 1, +    ACTION_FREEZE_COLOSSUS      = 2, +    ACTION_UNFREEZE_COLOSSUS    = 3, +}; -    struct boss_drakkari_colossusAI : public ScriptedAI -    { -        boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) -        { -            pInstance = pCreature->GetInstanceScript(); -        } +enum ColossusPhases +{ +    COLOSSUS_PHASE_NORMAL                   = 1, +    COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON   = 2, +    COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON  = 3 +}; -        InstanceScript* pInstance; +enum ColossusData +{ +    DATA_COLOSSUS_PHASE = 1, +    DATA_INTRO_DONE     = 2 +}; -        bool bHealth; -        bool bHealth1; +enum ElementalActions +{ +    ACTION_RETURN_TO_COLOSSUS = 1 +}; -        uint32 MightyBlowTimer; +enum ElementalEvents +{ +    EVENT_SURGE = 1 +}; -        void Reset() -        { -            if (pInstance) -                pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); -            if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) -                me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); -            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); -            me->ClearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); -            me->SetReactState(REACT_PASSIVE); -            MightyBlowTimer = 10*IN_MILLISECONDS; -            bHealth = false; -            bHealth1 = false; -        } +class boss_drakkari_colossus : public CreatureScript +{ +    public: +        boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { } -        void EnterCombat(Unit* /*who*/) +        struct boss_drakkari_colossusAI : public BossAI          { -            if (pInstance) -                pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); -        } +            boss_drakkari_colossusAI(Creature* creature) : BossAI(creature, DATA_DRAKKARI_COLOSSUS_EVENT)  +            { +                me->SetReactState(REACT_PASSIVE); +                introDone = false; +            } -        void CreatureState(Creature* pWho, bool bRestore = false) -        { -            if (!pWho) -                return; +            void InitializeAI() +            { +                if (!me->isDead()) +                    Reset(); +            } -            if (bRestore) +            void Reset()              { -                pWho->ClearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); -                pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); -                if (pWho == me) +                if (GetData(DATA_INTRO_DONE)) +                { +                    me->SetReactState(REACT_AGGRESSIVE); +                    me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE);                      me->RemoveAura(SPELL_FREEZE_ANIM); -            }else +                } + +                events.Reset(); +                events.ScheduleEvent(EVENT_MIGHTY_BLOW, urand(10000,30000)); + +                phase = COLOSSUS_PHASE_NORMAL; + +                instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); +            } + +            void EnterCombat(Unit* /*who*/)              { -                pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); -                pWho->AddUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); -                if (pWho == me) -                    DoCast(me,SPELL_FREEZE_ANIM); +                instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); + +                me->RemoveAura(SPELL_FREEZE_ANIM);              } -        } -        void UpdateAI(const uint32 diff) -        { -            //Return since we have no target -            if (!UpdateVictim()) -                return; +            void JustDied(Unit* /*killer*/) +            { +                instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); +            } -            if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5)) +            void JustReachedHome()              { -                CreatureState(me, false); -                DoCast(me,SPELL_FREEZE_ANIM); -                DoCast(me,SPELL_EMERGE); -                bHealth = true; +                instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, FAIL);              } -            if (!bHealth1 && HealthBelowPct(5)) +            void DoAction(const int32 action)              { -                DoCast(me,SPELL_EMERGE); -                CreatureState(me, false); -                bHealth1 = true; -                me->RemoveAllAuras(); +                switch (action) +                { +                    case ACTION_SUMMON_ELEMENTAL: +                        DoCast(SPELL_EMERGE); +                        break; +                    case ACTION_FREEZE_COLOSSUS: +                        me->GetMotionMaster()->MoveIdle(); + +                        me->SetReactState(REACT_PASSIVE); +                        me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); +                        DoCast(me,SPELL_FREEZE_ANIM); +                        break; +                    case ACTION_UNFREEZE_COLOSSUS: + +                        if (me->GetReactState() == REACT_AGGRESSIVE) +                            return; + +                        me->SetReactState(REACT_AGGRESSIVE); +                        me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); +                        me->RemoveAura(SPELL_FREEZE_ANIM); + +                        me->SetInCombatWithZone(); + +                        if (me->getVictim()) +                            me->GetMotionMaster()->MoveChase(me->getVictim(), 0,0); + +                        break; +                }              } -            if (MightyBlowTimer <= diff) +            void DamageTaken(Unit* /*attacker*/, uint32& damage)              { -                DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); -                MightyBlowTimer = 10*IN_MILLISECONDS; -            } else MightyBlowTimer -= diff; +                if (me->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE)) +                    damage = 0; -            if (!me->HasUnitState(UNIT_STAT_STUNNED)) -                DoMeleeAttackIfReady(); -        } +                if (phase == COLOSSUS_PHASE_NORMAL || +                    phase == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON) +                { +                    if (HealthBelowPct( phase == COLOSSUS_PHASE_NORMAL ? 50 : 5)) +                    { +                        damage = 0; +                        phase = (phase == COLOSSUS_PHASE_NORMAL ? COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON : COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON); +                        DoAction(ACTION_FREEZE_COLOSSUS); +                        DoAction(ACTION_SUMMON_ELEMENTAL); +                         +                    } +                } +            } -        void JustDied(Unit* /*killer*/) -        { -            if (pInstance) -                pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); -        } +            uint32 GetData(uint32 data) +            { +               if (data == DATA_COLOSSUS_PHASE) +                   return phase; +               else if (data == DATA_INTRO_DONE) +                   return introDone; + +               return 0; +            } + +            void SetData(uint32 type, uint32 data) +            { +                if (type == DATA_INTRO_DONE) +                    introDone = data; +            } + +            void UpdateAI(const uint32 diff) +            { +                if (!UpdateVictim()) +                    return; -        void JustSummoned(Creature* pSummon) +                events.Update(diff); + +                if (me->HasUnitState(UNIT_STAT_CASTING)) +                    return; + +                while (uint32 eventId = events.ExecuteEvent()) +                { +                    switch (eventId) +                    { +                        case EVENT_MIGHTY_BLOW: +                            DoCast(me->getVictim(),SPELL_MIGHTY_BLOW); +                            events.ScheduleEvent(EVENT_MIGHTY_BLOW, urand(5000,15000)); +                            break; +                    } +                } + +                if (me->GetReactState() == REACT_AGGRESSIVE) +                    DoMeleeAttackIfReady(); +            } + +            void JustSummoned(Creature* summon) +            { +               summon->SetInCombatWithZone(); + +               if (phase == COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON) +                   summon->SetHealth(summon->GetMaxHealth() / 2); +            } + +        private: +            uint8 phase; +            bool introDone; +        }; + +        CreatureAI* GetAI(Creature* creature) const          { -            if (HealthBelowPct(5)) -                pSummon->DealDamage(pSummon, uint32(pSummon->GetHealth() * 0.5), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); -            pSummon->AI()->AttackStart(me->getVictim()); +            return new boss_drakkari_colossusAI(creature);          } -    }; -  };  class boss_drakkari_elemental : public CreatureScript  { -public: -    boss_drakkari_elemental() : CreatureScript("boss_drakkari_elemental") { } - -    CreatureAI* GetAI(Creature* pCreature) const -    { -        return new boss_drakkari_elementalAI (pCreature); -    } +    public: +        boss_drakkari_elemental() : CreatureScript("boss_drakkari_elemental") { } -    struct boss_drakkari_elementalAI : public ScriptedAI -    { -        boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) +        struct boss_drakkari_elementalAI : public ScriptedAI          { -            pInstance = pCreature->GetInstanceScript(); -        } +            boss_drakkari_elementalAI(Creature* creature) : ScriptedAI(creature) +            { +                DoCast(me,SPELL_ELEMENTAL_SPAWN_EFEFCT); -        InstanceScript* pInstance; +                instance = creature->GetInstanceScript(); +            } -        uint32 uiSurgeTimer; +            void Reset() +            { +                events.Reset(); +                events.ScheduleEvent(EVENT_SURGE,urand(5000,15000)); -        bool bGoToColossus; +                me->AddAura(SPELL_MOJO_VOLLEY,me); +            } -        void Reset() -        { -            if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) -                CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true); -            uiSurgeTimer = 7*IN_MILLISECONDS; -            bGoToColossus = false; -        } +            void JustDied(Unit* killer) +            { +                if (killer == me) +                    return; -        void EnterEvadeMode() -        { -            me->RemoveFromWorld(); -        } +                if (instance) +                { +                    if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS))) +                        killer->Kill(colossus); +                } +            } -        void MovementInform(uint32 uiType, uint32 /*uiId*/) -        { -            if (uiType != POINT_MOTION_TYPE) -                return; -            if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) +            void UpdateAI(const uint32 diff)              { -                CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true); -                CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false; +                if (!UpdateVictim()) +                    return; +                 +                events.Update(diff); + +                if (me->HasUnitState(UNIT_STAT_CASTING)) +                    return; + +                while (uint32 eventId = events.ExecuteEvent()) +                { +                    switch (eventId) +                    { +                        case EVENT_SURGE: +                            DoCast(SPELL_SURGE_VISUAL); +                            if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) +                                DoCast(target,SPELL_SURGE); +                            events.ScheduleEvent(EVENT_SURGE,urand(5000,15000)); +                            break; +                    } +                } + +                DoMeleeAttackIfReady();              } -            me->RemoveFromWorld(); -        } -        void UpdateAI(const uint32 diff) -        { -            //Return since we have no target -            if (!UpdateVictim()) -                return; +           void DoAction(const int32 action) +            { +                switch (action) +                { +                    case ACTION_RETURN_TO_COLOSSUS: +                        DoCast(SPELL_SURGE_VISUAL); +                        if (instance) +                        { +                            if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS))) +                                DoCast(colossus,SPELL_MERGE); +                        } +                        break; +                } +           } -            if (!bGoToColossus && HealthBelowPct(50)) +            void DamageTaken(Unit* /*attacker*/, uint32& damage)              { -                if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) +                if (HealthBelowPct(50) && instance)                  { -                    if (!CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) +                    if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS)))                      { -                        me->InterruptNonMeleeSpells(true); -                        DoCast(pColossus, SPELL_MERGE); -                        bGoToColossus = true; +                        if (colossus->AI()->GetData(DATA_COLOSSUS_PHASE) ==  COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON) +                        { +                            DoAction(ACTION_RETURN_TO_COLOSSUS); +                            damage = 0; +                        }                      }                  }              } -            if (uiSurgeTimer <= diff) +            void EnterEvadeMode()              { -                DoCast(me->getVictim(), SPELL_SURGE); -                uiSurgeTimer = 7*IN_MILLISECONDS; -            } else uiSurgeTimer -= diff; +                me->DespawnOrUnsummon(); +            } -            DoMeleeAttackIfReady(); -        } +            void SpellHitTarget(Unit* target, SpellEntry const* spell) +            { +                if (spell->Id == SPELL_MERGE) +                { +                    if (Creature* colossus = target->ToCreature()) +                    { +                        colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); -        void JustDied(Unit* /*killer*/) +                        me->DespawnOrUnsummon(); +                    } +                } +            } + +        private: +            EventMap events; +            InstanceScript* instance; +        }; + +        CreatureAI* GetAI(Creature* creature) const          { -            if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) -                pColossus->Kill(pColossus); +            return new boss_drakkari_elementalAI(creature);          } -    }; -  }; +  class npc_living_mojo : public CreatureScript  {  public: @@ -244,51 +367,73 @@ public:      struct npc_living_mojoAI : public ScriptedAI      { -        npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) +        npc_living_mojoAI(Creature* creature) : ScriptedAI(creature)          { -            pInstance = pCreature->GetInstanceScript(); +            instance = creature->GetInstanceScript();          } -        InstanceScript* pInstance; - -        uint32 uiMojoWaveTimer; -        uint32 uiMojoPuddleTimer; -          void Reset()          { -            uiMojoWaveTimer = 2*IN_MILLISECONDS; -            uiMojoPuddleTimer = 7*IN_MILLISECONDS; +            mojoWaveTimer = 2*IN_MILLISECONDS; +            mojoPuddleTimer = 7*IN_MILLISECONDS; +        } + +        void MoveMojos(Creature* boss) +        { +            std::list<Creature*> mojosList; +            boss->GetCreatureListWithEntryInGrid(mojosList,me->GetEntry(),12.0f); +            if (!mojosList.empty()) +            { +                for (std::list<Creature*>::const_iterator itr = mojosList.begin(); itr != mojosList.end(); ++itr) +                { +                    if (Creature* mojo = *itr) +                        mojo->GetMotionMaster()->MovePoint(1,boss->GetHomePosition().GetPositionX(),boss->GetHomePosition().GetPositionY(),boss->GetHomePosition().GetPositionZ()); +                } +            }          } -        void EnterCombat(Unit* /*who*/) +        void MovementInform(uint32 type, uint32 id)          { +            if (type != POINT_MOTION_TYPE) +                return; -            //Check if the npc is near of Drakkari Colossus. -            if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) +            if (id == 1)              { -                if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) -                    me->SetReactState(REACT_PASSIVE); -                else -                    me->SetReactState(REACT_AGGRESSIVE); +                if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) +                { +                    colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); +                    if (!colossus->AI()->GetData(DATA_INTRO_DONE)) +                        colossus->AI()->SetData(DATA_INTRO_DONE,true); +                    colossus->SetInCombatWithZone(); +                    me->DespawnOrUnsummon(); +                }              }          } -        void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) + +        void AttackStart(Unit* attacker)          { -            if (me->HasReactState(REACT_PASSIVE)) +            if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) +                return; + +            // we do this checks to see if the creature is one of the creatures that sorround the boss +            if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))              { -                if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) +                Position homePosition; +                me->GetHomePosition().GetPosition(&homePosition); + +                Position colossusHomePosition; +                colossus->GetHomePosition().GetPosition(&colossusHomePosition); + +                float distance = homePosition.GetExactDist(colossusHomePosition.GetPositionX(),colossusHomePosition.GetPositionY(),colossusHomePosition.GetPositionZ()); +                 +                if (distance < 12.0f)                  { -                    if (pColossus->isAlive() && !pColossus->isInCombat()) -                    { -                        pColossus->RemoveAura(SPELL_FREEZE_ANIM); -                        pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); -                        pColossus->SetReactState(REACT_AGGRESSIVE); -                        if (pDone_by && pDone_by->isAlive()) -                            pColossus->AI()->AttackStart(pDone_by); -                        EnterEvadeMode(); -                    } +                    MoveMojos(colossus); +                    me->SetReactState(REACT_PASSIVE);                  } +                else +                    ScriptedAI::AttackStart(attacker);              }          } @@ -298,22 +443,25 @@ public:              if (!UpdateVictim())                  return; -            if (uiMojoWaveTimer <= diff) +            if (mojoWaveTimer <= diff)              {                  DoCast(me->getVictim(), SPELL_MOJO_WAVE); -                uiMojoWaveTimer = 15*IN_MILLISECONDS; -            } else uiMojoWaveTimer -= diff; +                mojoWaveTimer = 15*IN_MILLISECONDS; +            } else mojoWaveTimer -= diff; -            if (uiMojoPuddleTimer <= diff) +            if (mojoPuddleTimer <= diff)              {                  DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); -                uiMojoPuddleTimer = 18*IN_MILLISECONDS; -            } else uiMojoPuddleTimer -= diff; +                mojoPuddleTimer = 18*IN_MILLISECONDS; +            } else mojoPuddleTimer -= diff;              DoMeleeAttackIfReady();          } +    private: +        InstanceScript* instance; +        uint32 mojoWaveTimer; +        uint32 mojoPuddleTimer;      }; -  };  | 
