diff options
author | ForesterDev <11771800+ForesterDev@users.noreply.github.com> | 2020-09-04 18:58:57 +0400 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-02-05 10:55:59 +0100 |
commit | 1c22cd7d089eeeab93be4ee013bcd8739528433f (patch) | |
tree | a8a778d15152966390c7e95ca058c05252564dc0 | |
parent | e294f94617cd569054b6452c015dd93442311705 (diff) |
Scripts/ICC: update Lady Deathwhisper scripts to new model (#25393)
(cherry picked from commit aac3ae40f772c65bf976ba68ad24f3643fb69dab)
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp | 1527 |
1 files changed, 722 insertions, 805 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index b44a06fb468..0cdc652e9a0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -194,836 +194,811 @@ class DaranavanMoveEvent : public BasicEvent Creature& _darnavan; }; -class boss_lady_deathwhisper : public CreatureScript +struct boss_lady_deathwhisper : public BossAI { - public: - boss_lady_deathwhisper() : CreatureScript("boss_lady_deathwhisper") { } - - struct boss_lady_deathwhisperAI : public BossAI + boss_lady_deathwhisper(Creature* creature) : BossAI(creature, DATA_LADY_DEATHWHISPER), + _dominateMindCount(RAID_MODE<uint8>(0, 1, 1, 3)) + { + Initialize(); + } + + void Initialize() + { + _waveCounter = 0; + _nextVengefulShadeTargetGUID.clear(); + _cultistQueue.clear(); + _darnavanGUID.Clear(); + _phase = PHASE_ALL; + scheduler.SetValidator([this] + { + return !(me->HasUnitState(UNIT_STATE_CASTING) && _phase != PHASE_INTRO); + }); + } + + void Reset() override + { + _Reset(); + Initialize(); + _phase = PHASE_ONE; + DoCastSelf(SPELL_SHADOW_CHANNELING); + me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void DoAction(int32 action) override + { + if (action != ACTION_START_INTRO) + return; + + Talk(SAY_INTRO_1); + _phase = PHASE_INTRO; + scheduler.Schedule(Seconds(10), GROUP_INTRO, [this](TaskContext context) { - boss_lady_deathwhisperAI(Creature* creature) : BossAI(creature, DATA_LADY_DEATHWHISPER), - _dominateMindCount(RAID_MODE<uint8>(0, 1, 1, 3)) + switch (context.GetRepeatCounter()) { - Initialize(); + case 0: + Talk(SAY_INTRO_2); + context.Repeat(Seconds(21)); + break; + case 1: + Talk(SAY_INTRO_3); + context.Repeat(Seconds(11)); + break; + case 2: + Talk(SAY_INTRO_4); + context.Repeat(Seconds(9)); + break; + case 3: + Talk(SAY_INTRO_5); + context.Repeat(Seconds(21)); + break; + case 4: + Talk(SAY_INTRO_6); + context.Repeat(Seconds(10)); + break; + case 5: + Talk(SAY_INTRO_7); + return; + default: + break; } + }); + } - void Initialize() - { - _waveCounter = 0; - _nextVengefulShadeTargetGUID.clear(); - _cultistQueue.clear(); - _darnavanGUID.Clear(); - _phase = PHASE_ALL; - scheduler.SetValidator([this] - { - return !(me->HasUnitState(UNIT_STATE_CASTING) && _phase != PHASE_INTRO); - }); - } + void AttackStart(Unit* victim) override + { + if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) + return; - void Reset() override - { - _Reset(); - Initialize(); - _phase = PHASE_ONE; - DoCastSelf(SPELL_SHADOW_CHANNELING); - me->SetFullPower(POWER_MANA); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - } + if (victim && me->Attack(victim, true) && _phase != PHASE_ONE) + me->GetMotionMaster()->MoveChase(victim); + } - void DoAction(int32 action) override - { - if (action != ACTION_START_INTRO) - return; + void JustEngagedWith(Unit* who) override + { + if (!instance->CheckRequiredBosses(DATA_LADY_DEATHWHISPER, who->ToPlayer())) + { + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); + instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); + return; + } - Talk(SAY_INTRO_1); - _phase = PHASE_INTRO; - scheduler.Schedule(Seconds(10), GROUP_INTRO, [this](TaskContext context) + _phase = PHASE_ONE; + me->SetCombatPulseDelay(5); + me->setActive(true); + DoZoneInCombat(); + scheduler.CancelGroup(GROUP_INTRO); + // phase-independent events + scheduler + .Schedule(Minutes(10), [this](TaskContext /*context*/) + { + DoCastSelf(SPELL_BERSERK); + Talk(SAY_BERSERK); + }) + .Schedule(Seconds(17), [this](TaskContext death_and_decay) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + DoCast(target, SPELL_DEATH_AND_DECAY); + death_and_decay.Repeat(Seconds(22), Seconds(30)); + }); + if (GetDifficulty() != DIFFICULTY_10_N) + scheduler.Schedule(Seconds(27), [this](TaskContext dominate_mind) { - switch (context.GetRepeatCounter()) - { - case 0: - Talk(SAY_INTRO_2); - context.Repeat(Seconds(21)); - break; - case 1: - Talk(SAY_INTRO_3); - context.Repeat(Seconds(11)); - break; - case 2: - Talk(SAY_INTRO_4); - context.Repeat(Seconds(9)); - break; - case 3: - Talk(SAY_INTRO_5); - context.Repeat(Seconds(21)); - break; - case 4: - Talk(SAY_INTRO_6); - context.Repeat(Seconds(10)); - break; - case 5: - Talk(SAY_INTRO_7); - return; - default: - break; - } + Talk(SAY_DOMINATE_MIND); + std::list<Unit*> targets; + SelectTargetList(targets, _dominateMindCount, SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_DOMINATE_MIND); + for (Unit* target : targets) + DoCast(target, SPELL_DOMINATE_MIND); + dominate_mind.Repeat(Seconds(40), Seconds(45)); }); - } - - void AttackStart(Unit* victim) override + // phase one only + scheduler + .Schedule(Seconds(5), GROUP_ONE, [this](TaskContext wave) { - if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (victim && me->Attack(victim, true) && _phase != PHASE_ONE) - me->GetMotionMaster()->MoveChase(victim); - } - - void JustEngagedWith(Unit* who) override + SummonWaveP1(); + wave.Repeat(Seconds(IsHeroic() ? 45 : 60)); + }) + .Schedule(Seconds(2), GROUP_ONE, [this](TaskContext shadow_bolt) { - if (!instance->CheckRequiredBosses(DATA_LADY_DEATHWHISPER, who->ToPlayer())) - { - EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); - instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); - return; - } - - _phase = PHASE_ONE; - me->SetCombatPulseDelay(5); - me->setActive(true); - DoZoneInCombat(); - scheduler.CancelGroup(GROUP_INTRO); - // phase-independent events - scheduler - .Schedule(Minutes(10), [this](TaskContext /*context*/) - { - DoCastSelf(SPELL_BERSERK); - Talk(SAY_BERSERK); - }) - .Schedule(Seconds(17), [this](TaskContext death_and_decay) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - DoCast(target, SPELL_DEATH_AND_DECAY); - death_and_decay.Repeat(Seconds(22), Seconds(30)); - }); - if (GetDifficulty() != DIFFICULTY_10_N) - scheduler.Schedule(Seconds(27), [this](TaskContext dominate_mind) - { - Talk(SAY_DOMINATE_MIND); - std::list<Unit*> targets; - SelectTargetList(targets, _dominateMindCount, SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_DOMINATE_MIND); - for (Unit* target : targets) - DoCast(target, SPELL_DOMINATE_MIND); - dominate_mind.Repeat(Seconds(40), Seconds(45)); - }); - // phase one only - scheduler - .Schedule(Seconds(5), GROUP_ONE, [this](TaskContext wave) - { - SummonWaveP1(); - wave.Repeat(Seconds(IsHeroic() ? 45 : 60)); - }) - .Schedule(Seconds(2), GROUP_ONE, [this](TaskContext shadow_bolt) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - DoCast(target, SPELL_SHADOW_BOLT); - shadow_bolt.Repeat(Milliseconds(2450), Milliseconds(3600)); - }) - .Schedule(Seconds(15), GROUP_ONE, [this](TaskContext context) - { - DoImproveCultist(); - context.Repeat(Seconds(25)); - }); - - Talk(SAY_AGGRO); - DoStartNoMovement(who); - me->RemoveAurasDueToSpell(SPELL_SHADOW_CHANNELING); - DoCastSelf(SPELL_MANA_BARRIER, true); - instance->SetBossState(DATA_LADY_DEATHWHISPER, IN_PROGRESS); - } - - void JustDied(Unit* killer) override + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + DoCast(target, SPELL_SHADOW_BOLT); + shadow_bolt.Repeat(Milliseconds(2450), Milliseconds(3600)); + }) + .Schedule(Seconds(15), GROUP_ONE, [this](TaskContext context) { - Talk(SAY_DEATH); - - std::set<uint32> livingAddEntries; - // Full House achievement - for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr) - if (Unit* unit = ObjectAccessor::GetUnit(*me, *itr)) - if (unit->IsAlive() && unit->GetEntry() != NPC_VENGEFUL_SHADE) - livingAddEntries.insert(unit->GetEntry()); - - if (livingAddEntries.size() >= 5) - instance->DoUpdateCriteria(CriteriaType::BeSpellTarget, SPELL_FULL_HOUSE, 0, me); - - if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) - { - if (darnavan->IsAlive()) - { - darnavan->SetFaction(FACTION_FRIENDLY); - darnavan->CombatStop(true); - darnavan->GetMotionMaster()->MoveIdle(); - darnavan->SetReactState(REACT_PASSIVE); - darnavan->m_Events.AddEvent(new DaranavanMoveEvent(*darnavan), darnavan->m_Events.CalculateTime(10s)); - darnavan->AI()->Talk(SAY_DARNAVAN_RESCUED); - - if (!killer) - return; - - if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - if (Group* group = owner->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) - if (Player* member = itr->GetSource()) - if (member->IsInMap(owner)) - member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); - } - else - owner->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); - } - } - } - - _JustDied(); - } - - void EnterEvadeMode(EvadeReason /*why*/) override + DoImproveCultist(); + context.Repeat(Seconds(25)); + }); + + Talk(SAY_AGGRO); + DoStartNoMovement(who); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CHANNELING); + DoCastSelf(SPELL_MANA_BARRIER, true); + instance->SetBossState(DATA_LADY_DEATHWHISPER, IN_PROGRESS); + } + + void JustDied(Unit* killer) override + { + Talk(SAY_DEATH); + + std::set<uint32> livingAddEntries; + // Full House achievement + for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr) + if (Unit* unit = ObjectAccessor::GetUnit(*me, *itr)) + if (unit->IsAlive() && unit->GetEntry() != NPC_VENGEFUL_SHADE) + livingAddEntries.insert(unit->GetEntry()); + + if (livingAddEntries.size() >= 5) + instance->DoUpdateCriteria(CriteriaType::BeSpellTarget, SPELL_FULL_HOUSE, 0, me); + + if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) + { + if (darnavan->IsAlive()) { - scheduler.CancelAll(); - summons.DespawnAll(); - if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) - darnavan->DespawnOrUnsummon(); - - _DespawnAtEvade(); - } + darnavan->SetFaction(FACTION_FRIENDLY); + darnavan->CombatStop(true); + darnavan->GetMotionMaster()->MoveIdle(); + darnavan->SetReactState(REACT_PASSIVE); + darnavan->m_Events.AddEvent(new DaranavanMoveEvent(*darnavan), darnavan->m_Events.CalculateTime(10s)); + darnavan->AI()->Talk(SAY_DARNAVAN_RESCUED); - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_KILL); - } + if (!killer) + return; - void DamageTaken(Unit* /*damageDealer*/, uint32& damage) override - { - // phase transition - if (_phase == PHASE_ONE && damage > uint32(me->GetPower(POWER_MANA))) + if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) { - _phase = PHASE_TWO; - Talk(SAY_PHASE_2); - Talk(EMOTE_PHASE_2); - DoStartMovement(me->GetVictim()); - ResetThreatList(); - damage -= me->GetPower(POWER_MANA); - me->SetPower(POWER_MANA, 0); - me->RemoveAurasDueToSpell(SPELL_MANA_BARRIER); - scheduler.CancelGroup(GROUP_ONE); - - scheduler - .Schedule(Seconds(12), GROUP_TWO, [this](TaskContext frostbolt) - { - DoCastVictim(SPELL_FROSTBOLT); - frostbolt.Repeat(); - }) - .Schedule(Seconds(20), GROUP_TWO, [this](TaskContext frostboldVolley) - { - DoCastAOE(SPELL_FROSTBOLT_VOLLEY); - frostboldVolley.Repeat(); - }) - .Schedule(Seconds(6), Seconds(9), GROUP_TWO, [this](TaskContext touch) - { - if (me->GetVictim()) - me->AddAura(SPELL_TOUCH_OF_INSIGNIFICANCE, me->EnsureVictim()); - touch.Repeat(); - }) - .Schedule(Seconds(12), GROUP_TWO, [this](TaskContext summonShade) - { - CastSpellExtraArgs args; - args.AddSpellMod(SPELLVALUE_MAX_TARGETS, Is25ManRaid() ? 2 : 1); - me->CastSpell(nullptr, SPELL_SUMMON_SPIRITS, args); - summonShade.Repeat(); - }); - - // on heroic mode Lady Deathwhisper is immune to taunt effects in phase 2 and continues summoning adds - if (IsHeroic()) + if (Group* group = owner->GetGroup()) { - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); - scheduler.Schedule(Seconds(), GROUP_TWO, [this](TaskContext context) - { - SummonWaveP2(); - context.Repeat(Seconds(45)); - }); + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + if (Player* member = itr->GetSource()) + if (member->IsInMap(owner)) + member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); } + else + owner->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); } } + } - void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_SUMMON_SPIRITS) - _nextVengefulShadeTargetGUID.push_back(target->GetGUID()); - } - - void JustSummoned(Creature* summon) override - { - switch (summon->GetEntry()) + _JustDied(); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + scheduler.CancelAll(); + summons.DespawnAll(); + if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) + darnavan->DespawnOrUnsummon(); + + _DespawnAtEvade(); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_KILL); + } + + void DamageTaken(Unit* /*damageDealer*/, uint32& damage) override + { + // phase transition + if (_phase == PHASE_ONE && damage > uint32(me->GetPower(POWER_MANA))) + { + _phase = PHASE_TWO; + Talk(SAY_PHASE_2); + Talk(EMOTE_PHASE_2); + DoStartMovement(me->GetVictim()); + ResetThreatList(); + damage -= me->GetPower(POWER_MANA); + me->SetPower(POWER_MANA, 0); + me->RemoveAurasDueToSpell(SPELL_MANA_BARRIER); + scheduler.CancelGroup(GROUP_ONE); + + scheduler + .Schedule(Seconds(12), GROUP_TWO, [this](TaskContext frostbolt) { - case NPC_DARNAVAN_10: - case NPC_DARNAVAN_25: - _darnavanGUID = summon->GetGUID(); - summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random)); - return; - case NPC_VENGEFUL_SHADE: - if (_nextVengefulShadeTargetGUID.empty()) - break; - summon->AI()->SetGUID(_nextVengefulShadeTargetGUID.front()); - _nextVengefulShadeTargetGUID.pop_front(); - break; - case NPC_CULT_ADHERENT: - case NPC_CULT_FANATIC: - _cultistQueue.push_back(summon->GetGUID()); - summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random)); - break; - default: - break; - } - summons.Summon(summon); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && _phase != PHASE_INTRO) - return; - - scheduler.Update(diff, [this] + DoCastVictim(SPELL_FROSTBOLT); + frostbolt.Repeat(); + }) + .Schedule(Seconds(20), GROUP_TWO, [this](TaskContext frostboldVolley) { - // We should not melee attack when barrier is up - if (!me->HasAura(SPELL_MANA_BARRIER)) - DoMeleeAttackIfReady(); - }); - } - - // summoning function for first phase - void SummonWaveP1() - { - uint8 addIndex = _waveCounter & 1; - uint8 addIndexOther = uint8(addIndex ^ 1); - - // Summon first add, replace it with Darnavan if weekly quest is active - if (_waveCounter || !sQuestPoolMgr->IsQuestActive(QUEST_DEPROGRAMMING)) - Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3]); - else - Summon(NPC_DARNAVAN, SummonPositions[addIndex * 3]); - - Summon(SummonEntries[addIndexOther], SummonPositions[addIndex * 3 + 1]); - Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3 + 2]); - if (Is25ManRaid()) + DoCastAOE(SPELL_FROSTBOLT_VOLLEY); + frostboldVolley.Repeat(); + }) + .Schedule(Seconds(6), Seconds(9), GROUP_TWO, [this](TaskContext touch) { - Summon(SummonEntries[addIndexOther], SummonPositions[addIndexOther * 3]); - Summon(SummonEntries[addIndex], SummonPositions[addIndexOther * 3 + 1]); - Summon(SummonEntries[addIndexOther], SummonPositions[addIndexOther * 3 + 2]); - Summon(SummonEntries[urand(0, 1)], SummonPositions[6]); - } - - ++_waveCounter; - } + if (me->GetVictim()) + me->AddAura(SPELL_TOUCH_OF_INSIGNIFICANCE, me->EnsureVictim()); + touch.Repeat(); + }) + .Schedule(Seconds(12), GROUP_TWO, [this](TaskContext summonShade) + { + CastSpellExtraArgs args; + args.AddSpellMod(SPELLVALUE_MAX_TARGETS, Is25ManRaid() ? 2 : 1); + me->CastSpell(nullptr, SPELL_SUMMON_SPIRITS, args); + summonShade.Repeat(); + }); - // summoning function for second phase - void SummonWaveP2() + // on heroic mode Lady Deathwhisper is immune to taunt effects in phase 2 and continues summoning adds + if (IsHeroic()) { - if (Is25ManRaid()) + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + scheduler.Schedule(Seconds(), GROUP_TWO, [this](TaskContext context) { - uint8 addIndex = _waveCounter & 1; - Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3]); - Summon(SummonEntries[addIndex ^ 1], SummonPositions[addIndex * 3 + 1]); - Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3+ 2]); - } - else - Summon(SummonEntries[urand(0, 1)], SummonPositions[6]); - - ++_waveCounter; + SummonWaveP2(); + context.Repeat(Seconds(45)); + }); } + } + } - // helper for summoning wave mobs - void Summon(uint32 entry, Position const& pos) - { - if (TempSummon* summon = me->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10s)) - summon->CastSpell(summon, SPELL_TELEPORT_VISUAL); - } + void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_SUMMON_SPIRITS) + _nextVengefulShadeTargetGUID.push_back(target->GetGUID()); + } - void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override - { - if (summon->GetEntry() == NPC_CULT_ADHERENT || summon->GetEntry() == NPC_CULT_FANATIC) - _cultistQueue.remove(summon->GetGUID()); - } + void JustSummoned(Creature* summon) override + { + switch (summon->GetEntry()) + { + case NPC_DARNAVAN_10: + case NPC_DARNAVAN_25: + _darnavanGUID = summon->GetGUID(); + summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random)); + return; + case NPC_VENGEFUL_SHADE: + if (_nextVengefulShadeTargetGUID.empty()) + break; + summon->AI()->SetGUID(_nextVengefulShadeTargetGUID.front()); + _nextVengefulShadeTargetGUID.pop_front(); + break; + case NPC_CULT_ADHERENT: + case NPC_CULT_FANATIC: + _cultistQueue.push_back(summon->GetGUID()); + summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random)); + break; + default: + break; + } + summons.Summon(summon); + } - void DoImproveCultist() - { - if (_cultistQueue.empty()) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && _phase != PHASE_INTRO) + return; - _cultistGUID = Trinity::Containers::SelectRandomContainerElement(_cultistQueue); - _cultistQueue.remove(_cultistGUID); - Creature* cultist = ObjectAccessor::GetCreature(*me, _cultistGUID); - if (!cultist) - return; + scheduler.Update(diff, [this] + { + // We should not melee attack when barrier is up + if (!me->HasAura(SPELL_MANA_BARRIER)) + DoMeleeAttackIfReady(); + }); + } + + // summoning function for first phase + void SummonWaveP1() + { + uint8 addIndex = _waveCounter & 1; + uint8 addIndexOther = uint8(addIndex ^ 1); + + // Summon first add, replace it with Darnavan if weekly quest is active + if (_waveCounter || !sQuestPoolMgr->IsQuestActive(QUEST_DEPROGRAMMING)) + Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3]); + else + Summon(NPC_DARNAVAN, SummonPositions[addIndex * 3]); + + Summon(SummonEntries[addIndexOther], SummonPositions[addIndex * 3 + 1]); + Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3 + 2]); + if (Is25ManRaid()) + { + Summon(SummonEntries[addIndexOther], SummonPositions[addIndexOther * 3]); + Summon(SummonEntries[addIndex], SummonPositions[addIndexOther * 3 + 1]); + Summon(SummonEntries[addIndexOther], SummonPositions[addIndexOther * 3 + 2]); + Summon(SummonEntries[urand(0, 1)], SummonPositions[6]); + } - if (RAND(0,1)) - me->CastSpell(cultist, SPELL_DARK_MARTYRDOM_T); - else - { - me->CastSpell(cultist, cultist->GetEntry() == NPC_CULT_FANATIC ? SPELL_DARK_TRANSFORMATION_T : SPELL_DARK_EMPOWERMENT_T, true); - Talk(uint8(cultist->GetEntry() == NPC_CULT_FANATIC ? SAY_DARK_TRANSFORMATION : SAY_DARK_EMPOWERMENT)); - } - } + ++_waveCounter; + } - private: - ObjectGuid _darnavanGUID; - ObjectGuid _cultistGUID; - GuidList _cultistQueue; - GuidList _nextVengefulShadeTargetGUID; - uint32 _waveCounter; - uint8 const _dominateMindCount; - uint8 _phase; - }; - - CreatureAI* GetAI(Creature* creature) const override + // summoning function for second phase + void SummonWaveP2() + { + if (Is25ManRaid()) + { + uint8 addIndex = _waveCounter & 1; + Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3]); + Summon(SummonEntries[addIndex ^ 1], SummonPositions[addIndex * 3 + 1]); + Summon(SummonEntries[addIndex], SummonPositions[addIndex * 3+ 2]); + } + else + Summon(SummonEntries[urand(0, 1)], SummonPositions[6]); + + ++_waveCounter; + } + + // helper for summoning wave mobs + void Summon(uint32 entry, Position const& pos) + { + if (TempSummon* summon = me->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10s)) + summon->CastSpell(summon, SPELL_TELEPORT_VISUAL); + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + if (summon->GetEntry() == NPC_CULT_ADHERENT || summon->GetEntry() == NPC_CULT_FANATIC) + _cultistQueue.remove(summon->GetGUID()); + } + + void DoImproveCultist() + { + if (_cultistQueue.empty()) + return; + + _cultistGUID = Trinity::Containers::SelectRandomContainerElement(_cultistQueue); + _cultistQueue.remove(_cultistGUID); + Creature* cultist = ObjectAccessor::GetCreature(*me, _cultistGUID); + if (!cultist) + return; + + if (RAND(0,1)) + me->CastSpell(cultist, SPELL_DARK_MARTYRDOM_T); + else { - return GetIcecrownCitadelAI<boss_lady_deathwhisperAI>(creature); + me->CastSpell(cultist, cultist->GetEntry() == NPC_CULT_FANATIC ? SPELL_DARK_TRANSFORMATION_T : SPELL_DARK_EMPOWERMENT_T, true); + Talk(uint8(cultist->GetEntry() == NPC_CULT_FANATIC ? SAY_DARK_TRANSFORMATION : SAY_DARK_EMPOWERMENT)); } + } + +private: + ObjectGuid _darnavanGUID; + ObjectGuid _cultistGUID; + GuidList _cultistQueue; + GuidList _nextVengefulShadeTargetGUID; + uint32 _waveCounter; + uint8 const _dominateMindCount; + uint8 _phase; }; -class npc_cult_fanatic : public CreatureScript +struct npc_cult_fanatic : public ScriptedAI { - public: - npc_cult_fanatic() : CreatureScript("npc_cult_fanatic") { } + npc_cult_fanatic(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_cult_fanaticAI : public ScriptedAI - { - npc_cult_fanaticAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void Reset() override + void Reset() override + { + _scheduler.CancelAll(); + _scheduler + .SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }) + .Schedule(Seconds(17), [this](TaskContext vampiric_might) + { + DoCastSelf(SPELL_VAMPIRIC_MIGHT); + vampiric_might.Repeat(Seconds(25)); + }) + .Schedule(Seconds(12), [this](TaskContext shadow_cleave) + { + DoCastVictim(SPELL_SHADOW_CLEAVE); + shadow_cleave.Repeat(Seconds(14)); + }) + .Schedule(Seconds(10), [this](TaskContext necrotic_strike) { - _scheduler.CancelAll(); + DoCastVictim(SPELL_NECROTIC_STRIKE); + necrotic_strike.Repeat(Seconds(17)); + }); + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) + { + case SPELL_DARK_TRANSFORMATION_T: + me->InterruptNonMeleeSpells(true); + DoCastSelf(SPELL_DARK_TRANSFORMATION); + break; + case SPELL_DARK_TRANSFORMATION: + DoCastSelf(SPELL_FULL_HEAL); + me->UpdateEntry(NPC_DEFORMED_FANATIC); + break; + case SPELL_DARK_MARTYRDOM_T: + me->SetReactState(REACT_PASSIVE); + me->InterruptNonMeleeSpells(true); + me->AttackStop(); + DoCastSelf(SPELL_DARK_MARTYRDOM_FANATIC); + break; + case SPELL_DARK_MARTYRDOM_FANATIC: + case SPELL_DARK_MARTYRDOM_FANATIC_25N: + case SPELL_DARK_MARTYRDOM_FANATIC_10H: + case SPELL_DARK_MARTYRDOM_FANATIC_25H: _scheduler - .SetValidator([this] - { - return !me->HasUnitState(UNIT_STATE_CASTING); - }) - .Schedule(Seconds(17), [this](TaskContext vampiric_might) - { - DoCastSelf(SPELL_VAMPIRIC_MIGHT); - vampiric_might.Repeat(Seconds(25)); - }) - .Schedule(Seconds(12), [this](TaskContext shadow_cleave) + .Schedule(Seconds(2), [this](TaskContext /*context*/) { - DoCastVictim(SPELL_SHADOW_CLEAVE); - shadow_cleave.Repeat(Seconds(14)); + me->UpdateEntry(NPC_REANIMATED_FANATIC); + DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + DoCastSelf(SPELL_FULL_HEAL, true); + me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); }) - .Schedule(Seconds(10), [this](TaskContext necrotic_strike) + .Schedule(Seconds(6), [this](TaskContext /*context*/) { - DoCastVictim(SPELL_NECROTIC_STRIKE); - necrotic_strike.Repeat(Seconds(17)); - }); - } - - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override - { - switch (spellInfo->Id) - { - case SPELL_DARK_TRANSFORMATION_T: - me->InterruptNonMeleeSpells(true); - DoCastSelf(SPELL_DARK_TRANSFORMATION); - break; - case SPELL_DARK_TRANSFORMATION: - DoCastSelf(SPELL_FULL_HEAL); - me->UpdateEntry(NPC_DEFORMED_FANATIC); - break; - case SPELL_DARK_MARTYRDOM_T: - me->SetReactState(REACT_PASSIVE); - me->InterruptNonMeleeSpells(true); - me->AttackStop(); - DoCastSelf(SPELL_DARK_MARTYRDOM_FANATIC); - break; - case SPELL_DARK_MARTYRDOM_FANATIC: - case SPELL_DARK_MARTYRDOM_FANATIC_25N: - case SPELL_DARK_MARTYRDOM_FANATIC_10H: - case SPELL_DARK_MARTYRDOM_FANATIC_25H: - _scheduler - .Schedule(Seconds(2), [this](TaskContext /*context*/) - { - me->UpdateEntry(NPC_REANIMATED_FANATIC); - DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH); - DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); - DoCastSelf(SPELL_FULL_HEAL, true); - me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); - }) - .Schedule(Seconds(6), [this](TaskContext /*context*/) - { - me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); - me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); - me->SetReactState(REACT_AGGRESSIVE); - DoZoneInCombat(me); - - if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_LADY_DEATHWHISPER))) - ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD); - }); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) - return; - - _scheduler.Update(diff, [this] - { - DoMeleeAttackIfReady(); - }); - } - - protected: - TaskScheduler _scheduler; - InstanceScript* _instance; - }; + me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); + me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(me); - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_cult_fanaticAI>(creature); + if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_LADY_DEATHWHISPER))) + ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD); + }); + break; + default: + break; } -}; + } -class npc_cult_adherent : public CreatureScript -{ - public: - npc_cult_adherent() : CreatureScript("npc_cult_adherent") { } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) + return; - struct npc_cult_adherentAI : public ScriptedAI + _scheduler.Update(diff, [this] { - npc_cult_adherentAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void Reset() override - { - _scheduler.CancelAll(); - _scheduler - .SetValidator([this] - { - return !me->HasUnitState(UNIT_STATE_CASTING); - }) - .Schedule(Seconds(5), [this](TaskContext deathchill) - { - if (me->GetEntry() == NPC_EMPOWERED_ADHERENT) - DoCastVictim(SPELL_DEATHCHILL_BLAST); - else - DoCastVictim(SPELL_DEATHCHILL_BOLT); - deathchill.Repeat(Milliseconds(2500)); - }) - .Schedule(Seconds(15), [this](TaskContext shroud_of_the_occult) - { - DoCastSelf(SPELL_SHROUD_OF_THE_OCCULT); - shroud_of_the_occult.Repeat(Seconds(10)); - }) - .Schedule(Seconds(15), [this](TaskContext curse_of_torpor) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) - DoCast(target, SPELL_CURSE_OF_TORPOR); - curse_of_torpor.Repeat(Seconds(18)); - }); - } + DoMeleeAttackIfReady(); + }); + } - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override - { - switch (spellInfo->Id) - { - case SPELL_DARK_EMPOWERMENT_T: - me->UpdateEntry(NPC_EMPOWERED_ADHERENT); - break; - case SPELL_DARK_MARTYRDOM_T: - me->SetReactState(REACT_PASSIVE); - me->InterruptNonMeleeSpells(true); - me->AttackStop(); - DoCastSelf(SPELL_DARK_MARTYRDOM_ADHERENT); - break; - case SPELL_DARK_MARTYRDOM_ADHERENT: - case SPELL_DARK_MARTYRDOM_ADHERENT_25N: - case SPELL_DARK_MARTYRDOM_ADHERENT_10H: - case SPELL_DARK_MARTYRDOM_ADHERENT_25H: - _scheduler - .Schedule(Seconds(2), [this](TaskContext /*context*/) - { - me->UpdateEntry(NPC_REANIMATED_ADHERENT); - DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH); - DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); - DoCastSelf(SPELL_FULL_HEAL, true); - me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); - }) - .Schedule(Seconds(6), [this](TaskContext /*context*/) - { - me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); - me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); - me->SetReactState(REACT_AGGRESSIVE); - DoCastSelf(SPELL_SHROUD_OF_THE_OCCULT); - DoZoneInCombat(me); - - if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_LADY_DEATHWHISPER))) - ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD); - }); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) - return; - - _scheduler.Update(diff); - } - - protected: - TaskScheduler _scheduler; - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_cult_adherentAI>(creature); - } +protected: + TaskScheduler _scheduler; + InstanceScript* _instance; }; -class npc_vengeful_shade : public CreatureScript +struct npc_cult_adherent : public ScriptedAI { - public: - npc_vengeful_shade() : CreatureScript("npc_vengeful_shade") { } - - struct npc_vengeful_shadeAI : public ScriptedAI + npc_cult_adherent(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void Reset() override + { + _scheduler.CancelAll(); + _scheduler + .SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }) + .Schedule(Seconds(5), [this](TaskContext deathchill) + { + if (me->GetEntry() == NPC_EMPOWERED_ADHERENT) + DoCastVictim(SPELL_DEATHCHILL_BLAST); + else + DoCastVictim(SPELL_DEATHCHILL_BOLT); + deathchill.Repeat(Milliseconds(2500)); + }) + .Schedule(Seconds(15), [this](TaskContext shroud_of_the_occult) + { + DoCastSelf(SPELL_SHROUD_OF_THE_OCCULT); + shroud_of_the_occult.Repeat(Seconds(10)); + }) + .Schedule(Seconds(15), [this](TaskContext curse_of_torpor) + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) + DoCast(target, SPELL_CURSE_OF_TORPOR); + curse_of_torpor.Repeat(Seconds(18)); + }); + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) { - npc_vengeful_shadeAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { + case SPELL_DARK_EMPOWERMENT_T: + me->UpdateEntry(NPC_EMPOWERED_ADHERENT); + break; + case SPELL_DARK_MARTYRDOM_T: me->SetReactState(REACT_PASSIVE); - me->AddAura(SPELL_VENGEFUL_BLAST_PASSIVE, me); - + me->InterruptNonMeleeSpells(true); + me->AttackStop(); + DoCastSelf(SPELL_DARK_MARTYRDOM_ADHERENT); + break; + case SPELL_DARK_MARTYRDOM_ADHERENT: + case SPELL_DARK_MARTYRDOM_ADHERENT_25N: + case SPELL_DARK_MARTYRDOM_ADHERENT_10H: + case SPELL_DARK_MARTYRDOM_ADHERENT_25H: _scheduler .Schedule(Seconds(2), [this](TaskContext /*context*/) { - me->SetReactState(REACT_AGGRESSIVE); - me->AI()->AttackStart(ObjectAccessor::GetUnit(*me, _targetGUID)); - }) - .Schedule(Seconds(7), [this](TaskContext /*context*/) + me->UpdateEntry(NPC_REANIMATED_ADHERENT); + DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS); + DoCastSelf(SPELL_FULL_HEAL, true); + me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); + }) + .Schedule(Seconds(6), [this](TaskContext /*context*/) { - me->KillSelf(); - }); - } - - void SetGUID(ObjectGuid const& guid, int32 /*id*/) override - { - _targetGUID = guid; - } + me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); + me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE)); + me->SetReactState(REACT_AGGRESSIVE); + DoCastSelf(SPELL_SHROUD_OF_THE_OCCULT); + DoZoneInCombat(me); - void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override - { - switch (spellInfo->Id) - { - case SPELL_VENGEFUL_BLAST: - case SPELL_VENGEFUL_BLAST_25N: - case SPELL_VENGEFUL_BLAST_10H: - case SPELL_VENGEFUL_BLAST_25H: - me->KillSelf(); - break; - default: - break; - } - } + if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_LADY_DEATHWHISPER))) + ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD); + }); + break; + default: + break; + } + } - void UpdateAI(uint32 diff) override - { - _scheduler.Update(diff, [this] - { - DoMeleeAttackIfReady(); - }); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) + return; - private: - TaskScheduler _scheduler; - ObjectGuid _targetGUID; - }; + _scheduler.Update(diff); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_vengeful_shadeAI>(creature); - } +protected: + TaskScheduler _scheduler; + InstanceScript* _instance; }; -class npc_darnavan : public CreatureScript +struct npc_vengeful_shade : public ScriptedAI { - public: - npc_darnavan() : CreatureScript("npc_darnavan") { } + npc_vengeful_shade(Creature* creature) : ScriptedAI(creature) { } - struct npc_darnavanAI : public ScriptedAI - { - npc_darnavanAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - } + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + me->AddAura(SPELL_VENGEFUL_BLAST_PASSIVE, me); - void Initialize() + _scheduler + .Schedule(Seconds(2), [this](TaskContext /*context*/) { - _canCharge = true; - _canShatter = true; - } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 10s); - _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, 20s, 25s); - _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, 25s, 30s); - _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, 5s, 8s); - Initialize(); - } - - void JustDied(Unit* killer) override + me->SetReactState(REACT_AGGRESSIVE); + me->AI()->AttackStart(ObjectAccessor::GetUnit(*me, _targetGUID)); + }) + .Schedule(Seconds(7), [this](TaskContext /*context*/) { - _events.Reset(); + me->KillSelf(); + }); + } + + void SetGUID(ObjectGuid const& guid, int32 /*id*/) override + { + _targetGUID = guid; + } + + void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) + { + case SPELL_VENGEFUL_BLAST: + case SPELL_VENGEFUL_BLAST_25N: + case SPELL_VENGEFUL_BLAST_10H: + case SPELL_VENGEFUL_BLAST_25H: + me->KillSelf(); + break; + default: + break; + } + } - if (!killer) - return; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } - if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - if (Group* group = owner->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) - if (Player* member = itr->GetSource()) - if (member->IsInMap(owner)) - member->FailQuest(QUEST_DEPROGRAMMING); - } - else - owner->FailQuest(QUEST_DEPROGRAMMING); - } - } +private: + TaskScheduler _scheduler; + ObjectGuid _targetGUID; +}; - void MovementInform(uint32 type, uint32 id) override +struct npc_darnavan : public ScriptedAI +{ + npc_darnavan(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + } + + void Initialize() + { + _canCharge = true; + _canShatter = true; + } + + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 10s); + _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, 20s, 25s); + _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, 25s, 30s); + _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, 5s, 8s); + Initialize(); + } + + void JustDied(Unit* killer) override + { + _events.Reset(); + + if (!killer) + return; + + if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + if (Group* group = owner->GetGroup()) { - if (type != POINT_MOTION_TYPE || id != POINT_DESPAWN) - return; - - me->DespawnOrUnsummon(); + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + if (Player* member = itr->GetSource()) + if (member->IsInMap(owner)) + member->FailQuest(QUEST_DEPROGRAMMING); } + else + owner->FailQuest(QUEST_DEPROGRAMMING); + } + } - void JustEngagedWith(Unit* /*victim*/) override - { - Talk(SAY_DARNAVAN_AGGRO); - } + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE || id != POINT_DESPAWN) + return; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + me->DespawnOrUnsummon(); + } - _events.Update(diff); + void JustEngagedWith(Unit* /*victim*/) override + { + Talk(SAY_DARNAVAN_AGGRO); + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (_canShatter && me->GetVictim() && me->EnsureVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL)) - { - DoCastVictim(SPELL_SHATTERING_THROW); - _canShatter = false; - _events.ScheduleEvent(EVENT_DARNAVAN_SHATTERING_THROW, 30s); - return; - } + _events.Update(diff); - if (_canCharge && !me->IsWithinMeleeRange(me->GetVictim())) - { - DoCastVictim(SPELL_CHARGE); - _canCharge = false; - _events.ScheduleEvent(EVENT_DARNAVAN_CHARGE, 20s); - return; - } - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_DARNAVAN_BLADESTORM: - DoCast(SPELL_BLADESTORM); - _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 90s, 100s); - break; - case EVENT_DARNAVAN_CHARGE: - _canCharge = true; - break; - case EVENT_DARNAVAN_INTIMIDATING_SHOUT: - DoCast(SPELL_INTIMIDATING_SHOUT); - _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, Seconds(90), Minutes(2)); - break; - case EVENT_DARNAVAN_MORTAL_STRIKE: - DoCastVictim(SPELL_MORTAL_STRIKE); - _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, 15s, 30s); - break; - case EVENT_DARNAVAN_SHATTERING_THROW: - _canShatter = true; - break; - case EVENT_DARNAVAN_SUNDER_ARMOR: - DoCastVictim(SPELL_SUNDER_ARMOR); - _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, 3s, 7s); - break; - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - DoMeleeAttackIfReady(); - } + if (_canShatter && me->GetVictim() && me->EnsureVictim()->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL)) + { + DoCastVictim(SPELL_SHATTERING_THROW); + _canShatter = false; + _events.ScheduleEvent(EVENT_DARNAVAN_SHATTERING_THROW, 30s); + return; + } - private: - EventMap _events; - bool _canCharge; - bool _canShatter; - }; + if (_canCharge && !me->IsWithinMeleeRange(me->GetVictim())) + { + DoCastVictim(SPELL_CHARGE); + _canCharge = false; + _events.ScheduleEvent(EVENT_DARNAVAN_CHARGE, 20s); + return; + } - CreatureAI* GetAI(Creature* creature) const override + while (uint32 eventId = _events.ExecuteEvent()) { - return GetIcecrownCitadelAI<npc_darnavanAI>(creature); + switch (eventId) + { + case EVENT_DARNAVAN_BLADESTORM: + DoCast(SPELL_BLADESTORM); + _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 90s, 100s); + break; + case EVENT_DARNAVAN_CHARGE: + _canCharge = true; + break; + case EVENT_DARNAVAN_INTIMIDATING_SHOUT: + DoCast(SPELL_INTIMIDATING_SHOUT); + _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, Seconds(90), Minutes(2)); + break; + case EVENT_DARNAVAN_MORTAL_STRIKE: + DoCastVictim(SPELL_MORTAL_STRIKE); + _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, 15s, 30s); + break; + case EVENT_DARNAVAN_SHATTERING_THROW: + _canShatter = true; + break; + case EVENT_DARNAVAN_SUNDER_ARMOR: + DoCastVictim(SPELL_SUNDER_ARMOR); + _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, 3s, 7s); + break; + } } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; + bool _canCharge; + bool _canShatter; }; -class spell_deathwhisper_mana_barrier : public SpellScriptLoader +class spell_deathwhisper_mana_barrier : public AuraScript { - public: - spell_deathwhisper_mana_barrier() : SpellScriptLoader("spell_deathwhisper_mana_barrier") { } + PrepareAuraScript(spell_deathwhisper_mana_barrier); - class spell_deathwhisper_mana_barrier_AuraScript : public AuraScript + void HandlePeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) { - PrepareAuraScript(spell_deathwhisper_mana_barrier_AuraScript); + int32 missingHealth = int32(caster->GetMaxHealth() - caster->GetHealth()); + caster->ModifyHealth(missingHealth); + caster->ModifyPower(POWER_MANA, -missingHealth); + } + } - void HandlePeriodicTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - { - int32 missingHealth = int32(caster->GetMaxHealth() - caster->GetHealth()); - caster->ModifyHealth(missingHealth); - caster->ModifyPower(POWER_MANA, -missingHealth); - } - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathwhisper_mana_barrier::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } +}; - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathwhisper_mana_barrier_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; +class spell_deathwhisper_dominated_mind : public AuraScript +{ + PrepareAuraScript(spell_deathwhisper_dominated_mind); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_DOMINATE_MIND_SCALE }); + } + + void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_DOMINATE_MIND_SCALE, true); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_deathwhisper_dominated_mind::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); + } +}; - AuraScript* GetAuraScript() const override - { - return new spell_deathwhisper_mana_barrier_AuraScript(); - } +class spell_deathwhisper_summon_spirits : public SpellScript +{ + PrepareSpellScript(spell_deathwhisper_summon_spirits); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_SHADE }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_SHADE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_deathwhisper_summon_spirits::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } }; class at_lady_deathwhisper_entrance : public OnlyOnceAreaTriggerScript @@ -1042,78 +1017,20 @@ class at_lady_deathwhisper_entrance : public OnlyOnceAreaTriggerScript } }; -class spell_deathwhisper_dominated_mind : public SpellScriptLoader -{ - public: - spell_deathwhisper_dominated_mind() : SpellScriptLoader("spell_deathwhisper_dominated_mind") { } - - class spell_deathwhisper_dominated_mind_AuraScript : public AuraScript - { - PrepareAuraScript(spell_deathwhisper_dominated_mind_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_DOMINATE_MIND_SCALE }); - } - - void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - target->CastSpell(target, SPELL_DOMINATE_MIND_SCALE, true); - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_deathwhisper_dominated_mind_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_deathwhisper_dominated_mind_AuraScript(); - } -}; - -class spell_deathwhisper_summon_spirits : public SpellScriptLoader -{ - public: - spell_deathwhisper_summon_spirits() : SpellScriptLoader("spell_deathwhisper_summon_spirits") { } - - class spell_deathwhisper_summon_spirits_SpellScript : public SpellScript - { - PrepareSpellScript(spell_deathwhisper_summon_spirits_SpellScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_SUMMON_SHADE }); - } - - void HandleScriptEffect(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_SHADE, true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_deathwhisper_summon_spirits_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_deathwhisper_summon_spirits_SpellScript(); - } -}; - void AddSC_boss_lady_deathwhisper() { - new boss_lady_deathwhisper(); - new npc_cult_fanatic(); - new npc_cult_adherent(); - new npc_vengeful_shade(); - new npc_darnavan(); - new spell_deathwhisper_mana_barrier(); - new spell_deathwhisper_dominated_mind(); - new spell_deathwhisper_summon_spirits(); + // Creatures + RegisterIcecrownCitadelCreatureAI(boss_lady_deathwhisper); + RegisterIcecrownCitadelCreatureAI(npc_cult_fanatic); + RegisterIcecrownCitadelCreatureAI(npc_cult_adherent); + RegisterIcecrownCitadelCreatureAI(npc_vengeful_shade); + RegisterIcecrownCitadelCreatureAI(npc_darnavan); + + // Spells + RegisterSpellScript(spell_deathwhisper_mana_barrier); + RegisterSpellScript(spell_deathwhisper_dominated_mind); + RegisterSpellScript(spell_deathwhisper_summon_spirits); + + // AreaTriggers new at_lady_deathwhisper_entrance(); } |