aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorForesterDev <11771800+ForesterDev@users.noreply.github.com>2020-09-04 18:58:57 +0400
committerShauren <shauren.trinity@gmail.com>2022-02-05 10:55:59 +0100
commit1c22cd7d089eeeab93be4ee013bcd8739528433f (patch)
treea8a778d15152966390c7e95ca058c05252564dc0
parente294f94617cd569054b6452c015dd93442311705 (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.cpp1527
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();
}