diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h index bcff3b3a0..4944e0b7e 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.h +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -105,4 +105,6 @@ inline AI* GetBlackTempleAI(T* obj) return GetInstanceAI(obj, BlackTempleScriptName); } +#define RegisterBlackTempleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackTempleAI) + #endif // BLACK_TEMPLE_H_ diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index f628c6489..2a081dcbc 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -90,541 +90,477 @@ enum Misc EVENT_AKAMA_SCENE7 = 36 }; -class boss_shade_of_akama : public CreatureScript +struct boss_shade_of_akama : public BossAI { -public: - boss_shade_of_akama() : CreatureScript("boss_shade_of_akama") { } - - struct boss_shade_of_akamaAI : public BossAI + boss_shade_of_akama(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA), summonsChanneler(me), summonsGenerator(me) { - boss_shade_of_akamaAI(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA), summonsChanneler(me), summonsGenerator(me) - { - events2.ScheduleEvent(EVENT_SHADE_GATHER_NPCS, 1000); - } + events2.ScheduleEvent(EVENT_SHADE_GATHER_NPCS, 1000); + } - SummonList summonsChanneler; - SummonList summonsGenerator; - EventMap events2; + SummonList summonsChanneler; + SummonList summonsGenerator; + EventMap events2; - void ChannelersAction(int32 action) - { - for (SummonList::const_iterator i = summonsChanneler.begin(); i != summonsChanneler.end(); ++i) - if (Creature* summon = ObjectAccessor::GetCreature(*me, *i)) + void ChannelersAction(int32 action) + { + for (SummonList::const_iterator i = summonsChanneler.begin(); i != summonsChanneler.end(); ++i) + if (Creature* summon = ObjectAccessor::GetCreature(*me, *i)) + { + if (action == ACTION_CHANNELERS_START_CHANNEL) { - if (action == ACTION_CHANNELERS_START_CHANNEL) - { - summon->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); - summon->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - } - else if (action == ACTION_START_ENCOUNTER) - { - summon->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - } - else if (action == ACTION_KILL_CHANNELERS) - { - Unit::Kill(me, summon); - } + summon->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); + summon->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); } - } + else if (action == ACTION_START_ENCOUNTER) + { + summon->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + } + else if (action == ACTION_KILL_CHANNELERS) + { + Unit::Kill(me, summon); + } + } + } - void Reset() override - { - BossAI::Reset(); - me->SetReactState(REACT_PASSIVE); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetImmuneToAll(true); - me->SetWalk(true); - } + void Reset() override + { + BossAI::Reset(); + me->SetReactState(REACT_PASSIVE); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToAll(true); + me->SetWalk(true); + } - void EnterEvadeMode(EvadeReason why) override - { - BossAI::EnterEvadeMode(why); - summonsGenerator.DoAction(ACTION_DESPAWN_ALL); - events2.ScheduleEvent(EVENT_SHADE_RESET_ENCOUNTER, 20000); - me->SetVisible(false); - ChannelersAction(ACTION_KILL_CHANNELERS); - } + void EnterEvadeMode(EvadeReason why) override + { + BossAI::EnterEvadeMode(why); + summonsGenerator.DoAction(ACTION_DESPAWN_ALL); + events2.ScheduleEvent(EVENT_SHADE_RESET_ENCOUNTER, 20000); + me->SetVisible(false); + ChannelersAction(ACTION_KILL_CHANNELERS); + } - void JustDied(Unit* killer) override + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + summonsGenerator.DoAction(ACTION_DESPAWN_ALL); + summonsChanneler.DespawnAll(); + me->CastSpell(me, SPELL_SHADE_OF_AKAMA_TRIGGER, true); + if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) { - BossAI::JustDied(killer); - summonsGenerator.DoAction(ACTION_DESPAWN_ALL); - summonsChanneler.DespawnAll(); - me->CastSpell(me, SPELL_SHADE_OF_AKAMA_TRIGGER, true); + akama->SetHomePosition(*akama); + akama->AI()->DoAction(ACTION_SHADE_DIED); + } + } + + void DoAction(int32 param) override + { + if (param == ACTION_START_ENCOUNTER) + { + summonsGenerator.DoAction(ACTION_START_ENCOUNTER); + ChannelersAction(ACTION_START_ENCOUNTER); + events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000); + } + else if (param == ACTION_AKAMA_DIED) + { + EnterEvadeMode(EVADE_REASON_OTHER); + } + } + + void UpdateAI(uint32 diff) override + { + events2.Update(diff); + switch (events2.ExecuteEvent()) + { + case EVENT_SHADE_GATHER_NPCS: + { + std::list ChannelerList; + me->GetCreaturesWithEntryInRange(ChannelerList, 100.0f, NPC_ASHTONGUE_CHANNELER); + for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) + summonsChanneler.Summon(*itr); + + std::list SpawnerList; + me->GetCreaturesWithEntryInRange(SpawnerList, 100.0f, NPC_CREATURE_GENERATOR_AKAMA); + for (std::list::const_iterator itr = SpawnerList.begin(); itr != SpawnerList.end(); ++itr) + summonsGenerator.Summon(*itr); + + summonsChanneler.Respawn(); + summonsGenerator.Respawn(); + ChannelersAction(ACTION_CHANNELERS_START_CHANNEL); + if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) - { - akama->SetHomePosition(*akama); - akama->AI()->DoAction(ACTION_SHADE_DIED); - } + akama->Respawn(true); + break; + } + case EVENT_SHADE_RESET_ENCOUNTER: + me->SetVisible(true); + summonsGenerator.Respawn(); + summonsChanneler.Respawn(); + ChannelersAction(ACTION_CHANNELERS_START_CHANNEL); + + if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) + akama->Respawn(true); + break; } - void JustEngagedWith(Unit* who) override + if (!UpdateVictim()) + return; + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - BossAI::JustEngagedWith(who); - } - - void DoAction(int32 param) override - { - if (param == ACTION_START_ENCOUNTER) + case EVENT_SHADE_CHECK_DISTANCE: + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) { - summonsGenerator.DoAction(ACTION_START_ENCOUNTER); - ChannelersAction(ACTION_START_ENCOUNTER); - events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000); + int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED); + if (slow > -100) + { + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_START, 510.0f, 400.7993f, 112.7837f); + } } - else if (param == ACTION_AKAMA_DIED) + else { - EnterEvadeMode(EVADE_REASON_OTHER); - } - } - - void UpdateAI(uint32 diff) override - { - events2.Update(diff); - switch (events2.ExecuteEvent()) - { - case EVENT_SHADE_GATHER_NPCS: - { - std::list ChannelerList; - me->GetCreaturesWithEntryInRange(ChannelerList, 100.0f, NPC_ASHTONGUE_CHANNELER); - for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) - summonsChanneler.Summon(*itr); - - std::list SpawnerList; - me->GetCreaturesWithEntryInRange(SpawnerList, 100.0f, NPC_CREATURE_GENERATOR_AKAMA); - for (std::list::const_iterator itr = SpawnerList.begin(); itr != SpawnerList.end(); ++itr) - summonsGenerator.Summon(*itr); - - summonsChanneler.Respawn(); - summonsGenerator.Respawn(); - ChannelersAction(ACTION_CHANNELERS_START_CHANNEL); - - if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) - akama->Respawn(true); - break; - } - case EVENT_SHADE_RESET_ENCOUNTER: - me->SetVisible(true); - summonsGenerator.Respawn(); - summonsChanneler.Respawn(); - ChannelersAction(ACTION_CHANNELERS_START_CHANNEL); - - if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) - akama->Respawn(true); - break; + int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED); + if (slow < -100) + me->GetMotionMaster()->Clear(); + else if (slow == 0) + { + summonsGenerator.DoAction(ACTION_NO_SORCERERS); + me->SetWalk(false); + } } - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + if (me->IsWithinMeleeRange(me->GetVictim())) { - case EVENT_SHADE_CHECK_DISTANCE: - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) - { - int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED); - if (slow > -100) - { - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_START, 510.0f, 400.7993f, 112.7837f); - } - } - else - { - int32 slow = me->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED); - if (slow < -100) - me->GetMotionMaster()->Clear(); - else if (slow == 0) - { - summonsGenerator.DoAction(ACTION_NO_SORCERERS); - me->SetWalk(false); - } - } - - if (me->IsWithinMeleeRange(me->GetVictim())) - { - me->SetReactState(REACT_AGGRESSIVE); - DoResetThreatList(); - me->GetVictim()->InterruptNonMeleeSpells(false); - me->AddThreat(me->GetVictim(), 1000000.0f); - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->SetImmuneToAll(false); - summonsGenerator.DoAction(ACTION_STOP_SPAWNING); - break; - } - events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000); - break; + me->SetReactState(REACT_AGGRESSIVE); + DoResetThreatList(); + me->GetVictim()->InterruptNonMeleeSpells(false); + me->AddThreat(me->GetVictim(), 1000000.0f); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToAll(false); + summonsGenerator.DoAction(ACTION_STOP_SPAWNING); + break; } - - DoMeleeAttackIfReady(); + events.ScheduleEvent(EVENT_SHADE_CHECK_DISTANCE, 1000); + break; } - bool CheckEvadeIfOutOfCombatArea() const override - { - return !SelectTargetFromPlayerList(120.0f); - } - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override + bool CheckEvadeIfOutOfCombatArea() const override { - return GetBlackTempleAI(creature); + return !SelectTargetFromPlayerList(120.0f); } }; -class npc_akama_shade : public CreatureScript +struct npc_akama_shade : public ScriptedAI { -public: - npc_akama_shade() : CreatureScript("npc_akama_shade") { } - - struct npc_akamaAI : public ScriptedAI + npc_akama_shade(Creature* creature) : ScriptedAI(creature), summons(me) { - npc_akamaAI(Creature* creature) : ScriptedAI(creature), summons(me) + instance = creature->GetInstanceScript(); + } + + InstanceScript* instance; + EventMap events; + EventMap events2; + SummonList summons; + + void Reset() override + { + if (instance->GetBossState(DATA_SHADE_OF_AKAMA) == DONE) { - instance = creature->GetInstanceScript(); + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); + return; } - InstanceScript* instance; - EventMap events; - EventMap events2; - SummonList summons; + me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); + me->CastSpell(me, SPELL_STEALTH, true); + events.Reset(); + events2.Reset(); + } - void Reset() override - { - if (instance->GetBossState(DATA_SHADE_OF_AKAMA) == DONE) - { - me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); - return; - } - - me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); - me->CastSpell(me, SPELL_STEALTH, true); - events.Reset(); - events2.Reset(); - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != POINT_MOTION_TYPE || point != POINT_CHANNEL_SOUL) - return; - - me->SetFacingTo(0.0f); - events2.ScheduleEvent(EVENT_AKAMA_SCENE1, 1000); - events2.ScheduleEvent(EVENT_AKAMA_SCENE2, 16500); - events2.ScheduleEvent(EVENT_AKAMA_SCENE3, 17500); - events2.ScheduleEvent(EVENT_AKAMA_SCENE4, 27000); - events2.ScheduleEvent(EVENT_AKAMA_SCENE5, 37000); - events2.ScheduleEvent(EVENT_AKAMA_SCENE6, 51000); - events2.ScheduleEvent(EVENT_AKAMA_SCENE7, 56000); - } - - void DoAction(int32 param) override - { - if (param == ACTION_SHADE_DIED) - events2.ScheduleEvent(EVENT_AKAMA_SCENE0, 1000); - } - - void JustDied(Unit* /*killer*/) override + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE || point != POINT_CHANNEL_SOUL) + return; + + me->SetFacingTo(0.0f); + events2.ScheduleEvent(EVENT_AKAMA_SCENE1, 1000); + events2.ScheduleEvent(EVENT_AKAMA_SCENE2, 16500); + events2.ScheduleEvent(EVENT_AKAMA_SCENE3, 17500); + events2.ScheduleEvent(EVENT_AKAMA_SCENE4, 27000); + events2.ScheduleEvent(EVENT_AKAMA_SCENE5, 37000); + events2.ScheduleEvent(EVENT_AKAMA_SCENE6, 51000); + events2.ScheduleEvent(EVENT_AKAMA_SCENE7, 56000); + } + + void DoAction(int32 param) override + { + if (param == ACTION_SHADE_DIED) + events2.ScheduleEvent(EVENT_AKAMA_SCENE0, 1000); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADE_OF_AKAMA))) + shade->AI()->DoAction(ACTION_AKAMA_DIED); + } + + void JustEngagedWith(Unit* /*who*/) override + { + events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 2000); + events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, 5000); + } + + void JustSummoned(Creature* summon) override + { + float dist = frand(30.0f, 32.0f); + summon->SetWalk(true); + summon->GetMotionMaster()->MovePoint(POINT_START, summon->GetPositionX() + dist * cos(summon->GetOrientation()), summon->GetPositionY() + dist * std::sin(summon->GetOrientation()), summon->GetPositionZ(), false); + summons.Summon(summon); + } + + void UpdateAI(uint32 diff) override + { + events2.Update(diff); + switch (events2.ExecuteEvent()) { + case EVENT_AKAMA_START_ENCOUNTER: + me->RemoveAura(SPELL_STEALTH); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_START, 517.4877f, 400.7993f, 112.7837f, false); + events2.ScheduleEvent(EVENT_AKAMA_START_CHANNEL, 11000); + break; + case EVENT_AKAMA_START_CHANNEL: + me->CastSpell(me, SPELL_AKAMA_SOUL_CHANNEL, false); if (Creature* shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADE_OF_AKAMA))) - shade->AI()->DoAction(ACTION_AKAMA_DIED); - } - - void JustEngagedWith(Unit* /*who*/) override - { - events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, 2000); - events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, 5000); - } - - void JustSummoned(Creature* summon) override - { - float dist = frand(30.0f, 32.0f); - summon->SetWalk(true); - summon->GetMotionMaster()->MovePoint(POINT_START, summon->GetPositionX() + dist * cos(summon->GetOrientation()), summon->GetPositionY() + dist * std::sin(summon->GetOrientation()), summon->GetPositionZ(), false); - summons.Summon(summon); - } - - void UpdateAI(uint32 diff) override - { - events2.Update(diff); - switch (events2.ExecuteEvent()) { - case EVENT_AKAMA_START_ENCOUNTER: - me->RemoveAura(SPELL_STEALTH); - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_START, 517.4877f, 400.7993f, 112.7837f, false); - events2.ScheduleEvent(EVENT_AKAMA_START_CHANNEL, 11000); - break; - case EVENT_AKAMA_START_CHANNEL: - me->CastSpell(me, SPELL_AKAMA_SOUL_CHANNEL, false); - if (Creature* shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_SHADE_OF_AKAMA))) - { - shade->AI()->AttackStart(me); - shade->GetMotionMaster()->Clear(); - shade->AI()->DoAction(ACTION_START_ENCOUNTER); - } - break; - case EVENT_AKAMA_SCENE0: - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_CHANNEL_SOUL, 467.0f, 400.7993f, 118.537f); - break; - case EVENT_AKAMA_SCENE1: - me->CastSpell(me, SPELL_AKAMA_SOUL_RETRIEVE, true); - break; - case EVENT_AKAMA_SCENE2: - Talk(SAY_BROKEN_FREE_0); - break; - case EVENT_AKAMA_SCENE3: - me->SummonCreatureGroup(SUMMON_GROUP_BROKENS); - break; - case EVENT_AKAMA_SCENE4: - Talk(SAY_BROKEN_FREE_1); - break; - case EVENT_AKAMA_SCENE5: - for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) - if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr)) - broken->SetStandState(UNIT_STAND_STATE_KNEEL); - Talk(SAY_BROKEN_FREE_2); - break; - case EVENT_AKAMA_SCENE6: - if (Creature* broken = summons.GetCreatureWithEntry(NPC_ASHTONGUE_BROKEN)) - broken->AI()->Talk(SAY_BROKEN_S1); - break; - case EVENT_AKAMA_SCENE7: - for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) - if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr)) - broken->AI()->Talk(SAY_BROKEN_S2); - break; + shade->AI()->AttackStart(me); + shade->GetMotionMaster()->Clear(); + shade->AI()->DoAction(ACTION_START_ENCOUNTER); } - - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_CHAIN_LIGHTNING: - me->CastSpell(me->GetVictim(), SPELL_CHAIN_LIGHTNING, false); - events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, urand(10000, 15000)); - break; - case EVENT_SPELL_DESTRUCTIVE_POISON: - me->CastSpell(me, SPELL_DESTRUCTIVE_POISON, false); - events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, urand(4000, 5000)); - break; - } - - DoMeleeAttackIfReady(); + break; + case EVENT_AKAMA_SCENE0: + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_CHANNEL_SOUL, 467.0f, 400.7993f, 118.537f); + break; + case EVENT_AKAMA_SCENE1: + me->CastSpell(me, SPELL_AKAMA_SOUL_RETRIEVE, true); + break; + case EVENT_AKAMA_SCENE2: + Talk(SAY_BROKEN_FREE_0); + break; + case EVENT_AKAMA_SCENE3: + me->SummonCreatureGroup(SUMMON_GROUP_BROKENS); + break; + case EVENT_AKAMA_SCENE4: + Talk(SAY_BROKEN_FREE_1); + break; + case EVENT_AKAMA_SCENE5: + for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) + if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr)) + broken->SetStandState(UNIT_STAND_STATE_KNEEL); + Talk(SAY_BROKEN_FREE_2); + break; + case EVENT_AKAMA_SCENE6: + if (Creature* broken = summons.GetCreatureWithEntry(NPC_ASHTONGUE_BROKEN)) + broken->AI()->Talk(SAY_BROKEN_S1); + break; + case EVENT_AKAMA_SCENE7: + for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) + if (Creature* broken = ObjectAccessor::GetCreature(*me, *itr)) + broken->AI()->Talk(SAY_BROKEN_S2); + break; } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override + if (!UpdateVictim()) + return; + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - if (action == 0) - { - CloseGossipMenuFor(player); - me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); - events2.ScheduleEvent(EVENT_AKAMA_START_ENCOUNTER, 0); - } + case EVENT_SPELL_CHAIN_LIGHTNING: + me->CastSpell(me->GetVictim(), SPELL_CHAIN_LIGHTNING, false); + events.ScheduleEvent(EVENT_SPELL_CHAIN_LIGHTNING, urand(10000, 15000)); + break; + case EVENT_SPELL_DESTRUCTIVE_POISON: + me->CastSpell(me, SPELL_DESTRUCTIVE_POISON, false); + events.ScheduleEvent(EVENT_SPELL_DESTRUCTIVE_POISON, urand(4000, 5000)); + break; } - }; - CreatureAI* GetAI(Creature* creature) const override + DoMeleeAttackIfReady(); + } + + void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override { - return GetBlackTempleAI(creature); + if (action == 0) + { + CloseGossipMenuFor(player); + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); + events2.ScheduleEvent(EVENT_AKAMA_START_ENCOUNTER, 0); + } } }; -// ######################################################## -// Creature Generator Akama -// ######################################################## - -class npc_creature_generator_akama : public CreatureScript +struct npc_creature_generator_akama : public NullCreatureAI { -public: - npc_creature_generator_akama() : CreatureScript("npc_creature_generator_akama") { } - - struct npc_creature_generator_akamaAI : public NullCreatureAI + npc_creature_generator_akama(Creature* creature) : NullCreatureAI(creature), summons(me) { - npc_creature_generator_akamaAI(Creature* creature) : NullCreatureAI(creature), summons(me) + instance = creature->GetInstanceScript(); + } + + void Reset() override + { + events.Reset(); + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (summon->GetEntry() == NPC_ASHTONGUE_SORCERER) { - instance = creature->GetInstanceScript(); + std::list channelerList; + me->GetCreaturesWithEntryInRange(channelerList, 120.0f, NPC_ASHTONGUE_CHANNELER); + for (std::list::const_iterator itr = channelerList.begin(); itr != channelerList.end(); ++itr) + { + if ((*itr)->IsAlive() || (*itr)->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + continue; + + summon->SetInCombatWithZone(); + summon->SetReactState(REACT_PASSIVE); + summon->GetMotionMaster()->MovePoint(POINT_START, **itr); + (*itr)->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + return; + } } - void Reset() override + summon->SetInCombatWithZone(); + if (Unit* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) + { + summon->AddThreat(akama, 500.0f); + summon->AI()->AttackStart(akama); + } + } + + void SummonedCreatureDies(Creature* summon, Unit*) override + { + summon->DespawnOrUnsummon(10000); + summons.Despawn(summon); + } + + void DoAction(int32 param) override + { + if (param == ACTION_STOP_SPAWNING || param == ACTION_DESPAWN_ALL) { events.Reset(); - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (summon->GetEntry() == NPC_ASHTONGUE_SORCERER) + for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) { - std::list channelerList; - me->GetCreaturesWithEntryInRange(channelerList, 120.0f, NPC_ASHTONGUE_CHANNELER); - for (std::list::const_iterator itr = channelerList.begin(); itr != channelerList.end(); ++itr) + if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) { - if ((*itr)->IsAlive() || (*itr)->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + if (summon->GetEntry() != NPC_ASHTONGUE_SORCERER) continue; - + summon->InterruptNonMeleeSpells(false); + summon->GetMotionMaster()->Clear(); summon->SetInCombatWithZone(); - summon->SetReactState(REACT_PASSIVE); - summon->GetMotionMaster()->MovePoint(POINT_START, **itr); - (*itr)->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - return; } } - - summon->SetInCombatWithZone(); - if (Unit* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_AKAMA_SHADE))) - { - summon->AddThreat(akama, 500.0f); - summon->AI()->AttackStart(akama); - } } - - void SummonedCreatureDies(Creature* summon, Unit*) override + if (param == ACTION_DESPAWN_ALL) + summons.DespawnAll(); + else if (param == ACTION_NO_SORCERERS) + events.CancelEvent(EVENT_SUMMON_ASHTONGUE_SORCERER); + else if (param == ACTION_START_ENCOUNTER) { - summon->DespawnOrUnsummon(10000); - summons.Despawn(summon); + events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 5000); + events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 20000); + events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 35000); } + } - void DoAction(int32 param) override - { - if (param == ACTION_STOP_SPAWNING || param == ACTION_DESPAWN_ALL) - { - events.Reset(); - for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) - { - if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) - { - if (summon->GetEntry() != NPC_ASHTONGUE_SORCERER) - continue; - summon->InterruptNonMeleeSpells(false); - summon->GetMotionMaster()->Clear(); - summon->SetInCombatWithZone(); - } - } - } - if (param == ACTION_DESPAWN_ALL) - summons.DespawnAll(); - else if (param == ACTION_NO_SORCERERS) - events.CancelEvent(EVENT_SUMMON_ASHTONGUE_SORCERER); - else if (param == ACTION_START_ENCOUNTER) - { - events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 5000); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 20000); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 35000); - } - } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - switch (events.ExecuteEvent()) - { - case EVENT_SUMMON_WAVE_B: - me->CastSpell(me, SPELL_ASHTONGUE_WAVE_B, true); - events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 45000); - break; - case EVENT_SUMMON_ASHTONGUE_SORCERER: // left - me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_SORCERER, true); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 45000); - break; - case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right - me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_DEFENDER, true); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 45000); - break; - default: - break; - } - } - - private: - EventMap events; - SummonList summons; - InstanceScript* instance; - }; - - CreatureAI* GetAI(Creature* creature) const override + void UpdateAI(uint32 diff) override { - return GetBlackTempleAI(creature); + events.Update(diff); + + switch (events.ExecuteEvent()) + { + case EVENT_SUMMON_WAVE_B: + me->CastSpell(me, SPELL_ASHTONGUE_WAVE_B, true); + events.ScheduleEvent(EVENT_SUMMON_WAVE_B, 45000); + break; + case EVENT_SUMMON_ASHTONGUE_SORCERER: // left + me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_SORCERER, true); + events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, 45000); + break; + case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right + me->CastSpell(me, SPELL_SUMMON_ASHTONGUE_DEFENDER, true); + events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, 45000); + break; + default: + break; + } + } + +private: + EventMap events; + SummonList summons; + InstanceScript* instance; +}; + +class spell_shade_of_akama_shade_soul_channel : public AuraScript +{ + PrepareAuraScript(spell_shade_of_akama_shade_soul_channel); + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + caster->SetFacingToObject(GetTarget()); + } + + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Aura* aura = GetTarget()->GetAura(GetSpellInfo()->Effects[EFFECT_1].TriggerSpell)) + aura->ModStackAmount(-1); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_shade_of_akama_shade_soul_channel::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_shade_of_akama_shade_soul_channel::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; -class spell_shade_of_akama_shade_soul_channel : public SpellScriptLoader +class spell_shade_of_akama_akama_soul_expel : public SpellScript { -public: - spell_shade_of_akama_shade_soul_channel() : SpellScriptLoader("spell_shade_of_akama_shade_soul_channel") { } + PrepareSpellScript(spell_shade_of_akama_akama_soul_expel); - class spell_shade_of_akama_shade_soul_channel_AuraScript : public AuraScript + void SetDest(SpellDestination& dest) { - PrepareAuraScript(spell_shade_of_akama_shade_soul_channel_AuraScript) - - void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - caster->SetFacingToObject(GetTarget()); - } - - void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Aura* aura = GetTarget()->GetAura(GetSpellInfo()->Effects[EFFECT_1].TriggerSpell)) - aura->ModStackAmount(-1); - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_shade_of_akama_shade_soul_channel_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_shade_of_akama_shade_soul_channel_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_shade_of_akama_shade_soul_channel_AuraScript(); + // Adjust effect summon position + Position const offset = { 0.0f, 0.0f, 25.0f, 0.0f }; + dest.RelocateOffset(offset); } -}; -class spell_shade_of_akama_akama_soul_expel : public SpellScriptLoader -{ -public: - spell_shade_of_akama_akama_soul_expel() : SpellScriptLoader("spell_shade_of_akama_akama_soul_expel") { } - - class spell_shade_of_akama_akama_soul_expel_SpellScript : public SpellScript + void Register() override { - PrepareSpellScript(spell_shade_of_akama_akama_soul_expel_SpellScript); - - void SetDest(SpellDestination& dest) - { - // Adjust effect summon position - Position const offset = { 0.0f, 0.0f, 25.0f, 0.0f }; - dest.RelocateOffset(offset); - } - - void Register() override - { - OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_shade_of_akama_akama_soul_expel_SpellScript::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_shade_of_akama_akama_soul_expel_SpellScript(); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_shade_of_akama_akama_soul_expel::SetDest, EFFECT_0, TARGET_DEST_CASTER_RADIUS); } }; void AddSC_boss_shade_of_akama() { - new boss_shade_of_akama(); - new npc_akama_shade(); - new npc_creature_generator_akama(); - new spell_shade_of_akama_shade_soul_channel(); - new spell_shade_of_akama_akama_soul_expel(); + RegisterBlackTempleCreatureAI(boss_shade_of_akama); + RegisterBlackTempleCreatureAI(npc_akama_shade); + RegisterBlackTempleCreatureAI(npc_creature_generator_akama); + RegisterSpellScript(spell_shade_of_akama_shade_soul_channel); + RegisterSpellScript(spell_shade_of_akama_akama_soul_expel); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp index 89bded4e4..bafbbcadc 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -46,164 +46,141 @@ enum Supremus EVENT_GROUP_ABILITIES = 1 }; -class boss_supremus : public CreatureScript +struct boss_supremus : public BossAI { -public: - boss_supremus() : CreatureScript("boss_supremus") { } + boss_supremus(Creature* creature) : BossAI(creature, DATA_SUPREMUS) { } - CreatureAI* GetAI(Creature* creature) const override + void JustEngagedWith(Unit* who) override { - return GetBlackTempleAI(creature); + BossAI::JustEngagedWith(who); + + SchedulePhase(false); + events.ScheduleEvent(EVENT_SPELL_BERSERK, 900000); + events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 4000); } - struct boss_supremusAI : public BossAI + void SchedulePhase(bool run) { - boss_supremusAI(Creature* creature) : BossAI(creature, DATA_SUPREMUS) + events.CancelEventGroup(EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000); + DoResetThreatList(); + + if (!run) { + events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, 5000, EVENT_GROUP_ABILITIES); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + me->RemoveAurasDueToSpell(SPELL_SNARE_SELF); + } + else + { + events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, 5000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SWITCH_TARGET, 0, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_CHECK_DIST, 0, EVENT_GROUP_ABILITIES); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + me->CastSpell(me, SPELL_SNARE_SELF, true); + } + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (summon->GetEntry() == NPC_SUPREMUS_PUNCH_STALKER) + { + summon->ToTempSummon()->InitStats(20000); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true)) + summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); + } + else + summon->CastSpell(summon, SPELL_VOLCANIC_ERUPTION_TRIGGER, true); + } + + void SummonedCreatureDespawn(Creature* summon) override + { + summons.Despawn(summon); + } + + Unit* FindHatefulStrikeTarget() + { + Unit* target = nullptr; + ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList(); + for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) + { + Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); + if (unit && me->IsWithinMeleeRange(unit)) + if (!target || unit->GetHealth() > target->GetHealth()) + target = unit; } - void Reset() override + return target; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - BossAI::Reset(); - } - - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - - SchedulePhase(false); - events.ScheduleEvent(EVENT_SPELL_BERSERK, 900000); - events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 4000); - } - - void SchedulePhase(bool run) - { - events.CancelEventGroup(EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000); - DoResetThreatList(); - - if (!run) + case EVENT_SPELL_BERSERK: + me->CastSpell(me, SPELL_BERSERK, true); + break; + case EVENT_SPELL_HATEFUL_STRIKE: + if (Unit* target = FindHatefulStrikeTarget()) + me->CastSpell(target, SPELL_HATEFUL_STRIKE, false); + events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, urand(1500, 3000), EVENT_GROUP_ABILITIES); + break; + case EVENT_SPELL_MOLTEN_FLAMES: + me->CastSpell(me, SPELL_MOLTEN_PUNCH, false); + events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 20000, EVENT_GROUP_ABILITIES); + break; + case EVENT_SWITCH_PHASE: + SchedulePhase(!me->HasAura(SPELL_SNARE_SELF)); + break; + case EVENT_SWITCH_TARGET: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) { - events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, 5000, EVENT_GROUP_ABILITIES); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - me->RemoveAurasDueToSpell(SPELL_SNARE_SELF); + DoResetThreatList(); + me->AddThreat(target, 5000000.0f); + Talk(EMOTE_NEW_TARGET); } - else + events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, EVENT_GROUP_ABILITIES); + break; + case EVENT_CHECK_DIST: + if (me->GetDistance(me->GetVictim()) > 40.0f) { - events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, 5000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SWITCH_TARGET, 0, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_CHECK_DIST, 0, EVENT_GROUP_ABILITIES); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); - me->CastSpell(me, SPELL_SNARE_SELF, true); + Talk(EMOTE_PUNCH_GROUND); + me->CastSpell(me->GetVictim(), SPELL_CHARGE, true); + events.ScheduleEvent(EVENT_CHECK_DIST, 5000, EVENT_GROUP_ABILITIES); + break; } - } - - void JustDied(Unit* killer) override - { - BossAI::JustDied(killer); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (summon->GetEntry() == NPC_SUPREMUS_PUNCH_STALKER) + events.ScheduleEvent(EVENT_CHECK_DIST, 1, EVENT_GROUP_ABILITIES); + break; + case EVENT_SPELL_VOLCANIC_ERUPTION: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) { - summon->ToTempSummon()->InitStats(20000); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true)) - summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); + me->CastSpell(target, SPELL_VOLCANIC_ERUPTION, true); + Talk(EMOTE_GROUND_CRACK); } - else - summon->CastSpell(summon, SPELL_VOLCANIC_ERUPTION_TRIGGER, true); + events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, urand(10000, 18000), EVENT_GROUP_ABILITIES); + break; } - void SummonedCreatureDespawn(Creature* summon) override - { - summons.Despawn(summon); - } + DoMeleeAttackIfReady(); + } - Unit* FindHatefulStrikeTarget() - { - Unit* target = nullptr; - ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); - if (unit && me->IsWithinMeleeRange(unit)) - if (!target || unit->GetHealth() > target->GetHealth()) - target = unit; - } - - return target; - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_BERSERK: - me->CastSpell(me, SPELL_BERSERK, true); - break; - case EVENT_SPELL_HATEFUL_STRIKE: - if (Unit* target = FindHatefulStrikeTarget()) - me->CastSpell(target, SPELL_HATEFUL_STRIKE, false); - events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, urand(1500, 3000), EVENT_GROUP_ABILITIES); - break; - case EVENT_SPELL_MOLTEN_FLAMES: - me->CastSpell(me, SPELL_MOLTEN_PUNCH, false); - events.ScheduleEvent(EVENT_SPELL_MOLTEN_FLAMES, 20000, EVENT_GROUP_ABILITIES); - break; - case EVENT_SWITCH_PHASE: - SchedulePhase(!me->HasAura(SPELL_SNARE_SELF)); - break; - case EVENT_SWITCH_TARGET: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) - { - DoResetThreatList(); - me->AddThreat(target, 5000000.0f); - Talk(EMOTE_NEW_TARGET); - } - events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, EVENT_GROUP_ABILITIES); - break; - case EVENT_CHECK_DIST: - if (me->GetDistance(me->GetVictim()) > 40.0f) - { - Talk(EMOTE_PUNCH_GROUND); - me->CastSpell(me->GetVictim(), SPELL_CHARGE, true); - events.ScheduleEvent(EVENT_CHECK_DIST, 5000, EVENT_GROUP_ABILITIES); - break; - } - events.ScheduleEvent(EVENT_CHECK_DIST, 1, EVENT_GROUP_ABILITIES); - break; - case EVENT_SPELL_VOLCANIC_ERUPTION: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true)) - { - me->CastSpell(target, SPELL_VOLCANIC_ERUPTION, true); - Talk(EMOTE_GROUND_CRACK); - } - events.ScheduleEvent(EVENT_SPELL_VOLCANIC_ERUPTION, urand(10000, 18000), EVENT_GROUP_ABILITIES); - break; - } - - DoMeleeAttackIfReady(); - } - - bool CheckEvadeIfOutOfCombatArea() const override - { - return me->GetPositionX() < 565 || me->GetPositionX() > 865 || me->GetPositionY() < 545 || me->GetPositionY() > 1000; - } - }; + bool CheckEvadeIfOutOfCombatArea() const override + { + return me->GetPositionX() < 565 || me->GetPositionX() > 865 || me->GetPositionY() < 545 || me->GetPositionY() > 1000; + } }; void AddSC_boss_supremus() { - new boss_supremus(); + RegisterBlackTempleCreatureAI(boss_supremus); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp index f13f7f0fe..5f2f602fc 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -70,276 +70,213 @@ struct ShadowOfDeathSelector } }; -class boss_teron_gorefiend : public CreatureScript +struct boss_teron_gorefiend : public BossAI { -public: - boss_teron_gorefiend() : CreatureScript("boss_teron_gorefiend") { } + boss_teron_gorefiend(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND), intro(false) { } - CreatureAI* GetAI(Creature* creature) const override + bool intro; + + void Reset() override { - return GetBlackTempleAI(creature); + BossAI::Reset(); + me->CastSpell(me, SPELL_SHADOW_OF_DEATH_REMOVE, true); } - struct boss_teron_gorefiendAI : public BossAI + void SetData(uint32 type, uint32 id) override { - boss_teron_gorefiendAI(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND) + if (type || !me->IsAlive()) + return; + + if (id == SET_DATA_INTRO && !intro) { - intro = false; + intro = true; + Talk(SAY_INTRO); } + } - bool intro; + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + events.ScheduleEvent(EVENT_SPELL_INCINERATE, 24000); + events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 10000); + events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 17000); + events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 20000); + } - void Reset() override + void KilledUnit(Unit* /*victim*/) override + { + if (events.GetNextEventTime(EVENT_TALK_KILL) == 0) { - BossAI::Reset(); - me->CastSpell(me, SPELL_SHADOW_OF_DEATH_REMOVE, true); + Talk(SAY_SLAY); + events.ScheduleEvent(EVENT_TALK_KILL, 6000); } + } - void SetData(uint32 type, uint32 id) override + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + me->CastSpell(me, SPELL_SHADOW_OF_DEATH_REMOVE, true); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - if (type || !me->IsAlive()) - return; - - if (id == SET_DATA_INTRO && !intro) + case EVENT_SPELL_INCINERATE: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) { - intro = true; - Talk(SAY_INTRO); + if (roll_chance_i(50)) + Talk(SAY_INCINERATE); + me->CastSpell(target, SPELL_INCINERATE, false); } + events.ScheduleEvent(EVENT_SPELL_INCINERATE, 25000); + break; + case EVENT_SPELL_DOOM_BLOSSOM: + if (roll_chance_i(50)) + Talk(SAY_BLOSSOM); + + me->CastSpell(me, SPELL_SUMMON_DOOM_BLOSSOM, false); + events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 40000); + break; + case EVENT_SPELL_CRUSHING_SHADOWS: + if (roll_chance_i(20)) + Talk(SAY_CRUSHING); + me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me, false); + events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 15000); + break; + case EVENT_SPELL_SHADOW_OF_DEATH: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ShadowOfDeathSelector())) + me->CastSpell(target, SPELL_SHADOW_OF_DEATH, false); + events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 30000); + break; } - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SPELL_INCINERATE, 24000); - events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 10000); - events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 17000); - events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 20000); - } - - void KilledUnit(Unit* /*victim*/) override - { - if (events.GetNextEventTime(EVENT_TALK_KILL) == 0) - { - Talk(SAY_SLAY); - events.ScheduleEvent(EVENT_TALK_KILL, 6000); - } - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - } - - void JustDied(Unit* killer) override - { - BossAI::JustDied(killer); - Talk(SAY_DEATH); - me->CastSpell(me, SPELL_SHADOW_OF_DEATH_REMOVE, true); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() ) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_INCINERATE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - { - if (roll_chance_i(50)) - Talk(SAY_INCINERATE); - me->CastSpell(target, SPELL_INCINERATE, false); - } - events.ScheduleEvent(EVENT_SPELL_INCINERATE, 25000); - break; - case EVENT_SPELL_DOOM_BLOSSOM: - if (roll_chance_i(50)) - Talk(SAY_BLOSSOM); - - me->CastSpell(me, SPELL_SUMMON_DOOM_BLOSSOM, false); - events.ScheduleEvent(EVENT_SPELL_DOOM_BLOSSOM, 40000); - break; - case EVENT_SPELL_CRUSHING_SHADOWS: - if (roll_chance_i(20)) - Talk(SAY_CRUSHING); - me->CastCustomSpell(SPELL_CRUSHING_SHADOWS, SPELLVALUE_MAX_TARGETS, 5, me, false); - events.ScheduleEvent(EVENT_SPELL_CRUSHING_SHADOWS, 15000); - break; - case EVENT_SPELL_SHADOW_OF_DEATH: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ShadowOfDeathSelector())) - me->CastSpell(target, SPELL_SHADOW_OF_DEATH, false); - events.ScheduleEvent(EVENT_SPELL_SHADOW_OF_DEATH, 30000); - break; - } - - DoMeleeAttackIfReady(); - } - - bool CheckEvadeIfOutOfCombatArea() const override - { - return me->GetDistance(me->GetHomePosition()) > 100.0f; - } - }; + DoMeleeAttackIfReady(); + } }; -class spell_teron_gorefiend_shadow_of_death : public SpellScriptLoader +class spell_teron_gorefiend_shadow_of_death : public AuraScript { -public: - spell_teron_gorefiend_shadow_of_death() : SpellScriptLoader("spell_teron_gorefiend_shadow_of_death") { } + PrepareAuraScript(spell_teron_gorefiend_shadow_of_death); - class spell_teron_gorefiend_shadow_of_death_AuraScript : public AuraScript + void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& /*absorbAmount*/) { - PrepareAuraScript(spell_teron_gorefiend_shadow_of_death_AuraScript) + PreventDefaultAction(); + } - void Absorb(AuraEffect* /*aurEff*/, DamageInfo& /*dmgInfo*/, uint32& /*absorbAmount*/) - { - PreventDefaultAction(); - } + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + InstanceScript* instance = GetTarget()->GetInstanceScript(); + if (!GetCaster() || !instance || !instance->IsEncounterInProgress()) + return; + + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SPIRIT, true); + GetTarget()->CastSpell(GetTarget(), SPELL_POSSESS_SPIRIT_IMMUNE, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SPIRITUAL_VENGEANCE, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON1, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON2, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON3, true); + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON4, true); + } + + void Register() override + { + OnEffectAbsorb += AuraEffectAbsorbFn(spell_teron_gorefiend_shadow_of_death::Absorb, EFFECT_0); + AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_shadow_of_death::HandleEffectRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); + } +}; + +class spell_teron_gorefiend_spirit_lance : public AuraScript +{ + PrepareAuraScript(spell_teron_gorefiend_spirit_lance); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_2)) + amount -= (amount / effect->GetTotalTicks()) * effect->GetTickNumber(); + } + + void Update(AuraEffect const* /*effect*/) + { + PreventDefaultAction(); + if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1)) + effect->RecalculateAmount(); + } + + void Register() override + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_teron_gorefiend_spirit_lance::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DECREASE_SPEED); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_teron_gorefiend_spirit_lance::Update, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; + +class spell_teron_gorefiend_spiritual_vengeance : public AuraScript +{ + PrepareAuraScript(spell_teron_gorefiend_spiritual_vengeance); void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - InstanceScript* instance = GetTarget()->GetInstanceScript(); - if (!GetCaster() || !instance || !instance->IsEncounterInProgress()) - return; - - GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SPIRIT, true); - GetTarget()->CastSpell(GetTarget(), SPELL_POSSESS_SPIRIT_IMMUNE, true); - GetTarget()->CastSpell(GetTarget(), SPELL_SPIRITUAL_VENGEANCE, true); - GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON1, true); - GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON2, true); - GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON3, true); - GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SKELETON4, true); - } - - void Register() override - { - OnEffectAbsorb += AuraEffectAbsorbFn(spell_teron_gorefiend_shadow_of_death_AuraScript::Absorb, EFFECT_0); - AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_shadow_of_death_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override { - return new spell_teron_gorefiend_shadow_of_death_AuraScript(); + Unit::Kill(nullptr, GetTarget()); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance::HandleEffectRemove, EFFECT_2, SPELL_AURA_MOD_PACIFY_SILENCE, AURA_EFFECT_HANDLE_REAL); } }; -class spell_teron_gorefiend_spirit_lance : public SpellScriptLoader +class spell_teron_gorefiend_shadowy_construct : public AuraScript { -public: - spell_teron_gorefiend_spirit_lance() : SpellScriptLoader("spell_teron_gorefiend_spirit_lance") { } + PrepareAuraScript(spell_teron_gorefiend_shadowy_construct); - class spell_teron_gorefiend_spirit_lance_AuraScript : public AuraScript + bool Load() override { - PrepareAuraScript(spell_teron_gorefiend_spirit_lance_AuraScript); - - void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) - { - if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_2)) - amount -= (amount / effect->GetTotalTicks()) * effect->GetTickNumber(); - } - - void Update(AuraEffect const* /*effect*/) - { - PreventDefaultAction(); - if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1)) - effect->RecalculateAmount(); - } - - void Register() override - { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_teron_gorefiend_spirit_lance_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DECREASE_SPEED); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_teron_gorefiend_spirit_lance_AuraScript::Update, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_teron_gorefiend_spirit_lance_AuraScript(); + return GetUnitOwner()->GetTypeId() == TYPEID_UNIT; } -}; -class spell_teron_gorefiend_spiritual_vengeance : public SpellScriptLoader -{ -public: - spell_teron_gorefiend_spiritual_vengeance() : SpellScriptLoader("spell_teron_gorefiend_spiritual_vengeance") { } - - class spell_teron_gorefiend_spiritual_vengeance_AuraScript : public AuraScript + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PrepareAuraScript(spell_teron_gorefiend_spiritual_vengeance_AuraScript) + GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NORMAL, true); + GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_LANCE, true); + GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_CHAINS, true); + GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_VOLLEY, true); - void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit::Kill(nullptr, GetTarget()); - } + GetUnitOwner()->ToCreature()->SetInCombatWithZone(); + Map::PlayerList const& playerList = GetUnitOwner()->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i) + if (Player* player = i->GetSource()) + { + if (GetUnitOwner()->IsValidAttackTarget(player)) + GetUnitOwner()->AddThreat(player, 1000000.0f); + } - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_teron_gorefiend_spiritual_vengeance_AuraScript::HandleEffectRemove, EFFECT_2, SPELL_AURA_MOD_PACIFY_SILENCE, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_teron_gorefiend_spiritual_vengeance_AuraScript(); + GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_BRIEF_STUN, true); } -}; -class spell_teron_gorefiend_shadowy_construct : public SpellScriptLoader -{ -public: - spell_teron_gorefiend_shadowy_construct() : SpellScriptLoader("spell_teron_gorefiend_shadowy_construct") { } - - class spell_teron_gorefiend_shadowy_construct_AuraScript : public AuraScript + void Register() override { - PrepareAuraScript(spell_teron_gorefiend_shadowy_construct_AuraScript) - - bool Load() override - { - return GetUnitOwner()->GetTypeId() == TYPEID_UNIT; - } - - void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NORMAL, true); - GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_LANCE, true); - GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_CHAINS, true); - GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ALLOW_ID, SPELL_SPIRIT_VOLLEY, true); - - GetUnitOwner()->ToCreature()->SetInCombatWithZone(); - Map::PlayerList const& playerList = GetUnitOwner()->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i) - if (Player* player = i->GetSource()) - { - if (GetUnitOwner()->IsValidAttackTarget(player)) - GetUnitOwner()->AddThreat(player, 1000000.0f); - } - - GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_BRIEF_STUN, true); - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_teron_gorefiend_shadowy_construct_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_teron_gorefiend_shadowy_construct_AuraScript(); + AfterEffectApply += AuraEffectApplyFn(spell_teron_gorefiend_shadowy_construct::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; void AddSC_boss_teron_gorefiend() { - new boss_teron_gorefiend(); - new spell_teron_gorefiend_shadow_of_death(); - new spell_teron_gorefiend_spirit_lance(); - new spell_teron_gorefiend_spiritual_vengeance(); - new spell_teron_gorefiend_shadowy_construct(); + RegisterBlackTempleCreatureAI(boss_teron_gorefiend); + RegisterSpellScript(spell_teron_gorefiend_shadow_of_death); + RegisterSpellScript(spell_teron_gorefiend_spirit_lance); + RegisterSpellScript(spell_teron_gorefiend_spiritual_vengeance); + RegisterSpellScript(spell_teron_gorefiend_shadowy_construct); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index bab5cdea9..a618b7239 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -50,158 +50,118 @@ enum Events EVENT_KILL_SPEAK = 6 }; -class boss_najentus : public CreatureScript +struct boss_najentus : public BossAI { -public: - boss_najentus() : CreatureScript("boss_najentus") { } + boss_najentus(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS) { } - CreatureAI* GetAI(Creature* creature) const override + void KilledUnit(Unit* victim) override { - return GetBlackTempleAI(creature); + if (victim->GetTypeId() == TYPEID_PLAYER && events.GetNextEventTime(EVENT_KILL_SPEAK) == 0) + { + Talk(SAY_SLAY); + events.ScheduleEvent(EVENT_KILL_SPEAK, 5000); + } } - struct boss_najentusAI : public BossAI + void JustDied(Unit* killer) override { - boss_najentusAI(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS) - { - } + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - void Reset() override - { - BossAI::Reset(); - } + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_SPELL_BERSERK, 480000); + events.ScheduleEvent(EVENT_YELL, urand(25000, 100000)); + events.RescheduleEvent(EVENT_SPELL_NEEDLE, 10000); + events.RescheduleEvent(EVENT_SPELL_SPINE, 20001); + events.RescheduleEvent(EVENT_SPELL_SHIELD, 60000); + } - void KilledUnit(Unit* victim) override + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - if (victim->GetTypeId() == TYPEID_PLAYER && events.GetNextEventTime(EVENT_KILL_SPEAK) == 0) + case EVENT_SPELL_SHIELD: + me->CastSpell(me, SPELL_TIDAL_SHIELD, false); + events.DelayEvents(10000); + events.ScheduleEvent(EVENT_SPELL_SHIELD, 60000); + break; + case EVENT_SPELL_BERSERK: + Talk(SAY_ENRAGE); + me->CastSpell(me, SPELL_BERSERK, true); + break; + case EVENT_SPELL_NEEDLE: + me->CastCustomSpell(SPELL_NEEDLE_SPINE, SPELLVALUE_MAX_TARGETS, 3, me, false); + events.ScheduleEvent(EVENT_SPELL_NEEDLE, 15000); + break; + case EVENT_SPELL_SPINE: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) { - Talk(SAY_SLAY); - events.ScheduleEvent(EVENT_KILL_SPEAK, 5000); + me->CastSpell(target, SPELL_IMPALING_SPINE, false); + target->CastSpell(target, SPELL_SUMMON_IMPALING_SPINE, true); + Talk(SAY_NEEDLE); } - } - - void JustDied(Unit* killer) override - { - BossAI::JustDied(killer); - Talk(SAY_DEATH); - } - - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_SPELL_BERSERK, 480000); + events.ScheduleEvent(EVENT_SPELL_SPINE, 20000); + return; + case EVENT_YELL: + Talk(SAY_SPECIAL); events.ScheduleEvent(EVENT_YELL, urand(25000, 100000)); - events.RescheduleEvent(EVENT_SPELL_NEEDLE, 10000); - events.RescheduleEvent(EVENT_SPELL_SPINE, 20001); - events.RescheduleEvent(EVENT_SPELL_SHIELD, 60000); + break; } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SPELL_SHIELD: - me->CastSpell(me, SPELL_TIDAL_SHIELD, false); - events.DelayEvents(10000); - events.ScheduleEvent(EVENT_SPELL_SHIELD, 60000); - break; - case EVENT_SPELL_BERSERK: - Talk(SAY_ENRAGE); - me->CastSpell(me, SPELL_BERSERK, true); - break; - case EVENT_SPELL_NEEDLE: - me->CastCustomSpell(SPELL_NEEDLE_SPINE, SPELLVALUE_MAX_TARGETS, 3, me, false); - events.ScheduleEvent(EVENT_SPELL_NEEDLE, 15000); - break; - case EVENT_SPELL_SPINE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) - { - me->CastSpell(target, SPELL_IMPALING_SPINE, false); - target->CastSpell(target, SPELL_SUMMON_IMPALING_SPINE, true); - Talk(SAY_NEEDLE); - } - events.ScheduleEvent(EVENT_SPELL_SPINE, 20000); - return; - case EVENT_YELL: - Talk(SAY_SPECIAL); - events.ScheduleEvent(EVENT_YELL, urand(25000, 100000)); - break; - } - - DoMeleeAttackIfReady(); - } - }; -}; - -class spell_najentus_needle_spine : public SpellScriptLoader -{ -public: - spell_najentus_needle_spine() : SpellScriptLoader("spell_najentus_needle_spine") { } - - class spell_najentus_needle_spine_SpellScript : public SpellScript - { - PrepareSpellScript(spell_najentus_needle_spine_SpellScript); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - if (Unit* target = GetHitUnit()) - GetCaster()->CastSpell(target, SPELL_NEEDLE_SPINE_DAMAGE, true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_najentus_needle_spine_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_najentus_needle_spine_SpellScript(); + DoMeleeAttackIfReady(); } }; -class spell_najentus_hurl_spine : public SpellScriptLoader +class spell_najentus_needle_spine : public SpellScript { -public: - spell_najentus_hurl_spine() : SpellScriptLoader("spell_najentus_hurl_spine") { } + PrepareSpellScript(spell_najentus_needle_spine); - class spell_najentus_hurl_spine_SpellScript : public SpellScript + void HandleDummy(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_najentus_hurl_spine_SpellScript); + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, SPELL_NEEDLE_SPINE_DAMAGE, true); + } - void HandleSchoolDamage(SpellEffIndex /*effIndex*/) - { - Unit* target = GetHitUnit(); - if (target && target->HasAura(SPELL_TIDAL_SHIELD)) - { - target->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); - target->CastSpell(target, SPELL_TIDAL_BURST, true); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_najentus_hurl_spine_SpellScript::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_najentus_hurl_spine_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_najentus_needle_spine::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_najentus_hurl_spine : public SpellScript +{ + PrepareSpellScript(spell_najentus_hurl_spine); + + void HandleSchoolDamage(SpellEffIndex /*effIndex*/) + { + Unit* target = GetHitUnit(); + if (target && target->HasAura(SPELL_TIDAL_SHIELD)) + { + target->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); + target->CastSpell(target, SPELL_TIDAL_BURST, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_najentus_hurl_spine::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; void AddSC_boss_najentus() { - new boss_najentus(); - new spell_najentus_needle_spine(); - new spell_najentus_hurl_spine(); + RegisterBlackTempleCreatureAI(boss_najentus); + RegisterSpellScript(spell_najentus_needle_spine); + RegisterSpellScript(spell_najentus_hurl_spine); }