diff options
Diffstat (limited to 'src')
6 files changed, 438 insertions, 11 deletions
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 2bd8bfdacd0..e68f6adef90 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -483,6 +483,7 @@ void AddSC_icecrown_citadel(); void AddSC_instance_ruby_sanctum(); // Ruby Sanctum void AddSC_ruby_sanctum(); void AddSC_boss_baltharus_the_warborn(); +void AddSC_boss_saviana_ragefire(); void AddSC_dalaran(); void AddSC_borean_tundra(); @@ -1181,6 +1182,7 @@ void AddNorthrendScripts() AddSC_instance_ruby_sanctum(); // Ruby Sanctum AddSC_ruby_sanctum(); AddSC_boss_baltharus_the_warborn(); + AddSC_boss_saviana_ragefire(); AddSC_dalaran(); AddSC_borean_tundra(); diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index 68852f5e34b..cd28cf5a506 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -189,6 +189,7 @@ set(scripts_STAT_SRCS Northrend/RubySanctum/ruby_sanctum.h Northrend/RubySanctum/ruby_sanctum.cpp Northrend/RubySanctum/boss_baltharus_the_warborn.cpp + Northrend/RubySanctum/boss_saviana_ragefire.cpp ) message(" -> Prepared: Northrend") diff --git a/src/server/scripts/Northrend/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/RubySanctum/boss_baltharus_the_warborn.cpp index bccb5c1bd81..bd9b478a035 100644 --- a/src/server/scripts/Northrend/RubySanctum/boss_baltharus_the_warborn.cpp +++ b/src/server/scripts/Northrend/RubySanctum/boss_baltharus_the_warborn.cpp @@ -84,6 +84,7 @@ class boss_baltharus_the_warborn : public CreatureScript events.SetPhase(PHASE_INTRO); events.ScheduleEvent(EVENT_OOC_CHANNEL, 0, 0, PHASE_INTRO); _cloneCount = RAID_MODE<uint8>(1, 2, 2, 2); + instance->SetData(DATA_BALTHARUS_SHARED_HEALTH, me->GetMaxHealth()); } void DoAction(int32 const action) @@ -157,6 +158,9 @@ class boss_baltharus_the_warborn : public CreatureScript else if (me->HealthBelowPctDamaged(33, damage) && _cloneCount == 1) DoAction(ACTION_CLONE); } + + if (me->GetHealth() - damage > 0) + instance->SetData(DATA_BALTHARUS_SHARED_HEALTH, me->GetHealth() - damage); } void UpdateAI(uint32 const diff) @@ -164,6 +168,9 @@ class boss_baltharus_the_warborn : public CreatureScript if (!UpdateVictim() && !(events.GetPhaseMask() & PHASE_INTRO_MASK)) return; + if (!(events.GetPhaseMask() & PHASE_INTRO_MASK)) + me->SetHealth(instance->GetData(DATA_BALTHARUS_SHARED_HEALTH)); + events.Update(diff); if (me->HasUnitState(UNIT_STAT_CASTING) && !(events.GetPhaseMask() & PHASE_INTRO_MASK)) @@ -214,6 +221,84 @@ class boss_baltharus_the_warborn : public CreatureScript } }; +class npc_baltarhus_the_warborn_clone : public CreatureScript +{ + public: + npc_baltarhus_the_warborn_clone() : CreatureScript("npc_baltarhus_the_warborn_clone") { } + + struct npc_baltarhus_the_warborn_cloneAI : public ScriptedAI + { + npc_baltarhus_the_warborn_cloneAI(Creature* creature) : ScriptedAI(creature) + { + _instance = (InstanceScript*)creature->GetInstanceScript(); + } + + void EnterCombat(Unit* /*who*/) + { + DoZoneInCombat(); + _events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); + _events.ScheduleEvent(EVENT_BLADE_TEMPEST, urand(18000, 25000)); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + // Setting DATA_BALTHARUS_SHARED_HEALTH to 0 when killed would bug the boss. + if (_instance && me->GetHealth() - damage > 0) + _instance->SetData(DATA_BALTHARUS_SHARED_HEALTH, me->GetHealth() - damage); + } + + void JustDied(Unit* killer) + { + // This is here because DamageTaken wont trigger if the damage is deadly. + if (_instance) + if (Creature* baltarhus = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_BALTHARUS_THE_WARBORN))) + killer->Kill(baltarhus); + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + if (_instance) + me->SetHealth(_instance->GetData(DATA_BALTHARUS_SHARED_HEALTH)); + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + _events.ScheduleEvent(EVENT_CLEAVE, 24000); + break; + case EVENT_BLADE_TEMPEST: + DoCastVictim(SPELL_BLADE_TEMPEST); + _events.ScheduleEvent(EVENT_BLADE_TEMPEST, 24000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetRubySanctumAI<npc_baltarhus_the_warborn_cloneAI>(creature); + } +}; + class spell_baltharus_enervating_brand : public SpellScriptLoader { public: @@ -299,6 +384,7 @@ class spell_baltharus_enervating_brand_trigger : public SpellScriptLoader void AddSC_boss_baltharus_the_warborn() { new boss_baltharus_the_warborn(); + new npc_baltarhus_the_warborn_clone(); new spell_baltharus_enervating_brand(); new spell_baltharus_enervating_brand_trigger(); } diff --git a/src/server/scripts/Northrend/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/RubySanctum/boss_saviana_ragefire.cpp new file mode 100644 index 00000000000..3bf34c42c03 --- /dev/null +++ b/src/server/scripts/Northrend/RubySanctum/boss_saviana_ragefire.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2008-2011 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 "ScriptPCH.h" +#include "ruby_sanctum.h" + +enum Texts +{ + SAY_AGGRO = 0, // You will sssuffer for this intrusion! (17528) + SAY_CONFLAGRATION = 1, // Burn in the master's flame! (17532) + EMOTE_ENRAGED = 2, // %s becomes enraged! + SAY_KILL = 3, // Halion will be pleased. (17530) - As it should be.... (17529) +}; + +enum Spells +{ + SPELL_CONFLAGRATION = 74452, + SPELL_FLAME_BEACON = 74453, + SPELL_CONFLAGRATION_2 = 74454, // Unknown dummy effect + SPELL_ENRAGE = 78722, + SPELL_FLAME_BREATH = 74403, +}; + +enum Events +{ + EVENT_ENRAGE = 1, + EVENT_FLIGHT = 2, + EVENT_FLAME_BREATH = 3, + EVENT_CONFLAGRATION = 4, + + // Event group + EVENT_GROUP_LAND_PHASE = 1, +}; + +enum MovementPoints +{ + POINT_FLIGHT = 1, + POINT_LAND = 2, +}; + +enum Misc +{ + SOUND_ID_DEATH = 17531, +}; + +Position const SavianaRagefireFlyPos = {3155.51f, 683.844f, 95.20f, 4.69f}; +Position const SavianaRagefireLandPos = {3151.07f, 636.443f, 79.54f, 4.69f}; + +class boss_saviana_ragefire : public CreatureScript +{ + public: + boss_saviana_ragefire() : CreatureScript("boss_saviana_ragefire") { } + + struct boss_saviana_ragefireAI : public BossAI + { + boss_saviana_ragefireAI(Creature* creature) : BossAI(creature, DATA_SAVIANA_RAGEFIRE) + { + } + + void Reset() + { + _Reset(); + me->SetReactState(REACT_AGGRESSIVE); + events.ScheduleEvent(EVENT_ENRAGE, 20000, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_FLAME_BREATH, 30000, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_FLIGHT, 50000); + } + + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + Talk(SAY_AGGRO); + } + + void JustDied(Unit* /*killer*/) + { + _JustDied(); + me->PlayDirectSound(SOUND_ID_DEATH); + } + + void MovementInform(uint32 type, uint32 point) + { + if (type != POINT_MOTION_TYPE) + return; + + switch (point) + { + case POINT_FLIGHT: + events.ScheduleEvent(EVENT_CONFLAGRATION, 1000); + Talk(SAY_CONFLAGRATION); + break; + case POINT_LAND: + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetReactState(REACT_AGGRESSIVE); + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + DoStartMovement(me->getVictim()); + break; + default: + break; + } + } + + void JustReachedHome() + { + _JustReachedHome(); + me->SetFlying(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_KILL); + } + + void UpdateAI(uint32 const diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FLIGHT: + { + me->SetFlying(true); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MovePoint(POINT_FLIGHT, SavianaRagefireFlyPos); + events.ScheduleEvent(EVENT_FLIGHT, 50000); + events.DelayEvents(12500, EVENT_GROUP_LAND_PHASE); + break; + } + case EVENT_CONFLAGRATION: + DoCast(me, SPELL_CONFLAGRATION, true); + break; + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + Talk(EMOTE_ENRAGED); + events.ScheduleEvent(EVENT_ENRAGE, urand(15000, 20000), EVENT_GROUP_LAND_PHASE); + break; + case EVENT_FLAME_BREATH: + DoCastVictim(SPELL_FLAME_BREATH); + events.ScheduleEvent(EVENT_FLAME_BREATH, urand(20000, 30000), EVENT_GROUP_LAND_PHASE); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetRubySanctumAI<boss_saviana_ragefireAI>(creature); + } +}; + +class ConflagrationTargetSelector +{ + public: + ConflagrationTargetSelector() { } + + bool operator()(Unit* unit) + { + return unit->GetTypeId() != TYPEID_PLAYER; + } +}; + +class spell_saviana_conflagration_init : public SpellScriptLoader +{ + public: + spell_saviana_conflagration_init() : SpellScriptLoader("spell_saviana_conflagration_init") { } + + class spell_saviana_conflagration_init_SpellScript : public SpellScript + { + PrepareSpellScript(spell_saviana_conflagration_init_SpellScript); + + void FilterTargets(std::list<Unit*>& unitList) + { + unitList.remove_if(ConflagrationTargetSelector()); + uint8 maxSize = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 3); + if (unitList.size() > maxSize) + Trinity::RandomResizeList(unitList, maxSize); + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), SPELL_FLAME_BEACON, true); + GetCaster()->CastSpell(GetHitUnit(), SPELL_CONFLAGRATION_2, true); + } + + void Register() + { + OnUnitTargetSelect += SpellUnitTargetFn(spell_saviana_conflagration_init_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_AREA_ENEMY_SRC); + OnEffect += SpellEffectFn(spell_saviana_conflagration_init_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_saviana_conflagration_init_SpellScript(); + } +}; + +class spell_saviana_conflagration_throwback : public SpellScriptLoader +{ + public: + spell_saviana_conflagration_throwback() : SpellScriptLoader("spell_saviana_conflagration_throwback") { } + + class spell_saviana_conflagration_throwback_SpellScript : public SpellScript + { + PrepareSpellScript(spell_saviana_conflagration_throwback_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true); + GetHitUnit()->GetMotionMaster()->MovePoint(POINT_LAND, SavianaRagefireLandPos); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_saviana_conflagration_throwback_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_saviana_conflagration_throwback_SpellScript(); + } +}; + +void AddSC_boss_saviana_ragefire() +{ + new boss_saviana_ragefire(); + new spell_saviana_conflagration_init(); + new spell_saviana_conflagration_throwback(); +} diff --git a/src/server/scripts/Northrend/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/RubySanctum/instance_ruby_sanctum.cpp index 88f0a0fc217..8d4e1e2ad0c 100644 --- a/src/server/scripts/Northrend/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/RubySanctum/instance_ruby_sanctum.cpp @@ -38,10 +38,12 @@ class instance_ruby_sanctum : public InstanceMapScript LoadDoorData(doorData); BaltharusTheWarbornGUID = 0; GeneralZarithrianGUID = 0; - SavinaRagefireGUID = 0; + SavianaRagefireGUID = 0; HalionGUID = 0; CrystalChannelTargetGUID = 0; XerestraszaGUID = 0; + BaltharusSharedHealth = 0; + FlameWallsGUID = 0; } void OnCreatureCreate(Creature* creature) @@ -54,8 +56,8 @@ class instance_ruby_sanctum : public InstanceMapScript case NPC_GENERAL_ZARITHRIAN: GeneralZarithrianGUID = creature->GetGUID(); break; - case NPC_SAVINA_RAGEFIRE: - SavinaRagefireGUID = creature->GetGUID(); + case NPC_SAVIANA_RAGEFIRE: + SavianaRagefireGUID = creature->GetGUID(); break; case NPC_HALION: HalionGUID = creature->GetGUID(); @@ -78,6 +80,9 @@ class instance_ruby_sanctum : public InstanceMapScript case GO_FIRE_FIELD: AddDoor(go, true); break; + case GO_FLAME_WALLS: + FlameWallsGUID = go->GetGUID(); + break; default: break; } @@ -103,8 +108,8 @@ class instance_ruby_sanctum : public InstanceMapScript return BaltharusTheWarbornGUID; case DATA_GENERAL_ZARITHRIAN: return GeneralZarithrianGUID; - case DATA_SAVINA_RAGEFIRE: - return SavinaRagefireGUID; + case DATA_SAVIANA_RAGEFIRE: + return SavianaRagefireGUID; case DATA_HALION: return HalionGUID; case DATA_CRYSTAL_CHANNEL_TARGET: @@ -118,6 +123,72 @@ class instance_ruby_sanctum : public InstanceMapScript return 0; } + bool SetBossState(uint32 type, EncounterState state) + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_BALTHARUS_THE_WARBORN: + { + if (state == DONE && GetBossState(DATA_SAVIANA_RAGEFIRE) == DONE) + { + // GO_FLAME_WALLS + if (GameObject* flameWalls = instance->GetGameObject(FlameWallsGUID)) + { + flameWalls->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + flameWalls->SetGoState(GO_STATE_READY); + } + if (Creature* zarithrian = instance->GetCreature(GeneralZarithrianGUID)) + zarithrian->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE) + } + break; + } + case DATA_SAVIANA_RAGEFIRE: + { + if (state == DONE && GetBossState(DATA_BALTHARUS_THE_WARBORN) == DONE) + { + if (GameObject* flameWalls = instance->GetGameObject(FlameWallsGUID)) + { + flameWalls->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + flameWalls->SetGoState(GO_STATE_READY); + } + if (Creature* zarithrian = instance->GetCreature(GeneralZarithrianGUID)) + zarithrian->RemoveFlag(UNIT_FLAG, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE) + } + break; + } + default: + break; + } + + return true; + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case DATA_BALTHARUS_SHARED_HEALTH: + BaltharusSharedHealth = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case DATA_BALTHARUS_SHARED_HEALTH: + return BaltharusSharedHealth; + default: + break; + } + + return 0; + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; @@ -165,10 +236,12 @@ class instance_ruby_sanctum : public InstanceMapScript protected: uint64 BaltharusTheWarbornGUID; uint64 GeneralZarithrianGUID; - uint64 SavinaRagefireGUID; + uint64 SavianaRagefireGUID; uint64 HalionGUID; uint64 CrystalChannelTargetGUID; uint64 XerestraszaGUID; + uint64 FlameWallsGUID; + uint32 BaltharusSharedHealth; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/Northrend/RubySanctum/ruby_sanctum.h b/src/server/scripts/Northrend/RubySanctum/ruby_sanctum.h index 60b4c9f3e92..4ece06807cf 100644 --- a/src/server/scripts/Northrend/RubySanctum/ruby_sanctum.h +++ b/src/server/scripts/Northrend/RubySanctum/ruby_sanctum.h @@ -30,12 +30,13 @@ enum DataTypes // Encounter States/Boss GUIDs DATA_BALTHARUS_THE_WARBORN = 0, DATA_GENERAL_ZARITHRIAN = 1, - DATA_SAVINA_RAGEFIRE = 2, + DATA_SAVIANA_RAGEFIRE = 2, DATA_HALION = 3, // Etc DATA_XERESTRASZA = 4, DATA_CRYSTAL_CHANNEL_TARGET = 5, + DATA_BALTHARUS_SHARED_HEALTH = 6, }; enum SharedActions @@ -57,7 +58,7 @@ enum CreaturesIds NPC_ZARITHIAN_SPAWN_STALKER = 39794, // Saviana Ragefire - NPC_SAVINA_RAGEFIRE = 39747, + NPC_SAVIANA_RAGEFIRE = 39747, // Halion NPC_HALION = 39863, @@ -86,9 +87,9 @@ enum GameObjectsIds enum WorldStatesRS { - WORLDSTATE_UNK_1 = 5049, - WORLDSTATE_UNK_2 = 5050, - WORLDSTATE_UNK_3 = 5051, + WORLDSTATE_UNK_1 = 5049, // Halion corporeality amount - normal phase + WORLDSTATE_UNK_2 = 5050, // Halion corporeality amount - twilight phase + WORLDSTATE_UNK_3 = 5051, // Halion corporeality toggle show }; template<class AI> |