From f43ab8cd828ddc7d9b13d7e32ae51a600f5d008d Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 2 Oct 2017 12:55:53 -0400 Subject: [PATCH] Added more Scripts --- .../Northrend/DraktharonKeep/BossTrollgore.cs | 4 +- .../FrozenHalls/ForgeOfSouls/BossBronjahm.cs | 334 ++++++++++++++ .../ForgeOfSouls/BossDevourerOfSouls.cs | 417 ++++++++++++++++++ .../ForgeOfSouls/InstanceForgeOfSouls.cs | 380 ++++++++++++++++ .../PitOfSaron/InstancePitOfSaron.cs | 348 +++++++++++++++ .../FrozenHalls/PitOfSaron/PitOfSaron.cs | 334 ++++++++++++++ Scripts/Scripts.csproj | 7 +- Scripts/Spells/Monk.cs | 4 +- 8 files changed, 1821 insertions(+), 7 deletions(-) create mode 100644 Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossBronjahm.cs create mode 100644 Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossDevourerOfSouls.cs create mode 100644 Scripts/Northrend/FrozenHalls/ForgeOfSouls/InstanceForgeOfSouls.cs create mode 100644 Scripts/Northrend/FrozenHalls/PitOfSaron/InstancePitOfSaron.cs create mode 100644 Scripts/Northrend/FrozenHalls/PitOfSaron/PitOfSaron.cs diff --git a/Scripts/Northrend/DraktharonKeep/BossTrollgore.cs b/Scripts/Northrend/DraktharonKeep/BossTrollgore.cs index 4e8429d49..5bfb07988 100644 --- a/Scripts/Northrend/DraktharonKeep/BossTrollgore.cs +++ b/Scripts/Northrend/DraktharonKeep/BossTrollgore.cs @@ -265,9 +265,7 @@ namespace Scripts.Northrend.DraktharonKeep.Trollgore [Script] class achievement_consumption_junction : AchievementCriteriaScript { - public achievement_consumption_junction() : base("achievement_consumption_junction") - { - } + public achievement_consumption_junction() : base("achievement_consumption_junction") { } public override bool OnCheck(Player source, Unit target) { diff --git a/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossBronjahm.cs b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossBronjahm.cs new file mode 100644 index 000000000..924a8f829 --- /dev/null +++ b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossBronjahm.cs @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2012-2017 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 . + */ + +using Framework.Constants; +using Game.AI; +using Game.Entities; +using Game.Maps; +using Game.Scripting; +using Game.Spells; +using System; +using System.Collections.Generic; + +namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls.Bronjahm +{ + struct TextIds + { + public const uint SayAggro = 0; + public const uint SaySlay = 1; + public const uint SayDeath = 2; + public const uint SaySoulStorm = 3; + public const uint SayCorruptSoul = 4; + } + + struct SpellIds + { + public const uint MagicSBane = 68793; + public const uint ShadowBolt = 70043; + public const uint CorruptSoul = 68839; + public const uint ConsumeSoul = 68861; + public const uint Teleport = 68988; + public const uint Fear = 68950; + public const uint Soulstorm = 68872; + public const uint SoulstormChannel = 69008; // Pre-Fight + public const uint SoulstormVisual = 68870; // Pre-Cast Soulstorm + public const uint PurpleBanishVisual = 68862; // Used By Soul Fragment (Aura) + } + + struct EventIds + { + public const uint MagicBane = 1; + public const uint ShadowBolt = 2; + public const uint CorruptSoul = 3; + public const uint Soulstorm = 4; + public const uint Fear = 5; + } + + struct Misc + { + public const uint DataSoulPower = 1; + + public const byte Phase1 = 1; + public const byte Phase2 = 2; + + public static uint[] SoulstormVisualSpells = + { + 68904, + 68886, + 68905, + 68896, + 68906, + 68897, + 68907, + 68898 + }; + } + + [Script] + class boss_bronjahm : BossAI + { + public boss_bronjahm(Creature creature) : base(creature, DataType.Bronjahm) + { + DoCast(me, SpellIds.SoulstormChannel, true); + } + + public override void Reset() + { + _Reset(); + _events.SetPhase(Misc.Phase1); + _events.ScheduleEvent(EventIds.ShadowBolt, 2000); + _events.ScheduleEvent(EventIds.MagicBane, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(20)); + _events.ScheduleEvent(EventIds.CorruptSoul, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35), 0, Misc.Phase1); + } + + public override void JustReachedHome() + { + _JustReachedHome(); + DoCast(me, SpellIds.SoulstormChannel, true); + } + + public override void EnterCombat(Unit who) + { + _EnterCombat(); + Talk(TextIds.SayAggro); + me.RemoveAurasDueToSpell(SpellIds.SoulstormChannel); + } + + public override void JustDied(Unit killer) + { + _JustDied(); + Talk(TextIds.SayDeath); + } + + public override void KilledUnit(Unit who) + { + if (who.GetTypeId() == TypeId.Player) + Talk(TextIds.SaySlay); + } + + public override void DamageTaken(Unit attacker, ref uint damage) + { + if (_events.IsInPhase(Misc.Phase1) && !HealthAbovePct(30)) + { + _events.SetPhase(Misc.Phase2); + DoCast(me, SpellIds.Teleport); + _events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16), 0, Misc.Phase2); + _events.ScheduleEvent(EventIds.Soulstorm, 100, 0, Misc.Phase2); + } + } + + public override void JustSummoned(Creature summon) + { + if (summon.GetEntry() == CreatureIds.CorruptedSoulFragment) + { + summons.Summon(summon); + summon.SetReactState(ReactStates.Passive); + summon.GetMotionMaster().MoveFollow(me, me.GetObjectSize(), 0.0f); + summon.CastSpell(summon, SpellIds.PurpleBanishVisual, true); + } + } + + public override uint GetData(uint type) + { + if (type == Misc.DataSoulPower) + { + uint count = 0; + foreach (ObjectGuid guid in summons) + { + Creature summon = ObjectAccessor.GetCreature(me, guid); + if (summon) + if (summon.GetEntry() == CreatureIds.CorruptedSoulFragment && summon.IsAlive()) + ++count; + } + + return count; + } + + return 0; + } + + public override void UpdateAI(uint diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me.HasUnitState(UnitState.Casting)) + return; + + _events.ExecuteEvents(eventId => + { + switch (eventId) + { + case EventIds.MagicBane: + DoCastAOE(SpellIds.MagicSBane); + _events.ScheduleEvent(EventIds.MagicBane, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(20)); + break; + case EventIds.ShadowBolt: + if (_events.IsInPhase(Misc.Phase2)) + { + DoCastVictim(SpellIds.ShadowBolt); + _events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(2)); + } + else + { + if (!me.IsWithinMeleeRange(me.GetVictim())) + DoCastVictim(SpellIds.ShadowBolt); + _events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromMilliseconds(2)); + } + break; + case EventIds.CorruptSoul: + Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true); + if (target) + { + Talk(TextIds.SayCorruptSoul); + DoCast(target, SpellIds.CorruptSoul); + } + _events.ScheduleEvent(EventIds.CorruptSoul, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35), 0, Misc.Phase1); + break; + case EventIds.Soulstorm: + Talk(TextIds.SaySoulStorm); + me.CastSpell(me, SpellIds.SoulstormVisual, true); + me.CastSpell(me, SpellIds.Soulstorm, false); + break; + case EventIds.Fear: + me.CastCustomSpell(SpellIds.Fear, SpellValueMod.MaxTargets, 1, null, false); + _events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12), 0, Misc.Phase2); + break; + default: + break; + } + + if (me.HasUnitState(UnitState.Casting)) + return; + }); + + if (!_events.IsInPhase(Misc.Phase2)) + DoMeleeAttackIfReady(); + } + } + + [Script] + class npc_corrupted_soul_fragmentAI : ScriptedAI + { + public npc_corrupted_soul_fragmentAI(Creature creature) : base(creature) + { + instance = me.GetInstanceScript(); + } + + public override void IsSummonedBy(Unit summoner) + { + Creature bronjahm = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataType.Bronjahm)); + if (bronjahm) + bronjahm.GetAI().JustSummoned(me); + } + + public override void MovementInform(MovementGeneratorType type, uint id) + { + if (type != MovementGeneratorType.Follow) + return; + + if (instance.GetGuidData(DataType.Bronjahm).GetCounter() != id) + return; + + me.CastSpell((Unit)null, SpellIds.ConsumeSoul, true); + me.DespawnOrUnsummon(); + } + + InstanceScript instance; + } + + [Script] + class spell_bronjahm_magic_bane : SpellScript + { + void RecalculateDamage() + { + if (GetHitUnit().getPowerType() != PowerType.Mana) + return; + + int maxDamage = GetCaster().GetMap().IsHeroic() ? 15000 : 10000; + int newDamage = GetHitDamage() + (GetHitUnit().GetMaxPower(PowerType.Mana) / 2); + + SetHitDamage(Math.Min(maxDamage, newDamage)); + } + + public override void Register() + { + OnHit.Add(new HitHandler(RecalculateDamage)); + } + } + + [Script] + class spell_bronjahm_consume_soul : SpellScript + { + void HandleScript(uint effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect)); + } + } + + [Script] + class spell_bronjahm_soulstorm_visual : AuraScript + { + void HandlePeriodicTick(AuraEffect aurEff) + { + PreventDefaultAction(); + GetTarget().CastSpell(GetTarget(), Misc.SoulstormVisualSpells[aurEff.GetTickNumber() % 8], true); + } + + public override void Register() + { + OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodicTick, 0, AuraType.PeriodicDummy)); + } + } + + [Script] + class spell_bronjahm_soulstorm_targeting : SpellScript + { + void FilterTargets(List targets) + { + Unit caster = GetCaster(); + targets.RemoveAll(target => + { + return caster.GetExactDist2d(target) <= 10.0f; + }); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, SpellConst.EffectAll, Targets.UnitDestAreaEnemy)); + } + } + + [Script] + class achievement_bronjahm_soul_power : AchievementCriteriaScript + { + public achievement_bronjahm_soul_power() : base("achievement_bronjahm_soul_power") { } + + public override bool OnCheck(Player source, Unit target) + { + return target && target.GetAI().GetData(Misc.DataSoulPower) >= 4; + } + } +} diff --git a/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossDevourerOfSouls.cs b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossDevourerOfSouls.cs new file mode 100644 index 000000000..2735691e8 --- /dev/null +++ b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/BossDevourerOfSouls.cs @@ -0,0 +1,417 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Game.Entities; +using Framework.Constants; +using Game.Scripting; +using Game.AI; +using Game.Spells; + +namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls.DevourerOfSouls +{ + struct TextIds + { + public const uint SayFaceAggro = 0; + public const byte SayFaceAngerSlay = 1; + public const byte SayFaceSorrowSlay = 2; + public const byte SayFaceDesireSlay = 3; + public const uint SayFaceDeath = 4; + public const uint EmoteMirroredSoul = 5; + public const uint EmoteUnleashSoul = 6; + public const uint SayFaceUnleashSoul = 7; + public const uint EmoteWailingSoul = 8; + public const uint SayFaceWailingSoul = 9; + + public const uint SayJainaOutro = 0; + public const uint SaySylvanasOutro = 0; + } + + struct SpellIds + { + public const uint PhantomBlast = 68982; + public const uint MirroredSoulProcAura = 69023; + public const uint MirroredSoulDamage = 69034; + public const uint MirroredSoulTargetSelector = 69048; + public const uint MirroredSoulBuff = 69051; + public const uint WellOfSouls = 68820; + public const uint UnleashedSouls = 68939; + public const uint WailingSoulsStarting = 68912; // Initial Spell Cast At Begining Of Wailing Souls Phase + public const uint WailingSoulsBeam = 68875; // The Beam Visual + public const uint WailingSouls = 68873; // The Actual Spell + // 68871; 68873; 68875; 68876; 68899; 68912; 70324; + // 68899 Trigger 68871 + } + + struct ModelIds + { + public const uint Anger = 30148; + public const uint Sorrow = 30149; + public const uint Desire = 30150; + } + + struct Misc + { + public const uint DataThreeFaced = 1; + + public static outroPosition[] outroPositions = + { + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5590.47f, 2427.79f, 705.935f, 0.802851f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5593.59f, 2428.34f, 705.935f, 0.977384f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5600.81f, 2429.31f, 705.935f, 0.890118f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5600.81f, 2421.12f, 705.935f, 0.890118f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5601.43f, 2426.53f, 705.935f, 0.890118f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5601.55f, 2418.36f, 705.935f, 1.15192f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5598, 2429.14f, 705.935f, 1.0472f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5594.04f, 2424.87f, 705.935f, 1.15192f)), + new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5597.89f, 2421.54f, 705.935f, 0.610865f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5598.57f, 2434.62f, 705.935f, 1.13446f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5585.46f, 2417.99f, 705.935f, 1.06465f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5605.81f, 2428.42f, 705.935f, 0.820305f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5591.61f, 2412.66f, 705.935f, 0.925025f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5593.9f, 2410.64f, 705.935f, 0.872665f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5586.76f, 2416.73f, 705.935f, 0.942478f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5592.23f, 2419.14f, 705.935f, 0.855211f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5594.61f, 2416.87f, 705.935f, 0.907571f)), + new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5589.77f, 2421.03f, 705.935f, 0.855211f)), + + new outroPosition(CreatureIds.Koreln, CreatureIds.Loralen, new Position(5602.58f, 2435.95f, 705.935f, 0.959931f)), + new outroPosition(CreatureIds.Elandra, CreatureIds.Kalira, new Position(5606.13f, 2433.16f, 705.935f, 0.785398f)), + new outroPosition(CreatureIds.JainaPart2, CreatureIds.SylvanasPart2, new Position(5606.12f, 2436.6f, 705.935f, 0.890118f)), + }; + + public static Position CrucibleSummonPos = new Position(5672.294f, 2520.686f, 713.4386f, 0.9599311f); + } + + struct outroPosition + { + public outroPosition(uint allianceEntry, uint hordeEntry, Position movePosition) + { + Entry = new uint[2]; + Entry[0] = allianceEntry; + Entry[1] = hordeEntry; + + MovePosition = movePosition; + } + + public uint[] Entry; + public Position MovePosition; + } + + [Script] + class boss_devourer_of_souls : BossAI + { + public boss_devourer_of_souls(Creature creature) : base(creature, DataType.DevourerOfSouls) + { + Initialize(); + beamAngle = 0.0f; + beamAngleDiff = 0.0f; + wailingSoulTick = 0; + } + + void Initialize() + { + threeFaced = true; + } + + public override void Reset() + { + _Reset(); + me.SetControlled(false, UnitState.Root); + me.SetDisplayId(ModelIds.Anger); + me.SetReactState(ReactStates.Aggressive); + + Initialize(); + } + + public override void EnterCombat(Unit who) + { + _EnterCombat(); + Talk(TextIds.SayFaceAggro); + + if (!me.FindNearestCreature(CreatureIds.CrucibleOfSouls, 60)) // Prevent double spawn + me.GetMap().SummonCreature(CreatureIds.CrucibleOfSouls, Misc.CrucibleSummonPos); + + _scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting)); + + _scheduler.Schedule(TimeSpan.FromSeconds(5), task => + { + DoCastVictim(SpellIds.PhantomBlast); + task.Repeat(TimeSpan.FromSeconds(5)); + }); + + _scheduler.Schedule(TimeSpan.FromSeconds(8), task => + { + DoCastAOE(SpellIds.MirroredSoulTargetSelector); + Talk(TextIds.EmoteMirroredSoul); + task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30)); + }); + + _scheduler.Schedule(TimeSpan.FromSeconds(30), task => + { + Unit target = SelectTarget(SelectAggroTarget.Random, 0); + if (target) + DoCast(target, SpellIds.WellOfSouls); + task.Repeat(TimeSpan.FromSeconds(20)); + }); + + _scheduler.Schedule(TimeSpan.FromSeconds(20), task => + { + Unit target = SelectTarget(SelectAggroTarget.Random, 0); + if (target) + DoCast(target, SpellIds.UnleashedSouls); + me.SetDisplayId(ModelIds.Sorrow); + Talk(TextIds.SayFaceUnleashSoul); + Talk(TextIds.EmoteUnleashSoul); + task.Repeat(TimeSpan.FromSeconds(30)); + task.Schedule(TimeSpan.FromSeconds(5), () => me.SetDisplayId(ModelIds.Anger)); + }); + + _scheduler.Schedule(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(70), task => + { + me.SetDisplayId(ModelIds.Desire); + Talk(TextIds.SayFaceWailingSoul); + Talk(TextIds.EmoteWailingSoul); + DoCast(me, SpellIds.WailingSoulsStarting); + Unit target = SelectTarget(SelectAggroTarget.Random, 0); + if (target) + { + me.SetFacingToObject(target); + DoCast(me, SpellIds.WailingSoulsBeam); + } + + beamAngle = me.GetOrientation(); + + beamAngleDiff = (float)Math.PI / 30.0f; // PI/2 in 15 sec = PI/30 per tick + if (RandomHelper.RAND(true, false)) + beamAngleDiff = -beamAngleDiff; + + me.InterruptNonMeleeSpells(false); + me.SetReactState(ReactStates.Passive); + + //Remove any target + me.SetTarget(ObjectGuid.Empty); + + me.GetMotionMaster().Clear(); + me.SetControlled(true, UnitState.Root); + + wailingSoulTick = 15; + + _scheduler.DelayAll(TimeSpan.FromSeconds(18)); // no other events during wailing souls + + // first one after 3 secs. + _scheduler.Schedule(TimeSpan.FromSeconds(3), tickTask => + { + beamAngle += beamAngleDiff; + me.SetFacingTo(beamAngle, true); + me.StopMoving(); + + DoCast(me, SpellIds.WailingSouls); + + if (--wailingSoulTick != 0) + tickTask.Repeat(TimeSpan.FromSeconds(1)); + else + { + me.SetReactState(ReactStates.Aggressive); + me.SetDisplayId(ModelIds.Anger); + me.SetControlled(false, UnitState.Root); + me.GetMotionMaster().MoveChase(me.GetVictim()); + task.Repeat(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(70)); + } + }); + }); + } + + public override void KilledUnit(Unit victim) + { + if (victim.GetTypeId() != TypeId.Player) + return; + + byte textId = 0; + switch (me.GetDisplayId()) + { + case ModelIds.Anger: + textId = TextIds.SayFaceAngerSlay; + break; + case ModelIds.Sorrow: + textId = TextIds.SayFaceSorrowSlay; + break; + case ModelIds.Desire: + textId = TextIds.SayFaceDesireSlay; + break; + default: + break; + } + + if (textId != 0) + Talk(textId); + } + + public override void JustDied(Unit killer) + { + _JustDied(); + + Position spawnPoint = new Position(5618.139f, 2451.873f, 705.854f, 0); + + Talk(TextIds.SayFaceDeath); + + int entryIndex; + if (instance.GetData(DataType.TeamInInstance) == (uint)Team.Alliance) + entryIndex = 0; + else + entryIndex = 1; + + for (var i = 0; Misc.outroPositions[i].Entry[entryIndex] != 0; ++i) + { + Creature summon = me.SummonCreature(Misc.outroPositions[i].Entry[entryIndex], spawnPoint, TempSummonType.DeadDespawn); + if (summon) + { + summon.GetMotionMaster().MovePoint(0, Misc.outroPositions[i].MovePosition); + if (summon.GetEntry() == CreatureIds.JainaPart2) + summon.GetAI().Talk(TextIds.SayJainaOutro); + else if (summon.GetEntry() == CreatureIds.SylvanasPart2) + summon.GetAI().Talk(TextIds.SaySylvanasOutro); + } + } + } + + public override void SpellHitTarget(Unit target, SpellInfo spell) + { + if (spell.Id == SpellIds.PhantomBlast) + threeFaced = false; + } + + public override uint GetData(uint type) + { + if (type == Misc.DataThreeFaced) + return threeFaced ? 1 : 0u; + + return 0; + } + + public override void UpdateAI(uint diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + if (me.HasUnitState(UnitState.Casting)) + return; + + DoMeleeAttackIfReady(); + } + + bool threeFaced; + + // wailing soul event + float beamAngle; + float beamAngleDiff; + sbyte wailingSoulTick; + } + + [Script] // 69051 - Mirrored Soul + class spell_devourer_of_souls_mirrored_soul : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MirroredSoulProcAura); + } + + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target) + target.CastSpell(GetCaster(), SpellIds.MirroredSoulProcAura, true); + } + + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect)); + } + } + + [Script] // 69023 - Mirrored Soul (Proc) + class spell_devourer_of_souls_mirrored_soul_proc : AuraScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MirroredSoulDamage); + } + + bool CheckProc(ProcEventInfo eventInfo) + { + return GetCaster() && GetCaster().IsAlive(); + } + + void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo) + { + PreventDefaultAction(); + DamageInfo damageInfo = eventInfo.GetDamageInfo(); + if (damageInfo == null || damageInfo.GetDamage() == 0) + return; + + int damage = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), 45); + GetTarget().CastCustomSpell(SpellIds.MirroredSoulDamage, SpellValueMod.BasePoint0, damage, GetCaster(), true); + } + + public override void Register() + { + DoCheckProc.Add(new CheckProcHandler(CheckProc)); + OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, AuraType.ProcTriggerSpell)); + } + } + + [Script] // 69048 - Mirrored Soul (Target Selector) + class spell_devourer_of_souls_mirrored_soul_target_selector : SpellScript + { + public override bool Validate(SpellInfo spellInfo) + { + return ValidateSpellInfo(SpellIds.MirroredSoulBuff); + } + + void FilterTargets(List targets) + { + if (targets.Empty()) + return; + + WorldObject target = targets.SelectRandom(); + targets.Clear(); + targets.Add(target); + } + + void HandleScript(uint effIndex) + { + Unit target = GetHitUnit(); + if (target) + GetCaster().CastSpell(target, SpellIds.MirroredSoulBuff, false); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitSrcAreaEntry)); + OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect)); + } + } + + [Script] + class achievement_three_faced : AchievementCriteriaScript + { + public achievement_three_faced() : base("achievement_three_faced") { } + + public override bool OnCheck(Player player, Unit target) + { + if (!target) + return false; + + Creature devourer = target.ToCreature(); + if (devourer) + if (devourer.GetAI().GetData(Misc.DataThreeFaced) != 0) + return true; + + return false; + } + } +} diff --git a/Scripts/Northrend/FrozenHalls/ForgeOfSouls/InstanceForgeOfSouls.cs b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/InstanceForgeOfSouls.cs new file mode 100644 index 000000000..eaea6e498 --- /dev/null +++ b/Scripts/Northrend/FrozenHalls/ForgeOfSouls/InstanceForgeOfSouls.cs @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2012-2017 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 . + */ + +using Framework.Constants; +using Game.AI; +using Game.Entities; +using Game.Maps; +using Game.Scripting; +using System.Collections.Generic; + +namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls +{ + struct DataType + { + // Encounter states and GUIDs + public const uint Bronjahm = 0; + public const uint DevourerOfSouls = 1; + + // Additional Data + public const uint TeamInInstance = 2; + } + + struct CreatureIds + { + public const uint Bronjahm = 36497; + public const uint Devourer = 36502; + public const uint CorruptedSoulFragment = 36535; + + public const uint SylvanasPart1 = 37596; + public const uint SylvanasPart2 = 38161; + public const uint JainaPart1 = 37597; + public const uint JainaPart2 = 38160; + public const uint Kalira = 37583; + public const uint Elandra = 37774; + public const uint Loralen = 37779; + public const uint Koreln = 37582; + public const uint Champion1Horde = 37584; + public const uint Champion2Horde = 37587; + public const uint Champion3Horde = 37588; + public const uint Champion1Alliance = 37496; + public const uint Champion2Alliance = 37497; + public const uint CrucibleOfSouls = 37094; + } + + struct EventIds + { + public const uint None = 0; + + // Jaina/Sylvanas Intro + public const uint Intro1 = 1; + public const uint Intro2 = 2; + public const uint Intro3 = 3; + public const uint Intro4 = 4; + public const uint Intro5 = 5; + public const uint Intro6 = 6; + public const uint Intro7 = 7; + public const uint Intro8 = 8; + } + + struct TextIds + { + public const uint SayJainaIntro1 = 0; + public const uint SayJainaIntro2 = 1; + public const uint SayJainaIntro3 = 2; + public const uint SayJainaIntro4 = 3; + public const uint SayJainaIntro5 = 4; + public const uint SayJainaIntro6 = 5; + public const uint SayJainaIntro7 = 6; + public const uint SayJainaIntro8 = 7; + + public const uint SaySylvanasIntro1 = 0; + public const uint SaySylvanasIntro2 = 1; + public const uint SaySylvanasIntro3 = 2; + public const uint SaySylvanasIntro4 = 3; + public const uint SaySylvanasIntro5 = 4; + public const uint SaySylvanasIntro6 = 5; + } + + struct Misc + { + public const uint MenuIdJaina = 10943; + public const uint MenuIdSylvanas = 10971; + public const uint GossipOptionId = 0; + } + + enum Phase + { + Normal, + Intro, + } + + [Script] + class instance_forge_of_souls : InstanceMapScript + { + public instance_forge_of_souls() : base(nameof(instance_forge_of_souls), 632) { } + + class instance_forge_of_souls_InstanceScript : InstanceScript + { + public instance_forge_of_souls_InstanceScript(Map map) : base(map) + { + SetHeaders("FOS"); + SetBossNumber(2); + + teamInInstance = 0; + } + + public override void OnPlayerEnter(Player player) + { + if (teamInInstance == 0) + teamInInstance = player.GetTeam(); + } + + public override void OnCreatureCreate(Creature creature) + { + if (teamInInstance == 0) + { + var players = instance.GetPlayers(); + if (!players.Empty()) + { + Player player = players[0]; + if (player) + teamInInstance = player.GetTeam(); + } + } + + switch (creature.GetEntry()) + { + case CreatureIds.Bronjahm: + bronjahm = creature.GetGUID(); + break; + case CreatureIds.Devourer: + devourerOfSouls = creature.GetGUID(); + break; + case CreatureIds.SylvanasPart1: + if (teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.JainaPart1); + break; + case CreatureIds.Loralen: + if (teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Elandra); + break; + case CreatureIds.Kalira: + if (teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Koreln); + break; + } + } + + public override uint GetData(uint type) + { + switch (type) + { + case DataType.TeamInInstance: + return (uint)teamInInstance; + default: + break; + } + + return 0; + } + + public override ObjectGuid GetGuidData(uint type) + { + switch (type) + { + case DataType.Bronjahm: + return bronjahm; + case DataType.DevourerOfSouls: + return devourerOfSouls; + default: + break; + } + + return ObjectGuid.Empty; + } + + ObjectGuid bronjahm; + ObjectGuid devourerOfSouls; + + Team teamInInstance; + } + + public override InstanceScript GetInstanceScript(InstanceMap map) + { + return new instance_forge_of_souls_InstanceScript(map); + } + } + + [Script] + class npc_sylvanas_fos : ScriptedAI + { + public npc_sylvanas_fos(Creature creature) : base(creature) + { + Initialize(); + me.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip); + } + + void Initialize() + { + phase = Phase.Normal; + } + + public override void Reset() + { + _events.Reset(); + Initialize(); + } + + public override void sGossipSelect(Player player, uint menuId, uint gossipListId) + { + if (menuId == Misc.MenuIdSylvanas && gossipListId == Misc.GossipOptionId) + { + player.CLOSE_GOSSIP_MENU(); + phase = Phase.Intro; + me.RemoveFlag(UnitFields.NpcFlags, NPCFlags.Gossip); + + _events.Reset(); + _events.ScheduleEvent(EventIds.Intro1, 1000); + } + } + + public override void UpdateAI(uint diff) + { + if (phase == Phase.Intro) + { + _events.Update(diff); + switch (_events.ExecuteEvent()) + { + case EventIds.Intro1: + Talk(TextIds.SaySylvanasIntro1); + _events.ScheduleEvent(EventIds.Intro2, 11500); + break; + + case EventIds.Intro2: + Talk(TextIds.SaySylvanasIntro2); + _events.ScheduleEvent(EventIds.Intro3, 10500); + break; + + case EventIds.Intro3: + Talk(TextIds.SaySylvanasIntro3); + _events.ScheduleEvent(EventIds.Intro4, 9500); + break; + + case EventIds.Intro4: + Talk(TextIds.SaySylvanasIntro4); + _events.ScheduleEvent(EventIds.Intro5, 10500); + break; + + case EventIds.Intro5: + Talk(TextIds.SaySylvanasIntro5); + _events.ScheduleEvent(EventIds.Intro6, 9500); + break; + + case EventIds.Intro6: + Talk(TextIds.SaySylvanasIntro6); + // End of Intro + phase = Phase.Normal; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + _events.Update(diff); + DoMeleeAttackIfReady(); + } + + Phase phase; + } + + [Script] + class npc_jaina_fos : ScriptedAI + { + public npc_jaina_fos(Creature creature) : base(creature) + { + Initialize(); + me.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip); + } + + void Initialize() + { + phase = Phase.Normal; + } + + public override void Reset() + { + _events.Reset(); + Initialize(); + } + + public override void sGossipSelect(Player player, uint menuId, uint gossipListId) + { + if (menuId == Misc.MenuIdJaina && gossipListId == Misc.GossipOptionId) + { + player.CLOSE_GOSSIP_MENU(); + phase = Phase.Intro; + me.RemoveFlag(UnitFields.NpcFlags, NPCFlags.Gossip); + _events.Reset(); + _events.ScheduleEvent(EventIds.Intro1, 1000); + } + } + + public override void UpdateAI(uint diff) + { + if (phase == Phase.Intro) + { + _events.Update(diff); + switch (_events.ExecuteEvent()) + { + case EventIds.Intro1: + Talk(TextIds.SayJainaIntro1); + _events.ScheduleEvent(EventIds.Intro2, 8000); + break; + + case EventIds.Intro2: + Talk(TextIds.SayJainaIntro2); + _events.ScheduleEvent(EventIds.Intro3, 8500); + break; + + case EventIds.Intro3: + Talk(TextIds.SayJainaIntro3); + _events.ScheduleEvent(EventIds.Intro4, 8000); + break; + + case EventIds.Intro4: + Talk(TextIds.SayJainaIntro4); + _events.ScheduleEvent(EventIds.Intro5, 10000); + break; + + case EventIds.Intro5: + Talk(TextIds.SayJainaIntro5); + _events.ScheduleEvent(EventIds.Intro6, 8000); + break; + + case EventIds.Intro6: + Talk(TextIds.SayJainaIntro6); + _events.ScheduleEvent(EventIds.Intro7, 12000); + break; + + case EventIds.Intro7: + Talk(TextIds.SayJainaIntro7); + _events.ScheduleEvent(EventIds.Intro8, 8000); + break; + + case EventIds.Intro8: + Talk(TextIds.SayJainaIntro8); + // End of Intro + phase = Phase.Normal; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + _events.Update(diff); + + DoMeleeAttackIfReady(); + } + + Phase phase; + } +} diff --git a/Scripts/Northrend/FrozenHalls/PitOfSaron/InstancePitOfSaron.cs b/Scripts/Northrend/FrozenHalls/PitOfSaron/InstancePitOfSaron.cs new file mode 100644 index 000000000..9d70310ca --- /dev/null +++ b/Scripts/Northrend/FrozenHalls/PitOfSaron/InstancePitOfSaron.cs @@ -0,0 +1,348 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Game.Entities; +using Game.Scripting; +using Game.Maps; +using Framework.Constants; +using Framework.Dynamic; + +namespace Scripts.Northrend.FrozenHalls.PitOfSaron +{ + struct Misc + { + // positions for Martin Victus (37591) and Gorkun Ironskull (37592) + public static Position SlaveLeaderPos = new Position(689.7158f, -104.8736f, 513.7360f, 0.0f); + // position for Jaina and Sylvanas + public static Position EventLeaderPos2 = new Position(1054.368f, 107.14620f, 628.4467f, 0.0f); + + public static DoorData[] Doors = + { + new DoorData(GameObjectIds.IceWall, DataTypes.Garfrost, DoorType.Passage), + new DoorData(GameObjectIds.IceWall, DataTypes.Ick, DoorType.Passage), + new DoorData(GameObjectIds.HallsOfReflectionPortcullis, DataTypes.Tyrannus, DoorType.Passage), + }; + } + + class instance_pit_of_saron : InstanceMapScript + { + public instance_pit_of_saron() : base(nameof(instance_pit_of_saron), 658) { } + + class instance_pit_of_saron_InstanceScript : InstanceScript + { + public instance_pit_of_saron_InstanceScript(Map map) : base(map) + { + SetHeaders("POS"); + SetBossNumber(3); + LoadDoorData(Misc.Doors); + _teamInInstance = 0; + _cavernActive = 0; + _shardsHit = 0; + } + + public override void OnPlayerEnter(Player player) + { + if (_teamInInstance == 0) + _teamInInstance = player.GetTeam(); + } + + public override void OnCreatureCreate(Creature creature) + { + if (_teamInInstance == 0) + { + var players = instance.GetPlayers(); + if (!players.Empty()) + { + Player player = players[0]; + if (player) + _teamInInstance = player.GetTeam(); + } + } + + switch (creature.GetEntry()) + { + case CreatureIds.Garfrost: + _garfrostGUID = creature.GetGUID(); + break; + case CreatureIds.Krick: + _krickGUID = creature.GetGUID(); + break; + case CreatureIds.Ick: + _ickGUID = creature.GetGUID(); + break; + case CreatureIds.Tyrannus: + _tyrannusGUID = creature.GetGUID(); + break; + case CreatureIds.Rimefang: + _rimefangGUID = creature.GetGUID(); + break; + case CreatureIds.TyrannusEvents: + _tyrannusEventGUID = creature.GetGUID(); + break; + case CreatureIds.SylvanasPart1: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.JainaPart1); + _jainaOrSylvanas1GUID = creature.GetGUID(); + break; + case CreatureIds.SylvanasPart2: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.JainaPart2); + _jainaOrSylvanas2GUID = creature.GetGUID(); + break; + case CreatureIds.Kilara: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Elandra); + break; + case CreatureIds.Koralen: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Korlaen); + break; + case CreatureIds.Champion1Horde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Champion1Alliance); + break; + case CreatureIds.Champion2Horde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Champion2Alliance); + break; + case CreatureIds.Champion3Horde: // No 3rd set for Alliance? + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.Champion2Alliance); + break; + case CreatureIds.HordeSlave1: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.AllianceSlave1); + break; + case CreatureIds.HordeSlave2: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.AllianceSlave2); + break; + case CreatureIds.HordeSlave3: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.AllianceSlave3); + break; + case CreatureIds.HordeSlave4: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.AllianceSlave4); + break; + case CreatureIds.FreedSlave1Horde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.FreedSlave1Alliance); + break; + case CreatureIds.FreedSlave2Horde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.FreedSlave2Alliance); + break; + case CreatureIds.FreedSlave3Horde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.FreedSlave3Alliance); + break; + case CreatureIds.RescuedSlaveHorde: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.RescuedSlaveAlliance); + break; + case CreatureIds.MartinVictus1: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.MartinVictus1); + break; + case CreatureIds.MartinVictus2: + if (_teamInInstance == Team.Alliance) + creature.UpdateEntry(CreatureIds.MartinVictus2); + break; + case CreatureIds.CavernEventTrigger: + _cavernstriggersVector.Add(creature.GetGUID()); + break; + default: + break; + } + } + + public override void OnGameObjectCreate(GameObject go) + { + switch (go.GetEntry()) + { + case GameObjectIds.IceWall: + case GameObjectIds.HallsOfReflectionPortcullis: + AddDoor(go, true); + break; + } + } + + public override void OnGameObjectRemove(GameObject go) + { + switch (go.GetEntry()) + { + case GameObjectIds.IceWall: + case GameObjectIds.HallsOfReflectionPortcullis: + AddDoor(go, false); + break; + } + } + + public override bool SetBossState(uint type, EncounterState state) + { + if (!base.SetBossState(type, state)) + return false; + + switch (type) + { + case DataTypes.Garfrost: + if (state == EncounterState.Done) + { + Creature summoner = instance.GetCreature(_garfrostGUID); + if (summoner) + { + if (_teamInInstance == Team.Alliance) + summoner.SummonCreature(CreatureIds.MartinVictus1, Misc.SlaveLeaderPos, TempSummonType.ManualDespawn); + else + summoner.SummonCreature(CreatureIds.GorkunIronskull2, Misc.SlaveLeaderPos, TempSummonType.ManualDespawn); + } + } + break; + case DataTypes.Tyrannus: + if (state == EncounterState.Done) + { + Creature summoner = instance.GetCreature(_tyrannusGUID); + if (summoner) + { + if (_teamInInstance == Team.Alliance) + summoner.SummonCreature(CreatureIds.JainaPart2, Misc.EventLeaderPos2, TempSummonType.ManualDespawn); + else + summoner.SummonCreature(CreatureIds.SylvanasPart2, Misc.EventLeaderPos2, TempSummonType.ManualDespawn); + } + } + break; + default: + break; + } + + return true; + } + + public override uint GetData(uint type) + { + switch (type) + { + case DataTypes.TeamInInstance: + return (uint)_teamInInstance; + case DataTypes.IceShardsHit: + return _shardsHit; + case DataTypes.CavernActive: + return _cavernActive; + default: + break; + } + + return 0; + } + + public override void SetData(uint type, uint data) + { + switch (type) + { + case DataTypes.IceShardsHit: + _shardsHit = (byte)data; + break; + case DataTypes.CavernActive: + if (data != 0) + { + _cavernActive = (byte)data; + HandleCavernEventTrigger(true); + } + else + HandleCavernEventTrigger(false); + break; + default: + break; + } + } + + public override ObjectGuid GetGuidData(uint type) + { + switch (type) + { + case DataTypes.Garfrost: + return _garfrostGUID; + case DataTypes.Krick: + return _krickGUID; + case DataTypes.Ick: + return _ickGUID; + case DataTypes.Tyrannus: + return _tyrannusGUID; + case DataTypes.Rimefang: + return _rimefangGUID; + case DataTypes.TyrannusEvent: + return _tyrannusEventGUID; + case DataTypes.JainaSylvanas1: + return _jainaOrSylvanas1GUID; + case DataTypes.JainaSylvanas2: + return _jainaOrSylvanas2GUID; + default: + break; + } + + return ObjectGuid.Empty; + } + + void HandleCavernEventTrigger(bool activate) + { + foreach (ObjectGuid guid in _cavernstriggersVector) + { + Creature trigger = instance.GetCreature(guid); + if (trigger) + { + if (activate) + trigger.m_Events.AddEvent(new ScheduledIcicleSummons(trigger), trigger.m_Events.CalculateTime(1000)); + else + trigger.m_Events.KillAllEvents(false); + } + } + } + + ObjectGuid _garfrostGUID; + ObjectGuid _krickGUID; + ObjectGuid _ickGUID; + ObjectGuid _tyrannusGUID; + ObjectGuid _rimefangGUID; + + ObjectGuid _tyrannusEventGUID; + ObjectGuid _jainaOrSylvanas1GUID; + ObjectGuid _jainaOrSylvanas2GUID; + List _cavernstriggersVector = new List(); + + Team _teamInInstance; + byte _shardsHit; + byte _cavernActive; + } + + public override InstanceScript GetInstanceScript(InstanceMap map) + { + return new instance_pit_of_saron_InstanceScript(map); + } + } + + class ScheduledIcicleSummons : BasicEvent + { + public ScheduledIcicleSummons(Creature trigger) + { + _trigger = trigger; + } + + public override bool Execute(ulong time, uint diff) + { + if (RandomHelper.randChance(12)) + { + _trigger.CastSpell(_trigger, SpellIds.IcicleSummon, true); + _trigger.m_Events.AddEvent(new ScheduledIcicleSummons(_trigger), _trigger.m_Events.CalculateTime(RandomHelper.URand(20000, 35000))); + } + else + _trigger.m_Events.AddEvent(new ScheduledIcicleSummons(_trigger), _trigger.m_Events.CalculateTime(RandomHelper.URand(1000, 20000))); + + return true; + } + + Creature _trigger; + } +} diff --git a/Scripts/Northrend/FrozenHalls/PitOfSaron/PitOfSaron.cs b/Scripts/Northrend/FrozenHalls/PitOfSaron/PitOfSaron.cs new file mode 100644 index 000000000..0d2a497f4 --- /dev/null +++ b/Scripts/Northrend/FrozenHalls/PitOfSaron/PitOfSaron.cs @@ -0,0 +1,334 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Game.Entities; +using Game.AI; +using Game.Spells; +using Game.DataStorage; +using Game.Scripting; +using Framework.Constants; +using Game.Maps; + +namespace Scripts.Northrend.FrozenHalls.PitOfSaron +{ + struct TextIds + { + public const uint SayTyrannusCavernEntrance = 3; + } + + struct DataTypes + { + // Encounter States And Guids + public const uint Garfrost = 0; + public const uint Ick = 1; + public const uint Tyrannus = 2; + + // Guids + public const uint Rimefang = 3; + public const uint Krick = 4; + public const uint JainaSylvanas1 = 5; // Guid Of Either Jaina Or Sylvanas Part 1; Depending On Team; As It'S The Same Spawn. + public const uint JainaSylvanas2 = 6; // Guid Of Either Jaina Or Sylvanas Part 2; Depending On Team; As It'S The Same Spawn. + public const uint TyrannusEvent = 7; + public const uint TeamInInstance = 8; + public const uint IceShardsHit = 9; + public const uint CavernActive = 10; + } + + struct CreatureIds + { + public const uint Garfrost = 36494; + public const uint Krick = 36477; + public const uint Ick = 36476; + public const uint Tyrannus = 36658; + public const uint Rimefang = 36661; + + public const uint TyrannusEvents = 36794; + public const uint SylvanasPart1 = 36990; + public const uint SylvanasPart2 = 38189; + public const uint JainaPart1 = 36993; + public const uint JainaPart2 = 38188; + public const uint Kilara = 37583; + public const uint Elandra = 37774; + public const uint Koralen = 37779; + public const uint Korlaen = 37582; + public const uint Champion1Horde = 37584; + public const uint Champion2Horde = 37587; + public const uint Champion3Horde = 37588; + public const uint Champion1Alliance = 37496; + public const uint Champion2Alliance = 37497; + + public const uint HordeSlave1 = 36770; + public const uint HordeSlave2 = 36771; + public const uint HordeSlave3 = 36772; + public const uint HordeSlave4 = 36773; + public const uint AllianceSlave1 = 36764; + public const uint AllianceSlave2 = 36765; + public const uint AllianceSlave3 = 36766; + public const uint AllianceSlave4 = 36767; + public const uint FreedSlave1Alliance = 37575; + public const uint FreedSlave2Alliance = 37572; + public const uint FreedSlave3Alliance = 37576; + public const uint FreedSlave1Horde = 37579; + public const uint FreedSlave2Horde = 37578; + public const uint FreedSlave3Horde = 37577; + public const uint RescuedSlaveAlliance = 36888; + public const uint RescuedSlaveHorde = 36889; + public const uint MartinVictus1 = 37591; + public const uint MartinVictus2 = 37580; + public const uint GorkunIronskull1 = 37581; + public const uint GorkunIronskull2 = 37592; + + public const uint ForgemasterStalker = 36495; + public const uint ExplodingOrb = 36610; + public const uint YmirjarDeathbringer = 36892; + public const uint IcyBlast = 36731; + public const uint CavernEventTrigger = 32780; + } + + struct GameObjectIds + { + public const uint SaroniteRock = 196485; + public const uint IceWall = 201885; + public const uint HallsOfReflectionPortcullis = 201848; + } + + struct SpellIds + { + public const uint IcicleSummon = 69424; + public const uint IcicleFallTrigger = 69426; + public const uint IcicleFallVisual = 69428; + public const uint AchievDontLookUpCredit = 72845; + + public const uint Fireball = 69583; //Ymirjar Flamebearer + public const uint Hellfire = 69586; + public const uint TacticalBlink = 69584; + public const uint FrostBreath = 69527; //Iceborn Proto-Drake + public const uint LeapingFaceMaul = 69504; // Geist Ambusher + } + + [Script] + class npc_ymirjar_flamebearer : ScriptedAI + { + public npc_ymirjar_flamebearer(Creature creature) : base(creature) + { + } + + public override void Reset() + { + _scheduler.CancelAll(); + } + + public override void EnterCombat(Unit who) + { + _scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting)); + _scheduler.Schedule(TimeSpan.FromSeconds(4), task => + { + Unit target = SelectTarget(SelectAggroTarget.Random, 0); + if (target) + DoCast(target, SpellIds.Fireball); + task.Repeat(TimeSpan.FromSeconds(5)); + }); + + _scheduler.Schedule(TimeSpan.FromSeconds(15), task => + { + Unit target = SelectTarget(SelectAggroTarget.Random, 0); + if (target) + DoCast(target, SpellIds.TacticalBlink); + DoCast(me, SpellIds.Hellfire); + task.Repeat(TimeSpan.FromSeconds(12)); + }); + } + + public override void UpdateAI(uint diff) + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + if (me.HasUnitState(UnitState.Casting)) + return; + + DoMeleeAttackIfReady(); + } + } + + [Script] + class npc_iceborn_protodrake : ScriptedAI + { + public npc_iceborn_protodrake(Creature creature) : base(creature) { } + + public override void EnterCombat(Unit who) + { + Vehicle vehicle = me.GetVehicleKit(); + if (vehicle) + vehicle.RemoveAllPassengers(); + + _scheduler.Schedule(TimeSpan.FromSeconds(5), task => + { + DoCastVictim(SpellIds.FrostBreath); + task.Repeat(TimeSpan.FromSeconds(10)); + }); + } + + public override void UpdateAI(uint diff) + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + } + + [Script] + class npc_geist_ambusher : ScriptedAI + { + public npc_geist_ambusher(Creature creature) : base(creature) { } + + public override void EnterCombat(Unit who) + { + if (who.GetTypeId() != TypeId.Player) + return; + + // the max range is determined by aggro range + if (me.GetDistance(who) > 5.0f) + DoCast(who, SpellIds.LeapingFaceMaul); + + _scheduler.Schedule(TimeSpan.FromSeconds(9), task => + { + Unit target = SelectTarget(SelectAggroTarget.Random, 0, 5.0f, true); + if (target) + DoCast(target, SpellIds.LeapingFaceMaul); + + task.Repeat(TimeSpan.FromSeconds(9), TimeSpan.FromSeconds(14)); + }); + } + + public override void UpdateAI(uint diff) + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + } + + [Script] + class spell_trash_npc_glacial_strike : AuraScript + { + void PeriodicTick(AuraEffect aurEff) + { + if (GetTarget().IsFullHealth()) + { + GetTarget().RemoveAura(GetId(), ObjectGuid.Empty, 0, AuraRemoveMode.EnemySpell); + PreventDefaultAction(); + } + } + + public override void Register() + { + OnEffectPeriodic.Add(new EffectPeriodicHandler(PeriodicTick, 2, AuraType.PeriodicDamagePercent)); + } + } + + [Script] + class npc_pit_of_saron_icicle : PassiveAI + { + public npc_pit_of_saron_icicle(Creature creature) : base(creature) + { + me.SetDisplayId(me.GetCreatureTemplate().ModelId1); + } + + public override void IsSummonedBy(Unit summoner) + { + _summonerGUID = summoner.GetGUID(); + + _scheduler.Schedule(TimeSpan.FromMilliseconds(3650), task => + { + DoCastSelf(SpellIds.IcicleFallTrigger, true); + DoCastSelf(SpellIds.IcicleFallVisual); + + Unit caster = Global.ObjAccessor.GetUnit(me, _summonerGUID); + if (caster) + caster.RemoveDynObject(SpellIds.IcicleSummon); + }); + } + + public override void UpdateAI(uint diff) + { + _scheduler.Update(diff); + } + + ObjectGuid _summonerGUID; + } + + [Script] + class spell_pos_ice_shards : SpellScript + { + void HandleScriptEffect(uint effIndex) + { + if (GetHitPlayer()) + GetCaster().GetInstanceScript().SetData(DataTypes.CavernActive, 1); + } + + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.SchoolDamage)); + } + } + + [Script] + class at_pit_cavern_entrance : AreaTriggerScript + { + public at_pit_cavern_entrance() : base("at_pit_cavern_entrance") { } + + public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered) + { + if (!entered) + return true; + + InstanceScript instance = player.GetInstanceScript(); + if (instance != null) + { + if (instance.GetData(DataTypes.CavernActive) != 0) + return true; + + instance.SetData(DataTypes.CavernActive, 1); + + Creature tyrannus = ObjectAccessor.GetCreature(player, instance.GetGuidData(DataTypes.TyrannusEvent)); + if (tyrannus) + tyrannus.GetAI().Talk(TextIds.SayTyrannusCavernEntrance); + } + return true; + } + } + + [Script] + class at_pit_cavern_end : AreaTriggerScript + { + public at_pit_cavern_end() : base("at_pit_cavern_end") { } + + public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered) + { + if (!entered) + return true; + + InstanceScript instance = player.GetInstanceScript(); + if (instance != null) + { + instance.SetData(DataTypes.CavernActive, 0); + + if (instance.GetData(DataTypes.IceShardsHit) == 0) + instance.DoUpdateCriteria(CriteriaTypes.BeSpellTarget, SpellIds.AchievDontLookUpCredit, 0, player); + } + + return true; + } + } +} diff --git a/Scripts/Scripts.csproj b/Scripts/Scripts.csproj index 1f2db405e..abefa40bb 100644 --- a/Scripts/Scripts.csproj +++ b/Scripts/Scripts.csproj @@ -70,6 +70,11 @@ + + + + + @@ -175,9 +180,7 @@ - - diff --git a/Scripts/Spells/Monk.cs b/Scripts/Spells/Monk.cs index 37b3ae34f..f52c4a643 100644 --- a/Scripts/Spells/Monk.cs +++ b/Scripts/Spells/Monk.cs @@ -41,7 +41,7 @@ namespace Scripts.Spells.Monk { public override bool Validate(SpellInfo spellInfo) { - return ValidateSpellInfo(SpellIds.CracklingJadeLightningChiProc); + return ValidateSpellInfo(SpellIds.StanceOfTheSpiritedCrane, SpellIds.CracklingJadeLightningChiProc); } void OnTick(AuraEffect aurEff) @@ -90,7 +90,7 @@ namespace Scripts.Spells.Monk public override void Register() { DoCheckProc.Add(new CheckProcHandler(CheckProc)); - OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, Framework.Constants.AuraType.Dummy)); + OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, AuraType.Dummy)); } }