diff options
author | Gustavo <sirikfoll@hotmail.com> | 2016-10-14 16:44:49 -0300 |
---|---|---|
committer | SnapperRy <snapperryen@gmail.com> | 2016-10-14 21:44:49 +0200 |
commit | 8e82d8a9e79ba95fbd780fa093416ebe7431a1c0 (patch) | |
tree | f84d58a69ae53937ea6260714aa989f5c1c6d9a1 /src | |
parent | 1824347594f3a53fd50c9e7da0d546becd69db0d (diff) |
Core/Scripts Boss Lady DeathWhisper improvements (#17389)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp | 818 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_generic.cpp | 8 |
2 files changed, 430 insertions, 396 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 5f884ccee9e..85126b35cdb 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -56,21 +56,26 @@ enum Spells SPELL_MANA_BARRIER = 70842, SPELL_SHADOW_BOLT = 71254, SPELL_DEATH_AND_DECAY = 71001, - SPELL_DOMINATE_MIND_H = 71289, + SPELL_DOMINATE_MIND = 71289, + SPELL_DOMINATE_MIND_SCALE = 71290, SPELL_FROSTBOLT = 71420, SPELL_FROSTBOLT_VOLLEY = 72905, SPELL_TOUCH_OF_INSIGNIFICANCE = 71204, SPELL_SUMMON_SHADE = 71363, - SPELL_SHADOW_CHANNELING = 43897, // Prefight, during intro + SPELL_SHADOW_CHANNELING = 43897, SPELL_DARK_TRANSFORMATION_T = 70895, SPELL_DARK_EMPOWERMENT_T = 70896, SPELL_DARK_MARTYRDOM_T = 70897, + SPELL_SUMMON_SPIRITS = 72478, // Achievement SPELL_FULL_HOUSE = 72827, // does not exist in dbc but still can be used for criteria check // Both Adds SPELL_TELEPORT_VISUAL = 41236, + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_FULL_HEAL = 17683, + SPELL_PERMANENT_FEIGN_DEATH = 70628, // Fanatics SPELL_DARK_TRANSFORMATION = 70900, @@ -86,7 +91,7 @@ enum Spells SPELL_DEATHCHILL_BOLT = 70594, SPELL_DEATHCHILL_BLAST = 70906, SPELL_CURSE_OF_TORPOR = 71237, - SPELL_SHORUD_OF_THE_OCCULT = 70768, + SPELL_SHROUD_OF_THE_OCCULT = 70768, SPELL_ADHERENT_S_DETERMINATION = 71234, SPELL_DARK_MARTYRDOM_ADHERENT = 70903, @@ -108,44 +113,6 @@ enum Spells enum EventTypes { - // Lady Deathwhisper - EVENT_INTRO_2 = 1, - EVENT_INTRO_3 = 2, - EVENT_INTRO_4 = 3, - EVENT_INTRO_5 = 4, - EVENT_INTRO_6 = 5, - EVENT_INTRO_7 = 6, - EVENT_BERSERK = 7, - EVENT_DEATH_AND_DECAY = 8, - EVENT_DOMINATE_MIND_H = 9, - - // Phase 1 only - EVENT_P1_SUMMON_WAVE = 10, - EVENT_P1_SHADOW_BOLT = 11, - EVENT_P1_EMPOWER_CULTIST = 12, - EVENT_P1_REANIMATE_CULTIST = 13, - - // Phase 2 only - EVENT_P2_SUMMON_WAVE = 14, - EVENT_P2_FROSTBOLT = 15, - EVENT_P2_FROSTBOLT_VOLLEY = 16, - EVENT_P2_TOUCH_OF_INSIGNIFICANCE = 17, - EVENT_P2_SUMMON_SHADE = 18, - - // Shared adds events - EVENT_CULTIST_DARK_MARTYRDOM = 19, - - // Cult Fanatic - EVENT_FANATIC_NECROTIC_STRIKE = 20, - EVENT_FANATIC_SHADOW_CLEAVE = 21, - EVENT_FANATIC_VAMPIRIC_MIGHT = 22, - - // Cult Adherent - EVENT_ADHERENT_FROST_FEVER = 23, - EVENT_ADHERENT_DEATHCHILL = 24, - EVENT_ADHERENT_CURSE_OF_TORPOR = 25, - EVENT_ADHERENT_SHORUD_OF_THE_OCCULT = 26, - // Darnavan EVENT_DARNAVAN_BLADESTORM = 27, EVENT_DARNAVAN_CHARGE = 28, @@ -163,6 +130,13 @@ enum Phases PHASE_TWO = 3 }; +enum Groups +{ + GROUP_INTRO = 0, + GROUP_ONE = 1, + GROUP_TWO = 2 +}; + enum DeprogrammingData { NPC_DARNAVAN_10 = 38472, @@ -185,8 +159,6 @@ enum Actions uint32 const SummonEntries[2] = {NPC_CULT_FANATIC, NPC_CULT_ADHERENT}; -#define GUID_CULTIST 1 - Position const SummonPositions[7] = { {-578.7066f, 2154.167f, 51.01529f, 1.692969f}, // 1 Left Door 1 (Cult Fanatic) @@ -229,43 +201,67 @@ class boss_lady_deathwhisper : public CreatureScript void Initialize() { _waveCounter = 0; - _nextVengefulShadeTargetGUID.Clear(); + _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(); - me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)); - events.SetPhase(PHASE_ONE); Initialize(); - DoCast(me, SPELL_SHADOW_CHANNELING); - me->RemoveAurasDueToSpell(SPELL_BERSERK); - me->RemoveAurasDueToSpell(SPELL_MANA_BARRIER); + _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 { - switch (action) + if (action != ACTION_START_INTRO) + return; + + if (!_introDone) { - case ACTION_START_INTRO: - if (!_introDone) + _introDone = true; + Talk(SAY_INTRO_1); + _phase = PHASE_INTRO; + scheduler.Schedule(Seconds(10), GROUP_INTRO, [this](TaskContext context) + { + switch (context.GetRepeatCounter()) { - _introDone = true; - Talk(SAY_INTRO_1); - events.SetPhase(PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_2, 11000, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_3, 21000, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_4, 31500, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_5, 39500, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_6, 48500, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_7, 58000, 0, PHASE_INTRO); + 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; } - break; - default: - break; + }); } } @@ -274,7 +270,7 @@ class boss_lady_deathwhisper : public CreatureScript if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; - if (victim && me->Attack(victim, true) && !events.IsInPhase(PHASE_ONE)) + if (victim && me->Attack(victim, true) && _phase != PHASE_ONE) me->GetMotionMaster()->MoveChase(victim); } @@ -282,31 +278,61 @@ class boss_lady_deathwhisper : public CreatureScript { if (!instance->CheckRequiredBosses(DATA_LADY_DEATHWHISPER, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } + me->SetCombatPulseDelay(5); me->setActive(true); DoZoneInCombat(); - - events.Reset(); - events.SetPhase(PHASE_ONE); + _phase = PHASE_ONE; + scheduler.CancelGroup(GROUP_INTRO); // phase-independent events - events.ScheduleEvent(EVENT_BERSERK, 600000); - events.ScheduleEvent(EVENT_DEATH_AND_DECAY, 10000); + 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(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_DEATH_AND_DECAY); + death_and_decay.Repeat(Seconds(22), Seconds(30)); + }); + if (GetDifficulty() != RAID_DIFFICULTY_10MAN_NORMAL) + scheduler.Schedule(Seconds(27), [this](TaskContext dominate_mind) + { + Talk(SAY_DOMINATE_MIND); + for (uint8 i = 0; i < _dominateMindCount; i++) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_DOMINATE_MIND)) + DoCast(target, SPELL_DOMINATE_MIND); + dominate_mind.Repeat(Seconds(40), Seconds(45)); + }); // phase one only - events.ScheduleEvent(EVENT_P1_SUMMON_WAVE, 5000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_P1_SHADOW_BOLT, urand(5500, 6000), 0, PHASE_ONE); - events.ScheduleEvent(EVENT_P1_EMPOWER_CULTIST, urand(20000, 30000), 0, PHASE_ONE); - if (GetDifficulty() != RAID_DIFFICULTY_10MAN_NORMAL) - events.ScheduleEvent(EVENT_DOMINATE_MIND_H, 27000); + 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(SELECT_TARGET_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); - DoCast(me, SPELL_MANA_BARRIER, true); - + DoCastSelf(SPELL_MANA_BARRIER, true); instance->SetBossState(DATA_LADY_DEATHWHISPER, IN_PROGRESS); } @@ -338,7 +364,7 @@ class boss_lady_deathwhisper : public CreatureScript { if (Group* group = owner->GetGroup()) { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) if (Player* member = itr->GetSource()) member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT); } @@ -351,17 +377,14 @@ class boss_lady_deathwhisper : public CreatureScript _JustDied(); } - void JustReachedHome() override + void EnterEvadeMode(EvadeReason /*why*/) override { - _JustReachedHome(); - instance->SetBossState(DATA_LADY_DEATHWHISPER, FAIL); - + scheduler.CancelAll(); summons.DespawnAll(); if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) - { darnavan->DespawnOrUnsummon(); - _darnavanGUID.Clear(); - } + + _DespawnAtEvade(); } void KilledUnit(Unit* victim) override @@ -373,151 +396,98 @@ class boss_lady_deathwhisper : public CreatureScript void DamageTaken(Unit* /*damageDealer*/, uint32& damage) override { // phase transition - if (events.IsInPhase(PHASE_ONE) && damage > me->GetPower(POWER_MANA)) + if (_phase == PHASE_ONE && damage > me->GetPower(POWER_MANA)) { + _phase = PHASE_TWO; Talk(SAY_PHASE_2); Talk(EMOTE_PHASE_2); DoStartMovement(me->GetVictim()); + DoResetThreat(); damage -= me->GetPower(POWER_MANA); me->SetPower(POWER_MANA, 0); me->RemoveAurasDueToSpell(SPELL_MANA_BARRIER); - events.SetPhase(PHASE_TWO); - events.ScheduleEvent(EVENT_P2_FROSTBOLT, urand(10000, 12000), 0, PHASE_TWO); - events.ScheduleEvent(EVENT_P2_FROSTBOLT_VOLLEY, urand(19000, 21000), 0, PHASE_TWO); - events.ScheduleEvent(EVENT_P2_TOUCH_OF_INSIGNIFICANCE, urand(6000, 9000), 0, PHASE_TWO); - events.ScheduleEvent(EVENT_P2_SUMMON_SHADE, urand(12000, 15000), 0, PHASE_TWO); + 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) + { + me->CastCustomSpell(SPELL_SUMMON_SPIRITS, SPELLVALUE_MAX_TARGETS, Is25ManRaid() ? 2 : 1); + summonShade.Repeat(); + }); + // on heroic mode Lady Deathwhisper is immune to taunt effects in phase 2 and continues summoning adds if (IsHeroic()) { me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); - events.ScheduleEvent(EVENT_P2_SUMMON_WAVE, 45000, 0, PHASE_TWO); + scheduler.Schedule(Seconds(), GROUP_TWO, [this](TaskContext context) + { + SummonWaveP2(); + context.Repeat(Seconds(45)); + }); } } } - void JustSummoned(Creature* summon) override + void SpellHitTarget(Unit* target, const SpellInfo* spell) override { - if (summon->GetEntry() == NPC_DARNAVAN) - _darnavanGUID = summon->GetGUID(); - else - summons.Summon(summon); + if (spell->Id == SPELL_SUMMON_SPIRITS) + _nextVengefulShadeTargetGUID.push_back(target->GetGUID()); + } - Unit* target = NULL; - if (summon->GetEntry() == NPC_VENGEFUL_SHADE) + void JustSummoned(Creature* summon) override + { + switch (summon->GetEntry()) { - target = ObjectAccessor::GetUnit(*me, _nextVengefulShadeTargetGUID); // Vengeful Shade - _nextVengefulShadeTargetGUID.Clear(); + case NPC_DARNAVAN_10: + case NPC_DARNAVAN_25: + _darnavanGUID = summon->GetGUID(); + summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_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(SELECT_TARGET_RANDOM)); + break; + default: + break; } - else - target = SelectTarget(SELECT_TARGET_RANDOM); // Wave adds - - summon->AI()->AttackStart(target); // CAN be NULL - if (summon->GetEntry() == NPC_REANIMATED_FANATIC) - summon->CastSpell(summon, SPELL_FANATIC_S_DETERMINATION, true); - else if (summon->GetEntry() == NPC_REANIMATED_ADHERENT) - summon->CastSpell(summon, SPELL_ADHERENT_S_DETERMINATION, true); + summons.Summon(summon); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) + if (!UpdateVictim() && _phase != PHASE_INTRO) return; - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING) && !events.IsInPhase(PHASE_INTRO)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + scheduler.Update(diff, [this] { - switch (eventId) - { - case EVENT_INTRO_2: - Talk(SAY_INTRO_2); - break; - case EVENT_INTRO_3: - Talk(SAY_INTRO_3); - break; - case EVENT_INTRO_4: - Talk(SAY_INTRO_4); - break; - case EVENT_INTRO_5: - Talk(SAY_INTRO_5); - break; - case EVENT_INTRO_6: - Talk(SAY_INTRO_6); - break; - case EVENT_INTRO_7: - Talk(SAY_INTRO_7); - break; - case EVENT_DEATH_AND_DECAY: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_DEATH_AND_DECAY); - events.ScheduleEvent(EVENT_DEATH_AND_DECAY, urand(22000, 30000)); - break; - case EVENT_DOMINATE_MIND_H: - Talk(SAY_DOMINATE_MIND); - for (uint8 i = 0; i < _dominateMindCount; i++) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_DOMINATE_MIND_H)) - DoCast(target, SPELL_DOMINATE_MIND_H); - events.ScheduleEvent(EVENT_DOMINATE_MIND_H, urand(40000, 45000)); - break; - case EVENT_P1_SUMMON_WAVE: - SummonWaveP1(); - events.ScheduleEvent(EVENT_P1_SUMMON_WAVE, IsHeroic() ? 45000 : 60000, 0, PHASE_ONE); - break; - case EVENT_P1_SHADOW_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_P1_SHADOW_BOLT, urand(5000, 8000), 0, PHASE_ONE); - break; - case EVENT_P1_REANIMATE_CULTIST: - ReanimateCultist(); - break; - case EVENT_P1_EMPOWER_CULTIST: - EmpowerCultist(); - events.ScheduleEvent(EVENT_P1_EMPOWER_CULTIST, urand(18000, 25000)); - break; - case EVENT_P2_FROSTBOLT: - DoCastVictim(SPELL_FROSTBOLT); - events.ScheduleEvent(EVENT_P2_FROSTBOLT, urand(10000, 11000), 0, PHASE_TWO); - break; - case EVENT_P2_FROSTBOLT_VOLLEY: - DoCastAOE(SPELL_FROSTBOLT_VOLLEY); - events.ScheduleEvent(EVENT_P2_FROSTBOLT_VOLLEY, urand(13000, 15000), 0, PHASE_TWO); - break; - case EVENT_P2_TOUCH_OF_INSIGNIFICANCE: - DoCastVictim(SPELL_TOUCH_OF_INSIGNIFICANCE); - events.ScheduleEvent(EVENT_P2_TOUCH_OF_INSIGNIFICANCE, urand(9000, 13000), 0, PHASE_TWO); - break; - case EVENT_P2_SUMMON_SHADE: - if (Unit* shadeTarget = SelectTarget(SELECT_TARGET_RANDOM, 1)) - { - _nextVengefulShadeTargetGUID = shadeTarget->GetGUID(); - DoCast(shadeTarget, SPELL_SUMMON_SHADE); - } - events.ScheduleEvent(EVENT_P2_SUMMON_SHADE, urand(18000, 23000), 0, PHASE_TWO); - break; - case EVENT_P2_SUMMON_WAVE: - SummonWaveP2(); - events.ScheduleEvent(EVENT_P2_SUMMON_WAVE, 45000, 0, PHASE_TWO); - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - Talk(SAY_BERSERK); - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING) && !events.IsInPhase(PHASE_INTRO)) - return; - } - - // We should not melee attack when barrier is up - if (me->HasAura(SPELL_MANA_BARRIER)) - return; - - DoMeleeAttackIfReady(); + // We should not melee attack when barrier is up + if (!me->HasAura(SPELL_MANA_BARRIER)) + DoMeleeAttackIfReady(); + }); } // summoning function for first phase @@ -568,72 +538,40 @@ class boss_lady_deathwhisper : public CreatureScript summon->CastSpell(summon, SPELL_TELEPORT_VISUAL); } - void SetGUID(ObjectGuid guid, int32 id/* = 0*/) override + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override { - if (id != GUID_CULTIST) - return; - - _reanimationQueue.push_back(guid); - events.ScheduleEvent(EVENT_P1_REANIMATE_CULTIST, 3000, 0, PHASE_ONE); + if (summon->GetEntry() == NPC_CULT_ADHERENT || summon->GetEntry() == NPC_CULT_FANATIC) + _cultistQueue.remove(summon->GetGUID()); } - void ReanimateCultist() + void DoImproveCultist() { - if (_reanimationQueue.empty()) + if (_cultistQueue.empty()) return; - ObjectGuid cultistGUID = _reanimationQueue.front(); - Creature* cultist = ObjectAccessor::GetCreature(*me, cultistGUID); - _reanimationQueue.pop_front(); + _cultistGUID = Trinity::Containers::SelectRandomContainerElement(_cultistQueue); + _cultistQueue.remove(_cultistGUID); + Creature* cultist = ObjectAccessor::GetCreature(*me, _cultistGUID); if (!cultist) return; - Talk(SAY_ANIMATE_DEAD); - DoCast(cultist, SPELL_DARK_MARTYRDOM_T); - } - - void SpellHitTarget(Unit* target, SpellInfo const* spell) override - { - if (spell->Id == SPELL_DARK_MARTYRDOM_T) + if (RAND(0,1)) + me->CastSpell(cultist, SPELL_DARK_MARTYRDOM_T); + else { - Position pos = target->GetPosition(); - if (target->GetEntry() == NPC_CULT_FANATIC) - me->SummonCreature(NPC_REANIMATED_FANATIC, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - else - me->SummonCreature(NPC_REANIMATED_ADHERENT, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - - if (TempSummon* summon = target->ToTempSummon()) - summon->UnSummon(); + 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)); } } - void EmpowerCultist() - { - if (summons.empty()) - return; - - std::list<Creature*> temp; - for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr) - if (Creature* cre = ObjectAccessor::GetCreature(*me, *itr)) - if (cre->IsAlive() && (cre->GetEntry() == NPC_CULT_FANATIC || cre->GetEntry() == NPC_CULT_ADHERENT)) - temp.push_back(cre); - - // noone to empower - if (temp.empty()) - return; - - // select random cultist - Creature* cultist = Trinity::Containers::SelectRandomContainerElement(temp); - DoCast(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 _nextVengefulShadeTargetGUID; ObjectGuid _darnavanGUID; - GuidDeque _reanimationQueue; + ObjectGuid _cultistGUID; + GuidList _cultistQueue; + GuidList _nextVengefulShadeTargetGUID; uint32 _waveCounter; uint8 const _dominateMindCount; + uint8 _phase; bool _introDone; }; @@ -643,8 +581,6 @@ class boss_lady_deathwhisper : public CreatureScript } }; -typedef boss_lady_deathwhisper::boss_lady_deathwhisperAI DeathwisperAI; - class npc_cult_fanatic : public CreatureScript { public: @@ -652,71 +588,91 @@ class npc_cult_fanatic : public CreatureScript struct npc_cult_fanaticAI : public ScriptedAI { - npc_cult_fanaticAI(Creature* creature) : ScriptedAI(creature) { } + npc_cult_fanaticAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } void Reset() override { - Events.Reset(); - Events.ScheduleEvent(EVENT_FANATIC_NECROTIC_STRIKE, urand(10000, 12000)); - Events.ScheduleEvent(EVENT_FANATIC_SHADOW_CLEAVE, urand(14000, 16000)); - Events.ScheduleEvent(EVENT_FANATIC_VAMPIRIC_MIGHT, urand(20000, 27000)); - if (me->GetEntry() == NPC_CULT_FANATIC) - Events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM, urand(18000, 32000)); + _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) + { + DoCastVictim(SPELL_NECROTIC_STRIKE); + necrotic_strike.Repeat(Seconds(17)); + }); } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - if (spell->Id == SPELL_DARK_TRANSFORMATION) - me->UpdateEntry(NPC_DEFORMED_FANATIC); - else if (spell->Id == SPELL_DARK_TRANSFORMATION_T) + switch (spell->Id) { - Events.CancelEvent(EVENT_CULTIST_DARK_MARTYRDOM); - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_DARK_TRANSFORMATION); + 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: + _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->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE); + }) + .Schedule(Seconds(6), [this](TaskContext /*context*/) + { + me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); + me->RemoveFlag(UNIT_FIELD_FLAGS, 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()) - return; - - Events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) + if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) return; - while (uint32 eventId = Events.ExecuteEvent()) + _scheduler.Update(diff, [this] { - switch (eventId) - { - case EVENT_FANATIC_NECROTIC_STRIKE: - DoCastVictim(SPELL_NECROTIC_STRIKE); - Events.ScheduleEvent(EVENT_FANATIC_NECROTIC_STRIKE, urand(11000, 13000)); - break; - case EVENT_FANATIC_SHADOW_CLEAVE: - DoCastVictim(SPELL_SHADOW_CLEAVE); - Events.ScheduleEvent(EVENT_FANATIC_SHADOW_CLEAVE, urand(9500, 11000)); - break; - case EVENT_FANATIC_VAMPIRIC_MIGHT: - DoCast(me, SPELL_VAMPIRIC_MIGHT); - Events.ScheduleEvent(EVENT_FANATIC_VAMPIRIC_MIGHT, urand(20000, 27000)); - break; - case EVENT_CULTIST_DARK_MARTYRDOM: - DoCast(me, SPELL_DARK_MARTYRDOM_FANATIC); - Events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM, urand(16000, 21000)); - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } - - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + }); } protected: - EventMap Events; + TaskScheduler _scheduler; + InstanceScript* _instance; }; CreatureAI* GetAI(Creature* creature) const override @@ -732,80 +688,88 @@ class npc_cult_adherent : public CreatureScript struct npc_cult_adherentAI : public ScriptedAI { - npc_cult_adherentAI(Creature* creature) : ScriptedAI(creature) { } + npc_cult_adherentAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } void Reset() override { - Events.Reset(); - Events.ScheduleEvent(EVENT_ADHERENT_FROST_FEVER, urand(10000, 12000)); - Events.ScheduleEvent(EVENT_ADHERENT_DEATHCHILL, urand(14000, 16000)); - Events.ScheduleEvent(EVENT_ADHERENT_CURSE_OF_TORPOR, urand(14000, 16000)); - Events.ScheduleEvent(EVENT_ADHERENT_SHORUD_OF_THE_OCCULT, urand(32000, 39000)); - if (me->GetEntry() == NPC_CULT_ADHERENT) - Events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM, urand(18000, 32000)); + _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(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_CURSE_OF_TORPOR); + curse_of_torpor.Repeat(Seconds(18)); + }); } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - if (spell->Id == SPELL_DARK_EMPOWERMENT) - me->UpdateEntry(NPC_EMPOWERED_ADHERENT); - else if (spell->Id == SPELL_DARK_EMPOWERMENT_T) + switch (spell->Id) { - Events.CancelEvent(EVENT_CULTIST_DARK_MARTYRDOM); - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_DARK_EMPOWERMENT); + 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: + _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->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE); + }) + .Schedule(Seconds(6), [this](TaskContext /*context*/) + { + me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); + me->RemoveFlag(UNIT_FIELD_FLAGS, 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()) + if (!UpdateVictim() && !me->HasAura(SPELL_PERMANENT_FEIGN_DEATH)) return; - Events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = Events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_ADHERENT_FROST_FEVER: - DoCastVictim(SPELL_FROST_FEVER); - Events.ScheduleEvent(EVENT_ADHERENT_FROST_FEVER, urand(9000, 13000)); - break; - case EVENT_ADHERENT_DEATHCHILL: - if (me->GetEntry() == NPC_EMPOWERED_ADHERENT) - DoCastVictim(SPELL_DEATHCHILL_BLAST); - else - DoCastVictim(SPELL_DEATHCHILL_BOLT); - Events.ScheduleEvent(EVENT_ADHERENT_DEATHCHILL, urand(9000, 13000)); - break; - case EVENT_ADHERENT_CURSE_OF_TORPOR: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) - DoCast(target, SPELL_CURSE_OF_TORPOR); - Events.ScheduleEvent(EVENT_ADHERENT_CURSE_OF_TORPOR, urand(9000, 13000)); - break; - case EVENT_ADHERENT_SHORUD_OF_THE_OCCULT: - DoCast(me, SPELL_SHORUD_OF_THE_OCCULT); - Events.ScheduleEvent(EVENT_ADHERENT_SHORUD_OF_THE_OCCULT, urand(27000, 32000)); - break; - case EVENT_CULTIST_DARK_MARTYRDOM: - DoCast(me, SPELL_DARK_MARTYRDOM_ADHERENT); - Events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM, urand(16000, 21000)); - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } - - DoMeleeAttackIfReady(); + _scheduler.Update(diff); } protected: - EventMap Events; + TaskScheduler _scheduler; + InstanceScript* _instance; }; CreatureAI* GetAI(Creature* creature) const override @@ -821,15 +785,28 @@ class npc_vengeful_shade : public CreatureScript struct npc_vengeful_shadeAI : public ScriptedAI { - npc_vengeful_shadeAI(Creature* creature) : ScriptedAI(creature) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + npc_vengeful_shadeAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { + me->SetReactState(REACT_PASSIVE); me->AddAura(SPELL_VENGEFUL_BLAST_PASSIVE, me); + + _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->KillSelf(); + }); + } + + void SetGUID(ObjectGuid guid, int32 /*type*/) override + { + _targetGUID = guid; } void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override @@ -846,6 +823,18 @@ class npc_vengeful_shade : public CreatureScript break; } } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + + private: + TaskScheduler _scheduler; + ObjectGuid _targetGUID; }; CreatureAI* GetAI(Creature* creature) const override @@ -875,10 +864,10 @@ class npc_darnavan : public CreatureScript void Reset() override { _events.Reset(); - _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 10000); - _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, urand(20000, 25000)); - _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, urand(25000, 30000)); - _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, urand(5000, 8000)); + _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, Seconds(10)); + _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, Seconds(20), Seconds(25)); + _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, Seconds(25), Seconds(30)); + _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, Seconds(5), Seconds(8)); Initialize(); } @@ -889,7 +878,7 @@ class npc_darnavan : public CreatureScript { if (Group* group = owner->GetGroup()) { - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) if (Player* member = itr->GetSource()) member->FailQuest(QUEST_DEPROGRAMMING); } @@ -925,7 +914,7 @@ class npc_darnavan : public CreatureScript { DoCastVictim(SPELL_SHATTERING_THROW); _canShatter = false; - _events.ScheduleEvent(EVENT_DARNAVAN_SHATTERING_THROW, 30000); + _events.ScheduleEvent(EVENT_DARNAVAN_SHATTERING_THROW, Seconds(30)); return; } @@ -933,7 +922,7 @@ class npc_darnavan : public CreatureScript { DoCastVictim(SPELL_CHARGE); _canCharge = false; - _events.ScheduleEvent(EVENT_DARNAVAN_CHARGE, 20000); + _events.ScheduleEvent(EVENT_DARNAVAN_CHARGE, Seconds(20)); return; } @@ -943,25 +932,25 @@ class npc_darnavan : public CreatureScript { case EVENT_DARNAVAN_BLADESTORM: DoCast(SPELL_BLADESTORM); - _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, urand(90000, 100000)); + _events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, Seconds(90), Seconds(100)); break; case EVENT_DARNAVAN_CHARGE: _canCharge = true; break; case EVENT_DARNAVAN_INTIMIDATING_SHOUT: DoCast(SPELL_INTIMIDATING_SHOUT); - _events.ScheduleEvent(EVENT_DARNAVAN_INTIMIDATING_SHOUT, urand(90000, 120000)); + _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, urand(15000, 30000)); + _events.ScheduleEvent(EVENT_DARNAVAN_MORTAL_STRIKE, Seconds(15), Seconds(30)); break; case EVENT_DARNAVAN_SHATTERING_THROW: _canShatter = true; break; case EVENT_DARNAVAN_SUNDER_ARMOR: DoCastVictim(SPELL_SUNDER_ARMOR); - _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, urand(3000, 7000)); + _events.ScheduleEvent(EVENT_DARNAVAN_SUNDER_ARMOR, Seconds(3), Seconds(7)); break; } } @@ -1013,50 +1002,86 @@ class spell_deathwhisper_mana_barrier : public SpellScriptLoader } }; -class spell_cultist_dark_martyrdom : public SpellScriptLoader +class at_lady_deathwhisper_entrance : public AreaTriggerScript { public: - spell_cultist_dark_martyrdom() : SpellScriptLoader("spell_cultist_dark_martyrdom") { } + at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { } - class spell_cultist_dark_martyrdom_SpellScript : public SpellScript + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override { - PrepareSpellScript(spell_cultist_dark_martyrdom_SpellScript); + if (InstanceScript* instance = player->GetInstanceScript()) + if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE) + if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER))) + ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO); + + return true; + } +}; + +class spell_deathwhisper_dominated_mind : public SpellScriptLoader +{ + public: + spell_deathwhisper_dominated_mind() : SpellScriptLoader("spell_deathwhisper_dominated_mind") { } - void HandleEffect(SpellEffIndex /*effIndex*/) + class spell_deathwhisper_dominated_mind_AuraScript : public AuraScript + { + PrepareAuraScript(spell_deathwhisper_dominated_mind_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override { - if (GetCaster()->IsSummon()) - if (Unit* owner = GetCaster()->ToTempSummon()->GetSummoner()) - owner->GetAI()->SetGUID(GetCaster()->GetGUID(), GUID_CULTIST); + if (!sSpellMgr->GetSpellInfo(SPELL_DOMINATE_MIND_SCALE)) + return false; + return true; + } - GetCaster()->KillSelf(); - GetCaster()->SetDisplayId(uint32(GetCaster()->GetEntry() == NPC_CULT_FANATIC ? 38009 : 38010)); + void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_DOMINATE_MIND_SCALE, true); } void Register() override { - OnEffectHitTarget += SpellEffectFn(spell_cultist_dark_martyrdom_SpellScript::HandleEffect, EFFECT_2, SPELL_EFFECT_FORCE_DESELECT); + AfterEffectApply += AuraEffectApplyFn(spell_deathwhisper_dominated_mind_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); } }; - SpellScript* GetSpellScript() const override + AuraScript* GetAuraScript() const override { - return new spell_cultist_dark_martyrdom_SpellScript(); + return new spell_deathwhisper_dominated_mind_AuraScript(); } }; -class at_lady_deathwhisper_entrance : public AreaTriggerScript +class spell_deathwhisper_summon_spirits : public SpellScriptLoader { public: - at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { } + spell_deathwhisper_summon_spirits() : SpellScriptLoader("spell_deathwhisper_summon_spirits") { } - bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + class spell_deathwhisper_summon_spirits_SpellScript : public SpellScript { - if (InstanceScript* instance = player->GetInstanceScript()) - if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE) - if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_LADY_DEATHWHISPER))) - ladyDeathwhisper->AI()->DoAction(ACTION_START_INTRO); + PrepareSpellScript(spell_deathwhisper_summon_spirits_SpellScript); - return true; + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_SHADE)) + return false; + return true; + } + + 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(); } }; @@ -1068,6 +1093,7 @@ void AddSC_boss_lady_deathwhisper() new npc_vengeful_shade(); new npc_darnavan(); new spell_deathwhisper_mana_barrier(); - new spell_cultist_dark_martyrdom(); + new spell_deathwhisper_dominated_mind(); + new spell_deathwhisper_summon_spirits(); new at_lady_deathwhisper_entrance(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 794ef470d40..f1eaf45770e 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1100,9 +1100,17 @@ class spell_gen_creature_permanent_feign_death : public SpellScriptLoader target->ToCreature()->SetReactState(REACT_PASSIVE); } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + } + void Register() override { OnEffectApply += AuraEffectApplyFn(spell_gen_creature_permanent_feign_death_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_creature_permanent_feign_death_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; |