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

View File

@@ -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');

View File

@@ -14,6 +14,12 @@ enum Says
EMOTE_LOCUST = 3
};
enum GuardSays
{
EMOTE_SPAWN = 1,
EMOTE_SCARAB = 2
};
enum Spells
{
SPELL_IMPALE_10 = 28783,
@@ -22,14 +28,15 @@ enum Spells
SPELL_LOCUST_SWARM_25 = 54021,
SPELL_SUMMON_CORPSE_SCRABS_5 = 29105,
SPELL_SUMMON_CORPSE_SCRABS_10 = 28864,
SPELL_BERSERK = 26662,
SPELL_BERSERK = 26662
};
enum Events
{
EVENT_SPELL_IMPALE = 1,
EVENT_SPELL_LOCUST_SWARM = 2,
EVENT_SPELL_BERSERK = 3,
EVENT_IMPALE = 1,
EVENT_LOCUST_SWARM = 2,
EVENT_BERSERK = 3,
EVENT_SPAWN_GUARD = 4
};
enum Misc
@@ -37,7 +44,7 @@ enum Misc
NPC_CORPSE_SCARAB = 16698,
NPC_CRYPT_GUARD = 16573,
ACHIEV_TIMED_START_EVENT = 9891,
ACHIEV_TIMED_START_EVENT = 9891
};
class boss_anubrekhan : public CreatureScript
@@ -67,8 +74,8 @@ public:
{
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.087f, -3450.93f, 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.086f, -3450.929f, 287.077f, 3.999f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}
}
@@ -78,35 +85,41 @@ public:
events.Reset();
summons.DespawnAll();
SummonCryptGuards();
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
void JustSummoned(Creature* cr) override
{
if (me->IsInCombat())
cr->SetInCombatWithZone();
if (cr->GetEntry() == NPC_CORPSE_SCARAB)
{
cr->SetReactState(REACT_PASSIVE);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
cr->AI()->AttackStart(target);
cr->SetInCombatWithZone();
if (cr->GetEntry() == NPC_CRYPT_GUARD)
{
cr->AI()->Talk(EMOTE_SPAWN, me);
}
}
summons.Summon(cr);
}
void SummonedCreatureDies(Creature* cr, Unit*) override
{
if (cr->GetEntry() == NPC_CRYPT_GUARD)
{
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
{
@@ -124,31 +137,36 @@ public:
return;
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());
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void EnterCombat(Unit* who) override
{
BossAI::EnterCombat(who);
me->CallForHelp(30.0f); // catch helpers
me->CallForHelp(30.0f);
Talk(SAY_AGGRO);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
events.ScheduleEvent(EVENT_SPELL_IMPALE, 15000);
events.ScheduleEvent(EVENT_SPELL_LOCUST_SWARM, 70000 + urand(0, 50000));
events.ScheduleEvent(EVENT_SPELL_BERSERK, 600000);
events.ScheduleEvent(EVENT_IMPALE, 15000);
events.ScheduleEvent(EVENT_LOCUST_SWARM, urand(70000, 120000));
events.ScheduleEvent(EVENT_BERSERK, 600000);
if (!summons.HasEntry(NPC_CRYPT_GUARD))
{
SummonCryptGuards();
}
if (!Is25ManRaid())
{
events.ScheduleEvent(EVENT_SPAWN_GUARD, urand(15000, 20000));
}
}
void MoveInLineOfSight(Unit* who) override
@@ -158,12 +176,26 @@ public:
Talk(SAY_GREET);
sayGreet = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
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())
return;
@@ -173,27 +205,26 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_IMPALE:
case EVENT_IMPALE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
me->CastSpell(target, RAID_MODE(SPELL_IMPALE_10, SPELL_IMPALE_25), false);
}
events.RepeatEvent(20000);
break;
case EVENT_SPELL_LOCUST_SWARM:
{
Talk(EMOTE_LOCUST);
me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false);
Position pos;
me->GetNearPosition(pos, 10.0f, rand_norm() * 2 * M_PI);
me->SummonCreature(NPC_CRYPT_GUARD, pos);
events.RepeatEvent(90000);
break;
}
case EVENT_SPELL_BERSERK:
case EVENT_LOCUST_SWARM:
Talk(EMOTE_LOCUST);
me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false);
events.ScheduleEvent(EVENT_SPAWN_GUARD, 3000);
events.RepeatEvent(90000);
break;
case EVENT_SPAWN_GUARD:
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);
break;
}
DoMeleeAttackIfReady();
}
};

View File

@@ -27,19 +27,22 @@ enum Spells
SPELL_FRENZY_10 = 28798,
SPELL_FRENZY_25 = 54100,
SPELL_WIDOWS_EMBRACE = 28732,
SPELL_MINION_WIDOWS_EMBRACE = 54097
};
enum Events
{
EVENT_SPELL_POISON_BOLT = 1,
EVENT_SPELL_RAIN_OF_FIRE = 2,
EVENT_SPELL_FRENZY = 3,
EVENT_POISON_BOLT = 1,
EVENT_RAIN_OF_FIRE = 2,
EVENT_FRENZY = 3
};
enum Misc
{
NPC_NAXXRAMAS_WORSHIPPER = 16506,
NPC_NAXXRAMAS_FOLLOWER = 16505,
SPIDER_WEB_ENTRANCE = 181235
};
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, 3356.71f, -3620.05f, 261.08f, 4.57276f);
me->SummonCreature(NPC_NAXXRAMAS_WORSHIPPER, 3350.26f, -3619.11f, 261.08f, 4.67748f);
// Followers
if (Is25ManRaid())
{
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
{
@@ -88,6 +92,10 @@ public:
events.Reset();
summons.DespawnAll();
SummonHelpers();
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
void EnterCombat(Unit* who) override
@@ -96,10 +104,14 @@ public:
me->CallForHelp(VISIBLE_RANGE);
summons.DoZoneInCombat();
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_POISON_BOLT, urand(12000, 15000));
events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, urand(6000, 18000));
events.ScheduleEvent(EVENT_SPELL_FRENZY, urand(60000, 80000), 1);
events.ScheduleEvent(EVENT_POISON_BOLT, urand(7000, 15000));
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, urand(8000, 18000));
events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000), 1);
events.SetPhase(1);
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
}
void MoveInLineOfSight(Unit* who) override
@@ -109,7 +121,6 @@ public:
Talk(SAY_GREET);
sayGreet = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
@@ -119,20 +130,42 @@ public:
return;
if (!urand(0, 3))
{
Talk(SAY_SLAY);
}
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_DEATH);
if (GameObject* go = me->FindNearestGameObject(SPIDER_WEB_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
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())
return;
@@ -142,17 +175,21 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_POISON_BOLT:
if (!me->HasAura(SPELL_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);
case EVENT_POISON_BOLT:
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, RAID_MODE(3, 10), me, false);
}
events.RepeatEvent(urand(7000, 15000));
break;
case EVENT_SPELL_RAIN_OF_FIRE:
case EVENT_RAIN_OF_FIRE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
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;
case EVENT_SPELL_FRENZY:
case EVENT_FRENZY:
if (!me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25)))
{
Talk(SAY_FRENZY);
@@ -161,25 +198,29 @@ public:
events.RepeatEvent(60000);
}
else
{
events.RepeatEvent(30000);
}
break;
}
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);
if (me->HasAura(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);
if (Is25ManRaid())
{
Unit::Kill(caster, caster);
}
}
}
};

View File

@@ -12,44 +12,39 @@
enum Spells
{
SPELL_BERSERK = 26662,
// Marks
SPELL_MARK_OF_KORTHAZZ = 28832,
SPELL_MARK_OF_BLAUMEUX = 28833,
SPELL_MARK_OF_RIVENDARE = 28834,
SPELL_MARK_OF_ZELIEK = 28835,
SPELL_MARK_DAMAGE = 28836,
// Korth'azz
SPELL_KORTHAZZ_METEOR_10 = 28884,
SPELL_KORTHAZZ_METEOR_25 = 57467,
// Blaumeux
SPELL_BLAUMEUX_SHADOW_BOLT_10 = 57374,
SPELL_BLAUMEUX_SHADOW_BOLT_25 = 57464,
SPELL_BLAUMEUX_VOID_ZONE_10 = 28863,
SPELL_BLAUMEUX_VOID_ZONE_25 = 57463,
SPELL_BLAUMEUX_UNYIELDING_PAIN = 57381,
// Zeliek
SPELL_ZELIEK_HOLY_WRATH_10 = 28883,
SPELL_ZELIEK_HOLY_WRATH_25 = 57466,
SPELL_ZELIEK_HOLY_BOLT_10 = 57376,
SPELL_ZELIEK_HOLY_BOLT_25 = 57465,
SPELL_ZELIEK_CONDEMNATION = 57377,
// Rivendare
SPELL_RIVENDARE_UNHOLY_SHADOW_10 = 28882,
SPELL_RIVENDARE_UNHOLY_SHADOW_25 = 57369,
SPELL_RIVENDARE_UNHOLY_SHADOW_25 = 57369
};
enum Events
{
EVENT_SPELL_MARK_CAST = 1,
EVENT_SPELL_PRIMARY = 2,
EVENT_SPELL_SECONDARY = 3,
EVENT_SPELL_PUNISH = 4,
EVENT_BERSERK = 5,
EVENT_MARK_CAST = 1,
EVENT_PRIMARY_SPELL = 2,
EVENT_SECONDARY_SPELL = 3,
EVENT_PUNISH = 4,
EVENT_BERSERK = 5
};
enum Misc
@@ -58,12 +53,11 @@ enum Misc
MOVE_PHASE_NONE = 0,
MOVE_PHASE_STARTED = 1,
MOVE_PHASE_FINISHED = 2,
// Horseman
HORSEMAN_ZELIEK = 0,
HORSEMAN_BLAUMEUX = 1,
HORSEMAN_RIVENDARE = 2,
HORSEMAN_KORTHAZZ = 3,
HORSEMAN_KORTHAZZ = 3
};
enum FourHorsemen
@@ -72,20 +66,21 @@ enum FourHorsemen
SAY_TAUNT = 1,
SAY_SPECIAL = 2,
SAY_SLAY = 3,
SAY_DEATH = 4
SAY_DEATH = 4,
EMOTE_RAGECAST = 7
};
// MARKS
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_25[4] = {SPELL_ZELIEK_HOLY_BOLT_25, SPELL_BLAUMEUX_SHADOW_BOLT_25, SPELL_RIVENDARE_UNHOLY_SHADOW_25, SPELL_KORTHAZZ_METEOR_25};
// PUNISH
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_25[4] = {SPELL_ZELIEK_HOLY_WRATH_25, SPELL_BLAUMEUX_VOID_ZONE_25, 0, 0};
@@ -106,7 +101,7 @@ const Position WaypointPositions[12] =
// Sir waypoints
{2534.5f, -2921.7f, 241.53f, 1.363f},
{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
@@ -174,7 +169,6 @@ public:
EnterEvadeMode();
return false;
}
return true;
}
@@ -186,17 +180,16 @@ public:
currentWaypoint = 0;
me->SetReactState(REACT_AGGRESSIVE);
events.Reset();
// Schedule Events
events.RescheduleEvent(EVENT_SPELL_MARK_CAST, 24000);
events.RescheduleEvent(EVENT_BERSERK, 100 * 15000);
events.RescheduleEvent(EVENT_MARK_CAST, 24000);
events.RescheduleEvent(EVENT_BERSERK, 600000);
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
{
events.RescheduleEvent(EVENT_SPELL_PUNISH, 5000);
events.RescheduleEvent(EVENT_SPELL_SECONDARY, 15000);
events.RescheduleEvent(EVENT_PUNISH, 5000);
events.RescheduleEvent(EVENT_SECONDARY_SPELL, 15000);
}
}
@@ -210,14 +203,12 @@ public:
{
movementPhase = MOVE_PHASE_FINISHED;
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
if (!UpdateVictim())
{
EnterEvadeMode();
return;
}
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
me->GetMotionMaster()->Clear(false);
@@ -225,7 +216,6 @@ public:
}
return;
}
currentWaypoint = id + 1;
}
@@ -234,9 +224,13 @@ public:
if (movementPhase == MOVE_PHASE_FINISHED)
{
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
me->Attack(who, false);
}
else
{
ScriptedAI::AttackStart(who);
}
}
}
@@ -246,9 +240,10 @@ public:
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
@@ -259,11 +254,14 @@ public:
if (pInstance->GetBossState(BOSS_HORSEMAN) == DONE)
{
if (!me->GetMap()->GetPlayers().isEmpty())
{
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);
}
}
}
}
Talk(SAY_DEATH);
}
@@ -273,7 +271,6 @@ public:
if (movementPhase == MOVE_PHASE_NONE)
{
Talk(SAY_AGGRO);
me->SetReactState(REACT_PASSIVE);
movementPhase = MOVE_PHASE_STARTED;
me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
@@ -301,27 +298,28 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_MARK_CAST:
case EVENT_MARK_CAST:
me->CastSpell(me, TABLE_SPELL_MARK[horsemanId], false);
events.RepeatEvent((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) ? 15000 : 12000);
return;
case EVENT_BERSERK:
Talk(SAY_SPECIAL);
me->CastSpell(me, SPELL_BERSERK, true);
return;
case EVENT_SPELL_PRIMARY:
case EVENT_PRIMARY_SPELL:
Talk(SAY_TAUNT);
me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false);
events.RepeatEvent(15000);
return;
case EVENT_SPELL_PUNISH:
case EVENT_PUNISH:
if (!SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true))
{
me->CastSpell(me, TABLE_SPELL_PUNISH[horsemanId], false);
events.RepeatEvent(3000);
Talk(EMOTE_RAGECAST);
}
events.RepeatEvent(2010);
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);
events.RepeatEvent(15000);
return;
@@ -330,10 +328,14 @@ public:
if ((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK))
{
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);
}
}
else
{
DoMeleeAttackIfReady();
}
}
};
};
@@ -361,23 +363,25 @@ public:
damage = 500;
break;
case 3:
damage = 1000;
break;
case 4:
damage = 1500;
break;
case 5:
case 4:
damage = 4000;
break;
case 6:
case 5:
damage = 12000;
break;
case 6:
damage = 20000;
break;
default:
damage = 20000 + 1000 * (GetStackAmount() - 7);
break;
}
if (damage)
{
caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget());
}
}
}

View File

