diff options
author | offl <11556157+offl@users.noreply.github.com> | 2021-04-13 10:30:56 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-13 09:30:56 +0200 |
commit | 7dc1d5c5a1fad174e35dabb261431969f3db686a (patch) | |
tree | b9ac3f8fe01c0ca3770ff1f2a7aea1ed897c21dd /src | |
parent | cb82cded17f49c7736012f226c542c2240bbf7a4 (diff) |
Scripts/Naxxramas: Update Noth to new model (#26387)
Co-authored-by: offl <offl@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Northrend/Naxxramas/boss_noth.cpp | 435 |
1 files changed, 212 insertions, 223 deletions
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 0a8d6473e72..dd72982a514 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -73,268 +73,257 @@ const uint32 SummonGuardianSpells[N_GUARDIAN_SPELLS] = { 29239, 29256, 29268 }; #define SPELL_BLINK RAND(29208, 29209, 29210, 29211) -class boss_noth : public CreatureScript +struct boss_noth : public BossAI { -public: - boss_noth() : CreatureScript("boss_noth") { } - - struct boss_nothAI : public BossAI + boss_noth(Creature* creature) : BossAI(creature, BOSS_NOTH), balconyCount(0), justBlinked(false) { - boss_nothAI(Creature* creature) : BossAI(creature, BOSS_NOTH), balconyCount(0), justBlinked(false) - { - std::copy(SummonWarriorSpells, SummonWarriorSpells + N_WARRIOR_SPELLS, _SummonWarriorSpells); - std::copy(SummonChampionSpells, SummonChampionSpells + N_CHAMPION_SPELLS, _SummonChampionSpells); - std::copy(SummonGuardianSpells, SummonGuardianSpells + N_GUARDIAN_SPELLS, _SummonGuardianSpells); + std::copy(SummonWarriorSpells, SummonWarriorSpells + N_WARRIOR_SPELLS, _SummonWarriorSpells); + std::copy(SummonChampionSpells, SummonChampionSpells + N_CHAMPION_SPELLS, _SummonChampionSpells); + std::copy(SummonGuardianSpells, SummonGuardianSpells + N_GUARDIAN_SPELLS, _SummonGuardianSpells); - events.SetPhase(PHASE_NONE); - } + events.SetPhase(PHASE_NONE); + } - void EnterEvadeMode(EvadeReason why) override - { - // in case we reset during balcony phase - if (events.IsInPhase(PHASE_BALCONY)) - DoCastAOE(SPELL_TELEPORT_BACK); - BossAI::EnterEvadeMode(why); - } + void EnterEvadeMode(EvadeReason why) override + { + // in case we reset during balcony phase + if (events.IsInPhase(PHASE_BALCONY)) + DoCastAOE(SPELL_TELEPORT_BACK); + BossAI::EnterEvadeMode(why); + } - void Reset() override - { - _Reset(); + void Reset() override + { + _Reset(); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - balconyCount = 0; - events.SetPhase(PHASE_NONE); - justBlinked = false; - } + balconyCount = 0; + events.SetPhase(PHASE_NONE); + justBlinked = false; + } - void JustEngagedWith(Unit* who) override - { - BossAI::JustEngagedWith(who); - Talk(SAY_AGGRO); - EnterPhaseGround(); - } + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + EnterPhaseGround(); + } - void EnterPhaseGround() - { - events.SetPhase(PHASE_GROUND); + void EnterPhaseGround() + { + events.SetPhase(PHASE_GROUND); - DoZoneInCombat(); + DoZoneInCombat(); - if (!me->IsThreatened()) - EnterEvadeMode(EVADE_REASON_NO_HOSTILES); - else + if (!me->IsThreatened()) + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); + else + { + uint8 timeGround; + switch (balconyCount) { - uint8 timeGround; - switch (balconyCount) - { - case 0: - timeGround = 90; - break; - case 1: - timeGround = 110; - break; - case 2: - default: - timeGround = 180; - } - events.ScheduleEvent(EVENT_GROUND_ATTACKABLE, Seconds(2), 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BALCONY, Seconds(timeGround), 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_CURSE, randtime(Seconds(10), Seconds(25)), 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_WARRIOR, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_BLINK, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); + case 0: + timeGround = 90; + break; + case 1: + timeGround = 110; + break; + case 2: + default: + timeGround = 180; } + events.ScheduleEvent(EVENT_GROUND_ATTACKABLE, Seconds(2), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BALCONY, Seconds(timeGround), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_CURSE, randtime(Seconds(10), Seconds(25)), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_WARRIOR, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); + if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_BLINK, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); } + } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - summon->setActive(true); - summon->SetFarVisible(true); - summon->AI()->DoZoneInCombat(); - } + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + summon->setActive(true); + summon->SetFarVisible(true); + summon->AI()->DoZoneInCombat(); + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } - void DamageTaken(Unit* /*who*/, uint32& damage) override // prevent noth from somehow dying in the balcony phase - { - if (!events.IsInPhase(PHASE_BALCONY)) - return; - if (damage < me->GetHealth()) - return; + void DamageTaken(Unit* /*who*/, uint32& damage) override // prevent noth from somehow dying in the balcony phase + { + if (!events.IsInPhase(PHASE_BALCONY)) + return; + if (damage < me->GetHealth()) + return; - me->SetHealth(1u); - damage = 0u; - } + me->SetHealth(1u); + damage = 0u; + } - void HandleSummon(uint32* spellsList, const uint8 nSpells, uint8 num) - { // this ensures we do not spawn two mobs using the same spell (<=> in the same position) if we can help it - while (num) - for (uint8 it = 0; it < nSpells && num; ++it) - { - num--; - uint8 selected = urand(it, nSpells - 1); - DoCastAOE(spellsList[selected]); - if (selected != it) // shuffle the selected into the part of the array that is no longer being searched - std::swap(spellsList[selected], spellsList[it]); - } - } + void HandleSummon(uint32* spellsList, const uint8 nSpells, uint8 num) + { // this ensures we do not spawn two mobs using the same spell (<=> in the same position) if we can help it + while (num) + for (uint8 it = 0; it < nSpells && num; ++it) + { + num--; + uint8 selected = urand(it, nSpells - 1); + DoCastAOE(spellsList[selected]); + if (selected != it) // shuffle the selected into the part of the array that is no longer being searched + std::swap(spellsList[selected], spellsList[it]); + } + } - void CastSummon(uint8 nWarrior, uint8 nChampion, uint8 nGuardian) - { - HandleSummon(_SummonWarriorSpells, N_WARRIOR_SPELLS, nWarrior); - HandleSummon(_SummonChampionSpells, N_CHAMPION_SPELLS, nChampion); - HandleSummon(_SummonGuardianSpells, N_GUARDIAN_SPELLS, nGuardian); - } + void CastSummon(uint8 nWarrior, uint8 nChampion, uint8 nGuardian) + { + HandleSummon(_SummonWarriorSpells, N_WARRIOR_SPELLS, nWarrior); + HandleSummon(_SummonChampionSpells, N_CHAMPION_SPELLS, nChampion); + HandleSummon(_SummonGuardianSpells, N_GUARDIAN_SPELLS, nGuardian); + } - 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()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) + case EVENT_CURSE: { - case EVENT_CURSE: + DoCastAOE(SPELL_CURSE); + events.Repeat(randtime(Seconds(50), Seconds(70))); + break; + } + case EVENT_WARRIOR: + Talk(SAY_SUMMON); + Talk(EMOTE_SUMMON); + + CastSummon(RAID_MODE(2, 3), 0, 0); + + events.Repeat(Seconds(40)); + break; + case EVENT_BLINK: + DoCastAOE(SPELL_CRIPPLE, true); + DoCastAOE(SPELL_BLINK); + ResetThreatList(); + justBlinked = true; + + events.Repeat(Seconds(40)); + break; + case EVENT_BALCONY: + events.SetPhase(PHASE_BALCONY); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AttackStop(); + me->StopMoving(); + me->RemoveAllAuras(); + + events.ScheduleEvent(EVENT_BALCONY_TELEPORT, Seconds(3), 0, PHASE_BALCONY); + events.ScheduleEvent(EVENT_WAVE, randtime(Seconds(5), Seconds(8)), 0, PHASE_BALCONY); + + uint8 timeBalcony; + switch (balconyCount) { - DoCastAOE(SPELL_CURSE); - events.Repeat(randtime(Seconds(50), Seconds(70))); - break; + case 0: + timeBalcony = 70; + break; + case 1: + timeBalcony = 97; + break; + case 2: + default: + timeBalcony = 120; + break; } - case EVENT_WARRIOR: - Talk(SAY_SUMMON); - Talk(EMOTE_SUMMON); - - CastSummon(RAID_MODE(2, 3), 0, 0); - - events.Repeat(Seconds(40)); - break; - case EVENT_BLINK: - DoCastAOE(SPELL_CRIPPLE, true); - DoCastAOE(SPELL_BLINK); - ResetThreatList(); - justBlinked = true; - - events.Repeat(Seconds(40)); - break; - case EVENT_BALCONY: - events.SetPhase(PHASE_BALCONY); - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AttackStop(); - me->StopMoving(); - me->RemoveAllAuras(); - - events.ScheduleEvent(EVENT_BALCONY_TELEPORT, Seconds(3), 0, PHASE_BALCONY); - events.ScheduleEvent(EVENT_WAVE, randtime(Seconds(5), Seconds(8)), 0, PHASE_BALCONY); - - uint8 timeBalcony; - switch (balconyCount) - { - case 0: - timeBalcony = 70; - break; - case 1: - timeBalcony = 97; - break; - case 2: - default: - timeBalcony = 120; - break; - } - events.ScheduleEvent(EVENT_GROUND, Seconds(timeBalcony), 0, PHASE_BALCONY); - break; - case EVENT_BALCONY_TELEPORT: - Talk(EMOTE_TELEPORT_1); - DoCastAOE(SPELL_TELEPORT); - break; - case EVENT_WAVE: - Talk(EMOTE_SUMMON_WAVE); - switch (balconyCount) - { - case 0: - CastSummon(0, RAID_MODE(2, 4), 0); - break; - case 1: - CastSummon(0, RAID_MODE(1, 2), RAID_MODE(1, 2)); - break; - case 2: - CastSummon(0, 0, RAID_MODE(2, 4)); - break; - default: - CastSummon(0, RAID_MODE(5, 10), RAID_MODE(5, 10)); - break; - } - events.Repeat(randtime(Seconds(30), Seconds(45))); - break; - case EVENT_GROUND: - ++balconyCount; - - DoCastAOE(SPELL_TELEPORT_BACK); - Talk(EMOTE_TELEPORT_2); - - EnterPhaseGround(); - break; - case EVENT_GROUND_ATTACKABLE: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.ScheduleEvent(EVENT_GROUND, Seconds(timeBalcony), 0, PHASE_BALCONY); + break; + case EVENT_BALCONY_TELEPORT: + Talk(EMOTE_TELEPORT_1); + DoCastAOE(SPELL_TELEPORT); + break; + case EVENT_WAVE: + Talk(EMOTE_SUMMON_WAVE); + switch (balconyCount) + { + case 0: + CastSummon(0, RAID_MODE(2, 4), 0); + break; + case 1: + CastSummon(0, RAID_MODE(1, 2), RAID_MODE(1, 2)); + break; + case 2: + CastSummon(0, 0, RAID_MODE(2, 4)); + break; + default: + CastSummon(0, RAID_MODE(5, 10), RAID_MODE(5, 10)); + break; + } + events.Repeat(randtime(Seconds(30), Seconds(45))); + break; + case EVENT_GROUND: + ++balconyCount; + + DoCastAOE(SPELL_TELEPORT_BACK); + Talk(EMOTE_TELEPORT_2); + + EnterPhaseGround(); + break; + case EVENT_GROUND_ATTACKABLE: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + break; } - if (events.IsInPhase(PHASE_GROUND)) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + if (events.IsInPhase(PHASE_GROUND)) + { + /* workaround for movechase breaking after blinking + without this noth would just stand there unless his current target moves */ + if (justBlinked && me->GetVictim() && !me->IsWithinMeleeRange(me->EnsureVictim())) { - /* workaround for movechase breaking after blinking - without this noth would just stand there unless his current target moves */ - if (justBlinked && me->GetVictim() && !me->IsWithinMeleeRange(me->EnsureVictim())) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->EnsureVictim()); - justBlinked = false; - } - else - DoMeleeAttackIfReady(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->EnsureVictim()); + justBlinked = false; } + else + DoMeleeAttackIfReady(); } + } - private: - uint32 balconyCount; - - bool justBlinked; + private: + uint32 balconyCount; - uint32 _SummonWarriorSpells[N_WARRIOR_SPELLS]; - uint32 _SummonChampionSpells[N_CHAMPION_SPELLS]; - uint32 _SummonGuardianSpells[N_GUARDIAN_SPELLS]; - }; + bool justBlinked; - CreatureAI* GetAI(Creature* creature) const override - { - return GetNaxxramasAI<boss_nothAI>(creature); - } + uint32 _SummonWarriorSpells[N_WARRIOR_SPELLS]; + uint32 _SummonChampionSpells[N_CHAMPION_SPELLS]; + uint32 _SummonGuardianSpells[N_GUARDIAN_SPELLS]; }; void AddSC_boss_noth() { - new boss_noth(); + RegisterNaxxramasCreatureAI(boss_noth); } |