diff options
Diffstat (limited to 'src')
5 files changed, 474 insertions, 31 deletions
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp index fb44a403d86..dfc5f5992a6 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -108,6 +108,7 @@ class boss_grand_warlock_nethekurse : public CreatureScript void Reset() override { + _Reset(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Initialize(); @@ -115,9 +116,8 @@ class boss_grand_warlock_nethekurse : public CreatureScript void JustDied(Unit* /*killer*/) override { + _JustDied(); Talk(SAY_DIE); - - instance->SetBossState(DATA_NETHEKURSE, DONE); } void SetData(uint32 data, uint32 value) override diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp index 7d00cd97126..a950882eddd 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp @@ -160,6 +160,7 @@ class boss_warbringer_omrogg : public CreatureScript void Reset() override { + _Reset(); if (Unit* LeftHead = ObjectAccessor::GetUnit(*me, LeftHeadGUID)) { LeftHead->setDeathState(JUST_DIED); @@ -257,14 +258,14 @@ class boss_warbringer_omrogg : public CreatureScript Creature* LeftHead = ObjectAccessor::GetCreature(*me, LeftHeadGUID); Creature* RightHead = ObjectAccessor::GetCreature(*me, RightHeadGUID); + _JustDied(); + if (!LeftHead || !RightHead) return; LeftHead->AI()->Talk(YELL_DIE_L); RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL); - - instance->SetBossState(DATA_OMROGG, DONE); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index b44ae46c78c..21ed710f4d8 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -35,7 +35,10 @@ enum Says { SAY_AGGRO = 0, SAY_SLAY = 1, - SAY_DEATH = 2 + SAY_DEATH = 2, + + SAY_CALL_EXECUTIONER_A = 3, + SAY_CALL_EXECUTIONER_H = 4 }; enum Spells @@ -84,10 +87,28 @@ class boss_warchief_kargath_bladefist : public CreatureScript resetcheck_timer = 5000; } + void SetData(uint32 type, uint32 data) override + { + if (type == 1) + { + switch (data) + { + case ALLIANCE: + Talk(SAY_CALL_EXECUTIONER_A); + break; + case HORDE: + Talk(SAY_CALL_EXECUTIONER_H); + break; + default: + break; + } + } + } + void Reset() override { removeAdds(); - + _Reset(); me->SetSpeed(MOVE_RUN, 2); me->SetWalk(false); @@ -96,10 +117,9 @@ class boss_warchief_kargath_bladefist : public CreatureScript void JustDied(Unit* /*killer*/) override { + _JustDied(); Talk(SAY_DEATH); removeAdds(); - - instance->SetBossState(DATA_KARGATH, DONE); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index c6b08bdada1..88cfb5ac0bf 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -27,6 +27,22 @@ EndScriptData */ #include "InstanceScript.h" #include "shattered_halls.h" +enum Spells +{ + SPELL_CLEAVE = 15284, + + SPELL_EXECUTE_1 = 39288, + SPELL_EXECUTE_2, + SPELL_EXECUTE_3 +}; + +DoorData const doorData[] = +{ + {GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_S }, + {GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_N }, + {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} +}; + class instance_shattered_halls : public InstanceMapScript { public: @@ -43,6 +59,43 @@ class instance_shattered_halls : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadDoorData(doorData); + executionTimer = 0; + executed = 0; + _team = 0; + } + + void OnPlayerEnter(Player* player) override + { + Aura* ex = nullptr; + + if (!_team) + _team = player->GetTeam(); + + player->RemoveAurasDueToSpell(SPELL_EXECUTE_1); + player->RemoveAurasDueToSpell(SPELL_EXECUTE_2); + player->RemoveAurasDueToSpell(SPELL_EXECUTE_3); + + if (!executionTimer || executionerGUID.IsEmpty()) + return; + + switch (executed) + { + case 0: + ex = player->AddAura(SPELL_EXECUTE_1, player); + break; + case 1: + ex = player->AddAura(SPELL_EXECUTE_2, player); + break; + case 2: + ex = player->AddAura(SPELL_EXECUTE_3, player); + break; + default: + break; + } + + if (ex) + ex->SetDuration(executionTimer); } void OnGameObjectCreate(GameObject* go) override @@ -50,21 +103,53 @@ class instance_shattered_halls : public InstanceMapScript switch (go->GetEntry()) { case GO_GRAND_WARLOCK_CHAMBER_DOOR_1: - nethekurseDoor1GUID = go->GetGUID(); + case GO_GRAND_WARLOCK_CHAMBER_DOOR_2: + AddDoor(go, true); + default: break; + } + } + + void OnGameObjectRemove(GameObject* go) override + { + switch (go->GetEntry()) + { + case GO_GRAND_WARLOCK_CHAMBER_DOOR_1: case GO_GRAND_WARLOCK_CHAMBER_DOOR_2: - nethekurseDoor2GUID = go->GetGUID(); + AddDoor(go, false); + default: break; } } void OnCreatureCreate(Creature* creature) override { + if (!_team) + { + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* player = players.begin()->GetSource()) + _team = player->GetTeam(); + } + switch (creature->GetEntry()) { case NPC_GRAND_WARLOCK_NETHEKURSE: nethekurseGUID = creature->GetGUID(); break; + case NPC_KARGATH_BLADEFIST: + kargathGUID = creature->GetGUID(); + break; + case NPC_RANDY_WHIZZLESPROCKET: + if (_team == HORDE) + creature->UpdateEntry(NPC_DRISELLA); + break; + case NPC_SHATTERED_EXECUTIONER: + executionTimer = 55 * MINUTE * IN_MILLISECONDS; + DoCastSpellOnPlayers(SPELL_EXECUTE_1); + executionerGUID = creature->GetGUID(); + SaveToDB(); + break; } } @@ -75,18 +160,20 @@ class instance_shattered_halls : public InstanceMapScript switch (type) { - case DATA_NETHEKURSE: - if (state == IN_PROGRESS) + case DATA_SHATTERED_EXECUTIONER: + if (state == DONE) { - HandleGameObject(nethekurseDoor1GUID, false); - HandleGameObject(nethekurseDoor2GUID, false); - } - else - { - HandleGameObject(nethekurseDoor1GUID, true); - HandleGameObject(nethekurseDoor2GUID, true); + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1); + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2); + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3); + executionTimer = 0; + SaveToDB(); } break; + case DATA_KARGATH: + if (Creature* executioner = instance->GetCreature(executionerGUID)) + executioner->AI()->Reset(); + break; case DATA_OMROGG: break; } @@ -100,24 +187,307 @@ class instance_shattered_halls : public InstanceMapScript case NPC_GRAND_WARLOCK_NETHEKURSE: return nethekurseGUID; break; - case GO_GRAND_WARLOCK_CHAMBER_DOOR_1: - return nethekurseDoor1GUID; + case NPC_KARGATH_BLADEFIST: + return kargathGUID; break; - case GO_GRAND_WARLOCK_CHAMBER_DOOR_2: - return nethekurseDoor2GUID; + case NPC_SHATTERED_EXECUTIONER: + return executionerGUID; + break; + default: + return ObjectGuid::Empty; break; } - return ObjectGuid::Empty; + } + + void WriteSaveDataMore(std::ostringstream& data) override + { + if (!instance->IsHeroic()) + return; + + data << uint32(executed) << ' ' + << executionTimer << ' '; + } + + void ReadSaveDataMore(std::istringstream& data) override + { + if (!instance->IsHeroic()) + return; + + uint32 readbuff; + data >> readbuff; + executed = uint8(readbuff); + data >> readbuff; + + if (executed > VictimCount) + { + executed = VictimCount; + executionTimer = 0; + return; + } + + if (!readbuff) + return; + + Creature* executioner = nullptr; + + instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY()); + if (Creature* kargath = instance->GetCreature(kargathGUID)) + if (executionerGUID.IsEmpty()) + executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner); + + if (executioner) + for (uint8 i = executed; i < VictimCount; ++i) + executioner->SummonCreature(executionerVictims[i](GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos()); + + executionTimer = readbuff; + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_PRISONERS_EXECUTED: + return executed; + break; + case DATA_TEAM_IN_INSTANCE: + return _team; + break; + default: + return 0; + break; + } + } + + void Update(uint32 diff) override + { + if (!executionTimer) + return; + + if (executionTimer <= diff) + { + switch (++executed) + { + case 1: + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1); + DoCastSpellOnPlayers(SPELL_EXECUTE_2); + executionTimer = 10 * MINUTE * IN_MILLISECONDS; + break; + case 2: + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2); + DoCastSpellOnPlayers(SPELL_EXECUTE_3); + executionTimer = 15 * MINUTE * IN_MILLISECONDS; + break; + default: + DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3); + executionTimer = 0; + break; + } + + if (Creature* executioner = instance->GetCreature(executionerGUID)) + executioner->AI()->SetData(1, executed); + + SaveToDB(); + } + else + executionTimer -= diff; } protected: ObjectGuid nethekurseGUID; - ObjectGuid nethekurseDoor1GUID; - ObjectGuid nethekurseDoor2GUID; + ObjectGuid kargathGUID; + ObjectGuid executionerGUID; + + uint8 executed; + uint32 executionTimer; + uint32 _team; }; }; +class at_nethekurse_exit : public AreaTriggerScript +{ + public: + at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { }; + + bool OnTrigger(Player* player, AreaTriggerEntry const*, bool /* entered */) override + { + if (InstanceScript* is = player->GetInstanceScript()) + { + if (is->instance->IsHeroic()) + { + Creature* executioner = nullptr; + + is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY()); + if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST))) + { + if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty()) + { + executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner); + kargath->AI()->SetData(1, is->GetData(DATA_TEAM_IN_INSTANCE)); + } + } + + if (executioner) + for (uint8 i = 0; i < VictimCount; ++i) + executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos()); + } + } + + return false; + } +}; + +class boss_shattered_executioner : public CreatureScript +{ + public: + boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { } + + struct boss_shattered_executionerAI : public BossAI + { + boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER) + { + Initialize(); + }; + + void Initialize() + { + cleaveTimer = 500; + me->ResetLootMode(); + switch (instance->GetData(DATA_PRISONERS_EXECUTED)) + { + case 0: + me->AddLootMode(LOOT_MODE_HARD_MODE_3); + case 1: + me->AddLootMode(LOOT_MODE_HARD_MODE_2); + case 2: + me->AddLootMode(LOOT_MODE_HARD_MODE_1); + default: + break; + } + } + + void Reset() override + { + _Reset(); + if (instance->GetBossState(DATA_KARGATH) == DONE) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + else + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + + Initialize(); + } + + void JustSummoned(Creature*) override { } + + void JustDied(Unit*) override + { + _JustDied(); + Map::PlayerList const &players = instance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pl = itr->GetSource(); + uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; + if (pl->GetQuestStatus(qId) != QUEST_STATUS_NONE && pl->GetQuestStatus(qId) != QUEST_STATUS_FAILED) + pl->CompleteQuest(qId); + } + } + + void SetData(uint32 type, uint32 data) override + { + if (type == 1) + { + uint32 entry = executionerVictims[data - 1](instance->GetData(DATA_TEAM_IN_INSTANCE)); + if (Creature* victim = me->FindNearestCreature(entry, 30.0f, true)) + me->Kill(victim); + + if (data == 1) + { + Map::PlayerList const &players = instance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pl = itr->GetSource(); + uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; + if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE) + pl->FailQuest(qId); + } + } + + switch (data) + { + case 3: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_1); + case 2: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_2); + case 1: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_3); + default: + break; + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (cleaveTimer <= diff) + { + DoCast(SPELL_CLEAVE); + cleaveTimer = urand(5000, 7000); + } + else + cleaveTimer -= diff; + + DoMeleeAttackIfReady(); + } + private: + uint32 cleaveTimer; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_shattered_executionerAI>(creature); + } +}; + +class spell_kargath_executioner : public SpellScriptLoader +{ + public: + spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { } + + class spell_kargath_executioner_AuraScript : public AuraScript + { + PrepareAuraScript(spell_kargath_executioner_AuraScript); + + bool AreaCheck(Unit* target) + { + if (target->GetMap()->GetId() != 540) + return false; + + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void Register() override + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_kargath_executioner_AuraScript(); + } +}; + void AddSC_instance_shattered_halls() { new instance_shattered_halls(); + new at_nethekurse_exit(); + new boss_shattered_executioner(); + new spell_kargath_executioner(); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h index 90cbbe2a438..adc07bec2ff 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h @@ -21,18 +21,41 @@ #define DataHeader "SH" -uint32 const EncounterCount = 3; +uint32 const EncounterCount = 4; +uint32 const VictimCount = 3; enum DataTypes { - DATA_NETHEKURSE = 1, - DATA_OMROGG = 2, - DATA_KARGATH = 3 + DATA_NETHEKURSE = 0, + DATA_OMROGG = 1, + DATA_KARGATH = 2, + + DATA_SHATTERED_EXECUTIONER = 3, + DATA_PRISONERS_EXECUTED = 4, + + DATA_TEAM_IN_INSTANCE = 5 }; enum CreatureIds { - NPC_GRAND_WARLOCK_NETHEKURSE = 16807 + NPC_GRAND_WARLOCK_NETHEKURSE = 16807, + NPC_KARGATH_BLADEFIST = 16808, + + NPC_SHATTERED_EXECUTIONER = 17301, + + // Alliance Ids + NPC_RANDY_WHIZZLESPROCKET = 17288, + + NPC_CAPTAIN_ALINA = 17290, + NPC_ALLIANCE_VICTIM_1 = 17289, + NPC_ALLIANCE_VICTIM_2 = 17292, + + // Horde Ids + NPC_DRISELLA = 17294, + + NPC_CAPTAIN_BONESHATTER = 17296, + NPC_HORDE_VICTIM_1 = 17295, + NPC_HORDE_VICTIM_2 = 17297 }; enum GameobjectIds @@ -41,4 +64,33 @@ enum GameobjectIds GO_GRAND_WARLOCK_CHAMBER_DOOR_2 = 182540 }; +enum QuestIds +{ + QUEST_IMPRISONED_A = 9524, + QUEST_IMPRISONED_H = 9525 +}; + +const Position Executioner = { 152.8524f, -83.63912f, 2.021005f, 0.06981317f }; + +struct FactionSpawnerHelper +{ + FactionSpawnerHelper(uint32 allianceEntry, uint32 hordeEntry, const Position& pos) : _allianceNPC(allianceEntry), _hordeNPC(hordeEntry), _spawnPos(pos) { } + + inline uint32 operator()(uint32 teamID) const { return teamID == ALLIANCE ? _allianceNPC : _hordeNPC; } + inline const Position GetPos() const { return _spawnPos; } + +private: + const uint32 _allianceNPC; + const uint32 _hordeNPC; + const Position _spawnPos; +}; + +const FactionSpawnerHelper executionerVictims[VictimCount] = +{ + { NPC_CAPTAIN_ALINA, NPC_CAPTAIN_BONESHATTER, { 138.8807f, -84.22707f, 1.992269f, 0.06981317f } }, + { NPC_ALLIANCE_VICTIM_1, NPC_HORDE_VICTIM_1, { 151.2411f, -91.02930f, 2.019741f, 1.57079600f } }, + { NPC_ALLIANCE_VICTIM_2, NPC_HORDE_VICTIM_2, { 151.0459f, -77.51981f, 2.021008f, 4.74729500f } } +}; + + #endif |