Core/ICC: Lady Deathwhisper (#1630)

-  Added missing overrides and changed NULL for nullptr.
-  Fix timers (this needs atention, it might be wrong)
-  No more Dark Martyrdom being casted in phase 2.
-  Added temporal immunities to certain spell mechanics to avoid interrupt Dark Martyrdom cast.
-  Added the correct auras to reanimated cultists (fanatic's/adherent's determination).
-  Avoid spam of Dark Martyrdom.
-  Lady Deathwhisper should be immune to taunt on heroic.
-  Don't do the intro in combat (this can happen if the server crash or restart and there's people in front of the boss, when they login again and they don't activate the areatrigger, so avoid this).
-  Indentation correction.
This commit is contained in:
Nefertumm
2019-04-06 00:35:03 -03:00
committed by GitHub
parent d2511fe34b
commit 08b01462fc
2 changed files with 497 additions and 494 deletions
@@ -0,0 +1,2 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1553547175438159300');
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_cultist_dark_martyrdom';
@@ -57,6 +57,9 @@ enum Spells
SPELL_SHADOW_CLEAVE = 70670, SPELL_SHADOW_CLEAVE = 70670,
SPELL_VAMPIRIC_MIGHT = 70674, SPELL_VAMPIRIC_MIGHT = 70674,
SPELL_DARK_MARTYRDOM_FANATIC = 71236, SPELL_DARK_MARTYRDOM_FANATIC = 71236,
SPELL_DARK_MARTYRDOM_FANATIC_25N = 72495,
SPELL_DARK_MARTYRDOM_FANATIC_10H = 72496,
SPELL_DARK_MARTYRDOM_FANATIC_25H = 72497,
SPELL_FANATIC_S_DETERMINATION = 71235, SPELL_FANATIC_S_DETERMINATION = 71235,
SPELL_DARK_TRANSFORMATION = 70900, SPELL_DARK_TRANSFORMATION = 70900,
@@ -67,6 +70,9 @@ enum Spells
SPELL_CURSE_OF_TORPOR = 71237, SPELL_CURSE_OF_TORPOR = 71237,
SPELL_SHORUD_OF_THE_OCCULT = 70768, SPELL_SHORUD_OF_THE_OCCULT = 70768,
SPELL_DARK_MARTYRDOM_ADHERENT = 70903, SPELL_DARK_MARTYRDOM_ADHERENT = 70903,
SPELL_DARK_MARTYRDOM_ADHERENT_25N = 72498,
SPELL_DARK_MARTYRDOM_ADHERENT_10H = 72499,
SPELL_DARK_MARTYRDOM_ADHERENT_25H = 72500,
SPELL_ADHERENT_S_DETERMINATION = 71234, SPELL_ADHERENT_S_DETERMINATION = 71234,
SPELL_DARK_EMPOWERMENT = 70901, SPELL_DARK_EMPOWERMENT = 70901,
@@ -88,6 +94,9 @@ enum Spells
// misc // misc
SPELL_FULL_HOUSE = 72827, // achievement SPELL_FULL_HOUSE = 72827, // achievement
SPELL_TELEPORT_VISUAL = 52096, // used by adds SPELL_TELEPORT_VISUAL = 52096, // used by adds
SPELL_CLEAR_ALL_DEBUFFS = 34098,
SPELL_FULL_HEAL = 17683,
SPELL_PERMANENT_FEIGN_DEATH = 70628,
}; };
enum EventTypes enum EventTypes
@@ -107,7 +116,6 @@ enum EventTypes
// Phase 1: // Phase 1:
EVENT_SPELL_SHADOW_BOLT, EVENT_SPELL_SHADOW_BOLT,
EVENT_SUMMON_WAVE_P1, EVENT_SUMMON_WAVE_P1,
EVENT_REANIMATE_CULTIST,
EVENT_EMPOWER_CULTIST, EVENT_EMPOWER_CULTIST,
// Phase 2: // Phase 2:
@@ -119,7 +127,7 @@ enum EventTypes
// Shared adds events: // Shared adds events:
EVENT_SPELL_CULTIST_DARK_MARTYRDOM, EVENT_SPELL_CULTIST_DARK_MARTYRDOM,
EVENT_CULTIST_DARK_MARTYRDOM_SELF_KILL, EVENT_CULTIST_DARK_MARTYRDOM_REVIVE,
// Cult Fanatic: // Cult Fanatic:
EVENT_SPELL_FANATIC_NECROTIC_STRIKE, EVENT_SPELL_FANATIC_NECROTIC_STRIKE,
@@ -130,7 +138,7 @@ enum EventTypes
EVENT_SPELL_ADHERENT_FROST_FEVER, EVENT_SPELL_ADHERENT_FROST_FEVER,
EVENT_SPELL_ADHERENT_DEATHCHILL, EVENT_SPELL_ADHERENT_DEATHCHILL,
EVENT_SPELL_ADHERENT_CURSE_OF_TORPOR, EVENT_SPELL_ADHERENT_CURSE_OF_TORPOR,
EVENT_SPELL_ADHERENT_SHORUD_OF_THE_OCCULT, EVENT_SPELL_ADHERENT_SHROUD_OF_THE_OCCULT,
// Darnavan: // Darnavan:
EVENT_DARNAVAN_BLADESTORM, EVENT_DARNAVAN_BLADESTORM,
@@ -189,7 +197,7 @@ class DaranavanMoveEvent : public BasicEvent
public: public:
DaranavanMoveEvent(Creature& darnavan) : _darnavan(darnavan) { } DaranavanMoveEvent(Creature& darnavan) : _darnavan(darnavan) { }
bool Execute(uint64 /*time*/, uint32 /*diff*/) bool Execute(uint64 /*time*/, uint32 /*diff*/) override
{ {
_darnavan.GetMotionMaster()->MovePoint(POINT_DESPAWN, SummonPositions[6]); _darnavan.GetMotionMaster()->MovePoint(POINT_DESPAWN, SummonPositions[6]);
return true; return true;
@@ -199,6 +207,21 @@ class DaranavanMoveEvent : public BasicEvent
Creature& _darnavan; Creature& _darnavan;
}; };
void ApplyMechanicImmune(Creature* c, bool apply)
{
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_INTERRUPT, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
c->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
}
class boss_lady_deathwhisper : public CreatureScript class boss_lady_deathwhisper : public CreatureScript
{ {
public: public:
@@ -206,30 +229,29 @@ class boss_lady_deathwhisper : public CreatureScript
struct boss_lady_deathwhisperAI : public BossAI struct boss_lady_deathwhisperAI : public BossAI
{ {
boss_lady_deathwhisperAI(Creature* creature) : BossAI(creature, DATA_LADY_DEATHWHISPER), _introDone(false), _darnavanGUID(0) boss_lady_deathwhisperAI(Creature* creature) : BossAI(creature, DATA_LADY_DEATHWHISPER), _introDone(false), _darnavanGUID(0) { }
{
}
void Reset() void Reset() override
{ {
if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID)) if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID))
darnavan->DespawnOrUnsummon(); darnavan->DespawnOrUnsummon();
_darnavanGUID = 0; _darnavanGUID = 0;
_waveCounter = 0; _waveCounter = 0;
_reanimationQueue.clear();
_Reset(); _Reset();
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)); me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA));
events.SetPhase(PHASE_ONE); events.SetPhase(PHASE_ONE);
me->CastSpell(me, SPELL_SHADOW_CHANNELING, false); me->CastSpell(me, SPELL_SHADOW_CHANNELING, false);
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
} }
void AttackStart(Unit* victim) void AttackStart(Unit* victim) override
{ {
if (victim && me->Attack(victim, true) && !(events.GetPhaseMask() & PHASE_ONE_MASK)) if (victim && me->Attack(victim, true) && !(events.GetPhaseMask() & PHASE_ONE_MASK))
me->GetMotionMaster()->MoveChase(victim); me->GetMotionMaster()->MoveChase(victim);
} }
void EnterCombat(Unit* who) void EnterCombat(Unit* who) override
{ {
if (!instance->CheckRequiredBosses(DATA_LADY_DEATHWHISPER, who->ToPlayer())) if (!instance->CheckRequiredBosses(DATA_LADY_DEATHWHISPER, who->ToPlayer()))
{ {
@@ -246,8 +268,8 @@ class boss_lady_deathwhisper : public CreatureScript
events.ScheduleEvent(EVENT_BERSERK, 600000); events.ScheduleEvent(EVENT_BERSERK, 600000);
events.ScheduleEvent(EVENT_SPELL_DEATH_AND_DECAY, 10000); events.ScheduleEvent(EVENT_SPELL_DEATH_AND_DECAY, 10000);
if (GetDifficulty() != RAID_DIFFICULTY_10MAN_NORMAL) if (GetDifficulty() != RAID_DIFFICULTY_10MAN_NORMAL)
events.ScheduleEvent(EVENT_SPELL_DOMINATE_MIND_25, 27000); events.ScheduleEvent(EVENT_SPELL_DOMINATE_MIND_25, 30000);
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, urand(5500, 6000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, 2000, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_SUMMON_WAVE_P1, 5000, 0, PHASE_ONE); events.ScheduleEvent(EVENT_SUMMON_WAVE_P1, 5000, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_EMPOWER_CULTIST, urand(20000,30000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_EMPOWER_CULTIST, urand(20000,30000), 0, PHASE_ONE);
@@ -258,7 +280,7 @@ class boss_lady_deathwhisper : public CreatureScript
instance->SetBossState(DATA_LADY_DEATHWHISPER, IN_PROGRESS); instance->SetBossState(DATA_LADY_DEATHWHISPER, IN_PROGRESS);
} }
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{ {
if (events.GetPhaseMask() & PHASE_ONE_MASK && damage >= me->GetPower(POWER_MANA)) if (events.GetPhaseMask() & PHASE_ONE_MASK && damage >= me->GetPower(POWER_MANA))
{ {
@@ -284,11 +306,15 @@ class boss_lady_deathwhisper : public CreatureScript
events.ScheduleEvent(EVENT_SPELL_TOUCH_OF_INSIGNIFICANCE, urand(6000, 9000), 0, PHASE_TWO); events.ScheduleEvent(EVENT_SPELL_TOUCH_OF_INSIGNIFICANCE, urand(6000, 9000), 0, PHASE_TWO);
events.ScheduleEvent(EVENT_SPELL_SUMMON_SHADE, urand(12000,15000), 0, PHASE_TWO); events.ScheduleEvent(EVENT_SPELL_SUMMON_SHADE, urand(12000,15000), 0, PHASE_TWO);
if (IsHeroic()) 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_SUMMON_WAVE_P2, 45000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_SUMMON_WAVE_P2, 45000, 0, PHASE_TWO);
} }
} }
}
void UpdateAI(uint32 diff) void UpdateAI(uint32 diff) override
{ {
if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_INTRO_MASK)) || !CheckInRoom()) if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_INTRO_MASK)) || !CheckInRoom())
return; return;
@@ -375,31 +401,27 @@ class boss_lady_deathwhisper : public CreatureScript
case EVENT_SPELL_SHADOW_BOLT: case EVENT_SPELL_SHADOW_BOLT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
me->CastSpell(target, SPELL_SHADOW_BOLT, false); me->CastSpell(target, SPELL_SHADOW_BOLT, false);
events.RepeatEvent(urand(5000, 8000)); events.RepeatEvent(2100);
break; break;
case EVENT_SUMMON_WAVE_P1: case EVENT_SUMMON_WAVE_P1:
SummonWaveP1(); SummonWaveP1();
events.RepeatEvent(IsHeroic() ? 45000 : 60000); events.RepeatEvent(IsHeroic() ? 45000 : 60000);
break; break;
case EVENT_REANIMATE_CULTIST:
ReanimateCultist();
events.PopEvent();
break;
case EVENT_EMPOWER_CULTIST: case EVENT_EMPOWER_CULTIST:
EmpowerCultist(); EmpowerCultist();
events.RepeatEvent(urand(18000,25000)); events.RepeatEvent(urand(18000,25000));
break; break;
case EVENT_SPELL_FROSTBOLT: case EVENT_SPELL_FROSTBOLT:
me->CastSpell(me->GetVictim(), SPELL_FROSTBOLT, false); me->CastSpell(me->GetVictim(), SPELL_FROSTBOLT, false);
events.RepeatEvent(urand(10000, 11000)); events.RepeatEvent(12000);
break; break;
case EVENT_SPELL_FROSTBOLT_VOLLEY: case EVENT_SPELL_FROSTBOLT_VOLLEY:
me->CastSpell((Unit*)NULL, SPELL_FROSTBOLT_VOLLEY, false); me->CastSpell((Unit*)nullptr, SPELL_FROSTBOLT_VOLLEY, false);
events.RepeatEvent(urand(13000,15000)); events.RepeatEvent(urand(13000,15000));
break; break;
case EVENT_SPELL_TOUCH_OF_INSIGNIFICANCE: case EVENT_SPELL_TOUCH_OF_INSIGNIFICANCE:
me->CastSpell(me->GetVictim(), SPELL_TOUCH_OF_INSIGNIFICANCE, false); me->CastSpell(me->GetVictim(), SPELL_TOUCH_OF_INSIGNIFICANCE, false);
events.RepeatEvent(urand(9000, 13000)); events.RepeatEvent(urand(6000, 9000));
break; break;
case EVENT_SUMMON_WAVE_P2: case EVENT_SUMMON_WAVE_P2:
SummonWaveP2(); SummonWaveP2();
@@ -419,7 +441,7 @@ class boss_lady_deathwhisper : public CreatureScript
for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
me->CastSpell(*itr, SPELL_SUMMON_SHADE, true); me->CastSpell(*itr, SPELL_SUMMON_SHADE, true);
} }
events.RepeatEvent(urand(18000, 23000)); events.RepeatEvent(12000);
break; break;
} }
@@ -429,14 +451,14 @@ class boss_lady_deathwhisper : public CreatureScript
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
void JustSummoned(Creature* summon) void JustSummoned(Creature* summon) override
{ {
if (summon->GetEntry() == NPC_DARNAVAN) if (summon->GetEntry() == NPC_DARNAVAN)
_darnavanGUID = summon->GetGUID(); _darnavanGUID = summon->GetGUID();
else else
summons.Summon(summon); summons.Summon(summon);
Unit* target = NULL; Unit* target = nullptr;
if (summon->GetEntry() == NPC_VENGEFUL_SHADE) if (summon->GetEntry() == NPC_VENGEFUL_SHADE)
{ {
float minrange = 250.0f; float minrange = 250.0f;
@@ -460,12 +482,12 @@ class boss_lady_deathwhisper : public CreatureScript
summon->AI()->AttackStart(target); summon->AI()->AttackStart(target);
} }
void SummonedCreatureDespawn(Creature* summon) void SummonedCreatureDespawn(Creature* summon) override
{ {
summons.Despawn(summon); summons.Despawn(summon);
} }
void JustDied(Unit* killer) void JustDied(Unit* killer) override
{ {
Talk(SAY_DEATH); Talk(SAY_DEATH);
@@ -496,7 +518,7 @@ class boss_lady_deathwhisper : public CreatureScript
{ {
if (Group* group = owner->GetGroup()) 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()) if (Player* member = itr->GetSource())
if (member->IsInMap(owner)) if (member->IsInMap(owner))
member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT, 0); member->KilledMonsterCredit(NPC_DARNAVAN_CREDIT, 0);
@@ -510,18 +532,18 @@ class boss_lady_deathwhisper : public CreatureScript
_JustDied(); _JustDied();
} }
void KilledUnit(Unit* victim) void KilledUnit(Unit* victim) override
{ {
if (victim->GetTypeId() == TYPEID_PLAYER) if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL); Talk(SAY_KILL);
} }
void DoAction(int32 action) void DoAction(int32 action) override
{ {
if (action != ACTION_START_INTRO) if (action != ACTION_START_INTRO)
return; return;
if (!_introDone) if (!_introDone && !me->IsInCombat())
{ {
_introDone = true; _introDone = true;
Talk(SAY_INTRO_1); Talk(SAY_INTRO_1);
@@ -585,30 +607,6 @@ class boss_lady_deathwhisper : public CreatureScript
} }
} }
void SetGUID(uint64 guid, int32)
{
if (events.GetPhaseMask() & PHASE_ONE_MASK)
{
_reanimationQueue.push_back(guid);
events.ScheduleEvent(EVENT_REANIMATE_CULTIST, 3000, 0, PHASE_ONE);
}
}
void ReanimateCultist()
{
if (_reanimationQueue.empty())
return;
uint64 cultistGUID = _reanimationQueue.front();
Creature* cultist = ObjectAccessor::GetCreature(*me, cultistGUID);
_reanimationQueue.pop_front();
if (!cultist)
return;
Talk(SAY_ANIMATE_DEAD);
me->CastSpell(cultist, SPELL_DARK_MARTYRDOM_T, true);
}
void EmpowerCultist() void EmpowerCultist()
{ {
if (summons.empty()) if (summons.empty())
@@ -625,40 +623,35 @@ class boss_lady_deathwhisper : public CreatureScript
return; return;
// select random cultist // select random cultist
if (Creature* cultist = Trinity::Containers::SelectRandomContainerElement(temp)) Creature* cultist = Trinity::Containers::SelectRandomContainerElement(temp);
if (!cultist)
return;
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); 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)); Talk(uint8(cultist->GetEntry() == NPC_CULT_FANATIC ? SAY_DARK_TRANSFORMATION : SAY_DARK_EMPOWERMENT));
} }
} }
void SpellHitTarget(Unit* target, SpellInfo const* spell) void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{ {
if (spell->Id == SPELL_DARK_MARTYRDOM_T) if (spell->Id == SPELL_DOMINATE_MIND_25)
{
if (target->GetEntry() == NPC_CULT_FANATIC)
me->SummonCreature(NPC_REANIMATED_FANATIC, *target, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
else
me->SummonCreature(NPC_REANIMATED_ADHERENT, *target, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
if (TempSummon* summon = target->ToTempSummon())
summon->UnSummon();
}
else if (spell->Id == SPELL_DOMINATE_MIND_25)
{ {
const int32 val = 100; const int32 val = 100;
target->CastCustomSpell(target, 73261, &val, NULL, NULL, true); // scale aura, +100% size target->CastCustomSpell(target, 73261, &val, nullptr, nullptr, true); // scale aura, +100% size
} }
} }
private: private:
bool _introDone; bool _introDone;
uint64 _darnavanGUID; uint64 _darnavanGUID;
std::deque<uint64> _reanimationQueue;
uint32 _waveCounter; uint32 _waveCounter;
}; };
CreatureAI* GetAI(Creature* creature) const CreatureAI* GetAI(Creature* creature) const override
{ {
return GetIcecrownCitadelAI<boss_lady_deathwhisperAI>(creature); return GetIcecrownCitadelAI<boss_lady_deathwhisperAI>(creature);
} }
@@ -671,48 +664,53 @@ public:
struct npc_cult_fanaticAI : public ScriptedAI struct npc_cult_fanaticAI : public ScriptedAI
{ {
npc_cult_fanaticAI(Creature* creature) : ScriptedAI(creature) {} npc_cult_fanaticAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) {}
EventMap events; EventMap events;
InstanceScript* _instance;
void Reset() void Reset() override
{ {
events.Reset(); events.Reset();
events.ScheduleEvent(EVENT_SPELL_FANATIC_NECROTIC_STRIKE, urand(10000, 12000)); events.ScheduleEvent(EVENT_SPELL_FANATIC_NECROTIC_STRIKE, urand(10000, 12000));
events.ScheduleEvent(EVENT_SPELL_FANATIC_SHADOW_CLEAVE, urand(14000, 16000)); events.ScheduleEvent(EVENT_SPELL_FANATIC_SHADOW_CLEAVE, urand(14000, 16000));
events.ScheduleEvent(EVENT_SPELL_FANATIC_VAMPIRIC_MIGHT, urand(20000, 27000)); events.ScheduleEvent(EVENT_SPELL_FANATIC_VAMPIRIC_MIGHT, urand(20000, 27000));
if (me->GetEntry() == NPC_CULT_FANATIC)
events.ScheduleEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM, urand(15000, 32000));
} }
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{ {
if (spell->Id == SPELL_DARK_TRANSFORMATION) switch (spell->Id)
{
case SPELL_DARK_TRANSFORMATION:
me->UpdateEntry(NPC_DEFORMED_FANATIC); me->UpdateEntry(NPC_DEFORMED_FANATIC);
else if (spell->Id == SPELL_DARK_TRANSFORMATION_T) break;
{ case SPELL_DARK_TRANSFORMATION_T:
events.CancelEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM);
me->InterruptNonMeleeSpells(true); me->InterruptNonMeleeSpells(true);
me->CastSpell(me, SPELL_DARK_TRANSFORMATION, false); me->CastSpell(me, SPELL_DARK_TRANSFORMATION, false);
} break;
} case SPELL_DARK_MARTYRDOM_T:
void DoAction(int32 a)
{
if (a == -1)
{
me->SetControlled(true, UNIT_STATE_STUNNED);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
me->InterruptNonMeleeSpells(true);
ApplyMechanicImmune(me, true);
me->AttackStop();
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
me->StopMoving(); me->StopMoving();
events.Reset(); me->CastSpell(me, SPELL_DARK_MARTYRDOM_FANATIC, false);
events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM_SELF_KILL, 500); break;
case SPELL_DARK_MARTYRDOM_FANATIC:
case SPELL_DARK_MARTYRDOM_FANATIC_10H:
case SPELL_DARK_MARTYRDOM_FANATIC_25N:
case SPELL_DARK_MARTYRDOM_FANATIC_25H:
ApplyMechanicImmune(me, false);
events.ScheduleEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM, 5); // Visual purposes only.
break;
} }
} }
void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } void EnterCombat(Unit* /*who*/) override { DoZoneInCombat(); }
void UpdateAI(uint32 diff) void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
@@ -724,8 +722,6 @@ public:
switch (events.GetEvent()) switch (events.GetEvent())
{ {
case 0:
break;
case EVENT_SPELL_FANATIC_NECROTIC_STRIKE: case EVENT_SPELL_FANATIC_NECROTIC_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_NECROTIC_STRIKE, false); me->CastSpell(me->GetVictim(), SPELL_NECROTIC_STRIKE, false);
events.RepeatEvent(urand(11000, 13000)); events.RepeatEvent(urand(11000, 13000));
@@ -738,21 +734,39 @@ public:
me->CastSpell(me, SPELL_VAMPIRIC_MIGHT, false); me->CastSpell(me, SPELL_VAMPIRIC_MIGHT, false);
events.RepeatEvent(urand(20000, 27000)); events.RepeatEvent(urand(20000, 27000));
break; break;
case EVENT_SPELL_CULTIST_DARK_MARTYRDOM: case EVENT_CULTIST_DARK_MARTYRDOM_REVIVE:
me->CastSpell(me, SPELL_DARK_MARTYRDOM_FANATIC, false); me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
events.RepeatEvent(urand(16000, 21000)); me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
break; me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
case EVENT_CULTIST_DARK_MARTYRDOM_SELF_KILL: me->UpdateEntry(NPC_REANIMATED_FANATIC);
Unit::Kill(me, me); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat(me);
me->CastSpell(me, SPELL_FANATIC_S_DETERMINATION);
if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_LADY_DEATHWHISPER)))
ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD);
events.PopEvent(); events.PopEvent();
break; break;
case EVENT_SPELL_CULTIST_DARK_MARTYRDOM:
me->CastSpell(me, SPELL_PERMANENT_FEIGN_DEATH, true);
me->CastSpell(me, SPELL_CLEAR_ALL_DEBUFFS, true);
me->CastSpell(me, SPELL_FULL_HEAL, true);
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE);
Reset();
events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM_REVIVE, 6000);
break;
default:
break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
CreatureAI* GetAI(Creature* creature) const CreatureAI* GetAI(Creature* creature) const override
{ {
return GetIcecrownCitadelAI<npc_cult_fanaticAI>(creature); return GetIcecrownCitadelAI<npc_cult_fanaticAI>(creature);
} }
@@ -765,50 +779,54 @@ public:
struct npc_cult_adherentAI : public ScriptedAI struct npc_cult_adherentAI : public ScriptedAI
{ {
npc_cult_adherentAI(Creature* creature) : ScriptedAI(creature) {} npc_cult_adherentAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) {}
EventMap events; EventMap events;
InstanceScript* _instance;
void Reset() void Reset() override
{ {
events.Reset(); events.Reset();
events.ScheduleEvent(EVENT_SPELL_ADHERENT_FROST_FEVER, urand(10000, 12000)); events.ScheduleEvent(EVENT_SPELL_ADHERENT_FROST_FEVER, urand(10000, 12000));
events.ScheduleEvent(EVENT_SPELL_ADHERENT_DEATHCHILL, urand(14000, 16000)); events.ScheduleEvent(EVENT_SPELL_ADHERENT_DEATHCHILL, urand(14000, 16000));
events.ScheduleEvent(EVENT_SPELL_ADHERENT_CURSE_OF_TORPOR, urand(14000, 16000)); events.ScheduleEvent(EVENT_SPELL_ADHERENT_CURSE_OF_TORPOR, urand(14000, 16000));
events.ScheduleEvent(EVENT_SPELL_ADHERENT_SHORUD_OF_THE_OCCULT, urand(32000, 39000)); events.ScheduleEvent(EVENT_SPELL_ADHERENT_SHROUD_OF_THE_OCCULT, urand(32000, 39000));
if (me->GetEntry() == NPC_CULT_ADHERENT)
events.ScheduleEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM, urand(15000, 32000));
} }
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{ {
if (spell->Id == SPELL_DARK_EMPOWERMENT) switch (spell->Id)
{
case SPELL_DARK_EMPOWERMENT:
me->UpdateEntry(NPC_EMPOWERED_ADHERENT); me->UpdateEntry(NPC_EMPOWERED_ADHERENT);
else if (spell->Id == SPELL_DARK_EMPOWERMENT_T) break;
{ case SPELL_DARK_EMPOWERMENT_T:
events.CancelEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM);
me->InterruptNonMeleeSpells(true); me->InterruptNonMeleeSpells(true);
me->CastSpell(me, SPELL_DARK_EMPOWERMENT, false); me->CastSpell(me, SPELL_DARK_EMPOWERMENT, false);
} break;
} case SPELL_DARK_MARTYRDOM_T:
void DoAction(int32 a)
{
if (a == -1)
{
me->SetControlled(true, UNIT_STATE_STUNNED);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
me->InterruptNonMeleeSpells(true);
ApplyMechanicImmune(me, true);
me->AttackStop();
me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
me->StopMoving(); me->StopMoving();
events.Reset(); me->CastSpell(me, SPELL_DARK_MARTYRDOM_ADHERENT, false);
events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM_SELF_KILL, 500); break;
case SPELL_DARK_MARTYRDOM_ADHERENT:
case SPELL_DARK_MARTYRDOM_ADHERENT_10H:
case SPELL_DARK_MARTYRDOM_ADHERENT_25N:
case SPELL_DARK_MARTYRDOM_ADHERENT_25H:
ApplyMechanicImmune(me, false);
events.ScheduleEvent(EVENT_SPELL_CULTIST_DARK_MARTYRDOM, 5); // Visual purposes only.
break;
} }
} }
void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } void EnterCombat(Unit* /*who*/) override { DoZoneInCombat(); }
void UpdateAI(uint32 diff) void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
@@ -820,8 +838,6 @@ public:
switch (events.GetEvent()) switch (events.GetEvent())
{ {
case 0:
break;
case EVENT_SPELL_ADHERENT_FROST_FEVER: case EVENT_SPELL_ADHERENT_FROST_FEVER:
me->CastSpell(me->GetVictim(), SPELL_FROST_FEVER, false); me->CastSpell(me->GetVictim(), SPELL_FROST_FEVER, false);
events.RepeatEvent(urand(9000, 13000)); events.RepeatEvent(urand(9000, 13000));
@@ -838,25 +854,43 @@ public:
me->CastSpell(target, SPELL_CURSE_OF_TORPOR, false); me->CastSpell(target, SPELL_CURSE_OF_TORPOR, false);
events.RepeatEvent(urand(9000, 13000)); events.RepeatEvent(urand(9000, 13000));
break; break;
case EVENT_SPELL_ADHERENT_SHORUD_OF_THE_OCCULT: case EVENT_SPELL_ADHERENT_SHROUD_OF_THE_OCCULT:
me->CastSpell(me, SPELL_SHORUD_OF_THE_OCCULT, false); me->CastSpell(me, SPELL_SHORUD_OF_THE_OCCULT, false);
events.RepeatEvent(urand(27000, 32000)); events.RepeatEvent(urand(27000, 32000));
break; break;
case EVENT_SPELL_CULTIST_DARK_MARTYRDOM: case EVENT_CULTIST_DARK_MARTYRDOM_REVIVE:
me->CastSpell(me, SPELL_DARK_MARTYRDOM_ADHERENT, false); me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
events.RepeatEvent(urand(16000, 21000)); me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
break; me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
case EVENT_CULTIST_DARK_MARTYRDOM_SELF_KILL: me->UpdateEntry(NPC_REANIMATED_ADHERENT);
Unit::Kill(me, me); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat(me);
me->CastSpell(me, SPELL_ADHERENT_S_DETERMINATION);
if (Creature* ladyDeathwhisper = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_LADY_DEATHWHISPER)))
ladyDeathwhisper->AI()->Talk(SAY_ANIMATE_DEAD);
events.PopEvent(); events.PopEvent();
break; break;
case EVENT_SPELL_CULTIST_DARK_MARTYRDOM:
me->CastSpell(me, SPELL_PERMANENT_FEIGN_DEATH, true);
me->CastSpell(me, SPELL_CLEAR_ALL_DEBUFFS, true);
me->CastSpell(me, SPELL_FULL_HEAL, true);
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_UNK_29 | UNIT_FLAG_NOT_SELECTABLE);
Reset();
events.ScheduleEvent(EVENT_CULTIST_DARK_MARTYRDOM_REVIVE, 6000);
break;
default:
break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
CreatureAI* GetAI(Creature* creature) const CreatureAI* GetAI(Creature* creature) const override
{ {
return GetIcecrownCitadelAI<npc_cult_adherentAI>(creature); return GetIcecrownCitadelAI<npc_cult_adherentAI>(creature);
} }
@@ -879,13 +913,13 @@ public:
uint16 unroot_timer; uint16 unroot_timer;
uint64 targetGUID; uint64 targetGUID;
void Reset() void Reset() override
{ {
me->setAttackTimer(BASE_ATTACK, 2000); me->setAttackTimer(BASE_ATTACK, 2000);
me->AddAura(SPELL_VENGEFUL_BLAST_PASSIVE, me); me->AddAura(SPELL_VENGEFUL_BLAST_PASSIVE, me);
} }
void AttackStart(Unit* who) void AttackStart(Unit* who) override
{ {
if (!who) if (!who)
return; return;
@@ -898,7 +932,7 @@ public:
} }
} }
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override
{ {
switch (spell->Id) switch (spell->Id)
{ {
@@ -916,7 +950,7 @@ public:
} }
} }
void UpdateAI(uint32 diff) void UpdateAI(uint32 diff) override
{ {
if (unroot_timer) if (unroot_timer)
{ {
@@ -944,11 +978,11 @@ public:
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
void MoveInLineOfSight(Unit* /*who*/) {} void MoveInLineOfSight(Unit* /*who*/) override {}
void EnterEvadeMode() {} void EnterEvadeMode() override {}
}; };
CreatureAI* GetAI(Creature* creature) const CreatureAI* GetAI(Creature* creature) const override
{ {
return GetIcecrownCitadelAI<npc_vengeful_shadeAI>(creature); return GetIcecrownCitadelAI<npc_vengeful_shadeAI>(creature);
} }
@@ -967,7 +1001,7 @@ public:
bool _canCharge; bool _canCharge;
bool _canShatter; bool _canShatter;
void Reset() void Reset() override
{ {
events.Reset(); events.Reset();
events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 10000); events.ScheduleEvent(EVENT_DARNAVAN_BLADESTORM, 10000);
@@ -978,14 +1012,14 @@ public:
_canShatter = true; _canShatter = true;
} }
void JustDied(Unit* killer) void JustDied(Unit* killer) override
{ {
events.Reset(); events.Reset();
if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
{ {
if (Group* group = owner->GetGroup()) 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()) if (Player* member = itr->GetSource())
if (member->IsInMap(owner)) if (member->IsInMap(owner))
member->FailQuest(QUEST_DEPROGRAMMING); member->FailQuest(QUEST_DEPROGRAMMING);
@@ -995,7 +1029,7 @@ public:
} }
} }
void MovementInform(uint32 type, uint32 id) void MovementInform(uint32 type, uint32 id) override
{ {
if (type != POINT_MOTION_TYPE || id != POINT_DESPAWN) if (type != POINT_MOTION_TYPE || id != POINT_DESPAWN)
return; return;
@@ -1003,13 +1037,13 @@ public:
me->DespawnOrUnsummon(); me->DespawnOrUnsummon();
} }
void EnterCombat(Unit* /*victim*/) void EnterCombat(Unit* /*victim*/) override
{ {
DoZoneInCombat(); DoZoneInCombat();
Talk(SAY_DARNAVAN_AGGRO); Talk(SAY_DARNAVAN_AGGRO);
} }
void UpdateAI(uint32 diff) void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
@@ -1037,10 +1071,8 @@ public:
switch (events.GetEvent()) switch (events.GetEvent())
{ {
case 0:
break;
case EVENT_DARNAVAN_BLADESTORM: case EVENT_DARNAVAN_BLADESTORM:
me->CastSpell((Unit*)NULL, SPELL_BLADESTORM, false); me->CastSpell((Unit*)nullptr, SPELL_BLADESTORM, false);
events.RepeatEvent(urand(90000, 100000)); events.RepeatEvent(urand(90000, 100000));
break; break;
case EVENT_DARNAVAN_CHARGE: case EVENT_DARNAVAN_CHARGE:
@@ -1048,7 +1080,7 @@ public:
events.PopEvent(); events.PopEvent();
break; break;
case EVENT_DARNAVAN_INTIMIDATING_SHOUT: case EVENT_DARNAVAN_INTIMIDATING_SHOUT:
me->CastSpell((Unit*)NULL, SPELL_INTIMIDATING_SHOUT, false); me->CastSpell((Unit*)nullptr, SPELL_INTIMIDATING_SHOUT, false);
events.RepeatEvent(urand(90000, 120000)); events.RepeatEvent(urand(90000, 120000));
break; break;
case EVENT_DARNAVAN_MORTAL_STRIKE: case EVENT_DARNAVAN_MORTAL_STRIKE:
@@ -1063,13 +1095,15 @@ public:
me->CastSpell(me->GetVictim(), SPELL_SUNDER_ARMOR, false); me->CastSpell(me->GetVictim(), SPELL_SUNDER_ARMOR, false);
events.RepeatEvent(urand(3000, 7000)); events.RepeatEvent(urand(3000, 7000));
break; break;
default:
break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
CreatureAI* GetAI(Creature* creature) const CreatureAI* GetAI(Creature* creature) const override
{ {
return GetIcecrownCitadelAI<npc_darnavanAI>(creature); return GetIcecrownCitadelAI<npc_darnavanAI>(creature);
} }
@@ -1095,56 +1129,24 @@ class spell_deathwhisper_mana_barrier : public SpellScriptLoader
} }
} }
void Register() void Register() override
{ {
OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathwhisper_mana_barrier_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathwhisper_mana_barrier_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
} }
}; };
AuraScript* GetAuraScript() const AuraScript* GetAuraScript() const override
{ {
return new spell_deathwhisper_mana_barrier_AuraScript(); return new spell_deathwhisper_mana_barrier_AuraScript();
} }
}; };
class spell_cultist_dark_martyrdom : public SpellScriptLoader
{
public:
spell_cultist_dark_martyrdom() : SpellScriptLoader("spell_cultist_dark_martyrdom") { }
class spell_cultist_dark_martyrdom_SpellScript : public SpellScript
{
PrepareSpellScript(spell_cultist_dark_martyrdom_SpellScript);
void HandleEffect(SpellEffIndex /*effIndex*/)
{
if (GetCaster()->ToTempSummon())
if (Unit* owner = GetCaster()->ToTempSummon()->GetSummoner())
owner->GetAI()->SetGUID(GetCaster()->GetGUID());
if (Creature* caster = GetCaster()->ToCreature())
caster->AI()->DoAction(-1);
GetCaster()->SetDisplayId(GetCaster()->GetEntry() == NPC_CULT_FANATIC ? 30968 : 30966);
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_cultist_dark_martyrdom_SpellScript::HandleEffect, EFFECT_2, SPELL_EFFECT_FORCE_DESELECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_cultist_dark_martyrdom_SpellScript();
}
};
class at_lady_deathwhisper_entrance : public AreaTriggerScript class at_lady_deathwhisper_entrance : public AreaTriggerScript
{ {
public: public:
at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { } at_lady_deathwhisper_entrance() : AreaTriggerScript("at_lady_deathwhisper_entrance") { }
bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override
{ {
if (InstanceScript* instance = player->GetInstanceScript()) if (InstanceScript* instance = player->GetInstanceScript())
if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE) if (instance->GetBossState(DATA_LADY_DEATHWHISPER) != DONE)
@@ -1163,6 +1165,5 @@ void AddSC_boss_lady_deathwhisper()
new npc_vengeful_shade(); new npc_vengeful_shade();
new npc_darnavan(); new npc_darnavan();
new spell_deathwhisper_mana_barrier(); new spell_deathwhisper_mana_barrier();
new spell_cultist_dark_martyrdom();
new at_lady_deathwhisper_entrance(); new at_lady_deathwhisper_entrance();
} }