diff options
| author | Subv <s.v.h21@hotmail.com> | 2012-08-22 17:26:53 -0500 |
|---|---|---|
| committer | Subv <s.v.h21@hotmail.com> | 2012-08-22 17:26:53 -0500 |
| commit | dc95ce61b46ce2d542ee4c4dbdf35a9e854c4316 (patch) | |
| tree | e673101dc6554a76dfacb5cf3497dd1d2bde4f41 /src/server/scripts/Northrend | |
| parent | cecaab7948d5289439d1334d7bedcaae90e1fe3a (diff) | |
| parent | 85ed0e32a9b2b029c1db3cf1a914b3940cf72b9b (diff) | |
Merge branch 'master' of github.com:TrinityCore/TrinityCore into mmaps
Conflicts:
dep/PackageList.txt
src/server/game/Movement/MotionMaster.cpp
src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
src/server/game/Movement/MovementGenerators/PointMovementGenerator.h
src/server/game/Movement/Spline/MoveSplineInit.h
src/server/game/World/World.h
Diffstat (limited to 'src/server/scripts/Northrend')
156 files changed, 4514 insertions, 2282 deletions
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp index 8f34fa56525..89064a5d18c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp @@ -19,7 +19,8 @@ * Comment: Find correct mushrooms spell to make them visible - buffs of the mushrooms not ever applied to the users... */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ahnkahet.h" enum Spells diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp index ea757e86f4d..7f4da5666ff 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ahnkahet.h" //not in db diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index f1eaa0c87c5..e81d58b4ef3 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -19,7 +19,8 @@ * Comment: Missing AI for Twisted Visages */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ahnkahet.h" enum Spells diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index d6e50097765..7c167fb9c27 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -19,7 +19,8 @@ * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ahnkahet.h" enum Yells diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index 328d1ab1cd4..f8e2fc0f99f 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ahnkahet.h" enum Spells @@ -354,7 +355,7 @@ public: //! HACK: Creature's can't have MOVEMENTFLAG_FLYING me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); me->setFaction(16); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + me->SetObjectScale(1.0f); DoCast(me, SPELL_FLAME_SPHERE_VISUAL); DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp index 74643e58e30..f870c61dd5f 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "ahnkahet.h" /* Ahn'kahet encounters: diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index ca71d8c313e..dcf1338bc74 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "azjol_nerub.h" enum Spells diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp index 6587631f249..2690ea13ab1 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -28,7 +28,8 @@ * Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "azjol_nerub.h" enum Spells diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp index 4d83be53c93..1acc3b77a61 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp @@ -19,7 +19,8 @@ * Comment: Find in the future best timers and the event is not implemented. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "azjol_nerub.h" enum Spells diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp index 12622174e29..4e06ac0ba3a 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "azjol_nerub.h" #define MAX_ENCOUNTER 3 diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index 31aa924365d..dd8dd17c947 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -10,6 +10,7 @@ set(scripts_STAT_SRCS ${scripts_STAT_SRCS} + Northrend/wintergrasp.cpp Northrend/isle_of_conquest.cpp Northrend/storm_peaks.cpp Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -22,7 +23,7 @@ set(scripts_STAT_SRCS Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp Northrend/Ulduar/Ulduar/boss_thorim.cpp Northrend/Ulduar/Ulduar/boss_ignis.cpp - Northrend/Ulduar/Ulduar/boss_algalon.cpp + Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp Northrend/Ulduar/Ulduar/instance_ulduar.cpp Northrend/Ulduar/Ulduar/boss_auriaya.cpp Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp index b115a4ee827..a9d6d9d91ba 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp @@ -15,7 +15,12 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Cell.h" +#include "CellImpl.h" #include "obsidian_sanctum.h" enum eEnums diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp index 91d67697ebb..7d4438ed7c7 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "obsidian_sanctum.h" #define MAX_ENCOUNTER 1 diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp index b2cf755c7af..41eb31d815d 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "ruby_sanctum.h" diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp index 4e5e01cc745..c4008564029 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ruby_sanctum.h" enum Texts @@ -186,7 +187,7 @@ class ConflagrationTargetSelector public: ConflagrationTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return unit->GetTypeId() != TYPEID_PLAYER; } @@ -201,12 +202,12 @@ class spell_saviana_conflagration_init : public SpellScriptLoader { PrepareSpellScript(spell_saviana_conflagration_init_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if (ConflagrationTargetSelector()); + targets.remove_if(ConflagrationTargetSelector()); uint8 maxSize = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 3); - if (unitList.size() > maxSize) - Trinity::Containers::RandomResizeList(unitList, maxSize); + if (targets.size() > maxSize) + Trinity::Containers::RandomResizeList(targets, maxSize); } void HandleDummy(SpellEffIndex effIndex) @@ -218,7 +219,7 @@ class spell_saviana_conflagration_init : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_saviana_conflagration_init_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_saviana_conflagration_init_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_saviana_conflagration_init_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index f9e302d7634..5678bbbeb83 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "ruby_sanctum.h" diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp index 19ae66b6a60..273c860a2ad 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ruby_sanctum.h" enum Texts diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp index 305266ee628..d77c84b2978 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp @@ -22,7 +22,9 @@ SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more SDCategory: Trial of the Champion EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "trial_of_the_champion.h" #include "ScriptedEscortAI.h" @@ -60,9 +62,9 @@ class OrientationCheck : public std::unary_function<Unit*, bool> { public: explicit OrientationCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator()(WorldObject* object) { - return !unit->isInFront(caster, 2.5f) || !unit->IsWithinDist(caster, 40.0f); + return !object->isInFront(caster, 2.5f) || !object->IsWithinDist(caster, 40.0f); } private: @@ -76,15 +78,16 @@ class spell_eadric_radiance : public SpellScriptLoader class spell_eadric_radiance_SpellScript : public SpellScript { PrepareSpellScript(spell_eadric_radiance_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (OrientationCheck(GetCaster())); + unitList.remove_if(OrientationCheck(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -216,8 +219,6 @@ public: } InstanceScript* instance; - - Creature* pMemory; uint64 MemoryGUID; bool bHealth; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp index 9768b50b214..c56d44ceb08 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp @@ -22,7 +22,8 @@ SDComment: missing yells. not sure about timers. SDCategory: Trial of the Champion EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "trial_of_the_champion.h" diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp index 18c972b966c..f3b6078d536 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -23,7 +23,8 @@ SDComment: Is missing the ai to make the npcs look for a new mount and use it. SDCategory: Trial Of the Champion EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ScriptedEscortAI.h" #include "Vehicle.h" #include "trial_of_the_champion.h" diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp index 9ccd136731a..310dd1003c3 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp @@ -21,7 +21,9 @@ SDComment: SDCategory: Trial Of the Champion EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "trial_of_the_champion.h" #define MAX_ENCOUNTER 4 diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp index c8236ace88c..a2488513d63 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp @@ -26,7 +26,9 @@ EndScriptData */ npc_announcer_toc5 EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "trial_of_the_champion.h" #include "Vehicle.h" diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index c718c0cee5f..89fdcc7f725 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -31,20 +31,23 @@ EndScriptData */ // Scarab - Kill credit isn't crediting? // FrostSph - often they are casting Permafrost a little above the ground -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "trial_of_the_crusader.h" enum Yells { - SAY_INTRO = -1649055, - SAY_AGGRO = -1649056, - SAY_KILL1 = -1649057, - SAY_KILL2 = -1649058, - SAY_DEATH = -1649059, - EMOTE_SPIKE = -1649060, - SAY_BURROWER = -1649061, - EMOTE_LEECHING_SWARM = -1649062, - SAY_LEECHING_SWARM = -1649063, + SAY_INTRO = 0, + SAY_AGGRO = 1, + EMOTE_SUBMERGE = 2, + EMOTE_BURROWER = 3, + SAY_EMERGE = 4, + SAY_LEECHING_SWARM = 5, + EMOTE_LEECHING_SWARM = 6, + SAY_KILL_PLAYER = 7, + SAY_DEATH = 8, + + EMOTE_SPIKE = 0, }; enum Summons @@ -104,7 +107,7 @@ enum BossSpells SPELL_SPIKE_TELE = 66170, }; -#define SPELL_PERMAFROST_HELPER RAID_MODE<uint32>(66193, 67856, 67855, 67857) +#define SPELL_PERMAFROST_HELPER RAID_MODE<uint32>(66193, 67855, 67856, 67857) enum SummonActions { @@ -194,7 +197,7 @@ public: { if (who->GetTypeId() == TYPEID_PLAYER) { - DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, me); + Talk(SAY_KILL_PLAYER); if (instance) instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); } @@ -204,7 +207,7 @@ public: { if (!m_bIntro) { - DoScriptText(SAY_INTRO, me); + Talk(SAY_INTRO); m_bIntro = false; } } @@ -222,7 +225,7 @@ public: void JustDied(Unit* /*killer*/) { Summons.DespawnAll(); - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); if (instance) instance->SetData(TYPE_ANUBARAK, DONE); } @@ -239,7 +242,7 @@ public: break; case NPC_SPIKE: summoned->CombatStart(target); - DoScriptText(EMOTE_SPIKE, me, target); + Talk(EMOTE_SPIKE, target->GetGUID()); break; } Summons.Summon(summoned); @@ -257,7 +260,7 @@ public: void EnterCombat(Unit* /*who*/) { - DoScriptText(SAY_AGGRO, me); + Talk(SAY_AGGRO); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->SetInCombatWithZone(); if (instance) @@ -320,7 +323,7 @@ public: DoCast(me, SPELL_SUBMERGE_ANUBARAK); DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SAY_BURROWER, me); + Talk(EMOTE_BURROWER); m_uiScarabSummoned = 0; m_uiSummonScarabTimer = 4*IN_MILLISECONDS; m_uiStage = 2; @@ -402,8 +405,8 @@ public: { m_bReachedPhase3 = true; DoCastAOE(SPELL_LEECHING_SWARM); - DoScriptText(EMOTE_LEECHING_SWARM, me); - DoScriptText(SAY_LEECHING_SWARM, me); + Talk(EMOTE_LEECHING_SWARM); + Talk(SAY_LEECHING_SWARM); } if (m_uiBerserkTimer <= uiDiff && !me->HasAura(SPELL_BERSERK)) @@ -615,7 +618,7 @@ class mob_frost_sphere : public CreatureScript me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); DoCast(SPELL_PERMAFROST_VISUAL); DoCast(SPELL_PERMAFROST); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + me->SetObjectScale(2.0f); break; } } @@ -659,10 +662,16 @@ public: m_uiTargetGUID = 0; } + bool CanAIAttack(Unit const* victim) const + { + return victim->GetTypeId() == TYPEID_PLAYER; + } + void EnterCombat(Unit* who) { m_uiTargetGUID = who->GetGUID(); DoCast(who, SPELL_MARK); + Talk(EMOTE_SPIKE, who->GetGUID()); me->SetSpeed(MOVE_RUN, 0.5f); m_uiSpeed = 0; m_uiIncreaseSpeedTimer = 1*IN_MILLISECONDS; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 79bbb470edf..c662daf3671 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -27,13 +27,15 @@ EndScriptData */ // All - untested // Pets aren't being summoned by their masters -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "trial_of_the_crusader.h" -enum eYell +enum Yells { - SAY_GARROSH_KILL_ALLIANCE_PLAYER4 = -1649118, - SAY_VARIAN_KILL_HORDE_PLAYER4 = -1649123, + SAY_KILL_PLAYER = 6, }; enum eAIs @@ -356,11 +358,12 @@ struct boss_faction_championsAI : public ScriptedAI if (TeamInInstance == ALLIANCE) { if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_VARIAN))) - DoScriptText(SAY_VARIAN_KILL_HORDE_PLAYER4+urand(0, 3), temp); // + cause we are on negative + temp->AI()->Talk(SAY_KILL_PLAYER); } else - if (Creature* temp = me->FindNearestCreature(NPC_GARROSH, 300.f)) - DoScriptText(SAY_GARROSH_KILL_ALLIANCE_PLAYER4+urand(0, 3), temp); // + cause we are on negative + if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_GARROSH))) + temp->AI()->Talk(SAY_KILL_PLAYER); + instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); } @@ -945,18 +948,18 @@ public: }; -enum eWarlockSpells +enum WarlockSpells { - SPELL_HELLFIRE = 65816, - SPELL_CORRUPTION = 65810, - SPELL_CURSE_OF_AGONY = 65814, - SPELL_CURSE_OF_EXHAUSTION = 65815, - SPELL_FEAR = 65809, //8s - SPELL_SEARING_PAIN = 65819, - SPELL_SHADOW_BOLT = 65821, - SPELL_UNSTABLE_AFFLICTION = 65812, - SPELL_SUMMON_FELHUNTER = 67514, - H_SPELL_UNSTABLE_AFFLICTION = 68155, //15s + SPELL_HELLFIRE = 65816, + SPELL_CORRUPTION = 65810, + SPELL_CURSE_OF_AGONY = 65814, + SPELL_CURSE_OF_EXHAUSTION = 65815, + SPELL_FEAR = 65809, // 8s + SPELL_SEARING_PAIN = 65819, + SPELL_SHADOW_BOLT = 65821, + SPELL_UNSTABLE_AFFLICTION = 65812, // 15s + SPELL_UNSTABLE_AFFLICTION_DISPEL = 65813, + SPELL_SUMMON_FELHUNTER = 67514, }; class mob_toc_warlock : public CreatureScript @@ -2030,6 +2033,40 @@ public: }; }; +class spell_faction_champion_warl_unstable_affliction : public SpellScriptLoader +{ + public: + spell_faction_champion_warl_unstable_affliction() : SpellScriptLoader("spell_faction_champion_warl_unstable_affliction") { } + + class spell_faction_champion_warl_unstable_affliction_AuraScript : public AuraScript + { + PrepareAuraScript(spell_faction_champion_warl_unstable_affliction_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_UNSTABLE_AFFLICTION_DISPEL)) + return false; + return true; + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(dispelInfo->GetDispeller(), SPELL_UNSTABLE_AFFLICTION_DISPEL, true, NULL, GetEffect(EFFECT_0)); + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_faction_champion_warl_unstable_affliction_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_faction_champion_warl_unstable_affliction_AuraScript(); + } +}; + void AddSC_boss_faction_champions() { new boss_toc_champion_controller(); @@ -2049,4 +2086,5 @@ void AddSC_boss_faction_champions() new mob_toc_retro_paladin(); new mob_toc_pet_warlock(); new mob_toc_pet_hunter(); + new spell_faction_champion_warl_unstable_affliction(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 6f817a6d0eb..10f7150351e 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -30,21 +30,24 @@ EndScriptData */ // Redone summon's scripts in SAI // Add immunities to the boss and summons -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "trial_of_the_crusader.h" enum Yells { - SAY_INTRO = -1649030, - SAY_AGGRO = -1649031, - SAY_DEATH = -1649032, - EMOTE_INCINERATE = -1649033, - SAY_INCINERATE = -1649034, - EMOTE_LEGION_FLAME = -1649035, - EMOTE_NETHER_PORTAL = -1649036, - SAY_NETHER_PORTAL = -1649037, - EMOTE_INFERNAL_ERUPTION = -1649038, - SAY_INFERNAL_ERUPTION = -1649039, + SAY_INTRO = 0, + SAY_AGGRO = 1, + EMOTE_LEGION_FLAME = 2, + EMOTE_NETHER_PORTAL = 3, + SAY_MISTRESS_OF_PAIN = 4, + EMOTE_INCINERATE = 5, + SAY_INCINERATE = 6, + EMOTE_INFERNAL_ERUPTION = 7, + SAY_INFERNAL_ERUPTION = 8, + SAY_KILL_PLAYER = 9, + SAY_DEATH = 10, + SAY_BERSERK = 11, }; enum Equipment @@ -158,7 +161,7 @@ public: void JustDied(Unit* /*killer*/) { Summons.DespawnAll(); - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); if (instance) instance->SetData(TYPE_JARAXXUS, DONE); } @@ -173,7 +176,7 @@ public: me->SetInCombatWithZone(); if (instance) instance->SetData(TYPE_JARAXXUS, IN_PROGRESS); - DoScriptText(SAY_AGGRO, me); + Talk(SAY_AGGRO); } void UpdateAI(const uint32 uiDiff) @@ -183,16 +186,16 @@ public: if (m_uiSummonInfernalEruptionTimer <= uiDiff) { - DoScriptText(EMOTE_INFERNAL_ERUPTION, me); - DoScriptText(SAY_INFERNAL_ERUPTION, me); + Talk(EMOTE_INFERNAL_ERUPTION); + Talk(SAY_INFERNAL_ERUPTION); DoCast(SPELL_INFERNAL_ERUPTION); m_uiSummonInfernalEruptionTimer = 2*MINUTE*IN_MILLISECONDS; } else m_uiSummonInfernalEruptionTimer -= uiDiff; if (m_uiSummonNetherPortalTimer <= uiDiff) { - DoScriptText(EMOTE_NETHER_PORTAL, me); - DoScriptText(SAY_NETHER_PORTAL, me); + Talk(EMOTE_NETHER_PORTAL); + Talk(SAY_MISTRESS_OF_PAIN); DoCast(SPELL_NETHER_PORTAL); m_uiSummonNetherPortalTimer = 2*MINUTE*IN_MILLISECONDS; } else m_uiSummonNetherPortalTimer -= uiDiff; @@ -214,8 +217,8 @@ public: { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true)) { - DoScriptText(EMOTE_INCINERATE, me, target); - DoScriptText(SAY_INCINERATE, me); + Talk(EMOTE_INCINERATE, target->GetGUID()); + Talk(SAY_INCINERATE); DoCast(target, SPELL_INCINERATE_FLESH); } m_uiIncinerateFleshTimer = urand(20*IN_MILLISECONDS, 25*IN_MILLISECONDS); @@ -231,7 +234,7 @@ public: { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true)) { - DoScriptText(EMOTE_LEGION_FLAME, me, target); + Talk(EMOTE_LEGION_FLAME, target->GetGUID()); DoCast(target, SPELL_LEGION_FLAME); } m_uiLegionFlameTimer = 30*IN_MILLISECONDS; @@ -515,36 +518,6 @@ public: }; -class spell_spinning_pain_spike : public SpellScriptLoader -{ - public: - spell_spinning_pain_spike() : SpellScriptLoader("spell_spinning_pain_spike") {} - - class spell_spinning_pain_spike_SpellScript : public SpellScript - { - PrepareSpellScript(spell_spinning_pain_spike_SpellScript); - - void HandleScript(SpellEffIndex /*eff*/) - { - Unit* target = GetHitUnit(); - if (!target) - return; - - if (target->isAlive()) - SetHitDamage(target->CountPctFromMaxHealth(50)); - } - void Register() - { - OnEffectHitTarget += SpellEffectFn(spell_spinning_pain_spike_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_spinning_pain_spike_SpellScript(); - } -}; - void AddSC_boss_jaraxxus() { new boss_jaraxxus(); @@ -553,5 +526,4 @@ void AddSC_boss_jaraxxus() new mob_fel_infernal(); new mob_nether_portal(); new mob_mistress_of_pain(); - new spell_spinning_pain_spike(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 5bda32941c2..506467be8a5 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -29,21 +29,22 @@ EndScriptData */ // Snakes - miss the 1-hitkill from emerging // - visual changes between mobile and stationary models seems not to work sometimes -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "trial_of_the_crusader.h" enum Yells { - //Gormok - SAY_SNOBOLLED = -1649000, - //Acidmaw & Dreadscale - SAY_SUBMERGE = -1649010, - SAY_EMERGE = -1649011, - SAY_BERSERK = -1649012, - //Icehowl - SAY_TRAMPLE_STARE = -1649020, - SAY_TRAMPLE_FAIL = -1649021, - SAY_TRAMPLE_START = -1649022, + // Gormok + EMOTE_SNOBOLLED = 0, + + // Acidmaw & Dreadscale + EMOTE_ENRAGE = 0, + + // Icehowl + EMOTE_TRAMPLE_START = 0, + EMOTE_TRAMPLE_CRASH = 1, + EMOTE_TRAMPLE_FAIL = 2, }; enum Equipment @@ -238,7 +239,7 @@ public: if (m_uiSummonCount > 0) { me->SummonCreature(NPC_SNOBOLD_VASSAL, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN); - DoScriptText(SAY_SNOBOLLED, me); + Talk(EMOTE_SNOBOLLED); } m_uiSummonTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); } else m_uiSummonTimer -= diff; @@ -459,12 +460,11 @@ struct boss_jormungarAI : public ScriptedAI if (instanceScript && instanceScript->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !enraged) { - DoScriptText(SAY_EMERGE, me); me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); DoCast(SPELL_ENRAGE); enraged = true; - DoScriptText(SAY_BERSERK, me); + Talk(EMOTE_ENRAGE); switch (stage) { case 0: @@ -511,7 +511,6 @@ struct boss_jormungarAI : public ScriptedAI case 1: // Submerge me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_SUBMERGE_0); - DoScriptText(SAY_SUBMERGE, me); me->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX()+ frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionY() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionZ()); stage = 2; case 2: // Wait til emerge @@ -523,7 +522,6 @@ struct boss_jormungarAI : public ScriptedAI break; case 3: // Emerge me->SetDisplayId(modelStationary); - DoScriptText(SAY_EMERGE, me); me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); DoCast(me, SPELL_EMERGE_0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); @@ -557,7 +555,6 @@ struct boss_jormungarAI : public ScriptedAI case 5: // Submerge me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_SUBMERGE_0); - DoScriptText(SAY_SUBMERGE, me); me->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionY() + frand(-40.0f, 40.0f), ToCCommonLoc[1].GetPositionZ()); stage = 6; case 6: // Wait til emerge @@ -569,7 +566,6 @@ struct boss_jormungarAI : public ScriptedAI break; case 7: // Emerge me->SetDisplayId(modelMobile); - DoScriptText(SAY_EMERGE, me); me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); DoCast(me, SPELL_EMERGE_0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); @@ -909,6 +905,8 @@ public: if (m_uiMassiveCrashTimer <= diff) { me->GetMotionMaster()->MoveJump(ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 10.0f, 20.0f); // 1: Middle of the room + SetCombatMovement(false); + me->AttackStop(); m_uiStage = 7; //Invalid (Do nothing more than move) m_uiMassiveCrashTimer = 30*IN_MILLISECONDS; } else m_uiMassiveCrashTimer -= diff; @@ -917,23 +915,28 @@ public: break; case 1: DoCastAOE(SPELL_MASSIVE_CRASH); + me->StopMoving(); + me->AttackStop(); m_uiStage = 2; break; case 2: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) { + me->StopMoving(); + me->AttackStop(); m_uiTrampleTargetGUID = target->GetGUID(); me->SetTarget(m_uiTrampleTargetGUID); - DoScriptText(SAY_TRAMPLE_STARE, me, target); m_bTrampleCasted = false; - SetCombatMovement(false); - me->GetMotionMaster()->MoveIdle(); + //SetCombatMovement(false); + //me->GetMotionMaster()->MoveIdle(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_uiTrampleTimer = 4*IN_MILLISECONDS; m_uiStage = 3; } else m_uiStage = 6; break; case 3: + me->StopMoving(); + me->AttackStop(); if (m_uiTrampleTimer <= diff) { if (Unit* target = Unit::GetPlayer(*me, m_uiTrampleTargetGUID)) @@ -946,13 +949,15 @@ public: me->GetMotionMaster()->MoveJump(2*me->GetPositionX()-m_fTrampleTargetX, 2*me->GetPositionY()-m_fTrampleTargetY, me->GetPositionZ(), - 10.0f, 20.0f); // 2: Hop Backwards + 20.0f, 30.0f); // 2: Hop Backwards m_uiStage = 7; //Invalid (Do nothing more than move) } else m_uiStage = 6; } else m_uiTrampleTimer -= diff; break; case 4: - DoScriptText(SAY_TRAMPLE_START, me); + me->StopMoving(); + me->AttackStop(); + Talk(EMOTE_TRAMPLE_START, m_uiTrampleTargetGUID); me->GetMotionMaster()->MoveCharge(m_fTrampleTargetX, m_fTrampleTargetY, m_fTrampleTargetZ+2, 42, 1); me->SetTarget(0); m_uiStage = 5; @@ -984,7 +989,12 @@ public: if (!m_bTrampleCasted) { DoCast(me, SPELL_STAGGERED_DAZE); - DoScriptText(SAY_TRAMPLE_FAIL, me); + Talk(EMOTE_TRAMPLE_CRASH); + } + else + { + DoCast(me, SPELL_FROTHING_RAGE, true); + Talk(EMOTE_TRAMPLE_FAIL); } m_bMovementStarted = false; me->GetMotionMaster()->MovementExpired(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index 74b9c038482..a65eaebbc0c 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -27,22 +27,28 @@ EndScriptData */ // - They should be floating but they aren't respecting the floor =( // - Hardcoded bullets spawner -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Cell.h" +#include "CellImpl.h" #include "trial_of_the_crusader.h" enum Yells { - SAY_AGGRO = -1649040, - SAY_DEATH = -1649041, - SAY_BERSERK = -1649042, - EMOTE_SHIELD = -1649043, - SAY_SHIELD = -1649044, - SAY_KILL1 = -1649045, - SAY_KILL2 = -1649046, - EMOTE_LIGHT_VORTEX = -1649047, - SAY_LIGHT_VORTEX = -1649048, - EMOTE_DARK_VORTEX = -1649049, - SAY_DARK_VORTEX = -1649050, + SAY_AGGRO = 0, + SAY_NIGHT = 1, + SAY_LIGHT = 2, + EMOTE_VORTEX = 3, + EMOTE_TWINK_PACT = 4, + SAY_TWINK_PACT = 5, + SAY_KILL_PLAYER = 6, + SAY_BERSERK = 7, + SAY_DEATH = 8, }; enum Equipment @@ -159,7 +165,6 @@ struct boss_twin_baseAI : public ScriptedAI uint32 m_uiTouchTimer; uint32 m_uiBerserkTimer; - int32 m_uiVortexSay; int32 m_uiVortexEmote; uint32 m_uiSisterNpcId; uint32 m_uiMyEmphatySpellId; @@ -171,7 +176,8 @@ struct boss_twin_baseAI : public ScriptedAI uint32 m_uiSpikeSpellId; uint32 m_uiTouchSpellId; - void Reset() { + void Reset() + { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); me->SetReactState(REACT_PASSIVE); me->ModifyAuraState(m_uiAuraState, true); @@ -216,7 +222,7 @@ struct boss_twin_baseAI : public ScriptedAI { if (who->GetTypeId() == TYPEID_PLAYER) { - DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, me); + Talk(SAY_KILL_PLAYER); if (instance) instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELEGIBLE, 0); } @@ -248,7 +254,7 @@ struct boss_twin_baseAI : public ScriptedAI void JustDied(Unit* /*killer*/) { - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); if (instance) { if (Creature* pSister = GetSister()) @@ -290,7 +296,7 @@ struct boss_twin_baseAI : public ScriptedAI instance->SetData(TYPE_VALKIRIES, IN_PROGRESS); } - DoScriptText(SAY_AGGRO, me); + Talk(SAY_AGGRO); DoCast(me, m_uiSurgeSpellId); } @@ -328,8 +334,7 @@ struct boss_twin_baseAI : public ScriptedAI { if (Creature* pSister = GetSister()) pSister->AI()->DoAction(ACTION_VORTEX); - DoScriptText(m_uiVortexEmote, me); - DoScriptText(m_uiVortexSay, me); + Talk(m_uiVortexEmote); DoCastAOE(m_uiVortexSpellId); m_uiStage = 0; m_uiSpecialAbilityTimer = MINUTE*IN_MILLISECONDS; @@ -340,8 +345,8 @@ struct boss_twin_baseAI : public ScriptedAI case 2: // Shield+Pact if (m_uiSpecialAbilityTimer <= uiDiff) { - DoScriptText(EMOTE_SHIELD, me); - DoScriptText(SAY_SHIELD, me); + Talk(EMOTE_TWINK_PACT); + Talk(SAY_TWINK_PACT); if (Creature* pSister = GetSister()) { pSister->AI()->DoAction(ACTION_PACT); @@ -379,7 +384,7 @@ struct boss_twin_baseAI : public ScriptedAI if (!m_bIsBerserk && m_uiBerserkTimer <= uiDiff) { DoCast(me, SPELL_BERSERK); - DoScriptText(SAY_BERSERK, me); + Talk(SAY_BERSERK); m_bIsBerserk = true; } else @@ -418,8 +423,7 @@ public: m_uiStage = 0; m_uiWeapon = EQUIP_MAIN_1; m_uiAuraState = AURA_STATE_UNKNOWN22; - m_uiVortexEmote = EMOTE_LIGHT_VORTEX; - m_uiVortexSay = SAY_LIGHT_VORTEX; + m_uiVortexEmote = EMOTE_VORTEX; m_uiSisterNpcId = NPC_DARKBANE; m_uiMyEmphatySpellId = SPELL_TWIN_EMPATHY_DARK; m_uiOtherEssenceSpellId = SPELL_DARK_ESSENCE_HELPER; @@ -488,8 +492,7 @@ public: m_uiStage = 1; m_uiWeapon = EQUIP_MAIN_2; m_uiAuraState = AURA_STATE_UNKNOWN19; - m_uiVortexEmote = EMOTE_DARK_VORTEX; - m_uiVortexSay = SAY_DARK_VORTEX; + m_uiVortexEmote = EMOTE_VORTEX; m_uiSisterNpcId = NPC_LIGHTBANE; m_uiMyEmphatySpellId = SPELL_TWIN_EMPATHY_LIGHT; m_uiOtherEssenceSpellId = SPELL_LIGHT_ESSENCE_HELPER; @@ -759,7 +762,7 @@ class spell_powering_up : public SpellScriptLoader uint32 spellId; - bool Validate(SpellEntry const* /*spellEntry*/) + bool Load() { spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_SURGE_OF_SPEED, GetCaster()); if (!sSpellMgr->GetSpellInfo(spellId)) @@ -769,7 +772,7 @@ class spell_powering_up : public SpellScriptLoader void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - if (Unit* target = GetTargetUnit()) + if (Unit* target = GetExplTargetUnit()) if (urand(0, 99) < 15) target->CastSpell(target, spellId, true); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index 1966e26b128..9767126371b 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -23,7 +23,8 @@ SDComment: by /dev/rsa SDCategory: Trial of the Crusader EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "trial_of_the_crusader.h" class instance_trial_of_the_crusader : public InstanceMapScript @@ -46,6 +47,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript uint64 BarrentGUID; uint64 TirionGUID; + uint64 TirionFordringGUID; uint64 FizzlebangGUID; uint64 GarroshGUID; uint64 VarianGUID; @@ -84,6 +86,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript TrialCounter = 50; EventStage = 0; + TirionFordringGUID = 0; + TributeChestGUID = 0; MainGateDoorGUID = 0; @@ -146,6 +150,9 @@ class instance_trial_of_the_crusader : public InstanceMapScript case NPC_TIRION: TirionGUID = creature->GetGUID(); break; + case NPC_TIRION_FORDRING: + TirionFordringGUID = creature->GetGUID(); + break; case NPC_FIZZLEBANG: FizzlebangGUID = creature->GetGUID(); break; @@ -237,10 +244,18 @@ class instance_trial_of_the_crusader : public InstanceMapScript switch (type) { case TYPE_JARAXXUS: + // Cleanup Icehowl + if (Creature* icehowl = instance->GetCreature(IcehowlGUID)) + icehowl->DespawnOrUnsummon(); if (data == DONE) EventStage = 2000; break; case TYPE_CRUSADERS: + // Cleanup Jaraxxus + if (Creature* jaraxxus = instance->GetCreature(JaraxxusGUID)) + jaraxxus->DespawnOrUnsummon(); + if (Creature* fizzlebang = instance->GetCreature(FizzlebangGUID)) + fizzlebang->DespawnOrUnsummon(); switch (data) { case IN_PROGRESS: @@ -260,6 +275,9 @@ class instance_trial_of_the_crusader : public InstanceMapScript } break; case TYPE_VALKIRIES: + // Cleanup chest + if (GameObject* cache = instance->GetGameObject(CrusadersCacheGUID)) + cache->Delete(); switch (data) { case FAIL: @@ -393,7 +411,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript if (type < MAX_ENCOUNTERS) { - sLog->outDetail("[ToCr] EncounterStatus[type %u] %u = data %u;", type, EncounterStatus[type], data); + sLog->outInfo(LOG_FILTER_TSCR, "[ToCr] EncounterStatus[type %u] %u = data %u;", type, EncounterStatus[type], data); if (data == FAIL) { --TrialCounter; @@ -421,6 +439,8 @@ class instance_trial_of_the_crusader : public InstanceMapScript return BarrentGUID; case NPC_TIRION: return TirionGUID; + case NPC_TIRION_FORDRING: + return TirionFordringGUID; case NPC_FIZZLEBANG: return FizzlebangGUID; case NPC_GARROSH: diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index 1d4961eb8b4..37d08484f0b 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -27,50 +27,65 @@ EndScriptData */ // - Need better implementation of Gossip and correct gossip text and option // - Misses Dalaran Teleport at the end. -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "trial_of_the_crusader.h" enum eYells { - SAY_STAGE_0_01 = -1649070, - SAY_STAGE_0_02 = -1649071, - SAY_STAGE_0_03a = -1649072, - SAY_STAGE_0_03h = -1649073, - SAY_STAGE_0_04 = -1649074, - SAY_STAGE_0_05 = -1649075, - SAY_STAGE_0_06 = -1649076, - SAY_STAGE_0_WIPE = -1649077, - SAY_STAGE_1_01 = -1649080, - SAY_STAGE_1_02 = -1649081, - SAY_STAGE_1_03 = -1649082, - SAY_STAGE_1_04 = -1649083, - SAY_STAGE_1_05 = -1649030, //INTRO Jaraxxus - SAY_STAGE_1_06 = -1649084, - SAY_STAGE_1_07 = -1649086, - SAY_STAGE_1_08 = -1649087, - SAY_STAGE_1_09 = -1649088, - SAY_STAGE_1_10 = -1649089, - SAY_STAGE_1_11 = -1649090, - SAY_STAGE_2_01 = -1649091, - SAY_STAGE_2_02a = -1649092, - SAY_STAGE_2_02h = -1649093, - SAY_STAGE_2_03 = -1649094, - SAY_STAGE_2_04a = -1649095, - SAY_STAGE_2_04h = -1649096, - SAY_STAGE_2_05a = -1649097, - SAY_STAGE_2_05h = -1649098, - SAY_STAGE_2_06 = -1649099, - SAY_STAGE_3_01 = -1649100, - SAY_STAGE_3_02 = -1649101, - SAY_STAGE_3_03a = -1649102, - SAY_STAGE_3_03h = -1649103, - SAY_STAGE_4_01 = -1649104, - SAY_STAGE_4_02 = -1649105, - SAY_STAGE_4_03 = -1649106, - SAY_STAGE_4_04 = -1649107, - SAY_STAGE_4_05 = -1649108, - SAY_STAGE_4_06 = -1649109, - SAY_STAGE_4_07 = -1649110, + // Highlord Tirion Fordring - 34996 + SAY_STAGE_0_01 = 0, + SAY_STAGE_0_02 = 1, + SAY_STAGE_0_04 = 2, + SAY_STAGE_0_05 = 3, + SAY_STAGE_0_06 = 4, + SAY_STAGE_0_WIPE = 5, + SAY_STAGE_1_01 = 6, + SAY_STAGE_1_07 = 7, + SAY_STAGE_1_08 = 8, + SAY_STAGE_1_11 = 9, + SAY_STAGE_2_01 = 10, + SAY_STAGE_2_03 = 11, + SAY_STAGE_2_06 = 12, + SAY_STAGE_3_01 = 13, + SAY_STAGE_3_02 = 14, + SAY_STAGE_4_01 = 15, + SAY_STAGE_4_03 = 16, + + // Varian Wrynn + SAY_STAGE_0_03a = 0, + SAY_STAGE_1_10 = 1, + SAY_STAGE_2_02a = 2, + SAY_STAGE_2_04a = 3, + SAY_STAGE_2_05a = 4, + SAY_STAGE_3_03a = 5, + + // Garrosh + SAY_STAGE_0_03h = 0, + SAY_STAGE_1_09 = 1, + SAY_STAGE_2_02h = 2, + SAY_STAGE_2_04h = 3, + SAY_STAGE_2_05h = 4, + SAY_STAGE_3_03h = 5, + + // Wilfred Fizzlebang + SAY_STAGE_1_02 = 0, + SAY_STAGE_1_03 = 1, + SAY_STAGE_1_04 = 2, + SAY_STAGE_1_06 = 3, + + // Lord Jaraxxus + SAY_STAGE_1_05 = 0, + + // The Lich King + SAY_STAGE_4_02 = 0, + SAY_STAGE_4_05 = 1, + SAY_STAGE_4_04 = 2, + + // Highlord Tirion Fordring - 36095 + SAY_STAGE_4_06 = 0, + SAY_STAGE_4_07 = 1, }; struct _Messages @@ -287,13 +302,13 @@ class boss_lich_king_toc : public CreatureScript switch (instance->GetData(TYPE_EVENT)) { case 5010: - DoScriptText(SAY_STAGE_4_02, me); + Talk(SAY_STAGE_4_02); m_uiUpdateTimer = 3000; me->GetMotionMaster()->MovePoint(0, LichKingLoc[0]); instance->SetData(TYPE_EVENT, 5020); break; case 5030: - DoScriptText(SAY_STAGE_4_04, me); + Talk(SAY_STAGE_4_04); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); m_uiUpdateTimer = 10000; instance->SetData(TYPE_EVENT, 5040); @@ -310,7 +325,7 @@ class boss_lich_king_toc : public CreatureScript instance->SetData(TYPE_EVENT, 5060); break; case 5060: - DoScriptText(SAY_STAGE_4_05, me); + Talk(SAY_STAGE_4_05); me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); m_uiUpdateTimer = 2500; instance->SetData(TYPE_EVENT, 5070); @@ -369,7 +384,7 @@ class npc_fizzlebang_toc : public CreatureScript void JustDied(Unit* killer) { - DoScriptText(SAY_STAGE_1_06, me, killer); + Talk(SAY_STAGE_1_06, killer->GetGUID()); instance->SetData(TYPE_EVENT, 1180); if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_JARAXXUS))) { @@ -428,18 +443,18 @@ class npc_fizzlebang_toc : public CreatureScript m_uiUpdateTimer = 4000; break; case 1120: - DoScriptText(SAY_STAGE_1_02, me); + Talk(SAY_STAGE_1_02); instance->SetData(TYPE_EVENT, 1130); m_uiUpdateTimer = 12000; break; case 1130: me->GetMotionMaster()->MovementExpired(); - DoScriptText(SAY_STAGE_1_03, me); + Talk(SAY_STAGE_1_03); me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST_OMNI); if (Unit* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN)) { m_uiTriggerGUID = pTrigger->GetGUID(); - pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pTrigger->SetObjectScale(2.0f); pTrigger->SetDisplayId(22862); pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false); } @@ -456,7 +471,7 @@ class npc_fizzlebang_toc : public CreatureScript if (Creature* pPortal = me->SummonCreature(NPC_WILFRED_PORTAL, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.71239f, TEMPSUMMON_MANUAL_DESPAWN)) { pPortal->SetReactState(REACT_PASSIVE); - pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pPortal->SetObjectScale(2.0f); pPortal->CastSpell(pPortal, SPELL_WILFRED_PORTAL, false); m_uiPortalGUID = pPortal->GetGUID(); } @@ -468,7 +483,7 @@ class npc_fizzlebang_toc : public CreatureScript m_uiUpdateTimer = 3000; break; case 1140: - DoScriptText(SAY_STAGE_1_04, me); + Talk(SAY_STAGE_1_04); if (Creature* temp = me->SummonCreature(NPC_JARAXXUS, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 5.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -490,7 +505,7 @@ class npc_fizzlebang_toc : public CreatureScript break; case 1144: if (Creature* temp = Unit::GetCreature(*me, instance->GetData64(NPC_JARAXXUS))) - DoScriptText(SAY_STAGE_1_05, temp); + temp->AI()->Talk(SAY_STAGE_1_05); instance->SetData(TYPE_EVENT, 1150); m_uiUpdateTimer = 5000; break; @@ -553,13 +568,13 @@ class npc_tirion_toc : public CreatureScript { case 110: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(SAY_STAGE_0_01, me); + Talk(SAY_STAGE_0_01); m_uiUpdateTimer = 22000; instance->SetData(TYPE_EVENT, 120); break; case 140: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(SAY_STAGE_0_02, me); + Talk(SAY_STAGE_0_02); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 150); break; @@ -585,7 +600,7 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 160); break; case 200: - DoScriptText(SAY_STAGE_0_04, me); + Talk(SAY_STAGE_0_04); m_uiUpdateTimer = 8000; instance->SetData(TYPE_EVENT, 205); break; @@ -617,7 +632,7 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 230); break; case 300: - DoScriptText(SAY_STAGE_0_05, me); + Talk(SAY_STAGE_0_05); m_uiUpdateTimer = 8000; instance->SetData(TYPE_EVENT, 305); break; @@ -644,54 +659,54 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 320); break; case 400: - DoScriptText(SAY_STAGE_0_06, me); + Talk(SAY_STAGE_0_06); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 0); break; case 666: - DoScriptText(SAY_STAGE_0_WIPE, me); + Talk(SAY_STAGE_0_WIPE); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 0); break; case 1010: - DoScriptText(SAY_STAGE_1_01, me); + Talk(SAY_STAGE_1_01); m_uiUpdateTimer = 7000; instance->DoUseDoorOrButton(instance->GetData64(GO_MAIN_GATE_DOOR)); me->SummonCreature(NPC_FIZZLEBANG, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); instance->SetData(TYPE_EVENT, 0); break; case 1180: - DoScriptText(SAY_STAGE_1_07, me); + Talk(SAY_STAGE_1_07); m_uiUpdateTimer = 3000; instance->SetData(TYPE_EVENT, 0); break; case 2000: - DoScriptText(SAY_STAGE_1_08, me); + Talk(SAY_STAGE_1_08); m_uiUpdateTimer = 18000; instance->SetData(TYPE_EVENT, 2010); break; case 2030: - DoScriptText(SAY_STAGE_1_11, me); + Talk(SAY_STAGE_1_11); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 0); break; case 3000: - DoScriptText(SAY_STAGE_2_01, me); + Talk(SAY_STAGE_2_01); m_uiUpdateTimer = 12000; instance->SetData(TYPE_EVENT, 3050); break; case 3001: - DoScriptText(SAY_STAGE_2_01, me); + Talk(SAY_STAGE_2_01); m_uiUpdateTimer = 12000; instance->SetData(TYPE_EVENT, 3051); break; case 3060: - DoScriptText(SAY_STAGE_2_03, me); + Talk(SAY_STAGE_2_03); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 3070); break; case 3061: - DoScriptText(SAY_STAGE_2_03, me); + Talk(SAY_STAGE_2_03); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 3071); break; @@ -716,17 +731,17 @@ class npc_tirion_toc : public CreatureScript break; //Crusaders battle end case 3100: - DoScriptText(SAY_STAGE_2_06, me); + Talk(SAY_STAGE_2_06); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 0); break; case 4000: - DoScriptText(SAY_STAGE_3_01, me); + Talk(SAY_STAGE_3_01); m_uiUpdateTimer = 13000; instance->SetData(TYPE_EVENT, 4010); break; case 4010: - DoScriptText(SAY_STAGE_3_02, me); + Talk(SAY_STAGE_3_02); if (Creature* temp = me->SummonCreature(NPC_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { temp->SetVisible(false); @@ -767,17 +782,17 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 5000); break; case 5000: - DoScriptText(SAY_STAGE_4_01, me); + Talk(SAY_STAGE_4_01); m_uiUpdateTimer = 10000; instance->SetData(TYPE_EVENT, 5005); break; case 5005: m_uiUpdateTimer = 8000; instance->SetData(TYPE_EVENT, 5010); - me->SummonCreature(NPC_LICH_KING_1, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5); + me->SummonCreature(NPC_LICH_KING_1, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5); break; case 5020: - DoScriptText(SAY_STAGE_4_03, me); + Talk(SAY_STAGE_4_03); m_uiUpdateTimer = 1000; instance->SetData(TYPE_EVENT, 0); break; @@ -787,14 +802,16 @@ class npc_tirion_toc : public CreatureScript instance->SetData(TYPE_EVENT, 6005); break; case 6005: - DoScriptText(SAY_STAGE_4_06, me); + if (Creature* tirionFordring = Unit::GetCreature((*me), instance->GetData64(NPC_TIRION_FORDRING))) + tirionFordring->AI()->Talk(SAY_STAGE_4_06); m_uiUpdateTimer = 20000; instance->SetData(TYPE_EVENT, 6010); break; case 6010: if (IsHeroic()) { - DoScriptText(SAY_STAGE_4_07, me); + if (Creature* tirionFordring = Unit::GetCreature((*me), instance->GetData64(NPC_TIRION_FORDRING))) + tirionFordring->AI()->Talk(SAY_STAGE_4_07); m_uiUpdateTimer = 60000; instance->SetData(TYPE_ANUBARAK, SPECIAL); instance->SetData(TYPE_EVENT, 6020); @@ -852,7 +869,7 @@ class npc_garrosh_toc : public CreatureScript { case 130: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(SAY_STAGE_0_03h, me); + Talk(SAY_STAGE_0_03h); m_uiUpdateTimer = 3000; instance->SetData(TYPE_EVENT, 132); break; @@ -862,27 +879,27 @@ class npc_garrosh_toc : public CreatureScript instance->SetData(TYPE_EVENT, 140); break; case 2010: - DoScriptText(SAY_STAGE_1_09, me); + Talk(SAY_STAGE_1_09); m_uiUpdateTimer = 9000; instance->SetData(TYPE_EVENT, 2020); break; case 3050: - DoScriptText(SAY_STAGE_2_02h, me); + Talk(SAY_STAGE_2_02h); m_uiUpdateTimer = 15000; instance->SetData(TYPE_EVENT, 3060); break; case 3070: - DoScriptText(SAY_STAGE_2_04h, me); + Talk(SAY_STAGE_2_04h); m_uiUpdateTimer = 6000; instance->SetData(TYPE_EVENT, 3080); break; case 3081: - DoScriptText(SAY_STAGE_2_05h, me); + Talk(SAY_STAGE_2_05h); m_uiUpdateTimer = 3000; instance->SetData(TYPE_EVENT, 3091); break; case 4030: - DoScriptText(SAY_STAGE_3_03h, me); + Talk(SAY_STAGE_3_03h); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 4040); break; @@ -933,7 +950,7 @@ class npc_varian_toc : public CreatureScript { case 120: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(SAY_STAGE_0_03a, me); + Talk(SAY_STAGE_0_03a); m_uiUpdateTimer = 2000; instance->SetData(TYPE_EVENT, 122); break; @@ -943,27 +960,27 @@ class npc_varian_toc : public CreatureScript instance->SetData(TYPE_EVENT, 130); break; case 2020: - DoScriptText(SAY_STAGE_1_10, me); + Talk(SAY_STAGE_1_10); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 2030); break; case 3051: - DoScriptText(SAY_STAGE_2_02a, me); + Talk(SAY_STAGE_2_02a); m_uiUpdateTimer = 10000; instance->SetData(TYPE_EVENT, 3061); break; case 3071: - DoScriptText(SAY_STAGE_2_04a, me); + Talk(SAY_STAGE_2_04a); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 3081); break; case 3080: - DoScriptText(SAY_STAGE_2_05a, me); + Talk(SAY_STAGE_2_05a); m_uiUpdateTimer = 3000; instance->SetData(TYPE_EVENT, 3090); break; case 4020: - DoScriptText(SAY_STAGE_3_03a, me); + Talk(SAY_STAGE_3_03a); m_uiUpdateTimer = 5000; instance->SetData(TYPE_EVENT, 4040); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index 99525b6fb32..ba230551b24 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -53,8 +53,8 @@ const Position ToCCommonLoc[]= {563.833008f, 195.244995f, 394.585561f, 0}, // 5 - Center {573.5f, 180.5f, 395.14f, 0}, // 6 Move 0 Right {553.5f, 180.5f, 395.14f, 0}, // 7 Move 0 Left - {585.5f, 170.0f, 395.14f, 0}, // 8 Move 1 Right - {545.5f, 170.0f, 395.14f, 0}, // 9 Move 1 Left + {573.0f, 170.0f, 395.14f, 0}, // 8 Move 1 Right + {555.5f, 170.0f, 395.14f, 0}, // 9 Move 1 Left {563.8f, 216.1f, 395.1f, 0}, // 10 Behind the door {575.042358f, 195.260727f, 395.137146f, 0}, // 5 @@ -162,6 +162,7 @@ enum eCreature { NPC_BARRENT = 34816, NPC_TIRION = 34996, + NPC_TIRION_FORDRING = 36095, NPC_FIZZLEBANG = 35458, NPC_GARROSH = 34995, NPC_VARIAN = 34990, diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp index 95acc79231d..8b39fc51766 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp @@ -19,7 +19,8 @@ * Comment: MAYBE need more improve the "Raptor Call". */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "drak_tharon_keep.h" enum Spells diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 9ff8ee9c9ed..5d9acf4fca7 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "drak_tharon_keep.h" enum Spells diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp index b1d588a0d0d..969ccf4a059 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "drak_tharon_keep.h" enum Spells diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp index 26e4e9db99e..b6a4c40abdd 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp @@ -19,7 +19,9 @@ * Comment: TODO: spawn troll waves */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuras.h" #include "drak_tharon_keep.h" enum Spells diff --git a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp index aff3f1b8e36..99401c1d944 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "drak_tharon_keep.h" #define MAX_ENCOUNTER 4 @@ -69,6 +70,7 @@ public: void Initialize() { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); uiTrollgore = 0; uiNovos = 0; uiDred = 0; @@ -189,16 +191,12 @@ public: { OUT_SAVE_INST_DATA; - std::string str_data; - std::ostringstream saveStream; saveStream << "D K " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3]; - str_data = saveStream.str(); - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; + return saveStream.str(); } void Load(const char* in) diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index 4a28ebe6495..b790ed518d5 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "SpellAuraEffects.h" #include "forge_of_souls.h" @@ -359,7 +361,7 @@ class DistanceCheck public: explicit DistanceCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator() (WorldObject* unit) const { if (caster->GetExactDist2d(unit) <= 10.0f) return true; @@ -378,25 +380,25 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader { PrepareSpellScript(spell_bronjahm_soulstorm_targeting_SpellScript); - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { - unitList.remove_if (DistanceCheck(GetCaster())); - sharedUnitList = unitList; + targets.remove_if(DistanceCheck(GetCaster())); + sharedTargets = targets; } // use the same target for first and second effect - void FilterTargetsSubsequent(std::list<Unit*>& unitList) + void FilterTargetsSubsequent(std::list<WorldObject*>& targets) { - unitList = sharedUnitList; + targets = sharedTargets; } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY); } - std::list<Unit*> sharedUnitList; + std::list<WorldObject*> sharedTargets; }; SpellScript* GetSpellScript() const diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp index ad49f6cbce8..4fdcf96192b 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "forge_of_souls.h" /* diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp index 3158d58716f..c23479eea22 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp @@ -15,56 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "forge_of_souls.h" -enum Spells -{ - //Spiteful Apparition - SPELL_SPITE = 68895, - H_SPELL_SPITE = 70212, - - //Spectral Warden - SPELL_VEIL_OF_SHADOWS = 69633, - SPELL_WAIL_OF_SOULS = 69148, - H_SPELL_WAIL_OF_SOULS = 70210, - - //Soulguard Watchman - SPELL_SHROUD_OF_RUNES = 69056, - SPELL_UNHOLY_RAGE = 69053, - - //Soulguard Reaper - SPELL_FROST_NOVA = 69060, - H_SPELL_FROST_NOVA = 70209, - SPELL_SHADOW_LANCE = 69058, - - //Soulguard Bonecaster - SPELL_BONE_VOLLEY = 69080, - H_SPELL_BONE_VOLLEY = 70206, - SPELL_RAISE_DEAD = 69562, - SPELL_SHIELD_OF_BONES = 69069, - H_SPELL_SHIELD_OF_BONES = 70207, - - //Soulguard Animator - // Raise dead 69562 - SPELL_SHADOW_BOLT = 69068, - H_SPELL_SHADOW_BOLT = 70208, - SPELL_SOUL_SICKNESS = 69131, - SPELL_SOUL_SIPHON = 69128, - - //Soulguard Adept - //Raise dead 69562 - //Shadow Bolt 69068/70208 - SPELL_DRAIN_LIFE = 69066, - H_SPELL_DRAIN_LIFE = 70213, - SPELL_SHADOW_MEND = 69564, - H_SPELL_SHADOW_MEND = 70205, - - //Soul Horror - SPELL_SOUL_STRIKE = 69088, - H_SPELL_SOUL_STRIKE = 70211, -}; - enum Events { EVENT_NONE, @@ -78,38 +33,6 @@ enum Events EVENT_INTRO_6, EVENT_INTRO_7, EVENT_INTRO_8, - - //Spiteful Apparition - EVENT_SPITE, - - //Spectral Warden - EVENT_VEIL_OF_SHADOWS, - EVENT_WAIL_OF_SOULS, - - //Soulguard Watchman - EVENT_SHROUD_OF_RUNES, - EVENT_UNHOLY_RAGE, - - //Soulguard Reaper - EVENT_FROST_NOVA, - EVENT_SHADOW_LANCE, - - //Soulguard Bonecaster - EVENT_BONE_VOLLEY, - EVENT_RAISE_DEAD, - EVENT_SHIELD_OF_BONES, - - //Soulguard Animator - EVENT_SHADOW_BOLT, - EVENT_SOUL_SICKNESS, - EVENT_SOUL_SIPHON, - - //Soulguard Adept - EVENT_DRAIN_LIFE, - EVENT_SHADOW_MEND, - - //Soul Horror - EVENT_SOUL_STRIKE, }; /****************************************SYLVANAS************************************/ @@ -410,508 +333,8 @@ public: } }; -class mob_spiteful_apparition : public CreatureScript -{ -public: - mob_spiteful_apparition() : CreatureScript("mob_spiteful_apparition") { } - - struct mob_spiteful_apparitionAI: public ScriptedAI - { - mob_spiteful_apparitionAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPITE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SPITE: - DoCastVictim(SPELL_SPITE); - events.RescheduleEvent(EVENT_SPITE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_spiteful_apparitionAI(creature); - } -}; - -class mob_spectral_warden : public CreatureScript -{ -public: - mob_spectral_warden() : CreatureScript("mob_spectral_warden") { } - - struct mob_spectral_wardenAI: public ScriptedAI - { - mob_spectral_wardenAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); - events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_VEIL_OF_SHADOWS: - DoCastVictim(SPELL_VEIL_OF_SHADOWS); - events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); - return; - case EVENT_WAIL_OF_SOULS: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_WAIL_OF_SOULS); - events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); - return; - } - } - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_spectral_wardenAI(creature); - } -}; - -class mob_soulguard_watchman : public CreatureScript -{ -public: - mob_soulguard_watchman() : CreatureScript("mob_soulguard_watchman") { } - - struct mob_soulguard_watchmanAI: public ScriptedAI - { - mob_soulguard_watchmanAI(Creature* creature) : ScriptedAI(creature) { } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); - events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHROUD_OF_RUNES: - DoCast(me, SPELL_SHROUD_OF_RUNES); - events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); - return; - case EVENT_UNHOLY_RAGE: - DoCast(me, SPELL_UNHOLY_RAGE); - events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); - return; - } - } - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soulguard_watchmanAI(creature); - } -}; - -class mob_soulguard_reaper : public CreatureScript -{ -public: - mob_soulguard_reaper() : CreatureScript("mob_soulguard_reaper") { } - - struct mob_soulguard_reaperAI: public ScriptedAI - { - mob_soulguard_reaperAI(Creature* creature) : ScriptedAI(creature) { } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_NOVA, 8000); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_FROST_NOVA: - DoCast(me, SPELL_FROST_NOVA); - events.RescheduleEvent(EVENT_FROST_NOVA, 9600); - return; - case EVENT_SHADOW_LANCE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SHADOW_LANCE); - events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soulguard_reaperAI(creature); - } -}; - -class mob_soulguard_bonecaster : public CreatureScript -{ -public: - mob_soulguard_bonecaster() : CreatureScript("mob_soulguard_bonecaster") { } - - struct mob_soulguard_bonecasterAI: public ScriptedAI - { - mob_soulguard_bonecasterAI(Creature* creature) : ScriptedAI(creature) { } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BONE_VOLLEY: - DoCastAOE(SPELL_BONE_VOLLEY); - events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); - return; - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHIELD_OF_BONES: - DoCast(me, SPELL_SHIELD_OF_BONES); - events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soulguard_bonecasterAI(creature); - } -}; - -class mob_soulguard_animator : public CreatureScript -{ -public: - mob_soulguard_animator() : CreatureScript("mob_soulguard_animator") { } - - struct mob_soulguard_animatorAI : public ScriptedAI - { - mob_soulguard_animatorAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); - events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); - events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - case EVENT_SOUL_SICKNESS: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SOUL_SICKNESS); - events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); - return; - case EVENT_SOUL_SIPHON: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SOUL_SIPHON); - events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soulguard_animatorAI(creature); - } -}; - -class mob_soulguard_adept : public CreatureScript -{ -public: - mob_soulguard_adept() : CreatureScript("mob_soulguard_adept") { } - - struct mob_soulguard_adeptAI: public ScriptedAI - { - mob_soulguard_adeptAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); - events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); - events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); - return; - case EVENT_DRAIN_LIFE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_DRAIN_LIFE); - events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); - return; - case EVENT_SHADOW_MEND: - DoCast(me, SPELL_SHADOW_MEND); - events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soulguard_adeptAI(creature); - } -}; - -class mob_soul_horror : public CreatureScript -{ -public: - mob_soul_horror() : CreatureScript("mob_soul_horror") { } - - struct mob_soul_horrorAI : public ScriptedAI - { - mob_soul_horrorAI(Creature* creature) : ScriptedAI(creature) { } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SOUL_STRIKE: - DoCast(me->getVictim(), SPELL_SOUL_STRIKE); - events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_soul_horrorAI(creature); - } -}; - void AddSC_forge_of_souls() { new npc_sylvanas_fos(); new npc_jaina_fos(); - new mob_spiteful_apparition(); - new mob_spectral_warden(); - new mob_soulguard_watchman(); - new mob_soulguard_reaper(); - new mob_soulguard_bonecaster(); - new mob_soulguard_animator(); - new mob_soulguard_adept(); - new mob_soul_horror(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp index bad4b8e38b2..618b2b6a9a6 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "forge_of_souls.h" #define MAX_ENCOUNTER 2 diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp index 9cfcb78f6f1..4df13d32bf8 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_reflection.h" enum Yells diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp index a9bfb603794..8334a199791 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_reflection.h" enum Yells diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 2abb60d5de2..26ec9e53213 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "halls_of_reflection.h" enum Yells diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index 3c4d05854bb..e3604890e39 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "halls_of_reflection.h" #define MAX_ENCOUNTER 3 diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 64609efd7ff..a12bd96f6df 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -15,19 +15,23 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuras.h" #include "pit_of_saron.h" enum Yells { - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, - - SAY_TYRANNUS_DEATH = -1658007, + SAY_AGGRO = 0, + SAY_PHASE2 = 1, + SAY_PHASE3 = 2, + SAY_DEATH = 3, + SAY_SLAY = 4, + SAY_THROW_SARONITE = 5, + SAY_CAST_DEEP_FREEZE = 6, + + SAY_TYRANNUS_DEATH = -1658007, // todo }; enum Spells @@ -107,8 +111,9 @@ class boss_garfrost : public CreatureScript void EnterCombat(Unit* /*who*/) { - DoScriptText(SAY_AGGRO, me); + Talk(SAY_AGGRO); DoCast(me, SPELL_PERMAFROST); + me->CallForHelp(70.0f); events.ScheduleEvent(EVENT_THROW_SARONITE, 7000); instance->SetBossState(DATA_GARFROST, IN_PROGRESS); @@ -117,12 +122,13 @@ class boss_garfrost : public CreatureScript void KilledUnit(Unit* victim) { if (victim->GetTypeId() == TYPEID_PLAYER) - DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); + Talk(SAY_SLAY); } void JustDied(Unit* /*killer*/) { - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); + if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS))) DoScriptText(SAY_TYRANNUS_DEATH, tyrannus); @@ -134,6 +140,7 @@ class boss_garfrost : public CreatureScript if (events.GetPhaseMask() & PHASE_ONE_MASK && !HealthAbovePct(66)) { events.SetPhase(PHASE_TWO); + Talk(SAY_PHASE2); events.DelayEvents(8000); DoCast(me, SPELL_THUNDERING_STOMP); events.ScheduleEvent(EVENT_JUMP, 1500); @@ -143,6 +150,7 @@ class boss_garfrost : public CreatureScript if (events.GetPhaseMask() & PHASE_TWO_MASK && !HealthAbovePct(33)) { events.SetPhase(PHASE_THREE); + Talk(SAY_PHASE3); events.DelayEvents(8000); DoCast(me, SPELL_THUNDERING_STOMP); events.ScheduleEvent(EVENT_JUMP, 1500); @@ -152,15 +160,19 @@ class boss_garfrost : public CreatureScript void MovementInform(uint32 type, uint32 id) { - if (type != POINT_MOTION_TYPE || id != POINT_FORGE) + if (type != EFFECT_MOTION_TYPE || id != POINT_FORGE) return; if (events.GetPhaseMask() & PHASE_TWO_MASK) + { DoCast(me, SPELL_FORGE_BLADE); + SetEquipmentSlots(false, EQUIP_ID_SWORD); + } if (events.GetPhaseMask() & PHASE_THREE_MASK) { me->RemoveAurasDueToSpell(SPELL_FORGE_BLADE_HELPER); DoCast(me, SPELL_FORGE_MACE); + SetEquipmentSlots(false, EQUIP_ID_MACE); } events.ScheduleEvent(EVENT_RESUME_ATTACK, 5000); } @@ -172,10 +184,6 @@ class boss_garfrost : public CreatureScript if (Aura* aura = target->GetAura(SPELL_PERMAFROST_HELPER)) _permafrostStack = std::max<uint32>(_permafrostStack, aura->GetStackAmount()); } - else if (spell->Id == SPELL_FORGE_BLADE) - SetEquipmentSlots(false, EQUIP_ID_SWORD); - else if (spell->Id == SPELL_FORGE_MACE) - SetEquipmentSlots(false, EQUIP_ID_MACE); } uint32 GetData(uint32 /*type*/) @@ -199,7 +207,10 @@ class boss_garfrost : public CreatureScript { case EVENT_THROW_SARONITE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + { + Talk(SAY_THROW_SARONITE, target->GetGUID()); DoCast(target, SPELL_THROW_SARONITE); + } events.ScheduleEvent(EVENT_THROW_SARONITE, urand(12500, 20000)); break; case EVENT_CHILLING_WAVE: @@ -208,7 +219,10 @@ class boss_garfrost : public CreatureScript break; case EVENT_DEEP_FREEZE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + { + Talk(SAY_CAST_DEEP_FREEZE, target->GetGUID()); DoCast(target, SPELL_DEEP_FREEZE); + } events.ScheduleEvent(EVENT_DEEP_FREEZE, 35000, 0, PHASE_THREE); break; case EVENT_JUMP: diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index fa260cb298d..57d99908bfb 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "pit_of_saron.h" #include "Vehicle.h" diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 88e9bedcd07..ef4d9182f82 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "pit_of_saron.h" #include "Vehicle.h" @@ -387,8 +390,7 @@ class player_overlord_brandAI : public PlayerAI void SetGUID(uint64 guid, int32 /*type*/) { tyrannus = ObjectAccessor::GetCreature(*me, guid); - if (!tyrannus) - me->IsAIEnabled = false; + me->IsAIEnabled = tyrannus != NULL; } void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) @@ -423,10 +425,9 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader return; oldAI = GetTarget()->GetAI(); + oldAIState = GetTarget()->IsAIEnabled; GetTarget()->SetAI(new player_overlord_brandAI(GetTarget()->ToPlayer())); GetTarget()->GetAI()->SetGUID(GetCasterGUID()); - oldAIState = GetTarget()->IsAIEnabled; - GetTarget()->IsAIEnabled = true; } void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index 24529801564..a6537c45d6f 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "pit_of_saron.h" // positions for Martin Victus (37591) and Gorkun Ironskull (37592) @@ -23,6 +24,13 @@ Position const SlaveLeaderPos = {689.7158f, -104.8736f, 513.7360f, 0.0f}; // position for Jaina and Sylvanas Position const EventLeaderPos2 = {1054.368f, 107.14620f, 628.4467f, 0.0f}; +DoorData const Doors[] = +{ + {GO_ICE_WALL, DATA_GARFROST, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, + {GO_ICE_WALL, DATA_ICK, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, + {GO_HALLS_OF_REFLECTION_PORTCULLIS, DATA_TYRANNUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, +}; + class instance_pit_of_saron : public InstanceMapScript { public: @@ -33,6 +41,7 @@ class instance_pit_of_saron : public InstanceMapScript instance_pit_of_saron_InstanceScript(Map* map) : InstanceScript(map) { SetBossNumber(MAX_ENCOUNTER); + LoadDoorData(Doors); _garfrostGUID = 0; _krickGUID = 0; _ickGUID = 0; @@ -154,6 +163,28 @@ class instance_pit_of_saron : public InstanceMapScript } } + void OnGameObjectCreate(GameObject* go) + { + switch (go->GetEntry()) + { + case GO_ICE_WALL: + case GO_HALLS_OF_REFLECTION_PORTCULLIS: + AddDoor(go, true); + break; + } + } + + void OnGameObjectRemove(GameObject* go) + { + switch (go->GetEntry()) + { + case GO_ICE_WALL: + case GO_HALLS_OF_REFLECTION_PORTCULLIS: + AddDoor(go, false); + break; + } + } + bool SetBossState(uint32 type, EncounterState state) { if (!InstanceScript::SetBossState(type, state)) diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 70d72e52e67..eba19403517 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "pit_of_saron.h" #include "Vehicle.h" @@ -25,9 +28,6 @@ enum eSpells SPELL_HELLFIRE = 69586, SPELL_TACTICAL_BLINK = 69584, SPELL_FROST_BREATH = 69527, //Iceborn Proto-Drake - SPELL_BLINDING_DIRT = 70302, //Wrathbone Laborer - SPELL_PUNCTURE_WOUND = 70278, - SPELL_SHOVELLED = 69572, SPELL_LEAPING_FACE_MAUL = 69504, // Geist Ambusher }; @@ -36,11 +36,6 @@ enum eEvents // Ymirjar Flamebearer EVENT_FIREBALL = 1, EVENT_TACTICAL_BLINK = 2, - - //Wrathbone Laborer - EVENT_BLINDING_DIRT = 3, - EVENT_PUNCTURE_WOUND = 4, - EVENT_SHOVELLED = 5, }; class mob_ymirjar_flamebearer : public CreatureScript @@ -157,73 +152,6 @@ class mob_iceborn_protodrake : public CreatureScript } }; -class mob_wrathbone_laborer : public CreatureScript -{ - public: - mob_wrathbone_laborer() : CreatureScript("mob_wrathbone_laborer") { } - - struct mob_wrathbone_laborerAI: public ScriptedAI - { - mob_wrathbone_laborerAI(Creature* creature) : ScriptedAI(creature) - { - } - - void Reset() - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - _events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - _events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - _events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 10.0f, true)) - DoCast(target, SPELL_BLINDING_DIRT); - _events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCastVictim(SPELL_PUNCTURE_WOUND); - _events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, -5.0f)) - DoCast(target, SPELL_SHOVELLED); - _events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_wrathbone_laborerAI(creature); - } -}; - class mob_geist_ambusher : public CreatureScript { public: @@ -310,7 +238,6 @@ class spell_trash_mob_glacial_strike : public SpellScriptLoader void AddSC_pit_of_saron() { new mob_ymirjar_flamebearer(); - new mob_wrathbone_laborer(); new mob_iceborn_protodrake(); new mob_geist_ambusher(); new spell_trash_mob_glacial_strike(); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h index 728e0ccd955..768c3ba40ec 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -90,6 +90,8 @@ enum CreatureIds enum GameObjectIds { GO_SARONITE_ROCK = 196485, + GO_ICE_WALL = 201885, + GO_HALLS_OF_REFLECTION_PORTCULLIS = 201848, }; #endif diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index b66c3d795f3..fd1aba79e83 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -19,7 +19,8 @@ * Comment: The event with the Living Mojos is not implemented, just is done that when one of the mojos around the boss take damage will make the boss enter in combat! */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "gundrak.h" enum Spells diff --git a/src/server/scripts/Northrend/Gundrak/boss_eck.cpp b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp index 3e803c24d61..b75c5cbc2a9 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_eck.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "gundrak.h" enum Spells diff --git a/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp b/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp index be9b09a1263..0d89c402054 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "gundrak.h" //Spells diff --git a/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp b/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp index 1085e993322..c1301dbd2d0 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "gundrak.h" enum eSpells diff --git a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp index b827f43dc99..251c9ec2b83 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuras.h" #include "gundrak.h" //Spells diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp index c22a0e17cd5..15315c721d7 100644 --- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "gundrak.h" #define MAX_ENCOUNTER 5 diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index de104a78e43..6e7e3c49ef8 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -103,6 +103,7 @@ enum Spells SPELL_UNSTABLE = 72059, SPELL_KINETIC_BOMB_VISUAL = 72054, SPELL_KINETIC_BOMB_EXPLOSION = 72052, + SPELL_KINETIC_BOMB_KNOCKBACK = 72087, // Shock Vortex SPELL_SHOCK_VORTEX_PERIODIC = 71945, @@ -443,20 +444,12 @@ class boss_prince_keleseth_icc : public CreatureScript { summons.Summon(summon); Position pos; - pos.Relocate(summon); + me->GetPosition(&pos); float maxRange = me->GetDistance2d(summon); float angle = me->GetAngle(summon); - // prevent spawning outside of room - while (!me->IsWithinLOS(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ())) - { - maxRange -= 5.0f; - if (maxRange < 5.0f) - break; - - summon->MovePosition(pos, float(rand_norm() * maxRange), angle); - } - + me->MovePositionToFirstCollision(pos, maxRange, angle); summon->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); + summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); } void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType) @@ -894,6 +887,7 @@ class boss_prince_valanar_icc : public CreatureScript summon->GetPosition(x, y, z); float ground_Z = summon->GetMap()->GetHeight(summon->GetPhaseMask(), x, y, z, true, 500.0f); summon->GetMotionMaster()->MovePoint(POINT_KINETIC_BOMB_IMPACT, x, y, ground_Z); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); break; } case NPC_SHOCK_VORTEX: @@ -1073,7 +1067,7 @@ class npc_blood_queen_lana_thel : public CreatureScript if (_introDone) return; - if (!me->IsWithinDistInMap(who, 35.0f)) + if (!me->IsWithinDistInMap(who, 35.0f, false)) return; _introDone = true; @@ -1232,12 +1226,12 @@ class npc_kinetic_bomb : public CreatureScript void Reset() { _events.Reset(); - me->SetDisplayId(DISPLAY_KINETIC_BOMB); + me->SetWalk(true); me->CastSpell(me, SPELL_UNSTABLE, true); me->CastSpell(me, SPELL_KINETIC_BOMB_VISUAL, true); me->SetReactState(REACT_PASSIVE); - me->SetSpeed(MOVE_FLIGHT, IsHeroic() ? 0.3f : 0.15f, true); me->GetPosition(_x, _y, _groundZ); + me->DespawnOrUnsummon(60000); _groundZ = me->GetMap()->GetHeight(me->GetPhaseMask(), _x, _y, _groundZ, true, 500.0f); } @@ -1247,9 +1241,9 @@ class npc_kinetic_bomb : public CreatureScript _events.ScheduleEvent(EVENT_BOMB_DESPAWN, 1000); else if (action == ACTION_KINETIC_BOMB_JUMP) { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveJump(_x, _y, me->GetPositionZ() + 7.0f, 1.0f, 7.0f); - _events.ScheduleEvent(EVENT_CONTINUE_FALLING, 700); + if (!me->HasAura(SPELL_KINETIC_BOMB_KNOCKBACK)) + me->GetMotionMaster()->MoveCharge(_x, _y, me->GetPositionZ() + 100.0f, me->GetSpeed(MOVE_RUN), 0); + _events.RescheduleEvent(EVENT_CONTINUE_FALLING, 3000); } } @@ -1263,10 +1257,10 @@ class npc_kinetic_bomb : public CreatureScript { case EVENT_BOMB_DESPAWN: me->SetVisible(false); + me->DespawnOrUnsummon(5000); break; case EVENT_CONTINUE_FALLING: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(POINT_KINETIC_BOMB_IMPACT, _x, _y, _groundZ); + me->GetMotionMaster()->MoveCharge(_x, _y, _groundZ, me->GetSpeed(MOVE_WALK), POINT_KINETIC_BOMB_IMPACT); break; default: break; @@ -1302,7 +1296,7 @@ class npc_dark_nucleus : public CreatureScript void Reset() { - me->SetReactState(REACT_PASSIVE); + me->SetReactState(REACT_DEFENSIVE); me->CastSpell(me, SPELL_SHADOW_RESONANCE_AURA, true); } @@ -1321,9 +1315,6 @@ class npc_dark_nucleus : public CreatureScript void MoveInLineOfSight(Unit* who) { - if (me->GetDistance(who) >= 15.0f) - return; - ScriptedAI::MoveInLineOfSight(who); } @@ -1332,46 +1323,32 @@ class npc_dark_nucleus : public CreatureScript if (attacker == me) return; - if (!_lockedTarget) - if (me->getVictim() == attacker) - _lockedTarget = true; + me->DeleteThreatList(); + me->AddThreat(attacker, 500000000.0f); } - void UpdateAI(const uint32 diff) + void UpdateAI(uint32 const diff) { - if (!me->isInCombat()) + if (!UpdateVictim()) return; if (_targetAuraCheck <= diff) { _targetAuraCheck = 1000; if (Unit* victim = me->getVictim()) + { if (me->GetDistance(victim) < 15.0f && !victim->HasAura(SPELL_SHADOW_RESONANCE_RESIST, me->GetGUID())) { DoCast(victim, SPELL_SHADOW_RESONANCE_RESIST); me->ClearUnitState(UNIT_STATE_CASTING); } + else + MoveInLineOfSight(me->getVictim()); + } } else _targetAuraCheck -= diff; - - if (!_lockedTarget) - { - if (Unit* victim = me->SelectVictim()) - { - if (me->getVictim() && me->getVictim() != victim) - { - me->getVictim()->RemoveAurasDueToSpell(SPELL_SHADOW_RESONANCE_RESIST, me->GetGUID()); - _lockedTarget = true; - } - - _lockedTarget = true; - AttackStart(victim); - DoCast(victim, SPELL_SHADOW_RESONANCE_RESIST); - me->ClearUnitState(UNIT_STATE_CASTING); - } - } } private: @@ -1521,10 +1498,11 @@ class spell_valanar_kinetic_bomb : public SpellScriptLoader void ChangeSummonPos(SpellEffIndex /*effIndex*/) { - WorldLocation summonPos = *GetTargetDest(); + WorldLocation summonPos = *GetExplTargetDest(); Position offset = {0.0f, 0.0f, 20.0f, 0.0f}; summonPos.RelocateOffset(offset); - SetTargetDest(summonPos); + SetExplTargetDest(summonPos); + GetHitDest()->RelocateOffset(offset); } void Register() @@ -1586,7 +1564,7 @@ class spell_valanar_kinetic_bomb_knockback : public SpellScriptLoader void Register() { - AfterHit += SpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir); + BeforeHit += SpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir); } }; @@ -1663,7 +1641,7 @@ class spell_blood_council_shadow_prison_damage : public SpellScriptLoader void AddExtraDamage() { if (Aura* aur = GetHitUnit()->GetAura(GetSpellInfo()->Id)) - if (AuraEffect const* eff = aur->GetEffect(1)) + if (AuraEffect const* eff = aur->GetEffect(EFFECT_1)) SetHitDamage(GetHitDamage() + eff->GetAmount()); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index b6544fd9a2a..0d092ec86b2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -149,7 +149,7 @@ class boss_blood_queen_lana_thel : public CreatureScript events.ScheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL); events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(20000, 25000), EVENT_GROUP_NORMAL); events.ScheduleEvent(EVENT_AIR_PHASE, 124000 + uint32(Is25ManRaid() ? 3000 : 0)); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); + CleanAuras(); me->SetSpeed(MOVE_FLIGHT, 0.642857f, true); _offtank = NULL; _vampires.clear(); @@ -170,6 +170,7 @@ class boss_blood_queen_lana_thel : public CreatureScript DoZoneInCombat(); Talk(SAY_AGGRO); instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, IN_PROGRESS); + CleanAuras(); DoCast(me, SPELL_SHROUD_OF_SORROW, true); DoCast(me, SPELL_FRENZIED_BLOODTHIRST_VISUAL, true); @@ -180,15 +181,7 @@ class boss_blood_queen_lana_thel : public CreatureScript { _JustDied(); Talk(SAY_DEATH); - instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN); - instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR); - instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DAMAGE); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_VISUAL); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY); - instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); + CleanAuras(); // Blah, credit the quest if (_creditBloodQuickening) { @@ -207,6 +200,19 @@ class boss_blood_queen_lana_thel : public CreatureScript } } + void CleanAuras() + { + instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN); + instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR); + instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DAMAGE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_VISUAL); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY); + instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); + } + void DoAction(int32 const action) { if (action != ACTION_KILL_MINCHAR) @@ -227,6 +233,7 @@ class boss_blood_queen_lana_thel : public CreatureScript void EnterEvadeMode() { _EnterEvadeMode(); + CleanAuras(); if (_killMinchar) { _killMinchar = false; @@ -522,7 +529,7 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader SpellCastResult CheckTarget() { - if (IsVampire(GetTargetUnit())) + if (IsVampire(GetExplTargetUnit())) { SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES); return SPELL_FAILED_CUSTOM_ERROR; @@ -624,9 +631,9 @@ class BloodboltHitCheck public: explicit BloodboltHitCheck(LanaThelAI* ai) : _ai(ai) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return _ai->WasBloodbolted(unit->GetGUID()); + return _ai->WasBloodbolted(object->GetGUID()); } private: @@ -654,13 +661,13 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader return GetCaster()->GetEntry() == NPC_BLOOD_QUEEN_LANA_THEL; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { uint32 targetCount = (targets.size() + 2) / 3; - targets.remove_if (BloodboltHitCheck(static_cast<LanaThelAI*>(GetCaster()->GetAI()))); + targets.remove_if(BloodboltHitCheck(static_cast<LanaThelAI*>(GetCaster()->GetAI()))); Trinity::Containers::RandomResizeList(targets, targetCount); // mark targets now, effect hook has missile travel time delay (might cast next in that time) - for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) GetCaster()->GetAI()->SetGUID((*itr)->GetGUID(), GUID_BLOODBOLT); } @@ -672,7 +679,7 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_bloodbolt_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_bloodbolt_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_blood_queen_bloodbolt_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } }; @@ -692,19 +699,19 @@ class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader { PrepareSpellScript(spell_blood_queen_pact_of_the_darkfallen_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if (Trinity::UnitAuraCheck(false, SPELL_PACT_OF_THE_DARKFALLEN)); + targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_PACT_OF_THE_DARKFALLEN)); bool remove = true; - std::list<Unit*>::const_iterator itrEnd = unitList.end(), itr, itr2; + std::list<WorldObject*>::const_iterator itrEnd = targets.end(), itr, itr2; // we can do this, unitList is MAX 4 in size - for (itr = unitList.begin(); itr != itrEnd && remove; ++itr) + for (itr = targets.begin(); itr != itrEnd && remove; ++itr) { if (!GetCaster()->IsWithinDist(*itr, 5.0f, false)) remove = false; - for (itr2 = unitList.begin(); itr2 != itrEnd && remove; ++itr2) + for (itr2 = targets.begin(); itr2 != itrEnd && remove; ++itr2) if (itr != itr2 && !(*itr2)->IsWithinDist(*itr, 5.0f, false)) remove = false; } @@ -714,14 +721,14 @@ class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader if (InstanceScript* instance = GetCaster()->GetInstanceScript()) { instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); - unitList.clear(); + targets.clear(); } } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_pact_of_the_darkfallen_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_pact_of_the_darkfallen_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -778,15 +785,15 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg_target : public SpellScriptLo { PrepareSpellScript(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (Trinity::UnitAuraCheck(true, SPELL_PACT_OF_THE_DARKFALLEN)); + unitList.remove_if(Trinity::UnitAuraCheck(true, SPELL_PACT_OF_THE_DARKFALLEN)); unitList.push_back(GetCaster()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 249eed01643..5d3a6814eb2 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -39,6 +39,7 @@ enum ScriptTexts SAY_FRENZY = 11, SAY_BERSERK = 12, SAY_DEATH = 13, + EMOTE_SCENT_OF_BLOOD = 14, // High Overlord Saurfang SAY_INTRO_HORDE_1 = 0, @@ -145,6 +146,7 @@ enum EventTypes EVENT_BOILING_BLOOD = 20, EVENT_BLOOD_NOVA = 21, EVENT_RUNE_OF_BLOOD = 22, + EVENT_SCENT_OF_BLOOD = 52, EVENT_OUTRO_ALLIANCE_1 = 23, EVENT_OUTRO_ALLIANCE_2 = 24, @@ -297,7 +299,7 @@ class boss_deathbringer_saurfang : public CreatureScript Talk(SAY_AGGRO); events.ScheduleEvent(EVENT_SUMMON_BLOOD_BEAST, 30000, 0, PHASE_COMBAT); - events.ScheduleEvent(EVENT_BERSERK, 480000, 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_BERSERK, IsHeroic() ? 360000 : 480000, 0, PHASE_COMBAT); events.ScheduleEvent(EVENT_BOILING_BLOOD, 15500, 0, PHASE_COMBAT); events.ScheduleEvent(EVENT_BLOOD_NOVA, 17000, 0, PHASE_COMBAT); events.ScheduleEvent(EVENT_RUNE_OF_BLOOD, 20000, 0, PHASE_COMBAT); @@ -374,16 +376,13 @@ class boss_deathbringer_saurfang : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) summon->AI()->AttackStart(target); - if (IsHeroic()) - DoCast(summon, SPELL_SCENT_OF_BLOOD); - - summon->AI()->DoCast(summon, SPELL_BLOOD_LINK_BEAST, true); - summon->AI()->DoCast(summon, SPELL_RESISTANT_SKIN, true); + summon->CastSpell(summon, SPELL_BLOOD_LINK_BEAST, true); + summon->CastSpell(summon, SPELL_RESISTANT_SKIN, true); summons.Summon(summon); DoZoneInCombat(summon); } - void SummonedCreatureDespawn(Creature* summon) + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) { summons.Despawn(summon); } @@ -463,18 +462,13 @@ class boss_deathbringer_saurfang : public CreatureScript DoCast(me, SPELL_SUMMON_BLOOD_BEAST_25_MAN+i25); Talk(SAY_BLOOD_BEASTS); events.ScheduleEvent(EVENT_SUMMON_BLOOD_BEAST, 40000, 0, PHASE_COMBAT); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SCENT_OF_BLOOD, 10000, 0, PHASE_COMBAT); break; case EVENT_BLOOD_NOVA: - { - // select at range only - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, -10.0f, true); - if (!target) - target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true); // noone? select melee - if (target) - DoCast(target, SPELL_BLOOD_NOVA_TRIGGER); + DoCastAOE(SPELL_BLOOD_NOVA_TRIGGER); events.ScheduleEvent(EVENT_BLOOD_NOVA, urand(20000, 25000), 0, PHASE_COMBAT); break; - } case EVENT_RUNE_OF_BLOOD: DoCastVictim(SPELL_RUNE_OF_BLOOD); events.ScheduleEvent(EVENT_RUNE_OF_BLOOD, urand(20000, 25000), 0, PHASE_COMBAT); @@ -487,6 +481,13 @@ class boss_deathbringer_saurfang : public CreatureScript DoCast(me, SPELL_BERSERK); Talk(SAY_BERSERK); break; + case EVENT_SCENT_OF_BLOOD: + if (!summons.empty()) + { + Talk(EMOTE_SCENT_OF_BLOOD); + DoCastAOE(SPELL_SCENT_OF_BLOOD); + } + break; default: break; } @@ -630,9 +631,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript _events.ScheduleEvent(EVENT_OUTRO_HORDE_4, 24000); // cast _events.ScheduleEvent(EVENT_OUTRO_HORDE_5, 30000); // move me->SetDisableGravity(false); - me->SendMovementFlagUpdate(); - me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); + me->GetMotionMaster()->MoveFall(); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); break; @@ -837,9 +836,7 @@ class npc_muradin_bronzebeard_icc : public CreatureScript me->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY); Talk(SAY_OUTRO_ALLIANCE_1); me->SetDisableGravity(false); - me->SendMovementFlagUpdate(); - me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); + me->GetMotionMaster()->MoveFall(); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); @@ -1201,34 +1198,34 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader return true; } - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { - if (unitList.empty()) + if (targets.empty()) return; // select one random target, with preference of ranged targets uint32 targetsAtRange = 0; uint32 const minTargets = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 10 : 4); - unitList.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); // get target count at range - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr, ++targetsAtRange) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr, ++targetsAtRange) if ((*itr)->GetDistance(GetCaster()) < 12.0f) break; // set the upper cap if (targetsAtRange < minTargets) - targetsAtRange = std::min<uint32>(unitList.size() - 1, minTargets); + targetsAtRange = std::min<uint32>(targets.size() - 1, minTargets); - std::list<Unit*>::const_iterator itr = unitList.begin(); + std::list<WorldObject*>::const_iterator itr = targets.begin(); std::advance(itr, urand(0, targetsAtRange)); target = *itr; - unitList.clear(); - unitList.push_back(target); + targets.clear(); + targets.push_back(target); } // use the same target for first and second effect - void FilterTargetsSubsequent(std::list<Unit*>& unitList) + void FilterTargetsSubsequent(std::list<WorldObject*>& unitList) { if (!target) return; @@ -1237,13 +1234,19 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader unitList.push_back(target); } + void HandleForceCast(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), TRIGGERED_FULL_MASK); + } + void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_deathbringer_blood_nova_targeting_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); } - Unit* target; + WorldObject* target; }; SpellScript* GetSpellScript() const @@ -1266,20 +1269,20 @@ class spell_deathbringer_boiling_blood : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove(GetCaster()->getVictim()); - if (unitList.empty()) + targets.remove(GetCaster()->getVictim()); + if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_boiling_blood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_boiling_blood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 1672d8b2d87..0c5cb0aba52 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -416,7 +416,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader { PrepareSpellScript(spell_marrowgar_coldflame_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { targets.clear(); // select any unit but not the tank (by owners threatlist) @@ -438,7 +438,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_marrowgar_coldflame_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_coldflame_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index b66632b6eeb..a9ba0baa86f 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -64,6 +64,9 @@ enum Spells SPELL_MALLEABLE_GOO = 70852, SPELL_UNSTABLE_EXPERIMENT = 70351, SPELL_TEAR_GAS = 71617, // phase transition + SPELL_TEAR_GAS_CREATURE = 71618, + SPELL_TEAR_GAS_CANCEL = 71620, + SPELL_TEAR_GAS_PERIODIC_TRIGGER = 73170, SPELL_CREATE_CONCOCTION = 71621, SPELL_GUZZLE_POTIONS = 71893, SPELL_OOZE_TANK_PROTECTION = 71770, // protects the tank @@ -86,6 +89,7 @@ enum Spells SPELL_GASEOUS_BLOAT_PROC = 70215, SPELL_GASEOUS_BLOAT = 70672, SPELL_GASEOUS_BLOAT_PROTECTION = 70812, + SPELL_EXPUNGED_GAS = 70701, // Volatile Ooze SPELL_OOZE_ERUPTION = 70492, @@ -167,6 +171,33 @@ enum PutricideData #define EXPERIMENT_STATE_OOZE false #define EXPERIMENT_STATE_GAS true +class AbominationDespawner +{ + public: + explicit AbominationDespawner(Unit* owner) : _owner(owner) { } + + bool operator()(uint64 guid) + { + if (Unit* summon = ObjectAccessor::GetUnit(*_owner, guid)) + { + if (summon->GetEntry() == NPC_MUTATED_ABOMINATION_10 || summon->GetEntry() == NPC_MUTATED_ABOMINATION_25) + { + if (Vehicle* veh = summon->GetVehicleKit()) + veh->RemoveAllPassengers(); // also despawns the vehicle + + return true; + } + + return false; + } + + return true; + } + + private: + Unit* _owner; +}; + class boss_professor_putricide : public CreatureScript { public: @@ -265,6 +296,7 @@ class boss_professor_putricide : public CreatureScript summon->ModifyAuraState(AURA_STATE_UNKNOWN22, true); summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true); summon->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, summon, false); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); return; case NPC_VOLATILE_OOZE: @@ -272,6 +304,7 @@ class boss_professor_putricide : public CreatureScript summon->ModifyAuraState(AURA_STATE_UNKNOWN19, true); summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true); summon->CastSpell(summon, SPELL_VOLATILE_OOZE_ADHESIVE, false); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); return; case NPC_CHOKING_GAS_BOMB: @@ -477,8 +510,7 @@ class boss_professor_putricide : public CreatureScript SetPhase(PHASE_COMBAT_3); events.ScheduleEvent(EVENT_MUTATED_PLAGUE, 25000); events.CancelEvent(EVENT_UNSTABLE_EXPERIMENT); - summons.DespawnEntry(NPC_MUTATED_ABOMINATION_10); - summons.DespawnEntry(NPC_MUTATED_ABOMINATION_25); + summons.remove_if(AbominationDespawner(me)); break; default: break; @@ -514,7 +546,7 @@ class boss_professor_putricide : public CreatureScript void UpdateAI(uint32 const diff) { - if ((!UpdateVictim() && !(events.GetPhaseMask() & PHASE_MASK_NOT_SELF)) || !CheckInRoom()) + if ((!(events.GetPhaseMask() & PHASE_MASK_NOT_SELF) && !UpdateVictim()) || !CheckInRoom()) return; events.Update(diff); @@ -569,13 +601,15 @@ class boss_professor_putricide : public CreatureScript break; case EVENT_TEAR_GAS: me->GetMotionMaster()->MovePoint(POINT_TABLE, tablePos); + DoCast(me, SPELL_TEAR_GAS_PERIODIC_TRIGGER, true); break; case EVENT_RESUME_ATTACK: me->SetReactState(REACT_DEFENSIVE); AttackStart(me->getVictim()); // remove Tear Gas + me->RemoveAurasDueToSpell(SPELL_TEAR_GAS_PERIODIC_TRIGGER); instance->DoRemoveAurasDueToSpellOnPlayers(71615); - instance->DoRemoveAurasDueToSpellOnPlayers(71618); + DoCastAOE(SPELL_TEAR_GAS_CANCEL); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE); break; @@ -673,27 +707,36 @@ class npc_volatile_ooze : public CreatureScript public: npc_volatile_ooze() : CreatureScript("npc_volatile_ooze") { } - struct npc_volatile_oozeAI : public ScriptedAI + struct npc_putricide_oozeAI : public ScriptedAI { - npc_volatile_oozeAI(Creature* creature) : ScriptedAI(creature) + npc_putricide_oozeAI(Creature* creature) : ScriptedAI(creature) { _newTargetSelectTimer = 0; } void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) { - if (!_newTargetSelectTimer && sSpellMgr->GetSpellDifficultyId(spell->Id) == sSpellMgr->GetSpellDifficultyId(SPELL_OOZE_ERUPTION)) + if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_OOZE_ERUPTION, me)) + _newTargetSelectTimer = 1000; + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_TEAR_GAS_CREATURE) _newTargetSelectTimer = 1000; } void UpdateAI(uint32 const diff) { - if (!UpdateVictim()) + if (!UpdateVictim() && !_newTargetSelectTimer) return; if (!_newTargetSelectTimer) return; + if (me->HasAura(SPELL_TEAR_GAS_CREATURE)) + return; + if (_newTargetSelectTimer <= diff) { _newTargetSelectTimer = 0; @@ -704,13 +747,68 @@ class npc_volatile_ooze : public CreatureScript } private: - // no need to use EventMap for just one event uint32 _newTargetSelectTimer; }; CreatureAI* GetAI(Creature* creature) const { - return GetIcecrownCitadelAI<npc_volatile_oozeAI>(creature); + return GetIcecrownCitadelAI<npc_putricide_oozeAI>(creature); + } +}; + +class npc_gas_cloud : public CreatureScript +{ + public: + npc_gas_cloud() : CreatureScript("npc_gas_cloud") { } + + struct npc_gas_cloudAI : public ScriptedAI + { + npc_gas_cloudAI(Creature* creature) : ScriptedAI(creature) + { + _newTargetSelectTimer = 0; + } + + void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) + { + if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_EXPUNGED_GAS, me)) + _newTargetSelectTimer = 1000; + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_TEAR_GAS_CREATURE) + _newTargetSelectTimer = 1000; + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim() && !_newTargetSelectTimer) + return; + + DoMeleeAttackIfReady(); + + if (!_newTargetSelectTimer) + return; + + if (me->HasAura(SPELL_TEAR_GAS_CREATURE)) + return; + + if (_newTargetSelectTimer <= diff) + { + _newTargetSelectTimer = 0; + me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false); + } + else + _newTargetSelectTimer -= diff; + } + + private: + uint32 _newTargetSelectTimer; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetIcecrownCitadelAI<npc_gas_cloudAI>(creature); } }; @@ -729,8 +827,8 @@ class spell_putricide_gaseous_bloat : public SpellScriptLoader if (Unit* caster = GetCaster()) { target->RemoveAuraFromStack(GetSpellInfo()->Id, GetCasterGUID()); - if (!target->HasAura(GetId())&& caster->GetTypeId() == TYPEID_UNIT) - caster->ToCreature()->DespawnOrUnsummon(); + if (!target->HasAura(GetId())) + caster->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, caster, false); } } @@ -772,43 +870,56 @@ class spell_putricide_ooze_channel : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void SelectTarget(std::list<Unit*>& targetList) + void SelectTarget(std::list<WorldObject*>& targets) { - if (targetList.empty()) + if (targets.empty()) { FinishCast(SPELL_FAILED_NO_VALID_TARGETS); GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update return; } - Unit* target = Trinity::Containers::SelectRandomContainerElement(targetList); - targetList.clear(); - targetList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); _target = target; } - void SetTarget(std::list<Unit*>& targetList) + void SetTarget(std::list<WorldObject*>& targets) { - targetList.clear(); + targets.clear(); if (_target) - targetList.push_back(_target); + targets.push_back(_target); } void StartAttack() { GetCaster()->ClearUnitState(UNIT_STATE_CASTING); + GetCaster()->DeleteThreatList(); GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); + GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff + } + + // temporary, until SelectTarget are not called on empty lists + void CheckTarget() + { + if (_target) + return; + + FinishCast(SPELL_FAILED_NO_VALID_TARGETS); + GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack); + OnCast += SpellCastFn(spell_putricide_ooze_channel_SpellScript::CheckTarget); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -822,7 +933,7 @@ class ExactDistanceCheck public: ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return _source->GetExactDist2d(unit) > _dist; } @@ -841,15 +952,15 @@ class spell_putricide_slime_puddle : public SpellScriptLoader { PrepareSpellScript(spell_putricide_slime_puddle_SpellScript); - void ScaleRange(std::list<Unit*>& targets) + void ScaleRange(std::list<WorldObject*>& targets) { targets.remove_if(ExactDistanceCheck(GetCaster(), 2.5f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); } }; @@ -905,13 +1016,13 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader uint32 stage = GetCaster()->ToCreature()->AI()->GetData(DATA_EXPERIMENT_STAGE); Creature* target = NULL; std::list<Creature*> creList; - GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 100.0f); + GetCreatureListWithEntryInGrid(creList, GetCaster(), NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 200.0f); // 2 of them are spawned at green place - weird trick blizz for (std::list<Creature*>::iterator itr = creList.begin(); itr != creList.end(); ++itr) { target = *itr; std::list<Creature*> tmp; - GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 1.0f); + GetCreatureListWithEntryInGrid(tmp, target, NPC_ABOMINATION_WING_MAD_SCIENTIST_STALKER, 10.0f); if ((!stage && tmp.size() > 1) || (stage && tmp.size() == 1)) break; } @@ -931,42 +1042,6 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader } }; -class spell_putricide_ooze_summon : public SpellScriptLoader -{ - public: - spell_putricide_ooze_summon() : SpellScriptLoader("spell_putricide_ooze_summon") { } - - class spell_putricide_ooze_summon_AuraScript : public AuraScript - { - PrepareAuraScript(spell_putricide_ooze_summon_AuraScript); - - void HandleTriggerSpell(AuraEffect const* aurEff) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - { - uint32 triggerSpellId = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; - float x, y, z; - GetTarget()->GetPosition(x, y, z); - z = GetTarget()->GetMap()->GetHeight(GetTarget()->GetPhaseMask(), x, y, z, true, 25.0f); - x += 10.0f * cosf(caster->GetOrientation()); - y += 10.0f * sinf(caster->GetOrientation()); - caster->CastSpell(x, y, z, triggerSpellId, true, NULL, NULL, GetCasterGUID()); - } - } - - void Register() - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_putricide_ooze_summon_AuraScript::HandleTriggerSpell, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_putricide_ooze_summon_AuraScript(); - } -}; - class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader { public: @@ -1103,13 +1178,13 @@ class spell_putricide_eat_ooze : public SpellScriptLoader { PrepareSpellScript(spell_putricide_eat_ooze_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { if (targets.empty()) return; targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); - Unit* target = targets.front(); + WorldObject* target = targets.front(); targets.clear(); targets.push_back(target); } @@ -1136,7 +1211,7 @@ class spell_putricide_eat_ooze : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_putricide_eat_ooze_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_eat_ooze_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_eat_ooze_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); } }; @@ -1207,11 +1282,11 @@ class spell_putricide_mutation_init : public SpellScriptLoader SpellCastResult CheckRequirementInternal(SpellCustomErrors& extendedError) { - InstanceScript* instance = GetTargetUnit()->GetInstanceScript(); + InstanceScript* instance = GetExplTargetUnit()->GetInstanceScript(); if (!instance) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; - Creature* professor = ObjectAccessor::GetCreature(*GetTargetUnit(), instance->GetData64(DATA_PROFESSOR_PUTRICIDE)); + Creature* professor = ObjectAccessor::GetCreature(*GetExplTargetUnit(), instance->GetData64(DATA_PROFESSOR_PUTRICIDE)); if (!professor) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; @@ -1232,17 +1307,17 @@ class spell_putricide_mutation_init : public SpellScriptLoader SpellCastResult CheckRequirement() { - if (!GetTargetUnit()) + if (!GetExplTargetUnit()) return SPELL_FAILED_BAD_TARGETS; - if (GetTargetUnit()->GetTypeId() != TYPEID_PLAYER) + if (GetExplTargetUnit()->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_TARGET_NOT_PLAYER; SpellCustomErrors extension = SPELL_CUSTOM_ERROR_NONE; SpellCastResult result = CheckRequirementInternal(extension); if (result != SPELL_CAST_OK) { - Spell::SendCastResult(GetTargetUnit()->ToPlayer(), GetSpellInfo(), 0, result, extension); + Spell::SendCastResult(GetExplTargetUnit()->ToPlayer(), GetSpellInfo(), 0, result, extension); return result; } @@ -1383,15 +1458,15 @@ class spell_putricide_mutated_transformation_dmg : public SpellScriptLoader { PrepareSpellScript(spell_putricide_mutated_transformation_dmg_SpellScript); - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { if (Unit* owner = ObjectAccessor::GetUnit(*GetCaster(), GetCaster()->GetCreatorGUID())) - unitList.remove(owner); + targets.remove(owner); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_mutated_transformation_dmg_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_mutated_transformation_dmg_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -1429,14 +1504,15 @@ class spell_putricide_regurgitated_ooze : public SpellScriptLoader } }; -class spell_putricide_clear_mutated_plague : public SpellScriptLoader +// Removes aura with id stored in effect value +class spell_putricide_clear_aura_effect_value : public SpellScriptLoader { public: - spell_putricide_clear_mutated_plague() : SpellScriptLoader("spell_putricide_clear_mutated_plague") { } + spell_putricide_clear_aura_effect_value() : SpellScriptLoader("spell_putricide_clear_aura_effect_value") { } - class spell_putricide_clear_mutated_plague_SpellScript : public SpellScript + class spell_putricide_clear_aura_effect_value_SpellScript : public SpellScript { - PrepareSpellScript(spell_putricide_clear_mutated_plague_SpellScript); + PrepareSpellScript(spell_putricide_clear_aura_effect_value_SpellScript); void HandleScript(SpellEffIndex effIndex) { @@ -1447,13 +1523,13 @@ class spell_putricide_clear_mutated_plague : public SpellScriptLoader void Register() { - OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_mutated_plague_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHitTarget += SpellEffectFn(spell_putricide_clear_aura_effect_value_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; SpellScript* GetSpellScript() const { - return new spell_putricide_clear_mutated_plague_SpellScript(); + return new spell_putricide_clear_aura_effect_value_SpellScript(); } }; @@ -1492,12 +1568,12 @@ void AddSC_boss_professor_putricide() { new boss_professor_putricide(); new npc_volatile_ooze(); + new npc_gas_cloud(); new spell_putricide_gaseous_bloat(); new spell_putricide_ooze_channel(); new spell_putricide_slime_puddle(); new spell_putricide_slime_puddle_aura(); new spell_putricide_unstable_experiment(); - new spell_putricide_ooze_summon(); new spell_putricide_ooze_eruption_searcher(); new spell_putricide_choking_gas_bomb(); new spell_putricide_unbound_plague(); @@ -1508,6 +1584,6 @@ void AddSC_boss_professor_putricide() new spell_putricide_mutated_transformation(); new spell_putricide_mutated_transformation_dmg(); new spell_putricide_regurgitated_ooze(); - new spell_putricide_clear_mutated_plague(); + new spell_putricide_clear_aura_effect_value(); new spell_stinky_precious_decimate(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 85de6789784..5a0560293da 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -449,23 +449,23 @@ class spell_rotface_ooze_flood : public SpellScriptLoader GetHitUnit()->CastSpell(triggers.back(), uint32(GetEffectValue()), false, NULL, NULL, GetOriginalCaster() ? GetOriginalCaster()->GetGUID() : 0); } - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { // get 2 targets except 2 nearest - targetList.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); // .resize() runs pop_back(); - if (targetList.size() > 4) - targetList.resize(4); + if (targets.size() > 4) + targets.resize(4); - while (targetList.size() > 2) - targetList.pop_front(); + while (targets.size() > 2) + targets.pop_front(); } void Register() { OnEffectHitTarget += SpellEffectFn(spell_rotface_ooze_flood_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_ooze_flood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_ooze_flood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; @@ -490,21 +490,21 @@ class spell_rotface_mutated_infection : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { // remove targets with this aura already // tank is not on this list - targets.remove_if (Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(targets); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); targets.clear(); targets.push_back(target); _target = target; } - void ReplaceTargets(std::list<Unit*>& targets) + void ReplaceTargets(std::list<WorldObject*>& targets) { targets.clear(); if (_target) @@ -520,13 +520,13 @@ class spell_rotface_mutated_infection : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_rotface_mutated_infection_SpellScript::NotifyTargets); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -716,13 +716,13 @@ class spell_rotface_unstable_ooze_explosion : public SpellScriptLoader void CheckTarget(SpellEffIndex effIndex) { PreventHitDefaultEffect(EFFECT_0); - if (!GetTargetDest()) + if (!GetExplTargetDest()) return; uint32 triggered_spell_id = GetSpellInfo()->Effects[effIndex].TriggerSpell; float x, y, z; - GetTargetDest()->GetPosition(x, y, z); + GetExplTargetDest()->GetPosition(x, y, z); // let Rotface handle the cast - caster dies before this executes if (InstanceScript* script = GetCaster()->GetInstanceScript()) if (Creature* rotface = script->instance->GetCreature(script->GetData64(DATA_ROTFACE))) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index ab924d1b543..e3c0f2260df 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -19,6 +19,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" +#include "GridNotifiers.h" #include "icecrown_citadel.h" enum Texts @@ -167,7 +168,7 @@ class FrostwyrmLandEvent : public BasicEvent bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) { - _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest, 8.247422f); + _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest); return true; } @@ -183,7 +184,7 @@ class FrostBombExplosion : public BasicEvent bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) { - _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, true, NULL, NULL, _sindragosaGUID); + _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, false, NULL, NULL, _sindragosaGUID); _owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL); return true; } @@ -200,7 +201,7 @@ class boss_sindragosa : public CreatureScript struct boss_sindragosaAI : public BossAI { - boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA) + boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA), _summoned(false) { } @@ -220,7 +221,7 @@ class boss_sindragosa : public CreatureScript _isInAirPhase = false; _isThirdPhase = false; - if (instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -266,10 +267,13 @@ class boss_sindragosa : public CreatureScript { if (action == ACTION_START_FROSTWYRM) { + if (_summoned) + return; + + _summoned = true; if (TempSummon* summon = me->ToTempSummon()) summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN); - instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 255); if (me->isDead()) return; @@ -481,7 +485,7 @@ class boss_sindragosa : public CreatureScript Position pos; pos.Relocate(me); pos.m_positionZ += 17.0f; - me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos, 8.30078125f); + me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos); events.CancelEventGroup(EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_AIR_PHASE, 110000); break; @@ -523,7 +527,7 @@ class boss_sindragosa : public CreatureScript events.ScheduleEvent(EVENT_FROST_BREATH, urand(10000, 15000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(12000, 17000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000), EVENT_GROUP_LAND_PHASE); - me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos, 0.0f); + me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos); break; case EVENT_THIRD_PHASE_CHECK: { @@ -550,6 +554,7 @@ class boss_sindragosa : public CreatureScript uint8 _mysticBuffetStack; bool _isInAirPhase; bool _isThirdPhase; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -642,7 +647,7 @@ class npc_spinestalker : public CreatureScript struct npc_spinestalkerAI : public ScriptedAI { - npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) { } @@ -651,7 +656,7 @@ class npc_spinestalker : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -664,7 +669,7 @@ class npc_spinestalker : public CreatureScript _events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(8000, 12000)); me->SetReactState(REACT_DEFENSIVE); - if (_instance->GetData(DATA_SPINESTALKER) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -674,20 +679,22 @@ class npc_spinestalker : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) { if (action == ACTION_START_FROSTWYRM) { - _instance->SetData(DATA_SPINESTALKER, 255); + if (_summoned) + return; + + _summoned = true; if (me->isDead()) return; @@ -713,6 +720,7 @@ class npc_spinestalker : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetHomePosition(SpinestalkerLandPos); + me->SetFacingTo(SpinestalkerLandPos.GetOrientation()); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } @@ -753,6 +761,7 @@ class npc_spinestalker : public CreatureScript private: EventMap _events; InstanceScript* _instance; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -768,7 +777,7 @@ class npc_rimefang : public CreatureScript struct npc_rimefangAI : public ScriptedAI { - npc_rimefangAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + npc_rimefangAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) { } @@ -777,7 +786,7 @@ class npc_rimefang : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -790,7 +799,7 @@ class npc_rimefang : public CreatureScript me->SetReactState(REACT_DEFENSIVE); _icyBlastCounter = 0; - if (_instance->GetData(DATA_RIMEFANG) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -800,20 +809,22 @@ class npc_rimefang : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) { if (action == ACTION_START_FROSTWYRM) { - _instance->SetData(DATA_RIMEFANG, 255); + if (_summoned) + return; + + _summoned = true; if (me->isDead()) return; @@ -839,6 +850,7 @@ class npc_rimefang : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetHomePosition(RimefangLandPos); + me->SetFacingTo(RimefangLandPos.GetOrientation()); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); } @@ -906,6 +918,7 @@ class npc_rimefang : public CreatureScript EventMap _events; InstanceScript* _instance; uint8 _icyBlastCounter; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -932,7 +945,8 @@ class npc_sindragosa_trash : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -954,13 +968,8 @@ class npc_sindragosa_trash : public CreatureScript ScriptedAI::JustRespawned(); // Increase add count - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade - } - - void JustDied(Unit* /*killer*/) - { - // Decrease add count - _instance->SetData(_frostwyrmId, 0); + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void SetData(uint32 type, uint32 data) @@ -1033,12 +1042,31 @@ class spell_sindragosa_s_fury : public SpellScriptLoader bool Load() { _targetCount = 0; - return true; + + // This script should execute only in Icecrown Citadel + if (InstanceMap* instance = GetCaster()->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(ICCScriptName)) + return true; + + return false; + } + + void SelectDest() + { + if (Position* dest = const_cast<WorldLocation*>(GetExplTargetDest())) + { + float destX = float(rand_norm()) * 75.0f + 4350.0f; + float destY = float(rand_norm()) * 75.0f + 2450.0f; + float destZ = 205.0f; // random number close to ground, get exact in next call + GetCaster()->UpdateGroundPositionZ(destX, destY, destZ); + dest->Relocate(destX, destY, destZ); + } } - void CountTargets(std::list<Unit*>& unitList) + void CountTargets(std::list<WorldObject*>& targets) { - _targetCount = unitList.size(); + _targetCount = targets.size(); } void HandleDummy(SpellEffIndex effIndex) @@ -1049,10 +1077,10 @@ class spell_sindragosa_s_fury : public SpellScriptLoader return; float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask))); - uint32 minResistFactor = uint32((resistance / (resistance + 510.0f))* 10.0f) * 2; - uint32 randomResist = urand(0, (9 - minResistFactor) * 100)/100 + minResistFactor; + uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2; + uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor; - uint32 damage = (uint32(GetEffectValue()/_targetCount) * randomResist) / 10; + uint32 damage = (uint32(GetEffectValue() / _targetCount) * randomResist) / 10; SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpellInfo()->SchoolMask); damageInfo.damage = damage; @@ -1062,8 +1090,9 @@ class spell_sindragosa_s_fury : public SpellScriptLoader void Register() { + BeforeCast += SpellCastFn(spell_sindragosa_s_fury_SpellScript::SelectDest); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); OnEffectHitTarget += SpellEffectFn(spell_sindragosa_s_fury_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); } uint32 _targetCount; @@ -1080,9 +1109,11 @@ class UnchainedMagicTargetSelector public: UnchainedMagicTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return unit->getPowerType() != POWER_MANA; + if (Unit* unit = object->ToUnit()) + return unit->getPowerType() != POWER_MANA; + return true; } }; @@ -1095,7 +1126,7 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader { PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { unitList.remove_if(UnchainedMagicTargetSelector()); uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 2); @@ -1105,7 +1136,7 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -1288,7 +1319,7 @@ class MysticBuffetTargetFilter public: explicit MysticBuffetTargetFilter(Unit* caster) : _caster(caster) { } - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return !unit->IsWithinLOSInMap(_caster); } @@ -1306,14 +1337,14 @@ class spell_sindragosa_mystic_buffet : public SpellScriptLoader { PrepareSpellScript(spell_sindragosa_mystic_buffet_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if(MysticBuffetTargetFilter(GetCaster())); + targets.remove_if(MysticBuffetTargetFilter(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -1342,7 +1373,7 @@ class spell_rimefang_icy_blast : public SpellScriptLoader void HandleTriggerMissile(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - if (Position const* pos = GetTargetDest()) + if (Position const* pos = GetExplTargetDest()) if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICY_BLAST, *pos, TEMPSUMMON_TIMED_DESPAWN, 40000)) summon->CastSpell(summon, SPELL_ICY_BLAST_AREA, true); } @@ -1391,22 +1422,15 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();) - { - if ((*itr)->GetTypeId() != TYPEID_PLAYER) - unitList.erase(itr++); - else - ++itr; - } - - if (unitList.empty()) + targets.remove_if(Trinity::ObjectTypeIdCheck(TYPEID_PLAYER, false)); + if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } void HandleForcedCast(SpellEffIndex effIndex) @@ -1427,7 +1451,7 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_order_whelp_SpellScript::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); - OnUnitTargetSelect += SpellUnitTargetFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -1507,7 +1531,7 @@ class at_sindragosa_lair : public AreaTriggerScript if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_RIMEFANG))) rimefang->AI()->DoAction(ACTION_START_FROSTWYRM); - if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && instance->GetBossState(DATA_SINDRAGOSA) != DONE) + if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && !instance->GetData64(DATA_SINDRAGOSA) && instance->GetBossState(DATA_SINDRAGOSA) != DONE) { if (player->GetMap()->IsHeroic() && !instance->GetData(DATA_HEROIC_ATTEMPTS)) return true; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 2eb894a5153..a8657925131 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -138,7 +138,7 @@ enum Spells SPELL_IN_FROSTMOURNE_ROOM = 74276, SPELL_KILL_FROSTMOURNE_PLAYERS = 75127, SPELL_HARVESTED_SOUL = 72679, - SPELL_TRIGGER_VILE_SPIRIT_HEROIC = 73582, + SPELL_TRIGGER_VILE_SPIRIT_HEROIC = 73582, // TODO: Cast every 3 seconds during Frostmourne phase, targets a Wicked Spirit amd activates it // Frostmourne SPELL_LIGHTS_FAVOR = 69382, @@ -152,6 +152,7 @@ enum Spells SPELL_SUMMON_SPIRIT_BOMB_1 = 73581, // (Heroic) SPELL_SUMMON_SPIRIT_BOMB_2 = 74299, // (Heroic) SPELL_EXPLOSION = 73576, // Spirit Bomb (Heroic) + SPELL_HARVEST_SOUL_DAMAGE_AURA = 73655, // Outro SPELL_FURY_OF_FROSTMOURNE = 72350, @@ -221,7 +222,7 @@ enum Events EVENT_QUAKE_2 = 27, EVENT_VILE_SPIRITS = 28, EVENT_HARVEST_SOULS = 29, // heroic only - EVENT_WICKED_SPIRITS = 30, + EVENT_BERSERK = 30, EVENT_SOUL_RIP = 31, EVENT_DESTROY_SOUL = 32, EVENT_FROSTMOURNE_TALK_1 = 33, @@ -249,19 +250,18 @@ enum Events EVENT_OUTRO_TERENAS_TALK_2 = 55, EVENT_OUTRO_TALK_7 = 56, EVENT_OUTRO_TALK_8 = 57, - EVENT_BERSERK = 58, // Shambling Horror - EVENT_SHOCKWAVE = 59, - EVENT_ENRAGE = 60, + EVENT_SHOCKWAVE = 58, + EVENT_ENRAGE = 59, // Raging Spirit - EVENT_SOUL_SHRIEK = 61, + EVENT_SOUL_SHRIEK = 60, // Strangulate Vehicle (Harvest Soul) - EVENT_TELEPORT = 62, - EVENT_MOVE_TO_LICH_KING = 63, - EVENT_DESPAWN_SELF = 64, + EVENT_TELEPORT = 61, + EVENT_MOVE_TO_LICH_KING = 62, + EVENT_DESPAWN_SELF = 63, }; enum EventGroups @@ -391,7 +391,7 @@ class HeightDifferenceCheck { } - bool operator()(Unit* unit) const + bool operator()(WorldObject* unit) const { return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse; } @@ -475,6 +475,32 @@ class VileSpiritActivateEvent : public BasicEvent Creature* _owner; }; +class TriggerWickedSpirit : public BasicEvent +{ + public: + explicit TriggerWickedSpirit(Creature* owner) + : _owner(owner), _counter(13) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->CastCustomSpell(SPELL_TRIGGER_VILE_SPIRIT_HEROIC, SPELLVALUE_MAX_TARGETS, 1, NULL, true); + + if (--_counter) + { + _owner->m_Events.AddEvent(this, _owner->m_Events.CalculateTime(3000)); + return false; + } + + return true; + } + + private: + Creature* _owner; + uint32 _counter; +}; + class boss_the_lich_king : public CreatureScript { public: @@ -503,6 +529,8 @@ class boss_the_lich_king : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->GetMotionMaster()->MoveFall(); + if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) + frostmourne->DespawnOrUnsummon(); } void EnterCombat(Unit* target) @@ -601,8 +629,6 @@ class boss_the_lich_king : public CreatureScript summons.DoAction(ACTION_TELEPORT_BACK, pred); if (!IsHeroic()) Talk(SAY_LK_FROSTMOURNE_ESCAPE); - else - DoCastAOE(SPELL_TRIGGER_VILE_SPIRIT_HEROIC); break; } default: @@ -645,6 +671,8 @@ class boss_the_lich_king : public CreatureScript if (events.GetPhaseMask() & PHASE_MASK_ONE && !HealthAbovePct(70)) { events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition); return; } @@ -652,6 +680,8 @@ class boss_the_lich_king : public CreatureScript if (events.GetPhaseMask() & PHASE_MASK_TWO && !HealthAbovePct(40)) { events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition); return; } @@ -664,7 +694,8 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_OUTRO); summons.DespawnAll(); SendMusicToPlayers(MUSIC_FURY_OF_FROSTMOURNE); - DoCastAOE(SPELL_FURY_OF_FROSTMOURNE); + me->InterruptNonMeleeSpells(true); + me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); me->SetWalk(true); events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600, 0, PHASE_OUTRO); events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600, 0, PHASE_OUTRO); @@ -712,7 +743,6 @@ class boss_the_lich_king : public CreatureScript break; case NPC_FROSTMOURNE_TRIGGER: { - summons.Summon(summon); summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true); SendLightOverride(LIGHT_SOULSTORM, 10000); @@ -724,16 +754,11 @@ class boss_the_lich_king : public CreatureScript case NPC_VILE_SPIRIT: { summons.Summon(summon); - if (events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE) - { - TeleportSpirit(summon); - return; - } - summon->SetReactState(REACT_PASSIVE); summon->SetSpeed(MOVE_FLIGHT, 0.5f); summon->GetMotionMaster()->MoveRandom(10.0f); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); + if (!(events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE)) + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); return; } case NPC_STRANGULATE_VEHICLE: @@ -756,7 +781,6 @@ class boss_the_lich_king : public CreatureScript case NPC_VALKYR_SHADOWGUARD: case NPC_RAGING_SPIRIT: case NPC_VILE_SPIRIT: - case NPC_WICKED_SPIRIT: summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); break; default: @@ -802,8 +826,6 @@ class boss_the_lich_king : public CreatureScript me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); DoCast(me, SPELL_REMORSELESS_WINTER_1); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION); @@ -819,8 +841,6 @@ class boss_the_lich_king : public CreatureScript me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); DoCast(me, SPELL_REMORSELESS_WINTER_2); summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions @@ -992,10 +1012,6 @@ class boss_the_lich_king : public CreatureScript DoCastAOE(SPELL_VILE_SPIRITS); events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); break; - case EVENT_WICKED_SPIRITS: - DoCastAOE(SPELL_VILE_SPIRITS); - events.ScheduleEvent(EVENT_WICKED_SPIRITS, urand(35000, 40000), 0, PHASE_FROSTMOURNE); - break; case EVENT_HARVEST_SOULS: Talk(SAY_LK_HARVEST_SOUL); DoCastAOE(SPELL_HARVEST_SOULS); @@ -1003,7 +1019,6 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading) me->SetReactState(REACT_PASSIVE); me->AttackStop(); - events.ScheduleEvent(EVENT_WICKED_SPIRITS, events.GetNextEventTime(EVENT_VILE_SPIRITS) - events.GetTimer(), 0, PHASE_FROSTMOURNE); events.DelayEvents(50000, EVENT_GROUP_VILE_SPIRITS); events.RescheduleEvent(EVENT_DEFILE, 50000, 0, PHASE_THREE); events.RescheduleEvent(EVENT_SOUL_REAPER, urand(57000, 62000), 0, PHASE_THREE); @@ -1019,16 +1034,22 @@ class boss_the_lich_king : public CreatureScript if (!triggers.empty()) { triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true)); - Unit* spawner = triggers.front(); + Creature* spawner = triggers.front(); spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players + spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3000)); } for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i) { Creature* summon = ObjectAccessor::GetCreature(*me, *i); if (summon && summon->GetEntry() == NPC_VILE_SPIRIT) - TeleportSpirit(summon); + { + summon->m_Events.KillAllEvents(true); + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(50000)); + summon->GetMotionMaster()->MoveRandom(10.0f); + summon->SetReactState(REACT_PASSIVE); + } } } break; @@ -1099,22 +1120,6 @@ class boss_the_lich_king : public CreatureScript } private: - - void TeleportSpirit(Creature* summon) - { - float dist = me->GetObjectSize() + (15.0f - me->GetObjectSize()) * float(rand_norm()); - float angle = float(rand_norm()) * float(2.0f * M_PI); - Position dest = TerenasSpawnHeroic; - me->MovePosition(dest, dist, angle); - dest.m_positionZ += 15.0f; - summon->UpdateEntry(NPC_WICKED_SPIRIT); - summon->SetReactState(REACT_PASSIVE); - summon->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation()); - summon->SetSpeed(MOVE_FLIGHT, 0.5f); - summon->m_Events.KillAllEvents(true); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(1000)); - } - void SendMusicToPlayers(uint32 musicId) const { WorldPacket data(SMSG_PLAY_MUSIC, 4); @@ -1635,8 +1640,13 @@ class npc_strangulate_vehicle : public CreatureScript return; if (TempSummon* summ = me->ToTempSummon()) + { if (Unit* summoner = summ->GetSummoner()) + { DoCast(summoner, SPELL_HARVEST_SOUL_TELEPORT_BACK); + summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOUL_DAMAGE_AURA); + } + } if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING))) lichKing->AI()->SummonedCreatureDespawn(me); @@ -1993,6 +2003,10 @@ class npc_broken_frostmourne : public CreatureScript _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6000, 0, PHASE_OUTRO); } + void EnterEvadeMode() + { + } + void UpdateAI(uint32 const diff) { UpdateVictim(); @@ -2274,7 +2288,7 @@ class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic_SpellScript); - void CheckTargetCount(std::list<Unit*>& targets) + void CheckTargetCount(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2284,7 +2298,7 @@ class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -2308,10 +2322,10 @@ class spell_the_lich_king_quake : public SpellScriptLoader return GetCaster()->GetInstanceScript() != NULL; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetData64(DATA_ARTHAS_PLATFORM))) - unitList.remove_if(HeightDifferenceCheck(platform, 5.0f, false)); + targets.remove_if(HeightDifferenceCheck(platform, 5.0f, false)); } void HandleSendEvent(SpellEffIndex /*effIndex*/) @@ -2322,7 +2336,7 @@ class spell_the_lich_king_quake : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); OnEffectHit += SpellEffectFn(spell_the_lich_king_quake_SpellScript::HandleSendEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT); } }; @@ -2349,7 +2363,7 @@ class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader return true; } - void CheckTargetCount(std::list<Unit*>& unitList) + void CheckTargetCount(std::list<WorldObject*>& unitList) { if (unitList.empty()) return; @@ -2357,12 +2371,16 @@ class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader // if there is at least one affected target cast the explosion GetCaster()->CastSpell(GetCaster(), SPELL_ICE_BURST, true); if (GetCaster()->GetTypeId() == TYPEID_UNIT) + { + GetCaster()->ToCreature()->SetReactState(REACT_PASSIVE); + GetCaster()->AttackStop(); GetCaster()->ToCreature()->DespawnOrUnsummon(500); + } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -2411,7 +2429,7 @@ class ExactDistanceCheck public: ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) { return _source->GetExactDist2d(unit) > _dist; } @@ -2430,7 +2448,7 @@ class spell_the_lich_king_defile : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_defile_SpellScript); - void CorrectRange(std::list<Unit*>& targets) + void CorrectRange(std::list<WorldObject*>& targets) { targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); } @@ -2446,8 +2464,8 @@ class spell_the_lich_king_defile : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnHit += SpellHitFn(spell_the_lich_king_defile_SpellScript::ChangeDamageAndGrow); } }; @@ -2470,16 +2488,20 @@ class spell_the_lich_king_summon_into_air : public SpellScriptLoader void ModDestHeight(SpellEffIndex effIndex) { static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f}; - WorldLocation* dest = const_cast<WorldLocation*>(GetTargetDest()); + WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest()); dest->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); // spirit bombs get higher if (GetSpellInfo()->Effects[effIndex].MiscValue == NPC_SPIRIT_BOMB) + { dest->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); + } } void Register() { - OnEffectLaunch += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + OnEffectHit += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); } }; @@ -2545,26 +2567,26 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader return true; } - void SelectTarget(std::list<Unit*>& unitList) + void SelectTarget(std::list<WorldObject*>& targets) { - if (unitList.empty()) + if (targets.empty()) return; - unitList.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); - if (unitList.empty()) + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + if (targets.empty()) return; - _target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(_target); + _target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(_target); GetCaster()->GetAI()->SetGUID(_target->GetGUID()); } - void ReplaceTarget(std::list<Unit*>& unitList) + void ReplaceTarget(std::list<WorldObject*>& targets) { - unitList.clear(); + targets.clear(); if (_target) - unitList.push_back(_target); + targets.push_back(_target); } void HandleScript(SpellEffIndex effIndex) @@ -2575,12 +2597,12 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_valkyr_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -2727,7 +2749,7 @@ class spell_the_lich_king_vile_spirits_visual : public SpellScriptLoader void ModDestHeight(SpellEffIndex /*effIndex*/) { Position offset = {0.0f, 0.0f, 15.0f, 0.0f}; - const_cast<WorldLocation*>(GetTargetDest())->RelocateOffset(offset); + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); } void Register() @@ -2757,7 +2779,7 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2778,11 +2800,11 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -2805,7 +2827,7 @@ class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptL return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void CheckTargetCount(std::list<Unit*>& targets) + void CheckTargetCount(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2822,7 +2844,7 @@ class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptL void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } Unit* _target; @@ -2954,6 +2976,15 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f)) spawner->RemoveAllAuras(); + + std::list<Creature*> spirits; + GetCaster()->GetCreatureListWithEntryInGrid(spirits, NPC_WICKED_SPIRIT, 200.0f); + for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr) + { + (*itr)->m_Events.KillAllEvents(true); + (*itr)->SetReactState(REACT_PASSIVE); + (*itr)->AI()->EnterEvadeMode(); + } } void RemoveAura() @@ -3046,23 +3077,18 @@ class spell_the_lich_king_trigger_vile_spirit : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit_SpellScript); - void TeleportOutside() + void ActivateSpirit() { Creature* target = GetHitCreature(); if (!target) return; - Position dest; - Position offset; - TerenasSpawnHeroic.GetPositionOffsetTo(*target, offset); - GetCaster()->GetPosition(&dest); - dest.RelocateOffset(offset); - target->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation()); + VileSpiritActivateEvent(target).Execute(0, 0); } void Register() { - OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::TeleportOutside); + OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::ActivateSpirit); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index ed1ca4d20fb..826c62a4390 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -262,7 +262,7 @@ class ValithriaDespawner : public BasicEvent if (CreatureData const* data = creature->GetCreatureData()) creature->SetPosition(data->posX, data->posY, data->posZ, data->orientation); - creature->ForcedDespawn(); + creature->DespawnOrUnsummon(); creature->SetCorpseDelay(corpseDelay); creature->SetRespawnDelay(respawnDelay); @@ -1013,11 +1013,8 @@ class npc_dream_portal : public CreatureScript { } - void DoAction(int32 const action) + void OnSpellClick(Unit* /*clicker*/) { - if (action != EVENT_SPELLCLICK) - return; - _used = true; me->DespawnOrUnsummon(); } @@ -1087,7 +1084,7 @@ class npc_dream_cloud : public CreatureScript me->GetMotionMaster()->MoveIdle(); // must use originalCaster the same for all clouds to allow stacking me->CastSpell(me, EMERALD_VIGOR, false, NULL, NULL, _instance->GetData64(DATA_VALITHRIA_DREAMWALKER)); - me->ForcedDespawn(100); + me->DespawnOrUnsummon(100); break; default: break; @@ -1190,13 +1187,13 @@ class spell_dreamwalker_summoner : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { - targets.remove_if (Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(targets); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); targets.clear(); targets.push_back(target); } @@ -1212,7 +1209,7 @@ class spell_dreamwalker_summoner : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dreamwalker_summoner_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dreamwalker_summoner_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summoner_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); } }; @@ -1241,7 +1238,7 @@ class spell_dreamwalker_summon_suppresser : public SpellScriptLoader std::list<Creature*> summoners; GetCreatureListWithEntryInGrid(summoners, caster, NPC_WORLD_TRIGGER, 100.0f); - summoners.remove_if (Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); + summoners.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); Trinity::Containers::RandomResizeList(summoners, 2); if (summoners.empty()) return; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index c99fde1739c..17e33912a86 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -19,6 +19,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" +#include "PassiveAI.h" #include "Cell.h" #include "CellImpl.h" #include "GridNotifiers.h" @@ -158,6 +159,9 @@ enum Spells SPELL_FEL_IRON_BOMB_UNDEAD = 71787, SPELL_MACHINE_GUN_UNDEAD = 71788, SPELL_ROCKET_LAUNCH_UNDEAD = 71786, + + // Invisible Stalker (Float, Uninteractible, LargeAOI) + SPELL_SOUL_MISSILE = 72585, }; // Helper defines @@ -248,6 +252,9 @@ enum EventTypes EVENT_RUPERT_FEL_IRON_BOMB = 52, EVENT_RUPERT_MACHINE_GUN = 53, EVENT_RUPERT_ROCKET_LAUNCH = 54, + + // Invisible Stalker (Float, Uninteractible, LargeAOI) + EVENT_SOUL_MISSILE = 55, }; enum DataTypesICC @@ -346,7 +353,7 @@ class FrostwingGauntletRespawner if (CreatureData const* data = creature->GetCreatureData()) creature->SetPosition(data->posX, data->posY, data->posZ, data->orientation); - creature->ForcedDespawn(); + creature->DespawnOrUnsummon(); creature->SetCorpseDelay(corpseDelay); creature->SetRespawnDelay(respawnDelay); @@ -796,7 +803,8 @@ class boss_sister_svalna : public CreatureScript { _JustReachedHome(); me->SetReactState(REACT_PASSIVE); - me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetHover(false); } void DoAction(int32 const action) @@ -838,13 +846,14 @@ class boss_sister_svalna : public CreatureScript void MovementInform(uint32 type, uint32 id) { - if (type != POINT_MOTION_TYPE || id != POINT_LAND) + if (type != EFFECT_MOTION_TYPE || id != POINT_LAND) return; _isEventInProgress = false; me->setActive(false); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); - me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetHover(false); } void SpellHitTarget(Unit* target, SpellInfo const* spell) @@ -1288,7 +1297,7 @@ struct npc_argent_captainAI : public ScriptedAI if (spell->Id == SPELL_REVIVE_CHAMPION && !IsUndead) { IsUndead = true; - me->setDeathState(JUST_ALIVED); + me->setDeathState(JUST_RESPAWNED); uint32 newEntry = 0; switch (me->GetEntry()) { @@ -1666,6 +1675,56 @@ class npc_impaling_spear : public CreatureScript } }; +class npc_arthas_teleport_visual : public CreatureScript +{ + public: + npc_arthas_teleport_visual() : CreatureScript("npc_arthas_teleport_visual") { } + + struct npc_arthas_teleport_visualAI : public NullCreatureAI + { + npc_arthas_teleport_visualAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) + { + } + + void Reset() + { + _events.Reset(); + if (_instance->GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && + _instance->GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && + _instance->GetBossState(DATA_SINDRAGOSA) == DONE) + _events.ScheduleEvent(EVENT_SOUL_MISSILE, urand(1000, 6000)); + } + + void UpdateAI(uint32 const diff) + { + if (_events.Empty()) + return; + + _events.Update(diff); + + if (_events.ExecuteEvent() == EVENT_SOUL_MISSILE) + { + DoCastAOE(SPELL_SOUL_MISSILE); + _events.ScheduleEvent(EVENT_SOUL_MISSILE, urand(5000, 7000)); + } + } + + private: + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + // Distance from the center of the spire + if (creature->GetExactDist2d(4357.052f, 2769.421f) < 100.0f && creature->GetHomePosition().GetPositionZ() < 315.0f) + return GetIcecrownCitadelAI<npc_arthas_teleport_visualAI>(creature); + + // Default to no script + return NULL; + } +}; + class spell_icc_stoneform : public SpellScriptLoader { public: @@ -1775,15 +1834,15 @@ class DeathPlagueTargetSelector public: explicit DeathPlagueTargetSelector(Unit* caster) : _caster(caster) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - if (unit == _caster) + if (object == _caster) return true; - if (unit->GetTypeId() != TYPEID_PLAYER) + if (object->GetTypeId() != TYPEID_PLAYER) return true; - if (unit->HasAura(SPELL_RECENTLY_INFECTED) || unit->HasAura(SPELL_DEATH_PLAGUE_AURA)) + if (object->ToUnit()->HasAura(SPELL_RECENTLY_INFECTED) || object->ToUnit()->HasAura(SPELL_DEATH_PLAGUE_AURA)) return true; return false; @@ -1809,25 +1868,25 @@ class spell_frost_giant_death_plague : public SpellScriptLoader } // First effect - void CountTargets(std::list<Unit*>& unitList) + void CountTargets(std::list<WorldObject*>& targets) { - unitList.remove(GetCaster()); - _failed = unitList.empty(); + targets.remove(GetCaster()); + _failed = targets.empty(); } // Second effect - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { // Select valid targets for jump - unitList.remove_if (DeathPlagueTargetSelector(GetCaster())); - if (!unitList.empty()) + targets.remove_if(DeathPlagueTargetSelector(GetCaster())); + if (!targets.empty()) { - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } - unitList.push_back(GetCaster()); + targets.push_back(GetCaster()); } void HandleScript(SpellEffIndex effIndex) @@ -1841,8 +1900,8 @@ class spell_frost_giant_death_plague : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_frost_giant_death_plague_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_frost_giant_death_plague_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frost_giant_death_plague_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frost_giant_death_plague_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY); OnEffectHitTarget += SpellEffectFn(spell_frost_giant_death_plague_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } @@ -1891,9 +1950,11 @@ class spell_icc_harvest_blight_specimen : public SpellScriptLoader class AliveCheck { public: - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return unit->isAlive(); + if (Unit* unit = object->ToUnit()) + return unit->isAlive(); + return true; } }; @@ -1906,10 +1967,10 @@ class spell_svalna_revive_champion : public SpellScriptLoader { PrepareSpellScript(spell_svalna_revive_champion_SpellScript); - void RemoveAliveTarget(std::list<Unit*>& unitList) + void RemoveAliveTarget(std::list<WorldObject*>& targets) { - unitList.remove_if(AliveCheck()); - Trinity::Containers::RandomResizeList(unitList, 2); + targets.remove_if(AliveCheck()); + Trinity::Containers::RandomResizeList(targets, 2); } void Land(SpellEffIndex /*effIndex*/) @@ -1921,15 +1982,15 @@ class spell_svalna_revive_champion : public SpellScriptLoader Position pos; caster->GetPosition(&pos); caster->GetNearPosition(pos, 5.0f, 0.0f); - pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 20.0f); - pos.m_positionZ += 0.05f; + //pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), caster->GetPositionZ(), true, 50.0f); + //pos.m_positionZ += 0.05f; caster->SetHomePosition(pos); - caster->GetMotionMaster()->MovePoint(POINT_LAND, pos); + caster->GetMotionMaster()->MoveLand(POINT_LAND, pos); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_svalna_revive_champion_SpellScript::RemoveAliveTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_svalna_revive_champion_SpellScript::RemoveAliveTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); OnEffectHit += SpellEffectFn(spell_svalna_revive_champion_SpellScript::Land, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; @@ -1972,6 +2033,33 @@ class spell_svalna_remove_spear : public SpellScriptLoader } }; +class spell_icc_soul_missile : public SpellScriptLoader +{ + public: + spell_icc_soul_missile() : SpellScriptLoader("spell_icc_soul_missile") { } + + class spell_icc_soul_missile_SpellScript : public SpellScript + { + PrepareSpellScript(spell_icc_soul_missile_SpellScript); + + void RelocateDest() + { + static Position const offset = {0.0f, 0.0f, 200.0f, 0.0f}; + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + } + + void Register() + { + OnCast += SpellCastFn(spell_icc_soul_missile_SpellScript::RelocateDest); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_icc_soul_missile_SpellScript(); + } +}; + class at_icc_saurfang_portal : public AreaTriggerScript { public: @@ -2061,6 +2149,7 @@ void AddSC_icecrown_citadel() new npc_captain_rupert(); new npc_frostwing_vrykul(); new npc_impaling_spear(); + new npc_arthas_teleport_visual(); new spell_icc_stoneform(); new spell_icc_sprit_alarm(); new spell_frost_giant_death_plague(); @@ -2068,6 +2157,7 @@ void AddSC_icecrown_citadel() new spell_trigger_spell_from_caster("spell_svalna_caress_of_death", SPELL_IMPALING_SPEAR_KILL); new spell_svalna_revive_champion(); new spell_svalna_remove_spear(); + new spell_icc_soul_missile(); new at_icc_saurfang_portal(); new at_icc_shutdown_traps(); new at_icc_start_blood_quickening(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 224777c3db7..31639a698ef 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -51,6 +51,7 @@ enum SharedSpells SPELL_GREEN_BLIGHT_RESIDUE = 72145, // The Lich King + SPELL_ARTHAS_TELEPORTER_CEREMONY = 72915, SPELL_FROSTMOURNE_TELEPORT_VISUAL = 73078, }; @@ -275,6 +276,9 @@ enum CreaturesIds NPC_WORLD_TRIGGER_INFINITE_AOI = 36171, NPC_SPIRIT_BOMB = 39189, NPC_FROSTMOURNE_TRIGGER = 38584, + + // Generic + NPC_INVISIBLE_STALKER = 30298, }; enum GameObjectsIds @@ -345,6 +349,7 @@ enum GameObjectsIds GO_SIGIL_OF_THE_FROSTWING = 202181, // The Lich King + GO_SCOURGE_TRANSPORTER_LK = 202223, GO_ARTHAS_PLATFORM = 202161, GO_ARTHAS_PRECIPICE = 202078, GO_DOODAD_ICECROWN_THRONEFROSTYWIND01 = 202188, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index cb83efc748f..650f426d29c 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -130,6 +130,7 @@ class instance_icecrown_citadel : public InstanceMapScript SindragosaGUID = 0; SpinestalkerGUID = 0; RimefangGUID = 0; + TheLichKingTeleportGUID = 0; TheLichKingGUID = 0; HighlordTirionFordringGUID = 0; TerenasMenethilGUID = 0; @@ -138,9 +139,6 @@ class instance_icecrown_citadel : public InstanceMapScript FrozenThroneEdgeGUID = 0; FrozenThroneWindGUID = 0; FrozenThroneWarningGUID = 0; - FrostwyrmCount = 0; - SpinestalkerTrashCount = 0; - RimefangTrashCount = 0; IsBonedEligible = true; IsOozeDanceEligible = true; IsNauseaEligible = true; @@ -283,6 +281,11 @@ class instance_icecrown_citadel : public InstanceMapScript case NPC_RIMEFANG: RimefangGUID = creature->GetGUID(); break; + case NPC_INVISIBLE_STALKER: + // Teleporter visual at center + if (creature->GetExactDist2d(4357.052f, 2769.421f) < 10.0f) + creature->CastSpell(creature, SPELL_ARTHAS_TELEPORTER_CEREMONY, false); + break; case NPC_THE_LICH_KING: TheLichKingGUID = creature->GetGUID(); break; @@ -293,11 +296,22 @@ class instance_icecrown_citadel : public InstanceMapScript case NPC_TERENAS_MENETHIL_FROSTMOURNE_H: TerenasMenethilGUID = creature->GetGUID(); break; + case NPC_WICKED_SPIRIT: + // Remove corpse as soon as it dies (and respawn 10 seconds later) + creature->SetCorpseDelay(0); + creature->SetReactState(REACT_PASSIVE); + break; default: break; } } + void OnCreatureRemove(Creature* creature) + { + if (creature->GetEntry() == NPC_SINDRAGOSA) + SindragosaGUID = 0; + } + // Weekly quest spawn prevention uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) { @@ -347,6 +361,43 @@ class instance_icecrown_citadel : public InstanceMapScript if (Creature* crok = instance->GetCreature(CrokScourgebaneGUID)) crok->AI()->SetGUID(creature->GetGUID(), ACTION_VRYKUL_DEATH); break; + case NPC_FROSTWING_WHELP: + if (FrostwyrmGUIDs.empty()) + return; + + if (creature->AI()->GetData(1/*DATA_FROSTWYRM_OWNER*/) == DATA_SPINESTALKER) + { + SpinestalkerTrash.erase(creature->GetDBTableGUIDLow()); + if (SpinestalkerTrash.empty()) + if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + else + { + RimefangTrash.erase(creature->GetDBTableGUIDLow()); + if (RimefangTrash.empty()) + if (Creature* spinestalk = instance->GetCreature(RimefangGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + break; + case NPC_RIMEFANG: + case NPC_SPINESTALKER: + { + if (instance->IsHeroic() && !HeroicAttempts) + return; + + if (GetBossState(DATA_SINDRAGOSA) == DONE) + return; + + FrostwyrmGUIDs.erase(creature->GetDBTableGUIDLow()); + if (FrostwyrmGUIDs.empty()) + { + instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); + if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) + boss->AI()->DoAction(ACTION_START_FROSTWYRM); + } + break; + } default: break; } @@ -460,6 +511,11 @@ class instance_icecrown_citadel : public InstanceMapScript go->SetLootRecipient(valithria->GetLootRecipient()); go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN); break; + case GO_SCOURGE_TRANSPORTER_LK: + TheLichKingTeleportGUID = go->GetGUID(); + if (GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && GetBossState(DATA_SINDRAGOSA) == DONE) + go->SetGoState(GO_STATE_ACTIVE); + break; case GO_ARTHAS_PLATFORM: // this enables movement at The Frozen Throne, when printed this value is 0.000000f // however, when represented as integer client will accept only this value @@ -538,11 +594,11 @@ class instance_icecrown_citadel : public InstanceMapScript switch (type) { case DATA_SINDRAGOSA_FROSTWYRMS: - return FrostwyrmCount; + return FrostwyrmGUIDs.size(); case DATA_SPINESTALKER: - return SpinestalkerTrashCount; + return SpinestalkerTrash.size(); case DATA_RIMEFANG: - return RimefangTrashCount; + return RimefangTrash.size(); case DATA_COLDFLAME_JETS: return ColdflameJetsState; case DATA_TEAM_IN_INSTANCE: @@ -698,6 +754,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_PROFESSOR_PUTRICIDE: HandleGameObject(PlagueSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -712,6 +770,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_BLOOD_QUEEN_LANA_THEL: HandleGameObject(BloodwingSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -730,6 +790,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_SINDRAGOSA: HandleGameObject(FrostwingSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -798,89 +860,14 @@ class instance_icecrown_citadel : public InstanceMapScript IsOrbWhispererEligible = data ? true : false; break; case DATA_SINDRAGOSA_FROSTWYRMS: - { - if (FrostwyrmCount == 255) - return; - - if (instance->IsHeroic() && !HeroicAttempts) - return; - - if (GetBossState(DATA_SINDRAGOSA) == DONE) - return; - - switch (data) - { - case 0: - if (FrostwyrmCount) - { - --FrostwyrmCount; - if (!FrostwyrmCount) - { - instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); - if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) - boss->AI()->DoAction(ACTION_START_FROSTWYRM); - } - } - break; - case 1: - ++FrostwyrmCount; - break; - default: - FrostwyrmCount = data; - break; - } + FrostwyrmGUIDs.insert(data); break; - } case DATA_SPINESTALKER: - { - if (SpinestalkerTrashCount == 255) - return; - - switch (data) - { - case 0: - if (SpinestalkerTrashCount) - { - --SpinestalkerTrashCount; - if (!SpinestalkerTrashCount) - if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) - spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++SpinestalkerTrashCount; - break; - default: - SpinestalkerTrashCount = data; - break; - } + SpinestalkerTrash.insert(data); break; - } case DATA_RIMEFANG: - { - if (RimefangTrashCount == 255) - return; - - switch (data) - { - case 0: - if (RimefangTrashCount) - { - --RimefangTrashCount; - if (!RimefangTrashCount) - if (Creature* rime = instance->GetCreature(RimefangGUID)) - rime->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++RimefangTrashCount; - break; - default: - RimefangTrashCount = data; - break; - } + RimefangTrash.insert(data); break; - } case DATA_COLDFLAME_JETS: ColdflameJetsState = data; if (ColdflameJetsState == DONE) @@ -1095,6 +1082,28 @@ class instance_icecrown_citadel : public InstanceMapScript return true; } + void CheckLichKingAvailability() + { + if (GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && GetBossState(DATA_SINDRAGOSA) == DONE) + { + if (GameObject* teleporter = instance->GetGameObject(TheLichKingTeleportGUID)) + { + teleporter->SetGoState(GO_STATE_ACTIVE); + + std::list<Creature*> stalkers; + GetCreatureListWithEntryInGrid(stalkers, teleporter, NPC_INVISIBLE_STALKER, 100.0f); + if (stalkers.empty()) + return; + + stalkers.sort(Trinity::ObjectDistanceOrderPred(teleporter)); + stalkers.front()->CastSpell((Unit*)NULL, SPELL_ARTHAS_TELEPORTER_CEREMONY, false); + stalkers.pop_front(); + for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr) + (*itr)->AI()->Reset(); + } + } + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; @@ -1276,6 +1285,7 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 SindragosaGUID; uint64 SpinestalkerGUID; uint64 RimefangGUID; + uint64 TheLichKingTeleportGUID; uint64 TheLichKingGUID; uint64 HighlordTirionFordringGUID; uint64 TerenasMenethilGUID; @@ -1289,9 +1299,9 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 PillarsUnchainedGUID; uint32 TeamInInstance; uint32 ColdflameJetsState; - uint32 FrostwyrmCount; - uint32 SpinestalkerTrashCount; - uint32 RimefangTrashCount; + std::set<uint32> FrostwyrmGUIDs; + std::set<uint32> SpinestalkerTrash; + std::set<uint32> RimefangTrash; uint32 BloodQuickeningState; uint32 HeroicAttempts; uint16 BloodQuickeningMinutes; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 1671eab0b32..8901a61e79d 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" #define SAY_GREET RAND(-1533000, -1533004, -1533005, -1533006, -1533007) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 058c5b35e3a..636f2318712 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" enum Yells diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 17ed6a79c76..29a0a11af9b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "naxxramas.h" enum Horsemen @@ -26,6 +29,11 @@ enum Horsemen HORSEMEN_SIR, }; +enum Spells +{ + SPELL_MARK_DAMAGE = 28836 +}; + enum Events { EVENT_NONE, @@ -96,6 +104,7 @@ public: if (me->GetEntry() == MOB_HORSEMEN[i]) id = Horsemen(i); caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR); + encounterActionReset = false; } Horsemen id; @@ -395,7 +404,63 @@ public: }; +class spell_four_horsemen_mark : public SpellScriptLoader +{ + public: + spell_four_horsemen_mark() : SpellScriptLoader("spell_four_horsemen_mark") { } + + class spell_four_horsemen_mark_AuraScript : public AuraScript + { + PrepareAuraScript(spell_four_horsemen_mark_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + int32 damage; + switch (GetStackAmount()) + { + case 1: + damage = 0; + break; + case 2: + damage = 500; + break; + case 3: + damage = 1000; + break; + case 4: + damage = 1500; + break; + case 5: + damage = 4000; + break; + case 6: + damage = 12000; + break; + default: + damage = 20000 + 1000 * (GetStackAmount() - 7); + break; + } + if (damage) + caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget()); + } + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_four_horsemen_mark_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_four_horsemen_mark_AuraScript(); + } +}; + void AddSC_boss_four_horsemen() { new boss_four_horsemen(); + new spell_four_horsemen_mark(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 47dfaa7f772..69443b2824e 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" #define SPELL_MORTAL_WOUND 25646 diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 8d23de5427c..2ea234775c0 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -15,7 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "GridNotifiers.h" +#include "CombatAI.h" #include "naxxramas.h" enum Yells @@ -25,6 +29,7 @@ enum Yells SAY_DEATH = -1533042, SAY_TELEPORT = -1533043 }; + //Gothik enum Spells { @@ -36,8 +41,11 @@ enum Spells SPELL_INFORM_LIVE_RIDER = 27935, SPELL_INFORM_DEAD_TRAINEE = 27915, SPELL_INFORM_DEAD_KNIGHT = 27931, - SPELL_INFORM_DEAD_RIDER = 27937 + SPELL_INFORM_DEAD_RIDER = 27937, + + SPELL_SHADOW_MARK = 27825 }; + enum Creatures { MOB_LIVE_TRAINEE = 16124, @@ -192,7 +200,7 @@ class boss_gothik : public CreatureScript if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD) { - sLog->outError("Script Gothik: cannot summon triggers!"); + sLog->outError(LOG_FILTER_TSCR, "Script Gothik: cannot summon triggers!"); EnterEvadeMode(); return; } @@ -585,8 +593,35 @@ class mob_gothik_minion : public CreatureScript } }; +class spell_gothik_shadow_bolt_volley : public SpellScriptLoader +{ + public: + spell_gothik_shadow_bolt_volley() : SpellScriptLoader("spell_gothik_shadow_bolt_volley") { } + + class spell_gothik_shadow_bolt_volley_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gothik_shadow_bolt_volley_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_SHADOW_MARK)); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gothik_shadow_bolt_volley_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gothik_shadow_bolt_volley_SpellScript(); + } +}; + void AddSC_boss_gothik() { new boss_gothik(); new mob_gothik_minion(); + new spell_gothik_shadow_bolt_volley(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index 039b9b1e007..5a55a4f1c4b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" #define SPELL_BOMBARD_SLIME 28280 diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index d84cfb8949e..93eab5df237 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "naxxramas.h" #define SAY_AGGRO RAND(-1533109, -1533110, -1533111) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 4d6bfc578ff..10b40b490c4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -23,7 +23,10 @@ SDComment: VERIFY SCRIPT SDCategory: Naxxramas EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "naxxramas.h" enum Yells @@ -86,6 +89,7 @@ enum Spells SPELL_SHADOW_FISURE = 27810, SPELL_VOID_BLAST = 27812, SPELL_MANA_DETONATION = 27819, + SPELL_MANA_DETONATION_DAMAGE = 27820, SPELL_FROST_BLAST = 27808, SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect SPELL_KELTHUZAD_CHANNEL = 29423, @@ -299,7 +303,7 @@ public: for (itr = chained.begin(); itr != chained.end(); ++itr) { if (Player* charmed = Unit::GetPlayer(*me, (*itr).first)) - charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + charmed->SetObjectScale((*itr).second); } chained.clear(); @@ -347,7 +351,7 @@ public: for (itr = chained.begin(); itr != chained.end(); ++itr) { if (Player* player = Unit::GetPlayer(*me, (*itr).first)) - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + player->SetObjectScale((*itr).second); } chained.clear(); } @@ -512,7 +516,7 @@ public: DoCast(target, SPELL_CHAINS_OF_KELTHUZAD); float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X); chained.insert(std::make_pair(target->GetGUID(), scale)); - target->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); + target->SetObjectScale(scale * 2); events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm } } @@ -530,7 +534,7 @@ public: { if (!player->isCharmed()) { - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + player->SetObjectScale((*itr).second); std::map<uint64, float>::iterator next = itr; ++next; chained.erase(itr); @@ -773,6 +777,46 @@ class npc_kelthuzad_abomination : public CreatureScript } }; +class spell_kelthuzad_detonate_mana : public SpellScriptLoader +{ + public: + spell_kelthuzad_detonate_mana() : SpellScriptLoader("spell_kelthuzad_detonate_mana") { } + + class spell_kelthuzad_detonate_mana_AuraScript : public AuraScript + { + PrepareAuraScript(spell_kelthuzad_detonate_mana_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DETONATION_DAMAGE)) + return false; + return true; + } + + void HandleScript(AuraEffect const* aurEff) + { + PreventDefaultAction(); + + Unit* target = GetTarget(); + if (int32 mana = int32(target->GetMaxPower(POWER_MANA) / 10)) + { + mana = target->ModifyPower(POWER_MANA, -mana); + target->CastCustomSpell(SPELL_MANA_DETONATION_DAMAGE, SPELLVALUE_BASE_POINT0, -mana * 10, target, true, NULL, aurEff); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_kelthuzad_detonate_mana_AuraScript::HandleScript, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_kelthuzad_detonate_mana_AuraScript(); + } +}; + class achievement_just_cant_get_enough : public AchievementCriteriaScript { public: @@ -796,5 +840,6 @@ void AddSC_boss_kelthuzad() new boss_kelthuzad(); new at_kelthuzad_center(); new npc_kelthuzad_abomination(); + new spell_kelthuzad_detonate_mana(); new achievement_just_cant_get_enough(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index 58d3a4240b2..71623cb1959 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "naxxramas.h" enum Spells diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index 3c258f08030..8ec9bac7e86 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "PassiveAI.h" #include "naxxramas.h" enum Spells diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 75be596fd77..d106b99ace0 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" #define SAY_AGGRO RAND(-1533075, -1533076, -1533077) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index b826a530719..b1b57836a89 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" enum Spells diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp index e06aa6b03c5..d733cac001c 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" //Razuvious - NO TEXT sound only diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 37fb5f3f4a9..a2acf8a64da 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "naxxramas.h" #define EMOTE_BREATH -1533082 diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index ccc8e9a5663..e45700ebd72 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -456,10 +456,10 @@ class spell_thaddius_pos_neg_charge : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void HandleTargets(std::list<Unit*>& targetList) + void HandleTargets(std::list<WorldObject*>& targets) { uint8 count = 0; - for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + for (std::list<WorldObject*>::iterator ihit = targets.begin(); ihit != targets.end(); ++ihit) if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) if (Player* target = (*ihit)->ToPlayer()) if (target->HasAura(GetTriggeringSpell()->Id)) @@ -498,7 +498,7 @@ class spell_thaddius_pos_neg_charge : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnUnitTargetSelect += SpellUnitTargetFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 50eb52cc4c2..e806b60c848 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "naxxramas.h" const DoorData doorData[] = diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index ac5520b025a..9f5eb8d879a 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -27,7 +27,11 @@ Script Data End */ // Remove hack that re-adds targets to the aggro list after they enter to a vehicle when it works as expected // Improve whatever can be improved :) -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "PassiveAI.h" #include "eye_of_eternity.h" #include "ScriptedEscortAI.h" diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index fcb54985357..f6a12eee519 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "eye_of_eternity.h" class instance_eye_of_eternity : public InstanceMapScript diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp index 7552ba4f389..5e6dcbcd66e 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp @@ -16,7 +16,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "nexus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 5c1dee1d4e4..9e6930118f7 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -16,7 +16,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "nexus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp index ad188738c12..9602d1bc876 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp @@ -16,7 +16,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "nexus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp index c70db7d4ebc..9f9223f0161 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -16,7 +16,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "nexus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp index 5ea3eb32c1d..5463f6c9045 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp @@ -23,7 +23,8 @@ SDComment: Only Alliance Heroic SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #define SPELL_BATTLE_SHOUT 31403 #define SPELL_CHARGE 60067 diff --git a/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp index da4b49740c1..38808bc718d 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp @@ -23,7 +23,8 @@ SDComment: Only Horde Heroic SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #define SPELL_BATTLE_SHOUT 31403 #define SPELL_CHARGE 60067 diff --git a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp index 5af982bb694..5d430ae048d 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp @@ -16,7 +16,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "nexus.h" #define NUMBER_OF_ENCOUNTERS 4 @@ -57,6 +58,9 @@ public: Anomalus = 0; Keristrasza = 0; + AnomalusContainmentSphere = 0; + OrmoroksContainmentSphere = 0; + TelestrasContainmentSphere = 0; } void OnCreatureCreate(Creature* creature) diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp index bb75b789fff..035e1a9a6df 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "oculus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp index ab814a2ca22..708ed600933 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "oculus.h" //Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index b96d7c4aa84..791bc0180e5 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -22,7 +22,8 @@ SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, SDCategory: Instance Script EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "oculus.h" enum Spells diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp index 19a84fdae84..6d9450daf21 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "oculus.h" #include "MapManager.h" @@ -297,7 +300,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader { PrepareSpellScript(spell_varos_energize_core_area_enemySpellScript) - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { Creature* varos = GetCaster()->ToCreature(); if (!varos) @@ -308,7 +311,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader float orientation = CAST_AI(boss_varos::boss_varosAI, varos->AI())->GetCoreEnergizeOrientation(); - for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end();) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { Position pos; (*itr)->GetPosition(&pos); @@ -317,7 +320,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader float diff = fabs(orientation - angle); if (diff > 1.0f) - itr = targetList.erase(itr); + itr = targets.erase(itr); else ++itr; } @@ -325,7 +328,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_varos_energize_core_area_enemySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_varos_energize_core_area_enemySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -344,7 +347,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader { PrepareSpellScript(spell_varos_energize_core_area_entrySpellScript) - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { Creature* varos = GetCaster()->ToCreature(); if (!varos) @@ -355,7 +358,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader float orientation = CAST_AI(boss_varos::boss_varosAI, varos->AI())->GetCoreEnergizeOrientation(); - for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end();) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { Position pos; (*itr)->GetPosition(&pos); @@ -364,7 +367,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader float diff = fabs(orientation - angle); if (diff > 1.0f) - itr = targetList.erase(itr); + itr = targets.erase(itr); else ++itr; } @@ -372,7 +375,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_varos_energize_core_area_entrySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_varos_energize_core_area_entrySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index 46498a69c6f..ca4ae883747 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "InstanceScript.h" #include "oculus.h" #define MAX_ENCOUNTER 4 diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 23f55a3033b..1d8b5b986f6 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -15,7 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "oculus.h" #define GOSSIP_ITEM_DRAKES "So where do we go from here?" @@ -47,7 +51,9 @@ enum Drakes NPC_VERDISA = 27657, NPC_BELGARISTRASZ = 27658, - NPC_ETERNOS = 27659 + NPC_ETERNOS = 27659, + + SPELL_SHOCK_CHARGE = 49836, }; enum Says @@ -210,8 +216,40 @@ public: } }; +class spell_gen_stop_time : public SpellScriptLoader +{ +public: + spell_gen_stop_time() : SpellScriptLoader("spell_gen_stop_time") { } + + class spell_gen_stop_time_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_stop_time_AuraScript); + + void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (!caster) + return; + Unit* target = GetTarget(); + for (uint32 i = 0; i < 5; ++i) + caster->CastSpell(target, SPELL_SHOCK_CHARGE, false); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_gen_stop_time_AuraScript::Apply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_stop_time_AuraScript(); + } +}; + void AddSC_oculus() { new npc_oculus_drake(); new npc_image_belgaristrasz(); + new spell_gen_stop_time(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 9f39cecbb23..72ab5259693 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -23,7 +23,8 @@ SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieuten SDCategory: Halls of Lightning EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_lightning.h" enum eEnums diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index abdf5ecb1e1..d964f619a6e 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -20,7 +20,8 @@ * Comment: Timer check pending */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_lightning.h" enum Spells diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 2e2744baa3c..f42fd87c643 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -19,11 +19,13 @@ /* ScriptData SDName: Boss Loken SD%Complete: 60% -SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) +SDComment: Missing intro. SDCategory: Halls of Lightning EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "halls_of_lightning.h" enum eEnums @@ -73,23 +75,17 @@ public: InstanceScript* instance; - bool m_bIsAura; - uint32 m_uiArcLightning_Timer; uint32 m_uiLightningNova_Timer; - uint32 m_uiPulsingShockwave_Timer; uint32 m_uiResumePulsingShockwave_Timer; uint32 m_uiHealthAmountModifier; void Reset() { - m_bIsAura = false; - m_uiArcLightning_Timer = 15000; m_uiLightningNova_Timer = 20000; - m_uiPulsingShockwave_Timer = 2000; - m_uiResumePulsingShockwave_Timer = 15000; + m_uiResumePulsingShockwave_Timer = 1000; m_uiHealthAmountModifier = 1; @@ -116,7 +112,10 @@ public: Talk(SAY_DEATH); if (instance) + { instance->SetData(TYPE_LOKEN, DONE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA); + } } void KilledUnit(Unit* /*victim*/) @@ -130,44 +129,13 @@ public: if (!UpdateVictim()) return; - if (m_bIsAura) - { - // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer <= uiDiff) - { - Map* map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) - { - int32 dmg; - float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); - - dmg = DUNGEON_MODE(100, 150); // need to correct damage - if (m_fDist > 1.0f) // Further from 1 yard - dmg = int32(dmg*m_fDist); - - me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); - } - } - m_uiPulsingShockwave_Timer = 2000; - } else m_uiPulsingShockwave_Timer -= uiDiff; - } - else + if (m_uiResumePulsingShockwave_Timer) { if (m_uiResumePulsingShockwave_Timer <= uiDiff) { - //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support - m_bIsAura = true; + DoCast(me, SPELL_PULSING_SHOCKWAVE_N, true); m_uiResumePulsingShockwave_Timer = 0; } else @@ -190,7 +158,7 @@ public: Talk(EMOTE_NOVA); DoCast(me, SPELL_LIGHTNING_NOVA_N); - m_bIsAura = false; + me->RemoveAurasDueToSpell(DUNGEON_MODE<uint32>(SPELL_PULSING_SHOCKWAVE_N, SPELL_PULSING_SHOCKWAVE_H)); m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura m_uiLightningNova_Timer = urand(20000, 21000); } @@ -216,7 +184,39 @@ public: }; +class spell_loken_pulsing_shockwave : public SpellScriptLoader +{ + public: + spell_loken_pulsing_shockwave() : SpellScriptLoader("spell_loken_pulsing_shockwave") { } + + class spell_loken_pulsing_shockwave_SpellScript : public SpellScript + { + PrepareSpellScript(spell_loken_pulsing_shockwave_SpellScript); + + void CalculateDamage(SpellEffIndex /*effIndex*/) + { + if (!GetHitUnit()) + return; + + float distance = GetCaster()->GetDistance2d(GetHitUnit()); + if (distance > 1.0f) + SetHitDamage(int32(GetHitDamage() * distance)); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_loken_pulsing_shockwave_SpellScript::CalculateDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_loken_pulsing_shockwave_SpellScript(); + } +}; + void AddSC_boss_loken() { new boss_loken(); + new spell_loken_pulsing_shockwave(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 5c7bf0d1c1e..fe41e7a12dc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -23,7 +23,8 @@ SDComment: Event should be pretty close minus a few visual flaws SDCategory: Halls of Lightning EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_lightning.h" enum eEnums diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp index f25be6dae0d..93b246e9ddc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -23,7 +23,8 @@ SDComment: All ready. SDCategory: Halls of Lightning EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "halls_of_lightning.h" /* Halls of Lightning encounters: diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index bc57ce21a4d..93bea92503c 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -23,7 +23,9 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "halls_of_stone.h" enum Spells @@ -157,17 +159,12 @@ public: DoScriptText(SAY_KILL, me); } - void SpellHitTarget(Unit* target, const SpellInfo* pSpell) + void SpellHitTarget(Unit* /*target*/, const SpellInfo* pSpell) { //this part should be in the core if (pSpell->Id == SPELL_SHATTER || pSpell->Id == H_SPELL_SHATTER) { - //this spell must have custom handling in the core, dealing damage based on distance - target->CastSpell(target, DUNGEON_MODE(SPELL_SHATTER_EFFECT, H_SPELL_SHATTER_EFFECT), true); - - if (target->HasAura(SPELL_STONED)) - target->RemoveAurasDueToSpell(SPELL_STONED); - + // todo: we need eventmap to kill this stuff //clear this, if we are still performing if (bIsSlam) { @@ -186,7 +183,74 @@ public: }; +class spell_krystallus_shatter : public SpellScriptLoader +{ + public: + spell_krystallus_shatter() : SpellScriptLoader("spell_krystallus_shatter") { } + + class spell_krystallus_shatter_SpellScript : public SpellScript + { + PrepareSpellScript(spell_krystallus_shatter_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->RemoveAurasDueToSpell(SPELL_STONED); + target->CastSpell((Unit*)NULL, SPELL_SHATTER_EFFECT, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_krystallus_shatter_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krystallus_shatter_SpellScript(); + } +}; + +class spell_krystallus_shatter_effect : public SpellScriptLoader +{ + public: + spell_krystallus_shatter_effect() : SpellScriptLoader("spell_krystallus_shatter_effect") { } + + class spell_krystallus_shatter_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_krystallus_shatter_effect_SpellScript); + + void CalculateDamage() + { + if (!GetHitUnit()) + return; + + float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + if (!radius) + return; + + float distance = GetCaster()->GetDistance2d(GetHitUnit()); + if (distance > 1.0f) + SetHitDamage(int32(GetHitDamage() * ((radius - distance) / radius))); + } + + void Register() + { + OnHit += SpellHitFn(spell_krystallus_shatter_effect_SpellScript::CalculateDamage); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krystallus_shatter_effect_SpellScript(); + } +}; + void AddSC_boss_krystallus() { new boss_krystallus(); + new spell_krystallus_shatter(); + new spell_krystallus_shatter_effect(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index 65711643827..8d113bce226 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_stone.h" enum Spells diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp index c2a8e905950..28052a57576 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "halls_of_stone.h" enum Spells diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index a608de5fcf3..a90c346e470 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "halls_of_stone.h" diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index ee5cb87dd85..869cf46e74d 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "halls_of_stone.h" #define MAX_ENCOUNTER 4 diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp deleted file mode 100644 index 2dd13e7ce07..00000000000 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2008-2012 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 "ulduar.h" - -#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821 - -enum Spells -{ - SPELL_ASCEND = 64487, - SPELL_BERSERK = 47008, - SPELL_BIG_BANG = 64443, - H_SPELL_BIG_BANG = 64584, - SPELL_COSMIC_SMASH = 62301, - H_SPELL_COSMIC_SMASH = 64598, - SPELL_PHASE_PUNCH = 64412, - SPELL_QUANTUM_STRIKE = 64395, - H_SPELL_QUANTUM_STRIKE = 64592, - SPELL_BLACK_HOLE_EXPLOSION = 64122, - SPELL_ARCANE_BARAGE = 64599, - H_SPELL_ARCANE_BARAGE = 64607 -}; - -enum Creatures -{ - CREATURE_COLLAPSING_STAR = 32955, - CREATURE_BLACK_HOLE = 32953, - CREATURE_LIVING_CONSTELLATION = 33052, - CREATURE_DARK_MATTER = 33089 -}; - -enum Yells -{ - SAY_AGGRO = -1603000, - SAY_SLAY_1 = -1603001, - SAY_SLAY_2 = -1603002, - SAY_ENGADED_FOR_FIRTS_TIME = -1603003, - SAY_PHASE_2 = -1603004, - SAY_SUMMON_COLLAPSING_STAR = -1603005, - SAY_DEATH_1 = -1603006, - SAY_DEATH_2 = -1603007, - SAY_DEATH_3 = -1603008, - SAY_DEATH_4 = -1603009, - SAY_DEATH_5 = -1603010, - SAY_BERSERK = -1603011, - SAY_BIG_BANG_1 = -1603012, - SAY_BIG_BANG_2 = -1603013, - SAY_TIMER_1 = -1603014, - SAY_TIMER_2 = -1603015, - SAY_TIMER_3 = -1603016, - SAY_SUMMON_1 = -1603017, - SAY_SUMMON_2 = -1603018, - SAY_SUMMON_3 = -1603019, -}; - -class boss_algalon : public CreatureScript -{ -public: - boss_algalon() : CreatureScript("boss_algalon") { } - - CreatureAI* GetAI(Creature* creature) const - { - return GetUlduarAI<boss_algalonAI>(creature); - } - - struct boss_algalonAI : public ScriptedAI - { - boss_algalonAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - Summon = false; // not in reset. intro speech done only once. - } - - InstanceScript* instance; - - std::list<uint64> m_lCollapsingStarGUIDList; - - uint32 Phase; - uint32 Ascend_Timer; - uint32 Berserk_Timer; - uint32 BigBang_Timer; - uint32 CosmicSmash_Timer; - uint32 PhasePunch_Timer; - uint32 QuantumStrike_Timer; - uint32 CollapsingStar_Timer; - uint32 uiPhase_timer; - uint32 uiStep; - - uint64 BlackHoleGUID; - - bool Enrage; - bool Summon; - - void EnterCombat(Unit* who) - { - if (Summon) - { - DoScriptText(SAY_AGGRO, me); - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoZoneInCombat(who->ToCreature()); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - uiStep = 1; - } - - if (instance) - instance->SetData(BOSS_ALGALON, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); - } - - void Reset() - { - Phase = 1; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (instance) - instance->SetData(BOSS_ALGALON, NOT_STARTED); - - BlackHoleGUID = 0; - - uiPhase_timer = 0; - Ascend_Timer = 480000; //8 minutes - QuantumStrike_Timer = urand(4000, 14000); - Berserk_Timer = 360000; //6 minutes - CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds - BigBang_Timer = 90000; - PhasePunch_Timer = 8000; - CosmicSmash_Timer = urand(30000, 60000); - Enrage = false; - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhase_timer = uiTimer; - ++uiStep; - } - - void DespawnCollapsingStar() - { - if (m_lCollapsingStarGUIDList.empty()) - return; - - for (std::list<uint64>::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr) - { - if (Creature* temp = Unit::GetCreature(*me, *itr)) - { - if (temp->isAlive()) - temp->DespawnOrUnsummon(); - } - } - m_lCollapsingStarGUIDList.clear(); - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == CREATURE_COLLAPSING_STAR) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (me->getVictim()) - summoned->AI()->AttackStart(target ? target : me->getVictim()); - m_lCollapsingStarGUIDList.push_back(summoned->GetGUID()); - } - } - - void SummonCollapsingStar(Unit* target) - { - DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me); - me->SummonCreature(CREATURE_COLLAPSING_STAR, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 100000); - me->SummonCreature(CREATURE_BLACK_HOLE, target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 && HealthBelowPct(20)) - { - Phase = 2; - DoScriptText(SAY_PHASE_2, me); - } - - if (HealthBelowPct(2)) - { - me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667f, -295.101166f, 417.321381f, 0, 0, 0, 0, 0, 0); - - // All of them. or random? - DoScriptText(SAY_DEATH_1, me); - DoScriptText(SAY_DEATH_2, me); - DoScriptText(SAY_DEATH_3, me); - DoScriptText(SAY_DEATH_4, me); - DoScriptText(SAY_DEATH_5, me); - - me->DisappearAndDie(); - - if (instance) - instance->SetData(BOSS_ALGALON, DONE); - - return; - } - - if (Phase == 1) - { - if (!Summon) - { - if (uiPhase_timer <= diff) - { - switch (uiStep) - { - case 1: - DoScriptText(SAY_SUMMON_1, me); - JumpToNextStep(3000); - break; - case 2: - DoScriptText(SAY_SUMMON_2, me); - JumpToNextStep(3000); - break; - case 3: - DoScriptText(SAY_SUMMON_3, me); - JumpToNextStep(3000); - break; - case 4: - DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me); - JumpToNextStep(3000); - break; - case 5: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - Summon = true; - break; - } - } else uiPhase_timer -= diff; - - return; - } - - if (QuantumStrike_Timer <= diff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE, H_SPELL_QUANTUM_STRIKE), true); - - QuantumStrike_Timer = urand(4000, 14000); - } else QuantumStrike_Timer -= diff; - - if (BigBang_Timer <= diff) - { - DoScriptText(RAND(SAY_BIG_BANG_1, SAY_BIG_BANG_2), me); - DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG, H_SPELL_BIG_BANG), true); - - BigBang_Timer = 90000; - } else BigBang_Timer -= diff; - - if (Ascend_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASCEND, true); - - Ascend_Timer = 480000; - } else Ascend_Timer -= diff; - - if (PhasePunch_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PHASE_PUNCH, true); - - PhasePunch_Timer = 8000; - } else PhasePunch_Timer -= diff; - - if (CosmicSmash_Timer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH, H_SPELL_COSMIC_SMASH), true); - - CosmicSmash_Timer = urand(30000, 60000); - } else CosmicSmash_Timer -= diff; - - if (Berserk_Timer <= diff) - { - DoScriptText(SAY_BERSERK, me); - DoCast(me->getVictim(), SPELL_BERSERK, true); - - Berserk_Timer = 360000; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } - - if (Phase == 2) - { - if (Enrage) - { - if (Ascend_Timer <= diff) - { - DoCast(me, SPELL_ASCEND); - DoScriptText(SAY_BERSERK, me); - Ascend_Timer = urand(360000, 365000); - Enrage = false; - } else Ascend_Timer -= diff; - } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -//Collapsing Star -class mob_collapsing_star : public CreatureScript -{ -public: - mob_collapsing_star() : CreatureScript("mob_collapsing_star") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_collapsing_starAI(creature); - } - - struct mob_collapsing_starAI : public ScriptedAI - { - mob_collapsing_starAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - uint32 BlackHoleExplosion_Timer; - - void Reset() - { - BlackHoleExplosion_Timer = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BlackHoleExplosion_Timer <= diff) - { - me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false); - BlackHoleExplosion_Timer = 0; - } else BlackHoleExplosion_Timer -= diff; - } - }; - -}; - -void AddSC_boss_Algalon() -{ - new boss_algalon(); - new mob_collapsing_star(); -} diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp new file mode 100644 index 00000000000..7ee67060f97 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -0,0 +1,1374 @@ +/* + * Copyright (C) 2008-2012 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 "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "PassiveAI.h" +#include "GameObjectAI.h" +#include "MapManager.h" +#include "MoveSplineInit.h" +#include "ulduar.h" + +enum Texts +{ + SAY_BRANN_ALGALON_INTRO_1 = 0, + SAY_BRANN_ALGALON_INTRO_2 = 1, + SAY_BRANN_ALGALON_OUTRO = 2, + + SAY_ALGALON_INTRO_1 = 0, + SAY_ALGALON_INTRO_2 = 1, + SAY_ALGALON_INTRO_3 = 2, + SAY_ALGALON_START_TIMER = 3, + SAY_ALGALON_AGGRO = 4, + SAY_ALGALON_COLLAPSING_STAR = 5, + EMOTE_ALGALON_COLLAPSING_STAR = 6, + SAY_ALGALON_BIG_BANG = 7, + EMOTE_ALGALON_BIG_BANG = 8, + SAY_ALGALON_ASCEND = 9, + EMOTE_ALGALON_COSMIC_SMASH = 10, + SAY_ALGALON_PHASE_TWO = 11, + SAY_ALGALON_OUTRO_1 = 12, + SAY_ALGALON_OUTRO_2 = 13, + SAY_ALGALON_OUTRO_3 = 14, + SAY_ALGALON_OUTRO_4 = 15, + SAY_ALGALON_OUTRO_5 = 16, + SAY_ALGALON_DESPAWN_1 = 17, + SAY_ALGALON_DESPAWN_2 = 18, + SAY_ALGALON_DESPAWN_3 = 19, + SAY_ALGALON_KILL = 20, +}; + +enum Spells +{ + // Algalon the Observer + SPELL_ARRIVAL = 64997, + SPELL_RIDE_THE_LIGHTNING = 64986, + SPELL_SUMMON_AZEROTH = 64994, + SPELL_REORIGINATION = 64996, + SPELL_SUPERMASSIVE_FAIL = 65311, + SPELL_QUANTUM_STRIKE = 64395, + SPELL_PHASE_PUNCH = 64412, + SPELL_BIG_BANG = 64443, + SPELL_ASCEND_TO_THE_HEAVENS = 64487, + SPELL_COSMIC_SMASH = 62301, + SPELL_COSMIC_SMASH_TRIGGERED = 62304, + SPELL_COSMIC_SMASH_VISUAL_STATE = 62300, + SPELL_SELF_STUN = 65256, + SPELL_KILL_CREDIT = 65184, + SPELL_TELEPORT = 62940, + + // Algalon Stalker + SPELL_TRIGGER_3_ADDS = 62266, // Triggers Living Constellation + + // Living Constellation + SPELL_ARCANE_BARRAGE = 64599, + + // Collapsing Star + SPELL_COLLAPSE = 62018, + SPELL_BLACK_HOLE_SPAWN_VISUAL = 62003, + SPELL_SUMMON_BLACK_HOLE = 62189, + + // Black Hole + SPELL_BLACK_HOLE_TRIGGER = 62185, + SPELL_CONSTELLATION_PHASE_TRIGGER = 65508, + SPELL_CONSTELLATION_PHASE_EFFECT = 65509, + SPELL_BLACK_HOLE_EXPLOSION = 64122, + SPELL_SUMMON_VOID_ZONE_VISUAL = 64470, + SPELL_VOID_ZONE_VISUAL = 64469, + SPELL_BLACK_HOLE_CREDIT = 65312, + + // Worm Hole + SPELL_WORM_HOLE_TRIGGER = 65251, + SPELL_SUMMON_UNLEASHED_DARK_MATTER = 64450, +}; + +uint32 const PhasePunchAlphaId[5] = {64435, 64434, 64428, 64421, 64417}; + +enum Events +{ + // Celestial Planetarium Access + EVENT_DESPAWN_CONSOLE = 1, + + // Brann Bronzebeard + EVENT_BRANN_MOVE_INTRO = 2, + EVENT_SUMMON_ALGALON = 3, + EVENT_BRANN_OUTRO_1 = 4, + EVENT_BRANN_OUTRO_2 = 5, + + // Algalon the Observer + EVENT_INTRO_1 = 6, + EVENT_INTRO_2 = 7, + EVENT_INTRO_3 = 8, + EVENT_INTRO_FINISH = 9, + EVENT_START_COMBAT = 10, + EVENT_INTRO_TIMER_DONE = 11, + EVENT_QUANTUM_STRIKE = 12, + EVENT_PHASE_PUNCH = 13, + EVENT_SUMMON_COLLAPSING_STAR = 14, + EVENT_BIG_BANG = 15, + EVENT_RESUME_UPDATING = 16, + EVENT_ASCEND_TO_THE_HEAVENS = 17, + EVENT_EVADE = 18, + EVENT_COSMIC_SMASH = 19, + EVENT_UNLOCK_YELL = 20, + EVENT_OUTRO_START = 21, + EVENT_OUTRO_1 = 22, + EVENT_OUTRO_2 = 23, + EVENT_OUTRO_3 = 24, + EVENT_OUTRO_4 = 25, + EVENT_OUTRO_5 = 26, + EVENT_OUTRO_6 = 27, + EVENT_OUTRO_7 = 28, + EVENT_OUTRO_8 = 29, + EVENT_OUTRO_9 = 30, + EVENT_OUTRO_10 = 31, + EVENT_OUTRO_11 = 32, + EVENT_OUTRO_12 = 33, + EVENT_OUTRO_13 = 34, + EVENT_OUTRO_14 = 35, + EVENT_DESPAWN_ALGALON_1 = 36, + EVENT_DESPAWN_ALGALON_2 = 37, + EVENT_DESPAWN_ALGALON_3 = 38, + + // Living Constellation + EVENT_ARCANE_BARRAGE = 39, +}; + +enum Actions +{ + ACTION_START_INTRO = 0, + ACTION_FINISH_INTRO = 1, + ACTION_ACTIVATE_STAR = 2, + ACTION_BIG_BANG = 3, + ACTION_ASCEND = 4, + ACTION_OUTRO = 5, +}; + +enum Points +{ + POINT_BRANN_INTRO = 0, + MAX_BRANN_WAYPOINTS_INTRO = 10, + POINT_BRANN_OUTRO = 10, + POINT_BRANN_OUTRO_END = 11, + + POINT_ALGALON_LAND = 1, + POINT_ALGALON_OUTRO = 2, +}; + +enum EncounterPhases +{ + PHASE_NORMAL = 0, + PHASE_ROLE_PLAY = 1, + PHASE_BIG_BANG = 2, + + PHASE_MASK_NO_UPDATE = (1 << PHASE_ROLE_PLAY) | (1 << PHASE_BIG_BANG), + PHASE_MASK_NO_CAST_CHECK = 1 << PHASE_ROLE_PLAY, +}; + +enum AchievmentInfo +{ + EVENT_ID_SUPERMASSIVE_START = 21697, + DATA_HAS_FED_ON_TEARS = 30043005, +}; + + +Position const BrannIntroSpawnPos = {1676.277f, -162.5308f, 427.3326f, 3.235537f}; +Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] = +{ + {1642.482f, -164.0812f, 427.2602f, 0.0f}, + {1635.000f, -169.5145f, 427.2523f, 0.0f}, + {1632.814f, -173.9334f, 427.2621f, 0.0f}, + {1632.676f, -190.5927f, 425.8831f, 0.0f}, + {1631.497f, -214.2221f, 418.1152f, 0.0f}, + {1624.717f, -224.6876f, 418.1152f, 0.0f}, + {1631.497f, -214.2221f, 418.1152f, 0.0f}, + {1632.676f, -190.5927f, 425.8831f, 0.0f}, + {1632.814f, -173.9334f, 427.2621f, 0.0f}, + {1635.000f, -169.5145f, 427.2523f, 0.0f}, +}; +Position const AlgalonSummonPos = {1632.531f, -304.8516f, 450.1123f, 1.530165f}; +Position const AlgalonLandPos = {1632.668f, -302.7656f, 417.3211f, 1.530165f}; + +#define LIVING_CONSTELLATION_COUNT 11 +Position const ConstellationPos[LIVING_CONSTELLATION_COUNT] = +{ + {1625.208f, -267.2771f, 446.4296f, 5.044002f}, + {1658.279f, -262.5490f, 441.9073f, 4.188790f}, + {1678.677f, -276.3280f, 427.7531f, 3.979351f}, + {1593.389f, -299.4325f, 432.4636f, 6.073746f}, + {1685.613f, -300.1219f, 443.2366f, 3.385939f}, + {1591.706f, -263.8201f, 441.4153f, 5.253441f}, + {1668.317f, -324.7676f, 457.9394f, 3.211406f}, + {1592.242f, -325.5323f, 446.9508f, 0.226893f}, + {1635.821f, -363.3442f, 424.3459f, 1.466077f}, + {1672.188f, -357.2484f, 436.7337f, 2.338741f}, + {1615.800f, -348.0065f, 442.9586f, 1.134464f}, +}; + +#define COLLAPSING_STAR_COUNT 4 +Position const CollapsingStarPos[COLLAPSING_STAR_COUNT] = +{ + {1649.438f, -319.8127f, 418.3941f, 1.082104f}, + {1647.005f, -288.6790f, 417.3955f, 3.490659f}, + {1622.451f, -321.1563f, 417.6188f, 4.677482f}, + {1615.060f, -291.6816f, 417.7796f, 3.490659f}, +}; +Position const AlgalonOutroPos = {1633.64f, -317.78f, 417.3211f, 0.0f}; +Position const BrannOutroPos[3] = +{ + {1632.023f, -243.7434f, 417.9118f, 0.0f}, + {1631.986f, -297.7831f, 417.3210f, 0.0f}, + {1633.832f, -216.2948f, 417.0463f, 0.0f}, +}; + +class ActivateLivingConstellation : public BasicEvent +{ + public: + ActivateLivingConstellation(Unit* owner) : _owner(owner), _instance(owner->GetInstanceScript()) + { + } + + bool Execute(uint64 execTime, uint32 /*diff*/) + { + if (!_instance || _instance->GetBossState(BOSS_ALGALON) != IN_PROGRESS) + return true; // delete event + + _owner->CastSpell((Unit*)NULL, SPELL_TRIGGER_3_ADDS, TRIGGERED_FULL_MASK); + _owner->m_Events.AddEvent(this, execTime + urand(45000, 50000)); + return false; + } + + private: + Unit* _owner; + InstanceScript* _instance; +}; + +class CosmicSmashDamageEvent : public BasicEvent +{ + public: + CosmicSmashDamageEvent(Unit* caster) : _caster(caster) + { + } + + bool Execute(uint64 /*execTime*/, uint32 /*diff*/) + { + _caster->CastSpell((Unit*)NULL, SPELL_COSMIC_SMASH_TRIGGERED, TRIGGERED_FULL_MASK); + return true; + } + + private: + Unit* _caster; +}; + +class SummonUnleashedDarkMatter : public BasicEvent +{ + public: + SummonUnleashedDarkMatter(Unit* caster) : _caster(caster) + { + } + + bool Execute(uint64 execTime, uint32 /*diff*/) + { + _caster->CastSpell((Unit*)NULL, SPELL_SUMMON_UNLEASHED_DARK_MATTER, TRIGGERED_FULL_MASK); + _caster->m_Events.AddEvent(this, execTime + 30000); + return false; + } + + private: + Unit* _caster; +}; + +class boss_algalon_the_observer : public CreatureScript +{ + public: + boss_algalon_the_observer() : CreatureScript("boss_algalon_the_observer") {} + + struct boss_algalon_the_observerAI : public BossAI + { + boss_algalon_the_observerAI(Creature* creature) : BossAI(creature, BOSS_ALGALON) + { + _firstPull = true; + _fedOnTears = false; + } + + void Reset() + { + _Reset(); + me->SetReactState(REACT_PASSIVE); + _phaseTwo = false; + _fightWon = false; + _hasYelled = false; + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_UNIT) + { + _fedOnTears = true; + if (!_hasYelled) + { + _hasYelled = true; + events.ScheduleEvent(EVENT_UNLOCK_YELL, 1000); + Talk(SAY_ALGALON_KILL); + } + } + } + + void DoAction(int32 const action) + { + switch (action) + { + case ACTION_START_INTRO: + { + me->SetFlag(UNIT_FIELD_FLAGS_2, 0x20); + me->SetDisableGravity(true); + DoCast(me, SPELL_ARRIVAL, true); + DoCast(me, SPELL_RIDE_THE_LIGHTNING, true); + me->GetMotionMaster()->MovePoint(POINT_ALGALON_LAND, AlgalonLandPos); + me->SetHomePosition(AlgalonLandPos); + Movement::MoveSplineInit init(*me); + init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ()); + init.SetOrientationFixed(true); + init.Launch(); + events.Reset(); + events.SetPhase(PHASE_ROLE_PLAY); + events.ScheduleEvent(EVENT_INTRO_1, 5000, 0, PHASE_ROLE_PLAY); + events.ScheduleEvent(EVENT_INTRO_2, 15000, 0, PHASE_ROLE_PLAY); + events.ScheduleEvent(EVENT_INTRO_3, 23000, 0, PHASE_ROLE_PLAY); + events.ScheduleEvent(EVENT_INTRO_FINISH, 36000, 0, PHASE_ROLE_PLAY); + break; + } + case ACTION_ASCEND: + events.SetPhase(PHASE_BIG_BANG); + events.CancelEvent(EVENT_RESUME_UPDATING); + events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1500); + break; + case EVENT_DESPAWN_ALGALON: + events.Reset(); + events.SetPhase(PHASE_ROLE_PLAY); + if (me->isInCombat()) + events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1); + events.ScheduleEvent(EVENT_DESPAWN_ALGALON_1, 5000); + events.ScheduleEvent(EVENT_DESPAWN_ALGALON_2, 17000); + events.ScheduleEvent(EVENT_DESPAWN_ALGALON_3, 26000); + me->DespawnOrUnsummon(34000); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC); + break; + case ACTION_INIT_ALGALON: + _firstPull = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + break;; + } + } + + uint32 GetData(uint32 type) + { + return type == DATA_HAS_FED_ON_TEARS ? _fedOnTears : 1; + } + + void EnterCombat(Unit* /*target*/) + { + uint32 introDelay = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC); + events.Reset(); + events.SetPhase(PHASE_ROLE_PLAY); + + if (!_firstPull) + { + Talk(SAY_ALGALON_AGGRO); + _EnterCombat(); + introDelay = 8000; + } + else + { + _firstPull = false; + Talk(SAY_ALGALON_START_TIMER); + if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRANN_BRONZEBEARD_ALG))) + brann->AI()->DoAction(ACTION_FINISH_INTRO); + + me->setActive(true); + DoZoneInCombat(); + introDelay = 26000; + summons.DespawnEntry(NPC_AZEROTH); + instance->SetData(EVENT_DESPAWN_ALGALON, 0); + events.ScheduleEvent(EVENT_START_COMBAT, 18000); + } + + events.ScheduleEvent(EVENT_INTRO_TIMER_DONE, introDelay); + events.ScheduleEvent(EVENT_QUANTUM_STRIKE, 3500 + introDelay); + events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500 + introDelay); + events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 18000 + introDelay); + events.ScheduleEvent(EVENT_BIG_BANG, 90000 + introDelay); + events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 360000 + introDelay); + events.ScheduleEvent(EVENT_COSMIC_SMASH, 25000 + introDelay); + + std::list<Creature*> stalkers; + me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f); + for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr) + (*itr)->m_Events.KillAllEvents(true); + } + + void MovementInform(uint32 movementType, uint32 pointId) + { + if (movementType != POINT_MOTION_TYPE) + return; + + if (pointId == POINT_ALGALON_LAND) + me->SetDisableGravity(false); + else if (pointId == POINT_ALGALON_OUTRO) + { + me->SetFacingTo(1.605703f); + events.ScheduleEvent(EVENT_OUTRO_3, 1200); + events.ScheduleEvent(EVENT_OUTRO_4, 2400); + events.ScheduleEvent(EVENT_OUTRO_5, 8500); + events.ScheduleEvent(EVENT_OUTRO_6, 15500); + events.ScheduleEvent(EVENT_OUTRO_7, 55500); + events.ScheduleEvent(EVENT_OUTRO_8, 73500); + events.ScheduleEvent(EVENT_OUTRO_9, 85500); + events.ScheduleEvent(EVENT_OUTRO_10, 108500); + events.ScheduleEvent(EVENT_OUTRO_11, 123500); + } + } + + void JustSummoned(Creature* summon) + { + summons.Summon(summon); + switch (summon->GetEntry()) + { + case NPC_AZEROTH: + DoCastAOE(SPELL_REORIGINATION, true); + break; + case NPC_COLLAPSING_STAR: + summon->SetReactState(REACT_PASSIVE); + summon->GetMotionMaster()->MoveRandom(20.0f); + summon->CastSpell(summon, SPELL_COLLAPSE, TRIGGERED_FULL_MASK); + break; + case NPC_BLACK_HOLE: + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK); + summon->CastSpell(summon, SPELL_CONSTELLATION_PHASE_TRIGGER, TRIGGERED_FULL_MASK); + summon->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_EXPLOSION); + summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK); + break; + case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER: + summon->CastSpell(summon, SPELL_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK); + break; + case NPC_ALGALON_STALKER_ASTEROID_TARGET_01: + summon->CastSpell(summon, SPELL_COSMIC_SMASH_VISUAL_STATE, TRIGGERED_FULL_MASK); + break; + case NPC_ALGALON_STALKER_ASTEROID_TARGET_02: + summon->m_Events.AddEvent(new CosmicSmashDamageEvent(summon), summon->m_Events.CalculateTime(3250)); + break; + case NPC_WORM_HOLE: + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_WORM_HOLE_TRIGGER, TRIGGERED_FULL_MASK); + summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK); + break; + case NPC_UNLEASHED_DARK_MATTER: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) + if (summon->Attack(target, true)) + summon->GetMotionMaster()->MoveChase(target); + break; + } + } + + void EnterEvadeMode() + { + instance->SetBossState(BOSS_ALGALON, FAIL); + BossAI::EnterEvadeMode(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->SetSheath(SHEATH_STATE_UNARMED); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (_fightWon) + { + damage = 0; + return; + } + + if (!_phaseTwo && me->HealthBelowPctDamaged(20, damage)) + { + _phaseTwo = true; + Talk(SAY_ALGALON_PHASE_TWO); + summons.DespawnEntry(NPC_LIVING_CONSTELLATION); + summons.DespawnEntry(NPC_COLLAPSING_STAR); + summons.DespawnEntry(NPC_BLACK_HOLE); + summons.DespawnEntry(NPC_ALGALON_VOID_ZONE_VISUAL_STALKER); + events.CancelEvent(EVENT_SUMMON_COLLAPSING_STAR); + std::list<Creature*> stalkers; + me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f); + for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr) + (*itr)->m_Events.KillAllEvents(true); + for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i) + if (Creature* wormHole = DoSummon(NPC_WORM_HOLE, CollapsingStarPos[i], TEMPSUMMON_MANUAL_DESPAWN)) + wormHole->m_Events.AddEvent(new SummonUnleashedDarkMatter(wormHole), wormHole->m_Events.CalculateTime(i >= 2 ? 8000 : 6000)); + } + else if ((int32(me->GetHealth()) - int32(damage)) < CalculatePctF<int32>(int32(me->GetMaxHealth()), 2.5f) && !_fightWon) + { + _fightWon = true; + damage = 0; + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_SELF_STUN); + events.Reset(); + summons.DespawnAll(); + events.SetPhase(PHASE_ROLE_PLAY); + events.ScheduleEvent(EVENT_OUTRO_START, 1500); + events.ScheduleEvent(EVENT_OUTRO_1, 7200); + events.ScheduleEvent(EVENT_OUTRO_2, 8700); + } + } + + void UpdateAI(uint32 const diff) + { + if ((!(events.GetPhaseMask() & PHASE_MASK_NO_UPDATE) && !UpdateVictim()) || !CheckInRoom()) + return; + + events.Update(diff); + + if (!(events.GetPhaseMask() & PHASE_MASK_NO_CAST_CHECK)) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INTRO_1: + me->RemoveAurasDueToSpell(SPELL_RIDE_THE_LIGHTNING); + Talk(SAY_ALGALON_INTRO_1); + break; + case EVENT_INTRO_2: + DoCastAOE(SPELL_SUMMON_AZEROTH, true); + Talk(SAY_ALGALON_INTRO_2); + break; + case EVENT_INTRO_3: + Talk(SAY_ALGALON_INTRO_3); + break; + case EVENT_INTRO_FINISH: + events.Reset(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + break; + case EVENT_START_COMBAT: + instance->SetBossState(BOSS_ALGALON, IN_PROGRESS); + break; + case EVENT_INTRO_TIMER_DONE: + { + events.SetPhase(PHASE_NORMAL); + me->SetSheath(SHEATH_STATE_MELEE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_NPC); + me->SetReactState(REACT_DEFENSIVE); + DoCastAOE(SPELL_SUPERMASSIVE_FAIL, true); + //! Workaround for Creature::_IsTargetAcceptable returning false + //! for creatures that start combat in REACT_PASSIVE and UNIT_FLAG_NOT_SELECTABLE + //! causing them to immediately evade + if (!me->getThreatManager().isThreatListEmpty()) + AttackStart(me->getThreatManager().getHostilTarget()); + for (uint32 i = 0; i < LIVING_CONSTELLATION_COUNT; ++i) + if (Creature* summon = DoSummon(NPC_LIVING_CONSTELLATION, ConstellationPos[i], 0, TEMPSUMMON_DEAD_DESPAWN)) + summon->SetReactState(REACT_PASSIVE); + + std::list<Creature*> stalkers; + me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f); + if (!stalkers.empty()) + { + Unit* stalker = Trinity::Containers::SelectRandomContainerElement(stalkers); + stalker->m_Events.AddEvent(new ActivateLivingConstellation(stalker), stalker->m_Events.CalculateTime(urand(45000, 50000))); + } + break; + } + case EVENT_QUANTUM_STRIKE: + DoCastVictim(SPELL_QUANTUM_STRIKE); + events.ScheduleEvent(EVENT_QUANTUM_STRIKE, urand(3000, 5000)); + break; + case EVENT_PHASE_PUNCH: + DoCastVictim(SPELL_PHASE_PUNCH); + events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500); + break; + case EVENT_SUMMON_COLLAPSING_STAR: + Talk(SAY_ALGALON_COLLAPSING_STAR); + Talk(EMOTE_ALGALON_COLLAPSING_STAR); + for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i) + me->SummonCreature(NPC_COLLAPSING_STAR, CollapsingStarPos[i], TEMPSUMMON_CORPSE_DESPAWN); + events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 60000); + break; + case EVENT_BIG_BANG: + { + Talk(SAY_ALGALON_BIG_BANG); + Talk(EMOTE_ALGALON_BIG_BANG); + events.SetPhase(PHASE_BIG_BANG); + std::list<Creature*> constellations; + me->GetCreatureListWithEntryInGrid(constellations, NPC_LIVING_CONSTELLATION, 200.0f); + for (std::list<Creature*>::iterator itr = constellations.begin(); itr != constellations.end(); ++itr) + (*itr)->AI()->DoAction(ACTION_BIG_BANG); + DoCastAOE(SPELL_BIG_BANG); + events.ScheduleEvent(EVENT_BIG_BANG, 90500); + events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500); + break; + } + case EVENT_RESUME_UPDATING: + events.SetPhase(0); + break; + case EVENT_ASCEND_TO_THE_HEAVENS: + Talk(SAY_ALGALON_ASCEND); + DoCastAOE(SPELL_ASCEND_TO_THE_HEAVENS); + events.ScheduleEvent(EVENT_EVADE, 2500); + break; + case EVENT_EVADE: + EnterEvadeMode(); + break; + case EVENT_COSMIC_SMASH: + Talk(EMOTE_ALGALON_COSMIC_SMASH); + DoCastAOE(SPELL_COSMIC_SMASH); + events.ScheduleEvent(EVENT_COSMIC_SMASH, 25500); + break; + case EVENT_UNLOCK_YELL: + _hasYelled = false; + break; + case EVENT_OUTRO_START: + instance->SetBossState(BOSS_ALGALON, DONE); + break; + case EVENT_OUTRO_1: + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME); + break; + case EVENT_OUTRO_2: + _EnterEvadeMode(); + me->AddUnitState(UNIT_STATE_EVADE); + me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos); + break; + case EVENT_OUTRO_3: + DoCastAOE(SPELL_KILL_CREDIT); + break; + case EVENT_OUTRO_4: + DoCastAOE(SPELL_SUPERMASSIVE_FAIL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case EVENT_OUTRO_5: + if (Creature* brann = DoSummon(NPC_BRANN_BRONZBEARD_ALG, BrannOutroPos[0], 131500, TEMPSUMMON_TIMED_DESPAWN)) + brann->AI()->DoAction(ACTION_OUTRO); + break; + case EVENT_OUTRO_6: + Talk(SAY_ALGALON_OUTRO_1); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + break; + case EVENT_OUTRO_7: + Talk(SAY_ALGALON_OUTRO_2); + break; + case EVENT_OUTRO_8: + Talk(SAY_ALGALON_OUTRO_3); + break; + case EVENT_OUTRO_9: + Talk(SAY_ALGALON_OUTRO_4); + break; + case EVENT_OUTRO_10: + Talk(SAY_ALGALON_OUTRO_5); + break; + case EVENT_OUTRO_11: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_TELEPORT); + me->DespawnOrUnsummon(1500); + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + bool _firstPull; + bool _fedOnTears; + bool _phaseTwo; + bool _fightWon; + bool _hasYelled; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_algalon_the_observerAI>(creature); + } +}; + +class npc_living_constellation : public CreatureScript +{ + public: + npc_living_constellation() : CreatureScript("npc_living_constellation") { } + + struct npc_living_constellationAI : public CreatureAI + { + npc_living_constellationAI(Creature* creature) : CreatureAI(creature) + { + } + + void Reset() + { + _events.Reset(); + _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500); + _isActive = false; + } + + uint32 GetData(uint32 /*type*/) + { + return _isActive ? 1 : 0; + } + + void DoAction(int32 const action) + { + switch (action) + { + case ACTION_ACTIVATE_STAR: + if (Creature* algalon = me->FindNearestCreature(NPC_ALGALON, 200.0f)) + { + if (Unit* target = algalon->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(algalon))) + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + AttackStart(target); + DoZoneInCombat(); + _isActive = true; + } + } + break; + case ACTION_BIG_BANG: + _events.SetPhase(PHASE_BIG_BANG); + _events.DelayEvents(9500); + _events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500); + break; + } + } + + void SpellHit(Unit* caster, SpellInfo const* spell) + { + if (spell->Id != SPELL_CONSTELLATION_PHASE_EFFECT || caster->GetTypeId() != TYPEID_UNIT) + return; + + me->DespawnOrUnsummon(1); + if (InstanceScript* instance = me->GetInstanceScript()) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START); + caster->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK); + caster->ToCreature()->DespawnOrUnsummon(1); + } + + void UpdateAI(uint32 const diff) + { + if (!(_events.GetPhaseMask() & PHASE_MASK_NO_UPDATE) && !UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ARCANE_BARRAGE: + DoCastAOE(SPELL_ARCANE_BARRAGE); + _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500); + break; + case EVENT_RESUME_UPDATING: + _events.SetPhase(0); + break; + } + } + } + + private: + EventMap _events; + bool _isActive; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_living_constellationAI>(creature); + } +}; + +class npc_collapsing_star : public CreatureScript +{ + public: + npc_collapsing_star() : CreatureScript("npc_collapsing_star") { } + + struct npc_collapsing_starAI : public PassiveAI + { + npc_collapsing_starAI(Creature* creature) : PassiveAI(creature) + { + _dying = false; + } + + void JustSummoned(Creature* summon) + { + if (summon->GetEntry() != NPC_BLACK_HOLE) + return; + + if (TempSummon* summ = me->ToTempSummon()) + if (Creature* algalon = ObjectAccessor::GetCreature(*me, summ->GetSummonerGUID())) + algalon->AI()->JustSummoned(summon); + + me->DespawnOrUnsummon(1); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (_dying) + { + damage = 0; + return; + } + + if (damage >= me->GetHealth()) + { + _dying = true; + damage = 0; + DoCast(me, SPELL_BLACK_HOLE_SPAWN_VISUAL, true); + DoCast(me, SPELL_SUMMON_BLACK_HOLE, true); + } + } + + bool _dying; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_collapsing_starAI>(creature); + } +}; + +class npc_brann_bronzebeard_algalon : public CreatureScript +{ + public: + npc_brann_bronzebeard_algalon() : CreatureScript("npc_brann_bronzebeard_algalon") { } + + struct npc_brann_bronzebeard_algalonAI : public CreatureAI + { + npc_brann_bronzebeard_algalonAI(Creature* creature) : CreatureAI(creature) + { + } + + void DoAction(int32 const action) + { + switch (action) + { + case ACTION_START_INTRO: + _currentPoint = 0; + _events.Reset(); + me->SetWalk(false); + _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1); + break; + case ACTION_FINISH_INTRO: + Talk(SAY_BRANN_ALGALON_INTRO_2); + _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1); + break; + case ACTION_OUTRO: + me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO, BrannOutroPos[1]); + _events.ScheduleEvent(EVENT_BRANN_OUTRO_1, 89500); + _events.ScheduleEvent(EVENT_BRANN_OUTRO_2, 116500); + break; + } + } + + void MovementInform(uint32 movementType, uint32 pointId) + { + if (movementType != POINT_MOTION_TYPE) + return; + + uint32 delay = 1; + _currentPoint = pointId + 1; + switch (pointId) + { + case 2: + delay = 8000; + me->SetWalk(true); + break; + case 5: + me->SetWalk(false); + Talk(SAY_BRANN_ALGALON_INTRO_1); + _events.ScheduleEvent(EVENT_SUMMON_ALGALON, 7500); + return; + case 9: + me->DespawnOrUnsummon(1); + return; + case POINT_BRANN_OUTRO: + case POINT_BRANN_OUTRO_END: + return; + } + + _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay); + } + + void UpdateAI(uint32 const diff) + { + UpdateVictim(); + + if (_events.Empty()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BRANN_MOVE_INTRO: + if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO) + me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]); + break; + case EVENT_SUMMON_ALGALON: + if (Creature* algalon = me->GetMap()->SummonCreature(NPC_ALGALON, AlgalonSummonPos)) + algalon->AI()->DoAction(ACTION_START_INTRO); + break; + case EVENT_BRANN_OUTRO_1: + Talk(SAY_BRANN_ALGALON_OUTRO); + break; + case EVENT_BRANN_OUTRO_2: + me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO_END, BrannOutroPos[2]); + break; + } + } + } + + private: + EventMap _events; + uint32 _currentPoint; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_brann_bronzebeard_algalonAI>(creature); + } +}; + +class go_celestial_planetarium_access : public GameObjectScript +{ + public: + go_celestial_planetarium_access() : GameObjectScript("go_celestial_planetarium_access") {} + + struct go_celestial_planetarium_accessAI : public GameObjectAI + { + go_celestial_planetarium_accessAI(GameObject* go) : GameObjectAI(go) + { + } + + bool GossipHello(Player* player) + { + bool hasKey = true; + if (LockEntry const* lock = sLockStore.LookupEntry(go->GetGOInfo()->goober.lockId)) + { + hasKey = false; + for (uint32 i = 0; i < MAX_LOCK_CASE; ++i) + { + if (!lock->Index[i]) + continue; + + if (player->HasItemCount(lock->Index[i], 1)) + { + hasKey = true; + break; + } + } + } + + if (!hasKey) + return false; + + // Start Algalon event + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + _events.ScheduleEvent(EVENT_DESPAWN_CONSOLE, 5000); + if (Creature* brann = go->SummonCreature(NPC_BRANN_BRONZBEARD_ALG, BrannIntroSpawnPos)) + brann->AI()->DoAction(ACTION_START_INTRO); + + if (InstanceScript* instance = go->GetInstanceScript()) + { + instance->SetData(DATA_ALGALON_SUMMON_STATE, 1); + if (GameObject* sigil = ObjectAccessor::GetGameObject(*go, instance->GetData64(DATA_SIGILDOOR_01))) + sigil->SetGoState(GO_STATE_ACTIVE); + + if (GameObject* sigil = ObjectAccessor::GetGameObject(*go, instance->GetData64(DATA_SIGILDOOR_02))) + sigil->SetGoState(GO_STATE_ACTIVE); + } + + return false; + } + + void UpdateAI(uint32 diff) + { + if (_events.Empty()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DESPAWN_CONSOLE: + go->Delete(); + break; + } + } + } + + EventMap _events; + }; + + GameObjectAI* GetAI(GameObject* go) const + { + return GetUlduarAI<go_celestial_planetarium_accessAI>(go); + } +}; + +class spell_algalon_phase_punch : public SpellScriptLoader +{ + public: + spell_algalon_phase_punch() : SpellScriptLoader("spell_algalon_phase_punch") { } + + class spell_algalon_phase_punch_AuraScript : public AuraScript + { + PrepareAuraScript(spell_algalon_phase_punch_AuraScript); + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (GetStackAmount() != 1) + GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]); + GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK); + if (GetStackAmount() == 5) + Remove(AURA_REMOVE_BY_DEFAULT); + } + + void OnRemove(AuraEffect const*, AuraEffectHandleModes) + { + if (GetStackAmount() != 5) + GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_algalon_phase_punch_AuraScript(); + } +}; + +class NotVictimFilter +{ + public: + NotVictimFilter(Unit* caster) : _victim(caster->getVictim()) + { + } + + bool operator()(WorldObject* target) + { + return target != _victim; + } + + private: + Unit* _victim; +}; + +class spell_algalon_arcane_barrage : public SpellScriptLoader +{ + public: + spell_algalon_arcane_barrage() : SpellScriptLoader("spell_algalon_arcane_barrage") { } + + class spell_algalon_arcane_barrage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_arcane_barrage_SpellScript); + + void SelectTarget(std::list<WorldObject*>& targets) + { + targets.remove_if(NotVictimFilter(GetCaster())); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_arcane_barrage_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_arcane_barrage_SpellScript(); + } +}; + +class ActiveConstellationFilter +{ + public: + bool operator()(WorldObject* target) const + { + return target->ToUnit() && target->ToUnit()->GetAI() && target->ToUnit()->GetAI()->GetData(0); + } +}; + +class spell_algalon_trigger_3_adds : public SpellScriptLoader +{ + public: + spell_algalon_trigger_3_adds() : SpellScriptLoader("spell_algalon_trigger_3_adds") { } + + class spell_algalon_trigger_3_adds_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript); + + void SelectTarget(std::list<WorldObject*>& targets) + { + targets.remove_if(ActiveConstellationFilter()); + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + Creature* target = GetHitCreature(); + if (!target) + return; + + target->AI()->DoAction(ACTION_ACTIVATE_STAR); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_trigger_3_adds_SpellScript(); + } +}; + +class spell_algalon_collapse : public SpellScriptLoader +{ + public: + spell_algalon_collapse() : SpellScriptLoader("spell_algalon_collapse") { } + + class spell_algalon_collapse_AuraScript : public AuraScript + { + PrepareAuraScript(spell_algalon_collapse_AuraScript); + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->DealDamage(GetTarget(), GetTarget()->CountPctFromMaxHealth(1), NULL, NODAMAGE); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_algalon_collapse_AuraScript(); + } +}; + +class spell_algalon_big_bang : public SpellScriptLoader +{ + public: + spell_algalon_big_bang() : SpellScriptLoader("spell_algalon_big_bang") { } + + class spell_algalon_big_bang_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_big_bang_SpellScript); + + bool Load() + { + _targetCount = 0; + return true; + } + + void CountTargets(std::list<WorldObject*>& targets) + { + _targetCount = targets.size(); + } + + void CheckTargets() + { + if (!_targetCount) + GetCaster()->GetAI()->DoAction(ACTION_ASCEND); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets); + } + + uint32 _targetCount; + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_big_bang_SpellScript(); + } +}; + +class spell_algalon_remove_phase : public SpellScriptLoader +{ + public: + spell_algalon_remove_phase() : SpellScriptLoader("spell_algalon_remove_phase") { } + + class spell_algalon_remove_phase_AuraScript : public AuraScript + { + PrepareAuraScript(spell_algalon_remove_phase_AuraScript); + + void HandlePeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_algalon_remove_phase_AuraScript(); + } +}; + +class spell_algalon_cosmic_smash : public SpellScriptLoader +{ + public: + spell_algalon_cosmic_smash() : SpellScriptLoader("spell_algalon_cosmic_smash") { } + + class spell_algalon_cosmic_smash_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_cosmic_smash_SpellScript); + + void ModDestHeight(SpellEffIndex /*effIndex*/) + { + Position offset = {0.0f, 0.0f, 65.0f, 0.0f}; + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); + } + + void Register() + { + OnEffectLaunch += SpellEffectFn(spell_algalon_cosmic_smash_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_cosmic_smash_SpellScript(); + } +}; + +class spell_algalon_cosmic_smash_damage : public SpellScriptLoader +{ + public: + spell_algalon_cosmic_smash_damage() : SpellScriptLoader("spell_algalon_cosmic_smash_damage") { } + + class spell_algalon_cosmic_smash_damage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_cosmic_smash_damage_SpellScript); + + void RecalculateDamage() + { + if (!GetExplTargetDest() || !GetHitUnit()) + return; + + float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY()); + if (distance > 6.0f) + SetHitDamage(int32(float(GetHitDamage()) / distance) * 2); + } + + void Register() + { + OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage_SpellScript::RecalculateDamage); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_cosmic_smash_damage_SpellScript(); + } +}; + +class spell_algalon_supermassive_fail : public SpellScriptLoader +{ + public: + spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { } + + class spell_algalon_supermassive_fail_SpellScript : public SpellScript + { + PrepareSpellScript(spell_algalon_supermassive_fail_SpellScript); + + void RecalculateDamage() + { + if (!GetHitPlayer()) + return; + + GetHitPlayer()->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true); + } + + void Register() + { + OnHit += SpellHitFn(spell_algalon_supermassive_fail_SpellScript::RecalculateDamage); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_algalon_supermassive_fail_SpellScript(); + } +}; + +class achievement_he_feeds_on_your_tears : public AchievementCriteriaScript +{ + public: + achievement_he_feeds_on_your_tears() : AchievementCriteriaScript("achievement_he_feeds_on_your_tears") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return !target->GetAI()->GetData(DATA_HAS_FED_ON_TEARS); + } +}; + +void AddSC_boss_algalon_the_observer() +{ + new boss_algalon_the_observer(); + new npc_living_constellation(); + new npc_collapsing_star(); + new npc_brann_bronzebeard_algalon(); + new go_celestial_planetarium_access(); + new spell_algalon_phase_punch(); + new spell_algalon_arcane_barrage(); + new spell_algalon_trigger_3_adds(); + new spell_algalon_collapse(); + new spell_algalon_big_bang(); + new spell_algalon_remove_phase(); + new spell_algalon_cosmic_smash(); + new spell_algalon_cosmic_smash_damage(); + new spell_algalon_supermassive_fail(); + new achievement_he_feeds_on_your_tears(); +} diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index 6c2c08f07a0..ec3125f7c0a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -298,14 +298,14 @@ class npc_auriaya_seeping_trigger : public CreatureScript void Reset() { - me->ForcedDespawn(600000); + me->DespawnOrUnsummon(600000); DoCast(me, SPELL_SEEPING_ESSENCE); } void UpdateAI(uint32 const /*diff*/) { if (instance->GetBossState(BOSS_AURIAYA) != IN_PROGRESS) - me->ForcedDespawn(); + me->DespawnOrUnsummon(); } private: @@ -472,9 +472,9 @@ class npc_feral_defender : public CreatureScript class SanctumSentryCheck { public: - bool operator() (Unit* unit) + bool operator()(WorldObject* object) const { - if (unit->GetEntry() == NPC_SANCTUM_SENTRY) + if (object->GetEntry() == NPC_SANCTUM_SENTRY) return false; return true; @@ -490,14 +490,14 @@ class spell_auriaya_strenght_of_the_pack : public SpellScriptLoader { PrepareSpellScript(spell_auriaya_strenght_of_the_pack_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (SanctumSentryCheck()); + unitList.remove_if(SanctumSentryCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_strenght_of_the_pack_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_strenght_of_the_pack_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -516,15 +516,15 @@ class spell_auriaya_sentinel_blast : public SpellScriptLoader { PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (PlayerOrPetCheck()); + unitList.remove_if(PlayerOrPetCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 33415cda157..9d5adf39817 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -720,20 +720,18 @@ class boss_flame_leviathan_overload_device : public CreatureScript { } - void DoAction(const int32 param) + void OnSpellClick(Unit* /*clicker*/) { - if (param == EVENT_SPELLCLICK) + if (me->GetVehicle()) { - if (me->GetVehicle()) + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Unit* player = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (Unit* player = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) - { - me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true); - player->GetMotionMaster()->MoveKnockbackFrom(me->GetVehicleBase()->GetPositionX(), me->GetVehicleBase()->GetPositionY(), 30, 30); - player->ExitVehicle(); - } + me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true); + player->GetMotionMaster()->MoveKnockbackFrom(me->GetVehicleBase()->GetPositionX(), me->GetVehicleBase()->GetPositionY(), 30, 30); + player->ExitVehicle(); } } } @@ -1232,7 +1230,7 @@ public: //bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) //{ // player->PlayerTalkClass->ClearMenus(); - // switch(action) + // switch (action) // { // case GOSSIP_ACTION_INFO_DEF+1: // if (player) @@ -1273,7 +1271,7 @@ class go_ulduar_tower : public GameObjectScript public: go_ulduar_tower() : GameObjectScript("go_ulduar_tower") { } - void OnDestroyed(GameObject* go, Player* /*player*/, uint32 /*value*/) + void OnDestroyed(GameObject* go, Player* /*player*/) { InstanceScript* instance = go->GetInstanceScript(); if (!instance) @@ -1619,7 +1617,7 @@ class FlameLeviathanPursuedTargetSelector public: explicit FlameLeviathanPursuedTargetSelector(Unit* unit) : _me(unit) {}; - bool operator()(Unit* target) const + bool operator()(WorldObject* target) const { //! No players, only vehicles (todo: check if blizzlike) Creature* creatureTarget = target->ToCreature(); @@ -1667,7 +1665,7 @@ class spell_pursue : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { targets.remove_if(FlameLeviathanPursuedTargetSelector(GetCaster())); if (targets.empty()) @@ -1683,7 +1681,7 @@ class spell_pursue : public SpellScriptLoader } } - void FilterTargetsSubsequently(std::list<Unit*>& targets) + void FilterTargetsSubsequently(std::list<WorldObject*>& targets) { targets.clear(); if (_target) @@ -1710,12 +1708,12 @@ class spell_pursue : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_pursue_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_pursue_SpellScript::FilterTargetsSubsequently, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargetsSubsequently, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_pursue_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -1743,7 +1741,7 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader { // use 99 because it is 3d search std::list<WorldObject*> targetList; - Trinity::WorldObjectSpellAreaTargetCheck check(99, GetTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, NULL); + Trinity::WorldObjectSpellAreaTargetCheck check(99, GetExplTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, NULL); Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetCaster(), targetList, check); GetCaster()->GetMap()->VisitAll(GetCaster()->m_positionX, GetCaster()->m_positionY, 99, searcher); float minDist = 99 * 99; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 4ea38a7642d..a3c9cb847e5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -507,7 +507,7 @@ class boss_freya : public CreatureScript for (uint8 n = 0; n < 3; ++n) { summons.remove(Elemental[n][i]->GetGUID()); - Elemental[n][i]->ForcedDespawn(5000); + Elemental[n][i]->DespawnOrUnsummon(5000); trioDefeated[i] = true; Elemental[n][i]->CastSpell(me, SPELL_REMOVE_10STACK, true); } @@ -664,12 +664,12 @@ class boss_freya : public CreatureScript case NPC_DETONATING_LASHER: summoned->CastSpell(me, SPELL_REMOVE_2STACK, true); summoned->CastSpell(who, SPELL_DETONATE, true); - summoned->ForcedDespawn(5000); + summoned->DespawnOrUnsummon(5000); summons.remove(summoned->GetGUID()); break; case NPC_ANCIENT_CONSERVATOR: summoned->CastSpell(me, SPELL_REMOVE_25STACK, true); - summoned->ForcedDespawn(5000); + summoned->DespawnOrUnsummon(5000); summons.remove(summoned->GetGUID()); break; } @@ -1385,7 +1385,7 @@ class npc_healthy_spore : public CreatureScript if (lifeTimer <= diff) { me->RemoveAurasDueToSpell(SPELL_GROW); - me->ForcedDespawn(2200); + me->DespawnOrUnsummon(2200); lifeTimer = urand(22000, 30000); } else @@ -1423,7 +1423,7 @@ class npc_eonars_gift : public CreatureScript { me->RemoveAurasDueToSpell(SPELL_GROW); DoCast(SPELL_LIFEBINDERS_GIFT); - me->ForcedDespawn(2500); + me->DespawnOrUnsummon(2500); lifeBindersGiftTimer = 12000; } else diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 3556bf188de..8090b9e8a3e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -51,6 +51,8 @@ enum VezaxSpells SPELL_SHADOW_CRASH_HIT = 62659, SPELL_SURGE_OF_DARKNESS = 62662, SPELL_SARONITE_VAPORS = 63323, + SPELL_SARONITE_VAPORS_ENERGIZE = 63337, + SPELL_SARONITE_VAPORS_DAMAGE = 63338, SPELL_SUMMON_SARONITE_VAPORS = 63081, SPELL_BERSERK = 26662, @@ -463,6 +465,45 @@ class spell_mark_of_the_faceless : public SpellScriptLoader } }; +class spell_general_vezax_saronite_vapors : public SpellScriptLoader +{ + public: + spell_general_vezax_saronite_vapors() : SpellScriptLoader("spell_general_vezax_saronite_vapors") { } + + class spell_general_vezax_saronite_vapors_AuraScript : public AuraScript + { + PrepareAuraScript(spell_general_vezax_saronite_vapors_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SARONITE_VAPORS_ENERGIZE) || !sSpellMgr->GetSpellInfo(SPELL_SARONITE_VAPORS_DAMAGE)) + return false; + return true; + } + + void HandleEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + int32 mana = int32(aurEff->GetAmount() * pow(2.0f, GetStackAmount())); // mana restore - bp * 2^stackamount + int32 damage = mana * 2; + caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_ENERGIZE, &mana, NULL, NULL, true); + caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DAMAGE, &damage, NULL, NULL, true); + } + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_general_vezax_saronite_vapors_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_general_vezax_saronite_vapors_AuraScript(); + } +}; + class achievement_shadowdodger : public AchievementCriteriaScript { public: @@ -509,6 +550,7 @@ void AddSC_boss_general_vezax() new boss_saronite_animus(); new npc_saronite_vapors(); new spell_mark_of_the_faceless(); + new spell_general_vezax_saronite_vapors(); new achievement_shadowdodger(); new achievement_smell_saronite(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index d89d640b083..24a9171e29f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -354,7 +354,7 @@ class StoneGripTargetSelector : public std::unary_function<Unit*, bool> public: StoneGripTargetSelector(Creature* me, Unit const* victim) : _me(me), _victim(victim) {} - bool operator() (Unit* target) + bool operator()(WorldObject* target) { if (target == _victim && _me->getThreatManager().getThreatList().size() > 1) return true; @@ -385,10 +385,10 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader return true; } - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& unitList) { // Remove "main tank" and non-player targets - unitList.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->getVictim())); + unitList.remove_if(StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->getVictim())); // Maximum affected targets per difficulty mode uint32 maxTargets = 1; if (GetSpellInfo()->Id == 63981) @@ -397,7 +397,7 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader // Return a random amount of targets based on maxTargets while (maxTargets < unitList.size()) { - std::list<Unit*>::iterator itr = unitList.begin(); + std::list<WorldObject*>::iterator itr = unitList.begin(); advance(itr, urand(0, unitList.size()-1)); unitList.erase(itr); } @@ -406,20 +406,20 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader m_unitList = unitList; } - void FillTargetsSubsequential(std::list<Unit*>& unitList) + void FillTargetsSubsequential(std::list<WorldObject*>& unitList) { unitList = m_unitList; } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); } // Shared between effects - std::list<Unit*> m_unitList; + std::list<WorldObject*> m_unitList; }; SpellScript* GetSpellScript() const @@ -598,14 +598,14 @@ class spell_kologarn_stone_shout : public SpellScriptLoader { PrepareSpellScript(spell_kologarn_stone_shout_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (PlayerOrPetCheck()); + unitList.remove_if(PlayerOrPetCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index a1323b07899..e8e938dc06b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -1006,7 +1006,7 @@ class spell_razorscale_devouring_flame : public SpellScriptLoader PreventHitDefaultEffect(effIndex); Unit* caster = GetCaster(); uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); - WorldLocation const* summonLocation = GetTargetDest(); + WorldLocation const* summonLocation = GetExplTargetDest(); if (!caster || !summonLocation) return; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index 727f40aef81..7ada42144a8 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -170,7 +170,11 @@ enum AchievementCredits ACHIEV_MUST_DECONSTRUCT_FASTER = 21027, }; -#define HEART_VEHICLE_SEAT 0 +enum VehicleSeats +{ + HEART_VEHICLE_SEAT_NORMAL = 0, + HEART_VEHICLE_SEAT_EXPOSED = 1, +}; /*------------------------------------------------------- * @@ -198,6 +202,8 @@ class boss_xt002 : public CreatureScript _Reset(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoCast(me, SPELL_STAND); _healthRecovered = false; _gravityBombCasualty = false; @@ -356,15 +362,16 @@ class boss_xt002 : public CreatureScript me->AttackStop(); me->SetReactState(REACT_PASSIVE); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_NORMAL) : NULL; if (heart) { heart->CastSpell(heart, SPELL_HEART_OVERLOAD, false); heart->CastSpell(me, SPELL_HEART_LIGHTNING_TETHER, false); heart->CastSpell(heart, SPELL_HEART_HEAL_TO_FULL, true); heart->CastSpell(heart, SPELL_EXPOSED_HEART, false); // Channeled - - heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_EXPOSED, true); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); } events.CancelEvent(EVENT_SEARING_LIGHT); @@ -392,11 +399,13 @@ class boss_xt002 : public CreatureScript events.RescheduleEvent(EVENT_GRAVITY_BOMB, TIMER_GRAVITY_BOMB); events.RescheduleEvent(EVENT_TYMPANIC_TANTRUM, urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX)); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_EXPOSED) : NULL; if (!heart) return; - heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_NORMAL, false); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); heart->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); if (!_hardMode) @@ -425,43 +434,39 @@ class boss_xt002 : public CreatureScript * XT-002 HEART * *///---------------------------------------------------- + class mob_xt002_heart : public CreatureScript { public: mob_xt002_heart() : CreatureScript("mob_xt002_heart") { } - CreatureAI* GetAI(Creature* creature) const - { - return new mob_xt002_heartAI(creature); - } - - struct mob_xt002_heartAI : public ScriptedAI + struct mob_xt002_heartAI : public Scripted_NoMovementAI { - mob_xt002_heartAI(Creature* creature) : ScriptedAI(creature) + mob_xt002_heartAI(Creature* creature) : Scripted_NoMovementAI(creature), + _instance(creature->GetInstanceScript()) { - _instance = creature->GetInstanceScript(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); } - void DamageTaken(Unit* /*pDone*/, uint32 &damage) + void UpdateAI(uint32 const /*diff*/) { } + + void JustDied(Unit* /*killer*/) { - Creature* xt002 = me->GetCreature(*me, _instance->GetData64(BOSS_XT002)); + Creature* xt002 = _instance ? me->GetCreature(*me, _instance->GetData64(BOSS_XT002)) : NULL; if (!xt002 || !xt002->AI()) return; - if (damage >= me->GetHealth()) - { - xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth()); - xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); - damage = 0; - } + xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetHealth()); + xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); } - private: - InstanceScript* _instance; - uint32 _damageTaken; + private: + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_xt002_heartAI(creature); + } }; /*------------------------------------------------------- @@ -915,7 +920,7 @@ class spell_xt002_heart_overload_periodic : public SpellScriptLoader { uint8 a = urand(0, 4); uint32 spellId = spells[a]; - toyPile->CastSpell(toyPile, spellId, true); + toyPile->CastSpell(toyPile, spellId, true, NULL, NULL, instance->GetData64(BOSS_XT002)); } } } @@ -945,15 +950,21 @@ class spell_xt002_tympanic_tantrum : public SpellScriptLoader { PrepareSpellScript(spell_xt002_tympanic_tantrum_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(PlayerOrPetCheck()); + } + + void RecalculateDamage() { - unitList.remove_if (PlayerOrPetCheck()); + SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp index 3f01f21b189..58ba125b994 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp @@ -18,18 +18,27 @@ #include "ScriptMgr.h" #include "ulduar.h" -enum Sara_Yells +enum Sara { - SAY_SARA_PREFIGHT_1 = -1603310, - SAY_SARA_PREFIGHT_2 = -1603311, - SAY_SARA_AGGRO_1 = -1603312, - SAY_SARA_AGGRO_2 = -1603313, - SAY_SARA_AGGRO_3 = -1603314, - SAY_SARA_SLAY_1 = -1603315, - SAY_SARA_SLAY_2 = -1603316, - WHISP_SARA_INSANITY = -1603317, - SAY_SARA_PHASE2_1 = -1603318, - SAY_SARA_PHASE2_2 = -1603319, + // text + YELL_SARA_PREFIGHT = 0, + YELL_COMBAT_PHASE_1 = 1, + YELL_COMBAT_PHASE_2 = 2, + YELL_SLAY = 3, + + // Phase 1 spells + SPELL_SARAS_ANGER_1 = 63147, // Target Entry 33136 + SPELL_SARAS_ANGER_2 = 63744, // Target Entry 33136 + SPELL_SARAS_FEVOR_1 = 63138, // Target Player + SPELL_SARAS_FEVOR_2 = 63747, // Target Player + SPELL_SARAS_BLESSING_1 = 63134, // Target Player + SPELL_SARAS_BLESSING_2 = 63745, // Target Self + + // Phase 2 spells + SPELL_PHYCHOSIS = 63795, // Target Self + SPELL_MALADY_OF_THE_MIND = 63830, // Target Self + SPELL_DEATH_RAY = 63891, // Target Self + SPELL_BRAIN_LINK = 63802, // Target Self }; enum YoggSaron_Yells diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index e12393f047f..2f37fb06f24 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -22,9 +22,14 @@ static DoorData const doorData[] = { - { GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, - { GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, + {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, + {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, + {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, }; class instance_ulduar : public InstanceMapScript @@ -36,7 +41,6 @@ class instance_ulduar : public InstanceMapScript { instance_ulduar_InstanceMapScript(InstanceMap* map) : InstanceScript(map) { } - uint32 Encounter[MAX_ENCOUNTER]; std::string m_strInstData; // Creatures @@ -72,6 +76,12 @@ class instance_ulduar : public InstanceMapScript uint64 HodirDoorGUID; uint64 HodirIceDoorGUID; uint64 ArchivumDoorGUID; + uint64 AlgalonSigilDoorGUID[3]; + uint64 AlgalonFloorGUID[2]; + uint64 AlgalonUniverseGUID; + uint64 AlgalonTrapdoorGUID; + uint64 BrannBronzebeardAlgGUID; + uint64 GiftOfTheObserverGUID; // Miscellaneous uint32 TeamInInstance; @@ -111,35 +121,50 @@ class instance_ulduar : public InstanceMapScript HodirDoorGUID = 0; HodirIceDoorGUID = 0; ArchivumDoorGUID = 0; + AlgalonUniverseGUID = 0; + AlgalonTrapdoorGUID = 0; + BrannBronzebeardAlgGUID = 0; + GiftOfTheObserverGUID = 0; + _algalonTimer = 61; + _maxArmorItemLevel = 0; + _maxWeaponItemLevel = 0; TeamInInstance = 0; HodirRareCacheData = 0; ColossusData = 0; elderCount = 0; conSpeedAtory = false; Unbroken = true; + _algalonSummoned = false; + _summonAlgalon = false; - memset(Encounter, 0, sizeof(Encounter)); + memset(AlgalonSigilDoorGUID, 0, sizeof(AlgalonSigilDoorGUID)); + memset(AlgalonFloorGUID, 0, sizeof(AlgalonFloorGUID)); memset(XTToyPileGUIDs, 0, sizeof(XTToyPileGUIDs)); memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs)); memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs)); memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs)); } - bool IsEncounterInProgress() const + void FillInitialWorldStates(WorldPacket& packet) { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (Encounter[i] == IN_PROGRESS) - return true; - } - - return false; + packet << uint32(WORLD_STATE_ALGALON_TIMER_ENABLED) << uint32(_algalonTimer && _algalonTimer <= 60); + packet << uint32(WORLD_STATE_ALGALON_DESPAWN_TIMER) << uint32(std::min<uint32>(_algalonTimer, 60)); } void OnPlayerEnter(Player* player) { if (!TeamInInstance) TeamInInstance = player->GetTeam(); + + if (_summonAlgalon) + { + _summonAlgalon = false; + TempSummon* algalon = instance->SummonCreature(NPC_ALGALON, AlgalonLandPos); + if (_algalonTimer && _algalonTimer <= 60) + algalon->AI()->DoAction(ACTION_INIT_ALGALON); + else + algalon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + } } void OnCreatureCreate(Creature* creature) @@ -234,7 +259,6 @@ class instance_ulduar : public InstanceMapScript case NPC_ALGALON: AlgalonGUID = creature->GetGUID(); break; - // Hodir's Helper NPCs case NPC_EIVI_NIGHTFEATHER: if (TeamInInstance == HORDE) @@ -268,9 +292,32 @@ class instance_ulduar : public InstanceMapScript if (TeamInInstance == HORDE) creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA, HORDE); break; + case NPC_BRANN_BRONZBEARD_ALG: + BrannBronzebeardAlgGUID = creature->GetGUID(); + break; + //! These creatures are summoned by something else than Algalon + //! but need to be controlled/despawned by him - so they need to be + //! registered in his summon list + case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER: + case NPC_ALGALON_STALKER_ASTEROID_TARGET_01: + case NPC_ALGALON_STALKER_ASTEROID_TARGET_02: + case NPC_UNLEASHED_DARK_MATTER: + if (Creature* algalon = instance->GetCreature(AlgalonGUID)) + algalon->AI()->JustSummoned(creature); + break; } + } - } + void OnCreatureRemove(Creature* creature) + { + switch (creature->GetEntry()) + { + case NPC_BRANN_BRONZBEARD_ALG: + if (BrannBronzebeardAlgGUID == creature->GetGUID()) + BrannBronzebeardAlgGUID = 0; + break; + } + } void OnGameObjectCreate(GameObject* gameObject) { @@ -341,6 +388,45 @@ class instance_ulduar : public InstanceMapScript if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE) HandleGameObject(ArchivumDoorGUID, false); break; + case GO_CELESTIAL_PLANETARIUM_ACCESS_10: + case GO_CELESTIAL_PLANETARIUM_ACCESS_25: + if (_algalonSummoned) + gameObject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + break; + case GO_DOODAD_UL_SIGILDOOR_01: + AlgalonSigilDoorGUID[0] = gameObject->GetGUID(); + if (_algalonSummoned) + gameObject->SetGoState(GO_STATE_ACTIVE); + break; + case GO_DOODAD_UL_SIGILDOOR_02: + AlgalonSigilDoorGUID[1] = gameObject->GetGUID(); + if (_algalonSummoned) + gameObject->SetGoState(GO_STATE_ACTIVE); + break; + case GO_DOODAD_UL_SIGILDOOR_03: + AlgalonSigilDoorGUID[2] = gameObject->GetGUID(); + AddDoor(gameObject, true); + break; + case GO_DOODAD_UL_UNIVERSEFLOOR_01: + AlgalonFloorGUID[0] = gameObject->GetGUID(); + AddDoor(gameObject, true); + break; + case GO_DOODAD_UL_UNIVERSEFLOOR_02: + AlgalonFloorGUID[1] = gameObject->GetGUID(); + AddDoor(gameObject, true); + break; + case GO_DOODAD_UL_UNIVERSEGLOBE01: + AlgalonUniverseGUID = gameObject->GetGUID(); + AddDoor(gameObject, true); + break; + case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03: + AlgalonTrapdoorGUID = gameObject->GetGUID(); + AddDoor(gameObject, true); + break; + case GO_GIFT_OF_THE_OBSERVER_10: + case GO_GIFT_OF_THE_OBSERVER_25: + GiftOfTheObserverGUID = gameObject->GetGUID(); + break; } } @@ -349,10 +435,14 @@ class instance_ulduar : public InstanceMapScript switch (gameObject->GetEntry()) { case GO_LEVIATHAN_DOOR: - AddDoor(gameObject, false); - break; case GO_XT_002_DOOR: + case GO_DOODAD_UL_SIGILDOOR_03: + case GO_DOODAD_UL_UNIVERSEFLOOR_01: + case GO_DOODAD_UL_UNIVERSEFLOOR_02: + case GO_DOODAD_UL_UNIVERSEGLOBE01: + case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03: AddDoor(gameObject, false); + break; default: break; } @@ -390,6 +480,7 @@ class instance_ulduar : public InstanceMapScript // Flame Leviathan's Tower Event triggers Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID); if (FlameLeviathan && FlameLeviathan->isAlive()) // No leviathan, no event triggering ;) + { switch (eventId) { case EVENT_TOWER_OF_STORM_DESTROYED: @@ -405,6 +496,7 @@ class instance_ulduar : public InstanceMapScript FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED); break; } + } } @@ -465,6 +557,52 @@ class instance_ulduar : public InstanceMapScript if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID)) gameObject->SetRespawnTime(gameObject->GetRespawnDelay()); break; + case BOSS_ALGALON: + if (state == DONE) + { + _events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER); + _events.CancelEvent(EVENT_DESPAWN_ALGALON); + DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0); + _algalonTimer = 61; + if (GameObject* gameObject = instance->GetGameObject(GiftOfTheObserverGUID)) + gameObject->SetRespawnTime(gameObject->GetRespawnDelay()); + // get item level (recheck weapons) + Map::PlayerList const& players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player* player = itr->getSource()) + for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot) + if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetTemplate()->ItemLevel; + } + else if (state == IN_PROGRESS) + { + // get item level (armor cannot be swapped in combat) + Map::PlayerList const& players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* player = itr->getSource()) + { + for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) + { + if (slot == EQUIPMENT_SLOT_TABARD || slot == EQUIPMENT_SLOT_BODY) + continue; + + if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + { + if (slot >= EQUIPMENT_SLOT_MAINHAND && slot <= EQUIPMENT_SLOT_RANGED) + { + if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetTemplate()->ItemLevel; + } + else if (item->GetTemplate()->ItemLevel > _maxArmorItemLevel) + _maxArmorItemLevel = item->GetTemplate()->ItemLevel; + } + } + } + } + } + break; } return true; @@ -497,6 +635,16 @@ class instance_ulduar : public InstanceMapScript case DATA_UNBROKEN: Unbroken = bool(data); break; + case EVENT_DESPAWN_ALGALON: + DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1); + DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60); + _algalonTimer = 60; + _events.ScheduleEvent(EVENT_DESPAWN_ALGALON, 3600000); + _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000); + break; + case DATA_ALGALON_SUMMON_STATE: + _algalonSummoned = true; + break; default: break; } @@ -571,6 +719,22 @@ class instance_ulduar : public InstanceMapScript return KeeperGUIDs[1]; case BOSS_STONEBARK: return KeeperGUIDs[2]; + case DATA_SIGILDOOR_01: + return AlgalonSigilDoorGUID[0]; + case DATA_SIGILDOOR_02: + return AlgalonSigilDoorGUID[1]; + case DATA_SIGILDOOR_03: + return AlgalonSigilDoorGUID[2]; + case DATA_UNIVERSE_FLOOR_01: + return AlgalonFloorGUID[0]; + case DATA_UNIVERSE_FLOOR_02: + return AlgalonFloorGUID[1]; + case DATA_UNIVERSE_GLOBE: + return AlgalonUniverseGUID; + case DATA_ALGALON_TRAPDOOR: + return AlgalonTrapdoorGUID; + case DATA_BRANN_BRONZEBEARD_ALG: + return BrannBronzebeardAlgGUID; } return 0; @@ -593,12 +757,23 @@ class instance_ulduar : public InstanceMapScript return 0; } + bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* , Unit const* /* = NULL */, uint32 /* = 0 */) + { + switch (criteriaId) + { + case CRITERIA_HERALD_OF_TITANS: + return _maxArmorItemLevel <= MAX_HERALD_ARMOR_ITEMLEVEL && _maxWeaponItemLevel <= MAX_HERALD_WEAPON_ITEMLEVEL; + } + + return false; + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS); + saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS) << ' ' << _algalonTimer << ' ' << (_algalonSummoned ? 1 : 0); OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); @@ -628,15 +803,68 @@ class instance_ulduar : public InstanceMapScript if (tmpState == IN_PROGRESS || tmpState > SPECIAL) tmpState = NOT_STARTED; - if (i == DATA_COLOSSUS) - SetData(i, tmpState); - else - SetBossState(i, EncounterState(tmpState)); + SetBossState(i, EncounterState(tmpState)); + } + + uint32 tempState; + loadStream >> tempState; + if (tempState == IN_PROGRESS || tempState > SPECIAL) + tempState = NOT_STARTED; + SetData(DATA_COLOSSUS, tempState); + + loadStream >> _algalonTimer; + loadStream >> tempState; + _algalonSummoned = tempState != 0; + if (_algalonSummoned && GetBossState(BOSS_ALGALON) != DONE) + { + _summonAlgalon = true; + if (_algalonTimer && _algalonTimer <= 60) + { + _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000); + DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1); + DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer); + } } } OUT_LOAD_INST_DATA_COMPLETE; } + + void Update(uint32 diff) + { + if (_events.Empty()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_UPDATE_ALGALON_TIMER: + SaveToDB(); + DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, --_algalonTimer); + if (_algalonTimer) + _events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 60000); + else + { + DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0); + _events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER); + if (Creature* algalon = instance->GetCreature(AlgalonGUID)) + algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON); + } + break; + } + } + } + + private: + EventMap _events; + uint32 _algalonTimer; + bool _summonAlgalon; + bool _algalonSummoned; + uint32 _maxArmorItemLevel; + uint32 _maxWeaponItemLevel; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index a31954b8a16..858a82bbe57 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -21,6 +21,8 @@ #include "ObjectMgr.h" #define UlduarScriptName "instance_ulduar" +extern Position const AlgalonLandPos; + enum UlduarBosses { MAX_ENCOUNTER = 20, @@ -50,98 +52,124 @@ enum UlduarBosses enum UlduarNPCs { // General - NPC_LEVIATHAN = 33113, - NPC_SALVAGED_DEMOLISHER = 33109, - NPC_SALVAGED_SIEGE_ENGINE = 33060, - NPC_IGNIS = 33118, - NPC_RAZORSCALE = 33186, - NPC_RAZORSCALE_CONTROLLER = 33233, - NPC_STEELFORGED_DEFFENDER = 33236, - NPC_EXPEDITION_COMMANDER = 33210, - NPC_XT002 = 33293, - NPC_XT_TOY_PILE = 33337, - NPC_STEELBREAKER = 32867, - NPC_MOLGEIM = 32927, - NPC_BRUNDIR = 32857, - NPC_KOLOGARN = 32930, - NPC_FOCUSED_EYEBEAM = 33632, - NPC_FOCUSED_EYEBEAM_RIGHT = 33802, - NPC_LEFT_ARM = 32933, - NPC_RIGHT_ARM = 32934, - NPC_RUBBLE = 33768, - NPC_AURIAYA = 33515, - NPC_MIMIRON = 33350, - NPC_HODIR = 32845, - NPC_THORIM = 32865, - NPC_FREYA = 32906, - NPC_VEZAX = 33271, - NPC_YOGGSARON = 33288, - NPC_ALGALON = 32871, + NPC_LEVIATHAN = 33113, + NPC_SALVAGED_DEMOLISHER = 33109, + NPC_SALVAGED_SIEGE_ENGINE = 33060, + NPC_IGNIS = 33118, + NPC_RAZORSCALE = 33186, + NPC_RAZORSCALE_CONTROLLER = 33233, + NPC_STEELFORGED_DEFFENDER = 33236, + NPC_EXPEDITION_COMMANDER = 33210, + NPC_XT002 = 33293, + NPC_XT_TOY_PILE = 33337, + NPC_STEELBREAKER = 32867, + NPC_MOLGEIM = 32927, + NPC_BRUNDIR = 32857, + NPC_KOLOGARN = 32930, + NPC_FOCUSED_EYEBEAM = 33632, + NPC_FOCUSED_EYEBEAM_RIGHT = 33802, + NPC_LEFT_ARM = 32933, + NPC_RIGHT_ARM = 32934, + NPC_RUBBLE = 33768, + NPC_AURIAYA = 33515, + NPC_MIMIRON = 33350, + NPC_HODIR = 32845, + NPC_THORIM = 32865, + NPC_FREYA = 32906, + NPC_VEZAX = 33271, + NPC_YOGGSARON = 33288, + NPC_ALGALON = 32871, // Mimiron - NPC_LEVIATHAN_MKII = 33432, - NPC_VX_001 = 33651, - NPC_AERIAL_COMMAND_UNIT = 33670, + NPC_LEVIATHAN_MKII = 33432, + NPC_VX_001 = 33651, + NPC_AERIAL_COMMAND_UNIT = 33670, // Freya's Keepers - NPC_IRONBRANCH = 32913, - NPC_BRIGHTLEAF = 32915, - NPC_STONEBARK = 32914, + NPC_IRONBRANCH = 32913, + NPC_BRIGHTLEAF = 32915, + NPC_STONEBARK = 32914, // Hodir's Helper NPCs - NPC_TOR_GREYCLOUD = 32941, - NPC_KAR_GREYCLOUD = 33333, - NPC_EIVI_NIGHTFEATHER = 33325, - NPC_ELLIE_NIGHTFEATHER = 32901, - NPC_SPIRITWALKER_TARA = 33332, - NPC_SPIRITWALKER_YONA = 32950, - NPC_ELEMENTALIST_MAHFUUN = 33328, - NPC_ELEMENTALIST_AVUUN = 32900, - NPC_AMIRA_BLAZEWEAVER = 33331, - NPC_VEESHA_BLAZEWEAVER = 32946, - NPC_MISSY_FLAMECUFFS = 32893, - NPC_SISSY_FLAMECUFFS = 33327, - NPC_BATTLE_PRIEST_ELIZA = 32948, - NPC_BATTLE_PRIEST_GINA = 33330, - NPC_FIELD_MEDIC_PENNY = 32897, - NPC_FIELD_MEDIC_JESSI = 33326, + NPC_TOR_GREYCLOUD = 32941, + NPC_KAR_GREYCLOUD = 33333, + NPC_EIVI_NIGHTFEATHER = 33325, + NPC_ELLIE_NIGHTFEATHER = 32901, + NPC_SPIRITWALKER_TARA = 33332, + NPC_SPIRITWALKER_YONA = 32950, + NPC_ELEMENTALIST_MAHFUUN = 33328, + NPC_ELEMENTALIST_AVUUN = 32900, + NPC_AMIRA_BLAZEWEAVER = 33331, + NPC_VEESHA_BLAZEWEAVER = 32946, + NPC_MISSY_FLAMECUFFS = 32893, + NPC_SISSY_FLAMECUFFS = 33327, + NPC_BATTLE_PRIEST_ELIZA = 32948, + NPC_BATTLE_PRIEST_GINA = 33330, + NPC_FIELD_MEDIC_PENNY = 32897, + NPC_FIELD_MEDIC_JESSI = 33326, // Freya's trash NPCs - NPC_CORRUPTED_SERVITOR = 33354, - NPC_MISGUIDED_NYMPH = 33355, - NPC_GUARDIAN_LASHER = 33430, - NPC_FOREST_SWARMER = 33431, - NPC_MANGROVE_ENT = 33525, - NPC_IRONROOT_LASHER = 33526, - NPC_NATURES_BLADE = 33527, - NPC_GUARDIAN_OF_LIFE = 33528, + NPC_CORRUPTED_SERVITOR = 33354, + NPC_MISGUIDED_NYMPH = 33355, + NPC_GUARDIAN_LASHER = 33430, + NPC_FOREST_SWARMER = 33431, + NPC_MANGROVE_ENT = 33525, + NPC_IRONROOT_LASHER = 33526, + NPC_NATURES_BLADE = 33527, + NPC_GUARDIAN_OF_LIFE = 33528, + + // Algalon the Observer + NPC_BRANN_BRONZBEARD_ALG = 34064, + NPC_AZEROTH = 34246, + NPC_LIVING_CONSTELLATION = 33052, + NPC_ALGALON_STALKER = 33086, + NPC_COLLAPSING_STAR = 32955, + NPC_BLACK_HOLE = 32953, + NPC_WORM_HOLE = 34099, + NPC_ALGALON_VOID_ZONE_VISUAL_STALKER = 34100, + NPC_ALGALON_STALKER_ASTEROID_TARGET_01 = 33104, + NPC_ALGALON_STALKER_ASTEROID_TARGET_02 = 33105, + NPC_UNLEASHED_DARK_MATTER = 34097, }; enum UlduarGameObjects { - GO_KOLOGARN_CHEST_HERO = 195047, - GO_KOLOGARN_CHEST = 195046, - GO_KOLOGARN_BRIDGE = 194232, - GO_KOLOGARN_DOOR = 194553, - GO_THORIM_CHEST_HERO = 194315, - GO_THORIM_CHEST = 194314, - GO_HODIR_RARE_CACHE_OF_WINTER = 194200, - GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201, - GO_HODIR_CHEST_HERO = 194308, - GO_HODIR_CHEST = 194307, - GO_LEVIATHAN_DOOR = 194905, - GO_LEVIATHAN_GATE = 194630, - GO_XT_002_DOOR = 194631, - GO_VEZAX_DOOR = 194750, - GO_MOLE_MACHINE = 194316, - GO_RAZOR_HARPOON_1 = 194542, - GO_RAZOR_HARPOON_2 = 194541, - GO_RAZOR_HARPOON_3 = 194543, - GO_RAZOR_HARPOON_4 = 194519, - GO_RAZOR_BROKEN_HARPOON = 194565, - GO_HODIR_DOOR = 194634, - GO_HODIR_ICE_DOOR = 194441, - GO_ARCHIVUM_DOOR = 194556, + GO_KOLOGARN_CHEST_HERO = 195047, + GO_KOLOGARN_CHEST = 195046, + GO_KOLOGARN_BRIDGE = 194232, + GO_KOLOGARN_DOOR = 194553, + GO_THORIM_CHEST_HERO = 194315, + GO_THORIM_CHEST = 194314, + GO_HODIR_RARE_CACHE_OF_WINTER = 194200, + GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201, + GO_HODIR_CHEST_HERO = 194308, + GO_HODIR_CHEST = 194307, + GO_LEVIATHAN_DOOR = 194905, + GO_LEVIATHAN_GATE = 194630, + GO_XT_002_DOOR = 194631, + GO_VEZAX_DOOR = 194750, + GO_MOLE_MACHINE = 194316, + GO_RAZOR_HARPOON_1 = 194542, + GO_RAZOR_HARPOON_2 = 194541, + GO_RAZOR_HARPOON_3 = 194543, + GO_RAZOR_HARPOON_4 = 194519, + GO_RAZOR_BROKEN_HARPOON = 194565, + GO_HODIR_DOOR = 194634, + GO_HODIR_ICE_DOOR = 194441, + GO_ARCHIVUM_DOOR = 194556, + + // Algalon the Observer + GO_CELESTIAL_PLANETARIUM_ACCESS_10 = 194628, + GO_CELESTIAL_PLANETARIUM_ACCESS_25 = 194752, + GO_DOODAD_UL_SIGILDOOR_01 = 194767, + GO_DOODAD_UL_SIGILDOOR_02 = 194911, + GO_DOODAD_UL_SIGILDOOR_03 = 194910, + GO_DOODAD_UL_UNIVERSEFLOOR_01 = 194715, + GO_DOODAD_UL_UNIVERSEFLOOR_02 = 194716, + GO_DOODAD_UL_UNIVERSEGLOBE01 = 194148, + GO_DOODAD_UL_ULDUAR_TRAPDOOR_03 = 194253, + GO_GIFT_OF_THE_OBSERVER_10 = 194821, + GO_GIFT_OF_THE_OBSERVER_25 = 194822, }; enum LeviathanData @@ -161,6 +189,7 @@ enum UlduarAchievementCriteriaIds { CRITERIA_CON_SPEED_ATORY = 21597, CRITERIA_DISARMED = 21687, + CRITERIA_HERALD_OF_TITANS = 10678, }; enum UlduarData @@ -180,12 +209,38 @@ enum UlduarData // Hodir DATA_HODIR_RARE_CACHE, + + // Algalon the Observer + DATA_ALGALON_SUMMON_STATE, + DATA_SIGILDOOR_01, + DATA_SIGILDOOR_02, + DATA_SIGILDOOR_03, + DATA_UNIVERSE_FLOOR_01, + DATA_UNIVERSE_FLOOR_02, + DATA_UNIVERSE_GLOBE, + DATA_ALGALON_TRAPDOOR, + DATA_BRANN_BRONZEBEARD_ALG, +}; + +enum UlduarWorldStates +{ + WORLD_STATE_ALGALON_DESPAWN_TIMER = 4131, + WORLD_STATE_ALGALON_TIMER_ENABLED = 4132, }; enum UlduarAchievementData { // FL Achievement boolean DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs, + MAX_HERALD_ARMOR_ITEMLEVEL = 226, + MAX_HERALD_WEAPON_ITEMLEVEL = 232, +}; + +enum UlduarEvents +{ + EVENT_DESPAWN_ALGALON = 1, + EVENT_UPDATE_ALGALON_TIMER = 2, + ACTION_INIT_ALGALON = 6, }; template<class AI> @@ -199,13 +254,24 @@ CreatureAI* GetUlduarAI(Creature* creature) return NULL; } +template<class AI> +GameObjectAI* GetUlduarAI(GameObject* go) +{ + if (InstanceMap* instance = go->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(UlduarScriptName)) + return new AI(go); + + return NULL; +} + class PlayerOrPetCheck { public: - bool operator() (Unit* unit) + bool operator()(WorldObject* object) const { - if (unit->GetTypeId() != TYPEID_PLAYER) - if (!unit->ToCreature()->isPet()) + if (object->GetTypeId() != TYPEID_PLAYER) + if (!object->ToCreature()->isPet()) return true; return false; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index a7853a07e22..48667053373 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -22,7 +22,8 @@ SDComment: Some Problems with Annhylde Movement, Blizzlike Timers (just shadow a SDCategory: Udgarde Keep EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_keep.h" enum Yells @@ -100,6 +101,7 @@ public: boss_ingvar_the_plundererAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); + bIsUndead = false; } InstanceScript* instance; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index 93cc94923db..f53020a72c4 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -22,7 +22,10 @@ SDComment: SDCategory: Utgarde Keep EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "utgarde_keep.h" enum KelsethEncounter diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp index 915d1c71bb2..be8d60fbeb9 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp @@ -22,7 +22,8 @@ SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB SDCategory: Utgarde Keep EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_keep.h" enum eEnums diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp index fda4767e16b..1e79cc1c5bf 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp @@ -22,7 +22,8 @@ SDComment: Instance Data Scripts and functions to acquire mobs and set encounter SDCategory: Utgarde Keep EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "utgarde_keep.h" #define MAX_ENCOUNTER 3 @@ -119,7 +120,7 @@ public: } } - sLog->outDebug(LOG_FILTER_TSCR, "TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); + sLog->outDebug(LOG_FILTER_TSCR, "Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); return NULL; } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp index 95d2cb1709e..2d53e7062eb 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_keep.h" uint32 entry_search[3] = diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp index e2943f491f6..8cbfe4bafb4 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_pinnacle.h" enum Spells diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index 5132dd0f046..a6ad7befc38 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -25,7 +25,8 @@ SDComment: <Known Bugs> SDCategory: Utgarde Pinnacle Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_pinnacle.h" //Yell @@ -171,6 +172,7 @@ public: boss_skadiAI(Creature* creature) : ScriptedAI(creature), Summons(me) { instance = creature->GetInstanceScript(); + m_uiGraufGUID = 0; } InstanceScript* instance; @@ -206,7 +208,7 @@ public: Summons.DespawnAll(); me->SetSpeed(MOVE_FLIGHT, 3.0f); - if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) + if ((Unit::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted()) me->SummonCreature(CREATURE_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); if (instance) { @@ -220,7 +222,7 @@ public: me->SetCanFly(false); me->Dismount(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) + if (!Unit::GetCreature(*me, m_uiGraufGUID)) me->SummonCreature(CREATURE_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index 29b8f2e7f48..f2f03ff602b 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "utgarde_pinnacle.h" enum Spells @@ -276,7 +279,7 @@ public: arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); pos.Relocate(me); pos.m_positionZ += 8.0f; - me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f); + me->GetMotionMaster()->MoveTakeoff(0, pos); // spectators flee event if (instance) { @@ -333,7 +336,7 @@ public: pos.m_positionX = me->GetHomePosition().GetPositionX(); pos.m_positionY = me->GetHomePosition().GetPositionY(); pos.m_positionZ = 90.6065f; - me->GetMotionMaster()->MoveLand(0, pos, 6.247422f); + me->GetMotionMaster()->MoveLand(0, pos); me->SetDisableGravity(false, true); me->SetHover(true); ++introPhase; @@ -522,12 +525,12 @@ public: }; }; -class checkRitualTarget +class RitualTargetCheck { public: - explicit checkRitualTarget(Unit* _caster) : caster(_caster) { } + explicit RitualTargetCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator() (WorldObject* unit) const { if (InstanceScript* instance = caster->GetInstanceScript()) if (instance->GetData64(DATA_SACRIFICED_PLAYER) == unit->GetGUID()) @@ -549,14 +552,14 @@ class spell_paralyze_pinnacle : public SpellScriptLoader { PrepareSpellScript(spell_paralyze_pinnacle_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if(checkRitualTarget(GetCaster())); + unitList.remove_if(RitualTargetCheck(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp index f9251c637ba..39fd01a9269 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "utgarde_pinnacle.h" enum Spells @@ -120,6 +121,9 @@ public: m_uiActiveOrder[i] = m_uiActiveOrder[r]; m_uiActiveOrder[r] = temp; } + + m_uiActivedCreatureGUID = 0; + m_uiOrbGUID = 0; } bool m_bIsWalking; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp index 26fbbf4d717..c5d50d4e7fd 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "utgarde_pinnacle.h" #define MAX_ENCOUNTER 4 diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp index bffc6af2a3a..96e0bc66bd1 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "vault_of_archavon.h" #define EMOTE_BERSERK -1590002 diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp index 4980ed36ec3..903280d317a 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuras.h" #include "vault_of_archavon.h" //Emalon spells diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp index dd9db1c0a99..31003addf1f 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "vault_of_archavon.h" enum Events diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp index 100f1fccac8..9c60673522c 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "vault_of_archavon.h" enum Spells diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp index ec0de41ed6d..d1209b40a19 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "vault_of_archavon.h" /* Vault of Archavon encounters: diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp index 37ef8bf2788..b4ce402e7de 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp index 31902acfc46..bd59b731c3c 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp index a191d9349f2..f6d918e0493 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp index 7a8254ad2b6..510e9874dd7 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp index 1a70846e1b6..f368b07077a 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" //Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp index ac165ac39ef..a01b41bfbcf 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp index 4569741e459..d1c65259738 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "violet_hold.h" enum Spells diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index 79c54880430..4b6fed181e4 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "violet_hold.h" #define MAX_ENCOUNTER 3 @@ -690,7 +691,8 @@ public: { AddWave(); bActive = false; - uiActivationTimer = 5000; + // 1 minute waiting time after each boss fight + uiActivationTimer = (uiWaveCount == 6 || uiWaveCount == 12) ? 60000 : 5000; } else uiActivationTimer -= diff; } diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index e9d2c85e13e..122d051f1dd 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "violet_hold.h" diff --git a/src/server/scripts/Northrend/borean_tundra.cpp b/src/server/scripts/Northrend/borean_tundra.cpp index f83538b344c..9b207c257fc 100644 --- a/src/server/scripts/Northrend/borean_tundra.cpp +++ b/src/server/scripts/Northrend/borean_tundra.cpp @@ -37,7 +37,9 @@ npc_lurgglbr npc_nexus_drake_hatchling EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "ScriptedFollowerAI.h" @@ -186,7 +188,7 @@ public: if (owner->GetTypeId() == TYPEID_PLAYER) { owner->CastSpell(owner, 46231, true); - CAST_CRE(who)->ForcedDespawn(); + CAST_CRE(who)->DespawnOrUnsummon(); } } } diff --git a/src/server/scripts/Northrend/crystalsong_forest.cpp b/src/server/scripts/Northrend/crystalsong_forest.cpp index d48903696ec..7b8eb331702 100644 --- a/src/server/scripts/Northrend/crystalsong_forest.cpp +++ b/src/server/scripts/Northrend/crystalsong_forest.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: CrystalsongForest Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" /******************************************************* * npc_warmage_violetstand diff --git a/src/server/scripts/Northrend/dalaran.cpp b/src/server/scripts/Northrend/dalaran.cpp index e7b92732066..c19effbab1b 100644 --- a/src/server/scripts/Northrend/dalaran.cpp +++ b/src/server/scripts/Northrend/dalaran.cpp @@ -23,7 +23,9 @@ SDComment: For what is 63990+63991? Same function but don't work correct... SDCategory: Dalaran Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" /******************************************************* * npc_mageguard_dalaran diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index 4cbe280a9f2..ecc012eb25d 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -27,7 +27,11 @@ EndScriptData */ npc_alexstrasza_wr_gate EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "ScriptedEscortAI.h" enum eEnums @@ -69,7 +73,106 @@ public: } }; +/*###### +## Quest Strengthen the Ancients (12096|12092) +######*/ + +enum StrengthenAncientsMisc +{ + SAY_WALKER_FRIENDLY = 0, + SAY_WALKER_ENEMY = 1, + SAY_LOTHALOR = 0, + + SPELL_CREATE_ITEM_BARK = 47550, + SPELL_CONFUSED = 47044, + + NPC_LOTHALOR = 26321, + + FACTION_WALKER_ENEMY = 14, +}; + +class spell_q12096_q12092_dummy : public SpellScriptLoader // Strengthen the Ancients: On Interact Dummy to Woodlands Walker +{ +public: + spell_q12096_q12092_dummy() : SpellScriptLoader("spell_q12096_q12092_dummy") { } + + class spell_q12096_q12092_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_dummy_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = rand() % 2; + + Creature* tree = GetHitCreature(); + Player* player = GetCaster()->ToPlayer(); + + if (!tree || !player) + return; + + tree->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + + if (roll == 1) // friendly version + { + tree->CastSpell(player, SPELL_CREATE_ITEM_BARK); + tree->AI()->Talk(SAY_WALKER_FRIENDLY, player->GetGUID()); + tree->DespawnOrUnsummon(1000); + } + else if (roll == 0) // enemy version + { + tree->AI()->Talk(SAY_WALKER_ENEMY, player->GetGUID()); + tree->setFaction(FACTION_WALKER_ENEMY); + tree->Attack(player, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_dummy_SpellScript(); + } +}; + +class spell_q12096_q12092_bark : public SpellScriptLoader // Bark of the Walkers +{ +public: + spell_q12096_q12092_bark() : SpellScriptLoader("spell_q12096_q12092_bark") { } + + class spell_q12096_q12092_bark_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_bark_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Creature* lothalor = GetHitCreature(); + if (!lothalor || lothalor->GetEntry() != NPC_LOTHALOR) + return; + + lothalor->AI()->Talk(SAY_LOTHALOR); + lothalor->RemoveAura(SPELL_CONFUSED); + lothalor->DespawnOrUnsummon(4000); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_bark_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_bark_SpellScript(); + } +}; + void AddSC_dragonblight() { new npc_alexstrasza_wr_gate; + new spell_q12096_q12092_dummy; + new spell_q12096_q12092_bark; } diff --git a/src/server/scripts/Northrend/grizzly_hills.cpp b/src/server/scripts/Northrend/grizzly_hills.cpp index 2da84dd3fdb..4ca12bc82a1 100644 --- a/src/server/scripts/Northrend/grizzly_hills.cpp +++ b/src/server/scripts/Northrend/grizzly_hills.cpp @@ -16,7 +16,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "ScriptedEscortAI.h" /*###### @@ -599,100 +600,99 @@ enum eSmokeEmOut QUEST_SMOKE_EM_OUT_H = 12324, SPELL_SMOKE_BOMB = 49075, SPELL_CHOP = 43410, - NPC_VENTURE_CO_STABLES_KC = 27568, + SPELL_VENTURE_STRAGGLER_CREDIT = 49093, }; class npc_venture_co_straggler : public CreatureScript { -public: - npc_venture_co_straggler() : CreatureScript("npc_venture_co_straggler") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_venture_co_stragglerAI(creature); - } + public: + npc_venture_co_straggler() : CreatureScript("npc_venture_co_straggler") { } - struct npc_venture_co_stragglerAI : public ScriptedAI - { - npc_venture_co_stragglerAI(Creature* creature) : ScriptedAI(creature) { } + struct npc_venture_co_stragglerAI : public ScriptedAI + { + npc_venture_co_stragglerAI(Creature* creature) : ScriptedAI(creature) { } - uint64 uiPlayerGUID; - uint32 uiRunAwayTimer; - uint32 uiTimer; - uint32 uiChopTimer; + uint64 uiPlayerGUID; + uint32 uiRunAwayTimer; + uint32 uiTimer; + uint32 uiChopTimer; - void Reset() - { - uiPlayerGUID = 0; - uiTimer = 0; - uiChopTimer = urand(10000, 12500); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->SetReactState(REACT_AGGRESSIVE); - } + void Reset() + { + uiPlayerGUID = 0; + uiTimer = 0; + uiRunAwayTimer = 0; + uiChopTimer = urand(10000, 12500); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + me->SetReactState(REACT_AGGRESSIVE); + } - void UpdateAI(const uint32 uiDiff) - { - if (uiRunAwayTimer <= uiDiff) + void UpdateAI(const uint32 uiDiff) { - if (Player* player = Unit::GetPlayer(*me, uiPlayerGUID)) + if (uiPlayerGUID && uiRunAwayTimer <= uiDiff) { - switch (uiTimer) + if (Player* player = Unit::GetPlayer(*me, uiPlayerGUID)) { - case 0: - if (player->GetQuestStatus(QUEST_SMOKE_EM_OUT_A) == QUEST_STATUS_INCOMPLETE || - player->GetQuestStatus(QUEST_SMOKE_EM_OUT_H) == QUEST_STATUS_INCOMPLETE) - player->KilledMonsterCredit(NPC_VENTURE_CO_STABLES_KC, 0); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-7, me->GetPositionY()+7, me->GetPositionZ()); - uiRunAwayTimer = 2500; - ++uiTimer; - break; - case 1: - DoScriptText(RAND(SAY_SEO1, SAY_SEO2, SAY_SEO3, SAY_SEO4, SAY_SEO5), me); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-7, me->GetPositionY()-5, me->GetPositionZ()); - uiRunAwayTimer = 2500; - ++uiTimer; - break; - case 2: - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-5, me->GetPositionY()-5, me->GetPositionZ()); - uiRunAwayTimer = 2500; - ++uiTimer; - break; - case 3: - me->DisappearAndDie(); - uiTimer = 0; - break; + switch (uiTimer) + { + case 0: + DoCast(player, SPELL_VENTURE_STRAGGLER_CREDIT); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-7, me->GetPositionY()+7, me->GetPositionZ()); + uiRunAwayTimer = 2500; + ++uiTimer; + break; + case 1: + DoScriptText(RAND(SAY_SEO1, SAY_SEO2, SAY_SEO3, SAY_SEO4, SAY_SEO5), me); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-7, me->GetPositionY()-5, me->GetPositionZ()); + uiRunAwayTimer = 2500; + ++uiTimer; + break; + case 2: + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-5, me->GetPositionY()-5, me->GetPositionZ()); + uiRunAwayTimer = 2500; + ++uiTimer; + break; + case 3: + me->DisappearAndDie(); + uiTimer = 0; + break; + } } } - } - else - uiRunAwayTimer -= uiDiff; + else if (uiRunAwayTimer) + uiRunAwayTimer -= uiDiff; - if (!UpdateVictim()) - return; + if (!UpdateVictim()) + return; - if (uiChopTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CHOP); - uiChopTimer = urand(10000, 12000); - } - else - uiChopTimer -= uiDiff; + if (uiChopTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CHOP); + uiChopTimer = urand(10000, 12000); + } + else + uiChopTimer -= uiDiff; - DoMeleeAttackIfReady(); - } + DoMeleeAttackIfReady(); + } - void SpellHit(Unit* pCaster, const SpellInfo* pSpell) - { - if (pCaster && pCaster->GetTypeId() == TYPEID_PLAYER && pSpell->Id == SPELL_SMOKE_BOMB) + void SpellHit(Unit* caster, SpellInfo const* spell) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->SetReactState(REACT_PASSIVE); - me->CombatStop(false); - uiPlayerGUID = pCaster->GetGUID(); - uiRunAwayTimer = 3500; + if (spell->Id == SPELL_SMOKE_BOMB && caster->GetTypeId() == TYPEID_PLAYER) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + me->SetReactState(REACT_PASSIVE); + me->CombatStop(false); + uiPlayerGUID = caster->GetGUID(); + uiRunAwayTimer = 3500; + } } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_venture_co_stragglerAI(creature); } - }; }; void AddSC_grizzly_hills() diff --git a/src/server/scripts/Northrend/howling_fjord.cpp b/src/server/scripts/Northrend/howling_fjord.cpp index 88cc297868b..ffe38d6aade 100644 --- a/src/server/scripts/Northrend/howling_fjord.cpp +++ b/src/server/scripts/Northrend/howling_fjord.cpp @@ -27,7 +27,9 @@ npc_plaguehound_tracker npc_apothecary_hanes EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" /*###### diff --git a/src/server/scripts/Northrend/icecrown.cpp b/src/server/scripts/Northrend/icecrown.cpp index fb2e0f6c389..5989b5bad2e 100644 --- a/src/server/scripts/Northrend/icecrown.cpp +++ b/src/server/scripts/Northrend/icecrown.cpp @@ -27,7 +27,10 @@ EndScriptData */ npc_arete EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellAuras.h" /*###### ## npc_arete @@ -169,8 +172,7 @@ enum eArgentValiant { SPELL_CHARGE = 63010, SPELL_SHIELD_BREAKER = 65147, - - NPC_ARGENT_VALIANT_CREDIT = 24108 + SPELL_KILL_CREDIT = 63049 }; class npc_argent_valiant : public CreatureScript @@ -208,7 +210,7 @@ public: if (uiDamage > me->GetHealth() && pDoneBy->GetTypeId() == TYPEID_PLAYER) { uiDamage = 0; - CAST_PLR(pDoneBy)->KilledMonsterCredit(NPC_ARGENT_VALIANT_CREDIT, 0); + pDoneBy->CastSpell(pDoneBy, SPELL_KILL_CREDIT, true); me->setFaction(35); me->DespawnOrUnsummon(5000); me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/isle_of_conquest.cpp index 6d76e348980..1cf8f54b4fe 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/isle_of_conquest.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "PassiveAI.h" #include "BattlegroundIC.h" // TO-DO: This should be done with SmartAI, but yet it does not correctly support vehicles's AIs. diff --git a/src/server/scripts/Northrend/sholazar_basin.cpp b/src/server/scripts/Northrend/sholazar_basin.cpp index 93d0182ea08..56ef25c5753 100644 --- a/src/server/scripts/Northrend/sholazar_basin.cpp +++ b/src/server/scripts/Northrend/sholazar_basin.cpp @@ -28,8 +28,11 @@ npc_vekjik avatar_of_freya EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" +#include "SpellScript.h" /*###### ## npc_injured_rainspeaker_oracle @@ -746,6 +749,130 @@ public: } }; +/*###### +## Quest Kick, What Kick? (12589) +######*/ + +enum KickWhatKick +{ + NPC_LUCKY_WILHELM = 28054, + NPC_APPLE = 28053, + NPC_DROSTAN = 28328, + NPC_CRUNCHY = 28346, + NPC_THICKBIRD = 28093, + + SPELL_HIT_APPLE = 51331, + SPELL_MISS_APPLE = 51332, + SPELL_MISS_BIRD_APPLE = 51366, + SPELL_APPLE_FALL = 51371, + SPELL_BIRD_FALL = 51369, + + EVENT_MISS = 0, + EVENT_HIT = 1, + EVENT_MISS_BIRD = 2, + + SAY_WILHELM_MISS = 0, + SAY_WILHELM_HIT = 1, + SAY_DROSTAN_REPLY_MISS = 0, +}; + +class spell_q12589_shoot_rjr : public SpellScriptLoader +{ +public: + spell_q12589_shoot_rjr() : SpellScriptLoader("spell_q12589_shoot_rjr") { } + + class spell_q12589_shoot_rjr_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12589_shoot_rjr_SpellScript); + + SpellCastResult CheckCast() + { + if (Unit* target = GetExplTargetUnit()) + if (target->GetEntry() == NPC_LUCKY_WILHELM) + return SPELL_CAST_OK; + + SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM); + return SPELL_FAILED_CUSTOM_ERROR; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = urand(1, 100); + + uint8 ev; + if (roll <= 50) + ev = EVENT_MISS; + else if (roll <= 83) + ev = EVENT_HIT; + else + ev = EVENT_MISS_BIRD; + + Unit* shooter = GetCaster(); + Creature* wilhelm = GetHitUnit()->ToCreature(); + Creature* apple = shooter->FindNearestCreature(NPC_APPLE, 30); + Creature* drostan = shooter->FindNearestCreature(NPC_DROSTAN, 30); + + if (!wilhelm || !apple || !drostan) + return; + + switch (ev) + { + case EVENT_MISS_BIRD: + { + Creature* crunchy = shooter->FindNearestCreature(NPC_CRUNCHY, 30); + Creature* bird = shooter->FindNearestCreature(NPC_THICKBIRD, 30); + + if (!bird || !crunchy) + ; // fall to EVENT_MISS + else + { + shooter->CastSpell(bird, SPELL_MISS_BIRD_APPLE); + bird->CastSpell(bird, SPELL_BIRD_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + + bird->Kill(bird); + crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), + bird->GetMap()->GetWaterOrGroundLevel(bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); + // TODO: Make crunchy perform emote eat when he reaches the bird + + break; + } + } + case EVENT_MISS: + { + shooter->CastSpell(wilhelm, SPELL_MISS_APPLE); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + break; + } + case EVENT_HIT: + { + shooter->CastSpell(apple, SPELL_HIT_APPLE); + apple->CastSpell(apple, SPELL_APPLE_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_HIT); + if (Player* player = shooter->ToPlayer()) + player->KilledMonsterCredit(NPC_APPLE, 0); + apple->DespawnOrUnsummon(); + + break; + } + } + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_q12589_shoot_rjr_SpellScript::CheckCast); + OnEffectHitTarget += SpellEffectFn(spell_q12589_shoot_rjr_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12589_shoot_rjr_SpellScript(); + } +}; + void AddSC_sholazar_basin() { new npc_injured_rainspeaker_oracle(); @@ -756,4 +883,5 @@ void AddSC_sholazar_basin() new npc_adventurous_dwarf(); new npc_jungle_punch_target(); new spell_q12620_the_lifewarden_wrath(); + new spell_q12589_shoot_rjr(); } diff --git a/src/server/scripts/Northrend/storm_peaks.cpp b/src/server/scripts/Northrend/storm_peaks.cpp index 251bdb8278a..6bf342e4643 100644 --- a/src/server/scripts/Northrend/storm_peaks.cpp +++ b/src/server/scripts/Northrend/storm_peaks.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "Vehicle.h" @@ -550,7 +552,7 @@ public: // drake unsummoned, passengers dropped if (!me->IsOnVehicle(drake) && !hasEmptySeats) - me->ForcedDespawn(3000); + me->DespawnOrUnsummon(3000); if (enter_timer <= 0) return; @@ -605,7 +607,7 @@ public: me->ExitVehicle(); me->CastSpell(me, SPELL_SUMMON_LIBERATED, true); - me->ForcedDespawn(500); + me->DespawnOrUnsummon(500); // drake is empty now, deliver credit for drake and despawn him if (drake->GetVehicleKit()->HasEmptySeat(1) && @@ -616,7 +618,7 @@ public: if (rider->ToPlayer()) rider->ToPlayer()->KilledMonsterCredit(29709, 0); - drake->ForcedDespawn(0); + drake->DespawnOrUnsummon(0); } } } diff --git a/src/server/scripts/Northrend/wintergrasp.cpp b/src/server/scripts/Northrend/wintergrasp.cpp new file mode 100644 index 00000000000..fc967acf9e2 --- /dev/null +++ b/src/server/scripts/Northrend/wintergrasp.cpp @@ -0,0 +1,560 @@ +/* Copyright (C) 2008 - 2009 Trinity <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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattlefieldMgr.h" +#include "BattlefieldWG.h" +#include "Battlefield.h" +#include "ScriptSystem.h" +#include "WorldSession.h" +#include "ObjectMgr.h" +#include "Vehicle.h" +#include "GameObjectAI.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" + +#define GOSSIP_HELLO_DEMO1 "Build catapult." +#define GOSSIP_HELLO_DEMO2 "Build demolisher." +#define GOSSIP_HELLO_DEMO3 "Build siege engine." +#define GOSSIP_HELLO_DEMO4 "I cannot build more!" + +enum WGqueuenpctext +{ + WG_NPCQUEUE_TEXT_H_NOWAR = 14775, + WG_NPCQUEUE_TEXT_H_QUEUE = 14790, + WG_NPCQUEUE_TEXT_H_WAR = 14777, + WG_NPCQUEUE_TEXT_A_NOWAR = 14782, + WG_NPCQUEUE_TEXT_A_QUEUE = 14791, + WG_NPCQUEUE_TEXT_A_WAR = 14781, + WG_NPCQUEUE_TEXTOPTION_JOIN = -1850507, +}; + +enum Spells +{ + // Demolisher engineers spells + SPELL_BUILD_SIEGE_VEHICLE_FORCE_HORDE = 61409, + SPELL_BUILD_SIEGE_VEHICLE_FORCE_ALLIANCE = 56662, + SPELL_BUILD_CATAPULT_FORCE = 56664, + SPELL_BUILD_DEMOLISHER_FORCE = 56659, + SPELL_ACTIVATE_CONTROL_ARMS = 49899, + SPELL_RIDE_WG_VEHICLE = 60968, + + SPELL_VEHICLE_TELEPORT = 49759, + + // Spirit guide + SPELL_CHANNEL_SPIRIT_HEAL = 22011, +}; + +enum CreatureIds +{ + NPC_GOBLIN_MECHANIC = 30400, + NPC_GNOMISH_ENGINEER = 30499, + + NPC_WINTERGRASP_CONTROL_ARMS = 27852, + + NPC_WORLD_TRIGGER_LARGE_AOI_NOT_IMMUNE_PC_NPC = 23472, +}; + +enum QuestIds +{ + QUEST_BONES_AND_ARROWS_HORDE_ATT = 13193, + QUEST_JINXING_THE_WALLS_HORDE_ATT = 13202, + QUEST_SLAY_THEM_ALL_HORDE_ATT = 13180, + QUEST_FUELING_THE_DEMOLISHERS_HORDE_ATT = 13200, + QUEST_HEALING_WITH_ROSES_HORDE_ATT = 13201, + QUEST_DEFEND_THE_SIEGE_HORDE_ATT = 13223, + + QUEST_BONES_AND_ARROWS_HORDE_DEF = 13199, + QUEST_WARDING_THE_WALLS_HORDE_DEF = 13192, + QUEST_SLAY_THEM_ALL_HORDE_DEF = 13178, + QUEST_FUELING_THE_DEMOLISHERS_HORDE_DEF = 13191, + QUEST_HEALING_WITH_ROSES_HORDE_DEF = 13194, + QUEST_TOPPLING_THE_TOWERS_HORDE_DEF = 13539, + QUEST_STOP_THE_SIEGE_HORDE_DEF = 13185, + + QUEST_BONES_AND_ARROWS_ALLIANCE_ATT = 13196, + QUEST_WARDING_THE_WARRIORS_ALLIANCE_ATT = 13198, + QUEST_NO_MERCY_FOR_THE_MERCILESS_ALLIANCE_ATT = 13179, + QUEST_DEFEND_THE_SIEGE_ALLIANCE_ATT = 13222, + QUEST_A_RARE_HERB_ALLIANCE_ATT = 13195, + + QUEST_BONES_AND_ARROWS_ALLIANCE_DEF = 13154, + QUEST_WARDING_THE_WARRIORS_ALLIANCE_DEF = 13153, + QUEST_NO_MERCY_FOR_THE_MERCILESS_ALLIANCE_DEF = 13177, + QUEST_SHOUTHERN_SABOTAGE_ALLIANCE_DEF = 13538, + QUEST_STOP_THE_SIEGE_ALLIANCE_DEF = 13186, + QUEST_A_RARE_HERB_ALLIANCE_DEF = 13156, +}; + +uint8 const MAX_WINTERGRASP_VEHICLES = 4; + +uint32 const vehiclesList[MAX_WINTERGRASP_VEHICLES] = +{ + NPC_WINTERGRASP_CATAPULT, + NPC_WINTERGRASP_DEMOLISHER, + NPC_WINTERGRASP_SIEGE_ENGINE_ALLIANCE, + NPC_WINTERGRASP_SIEGE_ENGINE_HORDE +}; + +class npc_wg_demolisher_engineer : public CreatureScript +{ + public: + npc_wg_demolisher_engineer() : CreatureScript("npc_wg_demolisher_engineer") { } + + bool OnGossipHello(Player* player, Creature* creature) + { + if (creature->isQuestGiver()) + player->PrepareQuestMenu(creature->GetGUID()); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + + if (canBuild(creature)) + { + if (player->HasAura(SPELL_CORPORAL)) + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + else if (player->HasAura(SPELL_LIEUTENANT)) + { + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + } + } + else + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_DEMO4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + return true; + } + + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) + { + player->CLOSE_GOSSIP_MENU(); + + Battlefield* wintergrasp= sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + + if (canBuild(creature)) + { + switch (action - GOSSIP_ACTION_INFO_DEF) + { + case 0: + creature->CastSpell(player, SPELL_BUILD_CATAPULT_FORCE, true); + break; + case 1: + creature->CastSpell(player, SPELL_BUILD_DEMOLISHER_FORCE, true); + break; + case 2: + creature->CastSpell(player, player->GetTeamId() == TEAM_ALLIANCE ? SPELL_BUILD_SIEGE_VEHICLE_FORCE_ALLIANCE : SPELL_BUILD_SIEGE_VEHICLE_FORCE_HORDE, true); + break; + } + if (Creature* controlArms = creature->FindNearestCreature(NPC_WINTERGRASP_CONTROL_ARMS, 30.0f, true)) + creature->CastSpell(controlArms, SPELL_ACTIVATE_CONTROL_ARMS, true); + } + return true; + } + + private: + bool canBuild(Creature* creature) + { + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + + if (!wintergrasp) + return false; + switch (creature->GetEntry()) + { + case NPC_GOBLIN_MECHANIC: + return (wintergrasp->GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H) > wintergrasp->GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); + case NPC_GNOMISH_ENGINEER: + return (wintergrasp->GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A) > wintergrasp->GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); + default: + return false; + } + } +}; + +class npc_wg_spirit_guide : public CreatureScript +{ + public: + npc_wg_spirit_guide() : CreatureScript("npc_wg_spirit_guide") { } + + bool OnGossipHello(Player* player, Creature* creature) + { + if (creature->isQuestGiver()) + player->PrepareQuestMenu(creature->GetGUID()); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + if (!wintergrasp) + return true; + + GraveyardVect graveyard = wintergrasp->GetGraveyardVector(); + for (uint8 i = 0; i < graveyard.size(); i++) + if (graveyard[i]->GetControlTeamId() == player->GetTeamId()) + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(((BfGraveyardWG*)graveyard[i])->GetTextId()), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + i); + + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + return true; + } + + bool OnGossipSelect(Player* player, Creature* /*creature*/ , uint32 /*sender */ , uint32 action) + { + player->CLOSE_GOSSIP_MENU(); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + if (wintergrasp) + { + GraveyardVect gy = wintergrasp->GetGraveyardVector(); + for (uint8 i = 0; i < gy.size(); i++) + if (action - GOSSIP_ACTION_INFO_DEF == i && gy[i]->GetControlTeamId() == player->GetTeamId()) + if (WorldSafeLocsEntry const* safeLoc = sWorldSafeLocsStore.LookupEntry(gy[i]->GetGraveyardId())) + player->TeleportTo(safeLoc->map_id, safeLoc->x, safeLoc->y, safeLoc->z, 0); + } + return true; + } + + struct npc_wg_spirit_guideAI : public ScriptedAI + { + npc_wg_spirit_guideAI(Creature* creature) : ScriptedAI(creature) { } + + void UpdateAI(uint32 const /*diff*/) + { + if (!me->HasUnitState(UNIT_STATE_CASTING)) + DoCast(me, SPELL_CHANNEL_SPIRIT_HEAL); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_wg_spirit_guideAI(creature); + } +}; + +class npc_wg_queue : public CreatureScript +{ + public: + npc_wg_queue() : CreatureScript("npc_wg_queue") { } + + bool OnGossipHello(Player* player, Creature* creature) + { + if (creature->isQuestGiver()) + player->PrepareQuestMenu(creature->GetGUID()); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + if (!wintergrasp) + return true; + + if (wintergrasp->IsWarTime()) + { + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(WG_NPCQUEUE_TEXTOPTION_JOIN), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(wintergrasp->GetDefenderTeam() ? WG_NPCQUEUE_TEXT_H_WAR : WG_NPCQUEUE_TEXT_A_WAR, creature->GetGUID()); + } + else + { + uint32 timer = wintergrasp->GetTimer() / 1000; + player->SendUpdateWorldState(4354, time(NULL) + timer); + if (timer < 15 * MINUTE) + { + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, sObjectMgr->GetTrinityStringForDBCLocale(WG_NPCQUEUE_TEXTOPTION_JOIN), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(wintergrasp->GetDefenderTeam() ? WG_NPCQUEUE_TEXT_H_QUEUE : WG_NPCQUEUE_TEXT_A_QUEUE, creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(wintergrasp->GetDefenderTeam() ? WG_NPCQUEUE_TEXT_H_NOWAR : WG_NPCQUEUE_TEXT_A_NOWAR, creature->GetGUID()); + } + return true; + } + + bool OnGossipSelect(Player* player, Creature* /*creature*/ , uint32 /*sender*/ , uint32 /*action*/) + { + player->CLOSE_GOSSIP_MENU(); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + if (!wintergrasp) + return true; + + if (wintergrasp->IsWarTime()) + wintergrasp->InvitePlayerToWar(player); + else + { + uint32 timer = wintergrasp->GetTimer() / 1000; + if (timer < 15 * MINUTE) + wintergrasp->InvitePlayerToQueue(player); + } + return true; + } +}; + +class go_wg_vehicle_teleporter : public GameObjectScript +{ + public: + go_wg_vehicle_teleporter() : GameObjectScript("go_wg_vehicle_teleporter") { } + + struct go_wg_vehicle_teleporterAI : public GameObjectAI + { + go_wg_vehicle_teleporterAI(GameObject* gameObject) : GameObjectAI(gameObject), _checkTimer(1000) { } + + void UpdateAI(uint32 diff) + { + if (_checkTimer <= diff) + { + // Tabulation madness in the hole! + for (uint8 i = 0; i < MAX_WINTERGRASP_VEHICLES; i++) + if (Creature* vehicleCreature = go->FindNearestCreature(vehiclesList[i], 3.0f, true)) + if (!vehicleCreature->HasAura(SPELL_VEHICLE_TELEPORT)) + if (Vehicle* vehicle = vehicleCreature->GetVehicle()) + if (Unit* passenger = vehicle->GetPassenger(0)) + if (go->GetUInt32Value(GAMEOBJECT_FACTION) == passenger->getFaction()) + if (Creature* teleportTrigger = vehicleCreature->FindNearestCreature(NPC_WORLD_TRIGGER_LARGE_AOI_NOT_IMMUNE_PC_NPC, 100.0f, true)) + teleportTrigger->CastSpell(vehicleCreature, SPELL_VEHICLE_TELEPORT, true); + + _checkTimer = 1000; + } + else _checkTimer -= diff; + } + + private: + uint32 _checkTimer; + }; + + GameObjectAI* GetGameObjectAI(GameObject* go) const + { + return new go_wg_vehicle_teleporterAI(go); + } +}; + +class npc_wg_quest_giver : public CreatureScript +{ + public: + npc_wg_quest_giver() : CreatureScript("npc_wg_quest_giver") { } + + bool OnGossipHello(Player* player, Creature* creature) + { + if (creature->isQuestGiver()) + player->PrepareQuestMenu(creature->GetGUID()); + + Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); + if (!wintergrasp) + return true; + + if (creature->isQuestGiver()) + { + QuestRelationBounds objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry()); + QuestRelationBounds objectQIR = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(creature->GetEntry()); + + QuestMenu& qm = player->PlayerTalkClass->GetQuestMenu(); + qm.ClearMenu(); + + for (QuestRelations::const_iterator i = objectQIR.first; i != objectQIR.second; ++i) + { + uint32 questId = i->second; + QuestStatus status = player->GetQuestStatus(questId); + if (status == QUEST_STATUS_COMPLETE) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_INCOMPLETE) + qm.AddMenuItem(questId, 4); + //else if (status == QUEST_STATUS_AVAILABLE) + // qm.AddMenuItem(quest_id, 2); + } + + for (QuestRelations::const_iterator i = objectQR.first; i != objectQR.second; ++i) + { + uint32 questId = i->second; + Quest const* quest = sObjectMgr->GetQuestTemplate(questId); + if (!quest) + continue; + + switch (questId) + { + // Horde attacker + case QUEST_BONES_AND_ARROWS_HORDE_ATT: + case QUEST_JINXING_THE_WALLS_HORDE_ATT: + case QUEST_SLAY_THEM_ALL_HORDE_ATT: + case QUEST_FUELING_THE_DEMOLISHERS_HORDE_ATT: + case QUEST_HEALING_WITH_ROSES_HORDE_ATT: + case QUEST_DEFEND_THE_SIEGE_HORDE_ATT: + if (wintergrasp->GetAttackerTeam() == TEAM_HORDE) + { + QuestStatus status = player->GetQuestStatus(questId); + + if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 2); + } + break; + // Horde defender + case QUEST_BONES_AND_ARROWS_HORDE_DEF: + case QUEST_WARDING_THE_WALLS_HORDE_DEF: + case QUEST_SLAY_THEM_ALL_HORDE_DEF: + case QUEST_FUELING_THE_DEMOLISHERS_HORDE_DEF: + case QUEST_HEALING_WITH_ROSES_HORDE_DEF: + case QUEST_TOPPLING_THE_TOWERS_HORDE_DEF: + case QUEST_STOP_THE_SIEGE_HORDE_DEF: + if (wintergrasp->GetDefenderTeam() == TEAM_HORDE) + { + QuestStatus status = player->GetQuestStatus(questId); + + if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 2); + } + break; + // Alliance attacker + case QUEST_BONES_AND_ARROWS_ALLIANCE_ATT: + case QUEST_WARDING_THE_WARRIORS_ALLIANCE_ATT: + case QUEST_NO_MERCY_FOR_THE_MERCILESS_ALLIANCE_ATT: + case QUEST_DEFEND_THE_SIEGE_ALLIANCE_ATT: + case QUEST_A_RARE_HERB_ALLIANCE_ATT: + if (wintergrasp->GetAttackerTeam() == TEAM_ALLIANCE) + { + QuestStatus status = player->GetQuestStatus(questId); + + if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 2); + } + break; + // Alliance defender + case QUEST_BONES_AND_ARROWS_ALLIANCE_DEF: + case QUEST_WARDING_THE_WARRIORS_ALLIANCE_DEF: + case QUEST_NO_MERCY_FOR_THE_MERCILESS_ALLIANCE_DEF: + case QUEST_SHOUTHERN_SABOTAGE_ALLIANCE_DEF: + case QUEST_STOP_THE_SIEGE_ALLIANCE_DEF: + case QUEST_A_RARE_HERB_ALLIANCE_DEF: + if (wintergrasp->GetDefenderTeam() == TEAM_ALLIANCE) + { + QuestStatus status = player->GetQuestStatus(questId); + + if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 2); + } + break; + default: + QuestStatus status = player->GetQuestStatus(questId); + + if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 4); + else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) + qm.AddMenuItem(questId, 2); + break; + } + } + } + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + return true; + } +}; + +class spell_wintergrasp_force_building : public SpellScriptLoader +{ + public: + spell_wintergrasp_force_building() : SpellScriptLoader("spell_wintergrasp_force_building") { } + + class spell_wintergrasp_force_building_SpellScript : public SpellScript + { + PrepareSpellScript(spell_wintergrasp_force_building_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_BUILD_CATAPULT_FORCE) + || !sSpellMgr->GetSpellInfo(SPELL_BUILD_DEMOLISHER_FORCE) + || !sSpellMgr->GetSpellInfo(SPELL_BUILD_SIEGE_VEHICLE_FORCE_HORDE) + || !sSpellMgr->GetSpellInfo(SPELL_BUILD_SIEGE_VEHICLE_FORCE_ALLIANCE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetHitUnit(), GetEffectValue(), false); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_wintergrasp_force_building_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_wintergrasp_force_building_SpellScript(); + } +}; + +class spell_wintergrasp_grab_passenger : public SpellScriptLoader +{ + public: + spell_wintergrasp_grab_passenger() : SpellScriptLoader("spell_wintergrasp_grab_passenger") { } + + class spell_wintergrasp_grab_passenger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_wintergrasp_grab_passenger_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Player* target = GetHitPlayer()) + target->CastSpell(GetCaster(), SPELL_RIDE_WG_VEHICLE, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_wintergrasp_grab_passenger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_wintergrasp_grab_passenger_SpellScript(); + } +}; + +class achievement_wg_didnt_stand_a_chance : public AchievementCriteriaScript +{ +public: + achievement_wg_didnt_stand_a_chance() : AchievementCriteriaScript("achievement_wg_didnt_stand_a_chance") { } + + bool OnCheck(Player* source, Unit* target) + { + if (!target) + return false; + + if (Player* victim = target->ToPlayer()) + { + if (!victim->IsMounted()) + return false; + + if (Vehicle* vehicle = source->GetVehicle()) + if (vehicle->GetVehicleInfo()->m_ID == 244) // Wintergrasp Tower Cannon + return true; + } + + return false; + } +}; + +void AddSC_wintergrasp() +{ + new npc_wg_queue(); + new npc_wg_spirit_guide(); + new npc_wg_demolisher_engineer(); + new go_wg_vehicle_teleporter(); + new npc_wg_quest_giver(); + new spell_wintergrasp_force_building(); + new spell_wintergrasp_grab_passenger(); + new achievement_wg_didnt_stand_a_chance(); +} diff --git a/src/server/scripts/Northrend/zuldrak.cpp b/src/server/scripts/Northrend/zuldrak.cpp index 369f47cfb1c..6af96f3fdfd 100644 --- a/src/server/scripts/Northrend/zuldrak.cpp +++ b/src/server/scripts/Northrend/zuldrak.cpp @@ -15,7 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "ScriptedEscortAI.h" /*#### |
