diff options
4 files changed, 523 insertions, 506 deletions
diff --git a/sql/updates/world/2011_06_28_01_world_spelldifficulty_dbc.sql b/sql/updates/world/2011_06_28_01_world_spelldifficulty_dbc.sql new file mode 100644 index 00000000000..9f98c1b77e5 --- /dev/null +++ b/sql/updates/world/2011_06_28_01_world_spelldifficulty_dbc.sql @@ -0,0 +1,17 @@ +DELETE FROM `spelldifficulty_dbc` WHERE `id` BETWEEN 3251 AND 3261; +INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`,`spellid2`,`spellid3`) +VALUES +-- Steelbreaker +(3251,61980,63498,0,0), +(3252,61903,63493,0,0), +(3253,44008,63494,0,0), +(3254,64637,61888,0,0), +-- Runemaster Molgeim +(3255,62274,63489,0,0), +(3256,62277,63967,0,0), +(3257,62052,63492,0,0), +-- Stormcaller Brundir +(3258,61879,63479,0,0), +(3259,61869,63481,0,0), +(3260,61915,63483,0,0), +(3261,61887,63486,0,0); diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp index 67ea6bd23ba..5c979fa8ebd 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp @@ -28,73 +28,76 @@ EndScriptData */ #include "SpellAuraEffects.h" #include "ulduar.h" -enum eSpells +enum AssemblySpells { - // Any boss - SPELL_SUPERCHARGE = 61920, - SPELL_BERSERK = 47008, // Hard enrage, don't know the correct ID. + // General + SPELL_SUPERCHARGE = 61920, + SPELL_BERSERK = 47008, // Hard enrage, don't know the correct ID. // Steelbreaker - SPELL_HIGH_VOLTAGE = 61890, - SPELL_HIGH_VOLTAGE_H = 63498, - SPELL_FUSION_PUNCH = 61903, - SPELL_FUSION_PUNCH_H = 63493, - SPELL_STATIC_DISRUPTION = 44008, - SPELL_STATIC_DISRUPTION_H = 63494, - SPELL_OVERWHELMING_POWER_H = 61888, - SPELL_OVERWHELMING_POWER = 64637, - SPELL_ELECTRICAL_CHARGE = 61902, + SPELL_HIGH_VOLTAGE = 61890, + SPELL_FUSION_PUNCH = 61903, + SPELL_STATIC_DISRUPTION = 44008, + SPELL_OVERWHELMING_POWER = 64637, + SPELL_ELECTRICAL_CHARGE = 61902, // Runemaster Molgeim - SPELL_SHIELD_OF_RUNES = 62274, - SPELL_SHIELD_OF_RUNES_BUFF = 62277, - SPELL_SHIELD_OF_RUNES_H = 63489, - SPELL_SHIELD_OF_RUNES_H_BUFF = 63967, - SPELL_SUMMON_RUNE_OF_POWER = 63513, - SPELL_RUNE_OF_POWER = 61974, - SPELL_RUNE_OF_DEATH = 62269, - SPELL_RUNE_OF_SUMMONING = 62273, // This is the spell that summons the rune - SPELL_RUNE_OF_SUMMONING_VIS = 62019, // Visual - SPELL_RUNE_OF_SUMMONING_SUMMON = 62020, // Spell that summons - SPELL_LIGHTNING_ELEMENTAL_PASSIVE = 62052, - SPELL_LIGHTNING_ELEMENTAL_PASSIVE_H = 63492, + SPELL_SHIELD_OF_RUNES = 62274, + SPELL_SHIELD_OF_RUNES_BUFF = 62277, + SPELL_SUMMON_RUNE_OF_POWER = 63513, + SPELL_RUNE_OF_POWER = 61974, + SPELL_RUNE_OF_DEATH = 62269, + SPELL_RUNE_OF_SUMMONING = 62273, // This is the spell that summons the rune + SPELL_RUNE_OF_SUMMONING_VIS = 62019, // Visual + SPELL_RUNE_OF_SUMMONING_SUMMON = 62020, // Spell that summons + SPELL_LIGHTNING_ELEMENTAL_PASSIVE = 62052, // Stormcaller Brundir - SPELL_CHAIN_LIGHTNING_N = 61879, - SPELL_CHAIN_LIGHTNING_H = 63479, - SPELL_OVERLOAD = 61869, - SPELL_OVERLOAD_H = 63481, - SPELL_LIGHTNING_WHIRL = 61915, - SPELL_LIGHTNING_WHIRL_H = 63483, - SPELL_LIGHTNING_TENDRILS = 61887, - SPELL_LIGHTNING_TENDRILS_H = 63486, - SPELL_STORMSHIELD = 64187, + SPELL_CHAIN_LIGHTNING = 61879, + SPELL_OVERLOAD = 61869, + SPELL_LIGHTNING_WHIRL = 61915, + SPELL_LIGHTNING_TENDRILS = 61887, + SPELL_LIGHTNING_TENDRILS_SELF_VISUAL = 61883, + SPELL_STORMSHIELD = 64187, }; -enum Events +enum AssemblyEvents { - EVENT_NONE, - EVENT_UPDATEPHASE, - EVENT_ENRAGE, + // General + EVENT_BERSERK = 1, + // Steelbreaker - EVENT_FUSION_PUNCH, - EVENT_STATIC_DISRUPTION, - EVENT_OVERWHELMING_POWER, + EVENT_FUSION_PUNCH = 2, + EVENT_STATIC_DISRUPTION = 3, + EVENT_OVERWHELMING_POWER = 4, + // Molgeim - EVENT_RUNE_OF_POWER, - EVENT_SHIELD_OF_RUNES, - EVENT_RUNE_OF_DEATH, - EVENT_RUNE_OF_SUMMONING, - EVENT_LIGHTNING_BLAST, + EVENT_RUNE_OF_POWER = 5, + EVENT_SHIELD_OF_RUNES = 6, + EVENT_RUNE_OF_DEATH = 7, + EVENT_RUNE_OF_SUMMONING = 8, + EVENT_LIGHTNING_BLAST = 9, + // Brundir - EVENT_CHAIN_LIGHTNING, - EVENT_OVERLOAD, - EVENT_LIGHTNING_WHIRL, - EVENT_LIGHTNING_TENDRILS, - EVENT_STORMSHIELD, + EVENT_CHAIN_LIGHTNING = 10, + EVENT_OVERLOAD = 11, + EVENT_LIGHTNING_WHIRL = 12, + EVENT_LIGHTNING_TENDRILS = 13, + EVENT_FLIGHT = 14, + EVENT_ENDFLIGHT = 15, + EVENT_GROUND = 16, + EVENT_LAND = 17, + EVENT_MOVE_POSITION = 18, }; -enum Yells +enum AssemblyActions +{ + ACTION_STEELBREAKER = 0, + ACTION_MOLGEIM = 1, + ACTION_BRUNDIR = 2, +}; + +enum AssemblyYells { SAY_STEELBREAKER_AGGRO = -1603020, SAY_STEELBREAKER_SLAY_1 = -1603021, @@ -123,18 +126,27 @@ enum Yells SAY_BRUNDIR_BERSERK = -1603047, }; -bool IsEncounterComplete(InstanceScript* pInstance, Creature* me) +enum AssemblyNPCs +{ + NPC_WORLD_TRIGGER = 22515, +}; + +#define EMOTE_OVERLOAD "Stormcaller Brundir begins to Overload!" // Move it to DB +#define FLOOR_Z 427.28f +#define FINAL_FLIGHT_Z 435.0f + +bool IsEncounterComplete(InstanceScript* instance, Creature* me) { - if (!pInstance || !me) + if (!instance || !me) return false; for (uint8 i = 0; i < 3; ++i) { - uint64 guid = pInstance->GetData64(BOSS_STEELBREAKER+i); + uint64 guid = instance->GetData64(BOSS_STEELBREAKER + i); if (!guid) return false; - if (Creature *boss = Unit::GetCreature(*me, guid)) + if (Creature* boss = ObjectAccessor::GetCreature(*me, guid)) { if (boss->isAlive()) return false; @@ -142,18 +154,19 @@ bool IsEncounterComplete(InstanceScript* pInstance, Creature* me) else return false; } + return true; } -void RespawnEncounter(InstanceScript* pInstance, Creature* me) +void RespawnEncounter(InstanceScript* instance, Creature* me) { for (uint8 i = 0; i < 3; ++i) { - uint64 guid = pInstance->GetData64(BOSS_STEELBREAKER+i); + uint64 guid = instance->GetData64(BOSS_STEELBREAKER + i); if (!guid) continue; - if (Creature *boss = Unit::GetCreature(*me, guid)) + if (Creature* boss = ObjectAccessor::GetCreature(*me, guid)) { if (!boss->isAlive()) { @@ -164,576 +177,564 @@ void RespawnEncounter(InstanceScript* pInstance, Creature* me) } } -void StartEncounter(InstanceScript* pInstance, Creature* me, Unit* /*target*/) +void StartEncounter(InstanceScript* instance, Creature* me, Unit* /*target*/) { - if (pInstance->GetBossState(BOSS_ASSEMBLY_OF_IRON) == IN_PROGRESS) - return; // Prevent recursive calls + if (instance->GetBossState(BOSS_ASSEMBLY_OF_IRON) == IN_PROGRESS) + return; // Prevent recursive calls - pInstance->SetBossState(BOSS_ASSEMBLY_OF_IRON, IN_PROGRESS); + instance->SetBossState(BOSS_ASSEMBLY_OF_IRON, IN_PROGRESS); for (uint8 i = 0; i < 3; ++i) { - uint64 guid = pInstance->GetData64(BOSS_STEELBREAKER+i); + uint64 guid = instance->GetData64(BOSS_STEELBREAKER + i); if (!guid) continue; - if (Creature *boss = Unit::GetCreature(*me, guid)) - boss->SetInCombatWithZone(); + if (Creature* boss = ObjectAccessor::GetCreature(*me, guid)) + boss->SetInCombatWithZone(); } } -bool UpdateSupercharge(Creature* target) -{ - if (Aura* supercharge = target->GetAura(SPELL_SUPERCHARGE)) - { - supercharge->ModStackAmount(1); - if (UnitAI* AI = target->GetAI()) - { - AI->DoAction(EVENT_UPDATEPHASE); - return true; - } - } - - return false; -} - class boss_steelbreaker : public CreatureScript { -public: - boss_steelbreaker() : CreatureScript("boss_steelbreaker") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return GetUlduarAI<boss_steelbreakerAI>(pCreature); - } - - struct boss_steelbreakerAI : public ScriptedAI - { - boss_steelbreakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceScript(); - } + public: + boss_steelbreaker() : CreatureScript("boss_steelbreaker") { } - void Reset() + struct boss_steelbreakerAI : public BossAI { - events.Reset(); - phase = 0; - me->RemoveAllAuras(); - if (pInstance) + boss_steelbreakerAI(Creature* creature) : BossAI(creature, BOSS_ASSEMBLY_OF_IRON) { - pInstance->SetBossState(BOSS_ASSEMBLY_OF_IRON, NOT_STARTED); - RespawnEncounter(pInstance, me); + instance = me->GetInstanceScript(); } - } - EventMap events; - InstanceScript* pInstance; - uint32 phase; + InstanceScript* instance; + uint32 phase; - void EnterCombat(Unit* who) - { - StartEncounter(pInstance, me, who); - DoScriptText(SAY_STEELBREAKER_AGGRO, me); - DoZoneInCombat(); - DoCast(me, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H)); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - DoAction(EVENT_UPDATEPHASE); - } - - void DoAction(const int32 action) - { - switch (action) + void Reset() { - case EVENT_UPDATEPHASE: - events.SetPhase(++phase); - events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); - if (phase >= 2) - events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000); - break; + _Reset(); + phase = 0; + me->ResetLootMode(); + me->RemoveAllAuras(); + RespawnEncounter(instance, me); } - } - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) + void EnterCombat(Unit* who) { - bool has_supercharge = false; + StartEncounter(instance, me, who); + DoScriptText(SAY_STEELBREAKER_AGGRO, me); + DoZoneInCombat(); + DoCast(me, SPELL_HIGH_VOLTAGE); + events.SetPhase(++phase); + events.ScheduleEvent(EVENT_BERSERK, 900000); + events.ScheduleEvent(EVENT_FUSION_PUNCH, 15000); + } - if (Creature* Brundir = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(BOSS_BRUNDIR) : 0)) + void DoAction(int32 const action) + { + switch (action) { - if (Brundir->isAlive()) - { - Brundir->SetFullHealth(); - has_supercharge = UpdateSupercharge(Brundir); - } + case ACTION_STEELBREAKER: + me->SetHealth(me->GetMaxHealth()); + me->AddAura(SPELL_SUPERCHARGE, me); + events.SetPhase(++phase); + events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); + if (phase >= 2) + events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_OVERWHELMING_POWER, urand(2000, 5000)); + break; } + } - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(BOSS_MOLGEIM) : 0)) - { - if (Molgeim->isAlive()) - { - Molgeim->SetFullHealth(); - has_supercharge = UpdateSupercharge(Molgeim); - } - } + void JustDied(Unit* /*who*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1, SAY_STEELBREAKER_DEATH_2), me); + if (IsEncounterComplete(instance, me)) + instance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); + else + me->SetLootRecipient(NULL); - if (!has_supercharge) - DoCast(SPELL_SUPERCHARGE); - } - } + if (Creature* Brundir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_BRUNDIR))) + if (Brundir->isAlive()) + Brundir->AI()->DoAction(ACTION_BRUNDIR); - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1, SAY_STEELBREAKER_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); - } + if (Creature* Molgeim = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MOLGEIM))) + if (Molgeim->isAlive()) + Molgeim->AI()->DoAction(ACTION_MOLGEIM); + } - void KilledUnit(Unit* /*who*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1, SAY_STEELBREAKER_SLAY_2), me); + void KilledUnit(Unit* /*who*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1, SAY_STEELBREAKER_SLAY_2), me); - if (phase == 3) - DoCast(me, SPELL_ELECTRICAL_CHARGE); - } + if (phase == 3) + DoCast(me, SPELL_ELECTRICAL_CHARGE); + } - void SpellHit(Unit* /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - DoAction(EVENT_UPDATEPHASE); - } + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + events.Update(diff); - events.Update(diff); + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_ENRAGE: - DoScriptText(SAY_STEELBREAKER_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_FUSION_PUNCH: - DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH, SPELL_FUSION_PUNCH_H)); - events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); - break; - case EVENT_STATIC_DISRUPTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION, SPELL_STATIC_DISRUPTION_H)); - events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); - break; - case EVENT_OVERWHELMING_POWER: - DoScriptText(SAY_STEELBREAKER_POWER, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H)); - events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); - break; + switch (eventId) + { + case EVENT_BERSERK: + DoScriptText(SAY_STEELBREAKER_BERSERK, me); + DoCast(SPELL_BERSERK); + events.CancelEvent(EVENT_BERSERK); + break; + case EVENT_FUSION_PUNCH: + if (me->IsWithinMeleeRange(me->getVictim())) + DoCastVictim(SPELL_FUSION_PUNCH); + events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); + break; + case EVENT_STATIC_DISRUPTION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_STATIC_DISRUPTION); + events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); + break; + case EVENT_OVERWHELMING_POWER: + DoScriptText(SAY_STEELBREAKER_POWER, me); + DoCastVictim(SPELL_OVERWHELMING_POWER); + events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); + break; + } } + + DoMeleeAttackIfReady(); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_steelbreakerAI>(creature); } - }; - }; class boss_runemaster_molgeim : public CreatureScript { -public: - boss_runemaster_molgeim() : CreatureScript("boss_runemaster_molgeim") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return GetUlduarAI<boss_runemaster_molgeimAI>(pCreature); - } - - struct boss_runemaster_molgeimAI : public ScriptedAI - { - boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceScript(); - } + public: + boss_runemaster_molgeim() : CreatureScript("boss_runemaster_molgeim") { } - void Reset() + struct boss_runemaster_molgeimAI : public BossAI { - if (pInstance) + boss_runemaster_molgeimAI(Creature* creature) : BossAI(creature, BOSS_ASSEMBLY_OF_IRON) { - pInstance->SetData(BOSS_ASSEMBLY_OF_IRON, NOT_STARTED); - RespawnEncounter(pInstance, me); + instance = me->GetInstanceScript(); } - events.Reset(); - me->RemoveAllAuras(); - phase = 0; - } + InstanceScript* instance; + uint32 phase; - InstanceScript* pInstance; - EventMap events; - uint32 phase; - - void EnterCombat(Unit* who) - { - StartEncounter(pInstance, me, who); - DoScriptText(SAY_MOLGEIM_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - DoAction(EVENT_UPDATEPHASE); - } - - void DoAction(const int32 action) - { - switch (action) + void Reset() { - case EVENT_UPDATEPHASE: - events.SetPhase(++phase); - events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); - events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000); - if (phase >= 2) - events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000, 30000)); - break; + _Reset(); + phase = 0; + me->ResetLootMode(); + me->RemoveAllAuras(); + RespawnEncounter(instance, me); } - } - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) + void EnterCombat(Unit* who) { - bool has_supercharge = false; + StartEncounter(instance, me, who); + DoScriptText(SAY_MOLGEIM_AGGRO, me); + DoZoneInCombat(); + events.SetPhase(++phase); + events.ScheduleEvent(EVENT_BERSERK, 900000); + events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, 30000); + events.ScheduleEvent(EVENT_RUNE_OF_POWER, 20000); + } - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(BOSS_STEELBREAKER) : 0)) + void DoAction(int32 const action) + { + switch (action) { - if (Steelbreaker->isAlive()) - { - Steelbreaker->SetFullHealth(); - has_supercharge = UpdateSupercharge(Steelbreaker); - } + case ACTION_MOLGEIM: + me->SetHealth(me->GetMaxHealth()); + me->AddAura(SPELL_SUPERCHARGE, me); + events.SetPhase(++phase); + events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); + events.RescheduleEvent(EVENT_RUNE_OF_POWER, 25000); + if (phase >= 2) + events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000, 30000)); + break; } + } - if (Creature* Brundir = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(BOSS_BRUNDIR) : 0)) - { + void JustDied(Unit* /*who*/) + { + DoScriptText(RAND(SAY_MOLGEIM_DEATH_1, SAY_MOLGEIM_DEATH_2), me); + if (IsEncounterComplete(instance, me)) + instance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); + else + me->SetLootRecipient(NULL); + + if (Creature* Brundir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_BRUNDIR))) if (Brundir->isAlive()) - { - Brundir->SetFullHealth(); - has_supercharge = UpdateSupercharge(Brundir); - } - } + Brundir->AI()->DoAction(ACTION_BRUNDIR); - if (!has_supercharge) - DoCast(me, SPELL_SUPERCHARGE); + if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_STEELBREAKER))) + if (Steelbreaker->isAlive()) + Steelbreaker->AI()->DoAction(ACTION_STEELBREAKER); } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_MOLGEIM_DEATH_1, SAY_MOLGEIM_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); - } - void KilledUnit(Unit* /*who*/) - { - DoScriptText(RAND(SAY_MOLGEIM_SLAY_1, SAY_MOLGEIM_SLAY_2), me); - } + void KilledUnit(Unit* /*who*/) + { + DoScriptText(RAND(SAY_MOLGEIM_SLAY_1, SAY_MOLGEIM_SLAY_2), me); + } - void SpellHit(Unit* /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - DoAction(EVENT_UPDATEPHASE); - } + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + events.Update(diff); - events.Update(diff); + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_ENRAGE: - DoScriptText(SAY_MOLGEIM_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly + switch (eventId) { - Unit *pTarget = DoSelectLowestHpFriendly(60); - if (!pTarget || !pTarget->isAlive()) - pTarget = me; - DoCast(pTarget, SPELL_SUMMON_RUNE_OF_POWER); - events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); - break; + case EVENT_BERSERK: + DoScriptText(SAY_MOLGEIM_BERSERK, me); + DoCast(SPELL_BERSERK); + events.CancelEvent(EVENT_BERSERK); + break; + case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly + { + Unit* target = NULL; + switch (urand(0, 2)) + { + case 0: + target = me; + break; + case 1: + if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_STEELBREAKER))) + if (Steelbreaker->isAlive()) + target = Steelbreaker; + break; + case 2: + if (Creature* Brundir = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_STEELBREAKER))) + if (Brundir->isAlive()) + target = Brundir; + break; + } + DoCast(target, SPELL_SUMMON_RUNE_OF_POWER); + events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); + break; + } + case EVENT_SHIELD_OF_RUNES: + DoCast(me, SPELL_SHIELD_OF_RUNES); + events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000, 34000)); + break; + case EVENT_RUNE_OF_DEATH: + DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_RUNE_OF_DEATH); + events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000, 40000)); + break; + case EVENT_RUNE_OF_SUMMONING: + DoScriptText(SAY_MOLGEIM_SUMMON, me); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_RUNE_OF_SUMMONING); + events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(30000, 45000)); + break; } - case EVENT_SHIELD_OF_RUNES: - DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); - events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000, 34000)); - break; - case EVENT_RUNE_OF_DEATH: - DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_DEATH); - events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000, 40000)); - break; - case EVENT_RUNE_OF_SUMMONING: - DoScriptText(SAY_MOLGEIM_SUMMON, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); - events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000, 30000)); - break; } + + DoMeleeAttackIfReady(); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_runemaster_molgeimAI>(creature); } - }; }; class mob_rune_of_power : public CreatureScript { -public: - mob_rune_of_power() : CreatureScript("mob_rune_of_power") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_rune_of_powerAI(pCreature); - } + public: + mob_rune_of_power() : CreatureScript("mob_rune_of_power") { } - struct mob_rune_of_powerAI : public ScriptedAI - { - mob_rune_of_powerAI(Creature* c) : ScriptedAI(c) + struct mob_rune_of_powerAI : public ScriptedAI { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setFaction(16); // Same faction as bosses - DoCast(SPELL_RUNE_OF_POWER); + mob_rune_of_powerAI(Creature* creature) : ScriptedAI(creature) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setFaction(16); // Same faction as bosses + DoCast(SPELL_RUNE_OF_POWER); + + me->DespawnOrUnsummon(60000); + } + }; - me->DespawnOrUnsummon(60000); + CreatureAI* GetAI(Creature* creature) const + { + return new mob_rune_of_powerAI(creature); } - }; }; class mob_lightning_elemental : public CreatureScript { -public: - mob_lightning_elemental() : CreatureScript("mob_lightning_elemental") { } + public: + mob_lightning_elemental() : CreatureScript("mob_lightning_elemental") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_lightning_elementalAI (pCreature); - } + struct mob_lightning_elementalAI : public ScriptedAI + { + mob_lightning_elementalAI(Creature* creature) : ScriptedAI(creature) + { + me->SetInCombatWithZone(); + me->AddAura(SPELL_LIGHTNING_ELEMENTAL_PASSIVE, me); + } - struct mob_lightning_elementalAI : public ScriptedAI - { - mob_lightning_elementalAI(Creature *c) : ScriptedAI(c) + // Nothing to do here, just let the creature chase players and procflags == 2 on the applied aura will trigger explosion + }; + + CreatureAI* GetAI(Creature* creature) const { - me->SetInCombatWithZone(); - me->AddAura( RAID_MODE(SPELL_LIGHTNING_ELEMENTAL_PASSIVE, SPELL_LIGHTNING_ELEMENTAL_PASSIVE_H), me); + return new mob_lightning_elementalAI(creature); } - - // Nothing to do here, just let the creature chase players and procflags == 2 on the applied aura will trigger explosion - }; }; class mob_rune_of_summoning : public CreatureScript { -public: - mob_rune_of_summoning() : CreatureScript("mob_rune_of_summoning") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_rune_of_summoningAI (pCreature); - } + public: + mob_rune_of_summoning() : CreatureScript("mob_rune_of_summoning") { } - struct mob_rune_of_summoningAI : public ScriptedAI - { - mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c) + struct mob_rune_of_summoningAI : public ScriptedAI { - me->AddAura(SPELL_RUNE_OF_SUMMONING_VIS, me); - summonCount = 0; - summonTimer = 2000; - } + mob_rune_of_summoningAI(Creature* creature) : ScriptedAI(creature) + { + me->AddAura(SPELL_RUNE_OF_SUMMONING_VIS, me); + summonCount = 0; + summonTimer = 2000; + } - uint32 summonCount; - uint32 summonTimer; + uint32 summonCount; + uint32 summonTimer; - void UpdateAI(const uint32 diff) - { - if (summonTimer <= diff) - SummonLightningElemental(); - else - summonTimer -= diff; - } + void UpdateAI(uint32 const diff) + { + if (summonTimer <= diff) + SummonLightningElemental(); + else + summonTimer -= diff; + } + + void SummonLightningElemental() + { + me->CastSpell(me, SPELL_RUNE_OF_SUMMONING_SUMMON, false); + if (++summonCount == 10) // TODO: Find out if this amount is right + me->DespawnOrUnsummon(); + else + summonTimer = 2000; // TODO: Find out of timer is right + } + }; - void SummonLightningElemental() + CreatureAI* GetAI(Creature* creature) const { - me->CastSpell(me, SPELL_RUNE_OF_SUMMONING_SUMMON, false); - if (++summonCount == 10) // TODO: Find out if this amount is right - me->DespawnOrUnsummon(); - else - summonTimer = 2000; // TODO: Find out of timer is right + return new mob_rune_of_summoningAI(creature); } - }; }; class boss_stormcaller_brundir : public CreatureScript { -public: - boss_stormcaller_brundir() : CreatureScript("boss_stormcaller_brundir") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return GetUlduarAI<boss_stormcaller_brundirAI>(pCreature); - } - - struct boss_stormcaller_brundirAI : public ScriptedAI - { - boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceScript(); - } + public: + boss_stormcaller_brundir() : CreatureScript("boss_stormcaller_brundir") { } - void Reset() + struct boss_stormcaller_brundirAI : public BossAI { - if (pInstance) + boss_stormcaller_brundirAI(Creature* creature) : BossAI(creature, BOSS_ASSEMBLY_OF_IRON) { - pInstance->SetData(BOSS_ASSEMBLY_OF_IRON, NOT_STARTED); - RespawnEncounter(pInstance, me); + instance = me->GetInstanceScript(); } - me->RemoveAllAuras(); - events.Reset(); - phase = 0; - } - - EventMap events; - InstanceScript* pInstance; - uint32 phase; - - void EnterCombat(Unit* who) - { - StartEncounter(pInstance, me, who); - DoScriptText(SAY_BRUNDIR_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - DoAction(EVENT_UPDATEPHASE); - } + InstanceScript* instance; + uint32 phase; - void DoAction(const int32 action) - { - switch (action) + void Reset() { - case EVENT_UPDATEPHASE: - events.SetPhase(++phase); - events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000, 17000)); - events.RescheduleEvent(EVENT_OVERLOAD, urand(60000, 125000)); - if (phase >= 2) - events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000, 40000)); - if (phase >= 3) - { - DoCast(me, SPELL_STORMSHIELD); - events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(40000, 80000)); - } - break; - + _Reset(); + phase = 0; + me->ResetLootMode(); + me->RemoveAllAuras(); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + RespawnEncounter(instance, me); } - } - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) + void EnterCombat(Unit* who) { - bool has_supercharge = false; + StartEncounter(instance, me, who); + DoScriptText(SAY_BRUNDIR_AGGRO, me); + DoZoneInCombat(); + events.SetPhase(++phase); + events.ScheduleEvent(EVENT_MOVE_POSITION, 1000); + events.ScheduleEvent(EVENT_BERSERK, 900000); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 4000); + events.ScheduleEvent(EVENT_OVERLOAD, urand(60000, 120000)); + } - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(BOSS_STEELBREAKER) : 0)) + void DoAction(int32 const action) + { + switch (action) { - if (Steelbreaker->isAlive()) - { - Steelbreaker->SetFullHealth(); - has_supercharge = UpdateSupercharge(Steelbreaker); - } - } + case ACTION_BRUNDIR: + me->SetHealth(me->GetMaxHealth()); + me->AddAura(SPELL_SUPERCHARGE, me); + events.SetPhase(++phase); + events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(7000, 12000)); + events.RescheduleEvent(EVENT_OVERLOAD, urand(40000, 50000)); + if (phase >= 2) + events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(15000, 250000)); + if (phase >= 3) + { + DoCast(me, SPELL_STORMSHIELD); + events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(50000, 60000)); + } + break; - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(BOSS_MOLGEIM) : 0)) - { - if (Molgeim->isAlive()) - { - Molgeim->SetFullHealth(); - has_supercharge = UpdateSupercharge(Molgeim); - } } - - if (!has_supercharge) - DoCast(SPELL_SUPERCHARGE); } - } - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_BRUNDIR_DEATH_1, SAY_BRUNDIR_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); - } + void JustDied(Unit* /*who*/) + { + DoScriptText(RAND(SAY_BRUNDIR_DEATH_1, SAY_BRUNDIR_DEATH_2), me); + if (IsEncounterComplete(instance, me)) + instance->SetData(BOSS_ASSEMBLY_OF_IRON, DONE); + else + me->SetLootRecipient(NULL); + + if (Creature* Molgeim = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MOLGEIM))) + if (Molgeim->isAlive()) + Molgeim->AI()->DoAction(ACTION_MOLGEIM); + + if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_STEELBREAKER))) + if (Steelbreaker->isAlive()) + Steelbreaker->AI()->DoAction(ACTION_STEELBREAKER); + + // Prevent to have Brundir somewhere in the air when he die in Air phase + if (me->GetPositionZ() > FLOOR_Z/* + 5.0f*/) + me->GetMotionMaster()->MoveFall(FLOOR_Z); + } - void KilledUnit(Unit* /*who*/) - { - DoScriptText(RAND(SAY_BRUNDIR_SLAY_1, SAY_BRUNDIR_SLAY_2), me); - } + void KilledUnit(Unit* /*who*/) + { + DoScriptText(RAND(SAY_BRUNDIR_SLAY_1, SAY_BRUNDIR_SLAY_2), me); + } - void SpellHit(Unit* /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - DoAction(EVENT_UPDATEPHASE); - } + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; + events.Update(diff); - events.Update(diff); + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_ENRAGE: - DoScriptText(SAY_BRUNDIR_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_CHAIN_LIGHTNING: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H)); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000, 17000)); - break; - case EVENT_OVERLOAD: - DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H)); - events.ScheduleEvent(EVENT_OVERLOAD, urand(60000, 125000)); - break; - case EVENT_LIGHTNING_WHIRL: - DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H)); - events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000, 40000)); - break; - case EVENT_LIGHTNING_TENDRILS: - DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H)); - events.DelayEvents(15000, 5000); - DoResetThreat(); - break; + switch(eventId) + { + case EVENT_BERSERK: + DoScriptText(SAY_BRUNDIR_BERSERK, me); + DoCast(SPELL_BERSERK); + events.CancelEvent(EVENT_BERSERK); + break; + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(7000, 10000)); + break; + case EVENT_OVERLOAD: + me->MonsterTextEmote(EMOTE_OVERLOAD, 0, true); + DoScriptText(SAY_BRUNDIR_SPECIAL, me); + DoCast(SPELL_OVERLOAD); + events.ScheduleEvent(EVENT_OVERLOAD, urand(60000, 120000)); + break; + case EVENT_LIGHTNING_WHIRL: + DoCast(SPELL_LIGHTNING_WHIRL); + events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(15000, 20000)); + break; + case EVENT_LIGHTNING_TENDRILS: + DoScriptText(SAY_BRUNDIR_FLIGHT, me); + DoCast(SPELL_LIGHTNING_TENDRILS); + me->AttackStop(); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + DoCast(SPELL_LIGHTNING_TENDRILS_SELF_VISUAL); + me->GetMotionMaster()->Initialize(); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), FINAL_FLIGHT_Z); + events.DelayEvents(35000); + events.ScheduleEvent(EVENT_FLIGHT, 2500); + events.ScheduleEvent(EVENT_ENDFLIGHT, 32500); + events.ScheduleEvent(EVENT_LIGHTNING_TENDRILS, 90000); + break; + case EVENT_FLIGHT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + me->GetMotionMaster()->MovePoint(0, target->GetPositionX(), target->GetPositionY(), FINAL_FLIGHT_Z); + events.ScheduleEvent(EVENT_FLIGHT, 6000); + break; + case EVENT_ENDFLIGHT: + me->GetMotionMaster()->Initialize(); + me->GetMotionMaster()->MovePoint(0, 1586.920166f, 119.848984f, FINAL_FLIGHT_Z); + events.CancelEvent(EVENT_FLIGHT); + events.CancelEvent(EVENT_ENDFLIGHT); + events.ScheduleEvent(EVENT_LAND, 4000); + break; + case EVENT_LAND: + me->GetMotionMaster()->Initialize(); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), FLOOR_Z); + events.CancelEvent(EVENT_LAND); + events.ScheduleEvent(EVENT_GROUND, 2500); + break; + case EVENT_GROUND: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS); + me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_SELF_VISUAL); + DoStartMovement(me->getVictim()); + events.CancelEvent(EVENT_GROUND); + break; + case EVENT_MOVE_POSITION: + if (me->IsWithinMeleeRange(me->getVictim())) + { + float x = irand(-25, 25); + float y = irand(-25, 25); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX() + x, me->GetPositionY() + y, FLOOR_Z); + // Prevention to go outside the room or into the walls + if (Creature* trigger = me->FindNearestCreature(NPC_WORLD_TRIGGER, 100.0f, true)) + if (me->GetDistance(trigger) >= 50.0f) + me->GetMotionMaster()->MovePoint(0, trigger->GetPositionX(), trigger->GetPositionY(), FLOOR_Z); + } + events.ScheduleEvent(EVENT_MOVE_POSITION, urand(7500, 10000)); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_stormcaller_brundirAI>(creature); } - }; - }; class spell_shield_of_runes : public SpellScriptLoader diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp index 51fb290502d..30a1299ae57 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp @@ -85,11 +85,6 @@ enum Yells SAY_BERSERK = -1603238, }; -enum Achievemments -{ - ACHIEV_DISARMED_START_EVENT = 21687, -}; - class boss_kologarn : public CreatureScript { public: @@ -200,7 +195,7 @@ class boss_kologarn : public CreatureScript if (!right && !left) events.ScheduleEvent(EVENT_STONE_SHOUT, 5000); - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT); + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_DISARMED); } else { diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h index 3ddb2eaf036..703e1f6b37b 100644 --- a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h @@ -169,7 +169,11 @@ enum UlduarTowerEvents EVENT_TOWER_OF_LIFE_DESTROYED = 21030, }; -#define CRITERIA_CON_SPEED_ATORY 21597 +enum UlduarAchievementCriteriaIds +{ + CRITERIA_CON_SPEED_ATORY = 21597, + CRITERIA_DISARMED = 21687, +}; template<class AI> CreatureAI* GetUlduarAI(Creature* creature) |