@@ -17,38 +17,38 @@ enum Spells
SPELL_DECIMATE_25 = 54426,
SPELL_BERSERK = 26662,
SPELL_INFECTED_WOUND = 29306,
SPELL_CHOW_SEARCHER = 28404,
SPELL_CHOW_SEARCHER = 28404
};
enum Events
{
EVENT_SPELL_MORTAL_WOUND = 1,
EVENT_SPELL_ENRAGE = 2,
EVENT_SPELL_DECIMATE = 3,
EVENT_SPELL_BERSERK = 4,
EVENT_MORTAL_WOUND = 1,
EVENT_ENRAGE = 2,
EVENT_DECIMATE = 3,
EVENT_BERSERK = 4,
EVENT_SUMMON_ZOMBIE = 5,
EVENT_CAN_EAT_ZOMBIE = 6,
EVENT_CAN_EAT_ZOMBIE = 6
};
enum Misc
{
NPC_ZOMBIE_CHOW = 16360,
NPC_ZOMBIE_CHOW = 16360
};
enum Emotes
{
EMOTE_SPOTS_ONE = 0,
EMOTE_DECIMATE = 1,
EMOTE_ENRAGE = 2,
EMOTE_DEVOURS_ALL = 3,
EMOTE_BERSERK = 4
EMOTE_SPOTS_ONE = 0,
EMOTE_DECIMATE = 1,
EMOTE_ENRAGE = 2,
EMOTE_DEVOURS_ALL = 3,
EMOTE_BERSERK = 4
};
const Position zombiePos[3] =
{
{3267.9f, -3172.1f, 297.42f, 0.94f},
{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
@@ -91,7 +91,9 @@ public:
Talk(EMOTE_SPOTS_ONE);
}
else
{
ScriptedAI::MoveInLineOfSight(who);
}
}
}
@@ -99,10 +101,10 @@ public:
{
BossAI::EnterCombat(who);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_MORTAL_WOUND, 10000);
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 30000);
events.ScheduleEvent(EVENT_SPELL_DECIMATE, 105000);
events.ScheduleEvent(EVENT_SPELL_BERSERK, 8 * 60000);
events.ScheduleEvent(EVENT_MORTAL_WOUND, 10000);
events.ScheduleEvent(EVENT_ENRAGE, 22000);
events.ScheduleEvent(EVENT_DECIMATE, RAID_MODE(110000, 90000));
events.ScheduleEvent(EVENT_BERSERK, 360000);
events.ScheduleEvent(EVENT_SUMMON_ZOMBIE, 10000);
events.ScheduleEvent(EVENT_CAN_EAT_ZOMBIE, 1000);
}
@@ -110,8 +112,9 @@ public:
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() == NPC_ZOMBIE_CHOW)
{
summon->AI()->AttackStart(me);
}
summons.Summon(summon);
}
@@ -120,10 +123,13 @@ public:
void KilledUnit(Unit* who) override
{
if (me->IsAlive() && who->GetEntry() == NPC_ZOMBIE_CHOW)
{
me->ModifyHealth(int32(me->GetMaxHealth() * 0.05f));
}
if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
@@ -143,13 +149,13 @@ public:
Player* player = itr.GetSource();
if (!player || !player->IsAlive())
continue;
if (player->GetPositionZ() > 300.0f || me->GetExactDist(player) > 50.0f)
continue;
AttackStart(player);
return true;
}
return false;
}
@@ -164,23 +170,22 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_BERSERK:
case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_SPELL_ENRAGE:
case EVENT_ENRAGE:
Talk(EMOTE_ENRAGE);
me->CastSpell(me, RAID_MODE(SPELL_ENRAGE_10, SPELL_ENRAGE_25), true);
events.RepeatEvent(30000);
events.RepeatEvent(22000);
break;
case EVENT_SPELL_MORTAL_WOUND:
case EVENT_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.RepeatEvent(10000);
break;
case EVENT_SPELL_DECIMATE:
case EVENT_DECIMATE:
Talk(EMOTE_DECIMATE);
me->CastSpell(me, RAID_MODE(SPELL_DECIMATE_10, SPELL_DECIMATE_25), false);
events.RepeatEvent(105000);
events.RepeatEvent(RAID_MODE(110000, 90000));
break;
case EVENT_SUMMON_ZOMBIE:
{
@@ -191,12 +196,15 @@ public:
// \1 |0 /2 pos
// In 25 man raid - should spawn from all 3 gates
if (me->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)
{
me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[0]);
}
else
{
me->SummonCreature(NPC_ZOMBIE_CHOW, zombiePos[urand(0, 2)]);
}
(rand == 2 ? rand = 0 : rand++);
}
events.RepeatEvent(10000);
break;
}
@@ -210,7 +218,6 @@ public:
}
break;
}
DoMeleeAttackIfReady();
}
};
@@ -241,7 +248,6 @@ public:
Unit::DealDamage(GetCaster(), cTarget, damage);
return;
}
GetCaster()->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget);
}
}

View File

@@ -11,51 +11,52 @@
enum Yells
{
SAY_INTRO_1 = 0,
SAY_INTRO_2 = 1,
SAY_INTRO_3 = 2,
SAY_INTRO_4 = 3,
SAY_PHASE_TWO = 4,
SAY_DEATH = 5,
SAY_KILL = 6,
SAY_INTRO_1 = 0,
SAY_INTRO_2 = 1,
SAY_INTRO_3 = 2,
SAY_INTRO_4 = 3,
SAY_PHASE_TWO = 4,
SAY_DEATH = 5,
SAY_KILL = 6,
EMOTE_PHASE_TWO = 7,
EMOTE_GATE_OPENED = 8
EMOTE_PHASE_TWO = 7,
EMOTE_GATE_OPENED = 8
};
enum Spells
{
// Gothik
SPELL_HARVEST_SOUL = 28679,
SPELL_SHADOW_BOLT_10 = 29317,
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_KNIGHT = 27928,
SPELL_INFORM_LIVING_RIDER = 27935,
SPELL_INFORM_DEAD_TRAINEE = 27915,
SPELL_INFORM_DEAD_KNIGHT = 27931,
SPELL_INFORM_DEAD_RIDER = 27937,
// TRAINEES
SPELL_DEATH_PLAGUE = 55604, // LIVING TRAINEE
SPELL_ARCANE_EXPLOSION = 27989, // DEAD TRAINEE (20y)
// KNIGHT
SPELL_SHADOW_MARK = 27825, // LIVING KNIGHT
SPELL_WHIRLWIND = 56408, // DEAD KNIGHT
// RIDER
SPELL_BLOOD_PRESENCE = 55212, // LIVING RIDER
SPELL_DEATH_COIL = 55209, // LIVING RIDER
SPELL_HASTE_AURA = 13589, // LIVING RIDER
SPELL_HYSTERIA = 55213, // LIVING RIDER
SPELL_INTIMIDATING_SHOUT = 5246, // LIVING RIDER
SPELL_VEIL_OF_DARKNESS = 28350, // LIVING RIDER
SPELL_DRAIN_LIFE = 27994, // DEAD RIDER
SPELL_UNHOLY_AURA = 55606, // DEAD RIDER
SPELL_UNHOLY_FRENZY = 55648, // DEAD RIDER
// HORSE
SPELL_STOMP = 27993 // DEAD HORSE
/*SPELL_ANCHOR_2_TRAINEE = 27893,
SPELL_ANCHOR_2_DK = 27929,
SPELL_ANCHOR_2_RIDER = 27936, fix me */
// Living trainee
SPELL_DEATH_PLAGUE = 55604,
// Dead trainee
SPELL_ARCANE_EXPLOSION = 27989,
// Living knight
SPELL_SHADOW_MARK = 27825,
// Dead knight
SPELL_WHIRLWIND = 56408,
// Living rider
SPELL_SHADOW_BOLT_VOLLEY = 27831,
// Dead rider
SPELL_DRAIN_LIFE = 27994,
SPELL_UNHOLY_FRENZY = 55648,
// Horse
SPELL_STOMP = 27993
};
enum Misc
@@ -67,44 +68,37 @@ enum Misc
NPC_DEAD_KNIGHT = 16148,
NPC_DEAD_HORSE = 16149,
NPC_DEAD_RIDER = 16150,
ACTION_GATE_OPEN = 1,
//NPC_TRIGGER = 16137, fix me
};
enum Events
{
// Gothik
EVENT_SUMMON_ADDS = 1,
EVENT_SPELL_HARVEST_SOUL = 2,
EVENT_SPELL_SHADOW_BOLT = 3,
EVENT_HARVEST_SOUL = 2,
EVENT_SHADOW_BOLT = 3,
EVENT_TELEPORT = 4,
EVENT_CHECK_HEALTH = 5,
EVENT_CHECK_PLAYERS = 6,
// TRAINEES
EVENT_SPELL_DEATH_PLAGUE = 7,
EVENT_SPELL_ARCANE_EXPLOSION = 8,
// KNIGHT
EVENT_SPELL_SHADOW_MARK = 9,
EVENT_SPELL_WHIRLWIND = 10,
// RIDER
EVENT_SPELL_BLOOD_PRESENCE = 11,
EVENT_SPELL_DEATH_COIL = 12,
EVENT_SPELL_HASTE_AURA = 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,
// Living trainee
EVENT_DEATH_PLAGUE = 7,
// Dead trainee
EVENT_ARCANE_EXPLOSION = 8,
// Living knight
EVENT_SHADOW_MARK = 9,
// Dead knight
EVENT_WHIRLWIND = 10,
// Living rider
EVENT_SHADOW_BOLT_VOLLEY = 11,
// Dead rider
EVENT_DRAIN_LIFE = 12,
EVENT_UNHOLY_FRENZY = 13,
// HORSE
EVENT_SPELL_STOMP = 20,
EVENT_INTRO_2 = 21,
EVENT_INTRO_3 = 22,
EVENT_INTRO_4 = 23,
EVENT_STOMP = 14,
// Intro
EVENT_INTRO_2 = 15,
EVENT_INTRO_3 = 16,
EVENT_INTRO_4 = 17
};
const uint32 gothikWaves[24][2] =
@@ -142,7 +136,7 @@ const Position PosSummonLiving[6] =
{2714.4f, -3428.76f, 268.56f, 1.6f},
{2669.7f, -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] =
@@ -151,7 +145,7 @@ const Position PosSummonDead[5] =
{2699.3f, -3322.8f, 268.60f, 3.3f},
{2733.1f, -3348.5f, 268.84f, 3.1f},
{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};
@@ -193,7 +187,6 @@ public:
{
pInstance = me->GetInstanceScript();
}
EventMap events;
SummonList summons;
InstanceScript* pInstance;
@@ -208,7 +201,6 @@ public:
EnterEvadeMode();
return false;
}
return true;
}
@@ -217,20 +209,26 @@ public:
BossAI::Reset();
events.Reset();
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);
secondPhase = false;
gateOpened = false;
waveCount = 0;
me->NearTeleportTo(2642.139f, -3386.959f, 285.492f, 6.265f);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
}
@@ -242,31 +240,43 @@ public:
events.ScheduleEvent(EVENT_INTRO_2, 4000);
events.ScheduleEvent(EVENT_INTRO_3, 9000);
events.ScheduleEvent(EVENT_INTRO_4, 14000);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->NearTeleportTo(PosPlatform.GetPositionX(), PosPlatform.GetPositionY(), PosPlatform.GetPositionZ(), PosPlatform.GetOrientation());
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
events.ScheduleEvent(EVENT_CHECK_PLAYERS, 120000);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
}
void JustSummoned(Creature* summon) override
{
if (gateOpened)
summon->AI()->DoAction(ACTION_GATE_OPEN);
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
{
@@ -274,9 +284,10 @@ public:
return;
Talk(SAY_KILL);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
@@ -284,15 +295,20 @@ public:
BossAI::JustDied(killer);
Talk(SAY_DEATH);
summons.DespawnAll();
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_EXIT_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
@@ -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[1].GetPositionX(), PosSummonLiving[1].GetPositionY(), PosSummonLiving[1].GetPositionZ(), PosSummonLiving[1].GetOrientation());
if (Is25ManRaid())
{
me->SummonCreature(NPC_LIVING_TRAINEE, PosSummonLiving[2].GetPositionX(), PosSummonLiving[2].GetPositionY(), PosSummonLiving[2].GetPositionZ(), PosSummonLiving[2].GetOrientation());
}
break;
case NPC_LIVING_KNIGHT:
me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[3].GetPositionX(), PosSummonLiving[3].GetPositionY(), PosSummonLiving[3].GetPositionZ(), PosSummonLiving[3].GetOrientation());
if (Is25ManRaid())
{
me->SummonCreature(NPC_LIVING_KNIGHT, PosSummonLiving[5].GetPositionX(), PosSummonLiving[5].GetPositionY(), PosSummonLiving[5].GetPositionZ(), PosSummonLiving[5].GetOrientation());
}
break;
case NPC_LIVING_RIDER:
me->SummonCreature(NPC_LIVING_RIDER, PosSummonLiving[4].GetPositionX(), PosSummonLiving[4].GetPositionY(), PosSummonLiving[4].GetPositionZ(), PosSummonLiving[4].GetOrientation());
@@ -328,17 +348,21 @@ public:
{
Player* player = i.GetSource();
if (player->IsAlive() &&
player->GetPositionX() <= POS_X_NORTH &&
player->GetPositionX() >= POS_X_SOUTH &&
player->GetPositionY() <= POS_Y_GATE &&
player->GetPositionY() >= POS_Y_EAST)
checklife = true;
player->GetPositionX() <= POS_X_NORTH &&
player->GetPositionX() >= POS_X_SOUTH &&
player->GetPositionY() <= POS_Y_GATE &&
player->GetPositionY() >= POS_Y_EAST)
{
checklife = true;
}
else if (player->IsAlive() &&
player->GetPositionX() <= POS_X_NORTH &&
player->GetPositionX() >= POS_X_SOUTH &&
player->GetPositionY() >= POS_Y_GATE &&
player->GetPositionY() <= POS_Y_WEST)
checkdead = true;
{
checkdead = true;
}
if (checklife && checkdead)
return true;
@@ -363,14 +387,15 @@ public:
me->SummonCreature(NPC_DEAD_HORSE, PosSummonDead[pos].GetPositionX(), PosSummonDead[pos].GetPositionY(), PosSummonDead[pos].GetPositionZ(), PosSummonDead[pos].GetOrientation());
break;
}
me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST);
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!secondPhase)
{
damage = 0;
}
}
void UpdateAI(uint32 diff) override
@@ -389,31 +414,31 @@ public:
{
case EVENT_INTRO_2:
Talk(SAY_INTRO_2);
break;
case EVENT_INTRO_3:
Talk(SAY_INTRO_3);
break;
case EVENT_INTRO_4:
Talk(SAY_INTRO_4);
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);
events.RepeatEvent(2000);
events.RepeatEvent(1010);
break;
case EVENT_SPELL_HARVEST_SOUL:
case EVENT_HARVEST_SOUL:
me->CastSpell(me, SPELL_HARVEST_SOUL, false);
events.RepeatEvent(15000);
break;
case EVENT_TELEPORT:
me->AttackStop();
if (IN_LIVE_SIDE(me))
me->NearTeleportTo(PosGroundDeadSide.GetPositionX(), PosGroundDeadSide.GetPositionY(), PosGroundDeadSide.GetPositionZ(), PosGroundDeadSide.GetOrientation());
{
me->CastSpell(me, SPELL_TELEPORT_DEAD, false);
}
else
me->NearTeleportTo(PosGroundLivingSide.GetPositionX(), PosGroundLivingSide.GetPositionY(), PosGroundLivingSide.GetPositionZ(), PosGroundLivingSide.GetOrientation());
{
me->CastSpell(me, SPELL_TELEPORT_LIVE, false);
}
me->getThreatManager().resetAggro(NotOnSameSide(me));
if (Unit* pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0))
{
@@ -426,10 +451,10 @@ public:
if (me->HealthBelowPct(30) && pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
events.CancelEvent(EVENT_TELEPORT);
break;
}
events.RepeatEvent(1000);
@@ -445,35 +470,31 @@ public:
secondPhase = true;
Talk(SAY_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->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE);
summons.DoAction(ACTION_GATE_OPEN);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE);
me->RemoveAllAuras();
summons.DoZoneInCombat();
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, 1000);
events.ScheduleEvent(EVENT_SPELL_HARVEST_SOUL, urand(5000, 15000));
events.ScheduleEvent(EVENT_SHADOW_BOLT, 1000);
events.ScheduleEvent(EVENT_HARVEST_SOUL, urand(5000, 15000));
events.ScheduleEvent(EVENT_TELEPORT, 20000);
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
}
waveCount++;
break;
case EVENT_CHECK_PLAYERS:
if (!CheckGroupSplitted())
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
summons.DoAction(ACTION_GATE_OPEN);
}
summons.DoZoneInCombat();
gateOpened = true;
Talk(EMOTE_GATE_OPENED);
}
break;
}
DoMeleeAttackIfReady();
}
};
@@ -494,63 +515,58 @@ public:
explicit npc_boss_gothik_minionAI(Creature* c) : CombatAI(c)
{
livingSide = IN_LIVE_SIDE(me);
gateOpened = false;
}
EventMap events;
bool livingSide;
bool gateOpened;
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
{
me->SetInCombatWithZone();
switch (me->GetEntry())
{
case NPC_LIVING_TRAINEE:
events.ScheduleEvent(EVENT_SPELL_DEATH_PLAGUE, 2000);
events.ScheduleEvent(EVENT_DEATH_PLAGUE, 3000);
break;
case NPC_DEAD_TRAINEE:
events.ScheduleEvent(EVENT_SPELL_ARCANE_EXPLOSION, 2000);
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 2500);
break;
case NPC_LIVING_KNIGHT:
events.ScheduleEvent(EVENT_SPELL_SHADOW_MARK, 2000);
events.ScheduleEvent(EVENT_SHADOW_MARK, 3000);
break;
case NPC_DEAD_KNIGHT:
events.ScheduleEvent(EVENT_SPELL_WHIRLWIND, 2000);
events.ScheduleEvent(EVENT_WHIRLWIND, 2000);
break;
case NPC_LIVING_RIDER:
events.ScheduleEvent(EVENT_SPELL_BLOOD_PRESENCE, 1);
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));
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 3000);
break;
case NPC_DEAD_RIDER:
events.ScheduleEvent(EVENT_SPELL_DRAIN_LIFE, urand(2000, 3500));
events.ScheduleEvent(EVENT_SPELL_UNHOLY_AURA, 1);
events.ScheduleEvent(EVENT_SPELL_UNHOLY_FRENZY, urand(5000, 9000));
events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(2000, 3500));
events.ScheduleEvent(EVENT_UNHOLY_FRENZY, urand(5000, 9000));
break;
case NPC_DEAD_HORSE:
events.ScheduleEvent(EVENT_SPELL_STOMP, urand(2000, 5000));
events.ScheduleEvent(EVENT_STOMP, urand(2000, 5000));
break;
}
}
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!attacker || (!gateOpened && !IsOnSameSide(attacker)))
if (!attacker && !IsOnSameSide(attacker))
{
damage = 0;
}
void DoAction(int32 param) override
{
if (param == ACTION_GATE_OPEN)
gateOpened = true;
}
if (!me->IsInCombat())
{
me->CallForHelp(25.0f);
AttackStart(attacker);
}
}
void JustDied(Unit*) override
@@ -572,89 +588,82 @@ public:
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (me->GetUnitState() == UNIT_STATE_CASTING)
return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_DEATH_PLAGUE:
case EVENT_DEATH_PLAGUE:
me->CastSpell(me->GetVictim(), SPELL_DEATH_PLAGUE, false);
events.RepeatEvent(urand(15000, 20000));
events.RepeatEvent(urand(4000, 7000));
break;
case EVENT_SPELL_ARCANE_EXPLOSION:
case EVENT_ARCANE_EXPLOSION:
if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 20))
{
me->CastSpell(victim, SPELL_ARCANE_EXPLOSION, false);
events.RepeatEvent(urand(5000, 10000));
}
}
events.RepeatEvent(2500);
break;
case EVENT_SPELL_SHADOW_MARK:
case EVENT_SHADOW_MARK:
if (Unit* victim = me->GetVictim())
{
if (!victim->HasAura(SPELL_SHADOW_MARK))
{
me->CastSpell(me->GetVictim(), SPELL_SHADOW_MARK, false);
events.RepeatEvent(urand(15000, 20000));
}
}
events.RepeatEvent(urand(5000, 7000));
break;
case EVENT_SPELL_WHIRLWIND:
case EVENT_WHIRLWIND:
if (Unit* victim = me->GetVictim())
{
if (victim->IsWithinDist(me, 10))
{
me->CastSpell(victim, SPELL_WHIRLWIND, false);
events.RepeatEvent(urand(5000, 8000));
}
}
events.RepeatEvent(urand(4000, 6000));
break;
case EVENT_SPELL_BLOOD_PRESENCE:
if (!me->HasAura(SPELL_BLOOD_PRESENCE))
me->CastSpell(me, SPELL_BLOOD_PRESENCE, false);
case EVENT_SHADOW_BOLT_VOLLEY:
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT_VOLLEY, false);
events.RepeatEvent(5000);
break;
case EVENT_SPELL_HASTE_AURA:
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:
case EVENT_DRAIN_LIFE:
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))
me->CastSpell(victim, SPELL_INTIMIDATING_SHOUT, false);
events.RepeatEvent(urand(14000, 22000));
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);
{
me->CastSpell(victim, SPELL_STOMP, false);
}
}
events.RepeatEvent(urand(4000, 9000));
break;
default:
break;
}
DoMeleeAttackIfReady();
}
};

