diff --git a/data/sql/updates/pending_db_world/rev_1760824970973012794.sql b/data/sql/updates/pending_db_world/rev_1760824970973012794.sql new file mode 100644 index 000000000..ebc07bc11 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1760824970973012794.sql @@ -0,0 +1,53 @@ +-- +DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (53618, 53616, 53617, 53602); +INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES +(53618, 53618, 59350, 0, 0), +(53616, 53616, 59360, 0, 0), +(53617, 53617, 59359, 0, 0), +(53602, 53602, 59349, 0, 0); + +DELETE FROM `creature_summon_groups` WHERE `summonerId` = 29120 AND `entry` = 22515; +INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`, `Comment`) VALUES +(29120, 0, 1, 22515, 549.622, 352.047, 240.8899, 3.45575, 8, 0, 'Anub''arak - Group 1 - World Trigger'), +(29120, 0, 2, 22515, 478.739, 252.85, 250.544, 0.0523599, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 621.319, 268.482, 250.544, 3.33358, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 622.904, 252.945, 250.544, 3.12414, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 478.149, 269.009, 250.544, 6.12611, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 478.547, 297.045, 250.544, 5.79449, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 478.291, 224.827, 250.235, 0.401426, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 620.622, 298.263, 250.544, 3.7001, 8, 0, 'Anub''arak - Group 2 - World Trigger'), +(29120, 0, 2, 22515, 620.704, 224.562, 250.232, 2.53073, 8, 0, 'Anub''arak - Group 2 - World Trigger'); + +-- Position where Anub'ar Guardian and Anub'ar Venomancer run to after spawning +SET @POS_X := 551.0095; +SET @POS_Y := 274.026; +SET @POS_Z := 223.89513; + +-- Update comments, spelldifficulty_dbc +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29216); +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`, `event_param6`, `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 +(29216, 0, 0, 0, 0, 0, 100, 0, 5000, 8000, 6000, 6000, 0, 0, 11, 53618, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Guardian - In Combat - Cast \'Sunder Armor\''), +(29216, 0, 1, 0, 0, 0, 100, 0, 2000, 3000, 8000, 8000, 0, 0, 11, 52532, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Guardian - In Combat - Cast \'Strike\''), +(29216, 0, 2, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, @POS_X, @POS_Y, @POS_Z, 0, 'Anub\'ar Guardian - On Just Summoned - Move To Position'); + +-- Update comments, spelldifficulty_dbc +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29217); +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`, `event_param6`, `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 +(29217, 0, 0, 0, 0, 0, 100, 0, 5000, 8000, 18000, 22000, 0, 0, 11, 53616, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Venomancer - In Combat - Cast \'Poison Bolt Volley\''), +(29217, 0, 1, 0, 0, 0, 100, 0, 2000, 3000, 7000, 7000, 0, 0, 11, 53617, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Venomancer - In Combat - Cast \'Poison Bolt\''), +(29217, 0, 2, 0, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, @POS_X, @POS_Y, @POS_Z, 0, 'Anub\'ar Venomancer - On Just Summoned - Move To Position'); + +-- Update comments, bump jump range from 50 to 100 yards, spelldifficulty_dbc +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29213); +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`, `event_param6`, `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 +(29213, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 97, 20, 10, 1, 0, 0, 0, 21, 100, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Darter - On Respawn - Jump To Pos'), +(29213, 0, 1, 0, 0, 0, 100, 0, 4000, 5000, 7000, 7000, 0, 0, 11, 53602, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Darter - In Combat - Cast \'Dart\''); + +-- Update comments, remove visual, bump jump range from 50 to 100 yards, spelldifficulty_dbc +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 29214) AND (`source_type` = 0); +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`, `event_param6`, `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 +(29214, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 97, 20, 10, 1, 0, 0, 0, 21, 100, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Assassin - On Respawn - Jump To Pos'), +(29214, 0, 1, 0, 67, 0, 100, 0, 5000, 5000, 5000, 5000, 0, 5, 11, 52540, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Assassin - On Behind Target - Cast \'Backstab\''), +(29214, 0, 2, 0, 0, 0, 100, 1, 3000, 3000, 0, 0, 0, 0, 28, 53611, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Anub\'ar Assassin - In Combat - Remove Aura \'Anub`ar Assasssin Visual Passive\' (No Repeat)'); + +UPDATE `spell_script_names` SET `ScriptName`='spell_azjol_nerub_carrion_beetles' WHERE `spell_id`=53520 AND `ScriptName`='spell_azjol_nerub_carrion_beetels'; diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h index 39f15f6ab..90222743e 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h @@ -28,7 +28,7 @@ enum ANData { DATA_KRIKTHIR = 0, DATA_HADRONOX = 1, - DATA_ANUBARAK_EVENT = 2, + DATA_ANUBARAK = 2, MAX_ENCOUNTERS = 3 }; @@ -41,6 +41,8 @@ enum ANIds NPC_SKITTERING_INFECTIOR = 28736, NPC_KRIKTHIR_THE_GATEWATCHER = 28684, NPC_HADRONOX = 28921, + NPC_ANUBARAK = 29120, + NPC_ANUB_AR_CHAMPION = 29062, NPC_ANUB_AR_NECROMANCER = 29063, NPC_ANUB_AR_CRYPTFIEND = 29064, @@ -59,4 +61,6 @@ inline AI* GetAzjolNerubAI(T* obj) return GetInstanceAI(obj, AzjolNerubScriptName); } +#define RegisterAzjolNerubCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetAzjolNerubAI) + #endif diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index ef3bebdfa..ec4dd204c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -55,223 +55,347 @@ enum Yells enum Misc { ACHIEV_TIMED_START_EVENT = 20381, +}; - EVENT_CARRION_BEETELS = 1, +enum Events +{ + EVENT_CARRION_BEETLES = 1, EVENT_LEECHING_SWARM = 2, EVENT_IMPALE = 3, EVENT_POUND = 4, - EVENT_CLOSE_DOORS = 5, - EVENT_EMERGE = 6, - EVENT_SUMMON_VENOMANCER = 7, - EVENT_SUMMON_DARTER = 8, - EVENT_SUMMON_GUARDIAN = 9, - EVENT_SUMMON_ASSASSINS = 10, - EVENT_ENABLE_ROTATE = 11, + EVENT_ENABLE_ROTATE = 5, + EVENT_CLOSE_DOORS = 6, + EVENT_EMERGE = 7, + EVENT_SUMMON_GUARDIAN = 8, + EVENT_SUMMON_VENOMANCER = 9, + EVENT_SUMMON_DARTER = 10, + EVENT_SUMMON_ASSASSINS = 11, EVENT_KILL_TALK = 12 }; -enum ANAnubarakNpcs +enum CreatureIds { + NPC_WORLD_TRIGGER = 22515, NPC_ANUBAR_GUARDIAN = 29216, - NPC_ANUBAR_VENOMANCER = 29217 + NPC_ANUBAR_VENOMANCER = 29217, }; -class boss_anub_arak : public CreatureScript +enum Phases : uint8 { - public: - boss_anub_arak() : CreatureScript("boss_anub_arak") { } + PHASE_EMERGED = 1, + PHASE_SUBMERGED +}; - struct boss_anub_arakAI : public BossAI +enum SubPhase : uint8 +{ + SUBMERGE_NONE = 0, + SUBMERGE_75 = 1, + SUBMERGE_50 = 2, + SUBMERGE_25 = 3, +}; + +enum SummonGroups +{ + SUMMON_GROUP_WORLD_TRIGGER_GUARDIAN = 1, + SUMMON_GROUP_WORLD_TRIGGER_BALCONY = 2 +}; + +struct boss_anub_arak : public BossAI +{ + explicit boss_anub_arak(Creature* creature) : BossAI(creature, DATA_ANUBARAK), _intro(false), + _submergePhase(SUBMERGE_NONE), _remainingLargeSummonsBeforeEmerge(0), _balconySummons(me) + { + me->m_SightDistance = 120.0f; + } + + void Reset() override + { + BossAI::Reset(); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + _remainingLargeSummonsBeforeEmerge = 0; + _submergePhase = SUBMERGE_NONE; + + ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{ + events.Reset(); + Talk(SAY_SUBMERGE); + DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true); + DoCastSelf(SPELL_SUBMERGE, false); + }, false); + } + + void SpellHitTarget(Unit* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_SUBMERGE) { - boss_anub_arakAI(Creature* creature) : BossAI(creature, DATA_ANUBARAK_EVENT) - { - me->m_SightDistance = 120.0f; - _intro = false; - _summonedMinions = false; - } + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAurasDueToSpell(SPELL_LEECHING_SWARM); + DoCastSelf(SPELL_IMPALE_PERIODIC, true); - void EnterEvadeMode(EvadeReason why) override - { - me->DisableRotate(false); - BossAI::EnterEvadeMode(why); - } - - void MoveInLineOfSight(Unit* who) override - { - if (!_intro && who->IsPlayer()) - { - _intro = true; - Talk(SAY_INTRO); - } - BossAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* killer) override - { - Talk(SAY_DEATH); - BossAI::JustDied(killer); - } - - void KilledUnit(Unit* /*victim*/) override - { - if (!events.HasTimeUntilEvent(EVENT_KILL_TALK)) - { - Talk(SAY_SLAY); - events.ScheduleEvent(EVENT_KILL_TALK, 6s); - } - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (!summon->IsTrigger()) - summon->SetInCombatWithZone(); - } - - void Reset() override - { - BossAI::Reset(); - _summonedMinions = false; - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - - ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{ - Talk(SAY_SUBMERGE); - _summonedMinions = false; - DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true); - DoCastSelf(SPELL_SUBMERGE, false); - - me->m_Events.AddEventAtOffset([this] { - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - DoCastSelf(SPELL_IMPALE_PERIODIC, true); - }, 2s); - - events.Reset(); - events.ScheduleEvent(EVENT_EMERGE, 60s); - events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 2s); - events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s); - events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 15s); - events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 20s); - events.ScheduleEvent(EVENT_SUMMON_DARTER, 30s); - events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 35s); - }, false); - } - - void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override - { - if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) - return; - - if (_summonedMinions && !summons.IsAnyCreatureWithEntryAlive(NPC_ANUBAR_GUARDIAN) && !summons.IsAnyCreatureWithEntryAlive(NPC_ANUBAR_VENOMANCER)) - { - events.Reset(); - events.ScheduleEvent(EVENT_EMERGE, 5s); - } - } - - void JustEngagedWith(Unit* ) override - { - Talk(SAY_AGGRO); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - - events.ScheduleEvent(EVENT_CARRION_BEETELS, 6500ms); - events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s); - events.ScheduleEvent(EVENT_POUND, 15s); - events.ScheduleEvent(EVENT_CLOSE_DOORS, 5s); - } - - void SummonHelpers(float x, float y, float z, uint32 spellId) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - me->SummonCreature(spellInfo->Effects[EFFECT_0].MiscValue, x, y, z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - scheduler.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_CLOSE_DOORS: - _JustEngagedWith(); - break; - case EVENT_CARRION_BEETELS: - me->CastSpell(me, SPELL_CARRION_BEETLES, false); - events.ScheduleEvent(EVENT_CARRION_BEETELS, 25s); - break; - case EVENT_LEECHING_SWARM: - Talk(SAY_LOCUST); - me->CastSpell(me, SPELL_LEECHING_SWARM, false); - events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s); - break; - case EVENT_POUND: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f)) - { - me->CastSpell(me, SPELL_SELF_ROOT, true); - me->DisableRotate(true); - me->SendMovementFlagUpdate(); - events.ScheduleEvent(EVENT_ENABLE_ROTATE, 3300ms); - me->CastSpell(target, SPELL_POUND, false); - } - events.ScheduleEvent(EVENT_POUND, 18s); - break; - case EVENT_ENABLE_ROTATE: - me->RemoveAurasDueToSpell(SPELL_SELF_ROOT); - me->DisableRotate(false); - break; - case EVENT_EMERGE: - me->CastSpell(me, SPELL_EMERGE, true); - me->RemoveAura(SPELL_SUBMERGE); - me->RemoveAura(SPELL_IMPALE_PERIODIC); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_CARRION_BEETELS, 6500ms); - events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s); - events.ScheduleEvent(EVENT_POUND, 15s); - break; - case EVENT_SUMMON_ASSASSINS: - SummonHelpers(509.32f, 247.42f, 239.48f, SPELL_SUMMON_ASSASSIN); - SummonHelpers(589.51f, 240.19f, 236.0f, SPELL_SUMMON_ASSASSIN); - break; - case EVENT_SUMMON_DARTER: - SummonHelpers(509.32f, 247.42f, 239.48f, SPELL_SUMMON_DARTER); - SummonHelpers(589.51f, 240.19f, 236.0f, SPELL_SUMMON_DARTER); - break; - case EVENT_SUMMON_GUARDIAN: - SummonHelpers(550.34f, 316.00f, 234.30f, SPELL_SUMMON_GUARDIAN); - break; - case EVENT_SUMMON_VENOMANCER: - _summonedMinions = true; - SummonHelpers(550.34f, 316.00f, 234.30f, SPELL_SUMMON_VENOMANCER); - break; - } - - if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) - DoMeleeAttackIfReady(); - } - - private: - bool _intro; - bool _summonedMinions; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetAzjolNerubAI(creature); + ++_submergePhase; + ScheduleSubmerged(); } + } + + void ScheduleEmerged() + { + events.Reset(); + events.SetPhase(PHASE_EMERGED); + events.ScheduleEvent(EVENT_CARRION_BEETLES, 6500ms, 0, PHASE_EMERGED); + events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, 0, PHASE_EMERGED); + events.ScheduleEvent(EVENT_POUND, 15s, 0, PHASE_EMERGED); + }; + + void ScheduleSubmerged() + { + events.Reset(); + events.SetPhase(PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_EMERGE, 60s, 0, PHASE_SUBMERGED); + + switch (_submergePhase) + { + case SUBMERGE_75: + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED); + + _remainingLargeSummonsBeforeEmerge = IsHeroic() ? 2 : 1; + + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED); + break; + case SUBMERGE_50: + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, 0, PHASE_SUBMERGED); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, 0, PHASE_SUBMERGED); + + _remainingLargeSummonsBeforeEmerge = IsHeroic() ? 4 : 2; + + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED); + break; + case SUBMERGE_25: + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, 0, PHASE_SUBMERGED); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, 0, PHASE_SUBMERGED); + + _remainingLargeSummonsBeforeEmerge = IsHeroic() ? 4 : 2; + + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_DARTER, 4s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_DARTER, 12s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_DARTER, 26s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_DARTER, 32s, 0, PHASE_SUBMERGED); + + events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED); + events.ScheduleEvent(EVENT_SUMMON_DARTER, 45s, 0, PHASE_SUBMERGED); + break; + default: + break; + } + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + Talk(SAY_AGGRO); + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + + events.SetPhase(PHASE_EMERGED); + events.ScheduleEvent(EVENT_CLOSE_DOORS, 5s); + ScheduleEmerged(); + + // set up world triggers + std::list summoned; + me->SummonCreatureGroup(SUMMON_GROUP_WORLD_TRIGGER_GUARDIAN, &summoned); + if (summoned.empty()) + { + EnterEvadeMode(EVADE_REASON_OTHER); + return; + } + TempSummon* guardianTrigger = summoned.front(); + _guardianTriggerGUID = guardianTrigger->GetGUID(); + + summoned.clear(); + _balconySummons.clear(); + me->SummonCreatureGroup(SUMMON_GROUP_WORLD_TRIGGER_BALCONY, &summoned); + if (summoned.empty()) + { + EnterEvadeMode(EVADE_REASON_OTHER); + return; + } + for (auto const& summon : summoned) + _balconySummons.Summon(summon); + } + + void EnterEvadeMode(EvadeReason why) override + { + me->DisableRotate(false); + BossAI::EnterEvadeMode(why); + summons.DespawnAll(); + } + + void MoveInLineOfSight(Unit* who) override + { + if (!_intro && who->IsPlayer()) + { + _intro = true; + Talk(SAY_INTRO); + } + BossAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* killer) override + { + Talk(SAY_DEATH); + BossAI::JustDied(killer); + } + + void KilledUnit(Unit* /*victim*/) override + { + if (!events.HasTimeUntilEvent(EVENT_KILL_TALK)) + { + Talk(SAY_SLAY); + events.ScheduleEvent(EVENT_KILL_TALK, 6s); + } + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + return; + + switch (summon->GetEntry()) + { + case NPC_ANUBAR_GUARDIAN: + case NPC_ANUBAR_VENOMANCER: + { + --_remainingLargeSummonsBeforeEmerge; + if (_remainingLargeSummonsBeforeEmerge == 0) + { + events.Reset(); + events.ScheduleEvent(EVENT_EMERGE, 5s); + } + break; + } + default: + break; + } + } + + void SummonedCreatureEvade(Creature* /*summon*/) override + { + EnterEvadeMode(EVADE_REASON_OTHER); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + scheduler.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_CLOSE_DOORS: + BossAI::_JustEngagedWith(); + break; + case EVENT_CARRION_BEETLES: + DoCastSelf(SPELL_CARRION_BEETLES); + events.ScheduleEvent(EVENT_CARRION_BEETLES, 25s, 0, PHASE_EMERGED); + break; + case EVENT_LEECHING_SWARM: + Talk(SAY_LOCUST); + DoCastSelf(SPELL_LEECHING_SWARM); + events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, 0, PHASE_EMERGED); + break; + case EVENT_POUND: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f)) + { + DoCastSelf(SPELL_SELF_ROOT, true); + me->DisableRotate(true); + me->SendMovementFlagUpdate(); + events.ScheduleEvent(EVENT_ENABLE_ROTATE, 3300ms); + DoCast(target, SPELL_POUND); + } + events.ScheduleEvent(EVENT_POUND, 18s); + break; + case EVENT_ENABLE_ROTATE: + me->RemoveAurasDueToSpell(SPELL_SELF_ROOT); + me->DisableRotate(false); + break; + case EVENT_EMERGE: + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + me->RemoveAurasDueToSpell(SPELL_IMPALE_PERIODIC); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + DoCastSelf(SPELL_EMERGE); + ScheduleEmerged(); + break; + case EVENT_SUMMON_GUARDIAN: + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _guardianTriggerGUID)) + trigger->CastSpell(trigger, SPELL_SUMMON_GUARDIAN, true, nullptr, nullptr, me->GetGUID()); + break; + case EVENT_SUMMON_VENOMANCER: + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _guardianTriggerGUID)) + trigger->CastSpell(trigger, SPELL_SUMMON_VENOMANCER, true, nullptr, nullptr, me->GetGUID()); + break; + case EVENT_SUMMON_DARTER: + if (Creature* trigger = ObjectAccessor::GetCreature(*me, Acore::Containers::SelectRandomContainerElement(_balconySummons))) + trigger->CastSpell(trigger, SPELL_SUMMON_DARTER, true, nullptr, nullptr, me->GetGUID()); + break; + case EVENT_SUMMON_ASSASSINS: + if (Creature* trigger = ObjectAccessor::GetCreature(*me, Acore::Containers::SelectRandomContainerElement(_balconySummons))) + trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true, nullptr, nullptr, me->GetGUID()); + if (Creature* trigger = ObjectAccessor::GetCreature(*me, Acore::Containers::SelectRandomContainerElement(_balconySummons))) + trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true, nullptr, nullptr, me->GetGUID()); + break; + default: + break; + } + + if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE)) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override + { + if (me->HasAura(SPELL_SUBMERGE) && damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + + BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask); + } + + private: + bool _intro; + uint8 _submergePhase; + uint8 _remainingLargeSummonsBeforeEmerge; + ObjectGuid _guardianTriggerGUID; + SummonList _balconySummons; }; -class spell_azjol_nerub_carrion_beetels : public AuraScript +class spell_azjol_nerub_carrion_beetles : public AuraScript { - PrepareAuraScript(spell_azjol_nerub_carrion_beetels) + PrepareAuraScript(spell_azjol_nerub_carrion_beetles) - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) { // Xinef: 2 each second GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_SUMMON_CARRION_BEETLES, true); @@ -280,7 +404,7 @@ class spell_azjol_nerub_carrion_beetels : public AuraScript void Register() override { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_azjol_nerub_carrion_beetels::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_azjol_nerub_carrion_beetles::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; @@ -288,7 +412,7 @@ class spell_azjol_nerub_pound : public SpellScript { PrepareSpellScript(spell_azjol_nerub_pound); - void HandleApplyAura(SpellEffIndex /*effIndex*/) + void HandleApplyAura(SpellEffIndex /*effIndex*/) { if (Unit* unitTarget = GetHitUnit()) GetCaster()->CastSpell(unitTarget, SPELL_POUND_DAMAGE, true); @@ -320,8 +444,8 @@ class spell_azjol_nerub_impale_summon : public SpellScript void AddSC_boss_anub_arak() { - new boss_anub_arak(); - RegisterSpellScript(spell_azjol_nerub_carrion_beetels); + RegisterAzjolNerubCreatureAI(boss_anub_arak); + RegisterSpellScript(spell_azjol_nerub_carrion_beetles); RegisterSpellScript(spell_azjol_nerub_pound); RegisterSpellScript(spell_azjol_nerub_impale_summon); } diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp index 9d6616db9..ef6372c78 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp @@ -25,17 +25,18 @@ DoorData const doorData[] = { - { GO_KRIKTHIR_DOORS, DATA_KRIKTHIR, DOOR_TYPE_PASSAGE }, - { GO_ANUBARAK_DOORS1, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM }, - { GO_ANUBARAK_DOORS2, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM }, - { GO_ANUBARAK_DOORS3, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM }, - { 0, 0, DOOR_TYPE_ROOM } + { GO_KRIKTHIR_DOORS, DATA_KRIKTHIR, DOOR_TYPE_PASSAGE }, + { GO_ANUBARAK_DOORS1, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { GO_ANUBARAK_DOORS2, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { GO_ANUBARAK_DOORS3, DATA_ANUBARAK, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } }; ObjectData const creatureData[] = { { NPC_KRIKTHIR_THE_GATEWATCHER, DATA_KRIKTHIR }, { NPC_HADRONOX, DATA_HADRONOX }, + { NPC_ANUBARAK, DATA_ANUBARAK }, { 0, 0 } }; @@ -53,7 +54,7 @@ BossBoundaryData const boundaries = { { DATA_KRIKTHIR, new RectangleBoundary(400.0f, 580.0f, 623.5f, 810.0f) }, { DATA_HADRONOX, new ZRangeBoundary(666.0f, 776.0f) }, - { DATA_ANUBARAK_EVENT, new CircleBoundary(Position(550.6178f, 253.5917f), 26.0f) } + { DATA_ANUBARAK, new CircleBoundary(Position(550.6178f, 253.5917f), 32.0f) } }; class instance_azjol_nerub : public InstanceMapScript