aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp32
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp149
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp2087
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp89
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp230
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp1650
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h82
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp3
8 files changed, 2099 insertions, 2223 deletions
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
index c5dc4db2e50..a3da5f57881 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp
@@ -28,11 +28,6 @@
#include "TemporarySummon.h"
#include "trial_of_the_crusader.h"
-enum Yells
-{
- SAY_KILL_PLAYER = 6
-};
-
enum AIs
{
AI_MELEE = 0,
@@ -209,7 +204,7 @@ enum Events
EVENT_REGROWTH = 3,
EVENT_REJUVENATION = 4,
EVENT_TRANQUILITY = 5,
- EVENT_HEAL_BARKSKIN = 6,
+ EVENT_HEAL_BARKSKIN = 6,
EVENT_THORNS = 7,
EVENT_NATURE_GRASP = 8,
@@ -551,9 +546,7 @@ class boss_toc_champion_controller : public CreatureScript
case DONE:
{
_championsKilled++;
- if (_championsKilled == 1)
- instance->SetBossState(DATA_FACTION_CRUSADERS, SPECIAL);
- else if (_championsKilled >= summons.size())
+ if (_championsKilled >= summons.size())
{
instance->SetBossState(DATA_FACTION_CRUSADERS, DONE);
summons.DespawnAll();
@@ -584,7 +577,7 @@ class boss_toc_champion_controller : public CreatureScript
struct boss_faction_championsAI : public BossAI
{
- boss_faction_championsAI(Creature* creature, uint32 aitype) : BossAI(creature, DATA_FACTION_CHAMPIONS)
+ boss_faction_championsAI(Creature* creature, uint32 aitype) : BossAI(creature, DATA_FACTION_CHAMPIONS), _teamInstance(0)
{
_aiType = aitype;
SetBoundary(instance->GetBossBoundary(DATA_FACTION_CRUSADERS));
@@ -592,6 +585,7 @@ struct boss_faction_championsAI : public BossAI
void Reset() override
{
+ _teamInstance = instance->GetData(DATA_TEAM);
_events.ScheduleEvent(EVENT_THREAT, 5*IN_MILLISECONDS);
if (IsHeroic() && (_aiType != AI_PET))
_events.ScheduleEvent(EVENT_REMOVE_CC, 5*IN_MILLISECONDS);
@@ -656,22 +650,13 @@ struct boss_faction_championsAI : public BossAI
{
if (who->GetTypeId() == TYPEID_PLAYER)
{
- Map::PlayerList const& players = me->GetMap()->GetPlayers();
- uint32 TeamInInstance = 0;
-
- if (!players.isEmpty())
- if (Player* player = players.begin()->GetSource())
- TeamInInstance = player->GetTeam();
-
- if (TeamInInstance == ALLIANCE)
+ if (_teamInstance == ALLIANCE)
{
if (Creature* varian = instance->GetCreature(DATA_VARIAN))
- varian->AI()->Talk(SAY_KILL_PLAYER);
+ varian->AI()->DoAction(ACTION_SAY_KILLED_PLAYER);
}
- else
- if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
- garrosh->AI()->Talk(SAY_KILL_PLAYER);
-
+ else if (Creature* garrosh = instance->GetCreature(DATA_GARROSH))
+ garrosh->AI()->DoAction(ACTION_SAY_KILLED_PLAYER);
}
}
@@ -757,6 +742,7 @@ struct boss_faction_championsAI : public BossAI
private:
uint32 _aiType;
+ uint32 _teamInstance;
// make sure that every bosses separate events dont mix with these _events
EventMap _events;
};
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 9382f74ef1b..dcb939e57f8 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
@@ -17,6 +17,8 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
+#include "MotionMaster.h"
+#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
#include "SpellScript.h"
@@ -49,19 +51,21 @@ 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_BERSERK = 64238, // unused
+ 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_LORD_JARAXXUS_HITTIN_YA = 66327,
+ SPELL_FEL_LIGHTNING = 67888,
+
+ SPELL_BERSERK = 64238, // unused
// Mistress of Pain spells
SPELL_SHIVAN_SLASH = 67098,
@@ -78,18 +82,31 @@ enum BossSpells
enum Events
{
// Lord Jaraxxus
- EVENT_FEL_FIREBALL = 1,
- EVENT_FEL_LIGHTNING = 2,
- EVENT_INCINERATE_FLESH = 3,
- EVENT_NETHER_POWER = 4,
- EVENT_LEGION_FLAME = 5,
- EVENT_SUMMONO_NETHER_PORTAL = 6,
- EVENT_SUMMON_INFERNAL_ERUPTION = 7,
+ EVENT_INTRO = 1,
+ EVENT_FEL_FIREBALL,
+ EVENT_FEL_LIGHTNING,
+ EVENT_INCINERATE_FLESH,
+ EVENT_NETHER_POWER,
+ EVENT_LEGION_FLAME,
+ EVENT_SUMMONO_NETHER_PORTAL,
+ EVENT_SUMMON_INFERNAL_ERUPTION,
+ EVENT_TAUNT_GNOME,
+ EVENT_KILL_GNOME,
+ EVENT_CHANGE_ORIENTATION,
+ EVENT_START_COMBAT,
// Mistress of Pain
- EVENT_SHIVAN_SLASH = 8,
- EVENT_SPINNING_STRIKE = 9,
- EVENT_MISTRESS_KISS = 10
+ EVENT_SHIVAN_SLASH,
+ EVENT_SPINNING_STRIKE,
+ EVENT_MISTRESS_KISS
+};
+
+enum Misc
+{
+ PHASE_INTRO = 1,
+ PHASE_COMBAT = 2,
+ SPLINE_INITIAL_MOVEMENT = 1,
+ POINT_SUMMONED = 1
};
class boss_jaraxxus : public CreatureScript
@@ -104,22 +121,44 @@ class boss_jaraxxus : public CreatureScript
void Reset() override
{
_Reset();
- 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);
+ if (instance->GetBossState(DATA_JARAXXUS) == NOT_STARTED)
+ DoAction(ACTION_JARAXXUS_INTRO);
}
void JustReachedHome() override
{
_JustReachedHome();
instance->SetBossState(DATA_JARAXXUS, FAIL);
- DoCast(me, SPELL_JARAXXUS_CHAINS);
- me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
+ DoCastSelf(SPELL_JARAXXUS_CHAINS);
me->SetImmuneToPC(true);
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ 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 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 KilledUnit(Unit* who) override
@@ -138,11 +177,18 @@ class boss_jaraxxus : public CreatureScript
{
_EnterCombat();
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 UpdateAI(uint32 diff) override
{
- if (!UpdateVictim())
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
return;
events.Update(diff);
@@ -157,12 +203,12 @@ class boss_jaraxxus : public CreatureScript
case EVENT_FEL_FIREBALL:
DoCastVictim(SPELL_FEL_FIREBALL);
events.ScheduleEvent(EVENT_FEL_FIREBALL, urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS));
- return;
+ 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));
- return;
+ break;
case EVENT_INCINERATE_FLESH:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN))
{
@@ -171,11 +217,11 @@ class boss_jaraxxus : public CreatureScript
DoCast(target, SPELL_INCINERATE_FLESH);
}
events.ScheduleEvent(EVENT_INCINERATE_FLESH, urand(20*IN_MILLISECONDS, 25*IN_MILLISECONDS));
- return;
+ break;
case EVENT_NETHER_POWER:
me->CastCustomSpell(SPELL_NETHER_POWER, SPELLVALUE_AURA_STACK, RAID_MODE<uint32>(5, 10, 5, 10), me, true);
events.ScheduleEvent(EVENT_NETHER_POWER, 40*IN_MILLISECONDS);
- return;
+ break;
case EVENT_LEGION_FLAME:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN))
{
@@ -183,19 +229,42 @@ class boss_jaraxxus : public CreatureScript
DoCast(target, SPELL_LEGION_FLAME);
}
events.ScheduleEvent(EVENT_LEGION_FLAME, 30*IN_MILLISECONDS);
- return;
+ 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);
- return;
+ 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);
- return;
+ 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;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index aab0cd46128..de6ba1849e5 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -38,17 +38,9 @@ enum Yells
SAY_SPECIAL = 1,
// Icehowl
- EMOTE_TRAMPLE_START = 0,
- EMOTE_TRAMPLE_CRASH = 1,
- EMOTE_TRAMPLE_FAIL = 2
-};
-
-enum Equipment
-{
- EQUIP_MAIN = 50760,
- EQUIP_OFFHAND = 48040,
- EQUIP_RANGED = 47267,
- EQUIP_DONE = EQUIP_NO_CHANGE
+ EMOTE_TRAMPLE_ROAR = 0,
+ EMOTE_TRAMPLE_FAIL = 1,
+ EMOTE_TRAMPLE_ENRAGE = 2
};
enum Model
@@ -59,75 +51,81 @@ enum Model
MODEL_DREADSCALE_MOBILE = 24564
};
-enum BeastSummons
-{
- NPC_SNOBOLD_VASSAL = 34800,
- NPC_FIRE_BOMB = 34854,
- NPC_SLIME_POOL = 35176,
- MAX_SNOBOLDS = 4
-};
-
enum BossSpells
{
- //Gormok
- SPELL_IMPALE = 66331,
- SPELL_STAGGERING_STOMP = 67648,
- //Snobold
- SPELL_RISING_ANGER = 66636,
- SPELL_SNOBOLLED = 66406,
- SPELL_BATTER = 66408,
- SPELL_FIRE_BOMB = 66313,
- SPELL_FIRE_BOMB_1 = 66317,
- SPELL_FIRE_BOMB_DOT = 66318,
- SPELL_HEAD_CRACK = 66407,
- SPELL_JUMP_TO_HAND = 66342,
- SPELL_RIDE_PLAYER = 66245,
-
- //Acidmaw & Dreadscale Generic
- SPELL_SWEEP = 66794,
- SUMMON_SLIME_POOL = 66883,
- SPELL_EMERGE = 66947,
- SPELL_SUBMERGE = 66948,
- SPELL_ENRAGE = 68335,
- SPELL_SLIME_POOL_EFFECT = 66882, //In 60s it diameter grows from 10y to 40y (r=r+0.25 per second)
- SPELL_GROUND_VISUAL_0 = 66969,
- SPELL_GROUND_VISUAL_1 = 68302,
- SPELL_HATE_TO_ZERO = 63984,
- //Acidmaw
- SPELL_ACID_SPIT = 66880,
- SPELL_PARALYTIC_SPRAY = 66901,
- SPELL_PARALYTIC_BITE = 66824, //Paralytic Toxin
- SPELL_ACID_SPEW = 66818,
- SPELL_PARALYSIS = 66830,
- SPELL_PARALYTIC_TOXIN = 66823,
- //Dreadscale
- SPELL_BURNING_BITE = 66879, // Burning Bile
- SPELL_MOLTEN_SPEW = 66821,
- SPELL_FIRE_SPIT = 66796,
- SPELL_BURNING_SPRAY = 66902,
- SPELL_BURNING_BILE = 66869,
-
- //Icehowl
- SPELL_FEROCIOUS_BUTT = 66770,
- SPELL_MASSIVE_CRASH = 66683,
- SPELL_WHIRL = 67345,
- SPELL_ARCTIC_BREATH = 66689,
- SPELL_TRAMPLE = 66734,
- SPELL_FROTHING_RAGE = 66759,
- SPELL_STAGGERED_DAZE = 66758
+ // Gormok
+ SPELL_IMPALE = 66331,
+ SPELL_STAGGERING_STOMP = 66330,
+ SPELL_TANKING_GORMOK = 66415, // No idea what it does (SERVERSIDE spell)
+
+ // Snobold
+ SPELL_RISING_ANGER = 66636,
+ SPELL_SNOBOLLED = 66406,
+ SPELL_BATTER = 66408,
+ SPELL_FIRE_BOMB = 66313,
+ SPELL_HEAD_CRACK = 66407,
+ SPELL_JUMP_TO_HAND = 66342,
+ SPELL_RIDE_PLAYER = 66245,
+
+ // Acidmaw & Dreadscale Generic
+ SPELL_SWEEP = 66794,
+ SUMMON_SLIME_POOL = 66883,
+ SPELL_EMERGE = 66947,
+ SPELL_SUBMERGE = 66948,
+ SPELL_SUBMERGE_2 = 66936,
+ SPELL_ENRAGE = 68335,
+ SPELL_GROUND_VISUAL_0 = 66969,
+ SPELL_GROUND_VISUAL_1 = 68302,
+ SPELL_HATE_TO_ZERO = 63984,
+ // Acidmaw
+ SPELL_ACID_SPIT = 66880,
+ SPELL_PARALYTIC_SPRAY = 66901,
+ SPELL_PARALYTIC_BITE = 66824,
+ SPELL_ACID_SPEW = 66818,
+ SPELL_PARALYSIS = 66830,
+ SPELL_PARALYTIC_TOXIN = 66823,
+ // Dreadscale
+ SPELL_BURNING_BITE = 66879,
+ SPELL_MOLTEN_SPEW = 66821,
+ SPELL_FIRE_SPIT = 66796,
+ SPELL_BURNING_SPRAY = 66902,
+ SPELL_BURNING_BILE = 66869,
+
+ // Slime Pool
+ SPELL_SLIME_POOL_EFFECT = 66882,
+ SPELL_PACIFY_SELF = 19951,
+
+ // Icehowl
+ SPELL_FEROCIOUS_BUTT = 66770,
+ SPELL_MASSIVE_CRASH = 66683,
+ SPELL_WHIRL = 67345,
+ SPELL_ARCTIC_BREATH = 66688,
+ SPELL_TRAMPLE = 66734,
+ SPELL_FROTHING_RAGE = 66759,
+ SPELL_STAGGERED_DAZE = 66758,
+ SPELL_FURIOUS_CHARGE_SUMMON = 66729,
+ SPELL_ROAR = 66736,
+ SPELL_JUMP_BACK = 66733,
+ SPELL_SURGE_OF_ADRENALINE = 68667,
+ SPELL_BERSERK = 26662
};
enum MyActions
{
- ACTION_ENABLE_FIRE_BOMB = 1,
- ACTION_DISABLE_FIRE_BOMB = 2,
- ACTION_ACTIVE_SNOBOLD = 3
+ ACTION_ENABLE_FIRE_BOMB = 1,
+ ACTION_DISABLE_FIRE_BOMB,
+ ACTION_ACTIVE_SNOBOLD,
+ ACTION_ENRAGE,
+ ACTION_TRAMPLE_FAIL,
+ ACTION_GORMOK_DEAD,
+ ACTION_JORMUNGARS_DEAD
};
enum Events
{
// Gormok
- EVENT_IMPALE = 1,
+ EVENT_ENGAGE = 1,
+ EVENT_IMPALE,
EVENT_STAGGERING_STOMP,
EVENT_THROW,
@@ -138,11 +136,15 @@ enum Events
EVENT_SNOBOLLED,
EVENT_CHECK_MOUNT,
+ // Beasts Combat Stalker
+ EVENT_BERSERK,
+ EVENT_START_ICEHOWL,
+ EVENT_START_JORGMUNGARS,
+
// Acidmaw & Dreadscale
EVENT_BITE,
EVENT_SPEW,
EVENT_SLIME_POOL,
- EVENT_SPIT,
EVENT_SPRAY,
EVENT_SWEEP,
EVENT_SUBMERGE,
@@ -154,395 +156,513 @@ enum Events
EVENT_MASSIVE_CRASH,
EVENT_WHIRL,
EVENT_ARCTIC_BREATH,
+ EVENT_SELECT_CHARGE_TARGET,
+ EVENT_ROAR_EMOTE,
+ EVENT_ICEHOWL_ROAR,
+ EVENT_JUMP_BACK,
EVENT_TRAMPLE
};
enum Phases
{
- PHASE_MOBILE = 1,
- PHASE_STATIONARY = 2,
- PHASE_SUBMERGED = 3
+ PHASE_EVENT = 1,
+ PHASE_COMBAT,
+ PHASE_MOBILE,
+ PHASE_STATIONARY,
+ PHASE_SUBMERGED,
+ PHASE_CHARGE
};
-enum GormokMisc
+enum NorthrendBeastsPoint
{
- DATA_NEW_TARGET = 1,
- GORMOK_HAND_SEAT = 4,
- PLAYER_VEHICLE_ID = 444,
+ POINT_INITIAL_MOVEMENT = 1,
+ POINT_MIDDLE,
+ POINT_ICEHOWL_CHARGE
};
-class boss_gormok : public CreatureScript
+enum Misc
{
- public:
- boss_gormok() : CreatureScript("boss_gormok") { }
+ DATA_NEW_TARGET = 1,
+ GORMOK_HAND_SEAT = 4,
+ MAX_SNOBOLDS = 4,
+ SPLINE_INITIAL_MOVEMENT = 1
+};
- struct boss_gormokAI : public BossAI
- {
- boss_gormokAI(Creature* creature) : BossAI(creature, DATA_GORMOK_THE_IMPALER)
- {
- SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
- }
+Position const CombatStalkerPosition = { 563.8941f, 137.3333f, 405.8467f };
- void Reset() override
- {
- events.ScheduleEvent(EVENT_IMPALE, Seconds(8), Seconds(10));
- events.ScheduleEvent(EVENT_STAGGERING_STOMP, Seconds(15));
- events.ScheduleEvent(EVENT_THROW, Seconds(15), Seconds(30));
+class SnobolledTargetSelector
+{
+public:
+ SnobolledTargetSelector() { }
- summons.DespawnAll();
- }
+ bool operator()(Unit* unit) const
+ {
+ return unit->GetTypeId() == TYPEID_PLAYER && !unit->HasAura(SPELL_RIDE_PLAYER) && !unit->HasAura(SPELL_SNOBOLLED);
+ }
+};
- void EnterEvadeMode(EvadeReason why) override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- ScriptedAI::EnterEvadeMode(why);
- }
+struct boss_northrend_beastsAI : public BossAI
+{
+ boss_northrend_beastsAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId)
+ {
+ SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
+ Initialize();
+ }
- void MovementInform(uint32 type, uint32 pointId) override
- {
- if (type != POINT_MOTION_TYPE)
- return;
+ void Reset() override
+ {
+ events.Reset();
+ events.SetPhase(PHASE_EVENT);
+ summons.DespawnAll();
+ me->SetReactState(REACT_PASSIVE);
+ me->SetCombatPulseDelay(0);
+ Initialize();
+ HandleInitialMovement();
+ }
- switch (pointId)
- {
- case 0:
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetImmuneToPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
- me->SetInCombatWithZone();
- break;
- default:
- break;
- }
- }
+ void HandleInitialMovement()
+ {
+ switch (me->GetEntry())
+ {
+ case NPC_GORMOK:
+ case NPC_DREADSCALE:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_INITIAL_MOVEMENT, SPLINE_INITIAL_MOVEMENT, false);
+ break;
+ case NPC_ICEHOWL:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_INITIAL_MOVEMENT, SPLINE_INITIAL_MOVEMENT, true);
+ break;
+ default:
+ break;
+ }
+ }
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_DONE);
- }
+ void HandleWithHeroicEvents()
+ {
+ if (Creature* combatStalker = instance->GetCreature(DATA_BEASTS_COMBAT_STALKER))
+ {
+ if (me->GetEntry() == NPC_GORMOK)
+ combatStalker->AI()->DoAction(ACTION_START_JORMUNGARS);
+ else if (me->GetEntry() == NPC_DREADSCALE)
+ combatStalker->AI()->DoAction(ACTION_START_ICEHOWL);
+ }
+ }
- void JustReachedHome() override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
+ virtual void Initialize() { }
- me->DespawnOrUnsummon();
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ me->SetCombatPulseDelay(5);
+ me->setActive(true);
+ ScheduleTasks();
+ HandleInstanceProgress();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ if (IsHeroic())
+ HandleWithHeroicEvents();
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- me->SetCombatPulseDelay(5);
- me->setActive(true);
- //DoZoneInCombat();
+ void HandleInstanceProgress()
+ {
+ switch (me->GetEntry())
+ {
+ case NPC_GORMOK:
instance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_IN_PROGRESS);
- instance->SetBossState(DATA_NORTHREND_BEASTS, IN_PROGRESS);
- }
+ break;
+ case NPC_ACIDMAW:
+ case NPC_DREADSCALE:
+ if (instance->GetData(TYPE_NORTHREND_BEASTS) != SNAKES_IN_PROGRESS)
+ instance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_IN_PROGRESS);
+ break;
+ case NPC_ICEHOWL:
+ instance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS);
+ break;
+ default:
+ break;
+ }
+ }
- void DamageTaken(Unit* /*who*/, uint32& damage) override
- {
- // despawn the remaining passengers on death
- if (damage >= me->GetHealth())
- for (uint8 i = 0; i < MAX_SNOBOLDS; ++i)
- if (Unit* snobold = me->GetVehicleKit()->GetPassenger(i))
- snobold->ToCreature()->DespawnOrUnsummon();
- }
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ ScriptedAI::EnterEvadeMode(why);
+ instance->SetData(DATA_DESPAWN_SNOBOLDS, 0);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ // prevent losing 2 attempts at once on heroics
+ if (instance->GetData(TYPE_NORTHREND_BEASTS) != FAIL)
+ instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
+ if (Creature* combatStalker = instance->GetCreature(DATA_BEASTS_COMBAT_STALKER))
+ combatStalker->DespawnOrUnsummon();
+ summons.DespawnAll();
+ me->DespawnOrUnsummon();
+ }
- void PassengerBoarded(Unit* who, int8 seatId, bool apply) override
- {
- if (apply && seatId == GORMOK_HAND_SEAT)
- who->CastSpell(me, SPELL_RISING_ANGER, true);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ if (me->GetEntry() == NPC_GORMOK)
+ {
+ instance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_DONE);
+ if (Creature* combatStalker = instance->GetCreature(DATA_BEASTS_COMBAT_STALKER))
+ combatStalker->AI()->DoAction(ACTION_GORMOK_DEAD);
+ }
+ else
+ instance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_DONE);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_EVENT))
+ 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())
+ {
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- while (uint32 eventId = events.ExecuteEvent())
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct boss_gormok : public boss_northrend_beastsAI
+{
+ boss_gormok(Creature* creature) : boss_northrend_beastsAI(creature, DATA_GORMOK_THE_IMPALER) { }
+
+ void ScheduleTasks() override
+ {
+ events.ScheduleEvent(EVENT_IMPALE, 10s);
+ events.ScheduleEvent(EVENT_STAGGERING_STOMP, 15s);
+ events.ScheduleEvent(EVENT_THROW, 20s);
+ }
+
+ void PassengerBoarded(Unit* who, int8 seatId, bool apply) override
+ {
+ if (apply && seatId == GORMOK_HAND_SEAT)
+ who->CastSpell(who, SPELL_RISING_ANGER, true);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_INITIAL_MOVEMENT)
+ events.ScheduleEvent(EVENT_ENGAGE, 7s);
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_ENGAGE:
+ instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
+ me->SetImmuneToPC(false);
+ me->SetReactState(REACT_AGGRESSIVE);
+ // Npc that should keep raid in combat while boss change
+ if (Creature* combatStalker = me->SummonCreature(NPC_BEASTS_COMBAT_STALKER, CombatStalkerPosition))
{
- switch (eventId)
+ combatStalker->SetInCombatWithZone();
+ combatStalker->SetCombatPulseDelay(5);
+ }
+ DoZoneInCombat();
+ events.SetPhase(PHASE_COMBAT);
+ DoCastSelf(SPELL_TANKING_GORMOK, true);
+ break;
+ case EVENT_IMPALE:
+ DoCastVictim(SPELL_IMPALE);
+ events.Repeat(10s);
+ break;
+ case EVENT_STAGGERING_STOMP:
+ DoCastVictim(SPELL_STAGGERING_STOMP);
+ events.Repeat(22s);
+ break;
+ case EVENT_THROW:
+ for (uint8 i = 0; i < MAX_SNOBOLDS; ++i)
+ {
+ if (Unit* snobold = me->GetVehicleKit()->GetPassenger(i))
{
- case EVENT_IMPALE:
- DoCastVictim(SPELL_IMPALE);
- events.Repeat(Seconds(8), Seconds(10));
- break;
- case EVENT_STAGGERING_STOMP:
- DoCastVictim(SPELL_STAGGERING_STOMP);
- events.Repeat(Seconds(15));
- break;
- case EVENT_THROW:
- for (uint8 i = 0; i < MAX_SNOBOLDS; ++i)
- {
- if (Unit* snobold = me->GetVehicleKit()->GetPassenger(i))
- {
- snobold->ExitVehicle();
- snobold->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- snobold->GetAI()->DoAction(ACTION_DISABLE_FIRE_BOMB);
- snobold->CastSpell(me, SPELL_JUMP_TO_HAND, true);
- break;
- }
- }
- events.Repeat(Seconds(15), Seconds(30));
- break;
- default:
- break;
+ snobold->ExitVehicle();
+ snobold->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
+ snobold->GetAI()->DoAction(ACTION_DISABLE_FIRE_BOMB);
+ snobold->CastSpell(me, SPELL_JUMP_TO_HAND, true);
+ break;
}
}
-
- DoMeleeAttackIfReady();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<boss_gormokAI>(creature);
+ events.Repeat(20s);
+ break;
+ default:
+ break;
}
+ }
};
-class SnobolledTargetSelector : public std::unary_function<Unit*, bool>
+struct npc_snobold_vassal : public ScriptedAI
{
-public:
- SnobolledTargetSelector(Unit const* /*unit*/) { }
+ npc_snobold_vassal(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _mountedOnPlayer(false)
+ {
+ _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE);
+ SetCombatMovement(false);
+ }
- bool operator()(Unit* unit) const
+ bool CanAIAttack(Unit const* who) const override
{
- if (unit->GetTypeId() != TYPEID_PLAYER)
+ if (_mountedOnPlayer && who->GetGUID() != _targetGUID)
return false;
- if (unit->HasAura(SPELL_RIDE_PLAYER) || unit->HasAura(SPELL_SNOBOLLED))
- return false;
+ return ScriptedAI::CanAIAttack(who);
+ }
- return true;
+ void AttackStart(Unit* victim) override
+ {
+ Creature* gormok = _instance->GetCreature(DATA_GORMOK_THE_IMPALER);
+ if (!_mountedOnPlayer && (!gormok || !gormok->IsAlive()))
+ AttackStartCaster(victim, 30.0f);
+ else
+ ScriptedAI::AttackStart(victim);
}
-};
-class npc_snobold_vassal : public CreatureScript
-{
- public:
- npc_snobold_vassal() : CreatureScript("npc_snobold_vassal") { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_CHECK_MOUNT, 3s);
+ _events.ScheduleEvent(EVENT_FIRE_BOMB, 12s, 25s);
+ }
- struct npc_snobold_vassalAI : public ScriptedAI
+ void JustDied(Unit* /*killer*/) override
+ {
+ _instance->SetData(DATA_SNOBOLD_COUNT, DECREASE);
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- npc_snobold_vassalAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isActive(false)
- {
- _instance->SetData(DATA_SNOBOLD_COUNT, INCREASE);
- SetCombatMovement(false);
- }
+ case ACTION_ENABLE_FIRE_BOMB:
+ _events.ScheduleEvent(EVENT_FIRE_BOMB, 12s, 25s);
+ break;
+ case ACTION_DISABLE_FIRE_BOMB:
+ _events.CancelEvent(EVENT_FIRE_BOMB);
+ break;
+ case ACTION_ACTIVE_SNOBOLD:
+ _mountedOnPlayer = true;
+ break;
+ default:
+ break;
+ }
+ }
- void Reset() override
+ void SetGUID(ObjectGuid guid, int32 id) override
+ {
+ if (id == DATA_NEW_TARGET)
+ if (Unit* target = ObjectAccessor::GetPlayer(*me, guid))
{
- me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetInCombatWithZone();
- _events.ScheduleEvent(EVENT_CHECK_MOUNT, Seconds(1));
- _events.ScheduleEvent(EVENT_FIRE_BOMB, Seconds(5), Seconds(30));
+ _targetGUID = guid;
+ AttackStart(target);
+ _events.ScheduleEvent(EVENT_BATTER, 5s);
+ _events.ScheduleEvent(EVENT_SNOBOLLED, 1s);
+ _events.ScheduleEvent(EVENT_HEAD_CRACK, 1s);
}
+ }
- void JustDied(Unit* /*killer*/) override
- {
- if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID))
- target->RemoveAurasDueToSpell(SPELL_SNOBOLLED);
- _instance->SetData(DATA_SNOBOLD_COUNT, DECREASE);
- }
+ void MountOnBoss()
+ {
+ Unit* gormok = _instance->GetCreature(DATA_GORMOK_THE_IMPALER);
+ if (gormok && gormok->IsAlive())
+ {
+ me->AttackStop();
+ _targetGUID.Clear();
+ _mountedOnPlayer = false;
+ _events.CancelEvent(EVENT_BATTER);
+ _events.CancelEvent(EVENT_HEAD_CRACK);
- void DoAction(int32 action) override
+ for (uint8 i = 0; i < MAX_SNOBOLDS; i++)
{
- switch (action)
+ if (!gormok->GetVehicleKit()->GetPassenger(i))
{
- case ACTION_ENABLE_FIRE_BOMB:
- _events.ScheduleEvent(EVENT_FIRE_BOMB, Seconds(5), Seconds(30));
- break;
- case ACTION_DISABLE_FIRE_BOMB:
- _events.CancelEvent(EVENT_FIRE_BOMB);
- break;
- case ACTION_ACTIVE_SNOBOLD:
- _isActive = true;
- break;
- default:
- break;
+ me->EnterVehicle(gormok, i);
+ DoAction(ACTION_ENABLE_FIRE_BOMB);
+ break;
}
}
+ }
+ else
+ {
+ me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
+ _events.CancelEvent(EVENT_CHECK_MOUNT);
+ me->AttackStop();
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ AttackStart(target);
+ SetCombatMovement(true);
+ }
+ }
- void SetGUID(ObjectGuid guid, int32 id) override
- {
- if (id == DATA_NEW_TARGET)
- if (Unit* target = ObjectAccessor::GetPlayer(*me, guid))
- {
- _targetGUID = guid;
- AttackStart(target);
- _events.ScheduleEvent(EVENT_BATTER, Seconds(5));
- _events.ScheduleEvent(EVENT_HEAD_CRACK, Seconds(25));
- _events.ScheduleEvent(EVENT_SNOBOLLED, Milliseconds(500));
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void AttackStart(Unit* who) override
- {
- //Snobold only melee attack players that is your vehicle
- if (!_isActive || who->GetGUID() != _targetGUID)
- return;
+ _events.Update(diff);
- ScriptedAI::AttackStart(who);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void MountOnBoss()
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- Unit* gormok = _instance->GetCreature(DATA_GORMOK_THE_IMPALER);
- if (gormok && gormok->IsAlive())
- {
- me->AttackStop();
- _targetGUID.Clear();
- _isActive = false;
- _events.CancelEvent(EVENT_BATTER);
- _events.CancelEvent(EVENT_HEAD_CRACK);
-
- for (uint8 i = 0; i < MAX_SNOBOLDS; i++)
- {
- if (!gormok->GetVehicleKit()->GetPassenger(i))
- {
- me->EnterVehicle(gormok, i);
- DoAction(ACTION_ENABLE_FIRE_BOMB);
- break;
- }
- }
- }
- //Without Boss, snobolds should jump in another players
- else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SnobolledTargetSelector(me)))
- me->CastSpell(target, SPELL_RIDE_PLAYER, true);
+ case EVENT_FIRE_BOMB:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ me->CastSpell(target, SPELL_FIRE_BOMB);
+ _events.Repeat(20s, 30s);
+ break;
+ case EVENT_HEAD_CRACK:
+ if (Unit* target = me->GetVehicleBase())
+ DoCast(target, SPELL_HEAD_CRACK);
+ _events.Repeat(30s);
+ break;
+ case EVENT_BATTER:
+ if (Unit* target = me->GetVehicleBase())
+ DoCast(target, SPELL_BATTER);
+ _events.Repeat(10s, 15s);
+ break;
+ case EVENT_SNOBOLLED:
+ DoCastSelf(SPELL_SNOBOLLED);
+ break;
+ case EVENT_CHECK_MOUNT:
+ if (!me->GetVehicleBase())
+ MountOnBoss();
+ _events.Repeat(3s);
+ break;
+ default:
+ break;
}
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FIRE_BOMB:
- if (me->GetVehicleBase())
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -me->GetVehicleBase()->GetCombatReach(), true))
- me->CastSpell(target, SPELL_FIRE_BOMB);
- _events.Repeat(Seconds(20));
- break;
- case EVENT_HEAD_CRACK:
- DoCast(me->GetVehicleBase(), SPELL_HEAD_CRACK);
- _events.Repeat(Seconds(30));
- break;
- case EVENT_BATTER:
- DoCast(me->GetVehicleBase(), SPELL_BATTER);
- _events.Repeat(Seconds(10));
- break;
- case EVENT_SNOBOLLED:
- DoCastAOE(SPELL_SNOBOLLED);
- break;
- case EVENT_CHECK_MOUNT:
- if (!me->GetVehicleBase())
- MountOnBoss();
- _events.Repeat(Seconds(1));
- break;
- default:
- break;
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
+ // do melee attack only if is in player back.
+ if (_mountedOnPlayer)
+ DoMeleeAttackIfReady();
+ }
- if (!UpdateVictim())
- return;
+private:
+ EventMap _events;
+ InstanceScript* _instance;
+ ObjectGuid _targetGUID;
+ bool _mountedOnPlayer;
+};
- // do melee attack only if is in player back.
- if (_isActive)
- DoMeleeAttackIfReady();
- }
+struct npc_beasts_combat_stalker : public ScriptedAI
+{
+ npc_beasts_combat_stalker(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- private:
- EventMap _events;
- InstanceScript* _instance;
- ObjectGuid _targetGUID;
- bool _isActive;
- };
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _events.ScheduleEvent(EVENT_BERSERK, IsHeroic() ? 9min : 15min);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- return GetTrialOfTheCrusaderAI<npc_snobold_vassalAI>(creature);
+ case ACTION_START_JORMUNGARS:
+ _events.ScheduleEvent(EVENT_START_JORGMUNGARS, 2min + 30s);
+ break;
+ case ACTION_GORMOK_DEAD:
+ _events.CancelEvent(EVENT_START_JORGMUNGARS);
+ break;
+ case ACTION_START_ICEHOWL:
+ _events.ScheduleEvent(EVENT_START_ICEHOWL, 2min + 30s);
+ break;
+ case ACTION_JORMUNGARS_DEAD:
+ _events.CancelEvent(EVENT_START_ICEHOWL);
+ break;
+ default:
+ break;
}
-};
+ }
-class npc_firebomb : public CreatureScript
-{
- public:
- npc_firebomb() : CreatureScript("npc_firebomb") { }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- struct npc_firebombAI : public ScriptedAI
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_firebombAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
-
- void Reset() override
- {
- DoCast(me, SPELL_FIRE_BOMB_DOT, true);
- SetCombatMovement(false);
- me->SetReactState(REACT_PASSIVE);
- me->SetDisplayFromModel(1);
- }
-
- void UpdateAI(uint32 /*diff*/) override
+ switch (eventId)
{
- if (_instance->GetData(TYPE_NORTHREND_BEASTS) != GORMOK_IN_PROGRESS)
- me->DespawnOrUnsummon();
+ case EVENT_BERSERK:
+ if (Creature* gormok = _instance->GetCreature(DATA_GORMOK_THE_IMPALER))
+ gormok->CastSpell(gormok, SPELL_BERSERK, true);
+
+ if (Creature* dreadscale = _instance->GetCreature(DATA_DREADSCALE))
+ dreadscale->CastSpell(dreadscale, SPELL_BERSERK, true);
+
+ if (Creature* acidmaw = _instance->GetCreature(DATA_ACIDMAW))
+ acidmaw->CastSpell(acidmaw, SPELL_BERSERK, true);
+
+ if (Creature* icehowl = _instance->GetCreature(DATA_ICEHOWL))
+ icehowl->CastSpell(icehowl, SPELL_BERSERK, true);
+ break;
+ case EVENT_START_JORGMUNGARS:
+ if (Creature* tirion = _instance->GetCreature(DATA_FORDRING))
+ tirion->AI()->DoAction(ACTION_START_JORMUNGARS);
+ break;
+ case EVENT_START_ICEHOWL:
+ if (Creature* tirion = _instance->GetCreature(DATA_FORDRING))
+ tirion->AI()->DoAction(ACTION_START_ICEHOWL);
+ break;
+ default:
+ break;
}
-
- private:
- InstanceScript* _instance;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<npc_firebombAI>(creature);
}
+ }
+
+private:
+ EventMap _events;
+ InstanceScript* _instance;
};
-struct boss_jormungarAI : public BossAI
+struct boss_jormungarAI : public boss_northrend_beastsAI
{
- boss_jormungarAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId)
- {
- OtherWormEntry = 0;
- ModelStationary = 0;
- ModelMobile = 0;
+ boss_jormungarAI(Creature* creature, uint32 bossId) : boss_northrend_beastsAI(creature, bossId) { }
- BiteSpell = 0;
- SpewSpell = 0;
- SpitSpell = 0;
- SpraySpell = 0;
+ void Initialize() override
+ {
+ otherWormEntry = 0;
+ modelStationary = 0;
+ modelMobile = 0;
+ biteSpell = 0;
+ spewSpell = 0;
+ spitSpell = 0;
+ spraySpell = 0;
+ wasMobile = false;
+ }
- Phase = PHASE_MOBILE;
- Enraged = false;
- WasMobile = false;
- SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
+ void JustSummoned(Creature* summoned) override
+ {
+ if (summoned->GetEntry() == NPC_ACIDMAW)
+ BossAI::JustSummoned(summoned);
+ else
+ summons.Summon(summoned);
}
- void Reset() override
+ void ScheduleTasks() override
{
- Enraged = false;
+ if (events.IsInPhase(PHASE_STATIONARY))
+ {
+ events.ScheduleEvent(EVENT_SPRAY, me->GetEntry() == NPC_DREADSCALE ? 17s : 9s, 0, PHASE_STATIONARY);
+ events.ScheduleEvent(EVENT_SWEEP, 16s, 0, PHASE_STATIONARY);
+ }
+ else
+ {
+ events.ScheduleEvent(EVENT_BITE, 5s, 0, PHASE_MOBILE);
+ events.ScheduleEvent(EVENT_SPEW, 10s, 0, PHASE_MOBILE);
+ events.ScheduleEvent(EVENT_SLIME_POOL, 14s, 0, PHASE_MOBILE);
+ }
- events.ScheduleEvent(EVENT_SPIT, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SPRAY, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SWEEP, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_BITE, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SPEW, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SLIME_POOL, 15*IN_MILLISECONDS, 0, PHASE_MOBILE);
+ events.ScheduleEvent(EVENT_SUBMERGE, 45s);
}
uint32 GetOtherWormData(uint32 wormEntry)
@@ -552,825 +672,508 @@ struct boss_jormungarAI : public BossAI
void JustDied(Unit* /*killer*/) override
{
- if (Creature* otherWorm = instance->GetCreature(GetOtherWormData(OtherWormEntry)))
+ if (Creature* otherWorm = instance->GetCreature(GetOtherWormData(otherWormEntry)))
{
if (!otherWorm->IsAlive())
{
instance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE);
-
me->DespawnOrUnsummon();
otherWorm->DespawnOrUnsummon();
+ if (Creature* combatStalker = instance->GetCreature(DATA_BEASTS_COMBAT_STALKER))
+ combatStalker->AI()->DoAction(ACTION_JORMUNGARS_DEAD);
}
else
+ {
instance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL);
+ otherWorm->AI()->DoAction(ACTION_ENRAGE);
+ }
}
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
}
- void JustReachedHome() override
- {
- // prevent losing 2 attempts at once on heroics
- if (instance->GetData(TYPE_NORTHREND_BEASTS) != FAIL)
- instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
-
- me->DespawnOrUnsummon();
- }
-
- void EnterCombat(Unit* /*who*/) override
+ void DoAction(int32 action) override
{
- _EnterCombat();
- me->SetInCombatWithZone();
- instance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_IN_PROGRESS);
+ if (action == ACTION_ENRAGE)
+ {
+ DoCastSelf(SPELL_ENRAGE, true);
+ Talk(EMOTE_ENRAGE);
+ if (events.IsInPhase(PHASE_SUBMERGED))
+ events.RescheduleEvent(EVENT_EMERGE, 1ms);
+ }
}
- void UpdateAI(uint32 diff) override
+ void Submerge()
{
- if (!UpdateVictim())
- return;
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
- if (!Enraged && instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL)
+ if (wasMobile)
{
- me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
- me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- DoCast(SPELL_ENRAGE);
- Enraged = true;
- Talk(EMOTE_ENRAGE);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
+ DoCastSelf(SPELL_SUBMERGE);
+ me->SetSpeedRate(MOVE_RUN, 8.0f);
+ DoCastSelf(SPELL_GROUND_VISUAL_0, true);
+ events.SetPhase(PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_EMERGE, 5s, 0, PHASE_SUBMERGED);
+ me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
}
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
+ else
{
- switch (eventId)
- {
- case EVENT_EMERGE:
- Emerge();
- return;
- case EVENT_SUBMERGE:
- Submerge();
- return;
- case EVENT_BITE:
- DoCastVictim(BiteSpell);
- events.ScheduleEvent(EVENT_BITE, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- return;
- case EVENT_SPEW:
- DoCastAOE(SpewSpell);
- events.ScheduleEvent(EVENT_SPEW, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- return;
- case EVENT_SLIME_POOL:
- DoCast(me, SUMMON_SLIME_POOL);
- events.ScheduleEvent(EVENT_SLIME_POOL, 30*IN_MILLISECONDS, 0, PHASE_MOBILE);
- return;
- case EVENT_SUMMON_ACIDMAW:
- if (Creature* acidmaw = me->SummonCreature(NPC_ACIDMAW, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN))
- {
- acidmaw->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- acidmaw->SetImmuneToPC(false);
- acidmaw->SetReactState(REACT_AGGRESSIVE);
- acidmaw->SetInCombatWithZone();
- acidmaw->CastSpell(acidmaw, SPELL_EMERGE);
- acidmaw->CastSpell(acidmaw, SPELL_GROUND_VISUAL_1, true);
- }
- return;
- case EVENT_SPRAY:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SpraySpell);
- events.ScheduleEvent(EVENT_SPRAY, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- return;
- case EVENT_SWEEP:
- DoCastAOE(SPELL_SWEEP);
- events.ScheduleEvent(EVENT_SWEEP, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- return;
- default:
- return;
- }
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
+ DoCastSelf(SPELL_SUBMERGE_2);
+ me->RemoveAurasDueToSpell(SPELL_GROUND_VISUAL_1);
+ me->SetSpeedRate(MOVE_RUN, 1.1111f);
+ DoCastSelf(SPELL_GROUND_VISUAL_0, true);
+ events.SetPhase(PHASE_SUBMERGED);
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ events.ScheduleEvent(EVENT_EMERGE, 6s, 0, PHASE_SUBMERGED);
+ me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
}
- if (events.IsInPhase(PHASE_MOBILE))
- DoMeleeAttackIfReady();
- if (events.IsInPhase(PHASE_STATIONARY))
- DoCastVictim(SpitSpell);
- }
-
- void Submerge()
- {
- DoCast(me, SPELL_SUBMERGE);
- DoCast(me, SPELL_GROUND_VISUAL_0, true);
- me->RemoveAurasDueToSpell(SPELL_EMERGE);
- me->SetInCombatWithZone();
- events.SetPhase(PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_EMERGE, 5*IN_MILLISECONDS, 0, PHASE_SUBMERGED);
- me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
me->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionY() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionZ() + me->GetMidsectionHeight());
- WasMobile = !WasMobile;
}
void Emerge()
{
- DoCast(me, SPELL_EMERGE);
- DoCastAOE(SPELL_HATE_TO_ZERO, true);
- me->SetDisplayId(ModelMobile);
- me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
+ me->UpdateSpeed(MOVE_RUN);
+ uint32 submergeSpell = wasMobile ? SPELL_SUBMERGE : SPELL_SUBMERGE_2;
+ me->RemoveAurasDueToSpell(submergeSpell);
me->RemoveAurasDueToSpell(SPELL_GROUND_VISUAL_0);
+ DoCastSelf(SPELL_EMERGE);
+ DoCastAOE(SPELL_HATE_TO_ZERO, true);
me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ AttackStart(target);
// if the worm was mobile before submerging, make him stationary now
- if (WasMobile)
+ if (wasMobile)
{
me->SetControlled(true, UNIT_STATE_ROOT);
- SetCombatMovement(false);
- me->SetDisplayId(ModelStationary);
- me->CastSpell(me, SPELL_GROUND_VISUAL_1, true);
+ me->SetDisplayId(modelStationary);
+ DoCastSelf(SPELL_GROUND_VISUAL_1, true);
events.SetPhase(PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SUBMERGE, 45*IN_MILLISECONDS, 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SPIT, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SPRAY, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
- events.ScheduleEvent(EVENT_SWEEP, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY);
}
else
{
- me->SetControlled(false, UNIT_STATE_ROOT);
- SetCombatMovement(true);
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- me->SetDisplayId(ModelMobile);
- me->RemoveAurasDueToSpell(SPELL_GROUND_VISUAL_1);
+ if (Unit* target = me->GetVictim())
+ me->GetMotionMaster()->MoveChase(target);
+ me->SetDisplayId(modelMobile);
events.SetPhase(PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SUBMERGE, 45*IN_MILLISECONDS, 0, PHASE_MOBILE);
- events.ScheduleEvent(EVENT_BITE, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SPEW, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SLIME_POOL, 15*IN_MILLISECONDS, 0, PHASE_MOBILE);
}
+ wasMobile = !wasMobile;
+ ScheduleTasks();
}
- protected:
- uint32 OtherWormEntry;
- uint32 ModelStationary;
- uint32 ModelMobile;
-
- uint32 BiteSpell;
- uint32 SpewSpell;
- uint32 SpitSpell;
- uint32 SpraySpell;
-
- Phases Phase;
- bool Enraged;
- bool WasMobile;
-};
-
-class boss_acidmaw : public CreatureScript
-{
- public:
- boss_acidmaw() : CreatureScript("boss_acidmaw") { }
-
- struct boss_acidmawAI : public boss_jormungarAI
- {
- boss_acidmawAI(Creature* creature) : boss_jormungarAI(creature, DATA_ACIDMAW) { }
-
- void Reset() override
- {
- boss_jormungarAI::Reset();
- BiteSpell = SPELL_PARALYTIC_BITE;
- SpewSpell = SPELL_ACID_SPEW;
- SpitSpell = SPELL_ACID_SPIT;
- SpraySpell = SPELL_PARALYTIC_SPRAY;
- ModelStationary = MODEL_ACIDMAW_STATIONARY;
- ModelMobile = MODEL_ACIDMAW_MOBILE;
- OtherWormEntry = NPC_DREADSCALE;
-
- WasMobile = true;
- Emerge();
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<boss_acidmawAI>(creature);
- }
-};
-
-class boss_dreadscale : public CreatureScript
-{
- public:
- boss_dreadscale() : CreatureScript("boss_dreadscale") { }
-
- struct boss_dreadscaleAI : public boss_jormungarAI
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- boss_dreadscaleAI(Creature* creature) : boss_jormungarAI(creature, DATA_DREADSCALE) { }
-
- void Reset() override
- {
- boss_jormungarAI::Reset();
- BiteSpell = SPELL_BURNING_BITE;
- SpewSpell = SPELL_MOLTEN_SPEW;
- SpitSpell = SPELL_FIRE_SPIT;
- SpraySpell = SPELL_BURNING_SPRAY;
- ModelStationary = MODEL_DREADSCALE_STATIONARY;
- ModelMobile = MODEL_DREADSCALE_MOBILE;
- OtherWormEntry = NPC_ACIDMAW;
-
- events.SetPhase(PHASE_MOBILE);
- events.ScheduleEvent(EVENT_SUMMON_ACIDMAW, 3*IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_SUBMERGE, 45*IN_MILLISECONDS, 0, PHASE_MOBILE);
- WasMobile = false;
- }
-
- void MovementInform(uint32 type, uint32 pointId) override
- {
- if (type != POINT_MOTION_TYPE)
- return;
-
- switch (pointId)
+ case EVENT_ENGAGE:
+ if (me->GetEntry() == NPC_DREADSCALE)
{
- case 0:
- instance->DoCloseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetImmuneToPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
- me->SetInCombatWithZone();
- break;
- default:
- break;
+ instance->DoCloseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
+ me->SetImmuneToPC(false);
+ events.SetPhase(PHASE_MOBILE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoZoneInCombat();
+ events.ScheduleEvent(EVENT_SUMMON_ACIDMAW, 1ms);
}
- }
+ else
+ {
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoZoneInCombat();
+ }
+ break;
+ case EVENT_EMERGE:
+ Emerge();
+ break;
+ case EVENT_SUBMERGE:
+ Submerge();
+ break;
+ case EVENT_BITE:
+ DoCastVictim(biteSpell);
+ events.Repeat(15s);
+ break;
+ case EVENT_SPEW:
+ DoCastAOE(spewSpell);
+ events.Repeat(21s);
+ break;
+ case EVENT_SLIME_POOL:
+ DoCastSelf(SUMMON_SLIME_POOL);
+ events.Repeat(12s);
+ break;
+ case EVENT_SUMMON_ACIDMAW:
+ me->SummonCreature(NPC_ACIDMAW, ToCCommonLoc[9]);
+ break;
+ case EVENT_SPRAY:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ DoCast(target, spraySpell);
+ events.Repeat(21s);
+ break;
+ case EVENT_SWEEP:
+ DoCastAOE(SPELL_SWEEP);
+ events.Repeat(17s);
+ break;
+ default:
+ break;
+ }
+ }
- void EnterEvadeMode(EvadeReason why) override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- boss_jormungarAI::EnterEvadeMode(why);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_EVENT))
+ return;
- void JustReachedHome() override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
+ events.Update(diff);
- boss_jormungarAI::JustReachedHome();
- }
- };
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- CreatureAI* GetAI(Creature* creature) const override
+ while (uint32 eventId = events.ExecuteEvent())
{
- return GetTrialOfTheCrusaderAI<boss_dreadscaleAI>(creature);
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
-};
-
-class npc_slime_pool : public CreatureScript
-{
- public:
- npc_slime_pool() : CreatureScript("npc_slime_pool") { }
- struct npc_slime_poolAI : public ScriptedAI
- {
- npc_slime_poolAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- _instance = creature->GetInstanceScript();
- }
-
- void Initialize()
- {
- _cast = false;
- }
-
- void Reset() override
- {
- Initialize();
- me->SetReactState(REACT_PASSIVE);
- }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- if (!_cast)
- {
- _cast = true;
- DoCast(me, SPELL_SLIME_POOL_EFFECT);
- }
-
- if (_instance->GetData(TYPE_NORTHREND_BEASTS) != SNAKES_IN_PROGRESS && _instance->GetData(TYPE_NORTHREND_BEASTS) != SNAKES_SPECIAL)
- me->DespawnOrUnsummon();
- }
- private:
- InstanceScript* _instance;
- bool _cast;
-
- };
+ if (events.IsInPhase(PHASE_MOBILE))
+ DoMeleeAttackIfReady();
+ else
+ DoCastVictim(spitSpell);
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<npc_slime_poolAI>(creature);
- }
+ protected:
+ uint32 otherWormEntry;
+ uint32 modelStationary;
+ uint32 modelMobile;
+ uint32 biteSpell;
+ uint32 spewSpell;
+ uint32 spitSpell;
+ uint32 spraySpell;
+ bool wasMobile;
};
-class spell_gormok_fire_bomb : public SpellScriptLoader
+struct boss_dreadscale : public boss_jormungarAI
{
- public:
- spell_gormok_fire_bomb() : SpellScriptLoader("spell_gormok_fire_bomb") { }
+ boss_dreadscale(Creature* creature) : boss_jormungarAI(creature, DATA_DREADSCALE) { }
- class spell_gormok_fire_bomb_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_gormok_fire_bomb_SpellScript);
-
- void TriggerFireBomb(SpellEffIndex /*effIndex*/)
- {
- if (WorldLocation const* pos = GetExplTargetDest())
- {
- if (Unit* caster = GetCaster())
- caster->SummonCreature(NPC_FIRE_BOMB, pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30*IN_MILLISECONDS);
- }
- }
-
- void Register() override
- {
- OnEffectHit += SpellEffectFn(spell_gormok_fire_bomb_SpellScript::TriggerFireBomb, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE);
- }
- };
+ void Reset() override
+ {
+ boss_northrend_beastsAI::Reset();
+ biteSpell = SPELL_BURNING_BITE;
+ spewSpell = SPELL_MOLTEN_SPEW;
+ spitSpell = SPELL_FIRE_SPIT;
+ spraySpell = SPELL_BURNING_SPRAY;
+ modelStationary = MODEL_DREADSCALE_STATIONARY;
+ modelMobile = MODEL_DREADSCALE_MOBILE;
+ otherWormEntry = NPC_ACIDMAW;
+ wasMobile = true;
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_gormok_fire_bomb_SpellScript();
- }
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_INITIAL_MOVEMENT)
+ events.ScheduleEvent(EVENT_ENGAGE, Seconds(3));
+ }
};
-class boss_icehowl : public CreatureScript
+struct boss_acidmaw : public boss_jormungarAI
{
- public:
- boss_icehowl() : CreatureScript("boss_icehowl") { }
-
- struct boss_icehowlAI : public BossAI
- {
- boss_icehowlAI(Creature* creature) : BossAI(creature, DATA_ICEHOWL)
- {
- Initialize();
- SetBoundary(instance->GetBossBoundary(DATA_NORTHREND_BEASTS));
- }
-
- void Initialize()
- {
- _movementStarted = false;
- _movementFinish = false;
- _trampleCast = false;
- _trampleTargetGUID.Clear();
- _trampleTargetX = 0;
- _trampleTargetY = 0;
- _trampleTargetZ = 0;
- _stage = 0;
- }
+ boss_acidmaw(Creature* creature) : boss_jormungarAI(creature, DATA_ACIDMAW) { }
- void Reset() override
- {
- events.ScheduleEvent(EVENT_FEROCIOUS_BUTT, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS));
- events.ScheduleEvent(EVENT_ARCTIC_BREATH, urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS));
- events.ScheduleEvent(EVENT_WHIRL, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS));
- events.ScheduleEvent(EVENT_MASSIVE_CRASH, 30*IN_MILLISECONDS);
- Initialize();
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- instance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_DONE);
- }
-
- void MovementInform(uint32 type, uint32 pointId) override
- {
- if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
- return;
-
- switch (pointId)
- {
- case 0:
- if (_stage != 0)
- {
- if (me->GetDistance2d(ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY()) < 6.0f)
- // Middle of the room
- _stage = 1;
- else
- {
- // Landed from Hop backwards (start trample)
- if (ObjectAccessor::GetPlayer(*me, _trampleTargetGUID))
- _stage = 4;
- else
- _stage = 6;
- }
- }
- break;
- case 1: // Finish trample
- _movementFinish = true;
- break;
- case 2:
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetImmuneToPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
- me->SetInCombatWithZone();
- break;
- default:
- break;
- }
- }
-
- void EnterEvadeMode(EvadeReason why) override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- ScriptedAI::EnterEvadeMode(why);
- }
-
- void JustReachedHome() override
- {
- instance->DoUseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
- instance->SetData(TYPE_NORTHREND_BEASTS, FAIL);
- me->DespawnOrUnsummon();
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- instance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS);
- }
+ void Reset() override
+ {
+ boss_northrend_beastsAI::Reset();
+ biteSpell = SPELL_PARALYTIC_BITE;
+ spewSpell = SPELL_ACID_SPEW;
+ spitSpell = SPELL_ACID_SPIT;
+ spraySpell = SPELL_PARALYTIC_SPRAY;
+ modelStationary = MODEL_ACIDMAW_STATIONARY;
+ modelMobile = MODEL_ACIDMAW_MOBILE;
+ otherWormEntry = NPC_DREADSCALE;
+ events.SetPhase(PHASE_STATIONARY);
+ wasMobile = false;
+ me->SetControlled(true, UNIT_STATE_ROOT);
+ DoCastSelf(SPELL_GROUND_VISUAL_1, true);
+ events.ScheduleEvent(EVENT_ENGAGE, Seconds(3));
+ }
+};
- void SpellHitTarget(Unit* target, SpellInfo const* spell) override
- {
- if (spell->Id == SPELL_TRAMPLE && target->GetTypeId() == TYPEID_PLAYER)
- {
- if (!_trampleCast)
- {
- DoCast(me, SPELL_FROTHING_RAGE, true);
- _trampleCast = true;
- }
- }
- }
+struct npc_jormungars_slime_pool : public ScriptedAI
+{
+ npc_jormungars_slime_pool(Creature* creature) : ScriptedAI(creature) { }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void Reset() override
+ {
+ DoCastSelf(SPELL_SLIME_POOL_EFFECT, true);
+ DoCastSelf(SPELL_PACIFY_SELF, true);
+ }
+};
- events.Update(diff);
+struct boss_icehowl : public boss_northrend_beastsAI
+{
+ boss_icehowl(Creature* creature) : boss_northrend_beastsAI(creature, DATA_ICEHOWL) { }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ void ScheduleTasks() override
+ {
+ events.ScheduleEvent(EVENT_FEROCIOUS_BUTT, 8s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ARCTIC_BREATH, 20s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_WHIRL, 15s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_MASSIVE_CRASH, 35s, 0, PHASE_COMBAT);
+ }
- switch (_stage)
- {
- case 0:
- {
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_FEROCIOUS_BUTT:
- DoCastVictim(SPELL_FEROCIOUS_BUTT);
- events.ScheduleEvent(EVENT_FEROCIOUS_BUTT, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS));
- return;
- case EVENT_ARCTIC_BREATH:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_ARCTIC_BREATH);
- return;
- case EVENT_WHIRL:
- DoCastAOE(SPELL_WHIRL);
- events.ScheduleEvent(EVENT_WHIRL, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS));
- return;
- case EVENT_MASSIVE_CRASH:
- me->GetMotionMaster()->MoveJump(ToCCommonLoc[1], 20.0f, 20.0f, 0); // 1: Middle of the room
- SetCombatMovement(false);
- me->AttackStop();
- _stage = 7; //Invalid (Do nothing more than move)
- return;
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
- DoMeleeAttackIfReady();
- break;
- }
- case 1:
- DoCastAOE(SPELL_MASSIVE_CRASH);
- me->StopMoving();
- me->AttackStop();
- _stage = 2;
- break;
- case 2:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- {
- me->StopMoving();
- me->AttackStop();
- _trampleTargetGUID = target->GetGUID();
- me->SetTarget(_trampleTargetGUID);
- _trampleCast = false;
- SetCombatMovement(false);
- me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- me->SetControlled(true, UNIT_STATE_ROOT);
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveIdle();
- events.ScheduleEvent(EVENT_TRAMPLE, 4*IN_MILLISECONDS);
- _stage = 3;
- }
- else
- _stage = 6;
- break;
- case 3:
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_TRAMPLE:
- {
- if (Unit* target = ObjectAccessor::GetPlayer(*me, _trampleTargetGUID))
- {
- me->StopMoving();
- me->AttackStop();
- _trampleCast = false;
- _movementStarted = true;
- _trampleTargetX = target->GetPositionX();
- _trampleTargetY = target->GetPositionY();
- _trampleTargetZ = target->GetPositionZ();
- // 2: Hop Backwards
- me->GetMotionMaster()->MoveJump(2*me->GetPositionX() - _trampleTargetX, 2*me->GetPositionY() - _trampleTargetY, me->GetPositionZ(), me->GetOrientation(), 30.0f, 20.0f, 0);
- me->SetControlled(false, UNIT_STATE_ROOT);
- _stage = 7; //Invalid (Do nothing more than move)
- }
- else
- _stage = 6;
- break;
- }
- default:
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
- break;
- case 4:
- me->StopMoving();
- me->AttackStop();
- if (Player* target = ObjectAccessor::GetPlayer(*me, _trampleTargetGUID))
- Talk(EMOTE_TRAMPLE_START, target);
- me->GetMotionMaster()->MoveCharge(_trampleTargetX, _trampleTargetY, _trampleTargetZ, 42, 1);
- me->SetTarget(ObjectGuid::Empty);
- _stage = 5;
- break;
- case 5:
- if (_movementFinish)
- {
- DoCastAOE(SPELL_TRAMPLE);
- _movementFinish = false;
- _stage = 6;
- return;
- }
- if (events.ExecuteEvent() == EVENT_TRAMPLE)
- {
- Map::PlayerList const& lPlayers = me->GetMap()->GetPlayers();
- for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
- {
- if (Unit* player = itr->GetSource())
- {
- if (player->IsAlive() && player->IsWithinDistInMap(me, 6.0f))
- {
- DoCastAOE(SPELL_TRAMPLE);
- events.ScheduleEvent(EVENT_TRAMPLE, 4*IN_MILLISECONDS);
- break;
- }
- }
- }
- }
- break;
- case 6:
- if (!_trampleCast)
- {
- DoCast(me, SPELL_STAGGERED_DAZE);
- Talk(EMOTE_TRAMPLE_CRASH);
- }
- else
- {
- DoCast(me, SPELL_FROTHING_RAGE, true);
- Talk(EMOTE_TRAMPLE_FAIL);
- }
- _movementStarted = false;
- me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- SetCombatMovement(true);
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- AttackStart(me->GetVictim());
- events.ScheduleEvent(EVENT_MASSIVE_CRASH, 40*IN_MILLISECONDS);
- events.ScheduleEvent(EVENT_ARCTIC_BREATH, urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS));
- _stage = 0;
- break;
- default:
- break;
- }
- }
+ void RescheduleTasks()
+ {
+ events.ScheduleEvent(EVENT_FEROCIOUS_BUTT, 8s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_ARCTIC_BREATH, 20s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_WHIRL, 15s, 0, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_MASSIVE_CRASH, 45s, 0, PHASE_COMBAT);
+ }
- private:
- float _trampleTargetX, _trampleTargetY, _trampleTargetZ;
- ObjectGuid _trampleTargetGUID;
- bool _movementStarted;
- bool _movementFinish;
- bool _trampleCast;
- uint8 _stage;
- };
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
- CreatureAI* GetAI(Creature* creature) const override
+ switch (pointId)
{
- return GetTrialOfTheCrusaderAI<boss_icehowlAI>(creature);
+ case POINT_INITIAL_MOVEMENT:
+ events.ScheduleEvent(EVENT_ENGAGE, 3s);
+ break;
+ case POINT_MIDDLE:
+ DoCastSelf(SPELL_MASSIVE_CRASH);
+ events.ScheduleEvent(EVENT_SELECT_CHARGE_TARGET, 4s);
+ break;
+ case POINT_ICEHOWL_CHARGE:
+ events.Reset();
+ events.SetPhase(PHASE_COMBAT);
+ RescheduleTasks();
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoCastSelf(SPELL_TRAMPLE);
+ break;
+ default:
+ break;
}
-};
-
-class spell_gormok_jump_to_hand : public SpellScriptLoader
-{
-public:
- spell_gormok_jump_to_hand() : SpellScriptLoader("spell_gormok_jump_to_hand") { }
+ }
- class spell_gormok_jump_to_hand_AuraScript : public AuraScript
+ void DoAction(int32 action) override
{
- PrepareAuraScript(spell_gormok_jump_to_hand_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
+ if (action == ACTION_ENRAGE)
{
- return ValidateSpellInfo({ SPELL_RIDE_PLAYER });
+ DoCastSelf(SPELL_FROTHING_RAGE, true);
+ Talk(EMOTE_TRAMPLE_ENRAGE);
}
-
- bool Load() override
+ else if (action == ACTION_TRAMPLE_FAIL)
{
- if (GetCaster() && GetCaster()->GetEntry() == NPC_SNOBOLD_VASSAL)
- return true;
- return false;
+ DoCastSelf(SPELL_STAGGERED_DAZE, true);
+ Talk(EMOTE_TRAMPLE_FAIL);
+ events.DelayEvents(15s);
}
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
{
- if (Unit* caster = GetCaster())
- {
- if (CreatureAI* gormokAI = GetTarget()->ToCreature()->AI())
+ case EVENT_ENGAGE:
+ instance->DoCloseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
+ me->SetImmuneToPC(false);
+ events.SetPhase(PHASE_COMBAT);
+ me->SetReactState(REACT_AGGRESSIVE);
+ DoZoneInCombat();
+ break;
+ case EVENT_MASSIVE_CRASH:
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ events.SetPhase(PHASE_CHARGE);
+ me->GetMotionMaster()->MoveJump(ToCCommonLoc[1], 20.0f, 20.0f, POINT_MIDDLE);
+ break;
+ case EVENT_SELECT_CHARGE_TARGET:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
- if (Unit* target = gormokAI->SelectTarget(SELECT_TARGET_RANDOM, 0, SnobolledTargetSelector(GetTarget())))
- {
- gormokAI->Talk(EMOTE_SNOBOLLED);
- caster->GetAI()->DoAction(ACTION_ACTIVE_SNOBOLD);
- caster->CastSpell(target, SPELL_RIDE_PLAYER, true);
- }
+ DoCast(target, SPELL_FURIOUS_CHARGE_SUMMON, true);
+ me->SetTarget(target->GetGUID());
+ Talk(EMOTE_TRAMPLE_ROAR, target);
+ events.ScheduleEvent(EVENT_ICEHOWL_ROAR, 1s);
}
- }
- }
-
- void Register() override
- {
- AfterEffectRemove += AuraEffectRemoveFn(spell_gormok_jump_to_hand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
+ break;
+ case EVENT_ICEHOWL_ROAR:
+ if (Creature* stalker = instance->GetCreature(DATA_FURIOUS_CHARGE))
+ DoCast(stalker, SPELL_ROAR);
+ events.ScheduleEvent(EVENT_JUMP_BACK, 3s, 0, PHASE_CHARGE);
+ break;
+ case EVENT_JUMP_BACK:
+ if (Creature* stalker = instance->GetCreature(DATA_FURIOUS_CHARGE))
+ DoCast(stalker, SPELL_JUMP_BACK);
+ events.ScheduleEvent(EVENT_TRAMPLE, 2s, 0, PHASE_CHARGE);
+ break;
+ case EVENT_TRAMPLE:
+ if (Creature* stalker = instance->GetCreature(DATA_FURIOUS_CHARGE))
+ me->GetMotionMaster()->MoveCharge(stalker->GetPositionX(), stalker->GetPositionY(), stalker->GetPositionZ(), 42.0f, POINT_ICEHOWL_CHARGE);
+ me->SetTarget(ObjectGuid::Empty);
+ break;
+ case EVENT_FEROCIOUS_BUTT:
+ DoCastVictim(SPELL_FEROCIOUS_BUTT);
+ events.Repeat(20s);
+ break;
+ case EVENT_ARCTIC_BREATH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_ARCTIC_BREATH);
+ events.Repeat(24s);
+ break;
+ case EVENT_WHIRL:
+ DoCastSelf(SPELL_WHIRL);
+ events.Repeat(16s);
+ break;
+ default:
+ break;
}
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_gormok_jump_to_hand_AuraScript();
}
};
-class spell_gormok_ride_player : public SpellScriptLoader
+// 66342 - Jump to Hand
+class spell_gormok_jump_to_hand : public AuraScript
{
-public:
- spell_gormok_ride_player() : SpellScriptLoader("spell_gormok_ride_player") { }
+ PrepareAuraScript(spell_gormok_jump_to_hand);
- class spell_gormok_ride_player_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spell*/) override
{
- PrepareAuraScript(spell_gormok_ride_player_AuraScript);
+ return ValidateSpellInfo({ SPELL_RIDE_PLAYER });
+ }
- bool Load() override
- {
- if (GetCaster() && GetCaster()->GetEntry() == NPC_SNOBOLD_VASSAL)
- return true;
- return false;
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster || caster->GetEntry() != NPC_SNOBOLD_VASSAL)
+ return;
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* target = GetTarget();
- if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
- return;
+ if (Creature* gormok = GetTarget()->ToCreature())
+ if (Unit* target = gormok->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, SnobolledTargetSelector()))
+ {
+ gormok->AI()->Talk(EMOTE_SNOBOLLED);
+ caster->GetAI()->DoAction(ACTION_ACTIVE_SNOBOLD);
+ caster->CastSpell(target, SPELL_RIDE_PLAYER, true);
+ }
+ }
- if (!target->CreateVehicleKit(PLAYER_VEHICLE_ID, 0))
- return;
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_gormok_jump_to_hand::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- if (Unit *caster = GetCaster())
- caster->GetAI()->SetGUID(target->GetGUID(), DATA_NEW_TARGET);
- }
+// 66245 - Ride Vehicle
+class spell_gormok_ride_player : public AuraScript
+{
+ PrepareAuraScript(spell_gormok_ride_player);
- void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->RemoveVehicleKit();
- }
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
+ return;
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_gormok_ride_player_AuraScript::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_gormok_ride_player_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
- }
- };
+ if (Unit *caster = GetCaster())
+ if (caster->IsAIEnabled)
+ caster->GetAI()->SetGUID(target->GetGUID(), DATA_NEW_TARGET);
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_gormok_ride_player_AuraScript();
+ OnEffectApply += AuraEffectApplyFn(spell_gormok_ride_player::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
}
};
-class spell_gormok_snobolled : public SpellScriptLoader
+// 66406 - Snobolled!
+class spell_gormok_snobolled : public AuraScript
{
-public:
- spell_gormok_snobolled() : SpellScriptLoader("spell_gormok_snobolled") { }
+ PrepareAuraScript(spell_gormok_snobolled);
- class spell_gormok_snobolled_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spell*/) override
{
- PrepareAuraScript(spell_gormok_snobolled_AuraScript);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- return ValidateSpellInfo({ SPELL_RIDE_PLAYER });
- }
-
- void OnPeriodic(AuraEffect const* /*aurEff*/)
- {
- if (!GetTarget()->HasAura(SPELL_RIDE_PLAYER))
- Remove();
- }
+ return ValidateSpellInfo({ SPELL_RIDE_PLAYER });
+ }
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_gormok_snobolled_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ if (!GetTarget()->HasAura(SPELL_RIDE_PLAYER))
+ Remove();
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_gormok_snobolled_AuraScript();
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_gormok_snobolled::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
-class spell_jormungars_paralytic_toxin : public SpellScriptLoader
+// 66823 - Paralytic Toxin
+class spell_jormungars_paralytic_toxin : public AuraScript
{
-public:
- spell_jormungars_paralytic_toxin() : SpellScriptLoader("spell_jormungars_paralytic_toxin") { }
+ PrepareAuraScript(spell_jormungars_paralytic_toxin);
- class spell_jormungars_paralytic_toxin_AuraScript : public AuraScript
+ bool Validate(SpellInfo const* /*spell*/) override
{
- PrepareAuraScript(spell_jormungars_paralytic_toxin_AuraScript);
+ return ValidateSpellInfo({ SPELL_PARALYSIS });
+ }
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo({ SPELL_PARALYSIS });
- }
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* caster = GetCaster();
+ if (caster && caster->GetEntry() == NPC_ACIDMAW)
+ if (Creature* acidmaw = caster->ToCreature())
+ acidmaw->AI()->Talk(SAY_SPECIAL, GetTarget());
+ }
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* caster = GetCaster();
- if (caster && caster->GetEntry() == NPC_ACIDMAW)
- {
- if (Creature* acidMaw = caster->ToCreature())
- acidMaw->AI()->Talk(SAY_SPECIAL, GetTarget());
- }
- }
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_PARALYSIS);
+ }
- void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- GetTarget()->RemoveAurasDueToSpell(SPELL_PARALYSIS);
- }
+ void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)
+ {
+ if (!canBeRecalculated)
+ amount = aurEff->GetAmount();
+
+ canBeRecalculated = false;
+ }
- void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)
+ void HandleDummy(AuraEffect const* /*aurEff*/)
+ {
+ if (AuraEffect* slowEff = GetEffect(EFFECT_0))
{
- if (!canBeRecalculated)
- amount = aurEff->GetAmount();
+ int32 newAmount = slowEff->GetAmount() - 10;
+ if (newAmount < -100)
+ newAmount = -100;
+ slowEff->ChangeAmount(newAmount);
- canBeRecalculated = false;
+ if (newAmount == -100 && !GetTarget()->HasAura(SPELL_PARALYSIS))
+ GetTarget()->CastSpell(GetTarget(), SPELL_PARALYSIS, true, nullptr, slowEff, GetCasterGUID());
}
+ }
- void HandleDummy(AuraEffect const* /*aurEff*/)
- {
- if (AuraEffect* slowEff = GetEffect(EFFECT_0))
- {
- int32 newAmount = slowEff->GetAmount() - 10;
- if (newAmount < -100)
- newAmount = -100;
- slowEff->ChangeAmount(newAmount);
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralytic_toxin::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_jormungars_paralytic_toxin::OnRemove, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL);
+ DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_jormungars_paralytic_toxin::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_jormungars_paralytic_toxin::HandleDummy, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
- if (newAmount <= -100 && !GetTarget()->HasAura(SPELL_PARALYSIS))
- GetTarget()->CastSpell(GetTarget(), SPELL_PARALYSIS, true, nullptr, slowEff, GetCasterGUID());
- }
- }
+// 66870 - Burning Bile
+class spell_jormungars_burning_bile : public SpellScript
+{
+ PrepareSpellScript(spell_jormungars_burning_bile);
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralytic_toxin_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectRemoveFn(spell_jormungars_paralytic_toxin_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL);
- DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_jormungars_paralytic_toxin_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED);
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_jormungars_paralytic_toxin_AuraScript::HandleDummy, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
+ }
- AuraScript* GetAuraScript() const override
+ void Register() override
{
- return new spell_jormungars_paralytic_toxin_AuraScript();
+ OnEffectHitTarget += SpellEffectFn(spell_jormungars_burning_bile::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -1398,6 +1201,8 @@ class spell_jormungars_slime_pool : public AuraScript
}
};
+/* 66869 - Burning Bile
+ 66823 - Paralytic Toxin */
class spell_jormungars_snakes_spray : public SpellScriptLoader
{
public:
@@ -1418,15 +1223,13 @@ public:
void HandleScript(SpellEffIndex /*effIndex*/)
{
- if (Player* target = GetHitPlayer())
- GetCaster()->CastSpell(target, _spellId, true);
+ GetCaster()->CastSpell(GetHitUnit(), _spellId, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_jormungars_snakes_spray_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
-
uint32 _spellId;
};
@@ -1439,55 +1242,115 @@ private:
uint32 _spellId;
};
-class spell_jormungars_paralysis : public SpellScriptLoader
+// 66830 - Paralysis
+class spell_jormungars_paralysis : public AuraScript
{
-public:
- spell_jormungars_paralysis() : SpellScriptLoader("spell_jormungars_paralysis") { }
+ PrepareAuraScript(spell_jormungars_paralysis);
- class spell_jormungars_paralysis_AuraScript : public AuraScript
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- PrepareAuraScript(spell_jormungars_paralysis_AuraScript);
+ if (Unit* caster = GetCaster())
+ if (InstanceScript* instance = caster->GetInstanceScript())
+ if (instance->GetBossState(DATA_NORTHREND_BEASTS) == IN_PROGRESS)
+ return;
- void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- if (Unit* caster = GetCaster())
- if (InstanceScript* instance = caster->GetInstanceScript())
- if (instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_IN_PROGRESS || instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL)
- return;
+ Remove();
+ }
- Remove();
- }
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralysis::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- void Register() override
- {
- AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralysis_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
- }
- };
+// 66688 - Arctic Breath
+class spell_icehowl_arctic_breath : public SpellScript
+{
+ PrepareSpellScript(spell_icehowl_arctic_breath);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0)->CalcValue()) });
+ }
+
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ uint32 spellId = GetSpellInfo()->GetEffect(effIndex)->CalcValue();
+ GetCaster()->CastSpell(GetHitUnit(), spellId, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_icehowl_arctic_breath::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// 66734 - Trample
+class spell_icehowl_trample : public SpellScript
+{
+ PrepareSpellScript(spell_icehowl_trample);
+
+ void CheckTargets(std::list<WorldObject*>& targets)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster || !caster->IsAIEnabled)
+ return;
- AuraScript* GetAuraScript() const override
+ if (targets.empty())
+ caster->AI()->DoAction(ACTION_TRAMPLE_FAIL);
+ else
+ caster->AI()->DoAction(ACTION_ENRAGE);
+ }
+
+ void Register() override
{
- return new spell_jormungars_paralysis_AuraScript();
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_icehowl_trample::CheckTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+};
+
+// 66683 - Massive Crash
+class spell_icehowl_massive_crash : public AuraScript
+{
+ PrepareAuraScript(spell_icehowl_massive_crash);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SURGE_OF_ADRENALINE });
+ }
+
+ void HandleSpeed(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Player* target = GetTarget()->ToPlayer())
+ if (target->GetMap()->IsHeroic())
+ target->CastSpell(target, SPELL_SURGE_OF_ADRENALINE, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_icehowl_massive_crash::HandleSpeed, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_northrend_beasts()
{
- new boss_gormok();
- new npc_snobold_vassal();
- new npc_firebomb();
- new spell_gormok_fire_bomb();
- new spell_gormok_jump_to_hand();
- new spell_gormok_ride_player();
- new spell_gormok_snobolled();
-
- new boss_acidmaw();
- new boss_dreadscale();
- new npc_slime_pool();
- new spell_jormungars_paralytic_toxin();
+ RegisterTrialOfTheCrusaderCreatureAI(boss_gormok);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_snobold_vassal);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_beasts_combat_stalker);
+ RegisterTrialOfTheCrusaderCreatureAI(boss_acidmaw);
+ RegisterTrialOfTheCrusaderCreatureAI(boss_dreadscale);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_jormungars_slime_pool);
+ RegisterTrialOfTheCrusaderCreatureAI(boss_icehowl);
+
+ RegisterAuraScript(spell_gormok_jump_to_hand);
+ RegisterAuraScript(spell_gormok_ride_player);
+ RegisterAuraScript(spell_gormok_snobolled);
+ RegisterAuraScript(spell_jormungars_paralytic_toxin);
+ RegisterSpellScript(spell_jormungars_burning_bile);
RegisterAuraScript(spell_jormungars_slime_pool);
new spell_jormungars_snakes_spray("spell_jormungars_burning_spray", SPELL_BURNING_BILE);
new spell_jormungars_snakes_spray("spell_jormungars_paralytic_spray", SPELL_PARALYTIC_TOXIN);
- new spell_jormungars_paralysis();
-
- new boss_icehowl();
+ RegisterAuraScript(spell_jormungars_paralysis);
+ RegisterSpellScript(spell_icehowl_arctic_breath);
+ RegisterSpellScript(spell_icehowl_trample);
+ RegisterAuraScript(spell_icehowl_massive_crash);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index 350482157e1..232c2bf8139 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -44,10 +44,14 @@ enum Texts
SAY_DEATH = 8
};
-enum Equipment
+enum Misc
{
- EQUIP_MAIN_1 = 9423,
- EQUIP_MAIN_2 = 37377
+ EQUIP_MAIN_1 = 9423,
+ EQUIP_MAIN_2 = 37377,
+ POINT_INITIAL_MOVEMENT = 1,
+ SPLINE_INITIAL_MOVEMENT = 1,
+ PHASE_EVENT = 1,
+ PHASE_COMBAT = 2
};
enum Summons
@@ -100,7 +104,8 @@ enum Events
EVENT_TWIN_SPIKE = 1,
EVENT_TOUCH = 2,
EVENT_SPECIAL_ABILITY = 3,
- EVENT_BERSERK = 4
+ EVENT_BERSERK = 4,
+ EVENT_START_MOVE = 5
};
enum Stages
@@ -124,9 +129,7 @@ enum Actions
class OrbsDespawner : public BasicEvent
{
public:
- explicit OrbsDespawner(Creature* creature) : _creature(creature)
- {
- }
+ explicit OrbsDespawner(Creature* creature) : _creature(creature) { }
bool Execute(uint64 /*currTime*/, uint32 /*diff*/) override
{
@@ -177,7 +180,6 @@ struct boss_twin_baseAI : public BossAI
void Reset() override
{
- me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
me->SetReactState(REACT_PASSIVE);
me->ModifyAuraState(AuraState, true);
/* Uncomment this once that they are floating above the ground
@@ -185,30 +187,26 @@ struct boss_twin_baseAI : public BossAI
me->SetFlying(true); */
summons.DespawnAll();
+ events.SetPhase(PHASE_EVENT);
+ events.ScheduleEvent(EVENT_START_MOVE, 4s);
}
void JustReachedHome() override
{
instance->SetBossState(DATA_TWIN_VALKIRIES, FAIL);
-
+ HandleRemoveAuras();
summons.DespawnAll();
me->DespawnOrUnsummon();
}
- void MovementInform(uint32 uiType, uint32 uiId) override
+ void MovementInform(uint32 type, uint32 pointId) override
{
- if (uiType != POINT_MOTION_TYPE)
- return;
-
- switch (uiId)
+ if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_INITIAL_MOVEMENT)
{
- case 1:
- me->RemoveUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetImmuneToPC(false);
- me->SetReactState(REACT_AGGRESSIVE);
- break;
- default:
- break;
+ me->SetImmuneToPC(false);
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (me->GetEntry() == NPC_FJOLA_LIGHTBANE) // avoid call twice
+ instance->DoCloseDoorOrButton(instance->GetGuidData(DATA_MAIN_GATE));
}
}
@@ -218,25 +216,13 @@ struct boss_twin_baseAI : public BossAI
Talk(SAY_KILL_PLAYER);
}
- void SummonedCreatureDespawn(Creature* summoned) override
+ void HandleRemoveAuras()
{
- switch (summoned->GetEntry())
- {
- case NPC_LIGHT_ESSENCE:
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_LIGHT_ESSENCE);
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POWERING_UP);
- break;
- case NPC_DARK_ESSENCE:
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DARK_ESSENCE);
- instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POWERING_UP);
- break;
- case NPC_BULLET_CONTROLLER:
- me->m_Events.AddEvent(new OrbsDespawner(me), me->m_Events.CalculateTime(100));
- break;
- default:
- break;
- }
- summons.Despawn(summoned);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_LIGHT_ESSENCE);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POWERING_UP);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DARK_ESSENCE);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POWERING_UP);
+ me->m_Events.AddEventAtOffset(new OrbsDespawner(me), 100ms);
}
void JustDied(Unit* /*killer*/) override
@@ -250,6 +236,7 @@ struct boss_twin_baseAI : public BossAI
pSister->AddDynamicFlag(UNIT_DYNFLAG_LOOTABLE);
events.Reset();
summons.DespawnAll();
+ HandleRemoveAuras();
instance->SetBossState(DATA_TWIN_VALKIRIES, DONE);
}
else
@@ -332,11 +319,35 @@ struct boss_twin_baseAI : public BossAI
DoCast(me, SPELL_BERSERK);
Talk(SAY_BERSERK);
break;
+ case EVENT_START_MOVE:
+ events.SetPhase(PHASE_COMBAT);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_INITIAL_MOVEMENT, SPLINE_INITIAL_MOVEMENT, false);
+ break;
default:
break;
}
}
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_EVENT))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
protected:
AuraStateType AuraState;
uint32 Weapon;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
index b347a7ab6df..4784ec6a3aa 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
@@ -22,10 +22,13 @@
#include "Log.h"
#include "Map.h"
#include "Player.h"
+#include "ScriptedCreature.h"
#include "TemporarySummon.h"
#include "trial_of_the_crusader.h"
#include <sstream>
+ // ToDo: Remove magic numbers of events
+
BossBoundaryData const boundaries =
{
{ DATA_NORTHREND_BEASTS, new CircleBoundary(Position(563.26f, 139.6f), 75.0) },
@@ -37,23 +40,25 @@ BossBoundaryData const boundaries =
ObjectData const creatureData[] =
{
- { NPC_GORMOK, DATA_GORMOK_THE_IMPALER },
- { NPC_ACIDMAW, DATA_ACIDMAW },
- { NPC_DREADSCALE, DATA_DREADSCALE },
- { NPC_ICEHOWL, DATA_ICEHOWL },
- { NPC_JARAXXUS, DATA_JARAXXUS },
- { NPC_CHAMPIONS_CONTROLLER, DATA_FACTION_CRUSADERS },
- { NPC_FJOLA_LIGHTBANE, DATA_FJOLA_LIGHTBANE },
- { NPC_EYDIS_DARKBANE, DATA_EYDIS_DARKBANE },
- { NPC_LICH_KING, DATA_LICH_KING },
- { NPC_ANUBARAK, DATA_ANUBARAK },
- { NPC_BARRET_RAMSEY, DATA_BARRET_RAMSEY },
- { NPC_TIRION_FORDRING, DATA_FORDRING },
- { NPC_TIRION_FORDRING_ANUBARAK, DATA_FORDRING_ANUBARAK },
- { NPC_VARIAN, DATA_VARIAN },
- { NPC_GARROSH, DATA_GARROSH },
- { NPC_FIZZLEBANG, DATA_FIZZLEBANG },
- { 0, 0 } // END
+ { NPC_GORMOK, DATA_GORMOK_THE_IMPALER },
+ { NPC_ACIDMAW, DATA_ACIDMAW },
+ { NPC_DREADSCALE, DATA_DREADSCALE },
+ { NPC_ICEHOWL, DATA_ICEHOWL },
+ { NPC_BEASTS_COMBAT_STALKER, DATA_BEASTS_COMBAT_STALKER },
+ { NPC_FURIOUS_CHARGE_STALKER, DATA_FURIOUS_CHARGE },
+ { NPC_JARAXXUS, DATA_JARAXXUS },
+ { NPC_CHAMPIONS_CONTROLLER, DATA_FACTION_CRUSADERS },
+ { NPC_FJOLA_LIGHTBANE, DATA_FJOLA_LIGHTBANE },
+ { NPC_EYDIS_DARKBANE, DATA_EYDIS_DARKBANE },
+ { NPC_LICH_KING, DATA_LICH_KING },
+ { NPC_ANUBARAK, DATA_ANUBARAK },
+ { NPC_TIRION_FORDRING, DATA_FORDRING },
+ { NPC_TIRION_FORDRING_ANUBARAK, DATA_FORDRING_ANUBARAK },
+ { NPC_VARIAN, DATA_VARIAN },
+ { NPC_GARROSH, DATA_GARROSH },
+ { NPC_FIZZLEBANG, DATA_FIZZLEBANG },
+ { NPC_LICH_KING_VOICE, DATA_LICH_KING_VOICE },
+ { 0, 0 } // END
};
ObjectData const gameObjectData[] =
@@ -77,6 +82,17 @@ ObjectData const gameObjectData[] =
{ 0, 0 } // END
};
+DoorData const doorData[] =
+{
+ { GO_EAST_PORTCULLIS, DATA_NORTHREND_BEASTS, DOOR_TYPE_ROOM },
+ { GO_EAST_PORTCULLIS, DATA_JARAXXUS, DOOR_TYPE_ROOM },
+ { GO_EAST_PORTCULLIS, DATA_FACTION_CRUSADERS, DOOR_TYPE_ROOM },
+ { GO_EAST_PORTCULLIS, DATA_TWIN_VALKIRIES, DOOR_TYPE_ROOM },
+ { GO_EAST_PORTCULLIS, DATA_LICH_KING, DOOR_TYPE_ROOM },
+ { GO_WEB_DOOR, DATA_ANUBARAK, DOOR_TYPE_ROOM },
+ { 0, 0, DOOR_TYPE_ROOM } // END
+};
+
class instance_trial_of_the_crusader : public InstanceMapScript
{
public:
@@ -90,9 +106,12 @@ class instance_trial_of_the_crusader : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
LoadObjectData(creatureData, gameObjectData);
+ LoadDoorData(doorData);
TrialCounter = 50;
EventStage = 0;
NorthrendBeasts = NOT_STARTED;
+ NorthrendBeastsCount = 4;
+ Team = TEAM_OTHER;
EventTimer = 1000;
NotOneButTwoJormungarsTimer = 0;
ResilienceWillFixItTimer = 0;
@@ -102,19 +121,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
NeedSave = false;
}
- bool IsEncounterInProgress() const override
- {
- for (uint8 i = 0; i < EncounterCount; ++i)
- if (GetBossState(i) == IN_PROGRESS)
- return true;
-
- // Special state is set at Faction Champions after first champ dead, encounter is still in combat
- if (GetBossState(DATA_FACTION_CRUSADERS) == SPECIAL)
- return true;
-
- return false;
- }
-
void OnPlayerEnter(Player* player) override
{
if (instance->IsHeroic())
@@ -125,36 +131,27 @@ class instance_trial_of_the_crusader : public InstanceMapScript
else
player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 0);
- // make sure Anub'arak isnt missing
- if (GetBossState(DATA_LICH_KING) == DONE && TrialCounter && GetBossState(DATA_ANUBARAK) != DONE)
- if (!GetCreature(DATA_ANUBARAK))
- player->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
- }
+ if (Team == TEAM_OTHER)
+ Team = player->GetTeam();
- void OpenDoor(ObjectGuid guid)
- {
- if (!guid)
- return;
-
- if (GameObject* go = instance->GetGameObject(guid))
- go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ if (NorthrendBeasts == GORMOK_IN_PROGRESS)
+ player->CreateVehicleKit(PLAYER_VEHICLE_ID, 0);
}
- void CloseDoor(ObjectGuid guid)
+ void OnCreatureCreate(Creature* creature) override
{
- if (!guid)
- return;
-
- if (GameObject* go = instance->GetGameObject(guid))
- go->SetGoState(GO_STATE_READY);
+ InstanceScript::OnCreatureCreate(creature);
+ if (creature->GetEntry() == NPC_SNOBOLD_VASSAL)
+ snoboldGUIDS.push_back(creature->GetGUID());
}
- void OnCreatureCreate(Creature* creature) override
+ // Summon prevention to heroic modes
+ uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{
- InstanceScript::OnCreatureCreate(creature);
- if (creature->GetEntry() == NPC_BARRET_RAMSEY)
- if (!TrialCounter)
- creature->DespawnOrUnsummon();
+ if (!TrialCounter)
+ return 0;
+
+ return data->id;
}
void OnGameObjectCreate(GameObject* go) override
@@ -182,23 +179,28 @@ class instance_trial_of_the_crusader : public InstanceMapScript
case DATA_NORTHREND_BEASTS:
break;
case DATA_JARAXXUS:
- // Cleanup Icehowl
- if (Creature* icehowl = GetCreature(DATA_ICEHOWL))
- icehowl->DespawnOrUnsummon();
- if (state == DONE)
+ if (state == FAIL)
+ {
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_JARAXXUS_WIPE);
+ }
+ else if (state == DONE)
+ {
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_JARAXXUS_DEFEATED);
EventStage = 2000;
+ }
break;
case DATA_FACTION_CRUSADERS:
- // Cleanup Jaraxxus
- if (Creature* jaraxxus = GetCreature(DATA_JARAXXUS))
- jaraxxus->DespawnOrUnsummon();
- if (Creature* fizzlebang = GetCreature(DATA_FIZZLEBANG))
- fizzlebang->DespawnOrUnsummon();
switch (state)
{
case IN_PROGRESS:
ResilienceWillFixItTimer = 0;
break;
+ case FAIL:
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_FACTION_WIPE);
+ break;
case SPECIAL: //Means the first blood
ResilienceWillFixItTimer = 60*IN_MILLISECONDS;
state = IN_PROGRESS;
@@ -210,6 +212,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript
DoRespawnGameObject(GetGuidData(DATA_CRUSADERS_CHEST), 7 * DAY);
if (GameObject* cache = GetGameObject(DATA_CRUSADERS_CHEST))
cache->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_CHAMPIONS_DEFEATED);
EventStage = 3100;
break;
default:
@@ -223,12 +227,12 @@ class instance_trial_of_the_crusader : public InstanceMapScript
switch (state)
{
case FAIL:
- if (GetBossState(DATA_TWIN_VALKIRIES) == NOT_STARTED)
- state = NOT_STARTED;
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_VALKYR_WIPE);
break;
- case SPECIAL:
- if (GetBossState(DATA_TWIN_VALKIRIES) == SPECIAL)
- state = DONE;
+ case DONE:
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_VALKYR_DEFEATED);
break;
default:
break;
@@ -292,17 +296,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
break;
}
- if (IsEncounterInProgress())
- {
- CloseDoor(GetGuidData(DATA_EAST_PORTCULLIS));
- CloseDoor(GetGuidData(DATA_WEB_DOOR));
- }
- else
- {
- OpenDoor(GetGuidData(DATA_EAST_PORTCULLIS));
- OpenDoor(GetGuidData(DATA_WEB_DOOR));
- }
-
if (type < EncounterCount)
{
TC_LOG_DEBUG("scripts", "[ToCr] BossState(type %u) %u = state %u;", type, GetBossState(type), state);
@@ -320,9 +313,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
// if theres no more attemps allowed
if (!TrialCounter)
{
- if (Unit* announcer = GetCreature(DATA_BARRET_RAMSEY))
- announcer->ToCreature()->DespawnOrUnsummon();
-
if (Creature* anubarak = GetCreature(DATA_ANUBARAK))
anubarak->DespawnOrUnsummon();
}
@@ -333,15 +323,41 @@ class instance_trial_of_the_crusader : public InstanceMapScript
}
if (state == DONE || NeedSave)
- {
- if (Unit* announcer = GetCreature(DATA_BARRET_RAMSEY))
- announcer->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
Save();
- }
}
return true;
}
+ void HandleNorthrendBeastsDone()
+ {
+ --NorthrendBeastsCount;
+ if (!NorthrendBeastsCount)
+ {
+ SetData(TYPE_NORTHREND_BEASTS, DONE);
+ SetBossState(DATA_NORTHREND_BEASTS, DONE);
+ SetData(DATA_DESPAWN_SNOBOLDS, 0);
+ EventStage = 400;
+ if (Creature* combatStalker = GetCreature(DATA_BEASTS_COMBAT_STALKER))
+ combatStalker->DespawnOrUnsummon();
+ HandlePlayerVehicle(false);
+ if (Creature* fordring = GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_NORTHREND_BEASTS_DEFEATED);
+ }
+ }
+
+ void HandlePlayerVehicle(bool apply)
+ {
+ Map::PlayerList const &players = instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource())
+ {
+ if (apply)
+ player->CreateVehicleKit(PLAYER_VEHICLE_ID, 0);
+ else
+ player->RemoveVehicleKit();
+ }
+ }
+
void SetData(uint32 type, uint32 data) override
{
switch (type)
@@ -362,34 +378,49 @@ class instance_trial_of_the_crusader : public InstanceMapScript
NorthrendBeasts = data;
switch (data)
{
+ case GORMOK_IN_PROGRESS:
+ SetBossState(DATA_NORTHREND_BEASTS, IN_PROGRESS);
+ NorthrendBeastsCount = 4;
+ HandlePlayerVehicle(true);
+ break;
case GORMOK_DONE:
- EventStage = 200;
- SetData(TYPE_NORTHREND_BEASTS, IN_PROGRESS);
+ if (Creature* tirion = GetCreature(DATA_FORDRING))
+ tirion->AI()->DoAction(ACTION_START_JORMUNGARS);
+ HandleNorthrendBeastsDone();
break;
case SNAKES_IN_PROGRESS:
NotOneButTwoJormungarsTimer = 0;
break;
case SNAKES_SPECIAL:
NotOneButTwoJormungarsTimer = 10*IN_MILLISECONDS;
+ HandleNorthrendBeastsDone();
break;
case SNAKES_DONE:
if (NotOneButTwoJormungarsTimer > 0)
DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_WORMS_KILLED_IN_10_SECONDS);
- EventStage = 300;
- SetData(TYPE_NORTHREND_BEASTS, IN_PROGRESS);
+ if (Creature* tirion = GetCreature(DATA_FORDRING))
+ tirion->AI()->DoAction(ACTION_START_ICEHOWL);
+ HandleNorthrendBeastsDone();
break;
case ICEHOWL_DONE:
- EventStage = 400;
- SetData(TYPE_NORTHREND_BEASTS, DONE);
- SetBossState(DATA_NORTHREND_BEASTS, DONE);
+ HandleNorthrendBeastsDone();
break;
case FAIL:
+ HandlePlayerVehicle(false);
SetBossState(DATA_NORTHREND_BEASTS, FAIL);
+ if (Creature* tirion = GetCreature(DATA_FORDRING))
+ tirion->AI()->DoAction(ACTION_NORTHREND_BEASTS_WIPE);
break;
default:
break;
}
break;
+ case DATA_DESPAWN_SNOBOLDS:
+ for (ObjectGuid const guid : snoboldGUIDS)
+ if (Creature* snobold = instance->GetCreature(guid))
+ snobold->DespawnOrUnsummon();
+ snoboldGUIDS.clear();
+ break;
//Achievements
case DATA_SNOBOLD_COUNT:
if (data == INCREASE)
@@ -412,6 +443,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript
{
switch (type)
{
+ case DATA_TEAM:
+ return Team;
case TYPE_COUNTER:
return TrialCounter;
case TYPE_EVENT:
@@ -524,7 +557,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
NotOneButTwoJormungarsTimer -= diff;
}
- if (GetBossState(DATA_FACTION_CRUSADERS) == SPECIAL && ResilienceWillFixItTimer)
+ if (GetBossState(DATA_FACTION_CRUSADERS) == IN_PROGRESS && ResilienceWillFixItTimer)
{
if (ResilienceWillFixItTimer <= diff)
ResilienceWillFixItTimer = 0;
@@ -624,15 +657,18 @@ class instance_trial_of_the_crusader : public InstanceMapScript
uint32 EventStage;
uint32 EventTimer;
uint32 NorthrendBeasts;
- bool NeedSave;
+ uint32 Team;
+ bool NeedSave;
std::string SaveDataBuffer;
+ GuidVector snoboldGUIDS;
// Achievement stuff
uint32 NotOneButTwoJormungarsTimer;
uint32 ResilienceWillFixItTimer;
- uint8 SnoboldCount;
- uint8 MistressOfPainCount;
- bool TributeToImmortalityEligible;
+ uint8 SnoboldCount;
+ uint8 MistressOfPainCount;
+ uint8 NorthrendBeastsCount;
+ bool TributeToImmortalityEligible;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
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 1a134bbf191..7d57afe379b 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
@@ -15,9 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-//Known Bugs:
-// - Need better implementation of Gossip and correct gossip text and option
-
#include "ScriptMgr.h"
#include "GameObject.h"
#include "InstanceScript.h"
@@ -27,113 +24,143 @@
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
#include "TemporarySummon.h"
#include "trial_of_the_crusader.h"
+#include "Weather.h"
enum Yells
{
- // Highlord Tirion Fordring - 34996
- SAY_STAGE_0_01 = 0,
- SAY_STAGE_0_02 = 1,
- SAY_STAGE_0_04 = 2,
- SAY_STAGE_0_05 = 3,
- SAY_STAGE_0_06 = 4,
- SAY_STAGE_0_WIPE = 5,
- SAY_STAGE_1_01 = 6,
- SAY_STAGE_1_07 = 7,
- SAY_STAGE_1_08 = 8,
- SAY_STAGE_1_11 = 9,
- SAY_STAGE_2_01 = 10,
- SAY_STAGE_2_03 = 11,
- SAY_STAGE_2_06 = 12,
- SAY_STAGE_3_01 = 13,
- SAY_STAGE_3_02 = 14,
- SAY_STAGE_4_01 = 15,
- SAY_STAGE_4_03 = 16,
+ // Highlord Tirion Fordring
+ TIRION_SAY_WELCOME = 0,
+ TIRION_SAY_GORMOK = 1,
+ TIRION_SAY_JORMUNGARS = 2,
+ TIRION_SAY_ICEHOWL = 3,
+ TIRION_SAY_BEASTS_DONE = 4,
+ TIRION_SAY_BEASTS_WIPE = 5,
+ TIRION_SAY_WILFRED = 6,
+ TIRION_SAY_KILL_JARAXXUS = 7,
+ TIRION_SAY_LAMENT = 8,
+ TIRION_SAY_CALM_DOWN = 9,
+ TIRION_SAY_CHAMPIONS = 10,
+ TIRION_SAY_ALLOW_COMBAT = 11,
+ TIRION_SAY_TRAGIC_VICTORY = 12,
+ TIRION_SAY_WORK_TOGETHER = 13,
+ TIRION_SAY_GAME_BEGIN = 14,
+ TIRION_SAY_UNITED = 15,
+ TIRION_SAY_ARTHAS = 16,
// Varian Wrynn
- SAY_STAGE_0_03a = 0,
- SAY_STAGE_1_10 = 1,
- SAY_STAGE_2_02a = 2,
- SAY_STAGE_2_04a = 3,
- SAY_STAGE_2_05a = 4,
- SAY_STAGE_3_03a = 5,
+ VARIAN_SAY_BEASTS = 0,
+ VARIAN_SAY_COME_PIGS = 1,
+ VARIAN_SAY_DEMAND_JUSTICE = 2,
+ VARIAN_SAY_FIGHT_GLORY = 3,
+ VARIAN_SAY_FACTION_DEAD = 4,
+ VARIAN_SAY_VALKYR_DEAD = 5,
+ VARIAN_SAY_KILLED = 6,
// Garrosh
- SAY_STAGE_0_03h = 0,
- SAY_STAGE_1_09 = 1,
- SAY_STAGE_2_02h = 2,
- SAY_STAGE_2_04h = 3,
- SAY_STAGE_2_05h = 4,
- SAY_STAGE_3_03h = 5,
+ GARROSH_SAY_BEASTS = 0,
+ GARROSH_SAY_ALLIANCE_DOGS = 1,
+ GARROSH_SAY_DEMAND_JUSTICE = 2,
+ GARROSH_SAY_NO_MERCY = 3,
+ GARROSH_SAY_FACTION_DEAD = 4,
+ GARROSH_SAY_VALKYR_DEAD = 5,
+ GARROSH_SAY_KILLED = 6,
// Wilfred Fizzlebang
- SAY_STAGE_1_02 = 0,
- SAY_STAGE_1_03 = 1,
- SAY_STAGE_1_04 = 2,
- SAY_STAGE_1_06 = 3,
+ WILFRED_SAY_INTRO = 0,
+ WILFRED_SAY_OBLIVION = 1,
+ WILFRED_SAY_MASTER = 2,
+ WILFRED_SAY_DEAD = 3,
- // Lord Jaraxxus
- SAY_STAGE_1_05 = 0,
+ // The Lich King Voice
+ LK_VOICE_SAY_CHALLENGE = 4,
+ LK_VOICE_SAY_SOULS_WILL_BE_MINE = 5,
// The Lich King
- SAY_STAGE_4_02 = 0,
- SAY_STAGE_4_05 = 1,
- SAY_STAGE_4_04 = 2,
+ LK_SAY_EMPIRE = 0,
- // Highlord Tirion Fordring - 36095
- SAY_STAGE_4_06 = 0,
- SAY_STAGE_4_07 = 1
+ // Highlord Tirion Fordring (Anu'barak)
+ SAY_STAGE_4_06 = 0,
+ SAY_STAGE_4_07 = 1
};
-Position const ToCSpawnLoc[] =
+enum TrialMisc
{
- { 563.912f, 261.625f, 394.73f, 4.70437f }, // 0 Center
- { 575.451f, 261.496f, 394.73f, 4.6541f }, // 1 Left
- { 549.951f, 261.55f, 394.73f, 4.74835f } // 2 Right
+ SPLINE_INITIAL_MOVEMENT = 1,
+ POINT_SUMMON = 1,
+ POINT_MIDDLE = 2,
+ GROUP_VALKYR = 1,
+ GOSSIPID_FAIL = 1,
+ POINT_BARRETT_DESPAWN = 1,
+ AREA_TRIAL_OF_THE_CRUSADER = 4722
};
-Position const ToCCommonLoc[] =
+enum TrialEvents
{
- { 559.257996f, 90.266197f, 395.122986f, 0 }, // 0 Barrent
-
- { 563.672974f, 139.571f, 393.837006f, 0 }, // 1 Center
- { 563.833008f, 187.244995f, 394.5f, 0 }, // 2 Backdoor
- { 577.347839f, 195.338888f, 395.14f, 0 }, // 3 - Right
- { 550.955933f, 195.338888f, 395.14f, 0 }, // 4 - Left
- { 563.833008f, 195.244995f, 394.585561f, 0 }, // 5 - Center
- { 573.5f, 180.5f, 395.14f, 0 }, // 6 Move 0 Right
- { 553.5f, 180.5f, 395.14f, 0 }, // 7 Move 0 Left
- { 573.0f, 170.0f, 395.14f, 0 }, // 8 Move 1 Right
- { 555.5f, 170.0f, 395.14f, 0 }, // 9 Move 1 Left
- { 563.8f, 216.1f, 395.1f, 0 }, // 10 Behind the door
-
- { 575.042358f, 195.260727f, 395.137146f, 0 }, // 5
- { 552.248901f, 195.331955f, 395.132658f, 0 }, // 6
- { 573.342285f, 195.515823f, 395.135956f, 0 }, // 7
- { 554.239929f, 195.825577f, 395.137909f, 0 }, // 8
- { 571.042358f, 195.260727f, 395.137146f, 0 }, // 9
- { 556.720581f, 195.015472f, 395.132658f, 0 }, // 10
- { 569.534119f, 195.214478f, 395.139526f, 0 }, // 11
- { 569.231201f, 195.941071f, 395.139526f, 0 }, // 12
- { 558.811610f, 195.985779f, 394.671661f, 0 }, // 13
- { 567.641724f, 195.351501f, 394.659943f, 0 }, // 14
- { 560.633972f, 195.391708f, 395.137543f, 0 }, // 15
- { 565.816956f, 195.477921f, 395.136810f, 0 } // 16
+ EVENT_GORMOK_INTRO = 1,
+ EVENT_GORMOK_EXCLAMATION,
+ EVENT_SPAWM_GORMOK,
+ EVENT_EXCLAMATION,
+ EVENT_SUMMON_BARRET,
+ EVENT_START_CALL_WILFRED,
+ EVENT_KILL_JARAXXUS,
+ EVENT_EMOTE_SHEATHE,
+ EVENT_TIRION_LAMENT,
+ EVENT_TIRION_CALM_DOWN,
+ EVENT_ALLOW_COMBAT,
+ EVENT_TRAGIC_VICTORY,
+ EVENT_SUMMON_WILFRED,
+ EVENT_START_MOVE,
+ EVENT_OBLIVION,
+ EVENT_SUMMON_JARAXXUS,
+ EVENT_SET_TARGET,
+ EVENT_LAST_TALK,
+ EVENT_SUMMON_VALKYR,
+ EVENT_OPEN_GATE,
+ EVENT_SAY_ARTHAS,
+ EVENT_ALLIANCE_DOGS,
+ EVENT_COME_PIGS,
+ EVENT_DEMAND_JUSTICE,
+ EVENT_NO_MERCY,
+ EVENT_VALKYR_DEAD,
+ EVENT_LICH_KING_SAY_CHALLENGE,
+ EVENT_LICH_KING_SAY_SOULS,
+ EVENT_SUMMON_LICH_KING,
+ EVENT_BREAK_PLATFORM,
+ EVENT_EMOTE_TALK,
+ EVENT_REMOVE_EMOTE_TALK,
+ EVENT_EMOTE_EXCLAMATION,
+ EVENT_EMOTE_KNEEL,
+ EVENT_SUMMON_CHAMPIONS,
+ EVENT_START_CHAMPIONS,
+ EVENT_START_TALK
};
-Position const TwinValkyrsLoc[] =
+enum TocMenuIds
{
- { 586.060242f, 117.514809f, 394.41f, 0 }, // 0 - Dark essence 1
- { 541.602112f, 161.879837f, 394.41f, 0 }, // 1 - Dark essence 2
- { 541.021118f, 117.262932f, 394.41f, 0 }, // 2 - Light essence 1
- { 586.200562f, 162.145523f, 394.41f, 0 } // 3 - Light essence 2
+ MENUID_NORTHREND_BEASTS = 10600,
+ MENUID_JARAXXUS = 10610,
+ MENUID_FACTION_CHAMPIONS = 10687,
+ MENUID_VALKYR = 10688,
+ MENUID_LK = 10693
};
-Position const LichKingLoc[] =
+Position const BarretSpawnPosition = { 559.1528f, 90.55729f, 395.2734f, 5.078908f };
+Position const WilfredSpawnPosition = { 563.6007f, 208.5278f, 395.2696f, 4.729842f };
+Position const JaraxxusSpawnPosition = { 563.8264f, 140.6563f, 393.9861f, 4.694936f };
+Position const PortalTargetSpawnPosition = { 563.6597f, 139.7569f, 399.2507f, 4.712389f };
+Position const PurpleGroundSpawnPosition = { 563.6858f, 139.4323f, 393.9862f, 4.694936f };
+Position const ArthasPortalSpawnPosition = { 563.6996f, 175.9826f, 394.5042f, 4.694936f };
+Position const LichKingSpawnPosition = { 563.5712f, 174.8351f, 394.4954f, 4.712389f };
+Position const CorpseTeleportPosition = { 631.9390f, 136.5040f, 142.5540f, 0.803332f };
+
+Position const NorthrendBeastsSpawnPositions[] =
{
- { 563.549f, 152.474f, 394.393f, 0 }, // 0 - Lich king start
- { 563.547f, 141.613f, 393.908f, 0 } // 1 - Lich king end
+ { 563.9358f, 229.8299f, 394.8061f, 4.694936f }, // Gormok \ Icehowl
+ { 564.2802f, 233.1322f, 394.7897f, 1.621917f }, // Dreadscale
};
Position const AnubarakLoc[] =
@@ -153,895 +180,728 @@ Position const EndSpawnLoc[] =
{ 644.6250f, 149.2743f, 140.6015f, 5.f } // 2 - Portal to Dalaran
};
-struct _Messages
+// ToDo: Remove it in nexts rewrites
+Position const ToCCommonLoc[] =
{
- AnnouncerMessages msgnum;
- uint32 id;
- bool state;
- uint32 encounter;
-};
+ { 559.257996f, 90.266197f, 395.122986f, 0.0f }, // 0 Barrent
+ { 563.672974f, 139.57100f, 393.837006f, 0.0f }, // 1 Center
+ { 563.833008f, 187.244995f, 394.50000f, 0.0f }, // 2 Backdoor
+ { 577.347839f, 195.338888f, 395.14000f, 0.0f }, // 3 - Right
+ { 550.955933f, 195.338888f, 395.14000f, 0.0f }, // 4 - Left
+ { 563.833008f, 195.244995f, 394.585561f, 0.0f }, // 5 - Center
+ { 573.500000f, 180.500000f, 395.14f, 0.0f }, // 6 Move 0 Right
+ { 553.5f, 180.5f, 395.14f, 0 }, // 7 Move 0 Left
+ { 573.0f, 170.0f, 395.14f, 0 }, // 8 Move 1 Right
+ { 549.5139f, 170.1389f, 394.7965f, 5.009095f }, // 9 Move 1 Left
+ { 563.8f, 216.1f, 395.1f, 0 }, // 10 Behind the door
-static _Messages _GossipMessage[]=
-{
- {MSG_BEASTS, GOSSIP_ACTION_INFO_DEF + 1, false, DATA_NORTHREND_BEASTS},
- {MSG_JARAXXUS, GOSSIP_ACTION_INFO_DEF + 2, false, DATA_JARAXXUS},
- {MSG_CRUSADERS, GOSSIP_ACTION_INFO_DEF + 3, false, DATA_FACTION_CRUSADERS},
- {MSG_VALKIRIES, GOSSIP_ACTION_INFO_DEF + 4, false, DATA_TWIN_VALKIRIES},
- {MSG_LICH_KING, GOSSIP_ACTION_INFO_DEF + 5, false, DATA_ANUBARAK},
- {MSG_ANUBARAK, GOSSIP_ACTION_INFO_DEF + 6, true, DATA_ANUBARAK}
+ { 575.042358f, 195.260727f, 395.137146f, 0 }, // 5
+ { 552.248901f, 195.331955f, 395.132658f, 0 }, // 6
+ { 573.342285f, 195.515823f, 395.135956f, 0 }, // 7
+ { 554.239929f, 195.825577f, 395.137909f, 0 }, // 8
+ { 571.042358f, 195.260727f, 395.137146f, 0 }, // 9
+ { 556.720581f, 195.015472f, 395.132658f, 0 }, // 10
+ { 569.534119f, 195.214478f, 395.139526f, 0 }, // 11
+ { 569.231201f, 195.941071f, 395.139526f, 0 }, // 12
+ { 558.811610f, 195.985779f, 394.671661f, 0 }, // 13
+ { 567.641724f, 195.351501f, 394.659943f, 0 }, // 14
+ { 560.633972f, 195.391708f, 395.137543f, 0 }, // 15
+ { 565.816956f, 195.477921f, 395.136810f, 0 } // 16
};
-enum Messages
+class ArthasPortalEvent : public BasicEvent
{
- NUM_MESSAGES = 6
+public:
+ ArthasPortalEvent(Unit* owner) : BasicEvent(), _owner(owner) { }
+
+ bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override
+ {
+ _owner->CastSpell(_owner, SPELL_ARTHAS_PORTAL, true);
+ _owner->GetMap()->SetZoneWeather(AREA_TRIAL_OF_THE_CRUSADER, WEATHER_STATE_MEDIUM_SNOW, 0.75f);
+ return true;
+ }
+
+private:
+ Unit* _owner;
};
-class npc_announcer_toc10 : public CreatureScript
+struct npc_barrett_toc : public ScriptedAI
{
- public:
- npc_announcer_toc10() : CreatureScript("npc_announcer_toc10") { }
-
- struct npc_announcer_toc10AI : public ScriptedAI
+ npc_barrett_toc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void SendActionToTirion(uint32 action)
+ {
+ if (Creature* fordring = _instance->GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(action);
+ me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BARRETT_DESPAWN, SPLINE_INITIAL_MOVEMENT, false);
+ }
+
+ bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
+ {
+ switch (menuId)
{
- npc_announcer_toc10AI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
-
- InstanceScript* instance;
-
- void Reset() override
- {
- me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- if (Creature* pAlly = GetClosestCreatureWithEntry(me, NPC_THRALL, 300.0f))
- pAlly->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- if (Creature* pAlly = GetClosestCreatureWithEntry(me, NPC_PROUDMOORE, 300.0f))
- pAlly->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- }
-
- void AttackStart(Unit* /*who*/) override { }
-
- bool GossipHello(Player* player) override
- {
- char const* _message = "We are ready!";
-
- if (player->IsInCombat() || instance->IsEncounterInProgress())
- return true;
-
- uint8 i = 0;
- for (; i < NUM_MESSAGES; ++i)
+ case MENUID_NORTHREND_BEASTS:
+ if (gossipListId == GOSSIPID_FAIL)
+ SendActionToTirion(ACTION_START_GORMOK_FAIL);
+ else
+ SendActionToTirion(ACTION_START_GORMOK);
+ break;
+ case MENUID_JARAXXUS:
+ if (gossipListId == GOSSIPID_FAIL)
{
- if ((!_GossipMessage[i].state && instance->GetBossState(_GossipMessage[i].encounter) != DONE)
- || (_GossipMessage[i].state && instance->GetBossState(_GossipMessage[i].encounter) == DONE))
- {
- AddGossipItemFor(player, GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN, _GossipMessage[i].id);
- break;
- }
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
+ jaraxxus->AI()->DoAction(ACTION_JARAXXUS_ENGAGE);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_BARRETT_DESPAWN, SPLINE_INITIAL_MOVEMENT, false);
+ CloseGossipMenuFor(player);
+ return true;
}
+ else
+ SendActionToTirion(ACTION_START_JARAXXUS_EVENT);
+ break;
+ case MENUID_FACTION_CHAMPIONS:
+ if (gossipListId == GOSSIPID_FAIL)
+ SendActionToTirion(ACTION_START_CHAMPIONS_ENGAGE);
+ else
+ SendActionToTirion(ACTION_START_CHAMPIONS);
+ break;
+ case MENUID_VALKYR:
+ if (gossipListId == GOSSIPID_FAIL)
+ SendActionToTirion(ACTION_START_VALKYR_ENGAGE);
+ else
+ SendActionToTirion(ACTION_START_VALKYR);
+ break;
+ case MENUID_LK:
+ SendActionToTirion(ACTION_START_LK_EVENT);
+ break;
+ default:
+ return false;
+ }
- if (i >= NUM_MESSAGES)
- return false;
+ CloseGossipMenuFor(player);
+ return true;
+ }
- SendGossipMenuFor(player, _GossipMessage[i].msgnum, me->GetGUID());
- return true;
- }
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
- {
- ClearGossipMenuFor(player);
- CloseGossipMenuFor(player);
+ if (pointId == POINT_BARRETT_DESPAWN)
+ me->DespawnOrUnsummon();
+ }
- if (instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
- {
- instance->SetData(TYPE_EVENT, 110);
- instance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED);
- instance->SetBossState(DATA_NORTHREND_BEASTS, NOT_STARTED);
- }
- else if (instance->GetBossState(DATA_JARAXXUS) != DONE)
- {
- // if Jaraxxus is spawned, but the raid wiped
- if (Creature* jaraxxus = instance->GetCreature(DATA_JARAXXUS))
- {
- jaraxxus->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS);
- jaraxxus->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- jaraxxus->SetImmuneToPC(false);
- jaraxxus->SetReactState(REACT_DEFENSIVE);
- jaraxxus->SetInCombatWithZone();
- }
- else
- {
- instance->SetData(TYPE_EVENT, 1010);
- instance->SetBossState(DATA_JARAXXUS, NOT_STARTED);
- }
- }
- else if (instance->GetBossState(DATA_FACTION_CRUSADERS) != DONE)
- {
- if (player->GetTeam() == ALLIANCE)
- instance->SetData(TYPE_EVENT, 3000);
- else
- instance->SetData(TYPE_EVENT, 3001);
- instance->SetBossState(DATA_FACTION_CRUSADERS, NOT_STARTED);
- }
- else if (instance->GetBossState(DATA_TWIN_VALKIRIES) != DONE)
- {
- instance->SetData(TYPE_EVENT, 4000);
- instance->SetBossState(DATA_TWIN_VALKIRIES, NOT_STARTED);
- }
- else if (instance->GetBossState(DATA_LICH_KING) != DONE)
- {
- if (me->GetMap()->GetPlayers().getFirst()->GetSource()->GetTeam() == ALLIANCE)
- instance->SetData(TYPE_EVENT, 4020);
- else
- instance->SetData(TYPE_EVENT, 4030);
- instance->SetBossState(DATA_LICH_KING, NOT_STARTED);
- }
- me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- return true;
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<npc_announcer_toc10AI>(creature);
- }
+private:
+ InstanceScript* _instance;
};
-class boss_lich_king_toc : public CreatureScript
+struct boss_lich_king_toc : public ScriptedAI
{
- public:
- boss_lich_king_toc() : CreatureScript("boss_lich_king_toc") { }
+ boss_lich_king_toc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- struct boss_lich_king_tocAI : public ScriptedAI
- {
- boss_lich_king_tocAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = creature->GetInstanceScript();
- }
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _instance->SetBossState(DATA_LICH_KING, IN_PROGRESS);
+ _events.ScheduleEvent(EVENT_START_MOVE, 1s);
+ }
- void Reset() override
- {
- me->SetReactState(REACT_PASSIVE);
- if (Creature* summoned = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5, TEMPSUMMON_TIMED_DESPAWN, 1*MINUTE*IN_MILLISECONDS))
- {
- summoned->CastSpell(summoned, 51807, false);
- summoned->SetDisplayFromModel(1);
- }
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
- _instance->SetBossState(DATA_LICH_KING, IN_PROGRESS);
- me->SetWalk(true);
- }
+ if (pointId == POINT_MIDDLE)
+ _events.ScheduleEvent(EVENT_START_TALK, 4s);
+ }
- void MovementInform(uint32 uiType, uint32 uiId) override
- {
- if (uiType != POINT_MOTION_TYPE || !_instance)
- return;
-
- switch (uiId)
- {
- case 0:
- _instance->SetData(TYPE_EVENT, 5030);
- break;
- case 1:
- _instance->SetData(TYPE_EVENT, 5050);
- break;
- default:
- break;
- }
- }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- void UpdateAI(uint32 uiDiff) override
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (!_instance)
- return;
-
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING)
- return;
-
- uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
- if (_updateTimer <= uiDiff)
- {
- switch (_instance->GetData(TYPE_EVENT))
- {
- case 5010:
- Talk(SAY_STAGE_4_02);
- _updateTimer = 3*IN_MILLISECONDS;
- me->GetMotionMaster()->MovePoint(0, LichKingLoc[0]);
- _instance->SetData(TYPE_EVENT, 5020);
- break;
- case 5030:
- Talk(SAY_STAGE_4_04);
- me->SetEmoteState(EMOTE_STATE_TALK);
- _updateTimer = 10*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5040);
- break;
- case 5040:
- me->SetEmoteState(EMOTE_ONESHOT_NONE);
- me->GetMotionMaster()->MovePoint(1, LichKingLoc[1]);
- _updateTimer = 1*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 5050:
- me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5060);
- break;
- case 5060:
- Talk(SAY_STAGE_4_05);
- me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
- _updateTimer = 2.5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5070);
- break;
- case 5070:
- me->CastSpell(me, 68198, false);
- _updateTimer = 1.5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5080);
- break;
- case 5080:
- {
- if (GameObject* go = _instance->GetGameObject(DATA_COLISEUM_FLOOR))
- go->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
-
- me->CastSpell(me, SPELL_CORPSE_TELEPORT, false);
- me->CastSpell(me, SPELL_DESTROY_FLOOR_KNOCKUP, false);
-
- _instance->SetBossState(DATA_LICH_KING, DONE);
-
- if (!_instance->GetCreature(DATA_ANUBARAK))
- me->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
-
- _instance->SetData(TYPE_EVENT, 0);
-
- me->DespawnOrUnsummon();
- _updateTimer = 20*IN_MILLISECONDS;
- break;
- }
- default:
- break;
- }
- }
- else
- _updateTimer -= uiDiff;
-
- _instance->SetData(TYPE_EVENT_TIMER, _updateTimer);
+ case EVENT_START_MOVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_MIDDLE, SPLINE_INITIAL_MOVEMENT, true);
+ break;
+ case EVENT_BREAK_PLATFORM:
+ DoCastSelf(SPELL_LK_FROST_NOVA, true);
+ DoCastSelf(SPELL_CORPSE_TELEPORT, true);
+ DoCastSelf(SPELL_DESTROY_FLOOR_KNOCKUP, true);
+ if (Creature* fordring = _instance->GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_LK_EVENT_FINISHED);
+ if (GameObject* floor = _instance->GetGameObject(DATA_COLISEUM_FLOOR))
+ floor->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
+ _instance->SetBossState(DATA_LICH_KING, DONE);
+ break;
+ case EVENT_EMOTE_TALK:
+ me->SetEmoteState(EMOTE_STATE_TALK);
+ me->GetMap()->SetZoneWeather(AREA_TRIAL_OF_THE_CRUSADER, WEATHER_STATE_FOG, 0.0f);
+ _events.ScheduleEvent(EVENT_EMOTE_EXCLAMATION, 10s);
+ break;
+ case EVENT_EMOTE_EXCLAMATION:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ _events.ScheduleEvent(EVENT_EMOTE_KNEEL, 3s);
+ break;
+ case EVENT_EMOTE_KNEEL:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
+ break;
+ case EVENT_START_TALK:
+ Talk(LK_SAY_EMPIRE);
+ _events.ScheduleEvent(EVENT_EMOTE_TALK, 4s);
+ _events.ScheduleEvent(EVENT_BREAK_PLATFORM, 18s);
+ break;
+ default:
+ break;
}
-
- private:
- InstanceScript* _instance;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<boss_lich_king_tocAI>(creature);
}
+ }
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
};
-class npc_fizzlebang_toc : public CreatureScript
+struct npc_tirion_toc : public ScriptedAI
{
- public:
- npc_fizzlebang_toc() : CreatureScript("npc_fizzlebang_toc") { }
-
- struct npc_fizzlebang_tocAI : public ScriptedAI
+ npc_tirion_toc(Creature* creature) : ScriptedAI(creature), _instance (creature->GetInstanceScript()), _factionLeaderData(0), _summons(me),
+ _jormungarsSummoned(false), _icehowlSummoned(false) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _factionLeaderData = _instance->GetData(DATA_TEAM) == ALLIANCE ? DATA_VARIAN : DATA_GARROSH;
+ _jormungarsSummoned = false;
+ _icehowlSummoned = false;
+ HandleBarrettSummon();
+ }
+
+ void JustSummoned(Creature* summoned) override
+ {
+ _summons.Summon(summoned);
+ }
+
+ void HandleBarrettSummon()
+ {
+ if (IsHeroic() && _instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
+ me->SummonCreature(NPC_BARRETT_BEASTS_HC, BarretSpawnPosition);
+ 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);
+ else if (_instance->GetBossState(DATA_FACTION_CRUSADERS) != DONE)
+ me->SummonCreature(NPC_BARRETT_FACTION, BarretSpawnPosition);
+ else if (_instance->GetBossState(DATA_TWIN_VALKIRIES) != DONE)
+ me->SummonCreature(NPC_BARRETT_VALKYR, BarretSpawnPosition);
+ else if (_instance->GetBossState(DATA_LICH_KING) != DONE)
+ me->SummonCreature(NPC_BARRETT_LK, BarretSpawnPosition);
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- npc_fizzlebang_tocAI(Creature* creature) : ScriptedAI(creature), _summons(me)
+ case ACTION_START_GORMOK:
+ Talk(TIRION_SAY_WELCOME);
+ _events.ScheduleEvent(EVENT_GORMOK_INTRO, 24s);
+ break;
+ case ACTION_START_GORMOK_FAIL:
+ _events.ScheduleEvent(EVENT_GORMOK_INTRO, 1ms);
+ break;
+ case ACTION_START_JORMUNGARS:
+ if (_jormungarsSummoned)
+ return;
+ _jormungarsSummoned = true;
+ Talk(TIRION_SAY_JORMUNGARS);
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ me->SummonCreature(NPC_DREADSCALE, NorthrendBeastsSpawnPositions[1]);
+ _events.ScheduleEvent(EVENT_EXCLAMATION, 7s);
+ break;
+ case ACTION_START_ICEHOWL:
+ if (_icehowlSummoned)
+ return;
+ _icehowlSummoned = true;
+ Talk(TIRION_SAY_ICEHOWL);
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ me->SummonCreature(NPC_ICEHOWL, NorthrendBeastsSpawnPositions[0], TEMPSUMMON_DEAD_DESPAWN);
+ _events.ScheduleEvent(EVENT_EXCLAMATION, 6s);
+ break;
+ case ACTION_NORTHREND_BEASTS_WIPE:
+ _jormungarsSummoned = false;
+ _icehowlSummoned = false;
+ Talk(TIRION_SAY_BEASTS_WIPE);
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 13s);
+ break;
+ case ACTION_NORTHREND_BEASTS_DEFEATED:
+ Talk(TIRION_SAY_BEASTS_DONE);
+ _events.ScheduleEvent(EVENT_EXCLAMATION, 2s);
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 6s);
+ break;
+ case ACTION_START_JARAXXUS_EVENT:
+ _events.ScheduleEvent(EVENT_START_CALL_WILFRED, 1s);
+ break;
+ case ACTION_JARAXXUS_DEFEATED:
+ _events.ScheduleEvent(EVENT_TIRION_LAMENT, 7s);
+ break;
+ case ACTION_JARAXXUS_WIPE:
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 30s);
+ break;
+ case ACTION_START_CHAMPIONS:
{
- _instance = me->GetInstanceScript();
+ Talk(TIRION_SAY_CHAMPIONS);
+ uint32 data = _instance->GetData(DATA_TEAM) == ALLIANCE ? DATA_GARROSH : DATA_VARIAN;
+ if (Creature* otherFactionLeader = _instance->GetCreature(data))
+ otherFactionLeader->AI()->DoAction(ACTION_START_CHAMPIONS);
+ _events.ScheduleEvent(EVENT_ALLOW_COMBAT, 26s);
+ break;
}
-
- void JustDied(Unit* killer) override
+ case ACTION_FACTION_WIPE:
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 4s);
+ break;
+ case ACTION_START_CHAMPIONS_ENGAGE:
{
- Talk(SAY_STAGE_1_06, killer);
- _instance->SetData(TYPE_EVENT, 1180);
- if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
- {
- jaraxxus->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- jaraxxus->SetImmuneToPC(false);
- jaraxxus->SetReactState(REACT_AGGRESSIVE);
- jaraxxus->SetInCombatWithZone();
- }
+ uint32 data = _instance->GetData(DATA_TEAM) == ALLIANCE ? DATA_GARROSH : DATA_VARIAN;
+ if (Creature* otherFactionLeader = _instance->GetCreature(data))
+ otherFactionLeader->AI()->DoAction(ACTION_START_CHAMPIONS_ENGAGE);
+ _events.ScheduleEvent(EVENT_SUMMON_CHAMPIONS, 3s);
+ break;
}
+ case ACTION_CHAMPIONS_DEFEATED:
+ _events.ScheduleEvent(EVENT_TRAGIC_VICTORY, 7s);
+ break;
+ case ACTION_SUMMON_JARAXXUS:
+ me->SummonCreature(NPC_JARAXXUS, JaraxxusSpawnPosition);
+ break;
+ case ACTION_KILL_JARAXXUS:
+ _events.ScheduleEvent(EVENT_KILL_JARAXXUS, 6s);
+ break;
+ case ACTION_START_VALKYR:
+ Talk(TIRION_SAY_WORK_TOGETHER);
+ _events.ScheduleEvent(EVENT_SUMMON_VALKYR, 17s);
+ break;
+ case ACTION_VALKYR_WIPE:
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 6s);
+ _summons.DespawnEntry(NPC_LIGHT_ESSENCE);
+ _summons.DespawnEntry(NPC_DARK_ESSENCE);
+ break;
+ case ACTION_VALKYR_DEFEATED:
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 4s);
+ if (Creature* factionLeader = _instance->GetCreature(_factionLeaderData))
+ factionLeader->AI()->DoAction(ACTION_VALKYR_DEFEATED);
+ _summons.DespawnEntry(NPC_LIGHT_ESSENCE);
+ _summons.DespawnEntry(NPC_DARK_ESSENCE);
+ break;
+ case ACTION_START_VALKYR_ENGAGE:
+ Talk(TIRION_SAY_GAME_BEGIN);
+ _events.ScheduleEvent(EVENT_SUMMON_VALKYR, 5s);
+ break;
+ case ACTION_START_LK_EVENT:
+ Talk(TIRION_SAY_UNITED);
+ me->GetMap()->SetZoneWeather(AREA_TRIAL_OF_THE_CRUSADER, WEATHER_STATE_LIGHT_SNOW, 0.5f);
+ _events.ScheduleEvent(EVENT_LICH_KING_SAY_CHALLENGE, 19s);
+ _events.ScheduleEvent(EVENT_SAY_ARTHAS, 26s);
+ break;
+ case ACTION_LK_EVENT_FINISHED:
+ _events.ScheduleEvent(EVENT_LICH_KING_SAY_SOULS, 2s);
+ break;
+ default:
+ break;
+ }
+ }
- void Reset() override
- {
- _portalGUID.Clear();
- me->SetWalk(true);
- me->GetMotionMaster()->MovePoint(1, ToCCommonLoc[10].GetPositionX(), ToCCommonLoc[10].GetPositionY()-60, ToCCommonLoc[10].GetPositionZ());
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ // Needed when using hotswap
+ _summons.DespawnAll();
+ }
- void MovementInform(uint32 uiType, uint32 uiId) override
- {
- if (uiType != POINT_MOTION_TYPE)
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- switch (uiId)
- {
- case 1:
- me->SetWalk(false);
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- _instance->SetData(TYPE_EVENT, 1120);
- _instance->SetData(TYPE_EVENT_TIMER, 1*IN_MILLISECONDS);
- break;
- default:
- break;
- }
- }
-
- void JustSummoned(Creature* summoned) override
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch(eventId)
{
- _summons.Summon(summoned);
+ case EVENT_GORMOK_INTRO:
+ Talk(TIRION_SAY_GORMOK);
+ if (Creature* factionLeader = _instance->GetCreature(_factionLeaderData))
+ factionLeader->AI()->DoAction(ACTION_START_GORMOK);
+ _events.ScheduleEvent(EVENT_GORMOK_EXCLAMATION, 6s);
+ break;
+ case EVENT_GORMOK_EXCLAMATION:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ _events.ScheduleEvent(EVENT_SPAWM_GORMOK, 6s);
+ break;
+ case EVENT_SPAWM_GORMOK:
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ me->SummonCreature(NPC_GORMOK, NorthrendBeastsSpawnPositions[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 12s);
+ break;
+ case EVENT_EXCLAMATION:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case EVENT_SUMMON_BARRET:
+ HandleBarrettSummon();
+ break;
+ case EVENT_START_CALL_WILFRED:
+ Talk(TIRION_SAY_WILFRED);
+ _events.ScheduleEvent(EVENT_SUMMON_WILFRED, 7s);
+ break;
+ case EVENT_SUMMON_WILFRED:
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ me->SummonCreature(NPC_FIZZLEBANG, WilfredSpawnPosition, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 16s);
+ break;
+ case EVENT_KILL_JARAXXUS:
+ Talk(TIRION_SAY_KILL_JARAXXUS);
+ _events.ScheduleEvent(EVENT_EMOTE_SHEATHE, 2s);
+ break;
+ case EVENT_EMOTE_SHEATHE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE);
+ break;
+ case EVENT_TIRION_LAMENT:
+ Talk(TIRION_SAY_LAMENT);
+ if (Creature* varian = _instance->GetCreature(DATA_VARIAN))
+ varian->AI()->DoAction(ACTION_JARAXXUS_DEFEATED);
+ if (Creature* garrosh = _instance->GetCreature(DATA_GARROSH))
+ garrosh->AI()->DoAction(ACTION_JARAXXUS_DEFEATED);
+ _events.ScheduleEvent(EVENT_TIRION_CALM_DOWN, 33s);
+ break;
+ case EVENT_TIRION_CALM_DOWN:
+ Talk(TIRION_SAY_CALM_DOWN);
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 20s);
+ break;
+ case EVENT_ALLOW_COMBAT:
+ Talk(TIRION_SAY_ALLOW_COMBAT);
+ _events.ScheduleEvent(EVENT_SUMMON_CHAMPIONS, 7s);
+ break;
+ case EVENT_TRAGIC_VICTORY:
+ Talk(TIRION_SAY_TRAGIC_VICTORY);
+ _events.ScheduleEvent(EVENT_SUMMON_BARRET, 24s);
+ break;
+ case EVENT_SUMMON_VALKYR:
+ me->SummonCreatureGroup(GROUP_VALKYR);
+ _events.ScheduleEvent(EVENT_OPEN_GATE, 3s);
+ break;
+ case EVENT_OPEN_GATE:
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ break;
+ case EVENT_SAY_ARTHAS:
+ Talk(TIRION_SAY_ARTHAS);
+ break;
+ case EVENT_LICH_KING_SAY_CHALLENGE:
+ if (Creature* lkVoice = _instance->GetCreature(DATA_LICH_KING_VOICE))
+ lkVoice->AI()->Talk(LK_VOICE_SAY_CHALLENGE);
+ if (Creature* arthasPortal = me->SummonCreature(NPC_ARTHAS_PORTAL, ArthasPortalSpawnPosition, TEMPSUMMON_TIMED_DESPAWN, Seconds(34)))
+ arthasPortal->m_Events.AddEventAtOffset(new ArthasPortalEvent(arthasPortal), 3s);
+ _events.ScheduleEvent(EVENT_SUMMON_LICH_KING, 5s);
+ break;
+ case EVENT_LICH_KING_SAY_SOULS:
+ if (Creature* lkVoice = _instance->GetCreature(DATA_LICH_KING_VOICE))
+ lkVoice->AI()->Talk(LK_VOICE_SAY_SOULS_WILL_BE_MINE);
+ break;
+ case EVENT_SUMMON_LICH_KING:
+ me->SummonCreature(NPC_LICH_KING, LichKingSpawnPosition, TEMPSUMMON_TIMED_DESPAWN, 30s);
+ break;
+ case EVENT_SUMMON_CHAMPIONS:
+ if (Creature* factitonController = me->SummonCreature(NPC_CHAMPIONS_CONTROLLER, ToCCommonLoc[1]))
+ factitonController->AI()->SetData(0, _instance->GetData(DATA_TEAM)); // will be changed to DoAction soon
+ _events.ScheduleEvent(EVENT_START_CHAMPIONS, 3s);
+ break;
+ case EVENT_START_CHAMPIONS:
+ if (Creature* factitonController = _instance->GetCreature(DATA_FACTION_CRUSADERS))
+ factitonController->AI()->SetData(1, NOT_STARTED); // will be changed to DoAction soon
+ break;
+ default:
+ break;
}
+ }
+ }
+
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+ uint32 _factionLeaderData;
+ SummonList _summons;
+ bool _jormungarsSummoned;
+ bool _icehowlSummoned;
+};
- void UpdateAI(uint32 uiDiff) override
+struct npc_open_portal_target_toc : public ScriptedAI
+{
+ npc_open_portal_target_toc(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _scheduler.CancelAll();
+ me->SetDisableGravity(true);
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ if (spellInfo->Id == SPELL_OPEN_PORTAL)
+ {
+ _scheduler.Schedule(2s, [this](TaskContext /*wilfredPortal*/)
{
- if (!_instance)
- return;
-
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_FIZZLEBANG)
- return;
+ DoCastSelf(SPELL_WILFRED_PORTAL);
+ me->DespawnOrUnsummon(9s);
+ });
+ }
+ }
- uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
- if (_updateTimer <= uiDiff)
- {
- switch (_instance->GetData(TYPE_EVENT))
- {
- case 1110:
- _instance->SetData(TYPE_EVENT, 1120);
- _updateTimer = 4*IN_MILLISECONDS;
- break;
- case 1120:
- Talk(SAY_STAGE_1_02);
- _instance->SetData(TYPE_EVENT, 1130);
- _updateTimer = 12*IN_MILLISECONDS;
- break;
- case 1130:
- me->GetMotionMaster()->MovementExpired();
- Talk(SAY_STAGE_1_03);
- me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST_OMNI);
- if (Creature* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN))
- {
- _triggerGUID = pTrigger->GetGUID();
- pTrigger->SetObjectScale(2.0f);
- pTrigger->SetDisplayFromModel(0);
- pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false);
- }
- _instance->SetData(TYPE_EVENT, 1132);
- _updateTimer = 4*IN_MILLISECONDS;
- break;
- case 1132:
- me->GetMotionMaster()->MovementExpired();
- _instance->SetData(TYPE_EVENT, 1134);
- _updateTimer = 4*IN_MILLISECONDS;
- break;
- case 1134:
- me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST_OMNI);
- if (Creature* pPortal = me->SummonCreature(NPC_WILFRED_PORTAL, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.71239f, TEMPSUMMON_MANUAL_DESPAWN))
- {
- pPortal->SetReactState(REACT_PASSIVE);
- pPortal->SetObjectScale(2.0f);
- pPortal->CastSpell(pPortal, SPELL_WILFRED_PORTAL, false);
- _portalGUID = pPortal->GetGUID();
- }
- _updateTimer = 4*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 1135);
- break;
- case 1135:
- _instance->SetData(TYPE_EVENT, 1140);
- _updateTimer = 3*IN_MILLISECONDS;
- break;
- case 1140:
- Talk(SAY_STAGE_1_04);
- if (Creature* jaraxxus = me->SummonCreature(NPC_JARAXXUS, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 5.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
- {
- jaraxxus->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
- jaraxxus->SetImmuneToPC(true);
- jaraxxus->SetReactState(REACT_PASSIVE);
- jaraxxus->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY()-10, ToCCommonLoc[1].GetPositionZ());
- }
- _instance->SetData(TYPE_EVENT, 1142);
- _updateTimer = 5*IN_MILLISECONDS;
- break;
- case 1142:
- if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
- jaraxxus->SetTarget(me->GetGUID());
- if (Creature* pTrigger = ObjectAccessor::GetCreature(*me, _triggerGUID))
- pTrigger->DespawnOrUnsummon();
- if (Creature* pPortal = ObjectAccessor::GetCreature(*me, _portalGUID))
- pPortal->DespawnOrUnsummon();
- _instance->SetData(TYPE_EVENT, 1144);
- _updateTimer = 10*IN_MILLISECONDS;
- break;
- case 1144:
- if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
- jaraxxus->AI()->Talk(SAY_STAGE_1_05);
- _instance->SetData(TYPE_EVENT, 1150);
- _updateTimer = 5*IN_MILLISECONDS;
- break;
- case 1150:
- if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
- {
- //1-shot Fizzlebang
- jaraxxus->CastSpell(me, 67888, false); // 67888 - Fel Lightning
- AddThreat(me, 1000.0f, jaraxxus);
- jaraxxus->AI()->AttackStart(me);
- }
- _instance->SetData(TYPE_EVENT, 1160);
- _updateTimer = 3*IN_MILLISECONDS;
- break;
- }
- }
- else
- _updateTimer -= uiDiff;
- _instance->SetData(TYPE_EVENT_TIMER, _updateTimer);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
- private:
- InstanceScript* _instance;
- SummonList _summons;
- ObjectGuid _portalGUID;
- ObjectGuid _triggerGUID;
- };
+private:
+ TaskScheduler _scheduler;
+};
- CreatureAI* GetAI(Creature* creature) const override
+struct npc_fizzlebang_toc : public ScriptedAI
+{
+ npc_fizzlebang_toc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_START_MOVE, Seconds(1));
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE && pointId == POINT_SUMMON)
{
- return GetTrialOfTheCrusaderAI<npc_fizzlebang_tocAI>(creature);
+ _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
+ Talk(WILFRED_SAY_INTRO);
+ _events.ScheduleEvent(EVENT_EMOTE_TALK, 2s);
+ _events.ScheduleEvent(EVENT_REMOVE_EMOTE_TALK, 9s);
+ _events.ScheduleEvent(EVENT_OBLIVION, 11s);
}
-};
+ }
-class npc_tirion_toc : public CreatureScript
-{
- public:
- npc_tirion_toc() : CreatureScript("npc_tirion_toc") { }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- struct npc_tirion_tocAI : public ScriptedAI
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_tirion_tocAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- _instance = me->GetInstanceScript();
+ case EVENT_START_MOVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_SUMMON, SPLINE_INITIAL_MOVEMENT, true);
+ break;
+ case EVENT_OBLIVION:
+ me->SummonCreature(NPC_WILFRED_PORTAL, PortalTargetSpawnPosition);
+ me->SummonCreature(NPC_PURPLE_GROUND, PurpleGroundSpawnPosition, TEMPSUMMON_TIMED_DESPAWN, 16s);
+ Talk(WILFRED_SAY_OBLIVION);
+ DoCastSelf(SPELL_OPEN_PORTAL);
+ _events.ScheduleEvent(EVENT_SUMMON_JARAXXUS, 11s);
+ break;
+ case EVENT_SUMMON_JARAXXUS:
+ if (Creature* fordring = _instance->GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_SUMMON_JARAXXUS);
+ Talk(WILFRED_SAY_MASTER);
+ _events.ScheduleEvent(EVENT_EMOTE_TALK, 2s);
+ _events.ScheduleEvent(EVENT_REMOVE_EMOTE_TALK, 7s);
+ _events.ScheduleEvent(EVENT_SET_TARGET, 4s);
+ break;
+ case EVENT_SET_TARGET:
+ if (Creature* jaraxxus = _instance->GetCreature(DATA_JARAXXUS))
+ me->SetTarget(jaraxxus->GetGUID());
+ _events.ScheduleEvent(EVENT_EMOTE_SHEATHE, 6s);
+ break;
+ case EVENT_EMOTE_SHEATHE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE);
+ _events.ScheduleEvent(EVENT_LAST_TALK, 9s);
+ break;
+ case EVENT_LAST_TALK:
+ Talk(WILFRED_SAY_DEAD);
+ if (Creature* fordring = _instance->GetCreature(DATA_FORDRING))
+ fordring->AI()->DoAction(ACTION_KILL_JARAXXUS);
+ break;
+ case EVENT_EMOTE_TALK:
+ me->SetEmoteState(EMOTE_STATE_TALK);
+ break;
+ case EVENT_REMOVE_EMOTE_TALK:
+ me->SetEmoteState(EMOTE_ONESHOT_NONE);
+ break;
+ default:
+ break;
}
+ }
+ }
- void Reset() override { }
-
- void AttackStart(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 uiDiff) override
- {
- if (!_instance)
- return;
-
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_TIRION_FORDRING)
- return;
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+};
- uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
- if (_updateTimer <= uiDiff)
- {
- switch (_instance->GetData(TYPE_EVENT))
- {
- case 110:
- me->SetEmoteState(EMOTE_ONESHOT_TALK);
- Talk(SAY_STAGE_0_01);
- _updateTimer = 22*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 120);
- break;
- case 140:
- me->SetEmoteState(EMOTE_ONESHOT_TALK);
- Talk(SAY_STAGE_0_02);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 150);
- break;
- case 150:
- me->SetEmoteState(EMOTE_STATE_NONE);
- if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
- {
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
-
- if (Creature* gormok = me->SummonCreature(NPC_GORMOK, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS))
- {
- gormok->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ());
- gormok->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- gormok->SetReactState(REACT_PASSIVE);
- }
- }
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 155);
- break;
- case 155:
- // keep the raid in combat for the whole encounter, pauses included
- me->SetInCombatWithZone();
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 160);
- break;
- case 200:
- Talk(SAY_STAGE_0_04);
- if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
- {
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- if (Creature* dreadscale = me->SummonCreature(NPC_DREADSCALE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN))
- {
- dreadscale->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ());
- dreadscale->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- dreadscale->SetReactState(REACT_PASSIVE);
- }
- }
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 220);
- break;
- case 220:
- _instance->SetData(TYPE_EVENT, 230);
- break;
- case 300:
- Talk(SAY_STAGE_0_05);
- if (_instance->GetBossState(DATA_NORTHREND_BEASTS) != DONE)
- {
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- if (Creature* icehowl = me->SummonCreature(NPC_ICEHOWL, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_DEAD_DESPAWN))
- {
- icehowl->GetMotionMaster()->MovePoint(2, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ());
- me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- me->SetReactState(REACT_PASSIVE);
- }
- }
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 315);
- break;
- case 315:
- _instance->SetData(TYPE_EVENT, 320);
- break;
- case 400:
- Talk(SAY_STAGE_0_06);
- me->GetThreatManager().ClearAllThreat();
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 666:
- Talk(SAY_STAGE_0_WIPE);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 1010:
- Talk(SAY_STAGE_1_01);
- _updateTimer = 7*IN_MILLISECONDS;
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- me->SummonCreature(NPC_FIZZLEBANG, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 1180:
- Talk(SAY_STAGE_1_07);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 2000:
- Talk(SAY_STAGE_1_08);
- _updateTimer = 18*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 2010);
- break;
- case 2030:
- Talk(SAY_STAGE_1_11);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 3000:
- Talk(SAY_STAGE_2_01);
- _updateTimer = 12*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3050);
- break;
- case 3001:
- Talk(SAY_STAGE_2_01);
- _updateTimer = 10*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3051);
- break;
- case 3060:
- Talk(SAY_STAGE_2_03);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3070);
- break;
- case 3061:
- Talk(SAY_STAGE_2_03);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3071);
- break;
- //Summoning crusaders
- case 3091:
- if (Creature* pChampionController = me->SummonCreature(NPC_CHAMPIONS_CONTROLLER, ToCCommonLoc[1]))
- pChampionController->AI()->SetData(0, HORDE);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3092);
- break;
- //Summoning crusaders
- case 3090:
- if (Creature* pChampionController = me->SummonCreature(NPC_CHAMPIONS_CONTROLLER, ToCCommonLoc[1]))
- pChampionController->AI()->SetData(0, ALLIANCE);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3092);
- break;
- case 3092:
- if (Creature* pChampionController = _instance->GetCreature(DATA_FACTION_CRUSADERS))
- pChampionController->AI()->SetData(1, NOT_STARTED);
- _instance->SetData(TYPE_EVENT, 3095);
- break;
- //Crusaders battle end
- case 3100:
- Talk(SAY_STAGE_2_06);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 4000:
- Talk(SAY_STAGE_3_01);
- _updateTimer = 13*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 4010);
- break;
- case 4010:
- Talk(SAY_STAGE_3_02);
- if (Creature* lightbane = me->SummonCreature(NPC_FJOLA_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
- {
- lightbane->SetVisible(false);
- lightbane->SetReactState(REACT_PASSIVE);
- lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[0].GetPositionX(), TwinValkyrsLoc[0].GetPositionY(), TwinValkyrsLoc[0].GetPositionZ());
- lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[1].GetPositionX(), TwinValkyrsLoc[1].GetPositionY(), TwinValkyrsLoc[1].GetPositionZ());
- }
- if (Creature* darkbane = me->SummonCreature(NPC_EYDIS_DARKBANE, ToCSpawnLoc[2].GetPositionX(), ToCSpawnLoc[2].GetPositionY(), ToCSpawnLoc[2].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME))
- {
- darkbane->SetVisible(false);
- darkbane->SetReactState(REACT_PASSIVE);
- darkbane->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[2].GetPositionX(), TwinValkyrsLoc[2].GetPositionY(), TwinValkyrsLoc[2].GetPositionZ());
- darkbane->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[3].GetPositionX(), TwinValkyrsLoc[3].GetPositionY(), TwinValkyrsLoc[3].GetPositionZ());
- }
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 4015);
- break;
- case 4015:
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- if (Creature* lightbane = _instance->GetCreature(DATA_FJOLA_LIGHTBANE))
- {
- lightbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[8].GetPositionX(), ToCCommonLoc[8].GetPositionY(), ToCCommonLoc[8].GetPositionZ());
- lightbane->SetVisible(true);
- }
- if (Creature* darkbane = _instance->GetCreature(DATA_EYDIS_DARKBANE))
- {
- darkbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ());
- darkbane->SetVisible(true);
- }
- _updateTimer = 10*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 4016);
- break;
- case 4016:
- _instance->DoUseDoorOrButton(_instance->GetGuidData(DATA_MAIN_GATE));
- _instance->SetData(TYPE_EVENT, 4017);
- break;
- case 4040:
- _updateTimer = 1*MINUTE*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5000);
- break;
- case 5000:
- Talk(SAY_STAGE_4_01);
- _updateTimer = 10*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5005);
- break;
- case 5005:
- _updateTimer = 8*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 5010);
- me->SummonCreature(NPC_LICH_KING, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5);
- break;
- case 5020:
- Talk(SAY_STAGE_4_03);
- _updateTimer = 1*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 0);
- break;
- case 6000:
- me->SummonCreature(NPC_TIRION_FORDRING_ANUBARAK, EndSpawnLoc[0]);
- me->SummonCreature(NPC_ARGENT_MAGE, EndSpawnLoc[1]);
- me->SummonGameObject(GO_PORTAL_TO_DALARAN, EndSpawnLoc[2], QuaternionData::fromEulerAnglesZYX(EndSpawnLoc[2].GetOrientation(), 0.0f, 0.0f), 0);
- _updateTimer = 20*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 6005);
- break;
- case 6005:
- if (Creature* tirionFordring = _instance->GetCreature(DATA_FORDRING_ANUBARAK))
- tirionFordring->AI()->Talk(SAY_STAGE_4_06);
- _updateTimer = 20*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 6010);
- break;
- case 6010:
- if (IsHeroic())
- {
- if (Creature* tirionFordring = _instance->GetCreature(DATA_FORDRING_ANUBARAK))
- tirionFordring->AI()->Talk(SAY_STAGE_4_07);
- _updateTimer = 1*MINUTE*IN_MILLISECONDS;
- _instance->SetBossState(DATA_ANUBARAK, SPECIAL);
- _instance->SetData(TYPE_EVENT, 6020);
- }
- else
- _instance->SetData(TYPE_EVENT, 6030);
- break;
- case 6020:
- me->DespawnOrUnsummon();
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 6030);
- break;
- default:
- break;
- }
- }
- else
- _updateTimer -= uiDiff;
- _instance->SetData(TYPE_EVENT_TIMER, _updateTimer);
- }
- private:
- InstanceScript* _instance;
- };
+struct npc_garrosh_toc : public ScriptedAI
+{
+ npc_garrosh_toc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- return GetTrialOfTheCrusaderAI<npc_tirion_tocAI>(creature);
+ case ACTION_START_GORMOK:
+ _events.ScheduleEvent(EVENT_GORMOK_INTRO, 12s);
+ break;
+ case ACTION_JARAXXUS_DEFEATED:
+ _events.ScheduleEvent(EVENT_ALLIANCE_DOGS, 14s);
+ break;
+ case ACTION_START_CHAMPIONS:
+ _events.ScheduleEvent(EVENT_DEMAND_JUSTICE, 8s);
+ break;
+ case ACTION_SAY_KILLED_PLAYER:
+ Talk(GARROSH_SAY_KILLED);
+ break;
+ case ACTION_CHAMPIONS_DEFEATED:
+ Talk(GARROSH_SAY_FACTION_DEAD);
+ break;
+ case ACTION_VALKYR_DEFEATED:
+ _events.ScheduleEvent(EVENT_VALKYR_DEAD, 5s);
+ break;
+ case ACTION_START_CHAMPIONS_ENGAGE:
+ _events.ScheduleEvent(EVENT_NO_MERCY, 6s);
+ break;
+ default:
+ break;
}
-};
+ }
-class npc_garrosh_toc : public CreatureScript
-{
- public:
- npc_garrosh_toc() : CreatureScript("npc_garrosh_toc") { }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- struct npc_garrosh_tocAI : public ScriptedAI
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_garrosh_tocAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- _instance = me->GetInstanceScript();
+ case EVENT_GORMOK_INTRO:
+ Talk(GARROSH_SAY_BEASTS);
+ break;
+ case EVENT_ALLIANCE_DOGS:
+ Talk(GARROSH_SAY_ALLIANCE_DOGS);
+ break;
+ case EVENT_DEMAND_JUSTICE:
+ Talk(GARROSH_SAY_DEMAND_JUSTICE);
+ _events.ScheduleEvent(EVENT_NO_MERCY, 21s);
+ break;
+ case EVENT_NO_MERCY:
+ Talk(GARROSH_SAY_NO_MERCY);
+ break;
+ case EVENT_VALKYR_DEAD:
+ Talk(GARROSH_SAY_VALKYR_DEAD);
+ break;
+ default:
+ break;
}
+ }
+ }
- void Reset() override { }
-
- void AttackStart(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 uiDiff) override
- {
- if (!_instance)
- return;
-
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_GARROSH)
- return;
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+};
- uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
- if (_updateTimer <= uiDiff)
- {
- switch (_instance->GetData(TYPE_EVENT))
- {
- case 130:
- me->SetEmoteState(EMOTE_ONESHOT_TALK);
- Talk(SAY_STAGE_0_03h);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 132);
- break;
- case 132:
- me->SetEmoteState(EMOTE_STATE_NONE);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 140);
- break;
- case 2010:
- Talk(SAY_STAGE_1_09);
- _updateTimer = 9*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 2020);
- break;
- case 3050:
- Talk(SAY_STAGE_2_02h);
- _updateTimer = 15*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3060);
- break;
- case 3070:
- Talk(SAY_STAGE_2_04h);
- _updateTimer = 6*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3080);
- break;
- case 3081:
- Talk(SAY_STAGE_2_05h);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3091);
- break;
- case 4030:
- Talk(SAY_STAGE_3_03h);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 4040);
- break;
- default:
- break;
- }
- }
- else
- _updateTimer -= uiDiff;
- _instance->SetData(TYPE_EVENT_TIMER, _updateTimer);
- }
- private:
- InstanceScript* _instance;
- };
+struct npc_varian_toc : public ScriptedAI
+{
+ npc_varian_toc(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- CreatureAI* GetAI(Creature* creature) const override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- return GetTrialOfTheCrusaderAI<npc_garrosh_tocAI>(creature);
+ case ACTION_START_GORMOK:
+ _events.ScheduleEvent(EVENT_GORMOK_INTRO, 11s);
+ break;
+ case ACTION_JARAXXUS_DEFEATED:
+ _events.ScheduleEvent(EVENT_COME_PIGS, 24s);
+ break;
+ case ACTION_START_CHAMPIONS:
+ _events.ScheduleEvent(EVENT_DEMAND_JUSTICE, 9s);
+ break;
+ case ACTION_SAY_KILLED_PLAYER:
+ Talk(VARIAN_SAY_KILLED);
+ break;
+ case ACTION_CHAMPIONS_DEFEATED:
+ Talk(VARIAN_SAY_FACTION_DEAD);
+ break;
+ case ACTION_VALKYR_DEFEATED:
+ _events.ScheduleEvent(EVENT_VALKYR_DEAD, 6s);
+ break;
+ case ACTION_START_CHAMPIONS_ENGAGE:
+ _events.ScheduleEvent(EVENT_NO_MERCY, 6s);
+ break;
+ default:
+ break;
}
-};
+ }
-class npc_varian_toc : public CreatureScript
-{
- public:
- npc_varian_toc() : CreatureScript("npc_varian_toc") { }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- struct npc_varian_tocAI : public ScriptedAI
+ while (uint32 eventId = _events.ExecuteEvent())
{
- npc_varian_tocAI(Creature* creature) : ScriptedAI(creature)
+ switch (eventId)
{
- _instance = me->GetInstanceScript();
+ case EVENT_GORMOK_INTRO:
+ Talk(VARIAN_SAY_BEASTS);
+ break;
+ case EVENT_COME_PIGS:
+ Talk(VARIAN_SAY_COME_PIGS);
+ break;
+ case EVENT_DEMAND_JUSTICE:
+ Talk(VARIAN_SAY_DEMAND_JUSTICE);
+ _events.ScheduleEvent(EVENT_NO_MERCY, 20s);
+ break;
+ case EVENT_NO_MERCY:
+ Talk(VARIAN_SAY_FIGHT_GLORY);
+ break;
+ case EVENT_VALKYR_DEAD:
+ Talk(VARIAN_SAY_VALKYR_DEAD);
+ break;
+ default:
+ break;
}
+ }
+ }
- void Reset() override { }
-
- void AttackStart(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 uiDiff) override
- {
- if (!_instance)
- return;
+private:
+ InstanceScript* _instance;
+ EventMap _events;
+};
- if (_instance->GetData(TYPE_EVENT_NPC) != NPC_VARIAN)
- return;
+// 69016 - Corpse Teleport
+class spell_lich_king_teleport_corpse : public SpellScript
+{
+ PrepareSpellScript(spell_lich_king_teleport_corpse);
- uint32 _updateTimer = _instance->GetData(TYPE_EVENT_TIMER);
- if (_updateTimer <= uiDiff)
- {
- switch (_instance->GetData(TYPE_EVENT))
- {
- case 120:
- me->SetEmoteState(EMOTE_ONESHOT_TALK);
- Talk(SAY_STAGE_0_03a);
- _updateTimer = 2*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 122);
- break;
- case 122:
- me->SetEmoteState(EMOTE_STATE_NONE);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 130);
- break;
- case 2020:
- Talk(SAY_STAGE_1_10);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 2030);
- break;
- case 3051:
- Talk(SAY_STAGE_2_02a);
- _updateTimer = 17*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3061);
- break;
- case 3071:
- Talk(SAY_STAGE_2_04a);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3081);
- break;
- case 3080:
- Talk(SAY_STAGE_2_05a);
- _updateTimer = 3*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 3090);
- break;
- case 4020:
- Talk(SAY_STAGE_3_03a);
- _updateTimer = 5*IN_MILLISECONDS;
- _instance->SetData(TYPE_EVENT, 4040);
- break;
- default:
- break;
- }
- }
- else
- _updateTimer -= uiDiff;
- _instance->SetData(TYPE_EVENT_TIMER, _updateTimer);
- }
- private:
- InstanceScript* _instance;
- };
+ void HandleTeleport(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->NearTeleportTo(CorpseTeleportPosition);
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetTrialOfTheCrusaderAI<npc_varian_tocAI>(creature);
- }
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_lich_king_teleport_corpse::HandleTeleport, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
};
void AddSC_trial_of_the_crusader()
{
- new boss_lich_king_toc();
- new npc_announcer_toc10();
- new npc_fizzlebang_toc();
- new npc_tirion_toc();
- new npc_garrosh_toc();
- new npc_varian_toc();
+ RegisterTrialOfTheCrusaderCreatureAI(npc_barrett_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(boss_lich_king_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_tirion_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_open_portal_target_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_fizzlebang_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_garrosh_toc);
+ RegisterTrialOfTheCrusaderCreatureAI(npc_varian_toc);
+ RegisterSpellScript(spell_lich_king_teleport_corpse);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
index 76451d9b865..e740dba7ee3 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h
@@ -37,13 +37,12 @@ enum TCRDataTypes
DATA_ANUBARAK = 5,
// Additional Data
- DATA_GORMOK_THE_IMPALER = 5,
- DATA_ACIDMAW = 6,
- DATA_DREADSCALE = 7,
- DATA_ICEHOWL = 8,
- DATA_FJOLA_LIGHTBANE = 9,
- DATA_EYDIS_DARKBANE = 10,
- DATA_BARRET_RAMSEY = 11,
+ DATA_GORMOK_THE_IMPALER = 6,
+ DATA_ACIDMAW = 7,
+ DATA_DREADSCALE = 8,
+ DATA_ICEHOWL = 9,
+ DATA_FJOLA_LIGHTBANE = 10,
+ DATA_EYDIS_DARKBANE = 11,
DATA_FORDRING = 12,
DATA_FORDRING_ANUBARAK = 13,
DATA_VARIAN = 14,
@@ -57,9 +56,14 @@ enum TCRDataTypes
DATA_EAST_PORTCULLIS = 21,
DATA_WEB_DOOR = 22,
DATA_TRIBUTE_CHEST = 23,
+ DATA_BEASTS_COMBAT_STALKER = 24,
+ DATA_FURIOUS_CHARGE = 25,
+ DATA_DESPAWN_SNOBOLDS = 26,
+ DATA_TEAM = 27,
+ DATA_LICH_KING_VOICE = 28,
- TYPE_COUNTER = 24,
- TYPE_EVENT = 25,
+ TYPE_COUNTER = 29,
+ TYPE_EVENT = 30,
TYPE_EVENT_TIMER = 101,
TYPE_EVENT_NPC = 102,
@@ -69,20 +73,54 @@ enum TCRDataTypes
DATA_MISTRESS_OF_PAIN_COUNT = 302,
INCREASE = 501,
- DECREASE = 502,
+ DECREASE = 502
};
enum TCRSpellIds
{
SPELL_WILFRED_PORTAL = 68424,
+ SPELL_OPEN_PORTAL = 67864,
SPELL_JARAXXUS_CHAINS = 67924,
- SPELL_CORPSE_TELEPORT = 69016,
SPELL_DESTROY_FLOOR_KNOCKUP = 68193,
+ SPELL_ARTHAS_PORTAL = 51807,
+ SPELL_LK_FROST_NOVA = 68198,
+ SPELL_CORPSE_TELEPORT = 69016
};
-enum TCRMiscData
+enum TCRMisc
{
- DESPAWN_TIME = 1200000
+ DESPAWN_TIME = 1200000,
+ PLAYER_VEHICLE_ID = 444
+};
+
+enum TCRActions
+{
+ ACTION_START_GORMOK = 1,
+ ACTION_START_GORMOK_FAIL,
+ ACTION_START_JORMUNGARS,
+ ACTION_START_ICEHOWL,
+ ACTION_NORTHREND_BEASTS_WIPE,
+ ACTION_NORTHREND_BEASTS_DEFEATED,
+ ACTION_START_JARAXXUS_EVENT,
+ ACTION_KILL_JARAXXUS,
+ ACTION_JARAXXUS_DEFEATED,
+ ACTION_START_CHAMPIONS,
+ ACTION_SUMMON_CHAMPIONS,
+ ACTION_TIRION_ALLOW,
+ ACTION_CHAMPIONS_DEFEATED,
+ ACTION_SUMMON_JARAXXUS,
+ ACTION_JARAXXUS_INTRO,
+ ACTION_START_VALKYR,
+ ACTION_START_LK_EVENT,
+ ACTION_SAY_KILLED_PLAYER,
+ ACTION_VALKYR_DEFEATED,
+ ACTION_LK_EVENT_FINISHED,
+ ACTION_JARAXXUS_ENGAGE,
+ ACTION_START_CHAMPIONS_ENGAGE,
+ ACTION_START_VALKYR_ENGAGE,
+ ACTION_JARAXXUS_WIPE,
+ ACTION_FACTION_WIPE,
+ ACTION_VALKYR_WIPE
};
extern Position const ToCCommonLoc[];
@@ -119,7 +157,12 @@ enum AnnouncerMessages
enum TCRCreatureIds
{
- NPC_BARRET_RAMSEY = 34816,
+ NPC_BARRETT_BEASTS = 34816,
+ NPC_BARRETT_BEASTS_HC = 35909,
+ NPC_BARRETT_JARAXXUS = 35035,
+ NPC_BARRETT_FACTION = 35766,
+ NPC_BARRETT_VALKYR = 35770,
+ NPC_BARRETT_LK = 35771,
NPC_TIRION_FORDRING = 34996,
NPC_TIRION_FORDRING_ANUBARAK = 36095,
NPC_ARGENT_MAGE = 36097,
@@ -131,17 +174,19 @@ enum TCRCreatureIds
NPC_THRALL = 34994,
NPC_PROUDMOORE = 34992,
NPC_WILFRED_PORTAL = 17965,
- NPC_TRIGGER = 35651,
+ NPC_PURPLE_GROUND = 35651,
NPC_ICEHOWL = 34797,
NPC_GORMOK = 34796,
NPC_DREADSCALE = 34799,
NPC_ACIDMAW = 35144,
+ NPC_BEASTS_COMBAT_STALKER = 36549,
+ NPC_FURIOUS_CHARGE_STALKER = 35062,
+ NPC_SNOBOLD_VASSAL = 34800,
NPC_JARAXXUS = 34780,
NPC_CHAMPIONS_CONTROLLER = 34781,
-
NPC_ALLIANCE_DEATH_KNIGHT = 34461,
NPC_ALLIANCE_DRUID_BALANCE = 34460,
NPC_ALLIANCE_DRUID_RESTORATION = 34469,
@@ -178,6 +223,9 @@ enum TCRCreatureIds
NPC_DARK_ESSENCE = 34567,
NPC_LIGHT_ESSENCE = 34568,
+ NPC_LICH_KING_VOICE = 16980,
+ NPC_ARTHAS_PORTAL = 22517,
+
NPC_ANUBARAK = 34564
};
@@ -247,4 +295,6 @@ inline AI* GetTrialOfTheCrusaderAI(T* obj)
return GetInstanceAI<AI>(obj, ToCrScriptName);
}
+#define RegisterTrialOfTheCrusaderCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetTrialOfTheCrusaderAI)
+
#endif
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index c45451c869a..6c9e8cd80ac 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -2701,7 +2701,8 @@ class spell_gen_spectator_cheer_trigger : public SpellScript
void HandleDummy(SpellEffIndex /*effIndex*/)
{
- GetCaster()->HandleEmoteCommand(EmoteArray[urand(0, 2)]);
+ if (roll_chance_i(40))
+ GetCaster()->HandleEmoteCommand(EmoteArray[urand(0, 2)]);
}
void Register() override