diff options
author | Malcrom <malcromdev@gmail.com> | 2013-12-07 21:19:46 -0330 |
---|---|---|
committer | Malcrom <malcromdev@gmail.com> | 2013-12-07 21:19:46 -0330 |
commit | 89de7e74198e517dc7105f73af0f1d74c3629c64 (patch) | |
tree | 14b61130189a32c0bed9c2666dbfa157066026a8 | |
parent | 2b8fb0d8f65fcc0f1d969b9f125d79ece3a9d579 (diff) |
Scripting/Razorfen Downs: Additions and fixes for instance.
Moved bosses Glutton, Mordresh Fire Eye, Tuten Kash to cpp.
Cleaned up code for boss Amnennar The Coldbringer.
Fixed up gong event for gong to have sound and proper spawning.
Scripted quest 3525 "Extinguishing the Idol" so you can now fight Plagmaw the Rotting.
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 |