View File

@@ -7,31 +7,33 @@
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
enum Spells
{
SPELL_POISON_CLOUD = 28240,
SPELL_MUTATING_INJECTION = 28169,
SPELL_MUTATING_EXPLOSION = 28206,
SPELL_SLIME_SPRAY_10 = 28157,
SPELL_SLIME_SPRAY_25 = 54364,
SPELL_POISON_CLOUD_DAMAGE_AURA_10 = 28158,
SPELL_POISON_CLOUD_DAMAGE_AURA_25 = 54362,
SPELL_BERSERK = 26662,
SPELL_BOMBARD_SLIME = 28280, // Spawn slime when hit by slime spray
SPELL_BOMBARD_SLIME = 28280
};
enum Emotes
{
EMOTE_SLIME = 0
EMOTE_SLIME = 0
};
enum Events
{
EVENT_SPELL_BERSERK = 1,
EVENT_SPELL_POISON_CLOUD = 2,
EVENT_SPELL_SLIME_SPRAY = 3,
EVENT_SPELL_MUTATING_INJECTION = 4,
EVENT_BERSERK = 1,
EVENT_POISON_CLOUD = 2,
EVENT_SLIME_SPRAY = 3,
EVENT_MUTATING_INJECTION = 4
};
enum Misc
@@ -78,7 +80,9 @@ public:
for (std::list<Creature*>::const_iterator itr = StichedGiants.begin(); itr != StichedGiants.end(); ++itr)
{
if ((*itr)->GetGUID())
{
(*itr)->ToCreature()->AI()->AttackStart(me->GetVictim());
}
}
}
@@ -87,27 +91,33 @@ public:
BossAI::EnterCombat(who);
PullChamberAdds();
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_POISON_CLOUD, 15000);
events.ScheduleEvent(EVENT_SPELL_MUTATING_INJECTION, 20000);
events.ScheduleEvent(EVENT_SPELL_SLIME_SPRAY, 10000);
events.ScheduleEvent(EVENT_SPELL_BERSERK, RAID_MODE(12 * MINUTE * IN_MILLISECONDS, 9 * MINUTE * IN_MILLISECONDS));
events.ScheduleEvent(EVENT_POISON_CLOUD, 15000);
events.ScheduleEvent(EVENT_MUTATING_INJECTION, 20000);
events.ScheduleEvent(EVENT_SLIME_SPRAY, 10000);
events.ScheduleEvent(EVENT_BERSERK, RAID_MODE(720000, 540000));
}
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)
{
me->SummonCreature(NPC_FALLOUT_SLIME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
}
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() == NPC_FALLOUT_SLIME)
{
cr->SetInCombatWithZone();
}
summons.Summon(cr);
}
void SummonedCreatureDespawn(Creature* summon) override { summons.Despawn(summon); }
void SummonedCreatureDespawn(Creature* summon) override
{
summons.Despawn(summon);
}
void JustDied(Unit* killer) override
{
@@ -118,18 +128,20 @@ public:
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void UpdateAI(uint32 diff) override
{
// Some nice visuals
dropSludgeTimer += diff;
if (!me->IsInCombat() && dropSludgeTimer >= 5000)
{
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);
}
dropSludgeTimer = 0;
}
@@ -142,27 +154,26 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_POISON_CLOUD:
case EVENT_POISON_CLOUD:
me->CastSpell(me, SPELL_POISON_CLOUD, true);
events.RepeatEvent(15000);
break;
case EVENT_SPELL_BERSERK:
case EVENT_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_SPELL_SLIME_SPRAY:
case EVENT_SLIME_SPRAY:
Talk(EMOTE_SLIME);
me->CastSpell(me->GetVictim(), RAID_MODE(SPELL_SLIME_SPRAY_10, SPELL_SLIME_SPRAY_25), false);
events.RepeatEvent(20000);
break;
case EVENT_SPELL_MUTATING_INJECTION:
case EVENT_MUTATING_INJECTION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -SPELL_MUTATING_INJECTION))
{
me->CastSpell(target, SPELL_MUTATING_INJECTION, false);
events.RepeatEvent(8000 + uint32(120 * me->GetHealthPct()));
}
events.RepeatEvent(6000 + uint32(120 * me->GetHealthPct()));
break;
}
DoMeleeAttackIfReady();
}
};
@@ -190,19 +201,20 @@ public:
sizeTimer = 0;
auraVisualTimer = 1;
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 2.0f);
me->setFaction(21); // Grobbulus one
me->setFaction(21);
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void UpdateAI(uint32 diff) override
{
// this has to be delayed to be visible :/
if (auraVisualTimer)
if (auraVisualTimer) // this has to be delayed to be visible
{
auraVisualTimer += diff;
if (auraVisualTimer >= 1000)
@@ -211,9 +223,7 @@ public:
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));
}
};
@@ -232,12 +242,17 @@ public:
{
std::list<WorldObject*> tmplist;
for (auto& target : targets)
{
if (GetCaster()->IsWithinDist3d(target, 0.0f))
{
tmplist.push_back(target);
}
}
targets.clear();
for (auto& itr : tmplist)
{
targets.push_back(itr);
}
}
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()
{
new boss_grobbulus();
new boss_grobbulus_poison_cloud();
new spell_grobbulus_mutating_injection();
new spell_grobbulus_poison();
}

View File

