diff options
Diffstat (limited to 'src')
-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; }; - }; |