diff options
10 files changed, 988 insertions, 223 deletions
diff --git a/sql/updates/world/2013_12_07_00_world_misc.sql b/sql/updates/world/2013_12_07_00_world_misc.sql new file mode 100644 index 00000000000..42063be2e3a --- /dev/null +++ b/sql/updates/world/2013_12_07_00_world_misc.sql @@ -0,0 +1,77 @@ +-- Talk text for Mordresh Fire Eye from sniff +SET @ENTRY := 7357; +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'We will enslave the quilboar!',12,0,100,1,0,5819, 'Mordresh Fire Eye - SAY_OOC_1'), +(@ENTRY,1,0,'We will spread across this barren land!',12,0,100,1,0,5820, 'Mordresh Fire Eye - SAY_OOC_2'), +(@ENTRY,2,0,'Soon, the Scourge will rule the world!',12,0,100,22,0,5821, 'Mordresh Fire Eye - SAY_OOC_3'), +(@ENTRY,3,0,'Slay them, my brethren! For the Scourge!',14,0,100,0,0,5822, 'Mordresh Fire Eye - SAY_AGGRO'); + +-- Talk text for Belnistrasz from sniff +SET @ENTRY := 8516; +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'All right, stay close. These fiends will jump right out of the shadows at you if you let your guard down.',12,0,100,0,0,0,'Belnistrasz SAY_QUEST_ACCEPTED'), +(@ENTRY,1,0,'Okay, here we go. It's going to take about five minutes to shut this thing down through the ritual. Once I start, keep the vermin off of me or it will be the end of us all!',12,0,100,0,0,0,'Belnistrasz SAY_EVENT_START'), +(@ENTRY,2,0,'Three minutes left -- I can feel the energy starting to build! Keep up the solid defense!',14,0,100,0,0,0,'Belnistrasz SAY_EVENT_THREE_MIN_LEFT'), +(@ENTRY,3,0,'Just two minutes to go! We're half way there, but don't let your guard down!',14,0,100,0,0,0,'Belnistrasz SAY_EVENT_TWO_MIN_LEFT'), +(@ENTRY,4,0,'One more minute! Hold on now, the ritual is about to take hold!',14,0,100,0,0,0,'Belnistrasz SAY_EVENT_ONE_MIN_LEFT'), +(@ENTRY,5,0,'That's it -- we made it! The ritual is set in motion, and idol fires are about to go out for good! You truly are the heroes I thought you would be!',14,0,100,4,0,0,'Belnistrasz SAY_EVENT_END'), +(@ENTRY,6,0,'You'll rue the day you crossed me, $N',12,0,100,0,0,0,'Belnistrasz SAY_AGGRO'); +(@ENTRY,7,0,'Watch out for the $N!',12,0,100,0,0,0,'Belnistrasz SAY_WATCH_OUT'); + +-- Fix trigger location +UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=`flags_extra`|128 WHERE `entry`=8662; + +-- Condition for spell Belnistrasz Idol Shutdown Visual +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=12774; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 12774, 0, 0, 31, 0, 3, 8662, 0, 0, 0, 0, '', 'Belnistrasz Idol Shutdown Visual targets Idol Oven Fire Target'); + +-- Add cpp scripts +UPDATE creature_template SET `AIName`= '',ScriptName = 'boss_tuten_kash' WHERE entry=7355; +UPDATE creature_template SET `AIName`= '',ScriptName = 'boss_mordresh_fire_eye' WHERE entry=7357; +UPDATE creature_template SET `AIName`= '',ScriptName = 'boss_glutton' WHERE entry=8567; +UPDATE creature_template SET `AIName`= '',ScriptName = 'npc_belnistrasz' WHERE entry=8516; +UPDATE creature_template SET `AIName`= '',ScriptName = 'npc_idol_room_spawner' WHERE entry=8611; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (7355,7357,8567,8516) AND `source_type`=0; + +-- Pathing for Belnistrasz Entry: 8516 +SET @NPC := 87171; +SET @PATH := @NPC * 10; +DELETE FROM `creature_template_addon` WHERE `entry`=8516; +INSERT INTO `creature_template_addon` (`entry`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (8516,@PATH,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,2603.313,724.335,54.608,0,0,1,0,100,0), +(@PATH,2,2593.379,726.272,55.112,0,0,1,0,100,0), +(@PATH,3,2588.499,733.1947,55.3959,0,0,1,0,100,0), +(@PATH,4,2572.573,752.5162,54.71815,0,0,1,0,100,0), +(@PATH,5,2558.068,748.3008,54.3559,0,0,1,0,100,0), +(@PATH,6,2539.677,777.1356,46.95155,0,0,1,0,100,0), +(@PATH,7,2527.828,800.8403,44.74713,0,0,1,0,100,0), +(@PATH,8,2495.996,785.7536,39.51203,0,0,1,0,100,0), +(@PATH,9,2484.358,814.8914,43.57789,0,0,1,0,100,0), +(@PATH,10,2501.128,847.9614,47.5574,0,0,1,0,100,0), +(@PATH,11,2537.36,874.4713,47.67798,0,0,1,0,100,0), +(@PATH,12,2548.493,894.6515,47.69307,0,0,1,0,100,0), +(@PATH,13,2541.478,910.5101,46.17223,0,0,1,0,100,0), +(@PATH,14,2519.403,925.6332,46.51501,0,0,1,0,100,0), +(@PATH,15,2527.237,951.4606,49.2807,0,0,1,0,100,0), +(@PATH,16,2541.675,976.5887,50.41221,0,0,1,0,100,0), +(@PATH,17,2554.084,973.8665,50.36161,0,0,1,0,100,0), +(@PATH,18,2575.601,950.1381,52.84592,0,0,1,0,100,0); + +DELETE FROM `creature_questender` WHERE `id`=8516 AND `quest`=3525; +DELETE FROM `gameobject_questender` WHERE `id`=152097 AND `quest`=3525; +INSERT INTO `gameobject_questender` (`id`,`quest`) VALUES (152097,3525); + +-- Death's Head Geomancer SAI +SET @ENTRY := 7335; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,2,0,0,3000,4000,11,9053,64,0,0,0,0,2,0,0,0,0,0,0,0,"Death's Head Geomancer - Combat - Cast Fireball (Normal Dungeon)"), +(@ENTRY,0,1,0,0,0,100,2,8000,10000,6000,15000,11,6725,0,0,0,0,0,5,0,0,0,0,0,0,0,"Death's Head Geomancer - Combat - Cast Flame Spike (Normal Dungeon)"), +(@ENTRY,0,2,0,0,0,100,2,12000,16000,8000,20000,11,11436,1,0,0,0,0,5,0,0,0,0,0,0,0,"Death's Head Geomancer - Combat - Cast Slow (Normal Dungeon)"), +(@ENTRY,0,3,0,2,0,100,3,0,15,0,0,25,1,0,0,0,0,0,0,0,0,0,0,0,0,0,"Death's Head Geomancer - 0-15% Health - Flee For Assist (Normal Dungeon)"); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 28fe883feb9..b486eb45915 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -321,7 +321,10 @@ void AddSC_boss_ptheradras(); void AddSC_instance_maraudon(); void AddSC_boss_onyxia(); //Onyxia's Lair void AddSC_instance_onyxias_lair(); -void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs +void AddSC_boss_tuten_kash(); //Razorfen Downs +void AddSC_boss_mordresh_fire_eye(); +void AddSC_boss_glutton(); +void AddSC_boss_amnennar_the_coldbringer(); void AddSC_razorfen_downs(); void AddSC_instance_razorfen_downs(); void AddSC_razorfen_kraul(); //Razorfen Kraul @@ -1032,7 +1035,10 @@ void AddKalimdorScripts() AddSC_instance_maraudon(); AddSC_boss_onyxia(); //Onyxia's Lair AddSC_instance_onyxias_lair(); - AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs + AddSC_boss_tuten_kash(); //Razorfen Downs + AddSC_boss_mordresh_fire_eye(); + AddSC_boss_glutton(); + AddSC_boss_amnennar_the_coldbringer(); AddSC_razorfen_downs(); AddSC_instance_razorfen_downs(); AddSC_razorfen_kraul(); //Razorfen Kraul diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt index 17c360a54b2..c02e896a87d 100644 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ b/src/server/scripts/Kalimdor/CMakeLists.txt @@ -15,12 +15,15 @@ set(scripts_STAT_SRCS Kalimdor/zone_moonglade.cpp Kalimdor/RazorfenDowns/razorfen_downs.cpp Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp + Kalimdor/RazorfenDowns/boss_tuten_kash.cpp + Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp + Kalimdor/RazorfenDowns/boss_glutton.cpp Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp Kalimdor/RazorfenDowns/razorfen_downs.h - Kalimdor/ZulFarrak/zulfarrak.h Kalimdor/ZulFarrak/zulfarrak.cpp Kalimdor/ZulFarrak/instance_zulfarrak.cpp Kalimdor/ZulFarrak/boss_zum_rah.cpp + Kalimdor/ZulFarrak/zulfarrak.h Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp index 4a4d7fe4b07..323fd92a8f6 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 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 @@ -16,63 +15,57 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Amnennar_the_coldbringer -SD%Complete: 100 -SDComment: -SDCategory: Razorfen Downs -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "razorfen_downs.h" -enum AmnennarTheColdbringer +enum Say { SAY_AGGRO = 0, SAY_SUMMON60 = 1, SAY_SUMMON30 = 2, SAY_HP = 3, - SAY_KILL = 4, + SAY_KILL = 4 +}; +enum Spells +{ SPELL_AMNENNARSWRATH = 13009, SPELL_FROSTBOLT = 15530, SPELL_FROST_NOVA = 15531, SPELL_FROST_SPECTRES = 12642 }; +enum Events +{ + EVENT_AMNENNARSWRATH = 1, + EVENT_FROSTBOLT = 2, + EVENT_FROST_NOVA = 3 +}; + class boss_amnennar_the_coldbringer : public CreatureScript { public: boss_amnennar_the_coldbringer() : CreatureScript("boss_amnennar_the_coldbringer") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_amnennar_the_coldbringerAI(creature); - } - - struct boss_amnennar_the_coldbringerAI : public ScriptedAI + struct boss_amnennar_the_coldbringerAI : public BossAI { - boss_amnennar_the_coldbringerAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 AmnenarsWrath_Timer; - uint32 FrostBolt_Timer; - uint32 FrostNova_Timer; - bool Spectrals60; - bool Spectrals30; - bool Hp; + boss_amnennar_the_coldbringerAI(Creature* creature) : BossAI(creature, DATA_AMNENNAR_THE_COLD_BRINGER) { } void Reset() OVERRIDE { - AmnenarsWrath_Timer = 8000; - FrostBolt_Timer = 1000; - FrostNova_Timer = urand(10000, 15000); - Spectrals30 = false; - Spectrals60 = false; - Hp = false; + _Reset(); + hp60Spectrals = false; + hp30Spectrals = false; + hp50 = false; } void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); + events.ScheduleEvent(EVENT_AMNENNARSWRATH, 8000); + events.ScheduleEvent(EVENT_FROSTBOLT, 1000); + events.ScheduleEvent(EVENT_FROST_NOVA, urand(10000, 15000)); Talk(SAY_AGGRO); } @@ -81,55 +74,73 @@ public: Talk(SAY_KILL); } + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } + void UpdateAI(uint32 diff) OVERRIDE { if (!UpdateVictim()) return; - //AmnenarsWrath_Timer - if (AmnenarsWrath_Timer <= diff) - { - DoCastVictim(SPELL_AMNENNARSWRATH); - AmnenarsWrath_Timer = 12000; - } else AmnenarsWrath_Timer -= diff; + events.Update(diff); - //FrostBolt_Timer - if (FrostBolt_Timer <= diff) - { - DoCastVictim(SPELL_FROSTBOLT); - FrostBolt_Timer = 8000; - } else FrostBolt_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (FrostNova_Timer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - DoCast(me, SPELL_FROST_NOVA); - FrostNova_Timer = 15000; - } else FrostNova_Timer -= diff; + switch (eventId) + { + case EVENT_AMNENNARSWRATH: + DoCastVictim(SPELL_AMNENNARSWRATH); + events.ScheduleEvent(EVENT_AMNENNARSWRATH, 12000); + break; + case EVENT_FROSTBOLT: + DoCastVictim(SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 8000); + break; + case EVENT_FROST_NOVA: + DoCast(me, SPELL_FROST_NOVA); + events.ScheduleEvent(EVENT_FROST_NOVA, 15000); + break; + } + } - if (!Spectrals60 && HealthBelowPct(60)) + if (!hp60Spectrals && HealthBelowPct(60)) { Talk(SAY_SUMMON60); DoCastVictim(SPELL_FROST_SPECTRES); - Spectrals60 = true; + hp60Spectrals = true; } - if (!Hp && HealthBelowPct(50)) + if (!hp50 && HealthBelowPct(50)) { Talk(SAY_HP); - Hp = true; + hp50 = true; } - if (!Spectrals30 && HealthBelowPct(30)) + if (!hp30Spectrals && HealthBelowPct(30)) { Talk(SAY_SUMMON30); DoCastVictim(SPELL_FROST_SPECTRES); - Spectrals30 = true; + hp30Spectrals = true; } DoMeleeAttackIfReady(); } + + private: + bool hp60Spectrals; + bool hp30Spectrals; + bool hp50; }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new boss_amnennar_the_coldbringerAI(creature); + } }; void AddSC_boss_amnennar_the_coldbringer() diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp new file mode 100644 index 00000000000..a249013bd6a --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * + * 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "razorfen_downs.h" + +enum Say +{ + SAY_HP50 = 0, + SAY_HP15 = 1 +}; + +enum Spells +{ + SPELL_DISEASE_CLOUD = 12627, + SPELL_FRENZY = 12795 +}; + +class boss_glutton : public CreatureScript +{ +public: + boss_glutton() : CreatureScript("boss_glutton") { } + + struct boss_gluttonAI : public BossAI + { + boss_gluttonAI(Creature* creature) : BossAI(creature, DATA_GLUTTON) { } + + void Reset() OVERRIDE + { + _Reset(); + hp50 = false; + hp15 = false; + } + + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE + { + if (!UpdateVictim()) + return; + + if (!hp50 && HealthBelowPct(50)) + { + Talk(SAY_HP50); + hp50 = true; + } + + if (!hp15 && HealthBelowPct(15)) + { + Talk(SAY_HP15); + DoCast(me, SPELL_FRENZY); + hp15 = true; + } + + DoMeleeAttackIfReady(); + } + + private: + bool hp50; + bool hp15; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new boss_gluttonAI(creature); + } +}; + +void AddSC_boss_glutton() +{ + new boss_glutton(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp new file mode 100644 index 00000000000..1f45de3c4c6 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * + * 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "razorfen_downs.h" + +enum Say +{ + SAY_OOC_1 = 0, + SAY_OOC_2 = 1, + SAY_OOC_3 = 2, + SAY_AGGRO = 3 +}; + +enum Spells +{ + SPELL_FIREBALL = 12466, + SPELL_FIRE_NOVA = 12470 +}; + +enum Events +{ + EVENT_OOC_1 = 1, + EVENT_OOC_2 = 2, + EVENT_OOC_3 = 3, + EVENT_OOC_4 = 4, + EVENT_FIREBALL = 5, + EVENT_FIRE_NOVA = 6 +}; + +class boss_mordresh_fire_eye : public CreatureScript +{ +public: + boss_mordresh_fire_eye() : CreatureScript("boss_mordresh_fire_eye") { } + + struct boss_mordresh_fire_eyeAI : public BossAI + { + boss_mordresh_fire_eyeAI(Creature* creature) : BossAI(creature, DATA_MORDRESH_FIRE_EYE) { } + + void Reset() OVERRIDE + { + _Reset(); + events.ScheduleEvent(EVENT_OOC_1, 10000); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + events.Reset(); + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_FIREBALL, 100); + events.ScheduleEvent(EVENT_FIRE_NOVA, urand(8000, 12000)); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } + + void UpdateAI(uint32 diff) OVERRIDE + { + events.Update(diff); + + if (!UpdateVictim()) + { + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_OOC_1: + Talk(SAY_OOC_1); + events.ScheduleEvent(EVENT_OOC_2, 8000); + break; + case EVENT_OOC_2: + Talk(SAY_OOC_2); + events.ScheduleEvent(EVENT_OOC_3, 3000); + break; + case EVENT_OOC_3: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + events.ScheduleEvent(EVENT_OOC_4, 6000); + break; + case EVENT_OOC_4: + Talk(SAY_OOC_3); + events.ScheduleEvent(EVENT_OOC_1, 14000); + break; + } + } + return; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FIREBALL: + DoCastVictim(SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, urand(2400, 3800)); + break; + case EVENT_FIRE_NOVA: + DoCast(me, SPELL_FIRE_NOVA); + events.ScheduleEvent(EVENT_FIRE_NOVA, urand(11000, 16000)); + break; + } + } + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new boss_mordresh_fire_eyeAI(creature); + } +}; + +void AddSC_boss_mordresh_fire_eye() +{ + new boss_mordresh_fire_eye(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp new file mode 100644 index 00000000000..5cf8a2992a3 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> + * + * 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "razorfen_downs.h" + +enum Spells +{ + SPELL_THRASH = 8876, + SPELL_WEB_SPRAY = 12252, + SPELL_VIRULENT_POISON = 12254, + SPELL_CURSE_OF_TUTENKASH = 12255 +}; + +enum Events +{ + EVENT_WEB_SPRAY = 1, + EVENT_CURSE_OF_TUTENKASH = 2 +}; + +class boss_tuten_kash : public CreatureScript +{ +public: + boss_tuten_kash() : CreatureScript("boss_tuten_kash") { } + + struct boss_tuten_kashAI : public BossAI + { + boss_tuten_kashAI(Creature* creature) : BossAI(creature, DATA_TUTEN_KASH) { } + + void Reset() OVERRIDE + { + _Reset(); + if (!me->HasAura(SPELL_THRASH)) + DoCast(me, SPELL_THRASH); + if (!me->HasAura(SPELL_VIRULENT_POISON)) + DoCast(me, SPELL_VIRULENT_POISON); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + events.ScheduleEvent(EVENT_WEB_SPRAY, urand(3000, 5000)); + events.ScheduleEvent(EVENT_CURSE_OF_TUTENKASH, urand(9000, 14000)); + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_WEB_SPRAY: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, false)) + { + if (!target->HasAura(SPELL_WEB_SPRAY)) + DoCast(target, SPELL_WEB_SPRAY); + } + events.ScheduleEvent(EVENT_WEB_SPRAY, urand(6000, 8000)); + break; + case EVENT_CURSE_OF_TUTENKASH: + DoCast(me, SPELL_CURSE_OF_TUTENKASH); + events.ScheduleEvent(EVENT_CURSE_OF_TUTENKASH, urand(15000, 25000)); + break; + } + } + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new boss_tuten_kashAI(creature); + } +}; + +void AddSC_boss_tuten_kash() +{ + new boss_tuten_kash(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp index 091c7e46585..097f340891a 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp @@ -16,199 +16,219 @@ */ #include "ScriptMgr.h" +#include "ObjectMgr.h" #include "InstanceScript.h" #include "razorfen_downs.h" #include "Player.h" #include "TemporarySummon.h" -#define MAX_ENCOUNTER 1 +Position const PosSummonTutenkash[15] = +{ + // 7349 Tomb Fiend + { 2487.339f, 805.9111f, 43.08361f, 2.844887f }, + { 2485.405f, 804.1145f, 43.68511f, 3.054326f }, + { 2488.431f, 801.2809f, 42.70374f, 4.29351f }, + { 2489.914f, 804.7949f, 43.25175f, 1.658063f }, + { 2541.246f, 907.0941f, 46.64201f, 2.024582f }, + { 2544.701f, 907.6331f, 46.38007f, 1.605703f }, + { 2541.49f, 911.1756f, 46.26493f, 4.817109f }, + { 2544.693f, 912.8887f, 46.39912f, 2.129302f }, + { 2524.036f, 834.4852f, 48.37031f, 0.8028514f }, + { 2527.017f, 829.9793f, 48.06498f, 0.6981317f }, + // 7351 Tomb Reaver + { 2542.818f, 904.9359f, 46.80911f, 4.642576f }, + { 2543.287f, 911.2448f, 46.32785f, 0.6806784f }, + { 2489.083f, 806.5914f, 43.21102f, 3.682645f }, + { 2486.828f, 802.8737f, 43.19883f, 2.9147f }, + // 7355 Tuten'kash + { 2487.939f, 804.2224f, 43.10735f, 1.692969f } +}; class instance_razorfen_downs : public InstanceMapScript { public: - instance_razorfen_downs() : InstanceMapScript("instance_razorfen_downs", 129) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_razorfen_downs_InstanceMapScript(map); - } + instance_razorfen_downs() : InstanceMapScript(RFDScriptName, 129) { } struct instance_razorfen_downs_InstanceMapScript : public InstanceScript { instance_razorfen_downs_InstanceMapScript(Map* map) : InstanceScript(map) { + SetBossNumber(EncounterCount); } - uint64 uiGongGUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint16 uiGongWaves; - - std::string str_data; - void Initialize() OVERRIDE { - uiGongGUID = 0; - - uiGongWaves = 0; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << ' ' << uiGongWaves; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; + goGongGUID = 0; + gongWave = 0; + fiendsKilled = 0; + reaversKilled = 0; + summonLowRange = 0; + summonHighRange = 0; + summonCreature = 0; } - void Load(const char* in) OVERRIDE + void OnGameObjectCreate(GameObject* gameObject) OVERRIDE { - if (!in) + switch (gameObject->GetEntry()) { - OUT_LOAD_INST_DATA_FAIL; - return; + case GO_GONG: + goGongGUID = gameObject->GetGUID(); + if (GetBossState(DATA_TUTEN_KASH) == DONE) + gameObject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_IDOL_OVEN_FIRE: + case GO_IDOL_CUP_FIRE: + case GO_IDOL_MOUTH_FIRE: + if (GetBossState(DATA_EXTINGUISHING_THE_IDOL) == DONE) + gameObject->Delete(); + break; + default: + break; } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGongWaves = data1; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; } - void OnGameObjectCreate(GameObject* go) OVERRIDE + bool SetBossState(uint32 type, EncounterState state) OVERRIDE { - switch (go->GetEntry()) + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) { - case GO_GONG: - uiGongGUID = go->GetGUID(); - if (m_auiEncounter[0] == DONE) - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + case DATA_TUTEN_KASH: + case DATA_MORDRESH_FIRE_EYE: + case DATA_GLUTTON: + case DATA_AMNENNAR_THE_COLD_BRINGER: + case DATA_GONG: + case DATA_WAVE: + case DATA_EXTINGUISHING_THE_IDOL: break; default: break; } + return true; } - void SetData(uint32 uiType, uint32 uiData) OVERRIDE + void SetData(uint32 type, uint32 data) OVERRIDE { - if (uiType == DATA_GONG_WAVES) + if (type == DATA_WAVE) { - uiGongWaves = uiData; - - switch (uiGongWaves) + switch (data) { - case 9: - case 14: - if (GameObject* go = instance->GetGameObject(uiGongGUID)) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; - case 1: - case 10: - case 16: + case IN_PROGRESS: { - GameObject* go = instance->GetGameObject(uiGongGUID); - - if (!go) - return; - - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - - uint32 uiCreature = 0; - uint8 uiSummonTimes = 0; + if (GameObject* go = instance->GetGameObject(goGongGUID)) + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - switch (uiGongWaves) + switch (gongWave) { - case 1: - uiCreature = NPC_TOMB_FIEND; - uiSummonTimes = 7; - break; - case 10: - uiCreature = NPC_TOMB_REAVER; - uiSummonTimes = 3; + case 0: + summonLowRange = 0; + summonHighRange = 10; + summonCreature = NPC_TOMB_FIEND; break; - case 16: - uiCreature = NPC_TUTEN_KASH; + case 1: + summonLowRange = 10; + summonHighRange = 14; + summonCreature = NPC_TOMB_REAVER; break; - default: + case 2: + summonLowRange = 14; + summonHighRange = 15; + summonCreature = NPC_TUTEN_KASH; break; } - if (Creature* creature = go->SummonCreature(uiCreature, 2502.635f, 844.140f, 46.896f, 0.633f)) + if (GameObject* go = instance->GetGameObject(goGongGUID)) { - if (uiGongWaves == 10 || uiGongWaves == 1) + for (uint8 i = summonLowRange; i < summonHighRange; ++i) { - for (uint8 i = 0; i < uiSummonTimes; ++i) - { - if (Creature* summon = go->SummonCreature(uiCreature, 2502.635f + float(irand(-5, 5)), 844.140f + float(irand(-5, 5)), 46.896f, 0.633f)) - summon->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f); - } + Creature* creature = go->SummonCreature(summonCreature, PosSummonTutenkash[i]); + creature->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f); } - creature->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f); } + + ++gongWave; break; } - default: + case NPC_TOMB_FIEND: + if (++fiendsKilled == 10) + { + fiendsKilled = 0; + if (GameObject* go = instance->GetGameObject(goGongGUID)) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + break; + case NPC_TOMB_REAVER: + if (++reaversKilled == 4) + { + reaversKilled = 0; + if (GameObject* go = instance->GetGameObject(goGongGUID)) + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } break; } + } - if (uiType == BOSS_TUTEN_KASH) - { - m_auiEncounter[0] = uiData; + } - if (uiData == DONE) - SaveToDB(); - } + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "R D " << GetBossSaveData(); + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - uint32 GetData(uint32 uiType) const OVERRIDE + void Load(const char* str) OVERRIDE { - switch (uiType) + if (!str) { - case DATA_GONG_WAVES: - return uiGongWaves; + OUT_LOAD_INST_DATA_FAIL; + return; } - return 0; - } + OUT_LOAD_INST_DATA(str); - uint64 GetData64(uint32 uiType) const OVERRIDE - { - switch (uiType) + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'R' && dataHead2 == 'D') { - case DATA_GONG: return uiGongGUID; + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } } + else + OUT_LOAD_INST_DATA_FAIL; - return 0; + OUT_LOAD_INST_DATA_COMPLETE; } + + protected: + uint64 goGongGUID; + uint16 gongWave; + uint8 fiendsKilled; + uint8 reaversKilled; + uint8 summonLowRange; + uint8 summonHighRange; + uint32 summonCreature; }; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_razorfen_downs_InstanceMapScript(map); + } }; void AddSC_instance_razorfen_downs() diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp index 320c9970077..f81d634e019 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp @@ -32,6 +32,11 @@ EndContentData */ #include "ScriptedGossip.h" #include "razorfen_downs.h" #include "Player.h" +#include "GridDefines.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "ObjectDefines.h" +#include "ObjectMgr.h" /*### # npc_henry_stern @@ -101,32 +106,272 @@ public: }; /*###### -## go_gong +## npc_belnistrasz for Quest 3525 "Extinguishing the Idol" ######*/ -class go_gong : public GameObjectScript +Position const PosSummonSpawner[3] = +{ + { 2582.789f, 954.3925f, 52.48214f, 3.787364f }, + { 2569.42f, 956.3801f, 52.27323f, 5.427974f }, + { 2570.62f, 942.3934f, 53.7433f, 0.715585f } +}; + +enum Belnistrasz +{ + EVENT_CHANNEL = 1, + EVENT_IDOL_ROOM_SPAWNER = 2, + EVENT_PROGRESS = 3, + EVENT_COMPLETE = 4, + EVENT_FIREBALL = 5, + EVENT_FROST_NOVA = 6, + + FACTION_ESCORT = 250, + + PATH_ESCORT = 871710, + POINT_REACH_IDOL = 17, + + QUEST_EXTINGUISHING_THE_IDOL = 3525, + + SAY_QUEST_ACCEPTED = 0, + SAY_EVENT_START = 1, + SAY_EVENT_THREE_MIN_LEFT = 2, + SAY_EVENT_TWO_MIN_LEFT = 3, + SAY_EVENT_ONE_MIN_LEFT = 4, + SAY_EVENT_END = 5, + SAY_AGGRO = 6, // Combat + SAY_WATCH_OUT = 7, // 25% chance to target random creature and say on wave spawn + + SPELL_ARCANE_INTELLECT = 13326, + SPELL_FIREBALL = 9053, + SPELL_FROST_NOVA = 11831, + SPELL_IDOL_SHUTDOWN_VISUAL = 12774, // Hits Unit Entry: 8662 + SPELL_IDOM_ROOM_CAMERA_SHAKE = 12816 // Dummy needs scripting +}; + +class npc_belnistrasz : public CreatureScript { public: - go_gong() : GameObjectScript("go_gong") { } + npc_belnistrasz() : CreatureScript("npc_belnistrasz") { } - bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE + struct npc_belnistraszAI : public ScriptedAI { - //basic support, not blizzlike data is missing... - InstanceScript* instance = go->GetInstanceScript(); + npc_belnistraszAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + eventInProgress = false; + } - if (instance) + void Reset() OVERRIDE { - instance->SetData(DATA_GONG_WAVES, instance->GetData(DATA_GONG_WAVES)+1); - return true; + if (!eventInProgress) + { + if (!me->HasAura(SPELL_ARCANE_INTELLECT)) + DoCast(me, SPELL_ARCANE_INTELLECT); + + channeling = false; + eventProgress = 0; + spawnerCount = 0; + me->SetFlag(UNIT_NPC_FLAGS, GOSSIP_OPTION_QUESTGIVER); + } } - return false; + void EnterCombat(Unit* who) OVERRIDE + { + if (channeling) + { + Talk(SAY_WATCH_OUT, who->GetGUID()); + } + else + { + events.ScheduleEvent(EVENT_FIREBALL, 1000); + events.ScheduleEvent(EVENT_FROST_NOVA, urand(8000, 12000)); + if (urand(0, 100) > 40) + Talk(SAY_AGGRO, who->GetGUID()); + } + } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + instance->SetBossState(DATA_EXTINGUISHING_THE_IDOL, DONE); + me->DespawnOrUnsummon(5000); + } + + void sQuestAccept(Player* /*player*/, Quest const* quest) OVERRIDE + { + if (quest->GetQuestId() == QUEST_EXTINGUISHING_THE_IDOL) + { + eventInProgress = true; + Talk(SAY_QUEST_ACCEPTED); + me->RemoveFlag(UNIT_NPC_FLAGS, GOSSIP_OPTION_QUESTGIVER); + me->setFaction(FACTION_ESCORT); + me->GetMotionMaster()->MovePath(PATH_ESCORT, false); + } + } + + void MovementInform(uint32 type, uint32 id) OVERRIDE + { + if (type == WAYPOINT_MOTION_TYPE && id == POINT_REACH_IDOL) + { + channeling = true; + events.ScheduleEvent(EVENT_CHANNEL, 2000); + } + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (!eventInProgress) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CHANNEL: + Talk(SAY_EVENT_START); + DoCast(me, SPELL_IDOL_SHUTDOWN_VISUAL); + events.ScheduleEvent(EVENT_IDOL_ROOM_SPAWNER, 100); + events.ScheduleEvent(EVENT_PROGRESS, 120000); + break; + case EVENT_IDOL_ROOM_SPAWNER: + if (Creature* creature = me->SummonCreature(NPC_IDOL_ROOM_SPAWNER, PosSummonSpawner[urand(0,2)], TEMPSUMMON_TIMED_DESPAWN, 4000)) + creature->AI()->SetData(0,spawnerCount); + if (++spawnerCount < 8) + events.ScheduleEvent(EVENT_IDOL_ROOM_SPAWNER, 35000); + break; + case EVENT_PROGRESS: + { + switch (eventProgress) + { + case 0: + Talk(SAY_EVENT_THREE_MIN_LEFT); + ++eventProgress; + events.ScheduleEvent(EVENT_PROGRESS, 60000); + break; + case 1: + Talk(SAY_EVENT_TWO_MIN_LEFT); + ++eventProgress; + events.ScheduleEvent(EVENT_PROGRESS, 60000); + break; + case 2: + Talk(SAY_EVENT_ONE_MIN_LEFT); + ++eventProgress; + events.ScheduleEvent(EVENT_PROGRESS, 60000); + break; + case 3: + events.CancelEvent(EVENT_IDOL_ROOM_SPAWNER); + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + Talk(SAY_EVENT_END); + events.ScheduleEvent(EVENT_COMPLETE, 3000); + break; + } + break; + } + case EVENT_COMPLETE: + { + DoCast(me, SPELL_IDOM_ROOM_CAMERA_SHAKE); + me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, 0, 0, 0.9238796f, 0.3826832f, 3600000); + std::list<WorldObject*> ClusterList; + Trinity::AllWorldObjectsInRange objects(me, 50.0f); + Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(me, ClusterList, objects); + me->VisitNearbyObject(50.0f, searcher); + for (std::list<WorldObject*>::const_iterator itr = ClusterList.begin(); itr != ClusterList.end(); ++itr) + { + if (Player* player = (*itr)->ToPlayer()) + { + if (player->GetQuestStatus(QUEST_EXTINGUISHING_THE_IDOL) == QUEST_STATUS_INCOMPLETE) + player->CompleteQuest(QUEST_EXTINGUISHING_THE_IDOL); + } + else if (GameObject* go = (*itr)->ToGameObject()) + { + if (go->GetEntry() == GO_IDOL_OVEN_FIRE || go->GetEntry() == GO_IDOL_CUP_FIRE || go->GetEntry() == GO_IDOL_MOUTH_FIRE) + go->Delete(); + } + } + instance->SetBossState(DATA_EXTINGUISHING_THE_IDOL, DONE); + me->DespawnOrUnsummon(); + break; + } + case EVENT_FIREBALL: + if (me->HasUnitState(UNIT_STATE_CASTING) || !UpdateVictim()) + return; + DoCastVictim(SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 8000); + break; + case EVENT_FROST_NOVA: + if (me->HasUnitState(UNIT_STATE_CASTING) || !UpdateVictim()) + return; + DoCast(me, SPELL_FROST_NOVA); + events.ScheduleEvent(EVENT_FROST_NOVA, 15000); + break; + } + } + if (!channeling) + DoMeleeAttackIfReady(); + } + + private: + InstanceScript* instance; + EventMap events; + bool eventInProgress; + bool channeling; + uint8 eventProgress; + uint8 spawnerCount; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_belnistraszAI(creature); } +}; + +class npc_idol_room_spawner : public CreatureScript +{ +public: + npc_idol_room_spawner() : CreatureScript("npc_idol_room_spawner") { } + + struct npc_idol_room_spawnerAI : public ScriptedAI + { + npc_idol_room_spawnerAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } + + void Reset() OVERRIDE { } + void SetData(uint32 /*type*/, uint32 data) OVERRIDE + { + if(!instance) + return; + + if (data < 7) + { + me->SummonCreature(NPC_WITHERED_BATTLE_BOAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + if (data > 0 && me->GetOrientation() < 4.0f) + me->SummonCreature(NPC_WITHERED_BATTLE_BOAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + me->SummonCreature(NPC_DEATHS_HEAD_GEOMANCER, me->GetPositionX() + (cos(me->GetOrientation() - (M_PI/2)) * 2), me->GetPositionY() + (sin(me->GetOrientation() - (M_PI/2)) * 2), me->GetPositionZ(), me->GetOrientation()); + me->SummonCreature(NPC_WITHERED_QUILGUARD, me->GetPositionX() + (cos(me->GetOrientation() + (M_PI/2)) * 2), me->GetPositionY() + (sin(me->GetOrientation() + (M_PI/2)) * 2), me->GetPositionZ(), me->GetOrientation()); + } + else if (data =7) + me->SummonCreature(NPC_PLAGUEMAW_THE_ROTTING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + } + + private: + InstanceScript* instance; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_idol_room_spawnerAI(creature); + } }; enum TombCreature { + EVENT_WEB = 7, + SPELL_POISON_PROC = 3616, + SPELL_VIRULENT_POISON_PROC = 12254, SPELL_WEB = 745 }; @@ -135,11 +380,6 @@ class npc_tomb_creature : public CreatureScript public: npc_tomb_creature() : CreatureScript("npc_tomb_creature") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_tomb_creatureAI(creature); - } - struct npc_tomb_creatureAI : public ScriptedAI { npc_tomb_creatureAI(Creature* creature) : ScriptedAI(creature) @@ -147,45 +387,86 @@ public: instance = creature->GetInstanceScript(); } - InstanceScript* instance; + void Reset() OVERRIDE + { + if (!me->HasAura(SPELL_POISON_PROC) && me->GetEntry() == NPC_TOMB_FIEND) + DoCast(me, SPELL_POISON_PROC); - uint32 uiWebTimer; + if (!me->HasAura(SPELL_VIRULENT_POISON_PROC) && me->GetEntry() == NPC_TOMB_REAVER) + DoCast(me, SPELL_VIRULENT_POISON_PROC); + } - void Reset() OVERRIDE + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (instance) + instance->SetData(DATA_WAVE, me->GetEntry()); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE { - uiWebTimer = urand(5000, 8000); + events.ScheduleEvent(EVENT_WEB, urand(5000, 8000)); } - void UpdateAI(uint32 uiDiff) OVERRIDE + void UpdateAI(uint32 diff) OVERRIDE { if (!UpdateVictim()) return; - //from acid - if (me->GetEntry() == NPC_TOMB_REAVER) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - if (uiWebTimer <= uiDiff) + switch (eventId) { - DoCastVictim(SPELL_WEB); - uiWebTimer = urand(7000, 16000); - } else uiWebTimer -= uiDiff; + case EVENT_WEB: + DoCastVictim(SPELL_WEB); + events.ScheduleEvent(EVENT_WEB, urand(7000, 16000)); + break; + } } - DoMeleeAttackIfReady(); } - void JustDied(Unit* /*killer*/) OVERRIDE + private: + InstanceScript* instance; + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_tomb_creatureAI(creature); + } +}; + +/*###### +## go_gong +######*/ + +class go_gong : public GameObjectScript +{ +public: + go_gong() : GameObjectScript("go_gong") { } + + bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE + { + InstanceScript* instance = go->GetInstanceScript(); + + if (instance) { - if (instance) - instance->SetData(DATA_GONG_WAVES, instance->GetData(DATA_GONG_WAVES)+1); + go->SendCustomAnim(0); + instance->SetData(DATA_WAVE, IN_PROGRESS); + return true; } - }; + return false; + } }; void AddSC_razorfen_downs() { new npc_henry_stern(); - new go_gong(); + new npc_belnistrasz(); + new npc_idol_room_spawner(); new npc_tomb_creature(); + new go_gong(); } diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h index c0f63474f23..9fe5314fda0 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h @@ -18,27 +18,56 @@ #ifndef DEF_RAZORFEN_DOWNS_H #define DEF_RAZORFEN_DOWNS_H -enum Data +#define RFDScriptName "instance_razorfen_downs" + +uint32 const EncounterCount = 5; + +enum DataTypes { - BOSS_TUTEN_KASH, - DATA_GONG_WAVES + // Main Bosses + DATA_TUTEN_KASH = 0, + DATA_MORDRESH_FIRE_EYE = 1, + DATA_GLUTTON = 2, + DATA_AMNENNAR_THE_COLD_BRINGER = 3, + // Events + DATA_GONG = 4, + DATA_WAVE = 5, + DATA_EXTINGUISHING_THE_IDOL = 6 }; -enum Data64 +enum CreatureIds { - DATA_GONG + // Used in Tuten Kash summon event + NPC_TOMB_FIEND = 7349, + NPC_TOMB_REAVER = 7351, + NPC_TUTEN_KASH = 7355, + // Used for quest 3525 "Extinguishing the Idol" + NPC_IDOL_ROOM_SPAWNER = 8611, + NPC_WITHERED_BATTLE_BOAR = 7333, + NPC_DEATHS_HEAD_GEOMANCER = 7335, + NPC_WITHERED_QUILGUARD = 7329, + NPC_PLAGUEMAW_THE_ROTTING = 7356 }; enum GameObjectIds { - GO_GONG = 148917 + // Used for Tuten Kash summon event + GO_GONG = 148917, + // Used for quest 3525 "Extinguishing the Idol" + GO_IDOL_OVEN_FIRE = 151951, + GO_IDOL_CUP_FIRE = 151952, + GO_IDOL_MOUTH_FIRE = 151973, + GO_BELNISTRASZS_BRAZIER = 152097 }; -enum CreatureId +template<class AI> +CreatureAI* GetRazorfenDownsAI(Creature* creature) { - NPC_TOMB_FIEND = 7349, - NPC_TOMB_REAVER = 7351, - NPC_TUTEN_KASH = 7355 -}; + if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(RFDScriptName)) + return new AI(creature); + return NULL; +} #endif |