@@ -9,13 +9,13 @@
enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNT = 2,
SAY_DEATH = 3,
EMOTE_DANCE = 4,
EMOTE_DANCE_END = 5,
SAY_DANCE = 6
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNT = 2,
EMOTE_DEATH = 3,
EMOTE_DANCE = 4,
EMOTE_DANCE_END = 5,
SAY_DANCE = 6
};
enum Spells
@@ -24,21 +24,23 @@ enum Spells
SPELL_DECREPIT_FEVER_10 = 29998,
SPELL_DECREPIT_FEVER_25 = 55011,
SPELL_PLAGUE_CLOUD = 29350,
SPELL_TELEPORT_SELF = 30211
};
enum Events
{
EVENT_SPELL_SPELL_DISRUPTION = 1,
EVENT_SPELL_DECEPIT_FEVER = 2,
EVENT_DISRUPTION = 1,
EVENT_DECEPIT_FEVER = 2,
EVENT_ERUPT_SECTION = 3,
EVENT_SWITCH_PHASE = 4,
EVENT_SAFETY_DANCE = 5,
EVENT_PLAGUE_CLOUD = 6
};
enum Misc
{
PHASE_SLOW_DANCE = 0,
PHASE_FAST_DANCE = 1,
PHASE_FAST_DANCE = 1
};
class boss_heigan : public CreatureScript
@@ -71,11 +73,12 @@ public:
currentPhase = 0;
currentSection = 3;
moveRight = true;
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
@@ -85,15 +88,16 @@ public:
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_DEATH);
Talk(EMOTE_DEATH);
}
void EnterCombat(Unit* who) override
@@ -104,9 +108,10 @@ public:
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
StartFightPhase(PHASE_SLOW_DANCE);
}
@@ -117,22 +122,25 @@ public:
events.Reset();
if (phase == PHASE_SLOW_DANCE)
{
events.ScheduleEvent(EVENT_SPELL_SPELL_DISRUPTION, 0);
events.ScheduleEvent(EVENT_SPELL_DECEPIT_FEVER, 12000);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 10000);
me->CastStop();
me->SetReactState(REACT_AGGRESSIVE);
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);
}
else // if (phase == PHASE_FAST_DANCE)
{
Talk(EMOTE_DANCE);
Talk(SAY_DANCE);
// teleport
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o);
me->CastSpell(me, SPELL_PLAGUE_CLOUD, false);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 4000);
me->AttackStop();
me->StopMoving();
me->SetReactState(REACT_PASSIVE);
me->CastSpell(me, SPELL_TELEPORT_SELF, false);
me->SetFacingTo(2.40f);
events.ScheduleEvent(EVENT_PLAGUE_CLOUD, 1000);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 7000);
events.ScheduleEvent(EVENT_SWITCH_PHASE, 45000);
}
events.ScheduleEvent(EVENT_SAFETY_DANCE, 5000);
@@ -144,9 +152,9 @@ public:
{
if (who->GetGUID() == me->GetGUID())
EnterEvadeMode();
return false;
}
return true;
}
@@ -159,18 +167,19 @@ public:
return;
events.Update(diff);
//if (me->HasUnitState(UNIT_STATE_CASTING))
// return;
switch (events.ExecuteEvent())
{
case EVENT_SPELL_SPELL_DISRUPTION:
case EVENT_DISRUPTION:
me->CastSpell(me, SPELL_SPELL_DISRUPTION, false);
events.RepeatEvent(10000);
break;
case EVENT_SPELL_DECEPIT_FEVER:
case EVENT_DECEPIT_FEVER:
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;
case EVENT_SWITCH_PHASE:
if (currentPhase == PHASE_SLOW_DANCE)
@@ -180,31 +189,33 @@ public:
else
{
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;
case EVENT_ERUPT_SECTION:
if (pInstance)
{
pInstance->SetData(DATA_HEIGAN_ERUPTION, currentSection);
if (currentSection == 3)
{
moveRight = false;
}
else if (currentSection == 0)
{
moveRight = true;
}
moveRight ? currentSection++ : currentSection--;
}
if (currentPhase == PHASE_SLOW_DANCE)
{
Talk(SAY_TAUNT);
}
events.RepeatEvent(currentPhase == PHASE_SLOW_DANCE ? 10000 : 4000);
break;
case EVENT_SAFETY_DANCE:
{
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
for(const auto& itr : pList)
for (const auto& itr : pList)
{
if (IsInRoom(itr.GetSource()) && !itr.GetSource()->IsAlive())
{
@@ -217,7 +228,6 @@ public:
return;
}
}
DoMeleeAttackIfReady();
}
};

View File

@@ -10,23 +10,25 @@
enum Yells
{
SAY_TAUNT = 6,
SAY_AGGRO = 7,
SAY_SLAY = 8,
SAY_DEATH = 9,
SAY_CHAIN = 10,
SAY_FROST_BLAST = 11,
SAY_REQUEST_AID = 12, //start of phase 3
SAY_ANSWER_REQUEST = 3, //lich king answer
SAY_SUMMON_MINIONS = 14, //start of phase 1
SAY_SPECIAL = 15,
SAY_ANSWER_REQUEST = 3,
SAY_TAUNT = 6,
SAY_AGGRO = 7,
SAY_SLAY = 8,
SAY_DEATH = 9,
SAY_CHAIN = 10,
SAY_FROST_BLAST = 11,
SAY_REQUEST_AID = 12,
EMOTE_PHASE_TWO = 13,
SAY_SUMMON_MINIONS = 14,
SAY_SPECIAL = 15,
EMOTE_GUARDIAN_FLEE = 0,
EMOTE_GUARDIAN_APPEAR = 1
EMOTE_GUARDIAN_FLEE = 0,
EMOTE_GUARDIAN_APPEAR = 1
};
enum Spells
{
// Kel'Thzuad
SPELL_FROST_BOLT_SINGLE_10 = 28478,
SPELL_FROST_BOLT_SINGLE_25 = 55802,
SPELL_FROST_BOLT_MULTI_10 = 28479,
@@ -36,13 +38,14 @@ enum Spells
SPELL_DETONATE_MANA = 27819,
SPELL_MANA_DETONATION_DAMAGE = 27820,
SPELL_FROST_BLAST = 27808,
SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect
SPELL_CHAINS_OF_KELTHUZAD = 28410, // 28408 script effect
SPELL_BERSERK = 28498,
SPELL_KELTHUZAD_CHANNEL = 29423,
// Minions
SPELL_FRENZY = 28468,
SPELL_MORTAL_WOUND = 28467,
SPELL_BLOOD_TAP = 28470,
SPELL_BLOOD_TAP = 28470
};
enum Misc
@@ -55,6 +58,7 @@ enum Misc
ACTION_CALL_HELP_ON = 1,
ACTION_CALL_HELP_OFF = 2,
ACTION_SECOND_PHASE = 3,
ACTION_GUARDIANS_OFF = 4
};
enum Event
@@ -63,41 +67,35 @@ enum Event
EVENT_SUMMON_SOLDIER = 1,
EVENT_SUMMON_UNSTOPPABLE_ABOMINATION = 2,
EVENT_SUMMON_SOUL_WEAVER = 3,
EVENT_START_SECOND_PHASE = 4,
EVENT_SPELL_FROST_BOLT_SINGLE = 5,
EVENT_SPELL_FROST_BOLT_MULTI = 6,
EVENT_SPELL_DETONATE_MANA = 7,
EVENT_SECOND_PHASE_HEALTH_CHECK = 8,
EVENT_THIRD_PHASE_LICH_KING_SAY = 9,
EVENT_SPELL_SHADOW_FISSURE = 10,
EVENT_SPELL_FROST_BLAST = 11,
EVENT_SPELL_CHAINS = 12,
EVENT_PHASE_2 = 4,
EVENT_FROST_BOLT_SINGLE = 5,
EVENT_FROST_BOLT_MULTI = 6,
EVENT_DETONATE_MANA = 7,
EVENT_PHASE_3 = 8,
EVENT_P3_LICH_KING_SAY = 9,
EVENT_SHADOW_FISSURE = 10,
EVENT_FROST_BLAST = 11,
EVENT_CHAINS = 12,
EVENT_SUMMON_GUARDIAN_OF_ICECROWN = 13,
EVENT_FLOOR_CHANGE = 14,
EVENT_ENRAGE = 15,
EVENT_SPAWN_POOL = 16,
// Minions
EVENT_MINION_SPELL_FRENZY = 100,
EVENT_MINION_SPELL_MORTAL_WOUND = 101,
EVENT_MINION_SPELL_BLOOD_TAP = 102,
EVENT_MINION_FRENZY = 17,
EVENT_MINION_MORTAL_WOUND = 18,
EVENT_MINION_BLOOD_TAP = 19
};
const Position SummonPositions[12] =
const Position SummonGroups[12] =
{
// 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
// 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
{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
// Middle
{3769.34f, -5071.80f, 143.2082f, 3.658f},
@@ -108,6 +106,18 @@ const Position SummonPositions[12] =
{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
{
public:
@@ -133,34 +143,64 @@ public:
float NormalizeOrientation(float o)
{
// Only positive values will be passed
return fmod(o, 2.0f * static_cast<float>(M_PI));
return fmod(o, 2.0f * static_cast<float>(M_PI)); // Only positive values will be passed
}
void SpawnHelpers()
{
// Ehhh...
// in short: 6 rooms, 8 soldiers, 3 abominations and 1 weaver in each room
// middle positions in table starts from 6
// spawn at gate
me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, 3656.19f, -5093.78f, 143.33f, 6.08, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);// abo center
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 j = 0; j < 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 j = 1; j < 4; ++j)
{
float dist = j == 2 ? 0.0f : 8.0f; // second in middle
float angle = SummonPositions[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);
float angle = SummonGroups[i].GetOrientation() + M_PI * 2 / 4 * j;
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 j = 0; j < 1; ++j)
{
float angle = SummonPositions[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);
float angle = SummonGroups[i].GetOrientation() + M_PI;
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);
}
}
}
}
void Reset() override
@@ -170,19 +210,35 @@ public:
summons.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetReactState(REACT_AGGRESSIVE);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR)))
{
go->SetPhaseMask(1, true);
go->SetGoState(GO_STATE_READY);
}
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);
}
}
_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
@@ -197,25 +253,27 @@ public:
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
summons.DoAction(ACTION_GUARDIANS_OFF);
if (Creature* guardian = summons.GetCreatureWithEntry(NPC_GUARDIAN_OF_ICECROWN))
{
guardian->AI()->Talk(EMOTE_GUARDIAN_FLEE);
}
summons.DespawnAll();
Talk(SAY_DEATH);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
@@ -233,14 +291,13 @@ public:
me->RemoveAllAttackers();
me->SetTarget(0);
me->SetReactState(REACT_PASSIVE);
// Spawn helpers
SpawnHelpers();
events.ScheduleEvent(EVENT_SUMMON_SOLDIER, 3200);
me->CastSpell(me, SPELL_KELTHUZAD_CHANNEL, false);
events.ScheduleEvent(EVENT_SPAWN_POOL, 5000);
events.ScheduleEvent(EVENT_SUMMON_SOLDIER, 6400);
events.ScheduleEvent(EVENT_SUMMON_UNSTOPPABLE_ABOMINATION, 10000);
events.ScheduleEvent(EVENT_SUMMON_SOUL_WEAVER, 24000);
events.ScheduleEvent(EVENT_START_SECOND_PHASE, 228000);
events.ScheduleEvent(EVENT_SUMMON_SOUL_WEAVER, 12000);
events.ScheduleEvent(EVENT_PHASE_2, 228000);
events.ScheduleEvent(EVENT_ENRAGE, 900000);
if (pInstance)
{
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)))
{
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
{
@@ -261,8 +331,11 @@ public:
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->HasAura(SPELL_KELTHUZAD_CHANNEL))
{
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
switch (events.ExecuteEvent())
{
@@ -276,90 +349,80 @@ public:
go->SetPhaseMask(2, true);
}
}
break;
case EVENT_SPAWN_POOL:
SpawnHelpers();
break;
case EVENT_SUMMON_SOLDIER:
if (Creature* cr = me->SummonCreature(NPC_SOLDIER_OF_THE_FROZEN_WASTES, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
{
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
events.RepeatEvent(3200);
SummonHelper(NPC_SOLDIER_OF_THE_FROZEN_WASTES, 1);
events.RepeatEvent(3100);
break;
case EVENT_SUMMON_UNSTOPPABLE_ABOMINATION:
if (Creature* cr = me->SummonCreature(NPC_UNSTOPPABLE_ABOMINATION, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
{
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
events.RepeatEvent(30000);
SummonHelper(NPC_UNSTOPPABLE_ABOMINATION, 1);
events.RepeatEvent(18500);
break;
case EVENT_SUMMON_SOUL_WEAVER:
if (Creature* cr = me->SummonCreature(NPC_SOUL_WEAVER, SummonPositions[urand(0, 5)], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
{
if (Unit* target = SelectTargetFromPlayerList(100.0f))
{
cr->AI()->DoAction(ACTION_CALL_HELP_OFF);
cr->AI()->AttackStart(target);
}
}
SummonHelper(NPC_SOUL_WEAVER, 1);
events.RepeatEvent(30000);
break;
case EVENT_START_SECOND_PHASE:
// same as pop
case EVENT_PHASE_2:
Talk(EMOTE_PHASE_TWO);
Talk(SAY_AGGRO);
events.Reset();
summons.DoAction(ACTION_SECOND_PHASE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
me->GetMotionMaster()->MoveChase(me->GetVictim());
me->RemoveAura(SPELL_KELTHUZAD_CHANNEL);
me->SetReactState(REACT_AGGRESSIVE);
events.ScheduleEvent(EVENT_SPELL_FROST_BOLT_SINGLE, 2000);
events.ScheduleEvent(EVENT_SPELL_FROST_BOLT_MULTI, 15000);
events.ScheduleEvent(EVENT_SPELL_DETONATE_MANA, 20000);
events.ScheduleEvent(EVENT_SECOND_PHASE_HEALTH_CHECK, 1000);
events.ScheduleEvent(EVENT_SPELL_SHADOW_FISSURE, 25000);
events.ScheduleEvent(EVENT_SPELL_FROST_BLAST, 45000);
events.ScheduleEvent(EVENT_FROST_BOLT_SINGLE, urand(2000, 10000));
events.ScheduleEvent(EVENT_FROST_BOLT_MULTI, urand(15000, 30000));
events.ScheduleEvent(EVENT_DETONATE_MANA, 30000);
events.ScheduleEvent(EVENT_PHASE_3, 1000);
events.ScheduleEvent(EVENT_SHADOW_FISSURE, 25000);
events.ScheduleEvent(EVENT_FROST_BLAST, 45000);
if (Is25ManRaid())
events.ScheduleEvent(EVENT_SPELL_CHAINS, 50000);
{
events.ScheduleEvent(EVENT_CHAINS, 90000);
}
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);
events.RepeatEvent(urand(2000, 15000));
events.RepeatEvent(urand(2000, 10000));
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);
events.RepeatEvent(24000);
events.RepeatEvent(urand(15000, 30000));
break;
case EVENT_SPELL_SHADOW_FISSURE:
case EVENT_SHADOW_FISSURE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
{
me->CastSpell(target, SPELL_SHADOW_FISURE, false);
}
events.RepeatEvent(25000);
break;
case EVENT_SPELL_FROST_BLAST:
case EVENT_FROST_BLAST:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1, 0), 0, true))
{
me->CastSpell(target, SPELL_FROST_BLAST, false);
}
Talk(SAY_FROST_BLAST);
events.RepeatEvent(45000);
break;
case EVENT_SPELL_CHAINS:
case EVENT_CHAINS:
for (uint8 i = 0; i < 3; ++i)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true, -SPELL_CHAINS_OF_KELTHUZAD))
{
me->CastSpell(target, SPELL_CHAINS_OF_KELTHUZAD, true);
}
}
Talk(SAY_CHAIN);
events.RepeatEvent(50000);
events.RepeatEvent(90000);
break;
case EVENT_SPELL_DETONATE_MANA:
case EVENT_DETONATE_MANA:
{
std::vector<Unit*> unitList;
ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
@@ -368,9 +431,10 @@ public:
if (itr->getTarget()->GetTypeId() == TYPEID_PLAYER
&& itr->getTarget()->getPowerType() == POWER_MANA
&& itr->getTarget()->GetPower(POWER_MANA))
unitList.push_back(itr->getTarget());
{
unitList.push_back(itr->getTarget());
}
}
if (!unitList.empty())
{
auto itr = unitList.begin();
@@ -378,39 +442,56 @@ public:
me->CastSpell(*itr, SPELL_DETONATE_MANA, false);
Talk(SAY_SPECIAL);
}
events.RepeatEvent(30000);
break;
}
case EVENT_SECOND_PHASE_HEALTH_CHECK:
case EVENT_PHASE_3:
if (me->HealthBelowPct(45))
{
Talk(SAY_REQUEST_AID);
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;
}
events.RepeatEvent(1000);
break;
case EVENT_THIRD_PHASE_LICH_KING_SAY:
case EVENT_P3_LICH_KING_SAY:
if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_LICH_KING_BOSS)))
{
cr->AI()->Talk(SAY_ANSWER_REQUEST);
}
}
for (uint8 i = 0 ; i < RAID_MODE(2, 4); ++i)
{
events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_ICECROWN, 10000 + (i * 5000));
}
break;
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()->AttackStart(me->GetVictim());
}
break;
}
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
DoMeleeAttackIfReady();
}
@@ -444,13 +525,27 @@ public:
void DoAction(int32 param) override
{
if (param == ACTION_CALL_HELP_ON)
{
callHelp = true;
}
else if (param == ACTION_CALL_HELP_OFF)
{
callHelp = false;
}
else if (param == ACTION_SECOND_PHASE)
{
if (!me->IsInCombat())
{
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());
}
}
@@ -465,7 +560,9 @@ public:
void JustDied(Unit* ) override
{
if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_ABOMINATION_KILLED, 0);
}
}
void AttackStart(Unit* who) override
@@ -486,7 +583,9 @@ public:
}
if (me->GetEntry() != NPC_UNSTOPPABLE_ABOMINATION && me->GetEntry() != NPC_GUARDIAN_OF_ICECROWN)
{
me->AddThreat(who, 1000000.0f);
}
}
void EnterCombat(Unit* /*who*/) override
@@ -494,17 +593,29 @@ public:
me->SetInCombatWithZone();
if (me->GetEntry() == NPC_UNSTOPPABLE_ABOMINATION)
{
events.ScheduleEvent(EVENT_MINION_SPELL_FRENZY, 1000);
events.ScheduleEvent(EVENT_MINION_SPELL_MORTAL_WOUND, 5000);
events.ScheduleEvent(EVENT_MINION_FRENZY, 1000);
events.ScheduleEvent(EVENT_MINION_MORTAL_WOUND, 5000);
}
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
{
if (who->GetTypeId() == TYPEID_PLAYER && me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustReachedHome() override
{
if (me->GetEntry() == NPC_GUARDIAN_OF_ICECROWN)
{
me->DespawnOrUnsummon();
}
}
void UpdateAI(uint32 diff) override
@@ -518,25 +629,23 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_MINION_SPELL_MORTAL_WOUND:
case EVENT_MINION_MORTAL_WOUND:
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
events.RepeatEvent(15000);
break;
case EVENT_MINION_SPELL_FRENZY:
case EVENT_MINION_FRENZY:
if (me->HealthBelowPct(35))
{
me->CastSpell(me, SPELL_FRENZY, true);
break;
}
events.RepeatEvent(1000);
break;
case EVENT_MINION_SPELL_BLOOD_TAP:
case EVENT_MINION_BLOOD_TAP:
me->CastSpell(me->GetVictim(), SPELL_BLOOD_TAP, false);
events.RepeatEvent(15000);
break;
}
DoMeleeAttackIfReady();
}
};
@@ -559,12 +668,17 @@ public:
std::list<WorldObject*> tmplist;
for (auto& target : targets)
{
if (!target->ToUnit()->HasAura(SPELL_FROST_BLAST))
{
tmplist.push_back(target);
}
}
targets.clear();
for (auto& itr : tmplist)
{
targets.push_back(itr);
}
}
void Register() override
@@ -596,7 +710,6 @@ public:
void HandleScript(AuraEffect const* aurEff)
{
PreventDefaultAction();
Unit* target = GetTarget();
if (auto mana = int32(target->GetMaxPower(POWER_MANA) / 10))
{

View File

@@ -14,23 +14,25 @@ enum Spells
SPELL_DEATHBLOOM_25 = 55053,
SPELL_INEVITABLE_DOOM_10 = 29204,
SPELL_INEVITABLE_DOOM_25 = 55052,
SPELL_BERSERK = 26662,
SPELL_BERSERK = 26662
};
enum Events
{
EVENT_SPELL_NECROTIC_AURA = 1,
EVENT_SPELL_DEATHBLOOM = 2,
EVENT_SPELL_INEVITABLE_DOOM = 3,
EVENT_SPELL_BERSERK = 4,
EVENT_NECROTIC_AURA = 1,
EVENT_DEATHBLOOM = 2,
EVENT_INEVITABLE_DOOM = 3,
EVENT_BERSERK = 4,
EVENT_SUMMON_SPORE = 5,
EVENT_NECROTIC_AURA_FADING = 6,
EVENT_NECROTIC_AURA_REMOVED = 7
};
enum Texts
{
SAY_NECROTIC_AURA_APPLIED = 0,
SAY_NECROTIC_AURA_REMOVED = 1,
SAY_NECROTIC_AURA_FADING = 2,
SAY_NECROTIC_AURA_APPLIED = 0,
SAY_NECROTIC_AURA_REMOVED = 1,
SAY_NECROTIC_AURA_FADING = 2
};
class boss_loatheb : public CreatureScript
@@ -52,6 +54,7 @@ public:
}
InstanceScript* pInstance;
uint8 doomCounter;
EventMap events;
SummonList summons;
@@ -60,11 +63,14 @@ public:
BossAI::Reset();
events.Reset();
summons.DespawnAll();
doomCounter = 0;
if (pInstance)
{
pInstance->SetData(BOSS_LOATHEB, NOT_STARTED);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
@@ -77,38 +83,46 @@ public:
void SummonedCreatureDies(Creature* /*cr*/, Unit*) override
{
if (pInstance)
{
pInstance->SetData(DATA_SPORE_KILLED, 0);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void EnterCombat(Unit* who) override
{
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)
{
pInstance->SetData(BOSS_LOATHEB, IN_PROGRESS);
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE)))
{
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
{
BossAI::JustDied(killer);
if (pInstance)
pInstance->SetData(BOSS_LOATHEB, DONE);
summons.DespawnAll();
if (pInstance)
{
pInstance->SetData(BOSS_LOATHEB, DONE);
}
}
void UpdateAI(uint32 diff) override
@@ -126,24 +140,39 @@ public:
me->CastSpell(me, SPELL_SUMMON_SPORE, true);
events.RepeatEvent(35000);
break;
case EVENT_SPELL_NECROTIC_AURA:
case EVENT_NECROTIC_AURA:
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);
break;
case EVENT_SPELL_DEATHBLOOM:
case EVENT_DEATHBLOOM:
me->CastSpell(me, RAID_MODE(SPELL_DEATHBLOOM_10, SPELL_DEATHBLOOM_25), false);
events.RepeatEvent(30000);
break;
case EVENT_SPELL_INEVITABLE_DOOM:
case EVENT_INEVITABLE_DOOM:
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;
case EVENT_SPELL_BERSERK:
case EVENT_BERSERK:
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;
}
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()
{
new boss_loatheb();
new spell_loatheb_necrotic_aura_warning();
}

