Files
CypherCore/Source/Scripts/Northrend/IcecrownCitadel/LadyDeathwhisper.cs
T

1031 lines
38 KiB
C#

/*
* Copyright (C) 2012-2019 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Framework.Dynamic;
using Game;
using Game.AI;
using Game.DataStorage;
using Game.Entities;
using Game.Groups;
using Game.Maps;
using Game.Scripting;
using Game.Spells;
using System.Collections.Generic;
using System.Linq;
using System;
namespace Scripts.Northrend.IcecrownCitadel
{
struct TextIds
{
// Lady Deathwhisper
public const uint SayIntro1 = 0;
public const uint SayIntro2 = 1;
public const uint SayIntro3 = 2;
public const uint SayIntro4 = 3;
public const uint SayIntro5 = 4;
public const uint SayIntro6 = 5;
public const uint SayIntro7 = 6;
public const uint SayAggro = 7;
public const uint SayPhase2 = 8;
public const uint EmotePhase2 = 9;
public const uint SayDominateMind = 10;
public const uint SayDarkEmpowerment = 11;
public const uint SayDarkTransformation = 12;
public const uint SayAnimateDead = 13;
public const uint SayKill = 14;
public const uint SayBerserk = 15;
public const uint SayDeath = 16;
// Darnavan
public const uint SayDarnavanAggro = 0;
public const uint SayDarnavanRescued = 1;
}
struct SpellIds
{
public const uint Berserk = 26662;
// Lady Deathwhisper
public const uint ManaBarrier = 70842;
public const uint ShadowBolt = 71254;
public const uint DeathAndDecay = 71001;
public const uint DominateMind = 71289;
public const uint DominateMindScale = 71290;
public const uint Frostbolt = 71420;
public const uint FrostboltVolley = 72905;
public const uint TouchOfInsignificance = 71204;
public const uint SummonShade = 71363;
public const uint ShadowChanneling = 43897;
public const uint DarkTransformationT = 70895;
public const uint DarkEmpowermentT = 70896;
public const uint DarkMartyrdomT = 70897;
public const uint SummonSpirits = 72478;
// Achievement
public const uint FullHouse = 72827; // Does Not Exist In Dbc But Still Can Be Used For Criteria Check
// Both Adds
public const uint TeleportVisual = 41236;
public const uint ClearAllDebuffs = 34098;
public const uint FullHeal = 17683;
public const uint PermanentFeighDeath = 70628;
// Fanatics
public const uint DarkTransformation = 70900;
public const uint NecroticStrike = 70659;
public const uint ShadowCleave = 70670;
public const uint VampiricMight = 70674;
public const uint FanaticSDetermination = 71235;
public const uint DarkMartyrdomFanatic = 71236;
// Adherents
public const uint DarkEmpowerment = 70901;
public const uint FrostFever = 67767;
public const uint DeathchillBolt = 70594;
public const uint DeathchillBlast = 70906;
public const uint CurseOfTorpor = 71237;
public const uint ShorudOfTheOccult = 70768;
public const uint AdherentSDetermination = 71234;
public const uint DarkMartyrdomAdherent = 70903;
// Vengeful Shade
public const uint VengefulBlast = 71544;
public const uint VengefulBlastPassive = 71494;
public const uint VengefulBlast25N = 72010;
public const uint VengefulBlast10H = 72011;
public const uint VengefulBlast25H = 72012;
// Darnavan
public const uint Bladestorm = 65947;
public const uint Charge = 65927;
public const uint IntimidatingShout = 65930;
public const uint MortalStrike = 65926;
public const uint ShatteringThrow = 65940;
public const uint SunderArmor = 65936;
}
struct LadyEventTypes
{
// Darnavan
public const uint DARNAVAN_BLADESTORM = 27;
public const uint DARNAVAN_CHARGE = 28;
public const uint DARNAVAN_INTIMIDATING_SHOUT = 29;
public const uint DARNAVAN_MORTAL_STRIKE = 30;
public const uint DARNAVAN_SHATTERING_THROW = 31;
public const uint DARNAVAN_SUNDER_ARMOR = 32;
}
enum Phases
{
All,
Intro,
One,
Two
}
struct GroupIds
{
public const uint Intro = 0;
public const uint One = 1;
public const uint Two = 2;
}
struct DeprogrammingData
{
public const uint NpcDarnavan10 = 38472;
public const uint NpcDarnavan25 = 38485;
public const uint NpcDarnavanCredit10 = 39091;
public const uint NpcDarnavanCredit25 = 39092;
public const int ACTION_COMPLETE_QUEST = -384720;
public const uint POINT_DESPAWN = 384721;
}
struct LadyConst
{
public const uint GUIDCultist = 1;
public static uint[] SummonEntries = { CreatureIds.CultFanatic, CreatureIds.CultAdherent };
public static Position[] SummonPositions =
{
new Position(-578.7066f, 2154.167f, 51.01529f, 1.692969f), // 1 Left Door 1 (Cult Fanatic)
new Position(-598.9028f, 2155.005f, 51.01530f, 1.692969f), // 2 Left Door 2 (Cult Adherent)
new Position(-619.2864f, 2154.460f, 51.01530f, 1.692969f), // 3 Left Door 3 (Cult Fanatic)
new Position(-578.6996f, 2269.856f, 51.01529f, 4.590216f), // 4 Right Door 1 (Cult Adherent)
new Position(-598.9688f, 2269.264f, 51.01529f, 4.590216f), // 5 Right Door 2 (Cult Fanatic)
new Position(-619.4323f, 2268.523f, 51.01530f, 4.590216f), // 6 Right Door 3 (Cult Adherent)
new Position(-524.2480f, 2211.920f, 62.90960f, 3.141592f), // 7 Upper (Random Cultist)
};
}
class DaranavanMoveEvent : BasicEvent
{
public DaranavanMoveEvent(Creature darnavan)
{
_darnavan = darnavan;
}
public override bool Execute(ulong time, uint diff)
{
_darnavan.GetMotionMaster().MovePoint(DeprogrammingData.POINT_DESPAWN, LadyConst.SummonPositions[6]);
return true;
}
Creature _darnavan;
}
[Script]
public class boss_lady_deathwhisper : BossAI
{
public boss_lady_deathwhisper(Creature creature) : base(creature, Bosses.LadyDeathwhisper)
{
_dominateMindCount = RaidMode<byte>(0, 1, 1, 3);
_introDone = false;
Initialize();
}
void Initialize()
{
_waveCounter = 0;
_nextVengefulShadeTargetGUID.Clear();
_cultistQueue.Clear();
_darnavanGUID.Clear();
_phase = Phases.All;
_scheduler.SetValidator(() =>
{
return !(me.HasUnitState(UnitState.Casting) && _phase != Phases.Intro);
});
}
public override void Reset()
{
_Reset();
Initialize();
_phase = Phases.One;
DoCast(me, SpellIds.ShadowChanneling);
me.SetFullPower(PowerType.Mana);
me.ApplySpellImmune(0, SpellImmunity.State, AuraType.ModTaunt, false);
me.ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.AttackMe, false);
}
public override void DoAction(int action)
{
if (action != 0)
return;
if (!_introDone)
{
_introDone = true;
Talk(TextIds.SayIntro1);
_phase = Phases.Intro;
_scheduler.Schedule(TimeSpan.FromSeconds(10), GroupIds.Intro, task =>
{
switch (task.GetRepeatCounter())
{
case 0:
Talk(TextIds.SayIntro2);
task.Repeat(TimeSpan.FromSeconds(21));
break;
case 1:
Talk(TextIds.SayIntro3);
task.Repeat(TimeSpan.FromSeconds(11));
break;
case 2:
Talk(TextIds.SayIntro4);
task.Repeat(TimeSpan.FromSeconds(9));
break;
case 3:
Talk(TextIds.SayIntro5);
task.Repeat(TimeSpan.FromSeconds(21));
break;
case 4:
Talk(TextIds.SayIntro6);
task.Repeat(TimeSpan.FromSeconds(10));
break;
case 5:
Talk(TextIds.SayIntro7);
return;
default:
break;
}
});
}
}
public override void AttackStart(Unit victim)
{
if (me.HasUnitFlag(UnitFlags.NonAttackable))
return;
if (victim && me.Attack(victim, true) && _phase != Phases.One)
me.GetMotionMaster().MoveChase(victim);
}
public override void EnterCombat(Unit who)
{
if (!instance.CheckRequiredBosses(Bosses.LadyDeathwhisper, who.ToPlayer()))
{
EnterEvadeMode(EvadeReason.SequenceBreak);
instance.DoCastSpellOnPlayers(TeleporterSpells.LIGHT_S_HAMMER_TELEPORT);
return;
}
me.SetCombatPulseDelay(5);
me.setActive(true);
DoZoneInCombat();
_phase = Phases.One;
_scheduler.CancelGroup(GroupIds.Intro);
// phase-independent events
_scheduler.Schedule(TimeSpan.FromMinutes(10), context =>
{
DoCastSelf(SpellIds.Berserk);
Talk(TextIds.SayBerserk);
}).Schedule(TimeSpan.FromSeconds(17), death_and_decay =>
{
Unit target = SelectTarget(SelectAggroTarget.Random);
if (target)
DoCast(target, SpellIds.DeathAndDecay);
death_and_decay.Repeat(TimeSpan.FromSeconds(22), TimeSpan.FromSeconds(30));
});
if (GetDifficulty() != Difficulty.Raid10N)
{
_scheduler.Schedule(TimeSpan.FromSeconds(27), dominate_mind =>
{
Talk(TextIds.SayDominateMind);
for (byte i = 0; i < _dominateMindCount; i++)
{
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true, -(int)SpellIds.DominateMind);
if (target != null)
DoCast(target, SpellIds.DominateMind);
}
dominate_mind.Repeat(TimeSpan.FromSeconds(40), TimeSpan.FromSeconds(45));
});
}
// phase one only
_scheduler.Schedule(TimeSpan.FromSeconds(5), GroupIds.One, wave =>
{
SummonWaveP1();
wave.Repeat(TimeSpan.FromSeconds(IsHeroic() ? 45 : 60));
}).Schedule(TimeSpan.FromSeconds(2), GroupIds.One, shadow_bolt =>
{
Unit target = SelectTarget(SelectAggroTarget.Random);
if (target != null)
DoCast(target, SpellIds.ShadowBolt);
shadow_bolt.Repeat(TimeSpan.FromMilliseconds(2450), TimeSpan.FromMilliseconds(3600));
}).Schedule(TimeSpan.FromSeconds(15), GroupIds.One, context =>
{
DoImproveCultist();
context.Repeat(TimeSpan.FromSeconds(25));
});
Talk(TextIds.SayAggro);
DoStartNoMovement(who);
me.RemoveAurasDueToSpell(SpellIds.ShadowChanneling);
DoCast(me, SpellIds.ManaBarrier, true);
instance.SetBossState(Bosses.LadyDeathwhisper, EncounterState.InProgress);
}
public override void JustDied(Unit killer)
{
Talk(TextIds.SayDeath);
List<uint> livingAddEntries = new List<uint>();
// Full House achievement
foreach (var guid in summons)
{
Unit unit = Global.ObjAccessor.GetUnit(me, guid);
if (unit)
if (unit.IsAlive() && unit.GetEntry() != CreatureIds.VengefulShade)
livingAddEntries.Add(unit.GetEntry());
}
if (livingAddEntries.Count >= 5)
instance.DoUpdateCriteria(CriteriaTypes.BeSpellTarget, SpellIds.FullHouse, 0, me);
Creature darnavan = ObjectAccessor.GetCreature(me, _darnavanGUID);
if (darnavan)
{
if (darnavan.IsAlive())
{
darnavan.SetFaction(35);
darnavan.CombatStop(true);
darnavan.GetMotionMaster().MoveIdle();
darnavan.SetReactState(ReactStates.Passive);
darnavan.m_Events.AddEvent(new DaranavanMoveEvent(darnavan), darnavan.m_Events.CalculateTime(10000));
darnavan.GetAI().Talk(TextIds.SayDarnavanRescued);
Player owner = killer.GetCharmerOrOwnerPlayerOrPlayerItself();
if (owner)
{
Group group = owner.GetGroup();
if (group)
{
for (GroupReference groupRefe = group.GetFirstMember(); groupRefe != null; groupRefe = groupRefe.next())
{
Player member = groupRefe.GetSource();
if (member)
member.KilledMonsterCredit(NPC_DARNAVAN_CREDIT, ObjectGuid.Empty);
}
}
else
owner.KilledMonsterCredit(NPC_DARNAVAN_CREDIT, ObjectGuid.Empty);
}
}
}
_JustDied();
}
public override void EnterEvadeMode(EvadeReason why = EvadeReason.Other)
{
_scheduler.CancelAll();
summons.DespawnAll();
Creature darnavan = ObjectAccessor.GetCreature(me, _darnavanGUID);
if (darnavan != null)
darnavan.DespawnOrUnsummon();
_DespawnAtEvade();
}
public override void KilledUnit(Unit victim)
{
if (victim.IsTypeId(TypeId.Player))
Talk(TextIds.SayKill);
}
public override void DamageTaken(Unit damageDealer, ref uint damage)
{
// phase transition
if (_phase == Phases.One && damage > (uint)me.GetPower(PowerType.Mana))
{
_phase = Phases.Two;
Talk(TextIds.SayPhase2);
Talk(TextIds.EmotePhase2);
DoStartMovement(me.GetVictim());
DoResetThreat();
damage -= (uint)me.GetPower(PowerType.Mana);
me.SetPower(PowerType.Mana, 0);
me.RemoveAurasDueToSpell(SpellIds.ManaBarrier);
_scheduler.CancelGroup(GroupIds.One);
_scheduler.Schedule(TimeSpan.FromSeconds(12), GroupIds.Two, frostbolt =>
{
DoCastVictim(SpellIds.Frostbolt);
frostbolt.Repeat();
}).Schedule(TimeSpan.FromSeconds(20), GroupIds.Two, frostboldVolley =>
{
DoCastAOE(SpellIds.FrostboltVolley);
frostboldVolley.Repeat();
}).Schedule(TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(9), GroupIds.Two, touch =>
{
if (me.GetVictim())
me.AddAura(SpellIds.TouchOfInsignificance, me.GetVictim());
touch.Repeat();
}).Schedule(TimeSpan.FromSeconds(12), GroupIds.Two, summonShade =>
{
me.CastCustomSpell(SpellIds.SummonSpirits, SpellValueMod.MaxTargets, 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, SpellImmunity.State, AuraType.ModTaunt, true);
me.ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.AttackMe, true);
_scheduler.Schedule(TimeSpan.FromSeconds(0), GroupIds.Two, context =>
{
SummonWaveP2();
context.Repeat(TimeSpan.FromSeconds(45));
});
}
}
}
public override void SpellHitTarget(Unit target, SpellInfo spell)
{
if (spell.Id == SpellIds.SummonSpirits)
_nextVengefulShadeTargetGUID.Add(target.GetGUID());
}
public override void JustSummoned(Creature summon)
{
switch (summon.GetEntry())
{
case DeprogrammingData.NpcDarnavan10:
case DeprogrammingData.NpcDarnavan25:
_darnavanGUID = summon.GetGUID();
summon.GetAI().AttackStart(SelectTarget(SelectAggroTarget.Random));
return;
case CreatureIds.VengefulShade:
if (_nextVengefulShadeTargetGUID.Empty())
break;
summon.GetAI().SetGUID(_nextVengefulShadeTargetGUID.First());
_nextVengefulShadeTargetGUID.RemoveAt(0);
break;
case CreatureIds.CultAdherent:
case CreatureIds.CultFanatic:
_cultistQueue.Add(summon.GetGUID());
summon.GetAI().AttackStart(SelectTarget(SelectAggroTarget.Random));
break;
default:
break;
}
summons.Summon(summon);
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim() && _phase != Phases.Intro)
return;
_scheduler.Update(diff, () =>
{
// We should not melee attack when barrier is up
if (!me.HasAura(SpellIds.ManaBarrier))
DoMeleeAttackIfReady();
});
}
// summoning function for first phase
void SummonWaveP1()
{
byte addIndex = (byte)(_waveCounter & 1);
byte addIndexOther = (byte)(addIndex ^ 1);
// Summon first add, replace it with Darnavan if weekly quest is active
if (_waveCounter != 0 || !Global.PoolMgr.IsSpawnedObject<Quest>(QUEST_DEPROGRAMMING))
Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3]);
else
Summon(NPC_DARNAVAN, LadyConst.SummonPositions[addIndex * 3]);
Summon(LadyConst.SummonEntries[addIndexOther], LadyConst.SummonPositions[addIndex * 3 + 1]);
Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3 + 2]);
if (Is25ManRaid())
{
Summon(LadyConst.SummonEntries[addIndexOther], LadyConst.SummonPositions[addIndexOther * 3]);
Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndexOther * 3 + 1]);
Summon(LadyConst.SummonEntries[addIndexOther], LadyConst.SummonPositions[addIndexOther * 3 + 2]);
Summon(LadyConst.SummonEntries[RandomHelper.IRand(0, 1)], LadyConst.SummonPositions[6]);
}
++_waveCounter;
}
// summoning function for second phase
void SummonWaveP2()
{
if (Is25ManRaid())
{
byte addIndex = (byte)(_waveCounter & 1);
Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3]);
Summon(LadyConst.SummonEntries[addIndex ^ 1], LadyConst.SummonPositions[addIndex * 3 + 1]);
Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3 + 2]);
}
else
Summon(LadyConst.SummonEntries[RandomHelper.IRand(0, 1)], LadyConst.SummonPositions[6]);
++_waveCounter;
}
// helper for summoning wave mobs
void Summon(uint entry, Position pos)
{
TempSummon summon = me.SummonCreature(entry, pos, TempSummonType.CorpseTimedDespawn, 10000);
if (summon)
summon.CastSpell(summon, SpellIds.TeleportVisual);
}
public override void SummonedCreatureDies(Creature summon, Unit killer)
{
if (summon.GetEntry() == CreatureIds.CultAdherent || summon.GetEntry() == CreatureIds.CultFanatic)
_cultistQueue.Remove(summon.GetGUID());
}
void DoImproveCultist()
{
if (_cultistQueue.Empty())
return;
_cultistGUID = _cultistQueue.SelectRandom();
_cultistQueue.Remove(_cultistGUID);
Creature cultist = ObjectAccessor.GetCreature(me, _cultistGUID);
if (!cultist)
return;
if (RandomHelper.RAND(0, 1) != 0)
me.CastSpell(cultist, SpellIds.DarkMartyrdomT);
else
{
me.CastSpell(cultist, cultist.GetEntry() == CreatureIds.CultFanatic ? SpellIds.DarkTransformationT : SpellIds.DarkEmpowermentT, true);
Talk(cultist.GetEntry() == CreatureIds.CultFanatic ? TextIds.SayDarkTransformation : TextIds.SayDarkEmpowerment);
}
}
ObjectGuid _darnavanGUID;
ObjectGuid _cultistGUID;
List<ObjectGuid> _cultistQueue = new List<ObjectGuid>();
List<ObjectGuid> _nextVengefulShadeTargetGUID = new List<ObjectGuid>();
uint _waveCounter;
byte _dominateMindCount;
Phases _phase;
bool _introDone;
uint NPC_DARNAVAN { get { return RaidMode(DeprogrammingData.NpcDarnavan10, DeprogrammingData.NpcDarnavan25, DeprogrammingData.NpcDarnavan10, DeprogrammingData.NpcDarnavan25); } }
uint NPC_DARNAVAN_CREDIT { get { return RaidMode(DeprogrammingData.NpcDarnavanCredit10, DeprogrammingData.NpcDarnavanCredit25, DeprogrammingData.NpcDarnavanCredit10, DeprogrammingData.NpcDarnavanCredit25); } }
uint QUEST_DEPROGRAMMING { get { return RaidMode(WeeklyQuestIds.Deprogramming10, WeeklyQuestIds.Deprogramming25, WeeklyQuestIds.Deprogramming10, WeeklyQuestIds.Deprogramming25); } }
}
[Script]
class npc_cult_fanatic : ScriptedAI
{
public npc_cult_fanatic(Creature creature) : base(creature)
{
_instance = creature.GetInstanceScript();
}
public override void Reset()
{
_scheduler.CancelAll();
_scheduler.SetValidator(() =>
{
return !me.HasUnitState(UnitState.Casting);
});
_scheduler.Schedule(TimeSpan.FromSeconds(17), vampiric_might =>
{
DoCastSelf(SpellIds.VampiricMight);
vampiric_might.Repeat(TimeSpan.FromSeconds(25));
}).Schedule(TimeSpan.FromSeconds(12), shadow_cleave =>
{
DoCastVictim(SpellIds.ShadowCleave);
shadow_cleave.Repeat(TimeSpan.FromSeconds(14));
}).Schedule(TimeSpan.FromSeconds(10), necrotic_strike =>
{
DoCastVictim(SpellIds.NecroticStrike);
necrotic_strike.Repeat(TimeSpan.FromSeconds(17));
});
}
public override void SpellHit(Unit caster, SpellInfo spell)
{
switch (spell.Id)
{
case SpellIds.DarkTransformationT:
me.InterruptNonMeleeSpells(true);
DoCastSelf(SpellIds.DarkTransformation);
break;
case SpellIds.DarkTransformation:
DoCastSelf(SpellIds.FullHeal);
me.UpdateEntry(CreatureIds.DeformedFanatic);
break;
case SpellIds.DarkMartyrdomT:
me.SetReactState(ReactStates.Passive);
me.InterruptNonMeleeSpells(true);
me.AttackStop();
DoCastSelf(SpellIds.DarkMartyrdomFanatic);
break;
case SpellIds.DarkMartyrdomFanatic:
_scheduler.Schedule(TimeSpan.FromSeconds(2), context =>
{
me.UpdateEntry(CreatureIds.ReanimatedFanatic);
DoCastSelf(SpellIds.PermanentFeighDeath);
DoCastSelf(SpellIds.ClearAllDebuffs);
DoCastSelf(SpellIds.FullHeal, true);
me.AddUnitFlag(UnitFlags.Stunned | UnitFlags.Unk29 | UnitFlags.NotSelectable);
}).Schedule(TimeSpan.FromSeconds(6), context =>
{
me.RemoveAurasDueToSpell(SpellIds.PermanentFeighDeath);
me.RemoveUnitFlag(UnitFlags.Stunned | UnitFlags.Unk29 | UnitFlags.NotSelectable);
me.SetReactState(ReactStates.Aggressive);
DoZoneInCombat(me);
Creature ladyDeathwhisper = ObjectAccessor.GetCreature(me, _instance.GetGuidData(Bosses.LadyDeathwhisper));
if (ladyDeathwhisper != null)
ladyDeathwhisper.GetAI().Talk(TextIds.SayAnimateDead);
});
break;
default:
break;
}
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim() && !me.HasAura(SpellIds.PermanentFeighDeath))
return;
_scheduler.Update(diff, () =>
{
DoMeleeAttackIfReady();
});
}
InstanceScript _instance;
}
[Script]
class npc_cult_adherent : ScriptedAI
{
public npc_cult_adherent(Creature creature) : base(creature)
{
_instance = creature.GetInstanceScript();
}
public override void Reset()
{
_scheduler.CancelAll();
_scheduler.SetValidator(() =>
{
return !me.HasUnitState(UnitState.Casting);
});
_scheduler.Schedule(TimeSpan.FromSeconds(5), deathchill =>
{
if (me.GetEntry() == CreatureIds.EmpoweredAdherent)
DoCastVictim(SpellIds.DeathchillBlast);
else
DoCastVictim(SpellIds.DeathchillBolt);
deathchill.Repeat(TimeSpan.FromMilliseconds(2500));
}).Schedule(TimeSpan.FromSeconds(15), shroud_of_the_occult =>
{
DoCastSelf(SpellIds.ShorudOfTheOccult);
shroud_of_the_occult.Repeat(TimeSpan.FromSeconds(10));
}).Schedule(TimeSpan.FromSeconds(15), curse_of_torpor =>
{
Unit target = SelectTarget(SelectAggroTarget.Random, 1);
if (target != null)
DoCast(target, SpellIds.CurseOfTorpor);
curse_of_torpor.Repeat(TimeSpan.FromSeconds(18));
});
}
public override void SpellHit(Unit caster, SpellInfo spell)
{
switch (spell.Id)
{
case SpellIds.DarkEmpowermentT:
me.UpdateEntry(CreatureIds.EmpoweredAdherent);
break;
case SpellIds.DarkMartyrdomT:
me.SetReactState(ReactStates.Passive);
me.InterruptNonMeleeSpells(true);
me.AttackStop();
DoCastSelf(SpellIds.DarkMartyrdomAdherent);
break;
case SpellIds.DarkMartyrdomAdherent:
_scheduler.Schedule(TimeSpan.FromSeconds(2), context =>
{
me.UpdateEntry(CreatureIds.ReanimatedAdherent);
DoCastSelf(SpellIds.PermanentFeighDeath);
DoCastSelf(SpellIds.ClearAllDebuffs);
DoCastSelf(SpellIds.FullHeal, true);
me.AddUnitFlag(UnitFlags.Stunned | UnitFlags.Unk29 | UnitFlags.NotSelectable);
}).Schedule(TimeSpan.FromSeconds(6), context =>
{
me.RemoveAurasDueToSpell(SpellIds.PermanentFeighDeath);
me.RemoveUnitFlag(UnitFlags.Stunned | UnitFlags.Unk29 | UnitFlags.NotSelectable);
me.SetReactState(ReactStates.Aggressive);
DoCastSelf(SpellIds.ShorudOfTheOccult);
DoZoneInCombat(me);
Creature ladyDeathwhisper = ObjectAccessor.GetCreature(me, _instance.GetGuidData(Bosses.LadyDeathwhisper));
if (ladyDeathwhisper != null)
ladyDeathwhisper.GetAI().Talk(TextIds.SayAnimateDead);
});
break;
default:
break;
}
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim() && !me.HasAura(SpellIds.PermanentFeighDeath))
return;
_scheduler.Update(diff);
}
InstanceScript _instance;
}
[Script]
class npc_vengeful_shade : ScriptedAI
{
public npc_vengeful_shade(Creature creature) : base(creature) { }
public override void Reset()
{
me.SetReactState(ReactStates.Passive);
me.AddAura(SpellIds.VengefulBlastPassive, me);
_scheduler.Schedule(TimeSpan.FromSeconds(2), context =>
{
me.SetReactState(ReactStates.Aggressive);
me.GetAI().AttackStart(Global.ObjAccessor.GetUnit(me, _targetGUID));
}).Schedule(TimeSpan.FromSeconds(7), context =>
{
me.KillSelf();
});
}
public override void SetGUID(ObjectGuid guid, int id = 0)
{
_targetGUID = guid;
}
public override void SpellHitTarget(Unit target, SpellInfo spell)
{
switch (spell.Id)
{
case SpellIds.VengefulBlast:
case SpellIds.VengefulBlast25N:
case SpellIds.VengefulBlast10H:
case SpellIds.VengefulBlast25H:
me.KillSelf();
break;
default:
break;
}
}
public override void UpdateAI(uint diff)
{
_scheduler.Update(diff, () =>
{
DoMeleeAttackIfReady();
});
}
ObjectGuid _targetGUID;
}
[Script]
class npc_darnavan : ScriptedAI
{
public npc_darnavan(Creature creature) : base(creature)
{
Initialize();
}
void Initialize()
{
_canCharge = true;
_canShatter = true;
}
public override void Reset()
{
_events.Reset();
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_BLADESTORM, 10000);
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_INTIMIDATING_SHOUT, RandomHelper.URand(20000, 25000));
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_MORTAL_STRIKE, RandomHelper.URand(25000, 30000));
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_SUNDER_ARMOR, RandomHelper.URand(5000, 8000));
Initialize();
}
public override void JustDied(Unit killer)
{
_events.Reset();
Player owner = killer.GetCharmerOrOwnerPlayerOrPlayerItself();
if (owner)
{
Group group = owner.GetGroup();
if (group)
{
for (GroupReference groupRefe = group.GetFirstMember(); groupRefe != null; groupRefe = groupRefe.next())
{
Player member = groupRefe.GetSource();
if (member)
member.FailQuest(QUEST_DEPROGRAMMING);
}
}
else
owner.FailQuest(QUEST_DEPROGRAMMING);
}
}
public override void MovementInform(MovementGeneratorType type, uint id)
{
if (type != MovementGeneratorType.Point || id != DeprogrammingData.POINT_DESPAWN)
return;
me.DespawnOrUnsummon();
}
public override void EnterCombat(Unit victim)
{
Talk(TextIds.SayDarnavanAggro);
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_events.Update(diff);
if (me.HasUnitState(UnitState.Casting))
return;
if (_canShatter && me.GetVictim() && me.GetVictim().IsImmunedToDamage(SpellSchoolMask.Normal))
{
DoCastVictim(SpellIds.ShatteringThrow);
_canShatter = false;
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_SHATTERING_THROW, 30000);
return;
}
if (_canCharge && !me.IsWithinMeleeRange(me.GetVictim()))
{
DoCastVictim(SpellIds.Charge);
_canCharge = false;
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_CHARGE, 20000);
return;
}
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case LadyEventTypes.DARNAVAN_BLADESTORM:
DoCast(SpellIds.Bladestorm);
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_BLADESTORM, RandomHelper.URand(90000, 100000));
break;
case LadyEventTypes.DARNAVAN_CHARGE:
_canCharge = true;
break;
case LadyEventTypes.DARNAVAN_INTIMIDATING_SHOUT:
DoCast(SpellIds.IntimidatingShout);
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_INTIMIDATING_SHOUT, RandomHelper.URand(90000, 120000));
break;
case LadyEventTypes.DARNAVAN_MORTAL_STRIKE:
DoCastVictim(SpellIds.MortalStrike);
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_MORTAL_STRIKE, RandomHelper.URand(15000, 30000));
break;
case LadyEventTypes.DARNAVAN_SHATTERING_THROW:
_canShatter = true;
break;
case LadyEventTypes.DARNAVAN_SUNDER_ARMOR:
DoCastVictim(SpellIds.SunderArmor);
_events.ScheduleEvent(LadyEventTypes.DARNAVAN_SUNDER_ARMOR, RandomHelper.URand(3000, 7000));
break;
}
});
DoMeleeAttackIfReady();
}
uint QUEST_DEPROGRAMMING { get { return RaidMode<uint>(WeeklyQuestIds.Deprogramming10, WeeklyQuestIds.Deprogramming25, WeeklyQuestIds.Deprogramming10, WeeklyQuestIds.Deprogramming25); } }
bool _canCharge;
bool _canShatter;
}
[Script]
class spell_deathwhisper_mana_barrier : AuraScript
{
void HandlePeriodicTick(AuraEffect aurEff)
{
PreventDefaultAction();
Unit caster = GetCaster();
if (caster)
{
int missingHealth = (int)(caster.GetMaxHealth() - caster.GetHealth());
caster.ModifyHealth(missingHealth);
caster.ModifyPower(PowerType.Mana, -missingHealth);
}
}
public override void Register()
{
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodicTick, 0, AuraType.PeriodicTriggerSpell));
}
}
[Script]
class at_lady_deathwhisper_entrance : AreaTriggerScript
{
public at_lady_deathwhisper_entrance() : base("at_lady_deathwhisper_entrance") { }
public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered)
{
InstanceScript instance = player.GetInstanceScript();
if (instance != null)
{
if (instance.GetBossState(Bosses.LadyDeathwhisper) != EncounterState.Done)
{
Creature ladyDeathwhisper = ObjectAccessor.GetCreature(player, instance.GetGuidData(Bosses.LadyDeathwhisper));
if (ladyDeathwhisper)
ladyDeathwhisper.GetAI().DoAction(0);
}
}
return true;
}
}
[Script]
class spell_deathwhisper_dominated_mind : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.DominateMindScale);
}
void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit target = GetTarget();
target.CastSpell(target, SpellIds.DominateMindScale, true);
}
public override void Register()
{
AfterEffectApply.Add(new EffectApplyHandler(HandleApply, 0, AuraType.AoeCharm, AuraEffectHandleModes.Real));
}
}
[Script]
class spell_deathwhisper_summon_spirits : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.SummonShade);
}
void HandleScriptEffect(uint effIndex)
{
GetCaster().CastSpell(GetHitUnit(), SpellIds.SummonShade, true);
}
public override void Register()
{
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.Dummy));
}
}
}