From 51e914e0f36c2543be5f988e9d5b77e5707b3aa0 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sat, 22 Aug 2020 15:35:55 -0400 Subject: [PATCH] Scripts/IcecrownCitadel: Prevent players from becoming inaccessible when killed by Lord Marrowgar's Impale spell (the initial damage, not the DoT). Also fix the underlying bug in vehicle logic. Port From (https://github.com/TrinityCore/TrinityCore/commit/e69b5d8fcc44728abd189e4832a383543218e5c1) --- Source/Game/Entities/Vehicle.cs | 7 + .../IcecrownCitadel/LadyDeathwhisper.cs | 1847 +++++++++-------- .../IcecrownCitadel/LordMarrowgar.cs | 53 +- 3 files changed, 964 insertions(+), 943 deletions(-) diff --git a/Source/Game/Entities/Vehicle.cs b/Source/Game/Entities/Vehicle.cs index 6176169de..168f7449a 100644 --- a/Source/Game/Entities/Vehicle.cs +++ b/Source/Game/Entities/Vehicle.cs @@ -559,6 +559,13 @@ namespace Game.Entities Target.RemovePendingEventsForSeat(Seat.Key); Target.RemovePendingEventsForPassenger(Passenger); + // Passenger might've died in the meantime - abort if this is the case + if (!Passenger.IsAlive()) + { + Abort(0); + return true; + } + Passenger.SetVehicle(Target); Seat.Value.Passenger.Guid = Passenger.GetGUID(); Seat.Value.Passenger.IsUnselectable = Passenger.HasUnitFlag(UnitFlags.NotSelectable); diff --git a/Source/Scripts/Northrend/IcecrownCitadel/LadyDeathwhisper.cs b/Source/Scripts/Northrend/IcecrownCitadel/LadyDeathwhisper.cs index 102f35497..7f9943434 100644 --- a/Source/Scripts/Northrend/IcecrownCitadel/LadyDeathwhisper.cs +++ b/Source/Scripts/Northrend/IcecrownCitadel/LadyDeathwhisper.cs @@ -31,140 +31,142 @@ using System; namespace Scripts.Northrend.IcecrownCitadel { - struct TextIds + namespace LadyDeathwhisper { - // 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 = + 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) @@ -173,858 +175,859 @@ namespace Scripts.Northrend.IcecrownCitadel 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) + class DaranavanMoveEvent : BasicEvent { - _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(0, 1, 1, 3); - _introDone = false; - Initialize(); - } - - void Initialize() - { - _waveCounter = 0; - _nextVengefulShadeTargetGUID.Clear(); - _cultistQueue.Clear(); - _darnavanGUID.Clear(); - _phase = Phases.All; - _scheduler.SetValidator(() => + public DaranavanMoveEvent(Creature darnavan) { - 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; + _darnavan = darnavan; } - me.SetCombatPulseDelay(5); - me.SetActive(true); - DoZoneInCombat(); - _phase = Phases.One; - _scheduler.CancelGroup(GroupIds.Intro); + public override bool Execute(ulong time, uint diff) + { + _darnavan.GetMotionMaster().MovePoint(DeprogrammingData.POINT_DESPAWN, LadyConst.SummonPositions[6]); + return true; + } - // 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)); - }); + Creature _darnavan; + } - if (GetDifficulty() != Difficulty.Raid10N) + [Script] + public class boss_lady_deathwhisper : BossAI + { + public boss_lady_deathwhisper(Creature creature) : base(creature, Bosses.LadyDeathwhisper) { - _scheduler.Schedule(TimeSpan.FromSeconds(27), dominate_mind => + _dominateMindCount = RaidMode(0, 1, 1, 3); + _introDone = false; + Initialize(); + } + + void Initialize() + { + _waveCounter = 0; + _nextVengefulShadeTargetGUID.Clear(); + _cultistQueue.Clear(); + _darnavanGUID.Clear(); + _phase = Phases.All; + _scheduler.SetValidator(() => { - Talk(TextIds.SayDominateMind); - for (byte i = 0; i < _dominateMindCount; i++) - { - Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true, false, -(int)SpellIds.DominateMind); - if (target != null) - DoCast(target, SpellIds.DominateMind); - } - dominate_mind.Repeat(TimeSpan.FromSeconds(40), TimeSpan.FromSeconds(45)); + return !(me.HasUnitState(UnitState.Casting) && _phase != Phases.Intro); }); } - // phase one only - _scheduler.Schedule(TimeSpan.FromSeconds(5), GroupIds.One, wave => + public override void Reset() { - 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 livingAddEntries = new List(); - // 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()); + _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); } - if (livingAddEntries.Count >= 5) - instance.DoUpdateCriteria(CriteriaTypes.BeSpellTarget, SpellIds.FullHouse, 0, me); - - Creature darnavan = ObjectAccessor.GetCreature(me, _darnavanGUID); - if (darnavan) + public override void DoAction(int action) { - if (darnavan.IsAlive()) + if (action != 0) + return; + + if (!_introDone) { - 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) + _introDone = true; + Talk(TextIds.SayIntro1); + _phase = Phases.Intro; + _scheduler.Schedule(TimeSpan.FromSeconds(10), GroupIds.Intro, task => { - Group group = owner.GetGroup(); - if (group) + switch (task.GetRepeatCounter()) { - for (GroupReference groupRefe = group.GetFirstMember(); groupRefe != null; groupRefe = groupRefe.Next()) - { - Player member = groupRefe.GetSource(); - if (member) - member.KilledMonsterCredit(NPC_DARNAVAN_CREDIT, ObjectGuid.Empty); - } + 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; } - 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()); - ResetThreatList(); - - 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()) + public override void AttackStart(Unit victim) { - case DeprogrammingData.NpcDarnavan10: - case DeprogrammingData.NpcDarnavan25: - _darnavanGUID = summon.GetGUID(); - summon.GetAI().AttackStart(SelectTarget(SelectAggroTarget.Random)); + if (me.HasUnitFlag(UnitFlags.NonAttackable)) 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; + + if (victim && me.Attack(victim, true) && _phase != Phases.One) + me.GetMotionMaster().MoveChase(victim); } - summons.Summon(summon); - } - public override void UpdateAI(uint diff) - { - if (!UpdateVictim() && _phase != Phases.Intro) - return; - - _scheduler.Update(diff, () => + 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, false, -(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 livingAddEntries = new List(); + // 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()); + ResetThreatList(); + + 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_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]); + DoMeleeAttackIfReady(); + }); } - ++_waveCounter; - } - - // summoning function for second phase - void SummonWaveP2() - { - if (Is25ManRaid()) + // summoning function for first phase + void SummonWaveP1() { 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]); + byte addIndexOther = (byte)(addIndex ^ 1); - ++_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 _cultistQueue = new List(); - List _nextVengefulShadeTargetGUID = new List(); - - 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); + // Summon first add, replace it with Darnavan if weekly quest is active + if (_waveCounter != 0 || !Global.PoolMgr.IsSpawnedObject(QUEST_DEPROGRAMMING)) + Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3]); 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)); - }); - } + Summon(NPC_DARNAVAN, LadyConst.SummonPositions[addIndex * 3]); - 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) + Summon(LadyConst.SummonEntries[addIndexOther], LadyConst.SummonPositions[addIndex * 3 + 1]); + Summon(LadyConst.SummonEntries[addIndex], LadyConst.SummonPositions[addIndex * 3 + 2]); + if (Is25ManRaid()) { - for (GroupReference groupRefe = group.GetFirstMember(); groupRefe != null; groupRefe = groupRefe.Next()) + 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 _cultistQueue = new List(); + List _nextVengefulShadeTargetGUID = new List(); + + 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) { - Player member = groupRefe.GetSource(); - if (member) - member.FailQuest(QUEST_DEPROGRAMMING); + 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(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); } } - else - owner.FailQuest(QUEST_DEPROGRAMMING); + + return true; } } - public override void MovementInform(MovementGeneratorType type, uint id) + [Script] + class spell_deathwhisper_dominated_mind : AuraScript { - 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)) + public override bool Validate(SpellInfo spellInfo) { - DoCastVictim(SpellIds.ShatteringThrow); - _canShatter = false; - _events.ScheduleEvent(LadyEventTypes.DARNAVAN_SHATTERING_THROW, 30000); - return; + return ValidateSpellInfo(SpellIds.DominateMindScale); } - if (_canCharge && !me.IsWithinMeleeRange(me.GetVictim())) + void HandleApply(AuraEffect aurEff, AuraEffectHandleModes mode) { - DoCastVictim(SpellIds.Charge); - _canCharge = false; - _events.ScheduleEvent(LadyEventTypes.DARNAVAN_CHARGE, 20000); - return; + Unit target = GetTarget(); + target.CastSpell(target, SpellIds.DominateMindScale, true); } - _events.ExecuteEvents(eventId => + public override void Register() { - 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(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); + AfterEffectApply.Add(new EffectApplyHandler(HandleApply, 0, AuraType.AoeCharm, AuraEffectHandleModes.Real)); } } - public override void Register() + [Script] + class spell_deathwhisper_summon_spirits : SpellScript { - 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) + public override bool Validate(SpellInfo spellInfo) { - if (instance.GetBossState(Bosses.LadyDeathwhisper) != EncounterState.Done) - { - Creature ladyDeathwhisper = ObjectAccessor.GetCreature(player, instance.GetGuidData(Bosses.LadyDeathwhisper)); - if (ladyDeathwhisper) - ladyDeathwhisper.GetAI().DoAction(0); - } + return ValidateSpellInfo(SpellIds.SummonShade); } - return true; - } - } + void HandleScriptEffect(uint effIndex) + { + GetCaster().CastSpell(GetHitUnit(), SpellIds.SummonShade, 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)); + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.Dummy)); + } } } } diff --git a/Source/Scripts/Northrend/IcecrownCitadel/LordMarrowgar.cs b/Source/Scripts/Northrend/IcecrownCitadel/LordMarrowgar.cs index ae656c957..c36dd6aa6 100644 --- a/Source/Scripts/Northrend/IcecrownCitadel/LordMarrowgar.cs +++ b/Source/Scripts/Northrend/IcecrownCitadel/LordMarrowgar.cs @@ -41,7 +41,7 @@ namespace Scripts.Northrend.IcecrownCitadel public const int EmoteBoneStorm = 7; } - struct Spells + struct SpellIds { // Lord Marrowgar public const uint BoneSlice = 69055; @@ -106,7 +106,7 @@ namespace Scripts.Northrend.IcecrownCitadel if (!unit.IsTypeId(TypeId.Player)) return false; - if (unit.HasAura(Spells.Impaled)) + if (unit.HasAura(SpellIds.Impaled)) return false; // Check if it is one of the tanks soaking Bone Slice @@ -136,7 +136,7 @@ namespace Scripts.Northrend.IcecrownCitadel { _Reset(); me.SetSpeedRate(UnitMoveType.Run, _baseSpeed); - me.RemoveAurasDueToSpell(Spells.BoneStorm); + me.RemoveAurasDueToSpell(SpellIds.BoneStorm); me.RemoveAurasDueToSpell(InstanceSpells.Berserk); _events.ScheduleEvent(Misc.EventEnableBoneSlice, 10000); @@ -201,30 +201,30 @@ namespace Scripts.Northrend.IcecrownCitadel switch (eventId) { case Misc.EventBoneSpikeGraveyard: - if (IsHeroic() || !me.HasAura(Spells.BoneStorm)) - DoCast(me, Spells.BoneSpikeGraveyard); + if (IsHeroic() || !me.HasAura(SpellIds.BoneStorm)) + DoCast(me, SpellIds.BoneSpikeGraveyard); _events.ScheduleEvent(Misc.EventBoneSpikeGraveyard, RandomHelper.URand(15000, 20000), Misc.EventGroupSpecial); break; case Misc.EventColdflame: _coldflameLastPos.Relocate(me); _coldflameTarget.Clear(); - if (!me.HasAura(Spells.BoneStorm)) - DoCastAOE(Spells.ColdflameNormal); + if (!me.HasAura(SpellIds.BoneStorm)) + DoCastAOE(SpellIds.ColdflameNormal); else - DoCast(me, Spells.ColdflameBoneStorm); + DoCast(me, SpellIds.ColdflameBoneStorm); _events.ScheduleEvent(Misc.EventColdflame, 5000, Misc.EventGroupSpecial); break; case Misc.EventWarnBoneStorm: _boneSlice = false; Talk(Texts.SayBoneStorm); me.FinishSpell(CurrentSpellTypes.Melee, false); - DoCast(me, Spells.BoneStorm); + DoCast(me, SpellIds.BoneStorm); _events.DelayEvents(3000, Misc.EventGroupSpecial); _events.ScheduleEvent(Misc.EventBoneStormBegin, 3050); _events.ScheduleEvent(Misc.EventWarnBoneStorm, RandomHelper.URand(90000, 95000)); break; case Misc.EventBoneStormBegin: - Aura pStorm = me.GetAura(Spells.BoneStorm); + Aura pStorm = me.GetAura(SpellIds.BoneStorm); if (pStorm != null) pStorm.SetDuration((int)_boneStormDuration); me.SetSpeedRate(UnitMoveType.Run, _baseSpeed * 3.0f); @@ -263,12 +263,12 @@ namespace Scripts.Northrend.IcecrownCitadel }); // We should not melee attack when storming - if (me.HasAura(Spells.BoneStorm)) + if (me.HasAura(SpellIds.BoneStorm)) return; // 10 seconds since encounter start Bone Slice replaces melee attacks if (_boneSlice && !me.GetCurrentSpell(CurrentSpellTypes.Melee)) - DoCastVictim(Spells.BoneSlice); + DoCastVictim(SpellIds.BoneSlice); DoMeleeAttackIfReady(); } @@ -355,7 +355,7 @@ namespace Scripts.Northrend.IcecrownCitadel else pos.Relocate(owner); - if (owner.HasAura(Spells.BoneStorm)) + if (owner.HasAura(SpellIds.BoneStorm)) { float ang = Position.NormalizeOrientation(pos.GetAngle(me)); me.SetOrientation(ang); @@ -376,7 +376,7 @@ namespace Scripts.Northrend.IcecrownCitadel } me.NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me.GetPositionZ(), me.GetOrientation()); - DoCast(Spells.ColdflameSummon); + DoCast(SpellIds.ColdflameSummon); _events.ScheduleEvent(Misc.EventColdflameTrigger, 500); } @@ -388,7 +388,7 @@ namespace Scripts.Northrend.IcecrownCitadel { Position newPos = me.GetNearPosition(5.0f, 0.0f); me.NearTeleportTo(newPos.GetPositionX(), newPos.GetPositionY(), me.GetPositionZ(), me.GetOrientation()); - DoCast(Spells.ColdflameSummon); + DoCast(SpellIds.ColdflameSummon); _events.ScheduleEvent(Misc.EventColdflameTrigger, 500); } } @@ -412,7 +412,7 @@ namespace Scripts.Northrend.IcecrownCitadel { Unit trapped = summ.GetSummoner(); if (trapped) - trapped.RemoveAurasDueToSpell(Spells.Impaled); + trapped.RemoveAurasDueToSpell(SpellIds.Impaled); } me.DespawnOrUnsummon(); @@ -421,13 +421,13 @@ namespace Scripts.Northrend.IcecrownCitadel public override void KilledUnit(Unit victim) { me.DespawnOrUnsummon(); - victim.RemoveAurasDueToSpell(Spells.Impaled); + victim.RemoveAurasDueToSpell(SpellIds.Impaled); } public override void IsSummonedBy(Unit summoner) { - DoCast(summoner, Spells.Impaled); - summoner.CastSpell(me, Spells.RideVehicle, true); + DoCast(summoner, SpellIds.Impaled); + summoner.CastSpell(me, SpellIds.RideVehicle, true); _events.ScheduleEvent(Misc.EventFailBoned, 8000); _hasTrappedUnit = true; } @@ -471,7 +471,7 @@ namespace Scripts.Northrend.IcecrownCitadel { targets.Clear(); // select any unit but not the tank - Unit target = GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 1, -GetCaster().GetCombatReach(), true, false, -(int)Spells.Impaled); + Unit target = GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 1, -GetCaster().GetCombatReach(), true, false, -(int)SpellIds.Impaled); if (!target) target = GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true); // or the tank if its solo if (!target) @@ -516,7 +516,7 @@ namespace Scripts.Northrend.IcecrownCitadel { bool CanBeAppliedOn(Unit target) { - if (target.HasAura(Spells.Impaled)) + if (target.HasAura(SpellIds.Impaled)) return false; SpellEffectInfo effect = GetSpellInfo().GetEffect(0); @@ -573,6 +573,17 @@ namespace Scripts.Northrend.IcecrownCitadel foreach (var target in targets) { target.CastSpell(target, Misc.BoneSpikeSummonId[i], true); + if (!target.IsAlive()) // make sure we don't get any stuck spikes on dead targets + { + Aura aura = target.GetAura(SpellIds.Impaled); + if (aura != null) + { + Creature spike = ObjectAccessor.GetCreature(target, aura.GetCasterGUID()); + if (spike != null) + spike.DespawnOrUnsummon(); + aura.Remove(); + } + } i++; }