View File

@@ -17,30 +17,30 @@ enum Spells
SPELL_NECROTIC_POISON_10 = 54121,
SPELL_NECROTIC_POISON_25 = 28776,
SPELL_FRENZY_10 = 54123,
SPELL_FRENZY_25 = 54124,
SPELL_FRENZY_25 = 54124
};
enum Events
{
EVENT_SPELL_WEB_SPRAY = 1,
EVENT_SPELL_POISON_SHOCK = 2,
EVENT_SPELL_NECROTIC_POISON = 3,
EVENT_WEB_SPRAY = 1,
EVENT_POISON_SHOCK = 2,
EVENT_NECROTIC_POISON = 3,
EVENT_WEB_WRAP = 4,
EVENT_HEALTH_CHECK = 5,
EVENT_SUMMON_SPIDERLINGS = 6,
EVENT_SUMMON_SPIDERLINGS = 6
};
enum Emotes
{
EMOTE_SPIDERS = 0,
EMOTE_WEB_WRAP = 1,
EMOTE_WEB_SPRAY = 2
EMOTE_SPIDERS = 0,
EMOTE_WEB_WRAP = 1,
EMOTE_WEB_SPRAY = 2
};
enum Misc
{
NPC_WEB_WRAP = 16486,
NPC_MAEXXNA_SPIDERLING = 17055,
NPC_MAEXXNA_SPIDERLING = 17055
};
const Position PosWrap[3] =
@@ -78,7 +78,6 @@ public:
EnterEvadeMode();
return false;
}
return true;
}
@@ -87,11 +86,12 @@ public:
BossAI::Reset();
events.Reset();
summons.DespawnAll();
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
@@ -100,16 +100,17 @@ public:
BossAI::EnterCombat(who);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_WEB_WRAP, 20000);
events.ScheduleEvent(EVENT_SPELL_WEB_SPRAY, 40000);
events.ScheduleEvent(EVENT_SPELL_POISON_SHOCK, 10000);
events.ScheduleEvent(EVENT_SPELL_NECROTIC_POISON, 5000);
events.ScheduleEvent(EVENT_WEB_SPRAY, 40000);
events.ScheduleEvent(EVENT_POISON_SHOCK, 10000);
events.ScheduleEvent(EVENT_NECROTIC_POISON, 5000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
events.ScheduleEvent(EVENT_SUMMON_SPIDERLINGS, 30000);
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
}
@@ -119,16 +120,25 @@ public:
{
cr->SetInCombatWithZone();
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
cr->AI()->AttackStart(target);
}
}
summons.Summon(cr);
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
summons.DespawnAll();
}
void UpdateAI(uint32 diff) override
@@ -145,53 +155,53 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_WEB_SPRAY:
case EVENT_WEB_SPRAY:
Talk(EMOTE_WEB_SPRAY);
me->CastSpell(me, RAID_MODE(SPELL_WEB_SPRAY_10, SPELL_WEB_SPRAY_25), true);
events.RepeatEvent(40000);
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);
events.RepeatEvent(40000);
events.RepeatEvent(10000);
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);
events.RepeatEvent(30000);
break;
case EVENT_SUMMON_SPIDERLINGS:
Talk(EMOTE_SPIDERS);
for (uint8 i = 0; i < 8; ++i)
{
me->SummonCreature(NPC_MAEXXNA_SPIDERLING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
}
events.RepeatEvent(40000);
break;
case EVENT_HEALTH_CHECK:
if (me->GetHealthPct() < 30)
{
me->CastSpell(me, RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25), true);
break;
}
events.RepeatEvent(1000);
break;
case EVENT_WEB_WRAP:
Talk(EMOTE_WEB_WRAP);
for (uint8 i = 0; i < RAID_MODE(1, 2); ++i)
{
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));
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))
{
wrap->AI()->SetGUID(target->GetGUID());
target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20);
}
}
}
events.RepeatEvent(40000);
break;
}
DoMeleeAttackIfReady();
}
};
@@ -216,15 +226,23 @@ public:
{
victimGUID = guid;
if (me->m_spells[0] && victimGUID)
{
if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
{
victim->CastSpell(victim, me->m_spells[0], true, nullptr, nullptr, me->GetGUID());
}
}
}
void JustDied(Unit* /*killer*/) override
{
if (me->m_spells[0] && victimGUID)
{
if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID))
{
victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID());
}
}
}
};
};

View File

@@ -8,15 +8,15 @@
enum Says
{
SAY_AGGRO = 0,
SAY_SUMMON = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
EMOTE_SUMMON = 4,
EMOTE_SUMMON_WAVE = 5,
EMOTE_TELEPORT_BALCONY = 6,
EMOTE_TELEPORT_BACK = 7,
EMOTE_BLINK = 8
SAY_AGGRO = 0,
SAY_SUMMON = 1,
SAY_SLAY = 2,
SAY_DEATH = 3,
EMOTE_SUMMON = 4,
EMOTE_SUMMON_WAVE = 5,
EMOTE_TELEPORT_BALCONY = 6,
EMOTE_TELEPORT_BACK = 7,
EMOTE_BLINK = 8
};
enum Spells
@@ -27,20 +27,22 @@ enum Spells
SPELL_CRIPPLE_25 = 54814,
SPELL_SUMMON_PLAGUED_WARRIORS = 29237,
SPELL_TELEPORT = 29216,
SPELL_BLINK = 29208,
SPELL_TELEPORT_BACK = 29231,
SPELL_BERSERK = 68378,
SPELL_BLINK = 29208
};
enum Events
{
EVENT_SPELL_CURSE = 1,
EVENT_SPELL_CRIPPLE = 2,
EVENT_CURSE = 1,
EVENT_CRIPPLE = 2,
EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE = 3,
EVENT_MOVE_TO_BALCONY = 4,
EVENT_SPELL_BLINK = 5,
EVENT_BLINK = 5,
EVENT_MOVE_TO_GROUND = 6,
EVENT_SUMMON_PLAGUED_WARRIOR_REAL = 7,
EVENT_BALCONY_SUMMON_ANNOUNCE = 8,
EVENT_BALCONY_SUMMON_REAL = 9,
EVENT_BALCONY_SUMMON_REAL = 9
};
enum Misc
@@ -48,15 +50,17 @@ enum Misc
NPC_PLAGUED_WARRIOR = 16984,
NPC_PLAGUED_CHAMPION = 16983,
NPC_PLAGUED_GUARDIAN = 16981,
NOTH_ROOM_ENTRANCE = 181200
};
const Position summoningPosition[5] =
{
{2728.12f, -3544.43f, 261.91f, 6.04f},
{2729.05f, -3544.47f, 261.91f, 5.58f},
{2728.06f, -3535.38f, 263.21f, 2.75f},
{2725.71f, -3514.80f, 263.23f, 2.86f},
{2728.24f, -3465.08f, 264.20f, 3.56f},
{2704.11f, -3456.81f, 265.53f, 4.51f},
{2663.56f, -3464.43f, 262.66f, 5.20f},
{2704.79f, -3459.17f, 263.74f, 4.25f},
{2652.02f, -3459.13f, 262.50f, 5.39f}
};
const Position nothPosition = {2684.94f, -3502.53f, 261.31f, 4.7f};
@@ -79,6 +83,7 @@ public:
}
InstanceScript* pInstance;
uint8 timesInBalcony;
EventMap events;
SummonList summons;
@@ -87,14 +92,14 @@ public:
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetControlled(false, UNIT_STATE_ROOT);
events.SetPhase(0);
events.Reset();
events.ScheduleEvent(EVENT_MOVE_TO_BALCONY, 110000);
events.ScheduleEvent(EVENT_SPELL_CURSE, 15000);
events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE, 25000);
events.ScheduleEvent(EVENT_CURSE, 15000);
events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE, 10000);
if (Is25ManRaid())
events.ScheduleEvent(EVENT_SPELL_BLINK, 26000);
{
events.ScheduleEvent(EVENT_BLINK, 26000);
}
}
void StartBalconyPhase()
@@ -103,7 +108,6 @@ public:
me->AttackStop();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE);
me->SetControlled(true, UNIT_STATE_ROOT);
events.SetPhase(1);
events.Reset();
events.ScheduleEvent(EVENT_BALCONY_SUMMON_ANNOUNCE, 4000);
events.ScheduleEvent(EVENT_MOVE_TO_GROUND, 70000);
@@ -112,17 +116,18 @@ public:
void SummonHelper(uint32 entry, uint32 count)
{
for (uint8 i = 0; i < count; ++i)
{
me->SummonCreature(entry, summoningPosition[urand(0, 4)]);
}
}
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();
return false;
}
return true;
}
@@ -131,9 +136,14 @@ public:
BossAI::Reset();
events.Reset();
summons.DespawnAll();
me->CastSpell(me, SPELL_TELEPORT_BACK, true);
me->SetControlled(false, UNIT_STATE_ROOT);
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
@@ -147,6 +157,10 @@ public:
BossAI::EnterCombat(who);
Talk(SAY_AGGRO);
StartGroundPhase();
if (GameObject* go = me->FindNearestGameObject(NOTH_ROOM_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_READY);
}
}
void JustSummoned(Creature* summon) override
@@ -157,9 +171,17 @@ public:
void JustDied(Unit* killer) override
{
me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true);
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);
}
BossAI::JustDied(killer);
Talk(SAY_DEATH);
if (GameObject* go = me->FindNearestGameObject(NOTH_ROOM_ENTRANCE, 100.0f))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
void KilledUnit(Unit* who) override
@@ -168,9 +190,10 @@ public:
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void UpdateAI(uint32 diff) override
@@ -188,15 +211,17 @@ public:
switch (events.ExecuteEvent())
{
// GROUND
case EVENT_SPELL_CURSE:
case EVENT_CURSE:
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);
}
events.RepeatEvent(25000);
break;
case EVENT_SUMMON_PLAGUED_WARRIOR_ANNOUNCE:
Talk(SAY_SUMMON);
Talk(EMOTE_SUMMON);
events.RepeatEvent(25000);
events.RepeatEvent(30000);
events.ScheduleEvent(EVENT_SUMMON_PLAGUED_WARRIOR_REAL, 4000);
break;
case EVENT_SUMMON_PLAGUED_WARRIOR_REAL:
@@ -207,9 +232,8 @@ public:
Talk(EMOTE_TELEPORT_BALCONY);
me->CastSpell(me, SPELL_TELEPORT, true);
StartBalconyPhase();
// events.Reset()!!
break;
case EVENT_SPELL_BLINK:
case EVENT_BLINK:
DoResetThreat();
me->CastSpell(me, RAID_MODE(SPELL_CRIPPLE_10, SPELL_CRIPPLE_25), false);
me->CastSpell(me, SPELL_BLINK, true);
@@ -219,28 +243,36 @@ public:
// BALCONY
case EVENT_BALCONY_SUMMON_ANNOUNCE:
Talk(EMOTE_SUMMON_WAVE);
events.RepeatEvent(25000);
events.RepeatEvent(30000);
events.ScheduleEvent(EVENT_BALCONY_SUMMON_REAL, 4000);
break;
case EVENT_BALCONY_SUMMON_REAL:
me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); // visual only
if (events.GetPhaseMask() == 0)
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(2, 4));
else if (events.GetPhaseMask() == 1)
me->CastSpell(me, SPELL_SUMMON_PLAGUED_WARRIORS, true); // visual
switch (timesInBalcony)
{
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(1, 2));
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(1, 2));
case 0:
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(2, 4));
break;
case 1:
SummonHelper(NPC_PLAGUED_CHAMPION, RAID_MODE(1, 2));
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(1, 2));
break;
default:
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(2, 4));
break;
}
else
SummonHelper(NPC_PLAGUED_GUARDIAN, RAID_MODE(2, 4));
break;
case EVENT_MOVE_TO_GROUND:
Talk(EMOTE_TELEPORT_BACK);
me->CastSpell(me, SPELL_TELEPORT_BACK, true);
timesInBalcony++;
if (timesInBalcony == 3)
{
DoCastSelf(SPELL_BERSERK);
}
StartGroundPhase();
me->NearTeleportTo(nothPosition.GetPositionX(), nothPosition.GetPositionY(), nothPosition.GetPositionZ(), nothPosition.GetOrientation(), true);
break;
}
if (me->HasReactState(REACT_AGGRESSIVE))
DoMeleeAttackIfReady();
}

