fix(scripts/Naxx): The art of Naxxramas (1/2) (#4076)

This commit is contained in:
Silker
2021-03-23 12:30:09 -06:00
committed by GitHub
parent ba9a09dd0c
commit 8ba442bda2
18 changed files with 1628 additions and 910 deletions
@@ -0,0 +1,122 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1609119138728662700');
/* Anub'Rekhan */
-- Fix enrage for Crypt Guard
UPDATE `smart_scripts` SET `event_phase_mask`=0, `event_flags`=1, `event_param2`=29, `event_param3`=0, `event_param4`=0, `comment`='Crypt Guard - On 30% HP - CastSelf Frenzy' WHERE `entryorguid`=16573 AND `source_type`=0 AND `id`=3 AND `link`=0;
-- Add Frenzy emote for Crypt Guard
DELETE FROM `smart_scripts` WHERE `entryorguid`= 16573 AND `source_type`= 0 AND `id`= 5;
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(16573, 0, 5, 0, 2, 0, 100, 1, 0, 29, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Crypt Guard - On 30% HP - Say EMOTE_FRENZY');
/* Heigan the Unclean */
-- Enable random movement and adjust orientation
UPDATE `creature` SET `orientation`=2.40, `wander_distance`=4, `MovementType`=1 WHERE `guid`=127789;
-- Fix EMOTE_DEATH
UPDATE `creature_text` SET `Text`='%s takes his last breath.', `Type`=16, `BroadcastTextId`=13044, `comment`='heigan EMOTE_DEATH' WHERE `CreatureID`=15936 AND `GroupID`=3 AND `ID`=0;
/* Loatheb */
-- Useless, workaround implemented in boss_loatheb.cpp
DELETE FROM `spell_script_names` WHERE `spell_id`=59481;
-- Adjust movement speed for Spores
UPDATE `creature_template` SET `speed_walk`=0.4, `speed_run`=0.4 WHERE `entry` IN (16286, 30068);
/* Instructor Razuvious */
-- Fix all emotes / texts / dialogues / sound files
DELETE FROM `creature_text` WHERE `CreatureID`=16061;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(16061, 0, 0, 'Do as I taught you!', 14, 0, 25, 0, 0, 8855, 13075, 3, 'Razuvious SAY_AGGRO #1'),
(16061, 0, 1, 'The time for practice is over! Show me what you have learned!', 14, 0, 25, 0, 0, 8859, 13078, 3, 'Razuvious SAY_AGGRO #2'),
(16061, 0, 2, 'Show them no mercy!', 14, 0, 25, 0, 0, 8856, 13076, 3, 'Razuvious SAY_AGGRO #3'),
(16061, 0, 3, 'Sweep the leg... Do you have a problem with that?', 14, 0, 25, 0, 0, 8861, 13080, 3, 'Razuvious SAY_AGGRO #4'),
(16061, 1, 0, '%s lets loose a triumphant shout.', 16, 0, 50, 0, 0, 8863, 13082, 3, 'Razuvious SAY_SLAY #1'),
(16061, 1, 1, 'You should have stayed home.', 14, 0, 50, 0, 0, 8862, 13081, 3, 'Razuvious SAY_SLAY #2'),
(16061, 2, 0, 'Hah hah, I\'m just getting warmed up!', 14, 0, 20, 0, 0, 8852, 13072, 3, 'Razuvious SAY_TAUNTED #1'),
(16061, 2, 1, 'Stand and fight!', 14, 0, 20, 0, 0, 8853, 13073, 3, 'Razuvious SAY_TAUNTED #2'),
(16061, 2, 2, 'Show me what you\'ve got!', 14, 0, 20, 0, 0, 8854, 13074, 3, 'Razuvious SAY_TAUNTED #3'),
(16061, 2, 3, 'You disappoint me, students!', 14, 0, 20, 0, 0, 8858, 13077, 3, 'Razuvious SAY_TAUNTED #4'),
(16061, 2, 4, 'You should have stayed home.', 14, 0, 20, 0, 0, 8862, 13081, 3, 'Razuvious SAY_TAUNTED #5'),
(16061, 3, 0, 'An honorable... death.', 14, 0, 100, 0, 0, 8860, 13079, 3, 'Razuvious SAY_DEATH');
-- Fix translation
UPDATE `broadcast_text_locale` SET `MaleText`='%s suelta un grito triunfal.' WHERE `ID`=13082 AND `locale` IN ('esES', 'esMX');
/* Gothik the Harvester */
-- Minion difficulty spells
DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (55604, 27825, 27831, 27989, 56408, 27993, 55606, 27994, 55648);
INSERT INTO `spelldifficulty_dbc` (`id`,`DifficultySpellID_1`,`DifficultySpellID_2`) VALUES
(55604, 55604, 55645), -- death plague
(27831, 27831, 55638), -- shadow bolt volley
(27989, 27989, 56407), -- arcane explosion
(55606, 55606, 55608), -- unholy aura
(27994, 27994, 55646), -- drain life
(55648, 55648, 27995); -- unholy frenzy
-- Rider damage aura + visual aura
DELETE FROM `creature_template_addon` WHERE `entry` IN (16126, 29986, 16148, 29990, 16150, 29988);
INSERT INTO `creature_template_addon` (`entry`,`mount`,`auras`) VALUES
(16126, 25278, '55606'),
(29986, 25278, '55608'),
(16148, 0, '10848'),
(29990, 0, '10848'),
(16150, 0, '55606 10848'),
(29988, 0, '55608 10848');
/* Grobbulus */
-- Fix 'Slime spray' message: emote -> boss emote
UPDATE `creature_text` SET `Type`=41 WHERE `CreatureID`=15931 AND `GroupID`=0 AND `ID`=0;
-- Add spell script for 'mutating injection/explosion'
DELETE FROM `spell_script_names` WHERE `spell_id`=28169;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (28169, 'spell_grobbulus_mutating_injection');
-- Remove 'mutating injection' from DB as now has script)
DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=-28169 AND `spell_effect`=28206 AND `type`=0;
/* Thaddius */
-- Tesla coil search ignores LoS
DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (28096,28098,28110,28111);
INSERT INTO `disables` (`sourceType`,`entry`,`flags`,`comment`) VALUES
(0,28098,64,"Stalagg Tesla Periodic - Ignore LoS"),
(0,28096,64,"Stalagg Tesla Visual - Ignore LoS"),
(0,28110,64,"Feugen Tesla Periodic - Ignore LoS"),
(0,28111,64,"Feugen Tesla Visual - Ignore LoS");
-- Tesla coil shock visual needs implicit target
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (28096,28111,28159);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`Comment`) VALUES
(13,1,28096,0,0,31,0,3,15929,0,0,"Stalagg Chain Visual - Target Stalagg"),
(13,1,28111,0,0,31,0,3,15930,0,0,"Feugen Chain Visual - Target Feugen"),
(13,1,28159,0,0,31,0,3,15928,0,0,"Thaddius Shock Visual - Target Thaddius");
-- Tesla coil visual GOs
DELETE FROM `gameobject` WHERE `id` IN (181477,181478);
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES
(268049, 181478, 533, 0, 0, 3, 1, 3487.32, -2911.38, 318.898, 3.14159, 0, 0, -1, 0, 0, 0, 0, 0),
(268050, 181477, 533, 0, 0, 3, 1, 3527.94, -2952.26, 318.898, 3.14159, 0, 0, -1, 0, 0, 0, 0, 0);
/* Sapphiron */
-- Update Sapphiron's texts comments for better administration
UPDATE `creature_text` SET `comment`='Sapphiron EMOTE_AIR_PHASE' WHERE `CreatureID`=15989 AND `GroupID`=0 AND `ID`=0;
UPDATE `creature_text` SET `comment`='Sapphiron EMOTE_GROUND_PHASE' WHERE `CreatureID`=15989 AND `GroupID`=1 AND `ID`=0;
UPDATE `creature_text` SET `comment`='Sapphiron EMOTE_BREATH' WHERE `CreatureID`=15989 AND `GroupID`=2 AND `ID`=0;
UPDATE `creature_text` SET `comment`='Sapphiron EMOTE_ENRAGE' WHERE `CreatureID`=15989 AND `GroupID`=3 AND `ID`=0;
/* Kel'Thuzad */
-- Guardians of Icecrown should be immune to all CC
UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|1|2|4|8|32|64|256|512|1024|2048|4096|8192|65536|131072|524288|4194304|67108864|536870912 WHERE `entry` IN
(16441, 30057);
-- Fix translation for Spanish
UPDATE `broadcast_text_locale` SET `MaleText`='¡Kel\'Thuzad ataca!' WHERE `ID`=32803 AND `locale` IN ('esES', 'esMX');
@@ -14,6 +14,12 @@ enum Says
EMOTE_LOCUST = 3 EMOTE_LOCUST = 3
}; };
enum GuardSays
{
EMOTE_SPAWN = 1,
EMOTE_SCARAB = 2
};
enum Spells enum Spells
{ {
SPELL_IMPALE_10 = 28783, SPELL_IMPALE_10 = 28783,
@@ -22,14 +28,15 @@ enum Spells
SPELL_LOCUST_SWARM_25 = 54021, SPELL_LOCUST_SWARM_25 = 54021,
SPELL_SUMMON_CORPSE_SCRABS_5 = 29105, SPELL_SUMMON_CORPSE_SCRABS_5 = 29105,
SPELL_SUMMON_CORPSE_SCRABS_10 = 28864, SPELL_SUMMON_CORPSE_SCRABS_10 = 28864,
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662
}; };
enum Events enum Events
{ {
EVENT_SPELL_IMPALE = 1, EVENT_IMPALE = 1,
EVENT_SPELL_LOCUST_SWARM = 2, EVENT_LOCUST_SWARM = 2,
EVENT_SPELL_BERSERK = 3, EVENT_BERSERK = 3,
EVENT_SPAWN_GUARD = 4
}; };
enum Misc enum Misc
@@ -37,7 +44,7 @@ enum Misc
NPC_CORPSE_SCARAB = 16698, NPC_CORPSE_SCARAB = 16698,
NPC_CRYPT_GUARD = 16573, NPC_CRYPT_GUARD = 16573,
ACHIEV_TIMED_START_EVENT = 9891, ACHIEV_TIMED_START_EVENT = 9891
}; };
class boss_anubrekhan : public CreatureScript class boss_anubrekhan : public CreatureScript
@@ -67,8 +74,8 @@ public:
{ {
if (Is25ManRaid()) if (Is25ManRaid())
{ {
me->SummonCreature(NPC_CRYPT_GUARD, 3299.825f, -3502.27f, 287.16f, M_PI, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); me->SummonCreature(NPC_CRYPT_GUARD, 3299.732f, -3502.489f, 287.077f, 2.378f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
me->SummonCreature(NPC_CRYPT_GUARD, 3299.087f, -3450.93f, 287.16f, M_PI, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); me->SummonCreature(NPC_CRYPT_GUARD, 3299.086f, -3450.929f, 287.077f, 3.999f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
} }
} }
@@ -78,35 +85,41 @@ public:
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
SummonCryptGuards(); SummonCryptGuards();
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void JustSummoned(Creature* cr) override void JustSummoned(Creature* cr) override
{ {
if (me->IsInCombat()) if (me->IsInCombat())
cr->SetInCombatWithZone();
if (cr->GetEntry() == NPC_CORPSE_SCARAB)
{ {
cr->SetReactState(REACT_PASSIVE); cr->SetInCombatWithZone();
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) if (cr->GetEntry() == NPC_CRYPT_GUARD)
cr->AI()->AttackStart(target); {
cr->AI()->Talk(EMOTE_SPAWN, me);
}
} }
summons.Summon(cr); summons.Summon(cr);
} }
void SummonedCreatureDies(Creature* cr, Unit*) override void SummonedCreatureDies(Creature* cr, Unit*) override
{ {
if (cr->GetEntry() == NPC_CRYPT_GUARD) if (cr->GetEntry() == NPC_CRYPT_GUARD)
{
cr->CastSpell(cr, SPELL_SUMMON_CORPSE_SCRABS_10, true, nullptr, nullptr, me->GetGUID()); cr->CastSpell(cr, SPELL_SUMMON_CORPSE_SCRABS_10, true, nullptr, nullptr, me->GetGUID());
cr->AI()->Talk(EMOTE_SCARAB);
}
} }
void SummonedCreatureDespawn(Creature* cr) override { summons.Despawn(cr); } void SummonedCreatureDespawn(Creature* cr) override
{
summons.Despawn(cr);
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -124,32 +137,37 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
//Force the player to spawn corpse scarabs via spell
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCRABS_5, true, nullptr, nullptr, me->GetGUID()); victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCRABS_5, true, nullptr, nullptr, me->GetGUID());
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
me->CallForHelp(30.0f); // catch helpers me->CallForHelp(30.0f);
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
}
events.ScheduleEvent(EVENT_SPELL_IMPALE, 15000); events.ScheduleEvent(EVENT_IMPALE, 15000);
events.ScheduleEvent(EVENT_SPELL_LOCUST_SWARM, 70000 + urand(0, 50000)); events.ScheduleEvent(EVENT_LOCUST_SWARM, urand(70000, 120000));
events.ScheduleEvent(EVENT_SPELL_BERSERK, 600000); events.ScheduleEvent(EVENT_BERSERK, 600000);
if (!summons.HasEntry(NPC_CRYPT_GUARD)) if (!summons.HasEntry(NPC_CRYPT_GUARD))
{
SummonCryptGuards(); SummonCryptGuards();
} }
if (!Is25ManRaid())
{
events.ScheduleEvent(EVENT_SPAWN_GUARD, urand(15000, 20000));
}
}
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
@@ -158,12 +176,26 @@ public:
Talk(SAY_GREET); Talk(SAY_GREET);
sayGreet = true; sayGreet = true;
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!me->IsInCombat() && sayGreet)
{
for( std::list<uint64>::iterator itr = summons.begin(); itr != summons.end(); ++itr )
{
if (pInstance)
{
if (Creature* cr = pInstance->instance->GetCreature(*itr))
{
if (cr->IsInCombat())
DoZoneInCombat();
}
}
}
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
@@ -173,27 +205,26 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_IMPALE: case EVENT_IMPALE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
me->CastSpell(target, RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25), false); me->CastSpell(target, RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25), false);
}
events.RepeatEvent(20000); events.RepeatEvent(20000);
break; break;
case EVENT_SPELL_LOCUST_SWARM: case EVENT_LOCUST_SWARM:
{
Talk(EMOTE_LOCUST); Talk(EMOTE_LOCUST);
me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false); me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false);
Position pos; events.ScheduleEvent(EVENT_SPAWN_GUARD, 3000);
me->GetNearPosition(pos, 10.0f, rand_norm() * 2 * M_PI);
me->SummonCreature(NPC_CRYPT_GUARD, pos);
events.RepeatEvent(90000); events.RepeatEvent(90000);
break; break;
} case EVENT_SPAWN_GUARD:
case EVENT_SPELL_BERSERK: me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
break;
case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -27,19 +27,22 @@ enum Spells
SPELL_FRENZY_10 = 28798, SPELL_FRENZY_10 = 28798,
SPELL_FRENZY_25 = 54100, SPELL_FRENZY_25 = 54100,
SPELL_WIDOWS_EMBRACE = 28732, SPELL_WIDOWS_EMBRACE = 28732,
SPELL_MINION_WIDOWS_EMBRACE = 54097
}; };
enum Events enum Events
{ {
EVENT_SPELL_POISON_BOLT = 1, EVENT_POISON_BOLT = 1,
EVENT_SPELL_RAIN_OF_FIRE = 2, EVENT_RAIN_OF_FIRE = 2,
EVENT_SPELL_FRENZY = 3, EVENT_FRENZY = 3
}; };
enum Misc enum Misc
{ {
NPC_NAXXRAMAS_WORSHIPPER = 16506, NPC_NAXXRAMAS_WORSHIPPER = 16506,
NPC_NAXXRAMAS_FOLLOWER = 16505, NPC_NAXXRAMAS_FOLLOWER = 16505,
SPIDER_WEB_ENTRANCE = 181235
}; };
class boss_faerlina : public CreatureScript class boss_faerlina : public CreatureScript
@@ -71,8 +74,6 @@ public:
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3344.3f, -3618.31f, 261.08f, 4.69494f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3344.3f, -3618.31f, 261.08f, 4.69494f);
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3356.71f, -3620.05f, 261.08f, 4.57276f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3356.71f, -3620.05f, 261.08f, 4.57276f);
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3350.26f, -3619.11f, 261.08f, 4.67748f); me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3350.26f, -3619.11f, 261.08f, 4.67748f);
// Followers
if (Is25ManRaid()) if (Is25ManRaid())
{ {
me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3347.49f, -3617.59f, 261.0f, 4.49f); me->SummonCreature(NPC_NAXXRAMAS_FOLLOWER, 3347.49f, -3617.59f, 261.0f, 4.49f);
@@ -80,7 +81,10 @@ public:
} }
} }
void JustSummoned(Creature* cr) override { summons.Summon(cr); } void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
}
void Reset() override void Reset() override
{ {
@@ -88,6 +92,10 @@ public:
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
SummonHelpers(); SummonHelpers();
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
} }
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
@@ -96,10 +104,14 @@ public:
me->CallForHelp(VISIBLE_RANGE); me->CallForHelp(VISIBLE_RANGE);
summons.DoZoneInCombat(); summons.DoZoneInCombat();
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_POISON_BOLT, urand(12000, 15000)); events.ScheduleEvent(EVENT_POISON_BOLT, urand(7000, 15000));
events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, urand(6000, 18000)); events.ScheduleEvent(EVENT_RAIN_OF_FIRE, urand(8000, 18000));
events.ScheduleEvent(EVENT_SPELL_FRENZY, urand(60000, 80000), 1); events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000), 1);
events.SetPhase(1); events.SetPhase(1);
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
@@ -109,7 +121,6 @@ public:
Talk(SAY_GREET); Talk(SAY_GREET);
sayGreet = true; sayGreet = true;
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
@@ -119,20 +130,42 @@ public:
return; return;
if (!urand(0, 3)) if (!urand(0, 3))
{
Talk(SAY_SLAY); Talk(SAY_SLAY);
}
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!me->IsInCombat() && sayGreet)
{
for( std::list<uint64>::iterator itr = summons.begin(); itr != summons.end(); ++itr )
{
if (pInstance)
{
if (Creature* cr = pInstance->instance->GetCreature(*itr))
{
if (cr->IsInCombat())
DoZoneInCombat();
}
}
}
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
@@ -142,17 +175,21 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_POISON_BOLT: case EVENT_POISON_BOLT:
if (!me->HasAura(SPELL_WIDOWS_EMBRACE)) if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, SPELL_MINION_WIDOWS_EMBRACE)))
me->CastCustomSpell(RAID_MODE(SPELL_POISON_BOLT_VOLLEY_10, SPELL_POISON_BOLT_VOLLEY_25), SPELLVALUE_MAX_TARGETS, 3, me, false); {
events.RepeatEvent(14000); me->CastCustomSpell(RAID_MODE(SPELL_POISON_BOLT_VOLLEY_10, SPELL_POISON_BOLT_VOLLEY_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(3, 10), me, false);
}
events.RepeatEvent(urand(7000, 15000));
break; break;
case EVENT_SPELL_RAIN_OF_FIRE: case EVENT_RAIN_OF_FIRE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
me->CastSpell(target, RAID_MODE(SPELL_RAIN_OF_FIRE_10, SPELL_RAIN_OF_FIRE_25), false); me->CastSpell(target, RAID_MODE(SPELL_RAIN_OF_FIRE_10, SPELL_RAIN_OF_FIRE_25), false);
events.RepeatEvent(12000); }
events.RepeatEvent(urand(8000, 18000));
break; break;
case EVENT_SPELL_FRENZY: case EVENT_FRENZY:
if (!me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25))) if (!me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25)))
{ {
Talk(SAY_FRENZY); Talk(SAY_FRENZY);
@@ -161,25 +198,29 @@ public:
events.RepeatEvent(60000); events.RepeatEvent(60000);
} }
else else
{
events.RepeatEvent(30000); events.RepeatEvent(30000);
}
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override void SpellHit(Unit* caster, const SpellInfo* spell) override
{ {
if (spell->Id == SPELL_WIDOWS_EMBRACE) if (spell->Id == RAID_MODE(SPELL_WIDOWS_EMBRACE, SPELL_MINION_WIDOWS_EMBRACE))
{ {
Talk(EMOTE_WIDOWS_EMBRACE); Talk(EMOTE_WIDOWS_EMBRACE);
if (me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25))) if (me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25)))
{ {
me->RemoveAurasDueToSpell(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25)); me->RemoveAurasDueToSpell(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25));
events.RescheduleEvent(EVENT_SPELL_FRENZY, 60000); events.RescheduleEvent(EVENT_FRENZY, 60000);
} }
pInstance->SetData(DATA_FRENZY_REMOVED, 0); pInstance->SetData(DATA_FRENZY_REMOVED, 0);
if (Is25ManRaid())
{
Unit::Kill(caster, caster);
}
} }
} }
}; };
@@ -12,44 +12,39 @@
enum Spells enum Spells
{ {
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662,
// Marks // Marks
SPELL_MARK_OF_KORTHAZZ = 28832, SPELL_MARK_OF_KORTHAZZ = 28832,
SPELL_MARK_OF_BLAUMEUX = 28833, SPELL_MARK_OF_BLAUMEUX = 28833,
SPELL_MARK_OF_RIVENDARE = 28834, SPELL_MARK_OF_RIVENDARE = 28834,
SPELL_MARK_OF_ZELIEK = 28835, SPELL_MARK_OF_ZELIEK = 28835,
SPELL_MARK_DAMAGE = 28836, SPELL_MARK_DAMAGE = 28836,
// Korth'azz // Korth'azz
SPELL_KORTHAZZ_METEOR_10 = 28884, SPELL_KORTHAZZ_METEOR_10 = 28884,
SPELL_KORTHAZZ_METEOR_25 = 57467, SPELL_KORTHAZZ_METEOR_25 = 57467,
// Blaumeux // Blaumeux
SPELL_BLAUMEUX_SHADOW_BOLT_10 = 57374, SPELL_BLAUMEUX_SHADOW_BOLT_10 = 57374,
SPELL_BLAUMEUX_SHADOW_BOLT_25 = 57464, SPELL_BLAUMEUX_SHADOW_BOLT_25 = 57464,
SPELL_BLAUMEUX_VOID_ZONE_10 = 28863, SPELL_BLAUMEUX_VOID_ZONE_10 = 28863,
SPELL_BLAUMEUX_VOID_ZONE_25 = 57463, SPELL_BLAUMEUX_VOID_ZONE_25 = 57463,
SPELL_BLAUMEUX_UNYIELDING_PAIN = 57381, SPELL_BLAUMEUX_UNYIELDING_PAIN = 57381,
// Zeliek // Zeliek
SPELL_ZELIEK_HOLY_WRATH_10 = 28883, SPELL_ZELIEK_HOLY_WRATH_10 = 28883,
SPELL_ZELIEK_HOLY_WRATH_25 = 57466, SPELL_ZELIEK_HOLY_WRATH_25 = 57466,
SPELL_ZELIEK_HOLY_BOLT_10 = 57376, SPELL_ZELIEK_HOLY_BOLT_10 = 57376,
SPELL_ZELIEK_HOLY_BOLT_25 = 57465, SPELL_ZELIEK_HOLY_BOLT_25 = 57465,
SPELL_ZELIEK_CONDEMNATION = 57377, SPELL_ZELIEK_CONDEMNATION = 57377,
// Rivendare // Rivendare
SPELL_RIVENDARE_UNHOLY_SHADOW_10 = 28882, SPELL_RIVENDARE_UNHOLY_SHADOW_10 = 28882,
SPELL_RIVENDARE_UNHOLY_SHADOW_25 = 57369, SPELL_RIVENDARE_UNHOLY_SHADOW_25 = 57369
}; };
enum Events enum Events
{ {
EVENT_SPELL_MARK_CAST = 1, EVENT_MARK_CAST = 1,
EVENT_SPELL_PRIMARY = 2, EVENT_PRIMARY_SPELL = 2,
EVENT_SPELL_SECONDARY = 3, EVENT_SECONDARY_SPELL = 3,
EVENT_SPELL_PUNISH = 4, EVENT_PUNISH = 4,
EVENT_BERSERK = 5, EVENT_BERSERK = 5
}; };
enum Misc enum Misc
@@ -58,12 +53,11 @@ enum Misc
MOVE_PHASE_NONE = 0, MOVE_PHASE_NONE = 0,
MOVE_PHASE_STARTED = 1, MOVE_PHASE_STARTED = 1,
MOVE_PHASE_FINISHED = 2, MOVE_PHASE_FINISHED = 2,
// Horseman // Horseman
HORSEMAN_ZELIEK = 0, HORSEMAN_ZELIEK = 0,
HORSEMAN_BLAUMEUX = 1, HORSEMAN_BLAUMEUX = 1,
HORSEMAN_RIVENDARE = 2, HORSEMAN_RIVENDARE = 2,
HORSEMAN_KORTHAZZ = 3, HORSEMAN_KORTHAZZ = 3
}; };
enum FourHorsemen enum FourHorsemen
@@ -72,20 +66,21 @@ enum FourHorsemen
SAY_TAUNT = 1, SAY_TAUNT = 1,
SAY_SPECIAL = 2, SAY_SPECIAL = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4 SAY_DEATH = 4,
EMOTE_RAGECAST = 7
}; };
// MARKS // MARKS
const uint32 TABLE_SPELL_MARK[4] = {SPELL_MARK_OF_ZELIEK, SPELL_MARK_OF_BLAUMEUX, SPELL_MARK_OF_RIVENDARE, SPELL_MARK_OF_KORTHAZZ}; const uint32 TABLE_SPELL_MARK[4] = {SPELL_MARK_OF_ZELIEK, SPELL_MARK_OF_BLAUMEUX, SPELL_MARK_OF_RIVENDARE, SPELL_MARK_OF_KORTHAZZ};
// SPELL PRIMARY // PRIMARY SPELL
const uint32 TABLE_SPELL_PRIMARY_10[4] = {SPELL_ZELIEK_HOLY_BOLT_10, SPELL_BLAUMEUX_SHADOW_BOLT_10, SPELL_RIVENDARE_UNHOLY_SHADOW_10, SPELL_KORTHAZZ_METEOR_10}; const uint32 TABLE_SPELL_PRIMARY_10[4] = {SPELL_ZELIEK_HOLY_BOLT_10, SPELL_BLAUMEUX_SHADOW_BOLT_10, SPELL_RIVENDARE_UNHOLY_SHADOW_10, SPELL_KORTHAZZ_METEOR_10};
const uint32 TABLE_SPELL_PRIMARY_25[4] = {SPELL_ZELIEK_HOLY_BOLT_25, SPELL_BLAUMEUX_SHADOW_BOLT_25, SPELL_RIVENDARE_UNHOLY_SHADOW_25, SPELL_KORTHAZZ_METEOR_25}; const uint32 TABLE_SPELL_PRIMARY_25[4] = {SPELL_ZELIEK_HOLY_BOLT_25, SPELL_BLAUMEUX_SHADOW_BOLT_25, SPELL_RIVENDARE_UNHOLY_SHADOW_25, SPELL_KORTHAZZ_METEOR_25};
// PUNISH // PUNISH
const uint32 TABLE_SPELL_PUNISH[4] = {SPELL_ZELIEK_CONDEMNATION, SPELL_BLAUMEUX_UNYIELDING_PAIN, 0, 0}; const uint32 TABLE_SPELL_PUNISH[4] = {SPELL_ZELIEK_CONDEMNATION, SPELL_BLAUMEUX_UNYIELDING_PAIN, 0, 0};
// SPELL SECONDARY // SECONDARY SPELL
const uint32 TABLE_SPELL_SECONDARY_10[4] = {SPELL_ZELIEK_HOLY_WRATH_10, SPELL_BLAUMEUX_VOID_ZONE_10, 0, 0}; const uint32 TABLE_SPELL_SECONDARY_10[4] = {SPELL_ZELIEK_HOLY_WRATH_10, SPELL_BLAUMEUX_VOID_ZONE_10, 0, 0};
const uint32 TABLE_SPELL_SECONDARY_25[4] = {SPELL_ZELIEK_HOLY_WRATH_25, SPELL_BLAUMEUX_VOID_ZONE_25, 0, 0}; const uint32 TABLE_SPELL_SECONDARY_25[4] = {SPELL_ZELIEK_HOLY_WRATH_25, SPELL_BLAUMEUX_VOID_ZONE_25, 0, 0};
@@ -106,7 +101,7 @@ const Position WaypointPositions[12] =
// Sir waypoints // Sir waypoints
{2534.5f, -2921.7f, 241.53f, 1.363f}, {2534.5f, -2921.7f, 241.53f, 1.363f},
{2523.5f, -2902.8f, 241.28f, 2.095f}, {2523.5f, -2902.8f, 241.28f, 2.095f},
{2517.8f, -2896.6f, 241.28f, 2.315f}, {2517.8f, -2896.6f, 241.28f, 2.315f}
}; };
class boss_four_horsemen : public CreatureScript class boss_four_horsemen : public CreatureScript
@@ -174,7 +169,6 @@ public:
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -186,17 +180,16 @@ public:
currentWaypoint = 0; currentWaypoint = 0;
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
events.Reset(); events.Reset();
events.RescheduleEvent(EVENT_MARK_CAST, 24000);
// Schedule Events events.RescheduleEvent(EVENT_BERSERK, 600000);
events.RescheduleEvent(EVENT_SPELL_MARK_CAST, 24000);
events.RescheduleEvent(EVENT_BERSERK, 100 * 15000);
if ((me->GetEntry() != NPC_LADY_BLAUMEUX && me->GetEntry() != NPC_SIR_ZELIEK)) if ((me->GetEntry() != NPC_LADY_BLAUMEUX && me->GetEntry() != NPC_SIR_ZELIEK))
events.RescheduleEvent(EVENT_SPELL_PRIMARY, 10000 + rand() % 5000); {
events.RescheduleEvent(EVENT_PRIMARY_SPELL, 10000 + rand() % 5000);
}
else else
{ {
events.RescheduleEvent(EVENT_SPELL_PUNISH, 5000); events.RescheduleEvent(EVENT_PUNISH, 5000);
events.RescheduleEvent(EVENT_SPELL_SECONDARY, 15000); events.RescheduleEvent(EVENT_SECONDARY_SPELL, 15000);
} }
} }
@@ -210,14 +203,12 @@ public:
{ {
movementPhase = MOVE_PHASE_FINISHED; movementPhase = MOVE_PHASE_FINISHED;
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
if (!UpdateVictim()) if (!UpdateVictim())
{ {
EnterEvadeMode(); EnterEvadeMode();
return; return;
} }
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{ {
me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->Clear(false);
@@ -225,7 +216,6 @@ public:
} }
return; return;
} }
currentWaypoint = id + 1; currentWaypoint = id + 1;
} }
@@ -234,11 +224,15 @@ public:
if (movementPhase == MOVE_PHASE_FINISHED) if (movementPhase == MOVE_PHASE_FINISHED)
{ {
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
me->Attack(who, false); me->Attack(who, false);
}
else else
{
ScriptedAI::AttackStart(who); ScriptedAI::AttackStart(who);
} }
} }
}
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
@@ -246,10 +240,11 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -259,11 +254,14 @@ public:
if (pInstance->GetBossState(BOSS_HORSEMAN) == DONE) if (pInstance->GetBossState(BOSS_HORSEMAN) == DONE)
{ {
if (!me->GetMap()->GetPlayers().isEmpty()) if (!me->GetMap()->GetPlayers().isEmpty())
{
if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource()) if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource())
{
player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0); player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0);
} }
} }
}
}
Talk(SAY_DEATH); Talk(SAY_DEATH);
} }
@@ -273,7 +271,6 @@ public:
if (movementPhase == MOVE_PHASE_NONE) if (movementPhase == MOVE_PHASE_NONE)
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
movementPhase = MOVE_PHASE_STARTED; movementPhase = MOVE_PHASE_STARTED;
me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true); me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
@@ -301,27 +298,28 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_MARK_CAST: case EVENT_MARK_CAST:
me->CastSpell(me, TABLE_SPELL_MARK[horsemanId], false); me->CastSpell(me, TABLE_SPELL_MARK[horsemanId], false);
events.RepeatEvent((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) ? 15000 : 12000); events.RepeatEvent((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) ? 15000 : 12000);
return; return;
case EVENT_BERSERK: case EVENT_BERSERK:
Talk(SAY_SPECIAL); Talk(SAY_SPECIAL);
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
return; return;
case EVENT_SPELL_PRIMARY: case EVENT_PRIMARY_SPELL:
Talk(SAY_TAUNT); Talk(SAY_TAUNT);
me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false); me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
return; return;
case EVENT_SPELL_PUNISH: case EVENT_PUNISH:
if (!SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) if (!SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true))
{
me->CastSpell(me, TABLE_SPELL_PUNISH[horsemanId], false); me->CastSpell(me, TABLE_SPELL_PUNISH[horsemanId], false);
events.RepeatEvent(3000); Talk(EMOTE_RAGECAST);
}
events.RepeatEvent(2010);
return; return;
case EVENT_SPELL_SECONDARY: case EVENT_SECONDARY_SPELL:
me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_SECONDARY_10[horsemanId], TABLE_SPELL_SECONDARY_25[horsemanId]), false); me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_SECONDARY_10[horsemanId], TABLE_SPELL_SECONDARY_25[horsemanId]), false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
return; return;
@@ -330,11 +328,15 @@ public:
if ((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)) if ((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK))
{ {
if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true))
{
me->CastSpell(target, RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false); me->CastSpell(target, RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false);
} }
}
else else
{
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}
}; };
}; };
@@ -361,25 +363,27 @@ public:
damage = 500; damage = 500;
break; break;
case 3: case 3:
damage = 1000;
break;
case 4:
damage = 1500; damage = 1500;
break; break;
case 5: case 4:
damage = 4000; damage = 4000;
break; break;
case 6: case 5:
damage = 12000; damage = 12000;
break; break;
case 6:
damage = 20000;
break;
default: default:
damage = 20000 + 1000 * (GetStackAmount() - 7); damage = 20000 + 1000 * (GetStackAmount() - 7);
break; break;
} }
if (damage) if (damage)
{
caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget()); caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget());
} }
} }
}
void Register() override void Register() override
{ {
@@ -17,22 +17,22 @@ enum Spells
SPELL_DECIMATE_25 = 54426, SPELL_DECIMATE_25 = 54426,
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662,
SPELL_INFECTED_WOUND = 29306, SPELL_INFECTED_WOUND = 29306,
SPELL_CHOW_SEARCHER = 28404, SPELL_CHOW_SEARCHER = 28404
}; };
enum Events enum Events
{ {
EVENT_SPELL_MORTAL_WOUND = 1, EVENT_MORTAL_WOUND = 1,
EVENT_SPELL_ENRAGE = 2, EVENT_ENRAGE = 2,
EVENT_SPELL_DECIMATE = 3, EVENT_DECIMATE = 3,
EVENT_SPELL_BERSERK = 4, EVENT_BERSERK = 4,
EVENT_SUMMON_ZOMBIE = 5, EVENT_SUMMON_ZOMBIE = 5,
EVENT_CAN_EAT_ZOMBIE = 6, EVENT_CAN_EAT_ZOMBIE = 6
}; };
enum Misc enum Misc
{ {
NPC_ZOMBIE_CHOW = 16360, NPC_ZOMBIE_CHOW = 16360
}; };
enum Emotes enum Emotes
@@ -48,7 +48,7 @@ const Position zombiePos[3] =
{ {
{3267.9f, -3172.1f, 297.42f, 0.94f}, {3267.9f, -3172.1f, 297.42f, 0.94f},
{3253.2f, -3132.3f, 297.42f, 0}, {3253.2f, -3132.3f, 297.42f, 0},
{3308.3f, -3185.8f, 297.42f, 1.58f}, {3308.3f, -3185.8f, 297.42f, 1.58f}
}; };
class boss_gluth : public CreatureScript class boss_gluth : public CreatureScript
@@ -91,18 +91,20 @@ public:
Talk(EMOTE_SPOTS_ONE); Talk(EMOTE_SPOTS_ONE);
} }
else else
{
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_MORTAL_WOUND, 10000); events.ScheduleEvent(EVENT_MORTAL_WOUND, 10000);
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 30000); events.ScheduleEvent(EVENT_ENRAGE, 22000);
events.ScheduleEvent(EVENT_SPELL_DECIMATE, 105000); events.ScheduleEvent(EVENT_DECIMATE, RAID_MODE(110000, 90000));
events.ScheduleEvent(EVENT_SPELL_BERSERK, 8 * 60000); events.ScheduleEvent(EVENT_BERSERK, 360000);
events.ScheduleEvent(EVENT_SUMMON_ZOMBIE, 10000); events.ScheduleEvent(EVENT_SUMMON_ZOMBIE, 10000);
events.ScheduleEvent(EVENT_CAN_EAT_ZOMBIE, 1000); events.ScheduleEvent(EVENT_CAN_EAT_ZOMBIE, 1000);
} }
@@ -110,8 +112,9 @@ public:
void JustSummoned(Creature* summon) override void JustSummoned(Creature* summon) override
{ {
if (summon->GetEntry() == NPC_ZOMBIE_CHOW) if (summon->GetEntry() == NPC_ZOMBIE_CHOW)
{
summon->AI()->AttackStart(me); summon->AI()->AttackStart(me);
}
summons.Summon(summon); summons.Summon(summon);
} }
@@ -120,11 +123,14 @@ public:
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (me->IsAlive() && who->GetEntry() == NPC_ZOMBIE_CHOW) if (me->IsAlive() && who->GetEntry() == NPC_ZOMBIE_CHOW)
{
me->ModifyHealth(int32(me->GetMaxHealth() * 0.05f)); me->ModifyHealth(int32(me->GetMaxHealth() * 0.05f));
}
if (who->GetTypeId() == TYPEID_PLAYER && pInstance) if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -143,13 +149,13 @@ public:
Player* player = itr.GetSource(); Player* player = itr.GetSource();
if (!player || !player->IsAlive()) if (!player || !player->IsAlive())
continue; continue;
if (player->GetPositionZ() > 300.0f || me->GetExactDist(player) > 50.0f) if (player->GetPositionZ() > 300.0f || me->GetExactDist(player) > 50.0f)
continue; continue;
AttackStart(player); AttackStart(player);
return true; return true;
} }
return false; return false;
} }
@@ -164,23 +170,22 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_BERSERK: case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
break; break;
case EVENT_SPELL_ENRAGE: case EVENT_ENRAGE:
Talk(EMOTE_ENRAGE); Talk(EMOTE_ENRAGE);
me->CastSpell(me, RAID_MODE(SPELL_ENRAGE_10, SPELL_ENRAGE_25), true); me->CastSpell(me, RAID_MODE(SPELL_ENRAGE_10, SPELL_ENRAGE_25), true);
events.RepeatEvent(30000); events.RepeatEvent(22000);
break; break;
case EVENT_SPELL_MORTAL_WOUND: case EVENT_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false); me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.RepeatEvent(10000); events.RepeatEvent(10000);
break; break;
case EVENT_SPELL_DECIMATE: case EVENT_DECIMATE:
Talk(EMOTE_DECIMATE); Talk(EMOTE_DECIMATE);
me->CastSpell(me, RAID_MODE(SPELL_DECIMATE_10, SPELL_DECIMATE_25), false); me->CastSpell(me, RAID_MODE(SPELL_DECIMATE_10, SPELL_DECIMATE_25), false);
events.RepeatEvent(105000); events.RepeatEvent(RAID_MODE(110000, 90000));
break; break;
case EVENT_SUMMON_ZOMBIE: case EVENT_SUMMON_ZOMBIE:
{ {
@@ -191,12 +196,15 @@ public:
// \1 |0 /2 pos // \1 |0 /2 pos
// In 25 man raid - should spawn from all 3 gates // In 25 man raid - should spawn from all 3 gates
if (me->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) if (me->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
{
me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[0]); me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[0]);
}
else else
{
me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[urand(0, 2)]); me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[urand(0, 2)]);
}
(rand == 2 ? rand = 0 : rand++); (rand == 2 ? rand = 0 : rand++);
} }
events.RepeatEvent(10000); events.RepeatEvent(10000);
break; break;
} }
@@ -210,7 +218,6 @@ public:
} }
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -241,7 +248,6 @@ public:
Unit::DealDamage(GetCaster(), cTarget, damage); Unit::DealDamage(GetCaster(), cTarget, damage);
return; return;
} }
GetCaster()->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget); GetCaster()->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget);
} }
} }
@@ -25,37 +25,38 @@ enum Yells
enum Spells enum Spells
{ {
// Gothik
SPELL_HARVEST_SOUL = 28679, SPELL_HARVEST_SOUL = 28679,
SPELL_SHADOW_BOLT_10 = 29317, SPELL_SHADOW_BOLT_10 = 29317,
SPELL_SHADOW_BOLT_25 = 56405, SPELL_SHADOW_BOLT_25 = 56405,
// Teleport spells
SPELL_TELEPORT_DEAD = 28025,
SPELL_TELEPORT_LIVE = 28026,
// Visual spells
SPELL_INFORM_LIVING_TRAINEE = 27892, SPELL_INFORM_LIVING_TRAINEE = 27892,
SPELL_INFORM_LIVING_KNIGHT = 27928, SPELL_INFORM_LIVING_KNIGHT = 27928,
SPELL_INFORM_LIVING_RIDER = 27935, SPELL_INFORM_LIVING_RIDER = 27935,
SPELL_INFORM_DEAD_TRAINEE = 27915, SPELL_INFORM_DEAD_TRAINEE = 27915,
SPELL_INFORM_DEAD_KNIGHT = 27931, SPELL_INFORM_DEAD_KNIGHT = 27931,
SPELL_INFORM_DEAD_RIDER = 27937, SPELL_INFORM_DEAD_RIDER = 27937,
/*SPELL_ANCHOR_2_TRAINEE = 27893,
// TRAINEES SPELL_ANCHOR_2_DK = 27929,
SPELL_DEATH_PLAGUE = 55604, // LIVING TRAINEE SPELL_ANCHOR_2_RIDER = 27936, fix me */
SPELL_ARCANE_EXPLOSION = 27989, // DEAD TRAINEE (20y) // Living trainee
SPELL_DEATH_PLAGUE = 55604,
// KNIGHT // Dead trainee
SPELL_SHADOW_MARK = 27825, // LIVING KNIGHT SPELL_ARCANE_EXPLOSION = 27989,
SPELL_WHIRLWIND = 56408, // DEAD KNIGHT // Living knight
SPELL_SHADOW_MARK = 27825,
// RIDER // Dead knight
SPELL_BLOOD_PRESENCE = 55212, // LIVING RIDER SPELL_WHIRLWIND = 56408,
SPELL_DEATH_COIL = 55209, // LIVING RIDER // Living rider
SPELL_HASTE_AURA = 13589, // LIVING RIDER SPELL_SHADOW_BOLT_VOLLEY = 27831,
SPELL_HYSTERIA = 55213, // LIVING RIDER // Dead rider
SPELL_INTIMIDATING_SHOUT = 5246, // LIVING RIDER SPELL_DRAIN_LIFE = 27994,
SPELL_VEIL_OF_DARKNESS = 28350, // LIVING RIDER SPELL_UNHOLY_FRENZY = 55648,
SPELL_DRAIN_LIFE = 27994, // DEAD RIDER // Horse
SPELL_UNHOLY_AURA = 55606, // DEAD RIDER SPELL_STOMP = 27993
SPELL_UNHOLY_FRENZY = 55648, // DEAD RIDER
// HORSE
SPELL_STOMP = 27993 // DEAD HORSE
}; };
enum Misc enum Misc
@@ -67,44 +68,37 @@ enum Misc
NPC_DEAD_KNIGHT = 16148, NPC_DEAD_KNIGHT = 16148,
NPC_DEAD_HORSE = 16149, NPC_DEAD_HORSE = 16149,
NPC_DEAD_RIDER = 16150, NPC_DEAD_RIDER = 16150,
//NPC_TRIGGER = 16137, fix me
ACTION_GATE_OPEN = 1,
}; };
enum Events enum Events
{ {
// Gothik
EVENT_SUMMON_ADDS = 1, EVENT_SUMMON_ADDS = 1,
EVENT_SPELL_HARVEST_SOUL = 2, EVENT_HARVEST_SOUL = 2,
EVENT_SPELL_SHADOW_BOLT = 3, EVENT_SHADOW_BOLT = 3,
EVENT_TELEPORT = 4, EVENT_TELEPORT = 4,
EVENT_CHECK_HEALTH = 5, EVENT_CHECK_HEALTH = 5,
EVENT_CHECK_PLAYERS = 6, EVENT_CHECK_PLAYERS = 6,
// Living trainee
// TRAINEES EVENT_DEATH_PLAGUE = 7,
EVENT_SPELL_DEATH_PLAGUE = 7, // Dead trainee
EVENT_SPELL_ARCANE_EXPLOSION = 8, EVENT_ARCANE_EXPLOSION = 8,
// Living knight
// KNIGHT EVENT_SHADOW_MARK = 9,
EVENT_SPELL_SHADOW_MARK = 9, // Dead knight
EVENT_SPELL_WHIRLWIND = 10, EVENT_WHIRLWIND = 10,
// Living rider
// RIDER EVENT_SHADOW_BOLT_VOLLEY = 11,
EVENT_SPELL_BLOOD_PRESENCE = 11, // Dead rider
EVENT_SPELL_DEATH_COIL = 12, EVENT_DRAIN_LIFE = 12,
EVENT_SPELL_HASTE_AURA = 13, EVENT_UNHOLY_FRENZY = 13,
EVENT_SPELL_HYSTERIA = 14,
EVENT_SPELL_INTIMIDATING_SHOUT = 15,
EVENT_SPELL_VEIL_OF_DARKNESS = 16,
EVENT_SPELL_DRAIN_LIFE = 17,
EVENT_SPELL_UNHOLY_AURA = 18,
EVENT_SPELL_UNHOLY_FRENZY = 19,
// HORSE // HORSE
EVENT_SPELL_STOMP = 20, EVENT_STOMP = 14,
// Intro
EVENT_INTRO_2 = 21, EVENT_INTRO_2 = 15,
EVENT_INTRO_3 = 22, EVENT_INTRO_3 = 16,
EVENT_INTRO_4 = 23, EVENT_INTRO_4 = 17
}; };
const uint32 gothikWaves[24][2] = const uint32 gothikWaves[24][2] =
@@ -142,7 +136,7 @@ const Position PosSummonLiving[6] =
{2714.4f, -3428.76f, 268.56f, 1.6f}, {2714.4f, -3428.76f, 268.56f, 1.6f},
{2669.7f, -3431.67f, 268.56f, 1.6f}, {2669.7f, -3431.67f, 268.56f, 1.6f},
{2692.1f, -3431.67f, 268.56f, 1.6f}, {2692.1f, -3431.67f, 268.56f, 1.6f},
{2714.4f, -3431.67f, 268.56f, 1.6f}, {2714.4f, -3431.67f, 268.56f, 1.6f}
}; };
const Position PosSummonDead[5] = const Position PosSummonDead[5] =
@@ -151,7 +145,7 @@ const Position PosSummonDead[5] =
{2699.3f, -3322.8f, 268.60f, 3.3f}, {2699.3f, -3322.8f, 268.60f, 3.3f},
{2733.1f, -3348.5f, 268.84f, 3.1f}, {2733.1f, -3348.5f, 268.84f, 3.1f},
{2682.8f, -3304.2f, 268.85f, 3.9f}, {2682.8f, -3304.2f, 268.85f, 3.9f},
{2664.8f, -3340.7f, 268.23f, 3.7f}, {2664.8f, -3340.7f, 268.23f, 3.7f}
}; };
const Position PosGroundLivingSide = {2691.2f, -3387.0f, 267.68f, 1.52f}; const Position PosGroundLivingSide = {2691.2f, -3387.0f, 267.68f, 1.52f};
@@ -193,7 +187,6 @@ public:
{ {
pInstance = me->GetInstanceScript(); pInstance = me->GetInstanceScript();
} }
EventMap events; EventMap events;
SummonList summons; SummonList summons;
InstanceScript* pInstance; InstanceScript* pInstance;
@@ -208,7 +201,6 @@ public:
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -217,22 +209,28 @@ public:
BossAI::Reset(); BossAI::Reset();
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
secondPhase = false; secondPhase = false;
gateOpened = false; gateOpened = false;
waveCount = 0; waveCount = 0;
me->NearTeleportTo(2642.139f, -3386.959f, 285.492f, 6.265f);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
@@ -242,31 +240,43 @@ public:
events.ScheduleEvent(EVENT_INTRO_2, 4000); events.ScheduleEvent(EVENT_INTRO_2, 4000);
events.ScheduleEvent(EVENT_INTRO_3, 9000); events.ScheduleEvent(EVENT_INTRO_3, 9000);
events.ScheduleEvent(EVENT_INTRO_4, 14000); events.ScheduleEvent(EVENT_INTRO_4, 14000);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
me->NearTeleportTo(PosPlatform.GetPositionX(), PosPlatform.GetPositionY(), PosPlatform.GetPositionZ(), PosPlatform.GetOrientation());
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000); events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
events.ScheduleEvent(EVENT_CHECK_PLAYERS, 120000); events.ScheduleEvent(EVENT_CHECK_PLAYERS, 120000);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
} }
}
void JustSummoned(Creature* summon) override void JustSummoned(Creature* summon) override
{ {
if (gateOpened)
summon->AI()->DoAction(ACTION_GATE_OPEN);
summons.Summon(summon); summons.Summon(summon);
summon->SetInCombatWithZone(); if (gateOpened)
{
summons.DoZoneInCombat();
}
else
{
if (Unit* target = me->SelectNearestTarget(50.0f))
{
AttackStart(target);
DoZoneInCombat();
}
}
} }
void SummonedCreatureDespawn(Creature* cr) override { summons.Despawn(cr); } void SummonedCreatureDespawn(Creature* cr) override
{
summons.Despawn(cr);
}
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
@@ -274,27 +284,33 @@ public:
return; return;
Talk(SAY_KILL); Talk(SAY_KILL);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
summons.DespawnAll(); summons.DespawnAll();
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void SummonHelpers(uint32 entry) void SummonHelpers(uint32 entry)
{ {
@@ -304,12 +320,16 @@ public:
me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[0].GetPositionX(), PosSummonLiving[0].GetPositionY(), PosSummonLiving[0].GetPositionZ(), PosSummonLiving[0].GetOrientation()); me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[0].GetPositionX(), PosSummonLiving[0].GetPositionY(), PosSummonLiving[0].GetPositionZ(), PosSummonLiving[0].GetOrientation());
me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[1].GetPositionX(), PosSummonLiving[1].GetPositionY(), PosSummonLiving[1].GetPositionZ(), PosSummonLiving[1].GetOrientation()); me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[1].GetPositionX(), PosSummonLiving[1].GetPositionY(), PosSummonLiving[1].GetPositionZ(), PosSummonLiving[1].GetOrientation());
if (Is25ManRaid()) if (Is25ManRaid())
{
me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[2].GetPositionX(), PosSummonLiving[2].GetPositionY(), PosSummonLiving[2].GetPositionZ(), PosSummonLiving[2].GetOrientation()); me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[2].GetPositionX(), PosSummonLiving[2].GetPositionY(), PosSummonLiving[2].GetPositionZ(), PosSummonLiving[2].GetOrientation());
}
break; break;
case NPC_LIVING_KNIGHT: case NPC_LIVING_KNIGHT:
me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[3].GetPositionX(), PosSummonLiving[3].GetPositionY(), PosSummonLiving[3].GetPositionZ(), PosSummonLiving[3].GetOrientation()); me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[3].GetPositionX(), PosSummonLiving[3].GetPositionY(), PosSummonLiving[3].GetPositionZ(), PosSummonLiving[3].GetOrientation());
if (Is25ManRaid()) if (Is25ManRaid())
{
me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[5].GetPositionX(), PosSummonLiving[5].GetPositionY(), PosSummonLiving[5].GetPositionZ(), PosSummonLiving[5].GetOrientation()); me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[5].GetPositionX(), PosSummonLiving[5].GetPositionY(), PosSummonLiving[5].GetPositionZ(), PosSummonLiving[5].GetOrientation());
}
break; break;
case NPC_LIVING_RIDER: case NPC_LIVING_RIDER:
me->SummonCreature(NPC_LIVING_RIDER, PosSummonLiving[4].GetPositionX(), PosSummonLiving[4].GetPositionY(), PosSummonLiving[4].GetPositionZ(), PosSummonLiving[4].GetOrientation()); me->SummonCreature(NPC_LIVING_RIDER, PosSummonLiving[4].GetPositionX(), PosSummonLiving[4].GetPositionY(), PosSummonLiving[4].GetPositionZ(), PosSummonLiving[4].GetOrientation());
@@ -332,13 +352,17 @@ public:
player->GetPositionX() >= POS_X_SOUTH && player->GetPositionX() >= POS_X_SOUTH &&
player->GetPositionY() <= POS_Y_GATE && player->GetPositionY() <= POS_Y_GATE &&
player->GetPositionY() >= POS_Y_EAST) player->GetPositionY() >= POS_Y_EAST)
{
checklife = true; checklife = true;
}
else if (player->IsAlive() && else if (player->IsAlive() &&
player->GetPositionX() <= POS_X_NORTH && player->GetPositionX() <= POS_X_NORTH &&
player->GetPositionX() >= POS_X_SOUTH && player->GetPositionX() >= POS_X_SOUTH &&
player->GetPositionY() >= POS_Y_GATE && player->GetPositionY() >= POS_Y_GATE &&
player->GetPositionY() <= POS_Y_WEST) player->GetPositionY() <= POS_Y_WEST)
{
checkdead = true; checkdead = true;
}
if (checklife && checkdead) if (checklife && checkdead)
return true; return true;
@@ -363,15 +387,16 @@ public:
me->SummonCreature(NPC_DEAD_HORSE, PosSummonDead[pos].GetPositionX(), PosSummonDead[pos].GetPositionY(), PosSummonDead[pos].GetPositionZ(), PosSummonDead[pos].GetOrientation()); me->SummonCreature(NPC_DEAD_HORSE, PosSummonDead[pos].GetPositionX(), PosSummonDead[pos].GetPositionY(), PosSummonDead[pos].GetPositionZ(), PosSummonDead[pos].GetOrientation());
break; break;
} }
me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST); me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST);
} }
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{ {
if (!secondPhase) if (!secondPhase)
{
damage = 0; damage = 0;
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -389,31 +414,31 @@ public:
{ {
case EVENT_INTRO_2: case EVENT_INTRO_2:
Talk(SAY_INTRO_2); Talk(SAY_INTRO_2);
break; break;
case EVENT_INTRO_3: case EVENT_INTRO_3:
Talk(SAY_INTRO_3); Talk(SAY_INTRO_3);
break; break;
case EVENT_INTRO_4: case EVENT_INTRO_4:
Talk(SAY_INTRO_4); Talk(SAY_INTRO_4);
break; break;
case EVENT_SPELL_SHADOW_BOLT: case EVENT_SHADOW_BOLT:
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_SHADOW_BOLT_10, SPELL_SHADOW_BOLT_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_SHADOW_BOLT_10, SPELL_SHADOW_BOLT_25), false);
events.RepeatEvent(2000); events.RepeatEvent(1010);
break; break;
case EVENT_SPELL_HARVEST_SOUL: case EVENT_HARVEST_SOUL:
me->CastSpell(me, SPELL_HARVEST_SOUL, false); me->CastSpell(me, SPELL_HARVEST_SOUL, false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
break; break;
case EVENT_TELEPORT: case EVENT_TELEPORT:
me->AttackStop(); me->AttackStop();
if (IN_LIVE_SIDE(me)) if (IN_LIVE_SIDE(me))
me->NearTeleportTo(PosGroundDeadSide.GetPositionX(), PosGroundDeadSide.GetPositionY(), PosGroundDeadSide.GetPositionZ(), PosGroundDeadSide.GetOrientation()); {
me->CastSpell(me, SPELL_TELEPORT_DEAD, false);
}
else else
me->NearTeleportTo(PosGroundLivingSide.GetPositionX(), PosGroundLivingSide.GetPositionY(), PosGroundLivingSide.GetPositionZ(), PosGroundLivingSide.GetOrientation()); {
me->CastSpell(me, SPELL_TELEPORT_LIVE, false);
}
me->getThreatManager().resetAggro(NotOnSameSide(me)); me->getThreatManager().resetAggro(NotOnSameSide(me));
if (Unit* pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) if (Unit* pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0))
{ {
@@ -426,10 +451,10 @@ public:
if (me->HealthBelowPct(30) && pInstance) if (me->HealthBelowPct(30) && pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
events.CancelEvent(EVENT_TELEPORT); events.CancelEvent(EVENT_TELEPORT);
break; break;
} }
events.RepeatEvent(1000); events.RepeatEvent(1000);
@@ -445,35 +470,31 @@ public:
secondPhase = true; secondPhase = true;
Talk(SAY_PHASE_TWO); Talk(SAY_PHASE_TWO);
Talk(EMOTE_PHASE_TWO); Talk(EMOTE_PHASE_TWO);
me->NearTeleportTo(PosGroundLivingSide.GetPositionX(), PosGroundLivingSide.GetPositionY(), PosGroundLivingSide.GetPositionZ(), PosGroundLivingSide.GetOrientation()); me->CastSpell(me, SPELL_TELEPORT_LIVE, false);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE);
me->RemoveAllAuras();
summons.DoAction(ACTION_GATE_OPEN);
summons.DoZoneInCombat(); summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, 1000); events.ScheduleEvent(EVENT_SHADOW_BOLT, 1000);
events.ScheduleEvent(EVENT_SPELL_HARVEST_SOUL, urand(5000, 15000)); events.ScheduleEvent(EVENT_HARVEST_SOUL, urand(5000, 15000));
events.ScheduleEvent(EVENT_TELEPORT, 20000); events.ScheduleEvent(EVENT_TELEPORT, 20000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000); events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
} }
waveCount++; waveCount++;
break; break;
case EVENT_CHECK_PLAYERS: case EVENT_CHECK_PLAYERS:
if (!CheckGroupSplitted()) if (!CheckGroupSplitted())
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
summons.DoAction(ACTION_GATE_OPEN);
summons.DoZoneInCombat(); summons.DoZoneInCombat();
gateOpened = true; gateOpened = true;
Talk(EMOTE_GATE_OPENED); Talk(EMOTE_GATE_OPENED);
} }
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -494,63 +515,58 @@ public:
explicit npc_boss_gothik_minionAI(Creature* c) : CombatAI(c) explicit npc_boss_gothik_minionAI(Creature* c) : CombatAI(c)
{ {
livingSide = IN_LIVE_SIDE(me); livingSide = IN_LIVE_SIDE(me);
gateOpened = false;
} }
EventMap events; EventMap events;
bool livingSide; bool livingSide;
bool gateOpened;
bool IsOnSameSide(Unit const* who) const { return livingSide == IN_LIVE_SIDE(who); } bool IsOnSameSide(Unit const* who) const { return livingSide == IN_LIVE_SIDE(who); }
bool CanAIAttack(Unit const* target) const override { return gateOpened || IsOnSameSide(target); }
void Reset() override { events.Reset(); } void Reset() override
{
me->SetReactState(REACT_AGGRESSIVE);
me->SetNoCallAssistance(false);
events.Reset();
}
void EnterCombat(Unit* /*who*/) override void EnterCombat(Unit* /*who*/) override
{ {
me->SetInCombatWithZone();
switch (me->GetEntry()) switch (me->GetEntry())
{ {
case NPC_LIVING_TRAINEE: case NPC_LIVING_TRAINEE:
events.ScheduleEvent(EVENT_SPELL_DEATH_PLAGUE, 2000); events.ScheduleEvent(EVENT_DEATH_PLAGUE, 3000);
break; break;
case NPC_DEAD_TRAINEE: case NPC_DEAD_TRAINEE:
events.ScheduleEvent(EVENT_SPELL_ARCANE_EXPLOSION, 2000); events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 2500);
break; break;
case NPC_LIVING_KNIGHT: case NPC_LIVING_KNIGHT:
events.ScheduleEvent(EVENT_SPELL_SHADOW_MARK, 2000); events.ScheduleEvent(EVENT_SHADOW_MARK, 3000);
break; break;
case NPC_DEAD_KNIGHT: case NPC_DEAD_KNIGHT:
events.ScheduleEvent(EVENT_SPELL_WHIRLWIND, 2000); events.ScheduleEvent(EVENT_WHIRLWIND, 2000);
break; break;
case NPC_LIVING_RIDER: case NPC_LIVING_RIDER:
events.ScheduleEvent(EVENT_SPELL_BLOOD_PRESENCE, 1); events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 3000);
events.ScheduleEvent(EVENT_SPELL_DEATH_COIL, 3000);
events.ScheduleEvent(EVENT_SPELL_HYSTERIA, 10000);
events.ScheduleEvent(EVENT_SPELL_HASTE_AURA, 1000);
events.ScheduleEvent(EVENT_SPELL_INTIMIDATING_SHOUT, urand(4000, 9000));
events.ScheduleEvent(EVENT_SPELL_VEIL_OF_DARKNESS, urand(5000, 7000));
break; break;
case NPC_DEAD_RIDER: case NPC_DEAD_RIDER:
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, urand(2000, 3500)); events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(2000, 3500));
events.ScheduleEvent(EVENT_SPELL_UNHOLY_AURA, 1); events.ScheduleEvent(EVENT_UNHOLY_FRENZY, urand(5000, 9000));
events.ScheduleEvent(EVENT_SPELL_UNHOLY_FRENZY, urand(5000, 9000));
break; break;
case NPC_DEAD_HORSE: case NPC_DEAD_HORSE:
events.ScheduleEvent(EVENT_SPELL_STOMP, urand(2000, 5000)); events.ScheduleEvent(EVENT_STOMP, urand(2000, 5000));
break; break;
} }
} }
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{ {
if (!attacker || (!gateOpened && !IsOnSameSide(attacker))) if (!attacker && !IsOnSameSide(attacker))
{
damage = 0; damage = 0;
} }
if (!me->IsInCombat())
void DoAction(int32 param) override
{ {
if (param == ACTION_GATE_OPEN) me->CallForHelp(25.0f);
gateOpened = true; AttackStart(attacker);
}
} }
void JustDied(Unit*) override void JustDied(Unit*) override
@@ -572,89 +588,82 @@ public:
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript()) if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0); me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
events.Update(diff); events.Update(diff);
if (me->GetUnitState() == UNIT_STATE_CASTING) if (me->GetUnitState() == UNIT_STATE_CASTING)
return; return;
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_DEATH_PLAGUE: case EVENT_DEATH_PLAGUE:
me->CastSpell(me->GetVictim(), SPELL_DEATH_PLAGUE, false); me->CastSpell(me->GetVictim(), SPELL_DEATH_PLAGUE, false);
events.RepeatEvent(urand(15000, 20000)); events.RepeatEvent(urand(4000, 7000));
break; break;
case EVENT_SPELL_ARCANE_EXPLOSION: case EVENT_ARCANE_EXPLOSION:
if (Unit* victim = me->GetVictim()) if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 20)) if (victim->IsWithinDist(me, 20))
{
me->CastSpell(victim, SPELL_ARCANE_EXPLOSION, false); me->CastSpell(victim, SPELL_ARCANE_EXPLOSION, false);
events.RepeatEvent(urand(5000, 10000)); }
}
events.RepeatEvent(2500);
break; break;
case EVENT_SPELL_SHADOW_MARK: case EVENT_SHADOW_MARK:
if (Unit* victim = me->GetVictim()) if (Unit* victim = me->GetVictim())
{
if (!victim->HasAura(SPELL_SHADOW_MARK)) if (!victim->HasAura(SPELL_SHADOW_MARK))
{
me->CastSpell(me->GetVictim(), SPELL_SHADOW_MARK, false); me->CastSpell(me->GetVictim(), SPELL_SHADOW_MARK, false);
events.RepeatEvent(urand(15000, 20000)); }
}
events.RepeatEvent(urand(5000, 7000));
break; break;
case EVENT_SPELL_WHIRLWIND: case EVENT_WHIRLWIND:
if (Unit* victim = me->GetVictim()) if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 10)) if (victim->IsWithinDist(me, 10))
{
me->CastSpell(victim, SPELL_WHIRLWIND, false); me->CastSpell(victim, SPELL_WHIRLWIND, false);
events.RepeatEvent(urand(5000, 8000)); }
}
events.RepeatEvent(urand(4000, 6000));
break; break;
case EVENT_SPELL_BLOOD_PRESENCE: case EVENT_SHADOW_BOLT_VOLLEY:
if (!me->HasAura(SPELL_BLOOD_PRESENCE)) me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT_VOLLEY, false);
me->CastSpell(me, SPELL_BLOOD_PRESENCE, false); events.RepeatEvent(5000);
break; break;
case EVENT_SPELL_HASTE_AURA: case EVENT_DRAIN_LIFE:
if (!me->HasAura(SPELL_HASTE_AURA))
me->CastSpell(me, SPELL_HASTE_AURA, false);
break;
case EVENT_SPELL_DEATH_COIL:
me->CastSpell(me->GetVictim(), SPELL_DEATH_COIL, false);
events.RepeatEvent(urand(5000, 9000));
break;
case EVENT_SPELL_HYSTERIA:
if (!me->HasAura(SPELL_HYSTERIA))
me->CastSpell(me, SPELL_HYSTERIA, false);
events.RepeatEvent(urand(15000, 20000));
break;
case EVENT_SPELL_INTIMIDATING_SHOUT:
if (Unit* victim = me->GetVictim()) if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 20))
{
me->CastSpell(victim, SPELL_DRAIN_LIFE, false);
}
}
events.RepeatEvent(urand(8000, 12000));
break;
case EVENT_UNHOLY_FRENZY:
me->AddAura(SPELL_UNHOLY_FRENZY, me);
events.RepeatEvent(urand(15000, 17000));
break;
case EVENT_STOMP:
if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 10)) if (victim->IsWithinDist(me, 10))
me->CastSpell(victim, SPELL_INTIMIDATING_SHOUT, false); {
events.RepeatEvent(urand(14000, 22000)); me->CastSpell(victim, SPELL_STOMP, false);
break; }
case EVENT_SPELL_VEIL_OF_DARKNESS: }
me->CastSpell(me->GetVictim(), SPELL_VEIL_OF_DARKNESS, false);
events.RepeatEvent(urand(13000, 19000));
break;
case EVENT_SPELL_DRAIN_LIFE:
me->CastSpell(me->GetVictim(), SPELL_DRAIN_LIFE, false);
events.RepeatEvent(urand(6000, 15000));
break;
case EVENT_SPELL_UNHOLY_AURA:
if (!me->HasAura(SPELL_UNHOLY_AURA))
me->CastSpell(me, SPELL_UNHOLY_AURA, false);
events.RepeatEvent(urand(2000, 5000));
break;
case EVENT_SPELL_UNHOLY_FRENZY:
if (!me->HasAura(SPELL_UNHOLY_FRENZY))
me->CastSpell(me, SPELL_UNHOLY_FRENZY, false);
events.RepeatEvent(urand(2000, 5000));
break;
case NPC_DEAD_HORSE:
me->CastSpell(me->GetVictim(), SPELL_STOMP, false);
events.RepeatEvent(urand(4000, 9000)); events.RepeatEvent(urand(4000, 9000));
break; break;
default:
break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -7,18 +7,20 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "SpellScript.h" #include "SpellScript.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
enum Spells enum Spells
{ {
SPELL_POISON_CLOUD = 28240, SPELL_POISON_CLOUD = 28240,
SPELL_MUTATING_INJECTION = 28169, SPELL_MUTATING_INJECTION = 28169,
SPELL_MUTATING_EXPLOSION = 28206,
SPELL_SLIME_SPRAY_10 = 28157, SPELL_SLIME_SPRAY_10 = 28157,
SPELL_SLIME_SPRAY_25 = 54364, SPELL_SLIME_SPRAY_25 = 54364,
SPELL_POISON_CLOUD_DAMAGE_AURA_10 = 28158, SPELL_POISON_CLOUD_DAMAGE_AURA_10 = 28158,
SPELL_POISON_CLOUD_DAMAGE_AURA_25 = 54362, SPELL_POISON_CLOUD_DAMAGE_AURA_25 = 54362,
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662,
SPELL_BOMBARD_SLIME = 28280
SPELL_BOMBARD_SLIME = 28280, // Spawn slime when hit by slime spray
}; };
enum Emotes enum Emotes
@@ -28,10 +30,10 @@ enum Emotes
enum Events enum Events
{ {
EVENT_SPELL_BERSERK = 1, EVENT_BERSERK = 1,
EVENT_SPELL_POISON_CLOUD = 2, EVENT_POISON_CLOUD = 2,
EVENT_SPELL_SLIME_SPRAY = 3, EVENT_SLIME_SPRAY = 3,
EVENT_SPELL_MUTATING_INJECTION = 4, EVENT_MUTATING_INJECTION = 4
}; };
enum Misc enum Misc
@@ -78,36 +80,44 @@ public:
for (std::list<Creature*>::const_iterator itr = StichedGiants.begin(); itr != StichedGiants.end(); ++itr) for (std::list<Creature*>::const_iterator itr = StichedGiants.begin(); itr != StichedGiants.end(); ++itr)
{ {
if ((*itr)->GetGUID()) if ((*itr)->GetGUID())
{
(*itr)->ToCreature()->AI()->AttackStart(me->GetVictim()); (*itr)->ToCreature()->AI()->AttackStart(me->GetVictim());
} }
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
PullChamberAdds(); PullChamberAdds();
me->SetInCombatWithZone(); me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_POISON_CLOUD, 15000); events.ScheduleEvent(EVENT_POISON_CLOUD, 15000);
events.ScheduleEvent(EVENT_SPELL_MUTATING_INJECTION, 20000); events.ScheduleEvent(EVENT_MUTATING_INJECTION, 20000);
events.ScheduleEvent(EVENT_SPELL_SLIME_SPRAY, 10000); events.ScheduleEvent(EVENT_SLIME_SPRAY, 10000);
events.ScheduleEvent(EVENT_SPELL_BERSERK, RAID_MODE(12 * MINUTE * IN_MILLISECONDS, 9 * MINUTE * IN_MILLISECONDS)); events.ScheduleEvent(EVENT_BERSERK, RAID_MODE(720000, 540000));
} }
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override
{ {
if (spellInfo->Id == RAID_MODE(SPELL_SLIME_SPRAY_10, SPELL_SLIME_SPRAY_25) && target->GetTypeId() == TYPEID_PLAYER) if (spellInfo->Id == RAID_MODE(SPELL_SLIME_SPRAY_10, SPELL_SLIME_SPRAY_25) && target->GetTypeId() == TYPEID_PLAYER)
{
me->SummonCreature(NPC_FALLOUT_SLIME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); me->SummonCreature(NPC_FALLOUT_SLIME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
} }
}
void JustSummoned(Creature* cr) override void JustSummoned(Creature* cr) override
{ {
if (cr->GetEntry() == NPC_FALLOUT_SLIME) if (cr->GetEntry() == NPC_FALLOUT_SLIME)
{
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
}
summons.Summon(cr); summons.Summon(cr);
} }
void SummonedCreatureDespawn(Creature* summon) override { summons.Despawn(summon); } void SummonedCreatureDespawn(Creature* summon) override
{
summons.Despawn(summon);
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -118,18 +128,20 @@ public:
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && pInstance) if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
// Some nice visuals
dropSludgeTimer += diff; dropSludgeTimer += diff;
if (!me->IsInCombat() && dropSludgeTimer >= 5000) if (!me->IsInCombat() && dropSludgeTimer >= 5000)
{ {
if (me->IsWithinDist3d(3178, -3305, 319, 5.0f) && !summons.HasEntry(NPC_SEWAGE_SLIME)) if (me->IsWithinDist3d(3178, -3305, 319, 5.0f) && !summons.HasEntry(NPC_SEWAGE_SLIME))
{
me->CastSpell(3128.96f + irand(-20, 20), -3312.96f + irand(-20, 20), 293.25f, SPELL_BOMBARD_SLIME, false); me->CastSpell(3128.96f + irand(-20, 20), -3312.96f + irand(-20, 20), 293.25f, SPELL_BOMBARD_SLIME, false);
}
dropSludgeTimer = 0; dropSludgeTimer = 0;
} }
@@ -142,27 +154,26 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_POISON_CLOUD: case EVENT_POISON_CLOUD:
me->CastSpell(me, SPELL_POISON_CLOUD, true); me->CastSpell(me, SPELL_POISON_CLOUD, true);
events.RepeatEvent(15000); events.RepeatEvent(15000);
break; break;
case EVENT_SPELL_BERSERK: case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
break; break;
case EVENT_SPELL_SLIME_SPRAY: case EVENT_SLIME_SPRAY:
Talk(EMOTE_SLIME); Talk(EMOTE_SLIME);
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_SLIME_SPRAY_10, SPELL_SLIME_SPRAY_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_SLIME_SPRAY_10, SPELL_SLIME_SPRAY_25), false);
events.RepeatEvent(20000); events.RepeatEvent(20000);
break; break;
case EVENT_SPELL_MUTATING_INJECTION: case EVENT_MUTATING_INJECTION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -SPELL_MUTATING_INJECTION)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -SPELL_MUTATING_INJECTION))
{
me->CastSpell(target, SPELL_MUTATING_INJECTION, false); me->CastSpell(target, SPELL_MUTATING_INJECTION, false);
}
events.RepeatEvent(8000 + uint32(120 * me->GetHealthPct())); events.RepeatEvent(6000 + uint32(120 * me->GetHealthPct()));
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -190,19 +201,20 @@ public:
sizeTimer = 0; sizeTimer = 0;
auraVisualTimer = 1; auraVisualTimer = 1;
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 2.0f); me->SetFloatValue(UNIT_FIELD_COMBATREACH, 2.0f);
me->setFaction(21); // Grobbulus one me->setFaction(21);
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript()) if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0); me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
// this has to be delayed to be visible :/ if (auraVisualTimer) // this has to be delayed to be visible
if (auraVisualTimer)
{ {
auraVisualTimer += diff; auraVisualTimer += diff;
if (auraVisualTimer >= 1000) if (auraVisualTimer >= 1000)
@@ -211,9 +223,7 @@ public:
auraVisualTimer = 0; auraVisualTimer = 0;
} }
} }
sizeTimer += diff; // increase size to 15yd in 60 seconds, 0.00025 is the growth of size in 1ms
sizeTimer += diff;
// increase size to 15yd in 60 seconds, 0.00025 is the growth of size in 1ms
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 2.0f + (0.00025f * sizeTimer)); me->SetFloatValue(UNIT_FIELD_COMBATREACH, 2.0f + (0.00025f * sizeTimer));
} }
}; };
@@ -232,13 +242,18 @@ public:
{ {
std::list<WorldObject*> tmplist; std::list<WorldObject*> tmplist;
for (auto& target : targets) for (auto& target : targets)
{
if (GetCaster()->IsWithinDist3d(target, 0.0f)) if (GetCaster()->IsWithinDist3d(target, 0.0f))
{
tmplist.push_back(target); tmplist.push_back(target);
}
}
targets.clear(); targets.clear();
for (auto& itr : tmplist) for (auto& itr : tmplist)
{
targets.push_back(itr); targets.push_back(itr);
} }
}
void Register() override void Register() override
{ {
@@ -252,9 +267,52 @@ public:
} }
}; };
class spell_grobbulus_mutating_injection : public SpellScriptLoader
{
public:
spell_grobbulus_mutating_injection() : SpellScriptLoader("spell_grobbulus_mutating_injection") { }
class spell_grobbulus_mutating_injection_AuraScript : public AuraScript
{
PrepareAuraScript(spell_grobbulus_mutating_injection_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_MUTATING_EXPLOSION });
}
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
switch (GetTargetApplication()->GetRemoveMode())
{
case AURA_REMOVE_BY_ENEMY_SPELL:
case AURA_REMOVE_BY_EXPIRE:
if (auto caster = GetCaster())
{
caster->CastSpell(GetTarget(), SPELL_MUTATING_EXPLOSION, true);
}
break;
default:
return;
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_grobbulus_mutating_injection_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_grobbulus_mutating_injection_AuraScript();
}
};
void AddSC_boss_grobbulus() void AddSC_boss_grobbulus()
{ {
new boss_grobbulus(); new boss_grobbulus();
new boss_grobbulus_poison_cloud(); new boss_grobbulus_poison_cloud();
new spell_grobbulus_mutating_injection();
new spell_grobbulus_poison(); new spell_grobbulus_poison();
} }
@@ -12,7 +12,7 @@ enum Says
SAY_AGGRO = 0, SAY_AGGRO = 0,
SAY_SLAY = 1, SAY_SLAY = 1,
SAY_TAUNT = 2, SAY_TAUNT = 2,
SAY_DEATH = 3, EMOTE_DEATH = 3,
EMOTE_DANCE = 4, EMOTE_DANCE = 4,
EMOTE_DANCE_END = 5, EMOTE_DANCE_END = 5,
SAY_DANCE = 6 SAY_DANCE = 6
@@ -24,21 +24,23 @@ enum Spells
SPELL_DECREPIT_FEVER_10 = 29998, SPELL_DECREPIT_FEVER_10 = 29998,
SPELL_DECREPIT_FEVER_25 = 55011, SPELL_DECREPIT_FEVER_25 = 55011,
SPELL_PLAGUE_CLOUD = 29350, SPELL_PLAGUE_CLOUD = 29350,
SPELL_TELEPORT_SELF = 30211
}; };
enum Events enum Events
{ {
EVENT_SPELL_SPELL_DISRUPTION = 1, EVENT_DISRUPTION = 1,
EVENT_SPELL_DECEPIT_FEVER = 2, EVENT_DECEPIT_FEVER = 2,
EVENT_ERUPT_SECTION = 3, EVENT_ERUPT_SECTION = 3,
EVENT_SWITCH_PHASE = 4, EVENT_SWITCH_PHASE = 4,
EVENT_SAFETY_DANCE = 5, EVENT_SAFETY_DANCE = 5,
EVENT_PLAGUE_CLOUD = 6
}; };
enum Misc enum Misc
{ {
PHASE_SLOW_DANCE = 0, PHASE_SLOW_DANCE = 0,
PHASE_FAST_DANCE = 1, PHASE_FAST_DANCE = 1
}; };
class boss_heigan : public CreatureScript class boss_heigan : public CreatureScript
@@ -71,13 +73,14 @@ public:
currentPhase = 0; currentPhase = 0;
currentSection = 3; currentSection = 3;
moveRight = true; moveRight = true;
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
@@ -85,15 +88,16 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(EMOTE_DEATH);
} }
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
@@ -104,9 +108,10 @@ public:
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
}
StartFightPhase(PHASE_SLOW_DANCE); StartFightPhase(PHASE_SLOW_DANCE);
} }
@@ -117,22 +122,25 @@ public:
events.Reset(); events.Reset();
if (phase == PHASE_SLOW_DANCE) if (phase == PHASE_SLOW_DANCE)
{ {
events.ScheduleEvent(EVENT_SPELL_SPELL_DISRUPTION, 0); me->CastStop();
events.ScheduleEvent(EVENT_SPELL_DECEPIT_FEVER, 12000); me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 10000); DoZoneInCombat();
events.ScheduleEvent(EVENT_DISRUPTION, urand(12000, 15000));
events.ScheduleEvent(EVENT_DECEPIT_FEVER, 17000);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 15000);
events.ScheduleEvent(EVENT_SWITCH_PHASE, 90000); events.ScheduleEvent(EVENT_SWITCH_PHASE, 90000);
} }
else // if (phase == PHASE_FAST_DANCE) else // if (phase == PHASE_FAST_DANCE)
{ {
Talk(EMOTE_DANCE); Talk(EMOTE_DANCE);
Talk(SAY_DANCE); Talk(SAY_DANCE);
// teleport me->AttackStop();
float x, y, z, o; me->StopMoving();
me->GetHomePosition(x, y, z, o); me->SetReactState(REACT_PASSIVE);
me->NearTeleportTo(x, y, z, o); me->CastSpell(me, SPELL_TELEPORT_SELF, false);
me->SetFacingTo(2.40f);
me->CastSpell(me, SPELL_PLAGUE_CLOUD, false); events.ScheduleEvent(EVENT_PLAGUE_CLOUD, 1000);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 4000); events.ScheduleEvent(EVENT_ERUPT_SECTION, 7000);
events.ScheduleEvent(EVENT_SWITCH_PHASE, 45000); events.ScheduleEvent(EVENT_SWITCH_PHASE, 45000);
} }
events.ScheduleEvent(EVENT_SAFETY_DANCE, 5000); events.ScheduleEvent(EVENT_SAFETY_DANCE, 5000);
@@ -144,9 +152,9 @@ public:
{ {
if (who->GetGUID() == me->GetGUID()) if (who->GetGUID() == me->GetGUID())
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -159,18 +167,19 @@ public:
return; return;
events.Update(diff); events.Update(diff);
//if (me->HasUnitState(UNIT_STATE_CASTING))
// return;
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_SPELL_DISRUPTION: case EVENT_DISRUPTION:
me->CastSpell(me, SPELL_SPELL_DISRUPTION, false); me->CastSpell(me, SPELL_SPELL_DISRUPTION, false);
events.RepeatEvent(10000); events.RepeatEvent(10000);
break; break;
case EVENT_SPELL_DECEPIT_FEVER: case EVENT_DECEPIT_FEVER:
me->CastSpell(me, RAID_MODE(SPELL_DECREPIT_FEVER_10, SPELL_DECREPIT_FEVER_25), false); me->CastSpell(me, RAID_MODE(SPELL_DECREPIT_FEVER_10, SPELL_DECREPIT_FEVER_25), false);
events.RepeatEvent(20000); events.RepeatEvent(urand(22000, 25000));
break;
case EVENT_PLAGUE_CLOUD:
me->CastSpell(me, SPELL_PLAGUE_CLOUD, false);
break; break;
case EVENT_SWITCH_PHASE: case EVENT_SWITCH_PHASE:
if (currentPhase == PHASE_SLOW_DANCE) if (currentPhase == PHASE_SLOW_DANCE)
@@ -180,25 +189,27 @@ public:
else else
{ {
StartFightPhase(PHASE_SLOW_DANCE); StartFightPhase(PHASE_SLOW_DANCE);
Talk(EMOTE_DANCE_END); // we put this here to avoid play the emote on aggro. Talk(EMOTE_DANCE_END); // avoid play the emote on aggro
} }
// no pop, there is reset in start fight
break; break;
case EVENT_ERUPT_SECTION: case EVENT_ERUPT_SECTION:
if (pInstance) if (pInstance)
{ {
pInstance->SetData(DATA_HEIGAN_ERUPTION, currentSection); pInstance->SetData(DATA_HEIGAN_ERUPTION, currentSection);
if (currentSection == 3) if (currentSection == 3)
{
moveRight = false; moveRight = false;
}
else if (currentSection == 0) else if (currentSection == 0)
{
moveRight = true; moveRight = true;
}
moveRight ? currentSection++ : currentSection--; moveRight ? currentSection++ : currentSection--;
} }
if (currentPhase == PHASE_SLOW_DANCE) if (currentPhase == PHASE_SLOW_DANCE)
{
Talk(SAY_TAUNT); Talk(SAY_TAUNT);
}
events.RepeatEvent(currentPhase == PHASE_SLOW_DANCE ? 10000 : 4000); events.RepeatEvent(currentPhase == PHASE_SLOW_DANCE ? 10000 : 4000);
break; break;
case EVENT_SAFETY_DANCE: case EVENT_SAFETY_DANCE:
@@ -217,7 +228,6 @@ public:
return; return;
} }
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -10,15 +10,16 @@
enum Yells enum Yells
{ {
SAY_ANSWER_REQUEST = 3,
SAY_TAUNT = 6, SAY_TAUNT = 6,
SAY_AGGRO = 7, SAY_AGGRO = 7,
SAY_SLAY = 8, SAY_SLAY = 8,
SAY_DEATH = 9, SAY_DEATH = 9,
SAY_CHAIN = 10, SAY_CHAIN = 10,
SAY_FROST_BLAST = 11, SAY_FROST_BLAST = 11,
SAY_REQUEST_AID = 12, //start of phase 3 SAY_REQUEST_AID = 12,
SAY_ANSWER_REQUEST = 3, //lich king answer EMOTE_PHASE_TWO = 13,
SAY_SUMMON_MINIONS = 14, //start of phase 1 SAY_SUMMON_MINIONS = 14,
SAY_SPECIAL = 15, SAY_SPECIAL = 15,
EMOTE_GUARDIAN_FLEE = 0, EMOTE_GUARDIAN_FLEE = 0,
@@ -27,6 +28,7 @@ enum Yells
enum Spells enum Spells
{ {
// Kel'Thzuad
SPELL_FROST_BOLT_SINGLE_10 = 28478, SPELL_FROST_BOLT_SINGLE_10 = 28478,
SPELL_FROST_BOLT_SINGLE_25 = 55802, SPELL_FROST_BOLT_SINGLE_25 = 55802,
SPELL_FROST_BOLT_MULTI_10 = 28479, SPELL_FROST_BOLT_MULTI_10 = 28479,
@@ -38,11 +40,12 @@ enum Spells
SPELL_FROST_BLAST = 27808, SPELL_FROST_BLAST = 27808,
SPELL_CHAINS_OF_KELTHUZAD = 28410, // 28408 script effect SPELL_CHAINS_OF_KELTHUZAD = 28410, // 28408 script effect
SPELL_BERSERK = 28498, SPELL_BERSERK = 28498,
SPELL_KELTHUZAD_CHANNEL = 29423,
// Minions // Minions
SPELL_FRENZY = 28468, SPELL_FRENZY = 28468,
SPELL_MORTAL_WOUND = 28467, SPELL_MORTAL_WOUND = 28467,
SPELL_BLOOD_TAP = 28470, SPELL_BLOOD_TAP = 28470
}; };
enum Misc enum Misc
@@ -55,6 +58,7 @@ enum Misc
ACTION_CALL_HELP_ON = 1, ACTION_CALL_HELP_ON = 1,
ACTION_CALL_HELP_OFF = 2, ACTION_CALL_HELP_OFF = 2,
ACTION_SECOND_PHASE = 3, ACTION_SECOND_PHASE = 3,
ACTION_GUARDIANS_OFF = 4
}; };
enum Event enum Event
@@ -63,25 +67,27 @@ enum Event
EVENT_SUMMON_SOLDIER = 1, EVENT_SUMMON_SOLDIER = 1,
EVENT_SUMMON_UNSTOPPABLE_ABOMINATION = 2, EVENT_SUMMON_UNSTOPPABLE_ABOMINATION = 2,
EVENT_SUMMON_SOUL_WEAVER = 3, EVENT_SUMMON_SOUL_WEAVER = 3,
EVENT_START_SECOND_PHASE = 4, EVENT_PHASE_2 = 4,
EVENT_SPELL_FROST_BOLT_SINGLE = 5, EVENT_FROST_BOLT_SINGLE = 5,
EVENT_SPELL_FROST_BOLT_MULTI = 6, EVENT_FROST_BOLT_MULTI = 6,
EVENT_SPELL_DETONATE_MANA = 7, EVENT_DETONATE_MANA = 7,
EVENT_SECOND_PHASE_HEALTH_CHECK = 8, EVENT_PHASE_3 = 8,
EVENT_THIRD_PHASE_LICH_KING_SAY = 9, EVENT_P3_LICH_KING_SAY = 9,
EVENT_SPELL_SHADOW_FISSURE = 10, EVENT_SHADOW_FISSURE = 10,
EVENT_SPELL_FROST_BLAST = 11, EVENT_FROST_BLAST = 11,
EVENT_SPELL_CHAINS = 12, EVENT_CHAINS = 12,
EVENT_SUMMON_GUARDIAN_OF_ICECROWN = 13, EVENT_SUMMON_GUARDIAN_OF_ICECROWN = 13,
EVENT_FLOOR_CHANGE = 14, EVENT_FLOOR_CHANGE = 14,
EVENT_ENRAGE = 15,
EVENT_SPAWN_POOL = 16,
// Minions // Minions
EVENT_MINION_SPELL_FRENZY = 100, EVENT_MINION_FRENZY = 17,
EVENT_MINION_SPELL_MORTAL_WOUND = 101, EVENT_MINION_MORTAL_WOUND = 18,
EVENT_MINION_SPELL_BLOOD_TAP = 102, EVENT_MINION_BLOOD_TAP = 19
}; };
const Position SummonPositions[12] = const Position SummonGroups[12] =
{ {
// Portals // Portals
{3783.272705f, -5062.697266f, 143.711203f, 3.617599f}, // LEFT_FAR {3783.272705f, -5062.697266f, 143.711203f, 3.617599f}, // LEFT_FAR
@@ -91,14 +97,6 @@ const Position SummonPositions[12] =
{3700.724365f, -5185.123047f, 143.928024f, 1.309310f}, // RIGHT_MIDDLE {3700.724365f, -5185.123047f, 143.928024f, 1.309310f}, // RIGHT_MIDDLE
{3665.121094f, -5138.679199f, 143.183212f, 0.604023f}, // RIGHT_NEAR {3665.121094f, -5138.679199f, 143.183212f, 0.604023f}, // RIGHT_NEAR
// Edges
//{3754.431396f, -5080.727734f, 142.036316f, 3.736189f}, //LEFT_FAR
// {3724.396484f, -5061.330566f, 142.032700f, 4.564785f}, //LEFT_MIDDLE
//{3687.158424f, -5076.834473f, 142.017319f, 5.237086f}, //LEFT_NEAR
//{3687.571777f, -5126.831055f, 142.017807f, 0.604023f}, //RIGHT_FAR
//{3707.990733f, -5151.450195f, 142.032562f, 1.376855f}, //RIGHT_MIDDLE
// {3739.500000f, -5141.883989f, 142.014113f, 2.121412f} //RIGHT_NEAR
// Middle // Middle
{3769.34f, -5071.80f, 143.2082f, 3.658f}, {3769.34f, -5071.80f, 143.2082f, 3.658f},
{3729.78f, -5043.56f, 143.3867f, 4.475f}, {3729.78f, -5043.56f, 143.3867f, 4.475f},
@@ -108,6 +106,18 @@ const Position SummonPositions[12] =
{3665.30f, -5141.55f, 143.1846f, 0.566f} {3665.30f, -5141.55f, 143.1846f, 0.566f}
}; };
const Position SpawnPool[7] =
{
// Portals
{3783.272705f, -5062.697266f, 143.711203f, 3.617599f}, // LEFT_FAR
{3730.291260f, -5027.239258f, 143.956909f, 4.461900f}, // LEFT_MIDDLE
{3683.868652f, -5057.281250f, 143.183884f, 5.237086f}, // LEFT_NEAR
{3759.355225f, -5174.128418f, 143.802383f, 2.170104f}, // RIGHT_FAR
{3700.724365f, -5185.123047f, 143.928024f, 1.309310f}, // RIGHT_MIDDLE
{3665.121094f, -5138.679199f, 143.183212f, 0.604023f}, // RIGHT_NEAR
{3651.729980f, -5092.620117f, 143.380005f, 6.050000f} // GATE
};
class boss_kelthuzad : public CreatureScript class boss_kelthuzad : public CreatureScript
{ {
public: public:
@@ -133,33 +143,63 @@ public:
float NormalizeOrientation(float o) float NormalizeOrientation(float o)
{ {
// Only positive values will be passed return fmod(o, 2.0f * static_cast<float>(M_PI)); // Only positive values will be passed
return fmod(o, 2.0f * static_cast<float>(M_PI));
} }
void SpawnHelpers() void SpawnHelpers()
{ {
// Ehhh... // spawn at gate
// in short: 6 rooms, 8 soldiers, 3 abominations and 1 weaver in each room me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, 3656.19f, -5093.78f, 143.33f, 6.08, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);// abo center
// middle positions in table starts from 6 me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, 3657.94f, -5087.68f, 143.60f, 6.08, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);// abo left
me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, 3655.48f, -5100.05f, 143.53f, 6.08, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);// abo right
me->SummonCreature(NPC_SOUL_WEAVER, 3651.73f, -5092.62f, 143.38f, 6.05, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // soul behind
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3660.17f, -5092.45f, 143.37f, 6.07, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske front left
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3659.39f, -5096.21f, 143.29f, 6.07, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske front right
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3659.29f, -5090.19f, 143.48f, 6.07, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske left left
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3657.43f, -5098.03f, 143.41f, 6.07, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske right right
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3654.36f, -5090.51f, 143.48f, 6.09, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske behind left
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 3653.35f, -5095.91f, 143.41f, 6.09, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); // ske right right
// 6 rooms, 8 soldiers, 3 abominations and 1 weaver in each room | middle positions in table starts from 6
for (uint8 i = 6; i < 12; ++i) for (uint8 i = 6; i < 12; ++i)
{
for (uint8 j = 0; j < 8; ++j) for (uint8 j = 0; j < 8; ++j)
{ {
float angle = M_PI * 2 / 8 * j; float angle = M_PI * 2 / 8 * j;
me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, SummonPositions[i].GetPositionX() + 6 * cos(angle), SummonPositions[i].GetPositionY() + 6 * sin(angle), SummonPositions[i].GetPositionZ(), SummonPositions[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, SummonGroups[i].GetPositionX() + 6 * cos(angle), SummonGroups[i].GetPositionY() + 6 * sin(angle), SummonGroups[i].GetPositionZ(), SummonGroups[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
}
} }
for (uint8 i = 6; i < 12; ++i) for (uint8 i = 6; i < 12; ++i)
{
for (uint8 j = 1; j < 4; ++j) for (uint8 j = 1; j < 4; ++j)
{ {
float dist = j == 2 ? 0.0f : 8.0f; // second in middle float dist = j == 2 ? 0.0f : 8.0f; // second in middle
float angle = SummonPositions[i].GetOrientation() + M_PI * 2 / 4 * j; float angle = SummonGroups[i].GetOrientation() + M_PI * 2 / 4 * j;
me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, SummonPositions[i].GetPositionX() + dist * cos(angle), SummonPositions[i].GetPositionY() + dist * sin(angle), SummonPositions[i].GetPositionZ(), SummonPositions[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, SummonGroups[i].GetPositionX() + dist * cos(angle), SummonGroups[i].GetPositionY() + dist * sin(angle), SummonGroups[i].GetPositionZ(), SummonGroups[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
}
} }
for (uint8 i = 6; i < 12; ++i) for (uint8 i = 6; i < 12; ++i)
{
for (uint8 j = 0; j < 1; ++j) for (uint8 j = 0; j < 1; ++j)
{ {
float angle = SummonPositions[i].GetOrientation() + M_PI; float angle = SummonGroups[i].GetOrientation() + M_PI;
me->SummonCreature(NPC_SOUL_WEAVER, SummonPositions[i].GetPositionX() + 6 * cos(angle), SummonPositions[i].GetPositionY() + 6 * sin(angle), SummonPositions[i].GetPositionZ() + 0.5f, SummonPositions[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); me->SummonCreature(NPC_SOUL_WEAVER, SummonGroups[i].GetPositionX() + 6 * cos(angle), SummonGroups[i].GetPositionY() + 6 * sin(angle), SummonGroups[i].GetPositionZ() + 0.5f, SummonGroups[i].GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
}
}
}
void SummonHelper(uint32 entry, uint32 count)
{
for (uint8 i = 0; i < count; ++i)
{
if (Creature* cr = me->SummonCreature(entry, SpawnPool[urand(0, 6)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
{
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
} }
} }
@@ -170,19 +210,35 @@ public:
summons.DespawnAll(); summons.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR)))
{ {
go->SetPhaseMask(1, true); go->SetPhaseMask(1, true);
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE)))
{ {
if(!_justSpawned) /* Don't open the door if we just spawned and are still doing the RP */ if(!_justSpawned) // Don't open the door if we just spawned and are still doing the conversation
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
}
_justSpawned = false; _justSpawned = false;
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_1)))
{
go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_2)))
{
go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_3)))
{
go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_4)))
{
go->SetGoState(GO_STATE_READY);
}
} }
void EnterEvadeMode() override void EnterEvadeMode() override
@@ -197,27 +253,29 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
summons.DoAction(ACTION_GUARDIANS_OFF);
if (Creature* guardian = summons.GetCreatureWithEntry(NPC_GUARDIAN_OF_ICECROWN)) if (Creature* guardian = summons.GetCreatureWithEntry(NPC_GUARDIAN_OF_ICECROWN))
{ {
guardian->AI()->Talk(EMOTE_GUARDIAN_FLEE); guardian->AI()->Talk(EMOTE_GUARDIAN_FLEE);
} }
summons.DespawnAll();
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
@@ -233,14 +291,13 @@ public:
me->RemoveAllAttackers(); me->RemoveAllAttackers();
me->SetTarget(0); me->SetTarget(0);
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
me->CastSpell(me, SPELL_KELTHUZAD_CHANNEL, false);
// Spawn helpers events.ScheduleEvent(EVENT_SPAWN_POOL, 5000);
SpawnHelpers(); events.ScheduleEvent(EVENT_SUMMON_SOLDIER, 6400);
events.ScheduleEvent(EVENT_SUMMON_SOLDIER, 3200);
events.ScheduleEvent(EVENT_SUMMON_UNSTOPPABLE_ABOMINATION, 10000); events.ScheduleEvent(EVENT_SUMMON_UNSTOPPABLE_ABOMINATION, 10000);
events.ScheduleEvent(EVENT_SUMMON_SOUL_WEAVER, 24000); events.ScheduleEvent(EVENT_SUMMON_SOUL_WEAVER, 12000);
events.ScheduleEvent(EVENT_START_SECOND_PHASE, 228000); events.ScheduleEvent(EVENT_PHASE_2, 228000);
events.ScheduleEvent(EVENT_ENRAGE, 900000);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR)))
@@ -250,10 +307,23 @@ public:
} }
} }
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
}
void JustSummoned(Creature* cr) override { summons.Summon(cr); } void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
if (!cr->IsInCombat())
{
cr->GetMotionMaster()->MoveRandom(5);
}
if (cr->GetEntry() == NPC_GUARDIAN_OF_ICECROWN)
{
cr->SetHomePosition(cr->GetPositionX(), cr->GetPositionY(), cr->GetPositionZ(), cr->GetOrientation());
}
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -261,8 +331,11 @@ public:
return; return;
events.Update(diff); events.Update(diff);
if (!me->HasAura(SPELL_KELTHUZAD_CHANNEL))
{
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
return; return;
}
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
@@ -276,90 +349,80 @@ public:
go->SetPhaseMask(2, true); go->SetPhaseMask(2, true);
} }
} }
break;
case EVENT_SPAWN_POOL:
SpawnHelpers();
break; break;
case EVENT_SUMMON_SOLDIER: case EVENT_SUMMON_SOLDIER:
if (Creature* cr = me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000)) SummonHelper(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 1);
{ events.RepeatEvent(3100);
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
events.RepeatEvent(3200);
break; break;
case EVENT_SUMMON_UNSTOPPABLE_ABOMINATION: case EVENT_SUMMON_UNSTOPPABLE_ABOMINATION:
if (Creature* cr = me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000)) SummonHelper(NPC_UNSTOPPABLE_ABOMINATION, 1);
{ events.RepeatEvent(18500);
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
events.RepeatEvent(30000);
break; break;
case EVENT_SUMMON_SOUL_WEAVER: case EVENT_SUMMON_SOUL_WEAVER:
if (Creature* cr = me->SummonCreature(NPC_SOUL_WEAVER, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000)) SummonHelper(NPC_SOUL_WEAVER, 1);
{
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
events.RepeatEvent(30000); events.RepeatEvent(30000);
break; break;
case EVENT_START_SECOND_PHASE: case EVENT_PHASE_2:
// same as pop Talk(EMOTE_PHASE_TWO);
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
events.Reset(); events.Reset();
summons.DoAction(ACTION_SECOND_PHASE); summons.DoAction(ACTION_SECOND_PHASE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
me->GetMotionMaster()->MoveChase(me->GetVictim()); me->GetMotionMaster()->MoveChase(me->GetVictim());
me->RemoveAura(SPELL_KELTHUZAD_CHANNEL);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_SPELL_FROST_BOLT_SINGLE, 2000); events.ScheduleEvent(EVENT_FROST_BOLT_SINGLE, urand(2000, 10000));
events.ScheduleEvent(EVENT_SPELL_FROST_BOLT_MULTI, 15000); events.ScheduleEvent(EVENT_FROST_BOLT_MULTI, urand(15000, 30000));
events.ScheduleEvent(EVENT_SPELL_DETONATE_MANA, 20000); events.ScheduleEvent(EVENT_DETONATE_MANA, 30000);
events.ScheduleEvent(EVENT_SECOND_PHASE_HEALTH_CHECK, 1000); events.ScheduleEvent(EVENT_PHASE_3, 1000);
events.ScheduleEvent(EVENT_SPELL_SHADOW_FISSURE, 25000); events.ScheduleEvent(EVENT_SHADOW_FISSURE, 25000);
events.ScheduleEvent(EVENT_SPELL_FROST_BLAST, 45000); events.ScheduleEvent(EVENT_FROST_BLAST, 45000);
if (Is25ManRaid()) if (Is25ManRaid())
events.ScheduleEvent(EVENT_SPELL_CHAINS, 50000); {
events.ScheduleEvent(EVENT_CHAINS, 90000);
}
break; break;
case EVENT_SPELL_FROST_BOLT_SINGLE: case EVENT_ENRAGE:
me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_FROST_BOLT_SINGLE:
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_FROST_BOLT_SINGLE_10, SPELL_FROST_BOLT_SINGLE_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_FROST_BOLT_SINGLE_10, SPELL_FROST_BOLT_SINGLE_25), false);
events.RepeatEvent(urand(2000, 15000)); events.RepeatEvent(urand(2000, 10000));
break; break;
case EVENT_SPELL_FROST_BOLT_MULTI: case EVENT_FROST_BOLT_MULTI:
me->CastSpell(me, RAID_MODE(SPELL_FROST_BOLT_MULTI_10, SPELL_FROST_BOLT_MULTI_25), false); me->CastSpell(me, RAID_MODE(SPELL_FROST_BOLT_MULTI_10, SPELL_FROST_BOLT_MULTI_25), false);
events.RepeatEvent(24000); events.RepeatEvent(urand(15000, 30000));
break; break;
case EVENT_SPELL_SHADOW_FISSURE: case EVENT_SHADOW_FISSURE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
{
me->CastSpell(target, SPELL_SHADOW_FISURE, false); me->CastSpell(target, SPELL_SHADOW_FISURE, false);
}
events.RepeatEvent(25000); events.RepeatEvent(25000);
break; break;
case EVENT_SPELL_FROST_BLAST: case EVENT_FROST_BLAST:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
{
me->CastSpell(target, SPELL_FROST_BLAST, false); me->CastSpell(target, SPELL_FROST_BLAST, false);
}
Talk(SAY_FROST_BLAST); Talk(SAY_FROST_BLAST);
events.RepeatEvent(45000); events.RepeatEvent(45000);
break; break;
case EVENT_SPELL_CHAINS: case EVENT_CHAINS:
for (uint8 i = 0; i < 3; ++i) for (uint8 i = 0; i < 3; ++i)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true, -SPELL_CHAINS_OF_KELTHUZAD)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true, -SPELL_CHAINS_OF_KELTHUZAD))
{
me->CastSpell(target, SPELL_CHAINS_OF_KELTHUZAD, true); me->CastSpell(target, SPELL_CHAINS_OF_KELTHUZAD, true);
}
}
Talk(SAY_CHAIN); Talk(SAY_CHAIN);
events.RepeatEvent(50000); events.RepeatEvent(90000);
break; break;
case EVENT_SPELL_DETONATE_MANA: case EVENT_DETONATE_MANA:
{ {
std::vector<Unit*> unitList; std::vector<Unit*> unitList;
ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList(); ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
@@ -368,9 +431,10 @@ public:
if (itr->getTarget()->GetTypeId() == TYPEID_PLAYER if (itr->getTarget()->GetTypeId() == TYPEID_PLAYER
&& itr->getTarget()->getPowerType() == POWER_MANA && itr->getTarget()->getPowerType() == POWER_MANA
&& itr->getTarget()->GetPower(POWER_MANA)) && itr->getTarget()->GetPower(POWER_MANA))
{
unitList.push_back(itr->getTarget()); unitList.push_back(itr->getTarget());
} }
}
if (!unitList.empty()) if (!unitList.empty())
{ {
auto itr = unitList.begin(); auto itr = unitList.begin();
@@ -378,39 +442,56 @@ public:
me->CastSpell(*itr, SPELL_DETONATE_MANA, false); me->CastSpell(*itr, SPELL_DETONATE_MANA, false);
Talk(SAY_SPECIAL); Talk(SAY_SPECIAL);
} }
events.RepeatEvent(30000); events.RepeatEvent(30000);
break; break;
} }
case EVENT_SECOND_PHASE_HEALTH_CHECK: case EVENT_PHASE_3:
if (me->HealthBelowPct(45)) if (me->HealthBelowPct(45))
{ {
Talk(SAY_REQUEST_AID); Talk(SAY_REQUEST_AID);
events.DelayEvents(5500); events.DelayEvents(5500);
events.ScheduleEvent(EVENT_THIRD_PHASE_LICH_KING_SAY, 5000); events.ScheduleEvent(EVENT_P3_LICH_KING_SAY, 5000);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_1)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_2)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_3)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_PORTAL_4)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
} }
events.RepeatEvent(1000); events.RepeatEvent(1000);
break; break;
case EVENT_THIRD_PHASE_LICH_KING_SAY: case EVENT_P3_LICH_KING_SAY:
if (pInstance) if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_LICH_KING_BOSS))) if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_LICH_KING_BOSS)))
{
cr->AI()->Talk(SAY_ANSWER_REQUEST); cr->AI()->Talk(SAY_ANSWER_REQUEST);
}
}
for (uint8 i = 0 ; i < RAID_MODE(2, 4); ++i) for (uint8 i = 0 ; i < RAID_MODE(2, 4); ++i)
{
events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_ICECROWN, 10000 + (i * 5000)); events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_ICECROWN, 10000 + (i * 5000));
}
break; break;
case EVENT_SUMMON_GUARDIAN_OF_ICECROWN: case EVENT_SUMMON_GUARDIAN_OF_ICECROWN:
if (Creature* cr = me->SummonCreature(NPC_GUARDIAN_OF_ICECROWN, SummonPositions[RAND(0, 1, 3, 4)])) if (Creature* cr = me->SummonCreature(NPC_GUARDIAN_OF_ICECROWN, SpawnPool[RAND(0, 1, 3, 4)]))
{ {
cr->AI()->Talk(EMOTE_GUARDIAN_APPEAR); cr->AI()->Talk(EMOTE_GUARDIAN_APPEAR);
cr->AI()->AttackStart(me->GetVictim()); cr->AI()->AttackStart(me->GetVictim());
} }
break; break;
} }
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
@@ -444,15 +525,29 @@ public:
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
if (param == ACTION_CALL_HELP_ON) if (param == ACTION_CALL_HELP_ON)
{
callHelp = true; callHelp = true;
}
else if (param == ACTION_CALL_HELP_OFF) else if (param == ACTION_CALL_HELP_OFF)
{
callHelp = false; callHelp = false;
}
else if (param == ACTION_SECOND_PHASE) else if (param == ACTION_SECOND_PHASE)
{ {
if (!me->IsInCombat()) if (!me->IsInCombat())
{
me->DespawnOrUnsummon(500); me->DespawnOrUnsummon(500);
} }
} }
if (param == ACTION_GUARDIANS_OFF)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAllAuras();
EnterEvadeMode();
me->SetPosition(me->GetHomePosition());
}
}
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
@@ -465,8 +560,10 @@ public:
void JustDied(Unit* ) override void JustDied(Unit* ) override
{ {
if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION && me->GetInstanceScript()) if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_ABOMINATION_KILLED, 0); me->GetInstanceScript()->SetData(DATA_ABOMINATION_KILLED, 0);
} }
}
void AttackStart(Unit* who) override void AttackStart(Unit* who) override
{ {
@@ -486,26 +583,40 @@ public:
} }
if (me->GetEntry() != NPC_UNSTOPPABLE_ABOMINATION && me->GetEntry() != NPC_GUARDIAN_OF_ICECROWN) if (me->GetEntry() != NPC_UNSTOPPABLE_ABOMINATION && me->GetEntry() != NPC_GUARDIAN_OF_ICECROWN)
{
me->AddThreat(who, 1000000.0f); me->AddThreat(who, 1000000.0f);
} }
}
void EnterCombat(Unit* /*who*/) override void EnterCombat(Unit* /*who*/) override
{ {
me->SetInCombatWithZone(); me->SetInCombatWithZone();
if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION) if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION)
{ {
events.ScheduleEvent(EVENT_MINION_SPELL_FRENZY, 1000); events.ScheduleEvent(EVENT_MINION_FRENZY, 1000);
events.ScheduleEvent(EVENT_MINION_SPELL_MORTAL_WOUND, 5000); events.ScheduleEvent(EVENT_MINION_MORTAL_WOUND, 5000);
} }
else if (me->GetEntry() == NPC_GUARDIAN_OF_ICECROWN) else if (me->GetEntry() == NPC_GUARDIAN_OF_ICECROWN)
events.ScheduleEvent(EVENT_MINION_SPELL_BLOOD_TAP, 15000); {
events.ScheduleEvent(EVENT_MINION_BLOOD_TAP, 15000);
}
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript()) if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0); me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustReachedHome() override
{
if (me->GetEntry() == NPC_GUARDIAN_OF_ICECROWN)
{
me->DespawnOrUnsummon();
}
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -518,25 +629,23 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_MINION_SPELL_MORTAL_WOUND: case EVENT_MINION_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false); me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
break; break;
case EVENT_MINION_SPELL_FRENZY: case EVENT_MINION_FRENZY:
if (me->HealthBelowPct(35)) if (me->HealthBelowPct(35))
{ {
me->CastSpell(me, SPELL_FRENZY, true); me->CastSpell(me, SPELL_FRENZY, true);
break; break;
} }
events.RepeatEvent(1000); events.RepeatEvent(1000);
break; break;
case EVENT_MINION_SPELL_BLOOD_TAP: case EVENT_MINION_BLOOD_TAP:
me->CastSpell(me->GetVictim(), SPELL_BLOOD_TAP, false); me->CastSpell(me->GetVictim(), SPELL_BLOOD_TAP, false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -559,13 +668,18 @@ public:
std::list<WorldObject*> tmplist; std::list<WorldObject*> tmplist;
for (auto& target : targets) for (auto& target : targets)
{
if (!target->ToUnit()->HasAura(SPELL_FROST_BLAST)) if (!target->ToUnit()->HasAura(SPELL_FROST_BLAST))
{
tmplist.push_back(target); tmplist.push_back(target);
}
}
targets.clear(); targets.clear();
for (auto& itr : tmplist) for (auto& itr : tmplist)
{
targets.push_back(itr); targets.push_back(itr);
} }
}
void Register() override void Register() override
{ {
@@ -596,7 +710,6 @@ public:
void HandleScript(AuraEffect const* aurEff) void HandleScript(AuraEffect const* aurEff)
{ {
PreventDefaultAction(); PreventDefaultAction();
Unit* target = GetTarget(); Unit* target = GetTarget();
if (auto mana = int32(target->GetMaxPower(POWER_MANA) / 10)) if (auto mana = int32(target->GetMaxPower(POWER_MANA) / 10))
{ {
@@ -14,23 +14,25 @@ enum Spells
SPELL_DEATHBLOOM_25 = 55053, SPELL_DEATHBLOOM_25 = 55053,
SPELL_INEVITABLE_DOOM_10 = 29204, SPELL_INEVITABLE_DOOM_10 = 29204,
SPELL_INEVITABLE_DOOM_25 = 55052, SPELL_INEVITABLE_DOOM_25 = 55052,
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662
}; };
enum Events enum Events
{ {
EVENT_SPELL_NECROTIC_AURA = 1, EVENT_NECROTIC_AURA = 1,
EVENT_SPELL_DEATHBLOOM = 2, EVENT_DEATHBLOOM = 2,
EVENT_SPELL_INEVITABLE_DOOM = 3, EVENT_INEVITABLE_DOOM = 3,
EVENT_SPELL_BERSERK = 4, EVENT_BERSERK = 4,
EVENT_SUMMON_SPORE = 5, EVENT_SUMMON_SPORE = 5,
EVENT_NECROTIC_AURA_FADING = 6,
EVENT_NECROTIC_AURA_REMOVED = 7
}; };
enum Texts enum Texts
{ {
SAY_NECROTIC_AURA_APPLIED = 0, SAY_NECROTIC_AURA_APPLIED = 0,
SAY_NECROTIC_AURA_REMOVED = 1, SAY_NECROTIC_AURA_REMOVED = 1,
SAY_NECROTIC_AURA_FADING = 2, SAY_NECROTIC_AURA_FADING = 2
}; };
class boss_loatheb : public CreatureScript class boss_loatheb : public CreatureScript
@@ -52,6 +54,7 @@ public:
} }
InstanceScript* pInstance; InstanceScript* pInstance;
uint8 doomCounter;
EventMap events; EventMap events;
SummonList summons; SummonList summons;
@@ -60,13 +63,16 @@ public:
BossAI::Reset(); BossAI::Reset();
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
doomCounter = 0;
if (pInstance) if (pInstance)
{ {
pInstance->SetData(BOSS_LOATHEB, NOT_STARTED); pInstance->SetData(BOSS_LOATHEB, NOT_STARTED);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void JustSummoned(Creature* cr) override void JustSummoned(Creature* cr) override
{ {
@@ -77,38 +83,46 @@ public:
void SummonedCreatureDies(Creature* /*cr*/, Unit*) override void SummonedCreatureDies(Creature* /*cr*/, Unit*) override
{ {
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_SPORE_KILLED, 0); pInstance->SetData(DATA_SPORE_KILLED, 0);
} }
}
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && pInstance) if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_NECROTIC_AURA, 10000);
events.ScheduleEvent(EVENT_DEATHBLOOM, 5000);
events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 120000);
events.ScheduleEvent(EVENT_SUMMON_SPORE, 15000);
events.ScheduleEvent(EVENT_BERSERK, 720000);
if (pInstance) if (pInstance)
{ {
pInstance->SetData(BOSS_LOATHEB, IN_PROGRESS); pInstance->SetData(BOSS_LOATHEB, IN_PROGRESS);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
}
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_NECROTIC_AURA, 10000);
events.ScheduleEvent(EVENT_SPELL_DEATHBLOOM, 6000);
events.ScheduleEvent(EVENT_SUMMON_SPORE, 12000);
events.ScheduleEvent(EVENT_SPELL_BERSERK, 720000);
} }
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
if (pInstance)
pInstance->SetData(BOSS_LOATHEB, DONE);
summons.DespawnAll(); summons.DespawnAll();
if (pInstance)
{
pInstance->SetData(BOSS_LOATHEB, DONE);
}
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -126,24 +140,39 @@ public:
me->CastSpell(me, SPELL_SUMMON_SPORE, true); me->CastSpell(me, SPELL_SUMMON_SPORE, true);
events.RepeatEvent(35000); events.RepeatEvent(35000);
break; break;
case EVENT_SPELL_NECROTIC_AURA: case EVENT_NECROTIC_AURA:
me->CastSpell(me, SPELL_NECROTIC_AURA, true); me->CastSpell(me, SPELL_NECROTIC_AURA, true);
Talk(SAY_NECROTIC_AURA_APPLIED);
events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14000);
events.ScheduleEvent(EVENT_NECROTIC_AURA_REMOVED, 17000);
events.RepeatEvent(20000); events.RepeatEvent(20000);
break; break;
case EVENT_SPELL_DEATHBLOOM: case EVENT_DEATHBLOOM:
me->CastSpell(me, RAID_MODE(SPELL_DEATHBLOOM_10, SPELL_DEATHBLOOM_25), false); me->CastSpell(me, RAID_MODE(SPELL_DEATHBLOOM_10, SPELL_DEATHBLOOM_25), false);
events.RepeatEvent(30000); events.RepeatEvent(30000);
break; break;
case EVENT_SPELL_INEVITABLE_DOOM: case EVENT_INEVITABLE_DOOM:
me->CastSpell(me, RAID_MODE(SPELL_INEVITABLE_DOOM_10, SPELL_INEVITABLE_DOOM_25), false); me->CastSpell(me, RAID_MODE(SPELL_INEVITABLE_DOOM_10, SPELL_INEVITABLE_DOOM_25), false);
events.RepeatEvent(events.GetTimer() < 5 * MINUTE * IN_MILLISECONDS ? 30000 : 15000); doomCounter++;
if (doomCounter < 6)
{
events.RepeatEvent(30000);
}
else
{
events.RepeatEvent(15000);
}
break; break;
case EVENT_SPELL_BERSERK: case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_NECROTIC_AURA_FADING:
Talk(SAY_NECROTIC_AURA_FADING);
break;
case EVENT_NECROTIC_AURA_REMOVED:
Talk(SAY_NECROTIC_AURA_REMOVED);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
@@ -162,44 +191,7 @@ public:
}; };
}; };
class spell_loatheb_necrotic_aura_warning : public SpellScriptLoader
{
public:
spell_loatheb_necrotic_aura_warning() : SpellScriptLoader("spell_loatheb_necrotic_aura_warning") { }
class spell_loatheb_necrotic_aura_warning_AuraScript : public AuraScript
{
PrepareAuraScript(spell_loatheb_necrotic_aura_warning_AuraScript);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Creature* target = GetTarget()->ToCreature();
if (target->IsAIEnabled)
target->AI()->Talk(SAY_NECROTIC_AURA_APPLIED);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Creature* target = GetTarget()->ToCreature();
if (target->IsAIEnabled)
target->AI()->Talk(SAY_NECROTIC_AURA_REMOVED);
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_loatheb_necrotic_aura_warning_AuraScript();
}
};
void AddSC_boss_loatheb() void AddSC_boss_loatheb()
{ {
new boss_loatheb(); new boss_loatheb();
new spell_loatheb_necrotic_aura_warning();
} }
@@ -17,17 +17,17 @@ enum Spells
SPELL_NECROTIC_POISON_10 = 54121, SPELL_NECROTIC_POISON_10 = 54121,
SPELL_NECROTIC_POISON_25 = 28776, SPELL_NECROTIC_POISON_25 = 28776,
SPELL_FRENZY_10 = 54123, SPELL_FRENZY_10 = 54123,
SPELL_FRENZY_25 = 54124, SPELL_FRENZY_25 = 54124
}; };
enum Events enum Events
{ {
EVENT_SPELL_WEB_SPRAY = 1, EVENT_WEB_SPRAY = 1,
EVENT_SPELL_POISON_SHOCK = 2, EVENT_POISON_SHOCK = 2,
EVENT_SPELL_NECROTIC_POISON = 3, EVENT_NECROTIC_POISON = 3,
EVENT_WEB_WRAP = 4, EVENT_WEB_WRAP = 4,
EVENT_HEALTH_CHECK = 5, EVENT_HEALTH_CHECK = 5,
EVENT_SUMMON_SPIDERLINGS = 6, EVENT_SUMMON_SPIDERLINGS = 6
}; };
enum Emotes enum Emotes
@@ -40,7 +40,7 @@ enum Emotes
enum Misc enum Misc
{ {
NPC_WEB_WRAP = 16486, NPC_WEB_WRAP = 16486,
NPC_MAEXXNA_SPIDERLING = 17055, NPC_MAEXXNA_SPIDERLING = 17055
}; };
const Position PosWrap[3] = const Position PosWrap[3] =
@@ -78,7 +78,6 @@ public:
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -87,31 +86,33 @@ public:
BossAI::Reset(); BossAI::Reset();
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_WEB_WRAP, 20000); events.ScheduleEvent(EVENT_WEB_WRAP, 20000);
events.ScheduleEvent(EVENT_SPELL_WEB_SPRAY, 40000); events.ScheduleEvent(EVENT_WEB_SPRAY, 40000);
events.ScheduleEvent(EVENT_SPELL_POISON_SHOCK, 10000); events.ScheduleEvent(EVENT_POISON_SHOCK, 10000);
events.ScheduleEvent(EVENT_SPELL_NECROTIC_POISON, 5000); events.ScheduleEvent(EVENT_NECROTIC_POISON, 5000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000); events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
events.ScheduleEvent(EVENT_SUMMON_SPIDERLINGS, 30000); events.ScheduleEvent(EVENT_SUMMON_SPIDERLINGS, 30000);
if (pInstance) if (pInstance)
{ {
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE))) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE)))
{
go->SetGoState(GO_STATE_READY); go->SetGoState(GO_STATE_READY);
} }
} }
}
void JustSummoned(Creature* cr) override void JustSummoned(Creature* cr) override
{ {
@@ -119,17 +120,26 @@ public:
{ {
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
cr->AI()->AttackStart(target); cr->AI()->AttackStart(target);
} }
}
summons.Summon(cr); summons.Summon(cr);
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && pInstance) if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
summons.DespawnAll();
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -145,53 +155,53 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_WEB_SPRAY: case EVENT_WEB_SPRAY:
Talk(EMOTE_WEB_SPRAY); Talk(EMOTE_WEB_SPRAY);
me->CastSpell(me, RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25), true); me->CastSpell(me, RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25), true);
events.RepeatEvent(40000); events.RepeatEvent(40000);
break; break;
case EVENT_SPELL_POISON_SHOCK: case EVENT_POISON_SHOCK:
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_POISON_SHOCK_10, SPELL_POISON_SHOCK_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_POISON_SHOCK_10, SPELL_POISON_SHOCK_25), false);
events.RepeatEvent(40000); events.RepeatEvent(10000);
break; break;
case EVENT_SPELL_NECROTIC_POISON: case EVENT_NECROTIC_POISON:
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10, SPELL_NECROTIC_POISON_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10, SPELL_NECROTIC_POISON_25), false);
events.RepeatEvent(30000); events.RepeatEvent(30000);
break; break;
case EVENT_SUMMON_SPIDERLINGS: case EVENT_SUMMON_SPIDERLINGS:
Talk(EMOTE_SPIDERS); Talk(EMOTE_SPIDERS);
for (uint8 i = 0; i < 8; ++i) for (uint8 i = 0; i < 8; ++i)
{
me->SummonCreature(NPC_MAEXXNA_SPIDERLING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); me->SummonCreature(NPC_MAEXXNA_SPIDERLING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
}
events.RepeatEvent(40000); events.RepeatEvent(40000);
break; break;
case EVENT_HEALTH_CHECK: case EVENT_HEALTH_CHECK:
if (me->GetHealthPct() < 30) if (me->GetHealthPct() < 30)
{ {
me->CastSpell(me, RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25), true); me->CastSpell(me, RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25), true);
break; break;
} }
events.RepeatEvent(1000); events.RepeatEvent(1000);
break; break;
case EVENT_WEB_WRAP: case EVENT_WEB_WRAP:
Talk(EMOTE_WEB_WRAP); Talk(EMOTE_WEB_WRAP);
for (uint8 i = 0; i < RAID_MODE(1, 2); ++i) for (uint8 i = 0; i < RAID_MODE(1, 2); ++i)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP))
{ {
target->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25)); target->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25));
uint8 pos = urand(0, 2); uint8 pos = urand(0, 2);
if (Creature* wrap = me->SummonCreature(NPC_WEB_WRAP, PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000)) if (Creature* wrap = me->SummonCreature(NPC_WEB_WRAP, PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
{ {
wrap->AI()->SetGUID(target->GetGUID()); wrap->AI()->SetGUID(target->GetGUID());
target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
} }
} }
}
events.RepeatEvent(40000); events.RepeatEvent(40000);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -216,16 +226,24 @@ public:
{ {
victimGUID = guid; victimGUID = guid;
if (me->m_spells[0] && victimGUID) if (me->m_spells[0] && victimGUID)
{
if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID)) if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
{
victim->CastSpell(victim, me->m_spells[0], true, nullptr, nullptr, me->GetGUID()); victim->CastSpell(victim, me->m_spells[0], true, nullptr, nullptr, me->GetGUID());
} }
}
}
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
if (me->m_spells[0] && victimGUID) if (me->m_spells[0] && victimGUID)
{
if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID)) if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
{
victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID());
} }
}
}
}; };
}; };
@@ -27,20 +27,22 @@ enum Spells
SPELL_CRIPPLE_25 = 54814, SPELL_CRIPPLE_25 = 54814,
SPELL_SUMMON_PLAGUED_WARRIORS = 29237, SPELL_SUMMON_PLAGUED_WARRIORS = 29237,
SPELL_TELEPORT = 29216, SPELL_TELEPORT = 29216,
SPELL_BLINK = 29208, SPELL_TELEPORT_BACK = 29231,
SPELL_BERSERK = 68378,
SPELL_BLINK = 29208
}; };
enum Events enum Events
{ {
EVENT_SPELL_CURSE = 1, EVENT_CURSE = 1,
EVENT_SPELL_CRIPPLE = 2, EVENT_CRIPPLE = 2,
EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE = 3, EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE = 3,
EVENT_MOVE_TO_BALCONY = 4, EVENT_MOVE_TO_BALCONY = 4,
EVENT_SPELL_BLINK = 5, EVENT_BLINK = 5,
EVENT_MOVE_TO_GROUND = 6, EVENT_MOVE_TO_GROUND = 6,
EVENT_SUMMON_PLAGUED_WARRIOR_REAL = 7, EVENT_SUMMON_PLAGUED_WARRIOR_REAL = 7,
EVENT_BALCONY_SUMMON_ANNOUNCE = 8, EVENT_BALCONY_SUMMON_ANNOUNCE = 8,
EVENT_BALCONY_SUMMON_REAL = 9, EVENT_BALCONY_SUMMON_REAL = 9
}; };
enum Misc enum Misc
@@ -48,15 +50,17 @@ enum Misc
NPC_PLAGUED_WARRIOR = 16984, NPC_PLAGUED_WARRIOR = 16984,
NPC_PLAGUED_CHAMPION = 16983, NPC_PLAGUED_CHAMPION = 16983,
NPC_PLAGUED_GUARDIAN = 16981, NPC_PLAGUED_GUARDIAN = 16981,
NOTH_ROOM_ENTRANCE = 181200
}; };
const Position summoningPosition[5] = const Position summoningPosition[5] =
{ {
{2728.12f, -3544.43f, 261.91f, 6.04f}, {2728.06f, -3535.38f, 263.21f, 2.75f},
{2729.05f, -3544.47f, 261.91f, 5.58f}, {2725.71f, -3514.80f, 263.23f, 2.86f},
{2728.24f, -3465.08f, 264.20f, 3.56f}, {2728.24f, -3465.08f, 264.20f, 3.56f},
{2704.11f, -3456.81f, 265.53f, 4.51f}, {2704.79f, -3459.17f, 263.74f, 4.25f},
{2663.56f, -3464.43f, 262.66f, 5.20f}, {2652.02f, -3459.13f, 262.50f, 5.39f}
}; };
const Position nothPosition = {2684.94f, -3502.53f, 261.31f, 4.7f}; const Position nothPosition = {2684.94f, -3502.53f, 261.31f, 4.7f};
@@ -79,6 +83,7 @@ public:
} }
InstanceScript* pInstance; InstanceScript* pInstance;
uint8 timesInBalcony;
EventMap events; EventMap events;
SummonList summons; SummonList summons;
@@ -87,14 +92,14 @@ public:
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetControlled(false, UNIT_STATE_ROOT); me->SetControlled(false, UNIT_STATE_ROOT);
events.SetPhase(0);
events.Reset(); events.Reset();
events.ScheduleEvent(EVENT_MOVE_TO_BALCONY, 110000); events.ScheduleEvent(EVENT_MOVE_TO_BALCONY, 110000);
events.ScheduleEvent(EVENT_SPELL_CURSE, 15000); events.ScheduleEvent(EVENT_CURSE, 15000);
events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE, 25000); events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE, 10000);
if (Is25ManRaid()) if (Is25ManRaid())
events.ScheduleEvent(EVENT_SPELL_BLINK, 26000); {
events.ScheduleEvent(EVENT_BLINK, 26000);
}
} }
void StartBalconyPhase() void StartBalconyPhase()
@@ -103,7 +108,6 @@ public:
me->AttackStop(); me->AttackStop();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetControlled(true, UNIT_STATE_ROOT); me->SetControlled(true, UNIT_STATE_ROOT);
events.SetPhase(1);
events.Reset(); events.Reset();
events.ScheduleEvent(EVENT_BALCONY_SUMMON_ANNOUNCE, 4000); events.ScheduleEvent(EVENT_BALCONY_SUMMON_ANNOUNCE, 4000);
events.ScheduleEvent(EVENT_MOVE_TO_GROUND, 70000); events.ScheduleEvent(EVENT_MOVE_TO_GROUND, 70000);
@@ -112,17 +116,18 @@ public:
void SummonHelper(uint32 entry, uint32 count) void SummonHelper(uint32 entry, uint32 count)
{ {
for (uint8 i = 0; i < count; ++i) for (uint8 i = 0; i < count; ++i)
{
me->SummonCreature(entry, summoningPosition[urand(0, 4)]); me->SummonCreature(entry, summoningPosition[urand(0, 4)]);
} }
}
bool IsInRoom() bool IsInRoom()
{ {
if (me->GetPositionX() > 2730 || me->GetPositionX() < 2614 || me->GetPositionY() > -3455 || me->GetPositionY() < -3553) if (me->GetExactDist(2684.8f, -3502.5f, 261.3f) > 80.0f)
{ {
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -131,9 +136,14 @@ public:
BossAI::Reset(); BossAI::Reset();
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
me->CastSpell(me, SPELL_TELEPORT_BACK, true);
me->SetControlled(false, UNIT_STATE_ROOT); me->SetControlled(false, UNIT_STATE_ROOT);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
events.SetPhase(0); timesInBalcony = 0;
if (GameObject* go = me->FindNearestGameObject(NOTH_ROOM_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
} }
void EnterEvadeMode() override void EnterEvadeMode() override
@@ -147,6 +157,10 @@ public:
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
StartGroundPhase(); StartGroundPhase();
if (GameObject* go = me->FindNearestGameObject(NOTH_ROOM_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
} }
void JustSummoned(Creature* summon) override void JustSummoned(Creature* summon) override
@@ -157,9 +171,17 @@ public:
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
if (me->GetPositionZ() > 270.27f)
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true); me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true);
}
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
if (GameObject* go = me->FindNearestGameObject(NOTH_ROOM_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
@@ -168,10 +190,11 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -188,15 +211,17 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
// GROUND // GROUND
case EVENT_SPELL_CURSE: case EVENT_CURSE:
if (events.GetPhaseMask() == 0) if (events.GetPhaseMask() == 0)
{
me->CastCustomSpell(RAID_MODE(SPELL_CURSE_OF_THE_PLAGUEBRINGER_10, SPELL_CURSE_OF_THE_PLAGUEBRINGER_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(3, 10), me, false); me->CastCustomSpell(RAID_MODE(SPELL_CURSE_OF_THE_PLAGUEBRINGER_10, SPELL_CURSE_OF_THE_PLAGUEBRINGER_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(3, 10), me, false);
}
events.RepeatEvent(25000); events.RepeatEvent(25000);
break; break;
case EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE: case EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE:
Talk(SAY_SUMMON); Talk(SAY_SUMMON);
Talk(EMOTE_SUMMON); Talk(EMOTE_SUMMON);
events.RepeatEvent(25000); events.RepeatEvent(30000);
events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_REAL, 4000); events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_REAL, 4000);
break; break;
case EVENT_SUMMON_PLAGUED_WARRIOR_REAL: case EVENT_SUMMON_PLAGUED_WARRIOR_REAL:
@@ -207,9 +232,8 @@ public:
Talk(EMOTE_TELEPORT_BALCONY); Talk(EMOTE_TELEPORT_BALCONY);
me->CastSpell(me, SPELL_TELEPORT, true); me->CastSpell(me, SPELL_TELEPORT, true);
StartBalconyPhase(); StartBalconyPhase();
// events.Reset()!!
break; break;
case EVENT_SPELL_BLINK: case EVENT_BLINK:
DoResetThreat(); DoResetThreat();
me->CastSpell(me, RAID_MODE(SPELL_CRIPPLE_10, SPELL_CRIPPLE_25), false); me->CastSpell(me, RAID_MODE(SPELL_CRIPPLE_10, SPELL_CRIPPLE_25), false);
me->CastSpell(me, SPELL_BLINK, true); me->CastSpell(me, SPELL_BLINK, true);
@@ -219,28 +243,36 @@ public:
// BALCONY // BALCONY
case EVENT_BALCONY_SUMMON_ANNOUNCE: case EVENT_BALCONY_SUMMON_ANNOUNCE:
Talk(EMOTE_SUMMON_WAVE); Talk(EMOTE_SUMMON_WAVE);
events.RepeatEvent(25000); events.RepeatEvent(30000);
events.ScheduleEvent(EVENT_BALCONY_SUMMON_REAL, 4000); events.ScheduleEvent(EVENT_BALCONY_SUMMON_REAL, 4000);
break; break;
case EVENT_BALCONY_SUMMON_REAL: case EVENT_BALCONY_SUMMON_REAL:
me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); // visual only me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); // visual
if (events.GetPhaseMask() == 0) switch (timesInBalcony)
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(2, 4));
else if (events.GetPhaseMask() == 1)
{ {
case 0:
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(2, 4));
break;
case 1:
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(1, 2)); SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(1, 2));
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(1, 2)); SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(1, 2));
} break;
else default:
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(2, 4)); SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(2, 4));
break; break;
}
break;
case EVENT_MOVE_TO_GROUND: case EVENT_MOVE_TO_GROUND:
Talk(EMOTE_TELEPORT_BACK); Talk(EMOTE_TELEPORT_BACK);
me->CastSpell(me, SPELL_TELEPORT_BACK, true);
timesInBalcony++;
if (timesInBalcony == 3)
{
DoCastSelf(SPELL_BERSERK);
}
StartGroundPhase(); StartGroundPhase();
me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true);
break; break;
} }
if (me->HasReactState(REACT_AGGRESSIVE)) if (me->HasReactState(REACT_AGGRESSIVE))
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
@@ -21,20 +21,20 @@ enum Spells
SPELL_HATEFUL_STRIKE_25 = 59192, SPELL_HATEFUL_STRIKE_25 = 59192,
SPELL_FRENZY = 28131, SPELL_FRENZY = 28131,
SPELL_BERSERK = 26662, SPELL_BERSERK = 26662,
SPELL_SLIME_BOLT = 32309, SPELL_SLIME_BOLT = 32309
}; };
enum Events enum Events
{ {
EVENT_HEALTH_CHECK = 1, EVENT_HEALTH_CHECK = 1,
EVENT_SPELL_HATEFUL_STRIKE = 2, EVENT_HATEFUL_STRIKE = 2,
EVENT_SPELL_SLIME_BOLT = 3, EVENT_SLIME_BOLT = 3,
EVENT_SPELL_BERSERK = 4, EVENT_BERSERK = 4
}; };
enum Misc enum Misc
{ {
ACHIEV_TIMED_START_EVENT = 10286, ACHIEV_TIMED_START_EVENT = 10286
}; };
class boss_patchwerk : public CreatureScript class boss_patchwerk : public CreatureScript
@@ -69,11 +69,14 @@ public:
return; return;
if (!urand(0, 3)) if (!urand(0, 3))
{
Talk(SAY_SLAY); Talk(SAY_SLAY);
}
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -85,12 +88,10 @@ public:
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, 1200); events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 1500);
events.ScheduleEvent(EVENT_SPELL_BERSERK, 360000); events.ScheduleEvent(EVENT_BERSERK, 360000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000); events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
if (pInstance) if (pInstance)
{ {
pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
@@ -108,58 +109,60 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_HATEFUL_STRIKE: case EVENT_HATEFUL_STRIKE:
{ {
//Cast Hateful strike on the player with the highest // Cast Hateful strike on the player with the highest amount of HP within melee distance, and second threat amount
//amount of HP within melee distance, and second threat amount
std::list<Unit*> meleeRangeTargets; std::list<Unit*> meleeRangeTargets;
Unit* finalTarget = nullptr; Unit* finalTarget = nullptr;
uint8 counter = 0; uint8 counter = 0;
auto i = me->getThreatManager().getThreatList().begin(); auto i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i, ++counter) for (; i != me->getThreatManager().getThreatList().end(); ++i, ++counter)
{ {
// Gather all units with melee range // Gather all units with melee range
Unit* target = (*i)->getTarget(); Unit* target = (*i)->getTarget();
if (me->IsWithinMeleeRange(target)) if (me->IsWithinMeleeRange(target))
{
meleeRangeTargets.push_back(target); meleeRangeTargets.push_back(target);
}
// and add threat to most hated // and add threat to most hated
if (counter < RAID_MODE(2, 3)) if (counter < RAID_MODE(2, 3))
{
me->AddThreat(target, 500.0f); me->AddThreat(target, 500.0f);
} }
}
counter = 0; counter = 0;
list<Unit*, std::allocator<Unit*>>::iterator itr; list<Unit*, std::allocator<Unit*>>::iterator itr;
for (itr = meleeRangeTargets.begin(); itr != meleeRangeTargets.end(); ++itr, ++counter) for (itr = meleeRangeTargets.begin(); itr != meleeRangeTargets.end(); ++itr, ++counter)
{ {
// if there is only one target available // if there is only one target available
if (meleeRangeTargets.size() == 1) if (meleeRangeTargets.size() == 1)
{
finalTarget = (*itr); finalTarget = (*itr);
}
else if (counter > 0) // skip first target else if (counter > 0) // skip first target
{ {
if (!finalTarget || (*itr)->GetHealth() > finalTarget->GetHealth()) if (!finalTarget || (*itr)->GetHealth() > finalTarget->GetHealth())
{
finalTarget = (*itr); finalTarget = (*itr);
}
// third loop // third loop
if (counter >= 2) if (counter >= 2)
break; break;
} }
} }
if (finalTarget) if (finalTarget)
{
me->CastSpell(finalTarget, RAID_MODE(SPELL_HATEFUL_STRIKE_10, SPELL_HATEFUL_STRIKE_25), false); me->CastSpell(finalTarget, RAID_MODE(SPELL_HATEFUL_STRIKE_10, SPELL_HATEFUL_STRIKE_25), false);
}
events.RepeatEvent(1000); events.RepeatEvent(1000);
break; break;
} }
case EVENT_SPELL_BERSERK: case EVENT_BERSERK:
Talk(EMOTE_BERSERK); Talk(EMOTE_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
events.ScheduleEvent(EVENT_SPELL_SLIME_BOLT, 2000); events.ScheduleEvent(EVENT_SLIME_BOLT, 3000);
break; break;
case EVENT_SPELL_SLIME_BOLT: case EVENT_SLIME_BOLT:
me->CastSpell(me, SPELL_SLIME_BOLT, false); me->CastSpell(me, SPELL_SLIME_BOLT, false);
events.RepeatEvent(3000); events.RepeatEvent(3000);
break; break;
@@ -168,13 +171,11 @@ public:
{ {
Talk(EMOTE_ENRAGE); Talk(EMOTE_ENRAGE);
me->CastSpell(me, SPELL_FRENZY, true); me->CastSpell(me, SPELL_FRENZY, true);
break; break;
} }
events.RepeatEvent(1000); events.RepeatEvent(1000);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -11,37 +11,31 @@ enum Says
SAY_AGGRO = 0, SAY_AGGRO = 0,
SAY_SLAY = 1, SAY_SLAY = 1,
SAY_TAUNTED = 2, SAY_TAUNTED = 2,
SAY_DEATH = 3, SAY_DEATH = 3
SAY_SHOUT = 4
}; };
enum Spells enum Spells
{ {
SPELL_UNBALANCING_STRIKE = 26613, SPELL_UNBALANCING_STRIKE = 26613,
SPELL_DISRUPTING_SHOUT_10 = 29107, SPELL_DISRUPTING_SHOUT_10 = 55543,
SPELL_DISRUPTING_SHOUT_25 = 55543, SPELL_DISRUPTING_SHOUT_25 = 29107,
SPELL_JAGGED_KNIFE = 55550, SPELL_JAGGED_KNIFE = 55550,
SPELL_HOPELESS = 29125, SPELL_HOPELESS = 29125,
SPELL_BONE_BARRIER = 29061, SPELL_TAUNT = 29060
SPELL_BLOOD_STRIKE = 61696,
}; };
enum Events enum Events
{ {
EVENT_SPELL_UNBALANCING_STRIKE = 1, EVENT_UNBALANCING_STRIKE = 1,
EVENT_SPELL_DISRUPTING_SHOUT = 2, EVENT_DISRUPTING_SHOUT = 2,
EVENT_SPELL_JAGGED_KNIFE = 3, EVENT_JAGGED_KNIFE = 3
EVENT_PLAY_COMMAND = 4,
EVENT_MINION_BLOOD_STRIKE = 10,
EVENT_MINION_BONE_BARRIER = 11,
}; };
enum Misc enum Misc
{ {
NPC_DEATH_KNIGHT_UNDERSTUDY = 16803, NPC_DEATH_KNIGHT_UNDERSTUDY = 16803,
NPC_RAZUVIOUS = 16061, NPC_RAZUVIOUS = 16061
}; };
class boss_razuvious : public CreatureScript class boss_razuvious : public CreatureScript
@@ -66,17 +60,20 @@ public:
InstanceScript* pInstance; InstanceScript* pInstance;
void SpawnHelpers() void SpawnHelpers()
{
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2782.45f, -3088.03f, 267.685f, 0.75f);
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2778.56f, -3113.74f, 267.685f, 5.28f);
if (Is25ManRaid())
{ {
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2762.23f, -3085.07f, 267.685f, 1.95f); me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2762.23f, -3085.07f, 267.685f, 1.95f);
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2758.24f, -3110.97f, 267.685f, 3.94f); me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2758.24f, -3110.97f, 267.685f, 3.94f);
if (Is25ManRaid())
{
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2782.45f, -3088.03f, 267.685f, 0.75f);
me->SummonCreature(NPC_DEATH_KNIGHT_UNDERSTUDY, 2778.56f, -3113.74f, 267.685f, 5.28f);
} }
} }
void JustSummoned(Creature* cr) override { summons.Summon(cr); } void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
}
void Reset() override void Reset() override
{ {
@@ -88,40 +85,50 @@ public:
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() != TYPEID_PLAYER) if (roll_chance_i(30))
return; {
Talk(SAY_SLAY); Talk(SAY_SLAY);
}
if (who->GetTypeId() == TYPEID_PLAYER)
{
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
}
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
{ {
// Damage done by the controlled Death Knight understudies should also count toward damage done by players // Damage done by the controlled Death Knight understudies should also count toward damage done by players
if(who && who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_DEATH_KNIGHT_UNDERSTUDY) if(who && who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_DEATH_KNIGHT_UNDERSTUDY)
{
me->LowerPlayerDamageReq(damage); me->LowerPlayerDamageReq(damage);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
me->CastSpell(me, SPELL_HOPELESS, true); me->CastSpell(me, SPELL_HOPELESS, true);
} }
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (spell->Id == SPELL_TAUNT)
{
Talk(SAY_TAUNTED, caster);
}
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 20000);
events.ScheduleEvent(EVENT_SPELL_UNBALANCING_STRIKE, 30000); events.ScheduleEvent(EVENT_DISRUPTING_SHOUT, 15000);
events.ScheduleEvent(EVENT_SPELL_DISRUPTING_SHOUT, 25000); events.ScheduleEvent(EVENT_JAGGED_KNIFE, 10000);
events.ScheduleEvent(EVENT_SPELL_JAGGED_KNIFE, 15000);
events.ScheduleEvent(EVENT_PLAY_COMMAND, 40000);
summons.DoZoneInCombat(); summons.DoZoneInCombat();
} }
@@ -136,27 +143,22 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_UNBALANCING_STRIKE: case EVENT_UNBALANCING_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_UNBALANCING_STRIKE, false); me->CastSpell(me->GetVictim(), SPELL_UNBALANCING_STRIKE, false);
events.RepeatEvent(30000); events.RepeatEvent(20000);
break; break;
case EVENT_SPELL_DISRUPTING_SHOUT: case EVENT_DISRUPTING_SHOUT:
Talk(SAY_SHOUT);
me->CastSpell(me, RAID_MODE(SPELL_DISRUPTING_SHOUT_10, SPELL_DISRUPTING_SHOUT_25), false); me->CastSpell(me, RAID_MODE(SPELL_DISRUPTING_SHOUT_10, SPELL_DISRUPTING_SHOUT_25), false);
events.RepeatEvent(25000); events.RepeatEvent(15000);
break; break;
case EVENT_SPELL_JAGGED_KNIFE: case EVENT_JAGGED_KNIFE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
{
me->CastSpell(target, SPELL_JAGGED_KNIFE, false); me->CastSpell(target, SPELL_JAGGED_KNIFE, false);
}
events.RepeatEvent(25000); events.RepeatEvent(10000);
break;
case EVENT_PLAY_COMMAND:
Talk(SAY_TAUNTED);
events.RepeatEvent(40000);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -185,12 +187,14 @@ public:
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() != TYPEID_PLAYER) if (who->GetTypeId() == TYPEID_PLAYER)
return; {
if (me->GetInstanceScript()) if (me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0); me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
@@ -199,34 +203,19 @@ public:
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
cr->AI()->AttackStart(who); cr->AI()->AttackStart(who);
} }
events.ScheduleEvent(EVENT_MINION_BLOOD_STRIKE, 4000);
events.ScheduleEvent(EVENT_MINION_BONE_BARRIER, 9000);
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
if (!UpdateVictim()) if (UpdateVictim())
return; {
events.Update(diff);
events.Update(diff); if (!me->HasUnitState(UNIT_STATE_CASTING) || !me->IsCharmed())
if (me->HasUnitState(UNIT_STATE_CASTING) || me->IsCharmed())
return;
switch (events.ExecuteEvent())
{ {
case EVENT_MINION_BLOOD_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_BLOOD_STRIKE, false);
events.RepeatEvent(8000);
break;
case EVENT_MINION_BONE_BARRIER:
me->CastSpell(me, SPELL_BONE_BARRIER, true);
events.RepeatEvent(40000);
break;
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}
}
}; };
}; };
@@ -36,7 +36,7 @@ enum Spells
SPELL_FROST_EXPLOSION = 28524, SPELL_FROST_EXPLOSION = 28524,
// Visuals // Visuals
SPELL_SAPPHIRON_DIES = 29357, SPELL_SAPPHIRON_DIES = 29357
}; };
enum Misc enum Misc
@@ -44,27 +44,25 @@ enum Misc
GO_ICE_BLOCK = 181247, GO_ICE_BLOCK = 181247,
NPC_BLIZZARD = 16474, NPC_BLIZZARD = 16474,
POINT_CENTER = 1, POINT_CENTER = 1
FAKE_POINTER = 1,
}; };
enum Events enum Events
{ {
//EVENT_SAPPHIRON_BIRTH = 1, EVENT_BERSERK = 1,
EVENT_BERSERK = 2, EVENT_CLEAVE = 2,
EVENT_SPELL_CLEAVE = 3, EVENT_TAIL_SWEEP = 3,
EVENT_SPELL_TAIL_SWEEP = 4, EVENT_LIFE_DRAIN = 4,
EVENT_SPELL_LIFE_DRAIN = 5, EVENT_BLIZZARD = 5,
EVENT_SPELL_BLIZZARD = 6, EVENT_FLIGHT_START = 6,
EVENT_FLIGHT_START = 7, EVENT_FLIGHT_LIFTOFF = 7,
EVENT_FLIGHT_LIFTOFF = 8, EVENT_FLIGHT_ICEBOLT = 8,
EVENT_FLIGHT_ICEBOLT = 9, EVENT_FLIGHT_BREATH = 9,
EVENT_FLIGHT_BREATH = 10, EVENT_FLIGHT_SPELL_EXPLOSION = 10,
EVENT_FLIGHT_SPELL_EXPLOSION = 11, EVENT_FLIGHT_START_LAND = 11,
EVENT_FLIGHT_START_LAND = 12, EVENT_LAND = 12,
EVENT_LAND = 13, EVENT_GROUND = 13,
EVENT_GROUND = 14, EVENT_HUNDRED_CLUB = 14
EVENT_HUNDRED_CLUB = 15,
}; };
class boss_sapphiron : public CreatureScript class boss_sapphiron : public CreatureScript
@@ -107,7 +105,6 @@ public:
EnterEvadeMode(); EnterEvadeMode();
return false; return false;
} }
return true; return true;
} }
@@ -115,8 +112,9 @@ public:
{ {
BossAI::Reset(); BossAI::Reset();
if (me->IsVisible()) if (me->IsVisible())
{
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
}
events.Reset(); events.Reset();
iceboltCount = 0; iceboltCount = 0;
spawnTimer = 0; spawnTimer = 0;
@@ -129,12 +127,14 @@ public:
Map::PlayerList const& PlList = me->GetMap()->GetPlayers(); Map::PlayerList const& PlList = me->GetMap()->GetPlayers();
if (PlList.isEmpty()) if (PlList.isEmpty())
return; return;
for (const auto& i : PlList) for (const auto& i : PlList)
{ {
if (Player* player = i.GetSource()) if (Player* player = i.GetSource())
{ {
if (player->IsGameMaster()) if (player->IsGameMaster())
continue; continue;
if (player->IsAlive() && me->GetDistance(player) < 80.0f) if (player->IsAlive() && me->GetDistance(player) < 80.0f)
{ {
me->SetInCombatWith(player); me->SetInCombatWith(player);
@@ -150,12 +150,11 @@ public:
BossAI::EnterCombat(who); BossAI::EnterCombat(who);
EnterCombatSelfFunction(); EnterCombatSelfFunction();
me->CastSpell(me, RAID_MODE(SPELL_FROST_AURA_10, SPELL_FROST_AURA_25), true); me->CastSpell(me, RAID_MODE(SPELL_FROST_AURA_10, SPELL_FROST_AURA_25), true);
events.ScheduleEvent(EVENT_BERSERK, 900000);
events.ScheduleEvent(EVENT_BERSERK, 15 * 60000); events.ScheduleEvent(EVENT_CLEAVE, 5000);
events.ScheduleEvent(EVENT_SPELL_CLEAVE, 5000); events.ScheduleEvent(EVENT_TAIL_SWEEP, 10000);
events.ScheduleEvent(EVENT_SPELL_TAIL_SWEEP, 10000); events.ScheduleEvent(EVENT_LIFE_DRAIN, 17000);
events.ScheduleEvent(EVENT_SPELL_LIFE_DRAIN, 17000); events.ScheduleEvent(EVENT_BLIZZARD, 17000);
events.ScheduleEvent(EVENT_SPELL_BLIZZARD, 17000);
events.ScheduleEvent(EVENT_FLIGHT_START, 45000); events.ScheduleEvent(EVENT_FLIGHT_START, 45000);
events.ScheduleEvent(EVENT_HUNDRED_CLUB, 5000); events.ScheduleEvent(EVENT_HUNDRED_CLUB, 5000);
} }
@@ -169,14 +168,18 @@ public:
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
if (param == ACTION_SAPPHIRON_BIRTH) if (param == ACTION_SAPPHIRON_BIRTH)
{
spawnTimer = 1; spawnTimer = 1;
} }
}
void MovementInform(uint32 type, uint32 id) override void MovementInform(uint32 type, uint32 id) override
{ {
if (type == POINT_MOTION_TYPE && id == POINT_CENTER) if (type == POINT_MOTION_TYPE && id == POINT_CENTER)
{
events.ScheduleEvent(EVENT_FLIGHT_LIFTOFF, 500); events.ScheduleEvent(EVENT_FLIGHT_LIFTOFF, 500);
} }
}
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override
{ {
@@ -199,15 +202,16 @@ public:
return false; return false;
} }
} }
return true; return true;
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
if (who->GetTypeId() == TYPEID_PLAYER && pInstance) if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -240,28 +244,33 @@ public:
Talk(EMOTE_ENRAGE); Talk(EMOTE_ENRAGE);
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
return; return;
case EVENT_SPELL_CLEAVE: case EVENT_CLEAVE:
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false); me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
events.RepeatEvent(10000); events.RepeatEvent(10000);
return; return;
case EVENT_SPELL_TAIL_SWEEP: case EVENT_TAIL_SWEEP:
me->CastSpell(me, RAID_MODE(SPELL_TAIL_SWEEP_10, SPELL_TAIL_SWEEP_25), false); me->CastSpell(me, RAID_MODE(SPELL_TAIL_SWEEP_10, SPELL_TAIL_SWEEP_25), false);
events.RepeatEvent(10000); events.RepeatEvent(10000);
return; return;
case EVENT_SPELL_LIFE_DRAIN: case EVENT_LIFE_DRAIN:
me->CastCustomSpell(RAID_MODE(SPELL_LIFE_DRAIN_10, SPELL_LIFE_DRAIN_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(2, 5), me, false); me->CastCustomSpell(RAID_MODE(SPELL_LIFE_DRAIN_10, SPELL_LIFE_DRAIN_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(2, 5), me, false);
events.RepeatEvent(24000); events.RepeatEvent(24000);
return; return;
case EVENT_SPELL_BLIZZARD: case EVENT_BLIZZARD:
{ {
Creature* cr; Creature* cr;
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
{
cr = me->SummonCreature(NPC_BLIZZARD, *target, TEMPSUMMON_TIMED_DESPAWN, 16000); cr = me->SummonCreature(NPC_BLIZZARD, *target, TEMPSUMMON_TIMED_DESPAWN, 16000);
}
else else
{
cr = me->SummonCreature(NPC_BLIZZARD, *me, TEMPSUMMON_TIMED_DESPAWN, 16000); cr = me->SummonCreature(NPC_BLIZZARD, *me, TEMPSUMMON_TIMED_DESPAWN, 16000);
}
if (cr) if (cr)
{
cr->GetMotionMaster()->MoveRandom(40); cr->GetMotionMaster()->MoveRandom(40);
}
events.RepeatEvent(RAID_MODE(8000, 6500)); events.RepeatEvent(RAID_MODE(8000, 6500));
return; return;
} }
@@ -279,6 +288,7 @@ public:
me->GetMotionMaster()->MovePoint(POINT_CENTER, x, y, z); me->GetMotionMaster()->MovePoint(POINT_CENTER, x, y, z);
return; return;
case EVENT_FLIGHT_LIFTOFF: case EVENT_FLIGHT_LIFTOFF:
Talk(EMOTE_AIR_PHASE);
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
me->SendMeleeAttackStop(me->GetVictim()); me->SendMeleeAttackStop(me->GetVictim());
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
@@ -291,26 +301,37 @@ public:
case EVENT_FLIGHT_ICEBOLT: case EVENT_FLIGHT_ICEBOLT:
{ {
if (currentTarget) if (currentTarget)
{
if (Unit* target = ObjectAccessor::GetUnit(*me, currentTarget)) if (Unit* target = ObjectAccessor::GetUnit(*me, currentTarget))
{
me->SummonGameObject(GO_ICE_BLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); me->SummonGameObject(GO_ICE_BLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0);
}
}
std::vector<Unit*> targets; std::vector<Unit*> targets;
auto i = me->getThreatManager().getThreatList().begin(); auto i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i) for (; i != me->getThreatManager().getThreatList().end(); ++i)
{
if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER) if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER)
{ {
bool inList = false; bool inList = false;
if (!blockList.empty()) if (!blockList.empty())
{
for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr) for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
{
if ((*i)->getTarget()->GetGUID() == *itr) if ((*i)->getTarget()->GetGUID() == *itr)
{ {
inList = true; inList = true;
break; break;
} }
}
}
if (!inList) if (!inList)
{
targets.push_back((*i)->getTarget()); targets.push_back((*i)->getTarget());
} }
}
}
if (!targets.empty() && iceboltCount) if (!targets.empty() && iceboltCount)
{ {
@@ -323,7 +344,9 @@ public:
events.ScheduleEvent(EVENT_FLIGHT_ICEBOLT, (me->GetExactDist(*itr) / 13.0f)*IN_MILLISECONDS); events.ScheduleEvent(EVENT_FLIGHT_ICEBOLT, (me->GetExactDist(*itr) / 13.0f)*IN_MILLISECONDS);
} }
else else
{
events.ScheduleEvent(EVENT_FLIGHT_BREATH, 1000); events.ScheduleEvent(EVENT_FLIGHT_BREATH, 1000);
}
return; return;
} }
case EVENT_FLIGHT_BREATH: case EVENT_FLIGHT_BREATH:
@@ -338,10 +361,15 @@ public:
return; return;
case EVENT_FLIGHT_START_LAND: case EVENT_FLIGHT_START_LAND:
if (!blockList.empty()) if (!blockList.empty())
{
for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr) for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
{
if (Unit* block = ObjectAccessor::GetUnit(*me, *itr)) if (Unit* block = ObjectAccessor::GetUnit(*me, *itr))
{
block->RemoveAurasDueToSpell(SPELL_ICEBOLT_TRIGGER); block->RemoveAurasDueToSpell(SPELL_ICEBOLT_TRIGGER);
}
}
}
blockList.clear(); blockList.clear();
me->RemoveAllGameObjects(); me->RemoveAllGameObjects();
events.ScheduleEvent(EVENT_LAND, 1000); events.ScheduleEvent(EVENT_LAND, 1000);
@@ -349,12 +377,11 @@ public:
case EVENT_LAND: case EVENT_LAND:
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->SetDisableGravity(false); me->SetDisableGravity(false);
me->SetHover(false); me->SetHover(false);
events.ScheduleEvent(EVENT_GROUND, 1500); events.ScheduleEvent(EVENT_GROUND, 1500);
return; return;
case EVENT_GROUND: case EVENT_GROUND:
Talk(EMOTE_GROUND_PHASE);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
return; return;
@@ -373,7 +400,6 @@ public:
return; return;
} }
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -398,13 +424,16 @@ public:
for (auto& target : targets) for (auto& target : targets)
{ {
if (CAST_AI(boss_sapphiron::boss_sapphironAI, caster->ToCreature()->AI())->IsValidExplosionTarget(target)) if (CAST_AI(boss_sapphiron::boss_sapphironAI, caster->ToCreature()->AI())->IsValidExplosionTarget(target))
{
tmplist.push_back(target); tmplist.push_back(target);
} }
}
targets.clear(); targets.clear();
for (auto& itr : tmplist) for (auto& itr : tmplist)
{
targets.push_back(itr); targets.push_back(itr);
} }
}
void Register() override void Register() override
{ {
@@ -41,6 +41,7 @@ enum Spells
{ {
SPELL_MAGNETIC_PULL = 28337, SPELL_MAGNETIC_PULL = 28337,
SPELL_TESLA_SHOCK = 28099, SPELL_TESLA_SHOCK = 28099,
SPELL_SHOCK_VISUAL = 28159,
// Stalagg // Stalagg
SPELL_POWER_SURGE_10 = 54529, SPELL_POWER_SURGE_10 = 54529,
@@ -58,7 +59,6 @@ enum Spells
SPELL_CHAIN_LIGHTNING_10 = 28167, SPELL_CHAIN_LIGHTNING_10 = 28167,
SPELL_CHAIN_LIGHTNING_25 = 54531, SPELL_CHAIN_LIGHTNING_25 = 54531,
SPELL_BERSERK = 27680, SPELL_BERSERK = 27680,
SPELL_THADDIUS_VISUAL_LIGHTNING = 28136, SPELL_THADDIUS_VISUAL_LIGHTNING = 28136,
SPELL_THADDIUS_SPAWN_STUN = 28160, SPELL_THADDIUS_SPAWN_STUN = 28160,
@@ -67,22 +67,22 @@ enum Spells
SPELL_NEGATIVE_CHARGE = 28085, SPELL_NEGATIVE_CHARGE = 28085,
SPELL_NEGATIVE_CHARGE_STACK = 29660, SPELL_NEGATIVE_CHARGE_STACK = 29660,
SPELL_POSITIVE_POLARITY = 28059, SPELL_POSITIVE_POLARITY = 28059,
SPELL_NEGATIVE_POLARITY = 28084, SPELL_NEGATIVE_POLARITY = 28084
}; };
enum Events enum Events
{ {
EVENT_MINION_SPELL_POWER_SURGE = 1, EVENT_MINION_POWER_SURGE = 1,
EVENT_MINION_SPELL_MAGNETIC_PULL = 2, EVENT_MINION_MAGNETIC_PULL = 2,
EVENT_MINION_CHECK_DISTANCE = 3, EVENT_MINION_CHECK_DISTANCE = 3,
EVENT_MINION_SPELL_STATIC_FIELD = 4, EVENT_MINION_STATIC_FIELD = 4,
EVENT_THADDIUS_START = 10, EVENT_THADDIUS_INIT = 5,
EVENT_THADDIUS_SPELL_CHAIN_LIGHTNING = 11, EVENT_THADDIUS_ENTER_COMBAT = 6,
EVENT_THADDIUS_SPELL_BERSERK = 12, EVENT_THADDIUS_CHAIN_LIGHTNING = 7,
EVENT_THADDIUS_POLARITY_SHIFT = 13, EVENT_THADDIUS_BERSERK = 8,
EVENT_THADDIUS_START_2 = 14, EVENT_THADDIUS_POLARITY_SHIFT = 9,
EVENT_ACTIVATE_BALL_LIGHTNING = 15 EVENT_ALLOW_BALL_LIGHTNING = 10
}; };
enum Misc enum Misc
@@ -90,7 +90,10 @@ enum Misc
ACTION_MAGNETIC_PULL = 1, ACTION_MAGNETIC_PULL = 1,
ACTION_SUMMON_DIED = 2, ACTION_SUMMON_DIED = 2,
ACTION_RESTORE = 3, ACTION_RESTORE = 3,
NPC_TESLA_COIL = 16218, //the coils (emotes "Tesla Coil overloads!") GO_TESLA_COIL_LEFT = 181478,
GO_TESLA_COIL_RIGHT = 181477,
NPC_TESLA_COIL = 16218,
THADDIUS_ROOM_DOOR = 181121
}; };
class boss_thaddius : public CreatureScript class boss_thaddius : public CreatureScript
@@ -118,27 +121,16 @@ public:
uint32 resetTimer{}; uint32 resetTimer{};
bool ballLightningEnabled; bool ballLightningEnabled;
void StartEvent()
{
me->RemoveAllAuras();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->CastSpell(me, SPELL_THADDIUS_VISUAL_LIGHTNING, true);
events.ScheduleEvent(EVENT_THADDIUS_START_2, 1000);
}
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
if (param == ACTION_SUMMON_DIED) if (param == ACTION_SUMMON_DIED)
{ {
// Hooray, we did it!
if (summonTimer) if (summonTimer)
{ {
summonTimer = 0; summonTimer = 0;
reviveTimer = 1; reviveTimer = 1;
//events.ScheduleEvent(EVENT_THADDIUS_START, 12000);
return; return;
} }
summonTimer = 1; summonTimer = 1;
} }
} }
@@ -149,6 +141,7 @@ public:
events.Reset(); events.Reset();
summons.DespawnAll(); summons.DespawnAll();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetControlled(false, UNIT_STATE_ROOT);
summonTimer = 0; summonTimer = 0;
reviveTimer = 0; reviveTimer = 0;
resetTimer = 1; resetTimer = 1;
@@ -164,6 +157,7 @@ public:
cr->CastSpell(cr, SPELL_FEUGEN_CHAIN, false); cr->CastSpell(cr, SPELL_FEUGEN_CHAIN, false);
cr->SetDisableGravity(true); cr->SetDisableGravity(true);
cr->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); cr->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
cr->SetControlled(true, UNIT_STATE_ROOT);
} }
if (Creature* cr = me->SummonCreature(NPC_TESLA_COIL, 3487.04f, -2911.68f, 318.75f, 0.0f)) if (Creature* cr = me->SummonCreature(NPC_TESLA_COIL, 3487.04f, -2911.68f, 318.75f, 0.0f))
{ {
@@ -172,6 +166,20 @@ public:
cr->CastSpell(cr, SPELL_STALAGG_CHAIN, false); cr->CastSpell(cr, SPELL_STALAGG_CHAIN, false);
cr->SetDisableGravity(true); cr->SetDisableGravity(true);
cr->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); cr->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
cr->SetControlled(true, UNIT_STATE_ROOT);
}
if (GameObject* go = me->FindNearestGameObject(GO_TESLA_COIL_LEFT, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->FindNearestGameObject(GO_TESLA_COIL_RIGHT, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->FindNearestGameObject(THADDIUS_ROOM_DOOR, 200.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
} }
} }
@@ -181,10 +189,11 @@ public:
return; return;
Talk(SAY_SLAY); Talk(SAY_SLAY);
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
} }
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
@@ -195,9 +204,16 @@ public:
pInstance->DoRemoveAurasDueToSpellOnPlayers(28059); pInstance->DoRemoveAurasDueToSpellOnPlayers(28059);
pInstance->DoRemoveAurasDueToSpellOnPlayers(28084); pInstance->DoRemoveAurasDueToSpellOnPlayers(28084);
} }
if (GameObject* go = me->FindNearestGameObject(THADDIUS_ROOM_DOOR, 200.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
} }
void JustSummoned(Creature* cr) override { summons.Summon(cr); } void JustSummoned(Creature* cr) override
{
summons.Summon(cr);
}
void EnterCombat(Unit* who) override void EnterCombat(Unit* who) override
{ {
@@ -224,16 +240,19 @@ public:
reviveTimer += diff; reviveTimer += diff;
if (reviveTimer >= 12000) if (reviveTimer >= 12000)
{ {
events.ScheduleEvent(EVENT_THADDIUS_START, 1500);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr))) if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
{
if (cr->GetEntry() == NPC_TESLA_COIL) if (cr->GetEntry() == NPC_TESLA_COIL)
{ {
cr->AI()->Talk(EMOTE_TESLA_OVERLOAD); cr->AI()->Talk(EMOTE_TESLA_OVERLOAD);
cr->CastSpell(me, SPELL_TESLA_SHOCK, true); // till smth better is found ;( ZOMG cr->CastSpell(me, SPELL_SHOCK_VISUAL, true);
Unit::Kill(cr, cr); }
}
} }
reviveTimer = 0; reviveTimer = 0;
events.ScheduleEvent(EVENT_THADDIUS_INIT, 750);
} }
return; return;
} }
@@ -245,8 +264,7 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
return; return;
// Revive code! if (summonTimer) // Revive
if (summonTimer)
{ {
summonTimer += diff; summonTimer += diff;
if (summonTimer >= 5000) if (summonTimer >= 5000)
@@ -258,27 +276,46 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_THADDIUS_START: case EVENT_THADDIUS_INIT:
StartEvent(); {
me->RemoveAllAuras();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
{
if (cr->GetEntry() == NPC_TESLA_COIL)
{
Unit::Kill(cr, cr);
}
}
}
if (GameObject* go = me->FindNearestGameObject(GO_TESLA_COIL_LEFT, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->FindNearestGameObject(GO_TESLA_COIL_RIGHT, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
me->CastSpell(me, SPELL_THADDIUS_VISUAL_LIGHTNING, true);
events.ScheduleEvent(EVENT_THADDIUS_ENTER_COMBAT, 1000);
break; break;
case EVENT_THADDIUS_START_2: }
case EVENT_THADDIUS_ENTER_COMBAT:
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
me->SetControlled(false, UNIT_STATE_STUNNED); me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->setAttackTimer(BASE_ATTACK, 4000); events.ScheduleEvent(EVENT_THADDIUS_CHAIN_LIGHTNING, 14000);
events.ScheduleEvent(EVENT_THADDIUS_BERSERK, 360000);
events.ScheduleEvent(EVENT_THADDIUS_SPELL_CHAIN_LIGHTNING, 14000);
events.ScheduleEvent(EVENT_THADDIUS_SPELL_BERSERK, 360000);
events.ScheduleEvent(EVENT_THADDIUS_POLARITY_SHIFT, 30000); events.ScheduleEvent(EVENT_THADDIUS_POLARITY_SHIFT, 30000);
events.ScheduleEvent(EVENT_ACTIVATE_BALL_LIGHTNING, 5000); events.ScheduleEvent(EVENT_ALLOW_BALL_LIGHTNING, 5000);
return; return;
case EVENT_THADDIUS_SPELL_BERSERK: case EVENT_THADDIUS_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true); me->CastSpell(me, SPELL_BERSERK, true);
break; break;
case EVENT_THADDIUS_SPELL_CHAIN_LIGHTNING: case EVENT_THADDIUS_CHAIN_LIGHTNING:
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING_10, SPELL_CHAIN_LIGHTNING_25), false); me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING_10, SPELL_CHAIN_LIGHTNING_25), false);
events.RepeatEvent(15000); events.RepeatEvent(15000);
break; break;
@@ -286,17 +323,23 @@ public:
me->CastSpell(me, SPELL_POLARITY_SHIFT, false); me->CastSpell(me, SPELL_POLARITY_SHIFT, false);
events.RepeatEvent(30000); events.RepeatEvent(30000);
break; break;
case EVENT_ACTIVATE_BALL_LIGHTNING: case EVENT_ALLOW_BALL_LIGHTNING:
ballLightningEnabled = true; ballLightningEnabled = true;
me->SetControlled(true, UNIT_STATE_ROOT);
break; break;
} }
if (me->IsWithinMeleeRange(me->GetVictim())) if (me->IsWithinMeleeRange(me->GetVictim()))
{
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
}
else if (ballLightningEnabled) else if (ballLightningEnabled)
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) {
DoCast(target, SPELL_BALL_LIGHTNING); if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO))
{
me->CastSpell(target, SPELL_BALL_LIGHTNING, false);
}
}
} }
}; };
}; };
@@ -332,7 +375,6 @@ public:
pullTimer = 0; pullTimer = 0;
visualTimer = 1; visualTimer = 1;
overload = false; overload = false;
events.Reset(); events.Reset();
me->SetControlled(false, UNIT_STATE_STUNNED); me->SetControlled(false, UNIT_STATE_STUNNED);
if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f)) if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f))
@@ -352,33 +394,39 @@ public:
void EnterCombat(Unit* pWho) override void EnterCombat(Unit* pWho) override
{ {
me->SetInCombatWithZone(); me->SetInCombatWithZone();
if (GameObject* go = me->FindNearestGameObject(THADDIUS_ROOM_DOOR, 200.0f))
{
go->SetGoState(GO_STATE_READY);
}
if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.f, true)) if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.f, true))
{
myCoil = cr->GetGUID(); myCoil = cr->GetGUID();
}
if (me->GetEntry() == NPC_STALAGG) if (me->GetEntry() == NPC_STALAGG)
{ {
events.ScheduleEvent(EVENT_MINION_SPELL_POWER_SURGE, 10000); events.ScheduleEvent(EVENT_MINION_POWER_SURGE, 10000);
Talk(SAY_STAL_AGGRO); Talk(SAY_STAL_AGGRO);
} }
else else
{ {
events.ScheduleEvent(EVENT_MINION_SPELL_STATIC_FIELD, 5000); events.ScheduleEvent(EVENT_MINION_STATIC_FIELD, 5000);
Talk(SAY_FEUG_AGGRO); Talk(SAY_FEUG_AGGRO);
} }
events.ScheduleEvent(EVENT_MINION_CHECK_DISTANCE, 5000); events.ScheduleEvent(EVENT_MINION_CHECK_DISTANCE, 5000);
// This event needs synchronisation, called for stalagg only if (me->GetEntry() == NPC_STALAGG) // This event needs synchronisation, called for stalagg only
if (me->GetEntry() == NPC_STALAGG) {
events.ScheduleEvent(EVENT_MINION_SPELL_MAGNETIC_PULL, 25000); events.ScheduleEvent(EVENT_MINION_MAGNETIC_PULL, 20000);
}
if (pInstance) if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS))) if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS)))
{ {
cr->AI()->AttackStart(pWho); cr->AI()->AttackStart(pWho);
cr->AddThreat(pWho, 10.0f); cr->AddThreat(pWho, 10.0f);
} }
} }
}
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
@@ -396,18 +444,24 @@ public:
Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_REVIVE : EMOTE_FEUG_REVIVE); Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_REVIVE : EMOTE_FEUG_REVIVE);
} }
else else
{
me->SetHealth(me->GetMaxHealth()); me->SetHealth(me->GetMaxHealth());
} }
} }
}
void JustDied(Unit* ) override void JustDied(Unit* ) override
{ {
Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_DEATH : SAY_FEUG_DEATH); Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_DEATH : SAY_FEUG_DEATH);
Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_DEATH : EMOTE_FEUG_DEATH); Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_DEATH : EMOTE_FEUG_DEATH);
if (pInstance) if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS))) if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS)))
{
cr->AI()->DoAction(ACTION_SUMMON_DIED); cr->AI()->DoAction(ACTION_SUMMON_DIED);
} }
}
}
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
{ {
@@ -415,11 +469,14 @@ public:
return; return;
if (pInstance) if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0); pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
if (!urand(0, 2)) if (!urand(0, 2))
{
Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_SLAY : SAY_FEUG_SLAY); Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_SLAY : SAY_FEUG_SLAY);
} }
}
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
@@ -430,15 +487,16 @@ public:
{ {
visualTimer = 0; visualTimer = 0;
if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f)) if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f))
{
cr->CastSpell(cr, me->GetEntry() == NPC_STALAGG ? SPELL_STALAGG_CHAIN : SPELL_FEUGEN_CHAIN, false); cr->CastSpell(cr, me->GetEntry() == NPC_STALAGG ? SPELL_STALAGG_CHAIN : SPELL_FEUGEN_CHAIN, false);
} }
} }
}
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
// Disable AI during pull if (pullTimer) // Disable AI during pull
if (pullTimer)
{ {
pullTimer += diff; pullTimer += diff;
if (pullTimer >= 3000) if (pullTimer >= 3000)
@@ -455,17 +513,18 @@ public:
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
{ {
case EVENT_MINION_SPELL_POWER_SURGE: case EVENT_MINION_POWER_SURGE:
me->CastSpell(me, RAID_MODE(SPELL_POWER_SURGE_10, SPELL_POWER_SURGE_25), false); me->CastSpell(me, RAID_MODE(SPELL_POWER_SURGE_10, SPELL_POWER_SURGE_25), false);
events.RepeatEvent(19000); events.RepeatEvent(19000);
break; break;
case EVENT_MINION_SPELL_STATIC_FIELD: case EVENT_MINION_STATIC_FIELD:
me->CastSpell(me, RAID_MODE(SPELL_STATIC_FIELD_10, SPELL_STATIC_FIELD_25), false); me->CastSpell(me, RAID_MODE(SPELL_STATIC_FIELD_10, SPELL_STATIC_FIELD_25), false);
events.RepeatEvent(3000); events.RepeatEvent(3000);
break; break;
case EVENT_MINION_SPELL_MAGNETIC_PULL: case EVENT_MINION_MAGNETIC_PULL:
events.RepeatEvent(25000); events.RepeatEvent(20000);
if (pInstance) if (pInstance)
{
if (Creature* feugen = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_FEUGEN_BOSS))) if (Creature* feugen = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_FEUGEN_BOSS)))
{ {
if (!feugen->IsAlive() || !feugen->GetVictim() || !me->GetVictim()) if (!feugen->IsAlive() || !feugen->GetVictim() || !me->GetVictim())
@@ -486,7 +545,7 @@ public:
me->CastSpell(tankFeugen, SPELL_MAGNETIC_PULL, true); me->CastSpell(tankFeugen, SPELL_MAGNETIC_PULL, true);
DoAction(ACTION_MAGNETIC_PULL); DoAction(ACTION_MAGNETIC_PULL);
} }
}
break; break;
case EVENT_MINION_CHECK_DISTANCE: case EVENT_MINION_CHECK_DISTANCE:
if (Creature* cr = ObjectAccessor::GetCreature(*me, myCoil)) if (Creature* cr = ObjectAccessor::GetCreature(*me, myCoil))
@@ -514,11 +573,9 @@ public:
cr->CastSpell(cr, me->GetEntry() == NPC_STALAGG ? SPELL_STALAGG_CHAIN : SPELL_FEUGEN_CHAIN, false); cr->CastSpell(cr, me->GetEntry() == NPC_STALAGG ? SPELL_STALAGG_CHAIN : SPELL_FEUGEN_CHAIN, false);
} }
} }
events.RepeatEvent(5000); events.RepeatEvent(5000);
break; break;
} }
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
}; };
@@ -537,20 +594,29 @@ public:
{ {
uint8 count = 0; uint8 count = 0;
for (auto& ihit : targets) for (auto& ihit : targets)
{
if (ihit->GetGUID() != GetCaster()->GetGUID()) if (ihit->GetGUID() != GetCaster()->GetGUID())
{
if (Player* target = ihit->ToPlayer()) if (Player* target = ihit->ToPlayer())
{
if (target->HasAura(GetTriggeringSpell()->Id)) if (target->HasAura(GetTriggeringSpell()->Id))
{
++count; ++count;
}
}
}
}
if (count) if (count)
{ {
uint32 spellId = 0; uint32 spellId = 0;
if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE) if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE)
{
spellId = SPELL_POSITIVE_CHARGE_STACK; spellId = SPELL_POSITIVE_CHARGE_STACK;
}
else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE) else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE)
{
spellId = SPELL_NEGATIVE_CHARGE_STACK; spellId = SPELL_NEGATIVE_CHARGE_STACK;
}
GetCaster()->SetAuraStack(spellId, GetCaster(), count); GetCaster()->SetAuraStack(spellId, GetCaster(), count);
} }
} }
@@ -565,10 +631,14 @@ public:
return; return;
if (target->HasAura(GetTriggeringSpell()->Id) || target->GetTypeId() != TYPEID_PLAYER) if (target->HasAura(GetTriggeringSpell()->Id) || target->GetTypeId() != TYPEID_PLAYER)
{
SetHitDamage(0); SetHitDamage(0);
}
else if (target->GetInstanceScript()) else if (target->GetInstanceScript())
{
target->GetInstanceScript()->SetData(DATA_CHARGES_CROSSED, 0); target->GetInstanceScript()->SetData(DATA_CHARGES_CROSSED, 0);
} }
}
void Register() override void Register() override
{ {
@@ -601,19 +671,25 @@ public:
{ {
Unit* caster = GetCaster(); Unit* caster = GetCaster();
if (Unit* target = GetHitUnit()) if (Unit* target = GetHitUnit())
{
target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, nullptr, nullptr, caster->GetGUID()); target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, nullptr, nullptr, caster->GetGUID());
} }
}
void HandleAfterCast() void HandleAfterCast()
{ {
if (GetCaster()) if (GetCaster())
{
if (Creature* caster = GetCaster()->ToCreature()) if (Creature* caster = GetCaster()->ToCreature())
{
if (caster->GetEntry() == NPC_THADDIUS) if (caster->GetEntry() == NPC_THADDIUS)
{ {
caster->AI()->Talk(SAY_ELECT); caster->AI()->Talk(SAY_ELECT);
caster->AI()->Talk(EMOTE_POLARITY_SHIFTED); caster->AI()->Talk(EMOTE_POLARITY_SHIFTED);
} }
} }
}
}
void Register() override void Register() override
{ {
@@ -661,7 +737,9 @@ public:
return true; return true;
if (Creature* thaddius = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_THADDIUS_BOSS))) if (Creature* thaddius = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_THADDIUS_BOSS)))
{
thaddius->AI()->Talk(SAY_GREET); thaddius->AI()->Talk(SAY_GREET);
}
instance->SetData(DATA_HAD_THADDIUS_GREET, 1); instance->SetData(DATA_HAD_THADDIUS_GREET, 1);
return true; return true;
@@ -673,9 +751,7 @@ void AddSC_boss_thaddius()
new boss_thaddius(); new boss_thaddius();
new boss_thaddius_summon(); new boss_thaddius_summon();
new npc_tesla(); new npc_tesla();
new spell_thaddius_pos_neg_charge(); new spell_thaddius_pos_neg_charge();
new spell_thaddius_polarity_shift(); new spell_thaddius_polarity_shift();
new at_thaddius_entrance(); new at_thaddius_entrance();
} }
@@ -30,8 +30,10 @@ inline uint8 GetEruptionSection(float x, float y)
float slope = y / x; float slope = y / x;
for (uint32 i = 0; i < 3; ++i) for (uint32 i = 0; i < 3; ++i)
{
if (slope > HeiganEruptionSlope[i]) if (slope > HeiganEruptionSlope[i])
return i; return i;
}
return 3; return 3;
} }
@@ -68,6 +70,10 @@ public:
_horsemanGateGUID = 0; _horsemanGateGUID = 0;
_kelthuzadfloorGUID = 0; _kelthuzadfloorGUID = 0;
_kelthuzadgateGUID = 0; _kelthuzadgateGUID = 0;
_kelthuzadportal1GUID = 0;
_kelthuzadportal2GUID = 0;
_kelthuzadportal3GUID = 0;
_kelthuzadportal4GUID = 0;
_sapphironGateGUID = 0; _sapphironGateGUID = 0;
_horsemanPortalGUID = 0; _horsemanPortalGUID = 0;
_loathebPortalGUID = 0; _loathebPortalGUID = 0;
@@ -131,6 +137,10 @@ public:
uint64 _horsemanGateGUID; uint64 _horsemanGateGUID;
uint64 _kelthuzadfloorGUID; uint64 _kelthuzadfloorGUID;
uint64 _kelthuzadgateGUID; uint64 _kelthuzadgateGUID;
uint64 _kelthuzadportal1GUID;
uint64 _kelthuzadportal2GUID;
uint64 _kelthuzadportal3GUID;
uint64 _kelthuzadportal4GUID;
uint64 _sapphironGateGUID; uint64 _sapphironGateGUID;
uint64 _horsemanPortalGUID; uint64 _horsemanPortalGUID;
uint64 _loathebPortalGUID; uint64 _loathebPortalGUID;
@@ -272,57 +282,79 @@ public:
case GO_PATCHWERK_GATE: case GO_PATCHWERK_GATE:
_patchwerkGateGUID = pGo->GetGUID(); _patchwerkGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_PATCHWERK) == DONE) if (GetBossState(BOSS_PATCHWERK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_GLUTH_GATE: case GO_GLUTH_GATE:
_gluthGateGUID = pGo->GetGUID(); _gluthGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GLUTH) == DONE) if (GetBossState(BOSS_GLUTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_NOTH_GATE: case GO_NOTH_GATE:
_nothGateGUID = pGo->GetGUID(); _nothGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_NOTH) == DONE) if (GetBossState(BOSS_NOTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_HEIGAN_ENTERANCE_GATE: case GO_HEIGAN_ENTERANCE_GATE:
_heiganGateGUID = pGo->GetGUID(); _heiganGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_HEIGAN) == DONE || GetBossState(BOSS_NOTH) == DONE) if (GetBossState(BOSS_HEIGAN) == DONE || GetBossState(BOSS_NOTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_HEIGAN_EXIT_GATE: case GO_HEIGAN_EXIT_GATE:
_heiganGateExitGUID = pGo->GetGUID(); _heiganGateExitGUID = pGo->GetGUID();
if (GetBossState(BOSS_HEIGAN) == DONE) if (GetBossState(BOSS_HEIGAN) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_LOATHEB_GATE: case GO_LOATHEB_GATE:
_loathebGateGUID = pGo->GetGUID(); _loathebGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE) if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_ANUB_GATE: case GO_ANUB_GATE:
_anubGateGUID = pGo->GetGUID(); _anubGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_ANUB) == DONE) if (GetBossState(BOSS_ANUB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_ANUB_NEXT_GATE: case GO_ANUB_NEXT_GATE:
_anubNextGateGUID = pGo->GetGUID(); _anubNextGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_ANUB) == DONE) if (GetBossState(BOSS_ANUB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_FAERLINA_GATE: case GO_FAERLINA_GATE:
_faerlinaGateGUID = pGo->GetGUID(); _faerlinaGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_FAERLINA) == DONE) if (GetBossState(BOSS_FAERLINA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_MAEXXNA_GATE: case GO_MAEXXNA_GATE:
_maexxnaGateGUID = pGo->GetGUID(); _maexxnaGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_FAERLINA) == DONE) // faerlina is correct if (GetBossState(BOSS_FAERLINA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_THADDIUS_GATE: case GO_THADDIUS_GATE:
_thaddiusGateGUID = pGo->GetGUID(); _thaddiusGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GLUTH) == DONE) // gluth is correct if (GetBossState(BOSS_GLUTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_GOTHIK_ENTER_GATE: case GO_GOTHIK_ENTER_GATE:
_gothikEnterGateGUID = pGo->GetGUID(); _gothikEnterGateGUID = pGo->GetGUID();
@@ -333,12 +365,16 @@ public:
case GO_GOTHIK_EXIT_GATE: case GO_GOTHIK_EXIT_GATE:
_gothikExitGateGUID = pGo->GetGUID(); _gothikExitGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GOTHIK) == DONE) if (GetBossState(BOSS_GOTHIK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_HORSEMAN_GATE: case GO_HORSEMAN_GATE:
_horsemanGateGUID = pGo->GetGUID(); _horsemanGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GOTHIK) == DONE) // correct if (GetBossState(BOSS_GOTHIK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_KELTHUZAD_FLOOR: case GO_KELTHUZAD_FLOOR:
_kelthuzadfloorGUID = pGo->GetGUID(); _kelthuzadfloorGUID = pGo->GetGUID();
@@ -346,52 +382,84 @@ public:
case GO_KELTHUZAD_GATE: case GO_KELTHUZAD_GATE:
_kelthuzadgateGUID = pGo->GetGUID(); _kelthuzadgateGUID = pGo->GetGUID();
if (GetBossState(BOSS_SAPPHIRON) == DONE && _speakTimer == 0) if (GetBossState(BOSS_SAPPHIRON) == DONE && _speakTimer == 0)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_KELTHUZAD_PORTAL_1:
_kelthuzadportal1GUID = pGo->GetGUID();
break;
case GO_KELTHUZAD_PORTAL_2:
_kelthuzadportal2GUID = pGo->GetGUID();
break;
case GO_KELTHUZAD_PORTAL_3:
_kelthuzadportal3GUID = pGo->GetGUID();
break;
case GO_KELTHUZAD_PORTAL_4:
_kelthuzadportal4GUID = pGo->GetGUID();
break; break;
case GO_SAPPHIRON_GATE: case GO_SAPPHIRON_GATE:
_sapphironGateGUID = pGo->GetGUID(); _sapphironGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_SAPPHIRON) == DONE) if (GetBossState(BOSS_SAPPHIRON) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_DEATHKNIGHT_WING: case GO_DEATHKNIGHT_WING:
_loathebPortalGUID = pGo->GetGUID(); _loathebPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE) if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetPhaseMask(1, true); pGo->SetPhaseMask(1, true);
}
break; break;
case GO_THADDIUS_PORTAL: case GO_THADDIUS_PORTAL:
_thaddiusPortalGUID = pGo->GetGUID(); _thaddiusPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_THADDIUS) == DONE) if (GetBossState(BOSS_THADDIUS) == DONE)
{
pGo->SetPhaseMask(1, true); pGo->SetPhaseMask(1, true);
}
break; break;
case GO_MAEXXNA_PORTAL: case GO_MAEXXNA_PORTAL:
_maexxnaPortalGUID = pGo->GetGUID(); _maexxnaPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_MAEXXNA) == DONE) if (GetBossState(BOSS_MAEXXNA) == DONE)
{
pGo->SetPhaseMask(1, true); pGo->SetPhaseMask(1, true);
}
break; break;
case GO_HORSEMAN_PORTAL: case GO_HORSEMAN_PORTAL:
_horsemanPortalGUID = pGo->GetGUID(); _horsemanPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_HORSEMAN) == DONE) if (GetBossState(BOSS_HORSEMAN) == DONE)
{
pGo->SetPhaseMask(1, true); pGo->SetPhaseMask(1, true);
}
break; break;
case GO_DEATHKNIGHT_EYE_PORTAL: case GO_DEATHKNIGHT_EYE_PORTAL:
_deathknightEyePortalGUID = pGo->GetGUID(); _deathknightEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_HORSEMAN) == DONE) if (GetBossState(BOSS_HORSEMAN) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_PLAGUE_EYE_PORTAL: case GO_PLAGUE_EYE_PORTAL:
_plagueEyePortalGUID = pGo->GetGUID(); _plagueEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE) if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_SPIDER_EYE_PORTAL: case GO_SPIDER_EYE_PORTAL:
_spiderEyePortalGUID = pGo->GetGUID(); _spiderEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_MAEXXNA) == DONE) if (GetBossState(BOSS_MAEXXNA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case GO_ABOM_EYE_PORTAL: case GO_ABOM_EYE_PORTAL:
_abomEyePortalGUID = pGo->GetGUID(); _abomEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_THADDIUS) == DONE) if (GetBossState(BOSS_THADDIUS) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE); pGo->SetGoState(GO_STATE_ACTIVE);
}
break; break;
} }
} }
@@ -404,11 +472,14 @@ public:
HeiganEruption[section].erase(pGo); HeiganEruption[section].erase(pGo);
return; return;
} }
if (pGo->GetEntry() == GO_SAPPHIRON_BIRTH) if (pGo->GetEntry() == GO_SAPPHIRON_BIRTH)
{
if (Creature* cr = instance->GetCreature(_sapphironGUID)) if (Creature* cr = instance->GetCreature(_sapphironGUID))
{
cr->AI()->DoAction(ACTION_SAPPHIRON_BIRTH); cr->AI()->DoAction(ACTION_SAPPHIRON_BIRTH);
} }
}
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
{ {
@@ -484,9 +555,10 @@ public:
{ {
uint8 count = 0; uint8 count = 0;
for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
{
if (GetBossState(i) == NOT_STARTED) if (GetBossState(i) == NOT_STARTED)
++count; ++count;
}
return !count && immortalAchievement; return !count && immortalAchievement;
} }
@@ -550,10 +622,12 @@ public:
{ {
Creature* trash = ObjectAccessor::GetCreature(*patch, itr); Creature* trash = ObjectAccessor::GetCreature(*patch, itr);
if (trash && trash->IsAlive() && !trash->IsInCombat()) if (trash && trash->IsAlive() && !trash->IsInCombat())
{
trash->AI()->AttackStart(patch->GetVictim()); trash->AI()->AttackStart(patch->GetVictim());
} }
} }
} }
}
// Horseman handling // Horseman handling
if (bossId == BOSS_HORSEMAN && _horsemanLoadDoneState == false) if (bossId == BOSS_HORSEMAN && _horsemanLoadDoneState == false)
@@ -566,11 +640,12 @@ public:
{ {
return false; return false;
} }
// All horsemans are killed // All horsemans are killed
if (Creature* cr = instance->GetCreature(_blaumeuxGUID)) if (Creature* cr = instance->GetCreature(_blaumeuxGUID))
{
cr->CastSpell(cr, 59450, true); // credit cr->CastSpell(cr, 59450, true); // credit
} }
}
// respawn // respawn
else if (state == NOT_STARTED && _horsemanKilled > 0) else if (state == NOT_STARTED && _horsemanKilled > 0)
@@ -578,46 +653,64 @@ public:
Creature* cr; Creature* cr;
_horsemanKilled = 0; _horsemanKilled = 0;
if ((cr = instance->GetCreature(_blaumeuxGUID))) if ((cr = instance->GetCreature(_blaumeuxGUID)))
{
if (!cr->IsAlive()) if (!cr->IsAlive())
{ {
cr->SetPosition(cr->GetHomePosition()); cr->SetPosition(cr->GetHomePosition());
cr->Respawn(); cr->Respawn();
} }
}
if ((cr = instance->GetCreature(_rivendareGUID))) if ((cr = instance->GetCreature(_rivendareGUID)))
{
if (!cr->IsAlive()) if (!cr->IsAlive())
{ {
cr->SetPosition(cr->GetHomePosition()); cr->SetPosition(cr->GetHomePosition());
cr->Respawn(); cr->Respawn();
} }
}
if ((cr = instance->GetCreature(_zeliekGUID))) if ((cr = instance->GetCreature(_zeliekGUID)))
{
if (!cr->IsAlive()) if (!cr->IsAlive())
{ {
cr->SetPosition(cr->GetHomePosition()); cr->SetPosition(cr->GetHomePosition());
cr->Respawn(); cr->Respawn();
} }
}
if ((cr = instance->GetCreature(_korthazzGUID))) if ((cr = instance->GetCreature(_korthazzGUID)))
{
if (!cr->IsAlive()) if (!cr->IsAlive())
{ {
cr->SetPosition(cr->GetHomePosition()); cr->SetPosition(cr->GetHomePosition());
cr->Respawn(); cr->Respawn();
} }
} }
}
else if (state == IN_PROGRESS) else if (state == IN_PROGRESS)
{ {
Creature* cr; Creature* cr;
if ((cr = instance->GetCreature(_blaumeuxGUID))) if ((cr = instance->GetCreature(_blaumeuxGUID)))
{
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_rivendareGUID))) if ((cr = instance->GetCreature(_rivendareGUID)))
{
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_zeliekGUID))) if ((cr = instance->GetCreature(_zeliekGUID)))
{
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_korthazzGUID))) if ((cr = instance->GetCreature(_korthazzGUID)))
{
cr->SetInCombatWithZone(); cr->SetInCombatWithZone();
} }
}
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
_horsemanTimer = 0; _horsemanTimer = 0;
} }
}
if (!InstanceScript::SetBossState(bossId, state)) if (!InstanceScript::SetBossState(bossId, state))
return false; return false;
@@ -627,23 +720,33 @@ public:
{ {
case BOSS_KELTHUZAD: case BOSS_KELTHUZAD:
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
abominationsKilled = 0; abominationsKilled = 0;
}
break; break;
case BOSS_FAERLINA: case BOSS_FAERLINA:
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
faerlinaAchievement = true; faerlinaAchievement = true;
}
break; break;
case BOSS_THADDIUS: case BOSS_THADDIUS:
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
thaddiusAchievement = true; thaddiusAchievement = true;
}
break; break;
case BOSS_LOATHEB: case BOSS_LOATHEB:
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
loathebAchievement = true; loathebAchievement = true;
}
break; break;
case BOSS_HEIGAN: case BOSS_HEIGAN:
if (state == NOT_STARTED) if (state == NOT_STARTED)
{
heiganAchievement = true; heiganAchievement = true;
}
break; break;
case BOSS_SAPPHIRON: case BOSS_SAPPHIRON:
if (state == DONE) if (state == DONE)
@@ -653,7 +756,9 @@ public:
instance->LoadGrid(3763.43f, -5115.87f); instance->LoadGrid(3763.43f, -5115.87f);
} }
else if (state == NOT_STARTED) else if (state == NOT_STARTED)
{
sapphironAchievement = true; sapphironAchievement = true;
}
break; break;
default: default:
break; break;
@@ -668,87 +773,133 @@ public:
{ {
case BOSS_PATCHWERK: case BOSS_PATCHWERK:
if (GameObject* go = instance->GetGameObject(_patchwerkGateGUID)) if (GameObject* go = instance->GetGameObject(_patchwerkGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_GLUTH: case BOSS_GLUTH:
if (GameObject* go = instance->GetGameObject(_gluthGateGUID)) if (GameObject* go = instance->GetGameObject(_gluthGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_thaddiusGateGUID)) if (GameObject* go = instance->GetGameObject(_thaddiusGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_NOTH: case BOSS_NOTH:
if (GameObject* go = instance->GetGameObject(_nothGateGUID)) if (GameObject* go = instance->GetGameObject(_nothGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_heiganGateGUID)) if (GameObject* go = instance->GetGameObject(_heiganGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_HEIGAN: case BOSS_HEIGAN:
if (GameObject* go = instance->GetGameObject(_heiganGateGUID)) if (GameObject* go = instance->GetGameObject(_heiganGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_heiganGateExitGUID)) if (GameObject* go = instance->GetGameObject(_heiganGateExitGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_LOATHEB: case BOSS_LOATHEB:
if (GameObject* go = instance->GetGameObject(_loathebGateGUID)) if (GameObject* go = instance->GetGameObject(_loathebGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_loathebPortalGUID)) if (GameObject* go = instance->GetGameObject(_loathebPortalGUID))
{
go->SetPhaseMask(1, true); go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_plagueEyePortalGUID)) if (GameObject* go = instance->GetGameObject(_plagueEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break; break;
case BOSS_ANUB: case BOSS_ANUB:
if (GameObject* go = instance->GetGameObject(_anubGateGUID)) if (GameObject* go = instance->GetGameObject(_anubGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_anubNextGateGUID)) if (GameObject* go = instance->GetGameObject(_anubNextGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_FAERLINA: case BOSS_FAERLINA:
if (GameObject* go = instance->GetGameObject(_faerlinaGateGUID)) if (GameObject* go = instance->GetGameObject(_faerlinaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID)) if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_MAEXXNA: case BOSS_MAEXXNA:
if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID)) if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_maexxnaPortalGUID)) if (GameObject* go = instance->GetGameObject(_maexxnaPortalGUID))
{
go->SetPhaseMask(1, true); go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_spiderEyePortalGUID)) if (GameObject* go = instance->GetGameObject(_spiderEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break; break;
case BOSS_GOTHIK: case BOSS_GOTHIK:
if (GameObject* go = instance->GetGameObject(_gothikEnterGateGUID)) if (GameObject* go = instance->GetGameObject(_gothikEnterGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_gothikExitGateGUID)) if (GameObject* go = instance->GetGameObject(_gothikExitGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_horsemanGateGUID)) if (GameObject* go = instance->GetGameObject(_horsemanGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
case BOSS_SAPPHIRON: case BOSS_SAPPHIRON:
if (GameObject* go = instance->GetGameObject(_sapphironGateGUID)) events.ScheduleEvent(EVENT_FROSTWYRM_WATERFALL_DOOR, 5000);
go->SetGoState(GO_STATE_ACTIVE);
break; break;
case BOSS_THADDIUS: case BOSS_THADDIUS:
if (GameObject* go = instance->GetGameObject(_thaddiusPortalGUID)) if (GameObject* go = instance->GetGameObject(_thaddiusPortalGUID))
{
go->SetPhaseMask(1, true); go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_abomEyePortalGUID)) if (GameObject* go = instance->GetGameObject(_abomEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break; break;
case BOSS_HORSEMAN: case BOSS_HORSEMAN:
if (GameObject* go = instance->GetGameObject(_horsemanPortalGUID)) if (GameObject* go = instance->GetGameObject(_horsemanPortalGUID))
{
go->SetPhaseMask(1, true); go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_deathknightEyePortalGUID)) if (GameObject* go = instance->GetGameObject(_deathknightEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break; break;
default: default:
break; break;
} }
} }
return true; return true;
} }
@@ -759,9 +910,13 @@ public:
Creature* kel = instance->GetCreature(_kelthuzadGUID); Creature* kel = instance->GetCreature(_kelthuzadGUID);
Creature* lich = instance->GetCreature(_lichkingGUID); Creature* lich = instance->GetCreature(_lichkingGUID);
if (kel && lich) if (kel && lich)
{
_speakTimer += diff; _speakTimer += diff;
}
else else
{
return; return;
}
if (_speakTimer > 10000 && _speakTimer < 20000) if (_speakTimer > 10000 && _speakTimer < 20000)
{ {
kel->AI()->Talk(SAY_SAPP_DIALOG1); kel->AI()->Talk(SAY_SAPP_DIALOG1);
@@ -792,13 +947,17 @@ public:
kel->AI()->Talk(SAY_SAPP_DIALOG6); kel->AI()->Talk(SAY_SAPP_DIALOG6);
_speakTimer = 0; _speakTimer = 0;
if (GameObject* go = instance->GetGameObject(_kelthuzadgateGUID)) if (GameObject* go = instance->GetGameObject(_kelthuzadgateGUID))
{
go->SetGoState(GO_STATE_ACTIVE); go->SetGoState(GO_STATE_ACTIVE);
} }
} }
}
// And They would all // And They would all
if (_horsemanTimer) if (_horsemanTimer)
{
_horsemanTimer += diff; _horsemanTimer += diff;
}
if (_screamTimer && GetBossState(BOSS_THADDIUS) != DONE) if (_screamTimer && GetBossState(BOSS_THADDIUS) != DONE)
{ {
@@ -808,8 +967,10 @@ public:
_screamTimer = (2 * MINUTE + urand(0, 30)) * IN_MILLISECONDS; _screamTimer = (2 * MINUTE + urand(0, 30)) * IN_MILLISECONDS;
} }
else else
{
_screamTimer -= diff; _screamTimer -= diff;
} }
}
events.Update(diff); events.Update(diff);
switch (events.ExecuteEvent()) switch (events.ExecuteEvent())
@@ -818,9 +979,16 @@ public:
// Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work. // Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work.
instance->LoadGrid(3749.67f, -5114.06f); instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(_kelthuzadGUID)) if (Creature* kelthuzad = instance->GetCreature(_kelthuzadGUID))
{
kelthuzad->AI()->Talk(_currentWingTaunt); kelthuzad->AI()->Talk(_currentWingTaunt);
}
++_currentWingTaunt; ++_currentWingTaunt;
break;
case EVENT_FROSTWYRM_WATERFALL_DOOR:
if (GameObject* go = instance->GetGameObject(_sapphironGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break; break;
} }
} }
@@ -848,6 +1016,14 @@ public:
return _kelthuzadfloorGUID; return _kelthuzadfloorGUID;
case DATA_KELTHUZAD_GATE: case DATA_KELTHUZAD_GATE:
return _kelthuzadgateGUID; return _kelthuzadgateGUID;
case DATA_KELTHUZAD_PORTAL_1:
return _kelthuzadportal1GUID;
case DATA_KELTHUZAD_PORTAL_2:
return _kelthuzadportal2GUID;
case DATA_KELTHUZAD_PORTAL_3:
return _kelthuzadportal3GUID;
case DATA_KELTHUZAD_PORTAL_4:
return _kelthuzadportal4GUID;
// NPCs // NPCs
case DATA_THADDIUS_BOSS: case DATA_THADDIUS_BOSS:
@@ -896,9 +1072,13 @@ public:
uint32 tmpState; uint32 tmpState;
loadStream >> tmpState; loadStream >> tmpState;
if (tmpState == IN_PROGRESS) if (tmpState == IN_PROGRESS)
{
tmpState = NOT_STARTED; tmpState = NOT_STARTED;
}
if (i == BOSS_HORSEMAN && tmpState == DONE) if (i == BOSS_HORSEMAN && tmpState == DONE)
{
_horsemanLoadDoneState = true; _horsemanLoadDoneState = true;
}
SetBossState(i, EncounterState(tmpState)); SetBossState(i, EncounterState(tmpState));
} }
loadStream >> immortalAchievement; loadStream >> immortalAchievement;
@@ -906,8 +1086,10 @@ public:
OUT_LOAD_INST_DATA_COMPLETE; OUT_LOAD_INST_DATA_COMPLETE;
} }
else else
{
OUT_LOAD_INST_DATA_FAIL; OUT_LOAD_INST_DATA_FAIL;
} }
}
}; };
}; };
class boss_naxxramas_misc : public CreatureScript class boss_naxxramas_misc : public CreatureScript
@@ -963,9 +1145,11 @@ public:
acore::UnitLastSearcher<acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, target, u_check); acore::UnitLastSearcher<acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, target, u_check);
me->VisitNearbyObject(1.5f, searcher); me->VisitNearbyObject(1.5f, searcher);
if (target) if (target)
{
me->CastSpell(me, SPELL_FROGGER_EXPLODE, true); me->CastSpell(me, SPELL_FROGGER_EXPLODE, true);
} }
} }
}
}; };
}; };
@@ -51,6 +51,10 @@ enum NXData
DATA_IMMORTAL_FAIL = 119, DATA_IMMORTAL_FAIL = 119,
DATA_KELTHUZAD_GATE = 120, DATA_KELTHUZAD_GATE = 120,
DATA_HAD_THADDIUS_GREET = 121, DATA_HAD_THADDIUS_GREET = 121,
DATA_KELTHUZAD_PORTAL_1 = 122,
DATA_KELTHUZAD_PORTAL_2 = 123,
DATA_KELTHUZAD_PORTAL_3 = 124,
DATA_KELTHUZAD_PORTAL_4 = 125
}; };
enum NXGOs enum NXGOs
@@ -78,19 +82,20 @@ enum NXGOs
GO_SAPPHIRON_BIRTH = 181356, GO_SAPPHIRON_BIRTH = 181356,
GO_KELTHUZAD_FLOOR = 181444, GO_KELTHUZAD_FLOOR = 181444,
GO_KELTHUZAD_GATE = 181228, GO_KELTHUZAD_GATE = 181228,
GO_KELTHUZAD_PORTAL_1 = 181402,
GO_KELTHUZAD_PORTAL_2 = 181403,
GO_KELTHUZAD_PORTAL_3 = 181404,
GO_KELTHUZAD_PORTAL_4 = 181405,
GO_DEATHKNIGHT_WING = 181577, //Loatheb portal GO_DEATHKNIGHT_WING = 181577,
GO_THADDIUS_PORTAL = 181576, //Thadius portal GO_THADDIUS_PORTAL = 181576,
GO_MAEXXNA_PORTAL = 181575, //Maexxna portal GO_MAEXXNA_PORTAL = 181575,
GO_HORSEMAN_PORTAL = 181578, //Four Horseman portal GO_HORSEMAN_PORTAL = 181578,
GO_DEATHKNIGHT_EYE_PORTAL = 181210, GO_DEATHKNIGHT_EYE_PORTAL = 181210,
GO_PLAGUE_EYE_PORTAL = 181211, GO_PLAGUE_EYE_PORTAL = 181211,
GO_SPIDER_EYE_PORTAL = 181212, GO_SPIDER_EYE_PORTAL = 181212,
GO_ABOM_EYE_PORTAL = 181213, GO_ABOM_EYE_PORTAL = 181213
GO_CONS_NOX_TESLA_STALAGG = 268049,
GO_CONS_NOX_TESLA_FEUGEN = 268050
}; };
enum NXNPCs enum NXNPCs
@@ -130,14 +135,11 @@ enum NXNPCs
enum NXMisc enum NXMisc
{ {
// Spells
SPELL_ERUPTION = 29371, SPELL_ERUPTION = 29371,
SPELL_FROGGER_EXPLODE = 28433, SPELL_FROGGER_EXPLODE = 28433,
// Actions
ACTION_SAPPHIRON_BIRTH = 1, ACTION_SAPPHIRON_BIRTH = 1,
// Sounds
// Background screams in instance if Thaddius still alive, four of them from 8873 to 8876 // Background screams in instance if Thaddius still alive, four of them from 8873 to 8876
SOUND_SCREAM = 8873 SOUND_SCREAM = 8873
}; };
@@ -157,7 +159,8 @@ enum NXSays
enum NXEvents enum NXEvents
{ {
EVENT_THADDIUS_SCREAMS = 0, EVENT_THADDIUS_SCREAMS = 0,
EVENT_KELTHUZAD_WING_TAUNT EVENT_KELTHUZAD_WING_TAUNT = 1,
EVENT_FROSTWYRM_WATERFALL_DOOR = 2
}; };
#endif #endif