/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "naxxramas.h" enum Says { SAY_AGGRO = 0, SAY_SUMMON = 1, SAY_SLAY = 2, SAY_DEATH = 3, EMOTE_SUMMON = 4, EMOTE_SUMMON_WAVE = 5, EMOTE_TELEPORT_BALCONY = 6, EMOTE_TELEPORT_BACK = 7, EMOTE_BLINK = 8 }; enum Spells { SPELL_CURSE_OF_THE_PLAGUEBRINGER = 29213, SPELL_CRIPPLE = 29212, SPELL_SUMMON_PLAGUED_WARRIORS = 29237, SPELL_TELEPORT = 29216, SPELL_TELEPORT_BACK = 29231, SPELL_BERSERK = 68378, SPELL_BLINK = 29208 }; enum Events { EVENT_CURSE = 1, EVENT_CRIPPLE = 2, EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE = 3, EVENT_MOVE_TO_BALCONY = 4, EVENT_BLINK = 5, EVENT_MOVE_TO_GROUND = 6, EVENT_SUMMON_PLAGUED_WARRIOR_REAL = 7, EVENT_BALCONY_SUMMON_ANNOUNCE = 8, EVENT_BALCONY_SUMMON_REAL = 9 }; enum Misc { NPC_PLAGUED_WARRIOR = 351088, NPC_PLAGUED_CHAMPION = 351087, NPC_PLAGUED_GUARDIAN = 351086 }; const Position summoningPosition[5] = { {2728.06f, -3535.38f, 263.21f, 2.75f}, {2725.71f, -3514.80f, 263.23f, 2.86f}, {2728.24f, -3465.08f, 264.20f, 3.56f}, {2704.79f, -3459.17f, 263.74f, 4.25f}, {2652.02f, -3459.13f, 262.50f, 5.39f} }; const Position nothPosition = {2684.94f, -3502.53f, 261.31f, 4.7f}; class boss_noth_40 : public CreatureScript { public: boss_noth_40() : CreatureScript("boss_noth_40") { } CreatureAI* GetAI(Creature* pCreature) const override { return GetNaxxramasAI(pCreature); } struct boss_noth_40AI : public BossAI { explicit boss_noth_40AI(Creature* c) : BossAI(c, BOSS_NOTH), summons(me) { pInstance = me->GetInstanceScript(); } InstanceScript* pInstance; uint8 timesInBalcony; EventMap events; SummonList summons; void StartGroundPhase() { me->SetReactState(REACT_AGGRESSIVE); me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->SetControlled(false, UNIT_STATE_ROOT); events.Reset(); events.ScheduleEvent(EVENT_MOVE_TO_BALCONY, 110000); events.ScheduleEvent(EVENT_CURSE, 15000); events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE, 10000); if (Is25ManRaid()) { events.ScheduleEvent(EVENT_BLINK, 26000); } } void StartBalconyPhase() { me->SetReactState(REACT_PASSIVE); me->AttackStop(); me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->SetControlled(true, UNIT_STATE_ROOT); events.Reset(); events.ScheduleEvent(EVENT_BALCONY_SUMMON_ANNOUNCE, 4000); events.ScheduleEvent(EVENT_MOVE_TO_GROUND, 70000); } void SummonHelper(uint32 entry, uint32 count) { for (uint8 i = 0; i < count; ++i) { me->SummonCreature(entry, summoningPosition[urand(0, 4)]); } } bool IsInRoom() { if (me->GetExactDist(2684.8f, -3502.5f, 261.3f) > 80.0f) { EnterEvadeMode(EVADE_REASON_OTHER); return false; } return true; } void Reset() override { BossAI::Reset(); events.Reset(); summons.DespawnAll(); me->CastSpell(me, SPELL_TELEPORT_BACK, true); me->SetControlled(false, UNIT_STATE_ROOT); me->SetReactState(REACT_AGGRESSIVE); timesInBalcony = 0; if (pInstance) { if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_NOTH_ENTRY_GATE))) { go->SetGoState(GO_STATE_ACTIVE); } } } void EnterEvadeMode(EvadeReason why) override { me->SetControlled(false, UNIT_STATE_ROOT); ScriptedAI::EnterEvadeMode(why); } void EnterCombat(Unit* who) override { BossAI::EnterCombat(who); Talk(SAY_AGGRO); StartGroundPhase(); if (pInstance) { if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_NOTH_ENTRY_GATE))) { go->SetGoState(GO_STATE_READY); } } } void JustSummoned(Creature* summon) override { summons.Summon(summon); summon->SetInCombatWithZone(); } void JustDied(Unit* killer) override { if (me->GetPositionZ() > 270.27f) { me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true); } BossAI::JustDied(killer); Talk(SAY_DEATH); if (pInstance) { if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_NOTH_ENTRY_GATE))) { go->SetGoState(GO_STATE_ACTIVE); } } } void KilledUnit(Unit* who) override { if (who->GetTypeId() != TYPEID_PLAYER) return; Talk(SAY_SLAY); if (pInstance) { pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } } void UpdateAI(uint32 diff) override { if (!IsInRoom()) return; if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; switch (events.ExecuteEvent()) { // GROUND case EVENT_CURSE: if (events.GetPhaseMask() == 0) { me->CastCustomSpell(SPELL_CURSE_OF_THE_PLAGUEBRINGER, SPELLVALUE_MAX_TARGETS, 10, me, false); } events.RepeatEvent(25000); break; case EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE: Talk(SAY_SUMMON); Talk(EMOTE_SUMMON); events.RepeatEvent(30000); events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_REAL, 4000); break; case EVENT_SUMMON_PLAGUED_WARRIOR_REAL: me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); SummonHelper(NPC_PLAGUED_WARRIOR, 3); break; case EVENT_MOVE_TO_BALCONY: Talk(EMOTE_TELEPORT_BALCONY); me->CastSpell(me, SPELL_TELEPORT, true); StartBalconyPhase(); break; case EVENT_BLINK: DoResetThreat(); me->CastSpell(me, SPELL_CRIPPLE, false); me->CastSpell(me, SPELL_BLINK, true); Talk(EMOTE_BLINK); events.RepeatEvent(30000); break; // BALCONY case EVENT_BALCONY_SUMMON_ANNOUNCE: Talk(EMOTE_SUMMON_WAVE); events.RepeatEvent(30000); events.ScheduleEvent(EVENT_BALCONY_SUMMON_REAL, 4000); break; case EVENT_BALCONY_SUMMON_REAL: me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); // visual switch (timesInBalcony) { case 0: SummonHelper(NPC_PLAGUED_CHAMPION, 4); break; case 1: SummonHelper(NPC_PLAGUED_CHAMPION, 2); SummonHelper(NPC_PLAGUED_GUARDIAN, 2); break; default: SummonHelper(NPC_PLAGUED_GUARDIAN, 4); break; } break; case EVENT_MOVE_TO_GROUND: Talk(EMOTE_TELEPORT_BACK); me->CastSpell(me, SPELL_TELEPORT_BACK, true); timesInBalcony++; if (timesInBalcony == 3) { DoCastSelf(SPELL_BERSERK); } StartGroundPhase(); break; } if (me->HasReactState(REACT_AGGRESSIVE)) DoMeleeAttackIfReady(); } }; }; void AddSC_boss_noth_40() { new boss_noth_40(); }