diff --git a/data/sql/updates/pending_db_world/rev_1609119138728662700.sql b/data/sql/updates/pending_db_world/rev_1609119138728662700.sql new file mode 100644 index 000000000..04645b3ea --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1609119138728662700.sql @@ -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'); + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 9b640f8ff..48f8c1784 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -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::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(); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index b1ca7971b..85e680dd3 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -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::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); + } } } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 04a4d7ced..9d864d9e7 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -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()); + } } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 17cc0f7a2..40570ec32 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -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); } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 0123c5384..1cf8e8656 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -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(); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index f2019657e..227eb4d24 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -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::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 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(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index c3cf62808..6e48ef31a 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -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(); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 6871bddf8..72a90993b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -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(M_PI)); + return fmod(o, 2.0f * static_cast(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 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 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)) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index a183557db..170b66777 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -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(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index 0065b93f5..4b6a9f728 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -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()); + } + } } }; }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 781e69b32..38e188b68 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -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(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index 08116a653..69051ced1 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -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 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>::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(); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp index 472a66420..6db395420 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -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(); } }; }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 0df8add10..1af2ecf2b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -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 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::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::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 diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index a27330d92..dac7bfed3 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -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(); } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 8f2b57e31..5f16f88ed 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -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 searcher(me, target, u_check); me->VisitNearbyObject(1.5f, searcher); if (target) + { me->CastSpell(me, SPELL_FROGGER_EXPLODE, true); + } } } }; diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 263ee77e6..f36f64de8 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -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