View File

@@ -8,11 +8,11 @@
enum Yells
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2,
EMOTE_BERSERK = 3,
EMOTE_ENRAGE = 4
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2,
EMOTE_BERSERK = 3,
EMOTE_ENRAGE = 4
};
enum Spells
@@ -21,20 +21,20 @@ enum Spells
SPELL_HATEFUL_STRIKE_25 = 59192,
SPELL_FRENZY = 28131,
SPELL_BERSERK = 26662,
SPELL_SLIME_BOLT = 32309,
SPELL_SLIME_BOLT = 32309
};
enum Events
{
EVENT_HEALTH_CHECK = 1,
EVENT_SPELL_HATEFUL_STRIKE = 2,
EVENT_SPELL_SLIME_BOLT = 3,
EVENT_SPELL_BERSERK = 4,
EVENT_HATEFUL_STRIKE = 2,
EVENT_SLIME_BOLT = 3,
EVENT_BERSERK = 4
};
enum Misc
{
ACHIEV_TIMED_START_EVENT = 10286,
ACHIEV_TIMED_START_EVENT = 10286
};
class boss_patchwerk : public CreatureScript
@@ -69,10 +69,13 @@ public:
return;
if (!urand(0, 3))
{
Talk(SAY_SLAY);
}
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
@@ -85,12 +88,10 @@ public:
{
BossAI::EnterCombat(who);
Talk(SAY_AGGRO);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SPELL_HATEFUL_STRIKE, 1200);
events.ScheduleEvent(EVENT_SPELL_BERSERK, 360000);
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 1500);
events.ScheduleEvent(EVENT_BERSERK, 360000);
events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
if (pInstance)
{
pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
@@ -108,58 +109,60 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_HATEFUL_STRIKE:
case EVENT_HATEFUL_STRIKE:
{
//Cast Hateful strike on the player with the highest
//amount of HP within melee distance, and second threat amount
// Cast Hateful strike on the player with the highest amount of HP within melee distance, and second threat amount
std::list<Unit*> meleeRangeTargets;
Unit* finalTarget = nullptr;
uint8 counter = 0;
auto i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i, ++counter)
{
// Gather all units with melee range
Unit* target = (*i)->getTarget();
if (me->IsWithinMeleeRange(target))
{
meleeRangeTargets.push_back(target);
}
// and add threat to most hated
if (counter < RAID_MODE(2, 3))
{
me->AddThreat(target, 500.0f);
}
}
counter = 0;
list<Unit*, std::allocator<Unit*>>::iterator itr;
for (itr = meleeRangeTargets.begin(); itr != meleeRangeTargets.end(); ++itr, ++counter)
{
// if there is only one target available
if (meleeRangeTargets.size() == 1)
{
finalTarget = (*itr);
}
else if (counter > 0) // skip first target
{
if (!finalTarget || (*itr)->GetHealth() > finalTarget->GetHealth())
{
finalTarget = (*itr);
}
// third loop
if (counter >= 2)
break;
}
}
if (finalTarget)
{
me->CastSpell(finalTarget, RAID_MODE(SPELL_HATEFUL_STRIKE_10, SPELL_HATEFUL_STRIKE_25), false);
}
events.RepeatEvent(1000);
break;
}
case EVENT_SPELL_BERSERK:
case EVENT_BERSERK:
Talk(EMOTE_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
events.ScheduleEvent(EVENT_SPELL_SLIME_BOLT, 2000);
events.ScheduleEvent(EVENT_SLIME_BOLT, 3000);
break;
case EVENT_SPELL_SLIME_BOLT:
case EVENT_SLIME_BOLT:
me->CastSpell(me, SPELL_SLIME_BOLT, false);
events.RepeatEvent(3000);
break;
@@ -168,13 +171,11 @@ public:
{
Talk(EMOTE_ENRAGE);
me->CastSpell(me, SPELL_FRENZY, true);
break;
}
events.RepeatEvent(1000);
break;
}
DoMeleeAttackIfReady();
}
};

View File

@@ -8,40 +8,34 @@
enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNTED = 2,
SAY_DEATH = 3,
SAY_SHOUT = 4
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNTED = 2,
SAY_DEATH = 3
};
enum Spells
{
SPELL_UNBALANCING_STRIKE = 26613,
SPELL_DISRUPTING_SHOUT_10 = 29107,
SPELL_DISRUPTING_SHOUT_25 = 55543,
SPELL_DISRUPTING_SHOUT_10 = 55543,
SPELL_DISRUPTING_SHOUT_25 = 29107,
SPELL_JAGGED_KNIFE = 55550,
SPELL_HOPELESS = 29125,
SPELL_BONE_BARRIER = 29061,
SPELL_BLOOD_STRIKE = 61696,
SPELL_TAUNT = 29060
};
enum Events
{
EVENT_SPELL_UNBALANCING_STRIKE = 1,
EVENT_SPELL_DISRUPTING_SHOUT = 2,
EVENT_SPELL_JAGGED_KNIFE = 3,
EVENT_PLAY_COMMAND = 4,
EVENT_MINION_BLOOD_STRIKE = 10,
EVENT_MINION_BONE_BARRIER = 11,
EVENT_UNBALANCING_STRIKE = 1,
EVENT_DISRUPTING_SHOUT = 2,
EVENT_JAGGED_KNIFE = 3
};
enum Misc
{
NPC_DEATH_KNIGHT_UNDERSTUDY = 16803,
NPC_RAZUVIOUS = 16061,
NPC_RAZUVIOUS = 16061
};
class boss_razuvious : public CreatureScript
@@ -67,16 +61,19 @@ public:
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);
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);
if (Is25ManRaid())
{
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, 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
{
@@ -88,40 +85,50 @@ public:
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_SLAY);
if (pInstance)
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
if (roll_chance_i(30))
{
Talk(SAY_SLAY);
}
if (who->GetTypeId() == TYPEID_PLAYER)
{
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
}
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
if(who && who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_DEATH_KNIGHT_UNDERSTUDY)
{
me->LowerPlayerDamageReq(damage);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_DEATH);
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
{
BossAI::EnterCombat(who);
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_UNBALANCING_STRIKE, 30000);
events.ScheduleEvent(EVENT_SPELL_DISRUPTING_SHOUT, 25000);
events.ScheduleEvent(EVENT_SPELL_JAGGED_KNIFE, 15000);
events.ScheduleEvent(EVENT_PLAY_COMMAND, 40000);
events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 20000);
events.ScheduleEvent(EVENT_DISRUPTING_SHOUT, 15000);
events.ScheduleEvent(EVENT_JAGGED_KNIFE, 10000);
summons.DoZoneInCombat();
}
@@ -136,27 +143,22 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_SPELL_UNBALANCING_STRIKE:
case EVENT_UNBALANCING_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_UNBALANCING_STRIKE, false);
events.RepeatEvent(30000);
events.RepeatEvent(20000);
break;
case EVENT_SPELL_DISRUPTING_SHOUT:
Talk(SAY_SHOUT);
case EVENT_DISRUPTING_SHOUT:
me->CastSpell(me, RAID_MODE(SPELL_DISRUPTING_SHOUT_10, SPELL_DISRUPTING_SHOUT_25), false);
events.RepeatEvent(25000);
events.RepeatEvent(15000);
break;
case EVENT_SPELL_JAGGED_KNIFE:
case EVENT_JAGGED_KNIFE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f))
{
me->CastSpell(target, SPELL_JAGGED_KNIFE, false);
events.RepeatEvent(25000);
break;
case EVENT_PLAY_COMMAND:
Talk(SAY_TAUNTED);
events.RepeatEvent(40000);
}
events.RepeatEvent(10000);
break;
}
DoMeleeAttackIfReady();
}
};
@@ -185,11 +187,13 @@ public:
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
if (me->GetInstanceScript())
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
if (who->GetTypeId() == TYPEID_PLAYER)
{
if (me->GetInstanceScript())
{
me->GetInstanceScript()->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
}
void EnterCombat(Unit* who) override
@@ -199,33 +203,18 @@ public:
cr->SetInCombatWithZone();
cr->AI()->AttackStart(who);
}
events.ScheduleEvent(EVENT_MINION_BLOOD_STRIKE, 4000);
events.ScheduleEvent(EVENT_MINION_BONE_BARRIER, 9000);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING) || me->IsCharmed())
return;
switch (events.ExecuteEvent())
if (UpdateVictim())
{
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;
events.Update(diff);
if (!me->HasUnitState(UNIT_STATE_CASTING) || !me->IsCharmed())
{
DoMeleeAttackIfReady();
}
}
DoMeleeAttackIfReady();
}
};
};

View File

@@ -36,7 +36,7 @@ enum Spells
SPELL_FROST_EXPLOSION = 28524,
// Visuals
SPELL_SAPPHIRON_DIES = 29357,
SPELL_SAPPHIRON_DIES = 29357
};
enum Misc
@@ -44,27 +44,25 @@ enum Misc
GO_ICE_BLOCK = 181247,
NPC_BLIZZARD = 16474,
POINT_CENTER = 1,
FAKE_POINTER = 1,
POINT_CENTER = 1
};
enum Events
{
//EVENT_SAPPHIRON_BIRTH = 1,
EVENT_BERSERK = 2,
EVENT_SPELL_CLEAVE = 3,
EVENT_SPELL_TAIL_SWEEP = 4,
EVENT_SPELL_LIFE_DRAIN = 5,
EVENT_SPELL_BLIZZARD = 6,
EVENT_FLIGHT_START = 7,
EVENT_FLIGHT_LIFTOFF = 8,
EVENT_FLIGHT_ICEBOLT = 9,
EVENT_FLIGHT_BREATH = 10,
EVENT_FLIGHT_SPELL_EXPLOSION = 11,
EVENT_FLIGHT_START_LAND = 12,
EVENT_LAND = 13,
EVENT_GROUND = 14,
EVENT_HUNDRED_CLUB = 15,
EVENT_BERSERK = 1,
EVENT_CLEAVE = 2,
EVENT_TAIL_SWEEP = 3,
EVENT_LIFE_DRAIN = 4,
EVENT_BLIZZARD = 5,
EVENT_FLIGHT_START = 6,
EVENT_FLIGHT_LIFTOFF = 7,
EVENT_FLIGHT_ICEBOLT = 8,
EVENT_FLIGHT_BREATH = 9,
EVENT_FLIGHT_SPELL_EXPLOSION = 10,
EVENT_FLIGHT_START_LAND = 11,
EVENT_LAND = 12,
EVENT_GROUND = 13,
EVENT_HUNDRED_CLUB = 14
};
class boss_sapphiron : public CreatureScript
@@ -107,7 +105,6 @@ public:
EnterEvadeMode();
return false;
}
return true;
}
@@ -115,8 +112,9 @@ public:
{
BossAI::Reset();
if (me->IsVisible())
{
me->SetReactState(REACT_AGGRESSIVE);
}
events.Reset();
iceboltCount = 0;
spawnTimer = 0;
@@ -129,12 +127,14 @@ public:
Map::PlayerList const& PlList = me->GetMap()->GetPlayers();
if (PlList.isEmpty())
return;
for (const auto& i : PlList)
{
if (Player* player = i.GetSource())
{
if (player->IsGameMaster())
continue;
if (player->IsAlive() && me->GetDistance(player) < 80.0f)
{
me->SetInCombatWith(player);
@@ -150,12 +150,11 @@ public:
BossAI::EnterCombat(who);
EnterCombatSelfFunction();
me->CastSpell(me, RAID_MODE(SPELL_FROST_AURA_10, SPELL_FROST_AURA_25), true);
events.ScheduleEvent(EVENT_BERSERK, 15 * 60000);
events.ScheduleEvent(EVENT_SPELL_CLEAVE, 5000);
events.ScheduleEvent(EVENT_SPELL_TAIL_SWEEP, 10000);
events.ScheduleEvent(EVENT_SPELL_LIFE_DRAIN, 17000);
events.ScheduleEvent(EVENT_SPELL_BLIZZARD, 17000);
events.ScheduleEvent(EVENT_BERSERK, 900000);
events.ScheduleEvent(EVENT_CLEAVE, 5000);
events.ScheduleEvent(EVENT_TAIL_SWEEP, 10000);
events.ScheduleEvent(EVENT_LIFE_DRAIN, 17000);
events.ScheduleEvent(EVENT_BLIZZARD, 17000);
events.ScheduleEvent(EVENT_FLIGHT_START, 45000);
events.ScheduleEvent(EVENT_HUNDRED_CLUB, 5000);
}
@@ -169,13 +168,17 @@ public:
void DoAction(int32 param) override
{
if (param == ACTION_SAPPHIRON_BIRTH)
{
spawnTimer = 1;
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_CENTER)
{
events.ScheduleEvent(EVENT_FLIGHT_LIFTOFF, 500);
}
}
void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override
@@ -199,14 +202,15 @@ public:
return false;
}
}
return true;
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void UpdateAI(uint32 diff) override
@@ -240,28 +244,33 @@ public:
Talk(EMOTE_ENRAGE);
me->CastSpell(me, SPELL_BERSERK, true);
return;
case EVENT_SPELL_CLEAVE:
case EVENT_CLEAVE:
me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false);
events.RepeatEvent(10000);
return;
case EVENT_SPELL_TAIL_SWEEP:
case EVENT_TAIL_SWEEP:
me->CastSpell(me, RAID_MODE(SPELL_TAIL_SWEEP_10, SPELL_TAIL_SWEEP_25), false);
events.RepeatEvent(10000);
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);
events.RepeatEvent(24000);
return;
case EVENT_SPELL_BLIZZARD:
case EVENT_BLIZZARD:
{
Creature* cr;
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
{
cr = me->SummonCreature(NPC_BLIZZARD, *target, TEMPSUMMON_TIMED_DESPAWN, 16000);
}
else
{
cr = me->SummonCreature(NPC_BLIZZARD, *me, TEMPSUMMON_TIMED_DESPAWN, 16000);
}
if (cr)
{
cr->GetMotionMaster()->MoveRandom(40);
}
events.RepeatEvent(RAID_MODE(8000, 6500));
return;
}
@@ -279,6 +288,7 @@ public:
me->GetMotionMaster()->MovePoint(POINT_CENTER, x, y, z);
return;
case EVENT_FLIGHT_LIFTOFF:
Talk(EMOTE_AIR_PHASE);
me->GetMotionMaster()->MoveIdle();
me->SendMeleeAttackStop(me->GetVictim());
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
@@ -291,26 +301,37 @@ public:
case EVENT_FLIGHT_ICEBOLT:
{
if (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);
}
}
std::vector<Unit*> targets;
auto i = me->getThreatManager().getThreatList().begin();
for (; i != me->getThreatManager().getThreatList().end(); ++i)
{
if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER)
{
bool inList = false;
if (!blockList.empty())
{
for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
{
if ((*i)->getTarget()->GetGUID() == *itr)
{
inList = true;
break;
}
}
}
if (!inList)
{
targets.push_back((*i)->getTarget());
}
}
}
if (!targets.empty() && iceboltCount)
{
@@ -323,7 +344,9 @@ public:
events.ScheduleEvent(EVENT_FLIGHT_ICEBOLT, (me->GetExactDist(*itr) / 13.0f)*IN_MILLISECONDS);
}
else
{
events.ScheduleEvent(EVENT_FLIGHT_BREATH, 1000);
}
return;
}
case EVENT_FLIGHT_BREATH:
@@ -338,10 +361,15 @@ public:
return;
case EVENT_FLIGHT_START_LAND:
if (!blockList.empty())
{
for (std::list<uint64>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
{
if (Unit* block = ObjectAccessor::GetUnit(*me, *itr))
{
block->RemoveAurasDueToSpell(SPELL_ICEBOLT_TRIGGER);
}
}
}
blockList.clear();
me->RemoveAllGameObjects();
events.ScheduleEvent(EVENT_LAND, 1000);
@@ -349,12 +377,11 @@ public:
case EVENT_LAND:
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
me->SetDisableGravity(false);
me->SetHover(false);
events.ScheduleEvent(EVENT_GROUND, 1500);
return;
case EVENT_GROUND:
Talk(EMOTE_GROUND_PHASE);
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
return;
@@ -373,7 +400,6 @@ public:
return;
}
}
DoMeleeAttackIfReady();
}
};
@@ -398,12 +424,15 @@ public:
for (auto& target : targets)
{
if (CAST_AI(boss_sapphiron::boss_sapphironAI, caster->ToCreature()->AI())->IsValidExplosionTarget(target))
{
tmplist.push_back(target);
}
}
targets.clear();
for (auto& itr : tmplist)
{
targets.push_back(itr);
}
}
void Register() override

