diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Scripting/ScriptLoader.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/World/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/server/scripts/World/boss_emerald_dragons.cpp | 849 | ||||
-rw-r--r-- | src/server/scripts/World/boss_emeriss.cpp | 136 | ||||
-rw-r--r-- | src/server/scripts/World/boss_lethon.cpp | 27 | ||||
-rw-r--r-- | src/server/scripts/World/boss_taerar.cpp | 255 | ||||
-rw-r--r-- | src/server/scripts/World/boss_ysondre.cpp | 197 |
7 files changed, 852 insertions, 625 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 0b3a26992ce..2bd8bfdacd0 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -63,9 +63,7 @@ void AddSC_wp_commandscript(); #ifdef SCRIPTS //world void AddSC_areatrigger_scripts(); -void AddSC_boss_emeriss(); -void AddSC_boss_taerar(); -void AddSC_boss_ysondre(); +void AddSC_emerald_dragons(); void AddSC_generic_creature(); void AddSC_go_scripts(); void AddSC_guards(); @@ -664,9 +662,7 @@ void AddWorldScripts() { #ifdef SCRIPTS AddSC_areatrigger_scripts(); - AddSC_boss_emeriss(); - AddSC_boss_taerar(); - AddSC_boss_ysondre(); + AddSC_emerald_dragons(); AddSC_generic_creature(); AddSC_go_scripts(); AddSC_guards(); diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt index e0af140e964..41ba775efec 100644 --- a/src/server/scripts/World/CMakeLists.txt +++ b/src/server/scripts/World/CMakeLists.txt @@ -12,10 +12,7 @@ set(scripts_STAT_SRCS ${scripts_STAT_SRCS} World/achievement_scripts.cpp World/areatrigger_scripts.cpp - World/boss_emeriss.cpp - World/boss_lethon.cpp - World/boss_taerar.cpp - World/boss_ysondre.cpp + World/boss_emerald_dragons.cpp World/chat_log.cpp World/go_scripts.cpp World/guards.cpp diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp new file mode 100644 index 00000000000..e0a103d7e4f --- /dev/null +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -0,0 +1,849 @@ +/* +* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> +* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" + +// +// Emerald Dragon NPCs and IDs (kept here for reference) +// + +enum EmeraldDragonNPC +{ + NPC_DREAM_FOG = 15224, + NPC_DEMENTED_DRUID = 15260, + + DRAGON_YSONDRE = 14887, + DRAGON_LETHON = 14888, + DRAGON_EMERISS = 14889, + DRAGON_TAERAR = 14890, +}; + +// +// Emerald Dragon Spells (used for the dragons) +// + +enum EmeraldDragonSpells +{ + SPELL_TAIL_SWEEP = 15847, // tail sweep - slap everything behind dragon (2 seconds interval) + SPELL_SUMMON_PLAYER = 24776, // teleport highest threat player in front of dragon if wandering off + SPELL_DREAM_FOG = 24777, // used by summoned NPC (Dream Fog/15224) + SPELL_SEEPING_FOG_LEFT = 24813, // dream fog - summon left + SPELL_SEEPING_FOG_RIGHT = 24814, // dream fog - summon right + SPELL_NOXIOUS_BREATH = 24818, + SPELL_MARK_OF_NATURE = 25040, // Mark of Nature trigger (applied on target death - 15 minutes of being suspectible to Aura Of Nature) + SPELL_MARK_OF_NATURE_AURA = 25041, // Mark of Nature (passive marker-test, runs every 10 seconds from boss, triggers spellID 25042 (spell_dbc or script needed) + SPELL_AURA_OF_NATURE = 25043, // Stun for 2 minutes (used when SPELL_MARK_OF_NATURE exists on the target) +}; + +// +// Emerald Dragon Eventlists (shared and specials) +// + +enum EmeraldDragonEvents +{ + EVENT_SEEPING_FOG = 1, + EVENT_NOXIOUS_BREATH = 2, + EVENT_TAIL_SWEEP = 3, +}; + +enum YsondreEvents +{ + EVENT_LIGHTNING_WAVE = 11, + EVENT_SUMMON_DRUID_SPIRITS = 12, +}; + +enum LethonEvents +{ + EVENT_SHADOW_BOLT_WHIRL = 21, + EVENT_DRAW_SPIRIT = 22, +}; + +enum EmerissEvents +{ + EVENT_VOLATILE_INFECTION = 31, + EVENT_CORRUPTION_OF_EARTH = 32, +}; + +enum TaerarEvents +{ + EVENT_ARCANE_BLAST = 41, + EVENT_BELLOWING_ROAR = 42, +}; + +/* + * --- + * --- Emerald Dragons : Base AI-structure used for all the Emerald dragons + * --- + * + * TODO + * - Fix player teleportation when running off too far from the dragon (emerald_dragonAI) + * - Verify handling of Mark Of Nature / Aura of Nature + * + */ + +struct emerald_dragonAI : public WorldBossAI +{ + emerald_dragonAI(Creature* creature) : WorldBossAI(creature) + { + // Emerald Dragons are immune to nature + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + } + + void Reset() + { + WorldBossAI::Reset(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + events.ScheduleEvent(EVENT_TAIL_SWEEP, 4000); + events.ScheduleEvent(EVENT_NOXIOUS_BREATH, 8000); + events.ScheduleEvent(EVENT_SEEPING_FOG, urand(10000, 20000)); + } + + // Test if the player has been killed before, and if so, put them to sleep + void MoveInLineOfSight(Unit* who) + { + if (who && me->IsHostileTo(who)) + if (who->HasAura(SPELL_MARK_OF_NATURE_AURA) && !who->HasAura(SPELL_AURA_OF_NATURE)) + DoCast(who, SPELL_AURA_OF_NATURE, true); + } + + // Target killed during encounter, mark them as suspectible for Aura Of Nature + void KilledUnit(Unit* who) + { + DoCast(who, SPELL_MARK_OF_NATURE, true); + } + + // Execute and reschedule base events shared between all Emerald Dragons + void ExecuteEvent(uint32 const eventId) + { + switch (eventId) + { + case EVENT_SEEPING_FOG: + DoCast(me, SPELL_SEEPING_FOG_LEFT); + DoCast(me, SPELL_SEEPING_FOG_RIGHT); + events.ScheduleEvent(EVENT_SEEPING_FOG, urand(7500,17500)); + break; + case EVENT_NOXIOUS_BREATH: + DoCast(me, SPELL_NOXIOUS_BREATH); + events.ScheduleEvent(EVENT_NOXIOUS_BREATH, urand(15000, 20000)); + break; + case EVENT_TAIL_SWEEP: + DoCast(me, SPELL_TAIL_SWEEP); + events.ScheduleEvent(EVENT_TAIL_SWEEP, 2000); + break; + } + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + ExecuteEvent(eventId); + + DoMeleeAttackIfReady(); + } +}; + +/* + * --- Dream Fog NPC + * + * TODO: + * - Change to random targets on random intervals (?) + * - Check if targets are selected based on threatlevel(?) + * + */ + +class npc_dream_fog : public CreatureScript +{ + public: + npc_dream_fog() : CreatureScript("npc_dream_fog") { } + + struct npc_dream_fogAI : public ScriptedAI + { + npc_dream_fogAI(Creature* creature) : ScriptedAI(creature) + { + } + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + if (!_activeFog) + { + DoCast(SPELL_DREAM_FOG); + _activeFog = true; + } + + // Chase target, but don't attack - otherwise just roam around + Unit* target = SelectTarget(SELECT_TARGET_RANDOM); + if (target) + me->GetMotionMaster()->MoveChase(target); + else + me->GetMotionMaster()->MoveIdle(); + } + + private: + bool _activeFog; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_dream_fogAI(creature); + } +}; + +/* + * --- + * --- Dragonspecific scripts and handling: YSONDRE + * --- + * + * TODO: + * - Bugtesting... (?) + */ + +enum YsondreTexts +{ + SAY_YSONDRE_AGGRO = 0, + SAY_YSONDRE_SUMMON_DRUIDS = 1, +}; + +enum YsondreSpells +{ + SPELL_LIGHTNING_WAVE = 24819, + SPELL_SUMMON_DRUID_SPIRITS = 24795, +}; + +class boss_ysondre : public CreatureScript +{ + public: + boss_ysondre() : CreatureScript("boss_ysondre") { } + + struct boss_ysondreAI : public emerald_dragonAI + { + boss_ysondreAI(Creature* creature) : emerald_dragonAI(creature) + { + } + + void Reset() + { + _stage = 1; + _Reset(); + emerald_dragonAI::Reset(); + events.ScheduleEvent(EVENT_LIGHTNING_WAVE, 12000); + } + + void EnterCombat(Unit* who) + { + Talk(SAY_YSONDRE_AGGRO); + WorldBossAI::EnterCombat(who); + } + + // Summon druid spirits on 75%, 50% and 25% health + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) + { + if (!HealthAbovePct(100 - 25 * _stage)) + { + Talk(SAY_YSONDRE_SUMMON_DRUIDS); + for (int count = 0 ; count < 10 ; ++count) + DoCast(me, SPELL_SUMMON_DRUID_SPIRITS); + ++_stage; + } + } + + void ExecuteEvent(uint32 const eventId) + { + switch (eventId) + { + case EVENT_LIGHTNING_WAVE: + DoCastVictim(SPELL_LIGHTNING_WAVE); + events.ScheduleEvent(EVENT_LIGHTNING_WAVE, urand(7000, 12000)); + break; + default: + emerald_dragonAI::ExecuteEvent(eventId); + break; + } + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + ExecuteEvent(eventId); + + DoMeleeAttackIfReady(); + } + + private: + uint8 _stage; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ysondreAI(creature); + } +}; + +/* + * Ysondres' demented druids + * + * TODO: + * - Fix summoned druid lifetime (unsummon after 10 minutes) + * + */ + +enum DementedEvent +{ + EVENT_DRUID_MOONFIRE = 1, + EVENT_DRUID_CURSE_OF_THORNS = 2, + EVENT_DRUID_SILENCE = 3, +}; + +enum DementedSpell +{ + SPELL_SILENCE = 6726, + SPELL_CURSE_OF_THORNS = 16247, + SPELL_MOONFIRE = 21669, +}; + +class npc_demented_druid : public CreatureScript +{ + public: + npc_demented_druid() : CreatureScript("npc_demented_druid") { } + + struct npc_demented_druidAI : public ScriptedAI + { + npc_demented_druidAI(Creature* creature) : ScriptedAI(creature) + { + } + + void Reset() + { + _lifeTimer = 600000; + _events.ScheduleEvent(EVENT_DRUID_MOONFIRE, 2500); + _events.ScheduleEvent(EVENT_DRUID_SILENCE, 15000); + _events.ScheduleEvent(EVENT_DRUID_CURSE_OF_THORNS, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DRUID_MOONFIRE: + DoCastVictim(SPELL_MOONFIRE); + _events.ScheduleEvent(EVENT_DRUID_MOONFIRE, urand(10000, 15000)); + break; + case EVENT_DRUID_SILENCE: + DoCastVictim(SPELL_SILENCE); + _events.ScheduleEvent(EVENT_DRUID_SILENCE, urand(15000,20000)); + break; + case EVENT_DRUID_CURSE_OF_THORNS: + DoCastVictim(SPELL_SILENCE); + _events.ScheduleEvent(EVENT_DRUID_CURSE_OF_THORNS, urand(15000,20000)); + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + uint32 _lifeTimer; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_demented_druidAI(creature); + } +}; + +/* + * --- + * --- Dragonspecific scripts and handling: LETHON + * --- + * + * TODO: + * - Fix EVENT_DRAW_SPIRIT: + * Spirit Shade NPC helper needs to appear and walk toward Lethon and heal if they reach him + * Each shade heals for 15000 HP + * -Fix up EVENT_SHADOW_BOLT_WHIRL properly + * + */ + +enum LethonTexts +{ + SAY_LETHON_AGGRO = 0, + SAY_LETHON_DRAW_SPIRIT = 1, +}; + +enum LethonSpells +{ + SPELL_SHADOW_BOLT_WHIRL = 24834, + SPELL_DRAW_SPIRIT = 24811, +}; + +class boss_lethon : public CreatureScript +{ + public: + boss_lethon() : CreatureScript("boss_lethon") { } + + struct boss_lethonAI : public emerald_dragonAI + { + boss_lethonAI(Creature* creature) : emerald_dragonAI(creature) + { + } + + void Reset() + { + _stage = 1; + _Reset(); + emerald_dragonAI::Reset(); + events.ScheduleEvent(EVENT_SHADOW_BOLT_WHIRL, 5000); + } + + void EnterCombat(Unit* who) + { + Talk(SAY_LETHON_AGGRO); + WorldBossAI::EnterCombat(who); + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) + { + if (!HealthAbovePct(100 - 25 * _stage)) + { + Talk(SAY_LETHON_DRAW_SPIRIT); + DoCast(me, SPELL_DRAW_SPIRIT); + ++_stage; + } + } + + void ExecuteEvent(uint32 const eventId) + { + switch (eventId) + { + case EVENT_LIGHTNING_WAVE: + DoCast(SPELL_LIGHTNING_WAVE); + events.ScheduleEvent(EVENT_LIGHTNING_WAVE, 5000); + break; + default: + emerald_dragonAI::ExecuteEvent(eventId); + break; + } + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + ExecuteEvent(eventId); + + DoMeleeAttackIfReady(); + } + + private: + uint8 _stage; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_lethonAI(creature); + } +}; + +// --- +// --- Dragonspecific scripts and handling: EMERISS +// --- + +enum EmerissTexts +{ + SAY_EMERISS_AGGRO = 0, + SAY_EMERISS_CAST_CORRUPTION = 1, +}; + + +enum EmerissSpells +{ + SPELL_PUTRID_MUSHROOM = 24904, + SPELL_CORRUPTION_OF_EARTH = 24910, + SPELL_VOLATILE_INFECTION = 24928, +}; + +class boss_emeriss : public CreatureScript +{ + public: + boss_emeriss() : CreatureScript("boss_emeriss") { } + + struct boss_emerissAI : public emerald_dragonAI + { + boss_emerissAI(Creature* creature) : emerald_dragonAI(creature) + { + } + + void Reset() + { + _stage = 1; + _Reset(); + emerald_dragonAI::Reset(); + events.ScheduleEvent(EVENT_VOLATILE_INFECTION, 12000); + } + + void KilledUnit(Unit* who) + { + if (who->GetTypeId() == TYPEID_PLAYER) + DoCast(who, SPELL_PUTRID_MUSHROOM, true); + emerald_dragonAI::KilledUnit(who); + } + + void EnterCombat(Unit* who) + { + Talk(SAY_EMERISS_AGGRO); + WorldBossAI::EnterCombat(who); + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) + { + if (!HealthAbovePct(100 - 25 * _stage)) + { + Talk(SAY_EMERISS_CAST_CORRUPTION); + DoCast(me, SPELL_CORRUPTION_OF_EARTH); + ++_stage; + } + } + + void ExecuteEvent(uint32 const eventId) + { + switch (eventId) + { + case EVENT_VOLATILE_INFECTION: + DoCastVictim(SPELL_VOLATILE_INFECTION); + events.ScheduleEvent(EVENT_VOLATILE_INFECTION, 120000); + break; + default: + emerald_dragonAI::ExecuteEvent(eventId); + break; + } + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + ExecuteEvent(eventId); + + DoMeleeAttackIfReady(); + } + + private: + uint8 _stage; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_emerissAI(creature); + } +}; + +// --- +// --- Dragonspecific scripts and handling: TAERAR +// --- + +enum TaerarTexts +{ + SAY_TAERAR_AGGRO = 0, + SAY_TAERAR_SUMMON_SHADES = 1, +}; + +enum TaerarSpells +{ + SPELL_BELLOWING_ROAR = 22686, + SPELL_SHADE = 24313, + SPELL_SUMMON_SHADE_1 = 24841, + SPELL_SUMMON_SHADE_2 = 24842, + SPELL_SUMMON_SHADE_3 = 24843, + SPELL_ARCANE_BLAST = 24857, +}; + +uint32 const TaerarShadeSpells[] = +{ + SPELL_SUMMON_SHADE_1, SPELL_SUMMON_SHADE_2, SPELL_SUMMON_SHADE_3 +}; + +class boss_taerar : public CreatureScript +{ + public: + boss_taerar() : CreatureScript("boss_taerar") { } + + struct boss_taerarAI : public emerald_dragonAI + { + boss_taerarAI(Creature* creature) : emerald_dragonAI(creature) + { + _stage = 1; + _shades = 0; + _banished = false; + _banishedTimer = 0; + } + + void Reset() + { + me->RemoveAurasDueToSpell(SPELL_SHADE); + _stage = 1; + + _shades = 0; + _banished = false; + _banishedTimer = 0; + + _Reset(); + emerald_dragonAI::Reset(); + events.ScheduleEvent(EVENT_ARCANE_BLAST, 12000); + events.ScheduleEvent(EVENT_BELLOWING_ROAR, 30000); + } + + void EnterCombat(Unit* who) + { + Talk(SAY_TAERAR_AGGRO); + emerald_dragonAI::EnterCombat(who); + } + + void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) + { + --_shades; + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) + { + // At 75, 50 or 25 percent health, we need to activate the shades and go "banished" + // Note: _stage holds the amount of times they have been summoned + if (!_banished && !HealthAbovePct(100 - 25 * _stage)) + { + _banished = true; + _banishedTimer = 60000; + + me->InterruptNonMeleeSpells(false); + DoStopAttack(); + + Talk(SAY_TAERAR_SUMMON_SHADES); + + int count = sizeof(TaerarShadeSpells) / sizeof(uint32); + for (int i = 0; i < count; ++i) + DoCastVictim(TaerarShadeSpells[i], true); + _shades += count; + + DoCast(SPELL_SHADE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + + ++_stage; + } + } + + void ExecuteEvent(uint32 const eventId) + { + switch (eventId) + { + case EVENT_ARCANE_BLAST: + DoCast(SPELL_ARCANE_BLAST); + events.ScheduleEvent(EVENT_ARCANE_BLAST, urand(7000, 12000)); + break; + case EVENT_BELLOWING_ROAR: + DoCast(SPELL_BELLOWING_ROAR); + events.ScheduleEvent(EVENT_BELLOWING_ROAR, urand(20000, 30000)); + break; + default: + emerald_dragonAI::ExecuteEvent(eventId); + break; + } + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + if (_banished) + { + // If all three shades are dead, OR it has taken too long, end the current event and get Taerar back into business + if (_banishedTimer <= diff || !_shades) + { + _banished = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_SHADE); + me->SetReactState(REACT_AGGRESSIVE); + } + // _banishtimer has not expired, and we still have active shades: + else + _banishedTimer -= diff; + return; + } + + while (uint32 eventId = events.ExecuteEvent()) + ExecuteEvent(eventId); + + DoMeleeAttackIfReady(); + } + + private: + bool _banished; // used for shades activation testing + uint32 _banishedTimer; // counter for banishment timeout + uint8 _shades; // keep track of how many shades are dead + uint8 _stage; // check which "shade phase" we're at (75-50-25 percentage counters) + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_taerarAI(creature); + } +}; + +/* + * Taerars shades + */ + +enum ShadeEvents +{ + EVENT_SHADE_POISON_CLOUD = 1, + EVENT_SHADE_ACID_BREATH = 2, +}; + +enum ShadeSpells +{ + SPELL_POISON_CLOUD = 24840, + SPELL_ACID_BREATH = 20667, +}; + +class boss_shadeoftaerar : public CreatureScript +{ + public: + boss_shadeoftaerar() : CreatureScript("boss_shade_of_taerar") { } + + struct boss_shadeoftaerarAI : public ScriptedAI + { + boss_shadeoftaerarAI(Creature* creature) : ScriptedAI(creature) + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + } + + void Reset() + { + _events.Reset(); + _events.ScheduleEvent(EVENT_SHADE_ACID_BREATH, 12000); + _events.ScheduleEvent(EVENT_SHADE_POISON_CLOUD, 30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADE_ACID_BREATH: + DoCast(SPELL_ACID_BREATH); + _events.ScheduleEvent(EVENT_SHADE_ACID_BREATH, urand(10000, 14000)); + break; + case EVENT_SHADE_POISON_CLOUD: + DoCast(SPELL_POISON_CLOUD); + _events.ScheduleEvent(EVENT_SHADE_POISON_CLOUD, urand(25000, 30000)); + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_shadeoftaerarAI(creature); + } +}; + +void AddSC_emerald_dragons() +{ + // helper NPC scripts + new npc_dream_fog(); + + // ysondre and summons + new boss_ysondre(); + new npc_demented_druid(); + + // taerar and summons + new boss_taerar(); + new boss_shadeoftaerar(); + + // emeriss + new boss_emeriss(); + + // lethon and summons + new boss_lethon(); +}; diff --git a/src/server/scripts/World/boss_emeriss.cpp b/src/server/scripts/World/boss_emeriss.cpp deleted file mode 100644 index 9051e6f1a6d..00000000000 --- a/src/server/scripts/World/boss_emeriss.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Emeriss -SD%Complete: 90 -SDComment: Teleport function & Mark of Nature missing -SDCategory: Bosses -EndScriptData */ - -#include "ScriptPCH.h" - -enum eEnums -{ - SAY_AGGRO = -1000401, - SAY_CASTCORRUPTION = -1000402, //signed for 6182 - - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - SPELL_VOLATILEINFECTION = 24928, - SPELL_CORRUPTIONOFEARTH = 24910 -}; - -class boss_emeriss : public CreatureScript -{ -public: - boss_emeriss() : CreatureScript("boss_emeriss") { } - - struct boss_emerissAI : public ScriptedAI - { - boss_emerissAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - uint32 m_uiVolatileInfection_Timer; - uint32 m_uiCorruptionsCasted; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - m_uiVolatileInfection_Timer = 12000; - m_uiCorruptionsCasted = 0; - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%8000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - DoCast(me, SPELL_TAILSWEEP); - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //VolatileInfection_Timer - if (m_uiVolatileInfection_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); - m_uiVolatileInfection_Timer = 7000 + rand()%5000; - } - else - m_uiVolatileInfection_Timer -= uiDiff; - - //CorruptionofEarth_Timer - //CorruptionofEarth at 75%, 50% and 25% - if (!HealthAbovePct(100 - 25 * m_uiCorruptionsCasted)) - { - ++m_uiCorruptionsCasted; // prevent casting twice on same hp - DoScriptText(SAY_CASTCORRUPTION, me); - DoCast(me->getVictim(), SPELL_CORRUPTIONOFEARTH); - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI *GetAI(Creature *creature) const - { - return new boss_emerissAI(creature); - } -}; - -void AddSC_boss_emeriss() -{ - new boss_emeriss; -} - diff --git a/src/server/scripts/World/boss_lethon.cpp b/src/server/scripts/World/boss_lethon.cpp deleted file mode 100644 index deecf73e2d7..00000000000 --- a/src/server/scripts/World/boss_lethon.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Lethon -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Bosses -EndScriptData */ - -#include "ScriptPCH.h" - diff --git a/src/server/scripts/World/boss_taerar.cpp b/src/server/scripts/World/boss_taerar.cpp deleted file mode 100644 index e83aef49e16..00000000000 --- a/src/server/scripts/World/boss_taerar.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Taerar -SD%Complete: 70 -SDComment: Mark of Nature & Teleport NYI. Fix the way to be banished. -SDCategory: Bosses -EndScriptData */ - -#include "ScriptPCH.h" - -enum eEnums -{ - SAY_AGGRO = -1000399, //signed for 20021 - SAY_SUMMONSHADE = -1000400, //signed for 20021 - - //Spells of Taerar - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - SPELL_ARCANEBLAST = 24857, - SPELL_BELLOWINGROAR = 22686, - - SPELL_SUMMONSHADE_1 = 24841, - SPELL_SUMMONSHADE_2 = 24842, - SPELL_SUMMONSHADE_3 = 24843, - - //Spells of Shades of Taerar - SPELL_POSIONCLOUD = 24840, - SPELL_POSIONBREATH = 20667 -}; - -uint32 m_auiSpellSummonShade[] = -{ - SPELL_SUMMONSHADE_1, SPELL_SUMMONSHADE_2, SPELL_SUMMONSHADE_3 -}; - -class boss_taerar : public CreatureScript -{ -public: - boss_taerar() : CreatureScript("boss_taerar") { } - - struct boss_taerarAI : public ScriptedAI - { - boss_taerarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - uint32 m_uiArcaneBlast_Timer; - uint32 m_uiBellowingRoar_Timer; - uint32 m_uiShades_Timer; - uint32 m_uiShadesSummoned; - - bool m_bShades; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - m_uiArcaneBlast_Timer = 12000; - m_uiBellowingRoar_Timer = 30000; - m_uiShades_Timer = 60000; //The time that Taerar is banished - m_uiShadesSummoned = 0; - - m_bShades = false; - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_bShades && m_uiShades_Timer <= uiDiff) - { - //Become unbanished again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_bShades = false; - } - else if (m_bShades) - { - m_uiShades_Timer -= uiDiff; - //Do nothing while banished - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%7000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - DoCast(me, SPELL_TAILSWEEP); - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //ArcaneBlast_Timer - if (m_uiArcaneBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_ARCANEBLAST); - m_uiArcaneBlast_Timer = 7000 + rand()%5000; - } - else - m_uiArcaneBlast_Timer -= uiDiff; - - //BellowingRoar_Timer - if (m_uiBellowingRoar_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BELLOWINGROAR); - m_uiBellowingRoar_Timer = 20000 + rand()%10000; - } - else - m_uiBellowingRoar_Timer -= uiDiff; - - //Summon 3 Shades at 75%, 50% and 25% (if bShades is true we already left in line 117, no need to check here again) - if (!m_bShades && !HealthAbovePct(100 - 25 * m_uiShadesSummoned)) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - //Interrupt any spell casting - me->InterruptNonMeleeSpells(false); - - //horrible workaround, need to fix - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - DoScriptText(SAY_SUMMONSHADE, me); - - int iSize = sizeof(m_auiSpellSummonShade) / sizeof(uint32); - - for (int i = 0; i < iSize; ++i) - DoCast(pTarget, m_auiSpellSummonShade[i], true); - - ++m_uiShadesSummoned; // prevent casting twice at same health - m_bShades = true; - } - m_uiShades_Timer = 60000; - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI *GetAI(Creature *creature) const - { - return new boss_taerarAI(creature); - } -}; - -class boss_shadeoftaerar : public CreatureScript -{ -public: - boss_shadeoftaerar() : CreatureScript("boss_shade_of_taerar") { } - - struct boss_shadeoftaerarAI : public ScriptedAI - { - boss_shadeoftaerarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiPoisonCloud_Timer; - uint32 m_uiPosionBreath_Timer; - - void Reset() - { - m_uiPoisonCloud_Timer = 8000; - m_uiPosionBreath_Timer = 12000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //PoisonCloud_Timer - if (m_uiPoisonCloud_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_POSIONCLOUD); - m_uiPoisonCloud_Timer = 30000; - } - else - m_uiPoisonCloud_Timer -= uiDiff; - - //PosionBreath_Timer - if (m_uiPosionBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_POSIONBREATH); - m_uiPosionBreath_Timer = 12000; - } - else - m_uiPosionBreath_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI *GetAI(Creature *creature) const - { - return new boss_shadeoftaerarAI(creature); - } -}; - -void AddSC_boss_taerar() -{ - new boss_taerar; - new boss_shadeoftaerar; -} - diff --git a/src/server/scripts/World/boss_ysondre.cpp b/src/server/scripts/World/boss_ysondre.cpp deleted file mode 100644 index 9c3c5d40291..00000000000 --- a/src/server/scripts/World/boss_ysondre.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Ysondre -SD%Complete: 90 -SDComment: Mark of Nature & Teleport missing -SDCategory: Bosses -EndScriptData */ - -#include "ScriptPCH.h" - -enum eEnums -{ - SAY_AGGRO = -1000360, //signed for 17969 - SAY_SUMMONDRUIDS = -1000361, //signed for 17969 - - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - //SPELL_MARKOFNATURE = 25040, // Not working - SPELL_LIGHTNINGWAVE = 24819, - SPELL_SUMMONDRUIDS = 24795, - - SPELL_SUMMON_PLAYER = 24776, - - //druid spells - SPELL_MOONFIRE = 21669 -}; - -// Ysondre script -class boss_ysondre : public CreatureScript -{ -public: - boss_ysondre() : CreatureScript("boss_ysondre") { } - - struct boss_ysondreAI : public ScriptedAI - { - boss_ysondreAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - uint32 m_uiLightningWave_Timer; - uint32 m_uiSummonDruidModifier; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - m_uiLightningWave_Timer = 12000; - m_uiSummonDruidModifier = 0; - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%7000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TAILSWEEP); - - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //LightningWave_Timer - if (m_uiLightningWave_Timer <= uiDiff) - { - //Cast LIGHTNINGWAVE on a Random target - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LIGHTNINGWAVE); - - m_uiLightningWave_Timer = 7000 + rand()%5000; - } - else - m_uiLightningWave_Timer -= uiDiff; - - //Summon Druids - if (!HealthAbovePct(100 - 25 * m_uiSummonDruidModifier)) - { - DoScriptText(SAY_SUMMONDRUIDS, me); - - for (int i = 0; i < 10; ++i) - DoCast(me, SPELL_SUMMONDRUIDS, true); - - ++m_uiSummonDruidModifier; - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI *GetAI(Creature *creature) const - { - return new boss_ysondreAI(creature); - } -}; - -// Summoned druid script -class mob_dementeddruids : public CreatureScript -{ -public: - mob_dementeddruids() : CreatureScript("mob_dementeddruids") { } - - struct mob_dementeddruidsAI : public ScriptedAI - { - mob_dementeddruidsAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiMoonFire_Timer; - - void Reset() - { - m_uiMoonFire_Timer = 3000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //MoonFire_Timer - if (m_uiMoonFire_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MOONFIRE); - m_uiMoonFire_Timer = 5000; - } - else - m_uiMoonFire_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI *GetAI(Creature *creature) const - { - return new mob_dementeddruidsAI(creature); - } -}; - -void AddSC_boss_ysondre() -{ - new boss_ysondre; - new mob_dementeddruids; -} - |