diff options
Diffstat (limited to 'src')
2 files changed, 382 insertions, 507 deletions
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 4d8171b2485..747546b9d12 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -51,32 +51,29 @@ enum Summons enum BossSpells { - SPELL_LEGION_FLAME = 66197, // player should run away from raid because he triggers Legion Flame - SPELL_LEGION_FLAME_EFFECT = 66201, // used by trigger npc - SPELL_NETHER_POWER = 66228, // +20% of spell damage per stack, stackable up to 5/10 times, must be dispelled/stealed - SPELL_FEL_LIGHTING = 66528, // jumps to nearby targets - SPELL_FEL_FIREBALL = 66532, // does heavy damage to the tank, interruptable - SPELL_INCINERATE_FLESH = 66237, // target must be healed or will trigger Burning Inferno - SPELL_BURNING_INFERNO = 66242, // triggered by Incinerate Flesh - SPELL_INFERNAL_ERUPTION = 66258, // summons Infernal Volcano - SPELL_INFERNAL_ERUPTION_EFFECT = 66252, // summons Felflame Infernal (3 at Normal and inifinity at Heroic) - SPELL_NETHER_PORTAL = 66269, // summons Nether Portal - SPELL_NETHER_PORTAL_EFFECT = 66263, // summons Mistress of Pain (1 at Normal and infinity at Heroic) + SPELL_LEGION_FLAME = 66197, + SPELL_LEGION_FLAME_EFFECT = 66201, + SPELL_NETHER_POWER = 66228, + SPELL_FEL_LIGHTNING = 66528, + SPELL_FEL_FIREBALL = 66532, + SPELL_INCINERATE_FLESH = 66237, + SPELL_BURNING_INFERNO = 66242, + SPELL_INFERNAL_ERUPTION = 66258, + SPELL_INFERNAL_ERUPTION_EFFECT = 66252, + SPELL_NETHER_PORTAL = 66269, + SPELL_NETHER_PORTAL_EFFECT = 66263, SPELL_LORD_JARAXXUS_HITTIN_YA = 66327, - SPELL_FEL_LIGHTNING = 67888, - - SPELL_BERSERK = 64238, // unused + SPELL_FEL_LIGHTNING_INTRO = 67888, + SPELL_BERSERK = 64238, // Mistress of Pain spells - SPELL_SHIVAN_SLASH = 67098, - SPELL_SPINNING_STRIKE = 66283, + SPELL_SHIVAN_SLASH = 66378, + SPELL_SPINNING_SPIKE = 66283, SPELL_MISTRESS_KISS = 66336, - SPELL_LORD_HITTIN = 66326, // special effect preventing more specific spells be cast on the same player within 10 seconds SPELL_MISTRESS_KISS_DAMAGE_SILENCE = 66359, // Felflame Infernal - SPELL_FEL_STREAK_VISUAL = 66493, - SPELL_FEL_STREAK = 66494, + SPELL_FEL_STREAK_VISUAL = 66493 }; enum Events @@ -88,8 +85,9 @@ enum Events EVENT_INCINERATE_FLESH, EVENT_NETHER_POWER, EVENT_LEGION_FLAME, - EVENT_SUMMONO_NETHER_PORTAL, + EVENT_SUMMON_NETHER_PORTAL, EVENT_SUMMON_INFERNAL_ERUPTION, + EVENT_ENRAGE, EVENT_TAUNT_GNOME, EVENT_KILL_GNOME, EVENT_CHANGE_ORIENTATION, @@ -97,7 +95,7 @@ enum Events // Mistress of Pain EVENT_SHIVAN_SLASH, - EVENT_SPINNING_STRIKE, + EVENT_SPINNING_SPIKE, EVENT_MISTRESS_KISS }; @@ -109,588 +107,461 @@ enum Misc POINT_SUMMONED = 1 }; -class boss_jaraxxus : public CreatureScript + +struct boss_jaraxxus : public BossAI { - public: - boss_jaraxxus() : CreatureScript("boss_jaraxxus") { } + boss_jaraxxus(Creature* creature) : BossAI(creature, DATA_JARAXXUS) { } - struct boss_jaraxxusAI : public BossAI + void Reset() override + { + me->SetCombatPulseDelay(0); + me->ResetLootMode(); + events.Reset(); + summons.DespawnAll(); + + if (instance->GetBossState(DATA_JARAXXUS) == NOT_STARTED) + DoAction(ACTION_JARAXXUS_INTRO); + else if (instance->GetBossState(DATA_JARAXXUS) == FAIL) { - boss_jaraxxusAI(Creature* creature) : BossAI(creature, DATA_JARAXXUS) { } - - void Reset() override - { - _Reset(); - if (instance->GetBossState(DATA_JARAXXUS) == NOT_STARTED) - DoAction(ACTION_JARAXXUS_INTRO); - } + DoCastSelf(SPELL_JARAXXUS_CHAINS); + me->SetImmuneToPC(true); + me->SetReactState(REACT_PASSIVE); + } + } - void JustReachedHome() override - { - _JustReachedHome(); - instance->SetBossState(DATA_JARAXXUS, FAIL); - DoCastSelf(SPELL_JARAXXUS_CHAINS); - me->SetImmuneToPC(true); - me->SetReactState(REACT_PASSIVE); - } + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_FEL_FIREBALL, 6s); + events.ScheduleEvent(EVENT_FEL_LIGHTNING, 17s); + events.ScheduleEvent(EVENT_INCINERATE_FLESH, 14s); + events.ScheduleEvent(EVENT_NETHER_POWER, 22s); + events.ScheduleEvent(EVENT_LEGION_FLAME, 20s); + events.ScheduleEvent(EVENT_SUMMON_NETHER_PORTAL, 20s); + events.ScheduleEvent(EVENT_SUMMON_INFERNAL_ERUPTION, 1min + 20s); + events.ScheduleEvent(EVENT_ENRAGE, 10min); + } - void DoAction(int32 action) override - { - if (action == ACTION_JARAXXUS_INTRO) - { - me->SetReactState(REACT_PASSIVE); - events.SetPhase(PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO, 1s); - } - else if (action == ACTION_JARAXXUS_ENGAGE) - { - me->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); - me->SetImmuneToPC(false); - me->SetReactState(REACT_AGGRESSIVE); - DoZoneInCombat(); - } - } + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + instance->SetBossState(DATA_JARAXXUS, FAIL); + me->DespawnOrUnsummon(); + } - void MovementInform(uint32 type, uint32 pointId) override - { - if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_SUMMONED) - if (Creature* wilfred = instance->GetCreature(DATA_FIZZLEBANG)) - { - me->SetFacingToObject(wilfred); - events.ScheduleEvent(EVENT_TAUNT_GNOME, 9s); - } - } + void DoAction(int32 action) override + { + if (action == ACTION_JARAXXUS_INTRO) + { + me->SetReactState(REACT_PASSIVE); + events.SetPhase(PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO, 1s); + } + else if (action == ACTION_JARAXXUS_ENGAGE) + { + me->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + } + } - void KilledUnit(Unit* who) override + void MovementInform(uint32 type, uint32 pointId) override + { + if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_SUMMONED) + if (Creature* wilfred = instance->GetCreature(DATA_FIZZLEBANG)) { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_KILL_PLAYER); + me->SetFacingToObject(wilfred); + events.ScheduleEvent(EVENT_TAUNT_GNOME, 9s); } + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_KILL_PLAYER); + } - void JustEngagedWith(Unit* /*who*/) override - { - _JustEngagedWith(); - Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_FEL_FIREBALL, 5 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FEL_LIGHTNING, urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS)); - events.ScheduleEvent(EVENT_INCINERATE_FLESH, urand(20 * IN_MILLISECONDS, 25 * IN_MILLISECONDS)); - events.ScheduleEvent(EVENT_NETHER_POWER, 40 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_LEGION_FLAME, 30 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SUMMONO_NETHER_PORTAL, 20 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SUMMON_INFERNAL_ERUPTION, 80 * IN_MILLISECONDS); - } + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + _JustDied(); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FEL_FIREBALL: + DoCastVictim(SPELL_FEL_FIREBALL); + events.Repeat(11s, 13s); + break; + case EVENT_FEL_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_FEL_LIGHTNING); + events.Repeat(10s, 30s); + break; + case EVENT_INCINERATE_FLESH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) { - case EVENT_FEL_FIREBALL: - DoCastVictim(SPELL_FEL_FIREBALL); - events.ScheduleEvent(EVENT_FEL_FIREBALL, urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS)); - break; - case EVENT_FEL_LIGHTNING: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_LORD_HITTIN)) - DoCast(target, SPELL_FEL_LIGHTING); - events.ScheduleEvent(EVENT_FEL_LIGHTNING, urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS)); - break; - case EVENT_INCINERATE_FLESH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN)) - { - Talk(EMOTE_INCINERATE, target); - Talk(SAY_INCINERATE); - DoCast(target, SPELL_INCINERATE_FLESH); - } - events.ScheduleEvent(EVENT_INCINERATE_FLESH, urand(20*IN_MILLISECONDS, 25*IN_MILLISECONDS)); - break; - case EVENT_NETHER_POWER: - { - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.AddSpellMod(SPELLVALUE_AURA_STACK, RAID_MODE(5, 10, 5, 10)); - me->CastSpell(me, SPELL_NETHER_POWER, args); - events.ScheduleEvent(EVENT_NETHER_POWER, 40 * IN_MILLISECONDS); - break; - } - case EVENT_LEGION_FLAME: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN)) - { - Talk(EMOTE_LEGION_FLAME, target); - DoCast(target, SPELL_LEGION_FLAME); - } - events.ScheduleEvent(EVENT_LEGION_FLAME, 30*IN_MILLISECONDS); - break; - case EVENT_SUMMONO_NETHER_PORTAL: - Talk(EMOTE_NETHER_PORTAL); - Talk(SAY_MISTRESS_OF_PAIN); - DoCast(SPELL_NETHER_PORTAL); - events.ScheduleEvent(EVENT_SUMMONO_NETHER_PORTAL, 2*MINUTE*IN_MILLISECONDS); - break; - case EVENT_SUMMON_INFERNAL_ERUPTION: - Talk(EMOTE_INFERNAL_ERUPTION); - Talk(SAY_INFERNAL_ERUPTION); - DoCast(SPELL_INFERNAL_ERUPTION); - events.ScheduleEvent(EVENT_SUMMON_INFERNAL_ERUPTION, 2*MINUTE*IN_MILLISECONDS); - break; - case EVENT_INTRO: - DoCastSelf(SPELL_LORD_JARAXXUS_HITTIN_YA, true); - me->GetMotionMaster()->MoveAlongSplineChain(POINT_SUMMONED, SPLINE_INITIAL_MOVEMENT, true); - break; - case EVENT_TAUNT_GNOME: - Talk(SAY_INTRO); - events.ScheduleEvent(EVENT_KILL_GNOME, 9s); - break; - case EVENT_KILL_GNOME: - DoCastSelf(SPELL_FEL_LIGHTNING); - events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, 3s); - break; - case EVENT_CHANGE_ORIENTATION: - me->SetFacingTo(4.729842f); - events.ScheduleEvent(EVENT_START_COMBAT, 7s); - break; - case EVENT_START_COMBAT: - me->SetImmuneToPC(false); - me->SetReactState(REACT_AGGRESSIVE); - DoZoneInCombat(); - break; - default: - break; + Talk(EMOTE_INCINERATE, target); + Talk(SAY_INCINERATE); + DoCast(target, SPELL_INCINERATE_FLESH); } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.Repeat(23s); + break; + case EVENT_NETHER_POWER: + { + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.AddSpellMod(SPELLVALUE_AURA_STACK, RAID_MODE(5, 10, 5, 10)); + me->CastSpell(me, SPELL_NETHER_POWER, args); + events.Repeat(42s); + break; } - - DoMeleeAttackIfReady(); + case EVENT_LEGION_FLAME: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + { + Talk(EMOTE_LEGION_FLAME, target); + DoCast(target, SPELL_LEGION_FLAME); + } + events.Repeat(30s); + break; + case EVENT_SUMMON_NETHER_PORTAL: + Talk(EMOTE_NETHER_PORTAL); + Talk(SAY_MISTRESS_OF_PAIN); + DoCast(SPELL_NETHER_PORTAL); + events.Repeat(2min); + break; + case EVENT_SUMMON_INFERNAL_ERUPTION: + Talk(EMOTE_INFERNAL_ERUPTION); + Talk(SAY_INFERNAL_ERUPTION); + DoCast(SPELL_INFERNAL_ERUPTION); + events.Repeat(2min); + break; + case EVENT_INTRO: + DoCastSelf(SPELL_LORD_JARAXXUS_HITTIN_YA, true); + me->GetMotionMaster()->MoveAlongSplineChain(POINT_SUMMONED, SPLINE_INITIAL_MOVEMENT, true); + break; + case EVENT_TAUNT_GNOME: + Talk(SAY_INTRO); + events.ScheduleEvent(EVENT_KILL_GNOME, 9s); + break; + case EVENT_KILL_GNOME: + DoCastSelf(SPELL_FEL_LIGHTNING_INTRO); + events.ScheduleEvent(EVENT_CHANGE_ORIENTATION, 3s); + break; + case EVENT_CHANGE_ORIENTATION: + me->SetFacingTo(4.729842f); + events.ScheduleEvent(EVENT_START_COMBAT, 7s); + break; + case EVENT_START_COMBAT: + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + break; + case EVENT_ENRAGE: + Talk(SAY_BERSERK); + DoCastSelf(SPELL_BERSERK, true); + break; + default: + break; } - }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetTrialOfTheCrusaderAI<boss_jaraxxusAI>(creature); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } + + DoMeleeAttackIfReady(); + } }; -class npc_legion_flame : public CreatureScript +struct npc_legion_flame : public ScriptedAI { - public: - npc_legion_flame() : CreatureScript("npc_legion_flame") { } + npc_legion_flame(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + { + SetCombatMovement(false); + } - struct npc_legion_flameAI : public ScriptedAI + void Reset() override + { + if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) { - npc_legion_flameAI(Creature* creature) : ScriptedAI(creature) - { - SetCombatMovement(false); - _instance = creature->GetInstanceScript(); - } + me->DespawnOrUnsummon(); + return; + } - void Reset() override - { - me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)); - me->SetInCombatWithZone(); - DoCast(SPELL_LEGION_FLAME_EFFECT); - } + if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS)) + jaraxxus->AI()->JustSummoned(me); - void UpdateAI(uint32 /*diff*/) override - { - UpdateVictim(); - if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) - me->DespawnOrUnsummon(); - } - private: - InstanceScript* _instance; - }; + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_LEGION_FLAME_EFFECT, true); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetTrialOfTheCrusaderAI<npc_legion_flameAI>(creature); - } +private: + InstanceScript* _instance; }; -class npc_infernal_volcano : public CreatureScript +struct npc_infernal_volcano : public ScriptedAI { - public: - npc_infernal_volcano() : CreatureScript("npc_infernal_volcano") { } - - struct npc_infernal_volcanoAI : public ScriptedAI - { - npc_infernal_volcanoAI(Creature* creature) : ScriptedAI(creature), _summons(me) - { - SetCombatMovement(false); - } - - void Reset() override - { - me->SetReactState(REACT_PASSIVE); - - if (!IsHeroic()) - me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED)); - else - me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED)); - - _summons.DespawnAll(); - } - - void IsSummonedBy(Unit* /*summoner*/) override - { - DoCast(SPELL_INFERNAL_ERUPTION_EFFECT); - } - - void JustSummoned(Creature* summoned) override - { - _summons.Summon(summoned); - // makes immediate corpse despawn of summoned Felflame Infernals - summoned->SetCorpseDelay(0); - } - - void JustDied(Unit* /*killer*/) override - { - // used to despawn corpse immediately - me->DespawnOrUnsummon(); - } - - void UpdateAI(uint32 /*diff*/) override { } - - private: - SummonList _summons; - }; + npc_infernal_volcano(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetTrialOfTheCrusaderAI<npc_infernal_volcanoAI>(creature); - } + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_INFERNAL_ERUPTION_EFFECT, true); + if (IsHeroic()) + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + } }; -class npc_fel_infernal : public CreatureScript +struct npc_fel_infernal : public ScriptedAI { - public: - npc_fel_infernal() : CreatureScript("npc_fel_infernal") { } + npc_fel_infernal(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_fel_infernalAI : public ScriptedAI + void Reset() override + { + if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) { - npc_fel_infernalAI(Creature* creature) : ScriptedAI(creature) - { - _instance = creature->GetInstanceScript(); - } + me->DespawnOrUnsummon(); + return; + } - void Reset() override - { - _scheduler.Schedule(Seconds(2), [this](TaskContext context) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - DoCast(target, SPELL_FEL_STREAK_VISUAL); - context.Repeat(Seconds(15)); - }); - me->SetInCombatWithZone(); - } + if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS)) + jaraxxus->AI()->JustSummoned(me); - void UpdateAI(uint32 diff) override - { - if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) - { - me->DespawnOrUnsummon(); - return; - } + _scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + _scheduler.Schedule(Seconds(2), [this](TaskContext context) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_FEL_STREAK_VISUAL); + context.Repeat(Seconds(15)); + }); - if (!UpdateVictim()) - return; + DoCastSelf(SPELL_LORD_JARAXXUS_HITTIN_YA, true); + } - _scheduler.Update(diff, [this] - { - DoMeleeAttackIfReady(); - }); - } - private: - InstanceScript* _instance; - TaskScheduler _scheduler; - }; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const override + _scheduler.Update(diff, [this] { - return GetTrialOfTheCrusaderAI<npc_fel_infernalAI>(creature); - } + DoMeleeAttackIfReady(); + }); + } + +private: + InstanceScript* _instance; + TaskScheduler _scheduler; }; -class npc_nether_portal : public CreatureScript +struct npc_nether_portal : public ScriptedAI { - public: - npc_nether_portal() : CreatureScript("npc_nether_portal") { } - - struct npc_nether_portalAI : public ScriptedAI - { - npc_nether_portalAI(Creature* creature) : ScriptedAI(creature), _summons(me) { } + npc_nether_portal(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + } - void Reset() override - { - me->SetReactState(REACT_PASSIVE); + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_NETHER_PORTAL_EFFECT, true); + if (IsHeroic()) + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + } +}; - if (!IsHeroic()) - me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED)); - else - me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED)); +struct npc_mistress_of_pain : public ScriptedAI +{ + npc_mistress_of_pain(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - _summons.DespawnAll(); - } + void Reset() override + { + if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) + { + me->DespawnOrUnsummon(); + return; + } - void IsSummonedBy(Unit* /*summoner*/) override - { - DoCast(SPELL_NETHER_PORTAL_EFFECT); - } + if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS)) + jaraxxus->AI()->JustSummoned(me); - void JustSummoned(Creature* summoned) override - { - _summons.Summon(summoned); - // makes immediate corpse despawn of summoned Mistress of Pain - summoned->SetCorpseDelay(0); - } + DoCastSelf(SPELL_LORD_JARAXXUS_HITTIN_YA, true); + _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, INCREASE); + } - void JustDied(Unit* /*killer*/) override - { - // used to despawn corpse immediately - me->DespawnOrUnsummon(); - } + void JustEngagedWith(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_SHIVAN_SLASH, 4s); + _events.ScheduleEvent(EVENT_SPINNING_SPIKE, 9s); + if (IsHeroic()) + _events.ScheduleEvent(EVENT_MISTRESS_KISS, 15s); + } - void UpdateAI(uint32 /*diff*/) override { } + void JustDied(Unit* /*killer*/) override + { + _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, DECREASE); + } - private: - SummonList _summons; - }; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const override - { - return GetTrialOfTheCrusaderAI<npc_nether_portalAI>(creature); - } -}; + _events.Update(diff); -class npc_mistress_of_pain : public CreatureScript -{ - public: - npc_mistress_of_pain() : CreatureScript("npc_mistress_of_pain") { } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - struct npc_mistress_of_painAI : public ScriptedAI + while (uint32 eventId = _events.ExecuteEvent()) { - npc_mistress_of_painAI(Creature* creature) : ScriptedAI(creature) + switch (eventId) { - _instance = creature->GetInstanceScript(); - _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, INCREASE); - } - - void Reset() override - { - _events.ScheduleEvent(EVENT_SHIVAN_SLASH, 30*IN_MILLISECONDS); - _events.ScheduleEvent(EVENT_SPINNING_STRIKE, 30*IN_MILLISECONDS); - if (IsHeroic()) - _events.ScheduleEvent(EVENT_MISTRESS_KISS, 15*IN_MILLISECONDS); - me->SetInCombatWithZone(); - } - - void JustDied(Unit* /*killer*/) override - { - _instance->SetData(DATA_MISTRESS_OF_PAIN_COUNT, DECREASE); - } - - void UpdateAI(uint32 diff) override - { - if (_instance->GetBossState(DATA_JARAXXUS) != IN_PROGRESS) - { - me->DespawnOrUnsummon(); + case EVENT_SHIVAN_SLASH: + DoCastVictim(SPELL_SHIVAN_SLASH); + _events.Repeat(3s, 10s); return; - } - - if (!UpdateVictim()) + case EVENT_SPINNING_SPIKE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_SPINNING_SPIKE); + _events.Repeat(20s); return; - - _events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) + case EVENT_MISTRESS_KISS: + DoCastSelf(SPELL_MISTRESS_KISS); + _events.Repeat(30s); return; - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHIVAN_SLASH: - DoCastVictim(SPELL_SHIVAN_SLASH); - _events.ScheduleEvent(EVENT_SHIVAN_SLASH, 30*IN_MILLISECONDS); - return; - case EVENT_SPINNING_STRIKE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - DoCast(target, SPELL_SPINNING_STRIKE); - _events.ScheduleEvent(EVENT_SPINNING_STRIKE, 30*IN_MILLISECONDS); - return; - case EVENT_MISTRESS_KISS: - DoCast(me, SPELL_MISTRESS_KISS); - _events.ScheduleEvent(EVENT_MISTRESS_KISS, 30*IN_MILLISECONDS); - return; - default: - break; - } - } - - DoMeleeAttackIfReady(); + default: + break; } - private: - InstanceScript* _instance; - EventMap _events; - }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetTrialOfTheCrusaderAI<npc_mistress_of_painAI>(creature); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } -}; -class spell_mistress_kiss : public SpellScriptLoader -{ - public: - spell_mistress_kiss() : SpellScriptLoader("spell_mistress_kiss") { } + DoMeleeAttackIfReady(); + } - class spell_mistress_kiss_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mistress_kiss_AuraScript); +private: + InstanceScript* _instance; + EventMap _events; +}; - bool Load() override - { - return ValidateSpellInfo({ SPELL_MISTRESS_KISS_DAMAGE_SILENCE }); - } +// 66334, 67905, 67906, 67907 - Mistress' Kiss +class spell_mistress_kiss : public AuraScript +{ + PrepareAuraScript(spell_mistress_kiss); - void HandleDummyTick(AuraEffect const* /*aurEff*/) - { - Unit* caster = GetCaster(); - Unit* target = GetTarget(); - if (caster && target) - { - if (target->HasUnitState(UNIT_STATE_CASTING)) - { - caster->CastSpell(target, SPELL_MISTRESS_KISS_DAMAGE_SILENCE, true); - target->RemoveAurasDueToSpell(GetSpellInfo()->Id); - } - } - } + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_MISTRESS_KISS_DAMAGE_SILENCE }); + } - void Register() override + void HandleDummyTick(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + if (Unit* caster = GetCaster()) + if (target->HasUnitState(UNIT_STATE_CASTING)) { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mistress_kiss_AuraScript::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + caster->CastSpell(target, SPELL_MISTRESS_KISS_DAMAGE_SILENCE, true); + target->RemoveAurasDueToSpell(GetSpellInfo()->Id); } - }; + } - AuraScript* GetAuraScript() const override - { - return new spell_mistress_kiss_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mistress_kiss::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } }; -class MistressKissTargetSelector +// 66336, 67076, 67077, 67078 - Mistress' Kiss +class spell_mistress_kiss_area : public SpellScript { - public: - MistressKissTargetSelector() { } - - bool operator()(WorldObject* unit) const - { - if (unit->GetTypeId() == TYPEID_PLAYER && unit->ToUnit()->GetPowerType() == POWER_MANA) - return false; + PrepareSpellScript(spell_mistress_kiss_area); - return true; - } -}; - -class spell_mistress_kiss_area : public SpellScriptLoader -{ - public: - spell_mistress_kiss_area() : SpellScriptLoader("spell_mistress_kiss_area") { } + bool Validate(SpellInfo const* spellInfo) override + { + SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); + return effect0 && ValidateSpellInfo({ static_cast<uint32>(effect0->CalcValue()) }); + } - class spell_mistress_kiss_area_SpellScript : public SpellScript + void FilterTargets(std::list<WorldObject*>& targets) + { + // get a list of players with mana + targets.remove_if([](WorldObject* target) { - PrepareSpellScript(spell_mistress_kiss_area_SpellScript); - - void FilterTargets(std::list<WorldObject*>& targets) - { - // get a list of players with mana - targets.remove_if(MistressKissTargetSelector()); - if (targets.empty()) - return; + return target->GetTypeId() == TYPEID_PLAYER && target->ToUnit()->GetPowerIndex(POWER_MANA) == MAX_POWERS; + }); - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - targets.clear(); - targets.push_back(target); - } + if (targets.empty()) + return; - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); - } + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mistress_kiss_area_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mistress_kiss_area_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override - { - return new spell_mistress_kiss_area_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mistress_kiss_area::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mistress_kiss_area::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_fel_streak_visual : public SpellScriptLoader +// 66493 - Fel Streak +class spell_fel_streak_visual : public SpellScript { -public: - spell_fel_streak_visual() : SpellScriptLoader("spell_fel_streak_visual") { } + PrepareSpellScript(spell_fel_streak_visual); - class spell_fel_streak_visual_SpellScript : public SpellScript + bool Validate(SpellInfo const* spellInfo) override { - PrepareSpellScript(spell_fel_streak_visual_SpellScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_FEL_STREAK }); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); - } + SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); + return effect0 && ValidateSpellInfo({ static_cast<uint32>(effect0->CalcValue()) }); + } - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_fel_streak_visual_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), static_cast<uint32>(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_fel_streak_visual_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_fel_streak_visual::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; void AddSC_boss_jaraxxus() { - new boss_jaraxxus(); - new npc_legion_flame(); - new npc_infernal_volcano(); - new npc_fel_infernal(); - new npc_nether_portal(); - new npc_mistress_of_pain(); - - new spell_mistress_kiss(); - new spell_mistress_kiss_area(); - new spell_fel_streak_visual(); + RegisterTrialOfTheCrusaderCreatureAI(boss_jaraxxus); + RegisterTrialOfTheCrusaderCreatureAI(npc_legion_flame); + RegisterTrialOfTheCrusaderCreatureAI(npc_infernal_volcano); + RegisterTrialOfTheCrusaderCreatureAI(npc_fel_infernal); + RegisterTrialOfTheCrusaderCreatureAI(npc_nether_portal); + RegisterTrialOfTheCrusaderCreatureAI(npc_mistress_of_pain); + RegisterAuraScript(spell_mistress_kiss); + RegisterSpellScript(spell_mistress_kiss_area); + RegisterSpellScript(spell_fel_streak_visual); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index 7d57afe379b..ce0edfe8d88 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -390,7 +390,11 @@ struct npc_tirion_toc : public ScriptedAI else if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE) me->SummonCreature(NPC_BARRETT_BEASTS, BarretSpawnPosition); else if (_instance->GetBossState(DATA_JARAXXUS) != DONE) + { me->SummonCreature(NPC_BARRETT_JARAXXUS, BarretSpawnPosition); + if (_instance->GetBossState(DATA_JARAXXUS) == FAIL) + DoAction(ACTION_SUMMON_JARAXXUS); + } else if (_instance->GetBossState(DATA_FACTION_CRUSADERS) != DONE) me->SummonCreature(NPC_BARRETT_FACTION, BarretSpawnPosition); else if (_instance->GetBossState(DATA_TWIN_VALKIRIES) != DONE) |