View File

@@ -11,36 +11,37 @@
enum Says
{
// Stalagg
SAY_STAL_AGGRO = 0,
SAY_STAL_SLAY = 1,
SAY_STAL_DEATH = 2,
EMOTE_STAL_DEATH = 3,
EMOTE_STAL_REVIVE = 4,
SAY_STAL_AGGRO = 0,
SAY_STAL_SLAY = 1,
SAY_STAL_DEATH = 2,
EMOTE_STAL_DEATH = 3,
EMOTE_STAL_REVIVE = 4,
// Feugen
SAY_FEUG_AGGRO = 0,
SAY_FEUG_SLAY = 1,
SAY_FEUG_DEATH = 2,
EMOTE_FEUG_DEATH = 3,
EMOTE_FEUG_REVIVE = 4,
SAY_FEUG_AGGRO = 0,
SAY_FEUG_SLAY = 1,
SAY_FEUG_DEATH = 2,
EMOTE_FEUG_DEATH = 3,
EMOTE_FEUG_REVIVE = 4,
// Thaddius
SAY_GREET = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_ELECT = 3,
SAY_DEATH = 4,
EMOTE_POLARITY_SHIFTED = 6,
SAY_GREET = 0,
SAY_AGGRO = 1,
SAY_SLAY = 2,
SAY_ELECT = 3,
SAY_DEATH = 4,
EMOTE_POLARITY_SHIFTED = 6,
// Tesla Coil
EMOTE_TESLA_LINK_BREAKS = 0,
EMOTE_TESLA_OVERLOAD = 1
EMOTE_TESLA_LINK_BREAKS = 0,
EMOTE_TESLA_OVERLOAD = 1
};
enum Spells
{
SPELL_MAGNETIC_PULL = 28337,
SPELL_TESLA_SHOCK = 28099,
SPELL_SHOCK_VISUAL = 28159,
// Stalagg
SPELL_POWER_SURGE_10 = 54529,
@@ -58,7 +59,6 @@ enum Spells
SPELL_CHAIN_LIGHTNING_10 = 28167,
SPELL_CHAIN_LIGHTNING_25 = 54531,
SPELL_BERSERK = 27680,
SPELL_THADDIUS_VISUAL_LIGHTNING = 28136,
SPELL_THADDIUS_SPAWN_STUN = 28160,
@@ -67,22 +67,22 @@ enum Spells
SPELL_NEGATIVE_CHARGE = 28085,
SPELL_NEGATIVE_CHARGE_STACK = 29660,
SPELL_POSITIVE_POLARITY = 28059,
SPELL_NEGATIVE_POLARITY = 28084,
SPELL_NEGATIVE_POLARITY = 28084
};
enum Events
{
EVENT_MINION_SPELL_POWER_SURGE = 1,
EVENT_MINION_SPELL_MAGNETIC_PULL = 2,
EVENT_MINION_POWER_SURGE = 1,
EVENT_MINION_MAGNETIC_PULL = 2,
EVENT_MINION_CHECK_DISTANCE = 3,
EVENT_MINION_SPELL_STATIC_FIELD = 4,
EVENT_MINION_STATIC_FIELD = 4,
EVENT_THADDIUS_START = 10,
EVENT_THADDIUS_SPELL_CHAIN_LIGHTNING = 11,
EVENT_THADDIUS_SPELL_BERSERK = 12,
EVENT_THADDIUS_POLARITY_SHIFT = 13,
EVENT_THADDIUS_START_2 = 14,
EVENT_ACTIVATE_BALL_LIGHTNING = 15
EVENT_THADDIUS_INIT = 5,
EVENT_THADDIUS_ENTER_COMBAT = 6,
EVENT_THADDIUS_CHAIN_LIGHTNING = 7,
EVENT_THADDIUS_BERSERK = 8,
EVENT_THADDIUS_POLARITY_SHIFT = 9,
EVENT_ALLOW_BALL_LIGHTNING = 10
};
enum Misc
@@ -90,7 +90,10 @@ enum Misc
ACTION_MAGNETIC_PULL = 1,
ACTION_SUMMON_DIED = 2,
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
@@ -118,27 +121,16 @@ public:
uint32 resetTimer{};
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
{
if (param == ACTION_SUMMON_DIED)
{
// Hooray, we did it!
if (summonTimer)
{
summonTimer = 0;
reviveTimer = 1;
//events.ScheduleEvent(EVENT_THADDIUS_START, 12000);
return;
}
summonTimer = 1;
}
}
@@ -149,6 +141,7 @@ public:
events.Reset();
summons.DespawnAll();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetControlled(false, UNIT_STATE_ROOT);
summonTimer = 0;
reviveTimer = 0;
resetTimer = 1;
@@ -164,6 +157,7 @@ public:
cr->CastSpell(cr, SPELL_FEUGEN_CHAIN, false);
cr->SetDisableGravity(true);
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))
{
@@ -172,6 +166,20 @@ public:
cr->CastSpell(cr, SPELL_STALAGG_CHAIN, false);
cr->SetDisableGravity(true);
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,9 +189,10 @@ public:
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
@@ -195,9 +204,16 @@ public:
pInstance->DoRemoveAurasDueToSpellOnPlayers(28059);
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
{
@@ -224,16 +240,19 @@ public:
reviveTimer += diff;
if (reviveTimer >= 12000)
{
events.ScheduleEvent(EVENT_THADDIUS_START, 1500);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, (*itr)))
{
if (cr->GetEntry() == NPC_TESLA_COIL)
{
cr->AI()->Talk(EMOTE_TESLA_OVERLOAD);
cr->CastSpell(me, SPELL_TESLA_SHOCK, true); // till smth better is found ;( ZOMG
Unit::Kill(cr, cr);
cr->CastSpell(me, SPELL_SHOCK_VISUAL, true);
}
}
}
reviveTimer = 0;
events.ScheduleEvent(EVENT_THADDIUS_INIT, 750);
}
return;
}
@@ -245,8 +264,7 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
// Revive code!
if (summonTimer)
if (summonTimer) // Revive
{
summonTimer += diff;
if (summonTimer >= 5000)
@@ -258,27 +276,46 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_THADDIUS_START:
StartEvent();
case EVENT_THADDIUS_INIT:
{
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;
case EVENT_THADDIUS_START_2:
}
case EVENT_THADDIUS_ENTER_COMBAT:
Talk(SAY_AGGRO);
me->SetReactState(REACT_AGGRESSIVE);
me->SetControlled(false, UNIT_STATE_STUNNED);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->setAttackTimer(BASE_ATTACK, 4000);
events.ScheduleEvent(EVENT_THADDIUS_SPELL_CHAIN_LIGHTNING, 14000);
events.ScheduleEvent(EVENT_THADDIUS_SPELL_BERSERK, 360000);
events.ScheduleEvent(EVENT_THADDIUS_CHAIN_LIGHTNING, 14000);
events.ScheduleEvent(EVENT_THADDIUS_BERSERK, 360000);
events.ScheduleEvent(EVENT_THADDIUS_POLARITY_SHIFT, 30000);
events.ScheduleEvent(EVENT_ACTIVATE_BALL_LIGHTNING, 5000);
events.ScheduleEvent(EVENT_ALLOW_BALL_LIGHTNING, 5000);
return;
case EVENT_THADDIUS_SPELL_BERSERK:
case EVENT_THADDIUS_BERSERK:
me->CastSpell(me, SPELL_BERSERK, true);
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);
events.RepeatEvent(15000);
break;
@@ -286,17 +323,23 @@ public:
me->CastSpell(me, SPELL_POLARITY_SHIFT, false);
events.RepeatEvent(30000);
break;
case EVENT_ACTIVATE_BALL_LIGHTNING:
case EVENT_ALLOW_BALL_LIGHTNING:
ballLightningEnabled = true;
me->SetControlled(true, UNIT_STATE_ROOT);
break;
}
if (me->IsWithinMeleeRange(me->GetVictim()))
{
DoMeleeAttackIfReady();
}
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;
visualTimer = 1;
overload = false;
events.Reset();
me->SetControlled(false, UNIT_STATE_STUNNED);
if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f))
@@ -352,32 +394,38 @@ public:
void EnterCombat(Unit* pWho) override
{
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))
{
myCoil = cr->GetGUID();
}
if (me->GetEntry() == NPC_STALAGG)
{
events.ScheduleEvent(EVENT_MINION_SPELL_POWER_SURGE, 10000);
events.ScheduleEvent(EVENT_MINION_POWER_SURGE, 10000);
Talk(SAY_STAL_AGGRO);
}
else
{
events.ScheduleEvent(EVENT_MINION_SPELL_STATIC_FIELD, 5000);
events.ScheduleEvent(EVENT_MINION_STATIC_FIELD, 5000);
Talk(SAY_FEUG_AGGRO);
}
events.ScheduleEvent(EVENT_MINION_CHECK_DISTANCE, 5000);
// This event needs synchronisation, called for stalagg only
if (me->GetEntry() == NPC_STALAGG)
events.ScheduleEvent(EVENT_MINION_SPELL_MAGNETIC_PULL, 25000);
if (me->GetEntry() == NPC_STALAGG) // This event needs synchronisation, called for stalagg only
{
events.ScheduleEvent(EVENT_MINION_MAGNETIC_PULL, 20000);
}
if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS)))
{
cr->AI()->AttackStart(pWho);
cr->AddThreat(pWho, 10.0f);
}
}
}
void DoAction(int32 param) override
@@ -396,7 +444,9 @@ public:
Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_REVIVE : EMOTE_FEUG_REVIVE);
}
else
{
me->SetHealth(me->GetMaxHealth());
}
}
}
@@ -405,8 +455,12 @@ public:
Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_DEATH : SAY_FEUG_DEATH);
Talk(me->GetEntry() == NPC_STALAGG ? EMOTE_STAL_DEATH : EMOTE_FEUG_DEATH);
if (pInstance)
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_THADDIUS_BOSS)))
{
cr->AI()->DoAction(ACTION_SUMMON_DIED);
}
}
}
void KilledUnit(Unit* who) override
@@ -415,10 +469,13 @@ public:
return;
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
if (!urand(0, 2))
{
Talk(me->GetEntry() == NPC_STALAGG ? SAY_STAL_SLAY : SAY_FEUG_SLAY);
}
}
void UpdateAI(uint32 diff) override
@@ -430,15 +487,16 @@ public:
{
visualTimer = 0;
if (Creature* cr = me->FindNearestCreature(NPC_TESLA_COIL, 150.0f))
{
cr->CastSpell(cr, me->GetEntry() == NPC_STALAGG ? SPELL_STALAGG_CHAIN : SPELL_FEUGEN_CHAIN, false);
}
}
}
if (!UpdateVictim())
return;
// Disable AI during pull
if (pullTimer)
if (pullTimer) // Disable AI during pull
{
pullTimer += diff;
if (pullTimer >= 3000)
@@ -455,17 +513,18 @@ public:
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);
events.RepeatEvent(19000);
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);
events.RepeatEvent(3000);
break;
case EVENT_MINION_SPELL_MAGNETIC_PULL:
events.RepeatEvent(25000);
case EVENT_MINION_MAGNETIC_PULL:
events.RepeatEvent(20000);
if (pInstance)
{
if (Creature* feugen = ObjectAccessor::GetCreature(*me, pInstance->GetData64(DATA_FEUGEN_BOSS)))
{
if (!feugen->IsAlive() || !feugen->GetVictim() || !me->GetVictim())
@@ -486,7 +545,7 @@ public:
me->CastSpell(tankFeugen, SPELL_MAGNETIC_PULL, true);
DoAction(ACTION_MAGNETIC_PULL);
}
}
break;
case EVENT_MINION_CHECK_DISTANCE:
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);
}
}
events.RepeatEvent(5000);
break;
}
DoMeleeAttackIfReady();
}
};
@@ -537,20 +594,29 @@ public:
{
uint8 count = 0;
for (auto& ihit : targets)
{
if (ihit->GetGUID() != GetCaster()->GetGUID())
{
if (Player* target = ihit->ToPlayer())
{
if (target->HasAura(GetTriggeringSpell()->Id))
{
++count;
}
}
}
}
if (count)
{
uint32 spellId = 0;
if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE)
{
spellId = SPELL_POSITIVE_CHARGE_STACK;
}
else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE)
{
spellId = SPELL_NEGATIVE_CHARGE_STACK;
}
GetCaster()->SetAuraStack(spellId, GetCaster(), count);
}
}
@@ -565,9 +631,13 @@ public:
return;
if (target->HasAura(GetTriggeringSpell()->Id) || target->GetTypeId() != TYPEID_PLAYER)
{
SetHitDamage(0);
}
else if (target->GetInstanceScript())
{
target->GetInstanceScript()->SetData(DATA_CHARGES_CROSSED, 0);
}
}
void Register() override
@@ -601,18 +671,24 @@ public:
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
{
target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, nullptr, nullptr, caster->GetGUID());
}
}
void HandleAfterCast()
{
if (GetCaster())
{
if (Creature* caster = GetCaster()->ToCreature())
{
if (caster->GetEntry() == NPC_THADDIUS)
{
caster->AI()->Talk(SAY_ELECT);
caster->AI()->Talk(EMOTE_POLARITY_SHIFTED);
}
}
}
}
void Register() override
@@ -661,7 +737,9 @@ public:
return true;
if (Creature* thaddius = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_THADDIUS_BOSS)))
{
thaddius->AI()->Talk(SAY_GREET);
}
instance->SetData(DATA_HAD_THADDIUS_GREET, 1);
return true;
@@ -673,9 +751,7 @@ void AddSC_boss_thaddius()
new boss_thaddius();
new boss_thaddius_summon();
new npc_tesla();
new spell_thaddius_pos_neg_charge();
new spell_thaddius_polarity_shift();
new at_thaddius_entrance();
}

