diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp | 590 |
1 files changed, 277 insertions, 313 deletions
diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index 9868bdea0d4..336e7f30dd3 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -82,407 +82,371 @@ enum ElementalEvents EVENT_SURGE = 1 }; -class boss_drakkari_colossus : public CreatureScript +struct boss_drakkari_colossus : public BossAI { - public: - boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { } + boss_drakkari_colossus(Creature* creature) : BossAI(creature, DATA_DRAKKARI_COLOSSUS) + { + Initialize(); + me->SetReactState(REACT_PASSIVE); + introDone = false; + } - struct boss_drakkari_colossusAI : public BossAI - { - boss_drakkari_colossusAI(Creature* creature) : BossAI(creature, DATA_DRAKKARI_COLOSSUS) - { - Initialize(); - me->SetReactState(REACT_PASSIVE); - introDone = false; - } + void Initialize() + { + phase = COLOSSUS_PHASE_NORMAL; + } - void Initialize() - { - phase = COLOSSUS_PHASE_NORMAL; - } + void Reset() override + { + _Reset(); - void Reset() override - { - _Reset(); + if (GetData(DATA_INTRO_DONE)) + { + me->SetReactState(REACT_AGGRESSIVE); + me->SetImmuneToPC(false); + me->RemoveAura(SPELL_FREEZE_ANIM); + } - if (GetData(DATA_INTRO_DONE)) - { - me->SetReactState(REACT_AGGRESSIVE); - me->SetImmuneToPC(false); - me->RemoveAura(SPELL_FREEZE_ANIM); - } + events.ScheduleEvent(EVENT_MIGHTY_BLOW, 10s, 30s); - events.ScheduleEvent(EVENT_MIGHTY_BLOW, 10s, 30s); + Initialize(); + } - Initialize(); - } + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + me->RemoveAura(SPELL_FREEZE_ANIM); + } - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - me->RemoveAura(SPELL_FREEZE_ANIM); - } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - } + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_SUMMON_ELEMENTAL: + DoCast(SPELL_EMERGE); + break; + case ACTION_FREEZE_COLOSSUS: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_SUMMON_ELEMENTAL: - DoCast(SPELL_EMERGE); - break; - case ACTION_FREEZE_COLOSSUS: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - - me->SetReactState(REACT_PASSIVE); - me->SetImmuneToPC(true); - DoCast(me, SPELL_FREEZE_ANIM); - break; - case ACTION_UNFREEZE_COLOSSUS: - - if (me->GetReactState() == REACT_AGGRESSIVE) - return; + me->SetReactState(REACT_PASSIVE); + me->SetImmuneToPC(true); + DoCast(me, SPELL_FREEZE_ANIM); + break; + case ACTION_UNFREEZE_COLOSSUS: - me->SetImmuneToPC(false); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveAura(SPELL_FREEZE_ANIM); + if (me->GetReactState() == REACT_AGGRESSIVE) + return; - DoZoneInCombat(); + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveAura(SPELL_FREEZE_ANIM); - break; - } - } + DoZoneInCombat(); - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (me->IsImmuneToPC()) - damage = 0; + break; + } + } - 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 DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (me->IsImmuneToPC()) + damage = 0; - uint32 GetData(uint32 data) const override + if (phase == COLOSSUS_PHASE_NORMAL || + phase == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON) + { + if (HealthBelowPct(phase == COLOSSUS_PHASE_NORMAL ? 50 : 5)) { - if (data == DATA_COLOSSUS_PHASE) - return phase; - else if (data == DATA_INTRO_DONE) - return introDone; - - return 0; + 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 SetData(uint32 type, uint32 data) override - { - if (type == DATA_INTRO_DONE) - introDone = data != 0; - } + uint32 GetData(uint32 data) const override + { + if (data == DATA_COLOSSUS_PHASE) + return phase; + else if (data == DATA_INTRO_DONE) + return introDone; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + return 0; + } - events.Update(diff); + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_INTRO_DONE) + introDone = data != 0; + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_MIGHTY_BLOW: - DoCastVictim(SPELL_MIGHTY_BLOW); - events.ScheduleEvent(EVENT_MIGHTY_BLOW, 5s, 15s); - break; - } + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (me->GetReactState() == REACT_AGGRESSIVE) - DoMeleeAttackIfReady(); + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MIGHTY_BLOW: + DoCastVictim(SPELL_MIGHTY_BLOW); + events.ScheduleEvent(EVENT_MIGHTY_BLOW, 5s, 15s); + break; } - void JustSummoned(Creature* summon) override - { - DoZoneInCombat(summon); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } - if (phase == COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON) - summon->SetHealth(summon->GetMaxHealth() / 2); - } + if (me->GetReactState() == REACT_AGGRESSIVE) + DoMeleeAttackIfReady(); + } - private: - uint8 phase; - bool introDone; - }; + void JustSummoned(Creature* summon) override + { + DoZoneInCombat(summon); - CreatureAI* GetAI(Creature* creature) const override - { - return GetGundrakAI<boss_drakkari_colossusAI>(creature); - } + if (phase == COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON) + summon->SetHealth(summon->GetMaxHealth() / 2); + } + +private: + uint8 phase; + bool introDone; }; -class boss_drakkari_elemental : public CreatureScript +struct boss_drakkari_elemental : public ScriptedAI { - public: - boss_drakkari_elemental() : CreatureScript("boss_drakkari_elemental") { } + boss_drakkari_elemental(Creature* creature) : ScriptedAI(creature) + { + DoCast(me, SPELL_ELEMENTAL_SPAWN_EFFECT); + instance = creature->GetInstanceScript(); + } - struct boss_drakkari_elementalAI : public ScriptedAI - { - boss_drakkari_elementalAI(Creature* creature) : ScriptedAI(creature) - { - DoCast(me, SPELL_ELEMENTAL_SPAWN_EFFECT); - instance = creature->GetInstanceScript(); - } + void Reset() override + { + events.Reset(); + events.ScheduleEvent(EVENT_SURGE, 5s, 15s); - void Reset() override - { - events.Reset(); - events.ScheduleEvent(EVENT_SURGE, 5s, 15s); + me->AddAura(SPELL_MOJO_VOLLEY, me); + } - me->AddAura(SPELL_MOJO_VOLLEY, me); - } + void JustDied(Unit* killer) override + { + Talk(EMOTE_ACTIVATE_ALTAR); - void JustDied(Unit* killer) override - { - Talk(EMOTE_ACTIVATE_ALTAR); + if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) + Unit::Kill(killer, colossus); + } - if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) - Unit::Kill(killer, colossus); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + events.Update(diff); - events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SURGE: + DoCast(SPELL_SURGE_VISUAL); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true)) + DoCast(target, SPELL_SURGE); + events.ScheduleEvent(EVENT_SURGE, 5s, 15s); + break; + } - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SURGE: - DoCast(SPELL_SURGE_VISUAL); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true)) - DoCast(target, SPELL_SURGE); - events.ScheduleEvent(EVENT_SURGE, 5s, 15s); - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } - DoMeleeAttackIfReady(); - } + DoMeleeAttackIfReady(); + } - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_RETURN_TO_COLOSSUS: - Talk(EMOTE_MOJO); - DoCast(SPELL_SURGE_VISUAL); - if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) - // what if the elemental is more than 80 yards from drakkari colossus ? - DoCast(colossus, SPELL_MERGE, true); - break; - } - } + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_RETURN_TO_COLOSSUS: + Talk(EMOTE_MOJO); + DoCast(SPELL_SURGE_VISUAL); + if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) + // what if the elemental is more than 80 yards from drakkari colossus ? + DoCast(colossus, SPELL_MERGE, true); + break; + } + } - void DamageTaken(Unit* /*attacker*/, uint32& damage) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (HealthBelowPct(50)) + { + if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) { - if (HealthBelowPct(50)) + if (colossus->AI()->GetData(DATA_COLOSSUS_PHASE) == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON) { - if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) - { - if (colossus->AI()->GetData(DATA_COLOSSUS_PHASE) == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON) - { - damage = 0; - - // to prevent spell spaming - if (me->HasUnitState(UNIT_STATE_CHARGING)) - return; - - // not sure about this, the idea of this code is to prevent bug the elemental - // if it is not in a acceptable distance to cast the charge spell. - /*if (me->GetDistance(colossus) > 80.0f) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) - return; - - me->GetMotionMaster()->MovePoint(0, colossus->GetPositionX(), colossus->GetPositionY(), colossus->GetPositionZ()); - return; - }*/ - DoAction(ACTION_RETURN_TO_COLOSSUS); - } - } - } - } + damage = 0; - void EnterEvadeMode(EvadeReason /*why*/) override - { - me->DespawnOrUnsummon(); - } + // to prevent spell spaming + if (me->HasUnitState(UNIT_STATE_CHARGING)) + return; - void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_MERGE) - { - if (Creature* colossus = target->ToCreature()) + // not sure about this, the idea of this code is to prevent bug the elemental + // if it is not in a acceptable distance to cast the charge spell. + /*if (me->GetDistance(colossus) > 80.0f) { - colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); - me->DespawnOrUnsummon(); - } + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) + return; + + me->GetMotionMaster()->MovePoint(0, colossus->GetPositionX(), colossus->GetPositionY(), colossus->GetPositionZ()); + return; + }*/ + DoAction(ACTION_RETURN_TO_COLOSSUS); } } + } + } - private: - EventMap events; - InstanceScript* instance; - }; + void EnterEvadeMode(EvadeReason /*why*/) override + { + me->DespawnOrUnsummon(); + } - CreatureAI* GetAI(Creature* creature) const override + void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_MERGE) { - return GetGundrakAI<boss_drakkari_elementalAI>(creature); + if (Creature* colossus = target->ToCreature()) + { + colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); + me->DespawnOrUnsummon(); + } } + } + +private: + EventMap events; + InstanceScript* instance; }; -class npc_living_mojo : public CreatureScript +struct npc_living_mojo : public ScriptedAI { -public: - npc_living_mojo() : CreatureScript("npc_living_mojo") { } - - CreatureAI* GetAI(Creature* creature) const override + npc_living_mojo(Creature* creature) : ScriptedAI(creature) { - return GetGundrakAI<npc_living_mojoAI>(creature); + instance = creature->GetInstanceScript(); } - struct npc_living_mojoAI : public ScriptedAI + void Reset() override { - npc_living_mojoAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + _scheduler.CancelAll(); + } - void Initialize() + void JustEngagedWith(Unit* /*who*/) override + { + _scheduler.Schedule(2s, [this](TaskContext task) { - mojoWaveTimer = 2 * IN_MILLISECONDS; - mojoPuddleTimer = 7 * IN_MILLISECONDS; - } - - void Reset() override + DoCastVictim(SPELL_MOJO_WAVE); + task.Repeat(15s); + }) + .Schedule(7s, [this](TaskContext task) { - Initialize(); - } + DoCastVictim(SPELL_MOJO_PUDDLE); + task.Repeat(18s); + }); + } - void MoveMojos(Creature* boss) + void MoveMojos(Creature* boss) + { + std::list<Creature*> mojosList; + boss->GetCreatureListWithEntryInGrid(mojosList, me->GetEntry(), 12.0f); + if (!mojosList.empty()) { - 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) { - 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()); - } + if (Creature* mojo = *itr) + mojo->GetMotionMaster()->MovePoint(1, boss->GetHomePosition().GetPositionX(), boss->GetHomePosition().GetPositionY(), boss->GetHomePosition().GetPositionZ()); } } + } - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - { - if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) - { - colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); - if (!colossus->AI()->GetData(DATA_INTRO_DONE)) - colossus->AI()->SetData(DATA_INTRO_DONE, true); - DoZoneInCombat(colossus); - me->DespawnOrUnsummon(); - } - } - } + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + return; - void AttackStart(Unit* attacker) override + if (id == 1) { - 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 = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) { - Position homePosition = me->GetHomePosition(); - - float distance = homePosition.GetExactDist(&colossus->GetHomePosition()); - - if (distance < 12.0f) - { - MoveMojos(colossus); - me->SetReactState(REACT_PASSIVE); - } - else - ScriptedAI::AttackStart(attacker); + colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS); + if (!colossus->AI()->GetData(DATA_INTRO_DONE)) + colossus->AI()->SetData(DATA_INTRO_DONE, true); + DoZoneInCombat(colossus); + me->DespawnOrUnsummon(); } } + } + + void AttackStart(Unit* attacker) override + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) + return; - void UpdateAI(uint32 diff) override + // we do this checks to see if the creature is one of the creatures that sorround the boss + if (Creature* colossus = instance->GetCreature(DATA_DRAKKARI_COLOSSUS)) { - //Return since we have no target - if (!UpdateVictim()) - return; + Position homePosition = me->GetHomePosition(); - if (mojoWaveTimer <= diff) - { - DoCastVictim(SPELL_MOJO_WAVE); - mojoWaveTimer = 15*IN_MILLISECONDS; - } else mojoWaveTimer -= diff; + float distance = homePosition.GetExactDist(&colossus->GetHomePosition()); - if (mojoPuddleTimer <= diff) + if (distance < 12.0f) { - DoCastVictim(SPELL_MOJO_PUDDLE); - mojoPuddleTimer = 18*IN_MILLISECONDS; - } else mojoPuddleTimer -= diff; + MoveMojos(colossus); + me->SetReactState(REACT_PASSIVE); + } + else + ScriptedAI::AttackStart(attacker); + } + } + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, [this] + { DoMeleeAttackIfReady(); - } + }); + } - private: - InstanceScript* instance; - uint32 mojoWaveTimer; - uint32 mojoPuddleTimer; - }; +private: + InstanceScript* instance; + TaskScheduler _scheduler; }; void AddSC_boss_drakkari_colossus() { - new boss_drakkari_colossus(); - new boss_drakkari_elemental(); - new npc_living_mojo(); + RegisterCreatureAIWithFactory(boss_drakkari_colossus, GetGundrakAI); + RegisterCreatureAIWithFactory(boss_drakkari_elemental, GetGundrakAI); + RegisterCreatureAIWithFactory(npc_living_mojo, GetGundrakAI); } |