View File

@@ -30,8 +30,10 @@ inline uint8 GetEruptionSection(float x, float y)
float slope = y / x;
for (uint32 i = 0; i < 3; ++i)
{
if (slope > HeiganEruptionSlope[i])
return i;
}
return 3;
}
@@ -68,6 +70,10 @@ public:
_horsemanGateGUID = 0;
_kelthuzadfloorGUID = 0;
_kelthuzadgateGUID = 0;
_kelthuzadportal1GUID = 0;
_kelthuzadportal2GUID = 0;
_kelthuzadportal3GUID = 0;
_kelthuzadportal4GUID = 0;
_sapphironGateGUID = 0;
_horsemanPortalGUID = 0;
_loathebPortalGUID = 0;
@@ -131,6 +137,10 @@ public:
uint64 _horsemanGateGUID;
uint64 _kelthuzadfloorGUID;
uint64 _kelthuzadgateGUID;
uint64 _kelthuzadportal1GUID;
uint64 _kelthuzadportal2GUID;
uint64 _kelthuzadportal3GUID;
uint64 _kelthuzadportal4GUID;
uint64 _sapphironGateGUID;
uint64 _horsemanPortalGUID;
uint64 _loathebPortalGUID;
@@ -272,57 +282,79 @@ public:
case GO_PATCHWERK_GATE:
_patchwerkGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_PATCHWERK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_GLUTH_GATE:
_gluthGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GLUTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_NOTH_GATE:
_nothGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_NOTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_HEIGAN_ENTERANCE_GATE:
_heiganGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_HEIGAN) == DONE || GetBossState(BOSS_NOTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_HEIGAN_EXIT_GATE:
_heiganGateExitGUID = pGo->GetGUID();
if (GetBossState(BOSS_HEIGAN) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_LOATHEB_GATE:
_loathebGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_ANUB_GATE:
_anubGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_ANUB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_ANUB_NEXT_GATE:
_anubNextGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_ANUB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_FAERLINA_GATE:
_faerlinaGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_FAERLINA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_MAEXXNA_GATE:
_maexxnaGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_FAERLINA) == DONE) // faerlina is correct
if (GetBossState(BOSS_FAERLINA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_THADDIUS_GATE:
_thaddiusGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GLUTH) == DONE) // gluth is correct
if (GetBossState(BOSS_GLUTH) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_GOTHIK_ENTER_GATE:
_gothikEnterGateGUID = pGo->GetGUID();
@@ -333,12 +365,16 @@ public:
case GO_GOTHIK_EXIT_GATE:
_gothikExitGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GOTHIK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_HORSEMAN_GATE:
_horsemanGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_GOTHIK) == DONE) // correct
if (GetBossState(BOSS_GOTHIK) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_KELTHUZAD_FLOOR:
_kelthuzadfloorGUID = pGo->GetGUID();
@@ -346,52 +382,84 @@ public:
case GO_KELTHUZAD_GATE:
_kelthuzadgateGUID = pGo->GetGUID();
if (GetBossState(BOSS_SAPPHIRON) == DONE && _speakTimer == 0)
{
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;
case GO_SAPPHIRON_GATE:
_sapphironGateGUID = pGo->GetGUID();
if (GetBossState(BOSS_SAPPHIRON) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_DEATHKNIGHT_WING:
_loathebPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetPhaseMask(1, true);
}
break;
case GO_THADDIUS_PORTAL:
_thaddiusPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_THADDIUS) == DONE)
{
pGo->SetPhaseMask(1, true);
}
break;
case GO_MAEXXNA_PORTAL:
_maexxnaPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_MAEXXNA) == DONE)
{
pGo->SetPhaseMask(1, true);
}
break;
case GO_HORSEMAN_PORTAL:
_horsemanPortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_HORSEMAN) == DONE)
{
pGo->SetPhaseMask(1, true);
}
break;
case GO_DEATHKNIGHT_EYE_PORTAL:
_deathknightEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_HORSEMAN) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_PLAGUE_EYE_PORTAL:
_plagueEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_LOATHEB) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_SPIDER_EYE_PORTAL:
_spiderEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_MAEXXNA) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_ABOM_EYE_PORTAL:
_abomEyePortalGUID = pGo->GetGUID();
if (GetBossState(BOSS_THADDIUS) == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
}
}
@@ -404,10 +472,13 @@ public:
HeiganEruption[section].erase(pGo);
return;
}
if (pGo->GetEntry() == GO_SAPPHIRON_BIRTH)
{
if (Creature* cr = instance->GetCreature(_sapphironGUID))
{
cr->AI()->DoAction(ACTION_SAPPHIRON_BIRTH);
}
}
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
@@ -484,9 +555,10 @@ public:
{
uint8 count = 0;
for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
{
if (GetBossState(i) == NOT_STARTED)
++count;
}
return !count && immortalAchievement;
}
@@ -550,7 +622,9 @@ public:
{
Creature* trash = ObjectAccessor::GetCreature(*patch, itr);
if (trash && trash->IsAlive() && !trash->IsInCombat())
{
trash->AI()->AttackStart(patch->GetVictim());
}
}
}
}
@@ -566,10 +640,11 @@ public:
{
return false;
}
// All horsemans are killed
if (Creature* cr = instance->GetCreature(_blaumeuxGUID))
{
cr->CastSpell(cr, 59450, true); // credit
}
}
// respawn
@@ -578,45 +653,63 @@ public:
Creature* cr;
_horsemanKilled = 0;
if ((cr = instance->GetCreature(_blaumeuxGUID)))
{
if (!cr->IsAlive())
{
cr->SetPosition(cr->GetHomePosition());
cr->Respawn();
}
}
if ((cr = instance->GetCreature(_rivendareGUID)))
{
if (!cr->IsAlive())
{
cr->SetPosition(cr->GetHomePosition());
cr->Respawn();
}
}
if ((cr = instance->GetCreature(_zeliekGUID)))
{
if (!cr->IsAlive())
{
cr->SetPosition(cr->GetHomePosition());
cr->Respawn();
}
}
if ((cr = instance->GetCreature(_korthazzGUID)))
{
if (!cr->IsAlive())
{
cr->SetPosition(cr->GetHomePosition());
cr->Respawn();
}
}
}
else if (state == IN_PROGRESS)
{
Creature* cr;
if ((cr = instance->GetCreature(_blaumeuxGUID)))
{
cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_rivendareGUID)))
{
cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_zeliekGUID)))
{
cr->SetInCombatWithZone();
}
if ((cr = instance->GetCreature(_korthazzGUID)))
{
cr->SetInCombatWithZone();
}
}
if (state == NOT_STARTED)
{
_horsemanTimer = 0;
}
}
if (!InstanceScript::SetBossState(bossId, state))
@@ -627,23 +720,33 @@ public:
{
case BOSS_KELTHUZAD:
if (state == NOT_STARTED)
{
abominationsKilled = 0;
}
break;
case BOSS_FAERLINA:
if (state == NOT_STARTED)
{
faerlinaAchievement = true;
}
break;
case BOSS_THADDIUS:
if (state == NOT_STARTED)
{
thaddiusAchievement = true;
}
break;
case BOSS_LOATHEB:
if (state == NOT_STARTED)
{
loathebAchievement = true;
}
break;
case BOSS_HEIGAN:
if (state == NOT_STARTED)
{
heiganAchievement = true;
}
break;
case BOSS_SAPPHIRON:
if (state == DONE)
@@ -653,7 +756,9 @@ public:
instance->LoadGrid(3763.43f, -5115.87f);
}
else if (state == NOT_STARTED)
{
sapphironAchievement = true;
}
break;
default:
break;
@@ -668,87 +773,133 @@ public:
{
case BOSS_PATCHWERK:
if (GameObject* go = instance->GetGameObject(_patchwerkGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_GLUTH:
if (GameObject* go = instance->GetGameObject(_gluthGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_thaddiusGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_NOTH:
if (GameObject* go = instance->GetGameObject(_nothGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_heiganGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_HEIGAN:
if (GameObject* go = instance->GetGameObject(_heiganGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_heiganGateExitGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_LOATHEB:
if (GameObject* go = instance->GetGameObject(_loathebGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_loathebPortalGUID))
{
go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_plagueEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break;
case BOSS_ANUB:
if (GameObject* go = instance->GetGameObject(_anubGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_anubNextGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_FAERLINA:
if (GameObject* go = instance->GetGameObject(_faerlinaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_MAEXXNA:
if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_maexxnaPortalGUID))
{
go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_spiderEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break;
case BOSS_GOTHIK:
if (GameObject* go = instance->GetGameObject(_gothikEnterGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_gothikExitGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* go = instance->GetGameObject(_horsemanGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
case BOSS_SAPPHIRON:
if (GameObject* go = instance->GetGameObject(_sapphironGateGUID))
go->SetGoState(GO_STATE_ACTIVE);
events.ScheduleEvent(EVENT_FROSTWYRM_WATERFALL_DOOR, 5000);
break;
case BOSS_THADDIUS:
if (GameObject* go = instance->GetGameObject(_thaddiusPortalGUID))
{
go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_abomEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break;
case BOSS_HORSEMAN:
if (GameObject* go = instance->GetGameObject(_horsemanPortalGUID))
{
go->SetPhaseMask(1, true);
}
if (GameObject* go = instance->GetGameObject(_deathknightEyePortalGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
break;
default:
break;
}
}
return true;
}
@@ -759,9 +910,13 @@ public:
Creature* kel = instance->GetCreature(_kelthuzadGUID);
Creature* lich = instance->GetCreature(_lichkingGUID);
if (kel && lich)
{
_speakTimer += diff;
}
else
{
return;
}
if (_speakTimer > 10000 && _speakTimer < 20000)
{
kel->AI()->Talk(SAY_SAPP_DIALOG1);
@@ -792,13 +947,17 @@ public:
kel->AI()->Talk(SAY_SAPP_DIALOG6);
_speakTimer = 0;
if (GameObject* go = instance->GetGameObject(_kelthuzadgateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
// And They would all
if (_horsemanTimer)
{
_horsemanTimer += diff;
}
if (_screamTimer && GetBossState(BOSS_THADDIUS) != DONE)
{
@@ -808,7 +967,9 @@ public:
_screamTimer = (2 * MINUTE + urand(0, 30)) * IN_MILLISECONDS;
}
else
{
_screamTimer -= diff;
}
}
events.Update(diff);
@@ -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.
instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(_kelthuzadGUID))
{
kelthuzad->AI()->Talk(_currentWingTaunt);
}
++_currentWingTaunt;
break;
case EVENT_FROSTWYRM_WATERFALL_DOOR:
if (GameObject* go = instance->GetGameObject(_sapphironGateGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
}
break;
}
}
@@ -848,6 +1016,14 @@ public:
return _kelthuzadfloorGUID;
case DATA_KELTHUZAD_GATE:
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
case DATA_THADDIUS_BOSS:
@@ -896,9 +1072,13 @@ public:
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS)
{
tmpState = NOT_STARTED;
}
if (i == BOSS_HORSEMAN && tmpState == DONE)
{
_horsemanLoadDoneState = true;
}
SetBossState(i, EncounterState(tmpState));
}
loadStream >> immortalAchievement;
@@ -906,7 +1086,9 @@ public:
OUT_LOAD_INST_DATA_COMPLETE;
}
else
{
OUT_LOAD_INST_DATA_FAIL;
}
}
};
};
@@ -963,7 +1145,9 @@ public:
acore::UnitLastSearcher<acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, target, u_check);
me->VisitNearbyObject(1.5f, searcher);
if (target)
{
me->CastSpell(me, SPELL_FROGGER_EXPLODE, true);
}
}
}
};

View File

@@ -51,6 +51,10 @@ enum NXData
DATA_IMMORTAL_FAIL = 119,
DATA_KELTHUZAD_GATE = 120,
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
@@ -78,19 +82,20 @@ enum NXGOs
GO_SAPPHIRON_BIRTH = 181356,
GO_KELTHUZAD_FLOOR = 181444,
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_THADDIUS_PORTAL = 181576, //Thadius portal
GO_MAEXXNA_PORTAL = 181575, //Maexxna portal
GO_HORSEMAN_PORTAL = 181578, //Four Horseman portal
GO_DEATHKNIGHT_WING = 181577,
GO_THADDIUS_PORTAL = 181576,
GO_MAEXXNA_PORTAL = 181575,
GO_HORSEMAN_PORTAL = 181578,
GO_DEATHKNIGHT_EYE_PORTAL = 181210,
GO_PLAGUE_EYE_PORTAL = 181211,
GO_SPIDER_EYE_PORTAL = 181212,
GO_ABOM_EYE_PORTAL = 181213,
GO_CONS_NOX_TESLA_STALAGG = 268049,
GO_CONS_NOX_TESLA_FEUGEN = 268050
GO_ABOM_EYE_PORTAL = 181213
};
enum NXNPCs
@@ -130,14 +135,11 @@ enum NXNPCs
enum NXMisc
{
// Spells
SPELL_ERUPTION = 29371,
SPELL_FROGGER_EXPLODE = 28433,
// Actions
ACTION_SAPPHIRON_BIRTH = 1,
// Sounds
// Background screams in instance if Thaddius still alive, four of them from 8873 to 8876
SOUND_SCREAM = 8873
};
@@ -156,8 +158,9 @@ enum NXSays
enum NXEvents
{
EVENT_THADDIUS_SCREAMS = 0,
EVENT_KELTHUZAD_WING_TAUNT
EVENT_THADDIUS_SCREAMS = 0,
EVENT_KELTHUZAD_WING_TAUNT = 1,
EVENT_FROSTWYRM_WATERFALL_DOOR = 2
};
#endif